[BACK]Return to aout_syms.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / pmdb

Annotation of src/usr.bin/pmdb/aout_syms.c, Revision 1.11

1.11    ! deraadt     1: /*     $OpenBSD: aout_syms.c,v 1.10 2003/04/25 20:07:09 pvalchev 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:
1.7       fgsch      27: #include <sys/param.h>
                     28: #include <sys/ptrace.h>
                     29: #include <sys/mman.h>
                     30: #include <sys/stat.h>
                     31:
1.1       art        32: #include <stdio.h>
                     33: #include <stdlib.h>
                     34: #include <unistd.h>
                     35: #include <fcntl.h>
                     36: #include <string.h>
                     37: #include <err.h>
                     38:
                     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;
1.7       fgsch     101:        struct stat sb;
1.1       art       102:        u_int32_t symoff, stroff;
                    103:        struct exec ahdr;
                    104:
                    105:        if ((ash = malloc(sizeof(*ash))) == NULL) {
                    106:                return NULL;
                    107:        }
                    108:
                    109:        memset(ash, 0, sizeof(*ash));
                    110:        ash->ash_fd = -1;
                    111:
                    112:        if ((ash->ash_fd = open(name, O_RDONLY)) < 0) {
                    113:                warn("open(%s)", name);
                    114:                goto fail;
                    115:        }
                    116:
                    117:        if (pread(ash->ash_fd, &ahdr, sizeof(ahdr), 0) != sizeof(ahdr)) {
                    118:                warn("pread(header)");
                    119:                goto fail;
                    120:        }
                    121:
                    122:        if (N_BADMAG(ahdr)) {
                    123:                warnx("Bad magic.");
                    124:                goto fail;
                    125:        }
1.7       fgsch     126:
                    127:        /* Don't go further for stripped files. */
                    128:        if (fstat(ash->ash_fd, &sb) < 0 || N_SYMOFF(ahdr) == sb.st_size ||
                    129:            N_STROFF(ahdr) == sb.st_size)
                    130:                goto fail;
1.1       art       131:
                    132:        symoff = N_SYMOFF(ahdr);
                    133:        ash->ash_symsize = ahdr.a_syms;
                    134:        stroff = N_STROFF(ahdr);
1.8       art       135:
                    136:        if (ahdr.a_syms == 0) {
                    137:                warnx("No symbol table");
                    138:                goto fail;
                    139:        }
