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

Annotation of src/usr.bin/file/readelf.c, Revision 1.5

1.5     ! ian         1: /*
        !             2:  * ELF routines for the file command.
        !             3:  *
        !             4:  * Copyright (c) Ian F. Darwin 1986-1995.
        !             5:  * Software written by Ian F. Darwin and others;
        !             6:  * maintained 1995-present by Christos Zoulas and others.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice immediately at the beginning of the file, without modification,
        !            13:  *    this list of conditions, and the following disclaimer.
        !            14:  * 2. Redistributions in binary form must reproduce the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer in the
        !            16:  *    documentation and/or other materials provided with the distribution.
        !            17:  * 3. All advertising materials mentioning features or use of this software
        !            18:  *    must display the following acknowledgement:
        !            19:  *    This product includes software developed by Ian F. Darwin and others.
        !            20:  * 4. The name of the author may not be used to endorse or promote products
        !            21:  *    derived from this software without specific prior written permission.
        !            22:  *
        !            23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
        !            24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            26:  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
        !            27:  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            33:  * SUCH DAMAGE.
        !            34:  */
        !            35:
1.4       ian        36: #include "file.h"
1.1       millert    37:
                     38: #ifdef BUILTIN_ELF
                     39: #include <string.h>
                     40: #include <ctype.h>
                     41: #include <stdlib.h>
1.4       ian        42: #ifdef HAVE_UNISTD_H
1.1       millert    43: #include <unistd.h>
1.4       ian        44: #endif
1.1       millert    45:
                     46: #include "readelf.h"
1.4       ian        47:
                     48: #ifndef lint
