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

📄 sym.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <u.h>#include <libc.h>#include <bio.h>#include <mach.h>#define	HUGEINT	0x7fffffff#define	NNAME	20		/* a relic of the past */typedef	struct txtsym Txtsym;typedef	struct file File;typedef	struct hist Hist;struct txtsym {				/* Text Symbol table */	int 	n;			/* number of local vars */	Sym	**locals;		/* array of ptrs to autos */	Sym	*sym;			/* function symbol entry */};struct hist {				/* Stack of include files & #line directives */	char	*name;			/* Assumes names Null terminated in file */	long	line;			/* line # where it was included */	long	offset;			/* line # of #line directive */};struct file {				/* Per input file header to history stack */	uvlong	addr;			/* address of first text sym */	union {		Txtsym	*txt;		/* first text symbol */		Sym	*sym;		/* only during initilization */	};	int	n;			/* size of history stack */	Hist	*hist;			/* history stack */};static	int	debug = 0;static	Sym	**autos;		/* Base of auto variables */static	File	*files;			/* Base of file arena */static	int	fmax;			/* largest file path index */static	Sym	**fnames;		/* file names path component table */static	Sym	**globals;		/* globals by addr table */static	Hist	*hist;			/* base of history stack */static	int	isbuilt;		/* internal table init flag */static	long	nauto;			/* number of automatics */static	long	nfiles;			/* number of files */static	long	nglob;			/* number of globals */static	long	nhist;			/* number of history stack entries */static	long	nsym;			/* number of symbols */static	int	ntxt;			/* number of text symbols */static	uchar	*pcline;		/* start of pc-line state table */static	uchar 	*pclineend;		/* end of pc-line table */static	uchar	*spoff;			/* start of pc-sp state table */static	uchar	*spoffend;		/* end of pc-sp offset table */static	Sym	*symbols;		/* symbol table */static	Txtsym	*txt;			/* Base of text symbol table */static	uvlong	txtstart;		/* start of text segment */static	uvlong	txtend;			/* end of text segment */static void	cleansyms(void);static long	decodename(Biobuf*, Sym*);static short	*encfname(char*);static int 	fline(char*, int, long, Hist*, Hist**);static void	fillsym(Sym*, Symbol*);static int	findglobal(char*, Symbol*);static int	findlocvar(Symbol*, char *, Symbol*);static int	findtext(char*, Symbol*);static int	hcomp(Hist*, short*);static int	hline(File*, short*, long*);static void	printhist(char*, Hist*, int);static int	buildtbls(void);static int	symcomp(void*, void*);static int	symerrmsg(int, char*);static int	txtcomp(void*, void*);static int	filecomp(void*, void*);/* *	initialize the symbol tables */intsyminit(int fd, Fhdr *fp){	Sym *p;	long i, l, size;	vlong vl;	Biobuf b;	int svalsz;	if(fp->symsz == 0)		return 0;	if(fp->type == FNONE)		return 0;	cleansyms();	textseg(fp->txtaddr, fp);		/* minimum symbol record size = 4+1+2 bytes */	symbols = malloc((fp->symsz/(4+1+2)+1)*sizeof(Sym));	if(symbols == 0) {		werrstr("can't malloc %ld bytes", fp->symsz);		return -1;	}	Binit(&b, fd, OREAD);	Bseek(&b, fp->symoff, 0);	nsym = 0;	size = 0;	for(p = symbols; size < fp->symsz; p++, nsym++) {		if(fp->_magic && (fp->magic & HDR_MAGIC)){			svalsz = 8;			if(Bread(&b, &vl, 8) != 8)				return symerrmsg(8, "symbol");			p->value = beswav(vl);		}		else{			svalsz = 4;			if(Bread(&b, &l, 4) != 4)				return symerrmsg(4, "symbol");			p->value = (u32int)beswal(l);		}		if(Bread(&b, &p->type, sizeof(p->type)) != sizeof(p->type))			return symerrmsg(sizeof(p->value), "symbol");		i = decodename(&b, p);		if(i < 0)			return -1;		size += i+svalsz+sizeof(p->type);		/* count global & auto vars, text symbols, and file names */		switch (p->type) {		case 'l':		case 'L':		case 't':		case 'T':			ntxt++;			break;		case 'd':		case 'D':		case 'b':		case 'B':			nglob++;			break;		case 'f':			if(strcmp(p->name, ".frame") == 0) {				p->type = 'm';				nauto++;			}			else if(p->value > fmax)				fmax = p->value;	/* highest path index */			break;		case 'a':		case 'p':		case 'm':			nauto++;			break;		case 'z':			if(p->value == 1) {		/* one extra per file */				nhist++;				nfiles++;			}			nhist++;			break;		default:			break;		}	}	if (debug)		print("NG: %ld NT: %d NF: %d\n", nglob, ntxt, fmax);	if (fp->sppcsz) {			/* pc-sp offset table */		spoff = (uchar *)malloc(fp->sppcsz);		if(spoff == 0) {			werrstr("can't malloc %ld bytes", fp->sppcsz);			return -1;		}		Bseek(&b, fp->sppcoff, 0);		if(Bread(&b, spoff, fp->sppcsz) != fp->sppcsz){			spoff = 0;			return symerrmsg(fp->sppcsz, "sp-pc");		}		spoffend = spoff+fp->sppcsz;	}	if (fp->lnpcsz) {			/* pc-line number table */		pcline = (uchar *)malloc(fp->lnpcsz);		if(pcline == 0) {			werrstr("can't malloc %ld bytes", fp->lnpcsz);			return -1;		}		Bseek(&b, fp->lnpcoff, 0);		if(Bread(&b, pcline, fp->lnpcsz) != fp->lnpcsz){			pcline = 0;			return symerrmsg(fp->lnpcsz, "pc-line");		}		pclineend = pcline+fp->lnpcsz;	}	return nsym;}static intsymerrmsg(int n, char *table){	werrstr("can't read %d bytes of %s table", n, table);	return -1;}static longdecodename(Biobuf *bp, Sym *p){	char *cp;	int c1, c2;	long n;	vlong o;	if((p->type & 0x80) == 0) {		/* old-style, fixed length names */		p->name = malloc(NNAME);		if(p->name == 0) {			werrstr("can't malloc %d bytes", NNAME);			return -1;		}		if(Bread(bp, p->name, NNAME) != NNAME)			return symerrmsg(NNAME, "symbol");		Bseek(bp, 3, 1);		return NNAME+3;	}	p->type &= ~0x80;	if(p->type == 'z' || p->type == 'Z') {		o = Bseek(bp, 0, 1);		if(Bgetc(bp) < 0) {			werrstr("can't read symbol name");			return -1;		}		for(;;) {			c1 = Bgetc(bp);			c2 = Bgetc(bp);			if(c1 < 0 || c2 < 0) {				werrstr("can't read symbol name");				return -1;			}			if(c1 == 0 && c2 == 0)				break;		}		n = Bseek(bp, 0, 1)-o;		p->name = malloc(n);		if(p->name == 0) {			werrstr("can't malloc %ld bytes", n);			return -1;		}		Bseek(bp, -n, 1);		if(Bread(bp, p->name, n) != n) {			werrstr("can't read %ld bytes of symbol name", n);			return -1;		}	} else {		cp = Brdline(bp, '\0');		if(cp == 0) {			werrstr("can't read symbol name");			return -1;		}		n = Blinelen(bp);		p->name = malloc(n);		if(p->name == 0) {			werrstr("can't malloc %ld bytes", n);			return -1;		}		strcpy(p->name, cp);	}	return n;}/* *	free any previously loaded symbol tables */static voidcleansyms(void){	if(globals)		free(globals);	globals = 0;	nglob = 0;	if(txt)		free(txt);	txt = 0;	ntxt = 0;	if(fnames)		free(fnames);	fnames = 0;	fmax = 0;	if(files)		free(files);	files = 0;	nfiles = 0;	if(hist)		free(hist);	hist = 0;	nhist = 0;	if(autos)		free(autos);	autos = 0;	nauto = 0;	isbuilt = 0;	if(symbols)		free(symbols);	symbols = 0;	nsym = 0;	if(spoff)		free(spoff);	spoff = 0;	if(pcline)		free(pcline);	pcline = 0;}/* *	delimit the text segment */voidtextseg(uvlong base, Fhdr *fp){	txtstart = base;	txtend = base+fp->txtsz;}/* *	symbase: return base and size of raw symbol table *		(special hack for high access rate operations) */Sym *symbase(long *n){	*n = nsym;	return symbols;}/* *	Get the ith symbol table entry */Sym *getsym(int index){	if(index >= 0 && index < nsym)		return &symbols[index];	return 0;}/* *	initialize internal symbol tables */static intbuildtbls(void){	long i;	int j, nh, ng, nt;	File *f;	Txtsym *tp;	Hist *hp;	Sym *p, **ap;	if(isbuilt)		return 1;	isbuilt = 1;			/* allocate the tables */	if(nglob) {		globals = malloc(nglob*sizeof(*globals));		if(!globals) {			werrstr("can't malloc global symbol table");			return 0;		}	}	if(ntxt) {		txt = malloc(ntxt*sizeof(*txt));		if (!txt) {			werrstr("can't malloc text symbol table");			return 0;		}	}	fnames = malloc((fmax+1)*sizeof(*fnames));	if (!fnames) {		werrstr("can't malloc file name table");		return 0;	}	memset(fnames, 0, (fmax+1)*sizeof(*fnames));	files = malloc(nfiles*sizeof(*files));	if(!files) {		werrstr("can't malloc file table");		return 0;	}	hist = malloc(nhist*sizeof(Hist));	if(hist == 0) {		werrstr("can't malloc history stack");		return 0;	}	autos = malloc(nauto*sizeof(Sym*));	if(autos == 0) {		werrstr("can't malloc auto symbol table");		return 0;	}		/* load the tables */	ng = nt = nh = 0;	f = 0;	tp = 0;	i = nsym;	hp = hist;	ap = autos;	for(p = symbols; i-- > 0; p++) {		switch(p->type) {		case 'D':		case 'd':		case 'B':		case 'b':			if(debug)				print("Global: %s %llux\n", p->name, p->value);			globals[ng++] = p;			break;		case 'z':			if(p->value == 1) {		/* New file */				if(f) {					f->n = nh;					f->hist[nh].name = 0;	/* one extra */					hp += nh+1;					f++;				}				else					f = files;				f->hist = hp;				f->sym = 0;				f->addr = 0;				nh = 0;			}				/* alloc one slot extra as terminator */			f->hist[nh].name = p->name;			f->hist[nh].line = p->value;			f->hist[nh].offset = 0;			if(debug)				printhist("-> ", &f->hist[nh], 1);			nh++;			break;		case 'Z':			if(f && nh > 0)				f->hist[nh-1].offset = p->value;			break;		case 'T':		case 't':	/* Text: terminate history if first in file */		case 'L':		case 'l':			tp = &txt[nt++];			tp->n = 0;			tp->sym = p;			tp->locals = ap;			if(debug)				print("TEXT: %s at %llux\n", p->name, p->value);			if(f && !f->sym) {			/* first  */				f->sym = p;				f->addr = p->value;			}			break;		case 'a':		case 'p':		case 'm':		/* Local Vars */			if(!tp)				print("Warning: Free floating local var: %s\n",					p->name);			else {				if(debug)					print("Local: %s %llux\n", p->name, p->value);				tp->locals[tp->n] = p;				tp->n++;				ap++;			}			break;		case 'f':		/* File names */			if(debug)				print("Fname: %s\n", p->name);			fnames[p->value] = p;			break;		default:			break;		}	}		/* sort global and text tables into ascending address order */	qsort(globals, nglob, sizeof(Sym*), symcomp);	qsort(txt, ntxt, sizeof(Txtsym), txtcomp);	qsort(files, nfiles, sizeof(File), filecomp);	tp = txt;	for(i = 0, f = files; i < nfiles; i++, f++) {		for(j = 0; j < ntxt; j++) {			if(f->sym == tp->sym) {				if(debug) {					print("LINK: %s to at %llux", f->sym->name, f->addr);					printhist("... ", f->hist, 1);				}				f->txt = tp++;				break;			}			if(++tp >= txt+ntxt)	/* wrap around */				tp = txt;		}	}	return 1;}/* * find symbol function.var by name. *	fn != 0 && var != 0	=> look for fn in text, var in data *	fn != 0 && var == 0	=> look for fn in text *	fn == 0 && var != 0	=> look for var first in text then in data space. */intlookup(char *fn, char *var, Symbol *s){	int found;	if(buildtbls() == 0)		return 0;	if(fn) {		found = findtext(fn, s);		if(var == 0)		/* case 2: fn not in text */			return found;		else if(!found)		/* case 1: fn not found */			return 0;	} else if(var) {		found = findtext(var, s);		if(found)			return 1;	/* case 3: var found in text */	} else return 0;		/* case 4: fn & var == zero */	if(found)		return findlocal(s, var, s);	/* case 1: fn found */	return findglobal(var, s);		/* case 3: var not found */}/* * find a function by name */static intfindtext(char *name, Symbol *s){	int i;	for(i = 0; i < ntxt; i++) {		if(strcmp(txt[i].sym->name, name) == 0) {			fillsym(txt[i].sym, s);			s->handle = (void *) &txt[i];			s->index = i;			return 1;		}	}	return 0;}/* * find global variable by name */static intfindglobal(char *name, Symbol *s){	long i;	for(i = 0; i < nglob; i++) {		if(strcmp(globals[i]->name, name) == 0) {			fillsym(globals[i], s);			s->index = i;			return 1;		}	}	return 0;}/* *	find the local variable by name within a given function */intfindlocal(Symbol *s1, char *name, Symbol *s2){	if(s1 == 0)		return 0;	if(buildtbls() == 0)		return 0;	return findlocvar(s1, name, s2);}/* *	find the local variable by name within a given function *		(internal function - does no parameter validation) */static intfindlocvar(Symbol *s1, char *name, Symbol *s2){	Txtsym *tp;	int i;	tp = (Txtsym *)s1->handle;	if(tp && tp->locals) {		for(i = 0; i < tp->n; i++)			if (strcmp(tp->locals[i]->name, name) == 0) {				fillsym(tp->locals[i], s2);				s2->handle = (void *)tp;				s2->index = tp->n-1 - i;				return 1;			}	}	return 0;}/* *	Get ith text symbol */inttextsym(Symbol *s, int index){	if(buildtbls() == 0)		return 0;	if(index < 0 || index >= ntxt)		return 0;	fillsym(txt[index].sym, s);	s->handle = (void *)&txt[index];	s->index = index;	return 1;}/*	 *	Get ith file name */intfilesym(int index, char *buf, int n){	Hist *hp;	if(buildtbls() == 0)		return 0;	if(index < 0 || index >= nfiles)		return 0;	hp = files[index].hist;	if(!hp || !hp->name)		return 0;	return fileelem(fnames, (uchar*)hp->name, buf, n);}/* *	Lookup name of local variable located at an offset into the frame. *	The type selects either a parameter or automatic. */intgetauto(Symbol *s1, int off, int type, Symbol *s2){	Txtsym *tp;	Sym *p;	int i, t;	if(s1 == 0)		return 0;	if(type == CPARAM)		t = 'p';	else if(type == CAUTO)		t = 'a';	else		return 0;	if(buildtbls() == 0)		return 0;	tp = (Txtsym *)s1->handle;	if(tp == 0)		return 0;	for(i = 0; i < tp->n; i++) {		p = tp->locals[i];		if(p->type == t && p->value == off) {			fillsym(p, s2);			s2->handle = s1->handle;			s2->index = tp->n-1 - i;			return 1;		}	}	return 0;}/* * Find text symbol containing addr; binary search assumes text array is sorted by addr */static intsrchtext(uvlong addr){	uvlong val;	int top, bot, mid;	Sym *sp;	val = addr;	bot = 0;	top = ntxt;	for (mid = (bot+top)/2; mid < top; mid = (bot+top)/2) {		sp = txt[mid].sym;		if(val < sp->value)

⌨️ 快捷键说明

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