Annotation of src/usr.bin/pmdb/symbol.c, Revision 1.7
1.7 ! mickey 1: /* $OpenBSD: symbol.c,v 1.6 2002/07/24 14:06:27 vincent 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:
1.6 vincent 70: if (!(ps->ps_flags & PSF_SYMBOLS))
71: return;
1.1 art 72: while ((st = TAILQ_FIRST(&ps->ps_syms)) != NULL) {
73: TAILQ_REMOVE(&ps->ps_syms, st, st_list);
74: (*ps->ps_sops->sop_close)(st);
75: }
76: ps->ps_sym_exe = NULL;
77: }
78:
79: /*
80: * We have reasons to believe that the symbol tables we have are not consistent
81: * with the running binary. Update.
82: */
83: void
84: sym_update(struct pstate *ps)
85: {
86: (*ps->ps_sops->sop_update)(ps);
87: }
88:
89: char *
90: sym_name_and_offset(struct pstate *ps, reg pc, char *nam, size_t len, reg *off)
91: {
92: struct sym_table *st;
93: int bestoffisset = 0;
94: reg bestoff, noff;
95: char *res;
96:
97: TAILQ_FOREACH(st, &ps->ps_syms, st_list) {
98: res = (*ps->ps_sops->sop_name_and_off)(st, pc, &noff);
99: if (res == NULL)
100: continue;
101: if (noff < bestoff || !bestoffisset) {
102: bestoffisset = 1;
103: bestoff = noff;
104: strlcpy(nam, res, len);
105: }
106: }
107:
108: if (!bestoffisset || !strcmp(nam, "_end"))
109: return (NULL);
110:
111: *off = bestoff;
112: return (nam);
113: }
114:
115: int
116: sym_lookup(struct pstate *ps, const char *name, reg *res)
117: {
118: /*
119: * We let the sop do the table walking itself since it might have
120: * preferences about what symbols to pick (weak and stuff).
121: */
122: return ((*ps->ps_sops->sop_lookup)(ps, name, res));
123: }
124:
125: char *
126: sym_print(struct pstate *ps, reg pc, char *buf, size_t buflen)
127: {
128: char namebuf[1024], *name;
129: reg offs;
130:
131: name = sym_name_and_offset(ps, pc, namebuf, sizeof(namebuf), &offs);
132: if (name == NULL) {
133: snprintf(buf, buflen, "0x%lx", pc);
134: } else {
1.7 ! mickey 135: if (offs)
! 136: snprintf(buf, buflen, "%s+0x%lx(0x%lx)",
! 137: name, offs, pc);
! 138: else
! 139: snprintf(buf, buflen, "%s(0x%lx)", name, pc);
1.1 art 140: }
141:
142: return (buf);
143: }
144:
145: /*
146: * Open a symbol table and install it in the list. Don't do anything if
147: * it's already there.
148: */
149: struct sym_table *
1.3 art 150: st_open(struct pstate *ps, const char *name, reg offs)
1.1 art 151: {
152: struct sym_table *st;
153:
154: TAILQ_FOREACH(st, &ps->ps_syms, st_list) {
1.3 art 155: if (!strcmp(name, st->st_fname) && (st->st_offs == offs))
1.1 art 156: return (st);
157: }
158:
1.4 art 159: warnx("Loading symbols from %s at 0x%lx", name, offs);
1.1 art 160:
161: if ((st = (*ps->ps_sops->sop_open)(name)) != NULL) {
162: TAILQ_INSERT_TAIL(&ps->ps_syms, st, st_list);
163: strlcpy(st->st_fname, name, sizeof(st->st_fname));
1.5 art 164: st->st_offs = offs;
1.1 art 165: }
166:
167: return (st);
168: }
169:
1.4 art 170: /*
171: * Load a symbol table from file argv[1] at offset argv[2].
172: */
173: int
174: cmd_sym_load(int argc, char **argv, void *arg)
175: {
176: struct pstate *ps = arg;
177: char *fname, *ep;
178: reg offs;
179:
180: fname = argv[1];
181: errno = 0;
182: offs = strtol(argv[2], &ep, 0);
183: if (argv[2][0] == '\0' || *ep != '\0' || errno == ERANGE) {
184: fprintf(stderr, "%s is not a valid offset\n", argv[2]);
185: return (0);
186: }
187:
188: if (st_open(ps, fname, offs) == NULL) {
189: warnx("symbol loading failed");
190: }
191:
192: return (0);
193: }