1.5     ! ian        49: static char *RCSID = "@(#)$Id: readelf.c,v 1.4 2003/03/03 22:24:08 ian Exp $";
1.4       ian        50: #endif
                     51:
                     52: #ifdef ELFCORE
                     53: static void dophn_core(int, int, int, off_t, int, size_t);
                     54: #endif
                     55: static void dophn_exec(int, int, int, off_t, int, size_t);
                     56: static void doshn(int, int, int, off_t, int, size_t);
                     57:
                     58: static uint16_t getu16(int, uint16_t);
                     59: static uint32_t getu32(int, uint32_t);
                     60: static uint64_t getu64(int, uint64_t);
                     61:
                     62: static uint16_t
                     63: getu16(int swap, uint16_t value)
                     64: {
                     65:        union {
                     66:                uint16_t ui;
                     67:                char c[2];
                     68:        } retval, tmpval;
                     69:
                     70:        if (swap) {
                     71:                tmpval.ui = value;
                     72:
                     73:                retval.c[0] = tmpval.c[1];
                     74:                retval.c[1] = tmpval.c[0];
                     75:
                     76:                return retval.ui;
                     77:        } else
                     78:                return value;
                     79: }
                     80:
                     81: static uint32_t
                     82: getu32(int swap, uint32_t value)
                     83: {
                     84:        union {
                     85:                uint32_t ui;
                     86:                char c[4];
                     87:        } retval, tmpval;
                     88:
                     89:        if (swap) {
                     90:                tmpval.ui = value;
                     91:
                     92:                retval.c[0] = tmpval.c[3];
                     93:                retval.c[1] = tmpval.c[2];
                     94:                retval.c[2] = tmpval.c[1];
                     95:                retval.c[3] = tmpval.c[0];
                     96:
                     97:                return retval.ui;
                     98:        } else
                     99:                return value;
                    100: }
                    101:
                    102: static uint64_t
                    103: getu64(int swap, uint64_t value)
                    104: {
                    105:        union {
                    106:                uint64_t ui;
                    107:                char c[8];
                    108:        } retval, tmpval;
                    109:
                    110:        if (swap) {
                    111:                tmpval.ui = value;
                    112:
                    113:                retval.c[0] = tmpval.c[7];
                    114:                retval.c[1] = tmpval.c[6];
                    115:                retval.c[2] = tmpval.c[5];
                    116:                retval.c[3] = tmpval.c[4];
                    117:                retval.c[4] = tmpval.c[3];
                    118:                retval.c[5] = tmpval.c[2];
                    119:                retval.c[6] = tmpval.c[1];
                    120:                retval.c[7] = tmpval.c[0];
                    121:
                    122:                return retval.ui;
                    123:        } else
                    124:                return value;
                    125: }
                    126:
                    127: #define sh_addr                (class == ELFCLASS32            \
                    128:                         ? (void *) &sh32               \
                    129:                         : (void *) &sh64)
                    130: #define sh_size                (class == ELFCLASS32            \
                    131:                         ? sizeof sh32                  \
                    132:                         : sizeof sh64)
                    133: #define shs_type       (class == ELFCLASS32            \
                    134:                         ? getu32(swap, sh32.sh_type)   \
                    135:                         : getu32(swap, sh64.sh_type))
                    136: #define ph_addr                (class == ELFCLASS32            \
                    137:                         ? (void *) &ph32               \
                    138:                         : (void *) &ph64)
                    139: #define ph_size                (class == ELFCLASS32            \
                    140:                         ? sizeof ph32                  \
                    141:                         : sizeof ph64)
                    142: #define ph_type                (class == ELFCLASS32            \
                    143:                         ? getu32(swap, ph32.p_type)    \
                    144:                         : getu32(swap, ph64.p_type))
                    145: #define ph_offset      (class == ELFCLASS32            \
                    146:                         ? getu32(swap, ph32.p_offset)  \
                    147:                         : getu64(swap, ph64.p_offset))
                    148: #define ph_align       (class == ELFCLASS32            \
                    149:                         ? (ph32.p_align ? getu32(swap, ph32.p_align) : 4) \
                    150:                         : (ph64.p_align ? getu64(swap, ph64.p_align) : 4))
                    151: #define nh_size                (class == ELFCLASS32            \
                    152:                         ? sizeof *nh32                 \
                    153:                         : sizeof *nh64)
                    154: #define nh_type                (class == ELFCLASS32            \
                    155:                         ? getu32(swap, nh32->n_type)   \
                    156:                         : getu32(swap, nh64->n_type))
                    157: #define nh_namesz      (class == ELFCLASS32            \
                    158:                         ? getu32(swap, nh32->n_namesz) \
                    159:                         : getu32(swap, nh64->n_namesz))
                    160: #define nh_descsz      (class == ELFCLASS32            \
                    161:                         ? getu32(swap, nh32->n_descsz) \
                    162:                         : getu32(swap, nh64->n_descsz))
                    163: #define prpsoffsets(i) (class == ELFCLASS32            \
                    164:                         ? prpsoffsets32[i]             \
                    165:                         : prpsoffsets64[i])
1.1       millert   166:
                    167: static void
1.4       ian       168: doshn(int class, int swap, int fd, off_t off, int num, size_t size)
1.1       millert   169: {
1.4       ian       170:        Elf32_Shdr sh32;
                    171:        Elf64_Shdr sh64;
                    172:
                    173:        if (size != sh_size)
                    174:                error("corrupted section header size.\n");
1.1       millert   175:
                    176:        if (lseek(fd, off, SEEK_SET) == -1)
1.4       ian       177:                error("lseek failed (%s).\n", strerror(errno));
1.1       millert   178:
                    179:        for ( ; num; num--) {
1.4       ian       180:                if (read(fd, sh_addr, sh_size) == -1)
                    181:                        error("read failed (%s).\n", strerror(errno));
                    182:                if (shs_type == SHT_SYMTAB /* || shs_type == SHT_DYNSYM */) {
1.1       millert   183:                        (void) printf (", not stripped");
                    184:                        return;
                    185:                }
                    186:        }
                    187:        (void) printf (", stripped");
                    188: }
                    189:
                    190: /*
                    191:  * Look through the program headers of an executable image, searching
                    192:  * for a PT_INTERP section; if one is found, it's dynamically linked,
                    193:  * otherwise it's statically linked.
                    194:  */
                    195: static void
