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

Annotation of src/usr.bin/pmdb/elf_syms.c, Revision 1.8

1.8     ! mickey      1: /*     $OpenBSD: elf_syms.c,v 1.7 2002/07/31 04:42:01 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 <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 <nlist.h>
                     39: #ifdef __NetBSD__
                     40: #include <machine/elf_machdep.h>
                     41: #define ELFSIZE ARCH_ELFSIZE
                     42: #include <sys/exec_elf.h>
                     43: #else
                     44: #include <elf_abi.h>
                     45: #endif
                     46: #include <link.h>
                     47:
                     48: #include "pmdb.h"
                     49: #include "symbol.h"
                     50: #include "break.h"
                     51:
                     52: struct elf_symbol_handle {
                     53:        struct sym_table esh_st;
                     54:        int             esh_fd;
                     55:        char            *esh_strtab;
                     56:        Elf_Word        esh_strsize;
                     57:        Elf_Sym         *esh_symtab;
                     58:        Elf_Word        esh_symsize;
                     59: };
                     60:
                     61: #define ESH_TO_ST(esh) (&(esh)->esh_st)
                     62: #define ST_TO_ESH(st) ((struct elf_symbol_handle *)(st))
                     63:
                     64: struct sym_table *elf_open(const char *);
                     65: void elf_close(struct sym_table *);
                     66: char *elf_name_and_off(struct sym_table *, reg, reg *);
                     67: int elf_lookup(struct pstate *, const char *, reg *);
                     68: void elf_update(struct pstate *);
                     69:
                     70: struct sym_ops elf_sops = {
                     71:        elf_open,
                     72:        elf_close,
                     73:        elf_name_and_off,
                     74:        elf_lookup,
                     75:        elf_update
                     76: };
                     77:
                     78: int
                     79: sym_check_elf(const char *name, struct pstate *ps)
                     80: {
                     81:        Elf_Ehdr ehdr;
1.4       fgsch      82:        int error = 0;
1.1       art        83:        int fd;
                     84:
                     85:        if ((fd = open(name, O_RDONLY)) < 0)
1.4       fgsch      86:                return (1);
1.1       art        87:
                     88:        if (pread(fd, &ehdr, sizeof(Elf_Ehdr), 0) != sizeof(Elf_Ehdr))
1.4       fgsch      89:                error = 1;
1.1       art        90:
                     91: #ifndef __NetBSD__
1.5       fgsch      92:        if (!error && (!IS_ELF(ehdr) ||
1.1       art        93:            ehdr.e_ident[EI_CLASS] != ELF_TARG_CLASS ||
                     94:            ehdr.e_ident[EI_DATA] != ELF_TARG_DATA ||
                     95:            ehdr.e_ident[EI_VERSION] != ELF_TARG_VER ||
                     96:            ehdr.e_machine != ELF_TARG_MACH ||
1.5       fgsch      97:            ehdr.e_version != ELF_TARG_VER))
1.4       fgsch      98:                error = 1;
1.1       art        99: #endif
                    100:
                    101:        close(fd);
                    102:
1.4       fgsch     103:        if (!error)
                    104:                ps->ps_sops = &elf_sops;
1.1       art       105:
1.4       fgsch     106:        return (error);
1.1       art       107: }
                    108:
                    109: struct sym_table *
                    110: elf_open(const char *name)
                    111: {
                    112:        struct elf_symbol_handle *esh;
                    113:        Elf_Off symoff, stroff;
                    114:        Elf_Ehdr ehdr;
                    115:        Elf_Shdr *shdr;
                    116:        int i, fd;
                    117:
                    118:        /* Just a sanity check */
                    119:        if (sizeof(reg) != sizeof(Elf_Addr))
                    120:                errx(1, "sym_open: sizeof(reg) != sizeof(Elf_Addr)");
                    121:
                    122:        if ((esh = malloc(sizeof(*esh))) == NULL) {
                    123:                return (NULL);
                    124:        }
                    125:
                    126:        memset(esh, 0, sizeof(*esh));
                    127:        esh->esh_fd = -1;
                    128:
                    129:        if ((fd = esh->esh_fd = open(name, O_RDONLY)) < 0) {
                    130:                goto fail;
                    131:        }
                    132:
                    133:        if (pread(fd, &ehdr, sizeof(Elf_Ehdr), 0) != sizeof(Elf_Ehdr)) {
                    134:                goto fail;
                    135:        }
                    136: #ifndef __NetBSD__
                    137:        if (!IS_ELF(ehdr) ||
                    138:            ehdr.e_ident[EI_CLASS] != ELF_TARG_CLASS ||
                    139:            ehdr.e_ident[EI_DATA] != ELF_TARG_DATA ||
                    140:            ehdr.e_ident[EI_VERSION] != ELF_TARG_VER ||
                    141:            ehdr.e_machine != ELF_TARG_MACH ||
                    142:            ehdr.e_version != ELF_TARG_VER) {
                    143:                goto fail;
                    144:        }
                    145: #endif
                    146:
                    147:        if ((shdr = (Elf_Shdr *)mmap(NULL, ehdr.e_shentsize * ehdr.e_shnum,
                    148:            PROT_READ, MAP_SHARED, fd, ehdr.e_shoff)) == MAP_FAILED) {
                    149:                goto fail;
                    150:        }
                    151:
                    152:        for (i = 0; i < ehdr.e_shnum; i++) {
                    153:                if (shdr[i].sh_type == SHT_SYMTAB) {
                    154:                        symoff = shdr[i].sh_offset;
                    155:                        esh->esh_symsize = shdr[i].sh_size;
                    156:                        stroff = shdr[shdr[i].sh_link].sh_offset;
                    157:                        esh->esh_strsize = shdr[shdr[i].sh_link].sh_size;
                    158:                        break;
                    159:                }
                    160:        }
                    161:
                    162:        munmap(shdr, ehdr.e_shentsize * ehdr.e_shnum);
                    163:
                    164:        if (i == ehdr.e_shnum) {
                    165:                goto fail;
                    166:        }
                    167:
1.8     ! mickey    168:        if (esh->esh_symsize) {
        !           169:
        !           170:                if ((esh->esh_strtab = mmap(NULL, esh->esh_strsize, PROT_READ,
        !           171:                    MAP_SHARED, fd, stroff)) == MAP_FAILED) {
        !           172:                        goto fail;
        !           173:                }
1.1       art       174:
1.8     ! mickey    175:                if ((esh->esh_symtab = mmap(NULL, esh->esh_symsize, PROT_READ,
        !           176:                    MAP_SHARED, fd, symoff)) == MAP_FAILED) {
        !           177:                        goto fail;
        !           178:                }
1.1       art       179:        }
                    180:
                    181:        return (ESH_TO_ST(esh));
                    182: fail:
                    183:
                    184:        elf_close(ESH_TO_ST(esh));
                    185:        return (NULL);
                    186: }
                    187:
                    188: void
                    189: elf_close(struct sym_table *st)
                    190: {
                    191:        struct elf_symbol_handle *esh = ST_TO_ESH(st);
                    192:
                    193:        if (esh->esh_fd != -1)
                    194:                close(esh->esh_fd);
                    195:
                    196:        munmap(esh->esh_strtab, esh->esh_strsize);
                    197:        munmap(esh->esh_symtab, esh->esh_symsize);
                    198:        free(esh);
                    199: }
                    200:
                    201: char *
                    202: elf_name_and_off(struct sym_table *st, reg pc, reg *offs)
                    203: {
                    204:        struct elf_symbol_handle *esh = ST_TO_ESH(st);
                    205:        Elf_Sym *s, *bests = NULL;
                    206:        Elf_Addr bestoff = 0;
                    207:        int nsyms, i;
                    208:        char *symn;
                    209:
1.8     ! mickey    210:        if (esh == NULL)
        !           211:                return (NULL);
        !           212:
1.3       art       213: #define SYMVAL(S) (unsigned long)((S)->st_value + st->st_offs)
1.1       art       214:
                    215:        nsyms = esh->esh_symsize / sizeof(Elf_Sym);
                    216:
                    217:        bests = NULL;
                    218:        for (i = 0; i < nsyms; i++) {
                    219:                s = &esh->esh_symtab[i];
                    220:
                    221:                if (s->st_value == 0 ||
                    222:                    s->st_shndx == 0 ||
                    223:                    (ELF_ST_BIND(s->st_info) != STB_GLOBAL &&
                    224:                     ELF_ST_BIND(s->st_info) != STB_WEAK &&
                    225:                     ELF_ST_BIND(s->st_info) != STB_LOCAL))
                    226:                        continue;
                    227:                symn = &esh->esh_strtab[s->st_name];
                    228:                if (SYMVAL(s) <= pc && SYMVAL(s) > bestoff &&
                    229:                    symn[0] != '\0' && strcmp(symn, "gcc2_compiled.")) {
                    230:                        bests = s;
                    231:                        bestoff = SYMVAL(s);
                    232:                }
                    233:        }
                    234:
                    235:        if ((s = bests) == NULL)
                    236:                return (NULL);
                    237:
                    238:        *offs = pc - SYMVAL(s);
                    239:
                    240:        return &esh->esh_strtab[s->st_name];
                    241: }
                    242:
                    243: static Elf_Sym *
                    244: elf_lookup_table(struct elf_symbol_handle *esh, const char *name)
                    245: {
                    246:        int nsyms, i;
                    247:        char *symn;
                    248:        Elf_Sym *s = NULL;
1.8     ! mickey    249:
        !           250:        if (esh == NULL)
        !           251:                return (NULL);
1.1       art       252:
                    253:        /* XXX - dumb, doesn't follow the rules (weak, hash, etc.). */
                    254:        nsyms = esh->esh_symsize / sizeof(Elf_Sym);
                    255:        for (i = 0; i < nsyms; i++) {
                    256:                s = &esh->esh_symtab[i];
                    257:                symn = &esh->esh_strtab[s->st_name];
                    258:                if (strcmp(name, symn) == 0)
                    259:                        break;
                    260:        }
                    261:        if (i == nsyms)
                    262:                return (NULL);
                    263:
                    264:        return (s);
                    265: }
                    266:
                    267: int
                    268: elf_lookup(struct pstate *ps, const char *name, reg *res)
                    269: {
                    270:        struct sym_table *st;
                    271:        Elf_Sym *s;
                    272:
                    273:        TAILQ_FOREACH(st, &ps->ps_syms, st_list) {
                    274:                if ((s = elf_lookup_table(ST_TO_ESH(st), name)) != NULL)
                    275:                        break;
                    276:        }
                    277:
                    278:        if (s != NULL) {
1.3       art       279:                *res = s->st_value + st->st_offs;
1.1       art       280:                return (0);
                    281:        }
                    282:
                    283:        return (-1);
                    284: }
                    285:
                    286: #ifndef __NetBSD__
                    287: struct elf_object_v1 {
                    288:        Elf_Addr load_addr;
                    289:        Elf_Addr load_offs;
                    290:        char *load_name;
                    291:        Elf_Dyn *load_dyn;
                    292:        struct elf_object_v1 *next;
                    293:        struct elf_object_v1 *prev;
                    294:        void *load_list;
                    295:        u_int32_t load_size;
                    296:        u_long info[DT_NUM + DT_PROCNUM];
                    297:        struct elf_object_v1 *dep_next;
                    298:        int status;
                    299:        Elf_Phdr *phdrp;
                    300:        int phdrc;
                    301:        int refcount;
                    302:        int obj_type;
                    303: #define EOBJ1_LDR 1
                    304: #define EOBJ1_EXE 2
                    305: #define EOBJ1_LIB 3
                    306: #define EOBJ1_DLO 4
                    307: };
                    308: #endif
                    309:
                    310: /*
                    311:  * dlopen breakpoint (XXX make this generic?)
                    312:  */
                    313: int
                    314: sym_bkpt(struct pstate *ps, void *arg)
                    315: {
                    316:        fprintf(stderr, "pmdb: shared lib changed\n");
                    317:
                    318:        sym_update(ps);
                    319:
                    320:        return BKPT_KEEP_CONT;
                    321: }
                    322:
