[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     ! 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