elf_extractor.c (19802B)
1 /* 2 This file is part of libextractor. 3 Copyright (C) 2012 Vidyut Samanta and Christian Grothoff 4 5 libextractor is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published 7 by the Free Software Foundation; either version 3, or (at your 8 option) any later version. 9 10 libextractor is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with libextractor; see the file COPYING. If not, write to the 17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 Boston, MA 02110-1301, USA. 19 */ 20 /** 21 * @file plugins/elf_extractor.c 22 * @brief plugin to support ELF files 23 * @author Christian Grothoff 24 */ 25 #include "platform.h" 26 #include "extractor.h" 27 #include "pack.h" 28 #include <stdint.h> 29 30 31 typedef uint32_t Elf32_Addr; 32 typedef uint16_t Elf32_Half; 33 typedef uint32_t Elf32_Off; 34 typedef int32_t Elf32_Sword; 35 typedef uint32_t Elf32_Word; 36 37 typedef uint16_t Elf64_Half; 38 typedef uint32_t Elf64_Word; 39 typedef uint64_t Elf64_Addr; 40 typedef uint64_t Elf64_Off; 41 42 /* first 4 bytes of the ELF header */ 43 static char elfMagic[] = { 0x7f, 'E', 'L', 'F' }; 44 45 #define EI_CLASS 4 46 #define EI_DATA 5 47 #define EI_VERSION 6 48 #define EI_OSABI 7 49 #define EI_NIDENT 16 50 51 typedef struct 52 { 53 Elf32_Half e_type; 54 Elf32_Half e_machine; 55 Elf32_Word e_version; 56 Elf32_Addr e_entry; 57 Elf32_Off e_phoff; 58 Elf32_Off e_shoff; /* offset of the section header table */ 59 Elf32_Word e_flags; 60 Elf32_Half e_ehsize; 61 Elf32_Half e_phensize; 62 Elf32_Half e_phnum; 63 Elf32_Half e_shentsize; /* size of each entry in SH table */ 64 Elf32_Half e_shnum; /* how many entries in section header table */ 65 Elf32_Half e_shstrndx; /* section header's sh_name member is index into this string table! */ 66 } Elf32_Ehdr; 67 68 /* elf-header minus e_ident */ 69 #define ELF_HEADER_SIZE sizeof (Elf32_Ehdr) 70 71 #define ELF_HEADER_FIELDS(p) \ 72 & (p)->e_type, \ 73 &(p)->e_machine, \ 74 &(p)->e_version, \ 75 &(p)->e_entry, \ 76 &(p)->e_phoff, \ 77 &(p)->e_shoff, \ 78 &(p)->e_flags, \ 79 &(p)->e_ehsize, \ 80 &(p)->e_phensize, \ 81 &(p)->e_phnum, \ 82 &(p)->e_shentsize, \ 83 &(p)->e_shnum, \ 84 &(p)->e_shstrndx 85 static char *ELF_HEADER_SPECS[] = { 86 "hhwwwwwhhhhhh", 87 "HHWWWWWHHHHHH", 88 }; 89 90 typedef struct 91 { 92 Elf64_Half e_type; 93 Elf64_Half e_machine; 94 Elf64_Word e_version; 95 Elf64_Addr e_entry; 96 Elf64_Off e_phoff; 97 Elf64_Off e_shoff; 98 Elf64_Word e_flags; 99 Elf64_Half e_ehsize; 100 Elf64_Half e_phensize; 101 Elf64_Half e_phnum; 102 Elf64_Half e_shentsize; 103 Elf64_Half e_shnum; 104 Elf64_Half e_shstrndx; 105 } Elf64_Ehdr; 106 107 /* elf-header minus e_ident */ 108 #define ELF64_HEADER_SIZE sizeof (Elf64_Ehdr) 109 110 #define ELF64_HEADER_FIELDS(p) \ 111 & (p)->e_type, \ 112 &(p)->e_machine, \ 113 &(p)->e_version, \ 114 &(p)->e_entry, \ 115 &(p)->e_phoff, \ 116 &(p)->e_shoff, \ 117 &(p)->e_flags, \ 118 &(p)->e_ehsize, \ 119 &(p)->e_phensize, \ 120 &(p)->e_phnum, \ 121 &(p)->e_shentsize, \ 122 &(p)->e_shnum, \ 123 &(p)->e_shstrndx 124 static char *ELF64_HEADER_SPECS[] = { 125 "hhwxxxwhhhhhh", 126 "HHWXXXWHHHHHH", 127 }; 128 129 130 typedef struct 131 { 132 Elf32_Word sh_name; 133 Elf32_Word sh_type; 134 Elf32_Word sh_flags; 135 Elf32_Addr sh_addr; /* where loaded */ 136 Elf32_Off sh_offset; /* where in image (! sh_type==SHT_NOBITS) */ 137 Elf32_Word sh_size; /* section size in bytes */ 138 Elf32_Word sh_link; /* for symbol table: section header index of the associated string table! */ 139 Elf32_Word sh_info; /* "one greater than the symbol table index of the last local symbol _STB_LOCAL_" */ 140 Elf32_Word sh_addralign; 141 Elf32_Word sh_entsize; 142 } Elf32_Shdr; 143 #define ELF_SECTION_SIZE 40 144 145 #define ELF_SECTION_FIELDS(p) \ 146 & (p)->sh_name, \ 147 &(p)->sh_type, \ 148 &(p)->sh_flags, \ 149 &(p)->sh_addr, \ 150 &(p)->sh_offset, \ 151 &(p)->sh_size, \ 152 &(p)->sh_link, \ 153 &(p)->sh_info, \ 154 &(p)->sh_addralign, \ 155 &(p)->sh_entsize 156 static char *ELF_SECTION_SPECS[] = { 157 "wwwwwwwwww", 158 "WWWWWWWWWW", 159 }; 160 161 typedef struct 162 { 163 Elf32_Word p_type; 164 Elf32_Off p_offset; 165 Elf32_Addr p_vaddr; 166 Elf32_Addr p_paddr; 167 Elf32_Word p_filesz; 168 Elf32_Word p_memsz; 169 Elf32_Word p_flags; 170 Elf32_Word p_align; 171 } Elf32_Phdr; 172 #define ELF_PDHR_SIZE 32 173 #define ELF_PHDR_FIELDS(p) \ 174 & (p)->p_type, \ 175 &(p)->p_offset, \ 176 &(p)->p_vaddr, \ 177 &(p)->p_paddr, \ 178 &(p)->p_filesz, \ 179 &(p)->p_memsz, \ 180 &(p)->p_flags, \ 181 &(p)->p_align 182 static char *ELF_PHDR_SPECS[] = { 183 "wwwwwwww", 184 "WWWWWWWW", 185 }; 186 187 typedef struct 188 { 189 Elf32_Sword d_tag; 190 union 191 { 192 Elf32_Word d_val; 193 Elf32_Addr d_ptr; 194 } d_un; 195 } Elf32_Dyn; 196 #define ELF_DYN_SIZE 8 197 #define ELF_DYN_FIELDS(p) \ 198 & (p)->d_tag, \ 199 &(p)->d_un 200 static char *ELF_DYN_SPECS[] = { 201 "ww", 202 "WW", 203 }; 204 205 #define ET_NONE 0 206 #define ET_REL 1 207 #define ET_EXEC 2 208 #define ET_DYN 3 209 #define ET_CORE 4 210 #define ET_LOPROC 0xff00 211 #define ET_HIPROC 0xffff 212 213 #define EM_NONE 0 214 #define EM_M32 1 215 #define EM_SPARC 2 216 #define EM_386 3 217 #define EM_68K 4 218 #define EM_88K 5 219 #define EM_860 7 220 #define EM_MIPS 8 221 #define EM_PPC 20 222 #define EM_PPC64 21 223 #define EM_S390 22 224 #define EM_ARM 40 225 #define EM_ALPHA 41 226 #define EM_IA_64 50 227 #define EM_X86_64 62 228 #define EM_CUDA 190 229 230 #define ELFOSABI_NETBSD 2 231 #define ELFOSABI_LINUX 3 232 #define ELFOSABI_IRIX 8 233 #define ELFOSABI_FREEBSD 9 234 #define ELFOSABI_OPENBSD 12 235 236 #define EV_NONE 0 237 #define EV_CURRENT 1 238 239 #define SHT_NULL 0 240 #define SHT_PROGBITS 1 241 #define SHT_SYMTAB 2 242 /* string table! */ 243 #define SHT_STRTAB 3 244 #define SHT_RELA 4 245 #define SHT_HASH 5 246 /* dynamic linking info! */ 247 #define SHT_DYNAMIC 6 248 #define SHT_NOTE 7 249 #define SHT_NOBITS 8 250 #define SHT_REL 9 251 #define SHT_SHLIB 10 252 #define SHT_DYNSYM 11 253 #define SHT_LOPROC 0x70000000 254 #define SHT_HIPROC 0x7fffffff 255 #define SHT_LOUSER 0x80000000 256 #define SHT_HIUSER 0xffffffff 257 258 #define SHF_WRITE 0x1 259 #define SHF_ALLOC 0x2 260 #define SHF_EXECINSTR 0x4 261 #define SHF_MASKPROC 0xf000000 262 263 #define DT_NULL 0 264 /* name of a needed library, offset into table 265 recorded in DT_STRTAB entry */ 266 #define DT_NEEDED 1 267 #define DT_PLTRELSZ 2 268 #define DT_PLTGOT 3 269 #define DT_HASH 4 270 /* address of the string table from where symbol 271 names, library names, etc for this DT come from */ 272 #define DT_STRTAB 5 273 #define DT_SYMTAB 6 274 #define DT_SYMENT 7 275 #define DT_RELA 7 276 #define DT_RELASZ 8 277 #define DT_RELAENT 9 278 /* size of the string-table in bytes */ 279 #define DT_STRSZ 10 280 /* fixme 11 */ 281 #define DT_INIT 12 282 #define DT_FINI 13 283 /* string-table offset giving the name of the shared object */ 284 #define DT_SONAME 14 285 /* string-table offset of a null-terminated library search path */ 286 #define DT_RPATH 15 287 #define DT_SYMBOLIC 16 288 289 290 #define PT_NULL 0 291 #define PT_LOAD 1 292 #define PT_DYNAMIC 2 293 #define PT_INTERP 3 294 #define PT_NOTE 4 295 #define PT_SHLIB 5 296 #define PT_PHDR 6 297 #define PT_LOPROC 0x70000000 298 #define PT_HIPROC 0x7fffffff 299 300 301 #define ELFCLASSNONE 0 302 #define ELFCLASS32 1 303 #define ELFCLASS64 2 304 305 #define ELFDATANONE 0 306 /* little endian */ 307 #define ELFDATA2LSB 1 308 /* big endian */ 309 #define ELFDATA2MSB 2 310 311 /** 312 * @param ei_data ELFDATA2LSB or ELFDATA2MSB 313 * @return 1 if we need to convert, 0 if not 314 */ 315 static int 316 getByteorder (char ei_data) 317 { 318 if (ei_data == ELFDATA2LSB) 319 { 320 #if __BYTE_ORDER == __BIG_ENDIAN 321 return 1; 322 #else 323 return 0; 324 #endif 325 } 326 else 327 { 328 #if __BYTE_ORDER == __BIG_ENDIAN 329 return 0; 330 #else 331 return 1; 332 #endif 333 } 334 } 335 336 337 /** 338 * 339 * @return 0 on success, -1 on error 340 */ 341 static int 342 getSectionHdr (struct EXTRACTOR_ExtractContext *ec, 343 unsigned int bo, 344 const Elf32_Ehdr *ehdr, 345 Elf32_Half idx, 346 Elf32_Shdr *ret) 347 { 348 ssize_t size; 349 uint64_t max; 350 int64_t off; 351 void *data; 352 353 if (ehdr->e_shnum <= idx) 354 return -1; 355 max = ec->get_size (ec->cls); 356 if (ehdr->e_shoff + ehdr->e_shentsize * idx + sizeof (*ret) > max) 357 return -1; 358 off = ec->seek (ec->cls, 359 ehdr->e_shoff + ehdr->e_shentsize * idx, 360 SEEK_SET); 361 if (-1 == off) 362 return -1; 363 size = ec->read (ec->cls, 364 &data, 365 sizeof (*ret)); 366 if (size < sizeof (*ret)) 367 return -1; 368 EXTRACTOR_common_cat_unpack (data, 369 ELF_SECTION_SPECS[bo], 370 ELF_SECTION_FIELDS (ret)); 371 return 0; 372 } 373 374 375 /** 376 * 377 * @return 0 on success, -1 on error 378 */ 379 static int 380 getDynTag (struct EXTRACTOR_ExtractContext *ec, 381 unsigned int bo, 382 const Elf32_Ehdr *ehdr, 383 Elf32_Off off, 384 Elf32_Word osize, 385 unsigned int idx, 386 Elf32_Dyn *ret) 387 { 388 ssize_t size; 389 uint64_t max; 390 int64_t soff; 391 void *data; 392 393 max = ec->get_size (ec->cls); 394 if ( (off + osize > max) || 395 ((idx + 1) * ELF_DYN_SIZE > osize) ) 396 return -1; 397 if (off + idx * ELF_DYN_SIZE + sizeof (*ret) > max) 398 return -1; 399 soff = ec->seek (ec->cls, 400 off + idx * ELF_DYN_SIZE, 401 SEEK_SET); 402 if (-1 == soff) 403 return -1; 404 size = ec->read (ec->cls, 405 &data, 406 sizeof (*ret)); 407 if (size < sizeof (*ret)) 408 return -1; 409 EXTRACTOR_common_cat_unpack (data, 410 ELF_DYN_SPECS[bo], 411 ELF_DYN_FIELDS (ret)); 412 return 0; 413 } 414 415 416 /** 417 * 418 * @return 0 on success, -1 on error 419 */ 420 static int 421 getProgramHdr (struct EXTRACTOR_ExtractContext *ec, 422 unsigned int bo, 423 const Elf32_Ehdr *ehdr, 424 Elf32_Half idx, 425 Elf32_Phdr *ret) 426 { 427 void *data; 428 ssize_t size; 429 int64_t off; 430 431 if (ehdr->e_phnum <= idx) 432 return -1; 433 off = ec->seek (ec->cls, 434 ehdr->e_phoff + ehdr->e_phensize * idx, 435 SEEK_SET); 436 if (-1 == off) 437 return -1; 438 size = ec->read (ec->cls, 439 &data, 440 sizeof (*ret)); 441 if (size < sizeof (*ret)) 442 return -1; 443 EXTRACTOR_common_cat_unpack (data, 444 ELF_PHDR_SPECS[bo], 445 ELF_PHDR_FIELDS (ret)); 446 return 0; 447 } 448 449 450 /** 451 * @return the string (offset into data, do NOT free), NULL on error 452 */ 453 static char * 454 readStringTable (struct EXTRACTOR_ExtractContext *ec, 455 unsigned int bo, 456 const Elf32_Ehdr *ehdr, 457 Elf32_Half strTableOffset, 458 Elf32_Word sh_name) 459 { 460 Elf32_Shdr shrd; 461 char *data; 462 ssize_t size; 463 int64_t off; 464 465 if (-1 == getSectionHdr (ec, 466 bo, 467 ehdr, 468 strTableOffset, 469 &shrd)) 470 return NULL; 471 if ((shrd.sh_type != SHT_STRTAB) || 472 (shrd.sh_size <= sh_name) ) 473 return NULL; 474 off = ec->seek (ec->cls, 475 shrd.sh_offset, 476 SEEK_SET); 477 if (-1 == off) 478 return NULL; 479 size = ec->read (ec->cls, 480 (void **) &data, 481 shrd.sh_size); 482 if (size < shrd.sh_size) 483 return NULL; 484 if (data[shrd.sh_size - 1] != '\0') 485 return NULL; 486 return strdup (&data[sh_name]); 487 } 488 489 490 #define ADD(s, type) do { \ 491 if (0!=ec->proc (ec->cls, "elf", type, \ 492 EXTRACTOR_METAFORMAT_UTF8, "text/plain", \ 493 s, strlen (s) + 1)) \ 494 { \ 495 return; \ 496 } \ 497 } while (0) 498 499 500 /** 501 * Main entry method for the 'application/x-executable' extraction plugin. 502 * 503 * @param ec extraction context provided to the plugin 504 */ 505 void 506 EXTRACTOR_elf_extract_method (struct EXTRACTOR_ExtractContext *ec) 507 { 508 Elf32_Ehdr ehdr; 509 Elf64_Ehdr ehdr64; 510 int ret; 511 unsigned int bo; 512 char *data; 513 ssize_t size; 514 uint64_t max; 515 size_t want; 516 517 max = ec->get_size (ec->cls); 518 want = sizeof (ehdr); 519 if (sizeof (ehdr64) > want) 520 want = sizeof (ehdr64); 521 want += EI_NIDENT; 522 if (max < want) 523 return; 524 size = ec->read (ec->cls, 525 (void**) &data, 526 max); 527 if (size < EI_NIDENT) 528 return; 529 if (0 != memcmp (data, 530 elfMagic, 531 sizeof (elfMagic))) 532 return; /* not an elf */ 533 switch (data[EI_CLASS]) 534 { 535 case ELFCLASS32: 536 if (size < sizeof (Elf32_Ehdr) + EI_NIDENT) 537 return; 538 bo = getByteorder (data[EI_DATA]); 539 EXTRACTOR_common_cat_unpack (&data[EI_NIDENT], 540 ELF_HEADER_SPECS[bo], 541 ELF_HEADER_FIELDS (&ehdr)); 542 if (ehdr.e_shoff + ehdr.e_shentsize * ehdr.e_shnum > max) 543 return; /* invalid offsets... */ 544 if (ehdr.e_shentsize < ELF_SECTION_SIZE) 545 return; /* huh? */ 546 if (ehdr.e_phoff + ehdr.e_phensize * ehdr.e_phnum > max) 547 return; 548 ret = 0; 549 bo = getByteorder (data[EI_CLASS]); 550 break; 551 case ELFCLASS64: 552 if (size < sizeof (Elf64_Ehdr) + EI_NIDENT) 553 return; 554 bo = getByteorder (data[EI_DATA]); 555 EXTRACTOR_common_cat_unpack (&data[EI_NIDENT], 556 ELF64_HEADER_SPECS[bo], 557 ELF64_HEADER_FIELDS (&ehdr64)); 558 if (ehdr64.e_shoff + ((uint32_t) ehdr64.e_shentsize * ehdr64.e_shnum) > 559 max) 560 return; /* invalid offsets... */ 561 if (ehdr64.e_phoff + ((uint32_t) ehdr64.e_phensize * ehdr64.e_phnum) > 562 max) 563 return; 564 bo = getByteorder (data[EI_CLASS]); 565 ret = 1; 566 break; 567 default: 568 return; 569 } 570 571 ADD ("application/x-executable", 572 EXTRACTOR_METATYPE_MIMETYPE); 573 switch ( ((unsigned char*) data)[EI_OSABI]) 574 { 575 case ELFOSABI_LINUX: 576 ADD ("Linux", 577 EXTRACTOR_METATYPE_TARGET_OS); 578 break; 579 case ELFOSABI_FREEBSD: 580 ADD ("FreeBSD", 581 EXTRACTOR_METATYPE_TARGET_OS); 582 break; 583 case ELFOSABI_NETBSD: 584 ADD ("NetBSD", 585 EXTRACTOR_METATYPE_TARGET_OS); 586 break; 587 case ELFOSABI_OPENBSD: 588 ADD ("OpenBSD", 589 EXTRACTOR_METATYPE_TARGET_OS); 590 break; 591 case ELFOSABI_IRIX: 592 ADD ("IRIX", 593 EXTRACTOR_METATYPE_TARGET_OS); 594 break; 595 default: 596 break; 597 } 598 switch ( (0 == ret) ? ehdr.e_type : ehdr64.e_type) 599 { 600 case ET_REL: 601 ADD ("Relocatable file", 602 EXTRACTOR_METATYPE_RESOURCE_TYPE); 603 break; 604 case ET_EXEC: 605 ADD ("Executable file", 606 EXTRACTOR_METATYPE_RESOURCE_TYPE); 607 break; 608 case ET_DYN: 609 ADD ("Shared object file", 610 EXTRACTOR_METATYPE_RESOURCE_TYPE); 611 break; 612 case ET_CORE: 613 ADD ("Core file", 614 EXTRACTOR_METATYPE_RESOURCE_TYPE); 615 break; 616 default: 617 break; /* unknown */ 618 } 619 switch ( (0 == ret) ? ehdr.e_machine : ehdr64.e_machine) 620 { 621 case EM_M32: 622 ADD ("M32", 623 EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); 624 break; 625 case EM_386: 626 ADD ("i386", 627 EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); 628 break; 629 case EM_68K: 630 ADD ("68K", 631 EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); 632 break; 633 case EM_88K: 634 ADD ("88K", 635 EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); 636 break; 637 case EM_SPARC: 638 ADD ("Sparc", 639 EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); 640 break; 641 case EM_860: 642 ADD ("960", 643 EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); 644 break; 645 case EM_MIPS: 646 ADD ("MIPS", 647 EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); 648 break; 649 case EM_PPC: 650 ADD ("PPC", 651 EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); 652 break; 653 case EM_PPC64: 654 ADD ("PPC64", 655 EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); 656 break; 657 case EM_S390: 658 ADD ("S390", 659 EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); 660 break; 661 case EM_ARM: 662 ADD ("ARM", 663 EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); 664 break; 665 case EM_ALPHA: 666 ADD ("ALPHA", 667 EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); 668 break; 669 case EM_IA_64: 670 ADD ("IA-64", 671 EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); 672 break; 673 case EM_X86_64: 674 ADD ("x86_64", 675 EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); 676 break; 677 case EM_CUDA: 678 ADD ("NVIDIA CUDA", 679 EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); 680 break; 681 default: 682 break; /* oops */ 683 } 684 685 if (0 != ret) 686 return; /* FIXME: full support for 64-bit ELF... */ 687 for (Elf32_Half idx = 0; idx < ehdr.e_phnum; idx++) 688 { 689 Elf32_Phdr phdr; 690 691 if (0 != getProgramHdr (ec, 692 bo, 693 &ehdr, 694 idx, 695 &phdr)) 696 return; 697 if (phdr.p_type == PT_DYNAMIC) 698 { 699 unsigned int dc = phdr.p_filesz / ELF_DYN_SIZE; 700 Elf32_Addr stringPtr; 701 Elf32_Half stringIdx; 702 Elf32_Half six; 703 704 stringPtr = 0; 705 for (unsigned int id = 0; id < dc; id++) 706 { 707 Elf32_Dyn dyn; 708 709 if (0 != getDynTag (ec, 710 bo, 711 &ehdr, 712 phdr.p_offset, 713 phdr.p_filesz, 714 id, 715 &dyn)) 716 return; 717 if (DT_STRTAB == dyn.d_tag) 718 { 719 stringPtr = dyn.d_un.d_ptr; 720 break; 721 } 722 } 723 if (0 == stringPtr) 724 return; 725 for (six = 0; six < ehdr.e_shnum; six++) 726 { 727 Elf32_Shdr sec; 728 729 if (-1 == getSectionHdr (ec, 730 bo, 731 &ehdr, 732 six, 733 &sec)) 734 return; 735 if ( (sec.sh_addr == stringPtr) && 736 (sec.sh_type == SHT_STRTAB) ) 737 { 738 stringIdx = six; 739 break; 740 } 741 } 742 if (six == ehdr.e_shnum) 743 return; /* stringIdx not found */ 744 745 for (unsigned int id = 0; id < dc; id++) 746 { 747 Elf32_Dyn dyn; 748 749 if (0 != getDynTag (ec, 750 bo, 751 &ehdr, 752 phdr.p_offset, 753 phdr.p_filesz, 754 id, 755 &dyn)) 756 return; 757 switch (dyn.d_tag) 758 { 759 case DT_RPATH: 760 { 761 char *rpath; 762 763 rpath = readStringTable (ec, 764 bo, 765 &ehdr, 766 stringIdx, 767 dyn.d_un.d_val); 768 /* "source" of the dependencies: path 769 to dynamic libraries */ 770 if (NULL != rpath) 771 { 772 ADD (rpath, 773 EXTRACTOR_METATYPE_LIBRARY_SEARCH_PATH); 774 free (rpath); 775 } 776 break; 777 } 778 case DT_NEEDED: 779 { 780 char *needed; 781 782 needed = readStringTable (ec, 783 bo, 784 &ehdr, 785 stringIdx, 786 dyn.d_un.d_val); 787 if (NULL != needed) 788 { 789 ADD (needed, 790 EXTRACTOR_METATYPE_LIBRARY_DEPENDENCY); 791 free (needed); 792 } 793 break; 794 } 795 } 796 } 797 } 798 } 799 } 800 801 802 /* end of elf_extractor.c */