xref: /plan9/sys/src/cmd/db/print.c (revision 4de34a7edde43207e841ec91ecd12e6cf5f5ebe7)
13e12c5d1SDavid du Colombier /*
23e12c5d1SDavid du Colombier  *
33e12c5d1SDavid du Colombier  *	debugger
43e12c5d1SDavid du Colombier  *
53e12c5d1SDavid du Colombier  */
63e12c5d1SDavid du Colombier #include "defs.h"
73e12c5d1SDavid du Colombier #include "fns.h"
83e12c5d1SDavid du Colombier 
93e12c5d1SDavid du Colombier extern	int	infile;
103e12c5d1SDavid du Colombier extern	int	outfile;
113e12c5d1SDavid du Colombier extern	int	maxpos;
123e12c5d1SDavid du Colombier 
133e12c5d1SDavid du Colombier /* general printing routines ($) */
143e12c5d1SDavid du Colombier 
153e12c5d1SDavid du Colombier char	*Ipath = INCDIR;
16219b2ee8SDavid du Colombier static	int	tracetype;
17219b2ee8SDavid du Colombier static void	printfp(Map*, int);
18219b2ee8SDavid du Colombier 
19219b2ee8SDavid du Colombier /*
20219b2ee8SDavid du Colombier  *	callback on stack trace
21219b2ee8SDavid du Colombier  */
22219b2ee8SDavid du Colombier static void
ptrace(Map * map,uvlong pc,uvlong sp,Symbol * sym)23*4de34a7eSDavid du Colombier ptrace(Map *map, uvlong pc, uvlong sp, Symbol *sym)
24219b2ee8SDavid du Colombier {
25219b2ee8SDavid du Colombier 	char buf[512];
26219b2ee8SDavid du Colombier 
27219b2ee8SDavid du Colombier 	USED(map);
28219b2ee8SDavid du Colombier 	dprint("%s(", sym->name);
29219b2ee8SDavid du Colombier 	printparams(sym, sp);
30219b2ee8SDavid du Colombier 	dprint(") ");
31219b2ee8SDavid du Colombier 	printsource(sym->value);
32219b2ee8SDavid du Colombier 	dprint(" called from ");
33219b2ee8SDavid du Colombier 	symoff(buf, 512, pc, CTEXT);
34219b2ee8SDavid du Colombier 	dprint("%s ", buf);
35219b2ee8SDavid du Colombier 	printsource(pc);
36219b2ee8SDavid du Colombier 	dprint("\n");
37219b2ee8SDavid du Colombier 	if(tracetype == 'C')
38219b2ee8SDavid du Colombier 		printlocals(sym, sp);
39219b2ee8SDavid du Colombier }
403e12c5d1SDavid du Colombier 
413e12c5d1SDavid du Colombier void
printtrace(int modif)423e12c5d1SDavid du Colombier printtrace(int modif)
433e12c5d1SDavid du Colombier {
443e12c5d1SDavid du Colombier 	int i;
45*4de34a7eSDavid du Colombier 	uvlong pc, sp, link;
46*4de34a7eSDavid du Colombier 	ulong w;
473e12c5d1SDavid du Colombier 	BKPT *bk;
483e12c5d1SDavid du Colombier 	Symbol s;
493e12c5d1SDavid du Colombier 	int stack;
503e12c5d1SDavid du Colombier 	char *fname;
51219b2ee8SDavid du Colombier 	char buf[512];
523e12c5d1SDavid du Colombier 
533e12c5d1SDavid du Colombier 	if (cntflg==0)
543e12c5d1SDavid du Colombier 		cntval = -1;
553e12c5d1SDavid du Colombier 	switch (modif) {
563e12c5d1SDavid du Colombier 
573e12c5d1SDavid du Colombier 	case '<':
583e12c5d1SDavid du Colombier 		if (cntval == 0) {
593e12c5d1SDavid du Colombier 			while (readchar() != EOR)
603e12c5d1SDavid du Colombier 				;
613e12c5d1SDavid du Colombier 			reread();
623e12c5d1SDavid du Colombier 			break;
633e12c5d1SDavid du Colombier 		}
643e12c5d1SDavid du Colombier 		if (rdc() == '<')
653e12c5d1SDavid du Colombier 			stack = 1;
663e12c5d1SDavid du Colombier 		else {
673e12c5d1SDavid du Colombier 			stack = 0;
683e12c5d1SDavid du Colombier 			reread();
693e12c5d1SDavid du Colombier 		}
703e12c5d1SDavid du Colombier 		fname = getfname();
713e12c5d1SDavid du Colombier 		redirin(stack, fname);
723e12c5d1SDavid du Colombier 		break;
733e12c5d1SDavid du Colombier 
743e12c5d1SDavid du Colombier 	case '>':
753e12c5d1SDavid du Colombier 		fname = getfname();
763e12c5d1SDavid du Colombier 		redirout(fname);
773e12c5d1SDavid du Colombier 		break;
783e12c5d1SDavid du Colombier 
793e12c5d1SDavid du Colombier 	case 'a':
807dd7cddfSDavid du Colombier 		attachprocess();
813e12c5d1SDavid du Colombier 		break;
823e12c5d1SDavid du Colombier 
833e12c5d1SDavid du Colombier 	case 'k':
843e12c5d1SDavid du Colombier 		kmsys();
853e12c5d1SDavid du Colombier 		break;
863e12c5d1SDavid du Colombier 
873e12c5d1SDavid du Colombier 	case 'q':
883e12c5d1SDavid du Colombier 	case 'Q':
893e12c5d1SDavid du Colombier 		done();
903e12c5d1SDavid du Colombier 
913e12c5d1SDavid du Colombier 	case 'w':
923e12c5d1SDavid du Colombier 		maxpos=(adrflg?adrval:MAXPOS);
933e12c5d1SDavid du Colombier 		break;
943e12c5d1SDavid du Colombier 
953e12c5d1SDavid du Colombier 	case 'S':
963e12c5d1SDavid du Colombier 		printsym();
973e12c5d1SDavid du Colombier 		break;
983e12c5d1SDavid du Colombier 
993e12c5d1SDavid du Colombier 	case 's':
1003e12c5d1SDavid du Colombier 		maxoff=(adrflg?adrval:MAXOFF);
1013e12c5d1SDavid du Colombier 		break;
1023e12c5d1SDavid du Colombier 
1033e12c5d1SDavid du Colombier 	case 'm':
1043e12c5d1SDavid du Colombier 		printmap("? map", symmap);
1053e12c5d1SDavid du Colombier 		printmap("/ map", cormap);
1063e12c5d1SDavid du Colombier 		break;
1073e12c5d1SDavid du Colombier 
1083e12c5d1SDavid du Colombier 	case 0:
1093e12c5d1SDavid du Colombier 	case '?':
1103e12c5d1SDavid du Colombier 		if (pid)
1113e12c5d1SDavid du Colombier 			dprint("pid = %d\n",pid);
1123e12c5d1SDavid du Colombier 		else
1133e12c5d1SDavid du Colombier 			prints("no process\n");
1143e12c5d1SDavid du Colombier 		flushbuf();
1153e12c5d1SDavid du Colombier 
1163e12c5d1SDavid du Colombier 	case 'r':
1173e12c5d1SDavid du Colombier 	case 'R':
1183e12c5d1SDavid du Colombier 		printregs(modif);
1193e12c5d1SDavid du Colombier 		return;
1203e12c5d1SDavid du Colombier 
1213e12c5d1SDavid du Colombier 	case 'f':
1223e12c5d1SDavid du Colombier 	case 'F':
123219b2ee8SDavid du Colombier 		printfp(cormap, modif);
1243e12c5d1SDavid du Colombier 		return;
1253e12c5d1SDavid du Colombier 
1263e12c5d1SDavid du Colombier 	case 'c':
1273e12c5d1SDavid du Colombier 	case 'C':
128219b2ee8SDavid du Colombier 		tracetype = modif;
129219b2ee8SDavid du Colombier 		if (machdata->ctrace) {
130*4de34a7eSDavid du Colombier 			if (adrflg) {
131*4de34a7eSDavid du Colombier 				/*
132*4de34a7eSDavid du Colombier 				 * trace from jmpbuf for multi-threaded code.
133*4de34a7eSDavid du Colombier 				 * assume sp and pc are in adjacent locations
134*4de34a7eSDavid du Colombier 				 * and mach->szaddr in size.
135*4de34a7eSDavid du Colombier 				 */
136*4de34a7eSDavid du Colombier 				if (geta(cormap, adrval, &sp) < 0 ||
137*4de34a7eSDavid du Colombier 					geta(cormap, adrval+mach->szaddr, &pc) < 0)
138219b2ee8SDavid du Colombier 						error("%r");
139219b2ee8SDavid du Colombier 			} else {
140219b2ee8SDavid du Colombier 				sp = rget(cormap, mach->sp);
141219b2ee8SDavid du Colombier 				pc = rget(cormap, mach->pc);
142219b2ee8SDavid du Colombier 			}
143219b2ee8SDavid du Colombier 			if(mach->link)
144219b2ee8SDavid du Colombier 				link = rget(cormap, mach->link);
145219b2ee8SDavid du Colombier 			else
146219b2ee8SDavid du Colombier 				link = 0;
147219b2ee8SDavid du Colombier 			if (machdata->ctrace(cormap, pc, sp, link, ptrace) <= 0)
148219b2ee8SDavid du Colombier 				error("no stack frame");
149219b2ee8SDavid du Colombier 		}
1503e12c5d1SDavid du Colombier 		break;
1513e12c5d1SDavid du Colombier 
1523e12c5d1SDavid du Colombier 		/*print externals*/
1533e12c5d1SDavid du Colombier 	case 'e':
1543e12c5d1SDavid du Colombier 		for (i = 0; globalsym(&s, i); i++) {
155*4de34a7eSDavid du Colombier 			if (get4(cormap, s.value, &w) > 0)
156*4de34a7eSDavid du Colombier 				dprint("%s/%12t%#lux\n", s.name, w);
1573e12c5d1SDavid du Colombier 		}
1583e12c5d1SDavid du Colombier 		break;
1593e12c5d1SDavid du Colombier 
1603e12c5d1SDavid du Colombier 		/*print breakpoints*/
1613e12c5d1SDavid du Colombier 	case 'b':
1623e12c5d1SDavid du Colombier 	case 'B':
1633e12c5d1SDavid du Colombier 		for (bk=bkpthead; bk; bk=bk->nxtbkpt)
1643e12c5d1SDavid du Colombier 			if (bk->flag) {
165219b2ee8SDavid du Colombier 				symoff(buf, 512, (WORD)bk->loc, CTEXT);
166219b2ee8SDavid du Colombier 				dprint(buf);
1673e12c5d1SDavid du Colombier 				if (bk->count != 1)
1683e12c5d1SDavid du Colombier 					dprint(",%d", bk->count);
1693e12c5d1SDavid du Colombier 				dprint(":%c %s", bk->flag == BKPTTMP ? 'B' : 'b', bk->comm);
1703e12c5d1SDavid du Colombier 			}
1713e12c5d1SDavid du Colombier 		break;
1723e12c5d1SDavid du Colombier 
1733e12c5d1SDavid du Colombier 	case 'M':
1743e12c5d1SDavid du Colombier 		fname = getfname();
1753e12c5d1SDavid du Colombier 		if (machbyname(fname) == 0)
1763e12c5d1SDavid du Colombier 			dprint("unknown name\n");;
1773e12c5d1SDavid du Colombier 		break;
1783e12c5d1SDavid du Colombier 	default:
1793e12c5d1SDavid du Colombier 		error("bad `$' command");
1803e12c5d1SDavid du Colombier 	}
1813e12c5d1SDavid du Colombier 
1823e12c5d1SDavid du Colombier }
1833e12c5d1SDavid du Colombier 
1843e12c5d1SDavid du Colombier char *
getfname(void)1853e12c5d1SDavid du Colombier getfname(void)
1863e12c5d1SDavid du Colombier {
1873e12c5d1SDavid du Colombier 	static char fname[ARB];
1883e12c5d1SDavid du Colombier 	char *p;
1893e12c5d1SDavid du Colombier 
1903e12c5d1SDavid du Colombier 	if (rdc() == EOR) {
1913e12c5d1SDavid du Colombier 		reread();
1923e12c5d1SDavid du Colombier 		return (0);
1933e12c5d1SDavid du Colombier 	}
1943e12c5d1SDavid du Colombier 	p = fname;
1953e12c5d1SDavid du Colombier 	do {
1963e12c5d1SDavid du Colombier 		*p++ = lastc;
1973e12c5d1SDavid du Colombier 		if (p >= &fname[ARB-1])
1983e12c5d1SDavid du Colombier 			error("filename too long");
1993e12c5d1SDavid du Colombier 	} while (rdc() != EOR);
2003e12c5d1SDavid du Colombier 	*p = 0;
2013e12c5d1SDavid du Colombier 	reread();
2023e12c5d1SDavid du Colombier 	return (fname);
2033e12c5d1SDavid du Colombier }
2043e12c5d1SDavid du Colombier 
205219b2ee8SDavid du Colombier static void
printfp(Map * map,int modif)206219b2ee8SDavid du Colombier printfp(Map *map, int modif)
207219b2ee8SDavid du Colombier {
208219b2ee8SDavid du Colombier 	Reglist *rp;
209219b2ee8SDavid du Colombier 	int i;
210219b2ee8SDavid du Colombier 	int ret;
211219b2ee8SDavid du Colombier 	char buf[512];
212219b2ee8SDavid du Colombier 
213219b2ee8SDavid du Colombier 	for (i = 0, rp = mach->reglist; rp->rname; rp += ret) {
214219b2ee8SDavid du Colombier 		ret = 1;
215219b2ee8SDavid du Colombier 		if (!(rp->rflags&RFLT))
216219b2ee8SDavid du Colombier 			continue;
217219b2ee8SDavid du Colombier 		ret = fpformat(map, rp, buf, sizeof(buf), modif);
218219b2ee8SDavid du Colombier 		if (ret < 0) {
219219b2ee8SDavid du Colombier 			werrstr("Register %s: %r", rp->rname);
220219b2ee8SDavid du Colombier 			error("%r");
221219b2ee8SDavid du Colombier 		}
222219b2ee8SDavid du Colombier 			/* double column print */
223219b2ee8SDavid du Colombier 		if (i&0x01)
224219b2ee8SDavid du Colombier 			dprint("%40t%-8s%-12s\n", rp->rname, buf);
225219b2ee8SDavid du Colombier 		else
226219b2ee8SDavid du Colombier 			dprint("\t%-8s%-12s", rp->rname, buf);
227219b2ee8SDavid du Colombier 		i++;
228219b2ee8SDavid du Colombier 	}
229219b2ee8SDavid du Colombier }
230219b2ee8SDavid du Colombier 
2313e12c5d1SDavid du Colombier void
redirin(int stack,char * file)2323e12c5d1SDavid du Colombier redirin(int stack, char *file)
2333e12c5d1SDavid du Colombier {
234*4de34a7eSDavid du Colombier 	char *pfile;
2353e12c5d1SDavid du Colombier 
2363e12c5d1SDavid du Colombier 	if (file == 0) {
2373e12c5d1SDavid du Colombier 		iclose(-1, 0);
2383e12c5d1SDavid du Colombier 		return;
2393e12c5d1SDavid du Colombier 	}
2403e12c5d1SDavid du Colombier 	iclose(stack, 0);
2413e12c5d1SDavid du Colombier 	if ((infile = open(file, 0)) < 0) {
242*4de34a7eSDavid du Colombier 		pfile = smprint("%s/%s", Ipath, file);
243*4de34a7eSDavid du Colombier 		infile = open(pfile, 0);
244*4de34a7eSDavid du Colombier 		free(pfile);
245*4de34a7eSDavid du Colombier 		if(infile < 0) {
2463e12c5d1SDavid du Colombier 			infile = STDIN;
2473e12c5d1SDavid du Colombier 			error("cannot open");
2483e12c5d1SDavid du Colombier 		}
2493e12c5d1SDavid du Colombier 	}
2503e12c5d1SDavid du Colombier }
2513e12c5d1SDavid du Colombier 
2523e12c5d1SDavid du Colombier void
printmap(char * s,Map * map)253219b2ee8SDavid du Colombier printmap(char *s, Map *map)
2543e12c5d1SDavid du Colombier {
255219b2ee8SDavid du Colombier 	int i;
256219b2ee8SDavid du Colombier 
257219b2ee8SDavid du Colombier 	if (!map)
258219b2ee8SDavid du Colombier 		return;
259219b2ee8SDavid du Colombier 	if (map == symmap)
2603e12c5d1SDavid du Colombier 		dprint("%s%12t`%s'\n", s, fsym < 0 ? "-" : symfil);
261219b2ee8SDavid du Colombier 	else if (map == cormap)
2623e12c5d1SDavid du Colombier 		dprint("%s%12t`%s'\n", s, fcor < 0 ? "-" : corfil);
2633e12c5d1SDavid du Colombier 	else
2643e12c5d1SDavid du Colombier 		dprint("%s\n", s);
265219b2ee8SDavid du Colombier 	for (i = 0; i < map->nsegs; i++) {
266219b2ee8SDavid du Colombier 		if (map->seg[i].inuse)
267*4de34a7eSDavid du Colombier 			dprint("%s%8t%-16#llux %-16#llux %-16#llux\n",
268*4de34a7eSDavid du Colombier 				map->seg[i].name, map->seg[i].b,
269*4de34a7eSDavid du Colombier 				map->seg[i].e, map->seg[i].f);
270219b2ee8SDavid du Colombier 	}
2713e12c5d1SDavid du Colombier }
2723e12c5d1SDavid du Colombier 
2733e12c5d1SDavid du Colombier /*
2743e12c5d1SDavid du Colombier  *	dump the raw symbol table
2753e12c5d1SDavid du Colombier  */
2763e12c5d1SDavid du Colombier void
printsym(void)2773e12c5d1SDavid du Colombier printsym(void)
2783e12c5d1SDavid du Colombier {
2793e12c5d1SDavid du Colombier 	int i;
2803e12c5d1SDavid du Colombier 	Sym *sp;
2813e12c5d1SDavid du Colombier 
2823e12c5d1SDavid du Colombier 	for (i = 0; sp = getsym(i); i++) {
2833e12c5d1SDavid du Colombier 		switch(sp->type) {
2843e12c5d1SDavid du Colombier 		case 't':
2853e12c5d1SDavid du Colombier 		case 'l':
286*4de34a7eSDavid du Colombier 			dprint("%16#llux t %s\n", sp->value, sp->name);
2873e12c5d1SDavid du Colombier 			break;
2883e12c5d1SDavid du Colombier 		case 'T':
2893e12c5d1SDavid du Colombier 		case 'L':
290*4de34a7eSDavid du Colombier 			dprint("%16#llux T %s\n", sp->value, sp->name);
2913e12c5d1SDavid du Colombier 			break;
2923e12c5d1SDavid du Colombier 		case 'D':
2933e12c5d1SDavid du Colombier 		case 'd':
2943e12c5d1SDavid du Colombier 		case 'B':
2953e12c5d1SDavid du Colombier 		case 'b':
2963e12c5d1SDavid du Colombier 		case 'a':
2973e12c5d1SDavid du Colombier 		case 'p':
2983e12c5d1SDavid du Colombier 		case 'm':
299*4de34a7eSDavid du Colombier 			dprint("%16#llux %c %s\n", sp->value, sp->type, sp->name);
3003e12c5d1SDavid du Colombier 			break;
3013e12c5d1SDavid du Colombier 		default:
3023e12c5d1SDavid du Colombier 			break;
3033e12c5d1SDavid du Colombier 		}
3043e12c5d1SDavid du Colombier 	}
3053e12c5d1SDavid du Colombier }
3063e12c5d1SDavid du Colombier 
3073e12c5d1SDavid du Colombier #define	STRINGSZ	128
3083e12c5d1SDavid du Colombier 
3093e12c5d1SDavid du Colombier /*
3103e12c5d1SDavid du Colombier  *	print the value of dot as file:line
3113e12c5d1SDavid du Colombier  */
3123e12c5d1SDavid du Colombier void
printsource(ADDR dot)313*4de34a7eSDavid du Colombier printsource(ADDR dot)
3143e12c5d1SDavid du Colombier {
3153e12c5d1SDavid du Colombier 	char str[STRINGSZ];
3163e12c5d1SDavid du Colombier 
3173e12c5d1SDavid du Colombier 	if (fileline(str, STRINGSZ, dot))
3183e12c5d1SDavid du Colombier 		dprint("%s", str);
3193e12c5d1SDavid du Colombier }
3203e12c5d1SDavid du Colombier 
3213e12c5d1SDavid du Colombier void
printpc(void)3223e12c5d1SDavid du Colombier printpc(void)
3233e12c5d1SDavid du Colombier {
324219b2ee8SDavid du Colombier 	char buf[512];
325219b2ee8SDavid du Colombier 
326*4de34a7eSDavid du Colombier 	dot = rget(cormap, mach->pc);
3273e12c5d1SDavid du Colombier 	if(dot){
328219b2ee8SDavid du Colombier 		printsource((long)dot);
3293e12c5d1SDavid du Colombier 		printc(' ');
330219b2ee8SDavid du Colombier 		symoff(buf, sizeof(buf), (long)dot, CTEXT);
3317dd7cddfSDavid du Colombier 		dprint("%s/", buf);
3327dd7cddfSDavid du Colombier 		if (machdata->das(cormap, dot, 'i', buf, sizeof(buf)) < 0)
333219b2ee8SDavid du Colombier 			error("%r");
334219b2ee8SDavid du Colombier 		dprint("%16t%s\n", buf);
3353e12c5d1SDavid du Colombier 	}
3363e12c5d1SDavid du Colombier }
3373e12c5d1SDavid du Colombier 
3383e12c5d1SDavid du Colombier void
printlocals(Symbol * fn,ADDR fp)3393e12c5d1SDavid du Colombier printlocals(Symbol *fn, ADDR fp)
3403e12c5d1SDavid du Colombier {
3413e12c5d1SDavid du Colombier 	int i;
342*4de34a7eSDavid du Colombier 	ulong w;
3433e12c5d1SDavid du Colombier 	Symbol s;
3443e12c5d1SDavid du Colombier 
3453e12c5d1SDavid du Colombier 	s = *fn;
3463e12c5d1SDavid du Colombier 	for (i = 0; localsym(&s, i); i++) {
3473e12c5d1SDavid du Colombier 		if (s.class != CAUTO)
3483e12c5d1SDavid du Colombier 			continue;
349*4de34a7eSDavid du Colombier 		if (get4(cormap, fp-s.value, &w) > 0)
350*4de34a7eSDavid du Colombier 			dprint("%8t%s.%s/%10t%#lux\n", fn->name, s.name, w);
351219b2ee8SDavid du Colombier 		else
3523e12c5d1SDavid du Colombier 			dprint("%8t%s.%s/%10t?\n", fn->name, s.name);
3533e12c5d1SDavid du Colombier 	}
3543e12c5d1SDavid du Colombier }
3553e12c5d1SDavid du Colombier 
3563e12c5d1SDavid du Colombier void
printparams(Symbol * fn,ADDR fp)3577dd7cddfSDavid du Colombier printparams(Symbol *fn, ADDR fp)
3583e12c5d1SDavid du Colombier {
3593e12c5d1SDavid du Colombier 	int i;
3603e12c5d1SDavid du Colombier 	Symbol s;
361*4de34a7eSDavid du Colombier 	ulong w;
3623e12c5d1SDavid du Colombier 	int first = 0;
3633e12c5d1SDavid du Colombier 
364219b2ee8SDavid du Colombier 	fp += mach->szaddr;			/* skip saved pc */
3653e12c5d1SDavid du Colombier 	s = *fn;
3663e12c5d1SDavid du Colombier 	for (i = 0; localsym(&s, i); i++) {
3673e12c5d1SDavid du Colombier 		if (s.class != CPARAM)
3683e12c5d1SDavid du Colombier 			continue;
3693e12c5d1SDavid du Colombier 		if (first++)
3703e12c5d1SDavid du Colombier 			dprint(", ");
371*4de34a7eSDavid du Colombier 		if (get4(cormap, fp+s.value, &w) > 0)
372*4de34a7eSDavid du Colombier 			dprint("%s=%#lux", s.name, w);
3733e12c5d1SDavid du Colombier 	}
3743e12c5d1SDavid du Colombier }
375