Annotation of src/usr.bin/pmdb/aout_syms.c, Revision 1.6
1.6 ! deraadt 1: /* $OpenBSD: aout_syms.c,v 1.5 2002/03/19 21:19:39 fgsch Exp $ */
1.1 art 2: /*
3: * Copyright (c) 2002 Federico Schwindt <fgsch@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 <stdio.h>
28: #include <stdlib.h>
29: #include <unistd.h>
30: #include <fcntl.h>
31: #include <string.h>
32: #include <err.h>
33:
34: #include <sys/param.h>
35: #include <sys/ptrace.h>
36: #include <sys/mman.h>
37:
38: #include <sys/types.h>
39: #include <a.out.h>
40: #include <link.h>
41:
42: #include "pmdb.h"
43: #include "symbol.h"
44:
45: struct aout_symbol_handle {
46: struct sym_table ash_st;
47: int ash_fd;
48: char *ash_strtab;
49: u_int32_t ash_strsize;
50: struct nlist *ash_symtab;
51: int ash_symsize;
52: };
53:
54: #define ASH_TO_ST(ash) (&(ash)->ash_st)
55: #define ST_TO_ASH(st) ((struct aout_symbol_handle *)(st))
56:
57: struct sym_table *aout_open(const char *);
58: void aout_close(struct sym_table *);
59: char *aout_name_and_off(struct sym_table *, reg, reg *);
60: int aout_lookup(struct pstate *, const char *, reg *);
61: void aout_update(struct pstate *);
62:
63: struct sym_ops aout_sops = {
64: aout_open,
65: aout_close,
66: aout_name_and_off,
67: aout_lookup,
68: aout_update
69: };
70:
71: int
72: sym_check_aout(const char *name, struct pstate *ps)
73: {
74: struct exec ahdr;
1.4 fgsch 75: int error = 0;
1.1 art 76: int fd;
77:
78: if ((fd = open(name, O_RDONLY)) < 0)
1.4 fgsch 79: return (1);
1.1 art 80:
81: if (pread(fd, &ahdr, sizeof(ahdr), 0) != sizeof(ahdr)) {
1.4 fgsch 82: error = 1;
1.1 art 83: }
84:
1.5 fgsch 85: if (!error && N_BADMAG(ahdr)) {
1.4 fgsch 86: error = 1;
1.1 art 87: }
88:
89: close(fd);
90:
1.4 fgsch 91: if (!error)
92: ps->ps_sops = &aout_sops;
1.1 art 93:
1.4 fgsch 94: return (error);
1.1 art 95: }
96:
97: struct sym_table *
98: aout_open(const char *name)
99: {
100: struct aout_symbol_handle *ash;
101: u_int32_t symoff, stroff;
102: struct exec ahdr;
103:
104: if ((ash = malloc(sizeof(*ash))) == NULL) {
105: return NULL;
106: }
107:
108: memset(ash, 0, sizeof(*ash));
109: ash->ash_fd = -1;
110:
111: if ((ash->ash_fd = open(name, O_RDONLY)) < 0) {
112: warn("open(%s)", name);
113: goto fail;
114: }
115:
116: if (pread(ash->ash_fd, &ahdr, sizeof(ahdr), 0) != sizeof(ahdr)) {
117: warn("pread(header)");
118: goto fail;
119: }
120:
121: if (N_BADMAG(ahdr)) {
122: warnx("Bad magic.");
123: goto fail;
124: }
125:
126: symoff = N_SYMOFF(ahdr);
127: ash->ash_symsize = ahdr.a_syms;
128: stroff = N_STROFF(ahdr);
129:
130: if (pread(ash->ash_fd, &ash->ash_strsize, sizeof(u_int32_t),
131: stroff) != sizeof(u_int32_t)) {
132: warn("pread(strsize)");
133: goto fail;
134: }
135:
136: if ((ash->ash_strtab = mmap(NULL, ash->ash_strsize, PROT_READ,
137: MAP_SHARED, ash->ash_fd, stroff)) == MAP_FAILED) {
138: warn("mmap(strtab)");
139: goto fail;
140: }
141:
142: if ((ash->ash_symtab = mmap(NULL, ash->ash_symsize, PROT_READ,
143: MAP_SHARED, ash->ash_fd, symoff)) == MAP_FAILED) {
144: warn("mmap(symtab)");
145: goto fail;
146: }
147:
148: return (ASH_TO_ST(ash));
149: fail:
150:
151: aout_close(ASH_TO_ST(ash));
152: return (NULL);
153: }
154:
155: void
156: aout_close(struct sym_table *st)
157: {
158: struct aout_symbol_handle *ash = ST_TO_ASH(st);
159:
160: if (ash->ash_fd != -1)
161: close(ash->ash_fd);
162:
163: munmap(ash->ash_strtab, ash->ash_strsize);
164: munmap(ash->ash_symtab, ash->ash_symsize);
165: free(ash);
166: }
167:
168: char *
169: aout_name_and_off(struct sym_table *st, reg pc, reg *offs)
170: {
171: struct aout_symbol_handle *ash = ST_TO_ASH(st);
172: struct nlist *s, *bests = NULL;
173: int bestoff = 0;
174: int nsyms, i;
175: char *symn;
176:
1.3 art 177: #define SYMVAL(S) (unsigned long)((S)->n_value + st->st_offs)
1.1 art 178:
179: nsyms = ash->ash_symsize / sizeof(struct nlist);
180:
181: bests = NULL;
182: for (i = 0; i < nsyms; i++) {
183: s = &ash->ash_symtab[i];
184:
185: if (s->n_value == 0 ||
186: s->n_un.n_strx == 0)
187: continue;
188:
189: symn = &ash->ash_strtab[s->n_un.n_strx];
190: if (SYMVAL(s) <= pc && SYMVAL(s) > bestoff &&
191: symn[0] != '\0' && strcmp(symn, "gcc2_compiled.")) {
192: bests = s;
193: bestoff = SYMVAL(s);
194: }
195: }
196:
197: if ((s = bests) == NULL)
198: return (NULL);
199:
200: *offs = pc - SYMVAL(s);
201:
202: return &ash->ash_strtab[s->n_un.n_strx];
203: }
204:
205: static struct nlist *
206: aout_lookup_table(struct aout_symbol_handle *ash, const char *name)
207: {
208: int nsyms, i;
209: char *symn;
210: struct nlist *s = NULL;
211:
212: nsyms = ash->ash_symsize / sizeof(struct nlist);
213: for (i = 0; i < nsyms; i++) {
214: s = &ash->ash_symtab[i];
215: symn = &ash->ash_strtab[s->n_un.n_strx];
216: if (strcmp(name, symn) == 0)
217: break;
218: }
219:
220: if (i == nsyms)
221: return (NULL);
222:
223: return (s);
224: }
225:
226: int
227: aout_lookup(struct pstate *ps, const char *name, reg *res)
228: {
229: struct sym_table *st;
230: struct nlist *s;
231: int first = 1;
232: char *sname = (char *)name;
233:
234: restart:
235: TAILQ_FOREACH(st, &ps->ps_syms, st_list) {
236: if ((s = aout_lookup_table(ST_TO_ASH(st), sname)) != NULL)
237: break;
238: }
239:
240: if (!first)
241: free(sname);
242:
243: if (s == NULL) {
244: if (first) {
245: asprintf(&sname, "_%s", sname);
246: if (sname != NULL) {
247: first = 0;
248: goto restart;
249: }
250: }
251:
252: return (-1);
253: }
254:
1.3 art 255: *res = s->n_value + st->st_offs;
1.1 art 256: return (0);
257: }
258:
259: /*
260: * Called after execution started so that we can load any dynamic symbols.
261: */
262: void
263: aout_update(struct pstate *ps)
264: {
265: pid_t pid = ps->ps_pid;
266: struct _dynamic dyn;
267: struct so_debug sdeb;
268: struct section_dispatch_table sdt;
269: struct so_map som;
270: off_t somp;
271: reg addr;
272: struct nlist *s;
273:
274: if ((s = aout_lookup_table(ST_TO_ASH(ps->ps_sym_exe), "__DYNAMIC")) == NULL) {
275: warnx("Can't find __DYNAMIC");
276: return;
277: }
1.3 art 278: addr = s->n_value + ps->ps_sym_exe->st_offs;
1.1 art 279:
280: if (read_from_pid(pid, addr, &dyn, sizeof(dyn)) < 0) {
281: warn("Can't read __DYNAMIC");
282: return;
283: }
284:
285: if (dyn.d_version != LD_VERSION_BSD) {
286: warn("Can't handle __DYNAMIC version %d", dyn.d_version);
287: return;
288: }
289:
290: if (read_from_pid(pid, (off_t)(reg)dyn.d_debug, &sdeb, sizeof(sdeb)) < 0) {
291: warn("Can't read __DYNAMIC.d_debug");
292: return;
293: }
294:
295: if (sdeb.dd_version != 0) {
296: warn("Can't handle so_debug version %d", sdeb.dd_version);
297: return;
298: }
299:
300: if (read_from_pid(pid, (off_t)(reg)dyn.d_un.d_sdt, &sdt, sizeof(sdt)) < 0) {
301: warn("Can't read section dispatch table");
302: return;
303: }
304:
305: somp = (off_t)(reg)sdt.sdt_loaded;
306: while (somp) {
307: char fname[MAXPATHLEN];
308: int i;
309:
310: if (read_from_pid(pid, somp, &som, sizeof(som)) < 0) {
311: warn("Can't read so_map");
312: break;
313: }
314: somp = (off_t)(reg)som.som_next;
315: if (read_from_pid(pid, (off_t)(reg)som.som_path, fname,
316: sizeof(fname)) < 0) {
317: warn("Can't read so filename");
318: continue;
319: }
320:
321: /* sanity check the file name */
322: for (i = 0; i < MAXPATHLEN; i++)
323: if (fname[i] == '\0')
324: break;
325: if (i == MAXPATHLEN) {
326: warnx("so filename invalid");
327: continue;
328: }
329:
1.3 art 330: if (st_open(ps, fname, (reg)som.som_addr) == NULL)
1.1 art 331: warn("symbol loading failed");
332: }
333: }