[BACK]Return to nlist.c CVS log [TXT][DIR] Up to [local] / sys / arch / amd64 / stand / installboot

Annotation of sys/arch/amd64/stand/installboot/nlist.c, Revision 1.1.1.1

1.1       nbrk        1: /*
                      2:  * Copyright (c) 1989, 1993
                      3:  *     The Regents of the University of California.  All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. Neither the name of the University nor the names of its contributors
                     14:  *    may be used to endorse or promote products derived from this software
                     15:  *    without specific prior written permission.
                     16:  *
                     17:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     18:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     19:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     20:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     21:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     22:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     23:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     24:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     25:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     26:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     27:  * SUCH DAMAGE.
                     28:  */
                     29:
                     30: #if defined(LIBC_SCCS) && !defined(lint)
                     31: static char rcsid[] = "$OpenBSD: nlist.c,v 1.3 2007/04/10 17:47:54 miod Exp $";
                     32: #endif /* LIBC_SCCS and not lint */
                     33:
                     34: #include <sys/types.h>
                     35: #include <sys/param.h>
                     36: #include <sys/mman.h>
                     37: #include <sys/stat.h>
                     38:
                     39: #include <errno.h>
                     40: #include <fcntl.h>
                     41: #include <stdio.h>
                     42: #include <stdlib.h>
                     43: #include <string.h>
                     44: #include <unistd.h>
                     45: #include <a.out.h>             /* pulls in nlist.h */
                     46:
                     47: #ifdef _NLIST_DO_ELF
                     48: #include <elf_abi.h>
                     49: #include <olf_abi.h>
                     50: #endif
                     51:
                     52: #ifdef _NLIST_DO_ECOFF
                     53: #include <sys/exec_ecoff.h>
                     54: #endif
                     55:
                     56: int    __fdnlist(int, struct nlist *);
                     57: int    __aout_fdnlist(int, struct nlist *);
                     58: int    __ecoff_fdnlist(int, struct nlist *);
                     59: int    __elf_fdnlist(int, struct nlist *);
                     60: #ifdef _NLIST_DO_ELF
                     61: int    __elf_is_okay__(register Elf_Ehdr *ehdr);
                     62: #endif
                     63:
                     64: #define        ISLAST(p)       (p->n_un.n_name == 0 || p->n_un.n_name[0] == 0)
                     65:
                     66: #ifdef _NLIST_DO_AOUT
                     67: int
                     68: __aout_fdnlist(fd, list)
                     69:        register int fd;
                     70:        register struct nlist *list;
                     71: {
                     72:        register struct nlist *p, *s;
                     73:        register char *strtab;
                     74:        register off_t symoff, stroff;
                     75:        register u_long symsize;
                     76:        register int nent, cc;
                     77:        int strsize, usemalloc = 0;
                     78:        struct nlist nbuf[1024];
                     79:        struct exec exec;
                     80:
                     81:        if (pread(fd, &exec, sizeof(exec), (off_t)0) != sizeof(exec) ||
                     82:            N_BADMAG(exec) || exec.a_syms == NULL)
                     83:                return (-1);
                     84:
                     85:        stroff = N_STROFF(exec);
                     86:        symoff = N_SYMOFF(exec);
                     87:        symsize = exec.a_syms;
                     88:
                     89:        /* Read in the size of the string table. */
                     90:        if (pread(fd, (void *)&strsize, sizeof(strsize), stroff) !=
                     91:            sizeof(strsize))
                     92:                return (-1);
                     93:        else
                     94:                stroff += sizeof(strsize);
                     95:
                     96:        /*
                     97:         * Read in the string table.  We try mmap, but that will fail
                     98:         * for /dev/ksyms so fall back on malloc.  Since OpenBSD's malloc(3)
                     99:         * returns memory to the system on free this does not cause bloat.
                    100:         */
                    101:        strsize -= sizeof(strsize);
                    102:        strtab = mmap(NULL, (size_t)strsize, PROT_READ, MAP_SHARED|MAP_FILE,
                    103:            fd, stroff);
                    104:        if (strtab == MAP_FAILED) {
                    105:                usemalloc = 1;
                    106:                if ((strtab = (char *)malloc(strsize)) == NULL)
                    107:                        return (-1);
                    108:                errno = EIO;
                    109:                if (pread(fd, strtab, strsize, stroff) != strsize) {
                    110:                        nent = -1;
                    111:                        goto aout_done;
                    112:                }
                    113:        }
                    114:
                    115:        /*
                    116:         * clean out any left-over information for all valid entries.
                    117:         * Type and value defined to be 0 if not found; historical
                    118:         * versions cleared other and desc as well.  Also figure out
                    119:         * the largest string length so don't read any more of the
                    120:         * string table than we have to.
                    121:         *
                    122:         * XXX clearing anything other than n_type and n_value violates
                    123:         * the semantics given in the man page.
                    124:         */
                    125:        nent = 0;
                    126:        for (p = list; !ISLAST(p); ++p) {
                    127:                p->n_type = 0;
                    128:                p->n_other = 0;
                    129:                p->n_desc = 0;
                    130:                p->n_value = 0;
                    131:                ++nent;
                    132:        }
                    133:
                    134:        while (symsize > 0) {
                    135:                cc = MIN(symsize, sizeof(nbuf));
                    136:                if (pread(fd, nbuf, cc, symoff) != cc)
                    137:                        break;
                    138:                symsize -= cc;
                    139:                symoff += cc;
                    140:                for (s = nbuf; cc > 0; ++s, cc -= sizeof(*s)) {
                    141:                        char *sname = strtab + s->n_un.n_strx - sizeof(int);
                    142:
                    143:                        if (s->n_un.n_strx == 0 || (s->n_type & N_STAB) != 0)
                    144:                                continue;
                    145:                        for (p = list; !ISLAST(p); p++) {
                    146:                                char *pname = p->n_un.n_name;
                    147:
                    148:                                if (*sname != '_' && *pname == '_')
                    149:                                        pname++;
                    150:                                if (!strcmp(sname, pname)) {
                    151:                                        p->n_value = s->n_value;
                    152:                                        p->n_type = s->n_type;
                    153:                                        p->n_desc = s->n_desc;
                    154:                                        p->n_other = s->n_other;
                    155:                                        if (--nent <= 0)
                    156:                                                break;
                    157:                                }
                    158:                        }
                    159:                }
                    160:        }
                    161: aout_done:
                    162:        if (usemalloc)
                    163:                free(strtab);
                    164:        else
                    165:                munmap(strtab, strsize);
                    166:        return (nent);
                    167: }
                    168: #endif /* _NLIST_DO_AOUT */
                    169:
                    170: #ifdef _NLIST_DO_ECOFF
                    171: #define check(off, size)       ((off < 0) || (off + size > mappedsize))
                    172: #define        BAD                     do { rv = -1; goto out; } while (0)
                    173: #define        BADUNMAP                do { rv = -1; goto unmap; } while (0)
                    174:
                    175: int
                    176: __ecoff_fdnlist(fd, list)
                    177:        register int fd;
                    178:        register struct nlist *list;
                    179: {
                    180:        struct nlist *p;
                    181:        struct ecoff_exechdr *exechdrp;
                    182:        struct ecoff_symhdr *symhdrp;
                    183:        struct ecoff_extsym *esyms;
                    184:        struct stat st;
                    185:        char *mappedfile;
                    186:        size_t mappedsize;
                    187:        u_long symhdroff, extstroff;
                    188:        u_int symhdrsize;
                    189:        int rv, nent;
                    190:        long i, nesyms;
                    191:
                    192:        rv = -3;
                    193:
                    194:        if (fstat(fd, &st) < 0)
                    195:                BAD;
                    196:        if (st.st_size > SIZE_T_MAX) {
                    197:                errno = EFBIG;
                    198:                BAD;
                    199:        }
                    200:        mappedsize = st.st_size;
                    201:        mappedfile = mmap(NULL, mappedsize, PROT_READ, MAP_SHARED|MAP_FILE,
                    202:            fd, 0);
                    203:        if (mappedfile == MAP_FAILED)
                    204:                BAD;
                    205:
                    206:        if (check(0, sizeof *exechdrp))
                    207:                BADUNMAP;
                    208:        exechdrp = (struct ecoff_exechdr *)&mappedfile[0];
                    209:
                    210:        if (ECOFF_BADMAG(exechdrp))
                    211:                BADUNMAP;
                    212:
                    213:        symhdroff = exechdrp->f.f_symptr;
                    214:        symhdrsize = exechdrp->f.f_nsyms;
                    215:
                    216:        if (check(symhdroff, sizeof *symhdrp) ||
                    217:            sizeof *symhdrp != symhdrsize)
                    218:                BADUNMAP;
                    219:        symhdrp = (struct ecoff_symhdr *)&mappedfile[symhdroff];
                    220:
                    221:        nesyms = symhdrp->esymMax;
                    222:        if (check(symhdrp->cbExtOffset, nesyms * sizeof *esyms))
                    223:                BADUNMAP;
                    224:        esyms = (struct ecoff_extsym *)&mappedfile[symhdrp->cbExtOffset];
                    225:        extstroff = symhdrp->cbSsExtOffset;
                    226:
                    227:        /*
                    228:         * clean out any left-over information for all valid entries.
                    229:         * Type and value defined to be 0 if not found; historical
                    230:         * versions cleared other and desc as well.
                    231:         *
                    232:         * XXX clearing anything other than n_type and n_value violates
                    233:         * the semantics given in the man page.
                    234:         */
                    235:        nent = 0;
                    236:        for (p = list; !ISLAST(p); ++p) {
                    237:                p->n_type = 0;
                    238:                p->n_other = 0;
                    239:                p->n_desc = 0;
                    240:                p->n_value = 0;
                    241:                ++nent;
                    242:        }
                    243:
                    244:        for (i = 0; i < nesyms; i++) {
                    245:                for (p = list; !ISLAST(p); p++) {
                    246:                        char *nlistname;
                    247:                        char *symtabname;
                    248:
                    249:                        nlistname = p->n_un.n_name;
                    250:                        if (*nlistname == '_')
                    251:                                nlistname++;
                    252:                        symtabname =
                    253:                            &mappedfile[extstroff + esyms[i].es_strindex];
                    254:
                    255:                        if (!strcmp(symtabname, nlistname)) {
                    256:                                p->n_value = esyms[i].es_value;
                    257:                                p->n_type = N_EXT;              /* XXX */
                    258:                                p->n_desc = 0;                  /* XXX */
                    259:                                p->n_other = 0;                 /* XXX */
                    260:                                if (--nent <= 0)
                    261:                                        break;
                    262:                        }
                    263:                }
                    264:        }
                    265:        rv = nent;
                    266:
                    267: unmap:
                    268:        munmap(mappedfile, mappedsize);
                    269: out:
                    270:        return (rv);
                    271: }
                    272: #endif /* _NLIST_DO_ECOFF */
                    273:
                    274: #ifdef _NLIST_DO_ELF
                    275: /*
                    276:  * __elf_is_okay__ - Determine if ehdr really
                    277:  * is ELF and valid for the target platform.
                    278:  *
                    279:  * WARNING:  This is NOT a ELF ABI function and
                    280:  * as such its use should be restricted.
                    281:  */
                    282: int
                    283: __elf_is_okay__(ehdr)
                    284:        register Elf_Ehdr *ehdr;
                    285: {
                    286:        register int retval = 0;
                    287:        /*
                    288:         * We need to check magic, class size, endianess,
                    289:         * and version before we look at the rest of the
                    290:         * Elf_Ehdr structure.  These few elements are
                    291:         * represented in a machine independent fashion.
                    292:         */
                    293:        if ((IS_ELF(*ehdr) || IS_OLF(*ehdr)) &&
                    294:            ehdr->e_ident[EI_CLASS] == ELF_TARG_CLASS &&
                    295:            ehdr->e_ident[EI_DATA] == ELF_TARG_DATA &&
                    296:            ehdr->e_ident[EI_VERSION] == ELF_TARG_VER) {
                    297:
                    298:                /* Now check the machine dependant header */
                    299:                if (ehdr->e_machine == ELF_TARG_MACH &&
                    300:                    ehdr->e_version == ELF_TARG_VER)
                    301:                        retval = 1;
                    302:        }
                    303:
                    304:        return retval;
                    305: }
                    306:
                    307: int
                    308: __elf_fdnlist(fd, list)
                    309:        register int fd;
                    310:        register struct nlist *list;
                    311: {
                    312:        register struct nlist *p;
                    313:        register caddr_t strtab;
                    314:        register Elf_Off symoff = 0, symstroff = 0;
                    315:        register Elf_Word symsize = 0, symstrsize = 0;
                    316:        register Elf_Sword nent, cc, i;
                    317:        Elf_Sym sbuf[1024];
                    318:        Elf_Sym *s;
                    319:        Elf_Ehdr ehdr;
                    320:        Elf_Shdr *shdr = NULL;
                    321:        Elf_Word shdr_size;
                    322:        struct stat st;
                    323:        int usemalloc = 0;
                    324:
                    325:        /* Make sure obj is OK */
                    326:        if (pread(fd, &ehdr, sizeof(Elf_Ehdr), (off_t)0) != sizeof(Elf_Ehdr) ||
                    327:            /* !__elf_is_okay__(&ehdr) || */ fstat(fd, &st) < 0)
                    328:                return (-1);
                    329:
                    330:        /* calculate section header table size */
                    331:        shdr_size = ehdr.e_shentsize * ehdr.e_shnum;
                    332:
                    333:        /* mmap section header table */
                    334:        shdr = (Elf_Shdr *)mmap(NULL, (size_t)shdr_size, PROT_READ,
                    335:            MAP_SHARED|MAP_FILE, fd, (off_t) ehdr.e_shoff);
                    336:        if (shdr == MAP_FAILED) {
                    337:                usemalloc = 1;
                    338:                if ((shdr = malloc(shdr_size)) == NULL)
                    339:                        return (-1);
                    340:                if (pread(fd, shdr, shdr_size, ehdr.e_shoff) != shdr_size) {
                    341:                        free(shdr);
                    342:                        return (-1);
                    343:                }
                    344:        }
                    345:
                    346:        /*
                    347:         * Find the symbol table entry and its corresponding
                    348:         * string table entry.  Version 1.1 of the ABI states
                    349:         * that there is only one symbol table but that this
                    350:         * could change in the future.
                    351:         */
                    352:        for (i = 0; i < ehdr.e_shnum; i++) {
                    353:                if (shdr[i].sh_type == SHT_SYMTAB) {
                    354:                        symoff = shdr[i].sh_offset;
                    355:                        symsize = shdr[i].sh_size;
                    356:                        symstroff = shdr[shdr[i].sh_link].sh_offset;
                    357:                        symstrsize = shdr[shdr[i].sh_link].sh_size;
                    358:                        break;
                    359:                }
                    360:        }
                    361:
                    362:        /* Flush the section header table */
                    363:        if (usemalloc)
                    364:                free(shdr);
                    365:        else
                    366:                munmap((caddr_t)shdr, shdr_size);
                    367:
                    368:        /*
                    369:         * Map string table into our address space.  This gives us
                    370:         * an easy way to randomly access all the strings, without
                    371:         * making the memory allocation permanent as with malloc/free
                    372:         * (i.e., munmap will return it to the system).
                    373:         */
                    374:        if (usemalloc) {
                    375:                if ((strtab = malloc(symstrsize)) == NULL)
                    376:                        return (-1);
                    377:                if (pread(fd, strtab, symstrsize, symstroff) != symstrsize) {
                    378:                        free(strtab);
                    379:                        return (-1);
                    380:                }
                    381:        } else {
                    382:                strtab = mmap(NULL, (size_t)symstrsize, PROT_READ,
                    383:                    MAP_SHARED|MAP_FILE, fd, (off_t) symstroff);
                    384:                if (strtab == MAP_FAILED)
                    385:                        return (-1);
                    386:        }
                    387:        /*
                    388:         * clean out any left-over information for all valid entries.
                    389:         * Type and value defined to be 0 if not found; historical
                    390:         * versions cleared other and desc as well.  Also figure out
                    391:         * the largest string length so don't read any more of the
                    392:         * string table than we have to.
                    393:         *
                    394:         * XXX clearing anything other than n_type and n_value violates
                    395:         * the semantics given in the man page.
                    396:         */
                    397:        nent = 0;
                    398:        for (p = list; !ISLAST(p); ++p) {
                    399:                p->n_type = 0;
                    400:                p->n_other = 0;
                    401:                p->n_desc = 0;
                    402:                p->n_value = 0;
                    403:                ++nent;
                    404:        }
                    405:
                    406:        /* Don't process any further if object is stripped. */
                    407:        /* ELFism - dunno if stripped by looking at header */
                    408:        if (symoff == 0)
                    409:                goto elf_done;
                    410:
                    411:        while (symsize > 0) {
                    412:                cc = MIN(symsize, sizeof(sbuf));
                    413:                if (pread(fd, sbuf, cc, symoff) != cc)
                    414:                        break;
                    415:                symsize -= cc;
                    416:                symoff += cc;
                    417:                for (s = sbuf; cc > 0; ++s, cc -= sizeof(*s)) {
                    418:                        int soff = s->st_name;
                    419:
                    420:                        if (soff == 0)
                    421:                                continue;
                    422:                        for (p = list; !ISLAST(p); p++) {
                    423:                                char *sym;
                    424:
                    425:                                /*
                    426:                                 * First we check for the symbol as it was
                    427:                                 * provided by the user. If that fails,
                    428:                                 * skip the first char if it's an '_' and
                    429:                                 * try again.
                    430:                                 * XXX - What do we do when the user really
                    431:                                 *       wants '_foo' and the are symbols
                    432:                                 *       for both 'foo' and '_foo' in the
                    433:                                 *       table and 'foo' is first?
                    434:                                 */
                    435:                                sym = p->n_un.n_name;
                    436:                                if (strcmp(&strtab[soff], sym) != 0 &&
                    437:                                    ((sym[0] == '_') &&
                    438:                                     strcmp(&strtab[soff], sym + 1) != 0))
                    439:                                        continue;
                    440:
                    441:                                p->n_value = s->st_value;
                    442:
                    443:                                /* XXX - type conversion */
                    444:                                /*       is pretty rude. */
                    445:                                switch(ELF_ST_TYPE(s->st_info)) {
                    446:                                case STT_NOTYPE:
                    447:                                        switch (s->st_shndx) {
                    448:                                        case SHN_UNDEF:
                    449:                                                p->n_type = N_UNDF;
                    450:                                                break;
                    451:                                        case SHN_ABS:
                    452:                                                p->n_type = N_ABS;
                    453:                                                break;
                    454:                                        case SHN_COMMON:
                    455:                                                p->n_type = N_COMM;
                    456:                                                break;
                    457:                                        default:
                    458:                                                p->n_type = N_COMM | N_EXT;
                    459:                                                break;
                    460:                                        }
                    461:                                        break;
                    462:                                case STT_OBJECT:
                    463:                                        p->n_type = N_DATA;
                    464:                                        break;
                    465:                                case STT_FUNC:
                    466:                                        p->n_type = N_TEXT;
                    467:                                        break;
                    468:                                case STT_FILE:
                    469:                                        p->n_type = N_FN;
                    470:                                        break;
                    471:                                }
                    472:                                if (ELF_ST_BIND(s->st_info) ==
                    473:                                    STB_LOCAL)
                    474:                                        p->n_type = N_EXT;
                    475:                                p->n_desc = 0;
                    476:                                p->n_other = 0;
                    477:                                if (--nent <= 0)
                    478:                                        break;
                    479:                        }
                    480:                }
                    481:        }
                    482: elf_done:
                    483:        if (usemalloc)
                    484:                free(strtab);
                    485:        else
                    486:                munmap(strtab, symstrsize);
                    487:        return (nent);
                    488: }
                    489: #endif /* _NLIST_DO_ELF */
                    490:
                    491:
                    492: static struct nlist_handlers {
                    493:        int     (*fn)(int fd, struct nlist *list);
                    494: } nlist_fn[] = {
                    495: #ifdef _NLIST_DO_AOUT
                    496:        { __aout_fdnlist },
                    497: #endif
                    498: #ifdef _NLIST_DO_ELF
                    499:        { __elf_fdnlist },
                    500: #endif
                    501: #ifdef _NLIST_DO_ECOFF
                    502:        { __ecoff_fdnlist },
                    503: #endif
                    504: };
                    505:
                    506: int
                    507: __fdnlist(fd, list)
                    508:        register int fd;
                    509:        register struct nlist *list;
                    510: {
                    511:        int n = -1, i;
                    512:
                    513:        for (i = 0; i < sizeof(nlist_fn)/sizeof(nlist_fn[0]); i++) {
                    514:                n = (nlist_fn[i].fn)(fd, list);
                    515:                if (n != -1)
                    516:                        break;
                    517:        }
                    518:        return (n);
                    519: }
                    520:
                    521:
                    522: int
                    523: nlist(name, list)
                    524:        const char *name;
                    525:        struct nlist *list;
                    526: {
                    527:        int fd, n;
                    528:
                    529:        fd = open(name, O_RDONLY, 0);
                    530:        if (fd < 0)
                    531:                return (-1);
                    532:        n = __fdnlist(fd, list);
                    533:        (void)close(fd);
                    534:        return (n);
                    535: }

CVSweb