Charles.Forsyth20060303644188019 years agoHistory
642 lines · 11.9 KB · C
RawDownload
#include	"auxi.h" /* * in some embedded coff files, edata and end have type 0 not 4, * and file value is pointer to next file sym (as here), but the last one * points to an external symbol, not 0 as here. */ #define C_NULL	0#define C_AUTO	1#define C_EXT		2#define C_STAT	3#define C_ARG		9#define C_FCN		101#define C_FILE		103 #define T_VOID	0#define T_CHAR	2#define T_SHORT	3#define T_INT		4#define T_LONG	5 #define DT_NON	0#define DT_PTR	1#define DT_FCN	2#define DT_ARY	3 #define T(a, b)	(((a)<<4)|b) #define DOTTEXT	".text"#define DOTDATA	".data"#define DOTBSS	".bss"#define DOTBF		".bf"#define DOTEF		".ef" #define SINDEX(s)	(*((long*)(&s->become)))#define LINDEX(s)	(*((long*)(&s->used))) typedef struct Hist Hist; struct Hist{	Auto *a;	Hist *n;}; static int nsym, nlc, lines; static void cofflcsz(void); static Hist *freeh, *curh; static voiddohist(Auto *a){	Hist *h, **ha; 	if(a->aoffset == 1){	/* new file */		for(ha = &curh; *ha != nil; ha = &((*ha)->n))			;		*ha = freeh;		freeh = curh;		curh = nil;	}	if(freeh != nil){		h = freeh;		freeh = freeh->n;	}	else		h = malloc(sizeof(Hist));	h->a = a;	h->n = nil;	for(ha = &curh; *ha != nil; ha = &((*ha)->n))		;	*ha = h;} static longlineno(long n){	long o, d;	Hist *h; 	if(1)		return n;	/* now using fileline() not pc2line() */ 	if(curh == nil)		return 0;	o = curh->a->aoffset-1;	d = 1;	for(h = curh->n; d && h != nil; h = h->n){		if(h->a->asym->name[1] || h->a->asym->name[2]){			if(h->a->type == D_FILE1) {				;			}			else if(d == 1 && n < h->a->aoffset)				break;			else if(d++ == 1)				o -= h->a->aoffset;		}		else if(--d == 1)			o += h->a->aoffset;	}	return n-o;} static char *filelookup(int k){	int i;	Symx *s; 	for(i = 0; i < NHASH; i++){		for(s = hash[i]; s != nil; s = s->link){			if(s->type == SFILE && k == s->value)				return s->name+1;		}	}	return "";} static char*filename(char *s){	int j, k, l;	static char buf[256]; 	buf[0] = '\0';	if(s[0] != 0)		diag("bad filename");	for(j = 1; ; j += 2){		k = (s[j]<<8)|s[j+1];		if(k == 0)			break;		l = strlen(buf);		if(l != 0 && buf[l-1] != '/')			strcat(buf, "/");		strcat(buf, filelookup(k));	}	return buf;} static voidsput(char *s, int n){	int i; 	for(i = 0; i < n && s != nil && *s != '\0'; i++, s++)		cput(*s);	for( ; i < n; i++)		cput(0);} static voidcoffsect(char *s, long a, long sz, long o, long lp, long nl, long f){	if(0)		print("sect %s pa=%lux va=%lux sz=%lux\n", s, a, a, sz);	sput(s, 8);			/* name <= 8 chars in len */	lputl(a);			/* pa */	lputl(a);			/* va */	lputl(sz);			/* size */	lputl(o);			/* file offset */	lputl(0);			/* reloc */	lputl(lp);			/* line nos */	lputl(0);			/* no reloc entries */	lputl(nl);			/* no line no entries */	lputl(f);			/* flags */	hputl(0);			/* reserved */	hputl(0);			/* mem page no */} voidcoffhdr(void){	if(0){		print("H=%lux t=%lux d=%lux b=%lux\n", HEADR, textsize, datsize, bsssize);		print("e=%lux ts=%lux ds=%lux\n", entryvalue(), INITTEXT, INITDAT);	} 	/*	 * file header	 */	hputl(0xc2);			/* version ID */	hputl(3);				/* no section hdrs */	lputl(0);				/* date stamp */	lputl(HEADR+textsize+datsize+6*nlc);	/* sym table */	lputl(nsym);			/* no sym table entries */	hputl(28);				/* size optional hdr */	hputl(0x0103);			/* flags */	hputl(0x97);			/* target ID */	/*	 * optional file header	 */	hputl(0x108);			/* magic */	hputl(0);				/* version stamp */	lputl(textsize);			/* text size */	lputl(datsize);			/* data size */	lputl(bsssize);			/* bss size */	lputl(entryvalue());		/* entry pt */	lputl(INITTEXT);		/* text start */	lputl(INITDAT);			/* data start */	/*	 * sections	 */	coffsect(DOTTEXT, INITTEXT, textsize, HEADR, HEADR+textsize+datsize, nlc, 0x20);	coffsect(DOTDATA, INITDAT, datsize, HEADR+textsize, 0, 0, 0x40);	coffsect(DOTBSS, INITDAT+datsize, bsssize, 0, 0, 0, 0x80);} static intprivate(char *s){	return strcmp(s, "safe") == 0 || strcmp(s, "ret") == 0 || strcmp(s, "string") == 0;} static long stoff = 4; static longstput(char *s){	long r; 	r = stoff;	stoff += strlen(s)+1;	return r;} static longstrput(char *s){	int l; 	if((l = strlen(s)) > 8){		if(*s == '.' && private(s+1))			return 0;		while(*s)			cput(*s++);		cput(*s);		return l+1;	}	return 0;} static voidstflush(void){	int i;	long o;	Prog *p;	Auto *a, *f;	Symx *s;	char *fn, file[256]; 	lputl(stoff);	o = 4;	for(p = firstp; p != P; p = p->link){		if(p->as == ATEXT){			f = nil;			fn = nil;			for(a = p->to.autom; a != nil; a = a->link){				if(a->type == D_FILE){					f = a;					break;				}			}			if(f != nil)				fn = filename(f->asym->name);			if(fn != nil && *fn != '\0' && strcmp(fn, file) != 0){				strcpy(file, fn);				o += strput(file);			}			o += strput(p->from.sym->name);			for(a = p->to.autom; a != nil; a = a->link){				if(a->type == D_AUTO || a->type == D_PARAM)					o += strput(a->asym->name);			}		}	}	for(i = 0; i < NHASH; i++){		for(s = hash[i]; s != nil; s = s->link){			if(s->version > 0 && (s->type == SDATA || s->type == SBSS))				o += strput(s->name);		}	}	for(i = 0; i < NHASH; i++){		for(s = hash[i]; s != nil; s = s->link){			if(s->version == 0 && (s->type == SDATA || s->type == SBSS))				o += strput(s->name);		}	}	if(o != stoff)		diag("bad stflush offset");} static intputsect(Symx *s){	int sz, ln; 	sz = ln = 0;	// isn't this repetition ?	if(strcmp(s->name, DOTTEXT) == 0){		sz = textsize;		ln = nlc;	}	else if(strcmp(s->name, DOTDATA) == 0)		sz = datsize;	else if(strcmp(s->name, DOTBSS) == 0)		sz = bsssize;	else		diag("bad putsect sym");	lputl(sz);	hputl(0);	hputl(ln);	sput(nil, 10);	return 1;} static intputfun(Symx *s){	/* lputl(SINDEX(s)+2); */	lputl(0);	lputl(0);	/* patched later */	lputl(HEADR+textsize+datsize+LINDEX(s));	lputl(0);	/* patched later */	sput(nil, 2);	return 1;} static intputbf(int lno){	lputl(0);	hputl(lno);	hputl(lines);	lputl(autosize);	lputl(0);	/* patched later */	sput(nil, 2);	return 1;} static intputef(int lno){	sput(nil, 4);	hputl(lno);	sput(nil, 12);	return 1;} static intputsym(Symx *s, int sc, int t, int lno){	long v; 	if(s == nil || s->name == nil || s->name[0] == '\0' || (s->name[0] == '.' && private(s->name+1)))		return 0;	if(0)		print("putsym %s %d %ld %d %d\n", s->name, s->type, s->value, sc, t);	if(strlen(s->name) <= 8)		sput(s->name, 8);	else{		lputl(0);		lputl(stput(s->name));	}	/* value */	v = s->value;	if(s->type == SDATA || s->type == SDATA1 || s->type == SBSS)		lputl(INITDAT+v);	else if(sc == C_AUTO)		lputl(autosize+v);	else if(sc == C_ARG)		lputl(autosize+v+4);	else		lputl(v);	switch(s->type){	/* section number */	case STEXT:	case SLEAF:		hputl(1);		break;	case SDATA:	case SDATA1:		hputl(2);		break;	case SBSS:		hputl(3);		break;	case SFILE:		hputl(-2);		break;	default:		diag("type %d in putsym", s->type);		break;	}	hputl(t);			/* type */	cput(sc);			/* storage class */	/* aux entries */	if(sc == C_STAT && t == T_VOID && s->name[0] == '.'){	/* section */		cput(1);		return 1+putsect(s);	}	else if((t>>4) == DT_FCN){	/* function */		cput(1);		return 1+putfun(s);	}	else if(sc == C_FCN && strcmp(s->name, DOTBF) == 0){	/* bf */		cput(1);		return 1+putbf(lno);	}	else if(sc == C_FCN && strcmp(s->name, DOTEF) == 0){	/* ef */		cput(1);		return 1+putef(lno);	}	cput(0);			/* 0 aux entry */	return 1;} static Symx*defsym(char *p, int t, long v){	Symx *s; 	s = lookupsym(p, 0);	if(s->type == SDATA || s->type == SBSS)		return nil;		/* already output */	if(s->type == 0 || s->type == SXREF){		s->type = t;		s->value = v;	}	return s;} static intspecsym(char *p, int t, long v, int c){	return putsym(defsym(p, t, v), c, T_VOID, 0);} static intcclass(Symx *s){/*	if(s->version > 0 && dclass == D_EXTERN)		diag("%s: version %d dclass EXTERN", s->name, s->version);	if(s->version == 0 && dclass == D_STATIC)		diag("%s: version %d dclass STATIC", s->name, s->version);*/	return s->version > 0 ? C_STAT : C_EXT;} static voidpatchsym(long i, long o, long v){	long oo; 	cflush();	oo = seek(cout, 0, 1);	seek(cout, HEADR+textsize+datsize+6*nlc+18*i+o, 0);	lputl(v);	cflush();	seek(cout, oo, 0);} voidcoffsym(void){	int i;	long ns, lno, lpc, v, vs, lastf;	Prog *p;	Auto *a, *f;	Symx *s, *bf, *ef, ts;	char *fn, file[256]; 	file[0] = '\0';	cofflcsz();	seek(cout, 6*nlc, 1);		/* advance over line table */	ns = 0;	lpc = -1;	lno = -1;	lastf = -1;	bf = defsym(DOTBF, STEXT, 0);	ef = defsym(DOTEF, STEXT, 0);	for(p = firstp; p != P; p = p->link){		setarch(p);		if(p->as != ATEXT){			if(p->line != 0)				lno = lineno(p->line);		}		if(p->as == ATEXT){			curtext = p;			autosize = p->to.offset+4;			if(lpc >= 0){				ef->value = lpc;				ns += putsym(ef, C_FCN, T_VOID, lno);			}			f = nil;			fn = nil;			for(a = p->to.autom; a != nil; a = a->link){				if(a->type == D_FILE || a->type == D_FILE1)

Lines 1–500 of 642.