1.7       art       323: /* Is the ABI really so daft that it doesn't include the linking offset? */
                    324: struct xlink_map {
                    325:        struct link_map lm;
                    326:        Elf_Addr a;
                    327: };
                    328:
1.1       art       329: /*
                    330:  * Called after execution started so that we can load any dynamic symbols.
                    331:  */
                    332: void
                    333: elf_update(struct pstate *ps)
                    334: {
                    335: #ifndef __NetBSD__
1.7       art       336:        struct xlink_map xlm;
                    337: #define lm xlm.lm
1.1       art       338:        struct r_debug rdeb;
                    339:        reg addr;
                    340:        Elf_Dyn dyn;
                    341:        static int bkpt_set;
                    342:        Elf_Sym *s;
                    343:
                    344:        if ((s = elf_lookup_table(ST_TO_ESH(ps->ps_sym_exe), "_DYNAMIC")) == NULL) {
                    345:                warnx("Can't find _DYNAMIC");
                    346:                return;
                    347:        }
1.3       art       348:        addr = s->st_value + ps->ps_sym_exe->st_offs;
1.1       art       349:
                    350:        do {
1.6       art       351:                if (process_read(ps, addr, &dyn, sizeof(dyn)) < 0) {
1.1       art       352:                        warnx("Can't read _DYNAMIC");
                    353:                        return;
                    354:                }
                    355:                addr += sizeof(dyn);
                    356:        } while (dyn.d_tag != 0 && dyn.d_tag != DT_DEBUG);
                    357:
                    358:        if (dyn.d_tag == 0) {
                    359:                warnx("Can't find DT_DEBUG");
                    360:                return;
                    361:        }
                    362:
1.6       art       363:        if (process_read(ps, dyn.d_un.d_ptr, &rdeb, sizeof(rdeb)) < 0) {
1.1       art       364:                warnx("Can't read DT_DEBUG");
                    365:                return;
                    366:        }
                    367:
                    368:        if (rdeb.r_version != 1) {
                    369:                warn("Can't handle debug map version %d", rdeb.r_version);
                    370:                return;
                    371:        }
                    372:        if (rdeb.r_state != RT_CONSISTENT) {
                    373:                warn("debug map not consistent: %d", rdeb.r_state);
                    374:                return;
                    375:        }
                    376:
                    377:        if (!bkpt_set) {
                    378:                if (bkpt_add_cb(ps, rdeb.r_brk, sym_bkpt, NULL))
                    379:                        warn("sym_exec: can't set bkpt");
                    380:                bkpt_set = 1;
                    381:        }
                    382:
                    383:        addr = (Elf_Addr)rdeb.r_map;
                    384:        while (addr != 0 && addr != -1) {
                    385:                char fname[MAXPATHLEN];
                    386:                int i;
                    387:
1.7       art       388:                if (process_read(ps, addr, &xlm, sizeof(xlm)) < 0) {
1.1       art       389:                        warnx("Can't read symbols...");
                    390:                        return;
                    391:                }
                    392:
1.7       art       393:                addr = (Elf_Addr)lm.l_next;
1.1       art       394:
1.7       art       395:                if (lm.l_name == NULL || lm.l_name == (char *)-1)
1.1       art       396:                        continue;
1.7       art       397:                if (process_read(ps, (Elf_Addr)lm.l_name, fname,
1.1       art       398:                    sizeof(fname)) < 0) {
                    399:                        warnx("Can't read symbols...");
                    400:                        return;
                    401:                }
                    402:
                    403:                /* sanity check the file name */
                    404:                for (i = 0; i < MAXPATHLEN; i++)
                    405:                        if (fname[i] == '\0')
                    406:                                break;
                    407:                if (i == MAXPATHLEN)
                    408:                        continue;
                    409:
1.7       art       410:                if (st_open(ps, fname, xlm.a) == NULL)
1.1       art       411:                        warn("symbol loading failed");
                    412:        }
                    413: #endif
                    414: }