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

1.2     ! mickey      1: /*     $OpenBSD: readelf.c,v 1.1 1997/02/09 23:58:33 millert Exp $     */
1.1       millert     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)
1.2     ! mickey     34:                err(1, "lseek failed");
1.1       millert    35:
                     36:        for ( ; num; num--) {
                     37:                if (read(fd, buf, size) == -1)
1.2     ! mickey     38:                        err(1, "read failed");
1.1       millert    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)
1.2     ! mickey     64:                err(1, "lseek failed");
1.1       millert    65:
                     66:        for ( ; num; num--) {
                     67:                if (read(fd, buf, size) == -1)
1.2     ! mickey     68:                        err(1, "read failed");
1.1       millert    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)
1.2     ! mickey    125:                        err(1, "lseek failed");
1.1       millert   126:                if (read(fd, buf, size) == -1)
1.2     ! mickey    127:                        err(1, "read failed");
1.1       millert   128:                off += size;
                    129:                if (ph->p_type != PT_NOTE)
                    130:                        continue;
                    131:                if (lseek(fd, ph->p_offset, SEEK_SET) == -1)
1.2     ! mickey    132:                        err(1, "lseek failed");
1.1       millert   133:                bufsize = read(fd, nbuf, BUFSIZ);
                    134:                if (bufsize == -1)
1.2     ! mickey    135:                        err(1, "read failed");
1.1       millert   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