xref: /plan9/sys/src/cmd/db/print.c (revision ff8c3af2f44d95267f67219afa20ba82ff6cf7e4)
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
23 ptrace(Map *map, ulong pc, ulong 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
42 printtrace(int modif)
43 {
44 	int	i;
45 	ulong pc, sp, link;
46 	long v;
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) {	/* trace from jmpbuf for multi-threaded code */
131 				if (get4(cormap, adrval, (long*)&sp) < 0 ||
132 					get4(cormap, adrval+4, (long*)&pc) < 0)
133 						error("%r");
134 			} else {
135 				sp = rget(cormap, mach->sp);
136 				pc = rget(cormap, mach->pc);
137 			}
138 			if(mach->link)
139 				link = rget(cormap, mach->link);
140 			else
141 				link = 0;
142 			if (machdata->ctrace(cormap, pc, sp, link, ptrace) <= 0)
143 				error("no stack frame");
144 		}
145 		break;
146 
147 		/*print externals*/
148 	case 'e':
149 		for (i = 0; globalsym(&s, i); i++) {
150 			if (get4(cormap, s.value, &v) > 0)
151 				dprint("%s/%12t%#lux\n", s.name,	v);
152 		}
153 		break;
154 
155 		/*print breakpoints*/
156 	case 'b':
157 	case 'B':
158 		for (bk=bkpthead; bk; bk=bk->nxtbkpt)
159 			if (bk->flag) {
160 				symoff(buf, 512, (WORD)bk->loc, CTEXT);
161 				dprint(buf);
162 				if (bk->count != 1)
163 					dprint(",%d", bk->count);
164 				dprint(":%c %s", bk->flag == BKPTTMP ? 'B' : 'b', bk->comm);
165 			}
166 		break;
167 
168 	case 'M':
169 		fname = getfname();
170 		if (machbyname(fname) == 0)
171 			dprint("unknown name\n");;
172 		break;
173 	default:
174 		error("bad `$' command");
175 	}
176 
177 }
178 
179 char *
180 getfname(void)
181 {
182 	static char fname[ARB];
183 	char *p;
184 
185 	if (rdc() == EOR) {
186 		reread();
187 		return (0);
188 	}
189 	p = fname;
190 	do {
191 		*p++ = lastc;
192 		if (p >= &fname[ARB-1])
193 			error("filename too long");
194 	} while (rdc() != EOR);
195 	*p = 0;
196 	reread();
197 	return (fname);
198 }
199 
200 static void
201 printfp(Map *map, int modif)
202 {
203 	Reglist *rp;
204 	int i;
205 	int ret;
206 	char buf[512];
207 
208 	for (i = 0, rp = mach->reglist; rp->rname; rp += ret) {
209 		ret = 1;
210 		if (!(rp->rflags&RFLT))
211 			continue;
212 		ret = fpformat(map, rp, buf, sizeof(buf), modif);
213 		if (ret < 0) {
214 			werrstr("Register %s: %r", rp->rname);
215 			error("%r");
216 		}
217 			/* double column print */
218 		if (i&0x01)
219 			dprint("%40t%-8s%-12s\n", rp->rname, buf);
220 		else
221 			dprint("\t%-8s%-12s", rp->rname, buf);
222 		i++;
223 	}
224 }
225 
226 void
227 redirin(int stack, char *file)
228 {
229 	char pfile[ARB];
230 
231 	if (file == 0) {
232 		iclose(-1, 0);
233 		return;
234 	}
235 	iclose(stack, 0);
236 	if ((infile = open(file, 0)) < 0) {
237 		strcpy(pfile, Ipath);
238 		strcat(pfile, "/");
239 		strcat(pfile, file);
240 		if ((infile = open(pfile, 0)) < 0) {
241 			infile = STDIN;
242 			error("cannot open");
243 		}
244 	}
245 }
246 
247 void
248 printmap(char *s, Map *map)
249 {
250 	int i;
251 
252 	if (!map)
253 		return;
254 	if (map == symmap)
255 		dprint("%s%12t`%s'\n", s, fsym < 0 ? "-" : symfil);
256 	else if (map == cormap)
257 		dprint("%s%12t`%s'\n", s, fcor < 0 ? "-" : corfil);
258 	else
259 		dprint("%s\n", s);
260 	for (i = 0; i < map->nsegs; i++) {
261 		if (map->seg[i].inuse)
262 			dprint("%s%8t%-16#lux %-16#lux %-16#lux\n", map->seg[i].name,
263 				map->seg[i].b, map->seg[i].e, map->seg[i].f);
264 	}
265 }
266 
267 /*
268  *	dump the raw symbol table
269  */
270 void
271 printsym(void)
272 {
273 	int i;
274 	Sym *sp;
275 
276 	for (i = 0; sp = getsym(i); i++) {
277 		switch(sp->type) {
278 		case 't':
279 		case 'l':
280 			dprint("%8#lux t %s\n", sp->value, sp->name);
281 			break;
282 		case 'T':
283 		case 'L':
284 			dprint("%8#lux T %s\n", sp->value, sp->name);
285 			break;
286 		case 'D':
287 		case 'd':
288 		case 'B':
289 		case 'b':
290 		case 'a':
291 		case 'p':
292 		case 'm':
293 			dprint("%8#lux %c %s\n", sp->value, sp->type, sp->name);
294 			break;
295 		default:
296 			break;
297 		}
298 	}
299 }
300 
301 #define	STRINGSZ	128
302 
303 /*
304  *	print the value of dot as file:line
305  */
306 void
307 printsource(long dot)
308 {
309 	char str[STRINGSZ];
310 
311 	if (fileline(str, STRINGSZ, dot))
312 		dprint("%s", str);
313 }
314 
315 void
316 printpc(void)
317 {
318 	char buf[512];
319 
320 	dot = (ulong)rget(cormap, mach->pc);
321 	if(dot){
322 		printsource((long)dot);
323 		printc(' ');
324 		symoff(buf, sizeof(buf), (long)dot, CTEXT);
325 		dprint("%s/", buf);
326 		if (machdata->das(cormap, dot, 'i', buf, sizeof(buf)) < 0)
327 			error("%r");
328 		dprint("%16t%s\n", buf);
329 	}
330 }
331 
332 void
333 printlocals(Symbol *fn, ADDR fp)
334 {
335 	int i;
336 	long val;
337 	Symbol s;
338 
339 	s = *fn;
340 	for (i = 0; localsym(&s, i); i++) {
341 		if (s.class != CAUTO)
342 			continue;
343 		if (get4(cormap, fp-s.value, &val) > 0)
344 			dprint("%8t%s.%s/%10t%#lux\n", fn->name, s.name, val);
345 		else
346 			dprint("%8t%s.%s/%10t?\n", fn->name, s.name);
347 	}
348 }
349 
350 void
351 printparams(Symbol *fn, ADDR fp)
352 {
353 	int i;
354 	Symbol s;
355 	long v;
356 	int first = 0;
357 
358 	fp += mach->szaddr;			/* skip saved pc */
359 	s = *fn;
360 	for (i = 0; localsym(&s, i); i++) {
361 		if (s.class != CPARAM)
362 			continue;
363 		if (first++)
364 			dprint(", ");
365 		if (get4(cormap, fp+s.value, &v) > 0)
366 			dprint("%s=%#lux", s.name, v);
367 	}
368 }
369