1.4       ian       196: dophn_exec(int class, int swap, int fd, off_t off, int num, size_t size)
1.1       millert   197: {
1.4       ian       198:        Elf32_Phdr ph32;
                    199:        Elf32_Nhdr *nh32 = NULL;
                    200:        Elf64_Phdr ph64;
                    201:        Elf64_Nhdr *nh64 = NULL;
                    202:        char *linking_style = "statically";
                    203:        char *shared_libraries = "";
                    204:        char nbuf[BUFSIZ];
                    205:        int bufsize;
                    206:        size_t offset, nameoffset;
                    207:        off_t savedoffset;
1.1       millert   208:
1.4       ian       209:        if (size != ph_size)
                    210:                error("corrupted program header size.\n");
1.1       millert   211:        if (lseek(fd, off, SEEK_SET) == -1)
1.4       ian       212:                error("lseek failed (%s).\n", strerror(errno));
1.1       millert   213:
                    214:        for ( ; num; num--) {
1.4       ian       215:                if (read(fd, ph_addr, ph_size) == -1)
                    216:                        error("read failed (%s).\n", strerror(errno));
                    217:                if ((savedoffset = lseek(fd, 0, SEEK_CUR)) == -1)
                    218:                        error("lseek failed (%s).\n", strerror(errno));
                    219:
                    220:                switch (ph_type) {
                    221:                case PT_DYNAMIC:
                    222:                        linking_style = "dynamically";
                    223:                        break;
                    224:                case PT_INTERP:
                    225:                        shared_libraries = " (uses shared libs)";
                    226:                        break;
                    227:                case PT_NOTE:
1.1       millert   228:                        /*
1.4       ian       229:                         * This is a PT_NOTE section; loop through all the notes
                    230:                         * in the section.
1.1       millert   231:                         */
1.4       ian       232:                        if (lseek(fd, (off_t) ph_offset, SEEK_SET) == -1)
                    233:                                error("lseek failed (%s).\n", strerror(errno));
                    234:                        bufsize = read(fd, nbuf, sizeof(nbuf));
                    235:                        if (bufsize == -1)
                    236:                                error(": " "read failed (%s).\n",
                    237:                                    strerror(errno));
                    238:                        offset = 0;
                    239:                        for (;;) {
                    240:                                if (offset >= bufsize)
                    241:                                        break;
                    242:                                if (class == ELFCLASS32)
                    243:                                        nh32 = (Elf32_Nhdr *)&nbuf[offset];
                    244:                                else
                    245:                                        nh64 = (Elf64_Nhdr *)&nbuf[offset];
                    246:                                offset += nh_size;
                    247:
                    248:                                if (offset + nh_namesz >= bufsize) {
                    249:                                        /*
                    250:                                         * We're past the end of the buffer.
                    251:                                         */
                    252:                                        break;
                    253:                                }
                    254:
                    255:                                nameoffset = offset;
                    256:                                offset += nh_namesz;
                    257:                                offset = ((offset+ph_align-1)/ph_align)*ph_align;
                    258:
                    259:                                if ((nh_namesz == 0) && (nh_descsz == 0)) {
                    260:                                        /*
                    261:                                         * We're out of note headers.
                    262:                                         */
                    263:                                        break;
                    264:                                }
                    265:
                    266:                                if (offset + nh_descsz >= bufsize)
                    267:                                        break;
                    268:
                    269:                                if (nh_namesz == 4 &&
                    270:                                    strcmp(&nbuf[nameoffset], "GNU") == 0 &&
                    271:                                    nh_type == NT_GNU_VERSION &&
                    272:                                    nh_descsz == 16) {
                    273:                                        uint32_t *desc =
                    274:                                            (uint32_t *)&nbuf[offset];
                    275:
                    276:                                        printf(", for GNU/");
                    277:                                        switch (getu32(swap, desc[0])) {
                    278:                                        case GNU_OS_LINUX:
                    279:                                                printf("Linux");
                    280:                                                break;
                    281:                                        case GNU_OS_HURD:
                    282:                                                printf("Hurd");
                    283:                                                break;
                    284:                                        case GNU_OS_SOLARIS:
                    285:                                                printf("Solaris");
                    286:                                                break;
                    287:                                        default:
                    288:                                                printf("<unknown>");
                    289:                                        }
                    290:                                        printf(" %d.%d.%d",
                    291:                                            getu32(swap, desc[1]),
                    292:                                            getu32(swap, desc[2]),
                    293:                                            getu32(swap, desc[3]));
                    294:                                }
                    295:
                    296:                                if (nh_namesz == 7 &&
                    297:                                    strcmp(&nbuf[nameoffset], "NetBSD") == 0 &&
                    298:                                    nh_type == NT_NETBSD_VERSION &&
                    299:                                    nh_descsz == 4) {
                    300:                                        printf(", for NetBSD");
                    301:                                        /*
                    302:                                         * Version number is stuck at 199905,
                    303:                                         * and hence is basically content-free.
                    304:                                         */
                    305:                                }
                    306:
                    307:                                if (nh_namesz == 8 &&
                    308:                                    strcmp(&nbuf[nameoffset], "FreeBSD") == 0 &&
                    309:                                    nh_type == NT_FREEBSD_VERSION &&
                    310:                                    nh_descsz == 4) {
                    311:                                        uint32_t desc = getu32(swap,
                    312:                                            *(uint32_t *)&nbuf[offset]);
                    313:                                        printf(", for FreeBSD");
                    314:                                        /*
                    315:                                         * Contents is __FreeBSD_version,
                    316:                                         * whose relation to OS versions is
                    317:                                         * defined by a huge table in the
                    318:                                         * Porters' Handbook.  Happily, the
                    319:                                         * first three digits are the version
                    320:                                         * number, at least in versions of
                    321:                                         * FreeBSD that use this note.
                    322:                                         */
                    323:
                    324:                                        printf(" %d.%d", desc / 100000,
                    325:                                            desc / 10000 % 10);
                    326:                                        if (desc / 1000 % 10 > 0)
                    327:                                                printf(".%d",
                    328:                                                    desc / 1000 % 10);
                    329:                                }
                    330:
                    331:                                if (nh_namesz == 8 &&
                    332:                                    strcmp(&nbuf[nameoffset], "OpenBSD") == 0 &&
                    333:                                    nh_type == NT_OPENBSD_VERSION &&
                    334:                                    nh_descsz == 4) {
                    335:                                        printf(", for OpenBSD");
                    336:                                        /* Content of note is always 0 */
                    337:                                }
                    338:                        }
                    339:                        if ((lseek(fd, savedoffset + offset, SEEK_SET)) == -1)
                    340:                                error("lseek failed (%s).\n", strerror(errno));
                    341:                        break;
1.1       millert   342:                }
                    343:        }
1.4       ian       344:        printf(", %s linked%s", linking_style, shared_libraries);
1.1       millert   345: }
                    346:
