diff options
Diffstat (limited to 'usr.bin/pmdb/symbol.c')
-rw-r--r-- | usr.bin/pmdb/symbol.c | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/usr.bin/pmdb/symbol.c b/usr.bin/pmdb/symbol.c new file mode 100644 index 00000000000..8f6d1e6f64e --- /dev/null +++ b/usr.bin/pmdb/symbol.c @@ -0,0 +1,160 @@ +/* $PMDB: symbol.c,v 1.5 2002/03/07 14:27:08 art Exp $ */ +/* + * Copyright (c) 2002 Artur Grabowski <art@openbsd.org> + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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 <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <err.h> + +#include "pmdb.h" +#include "symbol.h" + +/* + * Initialize the executable and the symbol table. + */ +void +sym_init_exec(struct pstate *ps, const char *name) +{ + ps->ps_sops = NULL; + ps->ps_sym_exe = NULL; + TAILQ_INIT(&ps->ps_syms); + +#ifdef PMDB_ELF + if (sym_check_elf(name, ps)) +#endif +#ifdef PMDB_AOUT + if (sym_check_aout(name, ps)) +#endif + warnx("sym_init_exec: %s is not a supported file format", name); + + if (ps->ps_sops) { + ps->ps_sym_exe = st_open(ps, name); + if (ps->ps_sym_exe) + ps->ps_sym_exe->st_flags |= ST_EXEC; + } +} + +/* + * Destroy all symbol tables. + */ +void +sym_destroy(struct pstate *ps) +{ + struct sym_table *st; + + while ((st = TAILQ_FIRST(&ps->ps_syms)) != NULL) { + TAILQ_REMOVE(&ps->ps_syms, st, st_list); + (*ps->ps_sops->sop_close)(st); + } + ps->ps_sym_exe = NULL; +} + +/* + * We have reasons to believe that the symbol tables we have are not consistent + * with the running binary. Update. + */ +void +sym_update(struct pstate *ps) +{ + (*ps->ps_sops->sop_update)(ps); +} + +char * +sym_name_and_offset(struct pstate *ps, reg pc, char *nam, size_t len, reg *off) +{ + struct sym_table *st; + int bestoffisset = 0; + reg bestoff, noff; + char *res; + + TAILQ_FOREACH(st, &ps->ps_syms, st_list) { + res = (*ps->ps_sops->sop_name_and_off)(st, pc, &noff); + if (res == NULL) + continue; + if (noff < bestoff || !bestoffisset) { + bestoffisset = 1; + bestoff = noff; + strlcpy(nam, res, len); + } + } + + if (!bestoffisset || !strcmp(nam, "_end")) + return (NULL); + + *off = bestoff; + return (nam); +} + +int +sym_lookup(struct pstate *ps, const char *name, reg *res) +{ + /* + * We let the sop do the table walking itself since it might have + * preferences about what symbols to pick (weak and stuff). + */ + return ((*ps->ps_sops->sop_lookup)(ps, name, res)); +} + +char * +sym_print(struct pstate *ps, reg pc, char *buf, size_t buflen) +{ + char namebuf[1024], *name; + reg offs; + + name = sym_name_and_offset(ps, pc, namebuf, sizeof(namebuf), &offs); + if (name == NULL) { + snprintf(buf, buflen, "0x%lx", pc); + } else { + snprintf(buf, buflen, "%s+0x%lx(0x%lx)", name, offs, pc); + } + + return (buf); +} + +/* + * Open a symbol table and install it in the list. Don't do anything if + * it's already there. + */ +struct sym_table * +st_open(struct pstate *ps, const char *name) +{ + struct sym_table *st; + + TAILQ_FOREACH(st, &ps->ps_syms, st_list) { + if (!strcmp(name, st->st_fname)) + return (st); + } + + warnx("Loading symbols from %s", name); + + if ((st = (*ps->ps_sops->sop_open)(name)) != NULL) { + TAILQ_INSERT_TAIL(&ps->ps_syms, st, st_list); + strlcpy(st->st_fname, name, sizeof(st->st_fname)); + } + + return (st); +} + |