⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 obj4lb.c

📁 OXCC is a multipass, interpreting C compiler with several language extensions. It generates an Archi
💻 C
📖 第 1 页 / 共 2 页
字号:
/* obj4lb.c	-- fiddle with symbols in an a.out or coff format file 
** Copyright (C) 1995	Norman D. Culver	All rights reserved.
**
** COMPILE: (using djcc v1.12)
**		gcc -O2 -o obj4lb obj4lb.c
**		coff2exe -s go32.exe obj4lb
*/

#include <dos.h>
#include <limits.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdarg.h>
#include <memory.h>
#include <string.h>
#include <stdio.h>
#include <binimg.h>

#define coff_sym_is_fortrancommon(p) \
	((p->e_sclass == C_EXT) && (p->e_scnum == 0) && (p->e_value != 0))
#define coff_sym_is_undefined(p) \
	((p->e_scnum == 0) && (p->e_sclass == C_EXT))
#define coff_sym_is_global(p) \
	(p->e_sclass == C_EXT)

/* USEFUL DEFINITIONS */
#ifndef __GNUC__
typedef unsigned int u_int;
typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned long u_long;
#endif
typedef union {
  u_short val;
  u_char b[2];
} SVAL;

typedef union {
  u_long a0;
  void *a1;
  struct {
    SVAL offset;
    SVAL seg_addr;
  }a2;
} ADDR;

typedef struct _exports {
	struct _exports *fptr;
	char *name;
	int len;
} EXPORTS;

typedef struct _renames {
	struct _renames *fptr;
	char *oldname;
	int oldlen;
	char *newname;
	int newlen;
} RENAMES;

typedef struct _movdat {
	struct _movdat *fptr;
	unsigned long offset;
} MOVDAT, *PMOVDAT;

typedef struct relocation_info RELINFO;

#define round_up(size,amt) \
((size&(amt-1)) ? size+(amt-(size&(amt-1))) : size)

/* LOCAL VARIABLES */
static char infile[128];
static char outfile[128];
static char lb4file[128];
static struct exec header;
static FILE *ifd, *lb4fd, *ofd;
static EXPORTS exports;
static RENAMES renames;
static EXPORTS *lexports;
static RENAMES *lrenames;
static MOVDAT moves;
static MOVDAT *lmoves;
static int rename_diftot;
static long lowoffset;
static char *strtbl;
static char *nstrtbl;
static long strsize;
static long nstrsize;
static int nsyms;

/* INPUT DATA FROM THE .o FILE */

static NLIST *symtbl;
static char *text;
static RELINFO *text_relocs;
static int n_text_relocs;
static char *data;
static RELINFO *data_relocs;
static int n_data_relocs;

/* coff stuff */
typedef struct oxhdr {
	unsigned short info;
	unsigned short machine;
	unsigned start_addr;
	unsigned text_vaddr;
	unsigned text_size;
	unsigned text_fileaddr;
	unsigned data_vaddr;
	unsigned data_size;
	unsigned data_fileaddr;
	unsigned bss_vaddr;
	unsigned bss_size;
	unsigned image_size;
	unsigned text_reloc_fileaddr;
	unsigned text_reloc_size;
	unsigned text_reloc_cnt;
	unsigned data_reloc_fileaddr;
	unsigned data_reloc_size;
	unsigned data_reloc_cnt;
	unsigned symbols_fileaddr;
	unsigned symbols_size;
	unsigned symbols_cnt;
	unsigned strings_fileaddr;
	unsigned strings_size;
	unsigned section_headers_size;
} OXHDR, *POXHDR;

typedef struct {
	void *addr;
	long size;	
	unsigned long fileptr;
	long cnt;
} BUFS, *PBUFS;

static OXHDR xhdr;
static unsigned char scntype[128];
static PSCNHDR t,d,b,q,s;
static PBUFS sbf;
static PBUFS rbf;
static PBUFS lbf;
static PCOFF_SYMBOL coff_symtbl;
static short bss_section;

/* start of subroutines */

