xref: /plan9/sys/src/cmd/ktrace.c (revision 14cc0f535177405a84c5b73603a98e5db6674719)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier #include <mach.h>
57dd7cddfSDavid du Colombier #include <ctype.h>
67dd7cddfSDavid du Colombier 
74de34a7eSDavid du Colombier static	int	rtrace(uvlong, uvlong, uvlong);
84de34a7eSDavid du Colombier static	int	ctrace(uvlong, uvlong, uvlong);
94de34a7eSDavid du Colombier static	int	i386trace(uvlong, uvlong, uvlong);
1074f16c81SDavid du Colombier static	int	amd64trace(uvlong, uvlong, uvlong);
114de34a7eSDavid du Colombier static	uvlong	getval(uvlong);
127dd7cddfSDavid du Colombier static	void	inithdr(int);
137dd7cddfSDavid du Colombier static	void	fatal(char*, ...);
147dd7cddfSDavid du Colombier static	void	readstack(void);
157dd7cddfSDavid du Colombier 
167dd7cddfSDavid du Colombier static	Fhdr	fhdr;
177dd7cddfSDavid du Colombier static	int	interactive;
187dd7cddfSDavid du Colombier 
197dd7cddfSDavid du Colombier #define	FRAMENAME	".frame"
207dd7cddfSDavid du Colombier 
217dd7cddfSDavid du Colombier static void
usage(void)227dd7cddfSDavid du Colombier usage(void)
237dd7cddfSDavid du Colombier {
247dd7cddfSDavid du Colombier 	fprint(2, "usage: ktrace [-i] kernel pc sp [link]\n");
257dd7cddfSDavid du Colombier 	exits("usage");
267dd7cddfSDavid du Colombier }
277dd7cddfSDavid du Colombier 
287dd7cddfSDavid du Colombier static void
printaddr(char * addr,uvlong pc)294de34a7eSDavid du Colombier printaddr(char *addr, uvlong pc)
307dd7cddfSDavid du Colombier {
317dd7cddfSDavid du Colombier 	int i;
327dd7cddfSDavid du Colombier 	char *p;
337dd7cddfSDavid du Colombier 
347dd7cddfSDavid du Colombier 	/*
357dd7cddfSDavid du Colombier 	 * reformat the following.
367dd7cddfSDavid du Colombier 	 *
377dd7cddfSDavid du Colombier 	 * foo+1a1 -> src(foo+0x1a1);
387dd7cddfSDavid du Colombier 	 * 10101010 -> src(0x10101010);
397dd7cddfSDavid du Colombier 	 */
407dd7cddfSDavid du Colombier 
417dd7cddfSDavid du Colombier 	if(strlen(addr) == 8 && strchr(addr, '+') == nil){
427dd7cddfSDavid du Colombier 		for(i=0; i<8; i++)
437dd7cddfSDavid du Colombier 			if(!isxdigit(addr[i]))
447dd7cddfSDavid du Colombier 				break;
457dd7cddfSDavid du Colombier 		if(i == 8){
4674f16c81SDavid du Colombier 			print("src(%#.8llux); // 0x%s\n", pc, addr);
477dd7cddfSDavid du Colombier 			return;
487dd7cddfSDavid du Colombier 		}
497dd7cddfSDavid du Colombier 	}
507dd7cddfSDavid du Colombier 
517dd7cddfSDavid du Colombier 	if(p=strchr(addr, '+')){
527dd7cddfSDavid du Colombier 		*p++ = 0;
5374f16c81SDavid du Colombier 		print("src(%#.8llux); // %s+0x%s\n", pc, addr, p);
547dd7cddfSDavid du Colombier 	}else
5574f16c81SDavid du Colombier 		print("src(%#.8llux); // %s\n", pc, addr);
567dd7cddfSDavid du Colombier }
577dd7cddfSDavid du Colombier 
584de34a7eSDavid du Colombier static void (*fmt)(char*, uvlong) = printaddr;
597dd7cddfSDavid du Colombier 
607dd7cddfSDavid du Colombier void
main(int argc,char * argv[])617dd7cddfSDavid du Colombier main(int argc, char *argv[])
627dd7cddfSDavid du Colombier {
634de34a7eSDavid du Colombier 	int (*t)(uvlong, uvlong, uvlong);
644de34a7eSDavid du Colombier 	uvlong pc, sp, link;
657dd7cddfSDavid du Colombier 	int fd;
667dd7cddfSDavid du Colombier 
677dd7cddfSDavid du Colombier 	ARGBEGIN{
687dd7cddfSDavid du Colombier 	case 'i':
697dd7cddfSDavid du Colombier 		interactive++;
707dd7cddfSDavid du Colombier 		break;
717dd7cddfSDavid du Colombier 	default:
727dd7cddfSDavid du Colombier 		usage();
737dd7cddfSDavid du Colombier 	}ARGEND
747dd7cddfSDavid du Colombier 
757dd7cddfSDavid du Colombier 	link = 0;
767dd7cddfSDavid du Colombier 	t = ctrace;
777dd7cddfSDavid du Colombier 	switch(argc){
787dd7cddfSDavid du Colombier 	case 4:
797dd7cddfSDavid du Colombier 		t = rtrace;
804de34a7eSDavid du Colombier 		link = strtoull(argv[3], 0, 16);
817dd7cddfSDavid du Colombier 		break;
827dd7cddfSDavid du Colombier 	case 3:
837dd7cddfSDavid du Colombier 		break;
847dd7cddfSDavid du Colombier 	default:
857dd7cddfSDavid du Colombier 		usage();
867dd7cddfSDavid du Colombier 	}
874de34a7eSDavid du Colombier 	pc = strtoull(argv[1], 0, 16);
884de34a7eSDavid du Colombier 	sp = strtoull(argv[2], 0, 16);
897dd7cddfSDavid du Colombier 	if(!interactive)
907dd7cddfSDavid du Colombier 		readstack();
917dd7cddfSDavid du Colombier 
927dd7cddfSDavid du Colombier 	fd = open(argv[0], OREAD);
937dd7cddfSDavid du Colombier 	if(fd < 0)
947dd7cddfSDavid du Colombier 		fatal("can't open %s: %r", argv[0]);
957dd7cddfSDavid du Colombier 	inithdr(fd);
9680ee5cbfSDavid du Colombier 	switch(fhdr.magic){
9780ee5cbfSDavid du Colombier 	case I_MAGIC:	/* intel 386 */
987dd7cddfSDavid du Colombier 		t = i386trace;
9980ee5cbfSDavid du Colombier 		break;
10074f16c81SDavid du Colombier 	case S_MAGIC:	/* amd64 */
10174f16c81SDavid du Colombier 		t = amd64trace;
10274f16c81SDavid du Colombier 		break;
10380ee5cbfSDavid du Colombier 	case A_MAGIC:	/* 68020 */
10480ee5cbfSDavid du Colombier 	case J_MAGIC:	/* intel 960 */
10580ee5cbfSDavid du Colombier 		t = ctrace;
10680ee5cbfSDavid du Colombier 		break;
10780ee5cbfSDavid du Colombier 	case K_MAGIC:	/* sparc */
10880ee5cbfSDavid du Colombier 	case D_MAGIC:	/* amd 29000 */
10980ee5cbfSDavid du Colombier 	case V_MAGIC:	/* mips 3000 */
11080ee5cbfSDavid du Colombier 	case M_MAGIC:	/* mips 4000 */
11180ee5cbfSDavid du Colombier 	case E_MAGIC:	/* arm 7-something */
11280ee5cbfSDavid du Colombier 	case Q_MAGIC:	/* powerpc */
11380ee5cbfSDavid du Colombier 	case N_MAGIC:	/* mips 4000 LE */
11480ee5cbfSDavid du Colombier 	case L_MAGIC:	/* dec alpha */
11580ee5cbfSDavid du Colombier 		t = rtrace;
11680ee5cbfSDavid du Colombier 		break;
11780ee5cbfSDavid du Colombier 	case X_MAGIC:	/* att dsp 3210 */
118*14cc0f53SDavid du Colombier 		sysfatal("can't ktrace %s", argv[0]);
11980ee5cbfSDavid du Colombier 		break;
12080ee5cbfSDavid du Colombier 	default:
12180ee5cbfSDavid du Colombier 		fprint(2, "%s: warning: can't tell what type of stack %s uses; assuming it's %s\n",
12280ee5cbfSDavid du Colombier 			argv0, argv[0], argc == 4 ? "risc" : "cisc");
12380ee5cbfSDavid du Colombier 		break;
12480ee5cbfSDavid du Colombier 	}
1257dd7cddfSDavid du Colombier 	(*t)(pc, sp, link);
1267dd7cddfSDavid du Colombier 	exits(0);
1277dd7cddfSDavid du Colombier }
1287dd7cddfSDavid du Colombier 
1297dd7cddfSDavid du Colombier static void
inithdr(int fd)1307dd7cddfSDavid du Colombier inithdr(int fd)
1317dd7cddfSDavid du Colombier {
1327dd7cddfSDavid du Colombier 	seek(fd, 0, 0);
1337dd7cddfSDavid du Colombier 	if(!crackhdr(fd, &fhdr))
1347dd7cddfSDavid du Colombier 		fatal("read text header");
1357dd7cddfSDavid du Colombier 
1367dd7cddfSDavid du Colombier 	if(syminit(fd, &fhdr) < 0)
1377dd7cddfSDavid du Colombier 		fatal("%r\n");
1387dd7cddfSDavid du Colombier }
1397dd7cddfSDavid du Colombier 
1407dd7cddfSDavid du Colombier static int
rtrace(uvlong pc,uvlong sp,uvlong link)1414de34a7eSDavid du Colombier rtrace(uvlong pc, uvlong sp, uvlong link)
1427dd7cddfSDavid du Colombier {
1437dd7cddfSDavid du Colombier 	Symbol s, f;
1447dd7cddfSDavid du Colombier 	char buf[128];
1454de34a7eSDavid du Colombier 	uvlong oldpc;
1467dd7cddfSDavid du Colombier 	int i;
1477dd7cddfSDavid du Colombier 
1487dd7cddfSDavid du Colombier 	i = 0;
1497dd7cddfSDavid du Colombier 	while(findsym(pc, CTEXT, &s)) {
1507dd7cddfSDavid du Colombier 		if(pc == s.value)	/* at first instruction */
1517dd7cddfSDavid du Colombier 			f.value = 0;
1527dd7cddfSDavid du Colombier 		else if(findlocal(&s, FRAMENAME, &f) == 0)
1537dd7cddfSDavid du Colombier 			break;
1547dd7cddfSDavid du Colombier 
1557dd7cddfSDavid du Colombier 		symoff(buf, sizeof buf, pc, CANY);
1569a747e4fSDavid du Colombier 		fmt(buf, pc);
1577dd7cddfSDavid du Colombier 
1587dd7cddfSDavid du Colombier 		oldpc = pc;
15980ee5cbfSDavid du Colombier 		if(s.type == 'L' || s.type == 'l' || pc <= s.value+mach->pcquant){
16080ee5cbfSDavid du Colombier 			if(link == 0)
16180ee5cbfSDavid du Colombier 				fprint(2, "%s: need to supply a valid link register\n", argv0);
1627dd7cddfSDavid du Colombier 			pc = link;
16380ee5cbfSDavid du Colombier 		}else{
1647dd7cddfSDavid du Colombier 			pc = getval(sp);
1657dd7cddfSDavid du Colombier 			if(pc == 0)
1667dd7cddfSDavid du Colombier 				break;
1677dd7cddfSDavid du Colombier 		}
1687dd7cddfSDavid du Colombier 
1697dd7cddfSDavid du Colombier 		if(pc == 0 || (pc == oldpc && f.value == 0))
1707dd7cddfSDavid du Colombier 			break;
1717dd7cddfSDavid du Colombier 
1727dd7cddfSDavid du Colombier 		sp += f.value;
1737dd7cddfSDavid du Colombier 
1747dd7cddfSDavid du Colombier 		if(++i > 40)
1757dd7cddfSDavid du Colombier 			break;
1767dd7cddfSDavid du Colombier 	}
1777dd7cddfSDavid du Colombier 	return i;
1787dd7cddfSDavid du Colombier }
1797dd7cddfSDavid du Colombier 
1807dd7cddfSDavid du Colombier static int
ctrace(uvlong pc,uvlong sp,uvlong link)1814de34a7eSDavid du Colombier ctrace(uvlong pc, uvlong sp, uvlong link)
1827dd7cddfSDavid du Colombier {
1837dd7cddfSDavid du Colombier 	Symbol s;
1847dd7cddfSDavid du Colombier 	char buf[128];
1857dd7cddfSDavid du Colombier 	int found;
1864de34a7eSDavid du Colombier 	uvlong opc, moved;
1874de34a7eSDavid du Colombier 	long j;
1887dd7cddfSDavid du Colombier 
1897dd7cddfSDavid du Colombier 	USED(link);
1907dd7cddfSDavid du Colombier 	j = 0;
1917dd7cddfSDavid du Colombier 	opc = 0;
1927dd7cddfSDavid du Colombier 	while(pc && opc != pc) {
1937dd7cddfSDavid du Colombier 		moved = pc2sp(pc);
1944de34a7eSDavid du Colombier 		if (moved == ~0){
19574f16c81SDavid du Colombier 			print("pc2sp(%#.8llux) = -1 %r\n", pc);
1967dd7cddfSDavid du Colombier 			break;
1977dd7cddfSDavid du Colombier 		}
1987dd7cddfSDavid du Colombier 		found = findsym(pc, CTEXT, &s);
1997dd7cddfSDavid du Colombier 		if (!found){
2007dd7cddfSDavid du Colombier 			print("findsym fails\n");
2017dd7cddfSDavid du Colombier 			break;
2027dd7cddfSDavid du Colombier 		}
2037dd7cddfSDavid du Colombier 		symoff(buf, sizeof buf, pc, CANY);
2049a747e4fSDavid du Colombier 		fmt(buf, pc);
2057dd7cddfSDavid du Colombier 
2067dd7cddfSDavid du Colombier 		sp += moved;
2077dd7cddfSDavid du Colombier 		opc = pc;
2087dd7cddfSDavid du Colombier 		pc = getval(sp);
2097dd7cddfSDavid du Colombier 		if(pc == 0)
2107dd7cddfSDavid du Colombier 			break;
2117dd7cddfSDavid du Colombier 		sp += mach->szaddr;	/*assumes address size = stack width*/
2127dd7cddfSDavid du Colombier 		if(++j > 40)
2137dd7cddfSDavid du Colombier 			break;
2147dd7cddfSDavid du Colombier 	}
2157dd7cddfSDavid du Colombier 	return j;
2167dd7cddfSDavid du Colombier }
2177dd7cddfSDavid du Colombier 
2187dd7cddfSDavid du Colombier static int
i386trace(uvlong pc,uvlong sp,uvlong link)2194de34a7eSDavid du Colombier i386trace(uvlong pc, uvlong sp, uvlong link)
2207dd7cddfSDavid du Colombier {
2217dd7cddfSDavid du Colombier 	int i;
2224de34a7eSDavid du Colombier 	uvlong osp;
2237dd7cddfSDavid du Colombier 	Symbol s, f;
2247dd7cddfSDavid du Colombier 	char buf[128];
2257dd7cddfSDavid du Colombier 
2267dd7cddfSDavid du Colombier 	USED(link);
2277dd7cddfSDavid du Colombier 	i = 0;
2287dd7cddfSDavid du Colombier 	osp = 0;
2297dd7cddfSDavid du Colombier 	while(findsym(pc, CTEXT, &s)) {
2307dd7cddfSDavid du Colombier 
2317dd7cddfSDavid du Colombier 		symoff(buf, sizeof buf, pc, CANY);
2329a747e4fSDavid du Colombier 		fmt(buf, pc);
2337dd7cddfSDavid du Colombier 
2344de34a7eSDavid du Colombier //XXX		s.value &= ~(uintptr)0;
2357dd7cddfSDavid du Colombier 		if(pc != s.value) {	/* not at first instruction */
2367dd7cddfSDavid du Colombier 			if(findlocal(&s, FRAMENAME, &f) == 0)
2377dd7cddfSDavid du Colombier 				break;
2387dd7cddfSDavid du Colombier 			sp += f.value-mach->szaddr;
2399a747e4fSDavid du Colombier 		}else if(strcmp(s.name, "forkret") == 0){
2404de34a7eSDavid du Colombier //XXX
24174f16c81SDavid du Colombier 			print("//passing interrupt frame; last pc found at sp=%#llux\n", osp);
2424de34a7eSDavid du Colombier 
2439a747e4fSDavid du Colombier 			sp +=  15 * mach->szaddr;		/* pop interrupt frame */
2447dd7cddfSDavid du Colombier 		}
2457dd7cddfSDavid du Colombier 
2467dd7cddfSDavid du Colombier 		pc = getval(sp);
2474de34a7eSDavid du Colombier //XXX
2489a747e4fSDavid du Colombier 		if(pc == 0 && strcmp(s.name, "forkret") == 0){
2499a747e4fSDavid du Colombier 			sp += 3 * mach->szaddr;			/* pop iret eip, cs, eflags */
25074f16c81SDavid du Colombier 			print("//guessing call through invalid pointer, try again at sp=%#llux\n", sp);
2519a747e4fSDavid du Colombier 			s.name = "";
2529a747e4fSDavid du Colombier 			pc = getval(sp);
2539a747e4fSDavid du Colombier 		}
2549a747e4fSDavid du Colombier 		if(pc == 0) {
25574f16c81SDavid du Colombier 			print("//didn't find pc at sp=%#llux, last pc found at sp=%#llux\n", sp, osp);
2567dd7cddfSDavid du Colombier 			break;
2579a747e4fSDavid du Colombier 		}
2589a747e4fSDavid du Colombier 		osp = sp;
2597dd7cddfSDavid du Colombier 
2607dd7cddfSDavid du Colombier 		sp += mach->szaddr;
2614de34a7eSDavid du Colombier //XXX
2629a747e4fSDavid du Colombier 		if(strcmp(s.name, "forkret") == 0)
2639a747e4fSDavid du Colombier 			sp += 2 * mach->szaddr;			/* pop iret cs, eflags */
2647dd7cddfSDavid du Colombier 
2657dd7cddfSDavid du Colombier 		if(++i > 40)
2667dd7cddfSDavid du Colombier 			break;
2677dd7cddfSDavid du Colombier 	}
2687dd7cddfSDavid du Colombier 	return i;
2697dd7cddfSDavid du Colombier }
2707dd7cddfSDavid du Colombier 
27174f16c81SDavid du Colombier static int
amd64trace(uvlong pc,uvlong sp,uvlong link)27274f16c81SDavid du Colombier amd64trace(uvlong pc, uvlong sp, uvlong link)
27374f16c81SDavid du Colombier {
27474f16c81SDavid du Colombier 	int i, isintrr;
27574f16c81SDavid du Colombier 	uvlong osp;
27674f16c81SDavid du Colombier 	Symbol s, f;
27774f16c81SDavid du Colombier 	char buf[128];
27874f16c81SDavid du Colombier 
27974f16c81SDavid du Colombier 	USED(link);
28074f16c81SDavid du Colombier 	i = 0;
28174f16c81SDavid du Colombier 	osp = 0;
28274f16c81SDavid du Colombier 	while(findsym(pc, CTEXT, &s)) {
28374f16c81SDavid du Colombier 
28474f16c81SDavid du Colombier 		symoff(buf, sizeof buf, pc, CANY);
28574f16c81SDavid du Colombier 		fmt(buf, pc);
28674f16c81SDavid du Colombier 
28774f16c81SDavid du Colombier 		if(strcmp(s.name, "_intrr") == 0)
28874f16c81SDavid du Colombier 			isintrr = 1;
28974f16c81SDavid du Colombier 		else
29074f16c81SDavid du Colombier 			isintrr = 0;
29174f16c81SDavid du Colombier 		if(pc != s.value) {	/* not at first instruction */
29274f16c81SDavid du Colombier 			if(findlocal(&s, FRAMENAME, &f) == 0)
29374f16c81SDavid du Colombier 				break;
29474f16c81SDavid du Colombier 			sp += f.value-mach->szaddr;
29574f16c81SDavid du Colombier 		}
29674f16c81SDavid du Colombier 		else if(isintrr){
29774f16c81SDavid du Colombier 			print("//passing interrupt frame; last pc found at sp=%#llux\n", osp);
29874f16c81SDavid du Colombier 			/*
29974f16c81SDavid du Colombier 			 * Pop interrupt frame (ureg.h) up to the IP value.
30074f16c81SDavid du Colombier 			 */
30174f16c81SDavid du Colombier 			sp += 19 * mach->szaddr;
30274f16c81SDavid du Colombier 		}
30374f16c81SDavid du Colombier 
30474f16c81SDavid du Colombier 		pc = getval(sp);
30574f16c81SDavid du Colombier 		if(pc == 0 && isintrr){
30674f16c81SDavid du Colombier 			/*
30774f16c81SDavid du Colombier 			 * Pop IP, CS and FLAGS to get to the SP.
30874f16c81SDavid du Colombier 			 * The AMD64 aligns the interrupt stack on
30974f16c81SDavid du Colombier 			 * a 16-byte boundary so have the get the
31074f16c81SDavid du Colombier 			 * SP from the saved frame.
31174f16c81SDavid du Colombier 			 */
31274f16c81SDavid du Colombier 			sp += 3 * mach->szaddr;
31374f16c81SDavid du Colombier 			print("//guessing call through invalid pointer; try again at sp=%#llux\n", sp);
31474f16c81SDavid du Colombier 			s.name = "";
31574f16c81SDavid du Colombier 			sp = getval(sp);
31674f16c81SDavid du Colombier 			pc = getval(sp);
31774f16c81SDavid du Colombier 		}
31874f16c81SDavid du Colombier 		if(pc == 0) {
31974f16c81SDavid du Colombier 			print("//didn't find pc at sp=%#llux, last pc found at sp=%#llux\n", sp, osp);
32074f16c81SDavid du Colombier 			break;
32174f16c81SDavid du Colombier 		}
32274f16c81SDavid du Colombier 		osp = sp;
32374f16c81SDavid du Colombier 
32474f16c81SDavid du Colombier 		if(!isintrr)
32574f16c81SDavid du Colombier 			sp += mach->szaddr;
32674f16c81SDavid du Colombier 
32774f16c81SDavid du Colombier 		if(++i > 40)
32874f16c81SDavid du Colombier 			break;
32974f16c81SDavid du Colombier 	}
33074f16c81SDavid du Colombier 	return i;
33174f16c81SDavid du Colombier }
33274f16c81SDavid du Colombier 
3337dd7cddfSDavid du Colombier int naddr;
3344de34a7eSDavid du Colombier uvlong addr[1024];
3354de34a7eSDavid du Colombier uvlong val[1024];
3367dd7cddfSDavid du Colombier 
3377dd7cddfSDavid du Colombier static void
putval(uvlong a,uvlong v)3384de34a7eSDavid du Colombier putval(uvlong a, uvlong v)
3397dd7cddfSDavid du Colombier {
3407dd7cddfSDavid du Colombier 	if(naddr < nelem(addr)){
3417dd7cddfSDavid du Colombier 		addr[naddr] = a;
3427dd7cddfSDavid du Colombier 		val[naddr] = v;
3437dd7cddfSDavid du Colombier 		naddr++;
3447dd7cddfSDavid du Colombier 	}
3457dd7cddfSDavid du Colombier }
3467dd7cddfSDavid du Colombier 
3477dd7cddfSDavid du Colombier static void
readstack(void)3487dd7cddfSDavid du Colombier readstack(void)
3497dd7cddfSDavid du Colombier {
3507dd7cddfSDavid du Colombier 	Biobuf b;
3517dd7cddfSDavid du Colombier 	char *p;
3527dd7cddfSDavid du Colombier 	char *f[64];
3537dd7cddfSDavid du Colombier 	int nf, i;
3547dd7cddfSDavid du Colombier 
3557dd7cddfSDavid du Colombier 	Binit(&b, 0, OREAD);
3567dd7cddfSDavid du Colombier 	while(p=Brdline(&b, '\n')){
3577dd7cddfSDavid du Colombier 		p[Blinelen(&b)-1] = 0;
3587dd7cddfSDavid du Colombier 		nf = tokenize(p, f, nelem(f));
3597dd7cddfSDavid du Colombier 		for(i=0; i<nf; i++){
3607dd7cddfSDavid du Colombier 			if(p=strchr(f[i], '=')){
3617dd7cddfSDavid du Colombier 				*p++ = 0;
3624de34a7eSDavid du Colombier 				putval(strtoull(f[i], 0, 16), strtoull(p, 0, 16));
3637dd7cddfSDavid du Colombier 			}
3647dd7cddfSDavid du Colombier 		}
3657dd7cddfSDavid du Colombier 	}
3667dd7cddfSDavid du Colombier }
3677dd7cddfSDavid du Colombier 
3684de34a7eSDavid du Colombier static uvlong
getval(uvlong a)3694de34a7eSDavid du Colombier getval(uvlong a)
3707dd7cddfSDavid du Colombier {
3717dd7cddfSDavid du Colombier 	char buf[256];
3727dd7cddfSDavid du Colombier 	int i, n;
37374f16c81SDavid du Colombier 	uvlong r;
3747dd7cddfSDavid du Colombier 
3757dd7cddfSDavid du Colombier 	if(interactive){
37674f16c81SDavid du Colombier 		print("// data at %#8.8llux? ", a);
3777dd7cddfSDavid du Colombier 		n = read(0, buf, sizeof(buf)-1);
3787dd7cddfSDavid du Colombier 		if(n <= 0)
3797dd7cddfSDavid du Colombier 			return 0;
3807dd7cddfSDavid du Colombier 		buf[n] = '\0';
38174f16c81SDavid du Colombier 		r = strtoull(buf, 0, 16);
3827dd7cddfSDavid du Colombier 	}else{
38374f16c81SDavid du Colombier 		r = 0;
3847dd7cddfSDavid du Colombier 		for(i=0; i<naddr; i++)
3857dd7cddfSDavid du Colombier 			if(addr[i] == a)
38674f16c81SDavid du Colombier 				r = val[i];
3877dd7cddfSDavid du Colombier 	}
38874f16c81SDavid du Colombier 
38974f16c81SDavid du Colombier 	return r;
3907dd7cddfSDavid du Colombier }
3917dd7cddfSDavid du Colombier 
3927dd7cddfSDavid du Colombier static void
fatal(char * fmt,...)3937dd7cddfSDavid du Colombier fatal(char *fmt, ...)
3947dd7cddfSDavid du Colombier {
3957dd7cddfSDavid du Colombier 	char buf[4096];
3967dd7cddfSDavid du Colombier 	va_list arg;
3977dd7cddfSDavid du Colombier 
3987dd7cddfSDavid du Colombier 	va_start(arg, fmt);
3999a747e4fSDavid du Colombier 	vseprint(buf, buf+sizeof(buf), fmt, arg);
4007dd7cddfSDavid du Colombier 	va_end(arg);
4017dd7cddfSDavid du Colombier 	fprint(2, "ktrace: %s\n", buf);
4027dd7cddfSDavid du Colombier 	exits(buf);
4037dd7cddfSDavid du Colombier }
404