Charles.Forsyth20080116-1340f4bb33e18 years agoHistory
537 lines · 9.3 KB · Brainfuck
RawDownload
implement Mdb; include "sys.m";	sys: Sys;	stderr: ref Sys->FD;	print, sprint: import sys; include "draw.m";include "string.m";	str: String;include "bufio.m";	bufio: Bufio;	Iobuf: import bufio;include "dis.m";	dis: Dis;	Inst, Type, Data, Link, Mod: import dis;	XMAGIC: import Dis;	MUSTCOMPILE, DONTCOMPILE: import Dis;	AMP, AFP, AIMM, AXXX, AIND, AMASK: import Dis;	ARM, AXNON, AXIMM, AXINF, AXINM: import Dis;	DEFB, DEFW, DEFS, DEFF, DEFA, DIND, DAPOP, DEFL: import Dis;disfile: string;m: ref Mod; Mdb: module{	init: fn(nil: ref Draw->Context, argv: list of string);}; mfd: ref Sys->FD;dot := 0;lastaddr := 0;count := 1; atoi(s: string): int{        b := 10;        if(s == nil)                return 0;        if(s[0] == '0') {                b = 8;                s = s[1:];                if(s == nil)                        return 0;                if(s[0] == 'x' || s[0] == 'X') {                        b = 16;                        s = s[1:];                }        }        n: int;        (n, nil) = str->toint(s, b);        return n;} eatws(s: string): string{	for (i := 0; i < len s; i++)		if (s[i] != ' ' && s[i] != '\t')			return s[i:];	return nil;} eatnum(s: string): string{	if(len s == 0)		return s;	while(gotnum(s) || gotalpha(s))		s = s[1:];	return s;} gotnum(s: string): int{	if(len s == 0)		return 0;	if(s[0] >= '0' && s[0] <= '9')		return 1;	else		return 0;} gotalpha(s: string): int{	if(len s == 0)		return 0;	if((s[0] >= 'a' && s[0] <= 'z') || (s[0] >= 'A' && s[0] <= 'Z'))		return 1;	else		return 0;} getexpr(s: string): (string, int, int){	ov: int;	v := 0;	op := '+';	for(;;) {		ov = v;		s = eatws(s);		if(s == nil)			return (nil, 0, 0);		if(s[0] == '.' || s[0] == '+' || s[0] == '^') {			v = dot;			s = s[1:];		} else if(s[0] == '"') {			v = lastaddr;			s = s[1:];		} else if(s[0] == '(') {			(s, v, nil) = getexpr(s[1:]);			s = s[1:];		} else if(gotnum(s)) {			v = atoi(s);			s = eatnum(s);		} else			return (s, 0, 0);		case op {		'+' => v = ov+v;		'-' => v = ov-v;		'*' => v = ov*v;		'%' => v = ov/v;		'&' => v = ov&v;		'|' => v = ov|v;		}		if(s == nil)			return (nil, v, 1);		case s[0] {		'+' or '-' or '*' or '%' or '&' or '|' =>			op = s[0]; s = s[1:];		* =>			return (eatws(s), v, 1);		}	}} lastcmd := ""; docmd(s: string){	ok: int;	n: int;	s = eatws(s);	(s, n, ok) = getexpr(s);	if(ok) {		dot = n; 		lastaddr = n;	}	count = 1;	if(s != nil && s[0] == ',') {		(s, n, ok) = getexpr(s[1:]);		if(ok)			count = n;	}	if(s == nil && (s = lastcmd) == nil) 		return;	lastcmd = s;	cmd := s[0];	case cmd {	'?' or '/' =>		case s[1] {		'w' =>			writemem(2, s[2:]);		'W' =>			writemem(4, s[2:]);		'i' =>			das();		* =>			dumpmem(s[1:], cmd);		}	'$' =>		case s[1] {		'D' =>			desc();		'h' =>			hdr();		'l' =>			link();		'i' =>			imports();		'd' =>			dat();		'H' =>			handlers();		's' =>			if(m != nil)				print("%s\n", m.srcpath);		}	'=' =>		dumpmem(s[1:], cmd);	* =>		sys->fprint(stderr, "invalid cmd: %c\n", cmd);	}} octal(n: int, d: int): string{	s: string;	do {		s = string (n%8) + s;		n /= 8;	} while(d-- > 1);	return "0" + s;} printable(c: int): string{	case c {	32 to 126 =>		return sprint("%c", c);	'\n' =>		return "\\n";	'\r' =>		return "\\r";	'\b' =>		return "\\b";	'\a' =>		return "\\a";	'\v' =>		return "\\v";	* =>		return sprint("\\x%2.2x", c);	}		} dumpmem(s: string, t: int){	n := 0;	c := count;	while(c-- > 0) for(p:=0; p<len s; p++) {		fmt := s[p];		case fmt {		'b' or 'c' or 'C' =>			n = 1;		'x' or 'd' or 'u' or 'o' =>			n = 2; 		'X' or 'D' or 'U' or 'O' =>			n = 4;		's' or 'S' or 'r' or 'R' =>			print("'%c' format not yet supported\n", fmt);			continue;		'n' =>			print("\n");			continue;		'+' =>			dot++;			continue;		'-' =>			dot--;			continue;		'^' =>			dot -= n;			continue;		* =>			print("unknown format '%c'\n", fmt);			continue;		}		b := array[n] of byte;		v: int;		if(t == '=')			v = dot;		else {			sys->seek(mfd, big dot, Sys->SEEKSTART);			sys->read(mfd, b, len b);			v = 0;			for(i := 0; i < n; i++)				v |= int b[i] << (8*i);		}		case fmt {		'c' => print("%c", v);		'C' => print("%s", printable(v));		'b' => print("%#2.2ux ", v);		'x' => print("%#4.4ux ", v);		'X' => print("%#8.8ux ", v);		'd' => print("%-4d ", v);		'D' => print("%-8d ", v);		'u' => print("%-4ud ", v);		'U' => print("%-8ud ", v);		'o' => print("%s ", octal(v, 6));		'O' => print("%s ", octal(v, 11));		}		if(t != '=')			dot += n;	}	print("\n");} writemem(n: int, s: string){	v: int;	ok: int;	s = eatws(s);	sys->seek(mfd, big dot, Sys->SEEKSTART);	for(;;) {		(s, v, ok) = getexpr(s);		if(!ok)			return;		b := array[n] of byte;		for(i := 0; i < n; i++)			b[i] = byte (v >> (8*i));		if (sys->write(mfd, b, len b) != len b)			sys->fprint(stderr, "mdb: write error: %r\n");	}} usage(){	sys->fprint(stderr, "usage: mdb [-w] file [command]\n");	raise "fail:usage";} writeable := 0; init(nil: ref Draw->Context, argv: list of string){	sys = load Sys Sys->PATH;	stderr = sys->fildes(2);	str = load String String->PATH;	if (str == nil) {		sys->fprint(stderr, "mdb: cannot load %s: %r\n", String->PATH);		raise "fail:bad module";	}	bufio = load Bufio Bufio->PATH;	if (bufio == nil) {		sys->fprint(stderr, "mdb: cannot load %s: %r\n", Bufio->PATH);		raise "fail:bad module";	}	dis = load Dis Dis->PATH;	dis->init(); 	if (len argv < 2)		usage();	if (argv != nil)		argv = tl argv;	if (argv != nil && len hd argv && (hd argv)[0] == '-') {		if (hd argv != "-w")			usage();		writeable = 1;		argv = tl argv;	}	if (argv == nil)		usage();	fname := hd argv;	argv = tl argv;	cmd := "";	if(argv != nil)		cmd = hd argv; 	oflags := Sys->OREAD;	if (writeable)		oflags = Sys->ORDWR;	mfd = sys->open(fname, oflags);	if(mfd == nil) {		sys->fprint(stderr, "mdb: cannot open %s: %r\n", fname);		raise "fail:cannot open";	}	(m, nil) = dis->loadobj(fname); 	if(cmd != nil)		docmd(cmd);	else {		stdin := bufio->fopen(sys->fildes(0), Sys->OREAD);		while ((s := stdin.gets('\n')) != nil) {			if (s[len s -1] == '\n')				s = s[0:len s - 1];			docmd(s);		}	}} link(){	if(m == nil || m.magic == 0)		return; 	for(i := 0; i < m.lsize; i++) {		l := m.links[i];		print("	link %d,%d, 0x%ux, \"%s\"\n",					l.desc, l.pc, l.sig, l.name);	}} imports(){	if(m == nil || m.magic == 0)		return; 	mi := m.imports;	for(i := 0; i < len mi; i++) {		a := mi[i];		for(j := 0; j < len a; j++) {			ai := a[j];			print("	import 0x%ux, \"%s\"\n", ai.sig, ai.name);		}	}} handlers(){	if(m == nil || m.magic == 0)		return; 	hs := m.handlers;	for(i := 0; i < len hs; i++) {		h := hs[i];		tt := -1;		for(j := 0; j < len m.types; j++) {			if(h.t == m.types[j]) {				tt = j;				break;			}		}		print("	%d-%d, o=%d, e=%d t=%d\n", h.pc1, h.pc2, h.eoff, h.ne, tt);		et := h.etab;		for(j = 0; j < len et; j++) {			e := et[j];			if(e.s == nil)				print("		%d	*\n", e.pc);			else				print("		%d	\"%s\"\n", e.pc, e.s);		}	}} desc(){	if(m == nil || m.magic == 0)		return; 	for(i := 0; i < m.tsize; i++) {		h := m.types[i];		s := sprint("	desc $%d, %d, \"", i, h.size);		for(j := 0; j < h.np; j++)			s += sprint("%.2ux", int h.map[j]);		s += "\"\n";		print("%s", s);	}} hdr(){	if(m == nil || m.magic == 0)		return;	s := sprint("%.8ux Version %d Dis VM\n", m.magic, m.magic - XMAGIC + 1);	s += sprint("%.8ux Runtime flags %s\n", m.rt, rtflag(m.rt));	s += sprint("%8d bytes per stack extent\n\n", m.ssize);  	s += sprint("%8d instructions\n", m.isize);	s += sprint("%8d data size\n", m.dsize);	s += sprint("%8d heap type descriptors\n", m.tsize);	s += sprint("%8d link directives\n", m.lsize);	s += sprint("%8d entry pc\n", m.entry);	s += sprint("%8d entry type descriptor\n\n", m.entryt); 	if(m.sign == nil)		s += "Module is Insecure\n";	print("%s", s);} rtflag(flag: int): string{	if(flag == 0)		return ""; 	s := "["; 	if(flag & MUSTCOMPILE)		s += "MustCompile";	if(flag & DONTCOMPILE) {		if(flag & MUSTCOMPILE)			s += "|";		s += "DontCompile";	}	s[len s] = ']'; 	return s;} das(){	if(m == nil || m.magic == 0)		return; 	for(i := dot;  count-- > 0 && i < m.isize; i++) {		if(i % 10 == 0)			print("#%d\n", i);		print("\t%s\n", dis->inst2s(m.inst[i]));	}} dat(){	if(m == nil || m.magic == 0)		return;	print("	var @mp, %d\n", m.types[0].size); 	s := "";	for(d := m.data; d != nil; d = tl d) {		pick dat := hd d {		Bytes =>

Lines 1–500 of 537.