static void *
xmalloc (long n)
{
void *p;

  p = calloc (1,(size_t)n);
  if (n > 0 && p == 0)
  {
    puts ("obj4lb: virtual memory exhausted");
    exit (1);
  }
  return p;
}
static int
isglobal(char *str)
{
EXPORTS *l = &exports;

	while(l->fptr)
	{
		l = l->fptr;
		if(!strcmp(str, l->name))
			return 1;
	}
	return 0;
}
static RENAMES *
isrenamed(char *str)
{
RENAMES *r = &renames;

	while(r->fptr)
	{
		r = r->fptr;
		if(!strcmp(str, r->oldname))
			return r;
	}
	return NULL;
}
static void
aout_get_rid_of_fortrancommon(NLIST *sp, int symidx, int setglobal)
{/* move fortrancommon symbols to the bss segment */
u_long bssbase = N_BSSADDR(header);
u_long bssoffset = round_up(header.a_bss, sizeof(int));
u_long symbsize = sp->n_value;
u_long bssaddr = bssbase + bssoffset;
RELINFO *r;
int i;
void *ldata;

	sp->n_value = bssaddr;
	if(setglobal)
		sp->n_type = N_BSS|N_EXT;
	else
		sp->n_type = N_BSS;
	header.a_bss = bssoffset + symbsize;

	/* adjust all relocs which refence this variable */
	for(i = 0, r=text_relocs; i < n_text_relocs; ++i, ++r)
	{
		if(r->r_extern && r->r_symbolnum == symidx)
		{
			ldata = &text[r->r_address];
			r->r_extern = 0;
			r->r_symbolnum = N_BSS;
			if(r->r_length == 2)
				*((long *)ldata) += bssaddr;
			else
			{
				puts("4lb: non 32bit reloc encountered");
				exit(1);
			}
		}
	}
	for(i = 0, r=data_relocs; i < n_data_relocs; ++i, ++r)
	{
		if(r->r_extern && r->r_symbolnum == symidx)
		{
			ldata = &data[r->r_address];
			r->r_extern = 0;
			r->r_symbolnum = N_BSS;
			if(r->r_length == 2)
				*((long *)ldata) += bssaddr;
			else
			{
				puts("4lb: non 32bit reloc encountered");
				exit(1);
			}
		}
	}
}
static void
aout_adjust_symbol(long oldoffset, long newoffset, int setglobal)
{
NLIST *sp;
int i;

	for(i = 0, sp = symtbl; i < nsyms; ++i, ++sp)
	{
		if(sp->n_un.n_strx == oldoffset)
		{/* newoffset is set negative to avoid reuse */
			sp->n_un.n_strx = newoffset | 0x80000000;
			if(sym_is_fortrancommon(sp))
				aout_get_rid_of_fortrancommon(sp, i, setglobal);
			else if(setglobal)
				sp->n_type |= N_EXT;
			else if(!sym_is_undefined(sp))
				sp->n_type &= ~N_EXT;
			return;
		}
	}
}
static void
coff_get_rid_of_fortrancommon(COFF_SYMBOL *sp, int symidx, int setglobal)
{/* move fortrancommon symbols to the bss segment */
PCOFF_HDR p = (PCOFF_HDR)&header;
u_long bssbase = b->s_vaddr;
u_long bssoffset = round_up(b->s_size, sizeof(int));
u_long symbsize = sp->e_value;
u_long bssaddr = bssbase + bssoffset;
int i, j;

	sp->e_value = bssaddr;
	sp->e_scnum = bss_section;
	if(setglobal)
		sp->e_sclass = C_EXT;
	else
		sp->e_sclass = C_STAT;
	b->s_size = round_up(bssoffset + symbsize, sizeof(int));

	/* adjust all relocs which reference this variable */
	for(i = 0; i < p->f_nscns; ++i)
	{
	COFF_RELOC *r;

		if((r = rbf[i].addr))
		{
		int cnt = rbf[i].cnt;
		char *scndata = sbf[i].addr;
		unsigned long s_vaddr = s[i].s_vaddr;

			for(j = 0; j < cnt; ++j, ++r)
			{
				if(r->r_symndx == symidx)
				{
				void *ldata = &scndata[r->u.r_vaddr - s_vaddr];
					if(r->r_type == 0x0006)
					{
						*((long *)ldata) += bssaddr - symbsize;
					}
					else if(r->r_type == 0x0007)
					{
						puts("4lb: type 7 reloc encountered");
						exit(1);
					}
					else if(r->r_type == 0x0014)
					{
						puts("4lb: pcrel comdef encountered");
						exit(1);
					}
					else
					{
						puts("4lb: non 32bit reloc encountered");
						exit(1);
					}
				}
			}
		}
	}
}
static void
coff_adjust_symbol(long oldoffset, long newoffset, int setglobal)
{
COFF_SYMBOL *sp;
int i;

	for(i = 0, sp = coff_symtbl; i < nsyms; ++i, ++sp)
	{
		if(sp->e.e.e_offset == oldoffset)
		{/* newoffset is set negative to avoid reuse */
			sp->e.e.e_offset = newoffset | 0x80000000;
			if(coff_sym_is_fortrancommon(sp))
				coff_get_rid_of_fortrancommon(sp, i, setglobal);
			else if(setglobal)
				sp->e_sclass = C_EXT;
			else if(!coff_sym_is_undefined(sp))
			{
				if(coff_sym_is_global(sp))
					sp->e_sclass = C_STAT;
			}
		}
		if(sp->e_numaux)
		{/* ignore aux records */
			i += sp->e_numaux;
			sp += sp->e_numaux;
		}
	}
}
static void
adjust_strings(int format_fudge)
{/* HERE'S THE BEEF -- WRITE A NEW STRING TABLE AND ADJUST SYMTAB */
long istroff = lowoffset;
long ostroff = lowoffset;
char *ip, *ep, *op;
int i;

	nstrsize = strsize + rename_diftot;
	nstrtbl = xmalloc(nstrsize+12);
	ip = strtbl+lowoffset;
	op = nstrtbl+lowoffset;
	ep = ip + strsize;

	while(ip < ep)
	{/* scan over each of the strings in the old string table */
	int global;
	int	istrlen = strlen(ip);
	int olen;
	RENAMES *r;
		if(istrlen > 0)
		{
			if((r = isrenamed(ip)))
			{/* change the string on output */
				strcpy(op, r->newname);
				op += r->newlen+1;
				olen = r->newlen+1;
				global = isglobal(r->newname);
			}
			else
			{/* use the old string on output */
				strcpy(op, ip);
				op += istrlen+1;
				olen = istrlen+1;
				global = isglobal(ip);
			}
			if(coff_symtbl)
				coff_adjust_symbol(istroff, ostroff, global);
			else
				aout_adjust_symbol(istroff, ostroff, global);
			ostroff += olen;
		}
		ip += istrlen+1;
		istroff += istrlen+1;
	}
	nstrsize = ostroff + format_fudge;
	/* reset the negative values for offsets */
	if(coff_symtbl)
	{
	COFF_SYMBOL *sp;
		for(i = 0, sp = coff_symtbl; i < nsyms; ++i, ++sp)
		{
			if(sp->e.e.e_offset & 0x80000000)
				sp->e.e.e_offset &= 0x7fffffff;
			if(sp->e_numaux)
			{/* ignore aux records */
				i += sp->e_numaux;
				sp += sp->e_numaux;
			}
		}
	}
	else
	{
	NLIST *sp;
		for(i = 0, sp = symtbl; i < nsyms; ++i, ++sp)
		{
		  if(sp->n_un.n_strx & 0x80000000)
			  sp->n_un.n_strx &= 0x7fffffff;
		}
	}
}
static int
aout_read_symbols ()
{
int i;
NLIST *sp;

  nsyms = header.a_syms / sizeof (NLIST);
  if (nsyms == 0)
    return 1;

  symtbl = (NLIST *)xmalloc (header.a_syms);

  fseek (ifd, N_SYMOFF (header), 0);
  fread ((char *)symtbl, sizeof(NLIST), nsyms, ifd);

  fseek (ifd, N_STROFF(header), 0);
  fread ((char *)&strsize, sizeof strsize, 1, ifd);

  strtbl = xmalloc (strsize);
  fseek (ifd, N_STROFF (header), 0);
  fread ((char *)strtbl, (int)strsize, 1, ifd);

  lowoffset = 2000000;
  for (i = 0, sp = symtbl; i < nsyms; i++, sp++)
  {
    if (sp->n_un.n_strx != 0)
		if(sp->n_un.n_strx < lowoffset)
			lowoffset = sp->n_un.n_strx;
  }
}
static void
aout_read_text_and_data()
{
  text = xmalloc(header.a_text);
  data = xmalloc(header.a_data);

  if(header.a_text > 0)
  {
    fseek(ifd, N_TXTOFF(header), 0);
    fread(text, (u_int)header.a_text, 1, ifd);
  }
  if(header.a_data > 0)
  {
    fseek(ifd, N_DATOFF(header), 0);
    fread(data, (u_int)header.a_data, 1, ifd);
  }
}
static int
relcomp(const void *a,const void *b)
{
  return (int)((long)((RELINFO*)a)->r_address-(long)((RELINFO*)b)->r_address);
}
static void
aout_read_relocs()
{
int i;
RELINFO *reloc;

  n_text_relocs = header.a_trsize / sizeof (RELINFO); 
  n_data_relocs = header.a_drsize / sizeof (RELINFO);

  if(n_text_relocs > 0)
  {
    text_relocs = xmalloc(header.a_trsize); 
    fseek(ifd, N_TRELOFF(header), 0);
    fread((char *)text_relocs, (u_int)header.a_trsize, 1, ifd);
    qsort (text_relocs, n_text_relocs, sizeof (RELINFO), relcomp);
  }

  if(n_data_relocs > 0)
  {
    data_relocs = xmalloc(header.a_drsize);	
    fseek(ifd, N_DRELOFF(header), 0);
    fread((char *)data_relocs, (u_int)header.a_drsize, 1, ifd);
    qsort (data_relocs, n_data_relocs, sizeof (RELINFO),relcomp);
  }
}


static int
movcmp(char *s1, char *s2)
{
int i = E_SYMNMLEN;
	while(i--)
	{
		if(*s1++ != *s2++)
			return 1;
	}
	return 0;
}
static unsigned long
mark_moved(PCOFF_SYMBOL sp)
{
MOVDAT *m = &moves;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -