xref: /plan9/sys/src/cmd/db/print.c (revision 4de34a7edde43207e841ec91ecd12e6cf5f5ebe7)
1 /*
2  *
3  *	debugger
4  *
5  */
6 #include "defs.h"
7 #include "fns.h"
8 
9 extern	int	infile;
10 extern	int	outfile;
11 extern	int	maxpos;
12 
13 /* general printing routines ($) */
14 
15 char	*Ipath = INCDIR;
16 static	int	tracetype;
17 static void	printfp(Map*, int);
18 
19 /*
20  *	callback on stack trace
21  */
22 static void
ptrace(Map * map,uvlong pc,uvlong sp,Symbol * sym)23 ptrace(Map *map, uvlong pc, uvlong sp, Symbol *sym)
24 {
25 	char buf[512];
26 
27 	USED(map);
28 	dprint("%s(", sym->name);
29 	printparams(sym, sp);
30 	dprint(") ");
31 	printsource(sym->value);
32 	dprint(" called from ");
33 	symoff(buf, 512, pc, CTEXT);
34 	dprint("%s ", buf);
35 	printsource(pc);
36 	dprint("\n");
37 	if(tracetype == 'C')
38 		printlocals(sym, sp);
39 }
40 
41 void
printtrace(int modif)42 printtrace(int modif)
43 {
44 	int i;
45 	uvlong pc, sp, link;
46 	ulong w;
47 	BKPT *bk;
48 	Symbol s;
49 	int stack;
50 	char *fname;
51 	char buf[512];
52 
53 	if (cntflg==0)
54 		cntval = -1;
55 	switch (modif) {
56 
57 	case '<':
58 		if (cntval == 0) {
59 			while (readchar() != EOR)
60 				;
61 			reread();
62 			break;
63 		}
64 		if (rdc() == '<')
65 			stack = 1;
66 		else {
67 			stack = 0;
68 			reread();
69 		}
70 		fname = getfname();
71 		redirin(stack, fname);
72 		break;
73 
74 	case '>':
75 		fname = getfname();
76 		redirout(fname);
77 		break;
78 
79 	case 'a':
80 		attachprocess();
81 		break;
82 
83 	case 'k':
84 		kmsys();
85 		break;
86 
87 	case 'q':
88 	case 'Q':
89 		done();
90 
91 	case 'w':
92 		maxpos=(adrflg?adrval:MAXPOS);
93 		break;
94 
95 	case 'S':
96 		printsym();
97 		break;
98 
99 	case 's':
100 		maxoff=(adrflg?adrval:MAXOFF);
101 		break;
102 
103 	case 'm':
104 		printmap("? map", symmap);
105 		printmap("/ map", cormap);
106 		break;
107 
108 	case 0:
109 	case '?':
110 		if (pid)
111 			dprint("pid = %d\n",pid);
112 		else
113 			prints("no process\n");
114 		flushbuf();
115 
116 	case 'r':
117 	case 'R':
118 		printregs(modif);
119 		return;
120 
121 	case 'f':
122 	case 'F':
123 		printfp(cormap, modif);
124 		return;
125 
126 	case 'c':
127 	case 'C':
128 		tracetype = modif;
129 		if (machdata->ctrace) {
130 			if (adrflg) {
131 				/*
132 				 * trace from jmpbuf for multi-threaded code.
133 				 * assume sp and pc are in adjacent locations
134 				 * and mach->szaddr in size.
135 				 */
136 				if (geta(cormap, adrval, &sp) < 0 ||
137 					geta(cormap, adrval+mach->szaddr, &pc) < 0)
138 						error("%r");
139 			} else {
140 				sp = rget(cormap, mach->sp);
141 				pc = rget(cormap, mach->pc);
142 			}
143 			if(mach->link)
144 				link = rget(cormap, mach->link);
145 			else
146 				link = 0;
147 			if (machdata->ctrace(cormap, pc, sp, link, ptrace) <= 0)
148 				error("no stack frame");
149 		}
150 		break;
151 
152 		/*print externals*/
153 	case 'e':
154 		for (i = 0; globalsym(&s, i); i++) {
155 			if (get4(cormap, s.value, &w) > 0)
156 				dprint("%s/%12t%#lux\n", s.name, w);
157 		}
158 		break;
159 
160 		/*print breakpoints*/
161 	case 'b':
162 	case 'B':
163 		for (bk=bkpthead; bk; bk=bk->nxtbkpt)
164 			if (bk->flag) {
165 				symoff(buf, 512, (WORD)bk->loc, CTEXT);
166 				dprint(buf);
167 				if (bk->count != 1)
168 					dprint(",%d", bk->count);
169 				dprint(":%c %s", bk->flag == BKPTTMP ? 'B' : 'b', bk->comm);
170 			}
171 		break;
172 
173 	case 'M':
174 		fname = getfname();
175 		if (machbyname(fname) == 0)
176 			dprint("unknown name\n");;
177 		break;
178 	default:
179 		error("bad `$' command");
180 	}
181 
182 }
183 
184 char *
getfname(void)185 getfname(void)
186 {
187 	static char fname[ARB];
188 	char *p;
189 
190 	if (rdc() == EOR) {
191 		reread();
192 		return (0);
193 	}
194 	p = fname;
195 	do {
196 		*p++ = lastc;
197 		if (p >= &fname[ARB-1])
198 			error("filename too long");
199 	} while (rdc() != EOR);
200 	*p = 0;
201 	reread();
202 	return (fname);
203 }
204 
205 static void
printfp(Map * map,int modif)206 printfp(Map *map, int modif)
207 {
208 	Reglist *rp;
209 	int i;
210 	int ret;
211 	char buf[512];
212 
213 	for (i = 0, rp = mach->reglist; rp->rname; rp += ret) {
214 		ret = 1;
215 		if (!(rp->rflags&RFLT))
216 			continue;
217 		ret = fpformat(map, rp, buf, sizeof(buf), modif);
218 		if (ret < 0) {
219 			werrstr("Register %s: %r", rp->rname);
220 			error("%r");
221 		}
222 			/* double column print */
223 		if (i&0x01)
224 			dprint("%40t%-8s%-12s\n", rp->rname, buf);
225 		else
226 			dprint("\t%-8s%-12s", rp->rname, buf);
227 		i++;
228 	}
229 }
230 
231 void
redirin(int stack,char * file)232 redirin(int stack, char *file)
233 {
234 	char *pfile;
235 
236 	if (file == 0) {
237 		iclose(-1, 0);
238 		return;
239 	}
240 	iclose(stack, 0);
241 	if ((infile = open(file, 0)) < 0) {
242 		pfile = smprint("%s/%s", Ipath, file);
243 		infile = open(pfile, 0);
244 		free(pfile);
245 		if(infile < 0) {
246 			infile = STDIN;
247 			error("cannot open");
248 		}
249 	}
250 }
251 
252 void
printmap(char * s,Map * map)253 printmap(char *s, Map *map)
254 {
255 	int i;
256 
257 	if (!map)
258 		return;
259 	if (map == symmap)
260 		dprint("%s%12t`%s'\n", s, fsym < 0 ? "-" : symfil);
261 	else if (map == cormap)
262 		dprint("%s%12t`%s'\n", s, fcor < 0 ? "-" : corfil);
263 	else
264 		dprint("%s\n", s);
265 	for (i = 0; i < map->nsegs; i++) {
266 		if (map->seg[i].inuse)
267 			dprint("%s%8t%-16#llux %-16#llux %-16#llux\n",
268 				map->seg[i].name, map->seg[i].b,
269 				map->seg[i].e, map->seg[i].f);
270 	}
271 }
272 
273 /*
274  *	dump the raw symbol table
275  */
276 void
printsym(void)277 printsym(void)
278 {
279 	int i;
280 	Sym *sp;
281 
282 	for (i = 0; sp = getsym(i); i++) {
283 		switch(sp->type) {
284 		case 't':
285 		case 'l':
286 			dprint("%16#llux t %s\n", sp->value, sp->name);
287 			break;
288 		case 'T':
289 		case 'L':
290 			dprint("%16#llux T %s\n", sp->value, sp->name);
291 			break;
292 		case 'D':
293 		case 'd':
294 		case 'B':
295 		case 'b':
296 		case 'a':
297 		case 'p':
298 		case 'm':
299 			dprint("%16#llux %c %s\n", sp->value, sp->type, sp->name);
300 			break;
301 		default:
302 			break;
303 		}
304 	}
305 }
306 
307 #define	STRINGSZ	128
308 
309 /*
310  *	print the value of dot as file:line
311  */
312 void
printsource(ADDR dot)313 printsource(ADDR dot)
314 {
315 	char str[STRINGSZ];
316 
317 	if (fileline(str, STRINGSZ, dot))
318 		dprint("%s", str);
319 }
320 
321 void
printpc(void)322 printpc(void)
323 {
324 	char buf[512];
325 
326 	dot = rget(cormap, mach->pc);
327 	if(dot){
328 		printsource((long)dot);
329 		printc(' ');
330 		symoff(buf, sizeof(buf), (long)dot, CTEXT);
331 		dprint("%s/", buf);
332 		if (machdata->das(cormap, dot, 'i', buf, sizeof(buf)) < 0)
333 			error("%r");
334 		dprint("%16t%s\n", buf);
335 	}
336 }
337 
338 void
printlocals(Symbol * fn,ADDR fp)339 printlocals(Symbol *fn, ADDR fp)
340 {
341 	int i;
342 	ulong w;
343 	Symbol s;
344 
345 	s = *fn;
346 	for (i = 0; localsym(&s, i); i++) {
347 		if (s.class != CAUTO)
348 			continue;
349 		if (get4(cormap, fp-s.value, &w) > 0)
350 			dprint("%8t%s.%s/%10t%#lux\n", fn->name, s.name, w);
351 		else
352 			dprint("%8t%s.%s/%10t?\n", fn->name, s.name);
353 	}
354 }
355 
356 void
printparams(Symbol * fn,ADDR fp)357 printparams(Symbol *fn, ADDR fp)
358 {
359 	int i;
360 	Symbol s;
361 	ulong w;
362 	int first = 0;
363 
364 	fp += mach->szaddr;			/* skip saved pc */
365 	s = *fn;
366 	for (i = 0; localsym(&s, i); i++) {
367 		if (s.class != CPARAM)
368 			continue;
369 		if (first++)
370 			dprint(", ");
371 		if (get4(cormap, fp+s.value, &w) > 0)
372 			dprint("%s=%#lux", s.name, w);
373 	}
374 }
375