1.4       ian       347: #ifdef ELFCORE
                    348: size_t prpsoffsets32[] = {
                    349:        8,              /* FreeBSD */
                    350:        28,             /* Linux 2.0.36 */
                    351:        32,             /* Linux (I forget which kernel version) */
                    352:        84,             /* SunOS 5.x */
                    353: };
                    354:
                    355: size_t prpsoffsets64[] = {
                    356:        120,            /* SunOS 5.x, 64-bit */
1.1       millert   357: };
                    358:
1.4       ian       359: #define        NOFFSETS32      (sizeof prpsoffsets32 / sizeof prpsoffsets32[0])
                    360: #define NOFFSETS64     (sizeof prpsoffsets64 / sizeof prpsoffsets64[0])
                    361:
                    362: #define NOFFSETS       (class == ELFCLASS32 ? NOFFSETS32 : NOFFSETS64)
1.1       millert   363:
                    364: /*
                    365:  * Look through the program headers of an executable image, searching
1.4       ian       366:  * for a PT_NOTE section of type NT_PRPSINFO, with a name "CORE" or
                    367:  * "FreeBSD"; if one is found, try looking in various places in its
                    368:  * contents for a 16-character string containing only printable
                    369:  * characters - if found, that string should be the name of the program
                    370:  * that dropped core.  Note: right after that 16-character string is,
                    371:  * at least in SunOS 5.x (and possibly other SVR4-flavored systems) and
                    372:  * Linux, a longer string (80 characters, in 5.x, probably other
                    373:  * SVR4-flavored systems, and Linux) containing the start of the
                    374:  * command line for that program.
                    375:  *
                    376:  * The signal number probably appears in a section of type NT_PRSTATUS,
                    377:  * but that's also rather OS-dependent, in ways that are harder to
                    378:  * dissect with heuristics, so I'm not bothering with the signal number.
                    379:  * (I suppose the signal number could be of interest in situations where
                    380:  * you don't have the binary of the program that dropped core; if you
                    381:  * *do* have that binary, the debugger will probably tell you what
                    382:  * signal it was.)
1.1       millert   383:  */
1.4       ian       384:
                    385: #define        OS_STYLE_SVR4           0
                    386: #define        OS_STYLE_FREEBSD        1
                    387: #define        OS_STYLE_NETBSD         2
                    388:
                    389: static const char *os_style_names[] = {
                    390:        "SVR4",
                    391:        "FreeBSD",
                    392:        "NetBSD",
                    393: };
                    394:
