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