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