summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>2001-02-10 10:43:19 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>2001-02-10 10:43:19 +0000
commit5bfde2c9bd95671842fedd8d95bf23e072278fb3 (patch)
tree1abbcb3d3f121b6be953ef37a37676a20a6446cc
parent5e833b12704c89c1fad72b7b6f3706cfd15ab035 (diff)
new symbol handling in ddb for ELF, there is still a problem with hangman on alpha though..
-rw-r--r--sys/conf/files3
-rw-r--r--sys/ddb/db_aout.c481
-rw-r--r--sys/ddb/db_elf.c415
-rw-r--r--sys/ddb/db_extern.h22
-rw-r--r--sys/ddb/db_hangman.c123
-rw-r--r--sys/ddb/db_sym.c484
-rw-r--r--sys/ddb/db_sym.h92
-rw-r--r--sys/kern/kern_lkm.c4
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);
}