spewmerge maine61f2f51 year agoHistory
499 lines · 10.3 KB · C
RawDownload
#include "sl.h"#include <draw.h>#include <bio.h>#include <ctype.h>#include <mach.h>#include "cvalues.h"#include "types.h"#include "io.h" static char aout[1024];static sl_v gpregsym, fpregsym, mkregsym, mksymbolsym, mkframesym;static sl_type *bptype;static Map* coremap;static Fhdr fhdr;static ios *proc_stdin; voidlsd_init(void){	gpregsym = mk_csym(":gpreg");	fpregsym = mk_csym(":fpreg");	mksymbolsym = mk_csym("mk-symbol");	mkregsym = mk_csym("mk-reg");	mkframesym = mk_csym("mk-frame");	bptype = get_type(mk_list2(sl_arrsym, sl_u8sym));} sl_vmk_lsdptr(u64int n){	return mach->szreg == 8 ? mk_p64(n) : mk_p32(n);} static Reglist*rname(char *name){	Reglist *rp; 	for(rp = mach->reglist; rp->rname; rp++)	if(strcmp(name, rp->rname) == 0)		return rp;	return nil;} static uvlongrget(Map *map, char *name){	Reglist *rp;	ulong x;	uvlong v;	int r; 	rp = rname(name);	if(rp == nil)		cthrow(lerrorf(sl_errio, "invalid register name %s", name), map); 	switch(rp->rformat){	default:		r = get4(map, rp->roffs, &x);		v = x;		break;	case 'V': case 'W': case 'Y': case 'Z':		r = get8(map, rp->roffs, &v);		break;	}	if(r < 0)		cthrow(lerrorf(sl_errio, "could not get register %s: %r", name), map);	return v;} static sl_vmk_symbol(Symbol *s){	sl_v r; 	r = s->type;	return sl_applyn(3, sym_value(mksymbolsym), str_from_cstr(s->name), mk_rune(r), mk_lsdptr(s->value));} static sl_vsymslist(int (*loadsym)(Symbol*, int)){	Symbol s;	sl_v syms;	int i; 	syms = sl_nil;	sl_gc_handle(&syms);	for(i = 0; loadsym(&s, i); i++){		if(s.name[0] == '.' || strchr(s.name, '$') != nil)			continue;		syms = mk_cons(mk_symbol(&s), syms);	}	sl_free_gc_handles(1);	return syms;} static sl_vlocalslist(Symbol *fn, uvlong sp){	sl_v locals;	int i;	Symbol s; 	locals = sl_nil;	sl_gc_handle(&locals);	s = *fn;	for(i = 0; localsym(&s, i); i++){		if(s.name[0] == '.')			continue;		switch(s.class){		case CAUTO:			s.value = sp-s.value;			break;		case CPARAM:			s.value = sp+mach->szaddr+s.value;			break;		}		locals = mk_cons(mk_symbol(&s), locals);	}	sl_free_gc_handles(1);	return locals;} static voidload(int dummy){	int fd;	long nsym;	Map *symmap; 	fd = open(aout, OREAD);	if(fd < 0)		cthrow(lerrorf(sl_errio, "could not open \"%s\"", aout), dummy);	if(!crackhdr(fd, &fhdr)){		close(fd);		cthrow(lerrorf(sl_errio, "could not decode file header for \"%s\"", aout), dummy);	}	machbytype(fhdr.type);	symmap = loadmap(nil, fd, &fhdr);	if(symmap == nil){		close(fd);		cthrow(lerrorf(sl_errio, "could not load segments for \"%s\"", aout), dummy);	}	nsym = syminit(fd, &fhdr);	if(nsym < 0){		close(fd);		cthrow(lerrorf(sl_errio, "could not initialize the symbol table for \"%s\"", aout), dummy);	}	close(fd);	ios_printf(ios_stdout, "%s:%s\n", aout, fhdr.name);} static voidfreecore(void){	int i; 	if(coremap == nil)		return;	for(i = 0; i < coremap->nsegs; i++)	if(coremap->seg[i].inuse && coremap->seg[i].fd >= 0)		close(coremap->seg[i].fd);	MEM_FREE(coremap);	coremap = nil;} static voidattach(int pid){	static char buf[128];	int fd; 	if(pid < 0)		return; 	snprint(buf, sizeof(buf), "/proc/%d/mem", pid);	fd = open(buf, ORDWR);	if(fd < 0)		cthrow(lerrorf(sl_errio, "could not open \"%s\"", buf), pid); 	freecore();	coremap = attachproc(pid, 0, fd, &fhdr);	if(coremap == nil)		cthrow(lerrorf(sl_errio, "could not make coremap: %r"), pid);} voidwindow(Rectangle *r){	char buf[512];	char *wsyssrv;	int fd; 	if((wsyssrv = getenv("wsys")) == nil)		sysfatal("cannot find $wsys: %r");	if((fd = open(wsyssrv, ORDWR)) < 0)		sysfatal("cannot open $wsys: %r");	free(wsyssrv);	if(r != nil)		snprint(buf, sizeof(buf), "new -r %d %d %d %d", r->min.x, r->min.y, r->max.x, r->max.y);	else		snprint(buf, sizeof(buf), "new");	if(mount(fd, -1, "/mnt/wsys", MREPL, buf) < 0)		sysfatal("cannot create new window: %r");	close(fd);	if(bind("/mnt/wsys", "/dev", MBEFORE) < 0)		sysfatal("cannot create new window: %r");	close(1);	close(2);	open("/dev/cons", OWRITE);	open("/dev/cons", OWRITE);} static intnewproc(char **argv, int *outp, bool win, Rectangle *r){	int pid, fd, p[2];	char buf[128]; 	if(pipe(p) < 0)		cthrow(lerrorf(sl_errio, "could not create a pipe"), argv);	pid = rfork(RFPROC|RFFDG|RFREND|RFNAMEG|RFNOTEG);	switch(pid){	case -1:		cthrow(lerrorf(sl_errio, "could not fork"), argv);	case 0:		if(win)			window(r);		snprint(buf, sizeof(buf), "/proc/%d/ctl", getpid());		fd = open(buf, ORDWR);		if(fd < 0)			sysfatal("could not open %s: %r", buf);		write(fd, "hang", 4);		close(fd);		close(p[0]);		dup(p[1], 0);		close(p[1]);		exec(argv[0], argv);		sysfatal("could not exec %s: %r", aout);	}	close(p[1]);	attach(pid);	*outp = p[0];	return pid;} sl_vnew(sl_v *args, int nargs, bool win, Rectangle *r){	sl_v v;	int pid, p, i;	static char *argv[512]; 	if(nargs+2 >= nelem(argv))		bthrow(lerrorf(sl_errio, "too many arguments"));	argv[0] = aout;	for(i = 0; i < nargs; i++){		if(sl_unlikely(!isstr(args[i])))			bthrow(type_error(nil, "str", args[i]));		argv[i+1] = cvalue_data(args[i]);	}	argv[i+1] = nil;	pid = newproc(argv, &p, win, r); 	if(proc_stdin != nil){		MEM_FREE(proc_stdin->filename);		MEM_FREE(proc_stdin);	}	proc_stdin = MEM_ALLOC(sizeof(*proc_stdin));	ios_fd(proc_stdin, p, "proc-stdin", false, false); 	v = alloc_vec(2, 0);	sl_gc_handle(&v);	vec_elt(v, 0) = fixnum(pid);	vec_elt(v, 1) = cvalue_from_ref(sl_iotype, proc_stdin, sizeof(*proc_stdin));	sl_free_gc_handles(1);	return v; } static sl_v tracelist; static voidtrlist(Map *map, uvlong retpc, uvlong sp, Symbol *fn){	USED(map);	tracelist = mk_cons(sl_applyn(4, sym_value(mkframesym), mk_symbol(fn), mk_lsdptr(retpc), mk_lsdptr(sp), localslist(fn, sp)), tracelist);} BUILTIN("lsd-ctrace", lsd_ctrace){	sl_v *a;	uvlong pc, sp, res; 	argcount(nargs, 3);	for(a = args; a < args+3; a++)		if(sl_unlikely(!isnum(*a)))			bthrow(type_error(nil, "num", *a)); 	pc = tosize(args[0]);	sp = tosize(args[1]);	res = tosize(args[2]);	tracelist = sl_nil;	sl_gc_handle(&tracelist);	if(machdata->ctrace(coremap, pc, sp, res, trlist) <= 0){		sl_free_gc_handles(1);		bthrow(lerrorf(sl_errio, "could not retrieve stack frame: %r"));	}	sl_free_gc_handles(1);	return tracelist;} BUILTIN("lsd-cleanup", lsd_cleanup){	USED(args);	argcount(nargs, 0);	freecore();	return sl_void;} BUILTIN("lsd-load", lsd_load){	Reglist *r;	sl_v v, registers, ptrsz;	int pid, len; 	pid = -1;	argcount(nargs, 1);	if(sl_unlikely(!isstr(args[0]) && !isnum(args[0])))		bthrow(type_error("program", "(or str num)", args[0])); 	if(isnum(args[0])){		pid = tosize(args[0]);		snprint(aout, sizeof(aout), "/proc/%d/text", pid);	}else{		len = cv_len(ptr(args[0]));		if(len+1 > sizeof(aout))			bthrow(lerrorf(sl_errio, "path too long"));		strecpy(aout, aout+sizeof(aout), cvalue_data(args[0]));	} 	load(0);	attach(pid); 	registers = sl_nil;	v = sl_nil;	sl_gc_handle(&registers);	sl_gc_handle(&v);	for(r = mach->reglist; r->rname != nil; r++){		switch(r->rformat){		default:			ptrsz = sl_u32sym;			break;		case 'V': case 'W': case 'Y': case 'Z':			ptrsz = sl_u64sym;			break;		}		v = sl_applyn(4, sym_value(mkregsym), str_from_cstr(r->rname), r->rflags == RINT ? gpregsym : fpregsym, size_wrap(r->roffs), ptrsz);		set(mk_sym(r->rname, true), v);		registers = mk_cons(v, registers);	}	sl_free_gc_handles(2); 	v = alloc_vec(6, 0);	sl_gc_handle(&v);	vec_elt(v, 0) = fixnum(pid);	vec_elt(v, 1) = registers;	vec_elt(v, 2) = cvalue_from_ref(bptype, machdata->bpinst, machdata->bpsize);	vec_elt(v, 3) = symslist(textsym);	vec_elt(v, 4) = symslist(globalsym);	vec_elt(v, 5) = sym_value(mach->szreg == 8 ? sl_p64sym : sl_p32sym);	sl_free_gc_handles(1); 	return v;} BUILTIN("lsd-new", lsd_new){	return new(args, nargs, false, nil);} BUILTIN("lsd-winr", lsd_winr){	if(sl_unlikely(nargs < 4))		bthrow(arity_error(nargs, 4)); 	Rectangle r = Rect(numval(args[0]), numval(args[1]), numval(args[2]), numval(args[3]));	return new(args+4, nargs-4, true, &r);} BUILTIN("lsd-win", lsd_win){	return new(args, nargs, true, nil);} BUILTIN("lsd-follow", lsd_follow){	int n;	uvlong addr, f[10], *p;	sl_v foll; 	argcount(nargs, 1);	if(sl_unlikely(!isnum(args[0])))		bthrow(type_error("addr", "num", args[0]));	addr = tosize(args[0]); 	n = machdata->foll(coremap, addr, rget, f);	if(n < 0)		bthrow(lerrorf(sl_errio, "follow(%ux): %r", addr)); 	foll = sl_nil;	sl_gc_handle(&foll);	for(p = f; p < f+n; p++)		foll = mk_cons(mk_lsdptr(*p), foll);	sl_free_gc_handles(1);	return foll;} BUILTIN("lsd-das", lsd_das){	static char buf[512];	uvlong addr; 	argcount(nargs, 1);	if(sl_unlikely(!isnum(args[0])))		bthrow(type_error("addr", "num", args[0])); 	addr = tosize(args[0]);	if(machdata->das(coremap, addr, 'i', buf, sizeof(buf)) < 0)		bthrow(lerrorf(sl_errio, "could not disassemble at %ud", addr));	return str_from_cstr(buf);} BUILTIN("lsd-instsize", lsd_instsize){	uvlong addr;	int sz; 	argcount(nargs, 1);	if(sl_unlikely(!isnum(args[0])))		bthrow(type_error("addr", "num", args[0])); 	addr = tosize(args[0]);	sz = machdata->instsize(coremap, addr);	if(sz < 0)		bthrow(lerrorf(sl_errio, "could not get instruction size at %ud", addr));	return size_wrap(sz);} BUILTIN("lsd-fileline", lsd_fileline){	static char buf[1024];	uvlong addr; 	argcount(nargs, 1);	if(sl_unlikely(!isnum(args[0])))		bthrow(type_error("addr", "num", args[0])); 	addr = tosize(args[0]);	if(!fileline(buf, sizeof(buf), addr))		bthrow(lerrorf(sl_errio, "could not locate source code line at %ud", addr));	return str_from_cstr(buf);} BUILTIN("lsd-file2pc", lsd_file2pc){	uvlong addr;	char *file;	int line; 	argcount(nargs, 2);	if(sl_unlikely(!isstr(args[0])))		bthrow(type_error("file", "str", args[0]));	if(sl_unlikely(!isfixnum(args[1])))		bthrow(type_error("line", "num", args[1])); 	file = cvalue_data(args[0]);	line = numval(args[1]);	addr = file2pc(file, line);	if(addr == ~0)		bthrow(lerrorf(sl_errio, "could not find address of %s:%d", file, line));	return mk_lsdptr(addr);} BUILTIN("lsd-findsym", lsd_findsym){	Symbol s;	uvlong addr; 	argcount(nargs, 1);	if(sl_unlikely(!isnum(args[0])))		bthrow(type_error("addr", "num", args[0])); 	addr = tosize(args[0]);	if(!findsym(addr, CTEXT, &s))		bthrow(lerrorf(sl_errio, "could not locate sym near %ud", addr));	return mk_symbol(&s);}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t