1.1       millert   395: static void
1.4       ian       396: dophn_core(int class, int swap, int fd, off_t off, int num, size_t size)
1.1       millert   397: {
1.4       ian       398:        Elf32_Phdr ph32;
                    399:        Elf32_Nhdr *nh32 = NULL;
                    400:        Elf64_Phdr ph64;
                    401:        Elf64_Nhdr *nh64 = NULL;
                    402:        size_t offset, nameoffset, noffset, reloffset;
1.1       millert   403:        unsigned char c;
                    404:        int i, j;
                    405:        char nbuf[BUFSIZ];
                    406:        int bufsize;
1.4       ian       407:        int os_style = -1;
1.1       millert   408:
1.4       ian       409:        if (size != ph_size)
                    410:                error("corrupted program header size.\n");
                    411:        /*
                    412:         * Loop through all the program headers.
                    413:         */
1.1       millert   414:        for ( ; num; num--) {
                    415:                if (lseek(fd, off, SEEK_SET) == -1)
1.4       ian       416:                        error("lseek failed (%s).\n", strerror(errno));
                    417:                if (read(fd, ph_addr, ph_size) == -1)
                    418:                        error("read failed (%s).\n", strerror(errno));
1.1       millert   419:                off += size;
1.4       ian       420:                if (ph_type != PT_NOTE)
1.1       millert   421:                        continue;
1.4       ian       422:
                    423:                /*
                    424:                 * This is a PT_NOTE section; loop through all the notes
                    425:                 * in the section.
                    426:                 */
                    427:                if (lseek(fd, (off_t) ph_offset, SEEK_SET) == -1)
                    428:                        error("lseek failed (%s).\n", strerror(errno));
1.1       millert   429:                bufsize = read(fd, nbuf, BUFSIZ);
                    430:                if (bufsize == -1)
1.4       ian       431:                        error(": " "read failed (%s).\n", strerror(errno));
1.1       millert   432:                offset = 0;
                    433:                for (;;) {
                    434:                        if (offset >= bufsize)
                    435:                                break;
1.4       ian       436:                        if (class == ELFCLASS32)
                    437:                                nh32 = (Elf32_Nhdr *)&nbuf[offset];
                    438:                        else
                    439:                                nh64 = (Elf64_Nhdr *)&nbuf[offset];
                    440:                        offset += nh_size;
1.1       millert   441:
                    442:                        /*
1.4       ian       443:                         * Check whether this note has the name "CORE" or
                    444:                         * "FreeBSD", or "NetBSD-CORE".
1.1       millert   445:                         */
1.4       ian       446:                        if (offset + nh_namesz >= bufsize) {
1.1       millert   447:                                /*
                    448:                                 * We're past the end of the buffer.
                    449:                                 */
                    450:                                break;
                    451:                        }
1.4       ian       452:
                    453:                        nameoffset = offset;
                    454:                        offset += nh_namesz;
1.1       millert   455:                        offset = ((offset + 3)/4)*4;
                    456:
                    457:                        /*
1.4       ian       458:                         * Sigh.  The 2.0.36 kernel in Debian 2.1, at
                    459:                         * least, doesn't correctly implement name
                    460:                         * sections, in core dumps, as specified by
                    461:                         * the "Program Linking" section of "UNIX(R) System
                    462:                         * V Release 4 Programmer's Guide: ANSI C and
                    463:                         * Programming Support Tools", because my copy
                    464:                         * clearly says "The first 'namesz' bytes in 'name'
                    465:                         * contain a *null-terminated* [emphasis mine]
                    466:                         * character representation of the entry's owner
                    467:                         * or originator", but the 2.0.36 kernel code
                    468:                         * doesn't include the terminating null in the
                    469:                         * name....
1.1       millert   470:                         */
1.4       ian       471:                        if (os_style == -1) {
                    472:                                if ((nh_namesz == 4 &&
                    473:                                     strncmp(&nbuf[nameoffset],
                    474:                                            "CORE", 4) == 0) ||
                    475:                                    (nh_namesz == 5 &&
                    476:                                     strcmp(&nbuf[nameoffset],
                    477:                                            "CORE") == 0)) {
                    478:                                        os_style = OS_STYLE_SVR4;
                    479:                                } else
                    480:                                if ((nh_namesz == 8 &&
                    481:                                     strcmp(&nbuf[nameoffset],
                    482:                                            "FreeBSD") == 0)) {
                    483:                                        os_style = OS_STYLE_FREEBSD;
                    484:                                } else
                    485:                                if ((nh_namesz >= 11 &&
                    486:                                     strncmp(&nbuf[nameoffset],
                    487:                                             "NetBSD-CORE", 11) == 0)) {
                    488:                                        os_style = OS_STYLE_NETBSD;
                    489:                                } else
                    490:                                        continue;
                    491:                                printf(", %s-style", os_style_names[os_style]);
                    492:                        }
                    493:
                    494:                        if (os_style == OS_STYLE_NETBSD &&
                    495:                            nh_type == NT_NETBSD_CORE_PROCINFO) {
                    496:                                uint32_t signo;
                    497:
                    498:                                /*
                    499:                                 * Extract the program name.  It is at
                    500:                                 * offset 0x7c, and is up to 32-bytes,
                    501:                                 * including the terminating NUL.
                    502:                                 */
                    503:                                printf(", from '%.31s'", &nbuf[offset + 0x7c]);
                    504:
                    505:                                /*
                    506:                                 * Extract the signal number.  It is at
                    507:                                 * offset 0x08.
                    508:                                 */
                    509:                                memcpy(&signo, &nbuf[offset + 0x08],
                    510:                                    sizeof(signo));
                    511:                                printf(" (signal %u)", getu32(swap, signo));
                    512:                        } else
                    513:                        if (os_style != OS_STYLE_NETBSD &&
                    514:                            nh_type == NT_PRPSINFO) {
                    515:                                /*
                    516:                                 * Extract the program name.  We assume
                    517:                                 * it to be 16 characters (that's what it
                    518:                                 * is in SunOS 5.x and Linux).
                    519:                                 *
                    520:                                 * Unfortunately, it's at a different offset
                    521:                                 * in varous OSes, so try multiple offsets.
                    522:                                 * If the characters aren't all printable,
                    523:                                 * reject it.
                    524:                                 */
                    525:                                for (i = 0; i < NOFFSETS; i++) {
                    526:                                        reloffset = prpsoffsets(i);
                    527:                                        noffset = offset + reloffset;
                    528:                                        for (j = 0; j < 16;
                    529:                                            j++, noffset++, reloffset++) {
                    530:                                                /*
                    531:                                                 * Make sure we're not past
                    532:                                                 * the end of the buffer; if
                    533:                                                 * we are, just give up.
                    534:                                                 */
                    535:                                                if (noffset >= bufsize)
                    536:                                                        goto tryanother;
                    537:
                    538:                                                /*
                    539:                                                 * Make sure we're not past
                    540:                                                 * the end of the contents;
                    541:                                                 * if we are, this obviously
                    542:                                                 * isn't the right offset.
                    543:                                                 */
                    544:                                                if (reloffset >= nh_descsz)
                    545:                                                        goto tryanother;
                    546:
                    547:                                                c = nbuf[noffset];
                    548:                                                if (c == '\0') {
                    549:                                                        /*
                    550:                                                         * A '\0' at the
                    551:                                                         * beginning is
                    552:                                                         * obviously wrong.
                    553:                                                         * Any other '\0'
                    554:                                                         * means we're done.
                    555:                                                         */
                    556:                                                        if (j == 0)
                    557:                                                                goto tryanother;
                    558:                                                        else
                    559:                                                                break;
                    560:                                                } else {
                    561:                                                        /*
                    562:                                                         * A nonprintable
                    563:                                                         * character is also
                    564:                                                         * wrong.
                    565:                                                         */
                    566: #define isquote(c) (strchr("'\"`", (c)) != NULL)
                    567:                                                        if (!isprint(c) ||
                    568:                                                             isquote(c))
                    569:                                                                goto tryanother;
                    570:                                                }
                    571:                                        }
1.1       millert   572:
                    573:                                        /*
1.4       ian       574:                                         * Well, that worked.
1.1       millert   575:                                         */
1.4       ian       576:                                        printf(", from '%.16s'",
                    577:                                            &nbuf[offset + prpsoffsets(i)]);
                    578:                                        break;
1.1       millert   579:
1.4       ian       580:                                tryanother:
                    581:                                        ;
1.1       millert   582:                                }
1.4       ian       583:                                break;
1.1       millert   584:                        }
1.4       ian       585:                        offset += nh_descsz;
1.1       millert   586:                        offset = ((offset + 3)/4)*4;
                    587:                }
                    588:        }
                    589: }
