604 lines · 8.8 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h>#include <libc.h>#include <bio.h>#include <mach.h>#define Extern#include "acid.h"#include "y.tab.h" extern int _ifmt(Fmt*); static Biobuf	bioout;static char	prog[128];static char*	lm[16];static int	nlm;static char*	mtype; static	int attachfiles(char*, int);int	xfmt(Fmt*);int	isnumeric(char*);void	die(void);void	loadmoduleobjtype(void); voidusage(void){	fprint(2, "usage: acid [-kqw] [-l library] [-m machine] [pid] [file]\n");	exits("usage");} voidmain(int argc, char *argv[]){	Lsym *l;	Node *n;	char *s;	int pid, i; 	argv0 = argv[0];	pid = 0;	aout = "8.out";	quiet = 1; 	mtype = 0;	ARGBEGIN{	case 'm':		mtype = ARGF();		break;	case 'w':		wtflag = 1;		break;	case 'l':		s = ARGF();		if(s == 0)			usage();		lm[nlm++] = s;		break;	case 'k':		kernel++;		break;	case 'q':		quiet = 0;		break;	case 'r':		pid = 1;		remote++;		kernel++;		break;	default:		usage();	}ARGEND 	if(argc > 0) {		if(remote)			aout = argv[0];		else		if(isnumeric(argv[0])) {			pid = strtol(argv[0], 0, 0);			snprint(prog, sizeof(prog), "/proc/%d/text", pid);			aout = prog;			if(argc > 1)				aout = argv[1];			else if(kernel)				aout = system();		}		else {			if(kernel) {				fprint(2, "acid: -k requires a pid\n");				usage();			}			aout = argv[0];		}	} else	if(remote)		aout = "/mips/9ch"; 	fmtinstall('x', xfmt);	fmtinstall('L', Lfmt);	Binit(&bioout, 1, OWRITE);	bout = &bioout; 	kinit();	initialising = 1;	pushfile(0);	loadvars();	installbuiltin(); 	if(mtype && machbyname(mtype) == 0)		print("unknown machine %s", mtype); 	if (attachfiles(aout, pid) < 0)		varreg();		/* use default register set on error */ 	loadmodule("/sys/lib/acid/port");	loadmoduleobjtype(); 	for(i = 0; i < nlm; i++) {		if(access(lm[i], AREAD) >= 0)			loadmodule(lm[i]);		else {			s = smprint("/sys/lib/acid/%s", lm[i]);			loadmodule(s);			free(s);		}	} 	userinit();	varsym(); 	l = look("acidmap");	if(l && l->proc) {		n = an(ONAME, ZN, ZN);		n->sym = l;		n = an(OCALL, n, ZN);		execute(n);	} 	interactive = 1;	initialising = 0;	line = 1; 	notify(catcher); 	for(;;) {		if(setjmp(err)) {			Binit(&bioout, 1, OWRITE);			unwind();		}		stacked = 0; 		Bprint(bout, "acid: "); 		if(yyparse() != 1)			die();		restartio(); 		unwind();	}	/* not reached */} static intattachfiles(char *aout, int pid){	interactive = 0;	if(setjmp(err))		return -1; 	if(aout) {				/* executable given */		if(wtflag)			text = open(aout, ORDWR);		else			text = open(aout, OREAD); 		if(text < 0)			error("%s: can't open %s: %r\n", argv0, aout);		readtext(aout);	}	if(pid)					/* pid given */		sproc(pid);	return 0;} voiddie(void){	Lsym *s;	List *f; 	Bprint(bout, "\n"); 	s = look("proclist");	if(s && s->v->type == TLIST) {		for(f = s->v->l; f; f = f->next)			Bprint(bout, "echo kill > /proc/%d/ctl\n", (int)f->ival);	}	exits(0);} voidloadmoduleobjtype(void){	char *buf; 	buf = smprint("/sys/lib/acid/%s", mach->name);	loadmodule(buf);	free(buf);} voiduserinit(void){	Lsym *l;	Node *n;	char *buf, *p; 	p = getenv("home");	if(p != 0) {		buf = smprint("%s/lib/acid", p);		silent = 1;		loadmodule(buf);		free(buf);	} 	interactive = 0;	if(setjmp(err)) {		unwind();		return;	}	l = look("acidinit");	if(l && l->proc) {		n = an(ONAME, ZN, ZN);		n->sym = l;		n = an(OCALL, n, ZN);		execute(n);	}} voidloadmodule(char *s){	interactive = 0;	if(setjmp(err)) {		unwind();		return;	}	pushfile(s);	silent = 0;	yyparse();	popio();	return;} voidreadtext(char *s){	Dir *d;	Lsym *l;	Value *v;	uvlong length;	Symbol sym;	extern Machdata mipsmach; 	if(mtype != 0){		symmap = newmap(0, 1);		if(symmap == 0)			print("%s: (error) loadmap: cannot make symbol map\n", argv0);		length = 1<<24;		d = dirfstat(text);		if(d != nil){			length = d->length;			free(d);		}		setmap(symmap, text, 0, length, 0, "binary");		return;	} 	machdata = &mipsmach; 	if(!crackhdr(text, &fhdr)) {		print("can't decode file header\n");		return;	} 	symmap = loadmap(0, text, &fhdr);	if(symmap == 0)		print("%s: (error) loadmap: cannot make symbol map\n", argv0); 	if(syminit(text, &fhdr) < 0) {		print("%s: (error) syminit: %r\n", argv0);		return;	}	print("%s:%s\n", s, fhdr.name); 	if(mach->sbreg && lookup(0, mach->sbreg, &sym)) {		mach->sb = sym.value;		l = enter("SB", Tid);		l->v->fmt = 'X';		l->v->ival = mach->sb;		l->v->type = TINT;		l->v->set = 1;	} 	l = mkvar("objtype");	v = l->v;	v->fmt = 's';	v->set = 1;	v->string = strnode(mach->name);	v->type = TSTRING; 	l = mkvar("textfile");	v = l->v;	v->fmt = 's';	v->set = 1;	v->string = strnode(s);	v->type = TSTRING; 	machbytype(fhdr.type);	varreg();} Node*an(int op, Node *l, Node *r){	Node *n; 	n = gmalloc(sizeof(Node));	memset(n, 0, sizeof(Node));	n->gclink = gcl;	gcl = n;	n->op = op;	n->left = l;	n->right = r;	return n;} List*al(int t){	List *l; 	l = gmalloc(sizeof(List));	memset(l, 0, sizeof(List));	l->type = t;	l->gclink = gcl;	gcl = l;	return l;} Node*con(vlong v){	Node *n; 	n = an(OCONST, ZN, ZN);	n->ival = v;	n->fmt = 'W';	n->type = TINT;	return n;} voidfatal(char *fmt, ...){	char buf[128];	va_list arg; 	va_start(arg, fmt);	vseprint(buf, buf+sizeof(buf), fmt, arg);	va_end(arg);	fprint(2, "%s: %L (fatal problem) %s\n", argv0, buf);	exits(buf);} voidyyerror(char *fmt, ...){	char buf[128];	va_list arg; 	if(strcmp(fmt, "syntax error") == 0) {		yyerror("syntax error, near symbol '%s'", symbol);		return;	}	va_start(arg, fmt);	vseprint(buf, buf+sizeof(buf), fmt, arg);	va_end(arg);	print("%L: %s\n", buf);} voidmarktree(Node *n){ 	if(n == 0)		return; 	marktree(n->left);	marktree(n->right); 	n->gcmark = 1;	if(n->op != OCONST)		return; 	switch(n->type) {	case TSTRING:		n->string->gcmark = 1;		break;	case TLIST:		marklist(n->l);		break;	case TCODE:		marktree(n->cc);		break;	}} voidmarklist(List *l){	while(l) {		l->gcmark = 1;		switch(l->type) {		case TSTRING:			l->string->gcmark = 1;			break;		case TLIST:			marklist(l->l);			break;		case TCODE:			marktree(l->cc);			break;		}		l = l->next;	}} voidgc(void){	int i;	Lsym *f;	Value *v;	Gc *m, **p, *next; 	if(dogc < Mempergc)		return;	dogc = 0; 	/* Mark */	for(m = gcl; m; m = m->gclink)		m->gcmark = 0; 	/* Scan */	for(i = 0; i < Hashsize; i++) {		for(f = hash[i]; f; f = f->hash) {			marktree(f->proc);			if(f->lexval != Tid)				continue;			for(v = f->v; v; v = v->pop) {				switch(v->type) {				case TSTRING:					v->string->gcmark = 1;					break;				case TLIST:					marklist(v->l);					break;				case TCODE:					marktree(v->cc);					break;				}			}		}	} 	/* Free */	p = &gcl;	for(m = gcl; m; m = next) {		next = m->gclink;		if(m->gcmark == 0) {			*p = next;			free(m);	/* Sleazy reliance on my malloc */		}		else			p = &m->gclink;	}} void*gmalloc(long l){	void *p;

Lines 1–500 of 604.