diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 2001-02-10 10:43:19 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 2001-02-10 10:43:19 +0000 |
commit | 5bfde2c9bd95671842fedd8d95bf23e072278fb3 (patch) | |
tree | 1abbcb3d3f121b6be953ef37a37676a20a6446cc /sys/ddb/db_sym.c | |
parent | 5e833b12704c89c1fad72b7b6f3706cfd15ab035 (diff) |
new symbol handling in ddb for ELF, there is still a problem with hangman on alpha though..
Diffstat (limited to 'sys/ddb/db_sym.c')
-rw-r--r-- | sys/ddb/db_sym.c | 484 |
1 files changed, 364 insertions, 120 deletions
diff --git a/sys/ddb/db_sym.c b/sys/ddb/db_sym.c index 0cf3ed052e6..0b4840c5304 100644 --- a/sys/ddb/db_sym.c +++ b/sys/ddb/db_sym.c @@ -1,5 +1,5 @@ -/* $OpenBSD: db_sym.c,v 1.21 1997/07/19 22:31:20 niklas Exp $ */ -/* $NetBSD: db_sym.c,v 1.12 1996/02/05 01:57:15 christos Exp $ */ +/* $OpenBSD: db_sym.c,v 1.22 2001/02/10 10:42:35 niklas Exp $ */ +/* $NetBSD: db_sym.c,v 1.24 2000/08/11 22:50:47 tv Exp $ */ /* * Mach Operating System @@ -29,13 +29,11 @@ #include <sys/param.h> #include <sys/proc.h> -#include <sys/malloc.h> #include <sys/systm.h> -#include <vm/vm.h> - #include <machine/db_machdep.h> +#include <ddb/db_lex.h> #include <ddb/db_sym.h> #include <ddb/db_output.h> #include <ddb/db_extern.h> @@ -44,47 +42,141 @@ /* * Multiple symbol tables */ -static TAILQ_HEAD(, db_symtab) db_symtabs; -static struct db_symtab db_sym_kernel; -size_t db_nsymtabs = 0; +#ifndef MAXLKMS +#define MAXLKMS 20 +#endif + +#ifndef MAXNOSYMTABS +#define MAXNOSYMTABS MAXLKMS+1 /* Room for kernel + LKM's */ +#endif + +db_symtab_t db_symtabs[MAXNOSYMTABS] = {{0,},}; -db_symtab_t db_last_symtab; +db_symtab_t *db_last_symtab; + +static db_forall_func_t db_sift; /* - * Init sym module + * Put the most picky symbol table formats at the top! */ +const db_symformat_t *db_symformats[] = { +#ifdef DB_ELF_SYMBOLS + &db_symformat_elf, +#endif +#ifdef DB_AOUT_SYMBOLS + &db_symformat_aout, +#endif + NULL, +}; + +const db_symformat_t *db_symformat; + +boolean_t X_db_sym_init __P((int, void *, void *, const char *)); +db_sym_t X_db_lookup __P((db_symtab_t *, char *)); +db_sym_t X_db_search_symbol __P((db_symtab_t *, db_addr_t, + db_strategy_t, db_expr_t *)); +void X_db_symbol_values __P((db_symtab_t *, db_sym_t, char **, + db_expr_t *)); +boolean_t X_db_line_at_pc __P((db_symtab_t *, db_sym_t, char **, + int *, db_expr_t)); +int X_db_sym_numargs __P((db_symtab_t *, db_sym_t, int *, + char **)); + +/* + * Initialize the kernel debugger by initializing the master symbol + * table. Note that if initializing the master symbol table fails, + * no other symbol tables can be loaded. + */ +#if 0 void -db_sym_init(void) +ddb_init(symsize, vss, vse) + int symsize; + void *vss, *vse; { - TAILQ_INIT(&db_symtabs); + const db_symformat_t **symf; + const char *name = "bsd"; + + if (symsize <= 0) { + printf(" [ no symbols available ]\n"); + return; + } + + /* + * Do this check now for the master symbol table to avoid printing + * the message N times. + */ + if (ALIGNED_POINTER(vss, long) == 0) { + printf("[ %s symbol table has bad start address %p ]\n", + name, vss); + return; + } + + for (symf = db_symformats; *symf != NULL; symf++) { + db_symformat = *symf; + if (X_db_sym_init(symsize, vss, vse, name) == TRUE) + return; + } + + db_symformat = NULL; + printf("[ no symbol table formats found ]\n"); +} +#else +void +ddb_init() +{ + const db_symformat_t **symf; + const char *name = "bsd"; + extern char *esym; + extern long end; + + /* + * Do this check now for the master symbol table to avoid printing + * the message N times. + */ + if ((((vaddr_t)&end) & (sizeof(long) - 1)) != 0) { + printf("[ %s symbol table has bad start address %p ]\n", + name, &end); + return; + } + + for (symf = db_symformats; *symf != NULL; symf++) { + db_symformat = *symf; + if (X_db_sym_init((long)esym - (long)&end, &end, esym, name) == TRUE) + return; + } + + db_symformat = NULL; + printf("[ no symbol table formats found ]\n"); } +#endif /* * Add symbol table, with given name, to list of symbol tables. */ int -db_add_symbol_table(start, end, name, ref, rend) +db_add_symbol_table(start, end, name, ref) char *start; char *end; - char *name; + const char *name; char *ref; - char *rend; { - db_symtab_t new = db_nsymtabs? NULL : &db_sym_kernel; + int slot; - if (new == NULL && - (new = malloc(sizeof(*new), M_DEVBUF, M_WAITOK)) == NULL) - return -1; + for (slot = 0; slot < MAXNOSYMTABS; slot++) { + if (db_symtabs[slot].name == NULL) + break; + } + if (slot >= MAXNOSYMTABS) { + db_printf("No slots left for %s symbol table", name); + return(-1); + } - new->start = start; - new->end = end; - new->name = name; - new->private = ref; - new->rend = rend; - new->id = db_nsymtabs; - TAILQ_INSERT_TAIL(&db_symtabs, new, list); + db_symtabs[slot].start = start; + db_symtabs[slot].end = end; + db_symtabs[slot].name = name; + db_symtabs[slot].private = ref; - return db_nsymtabs++; + return(slot); } /* @@ -94,43 +186,22 @@ void db_del_symbol_table(name) char *name; { - register db_symtab_t p; + int slot; - for (p = db_symiter(NULL); p != NULL; p = db_symiter(p)) - if (!strcmp(name, p->name)) + for (slot = 0; slot < MAXNOSYMTABS; slot++) { + if (db_symtabs[slot].name && + ! strcmp(db_symtabs[slot].name, name)) break; + } + if (slot >= MAXNOSYMTABS) { + db_printf("Unable to find symbol table slot for %s.", name); + return; + } - if (p == NULL) - db_printf("ddb: %s symbol table was not allocated", name); - - if (--db_nsymtabs == 0) - panic("ddb: kernel symtab delete"); - - TAILQ_REMOVE(&db_symtabs, p, list); - free(p, M_DEVBUF); -} - -db_symtab_t -db_istab(i) - size_t i; -{ - register db_symtab_t p; - - for (p = db_symiter(NULL); i && p != NULL ; p = db_symiter(p)) - i--; - - return i? NULL : p; -} - -db_symtab_t -db_symiter(st) - db_symtab_t st; -{ - if (st == NULL) - st = db_symtabs.tqh_first; - else - st = st->list.tqe_next; - return st; + db_symtabs[slot].start = 0; + db_symtabs[slot].end = 0; + db_symtabs[slot].name = 0; + db_symtabs[slot].private = 0; } /* @@ -142,11 +213,11 @@ db_symiter(st) char * db_qualify(sym, symtabname) db_sym_t sym; - register char *symtabname; + const char *symtabname; { char *symname; static char tmp[256]; - register char *s; + char *s; db_symbol_values(sym, &symname, 0); s = tmp; @@ -172,7 +243,6 @@ db_eqname(src, dst, c) return (FALSE); } -#ifdef DDB boolean_t db_value_of_name(name, valuep) char *name; @@ -187,6 +257,7 @@ db_value_of_name(name, valuep) return (TRUE); } + /* * Lookup a symbol. * If the symbol has a qualifier (e.g., ux:vm_map), @@ -197,46 +268,155 @@ db_sym_t db_lookup(symstr) char *symstr; { - db_symtab_t st = NULL; - db_sym_t sp = NULL; - register char *cp; + db_sym_t sp; + int i; + int symtab_start = 0; + int symtab_end = MAXNOSYMTABS; + char *cp; /* * Look for, remove, and remember any symbol table specifier. */ - for (cp = symstr; *cp; cp++) + for (cp = symstr; *cp; cp++) { if (*cp == ':') { *cp = '\0'; - for (st = db_symiter(NULL); - st != NULL; - st = db_symiter(st)) - if (!strcmp(symstr, st->name)) + for (i = 0; i < MAXNOSYMTABS; i++) { + if (db_symtabs[i].name && + ! strcmp(symstr, db_symtabs[i].name)) { + symtab_start = i; + symtab_end = i + 1; break; + } + } *cp = ':'; - if (st == NULL) { + if (i == MAXNOSYMTABS) { db_error("invalid symbol table name"); - /* NOTREACHED */ + /*NOTREACHED*/ } symstr = cp+1; } + } /* * Look in the specified set of symbol tables. * Return on first match. */ - if (st != NULL) - sp = X_db_lookup(st, symstr); + for (i = symtab_start; i < symtab_end; i++) { + if (db_symtabs[i].name && + (sp = X_db_lookup(&db_symtabs[i], symstr))) { + db_last_symtab = &db_symtabs[i]; + return sp; + } + } + return 0; +} + +/* Private structure for passing args to db_sift() from db_sifting(). */ +struct db_sift_args { + char *symstr; + int mode; +}; + +/* + * Does the work of db_sifting(), called once for each + * symbol via X_db_forall(), prints out symbols matching + * criteria. + */ +static void +db_sift(stab, sym, name, suffix, prefix, arg) + db_symtab_t *stab; + db_sym_t sym; + char *name; + char *suffix; + int prefix; + void *arg; +{ + char c, sc; + char *find, *p; + size_t len; + struct db_sift_args *dsa; + + dsa = (struct db_sift_args*)arg; + + find = dsa->symstr; /* String we're looking for. */ + p = name; /* String we're searching within. */ + + /* Matching algorithm cribbed from strstr(), which is not + in the kernel. */ + if ((c = *find++) != 0) { + len = strlen(find); + do { + do { + if ((sc = *p++) == 0) + return; + } while (sc != c); + } while (strncmp(p, find, len) != 0); + } + if (dsa->mode=='F') /* ala ls -F */ + db_printf("%s%s ", name, suffix); else - for (st = db_symiter(NULL); st != NULL; st = db_symiter(st)) - if ((sp = X_db_lookup(st, symstr)) != NULL) - break; + db_printf("%s ", name); +} - if (sp != NULL && st != NULL) - db_last_symtab = st; +/* + * "Sift" for a partial symbol. + * Named for the Sun OpenPROM command ("sifting"). + * If the symbol has a qualifier (e.g., ux:vm_map), + * then only the specified symbol table will be searched; + * otherwise, all symbol tables will be searched.. + * + * "mode" is how-to-display, set from modifiers. + */ +void +db_sifting(symstr, mode) + char *symstr; + int mode; +{ + char *cp; + int i; + int symtab_start = 0; + int symtab_end = MAXNOSYMTABS; + struct db_sift_args dsa; - return sp; + /* + * Look for, remove, and remember any symbol table specifier. + */ + for (cp = symstr; *cp; cp++) { + if (*cp == ':') { + *cp = '\0'; + for (i = 0; i < MAXNOSYMTABS; i++) { + if (db_symtabs[i].name && + ! strcmp(symstr, db_symtabs[i].name)) { + symtab_start = i; + symtab_end = i + 1; + break; + } + } + *cp = ':'; + if (i == MAXNOSYMTABS) { + db_error("invalid symbol table name"); + /*NOTREACHED*/ + } + symstr = cp+1; + } + } + + /* Pass args to db_sift(). */ + dsa.symstr = symstr; + dsa.mode = mode; + + /* + * Look in the specified set of symbol tables. + */ + for (i = symtab_start; i < symtab_end; i++) + if (db_symtabs[i].name) { + db_printf("Sifting table %s:\n", db_symtabs[i].name); + X_db_forall(&db_symtabs[i], db_sift, &dsa); + } + + return; } -#endif + /* * Does this symbol name appear in more than one symbol table? @@ -249,16 +429,16 @@ db_symbol_is_ambiguous(sym) db_sym_t sym; { char *sym_name; - register db_symtab_t st; - register + int i; boolean_t found_once = FALSE; if (!db_qualify_ambiguous_names) return FALSE; db_symbol_values(sym, &sym_name, 0); - for (st = db_symiter(NULL); st != NULL; st = db_symiter(st)) { - if (X_db_lookup(st, sym_name) != NULL) { + for (i = 0; i < MAXNOSYMTABS; i++) { + if (db_symtabs[i].name && + X_db_lookup(&db_symtabs[i], sym_name)) { if (found_once) return TRUE; found_once = TRUE; @@ -273,22 +453,23 @@ db_symbol_is_ambiguous(sym) */ db_sym_t db_search_symbol( val, strategy, offp) - register db_addr_t val; + db_addr_t val; db_strategy_t strategy; db_expr_t *offp; { - register - db_expr_t diff; + unsigned int diff; db_expr_t newdiff; - db_symtab_t st; + int i; db_sym_t ret = DB_SYM_NULL, sym; - newdiff = diff = -1; + newdiff = diff = ~0; db_last_symtab = 0; - for (st = db_symiter(NULL); st != NULL; st = db_symiter(st)) { - sym = X_db_search_symbol(st, val, strategy, &newdiff); - if (newdiff < diff || diff < 0) { - db_last_symtab = st; + for (i = 0; i < MAXNOSYMTABS; i++) { + if (!db_symtabs[i].name) + continue; + sym = X_db_search_symbol(&db_symtabs[i], val, strategy, &newdiff); + if (newdiff < diff) { + db_last_symtab = &db_symtabs[i]; diff = newdiff; ret = sym; } @@ -313,7 +494,7 @@ db_symbol_values(sym, namep, valuep) return; } - X_db_symbol_values(sym, namep, &value); + X_db_symbol_values(db_last_symtab, sym, namep, &value); if (db_symbol_is_ambiguous(sym)) *namep = db_qualify(sym, db_last_symtab->name); @@ -341,8 +522,8 @@ db_symbol_values(sym, namep, valuep) * add support for symbols in loadable driver modules. */ extern char end[]; -u_long db_lastsym = (u_long)end; -db_expr_t db_maxoff = 0x10000000; +unsigned long db_lastsym = (unsigned long)end; +unsigned int db_maxoff = 0x10000000; void @@ -357,22 +538,22 @@ db_printsym(off, strategy) int linenum; db_sym_t cursym; - if ((u_long)off <= db_lastsym) { + if (off <= db_lastsym) { cursym = db_search_symbol(off, strategy, &d); db_symbol_values(cursym, &name, &value); if (name && (d < db_maxoff) && value) { db_printf("%s", name); - if (d) + if (d) { db_printf("+%#r", d); + } if (strategy == DB_STGY_PROC) { - if (db_line_at_pc(cursym, &filename, &linenum, - off)) - db_printf(" [%s:%d]", filename, - linenum); + if (db_line_at_pc(cursym, &filename, &linenum, off)) + db_printf(" [%s:%d]", filename, linenum); } return; } } + db_printf("%#ln", off); return; } @@ -397,27 +578,90 @@ db_sym_numargs(sym, nargp, argnames) return X_db_sym_numargs(db_last_symtab, sym, nargp, argnames); } +boolean_t +X_db_sym_init(symsize, vss, vse, name) + int symsize; + void *vss, *vse; + const char *name; +{ + + if (db_symformat != NULL) + return ((*db_symformat->sym_init)(symsize, vss, vse, name)); + return (FALSE); +} + +db_sym_t +X_db_lookup(stab, symstr) + db_symtab_t *stab; + char *symstr; +{ + + if (db_symformat != NULL) + return ((*db_symformat->sym_lookup)(stab, symstr)); + return ((db_sym_t)0); +} + +db_sym_t +X_db_search_symbol(stab, off, strategy, diffp) + db_symtab_t *stab; + db_addr_t off; + db_strategy_t strategy; + db_expr_t *diffp; +{ + + if (db_symformat != NULL) + return ((*db_symformat->sym_search)(stab, off, strategy, + diffp)); + return ((db_sym_t)0); +} + void -db_stub_xh(sym, xh) - db_symtab_t sym; - struct exec *xh; +X_db_symbol_values(stab, sym, namep, valuep) + db_symtab_t *stab; + db_sym_t sym; + char **namep; + db_expr_t *valuep; { - X_db_stub_xh(sym, xh); + + if (db_symformat != NULL) + (*db_symformat->sym_value)(stab, sym, namep, valuep); } -int -db_symtablen(sym) - db_symtab_t sym; +boolean_t +X_db_line_at_pc(stab, cursym, filename, linenum, off) + db_symtab_t *stab; + db_sym_t cursym; + char **filename; + int *linenum; + db_expr_t off; +{ + + if (db_symformat != NULL) + return ((*db_symformat->sym_line_at_pc)(stab, cursym, + filename, linenum, off)); + return (FALSE); +} + +boolean_t +X_db_sym_numargs(stab, cursym, nargp, argnamep) + db_symtab_t *stab; + db_sym_t cursym; + int *nargp; + char **argnamep; { - return X_db_symtablen(sym); + + if (db_symformat != NULL) + return ((*db_symformat->sym_numargs)(stab, cursym, nargp, + argnamep)); + return (FALSE); } -int -db_symatoff(sym, off, buf, len) - db_symtab_t sym; - int off; - void *buf; - int *len; +void +X_db_forall(stab, db_forall_func, arg) + db_symtab_t *stab; + db_forall_func_t db_forall_func; + void *arg; { - return X_db_symatoff(sym, off, buf, len); + if (db_symformat != NULL) + (*db_symformat->sym_forall)(stab, db_forall_func, arg); } |