summaryrefslogtreecommitdiff
path: root/usr.bin/pmdb/symbol.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/pmdb/symbol.c')
-rw-r--r--usr.bin/pmdb/symbol.c160
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);
+}
+