Annotation of src/usr.bin/pmdb/symbol.c, Revision 1.5
1.5 ! art 1: /* $OpenBSD: symbol.c,v 1.4 2002/03/15 18:04:41 art Exp $ */
1.1 art 2: /*
3: * Copyright (c) 2002 Artur Grabowski <art@openbsd.org>
4: * All rights reserved.
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: *
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. The name of the author may not be used to endorse or promote products
13: * derived from this software without specific prior written permission.
14: *
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
16: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
17: * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
18: * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25: */
26:
27: #include <stdlib.h>
28: #include <stdio.h>
29: #include <string.h>
30: #include <err.h>
1.4 art 31: #include <errno.h>
1.1 art 32:
33: #include "pmdb.h"
34: #include "symbol.h"
35:
36: /*
37: * Initialize the executable and the symbol table.
38: */
39: void
40: sym_init_exec(struct pstate *ps, const char *name)
41: {
42: ps->ps_sops = NULL;
43: ps->ps_sym_exe = NULL;
44: TAILQ_INIT(&ps->ps_syms);
45:
46: #ifdef PMDB_ELF
47: if (sym_check_elf(name, ps))
48: #endif
49: #ifdef PMDB_AOUT
50: if (sym_check_aout(name, ps))
51: #endif
52: warnx("sym_init_exec: %s is not a supported file format", name);
53:
54: if (ps->ps_sops) {
1.3 art 55: /* XXX - this 0 doesn't have to be correct.. */
56: ps->ps_sym_exe = st_open(ps, name, 0);
1.1 art 57: if (ps->ps_sym_exe)
58: ps->ps_sym_exe->st_flags |= ST_EXEC;
59: }
60: }
61:
62: /*
63: * Destroy all symbol tables.
64: */
65: void
66: sym_destroy(struct pstate *ps)
67: {
68: struct sym_table *st;
69:
70: while ((st = TAILQ_FIRST(&ps->ps_syms)) != NULL) {
71: TAILQ_REMOVE(&ps->ps_syms, st, st_list);
72: (*ps->ps_sops->sop_close)(st);
73: }
74: ps->ps_sym_exe = NULL;
75: }
76:
77: /*
78: * We have reasons to believe that the symbol tables we have are not consistent
79: * with the running binary. Update.
80: */
81: void
82: sym_update(struct pstate *ps)
83: {
84: (*ps->ps_sops->sop_update)(ps);
85: }
86:
87: char *
88: sym_name_and_offset(struct pstate *ps, reg pc, char *nam, size_t len, reg *off)
89: {
90: struct sym_table *st;
91: int bestoffisset = 0;
92: reg bestoff, noff;
93: char *res;
94:
95: TAILQ_FOREACH(st, &ps->ps_syms, st_list) {
96: res = (*ps->ps_sops->sop_name_and_off)(st, pc, &noff);
97: if (res == NULL)
98: continue;
99: if (noff < bestoff || !bestoffisset) {
100: bestoffisset = 1;
101: bestoff = noff;
102: strlcpy(nam, res, len);
103: }
104: }
105:
106: if (!bestoffisset || !strcmp(nam, "_end"))
107: return (NULL);
108:
109: *off = bestoff;
110: return (nam);
111: }
112:
113: int
114: sym_lookup(struct pstate *ps, const char *name, reg *res)
115: {
116: /*
117: * We let the sop do the table walking itself since it might have
118: * preferences about what symbols to pick (weak and stuff).
119: */
120: return ((*ps->ps_sops->sop_lookup)(ps, name, res));
121: }
122:
123: char *
124: sym_print(struct pstate *ps, reg pc, char *buf, size_t buflen)
125: {
126: char namebuf[1024], *name;
127: reg offs;
128:
129: name = sym_name_and_offset(ps, pc, namebuf, sizeof(namebuf), &offs);
130: if (name == NULL) {
131: snprintf(buf, buflen, "0x%lx", pc);
132: } else {
133: snprintf(buf, buflen, "%s+0x%lx(0x%lx)", name, offs, pc);
134: }
135:
136: return (buf);
137: }
138:
139: /*
140: * Open a symbol table and install it in the list. Don't do anything if
141: * it's already there.
142: */
143: struct sym_table *
1.3 art 144: st_open(struct pstate *ps, const char *name, reg offs)
1.1 art 145: {
146: struct sym_table *st;
147:
148: TAILQ_FOREACH(st, &ps->ps_syms, st_list) {
1.3 art 149: if (!strcmp(name, st->st_fname) && (st->st_offs == offs))
1.1 art 150: return (st);
151: }
152:
1.4 art 153: warnx("Loading symbols from %s at 0x%lx", name, offs);
1.1 art 154:
155: if ((st = (*ps->ps_sops->sop_open)(name)) != NULL) {
156: TAILQ_INSERT_TAIL(&ps->ps_syms, st, st_list);
157: strlcpy(st->st_fname, name, sizeof(st->st_fname));
1.5 ! art 158: st->st_offs = offs;
1.1 art 159: }
160:
161: return (st);
162: }
163:
1.4 art 164: /*
165: * Load a symbol table from file argv[1] at offset argv[2].
166: */
167: int
168: cmd_sym_load(int argc, char **argv, void *arg)
169: {
170: struct pstate *ps = arg;
171: char *fname, *ep;
172: reg offs;
173:
174: fname = argv[1];
175: errno = 0;
176: offs = strtol(argv[2], &ep, 0);
177: if (argv[2][0] == '\0' || *ep != '\0' || errno == ERANGE) {
178: fprintf(stderr, "%s is not a valid offset\n", argv[2]);
179: return (0);
180: }
181:
182: if (st_open(ps, fname, offs) == NULL) {
183: warnx("symbol loading failed");
184: }
185:
186: return (0);
187: }