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