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

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