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