xref: /plan9/sys/src/cmd/db/print.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
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 extern	char	lastc;
133e12c5d1SDavid du Colombier 
143e12c5d1SDavid du Colombier 
153e12c5d1SDavid du Colombier /* general printing routines ($) */
163e12c5d1SDavid du Colombier 
173e12c5d1SDavid du Colombier char	*Ipath = INCDIR;
18*219b2ee8SDavid du Colombier static	int	tracetype;
19*219b2ee8SDavid du Colombier static void	printfp(Map*, int);
20*219b2ee8SDavid du Colombier 
21*219b2ee8SDavid du Colombier /*
22*219b2ee8SDavid du Colombier  *	callback on stack trace
23*219b2ee8SDavid du Colombier  */
24*219b2ee8SDavid du Colombier static void
25*219b2ee8SDavid du Colombier ptrace(Map *map, ulong pc, ulong sp, Symbol *sym)
26*219b2ee8SDavid du Colombier {
27*219b2ee8SDavid du Colombier 	char buf[512];
28*219b2ee8SDavid du Colombier 
29*219b2ee8SDavid du Colombier 	USED(map);
30*219b2ee8SDavid du Colombier 	dprint("%s(", sym->name);
31*219b2ee8SDavid du Colombier 	printparams(sym, sp);
32*219b2ee8SDavid du Colombier 	dprint(") ");
33*219b2ee8SDavid du Colombier 	printsource(sym->value);
34*219b2ee8SDavid du Colombier 	dprint(" called from ");
35*219b2ee8SDavid du Colombier 	symoff(buf, 512, pc, CTEXT);
36*219b2ee8SDavid du Colombier 	dprint("%s ", buf);
37*219b2ee8SDavid du Colombier 	printsource(pc);
38*219b2ee8SDavid du Colombier 	dprint("\n");
39*219b2ee8SDavid du Colombier 	if(tracetype == 'C')
40*219b2ee8SDavid du Colombier 		printlocals(sym, sp);
41*219b2ee8SDavid du Colombier }
423e12c5d1SDavid du Colombier 
433e12c5d1SDavid du Colombier void
443e12c5d1SDavid du Colombier printtrace(int modif)
453e12c5d1SDavid du Colombier {
463e12c5d1SDavid du Colombier 	int	i;
47*219b2ee8SDavid du Colombier 	ulong pc, sp, link;
483e12c5d1SDavid du Colombier 	long v;
493e12c5d1SDavid du Colombier 	BKPT *bk;
503e12c5d1SDavid du Colombier 	Symbol s;
513e12c5d1SDavid du Colombier 	int	stack;
523e12c5d1SDavid du Colombier 	char	*fname;
53*219b2ee8SDavid du Colombier 	char buf[512];
543e12c5d1SDavid du Colombier 
553e12c5d1SDavid du Colombier 	if (cntflg==0)
563e12c5d1SDavid du Colombier 		cntval = -1;
573e12c5d1SDavid du Colombier 	switch (modif) {
583e12c5d1SDavid du Colombier 
593e12c5d1SDavid du Colombier 	case '<':
603e12c5d1SDavid du Colombier 		if (cntval == 0) {
613e12c5d1SDavid du Colombier 			while (readchar() != EOR)
623e12c5d1SDavid du Colombier 				;
633e12c5d1SDavid du Colombier 			reread();
643e12c5d1SDavid du Colombier 			break;
653e12c5d1SDavid du Colombier 		}
663e12c5d1SDavid du Colombier 		if (rdc() == '<')
673e12c5d1SDavid du Colombier 			stack = 1;
683e12c5d1SDavid du Colombier 		else {
693e12c5d1SDavid du Colombier 			stack = 0;
703e12c5d1SDavid du Colombier 			reread();
713e12c5d1SDavid du Colombier 		}
723e12c5d1SDavid du Colombier 		fname = getfname();
733e12c5d1SDavid du Colombier 		redirin(stack, fname);
743e12c5d1SDavid du Colombier 		break;
753e12c5d1SDavid du Colombier 
763e12c5d1SDavid du Colombier 	case '>':
773e12c5d1SDavid du Colombier 		fname = getfname();
783e12c5d1SDavid du Colombier 		redirout(fname);
793e12c5d1SDavid du Colombier 		break;
803e12c5d1SDavid du Colombier 
813e12c5d1SDavid du Colombier 	case 'a':
823e12c5d1SDavid du Colombier 		attachproc();
833e12c5d1SDavid du Colombier 		break;
843e12c5d1SDavid du Colombier 
853e12c5d1SDavid du Colombier 	case 'k':
863e12c5d1SDavid du Colombier 		kmsys();
873e12c5d1SDavid du Colombier 		break;
883e12c5d1SDavid du Colombier 
893e12c5d1SDavid du Colombier 	case 'q':
903e12c5d1SDavid du Colombier 	case 'Q':
913e12c5d1SDavid du Colombier 		done();
923e12c5d1SDavid du Colombier 
933e12c5d1SDavid du Colombier 	case 'w':
943e12c5d1SDavid du Colombier 		maxpos=(adrflg?adrval:MAXPOS);
953e12c5d1SDavid du Colombier 		break;
963e12c5d1SDavid du Colombier 
973e12c5d1SDavid du Colombier 	case 'S':
983e12c5d1SDavid du Colombier 		printsym();
993e12c5d1SDavid du Colombier 		break;
1003e12c5d1SDavid du Colombier 
1013e12c5d1SDavid du Colombier 	case 's':
1023e12c5d1SDavid du Colombier 		maxoff=(adrflg?adrval:MAXOFF);
1033e12c5d1SDavid du Colombier 		break;
1043e12c5d1SDavid du Colombier 
1053e12c5d1SDavid du Colombier 	case 'm':
1063e12c5d1SDavid du Colombier 		printmap("? map", symmap);
1073e12c5d1SDavid du Colombier 		printmap("/ map", cormap);
1083e12c5d1SDavid du Colombier 		break;
1093e12c5d1SDavid du Colombier 
1103e12c5d1SDavid du Colombier 	case 0:
1113e12c5d1SDavid du Colombier 	case '?':
1123e12c5d1SDavid du Colombier 		if (pid)
1133e12c5d1SDavid du Colombier 			dprint("pid = %d\n",pid);
1143e12c5d1SDavid du Colombier 		else
1153e12c5d1SDavid du Colombier 			prints("no process\n");
1163e12c5d1SDavid du Colombier 		flushbuf();
1173e12c5d1SDavid du Colombier 
1183e12c5d1SDavid du Colombier 	case 'r':
1193e12c5d1SDavid du Colombier 	case 'R':
1203e12c5d1SDavid du Colombier 		printregs(modif);
1213e12c5d1SDavid du Colombier 		return;
1223e12c5d1SDavid du Colombier 
1233e12c5d1SDavid du Colombier 	case 'f':
1243e12c5d1SDavid du Colombier 	case 'F':
125*219b2ee8SDavid du Colombier 		printfp(cormap, modif);
1263e12c5d1SDavid du Colombier 		return;
1273e12c5d1SDavid du Colombier 
1283e12c5d1SDavid du Colombier 	case 'c':
1293e12c5d1SDavid du Colombier 	case 'C':
130*219b2ee8SDavid du Colombier 		tracetype = modif;
131*219b2ee8SDavid du Colombier 		if (machdata->ctrace) {
132*219b2ee8SDavid du Colombier 			if (adrflg) {	/* trace from jmpbuf for multi-threaded code */
133*219b2ee8SDavid du Colombier 				if (get4(cormap, adrval, (long*)&sp) < 0 ||
134*219b2ee8SDavid du Colombier 					get4(cormap, adrval+4, (long*)&pc) < 0)
135*219b2ee8SDavid du Colombier 						error("%r");
136*219b2ee8SDavid du Colombier 			} else {
137*219b2ee8SDavid du Colombier 				sp = rget(cormap, mach->sp);
138*219b2ee8SDavid du Colombier 				pc = rget(cormap, mach->pc);
139*219b2ee8SDavid du Colombier 			}
140*219b2ee8SDavid du Colombier 			if(mach->link)
141*219b2ee8SDavid du Colombier 				link = rget(cormap, mach->link);
142*219b2ee8SDavid du Colombier 			else
143*219b2ee8SDavid du Colombier 				link = 0;
144*219b2ee8SDavid du Colombier 			if (machdata->ctrace(cormap, pc, sp, link, ptrace) <= 0)
145*219b2ee8SDavid du Colombier 				error("no stack frame");
146*219b2ee8SDavid du Colombier 		}
1473e12c5d1SDavid du Colombier 		break;
1483e12c5d1SDavid du Colombier 
1493e12c5d1SDavid du Colombier 		/*print externals*/
1503e12c5d1SDavid du Colombier 	case 'e':
1513e12c5d1SDavid du Colombier 		for (i = 0; globalsym(&s, i); i++) {
152*219b2ee8SDavid du Colombier 			if (get4(cormap, s.value, &v) > 0)
1533e12c5d1SDavid du Colombier 				dprint("%s/%12t%lux\n", s.name,	v);
1543e12c5d1SDavid du Colombier 		}
1553e12c5d1SDavid du Colombier 		break;
1563e12c5d1SDavid du Colombier 
1573e12c5d1SDavid du Colombier 		/*print breakpoints*/
1583e12c5d1SDavid du Colombier 	case 'b':
1593e12c5d1SDavid du Colombier 	case 'B':
1603e12c5d1SDavid du Colombier 		for (bk=bkpthead; bk; bk=bk->nxtbkpt)
1613e12c5d1SDavid du Colombier 			if (bk->flag) {
162*219b2ee8SDavid du Colombier 				symoff(buf, 512, (WORD)bk->loc, CTEXT);
163*219b2ee8SDavid du Colombier 				dprint(buf);
1643e12c5d1SDavid du Colombier 				if (bk->count != 1)
1653e12c5d1SDavid du Colombier 					dprint(",%d", bk->count);
1663e12c5d1SDavid du Colombier 				dprint(":%c %s", bk->flag == BKPTTMP ? 'B' : 'b', bk->comm);
1673e12c5d1SDavid du Colombier 			}
1683e12c5d1SDavid du Colombier 		break;
1693e12c5d1SDavid du Colombier 
1703e12c5d1SDavid du Colombier 	case 'M':
1713e12c5d1SDavid du Colombier 		fname = getfname();
1723e12c5d1SDavid du Colombier 		if (machbyname(fname) == 0)
1733e12c5d1SDavid du Colombier 			dprint("unknown name\n");;
1743e12c5d1SDavid du Colombier 		break;
1753e12c5d1SDavid du Colombier 	default:
1763e12c5d1SDavid du Colombier 		error("bad `$' command");
1773e12c5d1SDavid du Colombier 	}
1783e12c5d1SDavid du Colombier 
1793e12c5d1SDavid du Colombier }
1803e12c5d1SDavid du Colombier 
1813e12c5d1SDavid du Colombier char *
1823e12c5d1SDavid du Colombier getfname(void)
1833e12c5d1SDavid du Colombier {
1843e12c5d1SDavid du Colombier 	static char fname[ARB];
1853e12c5d1SDavid du Colombier 	char *p;
1863e12c5d1SDavid du Colombier 
1873e12c5d1SDavid du Colombier 	if (rdc() == EOR) {
1883e12c5d1SDavid du Colombier 		reread();
1893e12c5d1SDavid du Colombier 		return (0);
1903e12c5d1SDavid du Colombier 	}
1913e12c5d1SDavid du Colombier 	p = fname;
1923e12c5d1SDavid du Colombier 	do {
1933e12c5d1SDavid du Colombier 		*p++ = lastc;
1943e12c5d1SDavid du Colombier 		if (p >= &fname[ARB-1])
1953e12c5d1SDavid du Colombier 			error("filename too long");
1963e12c5d1SDavid du Colombier 	} while (rdc() != EOR);
1973e12c5d1SDavid du Colombier 	*p = 0;
1983e12c5d1SDavid du Colombier 	reread();
1993e12c5d1SDavid du Colombier 	return (fname);
2003e12c5d1SDavid du Colombier }
2013e12c5d1SDavid du Colombier 
202*219b2ee8SDavid du Colombier static void
203*219b2ee8SDavid du Colombier printfp(Map *map, int modif)
204*219b2ee8SDavid du Colombier {
205*219b2ee8SDavid du Colombier 	Reglist *rp;
206*219b2ee8SDavid du Colombier 	int i;
207*219b2ee8SDavid du Colombier 	int ret;
208*219b2ee8SDavid du Colombier 	char buf[512];
209*219b2ee8SDavid du Colombier 
210*219b2ee8SDavid du Colombier 	for (i = 0, rp = mach->reglist; rp->rname; rp += ret) {
211*219b2ee8SDavid du Colombier 		ret = 1;
212*219b2ee8SDavid du Colombier 		if (!(rp->rflags&RFLT))
213*219b2ee8SDavid du Colombier 			continue;
214*219b2ee8SDavid du Colombier 		ret = fpformat(map, rp, buf, sizeof(buf), modif);
215*219b2ee8SDavid du Colombier 		if (ret < 0) {
216*219b2ee8SDavid du Colombier 			werrstr("Register %s: %r", rp->rname);
217*219b2ee8SDavid du Colombier 			error("%r");
218*219b2ee8SDavid du Colombier 		}
219*219b2ee8SDavid du Colombier 			/* double column print */
220*219b2ee8SDavid du Colombier 		if (i&0x01)
221*219b2ee8SDavid du Colombier 			dprint("%40t%-8s%-12s\n", rp->rname, buf);
222*219b2ee8SDavid du Colombier 		else
223*219b2ee8SDavid du Colombier 			dprint("\t%-8s%-12s", rp->rname, buf);
224*219b2ee8SDavid du Colombier 		i++;
225*219b2ee8SDavid du Colombier 	}
226*219b2ee8SDavid du Colombier }
227*219b2ee8SDavid du Colombier 
2283e12c5d1SDavid du Colombier void
2293e12c5d1SDavid du Colombier redirin(int stack, char *file)
2303e12c5d1SDavid du Colombier {
2313e12c5d1SDavid du Colombier 	char pfile[ARB];
2323e12c5d1SDavid du Colombier 
2333e12c5d1SDavid du Colombier 	if (file == 0) {
2343e12c5d1SDavid du Colombier 		iclose(-1, 0);
2353e12c5d1SDavid du Colombier 		return;
2363e12c5d1SDavid du Colombier 	}
2373e12c5d1SDavid du Colombier 	iclose(stack, 0);
2383e12c5d1SDavid du Colombier 	if ((infile = open(file, 0)) < 0) {
2393e12c5d1SDavid du Colombier 		strcpy(pfile, Ipath);
2403e12c5d1SDavid du Colombier 		strcat(pfile, "/");
2413e12c5d1SDavid du Colombier 		strcat(pfile, file);
2423e12c5d1SDavid du Colombier 		if ((infile = open(pfile, 0)) < 0) {
2433e12c5d1SDavid du Colombier 			infile = STDIN;
2443e12c5d1SDavid du Colombier 			error("cannot open");
2453e12c5d1SDavid du Colombier 		}
2463e12c5d1SDavid du Colombier 	}
2473e12c5d1SDavid du Colombier }
2483e12c5d1SDavid du Colombier 
2493e12c5d1SDavid du Colombier void
250*219b2ee8SDavid du Colombier printmap(char *s, Map *map)
2513e12c5d1SDavid du Colombier {
252*219b2ee8SDavid du Colombier 	int i;
253*219b2ee8SDavid du Colombier 
254*219b2ee8SDavid du Colombier 	if (!map)
255*219b2ee8SDavid du Colombier 		return;
256*219b2ee8SDavid du Colombier 	if (map == symmap)
2573e12c5d1SDavid du Colombier 		dprint("%s%12t`%s'\n", s, fsym < 0 ? "-" : symfil);
258*219b2ee8SDavid du Colombier 	else if (map == cormap)
2593e12c5d1SDavid du Colombier 		dprint("%s%12t`%s'\n", s, fcor < 0 ? "-" : corfil);
2603e12c5d1SDavid du Colombier 	else
2613e12c5d1SDavid du Colombier 		dprint("%s\n", s);
262*219b2ee8SDavid du Colombier 	for (i = 0; i < map->nsegs; i++) {
263*219b2ee8SDavid du Colombier 		if (map->seg[i].inuse)
264*219b2ee8SDavid du Colombier 			dprint("%s%8t%-16lux %-16lux %-16lux\n", map->seg[i].name,
265*219b2ee8SDavid du Colombier 				map->seg[i].b, map->seg[i].e, map->seg[i].f);
266*219b2ee8SDavid du Colombier 	}
2673e12c5d1SDavid du Colombier }
2683e12c5d1SDavid du Colombier 
2693e12c5d1SDavid du Colombier /*
2703e12c5d1SDavid du Colombier  *	dump the raw symbol table
2713e12c5d1SDavid du Colombier  */
2723e12c5d1SDavid du Colombier void
2733e12c5d1SDavid du Colombier printsym(void)
2743e12c5d1SDavid du Colombier {
2753e12c5d1SDavid du Colombier 	int i;
2763e12c5d1SDavid du Colombier 	Sym *sp;
2773e12c5d1SDavid du Colombier 
2783e12c5d1SDavid du Colombier 	for (i = 0; sp = getsym(i); i++) {
2793e12c5d1SDavid du Colombier 		switch(sp->type) {
2803e12c5d1SDavid du Colombier 		case 't':
2813e12c5d1SDavid du Colombier 		case 'l':
2823e12c5d1SDavid du Colombier 			dprint("%8lux t %s\n", sp->value, sp->name);
2833e12c5d1SDavid du Colombier 			break;
2843e12c5d1SDavid du Colombier 		case 'T':
2853e12c5d1SDavid du Colombier 		case 'L':
2863e12c5d1SDavid du Colombier 			dprint("%8lux T %s\n", sp->value, sp->name);
2873e12c5d1SDavid du Colombier 			break;
2883e12c5d1SDavid du Colombier 		case 'D':
2893e12c5d1SDavid du Colombier 		case 'd':
2903e12c5d1SDavid du Colombier 		case 'B':
2913e12c5d1SDavid du Colombier 		case 'b':
2923e12c5d1SDavid du Colombier 		case 'a':
2933e12c5d1SDavid du Colombier 		case 'p':
2943e12c5d1SDavid du Colombier 		case 'm':
2953e12c5d1SDavid du Colombier 			dprint("%8lux %c %s\n", sp->value, sp->type, sp->name);
2963e12c5d1SDavid du Colombier 			break;
2973e12c5d1SDavid du Colombier 		default:
2983e12c5d1SDavid du Colombier 			break;
2993e12c5d1SDavid du Colombier 		}
3003e12c5d1SDavid du Colombier 	}
3013e12c5d1SDavid du Colombier }
3023e12c5d1SDavid du Colombier 
3033e12c5d1SDavid du Colombier #define	STRINGSZ	128
3043e12c5d1SDavid du Colombier 
3053e12c5d1SDavid du Colombier /*
3063e12c5d1SDavid du Colombier  *	print the value of dot as file:line
3073e12c5d1SDavid du Colombier  */
3083e12c5d1SDavid du Colombier void
3093e12c5d1SDavid du Colombier printsource(long dot)
3103e12c5d1SDavid du Colombier {
3113e12c5d1SDavid du Colombier 	char str[STRINGSZ];
3123e12c5d1SDavid du Colombier 
3133e12c5d1SDavid du Colombier 	if (fileline(str, STRINGSZ, dot))
3143e12c5d1SDavid du Colombier 		dprint("%s", str);
3153e12c5d1SDavid du Colombier }
3163e12c5d1SDavid du Colombier 
3173e12c5d1SDavid du Colombier void
3183e12c5d1SDavid du Colombier printpc(void)
3193e12c5d1SDavid du Colombier {
320*219b2ee8SDavid du Colombier 	char buf[512];
321*219b2ee8SDavid du Colombier 
322*219b2ee8SDavid du Colombier 	dot = (ulong)rget(cormap, mach->pc);
3233e12c5d1SDavid du Colombier 	if(dot){
324*219b2ee8SDavid du Colombier 		printsource((long)dot);
3253e12c5d1SDavid du Colombier 		printc(' ');
326*219b2ee8SDavid du Colombier 		symoff(buf, sizeof(buf), (long)dot, CTEXT);
327*219b2ee8SDavid du Colombier 		dprint("%s?", buf);
328*219b2ee8SDavid du Colombier 		if (machdata->das(symmap, dot, 'i', buf, sizeof(buf)) < 0)
329*219b2ee8SDavid du Colombier 				error("%r");
330*219b2ee8SDavid du Colombier 		dprint("%16t%s\n", buf);
3313e12c5d1SDavid du Colombier 	}
3323e12c5d1SDavid du Colombier }
3333e12c5d1SDavid du Colombier 
3343e12c5d1SDavid du Colombier void
3353e12c5d1SDavid du Colombier printlocals(Symbol *fn, ADDR fp)
3363e12c5d1SDavid du Colombier {
3373e12c5d1SDavid du Colombier 	int i;
338*219b2ee8SDavid du Colombier 	long val;
3393e12c5d1SDavid du Colombier 	Symbol s;
3403e12c5d1SDavid du Colombier 
3413e12c5d1SDavid du Colombier 	s = *fn;
3423e12c5d1SDavid du Colombier 	for (i = 0; localsym(&s, i); i++) {
3433e12c5d1SDavid du Colombier 		if (s.class != CAUTO)
3443e12c5d1SDavid du Colombier 			continue;
345*219b2ee8SDavid du Colombier 		if (get4(cormap, fp-s.value, &val) > 0)
3463e12c5d1SDavid du Colombier 			dprint("%8t%s.%s/%10t%lux\n", fn->name, s.name, val);
347*219b2ee8SDavid du Colombier 		else
3483e12c5d1SDavid du Colombier 			dprint("%8t%s.%s/%10t?\n", fn->name, s.name);
3493e12c5d1SDavid du Colombier 	}
3503e12c5d1SDavid du Colombier }
3513e12c5d1SDavid du Colombier 
3523e12c5d1SDavid du Colombier void
353*219b2ee8SDavid du Colombier printparams(Symbol *fn, ulong fp)
3543e12c5d1SDavid du Colombier {
3553e12c5d1SDavid du Colombier 	int i;
3563e12c5d1SDavid du Colombier 	Symbol s;
3573e12c5d1SDavid du Colombier 	long v;
3583e12c5d1SDavid du Colombier 	int first = 0;
3593e12c5d1SDavid du Colombier 
360*219b2ee8SDavid du Colombier 	fp += mach->szaddr;			/* skip saved pc */
3613e12c5d1SDavid du Colombier 	s = *fn;
3623e12c5d1SDavid du Colombier 	for (i = 0; localsym(&s, i); i++) {
3633e12c5d1SDavid du Colombier 		if (s.class != CPARAM)
3643e12c5d1SDavid du Colombier 			continue;
365*219b2ee8SDavid du Colombier 		if (get4(cormap, fp+s.value, &v) > 0) {
3663e12c5d1SDavid du Colombier 			if (first++)
3673e12c5d1SDavid du Colombier 				dprint(", ");
3683e12c5d1SDavid du Colombier 			dprint("%s=%lux", s.name, v);
3693e12c5d1SDavid du Colombier 		}
3703e12c5d1SDavid du Colombier 	}
371*219b2ee8SDavid du Colombier }
372