1.1       art       140:
                    141:        if (pread(ash->ash_fd, &ash->ash_strsize, sizeof(u_int32_t),
                    142:            stroff) != sizeof(u_int32_t)) {
                    143:                warn("pread(strsize)");
                    144:                goto fail;
                    145:        }
                    146:
                    147:        if ((ash->ash_strtab = mmap(NULL, ash->ash_strsize, PROT_READ,
                    148:            MAP_SHARED, ash->ash_fd, stroff)) == MAP_FAILED) {
                    149:                warn("mmap(strtab)");
                    150:                goto fail;
                    151:        }
                    152:
                    153:        if ((ash->ash_symtab = mmap(NULL, ash->ash_symsize, PROT_READ,
                    154:            MAP_SHARED, ash->ash_fd, symoff)) == MAP_FAILED) {
                    155:                warn("mmap(symtab)");
                    156:                goto fail;
                    157:        }
                    158:
                    159:        return (ASH_TO_ST(ash));
                    160: fail:
                    161:
                    162:        aout_close(ASH_TO_ST(ash));
                    163:        return (NULL);
                    164: }
                    165:
                    166: void
                    167: aout_close(struct sym_table *st)
                    168: {
                    169:        struct aout_symbol_handle *ash = ST_TO_ASH(st);
                    170:
                    171:        if (ash->ash_fd != -1)
                    172:                close(ash->ash_fd);
                    173:
                    174:        munmap(ash->ash_strtab, ash->ash_strsize);
                    175:        munmap(ash->ash_symtab, ash->ash_symsize);
                    176:        free(ash);
                    177: }
                    178:
                    179: char *
                    180: aout_name_and_off(struct sym_table *st, reg pc, reg *offs)
                    181: {
                    182:        struct aout_symbol_handle *ash = ST_TO_ASH(st);
                    183:        struct nlist *s, *bests = NULL;
                    184:        int bestoff = 0;
                    185:        int nsyms, i;
                    186:        char *symn;
                    187:
1.3       art       188: #define SYMVAL(S) (unsigned long)((S)->n_value + st->st_offs)
1.1       art       189:
                    190:        nsyms = ash->ash_symsize / sizeof(struct nlist);
                    191:
                    192:        bests = NULL;
                    193:        for (i = 0; i < nsyms; i++) {
                    194:                s = &ash->ash_symtab[i];
                    195:
                    196:                if (s->n_value == 0 ||
                    197:                    s->n_un.n_strx == 0)
                    198:                        continue;
                    199:
                    200:                symn = &ash->ash_strtab[s->n_un.n_strx];
                    201:                if (SYMVAL(s) <= pc && SYMVAL(s) > bestoff &&
                    202:                    symn[0] != '\0' && strcmp(symn, "gcc2_compiled.")) {
                    203:                        bests = s;
                    204:                        bestoff = SYMVAL(s);
                    205:                }
                    206:        }
                    207:
                    208:        if ((s = bests) == NULL)
                    209:                return (NULL);
                    210:
                    211:        *offs = pc - SYMVAL(s);
                    212:
                    213:        return &ash->ash_strtab[s->n_un.n_strx];
                    214: }
                    215:
                    216: static struct nlist *
                    217: aout_lookup_table(struct aout_symbol_handle *ash, const char *name)
                    218: {
                    219:        int nsyms, i;
                    220:        char *symn;
                    221:        struct nlist *s = NULL;
                    222:
                    223:        nsyms = ash->ash_symsize / sizeof(struct nlist);
                    224:        for (i = 0; i < nsyms; i++) {
                    225:                s = &ash->ash_symtab[i];
                    226:                symn = &ash->ash_strtab[s->n_un.n_strx];
                    227:                if (strcmp(name, symn) == 0)
                    228:                        break;
                    229:        }
                    230:
                    231:        if (i == nsyms)
                    232:                return (NULL);
                    233:
                    234:        return (s);
                    235: }
                    236:
                    237: int
                    238: aout_lookup(struct pstate *ps, const char *name, reg *res)
                    239: {
                    240:        struct sym_table *st;
1.11    ! deraadt   241:        struct nlist *s = NULL;
1.1       art       242:        int first = 1;
                    243:        char *sname = (char *)name;
                    244:
                    245: restart:
                    246:        TAILQ_FOREACH(st, &ps->ps_syms, st_list) {
                    247:                if ((s = aout_lookup_table(ST_TO_ASH(st), sname)) != NULL)
                    248:                        break;
                    249:        }
                    250:
                    251:        if (!first)
                    252:                free(sname);
                    253:
                    254:        if (s == NULL) {
                    255:                if (first) {
1.10      pvalchev  256:                        if (asprintf(&sname, "_%s", sname) != -1) {
1.1       art       257:                                first = 0;
                    258:                                goto restart;
                    259:                        }
                    260:                }
                    261:
                    262:                return (-1);
                    263:        }
                    264:
1.3       art       265:        *res = s->n_value + st->st_offs;
1.1       art       266:        return (0);
                    267: }
                    268:
                    269: /*
                    270:  * Called after execution started so that we can load any dynamic symbols.
                    271:  */
                    272: void
                    273: aout_update(struct pstate *ps)
                    274: {
                    275:        struct _dynamic dyn;
                    276:        struct so_debug sdeb;
                    277:        struct section_dispatch_table sdt;
                    278:        struct so_map som;
                    279:        off_t somp;
                    280:        reg addr;
                    281:        struct nlist *s;
                    282:
                    283:        if ((s = aout_lookup_table(ST_TO_ASH(ps->ps_sym_exe), "__DYNAMIC")) == NULL) {
                    284:                warnx("Can't find __DYNAMIC");
                    285:                return;
                    286:        }
1.3       art       287:        addr = s->n_value + ps->ps_sym_exe->st_offs;
1.1       art       288:
1.9       art       289:        if (process_read(ps, addr, &dyn, sizeof(dyn)) < 0) {
1.1       art       290:                warn("Can't read __DYNAMIC");
                    291:                return;
                    292:        }
                    293:
                    294:        if (dyn.d_version != LD_VERSION_BSD) {
                    295:                warn("Can't handle __DYNAMIC version %d", dyn.d_version);
                    296:                return;
                    297:        }
                    298:
1.9       art       299:        if (process_read(ps, (off_t)(reg)dyn.d_debug, &sdeb, sizeof(sdeb)) < 0) {
1.1       art       300:                warn("Can't read __DYNAMIC.d_debug");
                    301:                return;
                    302:        }
                    303:
                    304:        if (sdeb.dd_version != 0) {
                    305:                warn("Can't handle so_debug version %d", sdeb.dd_version);
                    306:                return;
                    307:        }
                    308:
1.9       art       309:        if (process_read(ps, (off_t)(reg)dyn.d_un.d_sdt, &sdt, sizeof(sdt)) < 0) {
1.1       art       310:                warn("Can't read section dispatch table");
                    311:                return;
                    312:        }
                    313:
                    314:        somp = (off_t)(reg)sdt.sdt_loaded;
                    315:        while (somp) {
                    316:                char fname[MAXPATHLEN];
                    317:                int i;
                    318:
1.9       art       319:                if (process_read(ps, somp, &som, sizeof(som)) < 0) {
1.1       art       320:                        warn("Can't read so_map");
                    321:                        break;
                    322:                }
                    323:                somp = (off_t)(reg)som.som_next;
1.9       art       324:                if (process_read(ps, (off_t)(reg)som.som_path, fname,
1.1       art       325:                    sizeof(fname)) < 0) {
                    326:                        warn("Can't read so filename");
                    327:                        continue;
                    328:                }
                    329:
                    330:                /* sanity check the file name */
                    331:                for (i = 0; i < MAXPATHLEN; i++)
                    332:                        if (fname[i] == '\0')
                    333:                                break;
                    334:                if (i == MAXPATHLEN) {
                    335:                        warnx("so filename invalid");
                    336:                        continue;
                    337:                }
                    338:
1.3       art       339:                if (st_open(ps, fname, (reg)som.som_addr) == NULL)
1.1       art       340:                        warn("symbol loading failed");
                    341:        }
                    342: }