[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.1

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