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

1.1     ! millert     1: /*     $OpenBSD: file.c,v 1.4 1997/01/15 23:42:26 millert Exp $        */
        !             2:
        !             3: #ifdef BUILTIN_ELF
        !             4: #include <sys/types.h>
        !             5: #include <string.h>
        !             6: #include <stdio.h>
        !             7: #include <ctype.h>
        !             8: #include <stdlib.h>
        !             9: #include <unistd.h>
        !            10: #include <errno.h>
        !            11:
        !            12: #include "readelf.h"
        !            13: #include "file.h"
        !            14:
        !            15: static void
        !            16: doshn(fd, off, num, size, buf)
        !            17:        int fd;
        !            18:        off_t off;
        !            19:        int num;
        !            20:        size_t size;
        !            21:        char *buf;
        !            22: {
        !            23:        /*
        !            24:         * This works for both 32-bit and 64-bit ELF formats,
        !            25:         * because it looks only at the "sh_type" field, which is
        !            26:         * always 32 bits, and is preceded only by the "sh_name"
        !            27:         * field which is also always 32 bits, and because it uses
        !            28:         * the shdr size from the ELF header rather than using
        !            29:         * the size of an "Elf32_Shdr".
        !            30:         */
        !            31:        Elf32_Shdr *sh = (Elf32_Shdr *) buf;
        !            32:
        !            33:        if (lseek(fd, off, SEEK_SET) == -1)
        !            34:                error("lseek failed (%s).\n", strerror(errno));
        !            35:
        !            36:        for ( ; num; num--) {
        !            37:                if (read(fd, buf, size) == -1)
        !            38:                        error("read failed (%s).\n", strerror(errno));
        !            39:                if (sh->sh_type == SHT_SYMTAB) {
        !            40:                        (void) printf (", not stripped");
        !            41:                        return;
        !            42:                }
        !            43:        }
        !            44:        (void) printf (", stripped");
        !            45: }
        !            46:
        !            47: /*
        !            48:  * Look through the program headers of an executable image, searching
        !            49:  * for a PT_INTERP section; if one is found, it's dynamically linked,
        !            50:  * otherwise it's statically linked.
        !            51:  */
        !            52: static void
        !            53: dophn_exec(fd, off, num, size, buf)
        !            54:        int fd;
        !            55:        off_t off;
        !            56:        int num;
        !            57:        size_t size;
        !            58:        char *buf;
        !            59: {
        !            60:        /* I am not sure if this works for 64 bit elf formats */
        !            61:        Elf32_Phdr *ph = (Elf32_Phdr *) buf;
        !            62:
        !            63:        if (lseek(fd, off, SEEK_SET) == -1)
        !            64:                error("lseek failed (%s).\n", strerror(errno));
        !            65:
        !            66:        for ( ; num; num--) {
        !            67:                if (read(fd, buf, size) == -1)
        !            68:                        error("read failed (%s).\n", strerror(errno));
        !            69:                if (ph->p_type == PT_INTERP) {
        !            70:                        /*
        !            71:                         * Has an interpreter - must be a dynamically-linked
        !            72:                         * executable.
        !            73:                         */
        !            74:                        printf(", dynamically linked");
        !            75:                        return;
        !            76:                }
        !            77:        }
        !            78:        printf(", statically linked");
        !            79: }
        !            80:
        !            81: size_t prpsoffsets[] = {
        !            82:        100,            /* SunOS 5.x */
        !            83:        32,             /* Linux */
        !            84: };
        !            85:
        !            86: #define        NOFFSETS        (sizeof prpsoffsets / sizeof prpsoffsets[0])
        !            87:
        !            88: /*
        !            89:  * Look through the program headers of an executable image, searching
        !            90:  * for a PT_NOTE section of type NT_PRPSINFO, with a name "CORE"; if one
        !            91:  * is found, try looking in various places in its contents for a 16-character
        !            92:  * string containing only printable characters - if found, that string
        !            93:  * should be the name of the program that dropped core.
        !            94:  * Note: right after that 16-character string is, at least in SunOS 5.x
        !            95:  * (and possibly other SVR4-flavored systems) and Linux, a longer string
        !            96:  * (80 characters, in 5.x, probably other SVR4-flavored systems, and Linux)
        !            97:  * containing the start of the command line for that program.
        !            98:  */
        !            99: static void
        !           100: dophn_core(fd, off, num, size, buf)
        !           101:        int fd;
        !           102:        off_t off;
        !           103:        int num;
        !           104:        size_t size;
        !           105:        char *buf;
        !           106: {
        !           107:        /*
        !           108:         * This doesn't work for 64-bit ELF, as the "p_offset" field is
        !           109:         * 64 bits in 64-bit ELF.
        !           110:         */
        !           111:        /*
        !           112:         * This doesn't work for 64-bit ELF, as the "p_offset" field is
        !           113:         * 64 bits in 64-bit ELF.
        !           114:         */
        !           115:        Elf32_Phdr *ph = (Elf32_Phdr *) buf;
        !           116:        Elf32_Nhdr *nh;
        !           117:        size_t offset, noffset, reloffset;
        !           118:        unsigned char c;
        !           119:        int i, j;
        !           120:        char nbuf[BUFSIZ];
        !           121:        int bufsize;
        !           122:
        !           123:        for ( ; num; num--) {
        !           124:                if (lseek(fd, off, SEEK_SET) == -1)
        !           125:                        error("lseek failed (%s).\n", strerror(errno));
        !           126:                if (read(fd, buf, size) == -1)
        !           127:                        error("read failed (%s).\n", strerror(errno));
        !           128:                off += size;
        !           129:                if (ph->p_type != PT_NOTE)
        !           130:                        continue;
        !           131:                if (lseek(fd, ph->p_offset, SEEK_SET) == -1)
        !           132:                        error("lseek failed (%s).\n", strerror(errno));
        !           133:                bufsize = read(fd, nbuf, BUFSIZ);
        !           134:                if (bufsize == -1)
        !           135:                        error("read failed (%s).\n", strerror(errno));
        !           136:                offset = 0;
        !           137:                for (;;) {
        !           138:                        if (offset >= bufsize)
        !           139:                                break;
        !           140:                        nh = (Elf32_Nhdr *)&nbuf[offset];
        !           141:                        offset += sizeof *nh;
        !           142:
        !           143:                        /*
        !           144:                         * If this note isn't an NT_PRPSINFO note, it's
        !           145:                         * not what we're looking for.
        !           146:                         */
        !           147:                        if (nh->n_type != NT_PRPSINFO) {
        !           148:                                offset += nh->n_namesz;
        !           149:                                offset = ((offset + 3)/4)*4;
        !           150:                                offset += nh->n_descsz;
        !           151:                                offset = ((offset + 3)/4)*4;
        !           152:                                continue;
        !           153:                        }
        !           154:
        !           155:                        /*
        !           156:                         * Make sure this note has the name "CORE".
        !           157:                         */
        !           158:                        if (offset + nh->n_namesz >= bufsize) {
        !           159:                                /*
        !           160:                                 * We're past the end of the buffer.
        !           161:                                 */
        !           162:                                break;
        !           163:                        }
        !           164:                        if (nh->n_namesz != 5
        !           165:                            || strcmp(&nbuf[offset], "CORE") != 0)
        !           166:                                continue;
        !           167:                        offset += nh->n_namesz;
        !           168:                        offset = ((offset + 3)/4)*4;
        !           169:
        !           170:                        /*
        !           171:                         * Extract the program name.  We assume it to be
        !           172:                         * 16 characters (that's what it is in SunOS 5.x
        !           173:                         * and Linux).
        !           174:                         *
        !           175:                         * Unfortunately, it's at a different offset in
        !           176:                         * SunOS 5.x and Linux, so try multiple offsets.
        !           177:                         * If the characters aren't all printable, reject
        !           178:                         * it.
        !           179:                         */
        !           180:                        for (i = 0; i < NOFFSETS; i++) {
        !           181:                                reloffset = prpsoffsets[i];
        !           182:                                noffset = offset + reloffset;
        !           183:                                for (j = 0; j < 16;
        !           184:                                    j++, noffset++, reloffset++) {
        !           185:                                        /*
        !           186:                                         * Make sure we're not past the end
        !           187:                                         * of the buffer; if we are, just
        !           188:                                         * give up.
        !           189:                                         */
        !           190:                                        if (noffset >= bufsize)
        !           191:                                                return;
        !           192:
        !           193:                                        /*
        !           194:                                         * Make sure we're not past the
        !           195:                                         * end of the contents; if we
        !           196:                                         * are, this obviously isn't
        !           197:                                         * the right offset.
        !           198:                                         */
        !           199:                                        if (reloffset >= nh->n_descsz)
        !           200:                                                goto tryanother;
        !           201:
        !           202:                                        c = nbuf[noffset];
        !           203:                                        if (c != '\0' && !isprint(c))
        !           204:                                                goto tryanother;
        !           205:                                }
        !           206:
        !           207:                                /*
        !           208:                                 * Well, that worked.
        !           209:                                 */
        !           210:                                printf(", from '%.16s'",
        !           211:                                    &nbuf[offset + prpsoffsets[i]]);
        !           212:                                return;
        !           213:
        !           214:                        tryanother:
        !           215:                                ;
        !           216:                        }
        !           217:                        offset += nh->n_descsz;
        !           218:                        offset = ((offset + 3)/4)*4;
        !           219:                }
        !           220:        }
        !           221: }
        !           222:
        !           223: void
        !           224: tryelf(fd, buf, nbytes)
        !           225:        int fd;
        !           226:        char *buf;
        !           227:        int nbytes;
        !           228: {
        !           229:        union {
        !           230:                int32 l;
        !           231:                char c[sizeof (int32)];
        !           232:        } u;
        !           233:
        !           234:        /*
        !           235:         * ELF executables have multiple section headers in arbitrary
        !           236:         * file locations and thus file(1) cannot determine it from easily.
        !           237:         * Instead we traverse thru all section headers until a symbol table
        !           238:         * one is found or else the binary is stripped.
        !           239:         */
        !           240:        if (buf[EI_MAG0] != ELFMAG0 || buf[EI_MAG1] != ELFMAG1
        !           241:            || buf[EI_MAG2] != ELFMAG2 || buf[EI_MAG3] != ELFMAG3)
        !           242:            return;
        !           243:
        !           244:
        !           245:        if (buf[4] == ELFCLASS32) {
        !           246:                Elf32_Ehdr elfhdr;
        !           247:                if (nbytes <= sizeof (Elf32_Ehdr))
        !           248:                        return;
        !           249:
        !           250:
        !           251:                u.l = 1;
        !           252:                (void) memcpy(&elfhdr, buf, sizeof elfhdr);
        !           253:                /*
        !           254:                 * If the system byteorder does not equal the
        !           255:                 * object byteorder then don't test.
        !           256:                 * XXX - we could conceivably fix up the "dophn_XXX()" and
        !           257:                 * "doshn()" routines to extract stuff in the right
        !           258:                 * byte order....
        !           259:                 */
        !           260:                if ((u.c[sizeof(long) - 1] + 1) == elfhdr.e_ident[5]) {
        !           261:                        if (elfhdr.e_type == ET_CORE)
        !           262:                                dophn_core(fd, elfhdr.e_phoff, elfhdr.e_phnum,
        !           263:                                      elfhdr.e_phentsize, buf);
        !           264:                        else {
        !           265:                                if (elfhdr.e_type == ET_EXEC) {
        !           266:                                        dophn_exec(fd, elfhdr.e_phoff,
        !           267:                                            elfhdr.e_phnum,
        !           268:                                              elfhdr.e_phentsize, buf);
        !           269:                                }
        !           270:                                doshn(fd, elfhdr.e_shoff, elfhdr.e_shnum,
        !           271:                                      elfhdr.e_shentsize, buf);
        !           272:                        }
        !           273:                }
        !           274:                return;
        !           275:        }
        !           276:
        !           277:         if (buf[4] == ELFCLASS64) {
        !           278:                Elf64_Ehdr elfhdr;
        !           279:                if (nbytes <= sizeof (Elf64_Ehdr))
        !           280:                        return;
        !           281:
        !           282:
        !           283:                u.l = 1;
        !           284:                (void) memcpy(&elfhdr, buf, sizeof elfhdr);
        !           285:
        !           286:                /*
        !           287:                 * If the system byteorder does not equal the
        !           288:                 * object byteorder then don't test.
        !           289:                 * XXX - we could conceivably fix up the "dophn_XXX()" and
        !           290:                 * "doshn()" routines to extract stuff in the right
        !           291:                 * byte order....
        !           292:                 */
        !           293:                if ((u.c[sizeof(long) - 1] + 1) == elfhdr.e_ident[5]) {
        !           294: #ifdef notyet
        !           295:                        if (elfhdr.e_type == ET_CORE)
        !           296:                                dophn_core(fd, elfhdr.e_phoff, elfhdr.e_phnum,
        !           297:                                      elfhdr.e_phentsize, buf);
        !           298:                        else
        !           299: #endif
        !           300:                        {
        !           301: #ifdef notyet
        !           302:                                if (elfhdr.e_type == ET_EXEC) {
        !           303:                                        dophn_exec(fd, elfhdr.e_phoff,
        !           304:                                            elfhdr.e_phnum,
        !           305:                                              elfhdr.e_phentsize, buf);
        !           306:                                }
        !           307: #endif
        !           308:                                doshn(fd, elfhdr.e_shoff, elfhdr.e_shnum,
        !           309:                                      elfhdr.e_shentsize, buf);
        !           310:                        }
        !           311:                }
        !           312:                return;
        !           313:        }
        !           314: }
        !           315: #endif