Annotation of embedaddon/php/ext/fileinfo/libmagic/readelf.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (c) Christos Zoulas 2003.
        !             3:  * All Rights Reserved.
        !             4:  * 
        !             5:  * Redistribution and use in source and binary forms, with or without
        !             6:  * modification, are permitted provided that the following conditions
        !             7:  * are met:
        !             8:  * 1. Redistributions of source code must retain the above copyright
        !             9:  *    notice immediately at the beginning of the file, without modification,
        !            10:  *    this list of conditions, and the following disclaimer.
        !            11:  * 2. Redistributions in binary form must reproduce the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer in the
        !            13:  *    documentation and/or other materials provided with the distribution.
        !            14:  *  
        !            15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
        !            16:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            17:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            18:  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
        !            19:  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            20:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            21:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            22:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            23:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            24:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            25:  * SUCH DAMAGE.
        !            26:  */
        !            27: #include "file.h"
        !            28: 
        !            29: #ifndef lint
        !            30: FILE_RCSID("@(#)$File: readelf.c,v 1.81 2008/11/04 16:38:28 christos Exp $")
        !            31: #endif
        !            32: 
        !            33: #ifdef BUILTIN_ELF
        !            34: #include <string.h>
        !            35: #include <ctype.h>
        !            36: #include <stdlib.h>
        !            37: #ifdef HAVE_UNISTD_H
        !            38: #include <unistd.h>
        !            39: #endif
        !            40: 
        !            41: #include "readelf.h"
        !            42: #include "magic.h"
        !            43: 
        !            44: #ifdef ELFCORE
        !            45: private int dophn_core(struct magic_set *, int, int, int, off_t, int, size_t,
        !            46:     off_t, int *);
        !            47: #endif
        !            48: private int dophn_exec(struct magic_set *, int, int, int, off_t, int, size_t,
        !            49:     off_t, int *, int);
        !            50: private int doshn(struct magic_set *, int, int, int, off_t, int, size_t, int *,
        !            51:     int);
        !            52: private size_t donote(struct magic_set *, unsigned char *, size_t, size_t, int,
        !            53:     int, size_t, int *);
        !            54: 
        !            55: #define        ELF_ALIGN(a)    ((((a) + align - 1) / align) * align)
        !            56: 
        !            57: #define isquote(c) (strchr("'\"`", (c)) != NULL)
        !            58: 
        !            59: private uint16_t getu16(int, uint16_t);
        !            60: private uint32_t getu32(int, uint32_t);
        !            61: private uint64_t getu64(int, uint64_t);
        !            62: 
        !            63: private uint16_t
        !            64: getu16(int swap, uint16_t value)
        !            65: {
        !            66:        union {
        !            67:                uint16_t ui;
        !            68:                char c[2];
        !            69:        } retval, tmpval;
        !            70: 
        !            71:        if (swap) {
        !            72:                tmpval.ui = value;
        !            73: 
        !            74:                retval.c[0] = tmpval.c[1];
        !            75:                retval.c[1] = tmpval.c[0];
        !            76:                
        !            77:                return retval.ui;
        !            78:        } else
        !            79:                return value;
        !            80: }
        !            81: 
        !            82: private uint32_t
        !            83: getu32(int swap, uint32_t value)
        !            84: {
        !            85:        union {
        !            86:                uint32_t ui;
        !            87:                char c[4];
        !            88:        } retval, tmpval;
        !            89: 
        !            90:        if (swap) {
        !            91:                tmpval.ui = value;
        !            92: 
        !            93:                retval.c[0] = tmpval.c[3];
        !            94:                retval.c[1] = tmpval.c[2];
        !            95:                retval.c[2] = tmpval.c[1];
        !            96:                retval.c[3] = tmpval.c[0];
        !            97:                
        !            98:                return retval.ui;
        !            99:        } else
        !           100:                return value;
        !           101: }
        !           102: 
        !           103: private uint64_t
        !           104: getu64(int swap, uint64_t value)
        !           105: {
        !           106:        union {
        !           107:                uint64_t ui;
        !           108:                char c[8];
        !           109:        } retval, tmpval;
        !           110: 
        !           111:        if (swap) {
        !           112:                tmpval.ui = value;
        !           113: 
        !           114:                retval.c[0] = tmpval.c[7];
        !           115:                retval.c[1] = tmpval.c[6];
        !           116:                retval.c[2] = tmpval.c[5];
        !           117:                retval.c[3] = tmpval.c[4];
        !           118:                retval.c[4] = tmpval.c[3];
        !           119:                retval.c[5] = tmpval.c[2];
        !           120:                retval.c[6] = tmpval.c[1];
        !           121:                retval.c[7] = tmpval.c[0];
        !           122:                
        !           123:                return retval.ui;
        !           124:        } else
        !           125:                return value;
        !           126: }
        !           127: 
        !           128: #define elf_getu16(swap, value) getu16(swap, value)
        !           129: #define elf_getu32(swap, value) getu32(swap, value)
        !           130: #ifdef USE_ARRAY_FOR_64BIT_TYPES
        !           131: # define elf_getu64(swap, array) \
        !           132:        ((swap ? ((uint64_t)elf_getu32(swap, array[0])) << 32 : elf_getu32(swap, array[0])) + \
        !           133:         (swap ? elf_getu32(swap, array[1]) : ((uint64_t)elf_getu32(swap, array[1]) << 32)))
        !           134: #else
        !           135: # define elf_getu64(swap, value) getu64(swap, value)
        !           136: #endif
        !           137: 
        !           138: #define xsh_addr       (clazz == ELFCLASS32                    \
        !           139:                         ? (void *) &sh32                       \
        !           140:                         : (void *) &sh64)
        !           141: #define xsh_sizeof     (clazz == ELFCLASS32                    \
        !           142:                         ? sizeof sh32                          \
        !           143:                         : sizeof sh64)
        !           144: #define xsh_size       (clazz == ELFCLASS32                    \
        !           145:                         ? elf_getu32(swap, sh32.sh_size)       \
        !           146:                         : elf_getu64(swap, sh64.sh_size))
        !           147: #define xsh_offset     (clazz == ELFCLASS32                    \
        !           148:                         ? elf_getu32(swap, sh32.sh_offset)     \
        !           149:                         : elf_getu64(swap, sh64.sh_offset))
        !           150: #define xsh_type       (clazz == ELFCLASS32                    \
        !           151:                         ? elf_getu32(swap, sh32.sh_type)       \
        !           152:                         : elf_getu32(swap, sh64.sh_type))
        !           153: #define xph_addr       (clazz == ELFCLASS32                    \
        !           154:                         ? (void *) &ph32                       \
        !           155:                         : (void *) &ph64)
        !           156: #define xph_sizeof     (clazz == ELFCLASS32                    \
        !           157:                         ? sizeof ph32                          \
        !           158:                         : sizeof ph64)
        !           159: #define xph_type       (clazz == ELFCLASS32                    \
        !           160:                         ? elf_getu32(swap, ph32.p_type)        \
        !           161:                         : elf_getu32(swap, ph64.p_type))
        !           162: #define xph_offset     (off_t)(clazz == ELFCLASS32             \
        !           163:                         ? elf_getu32(swap, ph32.p_offset)      \
        !           164:                         : elf_getu64(swap, ph64.p_offset))
        !           165: #define xph_align      (size_t)((clazz == ELFCLASS32           \
        !           166:                         ? (off_t) (ph32.p_align ?              \
        !           167:                            elf_getu32(swap, ph32.p_align) : 4) \
        !           168:                         : (off_t) (ph64.p_align ?              \
        !           169:                            elf_getu64(swap, ph64.p_align) : 4)))
        !           170: #define xph_filesz     (size_t)((clazz == ELFCLASS32           \
        !           171:                         ? elf_getu32(swap, ph32.p_filesz)      \
        !           172:                         : elf_getu64(swap, ph64.p_filesz)))
        !           173: #define xnh_addr       (clazz == ELFCLASS32                    \
        !           174:                         ? (void *) &nh32                       \
        !           175:                         : (void *) &nh64)
        !           176: #define xph_memsz      (size_t)((clazz == ELFCLASS32           \
        !           177:                         ? elf_getu32(swap, ph32.p_memsz)       \
        !           178:                         : elf_getu64(swap, ph64.p_memsz)))
        !           179: #define xnh_sizeof     (clazz == ELFCLASS32                    \
        !           180:                         ? sizeof nh32                          \
        !           181:                         : sizeof nh64)
        !           182: #define xnh_type       (clazz == ELFCLASS32                    \
        !           183:                         ? elf_getu32(swap, nh32.n_type)        \
        !           184:                         : elf_getu32(swap, nh64.n_type))
        !           185: #define xnh_namesz     (clazz == ELFCLASS32                    \
        !           186:                         ? elf_getu32(swap, nh32.n_namesz)      \
        !           187:                         : elf_getu32(swap, nh64.n_namesz))
        !           188: #define xnh_descsz     (clazz == ELFCLASS32                    \
        !           189:                         ? elf_getu32(swap, nh32.n_descsz)      \
        !           190:                         : elf_getu32(swap, nh64.n_descsz))
        !           191: #define prpsoffsets(i) (clazz == ELFCLASS32                    \
        !           192:                         ? prpsoffsets32[i]                     \
        !           193:                         : prpsoffsets64[i])
        !           194: #define xcap_addr      (clazz == ELFCLASS32                    \
        !           195:                         ? (void *) &cap32                      \
        !           196:                         : (void *) &cap64)
        !           197: #define xcap_sizeof    (clazz == ELFCLASS32                    \
        !           198:                         ? sizeof cap32                         \
        !           199:                         : sizeof cap64)
        !           200: #define xcap_tag       (clazz == ELFCLASS32                    \
        !           201:                         ? elf_getu32(swap, cap32.c_tag)        \
        !           202:                         : elf_getu64(swap, cap64.c_tag))
        !           203: #define xcap_val       (clazz == ELFCLASS32                    \
        !           204:                         ? elf_getu32(swap, cap32.c_un.c_val)   \
        !           205:                         : elf_getu64(swap, cap64.c_un.c_val))
        !           206: 
        !           207: #ifdef ELFCORE
        !           208: /*
        !           209:  * Try larger offsets first to avoid false matches
        !           210:  * from earlier data that happen to look like strings.
        !           211:  */
        !           212: static const size_t    prpsoffsets32[] = {
        !           213: #ifdef USE_NT_PSINFO
        !           214:        104,            /* SunOS 5.x (command line) */
        !           215:        88,             /* SunOS 5.x (short name) */
        !           216: #endif /* USE_NT_PSINFO */
        !           217: 
        !           218:        100,            /* SunOS 5.x (command line) */
        !           219:        84,             /* SunOS 5.x (short name) */
        !           220: 
        !           221:        44,             /* Linux (command line) */
        !           222:        28,             /* Linux 2.0.36 (short name) */
        !           223: 
        !           224:        8,              /* FreeBSD */
        !           225: };
        !           226: 
        !           227: static const size_t    prpsoffsets64[] = {
        !           228: #ifdef USE_NT_PSINFO
        !           229:        152,            /* SunOS 5.x (command line) */
        !           230:        136,            /* SunOS 5.x (short name) */
        !           231: #endif /* USE_NT_PSINFO */
        !           232: 
        !           233:        136,            /* SunOS 5.x, 64-bit (command line) */
        !           234:        120,            /* SunOS 5.x, 64-bit (short name) */
        !           235: 
        !           236:        56,             /* Linux (command line) */
        !           237:        40,             /* Linux (tested on core from 2.4.x, short name) */
        !           238: 
        !           239:        16,             /* FreeBSD, 64-bit */
        !           240: };
        !           241: 
        !           242: #define        NOFFSETS32      (sizeof prpsoffsets32 / sizeof prpsoffsets32[0])
        !           243: #define NOFFSETS64     (sizeof prpsoffsets64 / sizeof prpsoffsets64[0])
        !           244: 
        !           245: #define NOFFSETS       (clazz == ELFCLASS32 ? NOFFSETS32 : NOFFSETS64)
        !           246: 
        !           247: /*
        !           248:  * Look through the program headers of an executable image, searching
        !           249:  * for a PT_NOTE section of type NT_PRPSINFO, with a name "CORE" or
        !           250:  * "FreeBSD"; if one is found, try looking in various places in its
        !           251:  * contents for a 16-character string containing only printable
        !           252:  * characters - if found, that string should be the name of the program
        !           253:  * that dropped core.  Note: right after that 16-character string is,
        !           254:  * at least in SunOS 5.x (and possibly other SVR4-flavored systems) and
        !           255:  * Linux, a longer string (80 characters, in 5.x, probably other
        !           256:  * SVR4-flavored systems, and Linux) containing the start of the
        !           257:  * command line for that program.
        !           258:  *
        !           259:  * SunOS 5.x core files contain two PT_NOTE sections, with the types
        !           260:  * NT_PRPSINFO (old) and NT_PSINFO (new).  These structs contain the
        !           261:  * same info about the command name and command line, so it probably
        !           262:  * isn't worthwhile to look for NT_PSINFO, but the offsets are provided
        !           263:  * above (see USE_NT_PSINFO), in case we ever decide to do so.  The
        !           264:  * NT_PRPSINFO and NT_PSINFO sections are always in order and adjacent;
        !           265:  * the SunOS 5.x file command relies on this (and prefers the latter).
        !           266:  *
        !           267:  * The signal number probably appears in a section of type NT_PRSTATUS,
        !           268:  * but that's also rather OS-dependent, in ways that are harder to
        !           269:  * dissect with heuristics, so I'm not bothering with the signal number.
        !           270:  * (I suppose the signal number could be of interest in situations where
        !           271:  * you don't have the binary of the program that dropped core; if you
        !           272:  * *do* have that binary, the debugger will probably tell you what
        !           273:  * signal it was.)
        !           274:  */
        !           275: 
        !           276: #define        OS_STYLE_SVR4           0
        !           277: #define        OS_STYLE_FREEBSD        1
        !           278: #define        OS_STYLE_NETBSD         2
        !           279: 
        !           280: private const char os_style_names[][8] = {
        !           281:        "SVR4",
        !           282:        "FreeBSD",
        !           283:        "NetBSD",
        !           284: };
        !           285: 
        !           286: #define FLAGS_DID_CORE         1
        !           287: #define FLAGS_DID_NOTE         2
        !           288: #define FLAGS_DID_CORE_STYLE   4
        !           289: 
        !           290: private int
        !           291: dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
        !           292:     int num, size_t size, off_t fsize, int *flags)
        !           293: {
        !           294:        Elf32_Phdr ph32;
        !           295:        Elf64_Phdr ph64;
        !           296:        size_t offset;
        !           297:        unsigned char nbuf[BUFSIZ];
        !           298:        ssize_t bufsize;
        !           299:        off_t savedoffset;
        !           300:        struct stat st;
        !           301: 
        !           302:        if (fstat(fd, &st) < 0) {
        !           303:                file_badread(ms);
        !           304:                return -1;
        !           305:        }
        !           306: 
        !           307:        if (size != xph_sizeof) {
        !           308:                if (file_printf(ms, ", corrupted program header size") == -1)
        !           309:                        return -1;
        !           310:                return 0;
        !           311:        }
        !           312: 
        !           313:        /*
        !           314:         * Loop through all the program headers.
        !           315:         */
        !           316:        for ( ; num; num--) {
        !           317:                if ((savedoffset = lseek(fd, off, SEEK_SET)) == (off_t)-1) {
        !           318:                        file_badseek(ms);
        !           319:                        return -1;
        !           320:                }
        !           321:                if (read(fd, xph_addr, xph_sizeof) == -1) {
        !           322:                        file_badread(ms);
        !           323:                        return -1;
        !           324:                }
        !           325:                if (xph_offset > fsize) {
        !           326:                        if (lseek(fd, savedoffset, SEEK_SET) == (off_t)-1) {
        !           327:                                file_badseek(ms);
        !           328:                                return -1;
        !           329:                        }
        !           330:                        continue;
        !           331:                }
        !           332: 
        !           333:                off += size;
        !           334:                if (xph_type != PT_NOTE)
        !           335:                        continue;
        !           336: 
        !           337:                /*
        !           338:                 * This is a PT_NOTE section; loop through all the notes
        !           339:                 * in the section.
        !           340:                 */
        !           341:                if (lseek(fd, xph_offset, SEEK_SET) == (off_t)-1) {
        !           342:                        file_badseek(ms);
        !           343:                        return -1;
        !           344:                }
        !           345:                bufsize = read(fd, nbuf,
        !           346:                    ((xph_filesz < sizeof(nbuf)) ? xph_filesz : sizeof(nbuf)));
        !           347:                if (bufsize == -1) {
        !           348:                        file_badread(ms);
        !           349:                        return -1;
        !           350:                }
        !           351:                offset = 0;
        !           352:                for (;;) {
        !           353:                        if (offset >= (size_t)bufsize)
        !           354:                                break;
        !           355:                        offset = donote(ms, nbuf, offset, (size_t)bufsize,
        !           356:                            clazz, swap, 4, flags);
        !           357:                        if (offset == 0)
        !           358:                                break;
        !           359: 
        !           360:                }
        !           361:        }
        !           362:        return 0;
        !           363: }
        !           364: #endif
        !           365: 
        !           366: private size_t
        !           367: donote(struct magic_set *ms, unsigned char *nbuf, size_t offset, size_t size,
        !           368:     int clazz, int swap, size_t align, int *flags)
        !           369: {
        !           370:        Elf32_Nhdr nh32;
        !           371:        Elf64_Nhdr nh64;
        !           372:        size_t noff, doff;
        !           373: #ifdef ELFCORE
        !           374:        int os_style = -1;
        !           375: #endif
        !           376:        uint32_t namesz, descsz;
        !           377: 
        !           378:        (void)memcpy(xnh_addr, &nbuf[offset], xnh_sizeof);
        !           379:        offset += xnh_sizeof;
        !           380: 
        !           381:        namesz = xnh_namesz;
        !           382:        descsz = xnh_descsz;
        !           383:        if ((namesz == 0) && (descsz == 0)) {
        !           384:                /*
        !           385:                 * We're out of note headers.
        !           386:                 */
        !           387:                return (offset >= size) ? offset : size;
        !           388:        }
        !           389: 
        !           390:        if (namesz & 0x80000000) {
        !           391:            (void)file_printf(ms, ", bad note name size 0x%lx",
        !           392:                (unsigned long)namesz);
        !           393:            return offset;
        !           394:        }
        !           395: 
        !           396:        if (descsz & 0x80000000) {
        !           397:            (void)file_printf(ms, ", bad note description size 0x%lx",
        !           398:                (unsigned long)descsz);
        !           399:            return offset;
        !           400:        }
        !           401: 
        !           402: 
        !           403:        noff = offset;
        !           404:        doff = ELF_ALIGN(offset + namesz);
        !           405: 
        !           406:        if (offset + namesz > size) {
        !           407:                /*
        !           408:                 * We're past the end of the buffer.
        !           409:                 */
        !           410:                return doff;
        !           411:        }
        !           412: 
        !           413:        offset = ELF_ALIGN(doff + descsz);
        !           414:        if (doff + descsz > size) {
        !           415:                /*
        !           416:                 * We're past the end of the buffer.
        !           417:                 */
        !           418:                return (offset >= size) ? offset : size;
        !           419:        }
        !           420: 
        !           421:        if (*flags & FLAGS_DID_NOTE)
        !           422:                goto core;
        !           423: 
        !           424:        if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 &&
        !           425:            xnh_type == NT_GNU_VERSION && descsz == 16) {
        !           426:                uint32_t desc[4];
        !           427:                (void)memcpy(desc, &nbuf[doff], sizeof(desc));
        !           428: 
        !           429:                if (file_printf(ms, ", for GNU/") == -1)
        !           430:                        return size;
        !           431:                switch (elf_getu32(swap, desc[0])) {
        !           432:                case GNU_OS_LINUX:
        !           433:                        if (file_printf(ms, "Linux") == -1)
        !           434:                                return size;
        !           435:                        break;
        !           436:                case GNU_OS_HURD:
        !           437:                        if (file_printf(ms, "Hurd") == -1)
        !           438:                                return size;
        !           439:                        break;
        !           440:                case GNU_OS_SOLARIS:
        !           441:                        if (file_printf(ms, "Solaris") == -1)
        !           442:                                return size;
        !           443:                        break;
        !           444:                case GNU_OS_KFREEBSD:
        !           445:                        if (file_printf(ms, "kFreeBSD") == -1)
        !           446:                                return size;
        !           447:                        break;
        !           448:                case GNU_OS_KNETBSD:
        !           449:                        if (file_printf(ms, "kNetBSD") == -1)
        !           450:                                return size;
        !           451:                        break;
        !           452:                default:
        !           453:                        if (file_printf(ms, "<unknown>") == -1)
        !           454:                                return size; 
        !           455:                }
        !           456:                if (file_printf(ms, " %d.%d.%d", elf_getu32(swap, desc[1]),
        !           457:                    elf_getu32(swap, desc[2]), elf_getu32(swap, desc[3])) == -1)
        !           458:                        return size;
        !           459:                *flags |= FLAGS_DID_NOTE;
        !           460:                return size;
        !           461:        }
        !           462: 
        !           463:        if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0 &&
        !           464:            xnh_type == NT_NETBSD_VERSION && descsz == 4) {
        !           465:                uint32_t desc;
        !           466:                (void)memcpy(&desc, &nbuf[doff], sizeof(desc));
        !           467:                desc = elf_getu32(swap, desc);
        !           468: 
        !           469:                if (file_printf(ms, ", for NetBSD") == -1)
        !           470:                        return size;
        !           471:                /*
        !           472:                 * The version number used to be stuck as 199905, and was thus
        !           473:                 * basically content-free.  Newer versions of NetBSD have fixed
        !           474:                 * this and now use the encoding of __NetBSD_Version__:
        !           475:                 *
        !           476:                 *      MMmmrrpp00
        !           477:                 *
        !           478:                 * M = major version
        !           479:                 * m = minor version
        !           480:                 * r = release ["",A-Z,Z[A-Z] but numeric]
        !           481:                 * p = patchlevel
        !           482:                 */
        !           483:                if (desc > 100000000U) {
        !           484:                        uint32_t ver_patch = (desc / 100) % 100;
        !           485:                        uint32_t ver_rel = (desc / 10000) % 100;
        !           486:                        uint32_t ver_min = (desc / 1000000) % 100;
        !           487:                        uint32_t ver_maj = desc / 100000000;
        !           488: 
        !           489:                        if (file_printf(ms, " %u.%u", ver_maj, ver_min) == -1)
        !           490:                                return size;
        !           491:                        if (ver_rel == 0 && ver_patch != 0) {
        !           492:                                if (file_printf(ms, ".%u", ver_patch) == -1)
        !           493:                                        return size;
        !           494:                        } else if (ver_rel != 0) {
        !           495:                                while (ver_rel > 26) {
        !           496:                                        if (file_printf(ms, "Z") == -1)
        !           497:                                                return size;
        !           498:                                        ver_rel -= 26;
        !           499:                                }
        !           500:                                if (file_printf(ms, "%c", 'A' + ver_rel - 1)
        !           501:                                    == -1)
        !           502:                                        return size;
        !           503:                        }
        !           504:                }
        !           505:                *flags |= FLAGS_DID_NOTE;
        !           506:                return size;
        !           507:        }
        !           508: 
        !           509:        if (namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0 &&
        !           510:            xnh_type == NT_FREEBSD_VERSION && descsz == 4) {
        !           511:                uint32_t desc;
        !           512:                (void)memcpy(&desc, &nbuf[doff], sizeof(desc));
        !           513:                desc = elf_getu32(swap, desc);
        !           514:                if (file_printf(ms, ", for FreeBSD") == -1)
        !           515:                        return size;
        !           516: 
        !           517:                /*
        !           518:                 * Contents is __FreeBSD_version, whose relation to OS
        !           519:                 * versions is defined by a huge table in the Porter's
        !           520:                 * Handbook.  This is the general scheme:
        !           521:                 * 
        !           522:                 * Releases:
        !           523:                 *      Mmp000 (before 4.10)
        !           524:                 *      Mmi0p0 (before 5.0)
        !           525:                 *      Mmm0p0
        !           526:                 * 
        !           527:                 * Development branches:
        !           528:                 *      Mmpxxx (before 4.6)
        !           529:                 *      Mmp1xx (before 4.10)
        !           530:                 *      Mmi1xx (before 5.0)
        !           531:                 *      M000xx (pre-M.0)
        !           532:                 *      Mmm1xx
        !           533:                 * 
        !           534:                 * M = major version
        !           535:                 * m = minor version
        !           536:                 * i = minor version increment (491000 -> 4.10)
        !           537:                 * p = patchlevel
        !           538:                 * x = revision
        !           539:                 * 
        !           540:                 * The first release of FreeBSD to use ELF by default
        !           541:                 * was version 3.0.
        !           542:                 */
        !           543:                if (desc == 460002) {
        !           544:                        if (file_printf(ms, " 4.6.2") == -1)
        !           545:                                return size;
        !           546:                } else if (desc < 460100) {
        !           547:                        if (file_printf(ms, " %d.%d", desc / 100000,
        !           548:                            desc / 10000 % 10) == -1)
        !           549:                                return size;
        !           550:                        if (desc / 1000 % 10 > 0)
        !           551:                                if (file_printf(ms, ".%d", desc / 1000 % 10)
        !           552:                                    == -1)
        !           553:                                        return size;
        !           554:                        if ((desc % 1000 > 0) || (desc % 100000 == 0))
        !           555:                                if (file_printf(ms, " (%d)", desc) == -1)
        !           556:                                        return size;
        !           557:                } else if (desc < 500000) {
        !           558:                        if (file_printf(ms, " %d.%d", desc / 100000,
        !           559:                            desc / 10000 % 10 + desc / 1000 % 10) == -1)
        !           560:                                return size;
        !           561:                        if (desc / 100 % 10 > 0) {
        !           562:                                if (file_printf(ms, " (%d)", desc) == -1)
        !           563:                                        return size;
        !           564:                        } else if (desc / 10 % 10 > 0) {
        !           565:                                if (file_printf(ms, ".%d", desc / 10 % 10)
        !           566:                                    == -1)
        !           567:                                        return size;
        !           568:                        }
        !           569:                } else {
        !           570:                        if (file_printf(ms, " %d.%d", desc / 100000,
        !           571:                            desc / 1000 % 100) == -1)
        !           572:                                return size;
        !           573:                        if ((desc / 100 % 10 > 0) ||
        !           574:                            (desc % 100000 / 100 == 0)) {
        !           575:                                if (file_printf(ms, " (%d)", desc) == -1)
        !           576:                                        return size;
        !           577:                        } else if (desc / 10 % 10 > 0) {
        !           578:                                if (file_printf(ms, ".%d", desc / 10 % 10)
        !           579:                                    == -1)
        !           580:                                        return size;
        !           581:                        }
        !           582:                }
        !           583:                *flags |= FLAGS_DID_NOTE;
        !           584:                return size;
        !           585:        }
        !           586: 
        !           587:        if (namesz == 8 && strcmp((char *)&nbuf[noff], "OpenBSD") == 0 &&
        !           588:            xnh_type == NT_OPENBSD_VERSION && descsz == 4) {
        !           589:                if (file_printf(ms, ", for OpenBSD") == -1)
        !           590:                        return size;
        !           591:                /* Content of note is always 0 */
        !           592:                *flags |= FLAGS_DID_NOTE;
        !           593:                return size;
        !           594:        }
        !           595: 
        !           596:        if (namesz == 10 && strcmp((char *)&nbuf[noff], "DragonFly") == 0 &&
        !           597:            xnh_type == NT_DRAGONFLY_VERSION && descsz == 4) {
        !           598:                uint32_t desc;
        !           599:                if (file_printf(ms, ", for DragonFly") == -1)
        !           600:                        return size;
        !           601:                (void)memcpy(&desc, &nbuf[doff], sizeof(desc));
        !           602:                desc = elf_getu32(swap, desc);
        !           603:                if (file_printf(ms, " %d.%d.%d", desc / 100000,
        !           604:                    desc / 10000 % 10, desc % 10000) == -1)
        !           605:                        return size;
        !           606:                *flags |= FLAGS_DID_NOTE;
        !           607:                return size;
        !           608:        }
        !           609: 
        !           610: core:
        !           611:        /*
        !           612:         * Sigh.  The 2.0.36 kernel in Debian 2.1, at
        !           613:         * least, doesn't correctly implement name
        !           614:         * sections, in core dumps, as specified by
        !           615:         * the "Program Linking" section of "UNIX(R) System
        !           616:         * V Release 4 Programmer's Guide: ANSI C and
        !           617:         * Programming Support Tools", because my copy
        !           618:         * clearly says "The first 'namesz' bytes in 'name'
        !           619:         * contain a *null-terminated* [emphasis mine]
        !           620:         * character representation of the entry's owner
        !           621:         * or originator", but the 2.0.36 kernel code
        !           622:         * doesn't include the terminating null in the
        !           623:         * name....
        !           624:         */
        !           625:        if ((namesz == 4 && strncmp((char *)&nbuf[noff], "CORE", 4) == 0) ||
        !           626:            (namesz == 5 && strcmp((char *)&nbuf[noff], "CORE") == 0)) {
        !           627:                os_style = OS_STYLE_SVR4;
        !           628:        } 
        !           629: 
        !           630:        if ((namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0)) {
        !           631:                os_style = OS_STYLE_FREEBSD;
        !           632:        }
        !           633: 
        !           634:        if ((namesz >= 11 && strncmp((char *)&nbuf[noff], "NetBSD-CORE", 11)
        !           635:            == 0)) {
        !           636:                os_style = OS_STYLE_NETBSD;
        !           637:        }
        !           638: 
        !           639: #ifdef ELFCORE
        !           640:        if ((*flags & FLAGS_DID_CORE) != 0)
        !           641:                return size;
        !           642: 
        !           643:        if (os_style != -1 && (*flags & FLAGS_DID_CORE_STYLE) == 0) {
        !           644:                if (file_printf(ms, ", %s-style", os_style_names[os_style])
        !           645:                    == -1)
        !           646:                        return size;
        !           647:                *flags |= FLAGS_DID_CORE_STYLE;
        !           648:        }
        !           649: 
        !           650:        switch (os_style) {
        !           651:        case OS_STYLE_NETBSD:
        !           652:                if (xnh_type == NT_NETBSD_CORE_PROCINFO) {
        !           653:                        uint32_t signo;
        !           654:                        /*
        !           655:                         * Extract the program name.  It is at
        !           656:                         * offset 0x7c, and is up to 32-bytes,
        !           657:                         * including the terminating NUL.
        !           658:                         */
        !           659:                        if (file_printf(ms, ", from '%.31s'",
        !           660:                            &nbuf[doff + 0x7c]) == -1)
        !           661:                                return size;
        !           662:                        
        !           663:                        /*
        !           664:                         * Extract the signal number.  It is at
        !           665:                         * offset 0x08.
        !           666:                         */
        !           667:                        (void)memcpy(&signo, &nbuf[doff + 0x08],
        !           668:                            sizeof(signo));
        !           669:                        if (file_printf(ms, " (signal %u)",
        !           670:                            elf_getu32(swap, signo)) == -1)
        !           671:                                return size;
        !           672:                        *flags |= FLAGS_DID_CORE;
        !           673:                        return size;
        !           674:                }
        !           675:                break;
        !           676: 
        !           677:        default:
        !           678:                if (xnh_type == NT_PRPSINFO) {
        !           679:                        size_t i, j;
        !           680:                        unsigned char c;
        !           681:                        /*
        !           682:                         * Extract the program name.  We assume
        !           683:                         * it to be 16 characters (that's what it
        !           684:                         * is in SunOS 5.x and Linux).
        !           685:                         *
        !           686:                         * Unfortunately, it's at a different offset
        !           687:                         * in various OSes, so try multiple offsets.
        !           688:                         * If the characters aren't all printable,
        !           689:                         * reject it.
        !           690:                         */
        !           691:                        for (i = 0; i < NOFFSETS; i++) {
        !           692:                                unsigned char *cname, *cp;
        !           693:                                size_t reloffset = prpsoffsets(i);
        !           694:                                size_t noffset = doff + reloffset;
        !           695:                                for (j = 0; j < 16; j++, noffset++,
        !           696:                                    reloffset++) {
        !           697:                                        /*
        !           698:                                         * Make sure we're not past
        !           699:                                         * the end of the buffer; if
        !           700:                                         * we are, just give up.
        !           701:                                         */
        !           702:                                        if (noffset >= size)
        !           703:                                                goto tryanother;
        !           704: 
        !           705:                                        /*
        !           706:                                         * Make sure we're not past
        !           707:                                         * the end of the contents;
        !           708:                                         * if we are, this obviously
        !           709:                                         * isn't the right offset.
        !           710:                                         */
        !           711:                                        if (reloffset >= descsz)
        !           712:                                                goto tryanother;
        !           713: 
        !           714:                                        c = nbuf[noffset];
        !           715:                                        if (c == '\0') {
        !           716:                                                /*
        !           717:                                                 * A '\0' at the
        !           718:                                                 * beginning is
        !           719:                                                 * obviously wrong.
        !           720:                                                 * Any other '\0'
        !           721:                                                 * means we're done.
        !           722:                                                 */
        !           723:                                                if (j == 0)
        !           724:                                                        goto tryanother;
        !           725:                                                else
        !           726:                                                        break;
        !           727:                                        } else {
        !           728:                                                /*
        !           729:                                                 * A nonprintable
        !           730:                                                 * character is also
        !           731:                                                 * wrong.
        !           732:                                                 */
        !           733:                                                if (!isprint(c) || isquote(c))
        !           734:                                                        goto tryanother;
        !           735:                                        }
        !           736:                                }
        !           737:                                /*
        !           738:                                 * Well, that worked.
        !           739:                                 */
        !           740:                                cname = (unsigned char *)
        !           741:                                    &nbuf[doff + prpsoffsets(i)];
        !           742:                                for (cp = cname; *cp && isprint(*cp); cp++)
        !           743:                                        continue;
        !           744:                                /*
        !           745:                                 * Linux apparently appends a space at the end
        !           746:                                 * of the command line: remove it.
        !           747:                                 */
        !           748:                                while (cp > cname && isspace(cp[-1]))
        !           749:                                        cp--;
        !           750:                                if (file_printf(ms, ", from '%.*s'",
        !           751:                                    (int)(cp - cname), cname) == -1)
        !           752:                                        return size;
        !           753:                                *flags |= FLAGS_DID_CORE;
        !           754:                                return size;
        !           755: 
        !           756:                        tryanother:
        !           757:                                ;
        !           758:                        }
        !           759:                }
        !           760:                break;
        !           761:        }
        !           762: #endif
        !           763:        return offset;
        !           764: }
        !           765: 
        !           766: /* SunOS 5.x hardware capability descriptions */
        !           767: typedef struct cap_desc {
        !           768:        uint64_t cd_mask;
        !           769:        const char *cd_name;
        !           770: } cap_desc_t;
        !           771: 
        !           772: static const cap_desc_t cap_desc_sparc[] = {
        !           773:        { AV_SPARC_MUL32,               "MUL32" },
        !           774:        { AV_SPARC_DIV32,               "DIV32" },
        !           775:        { AV_SPARC_FSMULD,              "FSMULD" },
        !           776:        { AV_SPARC_V8PLUS,              "V8PLUS" },
        !           777:        { AV_SPARC_POPC,                "POPC" },
        !           778:        { AV_SPARC_VIS,                 "VIS" },
        !           779:        { AV_SPARC_VIS2,                "VIS2" },
        !           780:        { AV_SPARC_ASI_BLK_INIT,        "ASI_BLK_INIT" },
        !           781:        { AV_SPARC_FMAF,                "FMAF" },
        !           782:        { AV_SPARC_FJFMAU,              "FJFMAU" },
        !           783:        { AV_SPARC_IMA,                 "IMA" },
        !           784:        { 0, NULL }
        !           785: };
        !           786: 
        !           787: static const cap_desc_t cap_desc_386[] = {
        !           788:        { AV_386_FPU,                   "FPU" },
        !           789:        { AV_386_TSC,                   "TSC" },
        !           790:        { AV_386_CX8,                   "CX8" },
        !           791:        { AV_386_SEP,                   "SEP" },
        !           792:        { AV_386_AMD_SYSC,              "AMD_SYSC" },
        !           793:        { AV_386_CMOV,                  "CMOV" },
        !           794:        { AV_386_MMX,                   "MMX" },
        !           795:        { AV_386_AMD_MMX,               "AMD_MMX" },
        !           796:        { AV_386_AMD_3DNow,             "AMD_3DNow" },
        !           797:        { AV_386_AMD_3DNowx,            "AMD_3DNowx" },
        !           798:        { AV_386_FXSR,                  "FXSR" },
        !           799:        { AV_386_SSE,                   "SSE" },
        !           800:        { AV_386_SSE2,                  "SSE2" },
        !           801:        { AV_386_PAUSE,                 "PAUSE" },
        !           802:        { AV_386_SSE3,                  "SSE3" },
        !           803:        { AV_386_MON,                   "MON" },
        !           804:        { AV_386_CX16,                  "CX16" },
        !           805:        { AV_386_AHF,                   "AHF" },
        !           806:        { AV_386_TSCP,                  "TSCP" },
        !           807:        { AV_386_AMD_SSE4A,             "AMD_SSE4A" },
        !           808:        { AV_386_POPCNT,                "POPCNT" },
        !           809:        { AV_386_AMD_LZCNT,             "AMD_LZCNT" },
        !           810:        { AV_386_SSSE3,                 "SSSE3" },
        !           811:        { AV_386_SSE4_1,                "SSE4.1" },
        !           812:        { AV_386_SSE4_2,                "SSE4.2" },
        !           813:        { 0, NULL }
        !           814: };
        !           815: 
        !           816: private int
        !           817: doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
        !           818:     size_t size, int *flags, int mach)
        !           819: {
        !           820:        Elf32_Shdr sh32;
        !           821:        Elf64_Shdr sh64;
        !           822:        int stripped = 1;
        !           823:        void *nbuf;
        !           824:        off_t noff;
        !           825:        uint64_t cap_hw1 = 0;   /* SunOS 5.x hardware capabilites */
        !           826:        uint64_t cap_sf1 = 0;   /* SunOS 5.x software capabilites */
        !           827: 
        !           828:        if (size != xsh_sizeof) {
        !           829:                if (file_printf(ms, ", corrupted section header size") == -1)
        !           830:                        return -1;
        !           831:                return 0;
        !           832:        }
        !           833: 
        !           834:        if (lseek(fd, off, SEEK_SET) == (off_t)-1) {
        !           835:                file_badseek(ms);
        !           836:                return -1;
        !           837:        }
        !           838: 
        !           839:        for ( ; num; num--) {
        !           840:                if (read(fd, xsh_addr, xsh_sizeof) == -1) {
        !           841:                        file_badread(ms);
        !           842:                        return -1;
        !           843:                }
        !           844:                switch (xsh_type) {
        !           845:                case SHT_SYMTAB:
        !           846: #if 0
        !           847:                case SHT_DYNSYM:
        !           848: #endif
        !           849:                        stripped = 0;
        !           850:                        break;
        !           851:                case SHT_NOTE:
        !           852:                        if ((off = lseek(fd, (off_t)0, SEEK_CUR)) ==
        !           853:                            (off_t)-1) {
        !           854:                                file_badread(ms);
        !           855:                                return -1;
        !           856:                        }
        !           857:                        nbuf = emalloc((size_t)xsh_size);
        !           858:                        if ((noff = lseek(fd, (off_t)xsh_offset, SEEK_SET)) ==
        !           859:                            (off_t)-1) {
        !           860:                                file_badread(ms);
        !           861:                                efree(nbuf);
        !           862:                                return -1;
        !           863:                        }
        !           864:                        if (read(fd, nbuf, (size_t)xsh_size) !=
        !           865:                            (ssize_t)xsh_size) {
        !           866:                                efree(nbuf);
        !           867:                                file_badread(ms);
        !           868:                                return -1;
        !           869:                        }
        !           870: 
        !           871:                        noff = 0;
        !           872:                        for (;;) {
        !           873:                                if (noff >= (off_t)xsh_size)
        !           874:                                        break;
        !           875:                                noff = donote(ms, nbuf, (size_t)noff,
        !           876:                                    (size_t)xsh_size, clazz, swap, 4,
        !           877:                                    flags);
        !           878:                                if (noff == 0)
        !           879:                                        break;
        !           880:                        }
        !           881:                        if ((lseek(fd, off, SEEK_SET)) == (off_t)-1) {
        !           882:                                efree(nbuf);
        !           883:                                file_badread(ms);
        !           884:                                return -1;
        !           885:                        }
        !           886:                        efree(nbuf);
        !           887:                        break;
        !           888:                case SHT_SUNW_cap:
        !           889:                    {
        !           890:                        off_t coff;
        !           891:                        if ((off = lseek(fd, (off_t)0, SEEK_CUR)) ==
        !           892:                            (off_t)-1) {
        !           893:                                file_badread(ms);
        !           894:                                return -1;
        !           895:                        }
        !           896:                        if (lseek(fd, (off_t)xsh_offset, SEEK_SET) ==
        !           897:                            (off_t)-1) {
        !           898:                                file_badread(ms);
        !           899:                                return -1;
        !           900:                        }
        !           901:                        coff = 0;
        !           902:                        for (;;) {
        !           903:                                Elf32_Cap cap32;
        !           904:                                Elf64_Cap cap64;
        !           905:                                char cbuf[/*CONSTCOND*/
        !           906:                                    MAX(sizeof cap32, sizeof cap64)];
        !           907:                                if ((coff += xcap_sizeof) >= (off_t)xsh_size)
        !           908:                                        break;
        !           909:                                if (read(fd, cbuf, (size_t)xcap_sizeof) !=
        !           910:                                    (ssize_t)xcap_sizeof) {
        !           911:                                        file_badread(ms);
        !           912:                                        return -1;
        !           913:                                }
        !           914:                                (void)memcpy(xcap_addr, cbuf, xcap_sizeof);
        !           915:                                switch (xcap_tag) {
        !           916:                                case CA_SUNW_NULL:
        !           917:                                        break;
        !           918:                                case CA_SUNW_HW_1:
        !           919:                                        cap_hw1 |= xcap_val;
        !           920:                                        break;
        !           921:                                case CA_SUNW_SF_1:
        !           922:                                        cap_sf1 |= xcap_val;
        !           923:                                        break;
        !           924:                                default:
        !           925:                                        if (file_printf(ms,
        !           926:                                            ", with unknown capability "
        !           927:                                            "0x%llx = 0x%llx",
        !           928:                                            (unsigned long long)xcap_tag,
        !           929:                                            (unsigned long long)xcap_val) == -1)
        !           930:                                                return -1;
        !           931:                                        break;
        !           932:                                }
        !           933:                        }
        !           934:                        if (lseek(fd, off, SEEK_SET) == (off_t)-1) {
        !           935:                                file_badread(ms);
        !           936:                                return -1;
        !           937:                        }
        !           938:                        break;
        !           939:                    }
        !           940:                }
        !           941:        }
        !           942:        if (file_printf(ms, ", %sstripped", stripped ? "" : "not ") == -1)
        !           943:                return -1;
        !           944:        if (cap_hw1) {
        !           945:                const cap_desc_t *cdp;
        !           946:                switch (mach) {
        !           947:                case EM_SPARC:
        !           948:                case EM_SPARC32PLUS:
        !           949:                case EM_SPARCV9:
        !           950:                        cdp = cap_desc_sparc;
        !           951:                        break;
        !           952:                case EM_386:
        !           953:                case EM_IA_64:
        !           954:                case EM_AMD64:
        !           955:                        cdp = cap_desc_386;
        !           956:                        break;
        !           957:                default:
        !           958:                        cdp = NULL;
        !           959:                        break;
        !           960:                }
        !           961:                if (file_printf(ms, ", uses") == -1)
        !           962:                        return -1;
        !           963:                if (cdp) {
        !           964:                        while (cdp->cd_name) {
        !           965:                                if (cap_hw1 & cdp->cd_mask) {
        !           966:                                        if (file_printf(ms,
        !           967:                                            " %s", cdp->cd_name) == -1)
        !           968:                                                return -1;
        !           969:                                        cap_hw1 &= ~cdp->cd_mask;
        !           970:                                }
        !           971:                                ++cdp;
        !           972:                        }
        !           973:                        if (cap_hw1)
        !           974:                                if (file_printf(ms,
        !           975:                                    " unknown hardware capability 0x%llx",
        !           976:                                    (unsigned long long)cap_hw1) == -1)
        !           977:                                        return -1;
        !           978:                } else {
        !           979:                        if (file_printf(ms,
        !           980:                            " hardware capability 0x%llx",
        !           981:                            (unsigned long long)cap_hw1) == -1)
        !           982:                                return -1;
        !           983:                }
        !           984:        }
        !           985:        if (cap_sf1) {
        !           986:                if (cap_sf1 & SF1_SUNW_FPUSED) {
        !           987:                        if (file_printf(ms,
        !           988:                            (cap_sf1 & SF1_SUNW_FPKNWN)
        !           989:                            ? ", uses frame pointer"
        !           990:                            : ", not known to use frame pointer") == -1)
        !           991:                                return -1;
        !           992:                }
        !           993:                cap_sf1 &= ~SF1_SUNW_MASK;
        !           994:                if (cap_sf1)
        !           995:                        if (file_printf(ms,
        !           996:                            ", with unknown software capability 0x%llx",
        !           997:                            (unsigned long long)cap_sf1) == -1)
        !           998:                                return -1;
        !           999:        }
        !          1000:        return 0;
        !          1001: }
        !          1002: 
        !          1003: /*
        !          1004:  * Look through the program headers of an executable image, searching
        !          1005:  * for a PT_INTERP section; if one is found, it's dynamically linked,
        !          1006:  * otherwise it's statically linked.
        !          1007:  */
        !          1008: private int
        !          1009: dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
        !          1010:     int num, size_t size, off_t fsize, int *flags, int sh_num)
        !          1011: {
        !          1012:        Elf32_Phdr ph32;
        !          1013:        Elf64_Phdr ph64;
        !          1014:        const char *linking_style = "statically";
        !          1015:        const char *shared_libraries = "";
        !          1016:        unsigned char nbuf[BUFSIZ];
        !          1017:        int bufsize;
        !          1018:        size_t offset, align;
        !          1019:        off_t savedoffset = (off_t)-1;
        !          1020:        struct stat st;
        !          1021: 
        !          1022:        if (fstat(fd, &st) < 0) {
        !          1023:                file_badread(ms);
        !          1024:                return -1;
        !          1025:        }
        !          1026:        
        !          1027:        if (size != xph_sizeof) {
        !          1028:                if (file_printf(ms, ", corrupted program header size") == -1)
        !          1029:                        return -1;
        !          1030:                return 0;
        !          1031:        }
        !          1032: 
        !          1033:        if (lseek(fd, off, SEEK_SET) == (off_t)-1) {
        !          1034:                file_badseek(ms);
        !          1035:                return -1;
        !          1036:        }
        !          1037: 
        !          1038:        for ( ; num; num--) {
        !          1039:                if (read(fd, xph_addr, xph_sizeof) == -1) {
        !          1040:                        file_badread(ms);
        !          1041:                        return -1;
        !          1042:                }
        !          1043:                if (xph_offset > st.st_size && savedoffset != (off_t)-1) {
        !          1044:                        if (lseek(fd, savedoffset, SEEK_SET) == (off_t)-1) {
        !          1045:                                file_badseek(ms);
        !          1046:                                return -1;
        !          1047:                        }
        !          1048:                        continue;
        !          1049:                }
        !          1050: 
        !          1051:                if ((savedoffset = lseek(fd, (off_t)0, SEEK_CUR)) == (off_t)-1) {
        !          1052:                        file_badseek(ms);
        !          1053:                        return -1;
        !          1054:                }
        !          1055: 
        !          1056:                if (xph_offset > fsize) {
        !          1057:                        if (lseek(fd, savedoffset, SEEK_SET) == (off_t)-1) {
        !          1058:                                file_badseek(ms);
        !          1059:                                return -1;
        !          1060:                        }
        !          1061:                        continue;
        !          1062:                }
        !          1063: 
        !          1064:                switch (xph_type) {
        !          1065:                case PT_DYNAMIC:
        !          1066:                        linking_style = "dynamically";
        !          1067:                        break;
        !          1068:                case PT_INTERP:
        !          1069:                        shared_libraries = " (uses shared libs)";
        !          1070:                        break;
        !          1071:                case PT_NOTE:
        !          1072:                        if ((align = xph_align) & 0x80000000) {
        !          1073:                                if (file_printf(ms, 
        !          1074:                                    ", invalid note alignment 0x%lx",
        !          1075:                                    (unsigned long)align) == -1)
        !          1076:                                        return -1;
        !          1077:                                align = 4;
        !          1078:                        }
        !          1079:                        if (sh_num)
        !          1080:                                break;
        !          1081:                        /*
        !          1082:                         * This is a PT_NOTE section; loop through all the notes
        !          1083:                         * in the section.
        !          1084:                         */
        !          1085:                        if (lseek(fd, xph_offset, SEEK_SET)
        !          1086:                            == (off_t)-1) {
        !          1087:                                file_badseek(ms);
        !          1088:                                return -1;
        !          1089:                        }
        !          1090:                        bufsize = read(fd, nbuf, ((xph_filesz < sizeof(nbuf)) ?
        !          1091:                            xph_filesz : sizeof(nbuf)));
        !          1092:                        if (bufsize == -1) {
        !          1093:                                file_badread(ms);
        !          1094:                                return -1;
        !          1095:                        }
        !          1096:                        offset = 0;
        !          1097:                        for (;;) {
        !          1098:                                if (offset >= (size_t)bufsize)
        !          1099:                                        break;
        !          1100:                                offset = donote(ms, nbuf, offset,
        !          1101:                                    (size_t)bufsize, clazz, swap, align,
        !          1102:                                    flags);
        !          1103:                                if (offset == 0)
        !          1104:                                        break;
        !          1105:                        }
        !          1106:                        if (lseek(fd, savedoffset, SEEK_SET) == (off_t)-1) {
        !          1107:                                file_badseek(ms);
        !          1108:                                return -1;
        !          1109:                        }
        !          1110:                        break;
        !          1111:                default:
        !          1112:                        break;
        !          1113:                }
        !          1114:        }
        !          1115:        if (file_printf(ms, ", %s linked%s", linking_style, shared_libraries)
        !          1116:            == -1)
        !          1117:            return -1;
        !          1118:        return 0;
        !          1119: }
        !          1120: 
        !          1121: 
        !          1122: protected int
        !          1123: file_tryelf(struct magic_set *ms, int fd, const unsigned char *buf,
        !          1124:     size_t nbytes)
        !          1125: {
        !          1126:        union {
        !          1127:                int32_t l;
        !          1128:                char c[sizeof (int32_t)];
        !          1129:        } u;
        !          1130:        int clazz;
        !          1131:        int swap;
        !          1132:        struct stat st;
        !          1133:        off_t fsize;
        !          1134:        int flags = 0;
        !          1135:        Elf32_Ehdr elf32hdr;
        !          1136:        Elf64_Ehdr elf64hdr;
        !          1137:        uint16_t type;
        !          1138: 
        !          1139:        if (ms->flags & (MAGIC_MIME|MAGIC_APPLE))
        !          1140:                return 0;
        !          1141:        /*
        !          1142:         * ELF executables have multiple section headers in arbitrary
        !          1143:         * file locations and thus file(1) cannot determine it from easily.
        !          1144:         * Instead we traverse thru all section headers until a symbol table
        !          1145:         * one is found or else the binary is stripped.
        !          1146:         * Return immediately if it's not ELF (so we avoid pipe2file unless needed).
        !          1147:         */
        !          1148:        if (buf[EI_MAG0] != ELFMAG0
        !          1149:            || (buf[EI_MAG1] != ELFMAG1 && buf[EI_MAG1] != OLFMAG1)
        !          1150:            || buf[EI_MAG2] != ELFMAG2 || buf[EI_MAG3] != ELFMAG3)
        !          1151:                return 0;
        !          1152: 
        !          1153:        /*
        !          1154:         * If we cannot seek, it must be a pipe, socket or fifo.
        !          1155:         */
        !          1156:        if((lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) && (errno == ESPIPE))
        !          1157:                fd = file_pipe2file(ms, fd, buf, nbytes);
        !          1158: 
        !          1159:        if (fstat(fd, &st) == -1) {
        !          1160:                file_badread(ms);
        !          1161:                return -1;
        !          1162:        }
        !          1163:        fsize = st.st_size;
        !          1164: 
        !          1165:        clazz = buf[EI_CLASS];
        !          1166: 
        !          1167:        switch (clazz) {
        !          1168:        case ELFCLASS32:
        !          1169: #undef elf_getu
        !          1170: #define elf_getu(a, b) elf_getu32(a, b)
        !          1171: #undef elfhdr
        !          1172: #define elfhdr elf32hdr
        !          1173: #include "elfclass.h"
        !          1174:        case ELFCLASS64:
        !          1175: #undef elf_getu
        !          1176: #define elf_getu(a, b) elf_getu64(a, b)
        !          1177: #undef elfhdr
        !          1178: #define elfhdr elf64hdr
        !          1179: #include "elfclass.h"
        !          1180:        default:
        !          1181:            if (file_printf(ms, ", unknown class %d", clazz) == -1)
        !          1182:                    return -1;
        !          1183:            break;
        !          1184:        }
        !          1185:        return 0;
        !          1186: }
        !          1187: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>