| // Copyright (c) 2019 coolxv |
| // |
| // Distributed under the MIT Software License |
| // See accompanying file LICENSE.txt or copy at |
| // https://opensource.org/licenses/MIT |
| |
| /*** Start of inlined file: elfio_dump.hpp ***/ |
| #ifndef ELFIO_DUMP_HPP |
| #define ELFIO_DUMP_HPP |
| |
| #include <algorithm> |
| #include <string> |
| #include <ostream> |
| #include <sstream> |
| #include <iomanip> |
| |
| /*** Start of inlined file: elfio.hpp ***/ |
| #ifndef ELFIO_HPP |
| #define ELFIO_HPP |
| |
| #ifdef _MSC_VER |
| #pragma warning( push ) |
| #pragma warning( disable : 4996 ) |
| #pragma warning( disable : 4355 ) |
| #pragma warning( disable : 4244 ) |
| #endif |
| |
| #include <string> |
| #include <iostream> |
| #include <fstream> |
| #include <functional> |
| #include <algorithm> |
| #include <vector> |
| #include <deque> |
| #include <iterator> |
| |
| |
| /*** Start of inlined file: elf_types.hpp ***/ |
| #ifndef ELFTYPES_H |
| #define ELFTYPES_H |
| |
| #ifndef ELFIO_NO_OWN_TYPES |
| #if !defined( ELFIO_NO_CSTDINT ) && !defined( ELFIO_NO_INTTYPES ) |
| #include <stdint.h> |
| #else |
| typedef unsigned char uint8_t; |
| typedef signed char int8_t; |
| typedef unsigned short uint16_t; |
| typedef signed short int16_t; |
| #ifdef _MSC_VER |
| typedef unsigned __int32 uint32_t; |
| typedef signed __int32 int32_t; |
| typedef unsigned __int64 uint64_t; |
| typedef signed __int64 int64_t; |
| #else |
| typedef unsigned int uint32_t; |
| typedef signed int int32_t; |
| typedef unsigned long long uint64_t; |
| typedef signed long long int64_t; |
| #endif // _MSC_VER |
| #endif // ELFIO_NO_CSTDINT |
| #endif // ELFIO_NO_OWN_TYPES |
| |
| namespace ELFIO { |
| |
| // Attention! Platform depended definitions. |
| typedef uint16_t Elf_Half; |
| typedef uint32_t Elf_Word; |
| typedef int32_t Elf_Sword; |
| typedef uint64_t Elf_Xword; |
| typedef int64_t Elf_Sxword; |
| |
| typedef uint32_t Elf32_Addr; |
| typedef uint32_t Elf32_Off; |
| typedef uint64_t Elf64_Addr; |
| typedef uint64_t Elf64_Off; |
| |
| #define Elf32_Half Elf_Half |
| #define Elf64_Half Elf_Half |
| #define Elf32_Word Elf_Word |
| #define Elf64_Word Elf_Word |
| #define Elf32_Sword Elf_Sword |
| #define Elf64_Sword Elf_Sword |
| |
| /////////////////////// |
| // ELF Header Constants |
| |
| // File type |
| #define ET_NONE 0 |
| #define ET_REL 1 |
| #define ET_EXEC 2 |
| #define ET_DYN 3 |
| #define ET_CORE 4 |
| #define ET_LOOS 0xFE00 |
| #define ET_HIOS 0xFEFF |
| #define ET_LOPROC 0xFF00 |
| #define ET_HIPROC 0xFFFF |
| |
| #define EM_NONE 0 // No machine |
| #define EM_M32 1 // AT&T WE 32100 |
| #define EM_SPARC 2 // SUN SPARC |
| #define EM_386 3 // Intel 80386 |
| #define EM_68K 4 // Motorola m68k family |
| #define EM_88K 5 // Motorola m88k family |
| #define EM_486 6 // Intel 80486// Reserved for future use |
| #define EM_860 7 // Intel 80860 |
| #define EM_MIPS 8 // MIPS R3000 (officially, big-endian only) |
| #define EM_S370 9 // IBM System/370 |
| #define EM_MIPS_RS3_LE \ |
| 10 // MIPS R3000 little-endian (Oct 4 1999 Draft) Deprecated |
| #define EM_res011 11 // Reserved |
| #define EM_res012 12 // Reserved |
| #define EM_res013 13 // Reserved |
| #define EM_res014 14 // Reserved |
| #define EM_PARISC 15 // HPPA |
| #define EM_res016 16 // Reserved |
| #define EM_VPP550 17 // Fujitsu VPP500 |
| #define EM_SPARC32PLUS 18 // Sun's "v8plus" |
| #define EM_960 19 // Intel 80960 |
| #define EM_PPC 20 // PowerPC |
| #define EM_PPC64 21 // 64-bit PowerPC |
| #define EM_S390 22 // IBM S/390 |
| #define EM_SPU 23 // Sony/Toshiba/IBM SPU |
| #define EM_res024 24 // Reserved |
| #define EM_res025 25 // Reserved |
| #define EM_res026 26 // Reserved |
| #define EM_res027 27 // Reserved |
| #define EM_res028 28 // Reserved |
| #define EM_res029 29 // Reserved |
| #define EM_res030 30 // Reserved |
| #define EM_res031 31 // Reserved |
| #define EM_res032 32 // Reserved |
| #define EM_res033 33 // Reserved |
| #define EM_res034 34 // Reserved |
| #define EM_res035 35 // Reserved |
| #define EM_V800 36 // NEC V800 series |
| #define EM_FR20 37 // Fujitsu FR20 |
| #define EM_RH32 38 // TRW RH32 |
| #define EM_MCORE 39 // Motorola M*Core // May also be taken by Fujitsu MMA |
| #define EM_RCE 39 // Old name for MCore |
| #define EM_ARM 40 // ARM |
| #define EM_OLD_ALPHA 41 // Digital Alpha |
| #define EM_SH 42 // Renesas (formerly Hitachi) / SuperH SH |
| #define EM_SPARCV9 43 // SPARC v9 64-bit |
| #define EM_TRICORE 44 // Siemens Tricore embedded processor |
| #define EM_ARC 45 // ARC Cores |
| #define EM_H8_300 46 // Renesas (formerly Hitachi) H8/300 |
| #define EM_H8_300H 47 // Renesas (formerly Hitachi) H8/300H |
| #define EM_H8S 48 // Renesas (formerly Hitachi) H8S |
| #define EM_H8_500 49 // Renesas (formerly Hitachi) H8/500 |
| #define EM_IA_64 50 // Intel IA-64 Processor |
| #define EM_MIPS_X 51 // Stanford MIPS-X |
| #define EM_COLDFIRE 52 // Motorola Coldfire |
| #define EM_68HC12 53 // Motorola M68HC12 |
| #define EM_MMA 54 // Fujitsu Multimedia Accelerator |
| #define EM_PCP 55 // Siemens PCP |
| #define EM_NCPU 56 // Sony nCPU embedded RISC processor |
| #define EM_NDR1 57 // Denso NDR1 microprocesspr |
| #define EM_STARCORE 58 // Motorola Star*Core processor |
| #define EM_ME16 59 // Toyota ME16 processor |
| #define EM_ST100 60 // STMicroelectronics ST100 processor |
| #define EM_TINYJ 61 // Advanced Logic Corp. TinyJ embedded processor |
| #define EM_X86_64 62 // Advanced Micro Devices X86-64 processor |
| #define EM_PDSP 63 // Sony DSP Processor |
| #define EM_PDP10 64 // Digital Equipment Corp. PDP-10 |
| #define EM_PDP11 65 // Digital Equipment Corp. PDP-11 |
| #define EM_FX66 66 // Siemens FX66 microcontroller |
| #define EM_ST9PLUS 67 // STMicroelectronics ST9+ 8/16 bit microcontroller |
| #define EM_ST7 68 // STMicroelectronics ST7 8-bit microcontroller |
| #define EM_68HC16 69 // Motorola MC68HC16 Microcontroller |
| #define EM_68HC11 70 // Motorola MC68HC11 Microcontroller |
| #define EM_68HC08 71 // Motorola MC68HC08 Microcontroller |
| #define EM_68HC05 72 // Motorola MC68HC05 Microcontroller |
| #define EM_SVX 73 // Silicon Graphics SVx |
| #define EM_ST19 74 // STMicroelectronics ST19 8-bit cpu |
| #define EM_VAX 75 // Digital VAX |
| #define EM_CRIS 76 // Axis Communications 32-bit embedded processor |
| #define EM_JAVELIN 77 // Infineon Technologies 32-bit embedded cpu |
| #define EM_FIREPATH 78 // Element 14 64-bit DSP processor |
| #define EM_ZSP 79 // LSI Logic's 16-bit DSP processor |
| #define EM_MMIX 80 // Donald Knuth's educational 64-bit processor |
| #define EM_HUANY 81 // Harvard's machine-independent format |
| #define EM_PRISM 82 // SiTera Prism |
| #define EM_AVR 83 // Atmel AVR 8-bit microcontroller |
| #define EM_FR30 84 // Fujitsu FR30 |
| #define EM_D10V 85 // Mitsubishi D10V |
| #define EM_D30V 86 // Mitsubishi D30V |
| #define EM_V850 87 // NEC v850 |
| #define EM_M32R 88 // Renesas M32R (formerly Mitsubishi M32R) |
| #define EM_MN10300 89 // Matsushita MN10300 |
| #define EM_MN10200 90 // Matsushita MN10200 |
| #define EM_PJ 91 // picoJava |
| #define EM_OPENRISC 92 // OpenRISC 32-bit embedded processor |
| #define EM_ARC_A5 93 // ARC Cores Tangent-A5 |
| #define EM_XTENSA 94 // Tensilica Xtensa Architecture |
| #define EM_VIDEOCORE 95 // Alphamosaic VideoCore processor |
| #define EM_TMM_GPP 96 // Thompson Multimedia General Purpose Processor |
| #define EM_NS32K 97 // National Semiconductor 32000 series |
| #define EM_TPC 98 // Tenor Network TPC processor |
| #define EM_SNP1K 99 // Trebia SNP 1000 processor |
| #define EM_ST200 100 // STMicroelectronics ST200 microcontroller |
| #define EM_IP2K 101 // Ubicom IP2022 micro controller |
| #define EM_MAX 102 // MAX Processor |
| #define EM_CR 103 // National Semiconductor CompactRISC |
| #define EM_F2MC16 104 // Fujitsu F2MC16 |
| #define EM_MSP430 105 // TI msp430 micro controller |
| #define EM_BLACKFIN 106 // ADI Blackfin |
| #define EM_SE_C33 107 // S1C33 Family of Seiko Epson processors |
| #define EM_SEP 108 // Sharp embedded microprocessor |
| #define EM_ARCA 109 // Arca RISC Microprocessor |
| #define EM_UNICORE \ |
| 110 // Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University |
| #define EM_EXCESS 111 // eXcess: 16/32/64-bit configurable embedded CPU |
| #define EM_DXP 112 // Icera Semiconductor Inc. Deep Execution Processor |
| #define EM_ALTERA_NIOS2 113 // Altera Nios II soft-core processor |
| #define EM_CRX 114 // National Semiconductor CRX |
| #define EM_XGATE 115 // Motorola XGATE embedded processor |
| #define EM_C166 116 // Infineon C16x/XC16x processor |
| #define EM_M16C 117 // Renesas M16C series microprocessors |
| #define EM_DSPIC30F \ |
| 118 // Microchip Technology dsPIC30F Digital Signal Controller |
| #define EM_CE 119 // Freescale Communication Engine RISC core |
| #define EM_M32C 120 // Renesas M32C series microprocessors |
| #define EM_res121 121 // Reserved |
| #define EM_res122 122 // Reserved |
| #define EM_res123 123 // Reserved |
| #define EM_res124 124 // Reserved |
| #define EM_res125 125 // Reserved |
| #define EM_res126 126 // Reserved |
| #define EM_res127 127 // Reserved |
| #define EM_res128 128 // Reserved |
| #define EM_res129 129 // Reserved |
| #define EM_res130 130 // Reserved |
| #define EM_TSK3000 131 // Altium TSK3000 core |
| #define EM_RS08 132 // Freescale RS08 embedded processor |
| #define EM_res133 133 // Reserved |
| #define EM_ECOG2 134 // Cyan Technology eCOG2 microprocessor |
| #define EM_SCORE 135 // Sunplus Score |
| #define EM_SCORE7 135 // Sunplus S+core7 RISC processor |
| #define EM_DSP24 136 // New Japan Radio (NJR) 24-bit DSP Processor |
| #define EM_VIDEOCORE3 137 // Broadcom VideoCore III processor |
| #define EM_LATTICEMICO32 138 // RISC processor for Lattice FPGA architecture |
| #define EM_SE_C17 139 // Seiko Epson C17 family |
| #define EM_TI_C6000 140 // Texas Instruments TMS320C6000 DSP family |
| #define EM_TI_C2000 141 // Texas Instruments TMS320C2000 DSP family |
| #define EM_TI_C5500 142 // Texas Instruments TMS320C55x DSP family |
| #define EM_res143 143 // Reserved |
| #define EM_res144 144 // Reserved |
| #define EM_res145 145 // Reserved |
| #define EM_res146 146 // Reserved |
| #define EM_res147 147 // Reserved |
| #define EM_res148 148 // Reserved |
| #define EM_res149 149 // Reserved |
| #define EM_res150 150 // Reserved |
| #define EM_res151 151 // Reserved |
| #define EM_res152 152 // Reserved |
| #define EM_res153 153 // Reserved |
| #define EM_res154 154 // Reserved |
| #define EM_res155 155 // Reserved |
| #define EM_res156 156 // Reserved |
| #define EM_res157 157 // Reserved |
| #define EM_res158 158 // Reserved |
| #define EM_res159 159 // Reserved |
| #define EM_MMDSP_PLUS 160 // STMicroelectronics 64bit VLIW Data Signal Processor |
| #define EM_CYPRESS_M8C 161 // Cypress M8C microprocessor |
| #define EM_R32C 162 // Renesas R32C series microprocessors |
| #define EM_TRIMEDIA 163 // NXP Semiconductors TriMedia architecture family |
| #define EM_QDSP6 164 // QUALCOMM DSP6 Processor |
| #define EM_8051 165 // Intel 8051 and variants |
| #define EM_STXP7X 166 // STMicroelectronics STxP7x family |
| #define EM_NDS32 \ |
| 167 // Andes Technology compact code size embedded RISC processor family |
| #define EM_ECOG1 168 // Cyan Technology eCOG1X family |
| #define EM_ECOG1X 168 // Cyan Technology eCOG1X family |
| #define EM_MAXQ30 169 // Dallas Semiconductor MAXQ30 Core Micro-controllers |
| #define EM_XIMO16 170 // New Japan Radio (NJR) 16-bit DSP Processor |
| #define EM_MANIK 171 // M2000 Reconfigurable RISC Microprocessor |
| #define EM_CRAYNV2 172 // Cray Inc. NV2 vector architecture |
| #define EM_RX 173 // Renesas RX family |
| #define EM_METAG 174 // Imagination Technologies META processor architecture |
| #define EM_MCST_ELBRUS 175 // MCST Elbrus general purpose hardware architecture |
| #define EM_ECOG16 176 // Cyan Technology eCOG16 family |
| #define EM_CR16 177 // National Semiconductor CompactRISC 16-bit processor |
| #define EM_ETPU 178 // Freescale Extended Time Processing Unit |
| #define EM_SLE9X 179 // Infineon Technologies SLE9X core |
| #define EM_L1OM 180 // Intel L1OM |
| #define EM_INTEL181 181 // Reserved by Intel |
| #define EM_INTEL182 182 // Reserved by Intel |
| #define EM_res183 183 // Reserved by ARM |
| #define EM_res184 184 // Reserved by ARM |
| #define EM_AVR32 185 // Atmel Corporation 32-bit microprocessor family |
| #define EM_STM8 186 // STMicroeletronics STM8 8-bit microcontroller |
| #define EM_TILE64 187 // Tilera TILE64 multicore architecture family |
| #define EM_TILEPRO 188 // Tilera TILEPro multicore architecture family |
| #define EM_MICROBLAZE 189 // Xilinx MicroBlaze 32-bit RISC soft processor core |
| #define EM_CUDA 190 // NVIDIA CUDA architecture |
| #define EM_TILEGX 191 // Tilera TILE-Gx multicore architecture family |
| #define EM_CLOUDSHIELD 192 // CloudShield architecture family |
| #define EM_COREA_1ST 193 // KIPO-KAIST Core-A 1st generation processor family |
| #define EM_COREA_2ND 194 // KIPO-KAIST Core-A 2nd generation processor family |
| #define EM_ARC_COMPACT2 195 // Synopsys ARCompact V2 |
| #define EM_OPEN8 196 // Open8 8-bit RISC soft processor core |
| #define EM_RL78 197 // Renesas RL78 family |
| #define EM_VIDEOCORE5 198 // Broadcom VideoCore V processor |
| #define EM_78KOR 199 // Renesas 78KOR family |
| #define EM_56800EX 200 // Freescale 56800EX Digital Signal Controller (DSC) |
| #define EM_BA1 201 // Beyond BA1 CPU architecture |
| #define EM_BA2 202 // Beyond BA2 CPU architecture |
| #define EM_XCORE 203 // XMOS xCORE processor family |
| #define EM_MCHP_PIC 204 // Microchip 8-bit PIC(r) family |
| #define EM_INTEL205 205 // Reserved by Intel |
| #define EM_INTEL206 206 // Reserved by Intel |
| #define EM_INTEL207 207 // Reserved by Intel |
| #define EM_INTEL208 208 // Reserved by Intel |
| #define EM_INTEL209 209 // Reserved by Intel |
| #define EM_KM32 210 // KM211 KM32 32-bit processor |
| #define EM_KMX32 211 // KM211 KMX32 32-bit processor |
| #define EM_KMX16 212 // KM211 KMX16 16-bit processor |
| #define EM_KMX8 213 // KM211 KMX8 8-bit processor |
| #define EM_KVARC 214 // KM211 KVARC processor |
| #define EM_CDP 215 // Paneve CDP architecture family |
| #define EM_COGE 216 // Cognitive Smart Memory Processor |
| #define EM_COOL 217 // iCelero CoolEngine |
| #define EM_NORC 218 // Nanoradio Optimized RISC |
| #define EM_CSR_KALIMBA 219 // CSR Kalimba architecture family |
| #define EM_Z80 220 // Zilog Z80 |
| #define EM_VISIUM 221 // Controls and Data Services VISIUMcore processor |
| #define EM_FT32 222 // FTDI Chip FT32 high performance 32-bit RISC architecture |
| #define EM_MOXIE 223 // Moxie processor family |
| #define EM_AMDGPU 224 // AMD GPU architecture |
| #define EM_RISCV 243 // RISC-V |
| #define EM_LANAI 244 // Lanai processor |
| #define EM_CEVA 245 // CEVA Processor Architecture Family |
| #define EM_CEVA_X2 246 // CEVA X2 Processor Family |
| #define EM_BPF 247 // Linux BPF – in-kernel virtual machine |
| #define EM_GRAPHCORE_IPU 248 // Graphcore Intelligent Processing Unit |
| #define EM_IMG1 249 // Imagination Technologies |
| #define EM_NFP 250 // Netronome Flow Processor (P) |
| #define EM_CSKY 252 // C-SKY processor family |
| |
| // File version |
| #define EV_NONE 0 |
| #define EV_CURRENT 1 |
| |
| // Identification index |
| #define EI_MAG0 0 |
| #define EI_MAG1 1 |
| #define EI_MAG2 2 |
| #define EI_MAG3 3 |
| #define EI_CLASS 4 |
| #define EI_DATA 5 |
| #define EI_VERSION 6 |
| #define EI_OSABI 7 |
| #define EI_ABIVERSION 8 |
| #define EI_PAD 9 |
| #define EI_NIDENT 16 |
| |
| // Magic number |
| #define ELFMAG0 0x7F |
| #define ELFMAG1 'E' |
| #define ELFMAG2 'L' |
| #define ELFMAG3 'F' |
| |
| // File class |
| #define ELFCLASSNONE 0 |
| #define ELFCLASS32 1 |
| #define ELFCLASS64 2 |
| |
| // Encoding |
| #define ELFDATANONE 0 |
| #define ELFDATA2LSB 1 |
| #define ELFDATA2MSB 2 |
| |
| // OS extensions |
| #define ELFOSABI_NONE 0 // No extensions or unspecified |
| #define ELFOSABI_HPUX 1 // Hewlett-Packard HP-UX |
| #define ELFOSABI_NETBSD 2 // NetBSD |
| #define ELFOSABI_LINUX 3 // Linux |
| #define ELFOSABI_SOLARIS 6 // Sun Solaris |
| #define ELFOSABI_AIX 7 // AIX |
| #define ELFOSABI_IRIX 8 // IRIX |
| #define ELFOSABI_FREEBSD 9 // FreeBSD |
| #define ELFOSABI_TRU64 10 // Compaq TRU64 UNIX |
| #define ELFOSABI_MODESTO 11 // Novell Modesto |
| #define ELFOSABI_OPENBSD 12 // Open BSD |
| #define ELFOSABI_OPENVMS 13 // Open VMS |
| #define ELFOSABI_NSK 14 // Hewlett-Packard Non-Stop Kernel |
| #define ELFOSABI_AROS 15 // Amiga Research OS |
| #define ELFOSABI_FENIXOS 16 // The FenixOS highly scalable multi-core OS |
| // 64-255 Architecture-specific value range |
| #define ELFOSABI_AMDGPU_HSA \ |
| 64 // AMDGPU OS for HSA compatible compute // kernels. |
| #define ELFOSABI_AMDGPU_PAL \ |
| 65 // AMDGPU OS for AMD PAL compatible graphics // shaders and compute kernels. |
| #define ELFOSABI_AMDGPU_MESA3D \ |
| 66 // AMDGPU OS for Mesa3D compatible graphics // shaders and compute kernels. |
| |
| // AMDGPU specific e_flags |
| #define EF_AMDGPU_MACH 0x0ff // AMDGPU processor selection mask. |
| #define EF_AMDGPU_XNACK \ |
| 0x100 // Indicates if the XNACK target feature is // enabled for all code contained in the ELF. |
| // AMDGPU processors |
| #define EF_AMDGPU_MACH_NONE 0x000 // Unspecified processor. |
| #define EF_AMDGPU_MACH_R600_R600 0x001 |
| #define EF_AMDGPU_MACH_R600_R630 0x002 |
| #define EF_AMDGPU_MACH_R600_RS880 0x003 |
| #define EF_AMDGPU_MACH_R600_RV670 0x004 |
| #define EF_AMDGPU_MACH_R600_RV710 0x005 |
| #define EF_AMDGPU_MACH_R600_RV730 0x006 |
| #define EF_AMDGPU_MACH_R600_RV770 0x007 |
| #define EF_AMDGPU_MACH_R600_CEDAR 0x008 |
| #define EF_AMDGPU_MACH_R600_CYPRESS 0x009 |
| #define EF_AMDGPU_MACH_R600_JUNIPER 0x00a |
| #define EF_AMDGPU_MACH_R600_REDWOOD 0x00b |
| #define EF_AMDGPU_MACH_R600_SUMO 0x00c |
| #define EF_AMDGPU_MACH_R600_BARTS 0x00d |
| #define EF_AMDGPU_MACH_R600_CAICOS 0x00e |
| #define EF_AMDGPU_MACH_R600_CAYMAN 0x00f |
| #define EF_AMDGPU_MACH_R600_TURKS 0x010 |
| #define EF_AMDGPU_MACH_R600_RESERVED_FIRST 0x011 |
| #define EF_AMDGPU_MACH_R600_RESERVED_LAST 0x01f |
| #define EF_AMDGPU_MACH_R600_FIRST EF_AMDGPU_MACH_R600_R600 |
| #define EF_AMDGPU_MACH_R600_LAST EF_AMDGPU_MACH_R600_TURKS |
| #define EF_AMDGPU_MACH_AMDGCN_GFX600 0x020 |
| #define EF_AMDGPU_MACH_AMDGCN_GFX601 0x021 |
| #define EF_AMDGPU_MACH_AMDGCN_GFX700 0x022 |
| #define EF_AMDGPU_MACH_AMDGCN_GFX701 0x023 |
| #define EF_AMDGPU_MACH_AMDGCN_GFX702 0x024 |
| #define EF_AMDGPU_MACH_AMDGCN_GFX703 0x025 |
| #define EF_AMDGPU_MACH_AMDGCN_GFX704 0x026 |
| #define EF_AMDGPU_MACH_AMDGCN_GFX801 0x028 |
| #define EF_AMDGPU_MACH_AMDGCN_GFX802 0x029 |
| #define EF_AMDGPU_MACH_AMDGCN_GFX803 0x02a |
| #define EF_AMDGPU_MACH_AMDGCN_GFX810 0x02b |
| #define EF_AMDGPU_MACH_AMDGCN_GFX900 0x02c |
| #define EF_AMDGPU_MACH_AMDGCN_GFX902 0x02d |
| #define EF_AMDGPU_MACH_AMDGCN_GFX904 0x02e |
| #define EF_AMDGPU_MACH_AMDGCN_GFX906 0x02f |
| #define EF_AMDGPU_MACH_AMDGCN_RESERVED0 0x027 |
| #define EF_AMDGPU_MACH_AMDGCN_RESERVED1 0x030 |
| #define EF_AMDGPU_MACH_AMDGCN_FIRST EF_AMDGPU_MACH_AMDGCN_GFX600 |
| #define EF_AMDGPU_MACH_AMDGCN_LAST EF_AMDGPU_MACH_AMDGCN_GFX906 |
| |
| ///////////////////// |
| // Sections constants |
| |
| // Section indexes |
| #define SHN_UNDEF 0 |
| #define SHN_LORESERVE 0xFF00 |
| #define SHN_LOPROC 0xFF00 |
| #define SHN_HIPROC 0xFF1F |
| #define SHN_LOOS 0xFF20 |
| #define SHN_HIOS 0xFF3F |
| #define SHN_ABS 0xFFF1 |
| #define SHN_COMMON 0xFFF2 |
| #define SHN_XINDEX 0xFFFF |
| #define SHN_HIRESERVE 0xFFFF |
| |
| // Section types |
| #define SHT_NULL 0 |
| #define SHT_PROGBITS 1 |
| #define SHT_SYMTAB 2 |
| #define SHT_STRTAB 3 |
| #define SHT_RELA 4 |
| #define SHT_HASH 5 |
| #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_INIT_ARRAY 14 |
| #define SHT_FINI_ARRAY 15 |
| #define SHT_PREINIT_ARRAY 16 |
| #define SHT_GROUP 17 |
| #define SHT_SYMTAB_SHNDX 18 |
| #define SHT_LOOS 0x60000000 |
| #define SHT_HIOS 0x6fffffff |
| #define SHT_LOPROC 0x70000000 |
| #define SHT_HIPROC 0x7FFFFFFF |
| #define SHT_LOUSER 0x80000000 |
| #define SHT_HIUSER 0xFFFFFFFF |
| |
| // Section attribute flags |
| #define SHF_WRITE 0x1 |
| #define SHF_ALLOC 0x2 |
| #define SHF_EXECINSTR 0x4 |
| #define SHF_MERGE 0x10 |
| #define SHF_STRINGS 0x20 |
| #define SHF_INFO_LINK 0x40 |
| #define SHF_LINK_ORDER 0x80 |
| #define SHF_OS_NONCONFORMING 0x100 |
| #define SHF_GROUP 0x200 |
| #define SHF_TLS 0x400 |
| #define SHF_MASKOS 0x0ff00000 |
| #define SHF_MASKPROC 0xF0000000 |
| |
| // Section group flags |
| #define GRP_COMDAT 0x1 |
| #define GRP_MASKOS 0x0ff00000 |
| #define GRP_MASKPROC 0xf0000000 |
| |
| // Symbol binding |
| #define STB_LOCAL 0 |
| #define STB_GLOBAL 1 |
| #define STB_WEAK 2 |
| #define STB_LOOS 10 |
| #define STB_HIOS 12 |
| #define STB_MULTIDEF 13 |
| #define STB_LOPROC 13 |
| #define STB_HIPROC 15 |
| |
| // Note types |
| #define NT_AMDGPU_METADATA 1 |
| #define NT_AMD_AMDGPU_HSA_METADATA 10 |
| #define NT_AMD_AMDGPU_ISA 11 |
| #define NT_AMD_AMDGPU_PAL_METADATA 12 |
| |
| // Symbol types |
| #define STT_NOTYPE 0 |
| #define STT_OBJECT 1 |
| #define STT_FUNC 2 |
| #define STT_SECTION 3 |
| #define STT_FILE 4 |
| #define STT_COMMON 5 |
| #define STT_TLS 6 |
| #define STT_LOOS 10 |
| #define STT_AMDGPU_HSA_KERNEL 10 |
| #define STT_HIOS 12 |
| #define STT_LOPROC 13 |
| #define STT_HIPROC 15 |
| |
| // Symbol visibility |
| #define STV_DEFAULT 0 |
| #define STV_INTERNAL 1 |
| #define STV_HIDDEN 2 |
| #define STV_PROTECTED 3 |
| |
| // Undefined name |
| #define STN_UNDEF 0 |
| |
| // Relocation types |
| #define R_386_NONE 0 |
| #define R_X86_64_NONE 0 |
| #define R_AMDGPU_NONE 0 |
| #define R_386_32 1 |
| #define R_X86_64_64 1 |
| #define R_AMDGPU_ABS32_LO 1 |
| #define R_386_PC32 2 |
| #define R_X86_64_PC32 2 |
| #define R_AMDGPU_ABS32_HI 2 |
| #define R_386_GOT32 3 |
| #define R_X86_64_GOT32 3 |
| #define R_AMDGPU_ABS64 3 |
| #define R_386_PLT32 4 |
| #define R_X86_64_PLT32 4 |
| #define R_AMDGPU_REL32 4 |
| #define R_386_COPY 5 |
| #define R_X86_64_COPY 5 |
| #define R_AMDGPU_REL64 5 |
| #define R_386_GLOB_DAT 6 |
| #define R_X86_64_GLOB_DAT 6 |
| #define R_AMDGPU_ABS32 6 |
| #define R_386_JMP_SLOT 7 |
| #define R_X86_64_JUMP_SLOT 7 |
| #define R_AMDGPU_GOTPCREL 7 |
| #define R_386_RELATIVE 8 |
| #define R_X86_64_RELATIVE 8 |
| #define R_AMDGPU_GOTPCREL32_LO 8 |
| #define R_386_GOTOFF 9 |
| #define R_X86_64_GOTPCREL 9 |
| #define R_AMDGPU_GOTPCREL32_HI 9 |
| #define R_386_GOTPC 10 |
| #define R_X86_64_32 10 |
| #define R_AMDGPU_REL32_LO 10 |
| #define R_386_32PLT 11 |
| #define R_X86_64_32S 11 |
| #define R_AMDGPU_REL32_HI 11 |
| #define R_X86_64_16 12 |
| #define R_X86_64_PC16 13 |
| #define R_AMDGPU_RELATIVE64 13 |
| #define R_386_TLS_TPOFF 14 |
| #define R_X86_64_8 14 |
| #define R_386_TLS_IE 15 |
| #define R_X86_64_PC8 15 |
| #define R_386_TLS_GOTIE 16 |
| #define R_X86_64_DTPMOD64 16 |
| #define R_386_TLS_LE 17 |
| #define R_X86_64_DTPOFF64 17 |
| #define R_386_TLS_GD 18 |
| #define R_X86_64_TPOFF64 18 |
| #define R_386_TLS_LDM 19 |
| #define R_X86_64_TLSGD 19 |
| #define R_386_16 20 |
| #define R_X86_64_TLSLD 20 |
| #define R_386_PC16 21 |
| #define R_X86_64_DTPOFF32 21 |
| #define R_386_8 22 |
| #define R_X86_64_GOTTPOFF 22 |
| #define R_386_PC8 23 |
| #define R_X86_64_TPOFF32 23 |
| #define R_386_TLS_GD_32 24 |
| #define R_X86_64_PC64 24 |
| #define R_386_TLS_GD_PUSH 25 |
| #define R_X86_64_GOTOFF64 25 |
| #define R_386_TLS_GD_CALL 26 |
| #define R_X86_64_GOTPC32 26 |
| #define R_386_TLS_GD_POP 27 |
| #define R_X86_64_GOT64 27 |
| #define R_386_TLS_LDM_32 28 |
| #define R_X86_64_GOTPCREL64 28 |
| #define R_386_TLS_LDM_PUSH 29 |
| #define R_X86_64_GOTPC64 29 |
| #define R_386_TLS_LDM_CALL 30 |
| #define R_X86_64_GOTPLT64 30 |
| #define R_386_TLS_LDM_POP 31 |
| #define R_X86_64_PLTOFF64 31 |
| #define R_386_TLS_LDO_32 32 |
| #define R_386_TLS_IE_32 33 |
| #define R_386_TLS_LE_32 34 |
| #define R_X86_64_GOTPC32_TLSDESC 34 |
| #define R_386_TLS_DTPMOD32 35 |
| #define R_X86_64_TLSDESC_CALL 35 |
| #define R_386_TLS_DTPOFF32 36 |
| #define R_X86_64_TLSDESC 36 |
| #define R_386_TLS_TPOFF32 37 |
| #define R_X86_64_IRELATIVE 37 |
| #define R_386_SIZE32 38 |
| #define R_386_TLS_GOTDESC 39 |
| #define R_386_TLS_DESC_CALL 40 |
| #define R_386_TLS_DESC 41 |
| #define R_386_IRELATIVE 42 |
| #define R_386_GOT32X 43 |
| #define R_X86_64_GNU_VTINHERIT 250 |
| #define R_X86_64_GNU_VTENTRY 251 |
| |
| // Segment types |
| #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_TLS 7 |
| #define PT_LOOS 0x60000000 |
| #define PT_HIOS 0x6fffffff |
| #define PT_LOPROC 0x70000000 |
| #define PT_HIPROC 0x7FFFFFFF |
| |
| // Segment flags |
| #define PF_X 1 // Execute |
| #define PF_W 2 // Write |
| #define PF_R 4 // Read |
| #define PF_MASKOS 0x0ff00000 // Unspecified |
| #define PF_MASKPROC 0xf0000000 // Unspecified |
| |
| // Dynamic Array Tags |
| #define DT_NULL 0 |
| #define DT_NEEDED 1 |
| #define DT_PLTRELSZ 2 |
| #define DT_PLTGOT 3 |
| #define DT_HASH 4 |
| #define DT_STRTAB 5 |
| #define DT_SYMTAB 6 |
| #define DT_RELA 7 |
| #define DT_RELASZ 8 |
| #define DT_RELAENT 9 |
| #define DT_STRSZ 10 |
| #define DT_SYMENT 11 |
| #define DT_INIT 12 |
| #define DT_FINI 13 |
| #define DT_SONAME 14 |
| #define DT_RPATH 15 |
| #define DT_SYMBOLIC 16 |
| #define DT_REL 17 |
| #define DT_RELSZ 18 |
| #define DT_RELENT 19 |
| #define DT_PLTREL 20 |
| #define DT_DEBUG 21 |
| #define DT_TEXTREL 22 |
| #define DT_JMPREL 23 |
| #define DT_BIND_NOW 24 |
| #define DT_INIT_ARRAY 25 |
| #define DT_FINI_ARRAY 26 |
| #define DT_INIT_ARRAYSZ 27 |
| #define DT_FINI_ARRAYSZ 28 |
| #define DT_RUNPATH 29 |
| #define DT_FLAGS 30 |
| #define DT_ENCODING 32 |
| #define DT_PREINIT_ARRAY 32 |
| #define DT_PREINIT_ARRAYSZ 33 |
| #define DT_MAXPOSTAGS 34 |
| #define DT_LOOS 0x6000000D |
| #define DT_HIOS 0x6ffff000 |
| #define DT_LOPROC 0x70000000 |
| #define DT_HIPROC 0x7FFFFFFF |
| |
| // DT_FLAGS values |
| #define DF_ORIGIN 0x1 |
| #define DF_SYMBOLIC 0x2 |
| #define DF_TEXTREL 0x4 |
| #define DF_BIND_NOW 0x8 |
| #define DF_STATIC_TLS 0x10 |
| |
| // ELF file header |
| struct Elf32_Ehdr |
| { |
| unsigned char e_ident[EI_NIDENT]; |
| Elf_Half e_type; |
| Elf_Half e_machine; |
| Elf_Word e_version; |
| Elf32_Addr e_entry; |
| Elf32_Off e_phoff; |
| Elf32_Off e_shoff; |
| Elf_Word e_flags; |
| Elf_Half e_ehsize; |
| Elf_Half e_phentsize; |
| Elf_Half e_phnum; |
| Elf_Half e_shentsize; |
| Elf_Half e_shnum; |
| Elf_Half e_shstrndx; |
| }; |
| |
| struct Elf64_Ehdr |
| { |
| unsigned char e_ident[EI_NIDENT]; |
| Elf_Half e_type; |
| Elf_Half e_machine; |
| Elf_Word e_version; |
| Elf64_Addr e_entry; |
| Elf64_Off e_phoff; |
| Elf64_Off e_shoff; |
| Elf_Word e_flags; |
| Elf_Half e_ehsize; |
| Elf_Half e_phentsize; |
| Elf_Half e_phnum; |
| Elf_Half e_shentsize; |
| Elf_Half e_shnum; |
| Elf_Half e_shstrndx; |
| }; |
| |
| // Section header |
| struct Elf32_Shdr |
| { |
| Elf_Word sh_name; |
| Elf_Word sh_type; |
| Elf_Word sh_flags; |
| Elf32_Addr sh_addr; |
| Elf32_Off sh_offset; |
| Elf_Word sh_size; |
| Elf_Word sh_link; |
| Elf_Word sh_info; |
| Elf_Word sh_addralign; |
| Elf_Word sh_entsize; |
| }; |
| |
| struct Elf64_Shdr |
| { |
| Elf_Word sh_name; |
| Elf_Word sh_type; |
| Elf_Xword sh_flags; |
| Elf64_Addr sh_addr; |
| Elf64_Off sh_offset; |
| Elf_Xword sh_size; |
| Elf_Word sh_link; |
| Elf_Word sh_info; |
| Elf_Xword sh_addralign; |
| Elf_Xword sh_entsize; |
| }; |
| |
| // Segment header |
| struct Elf32_Phdr |
| { |
| Elf_Word p_type; |
| Elf32_Off p_offset; |
| Elf32_Addr p_vaddr; |
| Elf32_Addr p_paddr; |
| Elf_Word p_filesz; |
| Elf_Word p_memsz; |
| Elf_Word p_flags; |
| Elf_Word p_align; |
| }; |
| |
| struct Elf64_Phdr |
| { |
| Elf_Word p_type; |
| Elf_Word p_flags; |
| Elf64_Off p_offset; |
| Elf64_Addr p_vaddr; |
| Elf64_Addr p_paddr; |
| Elf_Xword p_filesz; |
| Elf_Xword p_memsz; |
| Elf_Xword p_align; |
| }; |
| |
| // Symbol table entry |
| struct Elf32_Sym |
| { |
| Elf_Word st_name; |
| Elf32_Addr st_value; |
| Elf_Word st_size; |
| unsigned char st_info; |
| unsigned char st_other; |
| Elf_Half st_shndx; |
| }; |
| |
| struct Elf64_Sym |
| { |
| Elf_Word st_name; |
| unsigned char st_info; |
| unsigned char st_other; |
| Elf_Half st_shndx; |
| Elf64_Addr st_value; |
| Elf_Xword st_size; |
| }; |
| |
| #define ELF_ST_BIND( i ) ( ( i ) >> 4 ) |
| #define ELF_ST_TYPE( i ) ( (i)&0xf ) |
| #define ELF_ST_INFO( b, t ) ( ( ( b ) << 4 ) + ( (t)&0xf ) ) |
| |
| #define ELF_ST_VISIBILITY( o ) ( (o)&0x3 ) |
| |
| // Relocation entries |
| struct Elf32_Rel |
| { |
| Elf32_Addr r_offset; |
| Elf_Word r_info; |
| }; |
| |
| struct Elf32_Rela |
| { |
| Elf32_Addr r_offset; |
| Elf_Word r_info; |
| Elf_Sword r_addend; |
| }; |
| |
| struct Elf64_Rel |
| { |
| Elf64_Addr r_offset; |
| Elf_Xword r_info; |
| }; |
| |
| struct Elf64_Rela |
| { |
| Elf64_Addr r_offset; |
| Elf_Xword r_info; |
| Elf_Sxword r_addend; |
| }; |
| |
| #define ELF32_R_SYM( i ) ( ( i ) >> 8 ) |
| #define ELF32_R_TYPE( i ) ( (unsigned char)( i ) ) |
| #define ELF32_R_INFO( s, t ) ( ( ( s ) << 8 ) + (unsigned char)( t ) ) |
| |
| #define ELF64_R_SYM( i ) ( ( i ) >> 32 ) |
| #define ELF64_R_TYPE( i ) ( (i)&0xffffffffL ) |
| #define ELF64_R_INFO( s, t ) \ |
| ( ( ( ( int64_t )( s ) ) << 32 ) + ( (t)&0xffffffffL ) ) |
| |
| // Dynamic structure |
| struct Elf32_Dyn |
| { |
| Elf_Sword d_tag; |
| union { |
| Elf_Word d_val; |
| Elf32_Addr d_ptr; |
| } d_un; |
| }; |
| |
| struct Elf64_Dyn |
| { |
| Elf_Sxword d_tag; |
| union { |
| Elf_Xword d_val; |
| Elf64_Addr d_ptr; |
| } d_un; |
| }; |
| |
| } // namespace ELFIO |
| |
| #endif // ELFTYPES_H |
| |
| /*** End of inlined file: elf_types.hpp ***/ |
| |
| |
| /*** Start of inlined file: elfio_version.hpp ***/ |
| #define ELFIO_VERSION "3.8" |
| |
| /*** End of inlined file: elfio_version.hpp ***/ |
| |
| |
| /*** Start of inlined file: elfio_utils.hpp ***/ |
| #ifndef ELFIO_UTILS_HPP |
| #define ELFIO_UTILS_HPP |
| |
| #define ELFIO_GET_ACCESS( TYPE, NAME, FIELD ) \ |
| TYPE get_##NAME() const { return ( *convertor )( FIELD ); } |
| #define ELFIO_SET_ACCESS( TYPE, NAME, FIELD ) \ |
| void set_##NAME( TYPE value ) \ |
| { \ |
| FIELD = value; \ |
| FIELD = ( *convertor )( FIELD ); \ |
| } |
| #define ELFIO_GET_SET_ACCESS( TYPE, NAME, FIELD ) \ |
| TYPE get_##NAME() const { return ( *convertor )( FIELD ); } \ |
| void set_##NAME( TYPE value ) \ |
| { \ |
| FIELD = value; \ |
| FIELD = ( *convertor )( FIELD ); \ |
| } |
| |
| #define ELFIO_GET_ACCESS_DECL( TYPE, NAME ) virtual TYPE get_##NAME() const = 0 |
| |
| #define ELFIO_SET_ACCESS_DECL( TYPE, NAME ) \ |
| virtual void set_##NAME( TYPE value ) = 0 |
| |
| #define ELFIO_GET_SET_ACCESS_DECL( TYPE, NAME ) \ |
| virtual TYPE get_##NAME() const = 0; \ |
| virtual void set_##NAME( TYPE value ) = 0 |
| |
| namespace ELFIO { |
| |
| //------------------------------------------------------------------------------ |
| class endianess_convertor |
| { |
| public: |
| //------------------------------------------------------------------------------ |
| endianess_convertor() { need_conversion = false; } |
| |
| //------------------------------------------------------------------------------ |
| void setup( unsigned char elf_file_encoding ) |
| { |
| need_conversion = ( elf_file_encoding != get_host_encoding() ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| uint64_t operator()( uint64_t value ) const |
| { |
| if ( !need_conversion ) { |
| return value; |
| } |
| value = ( ( value & 0x00000000000000FFull ) << 56 ) | |
| ( ( value & 0x000000000000FF00ull ) << 40 ) | |
| ( ( value & 0x0000000000FF0000ull ) << 24 ) | |
| ( ( value & 0x00000000FF000000ull ) << 8 ) | |
| ( ( value & 0x000000FF00000000ull ) >> 8 ) | |
| ( ( value & 0x0000FF0000000000ull ) >> 24 ) | |
| ( ( value & 0x00FF000000000000ull ) >> 40 ) | |
| ( ( value & 0xFF00000000000000ull ) >> 56 ); |
| |
| return value; |
| } |
| |
| //------------------------------------------------------------------------------ |
| int64_t operator()( int64_t value ) const |
| { |
| if ( !need_conversion ) { |
| return value; |
| } |
| return ( int64_t )( *this )( (uint64_t)value ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| uint32_t operator()( uint32_t value ) const |
| { |
| if ( !need_conversion ) { |
| return value; |
| } |
| value = |
| ( ( value & 0x000000FF ) << 24 ) | ( ( value & 0x0000FF00 ) << 8 ) | |
| ( ( value & 0x00FF0000 ) >> 8 ) | ( ( value & 0xFF000000 ) >> 24 ); |
| |
| return value; |
| } |
| |
| //------------------------------------------------------------------------------ |
| int32_t operator()( int32_t value ) const |
| { |
| if ( !need_conversion ) { |
| return value; |
| } |
| return ( int32_t )( *this )( (uint32_t)value ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| uint16_t operator()( uint16_t value ) const |
| { |
| if ( !need_conversion ) { |
| return value; |
| } |
| value = ( ( value & 0x00FF ) << 8 ) | ( ( value & 0xFF00 ) >> 8 ); |
| |
| return value; |
| } |
| |
| //------------------------------------------------------------------------------ |
| int16_t operator()( int16_t value ) const |
| { |
| if ( !need_conversion ) { |
| return value; |
| } |
| return ( int16_t )( *this )( (uint16_t)value ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| int8_t operator()( int8_t value ) const { return value; } |
| |
| //------------------------------------------------------------------------------ |
| uint8_t operator()( uint8_t value ) const { return value; } |
| |
| //------------------------------------------------------------------------------ |
| private: |
| //------------------------------------------------------------------------------ |
| unsigned char get_host_encoding() const |
| { |
| static const int tmp = 1; |
| if ( 1 == *(const char*)&tmp ) { |
| return ELFDATA2LSB; |
| } |
| else { |
| return ELFDATA2MSB; |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| private: |
| bool need_conversion; |
| }; |
| |
| //------------------------------------------------------------------------------ |
| inline uint32_t elf_hash( const unsigned char* name ) |
| { |
| uint32_t h = 0, g; |
| while ( *name ) { |
| h = ( h << 4 ) + *name++; |
| g = h & 0xf0000000; |
| if ( g != 0 ) |
| h ^= g >> 24; |
| h &= ~g; |
| } |
| return h; |
| } |
| |
| } // namespace ELFIO |
| |
| #endif // ELFIO_UTILS_HPP |
| |
| /*** End of inlined file: elfio_utils.hpp ***/ |
| |
| |
| /*** Start of inlined file: elfio_header.hpp ***/ |
| #ifndef ELF_HEADER_HPP |
| #define ELF_HEADER_HPP |
| |
| #include <iostream> |
| |
| namespace ELFIO { |
| |
| class elf_header |
| { |
| public: |
| virtual ~elf_header(){}; |
| virtual bool load( std::istream& stream ) = 0; |
| virtual bool save( std::ostream& stream ) const = 0; |
| |
| // ELF header functions |
| ELFIO_GET_ACCESS_DECL( unsigned char, class ); |
| ELFIO_GET_ACCESS_DECL( unsigned char, elf_version ); |
| ELFIO_GET_ACCESS_DECL( unsigned char, encoding ); |
| ELFIO_GET_ACCESS_DECL( Elf_Half, header_size ); |
| ELFIO_GET_ACCESS_DECL( Elf_Half, section_entry_size ); |
| ELFIO_GET_ACCESS_DECL( Elf_Half, segment_entry_size ); |
| |
| ELFIO_GET_SET_ACCESS_DECL( Elf_Word, version ); |
| ELFIO_GET_SET_ACCESS_DECL( unsigned char, os_abi ); |
| ELFIO_GET_SET_ACCESS_DECL( unsigned char, abi_version ); |
| ELFIO_GET_SET_ACCESS_DECL( Elf_Half, type ); |
| ELFIO_GET_SET_ACCESS_DECL( Elf_Half, machine ); |
| ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags ); |
| ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, entry ); |
| ELFIO_GET_SET_ACCESS_DECL( Elf_Half, sections_num ); |
| ELFIO_GET_SET_ACCESS_DECL( Elf64_Off, sections_offset ); |
| ELFIO_GET_SET_ACCESS_DECL( Elf_Half, segments_num ); |
| ELFIO_GET_SET_ACCESS_DECL( Elf64_Off, segments_offset ); |
| ELFIO_GET_SET_ACCESS_DECL( Elf_Half, section_name_str_index ); |
| }; |
| |
| template <class T> struct elf_header_impl_types; |
| template <> struct elf_header_impl_types<Elf32_Ehdr> |
| { |
| typedef Elf32_Phdr Phdr_type; |
| typedef Elf32_Shdr Shdr_type; |
| static const unsigned char file_class = ELFCLASS32; |
| }; |
| template <> struct elf_header_impl_types<Elf64_Ehdr> |
| { |
| typedef Elf64_Phdr Phdr_type; |
| typedef Elf64_Shdr Shdr_type; |
| static const unsigned char file_class = ELFCLASS64; |
| }; |
| |
| template <class T> class elf_header_impl : public elf_header |
| { |
| public: |
| //------------------------------------------------------------------------------ |
| elf_header_impl( endianess_convertor* convertor_, unsigned char encoding ) |
| { |
| convertor = convertor_; |
| |
| std::fill_n( reinterpret_cast<char*>( &header ), sizeof( header ), |
| '\0' ); |
| |
| header.e_ident[EI_MAG0] = ELFMAG0; |
| header.e_ident[EI_MAG1] = ELFMAG1; |
| header.e_ident[EI_MAG2] = ELFMAG2; |
| header.e_ident[EI_MAG3] = ELFMAG3; |
| header.e_ident[EI_CLASS] = elf_header_impl_types<T>::file_class; |
| header.e_ident[EI_DATA] = encoding; |
| header.e_ident[EI_VERSION] = EV_CURRENT; |
| header.e_version = ( *convertor )( (Elf_Word)EV_CURRENT ); |
| header.e_ehsize = ( sizeof( header ) ); |
| header.e_ehsize = ( *convertor )( header.e_ehsize ); |
| header.e_shstrndx = ( *convertor )( (Elf_Half)1 ); |
| header.e_phentsize = |
| sizeof( typename elf_header_impl_types<T>::Phdr_type ); |
| header.e_shentsize = |
| sizeof( typename elf_header_impl_types<T>::Shdr_type ); |
| header.e_phentsize = ( *convertor )( header.e_phentsize ); |
| header.e_shentsize = ( *convertor )( header.e_shentsize ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool load( std::istream& stream ) |
| { |
| stream.seekg( 0 ); |
| stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) ); |
| |
| return ( stream.gcount() == sizeof( header ) ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool save( std::ostream& stream ) const |
| { |
| stream.seekp( 0 ); |
| stream.write( reinterpret_cast<const char*>( &header ), |
| sizeof( header ) ); |
| |
| return stream.good(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| // ELF header functions |
| ELFIO_GET_ACCESS( unsigned char, class, header.e_ident[EI_CLASS] ); |
| ELFIO_GET_ACCESS( unsigned char, elf_version, header.e_ident[EI_VERSION] ); |
| ELFIO_GET_ACCESS( unsigned char, encoding, header.e_ident[EI_DATA] ); |
| ELFIO_GET_ACCESS( Elf_Half, header_size, header.e_ehsize ); |
| ELFIO_GET_ACCESS( Elf_Half, section_entry_size, header.e_shentsize ); |
| ELFIO_GET_ACCESS( Elf_Half, segment_entry_size, header.e_phentsize ); |
| |
| ELFIO_GET_SET_ACCESS( Elf_Word, version, header.e_version ); |
| ELFIO_GET_SET_ACCESS( unsigned char, os_abi, header.e_ident[EI_OSABI] ); |
| ELFIO_GET_SET_ACCESS( unsigned char, |
| abi_version, |
| header.e_ident[EI_ABIVERSION] ); |
| ELFIO_GET_SET_ACCESS( Elf_Half, type, header.e_type ); |
| ELFIO_GET_SET_ACCESS( Elf_Half, machine, header.e_machine ); |
| ELFIO_GET_SET_ACCESS( Elf_Word, flags, header.e_flags ); |
| ELFIO_GET_SET_ACCESS( Elf_Half, section_name_str_index, header.e_shstrndx ); |
| ELFIO_GET_SET_ACCESS( Elf64_Addr, entry, header.e_entry ); |
| ELFIO_GET_SET_ACCESS( Elf_Half, sections_num, header.e_shnum ); |
| ELFIO_GET_SET_ACCESS( Elf64_Off, sections_offset, header.e_shoff ); |
| ELFIO_GET_SET_ACCESS( Elf_Half, segments_num, header.e_phnum ); |
| ELFIO_GET_SET_ACCESS( Elf64_Off, segments_offset, header.e_phoff ); |
| |
| private: |
| T header; |
| endianess_convertor* convertor; |
| }; |
| |
| } // namespace ELFIO |
| |
| #endif // ELF_HEADER_HPP |
| |
| /*** End of inlined file: elfio_header.hpp ***/ |
| |
| |
| /*** Start of inlined file: elfio_section.hpp ***/ |
| #ifndef ELFIO_SECTION_HPP |
| #define ELFIO_SECTION_HPP |
| |
| #include <string> |
| #include <iostream> |
| #include <new> |
| |
| namespace ELFIO { |
| |
| class section |
| { |
| friend class elfio; |
| |
| public: |
| virtual ~section(){}; |
| |
| ELFIO_GET_ACCESS_DECL( Elf_Half, index ); |
| ELFIO_GET_SET_ACCESS_DECL( std::string, name ); |
| ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type ); |
| ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, flags ); |
| ELFIO_GET_SET_ACCESS_DECL( Elf_Word, info ); |
| ELFIO_GET_SET_ACCESS_DECL( Elf_Word, link ); |
| ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, addr_align ); |
| ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, entry_size ); |
| ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, address ); |
| ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, size ); |
| ELFIO_GET_SET_ACCESS_DECL( Elf_Word, name_string_offset ); |
| ELFIO_GET_ACCESS_DECL( Elf64_Off, offset ); |
| |
| virtual const char* get_data() const = 0; |
| virtual void set_data( const char* pData, Elf_Word size ) = 0; |
| virtual void set_data( const std::string& data ) = 0; |
| virtual void append_data( const char* pData, Elf_Word size ) = 0; |
| virtual void append_data( const std::string& data ) = 0; |
| virtual size_t get_stream_size() const = 0; |
| virtual void set_stream_size( size_t value ) = 0; |
| |
| protected: |
| ELFIO_SET_ACCESS_DECL( Elf64_Off, offset ); |
| ELFIO_SET_ACCESS_DECL( Elf_Half, index ); |
| |
| virtual void load( std::istream& stream, std::streampos header_offset ) = 0; |
| virtual void save( std::ostream& stream, |
| std::streampos header_offset, |
| std::streampos data_offset ) = 0; |
| virtual bool is_address_initialized() const = 0; |
| }; |
| |
| template <class T> class section_impl : public section |
| { |
| public: |
| //------------------------------------------------------------------------------ |
| section_impl( const endianess_convertor* convertor_ ) |
| : convertor( convertor_ ) |
| { |
| std::fill_n( reinterpret_cast<char*>( &header ), sizeof( header ), |
| '\0' ); |
| is_address_set = false; |
| data = 0; |
| data_size = 0; |
| index = 0; |
| stream_size = 0; |
| } |
| |
| //------------------------------------------------------------------------------ |
| ~section_impl() { delete[] data; } |
| |
| //------------------------------------------------------------------------------ |
| // Section info functions |
| ELFIO_GET_SET_ACCESS( Elf_Word, type, header.sh_type ); |
| ELFIO_GET_SET_ACCESS( Elf_Xword, flags, header.sh_flags ); |
| ELFIO_GET_SET_ACCESS( Elf_Xword, size, header.sh_size ); |
| ELFIO_GET_SET_ACCESS( Elf_Word, link, header.sh_link ); |
| ELFIO_GET_SET_ACCESS( Elf_Word, info, header.sh_info ); |
| ELFIO_GET_SET_ACCESS( Elf_Xword, addr_align, header.sh_addralign ); |
| ELFIO_GET_SET_ACCESS( Elf_Xword, entry_size, header.sh_entsize ); |
| ELFIO_GET_SET_ACCESS( Elf_Word, name_string_offset, header.sh_name ); |
| ELFIO_GET_ACCESS( Elf64_Addr, address, header.sh_addr ); |
| |
| //------------------------------------------------------------------------------ |
| Elf_Half get_index() const { return index; } |
| |
| //------------------------------------------------------------------------------ |
| std::string get_name() const { return name; } |
| |
| //------------------------------------------------------------------------------ |
| void set_name( std::string name_ ) { name = name_; } |
| |
| //------------------------------------------------------------------------------ |
| void set_address( Elf64_Addr value ) |
| { |
| header.sh_addr = value; |
| header.sh_addr = ( *convertor )( header.sh_addr ); |
| is_address_set = true; |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool is_address_initialized() const { return is_address_set; } |
| |
| //------------------------------------------------------------------------------ |
| const char* get_data() const { return data; } |
| |
| //------------------------------------------------------------------------------ |
| void set_data( const char* raw_data, Elf_Word size ) |
| { |
| if ( get_type() != SHT_NOBITS ) { |
| delete[] data; |
| data = new ( std::nothrow ) char[size]; |
| if ( 0 != data && 0 != raw_data ) { |
| data_size = size; |
| std::copy( raw_data, raw_data + size, data ); |
| } |
| else { |
| data_size = 0; |
| } |
| } |
| |
| set_size( data_size ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| void set_data( const std::string& str_data ) |
| { |
| return set_data( str_data.c_str(), (Elf_Word)str_data.size() ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| void append_data( const char* raw_data, Elf_Word size ) |
| { |
| if ( get_type() != SHT_NOBITS ) { |
| if ( get_size() + size < data_size ) { |
| std::copy( raw_data, raw_data + size, data + get_size() ); |
| } |
| else { |
| data_size = 2 * ( data_size + size ); |
| char* new_data = new ( std::nothrow ) char[data_size]; |
| |
| if ( 0 != new_data ) { |
| std::copy( data, data + get_size(), new_data ); |
| std::copy( raw_data, raw_data + size, |
| new_data + get_size() ); |
| delete[] data; |
| data = new_data; |
| } |
| else { |
| size = 0; |
| } |
| } |
| set_size( get_size() + size ); |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| void append_data( const std::string& str_data ) |
| { |
| return append_data( str_data.c_str(), (Elf_Word)str_data.size() ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| protected: |
| //------------------------------------------------------------------------------ |
| ELFIO_GET_SET_ACCESS( Elf64_Off, offset, header.sh_offset ); |
| |
| //------------------------------------------------------------------------------ |
| void set_index( Elf_Half value ) { index = value; } |
| |
| //------------------------------------------------------------------------------ |
| void load( std::istream& stream, std::streampos header_offset ) |
| { |
| std::fill_n( reinterpret_cast<char*>( &header ), sizeof( header ), |
| '\0' ); |
| |
| stream.seekg( 0, stream.end ); |
| set_stream_size( stream.tellg() ); |
| |
| stream.seekg( header_offset ); |
| stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) ); |
| |
| Elf_Xword size = get_size(); |
| if ( 0 == data && SHT_NULL != get_type() && SHT_NOBITS != get_type() && |
| size < get_stream_size() ) { |
| data = new ( std::nothrow ) char[size + 1]; |
| |
| if ( ( 0 != size ) && ( 0 != data ) ) { |
| stream.seekg( ( *convertor )( header.sh_offset ) ); |
| stream.read( data, size ); |
| data[size] = 0; // Ensure data is ended with 0 to avoid oob read |
| data_size = size; |
| } |
| else { |
| data_size = 0; |
| } |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| void save( std::ostream& stream, |
| std::streampos header_offset, |
| std::streampos data_offset ) |
| { |
| if ( 0 != get_index() ) { |
| header.sh_offset = data_offset; |
| header.sh_offset = ( *convertor )( header.sh_offset ); |
| } |
| |
| save_header( stream, header_offset ); |
| if ( get_type() != SHT_NOBITS && get_type() != SHT_NULL && |
| get_size() != 0 && data != 0 ) { |
| save_data( stream, data_offset ); |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| private: |
| //------------------------------------------------------------------------------ |
| void save_header( std::ostream& stream, std::streampos header_offset ) const |
| { |
| stream.seekp( header_offset ); |
| stream.write( reinterpret_cast<const char*>( &header ), |
| sizeof( header ) ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| void save_data( std::ostream& stream, std::streampos data_offset ) const |
| { |
| stream.seekp( data_offset ); |
| stream.write( get_data(), get_size() ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| size_t get_stream_size() const { return stream_size; } |
| |
| //------------------------------------------------------------------------------ |
| void set_stream_size( size_t value ) { stream_size = value; } |
| |
| //------------------------------------------------------------------------------ |
| private: |
| T header; |
| Elf_Half index; |
| std::string name; |
| char* data; |
| Elf_Word data_size; |
| const endianess_convertor* convertor; |
| bool is_address_set; |
| size_t stream_size; |
| }; |
| |
| } // namespace ELFIO |
| |
| #endif // ELFIO_SECTION_HPP |
| |
| /*** End of inlined file: elfio_section.hpp ***/ |
| |
| |
| /*** Start of inlined file: elfio_segment.hpp ***/ |
| #ifndef ELFIO_SEGMENT_HPP |
| #define ELFIO_SEGMENT_HPP |
| |
| #include <iostream> |
| #include <vector> |
| #include <new> |
| |
| namespace ELFIO { |
| |
| class segment |
| { |
| friend class elfio; |
| |
| public: |
| virtual ~segment(){}; |
| |
| ELFIO_GET_ACCESS_DECL( Elf_Half, index ); |
| ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type ); |
| ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags ); |
| ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, align ); |
| ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, virtual_address ); |
| ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, physical_address ); |
| ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, file_size ); |
| ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, memory_size ); |
| ELFIO_GET_ACCESS_DECL( Elf64_Off, offset ); |
| |
| virtual const char* get_data() const = 0; |
| |
| virtual Elf_Half add_section_index( Elf_Half index, |
| Elf_Xword addr_align ) = 0; |
| virtual Elf_Half get_sections_num() const = 0; |
| virtual Elf_Half get_section_index_at( Elf_Half num ) const = 0; |
| virtual bool is_offset_initialized() const = 0; |
| |
| protected: |
| ELFIO_SET_ACCESS_DECL( Elf64_Off, offset ); |
| ELFIO_SET_ACCESS_DECL( Elf_Half, index ); |
| |
| virtual const std::vector<Elf_Half>& get_sections() const = 0; |
| virtual void load( std::istream& stream, std::streampos header_offset ) = 0; |
| virtual void save( std::ostream& stream, |
| std::streampos header_offset, |
| std::streampos data_offset ) = 0; |
| }; |
| |
| //------------------------------------------------------------------------------ |
| template <class T> class segment_impl : public segment |
| { |
| public: |
| //------------------------------------------------------------------------------ |
| segment_impl( endianess_convertor* convertor_ ) |
| : stream_size( 0 ), index( 0 ), data( 0 ), convertor( convertor_ ) |
| { |
| is_offset_set = false; |
| std::fill_n( reinterpret_cast<char*>( &ph ), sizeof( ph ), '\0' ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| virtual ~segment_impl() { delete[] data; } |
| |
| //------------------------------------------------------------------------------ |
| // Section info functions |
| ELFIO_GET_SET_ACCESS( Elf_Word, type, ph.p_type ); |
| ELFIO_GET_SET_ACCESS( Elf_Word, flags, ph.p_flags ); |
| ELFIO_GET_SET_ACCESS( Elf_Xword, align, ph.p_align ); |
| ELFIO_GET_SET_ACCESS( Elf64_Addr, virtual_address, ph.p_vaddr ); |
| ELFIO_GET_SET_ACCESS( Elf64_Addr, physical_address, ph.p_paddr ); |
| ELFIO_GET_SET_ACCESS( Elf_Xword, file_size, ph.p_filesz ); |
| ELFIO_GET_SET_ACCESS( Elf_Xword, memory_size, ph.p_memsz ); |
| ELFIO_GET_ACCESS( Elf64_Off, offset, ph.p_offset ); |
| size_t stream_size; |
| |
| //------------------------------------------------------------------------------ |
| size_t get_stream_size() const { return stream_size; } |
| |
| //------------------------------------------------------------------------------ |
| void set_stream_size( size_t value ) { stream_size = value; } |
| |
| //------------------------------------------------------------------------------ |
| Elf_Half get_index() const { return index; } |
| |
| //------------------------------------------------------------------------------ |
| const char* get_data() const { return data; } |
| |
| //------------------------------------------------------------------------------ |
| Elf_Half add_section_index( Elf_Half sec_index, Elf_Xword addr_align ) |
| { |
| sections.push_back( sec_index ); |
| if ( addr_align > get_align() ) { |
| set_align( addr_align ); |
| } |
| |
| return (Elf_Half)sections.size(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| Elf_Half get_sections_num() const { return (Elf_Half)sections.size(); } |
| |
| //------------------------------------------------------------------------------ |
| Elf_Half get_section_index_at( Elf_Half num ) const |
| { |
| if ( num < sections.size() ) { |
| return sections[num]; |
| } |
| |
| return Elf_Half( -1 ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| protected: |
| //------------------------------------------------------------------------------ |
| |
| //------------------------------------------------------------------------------ |
| void set_offset( Elf64_Off value ) |
| { |
| ph.p_offset = value; |
| ph.p_offset = ( *convertor )( ph.p_offset ); |
| is_offset_set = true; |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool is_offset_initialized() const { return is_offset_set; } |
| |
| //------------------------------------------------------------------------------ |
| const std::vector<Elf_Half>& get_sections() const { return sections; } |
| |
| //------------------------------------------------------------------------------ |
| void set_index( Elf_Half value ) { index = value; } |
| |
| //------------------------------------------------------------------------------ |
| void load( std::istream& stream, std::streampos header_offset ) |
| { |
| |
| stream.seekg( 0, stream.end ); |
| set_stream_size( stream.tellg() ); |
| |
| stream.seekg( header_offset ); |
| stream.read( reinterpret_cast<char*>( &ph ), sizeof( ph ) ); |
| is_offset_set = true; |
| |
| if ( PT_NULL != get_type() && 0 != get_file_size() ) { |
| stream.seekg( ( *convertor )( ph.p_offset ) ); |
| Elf_Xword size = get_file_size(); |
| |
| if ( size > get_stream_size() ) { |
| data = 0; |
| } |
| else { |
| data = new (std::nothrow) char[size + 1]; |
| |
| if ( 0 != data ) { |
| stream.read( data, size ); |
| data[size] = 0; |
| } |
| } |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| void save( std::ostream& stream, |
| std::streampos header_offset, |
| std::streampos data_offset ) |
| { |
| ph.p_offset = data_offset; |
| ph.p_offset = ( *convertor )( ph.p_offset ); |
| stream.seekp( header_offset ); |
| stream.write( reinterpret_cast<const char*>( &ph ), sizeof( ph ) ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| private: |
| T ph; |
| Elf_Half index; |
| char* data; |
| std::vector<Elf_Half> sections; |
| endianess_convertor* convertor; |
| bool is_offset_set; |
| }; |
| |
| } // namespace ELFIO |
| |
| #endif // ELFIO_SEGMENT_HPP |
| |
| /*** End of inlined file: elfio_segment.hpp ***/ |
| |
| |
| /*** Start of inlined file: elfio_strings.hpp ***/ |
| #ifndef ELFIO_STRINGS_HPP |
| #define ELFIO_STRINGS_HPP |
| |
| #include <cstdlib> |
| #include <cstring> |
| #include <string> |
| |
| namespace ELFIO { |
| |
| //------------------------------------------------------------------------------ |
| template <class S> class string_section_accessor_template |
| { |
| public: |
| //------------------------------------------------------------------------------ |
| string_section_accessor_template( S* section_ ) : string_section( section_ ) |
| { |
| } |
| |
| //------------------------------------------------------------------------------ |
| const char* get_string( Elf_Word index ) const |
| { |
| if ( string_section ) { |
| if ( index < string_section->get_size() ) { |
| const char* data = string_section->get_data(); |
| if ( 0 != data ) { |
| return data + index; |
| } |
| } |
| } |
| |
| return 0; |
| } |
| |
| //------------------------------------------------------------------------------ |
| Elf_Word add_string( const char* str ) |
| { |
| Elf_Word current_position = 0; |
| |
| if ( string_section ) { |
| // Strings are addeded to the end of the current section data |
| current_position = (Elf_Word)string_section->get_size(); |
| |
| if ( current_position == 0 ) { |
| char empty_string = '\0'; |
| string_section->append_data( &empty_string, 1 ); |
| current_position++; |
| } |
| string_section->append_data( str, |
| (Elf_Word)std::strlen( str ) + 1 ); |
| } |
| |
| return current_position; |
| } |
| |
| //------------------------------------------------------------------------------ |
| Elf_Word add_string( const std::string& str ) |
| { |
| return add_string( str.c_str() ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| private: |
| S* string_section; |
| }; |
| |
| using string_section_accessor = string_section_accessor_template<section>; |
| using const_string_section_accessor = |
| string_section_accessor_template<const section>; |
| |
| } // namespace ELFIO |
| |
| #endif // ELFIO_STRINGS_HPP |
| |
| /*** End of inlined file: elfio_strings.hpp ***/ |
| |
| #define ELFIO_HEADER_ACCESS_GET( TYPE, FNAME ) \ |
| TYPE get_##FNAME() const { return header ? ( header->get_##FNAME() ) : 0; } |
| |
| #define ELFIO_HEADER_ACCESS_GET_SET( TYPE, FNAME ) \ |
| TYPE get_##FNAME() const \ |
| { \ |
| return header ? ( header->get_##FNAME() ) : 0; \ |
| } \ |
| void set_##FNAME( TYPE val ) \ |
| { \ |
| if ( header ) { \ |
| header->set_##FNAME( val ); \ |
| } \ |
| } |
| |
| namespace ELFIO { |
| |
| //------------------------------------------------------------------------------ |
| class elfio |
| { |
| public: |
| //------------------------------------------------------------------------------ |
| elfio() : sections( this ), segments( this ) |
| { |
| header = 0; |
| current_file_pos = 0; |
| create( ELFCLASS32, ELFDATA2LSB ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| ~elfio() { clean(); } |
| |
| //------------------------------------------------------------------------------ |
| void create( unsigned char file_class, unsigned char encoding ) |
| { |
| clean(); |
| convertor.setup( encoding ); |
| header = create_header( file_class, encoding ); |
| create_mandatory_sections(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool load( const std::string& file_name ) |
| { |
| std::ifstream stream; |
| stream.open( file_name.c_str(), std::ios::in | std::ios::binary ); |
| if ( !stream ) { |
| return false; |
| } |
| |
| return load( stream ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool load( std::istream& stream ) |
| { |
| clean(); |
| |
| unsigned char e_ident[EI_NIDENT]; |
| // Read ELF file signature |
| stream.read( reinterpret_cast<char*>( &e_ident ), sizeof( e_ident ) ); |
| |
| // Is it ELF file? |
| if ( stream.gcount() != sizeof( e_ident ) || |
| e_ident[EI_MAG0] != ELFMAG0 || e_ident[EI_MAG1] != ELFMAG1 || |
| e_ident[EI_MAG2] != ELFMAG2 || e_ident[EI_MAG3] != ELFMAG3 ) { |
| return false; |
| } |
| |
| if ( ( e_ident[EI_CLASS] != ELFCLASS64 ) && |
| ( e_ident[EI_CLASS] != ELFCLASS32 ) ) { |
| return false; |
| } |
| |
| convertor.setup( e_ident[EI_DATA] ); |
| header = create_header( e_ident[EI_CLASS], e_ident[EI_DATA] ); |
| if ( 0 == header ) { |
| return false; |
| } |
| if ( !header->load( stream ) ) { |
| return false; |
| } |
| |
| load_sections( stream ); |
| bool is_still_good = load_segments( stream ); |
| return is_still_good; |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool save( const std::string& file_name ) |
| { |
| std::ofstream stream; |
| stream.open( file_name.c_str(), std::ios::out | std::ios::binary ); |
| if ( !stream ) { |
| return false; |
| } |
| |
| return save( stream ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool save( std::ostream& stream ) |
| { |
| if ( !stream || !header ) { |
| return false; |
| } |
| |
| bool is_still_good = true; |
| // Define layout specific header fields |
| // The position of the segment table is fixed after the header. |
| // The position of the section table is variable and needs to be fixed |
| // before saving. |
| header->set_segments_num( segments.size() ); |
| header->set_segments_offset( segments.size() ? header->get_header_size() |
| : 0 ); |
| header->set_sections_num( sections.size() ); |
| header->set_sections_offset( 0 ); |
| |
| // Layout the first section right after the segment table |
| current_file_pos = header->get_header_size() + |
| header->get_segment_entry_size() * |
| (Elf_Xword)header->get_segments_num(); |
| |
| calc_segment_alignment(); |
| |
| is_still_good = layout_segments_and_their_sections(); |
| is_still_good = is_still_good && layout_sections_without_segments(); |
| is_still_good = is_still_good && layout_section_table(); |
| |
| is_still_good = is_still_good && save_header( stream ); |
| is_still_good = is_still_good && save_sections( stream ); |
| is_still_good = is_still_good && save_segments( stream ); |
| |
| return is_still_good; |
| } |
| |
| //------------------------------------------------------------------------------ |
| // ELF header access functions |
| ELFIO_HEADER_ACCESS_GET( unsigned char, class ); |
| ELFIO_HEADER_ACCESS_GET( unsigned char, elf_version ); |
| ELFIO_HEADER_ACCESS_GET( unsigned char, encoding ); |
| ELFIO_HEADER_ACCESS_GET( Elf_Word, version ); |
| ELFIO_HEADER_ACCESS_GET( Elf_Half, header_size ); |
| ELFIO_HEADER_ACCESS_GET( Elf_Half, section_entry_size ); |
| ELFIO_HEADER_ACCESS_GET( Elf_Half, segment_entry_size ); |
| |
| ELFIO_HEADER_ACCESS_GET_SET( unsigned char, os_abi ); |
| ELFIO_HEADER_ACCESS_GET_SET( unsigned char, abi_version ); |
| ELFIO_HEADER_ACCESS_GET_SET( Elf_Half, type ); |
| ELFIO_HEADER_ACCESS_GET_SET( Elf_Half, machine ); |
| ELFIO_HEADER_ACCESS_GET_SET( Elf_Word, flags ); |
| ELFIO_HEADER_ACCESS_GET_SET( Elf64_Addr, entry ); |
| ELFIO_HEADER_ACCESS_GET_SET( Elf64_Off, sections_offset ); |
| ELFIO_HEADER_ACCESS_GET_SET( Elf64_Off, segments_offset ); |
| ELFIO_HEADER_ACCESS_GET_SET( Elf_Half, section_name_str_index ); |
| |
| //------------------------------------------------------------------------------ |
| const endianess_convertor& get_convertor() const { return convertor; } |
| |
| //------------------------------------------------------------------------------ |
| Elf_Xword get_default_entry_size( Elf_Word section_type ) const |
| { |
| switch ( section_type ) { |
| case SHT_RELA: |
| if ( header->get_class() == ELFCLASS64 ) { |
| return sizeof( Elf64_Rela ); |
| } |
| else { |
| return sizeof( Elf32_Rela ); |
| } |
| case SHT_REL: |
| if ( header->get_class() == ELFCLASS64 ) { |
| return sizeof( Elf64_Rel ); |
| } |
| else { |
| return sizeof( Elf32_Rel ); |
| } |
| case SHT_SYMTAB: |
| if ( header->get_class() == ELFCLASS64 ) { |
| return sizeof( Elf64_Sym ); |
| } |
| else { |
| return sizeof( Elf32_Sym ); |
| } |
| case SHT_DYNAMIC: |
| if ( header->get_class() == ELFCLASS64 ) { |
| return sizeof( Elf64_Dyn ); |
| } |
| else { |
| return sizeof( Elf32_Dyn ); |
| } |
| default: |
| return 0; |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| private: |
| bool is_offset_in_section( Elf64_Off offset, const section* sec ) const |
| { |
| return ( offset >= sec->get_offset() ) && |
| ( offset < ( sec->get_offset() + sec->get_size() ) ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| public: |
| //! returns an empty string if no problems are detected, |
| //! or a string containing an error message if problems are found |
| std::string validate() const |
| { |
| |
| // check for overlapping sections in the file |
| for ( int i = 0; i < sections.size(); ++i ) { |
| for ( int j = i + 1; j < sections.size(); ++j ) { |
| const section* a = sections[i]; |
| const section* b = sections[j]; |
| if ( !( a->get_type() & SHT_NOBITS ) && |
| !( b->get_type() & SHT_NOBITS ) && ( a->get_size() > 0 ) && |
| ( b->get_size() > 0 ) && ( a->get_offset() > 0 ) && |
| ( b->get_offset() > 0 ) ) { |
| if ( is_offset_in_section( a->get_offset(), b ) || |
| is_offset_in_section( |
| a->get_offset() + a->get_size() - 1, b ) || |
| is_offset_in_section( b->get_offset(), a ) || |
| is_offset_in_section( |
| b->get_offset() + b->get_size() - 1, a ) ) { |
| return "Sections " + a->get_name() + " and " + |
| b->get_name() + " overlap in file"; |
| } |
| } |
| } |
| } |
| |
| // more checks to be added here... |
| |
| return ""; |
| } |
| |
| //------------------------------------------------------------------------------ |
| private: |
| //------------------------------------------------------------------------------ |
| void clean() |
| { |
| delete header; |
| header = 0; |
| |
| std::vector<section*>::const_iterator it; |
| for ( it = sections_.begin(); it != sections_.end(); ++it ) { |
| delete *it; |
| } |
| sections_.clear(); |
| |
| std::vector<segment*>::const_iterator it1; |
| for ( it1 = segments_.begin(); it1 != segments_.end(); ++it1 ) { |
| delete *it1; |
| } |
| segments_.clear(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| elf_header* create_header( unsigned char file_class, |
| unsigned char encoding ) |
| { |
| elf_header* new_header = 0; |
| |
| if ( file_class == ELFCLASS64 ) { |
| new_header = |
| new elf_header_impl<Elf64_Ehdr>( &convertor, encoding ); |
| } |
| else if ( file_class == ELFCLASS32 ) { |
| new_header = |
| new elf_header_impl<Elf32_Ehdr>( &convertor, encoding ); |
| } |
| else { |
| return 0; |
| } |
| |
| return new_header; |
| } |
| |
| //------------------------------------------------------------------------------ |
| section* create_section() |
| { |
| section* new_section; |
| unsigned char file_class = get_class(); |
| |
| if ( file_class == ELFCLASS64 ) { |
| new_section = new section_impl<Elf64_Shdr>( &convertor ); |
| } |
| else if ( file_class == ELFCLASS32 ) { |
| new_section = new section_impl<Elf32_Shdr>( &convertor ); |
| } |
| else { |
| return 0; |
| } |
| |
| new_section->set_index( (Elf_Half)sections_.size() ); |
| sections_.push_back( new_section ); |
| |
| return new_section; |
| } |
| |
| //------------------------------------------------------------------------------ |
| segment* create_segment() |
| { |
| segment* new_segment; |
| unsigned char file_class = header->get_class(); |
| |
| if ( file_class == ELFCLASS64 ) { |
| new_segment = new segment_impl<Elf64_Phdr>( &convertor ); |
| } |
| else if ( file_class == ELFCLASS32 ) { |
| new_segment = new segment_impl<Elf32_Phdr>( &convertor ); |
| } |
| else { |
| return 0; |
| } |
| |
| new_segment->set_index( (Elf_Half)segments_.size() ); |
| segments_.push_back( new_segment ); |
| |
| return new_segment; |
| } |
| |
| //------------------------------------------------------------------------------ |
| void create_mandatory_sections() |
| { |
| // Create null section without calling to 'add_section' as no string |
| // section containing section names exists yet |
| section* sec0 = create_section(); |
| sec0->set_index( 0 ); |
| sec0->set_name( "" ); |
| sec0->set_name_string_offset( 0 ); |
| |
| set_section_name_str_index( 1 ); |
| section* shstrtab = sections.add( ".shstrtab" ); |
| shstrtab->set_type( SHT_STRTAB ); |
| shstrtab->set_addr_align( 1 ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| Elf_Half load_sections( std::istream& stream ) |
| { |
| Elf_Half entry_size = header->get_section_entry_size(); |
| Elf_Half num = header->get_sections_num(); |
| Elf64_Off offset = header->get_sections_offset(); |
| |
| for ( Elf_Half i = 0; i < num; ++i ) { |
| section* sec = create_section(); |
| sec->load( stream, (std::streamoff)offset + |
| (std::streampos)i * entry_size ); |
| sec->set_index( i ); |
| // To mark that the section is not permitted to reassign address |
| // during layout calculation |
| sec->set_address( sec->get_address() ); |
| } |
| |
| Elf_Half shstrndx = get_section_name_str_index(); |
| |
| if ( SHN_UNDEF != shstrndx ) { |
| string_section_accessor str_reader( sections[shstrndx] ); |
| for ( Elf_Half i = 0; i < num; ++i ) { |
| Elf_Word section_offset = sections[i]->get_name_string_offset(); |
| const char* p = str_reader.get_string( section_offset ); |
| if ( p != 0 ) { |
| sections[i]->set_name( p ); |
| } |
| } |
| } |
| |
| return num; |
| } |
| |
| //------------------------------------------------------------------------------ |
| //! Checks whether the addresses of the section entirely fall within the given segment. |
| //! It doesn't matter if the addresses are memory addresses, or file offsets, |
| //! they just need to be in the same address space |
| bool is_sect_in_seg( Elf64_Off sect_begin, |
| Elf_Xword sect_size, |
| Elf64_Off seg_begin, |
| Elf64_Off seg_end ) |
| { |
| return ( seg_begin <= sect_begin ) && |
| ( sect_begin + sect_size <= seg_end ) && |
| ( sect_begin < |
| seg_end ); // this is important criteria when sect_size == 0 |
| // Example: seg_begin=10, seg_end=12 (-> covering the bytes 10 and 11) |
| // sect_begin=12, sect_size=0 -> shall return false! |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool load_segments( std::istream& stream ) |
| { |
| Elf_Half entry_size = header->get_segment_entry_size(); |
| Elf_Half num = header->get_segments_num(); |
| Elf64_Off offset = header->get_segments_offset(); |
| |
| for ( Elf_Half i = 0; i < num; ++i ) { |
| segment* seg; |
| unsigned char file_class = header->get_class(); |
| |
| if ( file_class == ELFCLASS64 ) { |
| seg = new segment_impl<Elf64_Phdr>( &convertor ); |
| } |
| else if ( file_class == ELFCLASS32 ) { |
| seg = new segment_impl<Elf32_Phdr>( &convertor ); |
| } |
| else { |
| return false; |
| } |
| |
| seg->load( stream, (std::streamoff)offset + |
| (std::streampos)i * entry_size ); |
| seg->set_index( i ); |
| |
| // Add sections to the segments (similar to readelfs algorithm) |
| Elf64_Off segBaseOffset = seg->get_offset(); |
| Elf64_Off segEndOffset = segBaseOffset + seg->get_file_size(); |
| Elf64_Off segVBaseAddr = seg->get_virtual_address(); |
| Elf64_Off segVEndAddr = segVBaseAddr + seg->get_memory_size(); |
| for ( Elf_Half j = 0; j < sections.size(); ++j ) { |
| const section* psec = sections[j]; |
| |
| // SHF_ALLOC sections are matched based on the virtual address |
| // otherwise the file offset is matched |
| if ( ( psec->get_flags() & SHF_ALLOC ) |
| ? is_sect_in_seg( psec->get_address(), |
| psec->get_size(), segVBaseAddr, |
| segVEndAddr ) |
| : is_sect_in_seg( psec->get_offset(), psec->get_size(), |
| segBaseOffset, segEndOffset ) ) { |
| // Alignment of segment shall not be updated, to preserve original value |
| // It will be re-calculated on saving. |
| seg->add_section_index( psec->get_index(), 0 ); |
| } |
| } |
| |
| // Add section into the segments' container |
| segments_.push_back( seg ); |
| } |
| |
| return true; |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool save_header( std::ostream& stream ) { return header->save( stream ); } |
| |
| //------------------------------------------------------------------------------ |
| bool save_sections( std::ostream& stream ) |
| { |
| for ( unsigned int i = 0; i < sections_.size(); ++i ) { |
| section* sec = sections_.at( i ); |
| |
| std::streampos headerPosition = |
| (std::streamoff)header->get_sections_offset() + |
| (std::streampos)header->get_section_entry_size() * |
| sec->get_index(); |
| |
| sec->save( stream, headerPosition, sec->get_offset() ); |
| } |
| return true; |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool save_segments( std::ostream& stream ) |
| { |
| for ( unsigned int i = 0; i < segments_.size(); ++i ) { |
| segment* seg = segments_.at( i ); |
| |
| std::streampos headerPosition = |
| header->get_segments_offset() + |
| (std::streampos)header->get_segment_entry_size() * |
| seg->get_index(); |
| |
| seg->save( stream, headerPosition, seg->get_offset() ); |
| } |
| return true; |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool is_section_without_segment( unsigned int section_index ) |
| { |
| bool found = false; |
| |
| for ( unsigned int j = 0; !found && ( j < segments.size() ); ++j ) { |
| for ( unsigned int k = 0; |
| !found && ( k < segments[j]->get_sections_num() ); ++k ) { |
| found = segments[j]->get_section_index_at( k ) == section_index; |
| } |
| } |
| |
| return !found; |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool is_subsequence_of( segment* seg1, segment* seg2 ) |
| { |
| // Return 'true' if sections of seg1 are a subset of sections in seg2 |
| const std::vector<Elf_Half>& sections1 = seg1->get_sections(); |
| const std::vector<Elf_Half>& sections2 = seg2->get_sections(); |
| |
| bool found = false; |
| if ( sections1.size() < sections2.size() ) { |
| found = std::includes( sections2.begin(), sections2.end(), |
| sections1.begin(), sections1.end() ); |
| } |
| |
| return found; |
| } |
| |
| //------------------------------------------------------------------------------ |
| std::vector<segment*> get_ordered_segments() |
| { |
| std::vector<segment*> res; |
| std::deque<segment*> worklist; |
| |
| res.reserve( segments.size() ); |
| std::copy( segments_.begin(), segments_.end(), |
| std::back_inserter( worklist ) ); |
| |
| // Bring the segments which start at address 0 to the front |
| size_t nextSlot = 0; |
| for ( size_t i = 0; i < worklist.size(); ++i ) { |
| if ( i != nextSlot && worklist[i]->is_offset_initialized() && |
| worklist[i]->get_offset() == 0 ) { |
| if ( worklist[nextSlot]->get_offset() == 0 ) { |
| ++nextSlot; |
| } |
| std::swap( worklist[i], worklist[nextSlot] ); |
| ++nextSlot; |
| } |
| } |
| |
| while ( !worklist.empty() ) { |
| segment* seg = worklist.front(); |
| worklist.pop_front(); |
| |
| size_t i = 0; |
| for ( ; i < worklist.size(); ++i ) { |
| if ( is_subsequence_of( seg, worklist[i] ) ) { |
| break; |
| } |
| } |
| |
| if ( i < worklist.size() ) |
| worklist.push_back( seg ); |
| else |
| res.push_back( seg ); |
| } |
| |
| return res; |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool layout_sections_without_segments() |
| { |
| for ( unsigned int i = 0; i < sections_.size(); ++i ) { |
| if ( is_section_without_segment( i ) ) { |
| section* sec = sections_[i]; |
| |
| Elf_Xword section_align = sec->get_addr_align(); |
| if ( section_align > 1 && |
| current_file_pos % section_align != 0 ) { |
| current_file_pos += |
| section_align - current_file_pos % section_align; |
| } |
| |
| if ( 0 != sec->get_index() ) |
| sec->set_offset( current_file_pos ); |
| |
| if ( SHT_NOBITS != sec->get_type() && |
| SHT_NULL != sec->get_type() ) { |
| current_file_pos += sec->get_size(); |
| } |
| } |
| } |
| |
| return true; |
| } |
| |
| //------------------------------------------------------------------------------ |
| void calc_segment_alignment() |
| { |
| for ( std::vector<segment*>::iterator s = segments_.begin(); |
| s != segments_.end(); ++s ) { |
| segment* seg = *s; |
| for ( int i = 0; i < seg->get_sections_num(); ++i ) { |
| section* sect = sections_[seg->get_section_index_at( i )]; |
| if ( sect->get_addr_align() > seg->get_align() ) { |
| seg->set_align( sect->get_addr_align() ); |
| } |
| } |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool layout_segments_and_their_sections() |
| { |
| std::vector<segment*> worklist; |
| std::vector<bool> section_generated( sections.size(), false ); |
| |
| // Get segments in a order in where segments which contain a |
| // sub sequence of other segments are located at the end |
| worklist = get_ordered_segments(); |
| |
| for ( unsigned int i = 0; i < worklist.size(); ++i ) { |
| Elf_Xword segment_memory = 0; |
| Elf_Xword segment_filesize = 0; |
| Elf_Xword seg_start_pos = current_file_pos; |
| segment* seg = worklist[i]; |
| |
| // Special case: PHDR segment |
| // This segment contains the program headers but no sections |
| if ( seg->get_type() == PT_PHDR && seg->get_sections_num() == 0 ) { |
| seg_start_pos = header->get_segments_offset(); |
| segment_memory = segment_filesize = |
| header->get_segment_entry_size() * |
| (Elf_Xword)header->get_segments_num(); |
| } |
| // Special case: |
| else if ( seg->is_offset_initialized() && seg->get_offset() == 0 ) { |
| seg_start_pos = 0; |
| if ( seg->get_sections_num() ) { |
| segment_memory = segment_filesize = current_file_pos; |
| } |
| } |
| // New segments with not generated sections |
| // have to be aligned |
| else if ( seg->get_sections_num() && |
| !section_generated[seg->get_section_index_at( 0 )] ) { |
| Elf_Xword align = seg->get_align() > 0 ? seg->get_align() : 1; |
| Elf64_Off cur_page_alignment = current_file_pos % align; |
| Elf64_Off req_page_alignment = |
| seg->get_virtual_address() % align; |
| Elf64_Off error = req_page_alignment - cur_page_alignment; |
| |
| current_file_pos += ( seg->get_align() + error ) % align; |
| seg_start_pos = current_file_pos; |
| } |
| else if ( seg->get_sections_num() ) { |
| seg_start_pos = |
| sections[seg->get_section_index_at( 0 )]->get_offset(); |
| } |
| |
| // Write segment's data |
| for ( unsigned int j = 0; j < seg->get_sections_num(); ++j ) { |
| Elf_Half index = seg->get_section_index_at( j ); |
| |
| section* sec = sections[index]; |
| |
| // The NULL section is always generated |
| if ( SHT_NULL == sec->get_type() ) { |
| section_generated[index] = true; |
| continue; |
| } |
| |
| Elf_Xword secAlign = 0; |
| // Fix up the alignment |
| if ( !section_generated[index] && |
| sec->is_address_initialized() && |
| SHT_NOBITS != sec->get_type() && |
| SHT_NULL != sec->get_type() && 0 != sec->get_size() ) { |
| // Align the sections based on the virtual addresses |
| // when possible (this is what matters for execution) |
| Elf64_Off req_offset = |
| sec->get_address() - seg->get_virtual_address(); |
| Elf64_Off cur_offset = current_file_pos - seg_start_pos; |
| if ( req_offset < cur_offset ) { |
| // something has gone awfully wrong, abort! |
| // secAlign would turn out negative, seeking backwards and overwriting previous data |
| return false; |
| } |
| secAlign = req_offset - cur_offset; |
| } |
| else if ( !section_generated[index] && |
| !sec->is_address_initialized() ) { |
| // If no address has been specified then only the section |
| // alignment constraint has to be matched |
| Elf_Xword align = sec->get_addr_align(); |
| if ( align == 0 ) { |
| align = 1; |
| } |
| Elf64_Off error = current_file_pos % align; |
| secAlign = ( align - error ) % align; |
| } |
| else if ( section_generated[index] ) { |
| // Alignment for already generated sections |
| secAlign = |
| sec->get_offset() - seg_start_pos - segment_filesize; |
| } |
| |
| // Determine the segment file and memory sizes |
| // Special case .tbss section (NOBITS) in non TLS segment |
| if ( ( sec->get_flags() & SHF_ALLOC ) && |
| !( ( sec->get_flags() & SHF_TLS ) && |
| ( seg->get_type() != PT_TLS ) && |
| ( SHT_NOBITS == sec->get_type() ) ) ) |
| segment_memory += sec->get_size() + secAlign; |
| |
| if ( SHT_NOBITS != sec->get_type() ) |
| segment_filesize += sec->get_size() + secAlign; |
| |
| // Nothing to be done when generating nested segments |
| if ( section_generated[index] ) { |
| continue; |
| } |
| |
| current_file_pos += secAlign; |
| |
| // Set the section addresses when missing |
| if ( !sec->is_address_initialized() ) |
| sec->set_address( seg->get_virtual_address() + |
| current_file_pos - seg_start_pos ); |
| |
| if ( 0 != sec->get_index() ) |
| sec->set_offset( current_file_pos ); |
| |
| if ( SHT_NOBITS != sec->get_type() ) |
| current_file_pos += sec->get_size(); |
| |
| section_generated[index] = true; |
| } |
| |
| seg->set_file_size( segment_filesize ); |
| |
| // If we already have a memory size from loading an elf file (value > 0), |
| // it must not shrink! |
| // Memory size may be bigger than file size and it is the loader's job to do something |
| // with the surplus bytes in memory, like initializing them with a defined value. |
| if ( seg->get_memory_size() < segment_memory ) { |
| seg->set_memory_size( segment_memory ); |
| } |
| |
| seg->set_offset( seg_start_pos ); |
| } |
| |
| return true; |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool layout_section_table() |
| { |
| // Simply place the section table at the end for now |
| Elf64_Off alignmentError = current_file_pos % 4; |
| current_file_pos += ( 4 - alignmentError ) % 4; |
| header->set_sections_offset( current_file_pos ); |
| return true; |
| } |
| |
| //------------------------------------------------------------------------------ |
| public: |
| friend class Sections; |
| class Sections |
| { |
| public: |
| //------------------------------------------------------------------------------ |
| Sections( elfio* parent_ ) : parent( parent_ ) {} |
| |
| //------------------------------------------------------------------------------ |
| Elf_Half size() const { return (Elf_Half)parent->sections_.size(); } |
| |
| //------------------------------------------------------------------------------ |
| section* operator[]( unsigned int index ) const |
| { |
| section* sec = 0; |
| |
| if ( index < parent->sections_.size() ) { |
| sec = parent->sections_[index]; |
| } |
| |
| return sec; |
| } |
| |
| //------------------------------------------------------------------------------ |
| section* operator[]( const std::string& name ) const |
| { |
| section* sec = 0; |
| |
| std::vector<section*>::const_iterator it; |
| for ( it = parent->sections_.begin(); it != parent->sections_.end(); |
| ++it ) { |
| if ( ( *it )->get_name() == name ) { |
| sec = *it; |
| break; |
| } |
| } |
| |
| return sec; |
| } |
| |
| //------------------------------------------------------------------------------ |
| section* add( const std::string& name ) |
| { |
| section* new_section = parent->create_section(); |
| new_section->set_name( name ); |
| |
| Elf_Half str_index = parent->get_section_name_str_index(); |
| section* string_table( parent->sections_[str_index] ); |
| string_section_accessor str_writer( string_table ); |
| Elf_Word pos = str_writer.add_string( name ); |
| new_section->set_name_string_offset( pos ); |
| |
| return new_section; |
| } |
| |
| //------------------------------------------------------------------------------ |
| std::vector<section*>::iterator begin() |
| { |
| return parent->sections_.begin(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| std::vector<section*>::iterator end() |
| { |
| return parent->sections_.end(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| std::vector<section*>::const_iterator begin() const |
| { |
| return parent->sections_.cbegin(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| std::vector<section*>::const_iterator end() const |
| { |
| return parent->sections_.cend(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| private: |
| elfio* parent; |
| } sections; |
| |
| //------------------------------------------------------------------------------ |
| public: |
| friend class Segments; |
| class Segments |
| { |
| public: |
| //------------------------------------------------------------------------------ |
| Segments( elfio* parent_ ) : parent( parent_ ) {} |
| |
| //------------------------------------------------------------------------------ |
| Elf_Half size() const { return (Elf_Half)parent->segments_.size(); } |
| |
| //------------------------------------------------------------------------------ |
| segment* operator[]( unsigned int index ) const |
| { |
| return parent->segments_[index]; |
| } |
| |
| //------------------------------------------------------------------------------ |
| segment* add() { return parent->create_segment(); } |
| |
| //------------------------------------------------------------------------------ |
| std::vector<segment*>::iterator begin() |
| { |
| return parent->segments_.begin(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| std::vector<segment*>::iterator end() |
| { |
| return parent->segments_.end(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| std::vector<segment*>::const_iterator begin() const |
| { |
| return parent->segments_.cbegin(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| std::vector<segment*>::const_iterator end() const |
| { |
| return parent->segments_.cend(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| private: |
| elfio* parent; |
| } segments; |
| |
| //------------------------------------------------------------------------------ |
| private: |
| elf_header* header; |
| std::vector<section*> sections_; |
| std::vector<segment*> segments_; |
| endianess_convertor convertor; |
| |
| Elf_Xword current_file_pos; |
| }; |
| |
| } // namespace ELFIO |
| |
| |
| /*** Start of inlined file: elfio_symbols.hpp ***/ |
| #ifndef ELFIO_SYMBOLS_HPP |
| #define ELFIO_SYMBOLS_HPP |
| |
| namespace ELFIO { |
| |
| //------------------------------------------------------------------------------ |
| template <class S> class symbol_section_accessor_template |
| { |
| public: |
| //------------------------------------------------------------------------------ |
| symbol_section_accessor_template( const elfio& elf_file_, |
| S* symbol_section_ ) |
| : elf_file( elf_file_ ), symbol_section( symbol_section_ ) |
| { |
| find_hash_section(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| Elf_Xword get_symbols_num() const |
| { |
| Elf_Xword nRet = 0; |
| if ( 0 != symbol_section->get_entry_size() ) { |
| nRet = |
| symbol_section->get_size() / symbol_section->get_entry_size(); |
| } |
| |
| return nRet; |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool get_symbol( Elf_Xword index, |
| std::string& name, |
| Elf64_Addr& value, |
| Elf_Xword& size, |
| unsigned char& bind, |
| unsigned char& type, |
| Elf_Half& section_index, |
| unsigned char& other ) const |
| { |
| bool ret = false; |
| |
| if ( elf_file.get_class() == ELFCLASS32 ) { |
| ret = generic_get_symbol<Elf32_Sym>( index, name, value, size, bind, |
| type, section_index, other ); |
| } |
| else { |
| ret = generic_get_symbol<Elf64_Sym>( index, name, value, size, bind, |
| type, section_index, other ); |
| } |
| |
| return ret; |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool get_symbol( const std::string& name, |
| Elf64_Addr& value, |
| Elf_Xword& size, |
| unsigned char& bind, |
| unsigned char& type, |
| Elf_Half& section_index, |
| unsigned char& other ) const |
| { |
| bool ret = false; |
| |
| if ( 0 != get_hash_table_index() ) { |
| Elf_Word nbucket = *(const Elf_Word*)hash_section->get_data(); |
| Elf_Word nchain = *(const Elf_Word*)( hash_section->get_data() + |
| sizeof( Elf_Word ) ); |
| Elf_Word val = elf_hash( (const unsigned char*)name.c_str() ); |
| Elf_Word y = *(const Elf_Word*)( hash_section->get_data() + |
| ( 2 + val % nbucket ) * |
| sizeof( Elf_Word ) ); |
| std::string str; |
| get_symbol( y, str, value, size, bind, type, section_index, other ); |
| while ( str != name && STN_UNDEF != y && y < nchain ) { |
| y = *(const Elf_Word*)( hash_section->get_data() + |
| ( 2 + nbucket + y ) * |
| sizeof( Elf_Word ) ); |
| get_symbol( y, str, value, size, bind, type, section_index, |
| other ); |
| } |
| if ( str == name ) { |
| ret = true; |
| } |
| } |
| else { |
| for ( Elf_Xword i = 0; i < get_symbols_num() && !ret; i++ ) { |
| std::string symbol_name; |
| if ( get_symbol( i, symbol_name, value, size, bind, type, |
| section_index, other ) ) { |
| if ( symbol_name == name ) { |
| ret = true; |
| } |
| } |
| } |
| } |
| |
| return ret; |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool get_symbol( const Elf64_Addr& value, |
| std::string& name, |
| Elf_Xword& size, |
| unsigned char& bind, |
| unsigned char& type, |
| Elf_Half& section_index, |
| unsigned char& other ) const |
| { |
| |
| const endianess_convertor& convertor = elf_file.get_convertor(); |
| |
| Elf_Xword idx = 0; |
| bool match = false; |
| Elf64_Addr v = 0; |
| |
| if ( elf_file.get_class() == ELFCLASS32 ) { |
| match = generic_search_symbols<Elf32_Sym>( |
| [&]( const Elf32_Sym* sym ) { |
| return convertor( sym->st_value ) == value; |
| }, |
| idx ); |
| } |
| else { |
| match = generic_search_symbols<Elf64_Sym>( |
| [&]( const Elf64_Sym* sym ) { |
| return convertor( sym->st_value ) == value; |
| }, |
| idx ); |
| } |
| |
| if ( match ) { |
| return get_symbol( idx, name, v, size, bind, type, section_index, |
| other ); |
| } |
| |
| return false; |
| } |
| |
| //------------------------------------------------------------------------------ |
| Elf_Word add_symbol( Elf_Word name, |
| Elf64_Addr value, |
| Elf_Xword size, |
| unsigned char info, |
| unsigned char other, |
| Elf_Half shndx ) |
| { |
| Elf_Word nRet; |
| |
| if ( symbol_section->get_size() == 0 ) { |
| if ( elf_file.get_class() == ELFCLASS32 ) { |
| nRet = generic_add_symbol<Elf32_Sym>( 0, 0, 0, 0, 0, 0 ); |
| } |
| else { |
| nRet = generic_add_symbol<Elf64_Sym>( 0, 0, 0, 0, 0, 0 ); |
| } |
| } |
| |
| if ( elf_file.get_class() == ELFCLASS32 ) { |
| nRet = generic_add_symbol<Elf32_Sym>( name, value, size, info, |
| other, shndx ); |
| } |
| else { |
| nRet = generic_add_symbol<Elf64_Sym>( name, value, size, info, |
| other, shndx ); |
| } |
| |
| return nRet; |
| } |
| |
| //------------------------------------------------------------------------------ |
| Elf_Word add_symbol( Elf_Word name, |
| Elf64_Addr value, |
| Elf_Xword size, |
| unsigned char bind, |
| unsigned char type, |
| unsigned char other, |
| Elf_Half shndx ) |
| { |
| return add_symbol( name, value, size, ELF_ST_INFO( bind, type ), other, |
| shndx ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| Elf_Word add_symbol( string_section_accessor& pStrWriter, |
| const char* str, |
| Elf64_Addr value, |
| Elf_Xword size, |
| unsigned char info, |
| unsigned char other, |
| Elf_Half shndx ) |
| { |
| Elf_Word index = pStrWriter.add_string( str ); |
| return add_symbol( index, value, size, info, other, shndx ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| Elf_Word add_symbol( string_section_accessor& pStrWriter, |
| const char* str, |
| Elf64_Addr value, |
| Elf_Xword size, |
| unsigned char bind, |
| unsigned char type, |
| unsigned char other, |
| Elf_Half shndx ) |
| { |
| return add_symbol( pStrWriter, str, value, size, |
| ELF_ST_INFO( bind, type ), other, shndx ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| Elf_Xword arrange_local_symbols( |
| std::function<void( Elf_Xword first, Elf_Xword second )> func = |
| nullptr ) |
| { |
| int nRet = 0; |
| |
| if ( elf_file.get_class() == ELFCLASS32 ) { |
| nRet = generic_arrange_local_symbols<Elf32_Sym>( func ); |
| } |
| else { |
| nRet = generic_arrange_local_symbols<Elf64_Sym>( func ); |
| } |
| |
| return nRet; |
| } |
| |
| //------------------------------------------------------------------------------ |
| private: |
| //------------------------------------------------------------------------------ |
| void find_hash_section() |
| { |
| hash_section = 0; |
| hash_section_index = 0; |
| Elf_Half nSecNo = elf_file.sections.size(); |
| for ( Elf_Half i = 0; i < nSecNo && 0 == hash_section_index; ++i ) { |
| const section* sec = elf_file.sections[i]; |
| if ( sec->get_link() == symbol_section->get_index() ) { |
| hash_section = sec; |
| hash_section_index = i; |
| } |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| Elf_Half get_string_table_index() const |
| { |
| return (Elf_Half)symbol_section->get_link(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| Elf_Half get_hash_table_index() const { return hash_section_index; } |
| |
| //------------------------------------------------------------------------------ |
| template <class T> const T* generic_get_symbol_ptr( Elf_Xword index ) const |
| { |
| if ( 0 != symbol_section->get_data() && index < get_symbols_num() ) { |
| const T* pSym = reinterpret_cast<const T*>( |
| symbol_section->get_data() + |
| index * symbol_section->get_entry_size() ); |
| |
| return pSym; |
| } |
| |
| return nullptr; |
| } |
| |
| //------------------------------------------------------------------------------ |
| template <class T> |
| bool generic_search_symbols( std::function<bool( const T* )> match, |
| Elf_Xword& idx ) const |
| { |
| for ( Elf_Xword i = 0; i < get_symbols_num(); i++ ) { |
| const T* symPtr = generic_get_symbol_ptr<T>( i ); |
| |
| if ( symPtr == nullptr ) |
| return false; |
| |
| if ( match( symPtr ) ) { |
| idx = i; |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| //------------------------------------------------------------------------------ |
| template <class T> |
| bool generic_get_symbol( Elf_Xword index, |
| std::string& name, |
| Elf64_Addr& value, |
| Elf_Xword& size, |
| unsigned char& bind, |
| unsigned char& type, |
| Elf_Half& section_index, |
| unsigned char& other ) const |
| { |
| bool ret = false; |
| |
| if ( 0 != symbol_section->get_data() && index < get_symbols_num() ) { |
| const T* pSym = reinterpret_cast<const T*>( |
| symbol_section->get_data() + |
| index * symbol_section->get_entry_size() ); |
| |
| const endianess_convertor& convertor = elf_file.get_convertor(); |
| |
| section* string_section = |
| elf_file.sections[get_string_table_index()]; |
| string_section_accessor str_reader( string_section ); |
| const char* pStr = |
| str_reader.get_string( convertor( pSym->st_name ) ); |
| if ( 0 != pStr ) { |
| name = pStr; |
| } |
| value = convertor( pSym->st_value ); |
| size = convertor( pSym->st_size ); |
| bind = ELF_ST_BIND( pSym->st_info ); |
| type = ELF_ST_TYPE( pSym->st_info ); |
| section_index = convertor( pSym->st_shndx ); |
| other = pSym->st_other; |
| |
| ret = true; |
| } |
| |
| return ret; |
| } |
| |
| //------------------------------------------------------------------------------ |
| template <class T> |
| Elf_Word generic_add_symbol( Elf_Word name, |
| Elf64_Addr value, |
| Elf_Xword size, |
| unsigned char info, |
| unsigned char other, |
| Elf_Half shndx ) |
| { |
| const endianess_convertor& convertor = elf_file.get_convertor(); |
| |
| T entry; |
| entry.st_name = convertor( name ); |
| entry.st_value = value; |
| entry.st_value = convertor( entry.st_value ); |
| entry.st_size = size; |
| entry.st_size = convertor( entry.st_size ); |
| entry.st_info = convertor( info ); |
| entry.st_other = convertor( other ); |
| entry.st_shndx = convertor( shndx ); |
| |
| symbol_section->append_data( reinterpret_cast<char*>( &entry ), |
| sizeof( entry ) ); |
| |
| Elf_Word nRet = symbol_section->get_size() / sizeof( entry ) - 1; |
| |
| return nRet; |
| } |
| |
| //------------------------------------------------------------------------------ |
| template <class T> |
| Elf_Xword generic_arrange_local_symbols( |
| std::function<void( Elf_Xword first, Elf_Xword second )> func ) |
| { |
| const endianess_convertor& convertor = elf_file.get_convertor(); |
| const Elf_Xword size = symbol_section->get_entry_size(); |
| |
| Elf_Xword first_not_local = |
| 1; // Skip the first entry. It is always NOTYPE |
| Elf_Xword current = 0; |
| Elf_Xword count = get_symbols_num(); |
| |
| while ( true ) { |
| T* p1 = nullptr; |
| T* p2 = nullptr; |
| |
| while ( first_not_local < count ) { |
| p1 = const_cast<T*>( |
| generic_get_symbol_ptr<T>( first_not_local ) ); |
| if ( ELF_ST_BIND( convertor( p1->st_info ) ) != STB_LOCAL ) |
| break; |
| ++first_not_local; |
| } |
| |
| current = first_not_local + 1; |
| while ( current < count ) { |
| p2 = const_cast<T*>( generic_get_symbol_ptr<T>( current ) ); |
| if ( ELF_ST_BIND( convertor( p2->st_info ) ) == STB_LOCAL ) |
| break; |
| ++current; |
| } |
| |
| if ( first_not_local < count && current < count ) { |
| if ( func ) |
| func( first_not_local, current ); |
| |
| // Swap the symbols |
| T tmp; |
| std::copy( p1, p1 + 1, &tmp ); |
| std::copy( p2, p2 + 1, p1 ); |
| std::copy( &tmp, &tmp + 1, p2 ); |
| } |
| else { |
| // Update 'info' field of the section |
| symbol_section->set_info( first_not_local ); |
| break; |
| } |
| } |
| |
| // Elf_Word nRet = symbol_section->get_size() / sizeof(entry) - 1; |
| |
| return first_not_local; |
| } |
| |
| //------------------------------------------------------------------------------ |
| private: |
| const elfio& elf_file; |
| S* symbol_section; |
| Elf_Half hash_section_index; |
| const section* hash_section; |
| }; |
| |
| using symbol_section_accessor = symbol_section_accessor_template<section>; |
| using const_symbol_section_accessor = |
| symbol_section_accessor_template<const section>; |
| |
| } // namespace ELFIO |
| |
| #endif // ELFIO_SYMBOLS_HPP |
| |
| /*** End of inlined file: elfio_symbols.hpp ***/ |
| |
| |
| /*** Start of inlined file: elfio_note.hpp ***/ |
| #ifndef ELFIO_NOTE_HPP |
| #define ELFIO_NOTE_HPP |
| |
| namespace ELFIO { |
| |
| //------------------------------------------------------------------------------ |
| // There are discrepancies in documentations. SCO documentation |
| // (http://www.sco.com/developers/gabi/latest/ch5.pheader.html#note_section) |
| // requires 8 byte entries alignment for 64-bit ELF file, |
| // but Oracle's definition uses the same structure |
| // for 32-bit and 64-bit formats. |
| // (https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-18048.html) |
| // |
| // It looks like EM_X86_64 Linux implementation is similar to Oracle's |
| // definition. Therefore, the same alignment works for both formats |
| //------------------------------------------------------------------------------ |
| |
| //------------------------------------------------------------------------------ |
| template <class S> class note_section_accessor_template |
| { |
| public: |
| //------------------------------------------------------------------------------ |
| note_section_accessor_template( const elfio& elf_file_, S* section_ ) |
| : elf_file( elf_file_ ), note_section( section_ ) |
| { |
| process_section(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| Elf_Word get_notes_num() const |
| { |
| return (Elf_Word)note_start_positions.size(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool get_note( Elf_Word index, |
| Elf_Word& type, |
| std::string& name, |
| void*& desc, |
| Elf_Word& descSize ) const |
| { |
| if ( index >= note_section->get_size() ) { |
| return false; |
| } |
| |
| const char* pData = |
| note_section->get_data() + note_start_positions[index]; |
| int align = sizeof( Elf_Word ); |
| |
| const endianess_convertor& convertor = elf_file.get_convertor(); |
| type = convertor( *(const Elf_Word*)( pData + 2 * align ) ); |
| Elf_Word namesz = convertor( *(const Elf_Word*)( pData ) ); |
| descSize = convertor( *(const Elf_Word*)( pData + sizeof( namesz ) ) ); |
| |
| Elf_Xword max_name_size = |
| note_section->get_size() - note_start_positions[index]; |
| if ( namesz < 1 || namesz > max_name_size || |
| (Elf_Xword)namesz + descSize > max_name_size ) { |
| return false; |
| } |
| name.assign( pData + 3 * align, namesz - 1 ); |
| if ( 0 == descSize ) { |
| desc = 0; |
| } |
| else { |
| desc = |
| const_cast<char*>( pData + 3 * align + |
| ( ( namesz + align - 1 ) / align ) * align ); |
| } |
| |
| return true; |
| } |
| |
| //------------------------------------------------------------------------------ |
| void add_note( Elf_Word type, |
| const std::string& name, |
| const void* desc, |
| Elf_Word descSize ) |
| { |
| const endianess_convertor& convertor = elf_file.get_convertor(); |
| |
| int align = sizeof( Elf_Word ); |
| Elf_Word nameLen = (Elf_Word)name.size() + 1; |
| Elf_Word nameLenConv = convertor( nameLen ); |
| std::string buffer( reinterpret_cast<char*>( &nameLenConv ), align ); |
| Elf_Word descSizeConv = convertor( descSize ); |
| |
| buffer.append( reinterpret_cast<char*>( &descSizeConv ), align ); |
| type = convertor( type ); |
| buffer.append( reinterpret_cast<char*>( &type ), align ); |
| buffer.append( name ); |
| buffer.append( 1, '\x00' ); |
| const char pad[] = { '\0', '\0', '\0', '\0' }; |
| if ( nameLen % align != 0 ) { |
| buffer.append( pad, align - nameLen % align ); |
| } |
| if ( desc != 0 && descSize != 0 ) { |
| buffer.append( reinterpret_cast<const char*>( desc ), descSize ); |
| if ( descSize % align != 0 ) { |
| buffer.append( pad, align - descSize % align ); |
| } |
| } |
| |
| note_start_positions.push_back( note_section->get_size() ); |
| note_section->append_data( buffer ); |
| } |
| |
| private: |
| //------------------------------------------------------------------------------ |
| void process_section() |
| { |
| const endianess_convertor& convertor = elf_file.get_convertor(); |
| const char* data = note_section->get_data(); |
| Elf_Xword size = note_section->get_size(); |
| Elf_Xword current = 0; |
| |
| note_start_positions.clear(); |
| |
| // Is it empty? |
| if ( 0 == data || 0 == size ) { |
| return; |
| } |
| |
| Elf_Word align = sizeof( Elf_Word ); |
| while ( current + (Elf_Xword)3 * align <= size ) { |
| note_start_positions.push_back( current ); |
| Elf_Word namesz = convertor( *(const Elf_Word*)( data + current ) ); |
| Elf_Word descsz = convertor( |
| *(const Elf_Word*)( data + current + sizeof( namesz ) ) ); |
| |
| current += (Elf_Xword)3 * sizeof( Elf_Word ) + |
| ( ( namesz + align - 1 ) / align ) * (Elf_Xword)align + |
| ( ( descsz + align - 1 ) / align ) * (Elf_Xword)align; |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| private: |
| const elfio& elf_file; |
| S* note_section; |
| std::vector<Elf_Xword> note_start_positions; |
| }; |
| |
| using note_section_accessor = note_section_accessor_template<section>; |
| using const_note_section_accessor = |
| note_section_accessor_template<const section>; |
| |
| } // namespace ELFIO |
| |
| #endif // ELFIO_NOTE_HPP |
| |
| /*** End of inlined file: elfio_note.hpp ***/ |
| |
| |
| /*** Start of inlined file: elfio_relocation.hpp ***/ |
| #ifndef ELFIO_RELOCATION_HPP |
| #define ELFIO_RELOCATION_HPP |
| |
| namespace ELFIO { |
| |
| template <typename T> struct get_sym_and_type; |
| template <> struct get_sym_and_type<Elf32_Rel> |
| { |
| static int get_r_sym( Elf_Xword info ) |
| { |
| return ELF32_R_SYM( (Elf_Word)info ); |
| } |
| static int get_r_type( Elf_Xword info ) |
| { |
| return ELF32_R_TYPE( (Elf_Word)info ); |
| } |
| }; |
| template <> struct get_sym_and_type<Elf32_Rela> |
| { |
| static int get_r_sym( Elf_Xword info ) |
| { |
| return ELF32_R_SYM( (Elf_Word)info ); |
| } |
| static int get_r_type( Elf_Xword info ) |
| { |
| return ELF32_R_TYPE( (Elf_Word)info ); |
| } |
| }; |
| template <> struct get_sym_and_type<Elf64_Rel> |
| { |
| static int get_r_sym( Elf_Xword info ) { return ELF64_R_SYM( info ); } |
| static int get_r_type( Elf_Xword info ) { return ELF64_R_TYPE( info ); } |
| }; |
| template <> struct get_sym_and_type<Elf64_Rela> |
| { |
| static int get_r_sym( Elf_Xword info ) { return ELF64_R_SYM( info ); } |
| static int get_r_type( Elf_Xword info ) { return ELF64_R_TYPE( info ); } |
| }; |
| |
| //------------------------------------------------------------------------------ |
| template <class S> class relocation_section_accessor_template |
| { |
| public: |
| //------------------------------------------------------------------------------ |
| relocation_section_accessor_template( const elfio& elf_file_, S* section_ ) |
| : elf_file( elf_file_ ), relocation_section( section_ ) |
| { |
| } |
| |
| //------------------------------------------------------------------------------ |
| Elf_Xword get_entries_num() const |
| { |
| Elf_Xword nRet = 0; |
| |
| if ( 0 != relocation_section->get_entry_size() ) { |
| nRet = relocation_section->get_size() / |
| relocation_section->get_entry_size(); |
| } |
| |
| return nRet; |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool get_entry( Elf_Xword index, |
| Elf64_Addr& offset, |
| Elf_Word& symbol, |
| Elf_Word& type, |
| Elf_Sxword& addend ) const |
| { |
| if ( index >= get_entries_num() ) { // Is index valid |
| return false; |
| } |
| |
| if ( elf_file.get_class() == ELFCLASS32 ) { |
| if ( SHT_REL == relocation_section->get_type() ) { |
| generic_get_entry_rel<Elf32_Rel>( index, offset, symbol, type, |
| addend ); |
| } |
| else if ( SHT_RELA == relocation_section->get_type() ) { |
| generic_get_entry_rela<Elf32_Rela>( index, offset, symbol, type, |
| addend ); |
| } |
| } |
| else { |
| if ( SHT_REL == relocation_section->get_type() ) { |
| generic_get_entry_rel<Elf64_Rel>( index, offset, symbol, type, |
| addend ); |
| } |
| else if ( SHT_RELA == relocation_section->get_type() ) { |
| generic_get_entry_rela<Elf64_Rela>( index, offset, symbol, type, |
| addend ); |
| } |
| } |
| |
| return true; |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool get_entry( Elf_Xword index, |
| Elf64_Addr& offset, |
| Elf64_Addr& symbolValue, |
| std::string& symbolName, |
| Elf_Word& type, |
| Elf_Sxword& addend, |
| Elf_Sxword& calcValue ) const |
| { |
| // Do regular job |
| Elf_Word symbol; |
| bool ret = get_entry( index, offset, symbol, type, addend ); |
| |
| // Find the symbol |
| Elf_Xword size; |
| unsigned char bind; |
| unsigned char symbolType; |
| Elf_Half section; |
| unsigned char other; |
| |
| symbol_section_accessor symbols( |
| elf_file, elf_file.sections[get_symbol_table_index()] ); |
| ret = ret && symbols.get_symbol( symbol, symbolName, symbolValue, size, |
| bind, symbolType, section, other ); |
| |
| if ( ret ) { // Was it successful? |
| switch ( type ) { |
| case R_386_NONE: // none |
| calcValue = 0; |
| break; |
| case R_386_32: // S + A |
| calcValue = symbolValue + addend; |
| break; |
| case R_386_PC32: // S + A - P |
| calcValue = symbolValue + addend - offset; |
| break; |
| case R_386_GOT32: // G + A - P |
| calcValue = 0; |
| break; |
| case R_386_PLT32: // L + A - P |
| calcValue = 0; |
| break; |
| case R_386_COPY: // none |
| calcValue = 0; |
| break; |
| case R_386_GLOB_DAT: // S |
| case R_386_JMP_SLOT: // S |
| calcValue = symbolValue; |
| break; |
| case R_386_RELATIVE: // B + A |
| calcValue = addend; |
| break; |
| case R_386_GOTOFF: // S + A - GOT |
| calcValue = 0; |
| break; |
| case R_386_GOTPC: // GOT + A - P |
| calcValue = 0; |
| break; |
| default: // Not recognized symbol! |
| calcValue = 0; |
| break; |
| } |
| } |
| |
| return ret; |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool set_entry( Elf_Xword index, |
| Elf64_Addr offset, |
| Elf_Word symbol, |
| Elf_Word type, |
| Elf_Sxword addend ) |
| { |
| if ( index >= get_entries_num() ) { // Is index valid |
| return false; |
| } |
| |
| if ( elf_file.get_class() == ELFCLASS32 ) { |
| if ( SHT_REL == relocation_section->get_type() ) { |
| generic_set_entry_rel<Elf32_Rel>( index, offset, symbol, type, |
| addend ); |
| } |
| else if ( SHT_RELA == relocation_section->get_type() ) { |
| generic_set_entry_rela<Elf32_Rela>( index, offset, symbol, type, |
| addend ); |
| } |
| } |
| else { |
| if ( SHT_REL == relocation_section->get_type() ) { |
| generic_set_entry_rel<Elf64_Rel>( index, offset, symbol, type, |
| addend ); |
| } |
| else if ( SHT_RELA == relocation_section->get_type() ) { |
| generic_set_entry_rela<Elf64_Rela>( index, offset, symbol, type, |
| addend ); |
| } |
| } |
| |
| return true; |
| } |
| |
| //------------------------------------------------------------------------------ |
| void add_entry( Elf64_Addr offset, Elf_Xword info ) |
| { |
| if ( elf_file.get_class() == ELFCLASS32 ) { |
| generic_add_entry<Elf32_Rel>( offset, info ); |
| } |
| else { |
| generic_add_entry<Elf64_Rel>( offset, info ); |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| void add_entry( Elf64_Addr offset, Elf_Word symbol, unsigned char type ) |
| { |
| Elf_Xword info; |
| if ( elf_file.get_class() == ELFCLASS32 ) { |
| info = ELF32_R_INFO( (Elf_Xword)symbol, type ); |
| } |
| else { |
| info = ELF64_R_INFO( (Elf_Xword)symbol, type ); |
| } |
| |
| add_entry( offset, info ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| void add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend ) |
| { |
| if ( elf_file.get_class() == ELFCLASS32 ) { |
| generic_add_entry<Elf32_Rela>( offset, info, addend ); |
| } |
| else { |
| generic_add_entry<Elf64_Rela>( offset, info, addend ); |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| void add_entry( Elf64_Addr offset, |
| Elf_Word symbol, |
| unsigned char type, |
| Elf_Sxword addend ) |
| { |
| Elf_Xword info; |
| if ( elf_file.get_class() == ELFCLASS32 ) { |
| info = ELF32_R_INFO( (Elf_Xword)symbol, type ); |
| } |
| else { |
| info = ELF64_R_INFO( (Elf_Xword)symbol, type ); |
| } |
| |
| add_entry( offset, info, addend ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| void add_entry( string_section_accessor str_writer, |
| const char* str, |
| symbol_section_accessor sym_writer, |
| Elf64_Addr value, |
| Elf_Word size, |
| unsigned char sym_info, |
| unsigned char other, |
| Elf_Half shndx, |
| Elf64_Addr offset, |
| unsigned char type ) |
| { |
| Elf_Word str_index = str_writer.add_string( str ); |
| Elf_Word sym_index = sym_writer.add_symbol( str_index, value, size, |
| sym_info, other, shndx ); |
| add_entry( offset, sym_index, type ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| void swap_symbols( Elf_Xword first, Elf_Xword second ) |
| { |
| Elf64_Addr offset; |
| Elf_Word symbol; |
| Elf_Word rtype; |
| Elf_Sxword addend; |
| for ( Elf_Word i = 0; i < get_entries_num(); i++ ) { |
| get_entry( i, offset, symbol, rtype, addend ); |
| if ( symbol == first ) { |
| set_entry( i, offset, (Elf_Word)second, rtype, addend ); |
| } |
| if ( symbol == second ) { |
| set_entry( i, offset, (Elf_Word)first, rtype, addend ); |
| } |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| private: |
| //------------------------------------------------------------------------------ |
| Elf_Half get_symbol_table_index() const |
| { |
| return (Elf_Half)relocation_section->get_link(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| template <class T> |
| void generic_get_entry_rel( Elf_Xword index, |
| Elf64_Addr& offset, |
| Elf_Word& symbol, |
| Elf_Word& type, |
| Elf_Sxword& addend ) const |
| { |
| const endianess_convertor& convertor = elf_file.get_convertor(); |
| |
| const T* pEntry = reinterpret_cast<const T*>( |
| relocation_section->get_data() + |
| index * relocation_section->get_entry_size() ); |
| offset = convertor( pEntry->r_offset ); |
| Elf_Xword tmp = convertor( pEntry->r_info ); |
| symbol = get_sym_and_type<T>::get_r_sym( tmp ); |
| type = get_sym_and_type<T>::get_r_type( tmp ); |
| addend = 0; |
| } |
| |
| //------------------------------------------------------------------------------ |
| template <class T> |
| void generic_get_entry_rela( Elf_Xword index, |
| Elf64_Addr& offset, |
| Elf_Word& symbol, |
| Elf_Word& type, |
| Elf_Sxword& addend ) const |
| { |
| const endianess_convertor& convertor = elf_file.get_convertor(); |
| |
| const T* pEntry = reinterpret_cast<const T*>( |
| relocation_section->get_data() + |
| index * relocation_section->get_entry_size() ); |
| offset = convertor( pEntry->r_offset ); |
| Elf_Xword tmp = convertor( pEntry->r_info ); |
| symbol = get_sym_and_type<T>::get_r_sym( tmp ); |
| type = get_sym_and_type<T>::get_r_type( tmp ); |
| addend = convertor( pEntry->r_addend ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| template <class T> |
| void generic_set_entry_rel( Elf_Xword index, |
| Elf64_Addr offset, |
| Elf_Word symbol, |
| Elf_Word type, |
| Elf_Sxword ) |
| { |
| const endianess_convertor& convertor = elf_file.get_convertor(); |
| |
| T* pEntry = const_cast<T*>( reinterpret_cast<const T*>( |
| relocation_section->get_data() + |
| index * relocation_section->get_entry_size() ) ); |
| |
| if ( elf_file.get_class() == ELFCLASS32 ) { |
| pEntry->r_info = ELF32_R_INFO( (Elf_Xword)symbol, type ); |
| } |
| else { |
| pEntry->r_info = ELF64_R_INFO( (Elf_Xword)symbol, type ); |
| } |
| pEntry->r_offset = offset; |
| pEntry->r_offset = convertor( pEntry->r_offset ); |
| pEntry->r_info = convertor( pEntry->r_info ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| template <class T> |
| void generic_set_entry_rela( Elf_Xword index, |
| Elf64_Addr offset, |
| Elf_Word symbol, |
| Elf_Word type, |
| Elf_Sxword addend ) |
| { |
| const endianess_convertor& convertor = elf_file.get_convertor(); |
| |
| T* pEntry = const_cast<T*>( reinterpret_cast<const T*>( |
| relocation_section->get_data() + |
| index * relocation_section->get_entry_size() ) ); |
| |
| if ( elf_file.get_class() == ELFCLASS32 ) { |
| pEntry->r_info = ELF32_R_INFO( (Elf_Xword)symbol, type ); |
| } |
| else { |
| pEntry->r_info = ELF64_R_INFO( (Elf_Xword)symbol, type ); |
| } |
| pEntry->r_offset = offset; |
| pEntry->r_addend = addend; |
| pEntry->r_offset = convertor( pEntry->r_offset ); |
| pEntry->r_info = convertor( pEntry->r_info ); |
| pEntry->r_addend = convertor( pEntry->r_addend ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| template <class T> |
| void generic_add_entry( Elf64_Addr offset, Elf_Xword info ) |
| { |
| const endianess_convertor& convertor = elf_file.get_convertor(); |
| |
| T entry; |
| entry.r_offset = offset; |
| entry.r_info = info; |
| entry.r_offset = convertor( entry.r_offset ); |
| entry.r_info = convertor( entry.r_info ); |
| |
| relocation_section->append_data( reinterpret_cast<char*>( &entry ), |
| sizeof( entry ) ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| template <class T> |
| void |
| generic_add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend ) |
| { |
| const endianess_convertor& convertor = elf_file.get_convertor(); |
| |
| T entry; |
| entry.r_offset = offset; |
| entry.r_info = info; |
| entry.r_addend = addend; |
| entry.r_offset = convertor( entry.r_offset ); |
| entry.r_info = convertor( entry.r_info ); |
| entry.r_addend = convertor( entry.r_addend ); |
| |
| relocation_section->append_data( reinterpret_cast<char*>( &entry ), |
| sizeof( entry ) ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| private: |
| const elfio& elf_file; |
| S* relocation_section; |
| }; |
| |
| using relocation_section_accessor = |
| relocation_section_accessor_template<section>; |
| using const_relocation_section_accessor = |
| relocation_section_accessor_template<const section>; |
| |
| } // namespace ELFIO |
| |
| #endif // ELFIO_RELOCATION_HPP |
| |
| /*** End of inlined file: elfio_relocation.hpp ***/ |
| |
| |
| /*** Start of inlined file: elfio_dynamic.hpp ***/ |
| #ifndef ELFIO_DYNAMIC_HPP |
| #define ELFIO_DYNAMIC_HPP |
| |
| namespace ELFIO { |
| |
| //------------------------------------------------------------------------------ |
| template <class S> class dynamic_section_accessor_template |
| { |
| public: |
| //------------------------------------------------------------------------------ |
| dynamic_section_accessor_template( const elfio& elf_file_, S* section_ ) |
| : elf_file( elf_file_ ), dynamic_section( section_ ) |
| { |
| } |
| |
| //------------------------------------------------------------------------------ |
| Elf_Xword get_entries_num() const |
| { |
| Elf_Xword nRet = 0; |
| |
| if ( 0 != dynamic_section->get_entry_size() ) { |
| nRet = |
| dynamic_section->get_size() / dynamic_section->get_entry_size(); |
| } |
| |
| return nRet; |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool get_entry( Elf_Xword index, |
| Elf_Xword& tag, |
| Elf_Xword& value, |
| std::string& str ) const |
| { |
| if ( index >= get_entries_num() ) { // Is index valid |
| return false; |
| } |
| |
| if ( elf_file.get_class() == ELFCLASS32 ) { |
| generic_get_entry_dyn<Elf32_Dyn>( index, tag, value ); |
| } |
| else { |
| generic_get_entry_dyn<Elf64_Dyn>( index, tag, value ); |
| } |
| |
| // If the tag may have a string table reference, prepare the string |
| if ( tag == DT_NEEDED || tag == DT_SONAME || tag == DT_RPATH || |
| tag == DT_RUNPATH ) { |
| string_section_accessor strsec = |
| elf_file.sections[get_string_table_index()]; |
| const char* result = strsec.get_string( value ); |
| if ( 0 == result ) { |
| str.clear(); |
| return false; |
| } |
| str = result; |
| } |
| else { |
| str.clear(); |
| } |
| |
| return true; |
| } |
| |
| //------------------------------------------------------------------------------ |
| void add_entry( Elf_Xword tag, Elf_Xword value ) |
| { |
| if ( elf_file.get_class() == ELFCLASS32 ) { |
| generic_add_entry<Elf32_Dyn>( tag, value ); |
| } |
| else { |
| generic_add_entry<Elf64_Dyn>( tag, value ); |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| void add_entry( Elf_Xword tag, const std::string& str ) |
| { |
| string_section_accessor strsec = |
| elf_file.sections[get_string_table_index()]; |
| Elf_Xword value = strsec.add_string( str ); |
| add_entry( tag, value ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| private: |
| //------------------------------------------------------------------------------ |
| Elf_Half get_string_table_index() const |
| { |
| return (Elf_Half)dynamic_section->get_link(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| template <class T> |
| void generic_get_entry_dyn( Elf_Xword index, |
| Elf_Xword& tag, |
| Elf_Xword& value ) const |
| { |
| const endianess_convertor& convertor = elf_file.get_convertor(); |
| |
| // Check unusual case when dynamic section has no data |
| if ( dynamic_section->get_data() == 0 || |
| ( index + 1 ) * dynamic_section->get_entry_size() > |
| dynamic_section->get_size() ) { |
| tag = DT_NULL; |
| value = 0; |
| return; |
| } |
| |
| const T* pEntry = reinterpret_cast<const T*>( |
| dynamic_section->get_data() + |
| index * dynamic_section->get_entry_size() ); |
| tag = convertor( pEntry->d_tag ); |
| switch ( tag ) { |
| case DT_NULL: |
| case DT_SYMBOLIC: |
| case DT_TEXTREL: |
| case DT_BIND_NOW: |
| value = 0; |
| break; |
| case DT_NEEDED: |
| case DT_PLTRELSZ: |
| case DT_RELASZ: |
| case DT_RELAENT: |
| case DT_STRSZ: |
| case DT_SYMENT: |
| case DT_SONAME: |
| case DT_RPATH: |
| case DT_RELSZ: |
| case DT_RELENT: |
| case DT_PLTREL: |
| case DT_INIT_ARRAYSZ: |
| case DT_FINI_ARRAYSZ: |
| case DT_RUNPATH: |
| case DT_FLAGS: |
| case DT_PREINIT_ARRAYSZ: |
| value = convertor( pEntry->d_un.d_val ); |
| break; |
| case DT_PLTGOT: |
| case DT_HASH: |
| case DT_STRTAB: |
| case DT_SYMTAB: |
| case DT_RELA: |
| case DT_INIT: |
| case DT_FINI: |
| case DT_REL: |
| case DT_DEBUG: |
| case DT_JMPREL: |
| case DT_INIT_ARRAY: |
| case DT_FINI_ARRAY: |
| case DT_PREINIT_ARRAY: |
| default: |
| value = convertor( pEntry->d_un.d_ptr ); |
| break; |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| template <class T> void generic_add_entry( Elf_Xword tag, Elf_Xword value ) |
| { |
| const endianess_convertor& convertor = elf_file.get_convertor(); |
| |
| T entry; |
| |
| switch ( tag ) { |
| case DT_NULL: |
| case DT_SYMBOLIC: |
| case DT_TEXTREL: |
| case DT_BIND_NOW: |
| value = 0; |
| case DT_NEEDED: |
| case DT_PLTRELSZ: |
| case DT_RELASZ: |
| case DT_RELAENT: |
| case DT_STRSZ: |
| case DT_SYMENT: |
| case DT_SONAME: |
| case DT_RPATH: |
| case DT_RELSZ: |
| case DT_RELENT: |
| case DT_PLTREL: |
| case DT_INIT_ARRAYSZ: |
| case DT_FINI_ARRAYSZ: |
| case DT_RUNPATH: |
| case DT_FLAGS: |
| case DT_PREINIT_ARRAYSZ: |
| entry.d_un.d_val = convertor( value ); |
| break; |
| case DT_PLTGOT: |
| case DT_HASH: |
| case DT_STRTAB: |
| case DT_SYMTAB: |
| case DT_RELA: |
| case DT_INIT: |
| case DT_FINI: |
| case DT_REL: |
| case DT_DEBUG: |
| case DT_JMPREL: |
| case DT_INIT_ARRAY: |
| case DT_FINI_ARRAY: |
| case DT_PREINIT_ARRAY: |
| default: |
| entry.d_un.d_ptr = convertor( value ); |
| break; |
| } |
| |
| entry.d_tag = convertor( tag ); |
| |
| dynamic_section->append_data( reinterpret_cast<char*>( &entry ), |
| sizeof( entry ) ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| private: |
| const elfio& elf_file; |
| S* dynamic_section; |
| }; |
| |
| using dynamic_section_accessor = dynamic_section_accessor_template<section>; |
| using const_dynamic_section_accessor = |
| dynamic_section_accessor_template<const section>; |
| |
| } // namespace ELFIO |
| |
| #endif // ELFIO_DYNAMIC_HPP |
| |
| /*** End of inlined file: elfio_dynamic.hpp ***/ |
| |
| |
| /*** Start of inlined file: elfio_modinfo.hpp ***/ |
| #ifndef ELFIO_MODINFO_HPP |
| #define ELFIO_MODINFO_HPP |
| |
| #include <string> |
| #include <vector> |
| |
| namespace ELFIO { |
| |
| //------------------------------------------------------------------------------ |
| template <class S> class modinfo_section_accessor_template |
| { |
| public: |
| //------------------------------------------------------------------------------ |
| modinfo_section_accessor_template( S* section_ ) |
| : modinfo_section( section_ ) |
| { |
| process_section(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| Elf_Word get_attribute_num() const { return (Elf_Word)content.size(); } |
| |
| //------------------------------------------------------------------------------ |
| bool |
| get_attribute( Elf_Word no, std::string& field, std::string& value ) const |
| { |
| if ( no < content.size() ) { |
| field = content[no].first; |
| value = content[no].second; |
| return true; |
| } |
| |
| return false; |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool get_attribute( std::string field_name, std::string& value ) const |
| { |
| for ( auto i = content.begin(); i != content.end(); i++ ) { |
| if ( field_name == i->first ) { |
| value = i->second; |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| //------------------------------------------------------------------------------ |
| Elf_Word add_attribute( std::string field, std::string value ) |
| { |
| Elf_Word current_position = 0; |
| |
| if ( modinfo_section ) { |
| // Strings are addeded to the end of the current section data |
| current_position = (Elf_Word)modinfo_section->get_size(); |
| |
| std::string attribute = field + "=" + value; |
| |
| modinfo_section->append_data( attribute + '\0' ); |
| content.push_back( |
| std::pair<std::string, std::string>( field, value ) ); |
| } |
| |
| return current_position; |
| } |
| |
| //------------------------------------------------------------------------------ |
| private: |
| void process_section() |
| { |
| const char* pdata = modinfo_section->get_data(); |
| if ( pdata ) { |
| ELFIO::Elf_Xword i = 0; |
| while ( i < modinfo_section->get_size() ) { |
| while ( i < modinfo_section->get_size() && !pdata[i] ) |
| i++; |
| if ( i < modinfo_section->get_size() ) { |
| std::string info = pdata + i; |
| size_t loc = info.find( '=' ); |
| std::pair<std::string, std::string> attribute( |
| info.substr( 0, loc ), info.substr( loc + 1 ) ); |
| |
| content.push_back( attribute ); |
| |
| i += info.length(); |
| } |
| } |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| private: |
| S* modinfo_section; |
| std::vector<std::pair<std::string, std::string>> content; |
| }; |
| |
| using modinfo_section_accessor = modinfo_section_accessor_template<section>; |
| using const_modinfo_section_accessor = |
| modinfo_section_accessor_template<const section>; |
| |
| } // namespace ELFIO |
| |
| #endif // ELFIO_MODINFO_HPP |
| |
| /*** End of inlined file: elfio_modinfo.hpp ***/ |
| |
| #ifdef _MSC_VER |
| #pragma warning( pop ) |
| #endif |
| |
| #endif // ELFIO_HPP |
| |
| /*** End of inlined file: elfio.hpp ***/ |
| |
| |
| namespace ELFIO { |
| |
| static struct class_table_t |
| { |
| const char key; |
| const char* str; |
| } class_table[] = { |
| { ELFCLASS32, "ELF32" }, |
| { ELFCLASS64, "ELF64" }, |
| }; |
| |
| static struct endian_table_t |
| { |
| const char key; |
| const char* str; |
| } endian_table[] = { |
| { ELFDATANONE, "None" }, |
| { ELFDATA2LSB, "Little endian" }, |
| { ELFDATA2MSB, "Big endian" }, |
| }; |
| |
| static struct version_table_t |
| { |
| const Elf64_Word key; |
| const char* str; |
| } version_table[] = { |
| { EV_NONE, "None" }, |
| { EV_CURRENT, "Current" }, |
| }; |
| |
| static struct type_table_t |
| { |
| const Elf32_Half key; |
| const char* str; |
| } type_table[] = { |
| { ET_NONE, "No file type" }, { ET_REL, "Relocatable file" }, |
| { ET_EXEC, "Executable file" }, { ET_DYN, "Shared object file" }, |
| { ET_CORE, "Core file" }, |
| }; |
| |
| static struct machine_table_t |
| { |
| const Elf64_Half key; |
| const char* str; |
| } machine_table[] = { |
| { EM_NONE, "No machine" }, |
| { EM_M32, "AT&T WE 32100" }, |
| { EM_SPARC, "SUN SPARC" }, |
| { EM_386, "Intel 80386" }, |
| { EM_68K, "Motorola m68k family" }, |
| { EM_88K, "Motorola m88k family" }, |
| { EM_486, "Intel 80486// Reserved for future use" }, |
| { EM_860, "Intel 80860" }, |
| { EM_MIPS, "MIPS R3000 (officially, big-endian only)" }, |
| { EM_S370, "IBM System/370" }, |
| { EM_MIPS_RS3_LE, |
| "MIPS R3000 little-endian (Oct 4 1999 Draft) Deprecated" }, |
| { EM_res011, "Reserved" }, |
| { EM_res012, "Reserved" }, |
| { EM_res013, "Reserved" }, |
| { EM_res014, "Reserved" }, |
| { EM_PARISC, "HPPA" }, |
| { EM_res016, "Reserved" }, |
| { EM_VPP550, "Fujitsu VPP500" }, |
| { EM_SPARC32PLUS, "Sun's v8plus" }, |
| { EM_960, "Intel 80960" }, |
| { EM_PPC, "PowerPC" }, |
| { EM_PPC64, "64-bit PowerPC" }, |
| { EM_S390, "IBM S/390" }, |
| { EM_SPU, "Sony/Toshiba/IBM SPU" }, |
| { EM_res024, "Reserved" }, |
| { EM_res025, "Reserved" }, |
| { EM_res026, "Reserved" }, |
| { EM_res027, "Reserved" }, |
| { EM_res028, "Reserved" }, |
| { EM_res029, "Reserved" }, |
| { EM_res030, "Reserved" }, |
| { EM_res031, "Reserved" }, |
| { EM_res032, "Reserved" }, |
| { EM_res033, "Reserved" }, |
| { EM_res034, "Reserved" }, |
| { EM_res035, "Reserved" }, |
| { EM_V800, "NEC V800 series" }, |
| { EM_FR20, "Fujitsu FR20" }, |
| { EM_RH32, "TRW RH32" }, |
| { EM_MCORE, "Motorola M*Core // May also be taken by Fujitsu MMA" }, |
| { EM_RCE, "Old name for MCore" }, |
| { EM_ARM, "ARM" }, |
| { EM_OLD_ALPHA, "Digital Alpha" }, |
| { EM_SH, "Renesas (formerly Hitachi) / SuperH SH" }, |
| { EM_SPARCV9, "SPARC v9 64-bit" }, |
| { EM_TRICORE, "Siemens Tricore embedded processor" }, |
| { EM_ARC, "ARC Cores" }, |
| { EM_H8_300, "Renesas (formerly Hitachi) H8/300" }, |
| { EM_H8_300H, "Renesas (formerly Hitachi) H8/300H" }, |
| { EM_H8S, "Renesas (formerly Hitachi) H8S" }, |
| { EM_H8_500, "Renesas (formerly Hitachi) H8/500" }, |
| { EM_IA_64, "Intel IA-64 Processor" }, |
| { EM_MIPS_X, "Stanford MIPS-X" }, |
| { EM_COLDFIRE, "Motorola Coldfire" }, |
| { EM_68HC12, "Motorola M68HC12" }, |
| { EM_MMA, "Fujitsu Multimedia Accelerator" }, |
| { EM_PCP, "Siemens PCP" }, |
| { EM_NCPU, "Sony nCPU embedded RISC processor" }, |
| { EM_NDR1, "Denso NDR1 microprocesspr" }, |
| { EM_STARCORE, "Motorola Star*Core processor" }, |
| { EM_ME16, "Toyota ME16 processor" }, |
| { EM_ST100, "STMicroelectronics ST100 processor" }, |
| { EM_TINYJ, "Advanced Logic Corp. TinyJ embedded processor" }, |
| { EM_X86_64, "Advanced Micro Devices X86-64 processor" }, |
| { EM_PDSP, "Sony DSP Processor" }, |
| { EM_PDP10, "Digital Equipment Corp. PDP-10" }, |
| { EM_PDP11, "Digital Equipment Corp. PDP-11" }, |
| { EM_FX66, "Siemens FX66 microcontroller" }, |
| { EM_ST9PLUS, "STMicroelectronics ST9+ 8/16 bit microcontroller" }, |
| { EM_ST7, "STMicroelectronics ST7 8-bit microcontroller" }, |
| { EM_68HC16, "Motorola MC68HC16 Microcontroller" }, |
| { EM_68HC11, "Motorola MC68HC11 Microcontroller" }, |
| { EM_68HC08, "Motorola MC68HC08 Microcontroller" }, |
| { EM_68HC05, "Motorola MC68HC05 Microcontroller" }, |
| { EM_SVX, "Silicon Graphics SVx" }, |
| { EM_ST19, "STMicroelectronics ST19 8-bit cpu" }, |
| { EM_VAX, "Digital VAX" }, |
| { EM_CRIS, "Axis Communications 32-bit embedded processor" }, |
| { EM_JAVELIN, "Infineon Technologies 32-bit embedded cpu" }, |
| { EM_FIREPATH, "Element 14 64-bit DSP processor" }, |
| { EM_ZSP, "LSI Logic's 16-bit DSP processor" }, |
| { EM_MMIX, "Donald Knuth's educational 64-bit processor" }, |
| { EM_HUANY, "Harvard's machine-independent format" }, |
| { EM_PRISM, "SiTera Prism" }, |
| { EM_AVR, "Atmel AVR 8-bit microcontroller" }, |
| { EM_FR30, "Fujitsu FR30" }, |
| { EM_D10V, "Mitsubishi D10V" }, |
| { EM_D30V, "Mitsubishi D30V" }, |
| { EM_V850, "NEC v850" }, |
| { EM_M32R, "Renesas M32R (formerly Mitsubishi M32R)" }, |
| { EM_MN10300, "Matsushita MN10300" }, |
| { EM_MN10200, "Matsushita MN10200" }, |
| { EM_PJ, "picoJava" }, |
| { EM_OPENRISC, "OpenRISC 32-bit embedded processor" }, |
| { EM_ARC_A5, "ARC Cores Tangent-A5" }, |
| { EM_XTENSA, "Tensilica Xtensa Architecture" }, |
| { EM_VIDEOCORE, "Alphamosaic VideoCore processor" }, |
| { EM_TMM_GPP, "Thompson Multimedia General Purpose Processor" }, |
| { EM_NS32K, "National Semiconductor 32000 series" }, |
| { EM_TPC, "Tenor Network TPC processor" }, |
| { EM_SNP1K, "Trebia SNP 1000 processor" }, |
| { EM_ST200, "STMicroelectronics ST200 microcontroller" }, |
| { EM_IP2K, "Ubicom IP2022 micro controller" }, |
| { EM_MAX, "MAX Processor" }, |
| { EM_CR, "National Semiconductor CompactRISC" }, |
| { EM_F2MC16, "Fujitsu F2MC16" }, |
| { EM_MSP430, "TI msp430 micro controller" }, |
| { EM_BLACKFIN, "ADI Blackfin" }, |
| { EM_SE_C33, "S1C33 Family of Seiko Epson processors" }, |
| { EM_SEP, "Sharp embedded microprocessor" }, |
| { EM_ARCA, "Arca RISC Microprocessor" }, |
| { EM_UNICORE, "Microprocessor series from PKU-Unity Ltd. and MPRC of " |
| "Peking University" }, |
| { EM_EXCESS, "eXcess: 16/32/64-bit configurable embedded CPU" }, |
| { EM_DXP, "Icera Semiconductor Inc. Deep Execution Processor" }, |
| { EM_ALTERA_NIOS2, "Altera Nios II soft-core processor" }, |
| { EM_CRX, "National Semiconductor CRX" }, |
| { EM_XGATE, "Motorola XGATE embedded processor" }, |
| { EM_C166, "Infineon C16x/XC16x processor" }, |
| { EM_M16C, "Renesas M16C series microprocessors" }, |
| { EM_DSPIC30F, "Microchip Technology dsPIC30F Digital Signal Controller" }, |
| { EM_CE, "Freescale Communication Engine RISC core" }, |
| { EM_M32C, "Renesas M32C series microprocessors" }, |
| { EM_res121, "Reserved" }, |
| { EM_res122, "Reserved" }, |
| { EM_res123, "Reserved" }, |
| { EM_res124, "Reserved" }, |
| { EM_res125, "Reserved" }, |
| { EM_res126, "Reserved" }, |
| { EM_res127, "Reserved" }, |
| { EM_res128, "Reserved" }, |
| { EM_res129, "Reserved" }, |
| { EM_res130, "Reserved" }, |
| { EM_TSK3000, "Altium TSK3000 core" }, |
| { EM_RS08, "Freescale RS08 embedded processor" }, |
| { EM_res133, "Reserved" }, |
| { EM_ECOG2, "Cyan Technology eCOG2 microprocessor" }, |
| { EM_SCORE, "Sunplus Score" }, |
| { EM_SCORE7, "Sunplus S+core7 RISC processor" }, |
| { EM_DSP24, "New Japan Radio (NJR) 24-bit DSP Processor" }, |
| { EM_VIDEOCORE3, "Broadcom VideoCore III processor" }, |
| { EM_LATTICEMICO32, "RISC processor for Lattice FPGA architecture" }, |
| { EM_SE_C17, "Seiko Epson C17 family" }, |
| { EM_TI_C6000, "Texas Instruments TMS320C6000 DSP family" }, |
| { EM_TI_C2000, "Texas Instruments TMS320C2000 DSP family" }, |
| { EM_TI_C5500, "Texas Instruments TMS320C55x DSP family" }, |
| { EM_res143, "Reserved" }, |
| { EM_res144, "Reserved" }, |
| { EM_res145, "Reserved" }, |
| { EM_res146, "Reserved" }, |
| { EM_res147, "Reserved" }, |
| { EM_res148, "Reserved" }, |
| { EM_res149, "Reserved" }, |
| { EM_res150, "Reserved" }, |
| { EM_res151, "Reserved" }, |
| { EM_res152, "Reserved" }, |
| { EM_res153, "Reserved" }, |
| { EM_res154, "Reserved" }, |
| { EM_res155, "Reserved" }, |
| { EM_res156, "Reserved" }, |
| { EM_res157, "Reserved" }, |
| { EM_res158, "Reserved" }, |
| { EM_res159, "Reserved" }, |
| { EM_MMDSP_PLUS, "STMicroelectronics 64bit VLIW Data Signal Processor" }, |
| { EM_CYPRESS_M8C, "Cypress M8C microprocessor" }, |
| { EM_R32C, "Renesas R32C series microprocessors" }, |
| { EM_TRIMEDIA, "NXP Semiconductors TriMedia architecture family" }, |
| { EM_QDSP6, "QUALCOMM DSP6 Processor" }, |
| { EM_8051, "Intel 8051 and variants" }, |
| { EM_STXP7X, "STMicroelectronics STxP7x family" }, |
| { EM_NDS32, |
| "Andes Technology compact code size embedded RISC processor family" }, |
| { EM_ECOG1, "Cyan Technology eCOG1X family" }, |
| { EM_ECOG1X, "Cyan Technology eCOG1X family" }, |
| { EM_MAXQ30, "Dallas Semiconductor MAXQ30 Core Micro-controllers" }, |
| { EM_XIMO16, "New Japan Radio (NJR) 16-bit DSP Processor" }, |
| { EM_MANIK, "M2000 Reconfigurable RISC Microprocessor" }, |
| { EM_CRAYNV2, "Cray Inc. NV2 vector architecture" }, |
| { EM_RX, "Renesas RX family" }, |
| { EM_METAG, "Imagination Technologies META processor architecture" }, |
| { EM_MCST_ELBRUS, "MCST Elbrus general purpose hardware architecture" }, |
| { EM_ECOG16, "Cyan Technology eCOG16 family" }, |
| { EM_CR16, "National Semiconductor CompactRISC 16-bit processor" }, |
| { EM_ETPU, "Freescale Extended Time Processing Unit" }, |
| { EM_SLE9X, "Infineon Technologies SLE9X core" }, |
| { EM_L1OM, "Intel L1OM" }, |
| { EM_INTEL181, "Reserved by Intel" }, |
| { EM_INTEL182, "Reserved by Intel" }, |
| { EM_res183, "Reserved by ARM" }, |
| { EM_res184, "Reserved by ARM" }, |
| { EM_AVR32, "Atmel Corporation 32-bit microprocessor family" }, |
| { EM_STM8, "STMicroeletronics STM8 8-bit microcontroller" }, |
| { EM_TILE64, "Tilera TILE64 multicore architecture family" }, |
| { EM_TILEPRO, "Tilera TILEPro multicore architecture family" }, |
| { EM_MICROBLAZE, "Xilinx MicroBlaze 32-bit RISC soft processor core" }, |
| { EM_CUDA, "NVIDIA CUDA architecture " }, |
| }; |
| |
| static struct section_type_table_t |
| { |
| const Elf64_Half key; |
| const char* str; |
| } section_type_table[] = { |
| { SHT_NULL, "NULL" }, |
| { SHT_PROGBITS, "PROGBITS" }, |
| { SHT_SYMTAB, "SYMTAB" }, |
| { SHT_STRTAB, "STRTAB" }, |
| { SHT_RELA, "RELA" }, |
| { SHT_HASH, "HASH" }, |
| { SHT_DYNAMIC, "DYNAMIC" }, |
| { SHT_NOTE, "NOTE" }, |
| { SHT_NOBITS, "NOBITS" }, |
| { SHT_REL, "REL" }, |
| { SHT_SHLIB, "SHLIB" }, |
| { SHT_DYNSYM, "DYNSYM" }, |
| { SHT_INIT_ARRAY, "INIT_ARRAY" }, |
| { SHT_FINI_ARRAY, "FINI_ARRAY" }, |
| { SHT_PREINIT_ARRAY, "PREINIT_ARRAY" }, |
| { SHT_GROUP, "GROUP" }, |
| { SHT_SYMTAB_SHNDX, "SYMTAB_SHNDX " }, |
| }; |
| |
| static struct segment_type_table_t |
| { |
| const Elf_Word key; |
| const char* str; |
| } segment_type_table[] = { |
| { PT_NULL, "NULL" }, { PT_LOAD, "LOAD" }, { PT_DYNAMIC, "DYNAMIC" }, |
| { PT_INTERP, "INTERP" }, { PT_NOTE, "NOTE" }, { PT_SHLIB, "SHLIB" }, |
| { PT_PHDR, "PHDR" }, { PT_TLS, "TLS" }, |
| }; |
| |
| static struct segment_flag_table_t |
| { |
| const Elf_Word key; |
| const char* str; |
| } segment_flag_table[] = { |
| { 0, "" }, { 1, "X" }, { 2, "W" }, { 3, "WX" }, |
| { 4, "R" }, { 5, "RX" }, { 6, "RW" }, { 7, "RWX" }, |
| }; |
| |
| static struct symbol_bind_t |
| { |
| const Elf_Word key; |
| const char* str; |
| } symbol_bind_table[] = { |
| { STB_LOCAL, "LOCAL" }, { STB_GLOBAL, "GLOBAL" }, |
| { STB_WEAK, "WEAK" }, { STB_LOOS, "LOOS" }, |
| { STB_HIOS, "HIOS" }, { STB_MULTIDEF, "MULTIDEF" }, |
| { STB_LOPROC, "LOPROC" }, { STB_HIPROC, "HIPROC" }, |
| }; |
| |
| static struct symbol_type_t |
| { |
| const Elf_Word key; |
| const char* str; |
| } symbol_type_table[] = { |
| { STT_NOTYPE, "NOTYPE" }, { STT_OBJECT, "OBJECT" }, |
| { STT_FUNC, "FUNC" }, { STT_SECTION, "SECTION" }, |
| { STT_FILE, "FILE" }, { STT_COMMON, "COMMON" }, |
| { STT_TLS, "TLS" }, { STT_LOOS, "LOOS" }, |
| { STT_HIOS, "HIOS" }, { STT_LOPROC, "LOPROC" }, |
| { STT_HIPROC, "HIPROC" }, |
| }; |
| |
| static struct dynamic_tag_t |
| { |
| const Elf_Word key; |
| const char* str; |
| } dynamic_tag_table[] = { |
| { DT_NULL, "NULL" }, |
| { DT_NEEDED, "NEEDED" }, |
| { DT_PLTRELSZ, "PLTRELSZ" }, |
| { DT_PLTGOT, "PLTGOT" }, |
| { DT_HASH, "HASH" }, |
| { DT_STRTAB, "STRTAB" }, |
| { DT_SYMTAB, "SYMTAB" }, |
| { DT_RELA, "RELA" }, |
| { DT_RELASZ, "RELASZ" }, |
| { DT_RELAENT, "RELAENT" }, |
| { DT_STRSZ, "STRSZ" }, |
| { DT_SYMENT, "SYMENT" }, |
| { DT_INIT, "INIT" }, |
| { DT_FINI, "FINI" }, |
| { DT_SONAME, "SONAME" }, |
| { DT_RPATH, "RPATH" }, |
| { DT_SYMBOLIC, "SYMBOLIC" }, |
| { DT_REL, "REL" }, |
| { DT_RELSZ, "RELSZ" }, |
| { DT_RELENT, "RELENT" }, |
| { DT_PLTREL, "PLTREL" }, |
| { DT_DEBUG, "DEBUG" }, |
| { DT_TEXTREL, "TEXTREL" }, |
| { DT_JMPREL, "JMPREL" }, |
| { DT_BIND_NOW, "BIND_NOW" }, |
| { DT_INIT_ARRAY, "INIT_ARRAY" }, |
| { DT_FINI_ARRAY, "FINI_ARRAY" }, |
| { DT_INIT_ARRAYSZ, "INIT_ARRAYSZ" }, |
| { DT_FINI_ARRAYSZ, "FINI_ARRAYSZ" }, |
| { DT_RUNPATH, "RUNPATH" }, |
| { DT_FLAGS, "FLAGS" }, |
| { DT_ENCODING, "ENCODING" }, |
| { DT_PREINIT_ARRAY, "PREINIT_ARRAY" }, |
| { DT_PREINIT_ARRAYSZ, "PREINIT_ARRAYSZ" }, |
| { DT_MAXPOSTAGS, "MAXPOSTAGS" }, |
| }; |
| |
| static const ELFIO::Elf_Xword MAX_DATA_ENTRIES = 64; |
| |
| //------------------------------------------------------------------------------ |
| class dump |
| { |
| #define DUMP_DEC_FORMAT( width ) \ |
| std::setw( width ) << std::setfill( ' ' ) << std::dec << std::right |
| #define DUMP_HEX_FORMAT( width ) \ |
| std::setw( width ) << std::setfill( '0' ) << std::hex << std::right |
| #define DUMP_STR_FORMAT( width ) \ |
| std::setw( width ) << std::setfill( ' ' ) << std::hex << std::left |
| |
| public: |
| //------------------------------------------------------------------------------ |
| static void header( std::ostream& out, const elfio& reader ) |
| { |
| if ( !reader.get_header_size() ) { |
| return; |
| } |
| out << "ELF Header" << std::endl |
| << std::endl |
| << " Class: " << str_class( reader.get_class() ) << std::endl |
| << " Encoding: " << str_endian( reader.get_encoding() ) |
| << std::endl |
| << " ELFVersion: " << str_version( reader.get_elf_version() ) |
| << std::endl |
| << " Type: " << str_type( reader.get_type() ) << std::endl |
| << " Machine: " << str_machine( reader.get_machine() ) |
| << std::endl |
| << " Version: " << str_version( reader.get_version() ) |
| << std::endl |
| << " Entry: " |
| << "0x" << std::hex << reader.get_entry() << std::endl |
| << " Flags: " |
| << "0x" << std::hex << reader.get_flags() << std::endl |
| << std::endl; |
| } |
| |
| //------------------------------------------------------------------------------ |
| static void section_headers( std::ostream& out, const elfio& reader ) |
| { |
| Elf_Half n = reader.sections.size(); |
| |
| if ( n == 0 ) { |
| return; |
| } |
| |
| out << "Section Headers:" << std::endl; |
| if ( reader.get_class() == ELFCLASS32 ) { // Output for 32-bit |
| out << "[ Nr ] Type Addr Size ES Flg Lk Inf " |
| "Al Name" |
| << std::endl; |
| } |
| else { // Output for 64-bit |
| out << "[ Nr ] Type Addr Size " |
| " ES Flg" |
| << std::endl |
| << " Lk Inf Al Name" << std::endl; |
| } |
| |
| for ( Elf_Half i = 0; i < n; ++i ) { // For all sections |
| section* sec = reader.sections[i]; |
| section_header( out, i, sec, reader.get_class() ); |
| } |
| |
| out << "Key to Flags: W (write), A (alloc), X (execute)\n\n" |
| << std::endl; |
| } |
| |
| //------------------------------------------------------------------------------ |
| static void section_header( std::ostream& out, |
| Elf_Half no, |
| const section* sec, |
| unsigned char elf_class ) |
| { |
| std::ios_base::fmtflags original_flags = out.flags(); |
| |
| if ( elf_class == ELFCLASS32 ) { // Output for 32-bit |
| out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] " |
| << DUMP_STR_FORMAT( 17 ) << str_section_type( sec->get_type() ) |
| << " " << DUMP_HEX_FORMAT( 8 ) << sec->get_address() << " " |
| << DUMP_HEX_FORMAT( 8 ) << sec->get_size() << " " |
| << DUMP_HEX_FORMAT( 2 ) << sec->get_entry_size() << " " |
| << DUMP_STR_FORMAT( 3 ) << section_flags( sec->get_flags() ) |
| << " " << DUMP_HEX_FORMAT( 2 ) << sec->get_link() << " " |
| << DUMP_HEX_FORMAT( 3 ) << sec->get_info() << " " |
| << DUMP_HEX_FORMAT( 2 ) << sec->get_addr_align() << " " |
| << DUMP_STR_FORMAT( 17 ) << sec->get_name() << " " << std::endl; |
| } |
| else { // Output for 64-bit |
| out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] " |
| << DUMP_STR_FORMAT( 17 ) << str_section_type( sec->get_type() ) |
| << " " << DUMP_HEX_FORMAT( 16 ) << sec->get_address() << " " |
| << DUMP_HEX_FORMAT( 16 ) << sec->get_size() << " " |
| << DUMP_HEX_FORMAT( 4 ) << sec->get_entry_size() << " " |
| << DUMP_STR_FORMAT( 3 ) << section_flags( sec->get_flags() ) |
| << " " << std::endl |
| << " " << DUMP_HEX_FORMAT( 4 ) << sec->get_link() << " " |
| << DUMP_HEX_FORMAT( 4 ) << sec->get_info() << " " |
| << DUMP_HEX_FORMAT( 4 ) << sec->get_addr_align() << " " |
| << DUMP_STR_FORMAT( 17 ) << sec->get_name() << " " << std::endl; |
| } |
| |
| out.flags( original_flags ); |
| |
| return; |
| } |
| |
| //------------------------------------------------------------------------------ |
| static void segment_headers( std::ostream& out, const elfio& reader ) |
| { |
| Elf_Half n = reader.segments.size(); |
| if ( n == 0 ) { |
| return; |
| } |
| |
| out << "Segment headers:" << std::endl; |
| if ( reader.get_class() == ELFCLASS32 ) { // Output for 32-bit |
| out << "[ Nr ] Type VirtAddr PhysAddr FileSize Mem.Size " |
| "Flags Align" |
| << std::endl; |
| } |
| else { // Output for 64-bit |
| out << "[ Nr ] Type VirtAddr PhysAddr " |
| "Flags" |
| << std::endl |
| << " FileSize Mem.Size " |
| "Align" |
| << std::endl; |
| } |
| |
| for ( Elf_Half i = 0; i < n; ++i ) { |
| segment* seg = reader.segments[i]; |
| segment_header( out, i, seg, reader.get_class() ); |
| } |
| |
| out << std::endl; |
| } |
| |
| //------------------------------------------------------------------------------ |
| static void segment_header( std::ostream& out, |
| Elf_Half no, |
| const segment* seg, |
| unsigned int elf_class ) |
| { |
| std::ios_base::fmtflags original_flags = out.flags(); |
| |
| if ( elf_class == ELFCLASS32 ) { // Output for 32-bit |
| out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] " |
| << DUMP_STR_FORMAT( 14 ) << str_segment_type( seg->get_type() ) |
| << " " << DUMP_HEX_FORMAT( 8 ) << seg->get_virtual_address() |
| << " " << DUMP_HEX_FORMAT( 8 ) << seg->get_physical_address() |
| << " " << DUMP_HEX_FORMAT( 8 ) << seg->get_file_size() << " " |
| << DUMP_HEX_FORMAT( 8 ) << seg->get_memory_size() << " " |
| << DUMP_STR_FORMAT( 8 ) << str_segment_flag( seg->get_flags() ) |
| << " " << DUMP_HEX_FORMAT( 8 ) << seg->get_align() << " " |
| << std::endl; |
| } |
| else { // Output for 64-bit |
| out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] " |
| << DUMP_STR_FORMAT( 14 ) << str_segment_type( seg->get_type() ) |
| << " " << DUMP_HEX_FORMAT( 16 ) << seg->get_virtual_address() |
| << " " << DUMP_HEX_FORMAT( 16 ) << seg->get_physical_address() |
| << " " << DUMP_STR_FORMAT( 16 ) |
| << str_segment_flag( seg->get_flags() ) << " " << std::endl |
| << " " << DUMP_HEX_FORMAT( 16 ) |
| << seg->get_file_size() << " " << DUMP_HEX_FORMAT( 16 ) |
| << seg->get_memory_size() << " " << DUMP_HEX_FORMAT( 16 ) |
| << seg->get_align() << " " << std::endl; |
| } |
| |
| out.flags( original_flags ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| static void symbol_tables( std::ostream& out, const elfio& reader ) |
| { |
| Elf_Half n = reader.sections.size(); |
| for ( Elf_Half i = 0; i < n; ++i ) { // For all sections |
| section* sec = reader.sections[i]; |
| if ( SHT_SYMTAB == sec->get_type() || |
| SHT_DYNSYM == sec->get_type() ) { |
| symbol_section_accessor symbols( reader, sec ); |
| |
| Elf_Xword sym_no = symbols.get_symbols_num(); |
| if ( sym_no > 0 ) { |
| out << "Symbol table (" << sec->get_name() << ")" |
| << std::endl; |
| if ( reader.get_class() == |
| ELFCLASS32 ) { // Output for 32-bit |
| out << "[ Nr ] Value Size Type Bind " |
| "Sect Name" |
| << std::endl; |
| } |
| else { // Output for 64-bit |
| out << "[ Nr ] Value Size Type " |
| " Bind Sect" |
| << std::endl |
| << " Name" << std::endl; |
| } |
| for ( Elf_Xword i = 0; i < sym_no; ++i ) { |
| std::string name; |
| Elf64_Addr value = 0; |
| Elf_Xword size = 0; |
| unsigned char bind = 0; |
| unsigned char type = 0; |
| Elf_Half section = 0; |
| unsigned char other = 0; |
| symbols.get_symbol( i, name, value, size, bind, type, |
| section, other ); |
| symbol_table( out, i, name, value, size, bind, type, |
| section, reader.get_class() ); |
| } |
| |
| out << std::endl; |
| } |
| } |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| static void symbol_table( std::ostream& out, |
| Elf_Xword no, |
| std::string& name, |
| Elf64_Addr value, |
| Elf_Xword size, |
| unsigned char bind, |
| unsigned char type, |
| Elf_Half section, |
| unsigned int elf_class ) |
| { |
| std::ios_base::fmtflags original_flags = out.flags(); |
| |
| if ( elf_class == ELFCLASS32 ) { // Output for 32-bit |
| out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] " |
| << DUMP_HEX_FORMAT( 8 ) << value << " " << DUMP_HEX_FORMAT( 8 ) |
| << size << " " << DUMP_STR_FORMAT( 7 ) |
| << str_symbol_type( type ) << " " << DUMP_STR_FORMAT( 8 ) |
| << str_symbol_bind( bind ) << " " << DUMP_DEC_FORMAT( 5 ) |
| << section << " " << DUMP_STR_FORMAT( 1 ) << name << " " |
| << std::endl; |
| } |
| else { // Output for 64-bit |
| out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] " |
| << DUMP_HEX_FORMAT( 16 ) << value << " " |
| << DUMP_HEX_FORMAT( 16 ) << size << " " << DUMP_STR_FORMAT( 7 ) |
| << str_symbol_type( type ) << " " << DUMP_STR_FORMAT( 8 ) |
| << str_symbol_bind( bind ) << " " << DUMP_DEC_FORMAT( 5 ) |
| << section << " " << std::endl |
| << " " << DUMP_STR_FORMAT( 1 ) << name << " " |
| << std::endl; |
| } |
| |
| out.flags( original_flags ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| static void notes( std::ostream& out, const elfio& reader ) |
| { |
| Elf_Half no = reader.sections.size(); |
| for ( Elf_Half i = 0; i < no; ++i ) { // For all sections |
| section* sec = reader.sections[i]; |
| if ( SHT_NOTE == sec->get_type() ) { // Look at notes |
| note_section_accessor notes( reader, sec ); |
| Elf_Word no_notes = notes.get_notes_num(); |
| if ( no > 0 ) { |
| out << "Note section (" << sec->get_name() << ")" |
| << std::endl |
| << " No Type Name" << std::endl; |
| for ( Elf_Word j = 0; j < no_notes; ++j ) { // For all notes |
| Elf_Word type; |
| std::string name; |
| void* desc; |
| Elf_Word descsz; |
| |
| if ( notes.get_note( j, type, name, desc, descsz ) ) { |
| // 'name' usually contains \0 at the end. Try to fix it |
| name = name.c_str(); |
| note( out, j, type, name ); |
| } |
| } |
| |
| out << std::endl; |
| } |
| } |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| static void modinfo( std::ostream& out, const elfio& reader ) |
| { |
| Elf_Half no = reader.sections.size(); |
| for ( Elf_Half i = 0; i < no; ++i ) { // For all sections |
| section* sec = reader.sections[i]; |
| if ( ".modinfo" == sec->get_name() ) { // Look for the section |
| out << "Section .modinfo" << std::endl; |
| |
| const_modinfo_section_accessor modinfo( sec ); |
| for ( Elf_Word i = 0; i < modinfo.get_attribute_num(); i++ ) { |
| std::string field; |
| std::string value; |
| if ( modinfo.get_attribute( i, field, value ) ) { |
| out << " " << std::setw( 20 ) << field |
| << std::setw( 0 ) << " = " << value << std::endl; |
| } |
| } |
| |
| out << std::endl; |
| break; |
| } |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| static void |
| note( std::ostream& out, int no, Elf_Word type, const std::string& name ) |
| { |
| out << " [" << DUMP_DEC_FORMAT( 2 ) << no << "] " |
| << DUMP_HEX_FORMAT( 8 ) << type << " " << DUMP_STR_FORMAT( 1 ) |
| << name << std::endl; |
| } |
| |
| //------------------------------------------------------------------------------ |
| static void dynamic_tags( std::ostream& out, const elfio& reader ) |
| { |
| Elf_Half n = reader.sections.size(); |
| for ( Elf_Half i = 0; i < n; ++i ) { // For all sections |
| section* sec = reader.sections[i]; |
| if ( SHT_DYNAMIC == sec->get_type() ) { |
| dynamic_section_accessor dynamic( reader, sec ); |
| |
| Elf_Xword dyn_no = dynamic.get_entries_num(); |
| if ( dyn_no > 0 ) { |
| out << "Dynamic section (" << sec->get_name() << ")" |
| << std::endl; |
| out << "[ Nr ] Tag Name/Value" << std::endl; |
| for ( Elf_Xword i = 0; i < dyn_no; ++i ) { |
| Elf_Xword tag = 0; |
| Elf_Xword value = 0; |
| std::string str; |
| dynamic.get_entry( i, tag, value, str ); |
| dynamic_tag( out, i, tag, value, str, |
| reader.get_class() ); |
| if ( DT_NULL == tag ) { |
| break; |
| } |
| } |
| |
| out << std::endl; |
| } |
| } |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| static void dynamic_tag( std::ostream& out, |
| Elf_Xword no, |
| Elf_Xword tag, |
| Elf_Xword value, |
| std::string str, |
| unsigned int /*elf_class*/ ) |
| { |
| out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] " |
| << DUMP_STR_FORMAT( 16 ) << str_dynamic_tag( tag ) << " "; |
| if ( str.empty() ) { |
| out << DUMP_HEX_FORMAT( 16 ) << value << " "; |
| } |
| else { |
| out << DUMP_STR_FORMAT( 32 ) << str << " "; |
| } |
| out << std::endl; |
| } |
| |
| //------------------------------------------------------------------------------ |
| static void section_data( std::ostream& out, const section* sec ) |
| { |
| std::ios_base::fmtflags original_flags = out.flags(); |
| |
| out << sec->get_name() << std::endl; |
| const char* pdata = sec->get_data(); |
| if ( pdata ) { |
| ELFIO::Elf_Xword i; |
| for ( i = 0; i < std::min( sec->get_size(), MAX_DATA_ENTRIES ); |
| ++i ) { |
| if ( i % 16 == 0 ) { |
| out << "[" << DUMP_HEX_FORMAT( 8 ) << i << "]"; |
| } |
| |
| out << " " << DUMP_HEX_FORMAT( 2 ) << ( pdata[i] & 0x000000FF ); |
| |
| if ( i % 16 == 15 ) { |
| out << std::endl; |
| } |
| } |
| if ( i % 16 != 0 ) { |
| out << std::endl; |
| } |
| |
| out.flags( original_flags ); |
| } |
| |
| return; |
| } |
| |
| //------------------------------------------------------------------------------ |
| static void section_datas( std::ostream& out, const elfio& reader ) |
| { |
| Elf_Half n = reader.sections.size(); |
| |
| if ( n == 0 ) { |
| return; |
| } |
| |
| out << "Section Data:" << std::endl; |
| |
| for ( Elf_Half i = 1; i < n; ++i ) { // For all sections |
| section* sec = reader.sections[i]; |
| if ( sec->get_type() == SHT_NOBITS ) { |
| continue; |
| } |
| section_data( out, sec ); |
| } |
| |
| out << std::endl; |
| } |
| |
| //------------------------------------------------------------------------------ |
| static void |
| segment_data( std::ostream& out, Elf_Half no, const segment* seg ) |
| { |
| std::ios_base::fmtflags original_flags = out.flags(); |
| |
| out << "Segment # " << no << std::endl; |
| const char* pdata = seg->get_data(); |
| if ( pdata ) { |
| ELFIO::Elf_Xword i; |
| for ( i = 0; i < std::min( seg->get_file_size(), MAX_DATA_ENTRIES ); |
| ++i ) { |
| if ( i % 16 == 0 ) { |
| out << "[" << DUMP_HEX_FORMAT( 8 ) << i << "]"; |
| } |
| |
| out << " " << DUMP_HEX_FORMAT( 2 ) << ( pdata[i] & 0x000000FF ); |
| |
| if ( i % 16 == 15 ) { |
| out << std::endl; |
| } |
| } |
| if ( i % 16 != 0 ) { |
| out << std::endl; |
| } |
| |
| out.flags( original_flags ); |
| } |
| |
| return; |
| } |
| |
| //------------------------------------------------------------------------------ |
| static void segment_datas( std::ostream& out, const elfio& reader ) |
| { |
| Elf_Half n = reader.segments.size(); |
| |
| if ( n == 0 ) { |
| return; |
| } |
| |
| out << "Segment Data:" << std::endl; |
| |
| for ( Elf_Half i = 0; i < n; ++i ) { // For all sections |
| segment* seg = reader.segments[i]; |
| segment_data( out, i, seg ); |
| } |
| |
| out << std::endl; |
| } |
| |
| private: |
| //------------------------------------------------------------------------------ |
| template <typename T, typename K> |
| std::string static find_value_in_table( const T& table, const K& key ) |
| { |
| std::string res = "?"; |
| for ( unsigned int i = 0; i < sizeof( table ) / sizeof( table[0] ); |
| ++i ) { |
| if ( table[i].key == key ) { |
| res = table[i].str; |
| break; |
| } |
| } |
| |
| return res; |
| } |
| |
| //------------------------------------------------------------------------------ |
| template <typename T, typename K> |
| static std::string format_assoc( const T& table, const K& key ) |
| { |
| std::string str = find_value_in_table( table, key ); |
| if ( str == "?" ) { |
| std::ostringstream oss; |
| oss << str << " (0x" << std::hex << key << ")"; |
| str = oss.str(); |
| } |
| |
| return str; |
| } |
| |
| //------------------------------------------------------------------------------ |
| template <typename T> |
| static std::string format_assoc( const T& table, const char key ) |
| { |
| return format_assoc( table, (const int)key ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| static std::string section_flags( Elf_Xword flags ) |
| { |
| std::string ret = ""; |
| if ( flags & SHF_WRITE ) { |
| ret += "W"; |
| } |
| if ( flags & SHF_ALLOC ) { |
| ret += "A"; |
| } |
| if ( flags & SHF_EXECINSTR ) { |
| ret += "X"; |
| } |
| |
| return ret; |
| } |
| |
| //------------------------------------------------------------------------------ |
| #define STR_FUNC_TABLE( name ) \ |
| template <typename T> static std::string str_##name( const T key ) \ |
| { \ |
| return format_assoc( name##_table, key ); \ |
| } |
| |
| STR_FUNC_TABLE( class ) |
| STR_FUNC_TABLE( endian ) |
| STR_FUNC_TABLE( version ) |
| STR_FUNC_TABLE( type ) |
| STR_FUNC_TABLE( machine ) |
| STR_FUNC_TABLE( section_type ) |
| STR_FUNC_TABLE( segment_type ) |
| STR_FUNC_TABLE( segment_flag ) |
| STR_FUNC_TABLE( symbol_bind ) |
| STR_FUNC_TABLE( symbol_type ) |
| STR_FUNC_TABLE( dynamic_tag ) |
| |
| #undef STR_FUNC_TABLE |
| #undef DUMP_DEC_FORMAT |
| #undef DUMP_HEX_FORMAT |
| #undef DUMP_STR_FORMAT |
| }; // class dump |
| |
| }; // namespace ELFIO |
| |
| #endif // ELFIO_DUMP_HPP |
| |
| /*** End of inlined file: elfio_dump.hpp ***/ |
| |