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 | |
parent | 5e833b12704c89c1fad72b7b6f3706cfd15ab035 (diff) |
new symbol handling in ddb for ELF, there is still a problem with hangman on alpha though..
-rw-r--r-- | sys/conf/files | 3 | ||||
-rw-r--r-- | sys/ddb/db_aout.c | 481 | ||||
-rw-r--r-- | sys/ddb/db_elf.c | 415 | ||||
-rw-r--r-- | sys/ddb/db_extern.h | 22 | ||||
-rw-r--r-- | sys/ddb/db_hangman.c | 123 | ||||
-rw-r--r-- | sys/ddb/db_sym.c | 484 | ||||
-rw-r--r-- | sys/ddb/db_sym.h | 92 | ||||
-rw-r--r-- | sys/kern/kern_lkm.c | 4 |
8 files changed, 1155 insertions, 469 deletions
diff --git a/sys/conf/files b/sys/conf/files index 0b1f92f30c5..37e843446cb 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,4 +1,4 @@ -# $OpenBSD: files,v 1.186 2001/02/08 18:46:21 itojun Exp $ +# $OpenBSD: files,v 1.187 2001/02/10 10:42:34 niklas Exp $ # $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 @@ -265,6 +265,7 @@ file ddb/db_access.c ddb | kgdb file ddb/db_aout.c ddb file ddb/db_break.c ddb file ddb/db_command.c ddb +file ddb/db_elf.c ddb file ddb/db_examine.c ddb file ddb/db_expr.c ddb file ddb/db_input.c ddb diff --git a/sys/ddb/db_aout.c b/sys/ddb/db_aout.c index a7776e93b07..04ecf41402e 100644 --- a/sys/ddb/db_aout.c +++ b/sys/ddb/db_aout.c @@ -1,5 +1,5 @@ -/* $OpenBSD: db_aout.c,v 1.25 2001/02/06 07:03:56 niklas Exp $ */ -/* $NetBSD: db_aout.c,v 1.14 1996/02/27 20:54:43 gwr Exp $ */ +/* $OpenBSD: db_aout.c,v 1.26 2001/02/10 10:42:35 niklas Exp $ */ +/* $NetBSD: db_aout.c,v 1.29 2000/07/07 21:55:18 jhawk Exp $ */ /* * Mach Operating System @@ -31,11 +31,6 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> -#include <sys/exec.h> -#include <sys/conf.h> -#include <sys/lkm.h> - -#include <vm/vm.h> #include <machine/db_machdep.h> /* data types */ @@ -43,10 +38,34 @@ #include <ddb/db_output.h> #include <ddb/db_extern.h> -#ifndef DB_NO_AOUT +#ifdef DB_AOUT_SYMBOLS #include <ddb/db_aout.h> +boolean_t db_aout_sym_init __P((int, void *, void *, const char *)); +db_sym_t db_aout_lookup __P((db_symtab_t *, char *)); +db_sym_t db_aout_search_symbol __P((db_symtab_t *, db_addr_t, + db_strategy_t, db_expr_t *)); +void db_aout_symbol_values __P((db_symtab_t *, db_sym_t, + char **, db_expr_t *)); +boolean_t db_aout_line_at_pc __P((db_symtab_t *, db_sym_t, + char **, int *, db_expr_t)); +boolean_t db_aout_sym_numargs __P((db_symtab_t *, db_sym_t, int *, + char **)); +void db_aout_forall __P((db_symtab_t *, + db_forall_func_t db_forall_func, void *)); + +db_symformat_t db_symformat_aout = { + "a.out", + db_aout_sym_init, + db_aout_lookup, + db_aout_search_symbol, + db_aout_symbol_values, + db_aout_line_at_pc, + db_aout_sym_numargs, + db_aout_forall +}; + /* * An a.out symbol table as loaded into the kernel debugger: * @@ -59,169 +78,163 @@ * including this word * -> strings */ - -#ifdef SYMTAB_SPACE -int db_symtabsize = SYMTAB_SPACE; -int db_symtab[SYMTAB_SPACE/sizeof(int)] = { 0, 1 }; -#endif static char *strtab; static int slen; -#ifdef SYMTAB_SPACE -#define X_db_getname(s) (s->n_un.n_name) -#else #define X_db_getname(s) (s->n_un.n_strx > slen ? NULL : strtab + s->n_un.n_strx) + +/* XXX */ +#ifndef ALIGNED_POINTER +#define ALIGNED_POINTER(p,t) ((((u_long)(p)) & (sizeof(t)-1)) == 0) #endif /* * Find the symbol table and strings; tell ddb about them. */ -void -X_db_sym_init(symtab, esymtab, name) - long *symtab; /* pointer to start of symbol table */ - char *esymtab; /* pointer to end of string table, +boolean_t +db_aout_sym_init(symsize, vsymtab, vesymtab, name) + int symsize; /* size of symbol table */ + void *vsymtab; /* pointer to start of symbol table */ + void *vesymtab; /* pointer to end of string table, for checking - rounded up to integer boundary */ - char *name; + const char *name; { struct nlist *sym_start, *sym_end; - char *estrtab; - -#ifdef __alpha__ - printf ("DDB: no symbols\n"); - return; -#endif + struct nlist *sp; + int bad = 0; + char *estrtab; -#ifdef SYMTAB_SPACE - if (*symtab < sizeof(int)) { - printf ("DDB: no symbols\n"); - return; + /* + * XXX - ddb_init should take arguments. + * Fixup the arguments. + */ + symsize = *(long *)vsymtab; + vsymtab = (void *)((long *)vsymtab + 1); + + + if (ALIGNED_POINTER(vsymtab, long) == 0) { + printf("[ %s symbol table has bad start address %p ]\n", + name, vsymtab); + return (FALSE); } -#endif /* * Find pointers to the start and end of the symbol entries, * given a pointer to the start of the symbol table. */ - sym_start = (struct nlist *)(symtab + 1); - sym_end = (struct nlist *)((char *)sym_start + *symtab); + sym_start = (struct nlist *)vsymtab; + sym_end = (struct nlist *)((char *)sym_start + symsize); strtab = (char *)sym_end; + if (ALIGNED_POINTER(strtab, int) == 0) { + printf("[ %s symbol table has bad string table address %p ]\n", + name, strtab); + return (FALSE); + } slen = *(int *)strtab; -#ifdef SYMTAB_SPACE - printf("DDB: found symbols [%d + %d bytes]\n", - *symtab, slen); - if ((*symtab + slen) > db_symtabsize) { - printf("DDB: symbols larger than SYMTAB_SPACE?\n"); - return; - } -#else estrtab = strtab + slen; #define round_to_size(x) \ - (((vaddr_t)(x) + sizeof(vsize_t) - 1) & ~(sizeof(vsize_t) - 1)) + (((vaddr_t)(x) + sizeof(vsize_t) - 1) & ~(sizeof(vsize_t) - 1)) - if (round_to_size(estrtab) != round_to_size(esymtab)) { - db_printf("[ %s symbol table not valid ]\n", name); - return; + if (round_to_size(estrtab) != round_to_size(vesymtab)) { + printf("[ %s a.out symbol table not valid ]\n", name); + return (FALSE); } #undef round_to_size -#endif + for (sp = sym_start; sp < sym_end; sp++) { + int strx; + strx = sp->n_un.n_strx; + if (strx != 0) { + if (strx > slen) { + printf("[ %s has bad a.out string table index " + "(0x%x) ]\n", + name, strx); + bad = 1; + continue; + } + } + } + + if (bad) + return (FALSE); if (db_add_symbol_table((char *)sym_start, (char *)sym_end, name, - (char *)symtab, esymtab) != -1) { -#ifndef SYMTAB_SPACE - db_printf("[ preserving %d bytes of %s symbol table ]\n", - esymtab - (char *)symtab, name); -#endif + NULL) != -1) { + printf("[ using %ld bytes of %s a.out symbol table ]\n", + (long)vesymtab - (long)vsymtab, name); + return (TRUE); } -} -size_t -X_db_nsyms(stab) - db_symtab_t stab; -{ - return (struct nlist *)stab->end - (struct nlist *)stab->start; -} - -db_sym_t -X_db_isym(stab, i) - db_symtab_t stab; - size_t i; -{ - if (i >= X_db_nsyms(stab)) - return NULL; - else - return (db_sym_t)((struct nlist *)stab->start + i); + return (FALSE); } db_sym_t -X_db_lookup(stab, symstr) - db_symtab_t stab; +db_aout_lookup(stab, symstr) + db_symtab_t *stab; char * symstr; { - register struct nlist *sp, *ep; + struct nlist *sp, *ep; char *n_name; sp = (struct nlist *)stab->start; ep = (struct nlist *)stab->end; for (; sp < ep; sp++) { - if ((n_name = X_db_getname(sp)) == 0) - continue; - if ((sp->n_type & N_STAB) == 0 && db_eqname(n_name, symstr, '_')) - return ((db_sym_t)sp); + if ((n_name = X_db_getname(sp)) == 0) + continue; + if ((sp->n_type & N_STAB) == 0 && + db_eqname(n_name, symstr, '_')) + return ((db_sym_t)sp); } return ((db_sym_t)0); } db_sym_t -X_db_search_symbol(symtab, off, strategy, diffp) - db_symtab_t symtab; - register +db_aout_search_symbol(symtab, off, strategy, diffp) + db_symtab_t * symtab; db_addr_t off; db_strategy_t strategy; db_expr_t *diffp; /* in/out */ { - register db_expr_t diff = *diffp; - register struct nlist *symp = 0; - register struct nlist *sp, *ep; + unsigned int diff = *diffp; + struct nlist *symp = 0; + struct nlist *sp, *ep; sp = (struct nlist *)symtab->start; ep = (struct nlist *)symtab->end; for (; sp < ep; sp++) { - if (X_db_getname(sp) == 0) - continue; - if ((sp->n_type & N_STAB) != 0 || (sp->n_type & N_TYPE) == N_FN) - continue; - if (off >= sp->n_value) { - if ((db_expr_t)(off - sp->n_value) < diff || diff < 0) { - diff = off - sp->n_value; - symp = sp; - if (diff == 0 && - ((strategy == DB_STGY_PROC && - sp->n_type == (N_TEXT|N_EXT)) || - (strategy == DB_STGY_ANY && - (sp->n_type & N_EXT)))) - break; - } - else if ((db_expr_t)(off - sp->n_value) == diff) { - if (symp == 0) - symp = sp; - else if ((symp->n_type & N_EXT) == 0 && - (sp->n_type & N_EXT) != 0) - symp = sp; /* pick the external symbol */ + if (X_db_getname(sp) == 0) + continue; + if ((sp->n_type & N_STAB) != 0 || + (sp->n_type & N_TYPE) == N_FN) + continue; + if (off >= sp->n_value) { + if (off - sp->n_value < diff) { + diff = off - sp->n_value; + symp = sp; + if (diff == 0 && ((strategy == DB_STGY_PROC && + sp->n_type == (N_TEXT|N_EXT)) || + (strategy == DB_STGY_ANY && + (sp->n_type & N_EXT)))) + break; + } else if (off - sp->n_value == diff) { + if (symp == 0) + symp = sp; + else if ((symp->n_type & N_EXT) == 0 && + (sp->n_type & N_EXT) != 0) + symp = sp; /* pick the ext. sym */ + } } - } } if (symp == 0) { - *diffp = off; - } - else { - *diffp = diff; + *diffp = off; + } else { + *diffp = diff; } return ((db_sym_t)symp); } @@ -230,217 +243,173 @@ X_db_search_symbol(symtab, off, strategy, diffp) * Return the name and value for a symbol. */ void -X_db_symbol_values(sym, namep, valuep) +db_aout_symbol_values(symtab, sym, namep, valuep) + db_symtab_t *symtab; db_sym_t sym; char **namep; db_expr_t *valuep; { - register struct nlist *sp; + struct nlist *sp; - if ((sp = (struct nlist *)sym) == NULL) - return; + sp = (struct nlist *)sym; if (namep) - *namep = X_db_getname(sp); + *namep = X_db_getname(sp); if (valuep) - *valuep = sp->n_value; + *valuep = sp->n_value; } boolean_t -X_db_line_at_pc(symtab, cursym, filename, linenum, off) - db_symtab_t symtab; +db_aout_line_at_pc(symtab, cursym, filename, linenum, off) + db_symtab_t * symtab; db_sym_t cursym; char **filename; int *linenum; db_expr_t off; { - register struct nlist *sp, *ep; - unsigned long sodiff = -1UL, lndiff = -1UL, ln = 0; - char *fname = NULL; + struct nlist *sp, *ep; + unsigned long sodiff = -1UL, lndiff = -1UL, ln = 0; + char *fname = NULL; sp = (struct nlist *)symtab->start; ep = (struct nlist *)symtab->end; /* XXX - gcc specific */ #define NEWSRC(str) ((str) != NULL && \ - (str)[0] == 'g' && strcmp((str), "gcc_compiled.") == 0) + (str)[0] == 'g' && strcmp((str), "gcc_compiled.") == 0) for (; sp < ep; sp++) { - /* - * Prevent bogus linenumbers in case module not compiled - * with debugging options - */ + /* + * Prevent bogus linenumbers in case module not compiled + * with debugging options + */ #if 0 - if (sp->n_value <= off && (off - sp->n_value) <= sodiff && - NEWSRC(X_db_getname(sp))) { + if (sp->n_value <= off && (off - sp->n_value) <= sodiff && + NEWSRC(X_db_getname(sp))) { #endif - if ((sp->n_type & N_TYPE) == N_FN || NEWSRC(X_db_getname(sp))) { - sodiff = lndiff = -1UL; - ln = 0; - fname = NULL; - } - - if (sp->n_type == N_SO) { - if ((db_expr_t)sp->n_value <= off && - (off - sp->n_value) < sodiff) { - sodiff = off - sp->n_value; - fname = X_db_getname(sp); + if ((sp->n_type & N_TYPE) == N_FN || + NEWSRC(X_db_getname(sp))) { + sodiff = lndiff = -1UL; + ln = 0; + fname = NULL; } - continue; - } - if (sp->n_type != N_SLINE) - continue; + if (sp->n_type == N_SO) { + if (sp->n_value <= off && + (off - sp->n_value) < sodiff) { + sodiff = off - sp->n_value; + fname = X_db_getname(sp); + } + continue; + } - if ((db_expr_t)sp->n_value > off) - break; + if (sp->n_type != N_SLINE) + continue; - if (off - sp->n_value < lndiff) { - lndiff = off - sp->n_value; - ln = sp->n_desc; - } + if (sp->n_value > off) + break; + + if (off - sp->n_value < lndiff) { + lndiff = off - sp->n_value; + ln = sp->n_desc; + } } if (fname != NULL && ln != 0) { *filename = fname; *linenum = ln; - return TRUE; + return (TRUE); } return (FALSE); } boolean_t -X_db_sym_numargs(symtab, cursym, nargp, argnamep) - db_symtab_t symtab; +db_aout_sym_numargs(symtab, cursym, nargp, argnamep) + db_symtab_t * symtab; db_sym_t cursym; int *nargp; char **argnamep; { - register struct nlist *sp, *ep; - u_long addr; - int maxnarg = *nargp, nargs = 0; - char *n_name; + struct nlist *sp, *ep; + u_long addr; + int maxnarg = *nargp, nargs = 0; + char *n_name; if (cursym == NULL) - return FALSE; + return (FALSE); addr = ((struct nlist *)cursym)->n_value; sp = (struct nlist *)symtab->start; ep = (struct nlist *)symtab->end; for (; sp < ep; sp++) { - if (sp->n_type == N_FUN && sp->n_value == addr) { - while (++sp < ep && sp->n_type == N_PSYM) { - if (nargs >= maxnarg) - break; - nargs++; - n_name = X_db_getname(sp); - *argnamep++ = n_name ? n_name : "???"; - { - /* XXX - remove trailers */ - /* XXX - this could hose /dev/ksyms! */ - char *cp = *(argnamep-1); - while (*cp != '\0' && *cp != ':') cp++; - if (*cp == ':') *cp = '\0'; + if (sp->n_type == N_FUN && sp->n_value == addr) { + while (++sp < ep && sp->n_type == N_PSYM) { + if (nargs >= maxnarg) + break; + nargs++; + n_name = X_db_getname(sp); + *argnamep++ = n_name ? n_name : "???"; + { + /* XXX - remove trailers */ + char *cp = *(argnamep - 1); + + while (*cp != '\0' && *cp != ':') + cp++; + if (*cp == ':') *cp = '\0'; + } } + *nargp = nargs; + return (TRUE); } - *nargp = nargs; - return TRUE; - } } - return FALSE; + return (FALSE); } void -X_db_stub_xh(sym, xh) - db_symtab_t sym; - struct exec *xh; +db_aout_forall(stab, db_forall_func, arg) + db_symtab_t *stab; + db_forall_func_t db_forall_func; + void *arg; { - extern char kernel_text[], etext[]; - - bzero(xh, sizeof(*xh)); - N_SETMAGIC(*xh, ZMAGIC, MID_MACHINE, 0); - xh->a_entry = (u_long)kernel_text; /* XXX not right, but who cares? */ - xh->a_syms = *(int *)sym->private; - xh->a_text = etext - kernel_text; - xh->a_data = 0; - if (sym->id != 0) { /* lkm */ -#ifdef LKM - struct lkm_table *p; - for (p = lkm_list(NULL); - p != NULL && p->sym_id != sym->id; p = lkm_list(p)) - ; - if (p != NULL) { - xh->a_entry = (u_long)p->entry; - xh->a_syms = p->sym_symsize; - } -#ifdef DIAGNOSTIC - else - printf("X_db_stub_xh: no lkm for symtab (ghost?)\n"); -#endif -#else - panic("X_db_stub_xh: symtab w/o lkm itself"); -#endif - } -} + static char suffix[2]; + struct nlist *sp, *ep; -int -X_db_symtablen(sym) - db_symtab_t sym; -{ - return sym->rend - sym->start; -} + sp = (struct nlist *)stab->start; + ep = (struct nlist *)stab->end; -int -X_db_symatoff(sym, off, buf, len) - db_symtab_t sym; - int off; - void *buf; - int *len; -{ - /* symtab */ - if (off < (sym->end - sym->start)) { - struct nlist n; - - bcopy (&((struct nlist *)sym->start)[off / sizeof(n)], - &n, sizeof(n)); - *len = min(*len, sizeof(n) - off % sizeof(n)); - bcopy ((u_int8_t*)&n + off % sizeof(n), buf, *len); - } else { - /* strtab */ - off -= sym->end - sym->start; - if (off < (sym->rend - sym->end)) { - /* no preprocessing for string table */ - *len = min(*len, (sym->rend - sym->end - off)); - bcopy(sym->end + off, buf, *len); - } else - return -1; + for (; sp < ep; sp++) { + if (X_db_getname(sp) == 0) + continue; + if ((sp->n_type & N_STAB) == 0) { + suffix[1] = '\0'; + switch(sp->n_type & N_TYPE) { + case N_ABS: + suffix[0] = '@'; + break; + case N_TEXT: + suffix[0] = '*'; + break; + case N_DATA: + suffix[0] = '+'; + break; + case N_BSS: + suffix[0] = '-'; + break; + case N_FN: + suffix[0] = '/'; + break; + default: + suffix[0] = '\0'; + } + (*db_forall_func)(stab, (db_sym_t)sp, X_db_getname(sp), + suffix, '_', arg); + } } - - return 0; -} - -/* - * Initialization routine for a.out files. - */ -void -ddb_init() -{ -#ifndef SYMTAB_SPACE - extern char *esym; - extern long end; - - db_sym_init(); - - if (esym > (char *)&end) - X_db_sym_init(&end, esym, "bsd"); -#else - db_sym_init(); - - X_db_sym_init (db_symtab, 0, "bsd"); -#endif + return; } -#endif /* DB_NO_AOUT */ + +#endif /* DB_AOUT_SYMBOLS */ diff --git a/sys/ddb/db_elf.c b/sys/ddb/db_elf.c new file mode 100644 index 00000000000..f207f2ffd1c --- /dev/null +++ b/sys/ddb/db_elf.c @@ -0,0 +1,415 @@ +/* $NetBSD: db_elf.c,v 1.13 2000/07/07 21:55:18 jhawk Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/exec.h> + +#include <machine/db_machdep.h> + +#include <ddb/db_sym.h> +#include <ddb/db_output.h> +#include <ddb/db_extern.h> + +#ifdef DB_ELF_SYMBOLS + +#ifndef DB_ELFSIZE +#error Must define DB_ELFSIZE! +#endif + +#define ELFSIZE DB_ELFSIZE + +#include <sys/exec_elf.h> + +static char *db_elf_find_strtab __P((db_symtab_t *)); + +#define STAB_TO_SYMSTART(stab) ((Elf_Sym *)((stab)->start)) +#define STAB_TO_SYMEND(stab) ((Elf_Sym *)((stab)->end)) +#define STAB_TO_EHDR(stab) ((Elf_Ehdr *)((stab)->private)) +#define STAB_TO_SHDR(stab, e) ((Elf_Shdr *)((stab)->private + (e)->e_shoff)) + +boolean_t db_elf_sym_init __P((int, void *, void *, const char *)); +db_sym_t db_elf_lookup __P((db_symtab_t *, char *)); +db_sym_t db_elf_search_symbol __P((db_symtab_t *, db_addr_t, + db_strategy_t, db_expr_t *)); +void db_elf_symbol_values __P((db_symtab_t *, db_sym_t, + char **, db_expr_t *)); +boolean_t db_elf_line_at_pc __P((db_symtab_t *, db_sym_t, + char **, int *, db_expr_t)); +boolean_t db_elf_sym_numargs __P((db_symtab_t *, db_sym_t, int *, + char **)); +void db_elf_forall __P((db_symtab_t *, + db_forall_func_t db_forall_func, void *)); + +db_symformat_t db_symformat_elf = { + "ELF", + db_elf_sym_init, + db_elf_lookup, + db_elf_search_symbol, + db_elf_symbol_values, + db_elf_line_at_pc, + db_elf_sym_numargs, + db_elf_forall +}; + +/* + * Find the symbol table and strings; tell ddb about them. + */ +boolean_t +db_elf_sym_init(symsize, symtab, esymtab, name) + int symsize; /* size of symbol table */ + void *symtab; /* pointer to start of symbol table */ + void *esymtab; /* pointer to end of string table, + for checking - rounded up to integer + boundary */ + const char *name; +{ + Elf_Ehdr *elf; + Elf_Shdr *shp; + Elf_Sym *symp, *symtab_start, *symtab_end; + char *shstrtab, *strtab_start, *strtab_end; + int i; + + if (ALIGNED_POINTER(symtab, long) == 0) { + printf("[ %s symbol table has bad start address %p ]\n", + name, symtab); + return (FALSE); + } + + symtab_start = symtab_end = NULL; + strtab_start = strtab_end = NULL; + + /* + * The format of the symbols loaded by the boot program is: + * + * Elf exec header + * first section header + * . . . + * . . . + * last section header + * first symbol or string table section + * . . . + * . . . + * last symbol or string table section + */ + + /* + * Validate the Elf header. + */ + elf = (Elf_Ehdr *)symtab; + if (memcmp(elf->e_ident, ELFMAG, SELFMAG) != 0 || + elf->e_ident[EI_CLASS] != ELFCLASS) + goto badheader; + + if (elf->e_machine != ELF_TARG_MACH) + goto badheader; + + /* + * Find the section header string table (.shstrtab), and look up + * the symbol table (.symtab) and string table (.strtab) via their + * names in shstrtab, rather than by table type. + * This works in the presence of multiple string tables, such as + * stabs data found when booting bsd.gdb. + */ + shp = (Elf_Shdr *)((char *)symtab + elf->e_shoff); + shstrtab = (char*)symtab + shp[elf->e_shstrndx].sh_offset; + for (i = 0; i < elf->e_shnum; i++) { + if (strcmp(".strtab", shstrtab+shp[i].sh_name) == 0) { + strtab_start = (char *)symtab + shp[i].sh_offset; + strtab_end = (char *)symtab + shp[i].sh_offset + + shp[i].sh_size; + } else if (strcmp(".symtab", shstrtab+shp[i].sh_name) == 0) { + symtab_start = (Elf_Sym *)((char *)symtab + + shp[i].sh_offset); + symtab_end = (Elf_Sym *)((char *)symtab + + shp[i].sh_offset + shp[i].sh_size); + } + } + + /* + * Now, sanity check the symbols against the string table. + */ + if (symtab_start == NULL || strtab_start == NULL || + ALIGNED_POINTER(symtab_start, long) == 0 || + ALIGNED_POINTER(strtab_start, long) == 0) + goto badheader; + for (symp = symtab_start; symp < symtab_end; symp++) + if (symp->st_name + strtab_start > strtab_end) + goto badheader; + + /* + * Link the symbol table into the debugger. + */ + if (db_add_symbol_table((char *)symtab_start, + (char *)symtab_end, name, (char *)symtab) != -1) { + printf("[ using %lu bytes of %s ELF symbol table ]\n", + (u_long)roundup(((char *)esymtab - (char *)symtab), + sizeof(u_long)), name); + return (TRUE); + } + + return (FALSE); + + badheader: + printf("[ %s ELF symbol table not valid ]\n", name); + return (FALSE); +} + +/* + * Internal helper function - return a pointer to the string table + * for the current symbol table. + */ +static char * +db_elf_find_strtab(stab) + db_symtab_t *stab; +{ + Elf_Ehdr *elf = STAB_TO_EHDR(stab); + Elf_Shdr *shp = STAB_TO_SHDR(stab, elf); + char *shstrtab; + int i; + + shstrtab = (char*)elf + shp[elf->e_shstrndx].sh_offset; + for (i = 0; i < elf->e_shnum; i++) { + if (strcmp(".strtab", shstrtab+shp[i].sh_name) == 0) + return ((char*)elf + shp[i].sh_offset); + } + + return (NULL); +} + +/* + * Lookup the symbol with the given name. + */ +db_sym_t +db_elf_lookup(stab, symstr) + db_symtab_t *stab; + char *symstr; +{ + Elf_Sym *symp, *symtab_start, *symtab_end; + char *strtab; + + symtab_start = STAB_TO_SYMSTART(stab); + symtab_end = STAB_TO_SYMEND(stab); + + strtab = db_elf_find_strtab(stab); + if (strtab == NULL) + return ((db_sym_t)0); + + for (symp = symtab_start; symp < symtab_end; symp++) { + if (symp->st_name != 0 && + db_eqname(strtab + symp->st_name, symstr, 0)) + return ((db_sym_t)symp); + } + + return ((db_sym_t)0); +} + +/* + * Search for the symbol with the given address (matching within the + * provided threshold). + */ +db_sym_t +db_elf_search_symbol(symtab, off, strategy, diffp) + db_symtab_t *symtab; + db_addr_t off; + db_strategy_t strategy; + db_expr_t *diffp; /* in/out */ +{ + Elf_Sym *rsymp, *symp, *symtab_start, *symtab_end; + db_expr_t diff = *diffp; + + symtab_start = STAB_TO_SYMSTART(symtab); + symtab_end = STAB_TO_SYMEND(symtab); + + rsymp = NULL; + + for (symp = symtab_start; symp < symtab_end; symp++) { + if (symp->st_name == 0) + continue; +#if 0 + /* This prevents me from seeing anythin in locore.s -- eeh */ + if (ELF_SYM_TYPE(symp->st_info) != Elf_estt_object && + ELF_SYM_TYPE(symp->st_info) != Elf_estt_func) + continue; +#endif + + if (off >= symp->st_value) { + if ((off - symp->st_value) < diff) { + diff = off - symp->st_value; + rsymp = symp; + if (diff == 0) { + if (strategy == DB_STGY_PROC && + ELFDEFNNAME(ST_TYPE)(symp->st_info) + == STT_FUNC && + ELFDEFNNAME(ST_BIND)(symp->st_info) + != STB_LOCAL) + break; + if (strategy == DB_STGY_ANY && + ELFDEFNNAME(ST_BIND)(symp->st_info) + != STB_LOCAL) + break; + } + } else if ((off - symp->st_value) == diff) { + if (rsymp == NULL) + rsymp = symp; + else if (ELFDEFNNAME(ST_BIND)(rsymp->st_info) + == STB_LOCAL && + ELFDEFNNAME(ST_BIND)(symp->st_info) + != STB_LOCAL) { + /* pick the external symbol */ + rsymp = symp; + } + } + } + } + + if (rsymp == NULL) + *diffp = off; + else + *diffp = diff; + + return ((db_sym_t)rsymp); +} + +/* + * Return the name and value for a symbol. + */ +void +db_elf_symbol_values(symtab, sym, namep, valuep) + db_symtab_t *symtab; + db_sym_t sym; + char **namep; + db_expr_t *valuep; +{ + Elf_Sym *symp = (Elf_Sym *)sym; + char *strtab; + + if (namep) { + strtab = db_elf_find_strtab(symtab); + if (strtab == NULL) + *namep = NULL; + else + *namep = strtab + symp->st_name; + } + + if (valuep) + *valuep = symp->st_value; +} + +/* + * Return the file and line number of the current program counter + * if we can find the appropriate debugging symbol. + */ +boolean_t +db_elf_line_at_pc(symtab, cursym, filename, linenum, off) + db_symtab_t *symtab; + db_sym_t cursym; + char **filename; + int *linenum; + db_expr_t off; +{ + + /* + * XXX We don't support this (yet). + */ + return (FALSE); +} + +/* + * Returns the number of arguments to a function and their + * names if we can find the appropriate debugging symbol. + */ +boolean_t +db_elf_sym_numargs(symtab, cursym, nargp, argnamep) + db_symtab_t *symtab; + db_sym_t cursym; + int *nargp; + char **argnamep; +{ + + /* + * XXX We don't support this (yet). + */ + return (FALSE); +} + +void +db_elf_forall(stab, db_forall_func, arg) + db_symtab_t *stab; + db_forall_func_t db_forall_func; + void *arg; +{ + char *strtab; + static char suffix[2]; + Elf_Sym *symp, *symtab_start, *symtab_end; + + symtab_start = STAB_TO_SYMSTART(stab); + symtab_end = STAB_TO_SYMEND(stab); + + strtab = db_elf_find_strtab(stab); + if (strtab == NULL) + return; + + for (symp = symtab_start; symp < symtab_end; symp++) + if (symp->st_name != 0) { + suffix[1] = '\0'; + switch (ELFDEFNNAME(ST_TYPE)(symp->st_info)) { + case STT_OBJECT: + suffix[0] = '+'; + break; + case STT_FUNC: + suffix[0] = '*'; + break; + case STT_SECTION: + suffix[0] = '&'; + break; + case STT_FILE: + suffix[0] = '/'; + break; + default: + suffix[0] = '\0'; + } + (*db_forall_func)(stab, (db_sym_t)symp, + strtab + symp->st_name, suffix, 0, arg); + } + return; +} +#endif /* DB_ELF_SYMBOLS */ diff --git a/sys/ddb/db_extern.h b/sys/ddb/db_extern.h index 00e318509ab..d04b82e218f 100644 --- a/sys/ddb/db_extern.h +++ b/sys/ddb/db_extern.h @@ -1,4 +1,4 @@ -/* $OpenBSD: db_extern.h,v 1.9 1997/07/08 10:48:32 niklas Exp $ */ +/* $OpenBSD: db_extern.h,v 1.10 2001/02/10 10:42:35 niklas Exp $ */ /* $NetBSD: db_extern.h,v 1.1 1996/02/05 01:57:00 christos Exp $ */ /* @@ -32,22 +32,7 @@ #ifndef _DDB_DB_EXTERN_H_ #define _DDB_DB_EXTERN_H_ -/* db_aout.c */ -void X_db_sym_init __P((long *, char *, char *)); -size_t X_db_nsyms __P((db_symtab_t)); -db_sym_t X_db_isym __P((db_symtab_t, size_t)); -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_sym_t, char **, db_expr_t *)); -void db_printsym __P((db_expr_t, db_strategy_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 **)); -struct exec; -void X_db_stub_xh __P((db_symtab_t, struct exec *)); -int X_db_symtablen __P((db_symtab_t)); -int X_db_symatoff __P((db_symtab_t, int, void*, int*)); +/* db_sym.c */ void ddb_init __P((void)); /* db_examine.c */ @@ -67,6 +52,9 @@ boolean_t db_add_expr __P((db_expr_t *)); boolean_t db_shift_expr __P((db_expr_t *)); int db_expression __P((db_expr_t *)); +/* db_hangman.c */ +void db_hangman __P((db_expr_t, int, db_expr_t, char *)); + /* db_input.c */ void db_putstring __P((char *, int)); void db_putnchars __P((int, int)); diff --git a/sys/ddb/db_hangman.c b/sys/ddb/db_hangman.c index 8a0b3a4ab23..ba230fdd526 100644 --- a/sys/ddb/db_hangman.c +++ b/sys/ddb/db_hangman.c @@ -1,4 +1,4 @@ -/* $OpenBSD: db_hangman.c,v 1.15 2001/02/08 23:06:32 niklas Exp $ */ +/* $OpenBSD: db_hangman.c,v 1.16 2001/02/10 10:42:35 niklas Exp $ */ /* * Copyright (c) 1996 Theo de Raadt, Michael Shalayeff @@ -39,6 +39,7 @@ #include <ddb/db_sym.h> #include <ddb/db_extern.h> +#include <ddb/db_output.h> #include <dev/cons.h> #include <dev/rndvar.h> @@ -57,49 +58,96 @@ static __inline size_t db_random __P((size_t)); static __inline char *db_randomsym __P((size_t *)); void db_hang __P((int, char *, char *)); -int db_hangon __P((void)); +static __inline int db_hangon __P((void)); static int skill; static __inline size_t db_random(mod) - register size_t mod; + size_t mod; { return arc4random() % mod; } +struct db_hang_forall_arg { + int cnt; + db_sym_t sym; +}; + +/* + * Horrible abuse of the forall function, but we're not in a hurry. + */ +static void db_hang_forall __P((db_symtab_t *, db_sym_t, char *, char *, int, + void *)); + +static void +db_hang_forall(stab, sym, name, suff, pre, varg) + db_symtab_t *stab; + db_sym_t sym; + char *name; + char *suff; + int pre; + void *varg; +{ + struct db_hang_forall_arg *arg = (struct db_hang_forall_arg *)varg; + + if (--arg->cnt == 0) + arg->sym = sym; +} + static __inline char * db_randomsym(lenp) size_t *lenp; { - register char *p, *q; - /* choose random symtab */ - register db_symtab_t stab = db_istab(db_random(db_nsymtabs)); + extern db_symtab_t db_symtabs[]; + db_symtab_t *stab; + int nsymtabs, nsyms; + char *p, *q; + struct db_hang_forall_arg dfa; - /* choose random symbol from the table */ - q = db_qualify(X_db_isym(stab, db_random(X_db_nsyms(stab))),stab->name); + for (nsymtabs = 0; db_symtabs[nsymtabs].name != NULL; nsymtabs++) + ; - /* don't show symtab name if there are less than 3 of 'em */ - if (db_nsymtabs < 3) + if (nsymtabs == 0) + return (NULL); + + stab = &db_symtabs[db_random(nsymtabs)]; + + dfa.cnt = 1000000; + X_db_forall(stab, db_hang_forall, &dfa); + if (dfa.cnt <= 0) + return (NULL); + nsyms = 1000000 - dfa.cnt; + + if (nsyms == 0) + return (NULL); + + dfa.cnt = db_random(nsyms); + X_db_forall(stab, db_hang_forall, &dfa); + + q = db_qualify(dfa.sym, stab->name); + + /* don't show symtab name if there are less than 3 of 'em */ + if (nsymtabs < 3) while(*q++ != ':'); - /* strlen(q) && ignoring underscores and colons */ + /* strlen(q) && ignoring underscores and colons */ for ((*lenp) = 0, p = q; *p; p++) if (ISALPHA(*p)) (*lenp)++; - return q; + return (q); } static char hangpic[]= - "\n88888 \r\n" - "9 7 6 \r\n" - "97 5 \r\n" - "9 423\r\n" - "9 2 \r\n" - "9 1 0\r\n" - "9\r\n" - "9 "; + "\n88888 \r\n" + "9 7 6 \r\n" + "97 5 \r\n" + "9 423\r\n" + "9 2 \r\n" + "9 1 0\r\n" + "9\r\n" + "9 "; static char substchar[]="\\/|\\/O|/-|"; void @@ -110,35 +158,24 @@ db_hang(tries, word, abc) { register char *p; - for(p=hangpic; *p; p++) { - if(*p>='0' && *p<='9') { - if(tries<=(*p)-'0') - cnputc(substchar[(*p)-'0']); - else - cnputc(' '); - } else - cnputc(*p); - } + for(p=hangpic; *p; p++) + cnputc((*p>='0' && *p<='9') ? ((tries<=(*p)-'0') ? + substchar[(*p)-'0'] : ' ') : *p); for (p = word; *p; p++) - if (ISALPHA(*p) && abc[TOLOWER(*p) - 'a'] == '-') - cnputc('-'); - else - cnputc(*p); + cnputc(ISALPHA(*p) && abc[TOLOWER(*p) - 'a'] == '-'?'-':*p); - cnputc(' '); - cnputc('('); + db_printf(" ("); for (p = abc; *p; p++) if (*p == '_') cnputc('a' + (p - abc)); - cnputc(')'); - cnputc('\r'); + db_printf(")\r"); } -int +static __inline int db_hangon(void) { static size_t len; @@ -153,8 +190,10 @@ db_hangon(void) *p = '-'; *p = '\0'; - tries = 2 * (1 + skill / 3); + tries = skill + 1; word = db_randomsym(&len); + if (word == NULL) + return (0); } { @@ -184,7 +223,7 @@ db_hangon(void) } if (tries && len) - return 1; + return (1); if (!tries && skill > 2) { register char *p = word; @@ -196,7 +235,7 @@ db_hangon(void) cnputc('\n'); word = NULL; - return !tries; + return (!tries); } void @@ -209,7 +248,7 @@ db_hangman(addr, haddr, count, modif) if (modif[0] == 's' && '0' <= modif[1] && modif[1] <= '9') skill = modif[1] - '0'; else - skill = 5; + skill = 3; while (db_hangon()); } 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); } diff --git a/sys/ddb/db_sym.h b/sys/ddb/db_sym.h index a1dc5c0548f..64ef5e467bf 100644 --- a/sys/ddb/db_sym.h +++ b/sys/ddb/db_sym.h @@ -1,5 +1,4 @@ -/* $OpenBSD: db_sym.h,v 1.11 1997/05/29 03:28:45 mickey Exp $ */ -/* $NetBSD: db_sym.h,v 1.7 1996/02/05 01:57:16 christos Exp $ */ +/* $NetBSD: db_sym.h,v 1.13 2000/05/25 19:57:36 jhawk Exp $ */ /* * Mach Operating System @@ -30,27 +29,17 @@ * Date: 8/90 */ -#ifndef _DDB_DB_SYM_ -#define _DDB_DB_SYM_ - /* * This module can handle multiple symbol tables */ - -#include <sys/queue.h> - -typedef struct db_symtab { - TAILQ_ENTRY(db_symtab) list; /* all the tabs */ - char *name; /* symtab name */ - u_int id; /* id */ +typedef struct { + const char *name; /* symtab name */ char *start; /* symtab location */ - char *end; /* end of symtab */ - char *rend; /* real end (as it passed) */ + char *end; char *private; /* optional machdep pointer */ -} *db_symtab_t; +} db_symtab_t; -extern db_symtab_t db_last_symtab; /* where last symbol was found */ -extern size_t db_nsymtabs; /* number of symbol tables */ +extern db_symtab_t *db_last_symtab; /* where last symbol was found */ /* * Symbol representation is specific to the symtab style: @@ -72,23 +61,57 @@ typedef int db_strategy_t; /* search strategy */ #define DB_STGY_XTRN 1 /* only external symbols */ #define DB_STGY_PROC 2 /* only procedures */ + +/* + * Internal db_forall function calling convention: + * + * (*db_forall_func)(stab, sym, name, suffix, prefix, arg); + * + * stab is the symbol table, symbol the (opaque) symbol pointer, + * name the name of the symbol, suffix a string representing + * the type, prefix an initial ignorable function prefix (e.g. "_" + * in a.out), and arg an opaque argument to be passed in. + */ +typedef void (db_forall_func_t) + __P((db_symtab_t *, db_sym_t, char *, char *, int, void *)); + +void X_db_forall __P((db_symtab_t *, + db_forall_func_t db_forall_func, void *)); + +/* + * A symbol table may be in one of many formats. All symbol tables + * must be of the same format as the master kernel symbol table. + */ +typedef struct { + const char *sym_format; + boolean_t (*sym_init) __P((int, void *, void *, const char *)); + db_sym_t (*sym_lookup) __P((db_symtab_t *, char *)); + db_sym_t (*sym_search) __P((db_symtab_t *, db_addr_t, db_strategy_t, + db_expr_t *)); + void (*sym_value) __P((db_symtab_t *, db_sym_t, char **, + db_expr_t *)); + boolean_t (*sym_line_at_pc) __P((db_symtab_t *, db_sym_t, + char **, int *, db_expr_t)); + boolean_t (*sym_numargs) __P((db_symtab_t *, db_sym_t, int *, + char **)); + void (*sym_forall) __P((db_symtab_t *, + db_forall_func_t *db_forall_func, void *)); +} db_symformat_t; + extern boolean_t db_qualify_ambiguous_names; /* if TRUE, check across symbol tables * for multiple occurrences of a name. * Might slow down quite a bit */ +extern unsigned int db_maxoff; /* like gdb's "max-symbolic-offset" */ /* * Functions exported by the symtable module */ -void db_sym_init __P((void)); -int db_add_symbol_table __P((char *, char *, char *, char *, char *)); +int db_add_symbol_table __P((char *, char *, const char *, char *)); /* extend the list of symbol tables */ void db_del_symbol_table __P((char *)); /* remove a symbol table from list */ -db_symtab_t db_istab __P((size_t)); -db_symtab_t db_symiter __P((db_symtab_t)); - /* iterate through all the symtabs, if any */ boolean_t db_eqname __P((char *, char *, int)); /* strcmp, modulo leading char */ @@ -98,7 +121,8 @@ int db_value_of_name __P((char *, db_expr_t *)); db_sym_t db_lookup __P((char *)); -char *db_qualify __P((db_sym_t, char *)); +void db_sifting __P((char *, int)); + /* print partially matching symbol names */ boolean_t db_symbol_is_ambiguous __P((db_sym_t)); @@ -122,12 +146,18 @@ void db_printsym __P((db_expr_t, db_strategy_t)); boolean_t db_line_at_pc __P((db_sym_t, char **, int *, db_expr_t)); int db_sym_numargs __P((db_sym_t, int *, char **)); -struct exec; -void db_stub_xh __P((db_symtab_t, struct exec *)); -int db_symtablen __P((db_symtab_t)); -int db_symatoff __P((db_symtab_t, int, void*, int*)); - -/* db_hangman.c */ -void db_hangman __P((db_expr_t, int, db_expr_t, char *)); +char *db_qualify __P((db_sym_t, const char *)); -#endif /* _DDB_DB_SYM_H_ */ +/* + * XXX - should explicitly ask for aout symbols in machine/db_machdep.h + */ +#ifndef DB_NO_AOUT +#define DB_AOUT_SYMBOLS +#endif + +#ifdef DB_AOUT_SYMBOLS +extern db_symformat_t db_symformat_aout; +#endif +#ifdef DB_ELF_SYMBOLS +extern db_symformat_t db_symformat_elf; +#endif diff --git a/sys/kern/kern_lkm.c b/sys/kern/kern_lkm.c index 77382bdecee..b6cff77961b 100644 --- a/sys/kern/kern_lkm.c +++ b/sys/kern/kern_lkm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_lkm.c,v 1.27 2001/02/06 16:38:13 fgsch Exp $ */ +/* $OpenBSD: kern_lkm.c,v 1.28 2001/02/10 10:42:35 niklas Exp $ */ /* $NetBSD: kern_lkm.c,v 1.31 1996/03/31 21:40:27 christos Exp $ */ /* @@ -509,7 +509,7 @@ lkmioctl(dev, cmd, data, flag, p) curp->sym_id = db_add_symbol_table(curp->syms, curp->syms + curp->sym_symsize, curp->private.lkm_any->lkm_name, - curp->syms, curp->syms + curp->sym_size); + curp->syms); printf("DDB symbols added: %ld bytes\n", curp->sym_symsize); } |