libextractor

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

commit 1cb89d0393bac19f3b9e409ba46d1fd4136ff332
parent ad9dc67eb7331616c4bbe6229576495a25741928
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sat,  1 May 2021 22:59:59 +0200

revive ELF plugin

Diffstat:
M.gitignore | 258++++---------------------------------------------------------------------------
MChangeLog | 3+++
Msrc/plugins/Makefile.am | 15+++++++++++++++
Asrc/plugins/elf_extractor.c | 802+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/plugins/old/elf_extractor.c | 666-------------------------------------------------------------------------------
Rsrc/plugins/old/pack.c -> src/plugins/pack.c | 0
Rsrc/plugins/old/pack.h -> src/plugins/pack.h | 0
Asrc/plugins/test_elf.c | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/testdata/chello-elf | 0
9 files changed, 915 insertions(+), 912 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1,8 +1,4 @@ -On branch master -Your branch is up-to-date with 'origin/master'. -Untracked files: - (use "git add <file>..." to include in what will be committed) - +**/*~ INSTALL Makefile Makefile.in @@ -72,290 +68,60 @@ src/main/extract.o src/main/getopt.o src/main/getopt1.o src/main/libextractor.la -src/main/libextractor_la-extractor.lo -src/main/libextractor_la-extractor.o -src/main/libextractor_la-extractor_common.lo -src/main/libextractor_la-extractor_common.o -src/main/libextractor_la-extractor_datasource.lo -src/main/libextractor_la-extractor_datasource.o -src/main/libextractor_la-extractor_ipc.lo -src/main/libextractor_la-extractor_ipc.o -src/main/libextractor_la-extractor_ipc_gnu.lo -src/main/libextractor_la-extractor_ipc_gnu.o -src/main/libextractor_la-extractor_logging.lo -src/main/libextractor_la-extractor_logging.o -src/main/libextractor_la-extractor_metatypes.lo -src/main/libextractor_la-extractor_metatypes.o -src/main/libextractor_la-extractor_plugin_main.lo -src/main/libextractor_la-extractor_plugin_main.o -src/main/libextractor_la-extractor_plugins.lo -src/main/libextractor_la-extractor_plugins.o -src/main/libextractor_la-extractor_plugpath.lo -src/main/libextractor_la-extractor_plugpath.o -src/main/libextractor_la-extractor_print.lo -src/main/libextractor_la-extractor_print.o -src/main/libextractor_test.la -src/main/libextractor_test2.la -src/main/test-suite.log -src/main/test2_extractor.lo -src/main/test2_extractor.o +src/main/*.o +src/main/*.lo +src/main/*.la +src/main/*.trs +src/main/*.log src/main/test_bzip2 -src/main/test_bzip2.log -src/main/test_bzip2.o -src/main/test_bzip2.trs -src/main/test_extractor.lo -src/main/test_extractor.o src/main/test_file -src/main/test_file.log -src/main/test_file.o -src/main/test_file.trs src/main/test_gzip -src/main/test_gzip.log -src/main/test_gzip.o -src/main/test_gzip.trs src/main/test_ipc -src/main/test_ipc.log -src/main/test_ipc.o -src/main/test_ipc.trs src/main/test_plugin_load_multi -src/main/test_plugin_load_multi.log -src/main/test_plugin_load_multi.o -src/main/test_plugin_load_multi.trs src/main/test_plugin_loading -src/main/test_plugin_loading.log -src/main/test_plugin_loading.o -src/main/test_plugin_loading.trs src/main/test_trivial -src/main/test_trivial.log -src/main/test_trivial.o -src/main/test_trivial.trs src/plugins/.deps/ src/plugins/.libs/ src/plugins/Makefile src/plugins/Makefile.in -src/plugins/archive_extractor.lo -src/plugins/archive_extractor.o -src/plugins/deb_extractor.lo -src/plugins/deb_extractor.o -src/plugins/dvi_extractor.lo -src/plugins/dvi_extractor.o -src/plugins/exiv2_extractor.lo -src/plugins/exiv2_extractor.o -src/plugins/flac_extractor.lo -src/plugins/flac_extractor.o -src/plugins/gif_extractor.lo -src/plugins/gif_extractor.o -src/plugins/html_extractor.lo -src/plugins/html_extractor.o -src/plugins/it_extractor.lo -src/plugins/it_extractor.o -src/plugins/jpeg_extractor.lo -src/plugins/jpeg_extractor.o -src/plugins/thumbnailffmpeg_extractor.lo -src/plugins/thumbnailffmpeg_extractor.o -src/plugins/libextractor_archive.la -src/plugins/libextractor_deb.la -src/plugins/libextractor_dvi.la -src/plugins/libextractor_exiv2.la -src/plugins/libextractor_flac.la -src/plugins/libextractor_gif.la -src/plugins/libextractor_gstreamer.la -src/plugins/libextractor_thumbnailffmpeg.la -src/plugins/libextractor_gstreamer_la-gstreamer_extractor.lo -src/plugins/libextractor_gstreamer_la-gstreamer_extractor.o -src/plugins/libextractor_html.la -src/plugins/libextractor_it.la -src/plugins/libextractor_jpeg.la -src/plugins/libextractor_man.la -src/plugins/libextractor_midi.la -src/plugins/libextractor_midi_la-midi_extractor.lo -src/plugins/libextractor_midi_la-midi_extractor.o -src/plugins/libextractor_mime.la -src/plugins/libextractor_mpeg.la -src/plugins/libextractor_nsf.la -src/plugins/libextractor_nsfe.la -src/plugins/libextractor_odf.la -src/plugins/libextractor_ogg.la -src/plugins/libextractor_ole2.la -src/plugins/libextractor_ole2_la-ole2_extractor.lo -src/plugins/libextractor_ole2_la-ole2_extractor.o -src/plugins/libextractor_pdf.la -src/plugins/libextractor_png.la -src/plugins/libextractor_ps.la -src/plugins/libextractor_riff.la -src/plugins/libextractor_rpm.la -src/plugins/libextractor_s3m.la -src/plugins/libextractor_sid.la -src/plugins/libextractor_thumbnailgtk.la -src/plugins/libextractor_thumbnailgtk_la-thumbnailgtk_extractor.lo -src/plugins/libextractor_thumbnailgtk_la-thumbnailgtk_extractor.o -src/plugins/libextractor_tiff.la -src/plugins/libextractor_wav.la -src/plugins/libextractor_xm.la -src/plugins/libextractor_zip.la -src/plugins/libtest.la -src/plugins/man_extractor.lo -src/plugins/man_extractor.o -src/plugins/mime_extractor.lo -src/plugins/mime_extractor.o -src/plugins/mpeg_extractor.lo -src/plugins/mpeg_extractor.o -src/plugins/nsf_extractor.lo -src/plugins/nsf_extractor.o -src/plugins/nsfe_extractor.lo -src/plugins/nsfe_extractor.o -src/plugins/odf_extractor.lo -src/plugins/odf_extractor.o -src/plugins/ogg_extractor.lo -src/plugins/ogg_extractor.o -src/plugins/pdf_extractor.lo -src/plugins/pdf_extractor.o -src/plugins/png_extractor.lo -src/plugins/png_extractor.o -src/plugins/ps_extractor.lo -src/plugins/ps_extractor.o -src/plugins/riff_extractor.lo -src/plugins/riff_extractor.o -src/plugins/rpm_extractor.lo -src/plugins/rpm_extractor.o -src/plugins/s3m_extractor.lo -src/plugins/s3m_extractor.o -src/plugins/sid_extractor.lo -src/plugins/sid_extractor.o +src/plugins/*.o +src/plugins/*.lo +src/plugins/*.la +src/plugins/*.log +src/plugins/*.trs src/plugins/test-suite.log src/plugins/test_archive -src/plugins/test_archive.log -src/plugins/test_archive.o -src/plugins/test_archive.trs src/plugins/test_deb -src/plugins/test_deb.log -src/plugins/test_deb.o -src/plugins/test_deb.trs src/plugins/test_dvi -src/plugins/test_dvi.log -src/plugins/test_dvi.o -src/plugins/test_dvi.trs +src/plugins/test_elf src/plugins/test_exiv2 -src/plugins/test_exiv2.log -src/plugins/test_exiv2.o -src/plugins/test_exiv2.trs src/plugins/test_flac -src/plugins/test_flac.log -src/plugins/test_flac.o -src/plugins/test_flac.trs src/plugins/test_gif -src/plugins/test_gif.log -src/plugins/test_gif.o -src/plugins/test_gif.trs src/plugins/test_gstreamer -src/plugins/test_gstreamer-test_gstreamer.o -src/plugins/test_gstreamer.log -src/plugins/test_gstreamer.trs src/plugins/test_html -src/plugins/test_html.log -src/plugins/test_html.o -src/plugins/test_html.trs src/plugins/test_it -src/plugins/test_it.log -src/plugins/test_it.o -src/plugins/test_it.trs src/plugins/test_jpeg -src/plugins/test_jpeg.log -src/plugins/test_jpeg.o -src/plugins/test_jpeg.trs -src/plugins/test_lib.lo -src/plugins/test_lib.o src/plugins/test_man -src/plugins/test_man.log -src/plugins/test_man.o -src/plugins/test_man.trs src/plugins/test_midi -src/plugins/test_midi.log -src/plugins/test_midi.o -src/plugins/test_midi.trs src/plugins/test_mime -src/plugins/test_mime.log -src/plugins/test_mime.o -src/plugins/test_mime.trs src/plugins/test_mpeg -src/plugins/test_mpeg.log -src/plugins/test_mpeg.o -src/plugins/test_mpeg.trs src/plugins/test_nsf -src/plugins/test_nsf.log -src/plugins/test_nsf.o -src/plugins/test_nsf.trs src/plugins/test_nsfe -src/plugins/test_nsfe.log -src/plugins/test_nsfe.o -src/plugins/test_nsfe.trs src/plugins/test_odf -src/plugins/test_odf.log -src/plugins/test_odf.o -src/plugins/test_odf.trs src/plugins/test_ogg -src/plugins/test_ogg.log -src/plugins/test_ogg.o -src/plugins/test_ogg.trs src/plugins/test_ole2 -src/plugins/test_ole2.log -src/plugins/test_ole2.o -src/plugins/test_ole2.trs src/plugins/test_png -src/plugins/test_png.log -src/plugins/test_png.o -src/plugins/test_png.trs src/plugins/test_ps -src/plugins/test_ps.log -src/plugins/test_ps.o -src/plugins/test_ps.trs src/plugins/test_riff -src/plugins/test_riff.log -src/plugins/test_riff.o -src/plugins/test_riff.trs src/plugins/test_rpm -src/plugins/test_rpm.log -src/plugins/test_rpm.o -src/plugins/test_rpm.trs src/plugins/test_s3m -src/plugins/test_s3m.log -src/plugins/test_s3m.o -src/plugins/test_s3m.trs src/plugins/test_sid -src/plugins/test_sid.log -src/plugins/test_sid.o -src/plugins/test_sid.trs src/plugins/test_thumbnailgtk -src/plugins/test_thumbnailgtk.log -src/plugins/test_thumbnailgtk.o -src/plugins/test_thumbnailgtk.trs src/plugins/test_tiff -src/plugins/test_tiff.log -src/plugins/test_tiff.o -src/plugins/test_tiff.trs src/plugins/test_wav -src/plugins/test_wav.log -src/plugins/test_wav.o -src/plugins/test_wav.trs src/plugins/test_xm -src/plugins/test_xm.log -src/plugins/test_xm.o -src/plugins/test_xm.trs src/plugins/test_zip -src/plugins/test_zip.log -src/plugins/test_zip.o -src/plugins/test_zip.trs -src/plugins/tiff_extractor.lo -src/plugins/tiff_extractor.o -src/plugins/wav_extractor.lo -src/plugins/wav_extractor.o -src/plugins/xm_extractor.lo -src/plugins/xm_extractor.o -src/plugins/zip_extractor.lo -src/plugins/zip_extractor.o stamp-h1 test-driver - -nothing added to commit but untracked files present (use "git add" to track) src/plugins/test_thumbnailffmpeg build-aux/ diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,6 @@ +Sat 01 May 2021 10:57:55 PM CEST + Revive ELF plugin (fixes #2516). -CG + Tue 20 Apr 2021 06:33:46 PM CEST Removing plugins depending on buggy, unstable libffmpeg library. -CG diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am @@ -165,6 +165,7 @@ endif plugin_LTLIBRARIES = \ libextractor_dvi.la \ + libextractor_elf.la \ libextractor_it.la \ libextractor_man.la \ libextractor_nsf.la \ @@ -200,6 +201,7 @@ endif check_PROGRAMS = \ test_dvi \ + test_elf \ test_it \ test_man \ test_nsf \ @@ -283,6 +285,19 @@ test_dvi_SOURCES = \ test_dvi_LDADD = \ $(top_builddir)/src/plugins/libtest.la +libextractor_elf_la_SOURCES = \ + elf_extractor.c \ + pack.c pack.h +libextractor_elf_la_LDFLAGS = \ + $(PLUGINFLAGS) +libextractor_elf_la_LIBADD = \ + $(XLIB) $(SOCKET_LIBS) + +test_elf_SOURCES = \ + test_elf.c +test_elf_LDADD = \ + $(top_builddir)/src/plugins/libtest.la + libextractor_exiv2_la_SOURCES = \ exiv2_extractor.cc diff --git a/src/plugins/elf_extractor.c b/src/plugins/elf_extractor.c @@ -0,0 +1,802 @@ +/* + This file is part of libextractor. + Copyright (C) 2012 Vidyut Samanta and Christian Grothoff + + libextractor is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + libextractor is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libextractor; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ +/** + * @file plugins/gif_extractor.c + * @brief plugin to support GIF files + * @author Christian Grothoff + */ +#include "platform.h" +#include "extractor.h" +#include "pack.h" +#include <stdint.h> + + +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Word; + +typedef uint16_t Elf64_Half; +typedef uint32_t Elf64_Word; +typedef uint64_t Elf64_Addr; +typedef uint64_t Elf64_Off; + +/* first 4 bytes of the ELF header */ +static char elfMagic[] = { 0x7f, 'E', 'L', 'F' }; + +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 +#define EI_OSABI 7 +#define EI_NIDENT 16 + +typedef struct +{ + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; /* offset of the section header table */ + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phensize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; /* size of each entry in SH table */ + Elf32_Half e_shnum; /* how many entries in section header table */ + Elf32_Half e_shstrndx; /* section header's sh_name member is index into this string table! */ +} Elf32_Ehdr; + +/* elf-header minus e_ident */ +#define ELF_HEADER_SIZE sizeof (Elf32_Ehdr) + +#define ELF_HEADER_FIELDS(p) \ + & (p)->e_type, \ + &(p)->e_machine, \ + &(p)->e_version, \ + &(p)->e_entry, \ + &(p)->e_phoff, \ + &(p)->e_shoff, \ + &(p)->e_flags, \ + &(p)->e_ehsize, \ + &(p)->e_phensize, \ + &(p)->e_phnum, \ + &(p)->e_shentsize, \ + &(p)->e_shnum, \ + &(p)->e_shstrndx +static char *ELF_HEADER_SPECS[] = { + "hhwwwwwhhhhhh", + "HHWWWWWHHHHHH", +}; + +typedef struct +{ + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; + Elf64_Addr e_entry; + Elf64_Off e_phoff; + Elf64_Off e_shoff; + Elf64_Word e_flags; + Elf64_Half e_ehsize; + Elf64_Half e_phensize; + Elf64_Half e_phnum; + Elf64_Half e_shentsize; + Elf64_Half e_shnum; + Elf64_Half e_shstrndx; +} Elf64_Ehdr; + +/* elf-header minus e_ident */ +#define ELF64_HEADER_SIZE sizeof (Elf64_Ehdr) + +#define ELF64_HEADER_FIELDS(p) \ + & (p)->e_type, \ + &(p)->e_machine, \ + &(p)->e_version, \ + &(p)->e_entry, \ + &(p)->e_phoff, \ + &(p)->e_shoff, \ + &(p)->e_flags, \ + &(p)->e_ehsize, \ + &(p)->e_phensize, \ + &(p)->e_phnum, \ + &(p)->e_shentsize, \ + &(p)->e_shnum, \ + &(p)->e_shstrndx +static char *ELF64_HEADER_SPECS[] = { + "hhwxxxwhhhhhh", + "HHWXXXWHHHHHH", +}; + + +typedef struct +{ + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; /* where loaded */ + Elf32_Off sh_offset; /* where in image (! sh_type==SHT_NOBITS) */ + Elf32_Word sh_size; /* section size in bytes */ + Elf32_Word sh_link; /* for symbol table: section header index of the associated string table! */ + Elf32_Word sh_info; /* "one greater than the symbol table index of the last local symbol _STB_LOCAL_" */ + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; +#define ELF_SECTION_SIZE 40 + +#define ELF_SECTION_FIELDS(p) \ + & (p)->sh_name, \ + &(p)->sh_type, \ + &(p)->sh_flags, \ + &(p)->sh_addr, \ + &(p)->sh_offset, \ + &(p)->sh_size, \ + &(p)->sh_link, \ + &(p)->sh_info, \ + &(p)->sh_addralign, \ + &(p)->sh_entsize +static char *ELF_SECTION_SPECS[] = { + "wwwwwwwwww", + "WWWWWWWWWW", +}; + +typedef struct +{ + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; +#define ELF_PDHR_SIZE 32 +#define ELF_PHDR_FIELDS(p) \ + & (p)->p_type, \ + &(p)->p_offset, \ + &(p)->p_vaddr, \ + &(p)->p_paddr, \ + &(p)->p_filesz, \ + &(p)->p_memsz, \ + &(p)->p_flags, \ + &(p)->p_align +static char *ELF_PHDR_SPECS[] = { + "wwwwwwww", + "WWWWWWWW", +}; + +typedef struct +{ + Elf32_Sword d_tag; + union + { + Elf32_Word d_val; + Elf32_Addr d_ptr; + } d_un; +} Elf32_Dyn; +#define ELF_DYN_SIZE 8 +#define ELF_DYN_FIELDS(p) \ + & (p)->d_tag, \ + &(p)->d_un +static char *ELF_DYN_SPECS[] = { + "ww", + "WW", +}; + +#define ET_NONE 0 +#define ET_REL 1 +#define ET_EXEC 2 +#define ET_DYN 3 +#define ET_CORE 4 +#define ET_LOPROC 0xff00 +#define ET_HIPROC 0xffff + +#define EM_NONE 0 +#define EM_M32 1 +#define EM_SPARC 2 +#define EM_386 3 +#define EM_68K 4 +#define EM_88K 5 +#define EM_860 7 +#define EM_MIPS 8 +#define EM_PPC 20 +#define EM_PPC64 21 +#define EM_S390 22 +#define EM_ARM 40 +#define EM_ALPHA 41 +#define EM_IA_64 50 +#define EM_X86_64 62 +#define EM_CUDA 190 + +#define ELFOSABI_NETBSD 2 +#define ELFOSABI_LINUX 3 +#define ELFOSABI_IRIX 8 +#define ELFOSABI_FREEBSD 9 +#define ELFOSABI_OPENBSD 12 + +#define EV_NONE 0 +#define EV_CURRENT 1 + +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +/* string table! */ +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +/* dynamic linking info! */ +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xffffffff + +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_MASKPROC 0xf000000 + +#define DT_NULL 0 +/* name of a needed library, offset into table + recorded in DT_STRTAB entry */ +#define DT_NEEDED 1 +#define DT_PLTRELSZ 2 +#define DT_PLTGOT 3 +#define DT_HASH 4 +/* address of the string table from where symbol + names, library names, etc for this DT come from */ +#define DT_STRTAB 5 +#define DT_SYMTAB 6 +#define DT_SYMENT 7 +#define DT_RELA 7 +#define DT_RELASZ 8 +#define DT_RELAENT 9 +/* size of the string-table in bytes */ +#define DT_STRSZ 10 +/* fixme 11 */ +#define DT_INIT 12 +#define DT_FINI 13 +/* string-table offset giving the name of the shared object */ +#define DT_SONAME 14 +/* string-table offset of a null-terminated library search path */ +#define DT_RPATH 15 +#define DT_SYMBOLIC 16 + + +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff + + +#define ELFCLASSNONE 0 +#define ELFCLASS32 1 +#define ELFCLASS64 2 + +#define ELFDATANONE 0 +/* little endian */ +#define ELFDATA2LSB 1 +/* big endian */ +#define ELFDATA2MSB 2 + +/** + * @param ei_data ELFDATA2LSB or ELFDATA2MSB + * @return 1 if we need to convert, 0 if not + */ +static int +getByteorder (char ei_data) +{ + if (ei_data == ELFDATA2LSB) + { +#if __BYTE_ORDER == __BIG_ENDIAN + return 1; +#else + return 0; +#endif + } + else + { +#if __BYTE_ORDER == __BIG_ENDIAN + return 0; +#else + return 1; +#endif + } +} + + +/** + * + * @return 0 on success, -1 on error + */ +static int +getSectionHdr (struct EXTRACTOR_ExtractContext *ec, + unsigned int bo, + const Elf32_Ehdr *ehdr, + Elf32_Half idx, + Elf32_Shdr *ret) +{ + ssize_t size; + uint64_t max; + int64_t off; + void *data; + + if (ehdr->e_shnum <= idx) + return -1; + max = ec->get_size (ec->cls); + if (ehdr->e_shoff + ehdr->e_shentsize * idx + sizeof (*ret) > max) + return -1; + off = ec->seek (ec->cls, + ehdr->e_shoff + ehdr->e_shentsize * idx, + SEEK_SET); + if (-1 == off) + return -1; + size = ec->read (ec->cls, + &data, + sizeof (*ret)); + if (size < sizeof (*ret)) + return -1; + EXTRACTOR_common_cat_unpack (data, + ELF_SECTION_SPECS[bo], + ELF_SECTION_FIELDS (ret)); + return 0; +} + + +/** + * + * @return 0 on success, -1 on error + */ +static int +getDynTag (struct EXTRACTOR_ExtractContext *ec, + unsigned int bo, + const Elf32_Ehdr *ehdr, + Elf32_Off off, + Elf32_Word osize, + unsigned int idx, + Elf32_Dyn *ret) +{ + ssize_t size; + uint64_t max; + int64_t soff; + void *data; + + max = ec->get_size (ec->cls); + if ( (off + osize > max) || + ((idx + 1) * ELF_DYN_SIZE > osize) ) + return -1; + if (off + idx * ELF_DYN_SIZE + sizeof (*ret) > max) + return -1; + soff = ec->seek (ec->cls, + off + idx * ELF_DYN_SIZE, + SEEK_SET); + if (-1 == soff) + return -1; + size = ec->read (ec->cls, + &data, + sizeof (*ret)); + if (size < sizeof (*ret)) + return -1; + EXTRACTOR_common_cat_unpack (data, + ELF_DYN_SPECS[bo], + ELF_DYN_FIELDS (ret)); + return 0; +} + + +/** + * + * @return 0 on success, -1 on error + */ +static int +getProgramHdr (struct EXTRACTOR_ExtractContext *ec, + unsigned int bo, + const Elf32_Ehdr *ehdr, + Elf32_Half idx, + Elf32_Phdr *ret) +{ + void *data; + ssize_t size; + int64_t off; + + if (ehdr->e_phnum <= idx) + return -1; + off = ec->seek (ec->cls, + ehdr->e_phoff + ehdr->e_phensize * idx, + SEEK_SET); + if (-1 == off) + return -1; + size = ec->read (ec->cls, + &data, + sizeof (*ret)); + if (size < sizeof (*ret)) + return -1; + EXTRACTOR_common_cat_unpack (data, + ELF_PHDR_SPECS[bo], + ELF_PHDR_FIELDS (ret)); + return 0; +} + + +/** + * @return the string (offset into data, do NOT free), NULL on error + */ +static char * +readStringTable (struct EXTRACTOR_ExtractContext *ec, + unsigned int bo, + const Elf32_Ehdr *ehdr, + Elf32_Half strTableOffset, + Elf32_Word sh_name) +{ + Elf32_Shdr shrd; + char *data; + ssize_t size; + int64_t off; + + if (-1 == getSectionHdr (ec, + bo, + ehdr, + strTableOffset, + &shrd)) + return NULL; + if ((shrd.sh_type != SHT_STRTAB) || + (shrd.sh_size <= sh_name) ) + return NULL; + off = ec->seek (ec->cls, + shrd.sh_offset, + SEEK_SET); + if (-1 == off) + return NULL; + size = ec->read (ec->cls, + (void **) &data, + shrd.sh_size); + if (size < shrd.sh_size) + return NULL; + if (data[shrd.sh_size - 1] != '\0') + return NULL; + return strdup (&data[sh_name]); +} + + +#define ADD(s, type) do { \ + if (0!=ec->proc (ec->cls, "elf", type, \ + EXTRACTOR_METAFORMAT_UTF8, "text/plain", \ + s, strlen (s) + 1)) \ + { \ + return; \ + } \ +} while (0) + + +/** + * Main entry method for the 'application/x-executable' extraction plugin. + * + * @param ec extraction context provided to the plugin + */ +void +EXTRACTOR_elf_extract_method (struct EXTRACTOR_ExtractContext *ec) +{ + Elf32_Ehdr ehdr; + Elf64_Ehdr ehdr64; + int ret; + unsigned int bo; + char *data; + ssize_t size; + uint64_t max; + size_t want; + + max = ec->get_size (ec->cls); + want = sizeof (ehdr); + if (sizeof (ehdr64) > want) + want = sizeof (ehdr64); + want += EI_NIDENT; + if (max < want) + return; + size = ec->read (ec->cls, + (void**) &data, + max); + if (size < EI_NIDENT) + return; + if (0 != memcmp (data, + elfMagic, + sizeof (elfMagic))) + return; /* not an elf */ + switch (data[EI_CLASS]) + { + case ELFCLASS32: + if (size < sizeof (Elf32_Ehdr) + EI_NIDENT) + return; + bo = getByteorder (data[EI_DATA]); + EXTRACTOR_common_cat_unpack (&data[EI_NIDENT], + ELF_HEADER_SPECS[bo], + ELF_HEADER_FIELDS (&ehdr)); + if (ehdr.e_shoff + ehdr.e_shentsize * ehdr.e_shnum > max) + return; /* invalid offsets... */ + if (ehdr.e_shentsize < ELF_SECTION_SIZE) + return; /* huh? */ + if (ehdr.e_phoff + ehdr.e_phensize * ehdr.e_phnum > max) + return; + ret = 0; + bo = getByteorder (data[EI_CLASS]); + break; + case ELFCLASS64: + if (size < sizeof (Elf64_Ehdr) + EI_NIDENT) + return; + bo = getByteorder (data[EI_DATA]); + EXTRACTOR_common_cat_unpack (&data[EI_NIDENT], + ELF64_HEADER_SPECS[bo], + ELF64_HEADER_FIELDS (&ehdr64)); + if (ehdr64.e_shoff + ((uint32_t) ehdr64.e_shentsize * ehdr64.e_shnum) > + max) + return; /* invalid offsets... */ + if (ehdr64.e_phoff + ((uint32_t) ehdr64.e_phensize * ehdr64.e_phnum) > + max) + return; + bo = getByteorder (data[EI_CLASS]); + ret = 1; + break; + default: + return; + } + + ADD ("application/x-executable", + EXTRACTOR_METATYPE_MIMETYPE); + switch ( ((unsigned char*) data)[EI_OSABI]) + { + case ELFOSABI_LINUX: + ADD ("Linux", + EXTRACTOR_METATYPE_TARGET_OS); + break; + case ELFOSABI_FREEBSD: + ADD ("FreeBSD", + EXTRACTOR_METATYPE_TARGET_OS); + break; + case ELFOSABI_NETBSD: + ADD ("NetBSD", + EXTRACTOR_METATYPE_TARGET_OS); + break; + case ELFOSABI_OPENBSD: + ADD ("OpenBSD", + EXTRACTOR_METATYPE_TARGET_OS); + break; + case ELFOSABI_IRIX: + ADD ("IRIX", + EXTRACTOR_METATYPE_TARGET_OS); + break; + default: + break; + } + switch ( (0 == ret) ? ehdr.e_type : ehdr64.e_type) + { + case ET_REL: + ADD ("Relocatable file", + EXTRACTOR_METATYPE_RESOURCE_TYPE); + break; + case ET_EXEC: + ADD ("Executable file", + EXTRACTOR_METATYPE_RESOURCE_TYPE); + break; + case ET_DYN: + ADD ("Shared object file", + EXTRACTOR_METATYPE_RESOURCE_TYPE); + break; + case ET_CORE: + ADD ("Core file", + EXTRACTOR_METATYPE_RESOURCE_TYPE); + break; + default: + break; /* unknown */ + } + switch ( (0 == ret) ? ehdr.e_machine : ehdr64.e_machine) + { + case EM_M32: + ADD ("M32", + EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); + break; + case EM_386: + ADD ("i386", + EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); + break; + case EM_68K: + ADD ("68K", + EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); + break; + case EM_88K: + ADD ("88K", + EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); + break; + case EM_SPARC: + ADD ("Sparc", + EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); + break; + case EM_860: + ADD ("960", + EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); + break; + case EM_MIPS: + ADD ("MIPS", + EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); + break; + case EM_PPC: + ADD ("PPC", + EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); + break; + case EM_PPC64: + ADD ("PPC64", + EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); + break; + case EM_S390: + ADD ("S390", + EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); + break; + case EM_ARM: + ADD ("ARM", + EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); + break; + case EM_ALPHA: + ADD ("ALPHA", + EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); + break; + case EM_IA_64: + ADD ("IA-64", + EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); + break; + case EM_X86_64: + ADD ("x86_64", + EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); + break; + case EM_CUDA: + ADD ("NVIDIA CUDA", + EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); + break; + default: + break; /* oops */ + } + + if (0 != ret) + return; /* FIXME: full support for 64-bit ELF... */ + for (Elf32_Half idx = 0; idx < ehdr.e_phnum; idx++) + { + Elf32_Phdr phdr; + + if (0 != getProgramHdr (ec, + bo, + &ehdr, + idx, + &phdr)) + return; + if (phdr.p_type == PT_DYNAMIC) + { + unsigned int dc = phdr.p_filesz / ELF_DYN_SIZE; + Elf32_Addr stringPtr; + Elf32_Half stringIdx; + Elf32_Half six; + + stringPtr = 0; + for (unsigned int id = 0; id < dc; id++) + { + Elf32_Dyn dyn; + + if (0 != getDynTag (ec, + bo, + &ehdr, + phdr.p_offset, + phdr.p_filesz, + id, + &dyn)) + return; + if (DT_STRTAB == dyn.d_tag) + { + stringPtr = dyn.d_un.d_ptr; + break; + } + } + if (0 == stringPtr) + return; + for (six = 0; six < ehdr.e_shnum; six++) + { + Elf32_Shdr sec; + + if (-1 == getSectionHdr (ec, + bo, + &ehdr, + six, + &sec)) + return; + if ( (sec.sh_addr == stringPtr) && + (sec.sh_type == SHT_STRTAB) ) + { + stringIdx = six; + break; + } + } + if (six == ehdr.e_shnum) + return; /* stringIdx not found */ + + for (unsigned int id = 0; id < dc; id++) + { + Elf32_Dyn dyn; + + if (0 != getDynTag (ec, + bo, + &ehdr, + phdr.p_offset, + phdr.p_filesz, + id, + &dyn)) + return; + switch (dyn.d_tag) + { + case DT_RPATH: + { + char *rpath; + + rpath = readStringTable (ec, + bo, + &ehdr, + stringIdx, + dyn.d_un.d_val); + /* "source" of the dependencies: path + to dynamic libraries */ + if (NULL != rpath) + { + ADD (rpath, + EXTRACTOR_METATYPE_LIBRARY_SEARCH_PATH); + free (rpath); + } + break; + } + case DT_NEEDED: + { + char *needed; + + needed = readStringTable (ec, + bo, + &ehdr, + stringIdx, + dyn.d_un.d_val); + if (NULL != needed) + { + ADD (needed, + EXTRACTOR_METATYPE_LIBRARY_DEPENDENCY); + free (needed); + } + break; + } + } + } + } + } +} + + +/* end of gif_extractor.c */ diff --git a/src/plugins/old/elf_extractor.c b/src/plugins/old/elf_extractor.c @@ -1,666 +0,0 @@ -/* - This file is part of libextractor. - Copyright (C) 2004, 2009 Vidyut Samanta and Christian Grothoff - - libextractor is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2, or (at your - option) any later version. - - libextractor is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with libextractor; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - */ - -#include "platform.h" -#include "extractor.h" -#include "pack.h" -#include <stdint.h> - -typedef uint32_t Elf32_Addr; -typedef uint16_t Elf32_Half; -typedef uint32_t Elf32_Off; -typedef int32_t Elf32_Sword; -typedef uint32_t Elf32_Word; - -typedef uint16_t Elf64_Half; -typedef uint32_t Elf64_Word; -typedef uint64_t Elf64_Addr; -typedef uint64_t Elf64_Off; - -/* first 4 bytes of the ELF header */ -static char elfMagic[] = { 0x7f, 'E', 'L', 'F' }; - -#define EI_CLASS 4 -#define EI_DATA 5 -#define EI_VERSION 6 -#define EI_OSABI 7 -#define EI_NIDENT 16 - -typedef struct -{ - Elf32_Half e_type; - Elf32_Half e_machine; - Elf32_Word e_version; - Elf32_Addr e_entry; - Elf32_Off e_phoff; - Elf32_Off e_shoff; /* offset of the section header table */ - Elf32_Word e_flags; - Elf32_Half e_ehsize; - Elf32_Half e_phensize; - Elf32_Half e_phnum; - Elf32_Half e_shentsize; /* size of each entry in SH table */ - Elf32_Half e_shnum; /* how many entries in section header table */ - Elf32_Half e_shstrndx; /* section header's sh_name member is index into this string table! */ -} Elf32_Ehdr; - -/* elf-header minus e_ident */ -#define ELF_HEADER_SIZE sizeof (Elf32_Ehdr) - -#define ELF_HEADER_FIELDS(p) \ - & (p)->e_type, \ - &(p)->e_machine, \ - &(p)->e_version, \ - &(p)->e_entry, \ - &(p)->e_phoff, \ - &(p)->e_shoff, \ - &(p)->e_flags, \ - &(p)->e_ehsize, \ - &(p)->e_phensize, \ - &(p)->e_phnum, \ - &(p)->e_shentsize, \ - &(p)->e_shnum, \ - &(p)->e_shstrndx -static char *ELF_HEADER_SPECS[] = { - "hhwwwwwhhhhhh", - "HHWWWWWHHHHHH", -}; - -typedef struct -{ - Elf64_Half e_type; - Elf64_Half e_machine; - Elf64_Word e_version; - Elf64_Addr e_entry; - Elf64_Off e_phoff; - Elf64_Off e_shoff; - Elf64_Word e_flags; - Elf64_Half e_ehsize; - Elf64_Half e_phensize; - Elf64_Half e_phnum; - Elf64_Half e_shentsize; - Elf64_Half e_shnum; - Elf64_Half e_shstrndx; -} Elf64_Ehdr; - -/* elf-header minus e_ident */ -#define ELF64_HEADER_SIZE sizeof (Elf64_Ehdr) - -#define ELF64_HEADER_FIELDS(p) \ - & (p)->e_type, \ - &(p)->e_machine, \ - &(p)->e_version, \ - &(p)->e_entry, \ - &(p)->e_phoff, \ - &(p)->e_shoff, \ - &(p)->e_flags, \ - &(p)->e_ehsize, \ - &(p)->e_phensize, \ - &(p)->e_phnum, \ - &(p)->e_shentsize, \ - &(p)->e_shnum, \ - &(p)->e_shstrndx -static char *ELF64_HEADER_SPECS[] = { - "hhwxxxwhhhhhh", - "HHWXXXWHHHHHH", -}; - - -typedef struct -{ - Elf32_Word sh_name; - Elf32_Word sh_type; - Elf32_Word sh_flags; - Elf32_Addr sh_addr; /* where loaded */ - Elf32_Off sh_offset; /* where in image (! sh_type==SHT_NOBITS) */ - Elf32_Word sh_size; /* section size in bytes */ - Elf32_Word sh_link; /* for symbol table: section header index of the associated string table! */ - Elf32_Word sh_info; /* "one greater than the symbol table index of the last local symbol _STB_LOCAL_" */ - Elf32_Word sh_addralign; - Elf32_Word sh_entsize; -} Elf32_Shdr; -#define ELF_SECTION_SIZE 40 - -#define ELF_SECTION_FIELDS(p) \ - & (p)->sh_name, \ - &(p)->sh_type, \ - &(p)->sh_flags, \ - &(p)->sh_addr, \ - &(p)->sh_offset, \ - &(p)->sh_size, \ - &(p)->sh_link, \ - &(p)->sh_info, \ - &(p)->sh_addralign, \ - &(p)->sh_entsize -static char *ELF_SECTION_SPECS[] = { - "wwwwwwwwww", - "WWWWWWWWWW", -}; - -typedef struct -{ - Elf32_Word p_type; - Elf32_Off p_offset; - Elf32_Addr p_vaddr; - Elf32_Addr p_paddr; - Elf32_Word p_filesz; - Elf32_Word p_memsz; - Elf32_Word p_flags; - Elf32_Word p_align; -} Elf32_Phdr; -#define ELF_PDHR_SIZE 32 -#define ELF_PHDR_FIELDS(p) \ - & (p)->p_type, \ - &(p)->p_offset, \ - &(p)->p_vaddr, \ - &(p)->p_paddr, \ - &(p)->p_filesz, \ - &(p)->p_memsz, \ - &(p)->p_flags, \ - &(p)->p_align -static char *ELF_PHDR_SPECS[] = { - "wwwwwwww", - "WWWWWWWW", -}; - -typedef struct -{ - Elf32_Sword d_tag; - union - { - Elf32_Word d_val; - Elf32_Addr d_ptr; - } d_un; -} Elf32_Dyn; -#define ELF_DYN_SIZE 8 -#define ELF_DYN_FIELDS(p) \ - & (p)->d_tag, \ - &(p)->d_un -static char *ELF_DYN_SPECS[] = { - "ww", - "WW", -}; - -#define ET_NONE 0 -#define ET_REL 1 -#define ET_EXEC 2 -#define ET_DYN 3 -#define ET_CORE 4 -#define ET_LOPROC 0xff00 -#define ET_HIPROC 0xffff - -#define EM_NONE 0 -#define EM_M32 1 -#define EM_SPARC 2 -#define EM_386 3 -#define EM_68K 4 -#define EM_88K 5 -#define EM_860 7 -#define EM_MIPS 8 -#define EM_PPC 20 -#define EM_PPC64 21 -#define EM_S390 22 -#define EM_ARM 40 -#define EM_ALPHA 41 -#define EM_IA_64 50 -#define EM_X86_64 62 -#define EM_CUDA 190 - -#define ELFOSABI_NETBSD 2 -#define ELFOSABI_LINUX 3 -#define ELFOSABI_IRIX 8 -#define ELFOSABI_FREEBSD 9 -#define ELFOSABI_OPENBSD 12 - -#define EV_NONE 0 -#define EV_CURRENT 1 - -#define SHT_NULL 0 -#define SHT_PROGBITS 1 -#define SHT_SYMTAB 2 -/* string table! */ -#define SHT_STRTAB 3 -#define SHT_RELA 4 -#define SHT_HASH 5 -/* dynamic linking info! */ -#define SHT_DYNAMIC 6 -#define SHT_NOTE 7 -#define SHT_NOBITS 8 -#define SHT_REL 9 -#define SHT_SHLIB 10 -#define SHT_DYNSYM 11 -#define SHT_LOPROC 0x70000000 -#define SHT_HIPROC 0x7fffffff -#define SHT_LOUSER 0x80000000 -#define SHT_HIUSER 0xffffffff - -#define SHF_WRITE 0x1 -#define SHF_ALLOC 0x2 -#define SHF_EXECINSTR 0x4 -#define SHF_MASKPROC 0xf000000 - -#define DT_NULL 0 -/* name of a needed library, offset into table - recorded in DT_STRTAB entry */ -#define DT_NEEDED 1 -#define DT_PLTRELSZ 2 -#define DT_PLTGOT 3 -#define DT_HASH 4 -/* address of the string table from where symbol - names, library names, etc for this DT come from */ -#define DT_STRTAB 5 -#define DT_SYMTAB 6 -#define DT_SYMENT 7 -#define DT_RELA 7 -#define DT_RELASZ 8 -#define DT_RELAENT 9 -/* size of the string-table in bytes */ -#define DT_STRSZ 10 -/* fixme 11 */ -#define DT_INIT 12 -#define DT_FINI 13 -/* string-table offset giving the name of the shared object */ -#define DT_SONAME 14 -/* string-table offset of a null-terminated library search path */ -#define DT_RPATH 15 -#define DT_SYMBOLIC 16 - - -#define PT_NULL 0 -#define PT_LOAD 1 -#define PT_DYNAMIC 2 -#define PT_INTERP 3 -#define PT_NOTE 4 -#define PT_SHLIB 5 -#define PT_PHDR 6 -#define PT_LOPROC 0x70000000 -#define PT_HIPROC 0x7fffffff - - -#define ELFCLASSNONE 0 -#define ELFCLASS32 1 -#define ELFCLASS64 2 - -#define ELFDATANONE 0 -/* little endian */ -#define ELFDATA2LSB 1 -/* big endian */ -#define ELFDATA2MSB 2 - -/** - * @param ei_data ELFDATA2LSB or ELFDATA2MSB - * @return 1 if we need to convert, 0 if not - */ -static int -getByteorder (char ei_data) -{ - if (ei_data == ELFDATA2LSB) - { -#if __BYTE_ORDER == __BIG_ENDIAN - return 1; -#else - return 0; -#endif - } - else - { -#if __BYTE_ORDER == __BIG_ENDIAN - return 0; -#else - return 1; -#endif - } -} - - -/** - * - * @return 0 on success, -1 on error - */ -static int -getSectionHdr (const char *data, - size_t size, - Elf32_Ehdr *ehdr, Elf32_Half idx, Elf32_Shdr *ret) -{ - if (ehdr->e_shnum <= idx) - return -1; - - EXTRACTOR_common_cat_unpack (&data[ehdr->e_shoff + ehdr->e_shentsize * idx], - ELF_SECTION_SPECS[getByteorder (data[EI_CLASS])], - ELF_SECTION_FIELDS (ret)); - return 0; -} - - -/** - * - * @return 0 on success, -1 on error - */ -static int -getDynTag (const char *data, - size_t size, - Elf32_Ehdr *ehdr, - Elf32_Off off, Elf32_Word osize, unsigned int idx, Elf32_Dyn *ret) -{ - if ((off + osize > size) || ((idx + 1) * ELF_DYN_SIZE > osize)) - return -1; - EXTRACTOR_common_cat_unpack (&data[off + idx * ELF_DYN_SIZE], - ELF_DYN_SPECS[getByteorder (data[EI_CLASS])], - ELF_DYN_FIELDS (ret)); - return 0; -} - - -/** - * - * @return 0 on success, -1 on error - */ -static int -getProgramHdr (const char *data, - size_t size, - Elf32_Ehdr *ehdr, Elf32_Half idx, Elf32_Phdr *ret) -{ - if (ehdr->e_phnum <= idx) - return -1; - - EXTRACTOR_common_cat_unpack (&data[ehdr->e_phoff + ehdr->e_phensize * idx], - ELF_PHDR_SPECS[getByteorder (data[EI_CLASS])], - ELF_PHDR_FIELDS (ret)); - return 0; -} - - -/** - * Parse ELF header. - * @return 0 on success for 32 bit, 1 on success for 64 bit, -1 on error - */ -static int -getELFHdr (const char *data, - size_t size, - Elf32_Ehdr *ehdr, - Elf64_Ehdr *ehdr64) -{ - /* catlib */ - if (size < EI_NIDENT) - return -1; - if (0 != strncmp (data, elfMagic, sizeof (elfMagic))) - return -1; /* not an elf */ - - switch (data[EI_CLASS]) - { - case ELFCLASS32: - if (size < sizeof (Elf32_Ehdr) + EI_NIDENT) - return -1; - EXTRACTOR_common_cat_unpack (&data[EI_NIDENT], - ELF_HEADER_SPECS[getByteorder (data[EI_DATA])], - ELF_HEADER_FIELDS (ehdr)); - if (ehdr->e_shoff + ehdr->e_shentsize * ehdr->e_shnum > size) - return -1; /* invalid offsets... */ - if (ehdr->e_shentsize < ELF_SECTION_SIZE) - return -1; /* huh? */ - if (ehdr->e_phoff + ehdr->e_phensize * ehdr->e_phnum > size) - return -1; - return 0; - case ELFCLASS64: - if (size < sizeof (Elf64_Ehdr) + EI_NIDENT) - return -1; - EXTRACTOR_common_cat_unpack (&data[EI_NIDENT], - ELF64_HEADER_SPECS[getByteorder ( - data[EI_DATA])], - ELF64_HEADER_FIELDS (ehdr64)); - if (ehdr64->e_shoff + ((uint32_t) ehdr64->e_shentsize * ehdr64->e_shnum) > - size) - return -1; /* invalid offsets... */ - if (ehdr64->e_phoff + ((uint32_t) ehdr64->e_phensize * ehdr64->e_phnum) > - size) - return -1; - return 1; - default: - return -1; - } -} - - -/** - * @return the string (offset into data, do NOT free), NULL on error - */ -static const char * -readStringTable (const char *data, - size_t size, - Elf32_Ehdr *ehdr, - Elf32_Half strTableOffset, Elf32_Word sh_name) -{ - Elf32_Shdr shrd; - if (-1 == getSectionHdr (data, size, ehdr, strTableOffset, &shrd)) - return NULL; - if ((shrd.sh_type != SHT_STRTAB) || - (shrd.sh_offset + shrd.sh_size > size) || - (shrd.sh_size <= sh_name) || - (data[shrd.sh_offset + shrd.sh_size - 1] != '\0')) - return NULL; - return &data[shrd.sh_offset + sh_name]; -} - - -#define ADD(s, type) do { if (0!=proc (proc_cls, "elf", type, \ - EXTRACTOR_METAFORMAT_UTF8, "text/plain", \ - s, strlen (s) + 1)) return 1; \ -} while (0) - -/* application/x-executable, ELF */ -int -EXTRACTOR_elf_extract (const char *data, - size_t size, - EXTRACTOR_MetaDataProcessor proc, - void *proc_cls, - const char *options) -{ - Elf32_Ehdr ehdr; - Elf32_Half idx; - Elf64_Ehdr ehdr64; - int ret; - - ret = getELFHdr (data, size, &ehdr, &ehdr64); - if (ret == -1) - return 0; - ADD ("application/x-executable", EXTRACTOR_METATYPE_MIMETYPE); - switch ( ((unsigned char*) data)[EI_OSABI]) - { - case ELFOSABI_LINUX: - ADD ("Linux", EXTRACTOR_METATYPE_TARGET_OS); - break; - case ELFOSABI_FREEBSD: - ADD ("FreeBSD", EXTRACTOR_METATYPE_TARGET_OS); - break; - case ELFOSABI_NETBSD: - ADD ("NetBSD", EXTRACTOR_METATYPE_TARGET_OS); - break; - case ELFOSABI_OPENBSD: - ADD ("OpenBSD", EXTRACTOR_METATYPE_TARGET_OS); - break; - case ELFOSABI_IRIX: - ADD ("IRIX", EXTRACTOR_METATYPE_TARGET_OS); - break; - default: - break; - } - switch ( (ret == 0) ? ehdr.e_type : ehdr64.e_type) - { - case ET_REL: - ADD ("Relocatable file", EXTRACTOR_METATYPE_RESOURCE_TYPE); - break; - case ET_EXEC: - ADD ("Executable file", EXTRACTOR_METATYPE_RESOURCE_TYPE); - break; - case ET_DYN: - ADD ("Shared object file", EXTRACTOR_METATYPE_RESOURCE_TYPE); - break; - case ET_CORE: - ADD ("Core file", EXTRACTOR_METATYPE_RESOURCE_TYPE); - break; - default: - break; /* unknown */ - } - switch ( (ret == 0) ? ehdr.e_machine : ehdr64.e_machine) - { - case EM_M32: - ADD ("M32", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); - break; - case EM_386: - ADD ("i386", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); - break; - case EM_68K: - ADD ("68K", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); - break; - case EM_88K: - ADD ("88K", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); - break; - case EM_SPARC: - ADD ("Sparc", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); - break; - case EM_860: - ADD ("960", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); - break; - case EM_MIPS: - ADD ("MIPS", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); - break; - case EM_PPC: - ADD ("PPC", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); - break; - case EM_PPC64: - ADD ("PPC64", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); - break; - case EM_S390: - ADD ("S390", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); - break; - case EM_ARM: - ADD ("ARM", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); - break; - case EM_ALPHA: - ADD ("ALPHA", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); - break; - case EM_IA_64: - ADD ("IA-64", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); - break; - case EM_X86_64: - ADD ("x86_64", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); - break; - case EM_CUDA: - ADD ("NVIDIA CUDA", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE); - break; - default: - break; /* oops */ - } - - if (ret != 0) - return 0; /* FIXME: full support for 64-bit ELF... */ - for (idx = 0; idx < ehdr.e_phnum; idx++) - { - Elf32_Phdr phdr; - - if (0 != getProgramHdr (data, size, &ehdr, idx, &phdr)) - return 0; - if (phdr.p_type == PT_DYNAMIC) - { - unsigned int dc = phdr.p_filesz / ELF_DYN_SIZE; - unsigned int id; - Elf32_Addr stringPtr; - Elf32_Half stringIdx; - Elf32_Half six; - - stringPtr = 0; - - for (id = 0; id < dc; id++) - { - Elf32_Dyn dyn; - if (0 != getDynTag (data, - size, - &ehdr, - phdr.p_offset, phdr.p_filesz, id, &dyn)) - return 0; - if (DT_STRTAB == dyn.d_tag) - { - stringPtr = dyn.d_un.d_ptr; - break; - } - } - if (stringPtr == 0) - return 0; - for (six = 0; six < ehdr.e_shnum; six++) - { - Elf32_Shdr sec; - if (-1 == getSectionHdr (data, size, &ehdr, six, &sec)) - return 0; - if ((sec.sh_addr == stringPtr) && (sec.sh_type == SHT_STRTAB)) - { - stringIdx = six; - break; - } - } - if (six == ehdr.e_shnum) - return 0; /* stringIdx not found */ - - for (id = 0; id < dc; id++) - { - Elf32_Dyn dyn; - if (0 != getDynTag (data, - size, - &ehdr, - phdr.p_offset, phdr.p_filesz, id, &dyn)) - return 0; - switch (dyn.d_tag) - { - case DT_RPATH: - { - const char *rpath; - - rpath = readStringTable (data, - size, - &ehdr, - stringIdx, dyn.d_un.d_val); - /* "source" of the dependencies: path - to dynamic libraries */ - if (rpath != NULL) - { - ADD (rpath, EXTRACTOR_METATYPE_LIBRARY_SEARCH_PATH); - } - break; - } - case DT_NEEDED: - { - const char *needed; - - needed = readStringTable (data, - size, - &ehdr, - stringIdx, dyn.d_un.d_val); - if (needed != NULL) - { - ADD (needed, EXTRACTOR_METATYPE_LIBRARY_DEPENDENCY); - } - break; - } - } - } - - } - } - - return 0; -} diff --git a/src/plugins/old/pack.c b/src/plugins/pack.c diff --git a/src/plugins/old/pack.h b/src/plugins/pack.h diff --git a/src/plugins/test_elf.c b/src/plugins/test_elf.c @@ -0,0 +1,83 @@ +/* + This file is part of libextractor. + Copyright (C) 2021 Christian Grothoff + + libextractor is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + libextractor is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libextractor; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +/** + * @file plugins/test_elf.c + * @brief testcase for elf plugin + * @author Christian Grothoff + */ +#include "platform.h" +#include "test_lib.h" + + +/** + * Main function for the ELF testcase. + * + * @param argc number of arguments (ignored) + * @param argv arguments (ignored) + * @return 0 on success + */ +int +main (int argc, char *argv[]) +{ + struct SolutionData elf_sol[] = { + { + EXTRACTOR_METATYPE_MIMETYPE, + EXTRACTOR_METAFORMAT_UTF8, + "text/plain", + "application/x-executable", + strlen ("application/x-executable") + 1, + 0 + }, + { + EXTRACTOR_METATYPE_TARGET_ARCHITECTURE, + EXTRACTOR_METAFORMAT_UTF8, + "text/plain", + "i386", + strlen ("i386") + 1, + 0 + }, + { + EXTRACTOR_METATYPE_RESOURCE_TYPE, + EXTRACTOR_METAFORMAT_UTF8, + "text/plain", + "Executable file", + strlen ("Executable file") + 1, + 0 + }, + { + EXTRACTOR_METATYPE_LIBRARY_DEPENDENCY, + EXTRACTOR_METAFORMAT_UTF8, + "text/plain", + "libc.so.6", + strlen ("libc.so.6") + 1, + 0 + }, + { 0, 0, NULL, NULL, 0, -1 } + }; + struct ProblemSet ps[] = { + { "testdata/chello-elf", + elf_sol }, + { NULL, NULL } + }; + return ET_main ("elf", ps); +} + + +/* end of test_elf.c */ diff --git a/src/plugins/testdata/chello-elf b/src/plugins/testdata/chello-elf Binary files differ.