diff options
Diffstat (limited to 'src/plugins/elf_extractor.c')
-rw-r--r-- | src/plugins/elf_extractor.c | 802 |
1 files changed, 802 insertions, 0 deletions
diff --git a/src/plugins/elf_extractor.c b/src/plugins/elf_extractor.c new file mode 100644 index 0000000..379f615 --- /dev/null +++ b/src/plugins/elf_extractor.c | |||
@@ -0,0 +1,802 @@ | |||
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/gif_extractor.c | ||
22 | * @brief plugin to support GIF 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 gif_extractor.c */ | ||