1.4       ian       590: #endif
1.1       millert   591:
                    592: void
1.4       ian       593: tryelf(int fd, unsigned char *buf, int nbytes)
1.1       millert   594: {
                    595:        union {
1.3       itojun    596:                int32_t l;
                    597:                char c[sizeof (int32_t)];
1.1       millert   598:        } u;
1.4       ian       599:        int class;
                    600:        int swap;
                    601:
                    602:        /*
                    603:         * If we can't seek, it must be a pipe, socket or fifo.
                    604:         */
                    605:        if((lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) && (errno == ESPIPE))
                    606:                fd = pipe2file(fd, buf, nbytes);
1.1       millert   607:
                    608:        /*
                    609:         * ELF executables have multiple section headers in arbitrary
                    610:         * file locations and thus file(1) cannot determine it from easily.
                    611:         * Instead we traverse thru all section headers until a symbol table
                    612:         * one is found or else the binary is stripped.
                    613:         */
1.4       ian       614:        if (buf[EI_MAG0] != ELFMAG0
                    615:            || (buf[EI_MAG1] != ELFMAG1 && buf[EI_MAG1] != OLFMAG1)
1.1       millert   616:            || buf[EI_MAG2] != ELFMAG2 || buf[EI_MAG3] != ELFMAG3)
                    617:            return;
                    618:
                    619:
1.4       ian       620:        class = buf[4];
                    621:
                    622:        if (class == ELFCLASS32) {
1.1       millert   623:                Elf32_Ehdr elfhdr;
                    624:                if (nbytes <= sizeof (Elf32_Ehdr))
                    625:                        return;
                    626:
                    627:
                    628:                u.l = 1;
                    629:                (void) memcpy(&elfhdr, buf, sizeof elfhdr);
1.4       ian       630:                swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[5];
                    631:
                    632:                if (getu16(swap, elfhdr.e_type) == ET_CORE)
                    633: #ifdef ELFCORE
                    634:                        dophn_core(class, swap,
                    635:                                   fd,
                    636:                                   getu32(swap, elfhdr.e_phoff),
                    637:                                   getu16(swap, elfhdr.e_phnum),
                    638:                                   getu16(swap, elfhdr.e_phentsize));
                    639: #else
                    640:                        ;
                    641: #endif
                    642:                else {
                    643:                        if (getu16(swap, elfhdr.e_type) == ET_EXEC) {
                    644:                                dophn_exec(class, swap,
                    645:                                           fd,
                    646:                                           getu32(swap, elfhdr.e_phoff),
                    647:                                           getu16(swap, elfhdr.e_phnum),
                    648:                                           getu16(swap, elfhdr.e_phentsize));
1.1       millert   649:                        }
1.4       ian       650:                        doshn(class, swap,
                    651:                              fd,
                    652:                              getu32(swap, elfhdr.e_shoff),
                    653:                              getu16(swap, elfhdr.e_shnum),
                    654:                              getu16(swap, elfhdr.e_shentsize));
1.1       millert   655:                }
                    656:                return;
                    657:        }
                    658:
1.4       ian       659:         if (class == ELFCLASS64) {
1.1       millert   660:                Elf64_Ehdr elfhdr;
                    661:                if (nbytes <= sizeof (Elf64_Ehdr))
                    662:                        return;
                    663:
                    664:
                    665:                u.l = 1;
                    666:                (void) memcpy(&elfhdr, buf, sizeof elfhdr);
1.4       ian       667:                swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[5];
1.1       millert   668:
1.4       ian       669:                if (getu16(swap, elfhdr.e_type) == ET_CORE)
                    670: #ifdef ELFCORE
                    671:                        dophn_core(class, swap,
                    672:                                   fd,
                    673: #ifdef USE_ARRAY_FOR_64BIT_TYPES
                    674:                                   getu32(swap, elfhdr.e_phoff[1]),
                    675: #else
                    676:                                   getu64(swap, elfhdr.e_phoff),
                    677: #endif
                    678:                                   getu16(swap, elfhdr.e_phnum),
                    679:                                   getu16(swap, elfhdr.e_phentsize));
                    680: #else
                    681:                        ;
1.1       millert   682: #endif
1.4       ian       683:                else
                    684:                {
                    685:                        if (getu16(swap, elfhdr.e_type) == ET_EXEC) {
                    686:                                dophn_exec(class, swap,
                    687:                                           fd,
                    688: #ifdef USE_ARRAY_FOR_64BIT_TYPES
                    689:                                           getu32(swap, elfhdr.e_phoff[1]),
                    690: #else
                    691:                                           getu64(swap, elfhdr.e_phoff),
1.1       millert   692: #endif
1.4       ian       693:                                           getu16(swap, elfhdr.e_phnum),
                    694:                                           getu16(swap, elfhdr.e_phentsize));
1.1       millert   695:                        }
1.4       ian       696:                        doshn(class, swap,
                    697:                              fd,
                    698: #ifdef USE_ARRAY_FOR_64BIT_TYPES
                    699:                              getu32(swap, elfhdr.e_shoff[1]),
                    700: #else
                    701:                              getu64(swap, elfhdr.e_shoff),
                    702: #endif
                    703:                              getu16(swap, elfhdr.e_shnum),
                    704:                              getu16(swap, elfhdr.e_shentsize));
1.1       millert   705:                }
                    706:                return;
                    707:        }
                    708: }
                    709: #endif