00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "file.h"
00028
00029 #ifdef BUILTIN_ELF
00030 #include <string.h>
00031 #include <ctype.h>
00032 #include <stdlib.h>
00033 #ifdef HAVE_UNISTD_H
00034 #include <unistd.h>
00035 #endif
00036
00037 #include "readelf.h"
00038
00039 #ifndef lint
00040 FILE_RCSID("@(#)$File: readelf.c,v 1.63 2007/01/16 14:56:45 ljt Exp $")
00041 #endif
00042
00043 #ifdef ELFCORE
00044 private int dophn_core(struct magic_set *ms, int class, int swap, int fd,
00045 off_t off, int num, size_t size, off_t fsize, int *flags)
00046 ;
00047 #endif
00048 private int dophn_exec(struct magic_set *ms, int class, int swap, int fd,
00049 off_t off, int num, size_t size, off_t fsize, int *flags, int sh_num)
00050 ;
00051 private int doshn(struct magic_set *ms, int class, int swap, int fd, off_t off,
00052 int num, size_t size, int *flags)
00053 ;
00054 private size_t donote(struct magic_set *ms, unsigned char *nbuf, size_t offset,
00055 size_t size, int class, int swap, size_t align, int *flags)
00056 ;
00057
00058 #define ELF_ALIGN(a) ((((a) + align - 1) / align) * align)
00059
00060 #define isquote(c) (strchr("'\"`", (c)) != NULL)
00061
00062 private uint16_t getu16(int, uint16_t)
00063 ;
00064 private uint32_t getu32(int, uint32_t)
00065 ;
00066 private uint64_t getu64(int, uint64_t)
00067 ;
00068
00069 private uint16_t
00070 getu16(int swap, uint16_t value)
00071 {
00072 union {
00073 uint16_t ui;
00074 char c[2];
00075 } retval, tmpval;
00076
00077 if (swap) {
00078 tmpval.ui = value;
00079
00080 retval.c[0] = tmpval.c[1];
00081 retval.c[1] = tmpval.c[0];
00082
00083 return retval.ui;
00084 } else
00085 return value;
00086 }
00087
00088 private uint32_t
00089 getu32(int swap, uint32_t value)
00090 {
00091 union {
00092 uint32_t ui;
00093 char c[4];
00094 } retval, tmpval;
00095
00096 if (swap) {
00097 tmpval.ui = value;
00098
00099 retval.c[0] = tmpval.c[3];
00100 retval.c[1] = tmpval.c[2];
00101 retval.c[2] = tmpval.c[1];
00102 retval.c[3] = tmpval.c[0];
00103
00104 return retval.ui;
00105 } else
00106 return value;
00107 }
00108
00109 private uint64_t
00110 getu64(int swap, uint64_t value)
00111 {
00112 union {
00113 uint64_t ui;
00114 char c[8];
00115 } retval, tmpval;
00116
00117 if (swap) {
00118 tmpval.ui = value;
00119
00120 retval.c[0] = tmpval.c[7];
00121 retval.c[1] = tmpval.c[6];
00122 retval.c[2] = tmpval.c[5];
00123 retval.c[3] = tmpval.c[4];
00124 retval.c[4] = tmpval.c[3];
00125 retval.c[5] = tmpval.c[2];
00126 retval.c[6] = tmpval.c[1];
00127 retval.c[7] = tmpval.c[0];
00128
00129 return retval.ui;
00130 } else
00131 return value;
00132 }
00133
00134 #ifdef USE_ARRAY_FOR_64BIT_TYPES
00135 # define elf_getu64(swap, array) \
00136 ((swap ? ((uint64_t)getu32(swap, array[0])) << 32 : getu32(swap, array[0])) + \
00137 (swap ? getu32(swap, array[1]) : ((uint64_t)getu32(swap, array[1]) << 32)))
00138 #else
00139 # define elf_getu64(swap, value) getu64(swap, value)
00140 #endif
00141
00142 #define xsh_addr (class == ELFCLASS32 \
00143 ? (void *) &sh32 \
00144 : (void *) &sh64)
00145 #define xsh_sizeof (class == ELFCLASS32 \
00146 ? sizeof sh32 \
00147 : sizeof sh64)
00148 #define xsh_size (class == ELFCLASS32 \
00149 ? getu32(swap, sh32.sh_size) \
00150 : getu64(swap, sh64.sh_size))
00151 #define xsh_offset (class == ELFCLASS32 \
00152 ? getu32(swap, sh32.sh_offset) \
00153 : getu64(swap, sh64.sh_offset))
00154 #define xsh_type (class == ELFCLASS32 \
00155 ? getu32(swap, sh32.sh_type) \
00156 : getu32(swap, sh64.sh_type))
00157 #define xph_addr (class == ELFCLASS32 \
00158 ? (void *) &ph32 \
00159 : (void *) &ph64)
00160 #define xph_sizeof (class == ELFCLASS32 \
00161 ? sizeof ph32 \
00162 : sizeof ph64)
00163 #define xph_type (class == ELFCLASS32 \
00164 ? getu32(swap, ph32.p_type) \
00165 : getu32(swap, ph64.p_type))
00166 #define xph_offset (off_t)(class == ELFCLASS32 \
00167 ? getu32(swap, ph32.p_offset) \
00168 : getu64(swap, ph64.p_offset))
00169 #define xph_align (size_t)((class == ELFCLASS32 \
00170 ? (off_t) (ph32.p_align ? \
00171 getu32(swap, ph32.p_align) : 4) \
00172 : (off_t) (ph64.p_align ? \
00173 getu64(swap, ph64.p_align) : 4)))
00174 #define xph_filesz (size_t)((class == ELFCLASS32 \
00175 ? getu32(swap, ph32.p_filesz) \
00176 : getu64(swap, ph64.p_filesz)))
00177 #define xnh_addr (class == ELFCLASS32 \
00178 ? (void *) &nh32 \
00179 : (void *) &nh64)
00180 #define xph_memsz (size_t)((class == ELFCLASS32 \
00181 ? getu32(swap, ph32.p_memsz) \
00182 : getu64(swap, ph64.p_memsz)))
00183 #define xnh_sizeof (class == ELFCLASS32 \
00184 ? sizeof nh32 \
00185 : sizeof nh64)
00186 #define xnh_type (class == ELFCLASS32 \
00187 ? getu32(swap, nh32.n_type) \
00188 : getu32(swap, nh64.n_type))
00189 #define xnh_namesz (class == ELFCLASS32 \
00190 ? getu32(swap, nh32.n_namesz) \
00191 : getu32(swap, nh64.n_namesz))
00192 #define xnh_descsz (class == ELFCLASS32 \
00193 ? getu32(swap, nh32.n_descsz) \
00194 : getu32(swap, nh64.n_descsz))
00195 #define prpsoffsets(i) (class == ELFCLASS32 \
00196 ? prpsoffsets32[i] \
00197 : prpsoffsets64[i])
00198
00199 #ifdef ELFCORE
00200
00201 size_t prpsoffsets32[] = {
00202 8,
00203 28,
00204 44,
00205 84,
00206 };
00207
00208
00209 size_t prpsoffsets64[] = {
00210 16,
00211 40,
00212 56,
00213 120,
00214 };
00215
00216 #define NOFFSETS32 (sizeof prpsoffsets32 / sizeof prpsoffsets32[0])
00217 #define NOFFSETS64 (sizeof prpsoffsets64 / sizeof prpsoffsets64[0])
00218
00219 #define NOFFSETS (class == ELFCLASS32 ? NOFFSETS32 : NOFFSETS64)
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 #define OS_STYLE_SVR4 0
00243 #define OS_STYLE_FREEBSD 1
00244 #define OS_STYLE_NETBSD 2
00245
00246
00247 private const char *os_style_names[] = {
00248 "SVR4",
00249 "FreeBSD",
00250 "NetBSD",
00251 };
00252
00253 #define FLAGS_DID_CORE 1
00254 #define FLAGS_DID_NOTE 2
00255
00256 private int
00257 dophn_core(struct magic_set *ms, int class, int swap, int fd, off_t off,
00258 int num, size_t size, off_t fsize, int *flags)
00259 {
00260 Elf32_Phdr ph32;
00261 Elf64_Phdr ph64;
00262 size_t offset;
00263 unsigned char nbuf[BUFSIZ];
00264 ssize_t bufsize;
00265 off_t savedoffset;
00266 struct stat st;
00267
00268 if (fstat(fd, &st) < 0) {
00269 file_badread(ms);
00270 return -1;
00271 }
00272
00273 if (size != xph_sizeof) {
00274 if (file_printf(ms, ", corrupted program header size") == -1)
00275 return -1;
00276 return 0;
00277 }
00278
00279
00280
00281
00282 for ( ; num; num--) {
00283 if ((savedoffset = lseek(fd, off, SEEK_SET)) == (off_t)-1) {
00284 file_badseek(ms);
00285 return -1;
00286 }
00287 if (read(fd, xph_addr, xph_sizeof) == -1) {
00288 file_badread(ms);
00289 return -1;
00290 }
00291 if (xph_offset > fsize) {
00292 if (lseek(fd, savedoffset, SEEK_SET) == (off_t)-1) {
00293 file_badseek(ms);
00294 return -1;
00295 }
00296 continue;
00297 }
00298
00299 off += size;
00300 if (xph_type != PT_NOTE)
00301 continue;
00302
00303
00304
00305
00306
00307 if (lseek(fd, xph_offset, SEEK_SET) == (off_t)-1) {
00308 file_badseek(ms);
00309 return -1;
00310 }
00311 bufsize = read(fd, nbuf,
00312 ((xph_filesz < sizeof(nbuf)) ? xph_filesz : sizeof(nbuf)));
00313 if (bufsize == -1) {
00314 file_badread(ms);
00315 return -1;
00316 }
00317 offset = 0;
00318 for (;;) {
00319 if (offset >= (size_t)bufsize)
00320 break;
00321 offset = donote(ms, nbuf, offset, (size_t)bufsize,
00322 class, swap, 4, flags);
00323 if (offset == 0)
00324 break;
00325
00326 }
00327 }
00328 return 0;
00329 }
00330 #endif
00331
00332 private size_t
00333 donote(struct magic_set *ms, unsigned char *nbuf, size_t offset, size_t size,
00334 int class, int swap, size_t align, int *flags)
00335 {
00336 Elf32_Nhdr nh32;
00337 Elf64_Nhdr nh64;
00338 size_t noff, doff;
00339 #ifdef ELFCORE
00340 int os_style = -1;
00341 #endif
00342 uint32_t namesz, descsz;
00343
00344 (void)memcpy(xnh_addr, &nbuf[offset], xnh_sizeof);
00345 offset += xnh_sizeof;
00346
00347 namesz = xnh_namesz;
00348 descsz = xnh_descsz;
00349 if ((namesz == 0) && (descsz == 0)) {
00350
00351
00352
00353 return (offset >= size) ? offset : size;
00354 }
00355
00356 if (namesz & 0x80000000) {
00357 (void)file_printf(ms, ", bad note name size 0x%lx",
00358 (unsigned long)namesz);
00359 return offset;
00360 }
00361
00362 if (descsz & 0x80000000) {
00363 (void)file_printf(ms, ", bad note description size 0x%lx",
00364 (unsigned long)descsz);
00365 return offset;
00366 }
00367
00368
00369 noff = offset;
00370 doff = ELF_ALIGN(offset + namesz);
00371
00372 if (offset + namesz > size) {
00373
00374
00375
00376 return doff;
00377 }
00378
00379 offset = ELF_ALIGN(doff + descsz);
00380 if (doff + descsz > size) {
00381
00382
00383
00384 return (offset >= size) ? offset : size;
00385 }
00386
00387 if (*flags & FLAGS_DID_NOTE)
00388 goto core;
00389
00390 if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 &&
00391 xnh_type == NT_GNU_VERSION && descsz == 16) {
00392 uint32_t desc[4];
00393 (void)memcpy(desc, &nbuf[doff], sizeof(desc));
00394
00395 if (file_printf(ms, ", for GNU/") == -1)
00396 return size;
00397 switch (getu32(swap, desc[0])) {
00398 case GNU_OS_LINUX:
00399 if (file_printf(ms, "Linux") == -1)
00400 return size;
00401 break;
00402 case GNU_OS_HURD:
00403 if (file_printf(ms, "Hurd") == -1)
00404 return size;
00405 break;
00406 case GNU_OS_SOLARIS:
00407 if (file_printf(ms, "Solaris") == -1)
00408 return size;
00409 break;
00410 default:
00411 if (file_printf(ms, "<unknown>") == -1)
00412 return size;
00413 }
00414 if (file_printf(ms, " %d.%d.%d", getu32(swap, desc[1]),
00415 getu32(swap, desc[2]), getu32(swap, desc[3])) == -1)
00416 return size;
00417 *flags |= FLAGS_DID_NOTE;
00418 return size;
00419 }
00420
00421 if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0 &&
00422 xnh_type == NT_NETBSD_VERSION && descsz == 4) {
00423 uint32_t desc;
00424 (void)memcpy(&desc, &nbuf[doff], sizeof(desc));
00425 desc = getu32(swap, desc);
00426
00427 if (file_printf(ms, ", for NetBSD") == -1)
00428 return size;
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441 if (desc > 100000000U) {
00442 uint32_t ver_patch = (desc / 100) % 100;
00443 uint32_t ver_rel = (desc / 10000) % 100;
00444 uint32_t ver_min = (desc / 1000000) % 100;
00445 uint32_t ver_maj = desc / 100000000;
00446
00447 if (file_printf(ms, " %u.%u", ver_maj, ver_min) == -1)
00448 return size;
00449 if (ver_rel == 0 && ver_patch != 0) {
00450 if (file_printf(ms, ".%u", ver_patch) == -1)
00451 return size;
00452 } else if (ver_rel != 0) {
00453 while (ver_rel > 26) {
00454 if (file_printf(ms, "Z") == -1)
00455 return size;
00456 ver_rel -= 26;
00457 }
00458 if (file_printf(ms, "%c", 'A' + ver_rel - 1)
00459 == -1)
00460 return size;
00461 }
00462 }
00463 *flags |= FLAGS_DID_NOTE;
00464 return size;
00465 }
00466
00467 if (namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0 &&
00468 xnh_type == NT_FREEBSD_VERSION && descsz == 4) {
00469 uint32_t desc;
00470 (void)memcpy(&desc, &nbuf[doff], sizeof(desc));
00471 desc = getu32(swap, desc);
00472 if (file_printf(ms, ", for FreeBSD") == -1)
00473 return size;
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501 if (desc == 460002) {
00502 if (file_printf(ms, " 4.6.2") == -1)
00503 return size;
00504 } else if (desc < 460100) {
00505 if (file_printf(ms, " %d.%d", desc / 100000,
00506 desc / 10000 % 10) == -1)
00507 return size;
00508 if (desc / 1000 % 10 > 0)
00509 if (file_printf(ms, ".%d", desc / 1000 % 10)
00510 == -1)
00511 return size;
00512 if ((desc % 1000 > 0) || (desc % 100000 == 0))
00513 if (file_printf(ms, " (%d)", desc) == -1)
00514 return size;
00515 } else if (desc < 500000) {
00516 if (file_printf(ms, " %d.%d", desc / 100000,
00517 desc / 10000 % 10 + desc / 1000 % 10) == -1)
00518 return size;
00519 if (desc / 100 % 10 > 0) {
00520 if (file_printf(ms, " (%d)", desc) == -1)
00521 return size;
00522 } else if (desc / 10 % 10 > 0) {
00523 if (file_printf(ms, ".%d", desc / 10 % 10)
00524 == -1)
00525 return size;
00526 }
00527 } else {
00528 if (file_printf(ms, " %d.%d", desc / 100000,
00529 desc / 1000 % 100) == -1)
00530 return size;
00531 if ((desc / 100 % 10 > 0) ||
00532 (desc % 100000 / 100 == 0)) {
00533 if (file_printf(ms, " (%d)", desc) == -1)
00534 return size;
00535 } else if (desc / 10 % 10 > 0) {
00536 if (file_printf(ms, ".%d", desc / 10 % 10)
00537 == -1)
00538 return size;
00539 }
00540 }
00541 *flags |= FLAGS_DID_NOTE;
00542 return size;
00543 }
00544
00545 if (namesz == 8 && strcmp((char *)&nbuf[noff], "OpenBSD") == 0 &&
00546 xnh_type == NT_OPENBSD_VERSION && descsz == 4) {
00547 if (file_printf(ms, ", for OpenBSD") == -1)
00548 return size;
00549
00550 *flags |= FLAGS_DID_NOTE;
00551 return size;
00552 }
00553
00554 if (namesz == 10 && strcmp((char *)&nbuf[noff], "DragonFly") == 0 &&
00555 xnh_type == NT_DRAGONFLY_VERSION && descsz == 4) {
00556 uint32_t desc;
00557 if (file_printf(ms, ", for DragonFly") == -1)
00558 return size;
00559 (void)memcpy(&desc, &nbuf[doff], sizeof(desc));
00560 desc = getu32(swap, desc);
00561 if (file_printf(ms, " %d.%d.%d", desc / 100000,
00562 desc / 10000 % 10, desc % 10000) == -1)
00563 return size;
00564 *flags |= FLAGS_DID_NOTE;
00565 return size;
00566 }
00567
00568 core:
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583 if ((namesz == 4 && strncmp((char *)&nbuf[noff], "CORE", 4) == 0) ||
00584 (namesz == 5 && strcmp((char *)&nbuf[noff], "CORE") == 0)) {
00585 os_style = OS_STYLE_SVR4;
00586 }
00587
00588 if ((namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0)) {
00589 os_style = OS_STYLE_FREEBSD;
00590 }
00591
00592 if ((namesz >= 11 && strncmp((char *)&nbuf[noff], "NetBSD-CORE", 11)
00593 == 0)) {
00594 os_style = OS_STYLE_NETBSD;
00595 }
00596
00597 #ifdef ELFCORE
00598 if ((*flags & FLAGS_DID_CORE) != 0)
00599 return size;
00600
00601 if (os_style != -1) {
00602 if (file_printf(ms, ", %s-style", os_style_names[os_style])
00603 == -1)
00604 return size;
00605 }
00606
00607 switch (os_style) {
00608 case OS_STYLE_NETBSD:
00609 if (xnh_type == NT_NETBSD_CORE_PROCINFO) {
00610 uint32_t signo;
00611
00612
00613
00614
00615
00616 if (file_printf(ms, ", from '%.31s'",
00617 &nbuf[doff + 0x7c]) == -1)
00618 return size;
00619
00620
00621
00622
00623
00624 (void)memcpy(&signo, &nbuf[doff + 0x08],
00625 sizeof(signo));
00626 if (file_printf(ms, " (signal %u)",
00627 getu32(swap, signo)) == -1)
00628 return size;
00629 return size;
00630 }
00631 break;
00632
00633 default:
00634 if (xnh_type == NT_PRPSINFO) {
00635 size_t i, j;
00636 unsigned char c;
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647 for (i = 0; i < NOFFSETS; i++) {
00648 size_t reloffset = prpsoffsets(i);
00649 size_t noffset = doff + reloffset;
00650 for (j = 0; j < 16; j++, noffset++,
00651 reloffset++) {
00652
00653
00654
00655
00656
00657 if (noffset >= size)
00658 goto tryanother;
00659
00660
00661
00662
00663
00664
00665
00666 if (reloffset >= descsz)
00667 goto tryanother;
00668
00669 c = nbuf[noffset];
00670 if (c == '\0') {
00671
00672
00673
00674
00675
00676
00677
00678 if (j == 0)
00679 goto tryanother;
00680 else
00681 break;
00682 } else {
00683
00684
00685
00686
00687
00688 if (!isprint(c) || isquote(c))
00689 goto tryanother;
00690 }
00691 }
00692
00693
00694
00695 if (file_printf(ms, ", from '%.16s'",
00696 &nbuf[doff + prpsoffsets(i)]) == -1)
00697 return size;
00698 return size;
00699
00700 tryanother:
00701 ;
00702 }
00703 }
00704 break;
00705 }
00706 #endif
00707 *flags |= FLAGS_DID_CORE;
00708 return offset;
00709 }
00710
00711 private int
00712 doshn(struct magic_set *ms, int class, int swap, int fd, off_t off, int num,
00713 size_t size, int *flags)
00714 {
00715 Elf32_Shdr sh32;
00716 Elf64_Shdr sh64;
00717 int stripped = 1;
00718 void *nbuf;
00719 off_t noff;
00720
00721 if (size != xsh_sizeof) {
00722 if (file_printf(ms, ", corrupted section header size") == -1)
00723 return -1;
00724 return 0;
00725 }
00726
00727 if (lseek(fd, off, SEEK_SET) == (off_t)-1) {
00728 file_badseek(ms);
00729 return -1;
00730 }
00731
00732 for ( ; num; num--) {
00733 if (read(fd, xsh_addr, xsh_sizeof) == -1) {
00734 file_badread(ms);
00735 return -1;
00736 }
00737 switch (xsh_type) {
00738 case SHT_SYMTAB:
00739 #if 0
00740 case SHT_DYNSYM:
00741 #endif
00742 stripped = 0;
00743 break;
00744 case SHT_NOTE:
00745 if ((off = lseek(fd, (off_t)0, SEEK_CUR)) ==
00746 (off_t)-1) {
00747 file_badread(ms);
00748 return -1;
00749 }
00750 if ((nbuf = malloc((size_t)xsh_size)) == NULL) {
00751 file_error(ms, errno, "Cannot allocate memory"
00752 " for note");
00753 return -1;
00754 }
00755 if ((noff = lseek(fd, (off_t)xsh_offset, SEEK_SET)) ==
00756 (off_t)-1) {
00757 file_badread(ms);
00758 free(nbuf);
00759 return -1;
00760 }
00761 if (read(fd, nbuf, (size_t)xsh_size) !=
00762 (ssize_t)xsh_size) {
00763 free(nbuf);
00764 file_badread(ms);
00765 return -1;
00766 }
00767
00768 noff = 0;
00769 for (;;) {
00770 if (noff >= (size_t)xsh_size)
00771 break;
00772 noff = donote(ms, nbuf, (size_t)noff,
00773 (size_t)xsh_size, class, swap, 4,
00774 flags);
00775 if (noff == 0)
00776 break;
00777 }
00778 if ((lseek(fd, off, SEEK_SET)) == (off_t)-1) {
00779 free(nbuf);
00780 file_badread(ms);
00781 return -1;
00782 }
00783 free(nbuf);
00784 break;
00785 }
00786 }
00787 if (file_printf(ms, ", %sstripped", stripped ? "" : "not ") == -1)
00788 return -1;
00789 return 0;
00790 }
00791
00792
00793
00794
00795
00796
00797 private int
00798 dophn_exec(struct magic_set *ms, int class, int swap, int fd, off_t off,
00799 int num, size_t size, off_t fsize, int *flags, int sh_num)
00800 {
00801 Elf32_Phdr ph32;
00802 Elf64_Phdr ph64;
00803 const char *linking_style = "statically";
00804 const char *shared_libraries = "";
00805 unsigned char nbuf[BUFSIZ];
00806 int bufsize;
00807 size_t offset, align;
00808 off_t savedoffset = (off_t)-1;
00809 struct stat st;
00810
00811 if (fstat(fd, &st) < 0) {
00812 file_badread(ms);
00813 return -1;
00814 }
00815
00816 if (size != xph_sizeof) {
00817 if (file_printf(ms, ", corrupted program header size") == -1)
00818 return -1;
00819 return 0;
00820 }
00821 if (lseek(fd, off, SEEK_SET) == (off_t)-1) {
00822 file_badseek(ms);
00823 return -1;
00824 }
00825
00826 for ( ; num; num--) {
00827 if (read(fd, xph_addr, xph_sizeof) == -1) {
00828 file_badread(ms);
00829 return -1;
00830 }
00831 if (xph_offset > st.st_size && savedoffset != (off_t)-1) {
00832 if (lseek(fd, savedoffset, SEEK_SET) == (off_t)-1) {
00833 file_badseek(ms);
00834 return -1;
00835 }
00836 continue;
00837 }
00838
00839 if ((savedoffset = lseek(fd, (off_t)0, SEEK_CUR)) == (off_t)-1) {
00840 file_badseek(ms);
00841 return -1;
00842 }
00843
00844 if (xph_offset > fsize) {
00845 if (lseek(fd, savedoffset, SEEK_SET) == (off_t)-1) {
00846 file_badseek(ms);
00847 return -1;
00848 }
00849 continue;
00850 }
00851
00852 switch (xph_type) {
00853 case PT_DYNAMIC:
00854 linking_style = "dynamically";
00855 break;
00856 case PT_INTERP:
00857 shared_libraries = " (uses shared libs)";
00858 break;
00859 case PT_NOTE:
00860 if ((align = xph_align) & 0x80000000) {
00861 if (file_printf(ms,
00862 ", invalid note alignment 0x%lx",
00863 (unsigned long)align) == -1)
00864 return -1;
00865 align = 4;
00866 }
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878 if (sh_num)
00879 break;
00880
00881
00882
00883
00884 if (lseek(fd, xph_offset, SEEK_SET)
00885 == (off_t)-1) {
00886 file_badseek(ms);
00887 return -1;
00888 }
00889 bufsize = read(fd, nbuf, ((xph_filesz < sizeof(nbuf)) ?
00890 xph_filesz : sizeof(nbuf)));
00891 if (bufsize == -1) {
00892 file_badread(ms);
00893 return -1;
00894 }
00895 offset = 0;
00896 for (;;) {
00897 if (offset >= (size_t)bufsize)
00898 break;
00899 offset = donote(ms, nbuf, offset,
00900 (size_t)bufsize, class, swap, align,
00901 flags);
00902 if (offset == 0)
00903 break;
00904 }
00905 if (lseek(fd, savedoffset, SEEK_SET) == (off_t)-1) {
00906 file_badseek(ms);
00907 return -1;
00908 }
00909 break;
00910 }
00911 }
00912 if (file_printf(ms, ", %s linked%s", linking_style, shared_libraries)
00913 == -1)
00914 return -1;
00915 return 0;
00916 }
00917
00918
00919 protected int
00920 file_tryelf(struct magic_set *ms, int fd, const unsigned char *buf,
00921 size_t nbytes)
00922 {
00923 union {
00924 int32_t l;
00925 char c[sizeof (int32_t)];
00926 } u;
00927 int class;
00928 int swap;
00929 struct stat st;
00930 off_t fsize;
00931 int flags = 0;
00932
00933
00934
00935
00936 if((lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) && (errno == ESPIPE))
00937 fd = file_pipe2file(ms, fd, buf, nbytes);
00938
00939 if (fstat(fd, &st) == -1) {
00940 file_badread(ms);
00941 return -1;
00942 }
00943 fsize = st.st_size;
00944
00945
00946
00947
00948
00949
00950
00951 if (buf[EI_MAG0] != ELFMAG0
00952 || (buf[EI_MAG1] != ELFMAG1 && buf[EI_MAG1] != OLFMAG1)
00953 || buf[EI_MAG2] != ELFMAG2 || buf[EI_MAG3] != ELFMAG3)
00954 return 0;
00955
00956
00957 class = buf[EI_CLASS];
00958
00959 if (class == ELFCLASS32) {
00960 Elf32_Ehdr elfhdr;
00961 if (nbytes <= sizeof (Elf32_Ehdr))
00962 return 0;
00963
00964
00965 u.l = 1;
00966 (void) memcpy(&elfhdr, buf, sizeof elfhdr);
00967 swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[EI_DATA];
00968
00969 if (getu16(swap, elfhdr.e_type) == ET_CORE) {
00970 #ifdef ELFCORE
00971 if (dophn_core(ms, class, swap, fd,
00972 (off_t)getu32(swap, elfhdr.e_phoff),
00973 getu16(swap, elfhdr.e_phnum),
00974 (size_t)getu16(swap, elfhdr.e_phentsize),
00975 fsize, &flags) == -1)
00976 return -1;
00977 #else
00978 ;
00979 #endif
00980 } else {
00981 if (getu16(swap, elfhdr.e_type) == ET_EXEC) {
00982 if (dophn_exec(ms, class, swap,
00983 fd, (off_t)getu32(swap, elfhdr.e_phoff),
00984 getu16(swap, elfhdr.e_phnum),
00985 (size_t)getu16(swap, elfhdr.e_phentsize),
00986 fsize, &flags,
00987 getu16(swap, elfhdr.e_shnum))
00988 == -1)
00989 return -1;
00990 }
00991 if (doshn(ms, class, swap, fd,
00992 (off_t)getu32(swap, elfhdr.e_shoff),
00993 getu16(swap, elfhdr.e_shnum),
00994 (size_t)getu16(swap, elfhdr.e_shentsize),
00995 &flags) == -1)
00996 return -1;
00997 }
00998 return 1;
00999 }
01000
01001 if (class == ELFCLASS64) {
01002 Elf64_Ehdr elfhdr;
01003 if (nbytes <= sizeof (Elf64_Ehdr))
01004 return 0;
01005
01006
01007 u.l = 1;
01008 (void) memcpy(&elfhdr, buf, sizeof elfhdr);
01009 swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[EI_DATA];
01010
01011 if (getu16(swap, elfhdr.e_type) == ET_CORE) {
01012 #ifdef ELFCORE
01013 if (dophn_core(ms, class, swap, fd,
01014 (off_t)elf_getu64(swap, elfhdr.e_phoff),
01015 getu16(swap, elfhdr.e_phnum),
01016 (size_t)getu16(swap, elfhdr.e_phentsize),
01017 fsize, &flags) == -1)
01018 return -1;
01019 #else
01020 ;
01021 #endif
01022 } else {
01023 if (getu16(swap, elfhdr.e_type) == ET_EXEC) {
01024 if (dophn_exec(ms, class, swap, fd,
01025 (off_t)elf_getu64(swap, elfhdr.e_phoff),
01026 getu16(swap, elfhdr.e_phnum),
01027 (size_t)getu16(swap, elfhdr.e_phentsize),
01028 fsize, &flags,
01029 getu16(swap, elfhdr.e_shnum)) == -1)
01030 return -1;
01031 }
01032 if (doshn(ms, class, swap, fd,
01033 (off_t)elf_getu64(swap, elfhdr.e_shoff),
01034 getu16(swap, elfhdr.e_shnum),
01035 (size_t)getu16(swap, elfhdr.e_shentsize), &flags)
01036 == -1)
01037 return -1;
01038 }
01039 return 1;
01040 }
01041 return 0;
01042 }
01043 #endif