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