libextractor

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

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 */