sync
[bitrig.git] / sys / ddb / db_sym.c
blob561cc0b63c84a8625cd599a5605ede6608b4e9a9
1 /* $OpenBSD: db_sym.c,v 1.32 2006/03/13 06:23:20 jsg Exp $ */
2 /* $NetBSD: db_sym.c,v 1.24 2000/08/11 22:50:47 tv Exp $ */
4 /*
5 * Mach Operating System
6 * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
7 * All Rights Reserved.
8 *
9 * Permission to use, copy, modify and distribute this software and its
10 * documentation is hereby granted, provided that both the copyright
11 * notice and this permission notice appear in all copies of the
12 * software, derivative works or modified versions, and any portions
13 * thereof, and that both notices appear in supporting documentation.
15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
17 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
19 * Carnegie Mellon requests users of this software to return to
21 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
22 * School of Computer Science
23 * Carnegie Mellon University
24 * Pittsburgh PA 15213-3890
26 * any improvements or extensions that they make and grant Carnegie Mellon
27 * the rights to redistribute these changes.
30 #include <sys/param.h>
31 #include <sys/proc.h>
32 #include <sys/systm.h>
34 #include <machine/db_machdep.h>
36 #include <ddb/db_lex.h>
37 #include <ddb/db_sym.h>
38 #include <ddb/db_output.h>
39 #include <ddb/db_extern.h>
40 #include <ddb/db_command.h>
43 * Multiple symbol tables
45 #ifndef MAXLKMS
46 #define MAXLKMS 20
47 #endif
49 #ifndef MAXNOSYMTABS
50 #define MAXNOSYMTABS MAXLKMS+1 /* Room for kernel + LKM's */
51 #endif
53 db_symtab_t db_symtabs[MAXNOSYMTABS] = {{0,},};
55 db_symtab_t *db_last_symtab;
57 static db_forall_func_t db_sift;
59 extern char end[];
62 * Put the most picky symbol table formats at the top!
64 const db_symformat_t *db_symformats[] = {
65 #ifdef DB_ELF_SYMBOLS
66 &db_symformat_elf,
67 #endif
68 NULL,
71 const db_symformat_t *db_symformat;
73 boolean_t X_db_sym_init(int, void *, void *, const char *);
74 db_sym_t X_db_lookup(db_symtab_t *, char *);
75 db_sym_t X_db_search_symbol(db_symtab_t *, db_addr_t,
76 db_strategy_t, db_expr_t *);
77 void X_db_symbol_values(db_symtab_t *, db_sym_t, char **,
78 db_expr_t *);
79 boolean_t X_db_line_at_pc(db_symtab_t *, db_sym_t, char **,
80 int *, db_expr_t);
81 int X_db_sym_numargs(db_symtab_t *, db_sym_t, int *,
82 char **);
85 * Initialize the kernel debugger by initializing the master symbol
86 * table. Note that if initializing the master symbol table fails,
87 * no other symbol tables can be loaded.
89 #if 0
90 void
91 ddb_init(int symsize, void *vss, void *vse)
93 const db_symformat_t **symf;
94 const char *name = "bsd";
96 if (symsize <= 0) {
97 printf(" [ no symbols available ]\n");
98 return;
102 * Do this check now for the master symbol table to avoid printing
103 * the message N times.
105 if (ALIGNED_POINTER(vss, long) == 0) {
106 printf("[ %s symbol table has bad start address %p ]\n",
107 name, vss);
108 return;
111 for (symf = db_symformats; *symf != NULL; symf++) {
112 db_symformat = *symf;
113 if (X_db_sym_init(symsize, vss, vse, name) == TRUE)
114 return;
117 db_symformat = NULL;
118 printf("[ no symbol table formats found ]\n");
120 #else
121 void
122 ddb_init(void)
124 const db_symformat_t **symf;
125 const char *name = "bsd";
126 extern char *esym;
127 #if defined(__sparc64__) || defined(__mips__)
128 extern char *ssym;
129 #endif
130 char *xssym, *xesym;
132 xesym = esym;
133 #if defined(__sparc64__) || defined(__mips__)
134 xssym = ssym;
135 #else
136 xssym = (char *)&end;
137 #endif
139 * Do this check now for the master symbol table to avoid printing
140 * the message N times.
142 if ((((vaddr_t)xssym) & (sizeof(long) - 1)) != 0) {
143 printf("[ %s symbol table has bad start address %p ]\n",
144 name, xssym);
145 return;
148 if (xesym != NULL && xesym != xssym)
149 for (symf = db_symformats; *symf != NULL; symf++) {
150 db_symformat = *symf;
151 if (X_db_sym_init((vaddr_t)xesym - (vaddr_t)xssym,
152 xssym, xesym, name) == TRUE)
153 return;
156 db_symformat = NULL;
157 printf("[ no symbol table formats found ]\n");
159 #endif
162 * Add symbol table, with given name, to list of symbol tables.
165 db_add_symbol_table(char *start, char *end, const char *name, char *ref)
167 int slot;
169 for (slot = 0; slot < MAXNOSYMTABS; slot++) {
170 if (db_symtabs[slot].name == NULL)
171 break;
173 if (slot >= MAXNOSYMTABS) {
174 db_printf("No slots left for %s symbol table", name);
175 return(-1);
178 db_symtabs[slot].start = start;
179 db_symtabs[slot].end = end;
180 db_symtabs[slot].name = name;
181 db_symtabs[slot].private = ref;
183 return(slot);
187 * Delete a symbol table. Caller is responsible for freeing storage.
189 void
190 db_del_symbol_table(char *name)
192 int slot;
194 for (slot = 0; slot < MAXNOSYMTABS; slot++) {
195 if (db_symtabs[slot].name &&
196 ! strcmp(db_symtabs[slot].name, name))
197 break;
199 if (slot >= MAXNOSYMTABS) {
200 db_printf("Unable to find symbol table slot for %s.", name);
201 return;
204 db_symtabs[slot].start = 0;
205 db_symtabs[slot].end = 0;
206 db_symtabs[slot].name = 0;
207 db_symtabs[slot].private = 0;
211 * db_qualify("vm_map", "bsd") returns "bsd:vm_map".
213 * Note: return value points to static data whose content is
214 * overwritten by each call... but in practice this seems okay.
216 char *
217 db_qualify(db_sym_t sym, const char *symtabname)
219 char *symname;
220 static char tmp[256];
221 char *s;
223 db_symbol_values(sym, &symname, 0);
224 s = tmp;
225 while ((*s++ = *symtabname++) != '\0')
227 s[-1] = ':';
228 while ((*s++ = *symname++) != '\0')
230 return tmp;
234 boolean_t
235 db_eqname(char *src, char *dst, int c)
237 if (!strcmp(src, dst))
238 return (TRUE);
239 if (src[0] == c)
240 return (!strcmp(src+1,dst));
241 return (FALSE);
244 boolean_t
245 db_value_of_name(char *name, db_expr_t *valuep)
247 db_sym_t sym;
249 sym = db_lookup(name);
250 if (sym == DB_SYM_NULL)
251 return (FALSE);
252 db_symbol_values(sym, &name, valuep);
253 return (TRUE);
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.
263 db_sym_t
264 db_lookup(char *symstr)
266 db_sym_t sp;
267 int i;
268 int symtab_start = 0;
269 int symtab_end = MAXNOSYMTABS;
270 char *cp;
273 * Look for, remove, and remember any symbol table specifier.
275 for (cp = symstr; *cp; cp++) {
276 if (*cp == ':') {
277 *cp = '\0';
278 for (i = 0; i < MAXNOSYMTABS; i++) {
279 if (db_symtabs[i].name &&
280 ! strcmp(symstr, db_symtabs[i].name)) {
281 symtab_start = i;
282 symtab_end = i + 1;
283 break;
286 *cp = ':';
287 if (i == MAXNOSYMTABS) {
288 db_error("invalid symbol table name");
289 /*NOTREACHED*/
291 symstr = cp+1;
296 * Look in the specified set of symbol tables.
297 * Return on first match.
299 for (i = symtab_start; i < symtab_end; i++) {
300 if (db_symtabs[i].name &&
301 (sp = X_db_lookup(&db_symtabs[i], symstr))) {
302 db_last_symtab = &db_symtabs[i];
303 return sp;
306 return 0;
309 /* Private structure for passing args to db_sift() from db_sifting(). */
310 struct db_sift_args {
311 char *symstr;
312 int mode;
316 * Does the work of db_sifting(), called once for each
317 * symbol via X_db_forall(), prints out symbols matching
318 * criteria.
320 static void
321 db_sift(db_symtab_t *stab, db_sym_t sym, char *name, char *suffix, int prefix,
322 void *arg)
324 char c, sc;
325 char *find, *p;
326 size_t len;
327 struct db_sift_args *dsa;
329 dsa = (struct db_sift_args*)arg;
331 find = dsa->symstr; /* String we're looking for. */
332 p = name; /* String we're searching within. */
334 /* Matching algorithm cribbed from strstr(), which is not
335 in the kernel. */
336 if ((c = *find++) != 0) {
337 len = strlen(find);
338 do {
339 do {
340 if ((sc = *p++) == 0)
341 return;
342 } while (sc != c);
343 } while (strncmp(p, find, len) != 0);
345 if (dsa->mode=='F') /* ala ls -F */
346 db_printf("%s%s ", name, suffix);
347 else
348 db_printf("%s ", name);
352 * "Sift" for a partial symbol.
353 * Named for the Sun OpenPROM command ("sifting").
354 * If the symbol has a qualifier (e.g., ux:vm_map),
355 * then only the specified symbol table will be searched;
356 * otherwise, all symbol tables will be searched..
358 * "mode" is how-to-display, set from modifiers.
360 void
361 db_sifting(char *symstr, int mode)
363 char *cp;
364 int i;
365 int symtab_start = 0;
366 int symtab_end = MAXNOSYMTABS;
367 struct db_sift_args dsa;
370 * Look for, remove, and remember any symbol table specifier.
372 for (cp = symstr; *cp; cp++) {
373 if (*cp == ':') {
374 *cp = '\0';
375 for (i = 0; i < MAXNOSYMTABS; i++) {
376 if (db_symtabs[i].name &&
377 ! strcmp(symstr, db_symtabs[i].name)) {
378 symtab_start = i;
379 symtab_end = i + 1;
380 break;
383 *cp = ':';
384 if (i == MAXNOSYMTABS) {
385 db_error("invalid symbol table name");
386 /*NOTREACHED*/
388 symstr = cp+1;
392 /* Pass args to db_sift(). */
393 dsa.symstr = symstr;
394 dsa.mode = mode;
397 * Look in the specified set of symbol tables.
399 for (i = symtab_start; i < symtab_end; i++)
400 if (db_symtabs[i].name) {
401 db_printf("Sifting table %s:\n", db_symtabs[i].name);
402 X_db_forall(&db_symtabs[i], db_sift, &dsa);
405 return;
410 * Does this symbol name appear in more than one symbol table?
411 * Used by db_symbol_values to decide whether to qualify a symbol.
413 boolean_t db_qualify_ambiguous_names = FALSE;
415 boolean_t
416 db_symbol_is_ambiguous(db_sym_t sym)
418 char *sym_name;
419 int i;
420 boolean_t found_once = FALSE;
422 if (!db_qualify_ambiguous_names)
423 return FALSE;
425 db_symbol_values(sym, &sym_name, 0);
426 for (i = 0; i < MAXNOSYMTABS; i++) {
427 if (db_symtabs[i].name &&
428 X_db_lookup(&db_symtabs[i], sym_name)) {
429 if (found_once)
430 return TRUE;
431 found_once = TRUE;
434 return FALSE;
438 * Find the closest symbol to val, and return its name
439 * and the difference between val and the symbol found.
441 db_sym_t
442 db_search_symbol(db_addr_t val, db_strategy_t strategy, db_expr_t *offp)
444 unsigned int diff;
445 db_expr_t newdiff;
446 int i;
447 db_sym_t ret = DB_SYM_NULL, sym;
449 newdiff = diff = ~0;
450 db_last_symtab = 0;
451 for (i = 0; i < MAXNOSYMTABS; i++) {
452 if (!db_symtabs[i].name)
453 continue;
454 sym = X_db_search_symbol(&db_symtabs[i], val, strategy, &newdiff);
455 if (newdiff < diff) {
456 db_last_symtab = &db_symtabs[i];
457 diff = newdiff;
458 ret = sym;
461 *offp = diff;
462 return ret;
466 * Return name and value of a symbol
468 void
469 db_symbol_values(db_sym_t sym, char **namep, db_expr_t *valuep)
471 db_expr_t value;
473 if (sym == DB_SYM_NULL) {
474 *namep = 0;
475 return;
478 X_db_symbol_values(db_last_symtab, sym, namep, &value);
480 if (db_symbol_is_ambiguous(sym))
481 *namep = db_qualify(sym, db_last_symtab->name);
482 if (valuep)
483 *valuep = value;
488 * Print a the closest symbol to value
490 * After matching the symbol according to the given strategy
491 * we print it in the name+offset format, provided the symbol's
492 * value is close enough (eg smaller than db_maxoff).
493 * We also attempt to print [filename:linenum] when applicable
494 * (eg for procedure names).
496 * If we could not find a reasonable name+offset representation,
497 * then we just print the value in hex. Small values might get
498 * bogus symbol associations, e.g. 3 might get some absolute
499 * value like _INCLUDE_VERSION or something, therefore we do
500 * not accept symbols whose value is zero (and use plain hex).
501 * Also, avoid printing as "end+0x????" which is useless.
502 * The variable db_lastsym is used instead of "end" in case we
503 * add support for symbols in loadable driver modules.
505 unsigned long db_lastsym = (unsigned long)end;
506 unsigned int db_maxoff = 0x10000000;
509 void
510 db_printsym(db_expr_t off, db_strategy_t strategy,
511 int (*pr)(const char *, ...))
513 db_expr_t d;
514 char *filename;
515 char *name;
516 db_expr_t value;
517 int linenum;
518 db_sym_t cursym;
519 char buf[DB_FORMAT_BUF_SIZE];
521 if (off <= db_lastsym) {
522 cursym = db_search_symbol(off, strategy, &d);
523 db_symbol_values(cursym, &name, &value);
524 if (name && (d < db_maxoff) && value) {
525 (*pr)("%s", name);
526 if (d) {
527 (*pr)("+%s", db_format(buf, sizeof(buf),
528 d, DB_FORMAT_R, 1, 0));
530 if (strategy == DB_STGY_PROC) {
531 if (db_line_at_pc(cursym, &filename, &linenum, off))
532 (*pr)(" [%s:%d]", filename, linenum);
534 return;
538 (*pr)("%s", db_format(buf, sizeof(buf), off, DB_FORMAT_N, 1, 0));
539 return;
543 boolean_t
544 db_line_at_pc(db_sym_t sym, char **filename, int *linenum, db_expr_t pc)
546 return X_db_line_at_pc(db_last_symtab, sym, filename, linenum, pc);
550 db_sym_numargs(db_sym_t sym, int *nargp, char **argnames)
552 return X_db_sym_numargs(db_last_symtab, sym, nargp, argnames);
555 boolean_t
556 X_db_sym_init(int symsize, void *vss, void *vse, const char *name)
559 if (db_symformat != NULL)
560 return ((*db_symformat->sym_init)(symsize, vss, vse, name));
561 return (FALSE);
564 db_sym_t
565 X_db_lookup(db_symtab_t *stab, char *symstr)
568 if (db_symformat != NULL)
569 return ((*db_symformat->sym_lookup)(stab, symstr));
570 return ((db_sym_t)0);
573 db_sym_t
574 X_db_search_symbol(db_symtab_t *stab, db_addr_t off, db_strategy_t strategy,
575 db_expr_t *diffp)
578 if (db_symformat != NULL)
579 return ((*db_symformat->sym_search)(stab, off, strategy,
580 diffp));
581 return ((db_sym_t)0);
584 void
585 X_db_symbol_values(db_symtab_t *stab, db_sym_t sym, char **namep,
586 db_expr_t *valuep)
589 if (db_symformat != NULL)
590 (*db_symformat->sym_value)(stab, sym, namep, valuep);
593 boolean_t
594 X_db_line_at_pc(db_symtab_t *stab, db_sym_t cursym, char **filename,
595 int *linenum, db_expr_t off)
598 if (db_symformat != NULL)
599 return ((*db_symformat->sym_line_at_pc)(stab, cursym,
600 filename, linenum, off));
601 return (FALSE);
604 boolean_t
605 X_db_sym_numargs(db_symtab_t *stab, db_sym_t cursym, int *nargp,
606 char **argnamep)
609 if (db_symformat != NULL)
610 return ((*db_symformat->sym_numargs)(stab, cursym, nargp,
611 argnamep));
612 return (FALSE);
615 void
616 X_db_forall(db_symtab_t *stab, db_forall_func_t db_forall_func, void *arg)
618 if (db_symformat != NULL)
619 (*db_symformat->sym_forall)(stab, db_forall_func, arg);