readelf.c revision 139368
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#ifdef BUILTIN_ELF 30#include <string.h> 31#include <ctype.h> 32#include <stdlib.h> 33#ifdef HAVE_UNISTD_H 34#include <unistd.h> 35#endif 36 37#include "readelf.h" 38 39#ifndef lint 40FILE_RCSID("@(#)$Id: readelf.c,v 1.45 2004/11/24 17:38:24 christos Exp $") 41#endif 42 43#ifdef ELFCORE 44private int dophn_core(struct magic_set *, int, int, int, off_t, int, size_t); 45#endif 46private int dophn_exec(struct magic_set *, int, int, int, off_t, int, size_t); 47private int doshn(struct magic_set *, int, int, int, off_t, int, size_t); 48private size_t donote(struct magic_set *, unsigned char *, size_t, size_t, int, 49 int, size_t); 50 51#define ELF_ALIGN(a) ((((a) + align - 1) / align) * align) 52 53private uint16_t getu16(int, uint16_t); 54private uint32_t getu32(int, uint32_t); 55private uint64_t getu64(int, uint64_t); 56 57private uint16_t 58getu16(int swap, uint16_t value) 59{ 60 union { 61 uint16_t ui; 62 char c[2]; 63 } retval, tmpval; 64 65 if (swap) { 66 tmpval.ui = value; 67 68 retval.c[0] = tmpval.c[1]; 69 retval.c[1] = tmpval.c[0]; 70 71 return retval.ui; 72 } else 73 return value; 74} 75 76private uint32_t 77getu32(int swap, uint32_t value) 78{ 79 union { 80 uint32_t ui; 81 char c[4]; 82 } retval, tmpval; 83 84 if (swap) { 85 tmpval.ui = value; 86 87 retval.c[0] = tmpval.c[3]; 88 retval.c[1] = tmpval.c[2]; 89 retval.c[2] = tmpval.c[1]; 90 retval.c[3] = tmpval.c[0]; 91 92 return retval.ui; 93 } else 94 return value; 95} 96 97private uint64_t 98getu64(int swap, uint64_t value) 99{ 100 union { 101 uint64_t ui; 102 char c[8]; 103 } retval, tmpval; 104 105 if (swap) { 106 tmpval.ui = value; 107 108 retval.c[0] = tmpval.c[7]; 109 retval.c[1] = tmpval.c[6]; 110 retval.c[2] = tmpval.c[5]; 111 retval.c[3] = tmpval.c[4]; 112 retval.c[4] = tmpval.c[3]; 113 retval.c[5] = tmpval.c[2]; 114 retval.c[6] = tmpval.c[1]; 115 retval.c[7] = tmpval.c[0]; 116 117 return retval.ui; 118 } else 119 return value; 120} 121 122#define sh_addr (class == ELFCLASS32 \ 123 ? (void *) &sh32 \ 124 : (void *) &sh64) 125#define sh_size (class == ELFCLASS32 \ 126 ? sizeof sh32 \ 127 : sizeof sh64) 128#define shs_type (class == ELFCLASS32 \ 129 ? getu32(swap, sh32.sh_type) \ 130 : getu32(swap, sh64.sh_type)) 131#define ph_addr (class == ELFCLASS32 \ 132 ? (void *) &ph32 \ 133 : (void *) &ph64) 134#define ph_size (class == ELFCLASS32 \ 135 ? sizeof ph32 \ 136 : sizeof ph64) 137#define ph_type (class == ELFCLASS32 \ 138 ? getu32(swap, ph32.p_type) \ 139 : getu32(swap, ph64.p_type)) 140#define ph_offset (class == ELFCLASS32 \ 141 ? getu32(swap, ph32.p_offset) \ 142 : getu64(swap, ph64.p_offset)) 143#define ph_align (size_t)((class == ELFCLASS32 \ 144 ? (off_t) (ph32.p_align ? \ 145 getu32(swap, ph32.p_align) : 4) \ 146 : (off_t) (ph64.p_align ? \ 147 getu64(swap, ph64.p_align) : 4))) 148#define ph_filesz (size_t)((class == ELFCLASS32 \ 149 ? getu32(swap, ph32.p_filesz) \ 150 : getu64(swap, ph64.p_filesz))) 151#define ph_memsz (size_t)((class == ELFCLASS32 \ 152 ? getu32(swap, ph32.p_memsz) \ 153 : getu64(swap, ph64.p_memsz))) 154#define nh_size (class == ELFCLASS32 \ 155 ? sizeof nh32 \ 156 : sizeof nh64) 157#define nh_type (class == ELFCLASS32 \ 158 ? getu32(swap, nh32.n_type) \ 159 : getu32(swap, nh64.n_type)) 160#define nh_namesz (class == ELFCLASS32 \ 161 ? getu32(swap, nh32.n_namesz) \ 162 : getu32(swap, nh64.n_namesz)) 163#define nh_descsz (class == ELFCLASS32 \ 164 ? getu32(swap, nh32.n_descsz) \ 165 : getu32(swap, nh64.n_descsz)) 166#define prpsoffsets(i) (class == ELFCLASS32 \ 167 ? prpsoffsets32[i] \ 168 : prpsoffsets64[i]) 169 170#ifdef ELFCORE 171size_t prpsoffsets32[] = { 172 8, /* FreeBSD */ 173 28, /* Linux 2.0.36 */ 174 32, /* Linux (I forget which kernel version) */ 175 84, /* SunOS 5.x */ 176}; 177 178size_t prpsoffsets64[] = { 179 120, /* SunOS 5.x, 64-bit */ 180}; 181 182#define NOFFSETS32 (sizeof prpsoffsets32 / sizeof prpsoffsets32[0]) 183#define NOFFSETS64 (sizeof prpsoffsets64 / sizeof prpsoffsets64[0]) 184 185#define NOFFSETS (class == ELFCLASS32 ? NOFFSETS32 : NOFFSETS64) 186 187/* 188 * Look through the program headers of an executable image, searching 189 * for a PT_NOTE section of type NT_PRPSINFO, with a name "CORE" or 190 * "FreeBSD"; if one is found, try looking in various places in its 191 * contents for a 16-character string containing only printable 192 * characters - if found, that string should be the name of the program 193 * that dropped core. Note: right after that 16-character string is, 194 * at least in SunOS 5.x (and possibly other SVR4-flavored systems) and 195 * Linux, a longer string (80 characters, in 5.x, probably other 196 * SVR4-flavored systems, and Linux) containing the start of the 197 * command line for that program. 198 * 199 * The signal number probably appears in a section of type NT_PRSTATUS, 200 * but that's also rather OS-dependent, in ways that are harder to 201 * dissect with heuristics, so I'm not bothering with the signal number. 202 * (I suppose the signal number could be of interest in situations where 203 * you don't have the binary of the program that dropped core; if you 204 * *do* have that binary, the debugger will probably tell you what 205 * signal it was.) 206 */ 207 208#define OS_STYLE_SVR4 0 209#define OS_STYLE_FREEBSD 1 210#define OS_STYLE_NETBSD 2 211 212private const char *os_style_names[] = { 213 "SVR4", 214 "FreeBSD", 215 "NetBSD", 216}; 217 218private int 219dophn_core(struct magic_set *ms, int class, int swap, int fd, off_t off, 220 int num, size_t size) 221{ 222 Elf32_Phdr ph32; 223 Elf64_Phdr ph64; 224 size_t offset; 225 unsigned char nbuf[BUFSIZ]; 226 ssize_t bufsize; 227 228 if (size != ph_size) { 229 if (file_printf(ms, ", corrupted program header size") == -1) 230 return -1; 231 return 0; 232 } 233 /* 234 * Loop through all the program headers. 235 */ 236 for ( ; num; num--) { 237 if (lseek(fd, off, SEEK_SET) == (off_t)-1) { 238 file_badseek(ms); 239 return -1; 240 } 241 if (read(fd, ph_addr, ph_size) == -1) { 242 file_badread(ms); 243 return -1; 244 } 245 off += size; 246 if (ph_type != PT_NOTE) 247 continue; 248 249 /* 250 * This is a PT_NOTE section; loop through all the notes 251 * in the section. 252 */ 253 if (lseek(fd, (off_t) ph_offset, SEEK_SET) == (off_t)-1) { 254 file_badseek(ms); 255 return -1; 256 } 257 bufsize = read(fd, nbuf, 258 ((ph_filesz < sizeof(nbuf)) ? ph_filesz : sizeof(nbuf))); 259 if (bufsize == -1) { 260 file_badread(ms); 261 return -1; 262 } 263 offset = 0; 264 for (;;) { 265 if (offset >= (size_t)bufsize) 266 break; 267 offset = donote(ms, nbuf, offset, (size_t)bufsize, 268 class, swap, 4); 269 if (offset == 0) 270 break; 271 272 } 273 } 274 return 0; 275} 276#endif 277 278private size_t 279donote(struct magic_set *ms, unsigned char *nbuf, size_t offset, size_t size, 280 int class, int swap, size_t align) 281{ 282 Elf32_Nhdr nh32; 283 Elf64_Nhdr nh64; 284 size_t noff, doff; 285#ifdef ELFCORE 286 int os_style = -1; 287#endif 288 uint32_t namesz, descsz; 289 290 if (class == ELFCLASS32) 291 memcpy(&nh32, &nbuf[offset], sizeof(nh32)); 292 else 293 memcpy(&nh64, &nbuf[offset], sizeof(nh64)); 294 offset += nh_size; 295 296 namesz = nh_namesz; 297 descsz = nh_descsz; 298 if ((namesz == 0) && (descsz == 0)) { 299 /* 300 * We're out of note headers. 301 */ 302 return offset; 303 } 304 305 if (namesz & 0x80000000) { 306 (void)file_printf(ms, ", bad note name size 0x%lx", 307 (unsigned long)namesz); 308 return offset; 309 } 310 311 if (descsz & 0x80000000) { 312 (void)file_printf(ms, ", bad note description size 0x%lx", 313 (unsigned long)descsz); 314 return offset; 315 } 316 317 318 noff = offset; 319 doff = ELF_ALIGN(offset + namesz); 320 321 if (offset + namesz > size) { 322 /* 323 * We're past the end of the buffer. 324 */ 325 return doff; 326 } 327 328 offset = ELF_ALIGN(doff + descsz); 329 if (doff + descsz > size) { 330 return offset; 331 } 332 333 if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 && 334 nh_type == NT_GNU_VERSION && descsz == 16) { 335 uint32_t desc[4]; 336 (void)memcpy(desc, &nbuf[doff], sizeof(desc)); 337 338 if (file_printf(ms, ", for GNU/") == -1) 339 return size; 340 switch (getu32(swap, desc[0])) { 341 case GNU_OS_LINUX: 342 if (file_printf(ms, "Linux") == -1) 343 return size; 344 break; 345 case GNU_OS_HURD: 346 if (file_printf(ms, "Hurd") == -1) 347 return size; 348 break; 349 case GNU_OS_SOLARIS: 350 if (file_printf(ms, "Solaris") == -1) 351 return size; 352 break; 353 default: 354 if (file_printf(ms, "<unknown>") == -1) 355 return size; 356 } 357 if (file_printf(ms, " %d.%d.%d", getu32(swap, desc[1]), 358 getu32(swap, desc[2]), getu32(swap, desc[3])) == -1) 359 return size; 360 return size; 361 } 362 363 if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0 && 364 nh_type == NT_NETBSD_VERSION && descsz == 4) { 365 uint32_t desc; 366 (void)memcpy(&desc, &nbuf[doff], sizeof(desc)); 367 desc = getu32(swap, desc); 368 369 if (file_printf(ms, ", for NetBSD") == -1) 370 return size; 371 /* 372 * The version number used to be stuck as 199905, and was thus 373 * basically content-free. Newer versions of NetBSD have fixed 374 * this and now use the encoding of __NetBSD_Version__: 375 * 376 * MMmmrrpp00 377 * 378 * M = major version 379 * m = minor version 380 * r = release ["",A-Z,Z[A-Z] but numeric] 381 * p = patchlevel 382 */ 383 if (desc > 100000000U) { 384 u_int ver_patch = (desc / 100) % 100; 385 u_int ver_rel = (desc / 10000) % 100; 386 u_int ver_min = (desc / 1000000) % 100; 387 u_int ver_maj = desc / 100000000; 388 389 if (file_printf(ms, " %u.%u", ver_maj, ver_min) == -1) 390 return size; 391 if (ver_rel == 0 && ver_patch != 0) { 392 if (file_printf(ms, ".%u", ver_patch) == -1) 393 return size; 394 } else if (ver_rel != 0) { 395 while (ver_rel > 26) { 396 file_printf(ms, "Z"); 397 ver_rel -= 26; 398 } 399 file_printf(ms, "%c", 'A' + ver_rel - 1); 400 } 401 } 402 return size; 403 } 404 405 if (namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0 && 406 nh_type == NT_FREEBSD_VERSION && descsz == 4) { 407 uint32_t desc; 408 (void)memcpy(&desc, &nbuf[doff], sizeof(desc)); 409 desc = getu32(swap, desc); 410 if (file_printf(ms, ", for FreeBSD") == -1) 411 return size; 412 413 /* 414 * Contents is __FreeBSD_version, whose relation to OS 415 * versions is defined by a huge table in the Porter's 416 * Handbook. This is the general scheme: 417 * 418 * Releases: 419 * Mmp000 (before 4.10) 420 * Mmi0p0 (before 5.0) 421 * Mmm0p0 422 * 423 * Development branches: 424 * Mmpxxx (before 4.6) 425 * Mmp1xx (before 4.10) 426 * Mmi1xx (before 5.0) 427 * M000xx (pre-M.0) 428 * Mmm1xx 429 * 430 * M = major version 431 * m = minor version 432 * i = minor version increment (491000 -> 4.10) 433 * p = patchlevel 434 * x = revision 435 * 436 * The first release of FreeBSD to use ELF by default 437 * was version 3.0. 438 */ 439 if (desc == 460002) { 440 if (file_printf(ms, " 4.6.2") == -1) 441 return size; 442 } else if (desc < 460100) { 443 if (file_printf(ms, " %d.%d", desc / 100000, 444 desc / 10000 % 10) == -1) 445 return size; 446 if (desc / 1000 % 10 > 0) 447 if (file_printf(ms, ".%d", desc / 1000 % 10) 448 == -1) 449 return size; 450 if ((desc % 1000 > 0) || (desc % 100000 == 0)) 451 if (file_printf(ms, " (%d)", desc) == -1) 452 return size; 453 } else if (desc < 500000) { 454 if (file_printf(ms, " %d.%d", desc / 100000, 455 desc / 10000 % 10 + desc / 1000 % 10) == -1) 456 return size; 457 if (desc / 100 % 10 > 0) { 458 if (file_printf(ms, " (%d)", desc) == -1) 459 return size; 460 } else if (desc / 10 % 10 > 0) { 461 if (file_printf(ms, ".%d", desc / 10 % 10) 462 == -1) 463 return size; 464 } 465 } else { 466 if (file_printf(ms, " %d.%d", desc / 100000, 467 desc / 1000 % 100) == -1) 468 return size; 469 if ((desc / 100 % 10 > 0) || 470 (desc % 100000 / 100 == 0)) { 471 if (file_printf(ms, " (%d)", desc) == -1) 472 return size; 473 } else if (desc / 10 % 10 > 0) { 474 if (file_printf(ms, ".%d", desc / 10 % 10) 475 == -1) 476 return size; 477 } 478 } 479 return size; 480 } 481 482 if (namesz == 8 && strcmp((char *)&nbuf[noff], "OpenBSD") == 0 && 483 nh_type == NT_OPENBSD_VERSION && descsz == 4) { 484 if (file_printf(ms, ", for OpenBSD") == -1) 485 return size; 486 /* Content of note is always 0 */ 487 return size; 488 } 489 490 /* 491 * Sigh. The 2.0.36 kernel in Debian 2.1, at 492 * least, doesn't correctly implement name 493 * sections, in core dumps, as specified by 494 * the "Program Linking" section of "UNIX(R) System 495 * V Release 4 Programmer's Guide: ANSI C and 496 * Programming Support Tools", because my copy 497 * clearly says "The first 'namesz' bytes in 'name' 498 * contain a *null-terminated* [emphasis mine] 499 * character representation of the entry's owner 500 * or originator", but the 2.0.36 kernel code 501 * doesn't include the terminating null in the 502 * name.... 503 */ 504 if ((namesz == 4 && strncmp((char *)&nbuf[noff], "CORE", 4) == 0) || 505 (namesz == 5 && strcmp((char *)&nbuf[noff], "CORE") == 0)) { 506 os_style = OS_STYLE_SVR4; 507 } 508 509 if ((namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0)) { 510 os_style = OS_STYLE_FREEBSD; 511 } 512 513 if ((namesz >= 11 && strncmp((char *)&nbuf[noff], "NetBSD-CORE", 11) 514 == 0)) { 515 os_style = OS_STYLE_NETBSD; 516 } 517 518#ifdef ELFCORE 519 if (os_style != -1) 520 if (file_printf(ms, ", %s-style", os_style_names[os_style]) == -1) 521 return size; 522 523 if (os_style == OS_STYLE_NETBSD && nh_type == NT_NETBSD_CORE_PROCINFO) { 524 uint32_t signo; 525 /* 526 * Extract the program name. It is at 527 * offset 0x7c, and is up to 32-bytes, 528 * including the terminating NUL. 529 */ 530 if (file_printf(ms, ", from '%.31s'", &nbuf[doff + 0x7c]) == -1) 531 return size; 532 533 /* 534 * Extract the signal number. It is at 535 * offset 0x08. 536 */ 537 memcpy(&signo, &nbuf[doff + 0x08], 538 sizeof(signo)); 539 if (file_printf(ms, " (signal %u)", getu32(swap, signo)) == -1) 540 return size; 541 return size; 542 } else if (os_style != OS_STYLE_NETBSD && nh_type == NT_PRPSINFO) { 543 size_t i, j; 544 unsigned char c; 545 /* 546 * Extract the program name. We assume 547 * it to be 16 characters (that's what it 548 * is in SunOS 5.x and Linux). 549 * 550 * Unfortunately, it's at a different offset 551 * in varous OSes, so try multiple offsets. 552 * If the characters aren't all printable, 553 * reject it. 554 */ 555 for (i = 0; i < NOFFSETS; i++) { 556 size_t reloffset = prpsoffsets(i); 557 size_t noffset = doff + reloffset; 558 for (j = 0; j < 16; j++, noffset++, reloffset++) { 559 /* 560 * Make sure we're not past 561 * the end of the buffer; if 562 * we are, just give up. 563 */ 564 if (noffset >= size) 565 goto tryanother; 566 567 /* 568 * Make sure we're not past 569 * the end of the contents; 570 * if we are, this obviously 571 * isn't the right offset. 572 */ 573 if (reloffset >= descsz) 574 goto tryanother; 575 576 c = nbuf[noffset]; 577 if (c == '\0') { 578 /* 579 * A '\0' at the 580 * beginning is 581 * obviously wrong. 582 * Any other '\0' 583 * means we're done. 584 */ 585 if (j == 0) 586 goto tryanother; 587 else 588 break; 589 } else { 590 /* 591 * A nonprintable 592 * character is also 593 * wrong. 594 */ 595#define isquote(c) (strchr("'\"`", (c)) != NULL) 596 if (!isprint(c) || isquote(c)) 597 goto tryanother; 598 } 599 } 600 601 /* 602 * Well, that worked. 603 */ 604 if (file_printf(ms, ", from '%.16s'", 605 &nbuf[doff + prpsoffsets(i)]) == -1) 606 return size; 607 return size; 608 609 tryanother: 610 ; 611 } 612 return offset; 613 } 614#endif 615 return offset; 616} 617 618private int 619doshn(struct magic_set *ms, int class, int swap, int fd, off_t off, int num, 620 size_t size) 621{ 622 Elf32_Shdr sh32; 623 Elf64_Shdr sh64; 624 625 if (size != sh_size) { 626 if (file_printf(ms, ", corrupted section header size") == -1) 627 return -1; 628 return 0; 629 } 630 631 if (lseek(fd, off, SEEK_SET) == (off_t)-1) { 632 file_badseek(ms); 633 return -1; 634 } 635 636 for ( ; num; num--) { 637 if (read(fd, sh_addr, sh_size) == -1) { 638 file_badread(ms); 639 return -1; 640 } 641 if (shs_type == SHT_SYMTAB /* || shs_type == SHT_DYNSYM */) { 642 if (file_printf(ms, ", not stripped") == -1) 643 return -1; 644 return 0; 645 } 646 } 647 if (file_printf(ms, ", stripped") == -1) 648 return -1; 649 return 0; 650} 651 652/* 653 * Look through the program headers of an executable image, searching 654 * for a PT_INTERP section; if one is found, it's dynamically linked, 655 * otherwise it's statically linked. 656 */ 657private int 658dophn_exec(struct magic_set *ms, int class, int swap, int fd, off_t off, 659 int num, size_t size) 660{ 661 Elf32_Phdr ph32; 662 Elf64_Phdr ph64; 663 const char *linking_style = "statically"; 664 const char *shared_libraries = ""; 665 unsigned char nbuf[BUFSIZ]; 666 int bufsize; 667 size_t offset, align; 668 off_t savedoffset; 669 670 if (size != ph_size) { 671 if (file_printf(ms, ", corrupted program header size") == -1) 672 return -1; 673 return 0; 674 } 675 if (lseek(fd, off, SEEK_SET) == (off_t)-1) { 676 file_badseek(ms); 677 return -1; 678 } 679 680 for ( ; num; num--) { 681 if (read(fd, ph_addr, ph_size) == -1) { 682 file_badread(ms); 683 return -1; 684 } 685 if ((savedoffset = lseek(fd, (off_t)0, SEEK_CUR)) == (off_t)-1) { 686 file_badseek(ms); 687 return -1; 688 } 689 690 switch (ph_type) { 691 case PT_DYNAMIC: 692 linking_style = "dynamically"; 693 break; 694 case PT_INTERP: 695 shared_libraries = " (uses shared libs)"; 696 break; 697 case PT_NOTE: 698 if ((align = ph_align) & 0x80000000) { 699 if (file_printf(ms, 700 ", invalid note alignment 0x%lx", 701 (unsigned long)align) == -1) 702 return -1; 703 align = 4; 704 } 705 /* 706 * This is a PT_NOTE section; loop through all the notes 707 * in the section. 708 */ 709 if (lseek(fd, (off_t) ph_offset, SEEK_SET) 710 == (off_t)-1) { 711 file_badseek(ms); 712 return -1; 713 } 714 bufsize = read(fd, nbuf, ((ph_filesz < sizeof(nbuf)) ? 715 ph_filesz : sizeof(nbuf))); 716 if (bufsize == -1) { 717 file_badread(ms); 718 return -1; 719 } 720 offset = 0; 721 for (;;) { 722 if (offset >= (size_t)bufsize) 723 break; 724 offset = donote(ms, nbuf, offset, 725 (size_t)bufsize, class, swap, align); 726 if (offset == 0) 727 break; 728 } 729 if (lseek(fd, savedoffset, SEEK_SET) == (off_t)-1) { 730 file_badseek(ms); 731 return -1; 732 } 733 break; 734 } 735 } 736 if (file_printf(ms, ", %s linked%s", linking_style, shared_libraries) 737 == -1) 738 return -1; 739 return 0; 740} 741 742 743protected int 744file_tryelf(struct magic_set *ms, int fd, const unsigned char *buf, 745 size_t nbytes) 746{ 747 union { 748 int32_t l; 749 char c[sizeof (int32_t)]; 750 } u; 751 int class; 752 int swap; 753 754 /* 755 * If we cannot seek, it must be a pipe, socket or fifo. 756 */ 757 if((lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) && (errno == ESPIPE)) 758 fd = file_pipe2file(ms, fd, buf, nbytes); 759 760 /* 761 * ELF executables have multiple section headers in arbitrary 762 * file locations and thus file(1) cannot determine it from easily. 763 * Instead we traverse thru all section headers until a symbol table 764 * one is found or else the binary is stripped. 765 */ 766 if (buf[EI_MAG0] != ELFMAG0 767 || (buf[EI_MAG1] != ELFMAG1 && buf[EI_MAG1] != OLFMAG1) 768 || buf[EI_MAG2] != ELFMAG2 || buf[EI_MAG3] != ELFMAG3) 769 return 0; 770 771 772 class = buf[4]; 773 774 if (class == ELFCLASS32) { 775 Elf32_Ehdr elfhdr; 776 if (nbytes <= sizeof (Elf32_Ehdr)) 777 return 0; 778 779 780 u.l = 1; 781 (void) memcpy(&elfhdr, buf, sizeof elfhdr); 782 swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[5]; 783 784 if (getu16(swap, elfhdr.e_type) == ET_CORE) { 785#ifdef ELFCORE 786 if (dophn_core(ms, class, swap, fd, 787 (off_t)getu32(swap, elfhdr.e_phoff), 788 getu16(swap, elfhdr.e_phnum), 789 (size_t)getu16(swap, elfhdr.e_phentsize)) == -1) 790 return -1; 791#else 792 ; 793#endif 794 } else { 795 if (getu16(swap, elfhdr.e_type) == ET_EXEC) { 796 if (dophn_exec(ms, class, swap, 797 fd, (off_t)getu32(swap, elfhdr.e_phoff), 798 getu16(swap, elfhdr.e_phnum), 799 (size_t)getu16(swap, elfhdr.e_phentsize)) 800 == -1) 801 return -1; 802 } 803 if (doshn(ms, class, swap, fd, 804 (off_t)getu32(swap, elfhdr.e_shoff), 805 getu16(swap, elfhdr.e_shnum), 806 (size_t)getu16(swap, elfhdr.e_shentsize)) == -1) 807 return -1; 808 } 809 return 1; 810 } 811 812 if (class == ELFCLASS64) { 813 Elf64_Ehdr elfhdr; 814 if (nbytes <= sizeof (Elf64_Ehdr)) 815 return 0; 816 817 818 u.l = 1; 819 (void) memcpy(&elfhdr, buf, sizeof elfhdr); 820 swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[5]; 821 822 if (getu16(swap, elfhdr.e_type) == ET_CORE) { 823#ifdef ELFCORE 824 if (dophn_core(ms, class, swap, fd, 825#ifdef USE_ARRAY_FOR_64BIT_TYPES 826 (off_t)getu32(swap, elfhdr.e_phoff[1]), 827#else 828 (off_t)getu64(swap, elfhdr.e_phoff), 829#endif 830 getu16(swap, elfhdr.e_phnum), 831 (size_t)getu16(swap, elfhdr.e_phentsize)) == -1) 832 return -1; 833#else 834 ; 835#endif 836 } else { 837 if (getu16(swap, elfhdr.e_type) == ET_EXEC) { 838 if (dophn_exec(ms, class, swap, fd, 839#ifdef USE_ARRAY_FOR_64BIT_TYPES 840 (off_t)getu32(swap, elfhdr.e_phoff[1]), 841#else 842 (off_t)getu64(swap, elfhdr.e_phoff), 843#endif 844 getu16(swap, elfhdr.e_phnum), 845 (size_t)getu16(swap, elfhdr.e_phentsize)) 846 == -1) 847 return -1; 848 } 849 if (doshn(ms, class, swap, fd, 850#ifdef USE_ARRAY_FOR_64BIT_TYPES 851 (off_t)getu32(swap, elfhdr.e_shoff[1]), 852#else 853 (off_t)getu64(swap, elfhdr.e_shoff), 854#endif 855 getu16(swap, elfhdr.e_shnum), 856 (size_t)getu16(swap, elfhdr.e_shentsize)) == -1) 857 return -1; 858 } 859 return 1; 860 } 861 return 0; 862} 863#endif 864