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 $ */
5 * Mach Operating System
6 * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
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>
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
50 #define MAXNOSYMTABS MAXLKMS+1 /* Room for kernel + LKM's */
53 db_symtab_t db_symtabs
[MAXNOSYMTABS
] = {{0,},};
55 db_symtab_t
*db_last_symtab
;
57 static db_forall_func_t db_sift
;
62 * Put the most picky symbol table formats at the top!
64 const db_symformat_t
*db_symformats
[] = {
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 **,
79 boolean_t
X_db_line_at_pc(db_symtab_t
*, db_sym_t
, char **,
81 int X_db_sym_numargs(db_symtab_t
*, db_sym_t
, int *,
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.
91 ddb_init(int symsize
, void *vss
, void *vse
)
93 const db_symformat_t
**symf
;
94 const char *name
= "bsd";
97 printf(" [ no symbols available ]\n");
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",
111 for (symf
= db_symformats
; *symf
!= NULL
; symf
++) {
112 db_symformat
= *symf
;
113 if (X_db_sym_init(symsize
, vss
, vse
, name
) == TRUE
)
118 printf("[ no symbol table formats found ]\n");
124 const db_symformat_t
**symf
;
125 const char *name
= "bsd";
127 #if defined(__sparc64__) || defined(__mips__)
133 #if defined(__sparc64__) || defined(__mips__)
136 xssym
= (char *)&end
;
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",
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
)
157 printf("[ no symbol table formats found ]\n");
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
)
169 for (slot
= 0; slot
< MAXNOSYMTABS
; slot
++) {
170 if (db_symtabs
[slot
].name
== NULL
)
173 if (slot
>= MAXNOSYMTABS
) {
174 db_printf("No slots left for %s symbol table", name
);
178 db_symtabs
[slot
].start
= start
;
179 db_symtabs
[slot
].end
= end
;
180 db_symtabs
[slot
].name
= name
;
181 db_symtabs
[slot
].private = ref
;
187 * Delete a symbol table. Caller is responsible for freeing storage.
190 db_del_symbol_table(char *name
)
194 for (slot
= 0; slot
< MAXNOSYMTABS
; slot
++) {
195 if (db_symtabs
[slot
].name
&&
196 ! strcmp(db_symtabs
[slot
].name
, name
))
199 if (slot
>= MAXNOSYMTABS
) {
200 db_printf("Unable to find symbol table slot for %s.", name
);
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.
217 db_qualify(db_sym_t sym
, const char *symtabname
)
220 static char tmp
[256];
223 db_symbol_values(sym
, &symname
, 0);
225 while ((*s
++ = *symtabname
++) != '\0')
228 while ((*s
++ = *symname
++) != '\0')
235 db_eqname(char *src
, char *dst
, int c
)
237 if (!strcmp(src
, dst
))
240 return (!strcmp(src
+1,dst
));
245 db_value_of_name(char *name
, db_expr_t
*valuep
)
249 sym
= db_lookup(name
);
250 if (sym
== DB_SYM_NULL
)
252 db_symbol_values(sym
, &name
, valuep
);
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.
264 db_lookup(char *symstr
)
268 int symtab_start
= 0;
269 int symtab_end
= MAXNOSYMTABS
;
273 * Look for, remove, and remember any symbol table specifier.
275 for (cp
= symstr
; *cp
; cp
++) {
278 for (i
= 0; i
< MAXNOSYMTABS
; i
++) {
279 if (db_symtabs
[i
].name
&&
280 ! strcmp(symstr
, db_symtabs
[i
].name
)) {
287 if (i
== MAXNOSYMTABS
) {
288 db_error("invalid symbol table name");
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
];
309 /* Private structure for passing args to db_sift() from db_sifting(). */
310 struct db_sift_args
{
316 * Does the work of db_sifting(), called once for each
317 * symbol via X_db_forall(), prints out symbols matching
321 db_sift(db_symtab_t
*stab
, db_sym_t sym
, char *name
, char *suffix
, int prefix
,
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
336 if ((c
= *find
++) != 0) {
340 if ((sc
= *p
++) == 0)
343 } while (strncmp(p
, find
, len
) != 0);
345 if (dsa
->mode
=='F') /* ala ls -F */
346 db_printf("%s%s ", name
, suffix
);
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.
361 db_sifting(char *symstr
, int mode
)
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
++) {
375 for (i
= 0; i
< MAXNOSYMTABS
; i
++) {
376 if (db_symtabs
[i
].name
&&
377 ! strcmp(symstr
, db_symtabs
[i
].name
)) {
384 if (i
== MAXNOSYMTABS
) {
385 db_error("invalid symbol table name");
392 /* Pass args to db_sift(). */
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
);
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
;
416 db_symbol_is_ambiguous(db_sym_t sym
)
420 boolean_t found_once
= FALSE
;
422 if (!db_qualify_ambiguous_names
)
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
)) {
438 * Find the closest symbol to val, and return its name
439 * and the difference between val and the symbol found.
442 db_search_symbol(db_addr_t val
, db_strategy_t strategy
, db_expr_t
*offp
)
447 db_sym_t ret
= DB_SYM_NULL
, sym
;
451 for (i
= 0; i
< MAXNOSYMTABS
; i
++) {
452 if (!db_symtabs
[i
].name
)
454 sym
= X_db_search_symbol(&db_symtabs
[i
], val
, strategy
, &newdiff
);
455 if (newdiff
< diff
) {
456 db_last_symtab
= &db_symtabs
[i
];
466 * Return name and value of a symbol
469 db_symbol_values(db_sym_t sym
, char **namep
, db_expr_t
*valuep
)
473 if (sym
== DB_SYM_NULL
) {
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
);
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;
510 db_printsym(db_expr_t off
, db_strategy_t strategy
,
511 int (*pr
)(const char *, ...))
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
) {
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
);
538 (*pr
)("%s", db_format(buf
, sizeof(buf
), off
, DB_FORMAT_N
, 1, 0));
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
);
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
));
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);
574 X_db_search_symbol(db_symtab_t
*stab
, db_addr_t off
, db_strategy_t strategy
,
578 if (db_symformat
!= NULL
)
579 return ((*db_symformat
->sym_search
)(stab
, off
, strategy
,
581 return ((db_sym_t
)0);
585 X_db_symbol_values(db_symtab_t
*stab
, db_sym_t sym
, char **namep
,
589 if (db_symformat
!= NULL
)
590 (*db_symformat
->sym_value
)(stab
, sym
, namep
, valuep
);
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
));
605 X_db_sym_numargs(db_symtab_t
*stab
, db_sym_t cursym
, int *nargp
,
609 if (db_symformat
!= NULL
)
610 return ((*db_symformat
->sym_numargs
)(stab
, cursym
, nargp
,
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
);