db_sym.c revision 1.26 1 /* $NetBSD: db_sym.c,v 1.26 2001/06/13 06:01:45 simonb Exp $ */
2
3 /*
4 * Mach Operating System
5 * Copyright (c) 1991,1990 Carnegie Mellon University
6 * All Rights Reserved.
7 *
8 * Permission to use, copy, modify and distribute this software and its
9 * documentation is hereby granted, provided that both the copyright
10 * notice and this permission notice appear in all copies of the
11 * software, derivative works or modified versions, and any portions
12 * thereof, and that both notices appear in supporting documentation.
13 *
14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17 *
18 * Carnegie Mellon requests users of this software to return to
19 *
20 * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
24 *
25 * any improvements or extensions that they make and grant Carnegie the
26 * rights to redistribute these changes.
27 */
28
29 #include "opt_ddbparam.h"
30
31 #include <sys/param.h>
32 #include <sys/proc.h>
33 #include <sys/systm.h>
34
35 #include <machine/db_machdep.h>
36
37 #include <ddb/db_lex.h>
38 #include <ddb/db_sym.h>
39 #include <ddb/db_output.h>
40 #include <ddb/db_extern.h>
41 #include <ddb/db_command.h>
42
43 /*
44 * Multiple symbol tables
45 */
46 #ifndef MAXLKMS
47 #define MAXLKMS 20
48 #endif
49
50 #ifndef MAXNOSYMTABS
51 #define MAXNOSYMTABS MAXLKMS+1 /* Room for kernel + LKM's */
52 #endif
53
54 db_symtab_t db_symtabs[MAXNOSYMTABS] = {{0,},};
55
56 db_symtab_t *db_last_symtab;
57
58 #ifdef SYMTAB_SPACE
59 #define SYMTAB_FILLER "|This is the symbol table!"
60
61 char db_symtab[SYMTAB_SPACE] = SYMTAB_FILLER;
62 int db_symtabsize = SYMTAB_SPACE;
63 #endif
64
65 static char *db_qualify __P((db_sym_t, const char *));
66 static db_forall_func_t db_sift;
67
68 /*
69 * Put the most picky symbol table formats at the top!
70 */
71 const db_symformat_t * const db_symformats[] = {
72 #ifdef DB_ELF_SYMBOLS
73 &db_symformat_elf,
74 #endif
75 #ifdef DB_AOUT_SYMBOLS
76 &db_symformat_aout,
77 #endif
78 NULL,
79 };
80
81 const db_symformat_t *db_symformat;
82
83 boolean_t X_db_sym_init __P((int, void *, void *, const char *));
84 db_sym_t X_db_lookup __P((db_symtab_t *, char *));
85 db_sym_t X_db_search_symbol __P((db_symtab_t *, db_addr_t,
86 db_strategy_t, db_expr_t *));
87 void X_db_symbol_values __P((db_symtab_t *, db_sym_t, char **,
88 db_expr_t *));
89 boolean_t X_db_line_at_pc __P((db_symtab_t *, db_sym_t, char **,
90 int *, db_expr_t));
91 int X_db_sym_numargs __P((db_symtab_t *, db_sym_t, int *,
92 char **));
93 void X_db_forall __P((db_symtab_t *,
94 db_forall_func_t db_forall_func, void *));
95
96 /*
97 * Initialize the kernel debugger by initializing the master symbol
98 * table. Note that if initializing the master symbol table fails,
99 * no other symbol tables can be loaded.
100 */
101 void
102 ddb_init(symsize, vss, vse)
103 int symsize;
104 void *vss, *vse;
105 {
106 const db_symformat_t * const *symf;
107 const char *name = "netbsd";
108
109 if (symsize <= 0) {
110 #ifdef SYMTAB_SPACE
111 if (strncmp(db_symtab, SYMTAB_FILLER, sizeof(SYMTAB_FILLER))) {
112 symsize = db_symtabsize;
113 vss = db_symtab;
114 vse = db_symtab + db_symtabsize;
115 } else {
116 #endif
117 printf(" [ no symbols available ]\n");
118 return;
119 #ifdef SYMTAB_SPACE
120 }
121 #endif
122 }
123
124 /*
125 * Do this check now for the master symbol table to avoid printing
126 * the message N times.
127 */
128 if (ALIGNED_POINTER(vss, long) == 0) {
129 printf("[ %s symbol table has bad start address %p ]\n",
130 name, vss);
131 return;
132 }
133
134 for (symf = db_symformats; *symf != NULL; symf++) {
135 db_symformat = *symf;
136 if (X_db_sym_init(symsize, vss, vse, name) == TRUE)
137 return;
138 }
139
140 db_symformat = NULL;
141 printf("[ no symbol table formats found ]\n");
142
143 /* XXX: try SYMTAB_SPACE if we get this far? */
144 }
145
146 /*
147 * Add symbol table, with given name, to list of symbol tables.
148 */
149 int
150 db_add_symbol_table(start, end, name, ref)
151 char *start;
152 char *end;
153 const char *name;
154 char *ref;
155 {
156 int slot;
157
158 for (slot = 0; slot < MAXNOSYMTABS; slot++) {
159 if (db_symtabs[slot].name == NULL)
160 break;
161 }
162 if (slot >= MAXNOSYMTABS) {
163 db_printf("No slots left for %s symbol table", name);
164 return(-1);
165 }
166
167 db_symtabs[slot].start = start;
168 db_symtabs[slot].end = end;
169 db_symtabs[slot].name = name;
170 db_symtabs[slot].private = ref;
171
172 return(slot);
173 }
174
175 /*
176 * Delete a symbol table. Caller is responsible for freeing storage.
177 */
178 void
179 db_del_symbol_table(name)
180 char *name;
181 {
182 int slot;
183
184 for (slot = 0; slot < MAXNOSYMTABS; slot++) {
185 if (db_symtabs[slot].name &&
186 ! strcmp(db_symtabs[slot].name, name))
187 break;
188 }
189 if (slot >= MAXNOSYMTABS) {
190 db_printf("Unable to find symbol table slot for %s.", name);
191 return;
192 }
193
194 db_symtabs[slot].start = 0;
195 db_symtabs[slot].end = 0;
196 db_symtabs[slot].name = 0;
197 db_symtabs[slot].private = 0;
198 }
199
200 /*
201 * db_qualify("vm_map", "netbsd") returns "netbsd:vm_map".
202 *
203 * Note: return value points to static data whose content is
204 * overwritten by each call... but in practice this seems okay.
205 */
206 static char *
207 db_qualify(sym, symtabname)
208 db_sym_t sym;
209 const char *symtabname;
210 {
211 char *symname;
212 static char tmp[256];
213 char *s;
214
215 db_symbol_values(sym, &symname, 0);
216 s = tmp;
217 while ((*s++ = *symtabname++) != '\0')
218 ;
219 s[-1] = ':';
220 while ((*s++ = *symname++) != '\0')
221 ;
222 return tmp;
223 }
224
225
226 boolean_t
227 db_eqname(src, dst, c)
228 char *src;
229 char *dst;
230 int c;
231 {
232 if (!strcmp(src, dst))
233 return (TRUE);
234 if (src[0] == c)
235 return (!strcmp(src+1,dst));
236 return (FALSE);
237 }
238
239 boolean_t
240 db_value_of_name(name, valuep)
241 char *name;
242 db_expr_t *valuep;
243 {
244 db_sym_t sym;
245
246 sym = db_lookup(name);
247 if (sym == DB_SYM_NULL)
248 return (FALSE);
249 db_symbol_values(sym, &name, valuep);
250 return (TRUE);
251 }
252
253
254 /*
255 * Lookup a symbol.
256 * If the symbol has a qualifier (e.g., ux:vm_map),
257 * then only the specified symbol table will be searched;
258 * otherwise, all symbol tables will be searched.
259 */
260 db_sym_t
261 db_lookup(symstr)
262 char *symstr;
263 {
264 db_sym_t sp;
265 int i;
266 int symtab_start = 0;
267 int symtab_end = MAXNOSYMTABS;
268 char *cp;
269
270 /*
271 * Look for, remove, and remember any symbol table specifier.
272 */
273 for (cp = symstr; *cp; cp++) {
274 if (*cp == ':') {
275 *cp = '\0';
276 for (i = 0; i < MAXNOSYMTABS; i++) {
277 if (db_symtabs[i].name &&
278 ! strcmp(symstr, db_symtabs[i].name)) {
279 symtab_start = i;
280 symtab_end = i + 1;
281 break;
282 }
283 }
284 *cp = ':';
285 if (i == MAXNOSYMTABS) {
286 db_error("invalid symbol table name");
287 /*NOTREACHED*/
288 }
289 symstr = cp+1;
290 }
291 }
292
293 /*
294 * Look in the specified set of symbol tables.
295 * Return on first match.
296 */
297 for (i = symtab_start; i < symtab_end; i++) {
298 if (db_symtabs[i].name &&
299 (sp = X_db_lookup(&db_symtabs[i], symstr))) {
300 db_last_symtab = &db_symtabs[i];
301 return sp;
302 }
303 }
304 return 0;
305 }
306
307 /* Private structure for passing args to db_sift() from db_sifting(). */
308 struct db_sift_args {
309 char *symstr;
310 int mode;
311 };
312
313 /*
314 * Does the work of db_sifting(), called once for each
315 * symbol via X_db_forall(), prints out symbols matching
316 * criteria.
317 */
318 static void
319 db_sift(stab, sym, name, suffix, prefix, arg)
320 db_symtab_t *stab;
321 db_sym_t sym;
322 char *name;
323 char *suffix;
324 int prefix;
325 void *arg;
326 {
327 char c, sc;
328 char *find, *p;
329 size_t len;
330 struct db_sift_args *dsa;
331
332 dsa = (struct db_sift_args*)arg;
333
334 find = dsa->symstr; /* String we're looking for. */
335 p = name; /* String we're searching within. */
336
337 /* Matching algorithm cribbed from strstr(), which is not
338 in the kernel. */
339 if ((c = *find++) != 0) {
340 len = strlen(find);
341 do {
342 do {
343 if ((sc = *p++) == 0)
344 return;
345 } while (sc != c);
346 } while (strncmp(p, find, len) != 0);
347 }
348 if (dsa->mode=='F') /* ala ls -F */
349 db_printf("%s%s ", name, suffix);
350 else
351 db_printf("%s ", name);
352 }
353
354 /*
355 * "Sift" for a partial symbol.
356 * Named for the Sun OpenPROM command ("sifting").
357 * If the symbol has a qualifier (e.g., ux:vm_map),
358 * then only the specified symbol table will be searched;
359 * otherwise, all symbol tables will be searched..
360 *
361 * "mode" is how-to-display, set from modifiers.
362 */
363 void
364 db_sifting(symstr, mode)
365 char *symstr;
366 int mode;
367 {
368 char *cp;
369 int i;
370 int symtab_start = 0;
371 int symtab_end = MAXNOSYMTABS;
372 struct db_sift_args dsa;
373
374 /*
375 * Look for, remove, and remember any symbol table specifier.
376 */
377 for (cp = symstr; *cp; cp++) {
378 if (*cp == ':') {
379 *cp = '\0';
380 for (i = 0; i < MAXNOSYMTABS; i++) {
381 if (db_symtabs[i].name &&
382 ! strcmp(symstr, db_symtabs[i].name)) {
383 symtab_start = i;
384 symtab_end = i + 1;
385 break;
386 }
387 }
388 *cp = ':';
389 if (i == MAXNOSYMTABS) {
390 db_error("invalid symbol table name");
391 /*NOTREACHED*/
392 }
393 symstr = cp+1;
394 }
395 }
396
397 /* Pass args to db_sift(). */
398 dsa.symstr = symstr;
399 dsa.mode = mode;
400
401 /*
402 * Look in the specified set of symbol tables.
403 */
404 for (i = symtab_start; i < symtab_end; i++)
405 if (db_symtabs[i].name) {
406 db_printf("Sifting table %s:\n", db_symtabs[i].name);
407 X_db_forall(&db_symtabs[i], db_sift, &dsa);
408 }
409
410 return;
411 }
412
413
414 /*
415 * Does this symbol name appear in more than one symbol table?
416 * Used by db_symbol_values to decide whether to qualify a symbol.
417 */
418 boolean_t db_qualify_ambiguous_names = FALSE;
419
420 boolean_t
421 db_symbol_is_ambiguous(sym)
422 db_sym_t sym;
423 {
424 char *sym_name;
425 int i;
426 boolean_t found_once = FALSE;
427
428 if (!db_qualify_ambiguous_names)
429 return FALSE;
430
431 db_symbol_values(sym, &sym_name, 0);
432 for (i = 0; i < MAXNOSYMTABS; i++) {
433 if (db_symtabs[i].name &&
434 X_db_lookup(&db_symtabs[i], sym_name)) {
435 if (found_once)
436 return TRUE;
437 found_once = TRUE;
438 }
439 }
440 return FALSE;
441 }
442
443 /*
444 * Find the closest symbol to val, and return its name
445 * and the difference between val and the symbol found.
446 */
447 db_sym_t
448 db_search_symbol( val, strategy, offp)
449 db_addr_t val;
450 db_strategy_t strategy;
451 db_expr_t *offp;
452 {
453 unsigned int diff;
454 db_expr_t newdiff;
455 int i;
456 db_sym_t ret = DB_SYM_NULL, sym;
457
458 newdiff = diff = ~0;
459 db_last_symtab = 0;
460 for (i = 0; i < MAXNOSYMTABS; i++) {
461 if (!db_symtabs[i].name)
462 continue;
463 sym = X_db_search_symbol(&db_symtabs[i], val, strategy, &newdiff);
464 if (newdiff < diff) {
465 db_last_symtab = &db_symtabs[i];
466 diff = newdiff;
467 ret = sym;
468 }
469 }
470 *offp = diff;
471 return ret;
472 }
473
474 /*
475 * Return name and value of a symbol
476 */
477 void
478 db_symbol_values(sym, namep, valuep)
479 db_sym_t sym;
480 char **namep;
481 db_expr_t *valuep;
482 {
483 db_expr_t value;
484
485 if (sym == DB_SYM_NULL) {
486 *namep = 0;
487 return;
488 }
489
490 X_db_symbol_values(db_last_symtab, sym, namep, &value);
491
492 if (db_symbol_is_ambiguous(sym))
493 *namep = db_qualify(sym, db_last_symtab->name);
494 if (valuep)
495 *valuep = value;
496 }
497
498
499 /*
500 * Print a the closest symbol to value
501 *
502 * After matching the symbol according to the given strategy
503 * we print it in the name+offset format, provided the symbol's
504 * value is close enough (eg smaller than db_maxoff).
505 * We also attempt to print [filename:linenum] when applicable
506 * (eg for procedure names).
507 *
508 * If we could not find a reasonable name+offset representation,
509 * then we just print the value in hex. Small values might get
510 * bogus symbol associations, e.g. 3 might get some absolute
511 * value like _INCLUDE_VERSION or something, therefore we do
512 * not accept symbols whose value is zero (and use plain hex).
513 * Also, avoid printing as "end+0x????" which is useless.
514 * The variable db_lastsym is used instead of "end" in case we
515 * add support for symbols in loadable driver modules.
516 */
517 extern char end[];
518 unsigned long db_lastsym = (unsigned long)end;
519 unsigned int db_maxoff = 0x10000000;
520
521
522 void
523 db_printsym(off, strategy, pr)
524 db_expr_t off;
525 db_strategy_t strategy;
526 void (*pr) __P((const char *, ...));
527 {
528 db_expr_t d;
529 char *filename;
530 char *name;
531 db_expr_t value;
532 int linenum;
533 db_sym_t cursym;
534
535 if (off <= db_lastsym) {
536 cursym = db_search_symbol(off, strategy, &d);
537 db_symbol_values(cursym, &name, &value);
538 if (name && (d < db_maxoff) && value) {
539 (*pr)("%s", name);
540 if (d) {
541 char tbuf[24];
542
543 db_format_radix(tbuf, 24, d, TRUE);
544 (*pr)("+%s", tbuf);
545 }
546 if (strategy == DB_STGY_PROC) {
547 if (db_line_at_pc(cursym, &filename, &linenum, off))
548 (*pr)(" [%s:%d]", filename, linenum);
549 }
550 return;
551 }
552 }
553 (*pr)(db_num_to_str(off));
554 return;
555 }
556
557
558 boolean_t
559 db_line_at_pc( sym, filename, linenum, pc)
560 db_sym_t sym;
561 char **filename;
562 int *linenum;
563 db_expr_t pc;
564 {
565 return X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc);
566 }
567
568 int
569 db_sym_numargs(sym, nargp, argnames)
570 db_sym_t sym;
571 int *nargp;
572 char **argnames;
573 {
574 return X_db_sym_numargs(db_last_symtab, sym, nargp, argnames);
575 }
576
577 boolean_t
578 X_db_sym_init(symsize, vss, vse, name)
579 int symsize;
580 void *vss, *vse;
581 const char *name;
582 {
583
584 if (db_symformat != NULL)
585 return ((*db_symformat->sym_init)(symsize, vss, vse, name));
586 return (FALSE);
587 }
588
589 db_sym_t
590 X_db_lookup(stab, symstr)
591 db_symtab_t *stab;
592 char *symstr;
593 {
594
595 if (db_symformat != NULL)
596 return ((*db_symformat->sym_lookup)(stab, symstr));
597 return ((db_sym_t)0);
598 }
599
600 db_sym_t
601 X_db_search_symbol(stab, off, strategy, diffp)
602 db_symtab_t *stab;
603 db_addr_t off;
604 db_strategy_t strategy;
605 db_expr_t *diffp;
606 {
607
608 if (db_symformat != NULL)
609 return ((*db_symformat->sym_search)(stab, off, strategy,
610 diffp));
611 return ((db_sym_t)0);
612 }
613
614 void
615 X_db_symbol_values(stab, sym, namep, valuep)
616 db_symtab_t *stab;
617 db_sym_t sym;
618 char **namep;
619 db_expr_t *valuep;
620 {
621
622 if (db_symformat != NULL)
623 (*db_symformat->sym_value)(stab, sym, namep, valuep);
624 }
625
626 boolean_t
627 X_db_line_at_pc(stab, cursym, filename, linenum, off)
628 db_symtab_t *stab;
629 db_sym_t cursym;
630 char **filename;
631 int *linenum;
632 db_expr_t off;
633 {
634
635 if (db_symformat != NULL)
636 return ((*db_symformat->sym_line_at_pc)(stab, cursym,
637 filename, linenum, off));
638 return (FALSE);
639 }
640
641 boolean_t
642 X_db_sym_numargs(stab, cursym, nargp, argnamep)
643 db_symtab_t *stab;
644 db_sym_t cursym;
645 int *nargp;
646 char **argnamep;
647 {
648
649 if (db_symformat != NULL)
650 return ((*db_symformat->sym_numargs)(stab, cursym, nargp,
651 argnamep));
652 return (FALSE);
653 }
654
655 void
656 X_db_forall(stab, db_forall_func, arg)
657 db_symtab_t *stab;
658 db_forall_func_t db_forall_func;
659 void *arg;
660 {
661 if (db_symformat != NULL)
662 (*db_symformat->sym_forall)(stab, db_forall_func, arg);
663 }
664