libextractor

GNU libextractor
Log | Files | Refs | Submodules | README | LICENSE

elf_extractor.c (19813B)


      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 0 for little-endian ELF (use lowercase pack specs),
    314  *         1 for big-endian ELF (use uppercase pack specs)
    315  */
    316 static unsigned int
    317 get_byte_order (char ei_data)
    318 {
    319   return (ei_data == ELFDATA2LSB) ? 0 : 1;
    320 }
    321 
    322 
    323 /**
    324  *
    325  * @return 0 on success, -1 on error
    326  */
    327 static int
    328 get_section_header (struct EXTRACTOR_ExtractContext *ec,
    329                     unsigned int bo,
    330                     const Elf32_Ehdr *ehdr,
    331                     Elf32_Half idx,
    332                     Elf32_Shdr *ret)
    333 {
    334   ssize_t size;
    335   uint64_t max;
    336   int64_t off;
    337   void *data;
    338 
    339   if (ehdr->e_shnum <= idx)
    340     return -1;
    341   max = ec->get_size (ec->cls);
    342   if (ehdr->e_shoff + ehdr->e_shentsize * idx + sizeof (*ret) > max)
    343     return -1;
    344   off = ec->seek (ec->cls,
    345                   ehdr->e_shoff + ehdr->e_shentsize * idx,
    346                   SEEK_SET);
    347   if (-1 == off)
    348     return -1;
    349   size = ec->read (ec->cls,
    350                    &data,
    351                    sizeof (*ret));
    352   if (size < sizeof (*ret))
    353     return -1;
    354   EXTRACTOR_common_cat_unpack (data,
    355                                ELF_SECTION_SPECS[bo],
    356                                ELF_SECTION_FIELDS (ret));
    357   return 0;
    358 }
    359 
    360 
    361 /**
    362  *
    363  * @return 0 on success, -1 on error
    364  */
    365 static int
    366 getDynTag (struct EXTRACTOR_ExtractContext *ec,
    367            unsigned int bo,
    368            const Elf32_Ehdr *ehdr,
    369            Elf32_Off off,
    370            Elf32_Word osize,
    371            unsigned int idx,
    372            Elf32_Dyn *ret)
    373 {
    374   ssize_t size;
    375   uint64_t max;
    376   int64_t soff;
    377   void *data;
    378 
    379   max = ec->get_size (ec->cls);
    380   if ( (off + osize > max) ||
    381        ((idx + 1) * ELF_DYN_SIZE > osize) )
    382     return -1;
    383   if (off + idx * ELF_DYN_SIZE + sizeof (*ret) > max)
    384     return -1;
    385   soff = ec->seek (ec->cls,
    386                    off + idx * ELF_DYN_SIZE,
    387                    SEEK_SET);
    388   if (-1 == soff)
    389     return -1;
    390   size = ec->read (ec->cls,
    391                    &data,
    392                    sizeof (*ret));
    393   if (size < sizeof (*ret))
    394     return -1;
    395   EXTRACTOR_common_cat_unpack (data,
    396                                ELF_DYN_SPECS[bo],
    397                                ELF_DYN_FIELDS (ret));
    398   return 0;
    399 }
    400 
    401 
    402 /**
    403  *
    404  * @return 0 on success, -1 on error
    405  */
    406 static int
    407 getProgramHdr (struct EXTRACTOR_ExtractContext *ec,
    408                unsigned int bo,
    409                const Elf32_Ehdr *ehdr,
    410                Elf32_Half idx,
    411                Elf32_Phdr *ret)
    412 {
    413   void *data;
    414   ssize_t size;
    415   int64_t off;
    416 
    417   if (ehdr->e_phnum <= idx)
    418     return -1;
    419   off = ec->seek (ec->cls,
    420                   ehdr->e_phoff + ehdr->e_phensize * idx,
    421                   SEEK_SET);
    422   if (-1 == off)
    423     return -1;
    424   size = ec->read (ec->cls,
    425                    &data,
    426                    sizeof (*ret));
    427   if (size < sizeof (*ret))
    428     return -1;
    429   EXTRACTOR_common_cat_unpack (data,
    430                                ELF_PHDR_SPECS[bo],
    431                                ELF_PHDR_FIELDS (ret));
    432   return 0;
    433 }
    434 
    435 
    436 /**
    437  * @return the string (offset into data, do NOT free), NULL on error
    438  */
    439 static char *
    440 readStringTable (struct EXTRACTOR_ExtractContext *ec,
    441                  unsigned int bo,
    442                  const Elf32_Ehdr *ehdr,
    443                  Elf32_Half strTableOffset,
    444                  Elf32_Word sh_name)
    445 {
    446   Elf32_Shdr shrd;
    447   char *data;
    448   ssize_t size;
    449   int64_t off;
    450 
    451   if (-1 == get_section_header (ec,
    452                                 bo,
    453                                 ehdr,
    454                                 strTableOffset,
    455                                 &shrd))
    456     return NULL;
    457   if ((shrd.sh_type != SHT_STRTAB) ||
    458       (shrd.sh_size <= sh_name) )
    459     return NULL;
    460   off = ec->seek (ec->cls,
    461                   shrd.sh_offset,
    462                   SEEK_SET);
    463   if (-1 == off)
    464     return NULL;
    465   size = ec->read (ec->cls,
    466                    (void **) &data,
    467                    shrd.sh_size);
    468   if (size < shrd.sh_size)
    469     return NULL;
    470   if (data[shrd.sh_size - 1] != '\0')
    471     return NULL;
    472   return strdup (&data[sh_name]);
    473 }
    474 
    475 
    476 #define ADD(s, type) do { \
    477           if (0!=ec->proc (ec->cls, "elf", type,                                 \
    478                            EXTRACTOR_METAFORMAT_UTF8, "text/plain",               \
    479                            s, strlen (s) + 1)) \
    480           { \
    481             return;                                         \
    482           } \
    483 } while (0)
    484 
    485 
    486 /**
    487  * Main entry method for the 'application/x-executable' extraction plugin.
    488  *
    489  * @param ec extraction context provided to the plugin
    490  */
    491 void
    492 EXTRACTOR_elf_extract_method (struct EXTRACTOR_ExtractContext *ec)
    493 {
    494   Elf32_Ehdr ehdr;
    495   Elf64_Ehdr ehdr64;
    496   int ret;
    497   unsigned int bo;
    498   char *data;
    499   ssize_t size;
    500   uint64_t max;
    501   size_t want;
    502 
    503   max = ec->get_size (ec->cls);
    504   want = sizeof (ehdr);
    505   if (sizeof (ehdr64) > want)
    506     want = sizeof (ehdr64);
    507   want += EI_NIDENT;
    508   if (max < want)
    509     return;
    510   size = ec->read (ec->cls,
    511                    (void**) &data,
    512                    max);
    513   if (size < EI_NIDENT)
    514     return;
    515   if (0 != memcmp (data,
    516                    elfMagic,
    517                    sizeof (elfMagic)))
    518     return;                  /* not an elf */
    519   switch (data[EI_CLASS])
    520   {
    521   case ELFCLASS32:
    522     if (size < sizeof (Elf32_Ehdr) + EI_NIDENT)
    523       return;
    524     bo = get_byte_order (data[EI_DATA]);
    525     EXTRACTOR_common_cat_unpack (&data[EI_NIDENT],
    526                                  ELF_HEADER_SPECS[bo],
    527                                  ELF_HEADER_FIELDS (&ehdr));
    528     if (ehdr.e_shoff + ehdr.e_shentsize * ehdr.e_shnum > max)
    529       return;              /* invalid offsets... */
    530     if (ehdr.e_shentsize < ELF_SECTION_SIZE)
    531       return;              /* huh? */
    532     if (ehdr.e_phoff + ehdr.e_phensize * ehdr.e_phnum > max)
    533       return;
    534     ret = 0;
    535     bo = get_byte_order (data[EI_DATA]);
    536     break;
    537   case ELFCLASS64:
    538     if (size < sizeof (Elf64_Ehdr) + EI_NIDENT)
    539       return;
    540     bo = get_byte_order (data[EI_DATA]);
    541     EXTRACTOR_common_cat_unpack (&data[EI_NIDENT],
    542                                  ELF64_HEADER_SPECS[bo],
    543                                  ELF64_HEADER_FIELDS (&ehdr64));
    544     if (ehdr64.e_shoff + ((uint32_t) ehdr64.e_shentsize * ehdr64.e_shnum) >
    545         max)
    546       return;              /* invalid offsets... */
    547     if (ehdr64.e_phoff + ((uint32_t) ehdr64.e_phensize * ehdr64.e_phnum) >
    548         max)
    549       return;
    550     bo = get_byte_order (data[EI_DATA]);
    551     ret = 1;
    552     break;
    553   default:
    554     return;
    555   }
    556 
    557   ADD ("application/x-executable",
    558        EXTRACTOR_METATYPE_MIMETYPE);
    559   switch ( ((unsigned char*) data)[EI_OSABI])
    560   {
    561   case ELFOSABI_LINUX:
    562     ADD ("Linux",
    563          EXTRACTOR_METATYPE_TARGET_OS);
    564     break;
    565   case ELFOSABI_FREEBSD:
    566     ADD ("FreeBSD",
    567          EXTRACTOR_METATYPE_TARGET_OS);
    568     break;
    569   case ELFOSABI_NETBSD:
    570     ADD ("NetBSD",
    571          EXTRACTOR_METATYPE_TARGET_OS);
    572     break;
    573   case ELFOSABI_OPENBSD:
    574     ADD ("OpenBSD",
    575          EXTRACTOR_METATYPE_TARGET_OS);
    576     break;
    577   case ELFOSABI_IRIX:
    578     ADD ("IRIX",
    579          EXTRACTOR_METATYPE_TARGET_OS);
    580     break;
    581   default:
    582     break;
    583   }
    584   switch ( (0 == ret) ? ehdr.e_type : ehdr64.e_type)
    585   {
    586   case ET_REL:
    587     ADD ("Relocatable file",
    588          EXTRACTOR_METATYPE_RESOURCE_TYPE);
    589     break;
    590   case ET_EXEC:
    591     ADD ("Executable file",
    592          EXTRACTOR_METATYPE_RESOURCE_TYPE);
    593     break;
    594   case ET_DYN:
    595     ADD ("Shared object file",
    596          EXTRACTOR_METATYPE_RESOURCE_TYPE);
    597     break;
    598   case ET_CORE:
    599     ADD ("Core file",
    600          EXTRACTOR_METATYPE_RESOURCE_TYPE);
    601     break;
    602   default:
    603     break;                      /* unknown */
    604   }
    605   switch ( (0 == ret) ? ehdr.e_machine : ehdr64.e_machine)
    606   {
    607   case EM_M32:
    608     ADD ("M32",
    609          EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
    610     break;
    611   case EM_386:
    612     ADD ("i386",
    613          EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
    614     break;
    615   case EM_68K:
    616     ADD ("68K",
    617          EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
    618     break;
    619   case EM_88K:
    620     ADD ("88K",
    621          EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
    622     break;
    623   case EM_SPARC:
    624     ADD ("Sparc",
    625          EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
    626     break;
    627   case EM_860:
    628     ADD ("960",
    629          EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
    630     break;
    631   case EM_MIPS:
    632     ADD ("MIPS",
    633          EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
    634     break;
    635   case EM_PPC:
    636     ADD ("PPC",
    637          EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
    638     break;
    639   case EM_PPC64:
    640     ADD ("PPC64",
    641          EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
    642     break;
    643   case EM_S390:
    644     ADD ("S390",
    645          EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
    646     break;
    647   case EM_ARM:
    648     ADD ("ARM",
    649          EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
    650     break;
    651   case EM_ALPHA:
    652     ADD ("ALPHA",
    653          EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
    654     break;
    655   case EM_IA_64:
    656     ADD ("IA-64",
    657          EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
    658     break;
    659   case EM_X86_64:
    660     ADD ("x86_64",
    661          EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
    662     break;
    663   case EM_CUDA:
    664     ADD ("NVIDIA CUDA",
    665          EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
    666     break;
    667   default:
    668     break;                      /* oops */
    669   }
    670 
    671   if (0 != ret)
    672     return; /* FIXME: full support for 64-bit ELF... */
    673   for (Elf32_Half idx = 0; idx < ehdr.e_phnum; idx++)
    674   {
    675     Elf32_Phdr phdr;
    676 
    677     if (0 != getProgramHdr (ec,
    678                             bo,
    679                             &ehdr,
    680                             idx,
    681                             &phdr))
    682       return;
    683     if (phdr.p_type == PT_DYNAMIC)
    684     {
    685       unsigned int dc = phdr.p_filesz / ELF_DYN_SIZE;
    686       Elf32_Addr stringPtr;
    687       Elf32_Half stringIdx;
    688       Elf32_Half six;
    689 
    690       stringPtr = 0;
    691       for (unsigned int id = 0; id < dc; id++)
    692       {
    693         Elf32_Dyn dyn;
    694 
    695         if (0 != getDynTag (ec,
    696                             bo,
    697                             &ehdr,
    698                             phdr.p_offset,
    699                             phdr.p_filesz,
    700                             id,
    701                             &dyn))
    702           return;
    703         if (DT_STRTAB == dyn.d_tag)
    704         {
    705           stringPtr = dyn.d_un.d_ptr;
    706           break;
    707         }
    708       }
    709       if (0 == stringPtr)
    710         return;
    711       for (six = 0; six < ehdr.e_shnum; six++)
    712       {
    713         Elf32_Shdr sec;
    714 
    715         if (-1 == get_section_header (ec,
    716                                       bo,
    717                                       &ehdr,
    718                                       six,
    719                                       &sec))
    720           return;
    721         if ( (sec.sh_addr == stringPtr) &&
    722              (sec.sh_type == SHT_STRTAB) )
    723         {
    724           stringIdx = six;
    725           break;
    726         }
    727       }
    728       if (six == ehdr.e_shnum)
    729         return; /* stringIdx not found */
    730 
    731       for (unsigned int id = 0; id < dc; id++)
    732       {
    733         Elf32_Dyn dyn;
    734 
    735         if (0 != getDynTag (ec,
    736                             bo,
    737                             &ehdr,
    738                             phdr.p_offset,
    739                             phdr.p_filesz,
    740                             id,
    741                             &dyn))
    742           return;
    743         switch (dyn.d_tag)
    744         {
    745         case DT_RPATH:
    746           {
    747             char *rpath;
    748 
    749             rpath = readStringTable (ec,
    750                                      bo,
    751                                      &ehdr,
    752                                      stringIdx,
    753                                      dyn.d_un.d_val);
    754             /* "source" of the dependencies: path
    755                to dynamic libraries */
    756             if (NULL != rpath)
    757             {
    758               ADD (rpath,
    759                    EXTRACTOR_METATYPE_LIBRARY_SEARCH_PATH);
    760               free (rpath);
    761             }
    762             break;
    763           }
    764         case DT_NEEDED:
    765           {
    766             char *needed;
    767 
    768             needed = readStringTable (ec,
    769                                       bo,
    770                                       &ehdr,
    771                                       stringIdx,
    772                                       dyn.d_un.d_val);
    773             if (NULL != needed)
    774             {
    775               ADD (needed,
    776                    EXTRACTOR_METATYPE_LIBRARY_DEPENDENCY);
    777               free (needed);
    778             }
    779             break;
    780           }
    781         }
    782       }
    783     }
    784   }
    785 }
    786 
    787 
    788 /* end of elf_extractor.c */