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