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