| /* | |
| * File elf_private.h - definitions for processing of ELF files | |
| * | |
| * Copyright (C) 1996, Eric Youngdale. | |
| * 1999-2007 Eric Pouech | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library 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 | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | |
| */ | |
| #ifdef HAVE_ELF_H | |
| # include <elf.h> | |
| #endif | |
| #ifdef HAVE_SYS_ELF32_H | |
| # include <sys/elf32.h> | |
| #endif | |
| #ifdef HAVE_SYS_EXEC_ELF_H | |
| # include <sys/exec_elf.h> | |
| #endif | |
| #if !defined(DT_NUM) | |
| # if defined(DT_COUNT) | |
| # define DT_NUM DT_COUNT | |
| # else | |
| /* this seems to be a satisfactory value on Solaris, which doesn't support this AFAICT */ | |
| # define DT_NUM 24 | |
| # endif | |
| #endif | |
| #ifdef HAVE_LINK_H | |
| # include <link.h> | |
| #endif | |
| #ifdef HAVE_SYS_LINK_H | |
| # include <sys/link.h> | |
| #endif | |
| #ifdef HAVE_MACH_O_LOADER_H | |
| #include <mach-o/loader.h> | |
| #ifdef _WIN64 | |
| typedef struct mach_header_64 macho_mach_header; | |
| typedef struct section_64 macho_section; | |
| #else | |
| typedef struct mach_header macho_mach_header; | |
| typedef struct section macho_section; | |
| #endif | |
| #endif | |
| #define IMAGE_NO_MAP ((void*)-1) | |
| #ifdef __ELF__ | |
| #ifdef _WIN64 | |
| #define Elf_Ehdr Elf64_Ehdr | |
| #define Elf_Shdr Elf64_Shdr | |
| #define Elf_Phdr Elf64_Phdr | |
| #define Elf_Dyn Elf64_Dyn | |
| #define Elf_Sym Elf64_Sym | |
| #define Elf_auxv_t Elf64_auxv_t | |
| #else | |
| #define Elf_Ehdr Elf32_Ehdr | |
| #define Elf_Shdr Elf32_Shdr | |
| #define Elf_Phdr Elf32_Phdr | |
| #define Elf_Dyn Elf32_Dyn | |
| #define Elf_Sym Elf32_Sym | |
| #define Elf_auxv_t Elf32_auxv_t | |
| #endif | |
| #else | |
| #ifndef SHT_NULL | |
| #define SHT_NULL 0 | |
| #endif | |
| #endif | |
| /* structure holding information while handling an ELF image | |
| * allows one by one section mapping for memory savings | |
| */ | |
| struct image_file_map | |
| { | |
| enum module_type modtype; | |
| unsigned addr_size; /* either 16 (not used), 32 or 64 */ | |
| union | |
| { | |
| struct elf_file_map | |
| { | |
| size_t elf_size; | |
| size_t elf_start; | |
| int fd; | |
| const char* shstrtab; | |
| struct image_file_map* alternate; /* another ELF file (linked to this one) */ | |
| char* target_copy; | |
| #ifdef __ELF__ | |
| Elf_Ehdr elfhdr; | |
| struct | |
| { | |
| Elf_Shdr shdr; | |
| const char* mapped; | |
| }* sect; | |
| #endif | |
| } elf; | |
| struct macho_file_map | |
| { | |
| size_t segs_size; | |
| size_t segs_start; | |
| int fd; | |
| struct image_file_map* dsym; /* the debug symbols file associated with this one */ | |
| #ifdef HAVE_MACH_O_LOADER_H | |
| macho_mach_header mach_header; | |
| const struct load_command* load_commands; | |
| const struct uuid_command* uuid; | |
| /* The offset in the file which is this architecture. mach_header was | |
| * read from arch_offset. */ | |
| unsigned arch_offset; | |
| int num_sections; | |
| struct | |
| { | |
| const macho_section* section; | |
| const char* mapped; | |
| unsigned int ignored : 1; | |
| }* sect; | |
| #endif | |
| } macho; | |
| struct pe_file_map | |
| { | |
| HANDLE hMap; | |
| IMAGE_NT_HEADERS ntheader; | |
| unsigned full_count; | |
| void* full_map; | |
| struct | |
| { | |
| IMAGE_SECTION_HEADER shdr; | |
| const char* mapped; | |
| }* sect; | |
| const char* strtable; | |
| } pe; | |
| } u; | |
| }; | |
| struct image_section_map | |
| { | |
| struct image_file_map* fmap; | |
| long sidx; | |
| }; | |
| extern BOOL elf_find_section(struct image_file_map* fmap, const char* name, | |
| unsigned sht, struct image_section_map* ism) DECLSPEC_HIDDEN; | |
| extern const char* elf_map_section(struct image_section_map* ism) DECLSPEC_HIDDEN; | |
| extern void elf_unmap_section(struct image_section_map* ism) DECLSPEC_HIDDEN; | |
| extern DWORD_PTR elf_get_map_rva(const struct image_section_map* ism) DECLSPEC_HIDDEN; | |
| extern unsigned elf_get_map_size(const struct image_section_map* ism) DECLSPEC_HIDDEN; | |
| extern BOOL macho_find_section(struct image_file_map* ifm, const char* segname, | |
| const char* sectname, struct image_section_map* ism) DECLSPEC_HIDDEN; | |
| extern const char* macho_map_section(struct image_section_map* ism) DECLSPEC_HIDDEN; | |
| extern void macho_unmap_section(struct image_section_map* ism) DECLSPEC_HIDDEN; | |
| extern DWORD_PTR macho_get_map_rva(const struct image_section_map* ism) DECLSPEC_HIDDEN; | |
| extern unsigned macho_get_map_size(const struct image_section_map* ism) DECLSPEC_HIDDEN; | |
| extern BOOL pe_find_section(struct image_file_map* fmap, const char* name, | |
| struct image_section_map* ism) DECLSPEC_HIDDEN; | |
| extern const char* pe_map_section(struct image_section_map* psm) DECLSPEC_HIDDEN; | |
| extern void pe_unmap_section(struct image_section_map* psm) DECLSPEC_HIDDEN; | |
| extern DWORD_PTR pe_get_map_rva(const struct image_section_map* psm) DECLSPEC_HIDDEN; | |
| extern unsigned pe_get_map_size(const struct image_section_map* psm) DECLSPEC_HIDDEN; | |
| static inline BOOL image_find_section(struct image_file_map* fmap, const char* name, | |
| struct image_section_map* ism) | |
| { | |
| switch (fmap->modtype) | |
| { | |
| case DMT_ELF: return elf_find_section(fmap, name, SHT_NULL, ism); | |
| case DMT_MACHO: return macho_find_section(fmap, NULL, name, ism); | |
| case DMT_PE: return pe_find_section(fmap, name, ism); | |
| default: assert(0); return FALSE; | |
| } | |
| } | |
| static inline const char* image_map_section(struct image_section_map* ism) | |
| { | |
| if (!ism->fmap) return NULL; | |
| switch (ism->fmap->modtype) | |
| { | |
| case DMT_ELF: return elf_map_section(ism); | |
| case DMT_MACHO: return macho_map_section(ism); | |
| case DMT_PE: return pe_map_section(ism); | |
| default: assert(0); return NULL; | |
| } | |
| } | |
| static inline void image_unmap_section(struct image_section_map* ism) | |
| { | |
| if (!ism->fmap) return; | |
| switch (ism->fmap->modtype) | |
| { | |
| case DMT_ELF: elf_unmap_section(ism); break; | |
| case DMT_MACHO: macho_unmap_section(ism); break; | |
| case DMT_PE: pe_unmap_section(ism); break; | |
| default: assert(0); return; | |
| } | |
| } | |
| static inline DWORD_PTR image_get_map_rva(const struct image_section_map* ism) | |
| { | |
| if (!ism->fmap) return 0; | |
| switch (ism->fmap->modtype) | |
| { | |
| case DMT_ELF: return elf_get_map_rva(ism); | |
| case DMT_MACHO: return macho_get_map_rva(ism); | |
| case DMT_PE: return pe_get_map_rva(ism); | |
| default: assert(0); return 0; | |
| } | |
| } | |
| static inline unsigned image_get_map_size(const struct image_section_map* ism) | |
| { | |
| if (!ism->fmap) return 0; | |
| switch (ism->fmap->modtype) | |
| { | |
| case DMT_ELF: return elf_get_map_size(ism); | |
| case DMT_MACHO: return macho_get_map_size(ism); | |
| case DMT_PE: return pe_get_map_size(ism); | |
| default: assert(0); return 0; | |
| } | |
| } |