• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 Copyright (C) 2001-present by Serge Lamikhov-Center
3 
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10 
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21 */
22 
23 #ifndef ELFIO_DUMP_HPP
24 #define ELFIO_DUMP_HPP
25 
26 #include <algorithm>
27 #include <string>
28 #include <ostream>
29 #include <sstream>
30 #include <iomanip>
31 #include <elfio/elfio.hpp>
32 
33 namespace ELFIO {
34 
35 static struct class_table_t
36 {
37     const char  key;
38     const char* str;
39 } class_table[] = {
40     { ELFCLASS32, "ELF32" },
41     { ELFCLASS64, "ELF64" },
42 };
43 
44 static struct endian_table_t
45 {
46     const char  key;
47     const char* str;
48 } endian_table[] = {
49     { ELFDATANONE, "None" },
50     { ELFDATA2LSB, "Little endian" },
51     { ELFDATA2MSB, "Big endian" },
52 };
53 
54 static struct version_table_t
55 {
56     const Elf64_Word key;
57     const char*      str;
58 } version_table[] = {
59     { EV_NONE, "None" },
60     { EV_CURRENT, "Current" },
61 };
62 
63 static struct type_table_t
64 {
65     const Elf32_Half key;
66     const char*      str;
67 } type_table[] = {
68     { ET_NONE, "No file type" },    { ET_REL, "Relocatable file" },
69     { ET_EXEC, "Executable file" }, { ET_DYN, "Shared object file" },
70     { ET_CORE, "Core file" },
71 };
72 
73 static struct machine_table_t
74 {
75     const Elf64_Half key;
76     const char*      str;
77 } machine_table[] = {
78     { EM_NONE, "No machine" },
79     { EM_M32, "AT&T WE 32100" },
80     { EM_SPARC, "SUN SPARC" },
81     { EM_386, "Intel 80386" },
82     { EM_68K, "Motorola m68k family" },
83     { EM_88K, "Motorola m88k family" },
84     { EM_486, "Intel 80486// Reserved for future use" },
85     { EM_860, "Intel 80860" },
86     { EM_MIPS, "MIPS R3000 (officially, big-endian only)" },
87     { EM_S370, "IBM System/370" },
88     { EM_MIPS_RS3_LE,
89       "MIPS R3000 little-endian (Oct 4 1999 Draft) Deprecated" },
90     { EM_res011, "Reserved" },
91     { EM_res012, "Reserved" },
92     { EM_res013, "Reserved" },
93     { EM_res014, "Reserved" },
94     { EM_PARISC, "HPPA" },
95     { EM_res016, "Reserved" },
96     { EM_VPP550, "Fujitsu VPP500" },
97     { EM_SPARC32PLUS, "Sun's v8plus" },
98     { EM_960, "Intel 80960" },
99     { EM_PPC, "PowerPC" },
100     { EM_PPC64, "64-bit PowerPC" },
101     { EM_S390, "IBM S/390" },
102     { EM_SPU, "Sony/Toshiba/IBM SPU" },
103     { EM_res024, "Reserved" },
104     { EM_res025, "Reserved" },
105     { EM_res026, "Reserved" },
106     { EM_res027, "Reserved" },
107     { EM_res028, "Reserved" },
108     { EM_res029, "Reserved" },
109     { EM_res030, "Reserved" },
110     { EM_res031, "Reserved" },
111     { EM_res032, "Reserved" },
112     { EM_res033, "Reserved" },
113     { EM_res034, "Reserved" },
114     { EM_res035, "Reserved" },
115     { EM_V800, "NEC V800 series" },
116     { EM_FR20, "Fujitsu FR20" },
117     { EM_RH32, "TRW RH32" },
118     { EM_MCORE, "Motorola M*Core // May also be taken by Fujitsu MMA" },
119     { EM_RCE, "Old name for MCore" },
120     { EM_ARM, "ARM" },
121     { EM_OLD_ALPHA, "Digital Alpha" },
122     { EM_SH, "Renesas (formerly Hitachi) / SuperH SH" },
123     { EM_SPARCV9, "SPARC v9 64-bit" },
124     { EM_TRICORE, "Siemens Tricore embedded processor" },
125     { EM_ARC, "ARC Cores" },
126     { EM_H8_300, "Renesas (formerly Hitachi) H8/300" },
127     { EM_H8_300H, "Renesas (formerly Hitachi) H8/300H" },
128     { EM_H8S, "Renesas (formerly Hitachi) H8S" },
129     { EM_H8_500, "Renesas (formerly Hitachi) H8/500" },
130     { EM_IA_64, "Intel IA-64 Processor" },
131     { EM_MIPS_X, "Stanford MIPS-X" },
132     { EM_COLDFIRE, "Motorola Coldfire" },
133     { EM_68HC12, "Motorola M68HC12" },
134     { EM_MMA, "Fujitsu Multimedia Accelerator" },
135     { EM_PCP, "Siemens PCP" },
136     { EM_NCPU, "Sony nCPU embedded RISC processor" },
137     { EM_NDR1, "Denso NDR1 microprocesspr" },
138     { EM_STARCORE, "Motorola Star*Core processor" },
139     { EM_ME16, "Toyota ME16 processor" },
140     { EM_ST100, "STMicroelectronics ST100 processor" },
141     { EM_TINYJ, "Advanced Logic Corp. TinyJ embedded processor" },
142     { EM_X86_64, "Advanced Micro Devices X86-64 processor" },
143     { EM_PDSP, "Sony DSP Processor" },
144     { EM_PDP10, "Digital Equipment Corp. PDP-10" },
145     { EM_PDP11, "Digital Equipment Corp. PDP-11" },
146     { EM_FX66, "Siemens FX66 microcontroller" },
147     { EM_ST9PLUS, "STMicroelectronics ST9+ 8/16 bit microcontroller" },
148     { EM_ST7, "STMicroelectronics ST7 8-bit microcontroller" },
149     { EM_68HC16, "Motorola MC68HC16 Microcontroller" },
150     { EM_68HC11, "Motorola MC68HC11 Microcontroller" },
151     { EM_68HC08, "Motorola MC68HC08 Microcontroller" },
152     { EM_68HC05, "Motorola MC68HC05 Microcontroller" },
153     { EM_SVX, "Silicon Graphics SVx" },
154     { EM_ST19, "STMicroelectronics ST19 8-bit cpu" },
155     { EM_VAX, "Digital VAX" },
156     { EM_CRIS, "Axis Communications 32-bit embedded processor" },
157     { EM_JAVELIN, "Infineon Technologies 32-bit embedded cpu" },
158     { EM_FIREPATH, "Element 14 64-bit DSP processor" },
159     { EM_ZSP, "LSI Logic's 16-bit DSP processor" },
160     { EM_MMIX, "Donald Knuth's educational 64-bit processor" },
161     { EM_HUANY, "Harvard's machine-independent format" },
162     { EM_PRISM, "SiTera Prism" },
163     { EM_AVR, "Atmel AVR 8-bit microcontroller" },
164     { EM_FR30, "Fujitsu FR30" },
165     { EM_D10V, "Mitsubishi D10V" },
166     { EM_D30V, "Mitsubishi D30V" },
167     { EM_V850, "NEC v850" },
168     { EM_M32R, "Renesas M32R (formerly Mitsubishi M32R)" },
169     { EM_MN10300, "Matsushita MN10300" },
170     { EM_MN10200, "Matsushita MN10200" },
171     { EM_PJ, "picoJava" },
172     { EM_OPENRISC, "OpenRISC 32-bit embedded processor" },
173     { EM_ARC_A5, "ARC Cores Tangent-A5" },
174     { EM_XTENSA, "Tensilica Xtensa Architecture" },
175     { EM_VIDEOCORE, "Alphamosaic VideoCore processor" },
176     { EM_TMM_GPP, "Thompson Multimedia General Purpose Processor" },
177     { EM_NS32K, "National Semiconductor 32000 series" },
178     { EM_TPC, "Tenor Network TPC processor" },
179     { EM_SNP1K, "Trebia SNP 1000 processor" },
180     { EM_ST200, "STMicroelectronics ST200 microcontroller" },
181     { EM_IP2K, "Ubicom IP2022 micro controller" },
182     { EM_MAX, "MAX Processor" },
183     { EM_CR, "National Semiconductor CompactRISC" },
184     { EM_F2MC16, "Fujitsu F2MC16" },
185     { EM_MSP430, "TI msp430 micro controller" },
186     { EM_BLACKFIN, "ADI Blackfin" },
187     { EM_SE_C33, "S1C33 Family of Seiko Epson processors" },
188     { EM_SEP, "Sharp embedded microprocessor" },
189     { EM_ARCA, "Arca RISC Microprocessor" },
190     { EM_UNICORE, "Microprocessor series from PKU-Unity Ltd. and MPRC of "
191                   "Peking University" },
192     { EM_EXCESS, "eXcess: 16/32/64-bit configurable embedded CPU" },
193     { EM_DXP, "Icera Semiconductor Inc. Deep Execution Processor" },
194     { EM_ALTERA_NIOS2, "Altera Nios II soft-core processor" },
195     { EM_CRX, "National Semiconductor CRX" },
196     { EM_XGATE, "Motorola XGATE embedded processor" },
197     { EM_C166, "Infineon C16x/XC16x processor" },
198     { EM_M16C, "Renesas M16C series microprocessors" },
199     { EM_DSPIC30F, "Microchip Technology dsPIC30F Digital Signal Controller" },
200     { EM_CE, "Freescale Communication Engine RISC core" },
201     { EM_M32C, "Renesas M32C series microprocessors" },
202     { EM_res121, "Reserved" },
203     { EM_res122, "Reserved" },
204     { EM_res123, "Reserved" },
205     { EM_res124, "Reserved" },
206     { EM_res125, "Reserved" },
207     { EM_res126, "Reserved" },
208     { EM_res127, "Reserved" },
209     { EM_res128, "Reserved" },
210     { EM_res129, "Reserved" },
211     { EM_res130, "Reserved" },
212     { EM_TSK3000, "Altium TSK3000 core" },
213     { EM_RS08, "Freescale RS08 embedded processor" },
214     { EM_res133, "Reserved" },
215     { EM_ECOG2, "Cyan Technology eCOG2 microprocessor" },
216     { EM_SCORE, "Sunplus Score" },
217     { EM_SCORE7, "Sunplus S+core7 RISC processor" },
218     { EM_DSP24, "New Japan Radio (NJR) 24-bit DSP Processor" },
219     { EM_VIDEOCORE3, "Broadcom VideoCore III processor" },
220     { EM_LATTICEMICO32, "RISC processor for Lattice FPGA architecture" },
221     { EM_SE_C17, "Seiko Epson C17 family" },
222     { EM_TI_C6000, "Texas Instruments TMS320C6000 DSP family" },
223     { EM_TI_C2000, "Texas Instruments TMS320C2000 DSP family" },
224     { EM_TI_C5500, "Texas Instruments TMS320C55x DSP family" },
225     { EM_res143, "Reserved" },
226     { EM_res144, "Reserved" },
227     { EM_res145, "Reserved" },
228     { EM_res146, "Reserved" },
229     { EM_res147, "Reserved" },
230     { EM_res148, "Reserved" },
231     { EM_res149, "Reserved" },
232     { EM_res150, "Reserved" },
233     { EM_res151, "Reserved" },
234     { EM_res152, "Reserved" },
235     { EM_res153, "Reserved" },
236     { EM_res154, "Reserved" },
237     { EM_res155, "Reserved" },
238     { EM_res156, "Reserved" },
239     { EM_res157, "Reserved" },
240     { EM_res158, "Reserved" },
241     { EM_res159, "Reserved" },
242     { EM_MMDSP_PLUS, "STMicroelectronics 64bit VLIW Data Signal Processor" },
243     { EM_CYPRESS_M8C, "Cypress M8C microprocessor" },
244     { EM_R32C, "Renesas R32C series microprocessors" },
245     { EM_TRIMEDIA, "NXP Semiconductors TriMedia architecture family" },
246     { EM_QDSP6, "QUALCOMM DSP6 Processor" },
247     { EM_8051, "Intel 8051 and variants" },
248     { EM_STXP7X, "STMicroelectronics STxP7x family" },
249     { EM_NDS32,
250       "Andes Technology compact code size embedded RISC processor family" },
251     { EM_ECOG1, "Cyan Technology eCOG1X family" },
252     { EM_ECOG1X, "Cyan Technology eCOG1X family" },
253     { EM_MAXQ30, "Dallas Semiconductor MAXQ30 Core Micro-controllers" },
254     { EM_XIMO16, "New Japan Radio (NJR) 16-bit DSP Processor" },
255     { EM_MANIK, "M2000 Reconfigurable RISC Microprocessor" },
256     { EM_CRAYNV2, "Cray Inc. NV2 vector architecture" },
257     { EM_RX, "Renesas RX family" },
258     { EM_METAG, "Imagination Technologies META processor architecture" },
259     { EM_MCST_ELBRUS, "MCST Elbrus general purpose hardware architecture" },
260     { EM_ECOG16, "Cyan Technology eCOG16 family" },
261     { EM_CR16, "National Semiconductor CompactRISC 16-bit processor" },
262     { EM_ETPU, "Freescale Extended Time Processing Unit" },
263     { EM_SLE9X, "Infineon Technologies SLE9X core" },
264     { EM_L1OM, "Intel L1OM" },
265     { EM_INTEL181, "Reserved by Intel" },
266     { EM_INTEL182, "Reserved by Intel" },
267     { EM_res183, "Reserved by ARM" },
268     { EM_res184, "Reserved by ARM" },
269     { EM_AVR32, "Atmel Corporation 32-bit microprocessor family" },
270     { EM_STM8, "STMicroeletronics STM8 8-bit microcontroller" },
271     { EM_TILE64, "Tilera TILE64 multicore architecture family" },
272     { EM_TILEPRO, "Tilera TILEPro multicore architecture family" },
273     { EM_MICROBLAZE, "Xilinx MicroBlaze 32-bit RISC soft processor core" },
274     { EM_CUDA, "NVIDIA CUDA architecture " },
275     { EM_TILEGX, "Tilera TILE-Gx multicore architecture family" },
276     { EM_CLOUDSHIELD, "CloudShield architecture family" },
277     { EM_COREA_1ST, "KIPO-KAIST Core-A 1st generation processor family" },
278     { EM_COREA_2ND, "KIPO-KAIST Core-A 2nd generation processor family" },
279     { EM_ARC_COMPACT2, "Synopsys ARCompact V2" },
280     { EM_OPEN8, "Open8 8-bit RISC soft processor core" },
281     { EM_RL78, "Renesas RL78 family" },
282     { EM_VIDEOCORE5, "Broadcom VideoCore V processor" },
283     { EM_78KOR, "Renesas 78KOR family" },
284     { EM_56800EX, "Freescale 56800EX Digital Signal Controller (DSC)" },
285     { EM_BA1, "Beyond BA1 CPU architecture" },
286     { EM_BA2, "Beyond BA2 CPU architecture" },
287     { EM_XCORE, "XMOS xCORE processor family" },
288     { EM_MCHP_PIC, "Microchip 8-bit PIC(r) family" },
289     { EM_INTEL205, "Reserved by Intel" },
290     { EM_INTEL206, "Reserved by Intel" },
291     { EM_INTEL207, "Reserved by Intel" },
292     { EM_INTEL208, "Reserved by Intel" },
293     { EM_INTEL209, "Reserved by Intel" },
294     { EM_KM32, "KM211 KM32 32-bit processor" },
295     { EM_KMX32, "KM211 KMX32 32-bit processor" },
296     { EM_KMX16, "KM211 KMX16 16-bit processor" },
297     { EM_KMX8, "KM211 KMX8 8-bit processor" },
298     { EM_KVARC, "KM211 KVARC processor" },
299     { EM_CDP, "Paneve CDP architecture family" },
300     { EM_COGE, "Cognitive Smart Memory Processor" },
301     { EM_COOL, "iCelero CoolEngine" },
302     { EM_NORC, "Nanoradio Optimized RISC" },
303     { EM_CSR_KALIMBA, "CSR Kalimba architecture family" },
304     { EM_Z80, "Zilog Z80" },
305     { EM_VISIUM, "Controls and Data Services VISIUMcore processor" },
306     { EM_FT32, "FTDI Chip FT32 high performance 32-bit RISC architecture" },
307     { EM_MOXIE, "Moxie processor family" },
308     { EM_AMDGPU, "AMD GPU architecture" },
309     { EM_RISCV, "RISC-V" },
310     { EM_LANAI, "Lanai processor" },
311     { EM_CEVA, "CEVA Processor Architecture Family" },
312     { EM_CEVA_X2, "CEVA X2 Processor Family" },
313     { EM_BPF, "Linux BPF – in-kernel virtual machine" },
314     { EM_GRAPHCORE_IPU, "Graphcore Intelligent Processing Unit" },
315     { EM_IMG1, "Imagination Technologies" },
316     { EM_NFP, "Netronome Flow Processor (P)" },
317     { EM_CSKY, "C-SKY processor family" },
318     { EM_ARC_COMPACT3_64, "Synopsys ARCv2.3 64-bit" },
319     { EM_MCS6502, "MOS Technology MCS 6502 processor" },
320     { EM_ARC_COMPACT3, "Synopsys ARCv2.3 32-bit" },
321     { EM_KVX, "Kalray VLIW core of the MPPA processor family" },
322     { EM_65816, "WDC 65816/65C816" },
323     { EM_LOONGARCH, "Loongson Loongarch" },
324     { EM_KF32, "ChipON KungFu32" },
325     { EM_MT, "Morpho Techologies MT processor" },
326     { EM_ALPHA, "Alpha" },
327     { EM_WEBASSEMBLY, "Web Assembly" },
328     { EM_DLX, "OpenDLX" },
329     { EM_XSTORMY16, "Sanyo XStormy16 CPU core" },
330     { EM_IQ2000, "Vitesse IQ2000" },
331     { EM_M32C_OLD, "M32C_OLD" },
332     { EM_NIOS32, "Altera Nios" },
333     { EM_CYGNUS_MEP, "Toshiba MeP Media Engine" },
334     { EM_ADAPTEVA_EPIPHANY, "Adapteva EPIPHANY" },
335     { EM_CYGNUS_FRV, "Fujitsu FR-V" },
336     { EM_S12Z, "Freescale S12Z" },
337 };
338 
339 static struct section_type_table_t
340 {
341     const Elf64_Half key;
342     const char*      str;
343 } section_type_table[] = {
344     { SHT_NULL, "NULL" },
345     { SHT_PROGBITS, "PROGBITS" },
346     { SHT_SYMTAB, "SYMTAB" },
347     { SHT_STRTAB, "STRTAB" },
348     { SHT_RELA, "RELA" },
349     { SHT_HASH, "HASH" },
350     { SHT_DYNAMIC, "DYNAMIC" },
351     { SHT_NOTE, "NOTE" },
352     { SHT_NOBITS, "NOBITS" },
353     { SHT_REL, "REL" },
354     { SHT_SHLIB, "SHLIB" },
355     { SHT_DYNSYM, "DYNSYM" },
356     { SHT_INIT_ARRAY, "INIT_ARRAY" },
357     { SHT_FINI_ARRAY, "FINI_ARRAY" },
358     { SHT_PREINIT_ARRAY, "PREINIT_ARRAY" },
359     { SHT_GROUP, "GROUP" },
360     { SHT_SYMTAB_SHNDX, "SYMTAB_SHNDX " },
361 };
362 
363 static struct segment_type_table_t
364 {
365     const Elf_Word key;
366     const char*    str;
367 } segment_type_table[] = {
368     { PT_NULL, "NULL" },     { PT_LOAD, "LOAD" }, { PT_DYNAMIC, "DYNAMIC" },
369     { PT_INTERP, "INTERP" }, { PT_NOTE, "NOTE" }, { PT_SHLIB, "SHLIB" },
370     { PT_PHDR, "PHDR" },     { PT_TLS, "TLS" },
371 };
372 
373 static struct segment_flag_table_t
374 {
375     const Elf_Word key;
376     const char*    str;
377 } segment_flag_table[] = {
378     { 0, "" },  { 1, "X" },  { 2, "W" },  { 3, "WX" },
379     { 4, "R" }, { 5, "RX" }, { 6, "RW" }, { 7, "RWX" },
380 };
381 
382 static struct symbol_bind_t
383 {
384     const Elf_Word key;
385     const char*    str;
386 } symbol_bind_table[] = {
387     { STB_LOCAL, "LOCAL" },   { STB_GLOBAL, "GLOBAL" },
388     { STB_WEAK, "WEAK" },     { STB_LOOS, "LOOS" },
389     { STB_HIOS, "HIOS" },     { STB_MULTIDEF, "MULTIDEF" },
390     { STB_LOPROC, "LOPROC" }, { STB_HIPROC, "HIPROC" },
391 };
392 
393 static struct symbol_type_t
394 {
395     const Elf_Word key;
396     const char*    str;
397 } symbol_type_table[] = {
398     { STT_NOTYPE, "NOTYPE" }, { STT_OBJECT, "OBJECT" },
399     { STT_FUNC, "FUNC" },     { STT_SECTION, "SECTION" },
400     { STT_FILE, "FILE" },     { STT_COMMON, "COMMON" },
401     { STT_TLS, "TLS" },       { STT_LOOS, "LOOS" },
402     { STT_HIOS, "HIOS" },     { STT_LOPROC, "LOPROC" },
403     { STT_HIPROC, "HIPROC" },
404 };
405 
406 static struct dynamic_tag_t
407 {
408     const Elf_Word key;
409     const char*    str;
410 } dynamic_tag_table[] = {
411     { DT_NULL, "NULL" },
412     { DT_NEEDED, "NEEDED" },
413     { DT_PLTRELSZ, "PLTRELSZ" },
414     { DT_PLTGOT, "PLTGOT" },
415     { DT_HASH, "HASH" },
416     { DT_STRTAB, "STRTAB" },
417     { DT_SYMTAB, "SYMTAB" },
418     { DT_RELA, "RELA" },
419     { DT_RELASZ, "RELASZ" },
420     { DT_RELAENT, "RELAENT" },
421     { DT_STRSZ, "STRSZ" },
422     { DT_SYMENT, "SYMENT" },
423     { DT_INIT, "INIT" },
424     { DT_FINI, "FINI" },
425     { DT_SONAME, "SONAME" },
426     { DT_RPATH, "RPATH" },
427     { DT_SYMBOLIC, "SYMBOLIC" },
428     { DT_REL, "REL" },
429     { DT_RELSZ, "RELSZ" },
430     { DT_RELENT, "RELENT" },
431     { DT_PLTREL, "PLTREL" },
432     { DT_DEBUG, "DEBUG" },
433     { DT_TEXTREL, "TEXTREL" },
434     { DT_JMPREL, "JMPREL" },
435     { DT_BIND_NOW, "BIND_NOW" },
436     { DT_INIT_ARRAY, "INIT_ARRAY" },
437     { DT_FINI_ARRAY, "FINI_ARRAY" },
438     { DT_INIT_ARRAYSZ, "INIT_ARRAYSZ" },
439     { DT_FINI_ARRAYSZ, "FINI_ARRAYSZ" },
440     { DT_RUNPATH, "RUNPATH" },
441     { DT_FLAGS, "FLAGS" },
442     { DT_ENCODING, "ENCODING" },
443     { DT_PREINIT_ARRAY, "PREINIT_ARRAY" },
444     { DT_PREINIT_ARRAYSZ, "PREINIT_ARRAYSZ" },
445     { DT_MAXPOSTAGS, "MAXPOSTAGS" },
446 };
447 
448 static const ELFIO::Elf_Xword MAX_DATA_ENTRIES = 64;
449 
450 //------------------------------------------------------------------------------
451 class dump
452 {
453 #define DUMP_DEC_FORMAT( width ) \
454     std::setw( width ) << std::setfill( ' ' ) << std::dec << std::right
455 #define DUMP_HEX_FORMAT( width ) \
456     std::setw( width ) << std::setfill( '0' ) << std::hex << std::right
457 #define DUMP_STR_FORMAT( width ) \
458     std::setw( width ) << std::setfill( ' ' ) << std::hex << std::left
459 
460   public:
461     //------------------------------------------------------------------------------
header(std::ostream & out,const elfio & reader)462     static void header( std::ostream& out, const elfio& reader )
463     {
464         if ( !reader.get_header_size() ) {
465             return;
466         }
467         out << "ELF Header" << std::endl
468             << std::endl
469             << "  Class:      " << str_class( reader.get_class() ) << std::endl
470             << "  Encoding:   " << str_endian( reader.get_encoding() )
471             << std::endl
472             << "  ELFVersion: " << str_version( reader.get_elf_version() )
473             << std::endl
474             << "  Type:       " << str_type( reader.get_type() ) << std::endl
475             << "  Machine:    " << str_machine( reader.get_machine() )
476             << std::endl
477             << "  Version:    " << str_version( reader.get_version() )
478             << std::endl
479             << "  Entry:      "
480             << "0x" << std::hex << reader.get_entry() << std::endl
481             << "  Flags:      "
482             << "0x" << std::hex << reader.get_flags() << std::endl
483             << std::endl;
484     }
485 
486     //------------------------------------------------------------------------------
section_headers(std::ostream & out,const elfio & reader)487     static void section_headers( std::ostream& out, const elfio& reader )
488     {
489         Elf_Half n = reader.sections.size();
490 
491         if ( n == 0 ) {
492             return;
493         }
494 
495         out << "Section Headers:" << std::endl;
496         if ( reader.get_class() == ELFCLASS32 ) { // Output for 32-bit
497             out << "[  Nr ] Type              Addr     Size     ES Flg Lk Inf "
498                    "Al Name"
499                 << std::endl;
500         }
501         else { // Output for 64-bit
502             out << "[  Nr ] Type              Addr             Size            "
503                    " ES   Flg"
504                 << std::endl
505                 << "        Lk   Inf  Al      Name" << std::endl;
506         }
507 
508         for ( Elf_Half i = 0; i < n; ++i ) { // For all sections
509             section* sec = reader.sections[i];
510             section_header( out, i, sec, reader.get_class() );
511         }
512 
513         out << "Key to Flags: W (write), A (alloc), X (execute)\n\n"
514             << std::endl;
515     }
516 
517     //------------------------------------------------------------------------------
section_header(std::ostream & out,Elf_Half no,const section * sec,unsigned char elf_class)518     static void section_header( std::ostream&  out,
519                                 Elf_Half       no,
520                                 const section* sec,
521                                 unsigned char  elf_class )
522     {
523         std::ios_base::fmtflags original_flags = out.flags();
524 
525         if ( elf_class == ELFCLASS32 ) { // Output for 32-bit
526             out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] "
527                 << DUMP_STR_FORMAT( 17 ) << str_section_type( sec->get_type() )
528                 << " " << DUMP_HEX_FORMAT( 8 ) << sec->get_address() << " "
529                 << DUMP_HEX_FORMAT( 8 ) << sec->get_size() << " "
530                 << DUMP_HEX_FORMAT( 2 ) << sec->get_entry_size() << " "
531                 << DUMP_STR_FORMAT( 3 ) << section_flags( sec->get_flags() )
532                 << " " << DUMP_HEX_FORMAT( 2 ) << sec->get_link() << " "
533                 << DUMP_HEX_FORMAT( 3 ) << sec->get_info() << " "
534                 << DUMP_HEX_FORMAT( 2 ) << sec->get_addr_align() << " "
535                 << DUMP_STR_FORMAT( 17 ) << sec->get_name() << " " << std::endl;
536         }
537         else { // Output for 64-bit
538             out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] "
539                 << DUMP_STR_FORMAT( 17 ) << str_section_type( sec->get_type() )
540                 << " " << DUMP_HEX_FORMAT( 16 ) << sec->get_address() << " "
541                 << DUMP_HEX_FORMAT( 16 ) << sec->get_size() << " "
542                 << DUMP_HEX_FORMAT( 4 ) << sec->get_entry_size() << " "
543                 << DUMP_STR_FORMAT( 3 ) << section_flags( sec->get_flags() )
544                 << " " << std::endl
545                 << "        " << DUMP_HEX_FORMAT( 4 ) << sec->get_link() << " "
546                 << DUMP_HEX_FORMAT( 4 ) << sec->get_info() << " "
547                 << DUMP_HEX_FORMAT( 4 ) << sec->get_addr_align() << "    "
548                 << DUMP_STR_FORMAT( 17 ) << sec->get_name() << " " << std::endl;
549         }
550 
551         out.flags( original_flags );
552 
553         return;
554     }
555 
556     //------------------------------------------------------------------------------
segment_headers(std::ostream & out,const elfio & reader)557     static void segment_headers( std::ostream& out, const elfio& reader )
558     {
559         Elf_Half n = reader.segments.size();
560         if ( n == 0 ) {
561             return;
562         }
563 
564         out << "Segment headers:" << std::endl;
565         if ( reader.get_class() == ELFCLASS32 ) { // Output for 32-bit
566             out << "[  Nr ] Type           VirtAddr PhysAddr FileSize Mem.Size "
567                    "Flags    Align"
568                 << std::endl;
569         }
570         else { // Output for 64-bit
571             out << "[  Nr ] Type           VirtAddr         PhysAddr         "
572                    "Flags"
573                 << std::endl
574                 << "                       FileSize         Mem.Size         "
575                    "Align"
576                 << std::endl;
577         }
578 
579         for ( Elf_Half i = 0; i < n; ++i ) {
580             segment* seg = reader.segments[i];
581             segment_header( out, i, seg, reader.get_class() );
582         }
583 
584         out << std::endl;
585     }
586 
587     //------------------------------------------------------------------------------
segment_header(std::ostream & out,Elf_Half no,const segment * seg,unsigned int elf_class)588     static void segment_header( std::ostream&  out,
589                                 Elf_Half       no,
590                                 const segment* seg,
591                                 unsigned int   elf_class )
592     {
593         std::ios_base::fmtflags original_flags = out.flags();
594 
595         if ( elf_class == ELFCLASS32 ) { // Output for 32-bit
596             out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] "
597                 << DUMP_STR_FORMAT( 14 ) << str_segment_type( seg->get_type() )
598                 << " " << DUMP_HEX_FORMAT( 8 ) << seg->get_virtual_address()
599                 << " " << DUMP_HEX_FORMAT( 8 ) << seg->get_physical_address()
600                 << " " << DUMP_HEX_FORMAT( 8 ) << seg->get_file_size() << " "
601                 << DUMP_HEX_FORMAT( 8 ) << seg->get_memory_size() << " "
602                 << DUMP_STR_FORMAT( 8 ) << str_segment_flag( seg->get_flags() )
603                 << " " << DUMP_HEX_FORMAT( 8 ) << seg->get_align() << " "
604                 << std::endl;
605         }
606         else { // Output for 64-bit
607             out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] "
608                 << DUMP_STR_FORMAT( 14 ) << str_segment_type( seg->get_type() )
609                 << " " << DUMP_HEX_FORMAT( 16 ) << seg->get_virtual_address()
610                 << " " << DUMP_HEX_FORMAT( 16 ) << seg->get_physical_address()
611                 << " " << DUMP_STR_FORMAT( 16 )
612                 << str_segment_flag( seg->get_flags() ) << " " << std::endl
613                 << "                       " << DUMP_HEX_FORMAT( 16 )
614                 << seg->get_file_size() << " " << DUMP_HEX_FORMAT( 16 )
615                 << seg->get_memory_size() << " " << DUMP_HEX_FORMAT( 16 )
616                 << seg->get_align() << " " << std::endl;
617         }
618 
619         out.flags( original_flags );
620     }
621 
622     //------------------------------------------------------------------------------
symbol_tables(std::ostream & out,const elfio & reader)623     static void symbol_tables( std::ostream& out, const elfio& reader )
624     {
625         Elf_Half n = reader.sections.size();
626         for ( Elf_Half i = 0; i < n; ++i ) { // For all sections
627             section* sec = reader.sections[i];
628             if ( SHT_SYMTAB == sec->get_type() ||
629                  SHT_DYNSYM == sec->get_type() ) {
630                 symbol_section_accessor symbols( reader, sec );
631 
632                 Elf_Xword sym_no = symbols.get_symbols_num();
633                 if ( sym_no > 0 ) {
634                     out << "Symbol table (" << sec->get_name() << ")"
635                         << std::endl;
636                     if ( reader.get_class() ==
637                          ELFCLASS32 ) { // Output for 32-bit
638                         out << "[  Nr ] Value    Size     Type    Bind      "
639                                "Sect Name"
640                             << std::endl;
641                     }
642                     else { // Output for 64-bit
643                         out << "[  Nr ] Value            Size             Type "
644                                "   Bind      Sect"
645                             << std::endl
646                             << "        Name" << std::endl;
647                     }
648                     for ( Elf_Xword i = 0; i < sym_no; ++i ) {
649                         std::string   name;
650                         Elf64_Addr    value   = 0;
651                         Elf_Xword     size    = 0;
652                         unsigned char bind    = 0;
653                         unsigned char type    = 0;
654                         Elf_Half      section = 0;
655                         unsigned char other   = 0;
656                         symbols.get_symbol( i, name, value, size, bind, type,
657                                             section, other );
658                         symbol_table( out, i, name, value, size, bind, type,
659                                       section, reader.get_class() );
660                     }
661 
662                     out << std::endl;
663                 }
664             }
665         }
666     }
667 
668     //------------------------------------------------------------------------------
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)669     static void symbol_table( std::ostream& out,
670                               Elf_Xword     no,
671                               std::string&  name,
672                               Elf64_Addr    value,
673                               Elf_Xword     size,
674                               unsigned char bind,
675                               unsigned char type,
676                               Elf_Half      section,
677                               unsigned int  elf_class )
678     {
679         std::ios_base::fmtflags original_flags = out.flags();
680 
681         if ( elf_class == ELFCLASS32 ) { // Output for 32-bit
682             out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] "
683                 << DUMP_HEX_FORMAT( 8 ) << value << " " << DUMP_HEX_FORMAT( 8 )
684                 << size << " " << DUMP_STR_FORMAT( 7 )
685                 << str_symbol_type( type ) << " " << DUMP_STR_FORMAT( 8 )
686                 << str_symbol_bind( bind ) << " " << DUMP_DEC_FORMAT( 5 )
687                 << section << " " << DUMP_STR_FORMAT( 1 ) << name << " "
688                 << std::endl;
689         }
690         else { // Output for 64-bit
691             out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] "
692                 << DUMP_HEX_FORMAT( 16 ) << value << " "
693                 << DUMP_HEX_FORMAT( 16 ) << size << " " << DUMP_STR_FORMAT( 7 )
694                 << str_symbol_type( type ) << " " << DUMP_STR_FORMAT( 8 )
695                 << str_symbol_bind( bind ) << " " << DUMP_DEC_FORMAT( 5 )
696                 << section << " " << std::endl
697                 << "        " << DUMP_STR_FORMAT( 1 ) << name << " "
698                 << std::endl;
699         }
700 
701         out.flags( original_flags );
702     }
703 
704     //------------------------------------------------------------------------------
notes(std::ostream & out,const elfio & reader)705     static void notes( std::ostream& out, const elfio& reader )
706     {
707         Elf_Half no = reader.sections.size();
708         for ( Elf_Half i = 0; i < no; ++i ) { // For all sections
709             section* sec = reader.sections[i];
710             if ( SHT_NOTE == sec->get_type() ) { // Look at notes
711                 note_section_accessor notes( reader, sec );
712                 Elf_Word              no_notes = notes.get_notes_num();
713                 if ( no > 0 ) {
714                     out << "Note section (" << sec->get_name() << ")"
715                         << std::endl
716                         << "    No Type     Name" << std::endl;
717                     for ( Elf_Word j = 0; j < no_notes; ++j ) { // For all notes
718                         Elf_Word    type;
719                         std::string name;
720                         void*       desc;
721                         Elf_Word    descsz;
722 
723                         if ( notes.get_note( j, type, name, desc, descsz ) ) {
724                             // 'name' usually contains \0 at the end. Try to fix it
725                             name = name.c_str();
726                             note( out, j, type, name );
727                         }
728                     }
729 
730                     out << std::endl;
731                 }
732             }
733         }
734     }
735 
736     //------------------------------------------------------------------------------
modinfo(std::ostream & out,const elfio & reader)737     static void modinfo( std::ostream& out, const elfio& reader )
738     {
739         Elf_Half no = reader.sections.size();
740         for ( Elf_Half i = 0; i < no; ++i ) { // For all sections
741             section* sec = reader.sections[i];
742             if ( ".modinfo" == sec->get_name() ) { // Look for the section
743                 out << "Section .modinfo" << std::endl;
744 
745                 const_modinfo_section_accessor modinfo( sec );
746                 for ( Elf_Word i = 0; i < modinfo.get_attribute_num(); i++ ) {
747                     std::string field;
748                     std::string value;
749                     if ( modinfo.get_attribute( i, field, value ) ) {
750                         out << "  " << std::setw( 20 ) << field
751                             << std::setw( 0 ) << " = " << value << std::endl;
752                     }
753                 }
754 
755                 out << std::endl;
756                 break;
757             }
758         }
759     }
760 
761     //------------------------------------------------------------------------------
762     static void
note(std::ostream & out,int no,Elf_Word type,const std::string & name)763     note( std::ostream& out, int no, Elf_Word type, const std::string& name )
764     {
765         out << "  [" << DUMP_DEC_FORMAT( 2 ) << no << "] "
766             << DUMP_HEX_FORMAT( 8 ) << type << " " << DUMP_STR_FORMAT( 1 )
767             << name << std::endl;
768     }
769 
770     //------------------------------------------------------------------------------
dynamic_tags(std::ostream & out,const elfio & reader)771     static void dynamic_tags( std::ostream& out, const elfio& reader )
772     {
773         Elf_Half n = reader.sections.size();
774         for ( Elf_Half i = 0; i < n; ++i ) { // For all sections
775             section* sec = reader.sections[i];
776             if ( SHT_DYNAMIC == sec->get_type() ) {
777                 dynamic_section_accessor dynamic( reader, sec );
778 
779                 Elf_Xword dyn_no = dynamic.get_entries_num();
780                 if ( dyn_no > 0 ) {
781                     out << "Dynamic section (" << sec->get_name() << ")"
782                         << std::endl;
783                     out << "[  Nr ] Tag              Name/Value" << std::endl;
784                     for ( Elf_Xword i = 0; i < dyn_no; ++i ) {
785                         Elf_Xword   tag   = 0;
786                         Elf_Xword   value = 0;
787                         std::string str;
788                         dynamic.get_entry( i, tag, value, str );
789                         dynamic_tag( out, i, tag, value, str,
790                                      reader.get_class() );
791                         if ( DT_NULL == tag ) {
792                             break;
793                         }
794                     }
795 
796                     out << std::endl;
797                 }
798             }
799         }
800     }
801 
802     //------------------------------------------------------------------------------
dynamic_tag(std::ostream & out,Elf_Xword no,Elf_Xword tag,Elf_Xword value,std::string str,unsigned int)803     static void dynamic_tag( std::ostream& out,
804                              Elf_Xword     no,
805                              Elf_Xword     tag,
806                              Elf_Xword     value,
807                              std::string   str,
808                              unsigned int /*elf_class*/ )
809     {
810         out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] "
811             << DUMP_STR_FORMAT( 16 ) << str_dynamic_tag( tag ) << " ";
812         if ( str.empty() ) {
813             out << DUMP_HEX_FORMAT( 16 ) << value << " ";
814         }
815         else {
816             out << DUMP_STR_FORMAT( 32 ) << str << " ";
817         }
818         out << std::endl;
819     }
820 
821     //------------------------------------------------------------------------------
section_data(std::ostream & out,const section * sec)822     static void section_data( std::ostream& out, const section* sec )
823     {
824         std::ios_base::fmtflags original_flags = out.flags();
825 
826         out << sec->get_name() << std::endl;
827         const char* pdata = sec->get_data();
828         if ( pdata ) {
829             ELFIO::Elf_Xword i;
830             for ( i = 0; i < std::min( sec->get_size(), MAX_DATA_ENTRIES );
831                   ++i ) {
832                 if ( i % 16 == 0 ) {
833                     out << "[" << DUMP_HEX_FORMAT( 8 ) << i << "]";
834                 }
835 
836                 out << " " << DUMP_HEX_FORMAT( 2 ) << ( pdata[i] & 0x000000FF );
837 
838                 if ( i % 16 == 15 ) {
839                     out << std::endl;
840                 }
841             }
842             if ( i % 16 != 0 ) {
843                 out << std::endl;
844             }
845 
846             out.flags( original_flags );
847         }
848 
849         return;
850     }
851 
852     //------------------------------------------------------------------------------
section_datas(std::ostream & out,const elfio & reader)853     static void section_datas( std::ostream& out, const elfio& reader )
854     {
855         Elf_Half n = reader.sections.size();
856 
857         if ( n == 0 ) {
858             return;
859         }
860 
861         out << "Section Data:" << std::endl;
862 
863         for ( Elf_Half i = 1; i < n; ++i ) { // For all sections
864             section* sec = reader.sections[i];
865             if ( sec->get_type() == SHT_NOBITS ) {
866                 continue;
867             }
868             section_data( out, sec );
869         }
870 
871         out << std::endl;
872     }
873 
874     //------------------------------------------------------------------------------
875     static void
segment_data(std::ostream & out,Elf_Half no,const segment * seg)876     segment_data( std::ostream& out, Elf_Half no, const segment* seg )
877     {
878         std::ios_base::fmtflags original_flags = out.flags();
879 
880         out << "Segment # " << no << std::endl;
881         const char* pdata = seg->get_data();
882         if ( pdata ) {
883             ELFIO::Elf_Xword i;
884             for ( i = 0; i < std::min( seg->get_file_size(), MAX_DATA_ENTRIES );
885                   ++i ) {
886                 if ( i % 16 == 0 ) {
887                     out << "[" << DUMP_HEX_FORMAT( 8 ) << i << "]";
888                 }
889 
890                 out << " " << DUMP_HEX_FORMAT( 2 ) << ( pdata[i] & 0x000000FF );
891 
892                 if ( i % 16 == 15 ) {
893                     out << std::endl;
894                 }
895             }
896             if ( i % 16 != 0 ) {
897                 out << std::endl;
898             }
899 
900             out.flags( original_flags );
901         }
902 
903         return;
904     }
905 
906     //------------------------------------------------------------------------------
segment_datas(std::ostream & out,const elfio & reader)907     static void segment_datas( std::ostream& out, const elfio& reader )
908     {
909         Elf_Half n = reader.segments.size();
910 
911         if ( n == 0 ) {
912             return;
913         }
914 
915         out << "Segment Data:" << std::endl;
916 
917         for ( Elf_Half i = 0; i < n; ++i ) { // For all sections
918             segment* seg = reader.segments[i];
919             segment_data( out, i, seg );
920         }
921 
922         out << std::endl;
923     }
924 
925   private:
926     //------------------------------------------------------------------------------
927     template <typename T, typename K>
find_value_in_table(const T & table,const K & key)928     std::string static find_value_in_table( const T& table, const K& key )
929     {
930         std::string res = "?";
931         for ( unsigned int i = 0; i < sizeof( table ) / sizeof( table[0] );
932               ++i ) {
933             if ( table[i].key == key ) {
934                 res = table[i].str;
935                 break;
936             }
937         }
938 
939         return res;
940     }
941 
942     //------------------------------------------------------------------------------
943     template <typename T, typename K>
format_assoc(const T & table,const K & key)944     static std::string format_assoc( const T& table, const K& key )
945     {
946         std::string str = find_value_in_table( table, key );
947         if ( str == "?" ) {
948             std::ostringstream oss;
949             oss << str << " (0x" << std::hex << key << ")";
950             str = oss.str();
951         }
952 
953         return str;
954     }
955 
956     //------------------------------------------------------------------------------
957     template <typename T>
format_assoc(const T & table,const char key)958     static std::string format_assoc( const T& table, const char key )
959     {
960         return format_assoc( table, (const int)key );
961     }
962 
963     //------------------------------------------------------------------------------
section_flags(Elf_Xword flags)964     static std::string section_flags( Elf_Xword flags )
965     {
966         std::string ret = "";
967         if ( flags & SHF_WRITE ) {
968             ret += "W";
969         }
970         if ( flags & SHF_ALLOC ) {
971             ret += "A";
972         }
973         if ( flags & SHF_EXECINSTR ) {
974             ret += "X";
975         }
976 
977         return ret;
978     }
979 
980 //------------------------------------------------------------------------------
981 #define STR_FUNC_TABLE( name )                                         \
982     template <typename T> static std::string str_##name( const T key ) \
983     {                                                                  \
984         return format_assoc( name##_table, key );                      \
985     }
986 
987     STR_FUNC_TABLE( class )
988     STR_FUNC_TABLE( endian )
989     STR_FUNC_TABLE( version )
990     STR_FUNC_TABLE( type )
991     STR_FUNC_TABLE( machine )
992     STR_FUNC_TABLE( section_type )
993     STR_FUNC_TABLE( segment_type )
994     STR_FUNC_TABLE( segment_flag )
995     STR_FUNC_TABLE( symbol_bind )
996     STR_FUNC_TABLE( symbol_type )
997     STR_FUNC_TABLE( dynamic_tag )
998 
999 #undef STR_FUNC_TABLE
1000 #undef DUMP_DEC_FORMAT
1001 #undef DUMP_HEX_FORMAT
1002 #undef DUMP_STR_FORMAT
1003 }; // class dump
1004 
1005 }; // namespace ELFIO
1006 
1007 #endif // ELFIO_DUMP_HPP
1008