1 /* file-elf.c
2  * Routines for Executable and Linkable Format
3  * Based on: SYSTEM V APPLICATION BINARY INTERFACE Edition 4.1
4  * https://www.sco.com/developers/devspecs/
5  * https://www.sco.com/developers/gabi/latest/contents.html
6  * https://refspecs.linuxfoundation.org/
7  * https://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
8  * http://dwarfstd.org/doc/DWARF4.pdf
9  *
10  * Copyright 2013, Michal Labedzki for Tieto Corporation
11  * Copyright (C) 2019 Peter Wu <peter@lekensteyn.nl>
12  *
13  * Wireshark - Network traffic analyzer
14  * By Gerald Combs <gerald@wireshark.org>
15  * Copyright 1998 Gerald Combs
16  *
17  * SPDX-License-Identifier: GPL-2.0-or-later
18  */
19 
20 #include "config.h"
21 
22 #include <epan/packet.h>
23 #include <epan/prefs.h>
24 #include <epan/expert.h>
25 
26 static dissector_handle_t elf_handle;
27 
28 static int proto_elf = -1;
29 
30 static int hf_elf_magic_bytes = -1;
31 static int hf_elf_file_size = -1;
32 static int hf_elf_header_segment_size = -1;
33 static int hf_elf_blackholes_size = -1;
34 static int hf_elf_blackhole_size = -1;
35 static int hf_elf_overlapping_size = -1;
36 static int hf_elf_segment = -1;
37 static int hf_elf_entry_bytes = -1;
38 static int hf_elf_file_class = -1;
39 static int hf_elf_data_encoding = -1;
40 static int hf_elf_file_version = -1;
41 static int hf_elf_os_abi = -1;
42 static int hf_elf_abi_version = -1;
43 static int hf_elf_file_padding = -1;
44 static int hf_elf_type = -1;
45 static int hf_elf_machine = -1;
46 static int hf_elf_version = -1;
47 static int hf_elf_entry = -1;
48 static int hf_elf_phoff = -1;
49 static int hf_elf_shoff = -1;
50 static int hf_elf64_entry = -1;
51 static int hf_elf64_phoff = -1;
52 static int hf_elf64_shoff = -1;
53 static int hf_elf_flags = -1;
54 static int hf_elf_ehsize = -1;
55 static int hf_elf_phentsize = -1;
56 static int hf_elf_phnum = -1;
57 static int hf_elf_shentsize = -1;
58 static int hf_elf_shnum = -1;
59 static int hf_elf_shstrndx = -1;
60 static int hf_elf_p_type = -1;
61 static int hf_elf_p_type_operating_system_specific = -1;
62 static int hf_elf_p_type_processor_specific = -1;
63 static int hf_elf_p_flags_execute = -1;
64 static int hf_elf_p_flags_write = -1;
65 static int hf_elf_p_flags_read = -1;
66 static int hf_elf_p_flags_reserved = -1;
67 static int hf_elf_p_flags_operating_system_specific = -1;
68 static int hf_elf_p_flags_processor_specific = -1;
69 static int hf_elf_p_offset = -1;
70 static int hf_elf64_p_offset = -1;
71 static int hf_elf_p_vaddr = -1;
72 static int hf_elf64_p_vaddr = -1;
73 static int hf_elf_p_paddr = -1;
74 static int hf_elf64_p_paddr = -1;
75 static int hf_elf_p_filesz = -1;
76 static int hf_elf64_p_filesz = -1;
77 static int hf_elf_p_memsz = -1;
78 static int hf_elf64_p_memsz = -1;
79 static int hf_elf_p_align = -1;
80 static int hf_elf64_p_align = -1;
81 
82 static int hf_elf_sh_name = -1;
83 static int hf_elf_sh_type_user_specific = -1;
84 static int hf_elf_sh_type_operating_system_specific = -1;
85 static int hf_elf_sh_type_processor_specific = -1;
86 static int hf_elf_sh_type = -1;
87 
88 static int hf_elf_sh_flags_processor_specific = -1;
89 static int hf_elf_sh_flags_operating_system_specific = -1;
90 static int hf_elf_sh_flags_reserved = -1;
91 static int hf_elf_sh_flags_tls = -1;
92 static int hf_elf_sh_flags_group = -1;
93 static int hf_elf_sh_flags_os_nonconforming = -1;
94 static int hf_elf_sh_flags_link_order = -1;
95 static int hf_elf_sh_flags_info_link = -1;
96 static int hf_elf_sh_flags_strings = -1;
97 static int hf_elf_sh_flags_merge = -1;
98 static int hf_elf_sh_flags_reserved_8 = -1;
99 static int hf_elf_sh_flags_exec_instr = -1;
100 static int hf_elf_sh_flags_alloc = -1;
101 static int hf_elf_sh_flags_write = -1;
102 static int hf_elf_sh_addr = -1;
103 static int hf_elf64_sh_addr = -1;
104 
105 static int hf_elf_sh_offset = -1;
106 static int hf_elf64_sh_offset = -1;
107 static int hf_elf_sh_size = -1;
108 static int hf_elf64_sh_size = -1;
109 static int hf_elf_sh_link = -1;
110 static int hf_elf_sh_info = -1;
111 static int hf_elf_sh_addralign = -1;
112 static int hf_elf64_sh_addralign = -1;
113 static int hf_elf_sh_entsize = -1;
114 static int hf_elf64_sh_entsize = -1;
115 
116 static int hf_elf_eh_frame_length = -1;
117 static int hf_elf_eh_frame_extended_length = -1;
118 static int hf_elf_eh_frame_cie_id = -1;
119 static int hf_elf_eh_frame_version = -1;
120 static int hf_elf_eh_frame_augmentation_string = -1;
121 static int hf_elf_eh_frame_code_alignment_factor = -1;
122 static int hf_elf_eh_frame_data_alignment_factor = -1;
123 static int hf_elf_eh_frame_return_address_register = -1;
124 static int hf_elf_eh_frame_augmentation_length = -1;
125 static int hf_elf_eh_frame_augmentation_data = -1;
126 static int hf_elf_eh_frame_initial_instructions = -1;
127 
128 static int hf_elf_eh_frame_fde_length = -1;
129 static int hf_elf_eh_frame_fde_extended_length = -1;
130 static int hf_elf_eh_frame_fde_cie_pointer = -1;
131 static int hf_elf_eh_frame_fde_pc_begin = -1;
132 static int hf_elf_eh_frame_fde_pc_range = -1;
133 static int hf_elf_eh_frame_fde_augmentation_length = -1;
134 static int hf_elf_eh_frame_fde_augmentation_data = -1;
135 static int hf_elf_eh_frame_fde_call_frame_instructions = -1;
136 
137 static int hf_elf_eh_frame_hdr_version = -1;
138 static int hf_elf_eh_frame_hdr_exception_frame_pointer_encoding = -1;
139 static int hf_elf_eh_frame_hdr_fde_count_encoding = -1;
140 static int hf_elf_eh_frame_hdr_binary_search_table_encoding = -1;
141 static int hf_elf_eh_frame_hdr_eh_frame_ptr = -1;
142 static int hf_elf_eh_frame_hdr_fde_count = -1;
143 static int hf_elf_eh_frame_hdr_binary_search_table_entry_initial_location = -1;
144 static int hf_elf_eh_frame_hdr_binary_search_table_entry_address = -1;
145 
146 static int hf_elf_symbol_table_name_index = -1;
147 static int hf_elf_symbol_table_value = -1;
148 static int hf_elf64_symbol_table_value = -1;
149 static int hf_elf_symbol_table_size = -1;
150 static int hf_elf64_symbol_table_size = -1;
151 static int hf_elf_symbol_table_info = -1;
152 static int hf_elf_symbol_table_info_bind = -1;
153 static int hf_elf_symbol_table_info_type = -1;
154 static int hf_elf_symbol_table_other = -1;
155 static int hf_elf_symbol_table_shndx = -1;
156 
157 static int hf_elf_dynamic_tag = -1;
158 static int hf_elf_dynamic_value = -1;
159 static int hf_elf_dynamic_pointer = -1;
160 static int hf_elf_dynamic_ignored = -1;
161 static int hf_elf_dynamic_unspecified = -1;
162 static int hf_elf64_dynamic_tag = -1;
163 static int hf_elf64_dynamic_value = -1;
164 static int hf_elf64_dynamic_pointer = -1;
165 static int hf_elf64_dynamic_ignored = -1;
166 static int hf_elf64_dynamic_unspecified = -1;
167 
168 static int hf_elf_string = -1;
169 
170 static int hf_dwarf_omit = -1;
171 static int hf_dwarf_upper = -1;
172 static int hf_dwarf_format = -1;
173 
174 static expert_field ei_invalid_segment_size                           = EI_INIT;
175 static expert_field ei_invalid_entry_size                             = EI_INIT;
176 static expert_field ei_cfi_extraneous_data                            = EI_INIT;
177 static expert_field ei_invalid_cie_length                             = EI_INIT;
178 
179 static gint ett_elf = -1;
180 static gint ett_elf_header = -1;
181 static gint ett_elf_program_header = -1;
182 static gint ett_elf_program_header_entry = -1;
183 static gint ett_elf_section_header = -1;
184 static gint ett_elf_section_header_entry = -1;
185 static gint ett_elf_segment = -1;
186 static gint ett_elf_cfi_record = -1;
187 static gint ett_elf_cie_entry = -1;
188 static gint ett_elf_fde_entry = -1;
189 static gint ett_elf_cie_terminator = -1;
190 static gint ett_elf_info = -1;
191 static gint ett_elf_black_holes = -1;
192 static gint ett_elf_overlapping = -1;
193 static gint ett_dwarf_encoding = -1;
194 static gint ett_binary_table = -1;
195 static gint ett_binary_table_entry = -1;
196 static gint ett_symbol_table_entry = -1;
197 static gint ett_symbol_table_info = -1;
198 
199 #define REGISTER_32_SIZE  4
200 #define REGISTER_64_SIZE  8
201 
202 static const value_string class_vals[] = {
203     { 0x00,  "Invalid class" },
204     { 0x01,  "32-bit object" },
205     { 0x02,  "64-bit object" },
206     { 0, NULL }
207 };
208 
209 static const value_string data_encoding_vals[] = {
210     { 0x00,  "None" },
211     { 0x01,  "Least Significant Bit" },
212     { 0x02,  "Most Significant Bit " },
213     { 0, NULL }
214 };
215 
216 static const value_string version_vals[] = {
217     { 0x00,  "None" },
218     { 0x01,  "Current" },
219     { 0, NULL }
220 };
221 
222 static const value_string type_vals[] = {
223     { 0x0000,  "No file type" },
224     { 0x0001,  "Relocatable file" },
225     { 0x0002,  "Executable file" },
226     { 0x0003,  "Shared object file" },
227     { 0x0004,  "Core file" },
228     { 0xFE00,  "Operating system-specific Lo" }, /* From Draft */
229     { 0xFEFF,  "Operating system-specific Hi" }, /* From Draft */
230     { 0xFF00,  "Processor Specific Lo" },
231     { 0xFFFF,  "Processor Specific Hi" },
232     { 0, NULL }
233 };
234 
235 /* From https://www.sco.com/developers/gabi/latest/ch4.eheader.html */
236 static const value_string machine_vals[] = {
237     {   0,  "No machine" },
238     {   1,  "AT&T WE 32100" },
239     {   2,  "SPARC" },
240     {   3,  "Intel 80386" },
241     {   4,  "Motorola 68000" },
242     {   5,  "Motorola 88000" },
243     {   6,  "Intel MCU" },
244     {   7,  "Intel 80860" },
245     {   8,  "MIPS I Architecture" },
246     {   9,  "IBM System/370 Processor" },
247     {  10,  "MIPS RS3000 Little-endian" },
248     {  15,  "Hewlett-Packard PA-RISC" },
249     {  17,  "Fujitsu VPP500" },
250     {  18,  "Enhanced instruction set SPARC" },
251     {  19,  "Intel 80960" },
252     {  20,  "PowerPC" },
253     {  21,  "64-bit PowerPC" },
254     {  22,  "IBM System/390 Processor" },
255     {  23,  "IBM SPU/SPC" },
256     {  36,  "NEC V800" },
257     {  37,  "Fujitsu FR20" },
258     {  38,  "TRW RH-32" },
259     {  39,  "Motorola RCE" },
260     {  40,  "ARM 32-bit architecture (AARCH32)" },
261     {  41,  "Digital Alpha" },
262     {  42,  "Hitachi SH" },
263     {  43,  "SPARC Version 9" },
264     {  44,  "Siemens TriCore embedded processor" },
265     {  45,  "Argonaut RISC Core, Argonaut Technologies Inc." },
266     {  46,  "Hitachi H8/300" },
267     {  47,  "Hitachi H8/300H" },
268     {  48,  "Hitachi H8S" },
269     {  49,  "Hitachi H8/500" },
270     {  50,  "Intel IA-64 processor architecture" },
271     {  51,  "Stanford MIPS-X" },
272     {  52,  "Motorola ColdFire" },
273     {  53,  "Motorola M68HC12" },
274     {  54,  "Fujitsu MMA Multimedia Accelerator" },
275     {  55,  "Siemens PCP" },
276     {  56,  "Sony nCPU embedded RISC processor" },
277     {  57,  "Denso NDR1 microprocessor" },
278     {  58,  "Motorola Star*Core processor" },
279     {  59,  "Toyota ME16 processor" },
280     {  60,  "STMicroelectronics ST100 processor" },
281     {  61,  "Advanced Logic Corp. TinyJ embedded processor family" },
282     {  62,  "AMD x86-64 architecture" },
283     {  63,  "Sony DSP Processor" },
284     {  64,  "Digital Equipment Corp. PDP-10" },
285     {  65,  "Digital Equipment Corp. PDP-11" },
286     {  66,  "Siemens FX66 microcontroller" },
287     {  67,  "STMicroelectronics ST9+ 8/16 bit microcontroller" },
288     {  68,  "STMicroelectronics ST7 8-bit microcontroller" },
289     {  69,  "Motorola MC68HC16 Microcontroller" },
290     {  70,  "Motorola MC68HC11 Microcontroller" },
291     {  71,  "Motorola MC68HC08 Microcontroller" },
292     {  72,  "Motorola MC68HC05 Microcontroller" },
293     {  73,  "Silicon Graphics SVx" },
294     {  74,  "STMicroelectronics ST19 8-bit microcontroller" },
295     {  75,  "Digital VAX" },
296     {  76,  "Axis Communications 32-bit embedded processor" },
297     {  77,  "Infineon Technologies 32-bit embedded processor" },
298     {  78,  "Element 14 64-bit DSP Processor" },
299     {  79,  "LSI Logic 16-bit DSP Processor" },
300     {  80,  "Donald Knuth's educational 64-bit processor" },
301     {  81,  "Harvard University machine-independent object files" },
302     {  82,  "SiTera Prism" },
303     {  83,  "Atmel AVR 8-bit microcontroller" },
304     {  84,  "Fujitsu FR30" },
305     {  85,  "Mitsubishi D10V" },
306     {  86,  "Mitsubishi D30V" },
307     {  87,  "NEC v850" },
308     {  88,  "Mitsubishi M32R" },
309     {  89,  "Matsushita MN10300" },
310     {  90,  "Matsushita MN10200" },
311     {  91,  "picoJava" },
312     {  92,  "OpenRISC 32-bit embedded processor" },
313     {  93,  "ARC International ARCompact processor (old spelling/synonym: EM_ARC_A5)" },
314     {  94,  "Tensilica Xtensa Architecture" },
315     {  95,  "Alphamosaic VideoCore processor" },
316     {  96,  "Thompson Multimedia General Purpose Processor" },
317     {  97,  "National Semiconductor 32000 series" },
318     {  98,  "Tenor Network TPC processor" },
319     {  99,  "Trebia SNP 1000 processor" },
320     { 100,  "STMicroelectronics (www.st.com) ST200 microcontroller" },
321     { 101,  "Ubicom IP2xxx microcontroller family" },
322     { 102,  "MAX Processor" },
323     { 103,  "National Semiconductor CompactRISC microprocessor" },
324     { 104,  "Fujitsu F2MC16" },
325     { 105,  "Texas Instruments embedded microcontroller msp430" },
326     { 106,  "Analog Devices Blackfin (DSP) processor" },
327     { 107,  "S1C33 Family of Seiko Epson processors" },
328     { 108,  "Sharp embedded microprocessor" },
329     { 109,  "Arca RISC Microprocessor" },
330     { 110,  "Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University" },
331     { 111,  "eXcess: 16/32/64-bit configurable embedded CPU" },
332     { 112,  "Icera Semiconductor Inc. Deep Execution Processor" },
333     { 113,  "Altera Nios II soft-core processor" },
334     { 114,  "National Semiconductor CompactRISC CRX microprocessor" },
335     { 115,  "Motorola XGATE embedded processor" },
336     { 116,  "Infineon C16x/XC16x processor" },
337     { 117,  "Renesas M16C series microprocessors" },
338     { 118,  "Microchip Technology dsPIC30F Digital Signal Controller" },
339     { 119,  "Freescale Communication Engine RISC core" },
340     { 120,  "Renesas M32C series microprocessors" },
341     { 131,  "Altium TSK3000 core" },
342     { 132,  "Freescale RS08 embedded processor" },
343     { 133,  "Analog Devices SHARC family of 32-bit DSP processors" },
344     { 134,  "Cyan Technology eCOG2 microprocessor" },
345     { 135,  "Sunplus S+core7 RISC processor" },
346     { 136,  "New Japan Radio (NJR) 24-bit DSP Processor" },
347     { 137,  "Broadcom VideoCore III processor" },
348     { 138,  "RISC processor for Lattice FPGA architecture" },
349     { 139,  "Seiko Epson C17 family" },
350     { 140,  "The Texas Instruments TMS320C6000 DSP family" },
351     { 141,  "The Texas Instruments TMS320C2000 DSP family" },
352     { 142,  "The Texas Instruments TMS320C55x DSP family" },
353     { 143,  "Texas Instruments Application Specific RISC Processor, 32bit fetch" },
354     { 144,  "Texas Instruments Programmable Realtime Unit" },
355     { 160,  "STMicroelectronics 64bit VLIW Data Signal Processor" },
356     { 161,  "Cypress M8C microprocessor" },
357     { 162,  "Renesas R32C series microprocessors" },
358     { 163,  "NXP Semiconductors TriMedia architecture family" },
359     { 164,  "QUALCOMM DSP6 Processor" },
360     { 165,  "Intel 8051 and variants" },
361     { 166,  "STMicroelectronics STxP7x family of configurable and extensible RISC processors" },
362     { 167,  "Andes Technology compact code size embedded RISC processor family" },
363     { 168,  "Cyan Technology eCOG1X family" },
364     { 168,  "Cyan Technology eCOG1X family" },
365     { 169,  "Dallas Semiconductor MAXQ30 Core Micro-controllers" },
366     { 170,  "New Japan Radio (NJR) 16-bit DSP Processor" },
367     { 171,  "M2000 Reconfigurable RISC Microprocessor" },
368     { 172,  "Cray Inc. NV2 vector architecture" },
369     { 173,  "Renesas RX family" },
370     { 174,  "Imagination Technologies META processor architecture" },
371     { 175,  "MCST Elbrus general purpose hardware architecture" },
372     { 176,  "Cyan Technology eCOG16 family" },
373     { 177,  "National Semiconductor CompactRISC CR16 16-bit microprocessor" },
374     { 178,  "Freescale Extended Time Processing Unit" },
375     { 179,  "Infineon Technologies SLE9X core" },
376     { 180,  "Intel L10M" },
377     { 181,  "Intel K10M" },
378     { 182,  "Reserved for future Intel use" },
379     { 183,  "ARM 64-bit architecture (AARCH64)" },
380     { 184,  "Reserved for future ARM use" },
381     { 185,  "Atmel Corporation 32-bit microprocessor family" },
382     { 186,  "STMicroeletronics STM8 8-bit microcontroller" },
383     { 187,  "Tilera TILE64 multicore architecture family" },
384     { 188,  "Tilera TILEPro multicore architecture family" },
385     { 189,  "Xilinx MicroBlaze 32-bit RISC soft processor core" },
386     { 190,  "NVIDIA CUDA architecture" },
387     { 191,  "Tilera TILE-Gx multicore architecture family" },
388     { 192,  "CloudShield architecture family" },
389     { 193,  "KIPO-KAIST Core-A 1st generation processor family" },
390     { 194,  "KIPO-KAIST Core-A 2nd generation processor family" },
391     { 195,  "Synopsys ARCompact V2" },
392     { 196,  "Open8 8-bit RISC soft processor core" },
393     { 197,  "Renesas RL78 family" },
394     { 198,  "Broadcom VideoCore V processor" },
395     { 199,  "Renesas 78KOR family" },
396     { 200,  "Freescale 56800EX Digital Signal Controller (DSC)" },
397     { 201,  "Beyond BA1 CPU architecture" },
398     { 202,  "Beyond BA2 CPU architecture" },
399     { 203,  "XMOS xCORE processor family" },
400     { 204,  "Microchip 8-bit PIC(r) family" },
401     { 205,  "Reserved by Intel" },
402     { 206,  "Reserved by Intel" },
403     { 207,  "Reserved by Intel" },
404     { 208,  "Reserved by Intel" },
405     { 209,  "Reserved by Intel" },
406     { 210,  "KM211 KM32 32-bit processor" },
407     { 211,  "KM211 KMX32 32-bit processor" },
408     { 212,  "KM211 KMX16 16-bit processor" },
409     { 213,  "KM211 KMX8 8-bit processor" },
410     { 214,  "KM211 KVARC processor" },
411     { 215,  "Paneve CDP architecture family" },
412     { 216,  "Cognitive Smart Memory Processor" },
413     { 217,  "Bluechip Systems CoolEngine" },
414     { 218,  "Nanoradio Optimized RISC" },
415     { 219,  "CSR Kalimba architecture family" },
416     { 220,  "Zilog Z80" },
417     { 221,  "Controls and Data Services VISIUMcore processor" },
418     { 222,  "FTDI Chip FT32 high performance 32-bit RISC architecture" },
419     { 223,  "Moxie processor family" },
420     { 224,  "AMD GPU architecture" },
421     { 243,  "RISC-V" },
422     { 247,  "Linux kernel bpf virtual machine" }, /* From LLVM / glibc 2.24 */
423     { 252,  "C-SKY" },  /* from glibc 2.30 elf/elf.h commit 5fbcd76351ee */
424     { 0, NULL }
425 };
426 static value_string_ext machine_vals_ext = VALUE_STRING_EXT_INIT(machine_vals);
427 
428 /* From Draft */
429 static const value_string os_abi_vals[] = {
430     { 0x00,  "No extensions or unspecified" },
431     { 0x01,  "Hewlett-Packard HP-UX" },
432     { 0x02,  "NetBSD" },
433     { 0x03,  "GNU (historical alias: Linux)" },
434     { 0x06,  "Sun Solaris" },
435     { 0x07,  "AIX" },
436     { 0x08,  "IRIX" },
437     { 0x09,  "FreeBSD" },
438     { 0x0A,  "Compaq TRU64 UNIX" },
439     { 0x0B,  "Novell Modesto" },
440     { 0x0C,  "Open BSD" },
441     { 0x0D,  "Open VMS" },
442     { 0x0E,  "Hewlett-Packard Non-Stop Kernel" },
443     { 0x0F,  "Amiga Research OS" },
444     { 0x10,  "The FenixOS highly scalable multi-core OS" },
445     { 0, NULL }
446 };
447 static value_string_ext os_abi_vals_ext = VALUE_STRING_EXT_INIT(os_abi_vals);
448 
449 static const value_string p_type_vals[] = {
450     { 0,  "PT_NULL" },
451     { 1,  "PT_LOAD" },
452     { 2,  "PT_DYNAMIC" },
453     { 3,  "PT_INTERP" },
454     { 4,  "PT_NOTE" },
455     { 5,  "PT_SHLIB" },
456     { 6,  "PT_PHDR" },
457     { 7,  "PT_TLS" },
458     { 0, NULL }
459 };
460 
461 static const value_string sh_type_vals[] = {
462     {  0,  "SHT_NULL" },
463     {  1,  "SHT_PROGBITS" },
464     {  2,  "SHT_SYMTAB" },
465     {  3,  "SHT_STRTAB" },
466     {  4,  "SHT_RELA" },
467     {  5,  "SHT_HASH" },
468     {  6,  "SHT_DYNAMIC" },
469     {  7,  "SHT_NOTE" },
470     {  8,  "SHT_NOBITS" },
471     {  9,  "SHT_REL" },
472     { 10,  "SHT_SHLIB" },
473     { 11,  "SHT_DYNSYM" },
474     { 14,  "SHT_INIT_ARRAY" },
475     { 15,  "SHT_FINI_ARRAY" },
476     { 16,  "SHT_PREINIT_ARRAY" },
477     { 17,  "SHT_GROUP" },
478     { 18,  "SHT_SYMTAB_SHNDX" },
479     /* TODO: https://www.sco.com/developers/gabi/latest/ch4.sheader.html range_string? */
480     { 0, NULL }
481 };
482 static value_string_ext sh_type_vals_ext = VALUE_STRING_EXT_INIT(sh_type_vals);
483 
484 static const value_string eh_dwarf_upper[] = {
485     { 0x0,  "Normal Value"  },
486     { 0x1,  "Value is relative to the current program counter. (DW_EH_PE_pcrel)" },
487     { 0x2,  "Value is relative to the beginning of the .text section. (DW_EH_PE_textrel)" },
488     { 0x3,  "Value is relative to the beginning of the .got or .eh_frame_hdr section. (DW_EH_PE_datarel)" },
489     { 0x4,  "Value is relative to the beginning of the function. (DW_EH_PE_funcrel)" },
490     { 0x5,  "Value is aligned to an address unit sized boundary. (DW_EH_PE_aligned)" },
491     { 0, NULL }
492 };
493 
494 static const value_string eh_dwarf_format[] = {
495     { 0x0,  "The Value is a literal pointer whose size is determined by the architecture. (DW_EH_PE_absptr)" },
496     { 0x1,  "Unsigned value is encoded using the Little Endian Base 128 (LEB128). (DW_EH_PE_uleb128)" },
497     { 0x2,  "A 2 bytes unsigned value. (DW_EH_PE_udata2)" },
498     { 0x3,  "A 4 bytes unsigned value. (DW_EH_PE_udata4)" },
499     { 0x4,  "An 8 bytes unsigned value. (DW_EH_PE_udata8)" },
500     { 0x9,  "Signed value is encoded using the Little Endian Base 128 (LEB128). (DW_EH_PE_sleb128)" },
501     { 0xA,  "A 2 bytes signed value. (DW_EH_PE_sdata2)" },
502     { 0xB,  "A 4 bytes signed value. (DW_EH_PE_sdata4)" },
503     { 0xC,  "An 8 bytes signed value. (DW_EH_PE_sdata8)" },
504     { 0, NULL }
505 };
506 
507 static const value_string symbol_table_other_vals[] = {
508     { 0,   "Default" },
509     { 1,   "Internal" },
510     { 2,   "Hidden" },
511     { 3,   "Protected" },
512     { 0, NULL }
513 };
514 
515 
516 static const value_string symbol_table_info_bind_vals[] = {
517     {  0,   "Local" },
518     {  1,   "Global" },
519     {  2,   "Weak" },
520     { 10,   "Operating System Specific" },
521     { 11,   "Operating System Specific" },
522     { 12,   "Operating System Specific" },
523     { 13,   "Processor Specific" },
524     { 14,   "Processor Specific" },
525     { 15,   "Processor Specific" },
526     { 0, NULL }
527 };
528 
529 static const value_string symbol_table_info_type_vals[] = {
530     {  0,   "No Type" },
531     {  1,   "Object" },
532     {  2,   "Function" },
533     {  3,   "Section" },
534     {  4,   "File" },
535     {  5,   "Common" },
536     {  6,   "Thread-Local Storage" },
537     { 10,   "Operating System Specific" },
538     { 11,   "Operating System Specific" },
539     { 12,   "Operating System Specific" },
540     { 13,   "Processor Specific" },
541     { 14,   "Processor Specific" },
542     { 15,   "Processor Specific" },
543     { 0, NULL }
544 };
545 static value_string_ext symbol_table_info_type_vals_ext = VALUE_STRING_EXT_INIT(symbol_table_info_type_vals);
546 
547 static const range_string symbol_table_shndx_rvals[] = {
548     { 0x0000, 0x0000,  "Undefined" },
549     { 0x0001, 0xfeff,  "Normal Section" },
550     { 0xff00, 0xff1f,  "Processor Specific" },
551     { 0xff20, 0xff3f,  "Operating System Specific" },
552     { 0xff40, 0xfff0,  "Reserved" },
553     { 0xfff1, 0xfff1,  "Absolute Value" },
554     { 0xfff2, 0xfff2,  "Common" },
555     { 0xfff3, 0xfffe,  "Reserved" },
556     { 0xffff, 0xffff,  "Xindex" },
557     { 0, 0, NULL }
558 };
559 
560 static const range_string dynamic_tag_rvals[] = {
561     {  0,  0,   "NULL" },
562     {  1,  1,   "Needed" },
563     {  2,  2,   "Procedure Linkage Table Size" },
564     {  3,  3,   "Procedure Linkage Table and/or the Global Offset Table Address" },
565     {  4,  4,   "Hash" },
566 
567     {  5,  5,   "String Table Address" },
568     {  6,  6,   "Symbol Table Address" },
569     {  7,  7,   "Relocation Table Address" },
570     {  8,  8,   "Relocation Table Size" },
571     {  9,  9,   "Relocation Table Entry Size" },
572     { 10, 10,   "String Table Size" },
573     { 11, 11,   "Symbol Table Entry Size" },
574     { 12, 12,   "Initialization Function Address" },
575     { 13, 13,   "Termination Function Address" },
576     { 14, 14,   "Shared Object Name Offset" },
577     { 15, 15,   "Search Library Path (Rpath)" },
578     { 16, 16,   "Symbolic" },
579     { 17, 17,   "Relocation Table with Implicit Addends" },
580     { 18, 18,   "Relocation Table with Implicit Addends Size" },
581     { 19, 19,   "Relocation Table with Implicit Addends Entry Size" },
582     { 20, 20,   "Procedure Linkage Table Relocation Entry Type" },
583     { 21, 21,   "Debug" },
584     { 22, 22,   "TEXT Relocation" },
585     { 23, 23,   "Procedure Linkage Table Relocation Entries Address" },
586     { 24, 24,   "Bind Now" },
587     { 25, 25,   "Initialization Functions Array Address" },
588     { 26, 26,   "Termination Functions Array Address" },
589     { 27, 27,   "Initialization Functions Array Size" },
590     { 28, 28,   "Termination Functions Array Size" },
591     { 29, 29,   "Run Path" },
592     { 30, 30,   "Flags" },
593     { 31, 31,   "Preinitialization Functions Array Address" },
594     { 32, 32,   "Preinitialization Functions Array Size" },
595     { 33, 33,   "Encoding" },
596 
597     { 0x6000000D, 0x6ffff000,   "Operating System Specific" },
598     { 0x70000000, 0x7fffffff,   "Processor Specific" },
599     { 0, 0, NULL }
600 };
601 
602 
603 typedef struct _segment_info_t {
604     guint64        offset;
605     guint64        size;
606     const char  *name;
607 } segment_info_t;
608 
609 void proto_register_elf(void);
610 void proto_reg_handoff_elf(void);
611 
612 static gint
dissect_leb128(tvbuff_t * tvb,gint offset,gint64 * value)613 dissect_leb128(tvbuff_t *tvb, gint offset, gint64 *value)
614 {
615     guint  start_offset = offset;
616     guint  shift = 0;
617     guint8 byte;
618 
619     *value = 0;
620 
621     do {
622         byte = tvb_get_guint8(tvb, offset);
623         offset += 1;
624 
625         *value |= ((guint64)(byte & 0x7F) << shift);
626         shift += 7;
627     } while ((byte & 0x80) && (shift < 64));
628 
629     if (shift < 64 && byte & 0x40)
630         *value |= - ((gint64)1 << shift);
631 
632     return offset - start_offset;
633 }
634 
635 /* Wireshark support "offset" as gint, but ELF needed guint64 size, so check if there is no overflow */
636 static gint
value_guard(guint64 value)637 value_guard(guint64 value)
638 {
639     DISSECTOR_ASSERT_HINT(value <= G_MAXINT, "Too big file - not supported");
640 
641     return (gint) value;
642 }
643 
644 static guint8
dissect_dwarf_encoding(tvbuff_t * tvb,gint offset,proto_item * item)645 dissect_dwarf_encoding(tvbuff_t *tvb, gint offset, proto_item *item)
646 {
647     guint8      value;
648     proto_tree *tree;
649 
650     tree = proto_item_add_subtree(item, ett_dwarf_encoding);
651 
652     value = tvb_get_guint8(tvb, offset);
653 
654     if (value == 0xFF) {
655         proto_tree_add_item(tree, hf_dwarf_omit,   tvb, offset, 1, ENC_NA);
656     } else {
657         proto_tree_add_item(tree, hf_dwarf_upper,  tvb, offset, 1, ENC_NA);
658         proto_tree_add_item(tree, hf_dwarf_format, tvb, offset, 1, ENC_NA);
659     }
660 
661     return value;
662 }
663 
664 #define LENGTH_LEB128   -1
665 #define LENGTH_ULEB128  -2
666 
667 static gint8
get_dwarf_extension_length(guint8 format,guint register_size)668 get_dwarf_extension_length(guint8 format, guint register_size)
669 {
670     switch (format & 0x0F) {
671     case 0x0:
672         return register_size;
673     case 0x1:
674         return LENGTH_ULEB128;
675     case 0x2:
676         return 2;
677     case 0x3:
678         return 4;
679     case 0x4:
680         return 8;
681     case 0x9:
682         return LENGTH_LEB128;
683     case 0xA:
684         return 2;
685     case 0xB:
686         return 4;
687     case 0xC:
688         return 8;
689     }
690 
691     return 0;
692 }
693 
694 static const guint8 *
get_section_name_offset(tvbuff_t * tvb,guint64 shoff,guint16 shnum,guint16 shentsize,guint16 shndx,guint64 shstrtab_offset,guint machine_encoding)695 get_section_name_offset(tvbuff_t *tvb, guint64 shoff, guint16 shnum, guint16 shentsize, guint16 shndx, guint64 shstrtab_offset, guint machine_encoding)
696 {
697     gint     offset;
698     guint32  sh_name;
699 
700     if (shndx > shnum)
701         return NULL;
702 
703     offset = value_guard(shoff + (guint32)shndx * (guint32)shentsize);
704     sh_name = (machine_encoding == ENC_BIG_ENDIAN) ? tvb_get_ntohl(tvb, offset) : tvb_get_letohl(tvb, offset);
705     return tvb_get_const_stringz(tvb, value_guard(shstrtab_offset + sh_name), NULL);
706 }
707 
708 #define MAX_TAG_TO_TYPE 34
709 static gint
dissect_dynamic(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * entry_tree,proto_item * entry_item,gint offset,gint register_size,guint machine_encoding)710 dissect_dynamic(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *entry_tree, proto_item *entry_item,
711         gint offset, gint register_size, guint machine_encoding)
712 {
713     enum enum_tag_type {
714         DYNAMIC_TYPE_VALUE,
715         DYNAMIC_TYPE_POINTER,
716         DYNAMIC_TYPE_IGNORED,
717         DYNAMIC_TYPE_UNSPECIFIED
718     };
719 
720     guint64                          tag;
721     static const enum enum_tag_type  tag_to_type[MAX_TAG_TO_TYPE] = {
722         DYNAMIC_TYPE_IGNORED,
723         DYNAMIC_TYPE_VALUE,
724         DYNAMIC_TYPE_VALUE,
725         DYNAMIC_TYPE_POINTER,
726         DYNAMIC_TYPE_POINTER,
727         DYNAMIC_TYPE_POINTER,
728         DYNAMIC_TYPE_POINTER,
729         DYNAMIC_TYPE_POINTER,
730         DYNAMIC_TYPE_VALUE,
731         DYNAMIC_TYPE_VALUE,
732         DYNAMIC_TYPE_VALUE,
733         DYNAMIC_TYPE_VALUE,
734         DYNAMIC_TYPE_POINTER,
735         DYNAMIC_TYPE_POINTER,
736         DYNAMIC_TYPE_VALUE,
737         DYNAMIC_TYPE_VALUE,
738         DYNAMIC_TYPE_IGNORED,
739         DYNAMIC_TYPE_POINTER,
740         DYNAMIC_TYPE_VALUE,
741         DYNAMIC_TYPE_VALUE,
742         DYNAMIC_TYPE_VALUE,
743         DYNAMIC_TYPE_POINTER,
744         DYNAMIC_TYPE_IGNORED,
745         DYNAMIC_TYPE_POINTER,
746         DYNAMIC_TYPE_IGNORED,
747         DYNAMIC_TYPE_POINTER,
748         DYNAMIC_TYPE_POINTER,
749         DYNAMIC_TYPE_VALUE,
750         DYNAMIC_TYPE_VALUE,
751         DYNAMIC_TYPE_VALUE,
752         DYNAMIC_TYPE_VALUE,
753         DYNAMIC_TYPE_UNSPECIFIED,
754         DYNAMIC_TYPE_POINTER,
755         DYNAMIC_TYPE_VALUE
756      };
757 
758     if (register_size == REGISTER_32_SIZE) {
759         proto_tree_add_item(entry_tree, hf_elf_dynamic_tag, tvb, offset, 4, machine_encoding);
760         tag = (machine_encoding == ENC_BIG_ENDIAN) ? tvb_get_ntohl(tvb, offset) : tvb_get_letohl(tvb, offset);
761         offset += 4;
762 
763         if (tag < MAX_TAG_TO_TYPE && tag_to_type[tag] == DYNAMIC_TYPE_VALUE)
764             proto_tree_add_item(entry_tree, hf_elf_dynamic_value, tvb, offset, 4, machine_encoding);
765         else if (tag < MAX_TAG_TO_TYPE && tag_to_type[tag] == DYNAMIC_TYPE_POINTER)
766             proto_tree_add_item(entry_tree, hf_elf_dynamic_pointer, tvb, offset, 4, machine_encoding);
767         else if (tag < MAX_TAG_TO_TYPE && tag_to_type[tag] == DYNAMIC_TYPE_IGNORED)
768             proto_tree_add_item(entry_tree, hf_elf_dynamic_ignored, tvb, offset, 4, machine_encoding);
769         else
770             proto_tree_add_item(entry_tree, hf_elf_dynamic_unspecified, tvb, offset, 4, machine_encoding);
771         offset += 4;
772     } else {
773         proto_item  *pitem;
774 
775         pitem = proto_tree_add_item(entry_tree, hf_elf64_dynamic_tag, tvb, offset, 8, machine_encoding);
776         tag = (machine_encoding == ENC_BIG_ENDIAN) ? tvb_get_ntoh64(tvb, offset) : tvb_get_letoh64(tvb, offset);
777         proto_item_append_text(pitem, " (%s)", rval_to_str(value_guard(tag), dynamic_tag_rvals, "Unknown"));
778         offset += 8;
779 
780         if (tag < MAX_TAG_TO_TYPE && tag_to_type[tag] == DYNAMIC_TYPE_VALUE)
781             proto_tree_add_item(entry_tree, hf_elf64_dynamic_value, tvb, offset, 8, machine_encoding);
782         else if (tag < MAX_TAG_TO_TYPE && tag_to_type[tag] == DYNAMIC_TYPE_POINTER)
783             proto_tree_add_item(entry_tree, hf_elf64_dynamic_pointer, tvb, offset, 8, machine_encoding);
784         else if (tag < MAX_TAG_TO_TYPE && tag_to_type[tag] == DYNAMIC_TYPE_IGNORED)
785             proto_tree_add_item(entry_tree, hf_elf64_dynamic_ignored, tvb, offset, 8, machine_encoding);
786         else
787             proto_tree_add_item(entry_tree, hf_elf64_dynamic_unspecified, tvb, offset, 8, machine_encoding);
788         offset += 8;
789     }
790 
791     proto_item_append_text(entry_item, ": %s", rval_to_str(value_guard(tag), dynamic_tag_rvals, "Unknown"));
792 
793     return offset;
794 }
795 
796 static gint
dissect_symbol_table(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * entry_tree,proto_item * entry_item,gint offset,gint register_size,guint machine_encoding,guint64 strtab_offset,guint64 shoff,guint16 shnum,guint16 shentsize,guint64 shstrtab_offset)797 dissect_symbol_table(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *entry_tree, proto_item *entry_item,
798         gint offset, gint register_size, guint machine_encoding, guint64 strtab_offset,
799         guint64 shoff, guint16 shnum, guint16 shentsize, guint64 shstrtab_offset)
800 {
801     proto_item   *pitem;
802     proto_item   *info_item;
803     proto_tree   *info_tree;
804     guint16       shndx;
805     guint32       name_index;
806     const guint8 *section_name;
807     const guint8 *name;
808     guint8        info_bind;
809     guint8        info_type;
810 
811     pitem = proto_tree_add_item(entry_tree, hf_elf_symbol_table_name_index, tvb, offset, 4, machine_encoding);
812     if (strtab_offset) {
813         name_index = (machine_encoding == ENC_BIG_ENDIAN) ? tvb_get_ntohl(tvb, offset) : tvb_get_letohl(tvb, offset);
814         name = tvb_get_const_stringz(tvb, value_guard(strtab_offset + name_index), NULL);
815         if (name) {
816             proto_item_append_text(pitem, ": %s", name);
817             proto_item_append_text(entry_item, ": %s", name);
818         }
819     }
820     offset += 4;
821 
822     if (register_size == REGISTER_32_SIZE) {
823         proto_tree_add_item(entry_tree, hf_elf_symbol_table_value, tvb, offset, 4, machine_encoding);
824         offset += 4;
825 
826         proto_tree_add_item(entry_tree, hf_elf_symbol_table_size, tvb, offset, 4, machine_encoding);
827         offset += 4;
828 
829         info_item = proto_tree_add_item(entry_tree, hf_elf_symbol_table_info, tvb, offset, 1, machine_encoding);
830         info_tree = proto_item_add_subtree(info_item, ett_symbol_table_info);
831         proto_tree_add_item(info_tree, hf_elf_symbol_table_info_bind, tvb, offset, 1, machine_encoding);
832         proto_tree_add_item(info_tree, hf_elf_symbol_table_info_type, tvb, offset, 1, machine_encoding);
833         info_bind = tvb_get_guint8(tvb, offset) >> 4;
834         info_type = tvb_get_guint8(tvb, offset) & 0x0F;
835         offset += 1;
836 
837         proto_tree_add_item(entry_tree, hf_elf_symbol_table_other, tvb, offset, 1, machine_encoding);
838         offset += 1;
839 
840         pitem = proto_tree_add_item(entry_tree, hf_elf_symbol_table_shndx, tvb, offset, 2, machine_encoding);
841         shndx = (machine_encoding == ENC_BIG_ENDIAN) ? tvb_get_ntohs(tvb, offset) : tvb_get_letohs(tvb, offset);
842         if (shndx <= shnum) {
843             section_name = get_section_name_offset(tvb, shoff, shnum, shentsize, shndx, shstrtab_offset, machine_encoding);
844             if (section_name && section_name[0] != '\0')
845                 proto_item_append_text(pitem, " (%u: %s)", shndx, section_name);
846         } else {
847             proto_item_append_text(pitem, " (%u)", shndx);
848         }
849         offset += 2;
850     } else {
851         info_item = proto_tree_add_item(entry_tree, hf_elf_symbol_table_info, tvb, offset, 1, machine_encoding);
852         info_tree = proto_item_add_subtree(info_item, ett_symbol_table_info);
853         proto_tree_add_item(info_tree, hf_elf_symbol_table_info_bind, tvb, offset, 1, machine_encoding);
854         proto_tree_add_item(info_tree, hf_elf_symbol_table_info_type, tvb, offset, 1, machine_encoding);
855         info_bind = tvb_get_guint8(tvb, offset) >> 4;
856         info_type = tvb_get_guint8(tvb, offset) & 0x0F;
857         offset += 1;
858 
859         proto_tree_add_item(entry_tree, hf_elf_symbol_table_other, tvb, offset, 1, machine_encoding);
860         offset += 1;
861 
862         pitem = proto_tree_add_item(entry_tree, hf_elf_symbol_table_shndx, tvb, offset, 2, machine_encoding);
863         shndx = (machine_encoding == ENC_BIG_ENDIAN) ? tvb_get_ntohs(tvb, offset) : tvb_get_letohs(tvb, offset);
864         if (shndx <= shnum) {
865             section_name = get_section_name_offset(tvb, shoff, shnum, shentsize, shndx, shstrtab_offset, machine_encoding);
866             if (section_name && section_name[0] != '\0')
867                 proto_item_append_text(pitem, " (%u: %s)", shndx, section_name);
868         } else {
869             proto_item_append_text(pitem, " (%u)", shndx);
870         }
871         offset += 2;
872 
873         proto_tree_add_item(entry_tree, hf_elf64_symbol_table_value, tvb, offset, 8, machine_encoding);
874         offset += 8;
875 
876         proto_tree_add_item(entry_tree, hf_elf64_symbol_table_size, tvb, offset, 8, machine_encoding);
877         offset += 8;
878     }
879 
880     proto_item_append_text(info_item, " (Bind: %s, Type: %s)",
881             val_to_str_const(info_bind, symbol_table_info_bind_vals, "Unknown"),
882             val_to_str_ext_const(info_type, &symbol_table_info_type_vals_ext, "Unknown"));
883 
884     proto_item_append_text(entry_item, " (Bind: %s, Type: %s)",
885             val_to_str_const(info_bind, symbol_table_info_bind_vals, "Unknown"),
886             val_to_str_ext_const(info_type, &symbol_table_info_type_vals_ext, "Unknown"));
887 
888     return offset;
889 }
890 
891 static gint
dissect_eh_frame_hdr(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * segment_tree,gint offset,gint segment_size _U_,gint register_size,guint machine_encoding)892 dissect_eh_frame_hdr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *segment_tree,
893         gint offset, gint segment_size _U_, gint register_size, guint machine_encoding)
894 {
895     proto_item  *item;
896     proto_tree  *table_tree;
897     guint8       format;
898     gint         efp_length;
899     gint         fde_count_length;
900     gint         table_entry_length;
901     guint64      fde_count;
902     guint        i_entry;
903 
904     proto_tree_add_item(segment_tree, hf_elf_eh_frame_hdr_version, tvb, offset, 1, machine_encoding);
905     offset += 1;
906 
907     item = proto_tree_add_item(segment_tree, hf_elf_eh_frame_hdr_exception_frame_pointer_encoding, tvb, offset, 1, machine_encoding);
908     format = dissect_dwarf_encoding(tvb, offset, item);
909     efp_length = get_dwarf_extension_length(format, register_size);
910     offset += 1;
911 
912     item = proto_tree_add_item(segment_tree, hf_elf_eh_frame_hdr_fde_count_encoding, tvb, offset, 1, machine_encoding);
913     format = dissect_dwarf_encoding(tvb, offset, item);
914     fde_count_length = get_dwarf_extension_length(format, register_size);
915     offset += 1;
916 
917     item = proto_tree_add_item(segment_tree, hf_elf_eh_frame_hdr_binary_search_table_encoding, tvb, offset, 1, machine_encoding);
918     format = dissect_dwarf_encoding(tvb, offset, item);
919     table_entry_length = get_dwarf_extension_length(format, register_size);
920     offset += 1;
921 
922     if (efp_length == LENGTH_ULEB128) {
923         guint64 value;
924 
925         efp_length = tvb_get_varint(tvb, offset, FT_VARINT_MAX_LEN, &value, ENC_VARINT_PROTOBUF);
926     } else if (efp_length == LENGTH_LEB128) {
927         gint64 value;
928 
929         efp_length = dissect_leb128(tvb, offset, &value);
930     }
931 
932     proto_tree_add_item(segment_tree, hf_elf_eh_frame_hdr_eh_frame_ptr, tvb, offset, efp_length, machine_encoding);
933     offset += efp_length;
934 
935 
936     if (fde_count_length == LENGTH_ULEB128) {
937         fde_count_length = tvb_get_varint(tvb, offset, FT_VARINT_MAX_LEN, &fde_count, ENC_VARINT_PROTOBUF);
938     } else if (fde_count_length == LENGTH_LEB128) {
939         gint64 value;
940 
941         fde_count_length = dissect_leb128(tvb, offset, &value);
942         fde_count = (guint64) value;
943     } else {
944         if (fde_count_length == 0) fde_count_length = register_size;
945 
946         switch(fde_count_length) {
947         case 2:
948             fde_count = (machine_encoding == ENC_BIG_ENDIAN) ? tvb_get_ntohs(tvb, offset) : tvb_get_letohs(tvb, offset);
949             break;
950         case 4:
951             fde_count = (machine_encoding == ENC_BIG_ENDIAN) ? tvb_get_ntohl(tvb, offset) : tvb_get_letohl(tvb, offset);
952             break;
953         case 8:
954             fde_count = (machine_encoding == ENC_BIG_ENDIAN) ? tvb_get_ntoh64(tvb, offset) : tvb_get_letoh64(tvb, offset);
955             break;
956         case 0:
957         default:
958             fde_count = 0;
959             break;
960         }
961     }
962 
963     proto_tree_add_item(segment_tree, hf_elf_eh_frame_hdr_fde_count, tvb, offset,
964                         fde_count_length, machine_encoding);
965     offset += fde_count_length;
966 
967     if (table_entry_length == LENGTH_ULEB128) {
968         guint64 value;
969 
970         table_entry_length = tvb_get_varint(tvb, offset, FT_VARINT_MAX_LEN, &value, ENC_VARINT_PROTOBUF);
971     } else if (table_entry_length == LENGTH_LEB128) {
972         gint64 value;
973 
974         table_entry_length = dissect_leb128(tvb, offset, &value);
975     }
976 
977     i_entry = 0;
978 
979     table_tree = proto_tree_add_subtree(segment_tree, tvb, offset, value_guard(fde_count * table_entry_length * 2),
980                     ett_binary_table, NULL, "Binary Search Table");
981 
982     while (++i_entry <= fde_count) {
983         proto_tree *entry_tree;
984 
985         entry_tree = proto_tree_add_subtree_format(table_tree, tvb, offset, table_entry_length * 2, ett_binary_table_entry,
986                 NULL, "Binary Table Entry #%u", i_entry);
987 
988         proto_tree_add_item(entry_tree, hf_elf_eh_frame_hdr_binary_search_table_entry_initial_location, tvb, offset, table_entry_length, machine_encoding);
989         offset += table_entry_length;
990 
991         proto_tree_add_item(entry_tree, hf_elf_eh_frame_hdr_binary_search_table_entry_address, tvb, offset, table_entry_length, machine_encoding);
992         offset += table_entry_length;
993     }
994 
995     return offset;
996 }
997 
998 
999 static gint
dissect_eh_frame(tvbuff_t * tvb,packet_info * pinfo,proto_tree * segment_tree,gint offset,gint segment_size,gint register_size _U_,guint machine_encoding)1000 dissect_eh_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *segment_tree,
1001         gint offset, gint segment_size, gint register_size _U_, guint machine_encoding)
1002 {
1003     proto_tree    *cfi_tree = NULL;
1004     proto_item    *cfi_tree_item = NULL;
1005     proto_tree    *entry_tree;
1006     proto_item    *pi = NULL;
1007     guint64        length;
1008     guint          lengths_size;
1009     gboolean       is_cie;
1010     guint          entry_size, entry_end = 0;
1011     guint          cfi_size = 0;
1012     guint64        unsigned_value;
1013     gint64         signed_value;
1014     gint           size;
1015     const gchar   *augmentation_string = "";
1016     gboolean       is_extended_length;
1017     gint           start_offset = offset;
1018     guint          cfi_number = 0;
1019     gint           entry_number = 0;
1020 
1021     while (offset - start_offset < segment_size) {
1022         length = (machine_encoding == ENC_BIG_ENDIAN) ?
1023                 tvb_get_ntohl(tvb, offset) : tvb_get_letohl(tvb, offset);
1024         is_extended_length = length == 0xFFFFFFFF;
1025         if (is_extended_length) {
1026             length = (machine_encoding == ENC_BIG_ENDIAN) ?
1027                         tvb_get_ntoh64(tvb, offset + 4) :
1028                         tvb_get_letoh64(tvb, offset + 4);
1029         }
1030         /* CIE ID/pointer is located after Length (4 bytes), or Length (4 bytes)
1031          * + Extended Length (8 bytes). Entry is CIE when field is 0. */
1032         lengths_size = is_extended_length ? 12 : 4;
1033         is_cie = length == 0 || tvb_get_ntohl(tvb, offset + lengths_size) == 0;
1034         entry_size = value_guard(length + lengths_size);
1035         entry_end = offset + entry_size;
1036 
1037         if (length == 0) {
1038             /* CIE Terminator, add it directly under the Segment tree as we stop
1039              * processing after this item. */
1040             entry_tree = proto_tree_add_subtree(segment_tree,
1041                     tvb, offset, entry_size,
1042                     ett_elf_cie_terminator, NULL, "CIE Terminator");
1043         } else if (cfi_number == 0 || is_cie) {
1044             /* New CIE, so create a new CFI subtree and reset FDE Entry. */
1045             ++cfi_number;
1046             cfi_tree = proto_tree_add_subtree_format(segment_tree,
1047                     tvb, offset, entry_size, ett_elf_cfi_record, &cfi_tree_item,
1048                     "Call Frame Information Entry %i", cfi_number);
1049             entry_tree = proto_tree_add_subtree(cfi_tree, tvb, offset,
1050                     entry_size, ett_elf_cie_entry, NULL, "Common Information Entry");
1051             cfi_size = entry_size;
1052             entry_number = 0;
1053         } else {
1054             /* FDE, add it in the CFI subtree. */
1055             ++entry_number;
1056             cfi_size += entry_size;
1057             proto_item_set_len(cfi_tree_item, cfi_size);
1058             entry_tree = proto_tree_add_subtree_format(cfi_tree,
1059                     tvb, offset, entry_size, ett_elf_fde_entry, NULL,
1060                     "Frame Description Entry %i", entry_number);
1061         }
1062 
1063         pi = proto_tree_add_item(entry_tree, is_cie ?
1064                                     hf_elf_eh_frame_length :
1065                                     hf_elf_eh_frame_fde_length,
1066                                  tvb, offset, 4, machine_encoding);
1067         offset += 4;
1068 
1069         if (is_extended_length) {
1070             pi = proto_tree_add_item(entry_tree, is_cie ?
1071                                         hf_elf_eh_frame_extended_length :
1072                                         hf_elf_eh_frame_fde_extended_length,
1073                                      tvb, offset, 8, machine_encoding);
1074             offset += 8;
1075         }
1076 
1077         /* CIE terminator */
1078         if (length == 0)
1079             break;
1080 
1081         /* CIE ID (8) + Augment. Str (1) + CAF+DAF+Aug.Len (3) = 12 (min. length) */
1082         if (length < 12 || entry_end - start_offset > (guint64)segment_size) {
1083             expert_add_info(pinfo, pi, &ei_invalid_cie_length);
1084             return offset;
1085         }
1086 
1087         proto_tree_add_item(entry_tree, is_cie ?
1088                             hf_elf_eh_frame_cie_id :
1089                             hf_elf_eh_frame_fde_cie_pointer,
1090                             tvb, offset, 4, machine_encoding);
1091         offset += 4;
1092         if (is_cie) {
1093             proto_tree_add_item(entry_tree, hf_elf_eh_frame_version,
1094                                 tvb, offset, 1, machine_encoding);
1095             offset += 1;
1096 
1097             augmentation_string = (const gchar*)tvb_get_const_stringz(tvb, offset, &size);
1098             proto_tree_add_item(entry_tree, hf_elf_eh_frame_augmentation_string,
1099                                 tvb, offset, size, machine_encoding);
1100             offset += size;
1101 
1102             proto_tree_add_item_ret_length(entry_tree, hf_elf_eh_frame_code_alignment_factor, tvb, offset, -1, ENC_LITTLE_ENDIAN|ENC_VARINT_PROTOBUF, &size);
1103             offset += size;
1104 
1105             size = dissect_leb128(tvb, offset, &signed_value);
1106             proto_tree_add_int64(entry_tree, hf_elf_eh_frame_data_alignment_factor,
1107                                  tvb, offset, size, signed_value);
1108             offset += size;
1109 
1110             /* according to DWARF v4 this is uLEB128 */
1111             proto_tree_add_item_ret_length(entry_tree, hf_elf_eh_frame_return_address_register, tvb, offset, -1, ENC_LITTLE_ENDIAN|ENC_VARINT_PROTOBUF, &size);
1112             offset += size;
1113         } else {
1114             proto_tree_add_item(entry_tree, hf_elf_eh_frame_fde_pc_begin, tvb,
1115                                 offset, 4, machine_encoding);
1116             offset += 4;
1117 
1118             proto_tree_add_item(entry_tree, hf_elf_eh_frame_fde_pc_range, tvb,
1119                                 offset, 4, machine_encoding);
1120             offset += 4;
1121         }
1122 
1123         /* "A 'z' may be present as the first character of the string. If
1124          * present, the Augmentation Data field shall be present." (LSB 4.1) */
1125         if (augmentation_string[0] == 'z') {
1126             proto_tree_add_item_ret_varint(entry_tree, is_cie ? hf_elf_eh_frame_augmentation_length : hf_elf_eh_frame_fde_augmentation_length,
1127                                             tvb, offset, -1, ENC_LITTLE_ENDIAN|ENC_VARINT_PROTOBUF, &unsigned_value, &size);
1128             offset += size;
1129 
1130             proto_tree_add_item(entry_tree, is_cie ?
1131                                     hf_elf_eh_frame_augmentation_data :
1132                                     hf_elf_eh_frame_fde_augmentation_data,
1133                                 tvb, offset, value_guard(unsigned_value),
1134                                 machine_encoding);
1135             offset += value_guard(unsigned_value);
1136         }
1137 
1138         proto_tree_add_item(entry_tree, is_cie ?
1139                                 hf_elf_eh_frame_initial_instructions :
1140                                 hf_elf_eh_frame_fde_call_frame_instructions,
1141                             tvb, offset, value_guard(entry_end - offset),
1142                             machine_encoding);
1143         offset = value_guard(entry_end);
1144     }
1145 
1146     if (entry_end - start_offset != (guint64)segment_size)
1147         expert_add_info(pinfo, pi, &ei_cfi_extraneous_data);
1148 
1149     return offset;
1150 }
1151 
1152 static int
dissect_elf(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)1153 dissect_elf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1154 {
1155     static const guint8 magic[] = { 0x7F, 'E', 'L', 'F'};
1156     gint             offset = 0;
1157     proto_tree      *main_tree;
1158     proto_item      *main_item, *ti;
1159     proto_tree      *header_tree;
1160     proto_item      *header_item;
1161     proto_tree      *program_header_tree;
1162     proto_tree      *section_header_tree;
1163     proto_tree      *ph_entry_tree;
1164     proto_item      *sh_entry_item;
1165     proto_tree      *sh_entry_tree;
1166     proto_item      *segment_item;
1167     proto_tree      *segment_tree;
1168     proto_item      *generated_item;
1169     proto_tree      *generated_tree;
1170     proto_tree      *overlapping_tree;
1171     proto_tree      *blackhole_tree;
1172     proto_item      *entry_item;
1173     proto_tree      *entry_tree;
1174     guint            machine_encoding = ENC_NA;
1175     gint             register_size = 4;
1176     guint16          phentsize;
1177     guint16          phnum;
1178     guint16          shentsize;
1179     guint16          shnum;
1180     guint64          phoff;
1181     guint64          shoff;
1182     guint16          i_16;
1183     guint32          p_type;
1184     guint32          sh_type;
1185     guint16          shstrndx;
1186     guint64          shstrtab_offset;
1187     guint32          sh_name;
1188     const char      *section_name;
1189     guint64          length;
1190     guint64          segment_offset;
1191     guint64          segment_size;
1192     guint64          file_size;
1193     guint64          p_offset;
1194     gint             ehsize;
1195     guint            area_counter = 0;
1196     segment_info_t  *segment_info;
1197     guint            i;
1198     guint            i_next;
1199     gint             next_offset;
1200     gint             len;
1201     guint64          sh_entsize;
1202     guint64          strtab_offset = 0;
1203     guint64          dynstr_offset = 0;
1204 
1205     if (tvb_captured_length(tvb) < 52)
1206         return 0;
1207 
1208     if (tvb_memeql(tvb, 0, magic, sizeof(magic)) != 0)
1209         return 0;
1210 
1211     main_item = proto_tree_add_item(tree, proto_elf, tvb, offset, -1, ENC_NA);
1212     main_tree = proto_item_add_subtree(main_item, ett_elf);
1213 
1214     header_tree = proto_tree_add_subtree(main_tree, tvb, offset, 1, ett_elf_header, &header_item, "Header");
1215 
1216     /* e_ident */
1217     proto_tree_add_item(header_tree, hf_elf_magic_bytes, tvb, offset, sizeof(magic), ENC_NA);
1218     offset += (int)sizeof(magic);
1219 
1220     proto_tree_add_item(header_tree, hf_elf_file_class, tvb, offset, 1, ENC_NA);
1221     register_size *= tvb_get_guint8(tvb, offset);
1222     offset += 1;
1223 
1224     proto_tree_add_item(header_tree, hf_elf_data_encoding, tvb, offset, 1, ENC_NA);
1225     if (tvb_get_guint8(tvb, offset) == 1)
1226         machine_encoding = ENC_LITTLE_ENDIAN;
1227     else
1228         machine_encoding = ENC_BIG_ENDIAN;
1229     offset += 1;
1230 
1231     proto_tree_add_item(header_tree, hf_elf_file_version, tvb, offset, 1, ENC_NA);
1232     offset += 1;
1233 
1234     /* From Draft */
1235     proto_tree_add_item(header_tree, hf_elf_os_abi, tvb, offset, 1, ENC_NA);
1236     offset += 1;
1237 
1238     proto_tree_add_item(header_tree, hf_elf_abi_version, tvb, offset, 1, ENC_NA);
1239     offset += 1;
1240 
1241     proto_tree_add_item(header_tree, hf_elf_file_padding, tvb, offset, 7, ENC_NA);
1242     offset += 7;
1243 
1244     /* other */
1245 
1246     proto_tree_add_item(header_tree, hf_elf_type, tvb, offset, 2, machine_encoding);
1247     offset += 2;
1248 
1249     proto_tree_add_item(header_tree, hf_elf_machine, tvb, offset, 2, machine_encoding);
1250     offset += 2;
1251 
1252     proto_tree_add_item(header_tree, hf_elf_version, tvb, offset, 4, machine_encoding);
1253     offset += 4;
1254 
1255     proto_tree_add_item(header_tree,
1256             (register_size == REGISTER_32_SIZE) ? hf_elf_entry : hf_elf64_entry,
1257             tvb, offset, register_size, machine_encoding);
1258     offset += register_size;
1259 
1260     if (register_size == REGISTER_32_SIZE) {
1261         proto_tree_add_item(header_tree, hf_elf_phoff, tvb, offset,
1262                 register_size, machine_encoding);
1263         phoff = (machine_encoding == ENC_BIG_ENDIAN) ?
1264                 tvb_get_ntohl(tvb, offset) : tvb_get_letohl(tvb, offset);
1265     } else {
1266         proto_tree_add_item(header_tree, hf_elf64_phoff, tvb, offset,
1267                 register_size, machine_encoding);
1268         phoff = (machine_encoding == ENC_BIG_ENDIAN) ?
1269                 tvb_get_ntoh64(tvb, offset) : tvb_get_letoh64(tvb, offset);
1270     }
1271     offset += register_size;
1272 
1273 
1274     if (register_size == REGISTER_32_SIZE) {
1275         proto_tree_add_item(header_tree, hf_elf_shoff, tvb, offset,
1276                 register_size, machine_encoding);
1277         shoff = (machine_encoding == ENC_BIG_ENDIAN) ?
1278                 tvb_get_ntohl(tvb, offset) : tvb_get_letohl(tvb, offset);
1279     } else {
1280         proto_tree_add_item(header_tree, hf_elf64_shoff, tvb, offset,
1281                 register_size, machine_encoding);
1282         shoff = (machine_encoding == ENC_BIG_ENDIAN) ?
1283                 tvb_get_ntoh64(tvb, offset) : tvb_get_letoh64(tvb, offset);
1284     }
1285     offset += register_size;
1286 
1287     proto_tree_add_item(header_tree, hf_elf_flags, tvb, offset, 4, machine_encoding);
1288     offset += 4;
1289 
1290     proto_tree_add_item(header_tree, hf_elf_ehsize, tvb, offset, 2, machine_encoding);
1291     ehsize =  (machine_encoding == ENC_BIG_ENDIAN) ? tvb_get_ntohs(tvb, offset) : tvb_get_letohs(tvb, offset);
1292     proto_item_set_len(header_item, ehsize);
1293     offset += 2;
1294 
1295     proto_tree_add_item(header_tree, hf_elf_phentsize, tvb, offset, 2, machine_encoding);
1296     phentsize = (machine_encoding == ENC_BIG_ENDIAN) ? tvb_get_ntohs(tvb, offset) : tvb_get_letohs(tvb, offset);
1297     offset += 2;
1298 
1299     proto_tree_add_item(header_tree, hf_elf_phnum, tvb, offset, 2, machine_encoding);
1300     phnum = (machine_encoding == ENC_BIG_ENDIAN) ? tvb_get_ntohs(tvb, offset) : tvb_get_letohs(tvb, offset);
1301     offset += 2;
1302 
1303     proto_tree_add_item(header_tree, hf_elf_shentsize, tvb, offset, 2, machine_encoding);
1304     shentsize = (machine_encoding == ENC_BIG_ENDIAN) ? tvb_get_ntohs(tvb, offset) : tvb_get_letohs(tvb, offset);
1305     offset += 2;
1306 
1307     proto_tree_add_item(header_tree, hf_elf_shnum, tvb, offset, 2, machine_encoding);
1308     shnum = (machine_encoding == ENC_BIG_ENDIAN) ? tvb_get_ntohs(tvb, offset) : tvb_get_letohs(tvb, offset);
1309     offset += 2;
1310 
1311     proto_tree_add_item(header_tree, hf_elf_shstrndx, tvb, offset, 2, machine_encoding);
1312     shstrndx = (machine_encoding == ENC_BIG_ENDIAN) ?
1313             tvb_get_ntohs(tvb, offset) : tvb_get_letohs(tvb, offset);
1314     /*offset += 2;*/
1315 
1316     program_header_tree = proto_tree_add_subtree_format(main_tree, tvb, value_guard(phoff),
1317             phnum * phentsize, ett_elf_program_header, NULL, "Program Header Table [%d entries]", phnum);
1318 
1319     section_header_tree = proto_tree_add_subtree_format(main_tree, tvb, value_guard(shoff),
1320             shnum * shentsize, ett_elf_section_header, NULL, "Section Header Table [%d entries]", shnum);
1321 
1322     file_size = ehsize + (guint32)phnum * (guint32)phentsize + (guint32)shnum * (guint32)shentsize;
1323 
1324     /* Collect infos for blackholes */
1325     segment_info = (segment_info_t *) wmem_alloc(pinfo->pool, sizeof(segment_info_t) * (shnum + phnum + 3));
1326 
1327     segment_info[area_counter].offset = 0;
1328     segment_info[area_counter].size = ehsize;
1329     segment_info[area_counter].name = "Header";
1330     area_counter += 1;
1331 
1332     if (phoff) {
1333         segment_info[area_counter].offset = phoff;
1334         segment_info[area_counter].size = (guint32)phnum * (guint32)phentsize;
1335         segment_info[area_counter].name = "ProgramHeader";
1336         area_counter += 1;
1337     }
1338 
1339     if (shoff) {
1340         segment_info[area_counter].offset = shoff;
1341         segment_info[area_counter].size = (guint32)shnum * (guint32)shentsize;
1342         segment_info[area_counter].name = "SectionHeader";
1343         area_counter += 1;
1344     }
1345 
1346     offset = value_guard(phoff);
1347 
1348     i_16 = phnum;
1349     while (i_16-- > 0) {
1350         p_type = (machine_encoding == ENC_BIG_ENDIAN) ?
1351                 tvb_get_ntohl(tvb, offset) : tvb_get_letohl(tvb, offset);
1352         if (p_type >= 0x60000000 && p_type <= 0x6FFFFFFF) {
1353             ph_entry_tree = proto_tree_add_subtree_format(program_header_tree,
1354                      tvb, offset, phentsize, ett_elf_program_header_entry, NULL,
1355                     "Entry #%d: Operating System Specific (0x%08x)", phnum - i_16 - 1, p_type);
1356             proto_tree_add_item(ph_entry_tree, hf_elf_p_type_operating_system_specific, tvb, offset, 4, machine_encoding);
1357         } else if (p_type >= 0x70000000 && p_type <= 0x7FFFFFFF) {
1358             ph_entry_tree = proto_tree_add_subtree_format(program_header_tree,
1359                      tvb, offset, phentsize, ett_elf_program_header_entry, NULL,
1360                     "Entry #%d: Processor Specific (0x%08x)", phnum - i_16 - 1, p_type);
1361             proto_tree_add_item(ph_entry_tree, hf_elf_p_type_processor_specific, tvb, offset, 4, machine_encoding);
1362         } else {
1363             ph_entry_tree = proto_tree_add_subtree_format(program_header_tree,
1364                      tvb, offset, phentsize, ett_elf_program_header_entry, NULL,
1365                     "Entry #%d: %s", phnum - i_16 - 1,
1366                     val_to_str_const(p_type, p_type_vals, "Unknown"));
1367             proto_tree_add_item(ph_entry_tree, hf_elf_p_type, tvb, offset, 4, machine_encoding);
1368         }
1369         offset += 4;
1370 
1371         if (register_size == REGISTER_64_SIZE) {
1372             proto_tree_add_item(ph_entry_tree, hf_elf_p_flags_processor_specific, tvb, offset, 4, machine_encoding);
1373             proto_tree_add_item(ph_entry_tree, hf_elf_p_flags_operating_system_specific, tvb, offset, 4, machine_encoding);
1374             proto_tree_add_item(ph_entry_tree, hf_elf_p_flags_reserved, tvb, offset, 4, machine_encoding);
1375             proto_tree_add_item(ph_entry_tree, hf_elf_p_flags_read, tvb, offset, 4, machine_encoding);
1376             proto_tree_add_item(ph_entry_tree, hf_elf_p_flags_write, tvb, offset, 4, machine_encoding);
1377             proto_tree_add_item(ph_entry_tree, hf_elf_p_flags_execute, tvb, offset, 4, machine_encoding);
1378             offset += 4;
1379         }
1380 
1381         proto_tree_add_item(ph_entry_tree,
1382                 (register_size == REGISTER_32_SIZE) ? hf_elf_p_offset : hf_elf64_p_offset,
1383                 tvb, offset, register_size, machine_encoding);
1384         if (register_size == REGISTER_32_SIZE) {
1385             p_offset = (machine_encoding == ENC_BIG_ENDIAN) ?
1386                     tvb_get_ntohl(tvb, offset) : tvb_get_letohl(tvb, offset);
1387         } else {
1388             p_offset = (machine_encoding == ENC_BIG_ENDIAN) ?
1389                     tvb_get_ntoh64(tvb, offset) : tvb_get_letoh64(tvb, offset);
1390         }
1391 
1392         offset += register_size;
1393 
1394         proto_tree_add_item(ph_entry_tree,
1395                 (register_size == REGISTER_32_SIZE) ? hf_elf_p_vaddr : hf_elf64_p_vaddr,
1396                 tvb, offset, register_size, machine_encoding);
1397         offset += register_size;
1398 
1399         proto_tree_add_item(ph_entry_tree,
1400                 (register_size == REGISTER_32_SIZE) ? hf_elf_p_paddr : hf_elf64_p_paddr,
1401                 tvb, offset, register_size, machine_encoding);
1402         offset += register_size;
1403 
1404         proto_tree_add_item(ph_entry_tree,
1405                 (register_size == REGISTER_32_SIZE) ? hf_elf_p_filesz : hf_elf64_p_filesz,
1406                 tvb, offset, register_size, machine_encoding);
1407         if (register_size == REGISTER_32_SIZE) {
1408             segment_size = (machine_encoding == ENC_BIG_ENDIAN) ?
1409                     tvb_get_ntohl(tvb, offset) : tvb_get_letohl(tvb, offset);
1410         } else {
1411             segment_size = (machine_encoding == ENC_BIG_ENDIAN) ?
1412                     tvb_get_ntoh64(tvb, offset) : tvb_get_letoh64(tvb, offset);
1413         }
1414         offset += register_size;
1415 
1416         proto_tree_add_item(ph_entry_tree,
1417                 (register_size == REGISTER_32_SIZE) ? hf_elf_p_memsz : hf_elf64_p_memsz,
1418                 tvb, offset, register_size, machine_encoding);
1419         offset += register_size;
1420 
1421         if (register_size == REGISTER_32_SIZE) {
1422             proto_tree_add_item(ph_entry_tree, hf_elf_p_flags_processor_specific, tvb, offset, 4, machine_encoding);
1423             proto_tree_add_item(ph_entry_tree, hf_elf_p_flags_operating_system_specific, tvb, offset, 4, machine_encoding);
1424             proto_tree_add_item(ph_entry_tree, hf_elf_p_flags_reserved, tvb, offset, 4, machine_encoding);
1425             proto_tree_add_item(ph_entry_tree, hf_elf_p_flags_read, tvb, offset, 4, machine_encoding);
1426             proto_tree_add_item(ph_entry_tree, hf_elf_p_flags_write, tvb, offset, 4, machine_encoding);
1427             proto_tree_add_item(ph_entry_tree, hf_elf_p_flags_execute, tvb, offset, 4, machine_encoding);
1428             offset += 4;
1429         }
1430 
1431         proto_tree_add_item(ph_entry_tree,
1432                 (register_size == REGISTER_32_SIZE) ? hf_elf_p_align : hf_elf64_p_align,
1433                 tvb, offset, register_size, machine_encoding);
1434         offset += register_size;
1435 
1436         if (segment_size) {
1437             gchar  *name;
1438 
1439             name = wmem_strdup_printf(pinfo->pool, "ProgramHeaderEntry #%u", phnum - i_16 - 1);
1440 
1441             proto_tree_add_bytes_format(ph_entry_tree, hf_elf_segment, tvb, value_guard(p_offset), value_guard(segment_size), NULL, "Segment");
1442 
1443             file_size += segment_size;
1444 
1445             segment_info[area_counter].offset = p_offset;
1446             segment_info[area_counter].size = segment_size;
1447             segment_info[area_counter].name = name;
1448 
1449             area_counter += 1;
1450         }
1451     }
1452 
1453 /* Find and save some information for later */
1454     offset = value_guard(shoff);
1455 
1456     i_16 = shnum;
1457     while (i_16-- > 0) {
1458         sh_name = (machine_encoding == ENC_BIG_ENDIAN) ?
1459                     tvb_get_ntohl(tvb, offset) : tvb_get_letohl(tvb, offset);
1460 
1461         offset += 4;
1462 
1463         offset += 4;
1464 
1465         length = shoff + (guint32)shstrndx * (guint32)shentsize + 2 * 4 + 2 * register_size;
1466         if (register_size == REGISTER_32_SIZE) {
1467             shstrtab_offset = (machine_encoding == ENC_BIG_ENDIAN) ?
1468                     tvb_get_ntohl(tvb, value_guard(length)) : tvb_get_letohl(tvb, value_guard(length));
1469         } else {
1470             shstrtab_offset = (machine_encoding == ENC_BIG_ENDIAN) ?
1471                     tvb_get_ntoh64(tvb, value_guard(length)) : tvb_get_letoh64(tvb, value_guard(length));
1472         }
1473 
1474         section_name = (const char *)tvb_get_const_stringz(tvb, value_guard(shstrtab_offset + sh_name), NULL);
1475 
1476         if (register_size == REGISTER_64_SIZE && machine_encoding == ENC_BIG_ENDIAN) {
1477             offset += 4;
1478         }
1479 
1480         offset += 4;
1481 
1482         if (register_size == REGISTER_64_SIZE && machine_encoding == ENC_LITTLE_ENDIAN) {
1483             offset += 4;
1484         }
1485 
1486         offset += register_size;
1487 
1488         if (register_size == REGISTER_32_SIZE) {
1489             segment_offset = (machine_encoding == ENC_BIG_ENDIAN) ?
1490                     tvb_get_ntohl(tvb, offset) : tvb_get_letohl(tvb, offset);
1491         } else {
1492             segment_offset = (machine_encoding == ENC_BIG_ENDIAN) ?
1493                     tvb_get_ntoh64(tvb, offset) : tvb_get_letoh64(tvb, offset);
1494         }
1495 
1496         if (g_strcmp0(section_name, ".strtab") == 0) {
1497             strtab_offset = segment_offset;
1498         } else if (g_strcmp0(section_name, ".dynstr") == 0) {
1499             dynstr_offset = segment_offset;
1500         }
1501         offset += register_size;
1502         offset += register_size;
1503         offset += 4;
1504         offset += 4;
1505         offset += register_size;
1506         offset += register_size;
1507     }
1508 
1509 /* Sections */
1510     offset = value_guard(shoff);
1511 
1512     i_16 = shnum;
1513     while (i_16-- > 0) {
1514         sh_entry_tree = proto_tree_add_subtree_format(section_header_tree, tvb, offset, shentsize,
1515                 ett_elf_section_header_entry, &sh_entry_item,
1516                 "Entry #%d: ", shnum - i_16 - 1);
1517 
1518         proto_tree_add_item(sh_entry_tree, hf_elf_sh_name, tvb, offset, 4, machine_encoding);
1519         sh_name = (machine_encoding == ENC_BIG_ENDIAN) ?
1520                     tvb_get_ntohl(tvb, offset) : tvb_get_letohl(tvb, offset);
1521         offset += 4;
1522 
1523         sh_type = (machine_encoding == ENC_BIG_ENDIAN) ?
1524                 tvb_get_ntohl(tvb, offset) : tvb_get_letohl(tvb, offset);
1525         if (sh_type >= 0x60000000 && sh_type <= 0x6FFFFFFF) {
1526             proto_item_append_text(sh_entry_item, "Operating System Specific (0x%08x)", sh_type);
1527             proto_tree_add_item(sh_entry_tree, hf_elf_sh_type_operating_system_specific, tvb, offset, 4, machine_encoding);
1528         } else if (sh_type >= 0x70000000 && sh_type <= 0x7FFFFFFF) {
1529             proto_item_append_text(sh_entry_item, "Processor Specific (0x%08x)", sh_type);
1530             proto_tree_add_item(sh_entry_tree, hf_elf_sh_type_processor_specific, tvb, offset, 4, machine_encoding);
1531         } else if (sh_type >= 0x80000000) {
1532             proto_item_append_text(sh_entry_item, "User Specific (0x%08x)", sh_type);
1533             proto_tree_add_item(sh_entry_tree, hf_elf_sh_type_user_specific, tvb, offset, 4, machine_encoding);
1534         }else {
1535             proto_item_append_text(sh_entry_item, "%s", val_to_str_ext_const(sh_type, &sh_type_vals_ext, "Unknown"));
1536             proto_tree_add_item(sh_entry_tree, hf_elf_sh_type, tvb, offset, 4, machine_encoding);
1537         }
1538         offset += 4;
1539 
1540         length = shoff + (guint32)shstrndx * (guint32)shentsize + 2 * 4 + 2 * register_size;
1541         if (register_size == REGISTER_32_SIZE) {
1542             shstrtab_offset = (machine_encoding == ENC_BIG_ENDIAN) ?
1543                     tvb_get_ntohl(tvb, value_guard(length)) : tvb_get_letohl(tvb, value_guard(length));
1544         } else {
1545             shstrtab_offset = (machine_encoding == ENC_BIG_ENDIAN) ?
1546                     tvb_get_ntoh64(tvb, value_guard(length)) : tvb_get_letoh64(tvb, value_guard(length));
1547         }
1548 
1549         section_name = (const char*)tvb_get_const_stringz(tvb, value_guard(shstrtab_offset + sh_name), NULL);
1550         if (section_name)
1551             proto_item_append_text(sh_entry_item, ": %s", section_name);
1552 
1553         if (register_size == REGISTER_64_SIZE && machine_encoding == ENC_BIG_ENDIAN) {
1554             offset += 4;
1555         }
1556 
1557         proto_tree_add_item(sh_entry_tree, hf_elf_sh_flags_processor_specific, tvb, offset, 4, machine_encoding);
1558         proto_tree_add_item(sh_entry_tree, hf_elf_sh_flags_operating_system_specific, tvb, offset, 4, machine_encoding);
1559         proto_tree_add_item(sh_entry_tree, hf_elf_sh_flags_reserved, tvb, offset, 4, machine_encoding);
1560         proto_tree_add_item(sh_entry_tree, hf_elf_sh_flags_tls, tvb, offset, 4, machine_encoding);
1561         proto_tree_add_item(sh_entry_tree, hf_elf_sh_flags_group, tvb, offset, 4, machine_encoding);
1562         proto_tree_add_item(sh_entry_tree, hf_elf_sh_flags_os_nonconforming, tvb, offset, 4, machine_encoding);
1563         proto_tree_add_item(sh_entry_tree, hf_elf_sh_flags_link_order, tvb, offset, 4, machine_encoding);
1564         proto_tree_add_item(sh_entry_tree, hf_elf_sh_flags_info_link, tvb, offset, 4, machine_encoding);
1565         proto_tree_add_item(sh_entry_tree, hf_elf_sh_flags_strings, tvb, offset, 4, machine_encoding);
1566         proto_tree_add_item(sh_entry_tree, hf_elf_sh_flags_merge, tvb, offset, 4, machine_encoding);
1567         proto_tree_add_item(sh_entry_tree, hf_elf_sh_flags_reserved_8, tvb, offset, 4, machine_encoding);
1568         proto_tree_add_item(sh_entry_tree, hf_elf_sh_flags_exec_instr, tvb, offset, 4, machine_encoding);
1569         proto_tree_add_item(sh_entry_tree, hf_elf_sh_flags_alloc, tvb, offset, 4, machine_encoding);
1570         proto_tree_add_item(sh_entry_tree, hf_elf_sh_flags_write, tvb, offset, 4, machine_encoding);
1571         offset += 4;
1572 
1573         if (register_size == REGISTER_64_SIZE && machine_encoding == ENC_LITTLE_ENDIAN) {
1574             offset += 4;
1575         }
1576 
1577         proto_tree_add_item(sh_entry_tree,
1578                 (register_size == REGISTER_32_SIZE) ? hf_elf_sh_addr : hf_elf64_sh_addr,
1579                 tvb, offset, register_size, machine_encoding);
1580         offset += register_size;
1581 
1582         proto_tree_add_item(sh_entry_tree,
1583                 (register_size == REGISTER_32_SIZE) ? hf_elf_sh_offset : hf_elf64_sh_offset,
1584                 tvb, offset, register_size, machine_encoding);
1585         if (register_size == REGISTER_32_SIZE) {
1586             segment_offset = (machine_encoding == ENC_BIG_ENDIAN) ?
1587                     tvb_get_ntohl(tvb, offset) : tvb_get_letohl(tvb, offset);
1588         } else {
1589             segment_offset = (machine_encoding == ENC_BIG_ENDIAN) ?
1590                     tvb_get_ntoh64(tvb, offset) : tvb_get_letoh64(tvb, offset);
1591         }
1592         offset += register_size;
1593 
1594         proto_tree_add_item(sh_entry_tree,
1595                 (register_size == REGISTER_32_SIZE) ? hf_elf_sh_size : hf_elf64_sh_size,
1596                 tvb, offset, register_size, machine_encoding);
1597         if (register_size == REGISTER_32_SIZE) {
1598             segment_size = (machine_encoding == ENC_BIG_ENDIAN) ?
1599                     tvb_get_ntohl(tvb, offset) : tvb_get_letohl(tvb, offset);
1600         } else {
1601             segment_size = (machine_encoding == ENC_BIG_ENDIAN) ?
1602                     tvb_get_ntoh64(tvb, offset) : tvb_get_letoh64(tvb, offset);
1603         }
1604         offset += register_size;
1605 
1606         proto_tree_add_item(sh_entry_tree, hf_elf_sh_link, tvb, offset, 4, machine_encoding);
1607         offset += 4;
1608 
1609         proto_tree_add_item(sh_entry_tree, hf_elf_sh_info, tvb, offset, 4, machine_encoding);
1610         offset += 4;
1611 
1612         proto_tree_add_item(sh_entry_tree,
1613                 (register_size == REGISTER_32_SIZE) ? hf_elf_sh_addralign : hf_elf64_sh_addralign,
1614                 tvb, offset, register_size, machine_encoding);
1615         offset += register_size;
1616 
1617         proto_tree_add_item(sh_entry_tree,
1618                 (register_size == REGISTER_32_SIZE) ? hf_elf_sh_entsize : hf_elf64_sh_entsize,
1619                 tvb, offset, register_size, machine_encoding);
1620         if (register_size == REGISTER_32_SIZE) {
1621             sh_entsize = (machine_encoding == ENC_BIG_ENDIAN) ?
1622                     tvb_get_ntohl(tvb, offset) : tvb_get_letohl(tvb, offset);
1623         } else {
1624             sh_entsize = (machine_encoding == ENC_BIG_ENDIAN) ?
1625                     tvb_get_ntoh64(tvb, offset) : tvb_get_letoh64(tvb, offset);
1626         }
1627         offset += register_size;
1628 
1629         if (segment_size > 0 && sh_type != 8) { /* ! SHT_NOBITS */
1630             file_size += segment_size;
1631 
1632             segment_info[area_counter].offset = segment_offset;
1633             segment_info[area_counter].size = segment_size;
1634             segment_info[area_counter].name = section_name;
1635             area_counter += 1;
1636 
1637             segment_tree = proto_tree_add_subtree(sh_entry_tree, tvb, value_guard(segment_offset),
1638                     value_guard(segment_size), ett_elf_segment, &segment_item, "Segment");
1639 
1640             if (g_strcmp0(section_name, ".eh_frame") == 0) {
1641                 next_offset = dissect_eh_frame(tvb, pinfo, segment_tree,
1642                         value_guard(segment_offset), value_guard(segment_size), register_size,
1643                         machine_encoding);
1644                 if (next_offset != (gint) (segment_offset + segment_size))
1645                     expert_add_info(pinfo, segment_item, &ei_invalid_segment_size);
1646             } else if (g_strcmp0(section_name, ".eh_frame_hdr") == 0) {
1647                 next_offset = dissect_eh_frame_hdr(tvb, pinfo, segment_tree,
1648                         value_guard(segment_offset), value_guard(segment_size), register_size,
1649                         machine_encoding);
1650                 if (next_offset != (gint) (segment_offset + segment_size))
1651                     expert_add_info(pinfo, segment_item, &ei_invalid_segment_size);
1652             } else if (sh_type == 0x06) { /* SHT_DYNAMIC */
1653                 if (sh_entsize > 0) {
1654                     next_offset = value_guard(segment_offset);
1655                     for  (i = 1; i < (segment_size / sh_entsize) + 1; i += 1) {
1656                         entry_tree = proto_tree_add_subtree_format(segment_tree, tvb, next_offset,
1657                                value_guard(sh_entsize), ett_symbol_table_entry, &entry_item, "Entry #%d", i);
1658 
1659                         next_offset = dissect_dynamic(tvb, pinfo, entry_tree, entry_item,
1660                                 next_offset, register_size, machine_encoding);
1661                         if (next_offset != (gint) (segment_offset + i * sh_entsize))
1662                             expert_add_info(pinfo, segment_item, &ei_invalid_entry_size);
1663                     }
1664                 }
1665             } else if (sh_type == 0x02 || sh_type == 0x0b) { /* SHT_SYMTAB || SHT_DYNSYM */
1666                 if (sh_entsize > 0) {
1667                     next_offset = value_guard(segment_offset);
1668                     for  (i = 1; i < (segment_size / sh_entsize) + 1; i += 1) {
1669                         entry_tree = proto_tree_add_subtree_format(segment_tree, tvb, next_offset,
1670                                value_guard(sh_entsize), ett_symbol_table_entry, &entry_item, "Entry #%d", i);
1671 
1672                         next_offset = dissect_symbol_table(tvb, pinfo, entry_tree, entry_item,
1673                                 next_offset, register_size, machine_encoding, (sh_type == 0x02) ? strtab_offset : dynstr_offset,
1674                                 shoff, shnum, shentsize, shstrtab_offset);
1675                         if (next_offset != (gint) (segment_offset + i * sh_entsize))
1676                             expert_add_info(pinfo, segment_item, &ei_invalid_entry_size);
1677                     }
1678                 }
1679             } else if (sh_type == 0x03) { /* SHT_STRTAB */
1680                     next_offset = value_guard(segment_offset);
1681                     i = 1;
1682                     while (next_offset < (gint) (segment_offset + segment_size)) {
1683                         tvb_get_const_stringz(tvb, next_offset, &len);
1684                         entry_item = proto_tree_add_item(segment_tree, hf_elf_string, tvb, next_offset, len, ENC_ASCII | ENC_NA);
1685                         proto_item_append_text(entry_item, " (Number: %u, Index: %u, Length: %u)", (guint) i, (guint) (next_offset - segment_offset), len - 1);
1686                         next_offset += len;
1687                         i += 1;
1688                     }
1689             } else {
1690                 /* .debug_str sections have sh_entsize 1, displaying every byte
1691                  * individually can explode the tree size, so require > 1. */
1692                 if (sh_entsize > 1) {
1693                     next_offset = value_guard(segment_offset);
1694                     for  (i = 1; i < (segment_size / sh_entsize) + 1; i += 1) {
1695                         proto_tree_add_bytes_format(segment_tree, hf_elf_entry_bytes, tvb, next_offset,
1696                                value_guard(sh_entsize), NULL, "Entry #%d ", i);
1697                         next_offset += value_guard(sh_entsize);
1698                     }
1699                 }
1700             }
1701         }
1702     }
1703 
1704     /* Try to detect blackholes and overlapping segments */
1705     generated_tree = proto_tree_add_subtree(main_tree, tvb, 0, 0, ett_elf_info, &generated_item, "Infos");
1706     proto_item_set_generated(generated_item);
1707 
1708     blackhole_tree = proto_tree_add_subtree(generated_tree, tvb, 0, 0, ett_elf_black_holes, NULL, "Backholes");
1709     overlapping_tree = proto_tree_add_subtree(generated_tree, tvb, 0, 0, ett_elf_overlapping, NULL, "Overlapping");
1710 
1711     /* sorting... */
1712     for (i = 0; i < area_counter; i += 1) {
1713         segment_info_t   tmp_segment;
1714         segment_info_t  *min_offset_segment;
1715 
1716         min_offset_segment = &segment_info[i];
1717 
1718         for (i_next = i + 1; i_next <  area_counter; i_next += 1) {
1719             if (min_offset_segment->offset <= segment_info[i_next].offset) continue;
1720 
1721             tmp_segment = *min_offset_segment;
1722             *min_offset_segment = segment_info[i_next];
1723             segment_info[i_next] = tmp_segment;
1724         }
1725     }
1726 
1727     for (i = 1; i < area_counter; i += 1) {
1728         if (segment_info[i - 1].offset + segment_info[i - 1].size < segment_info[i].offset) {
1729             /* blackhole */
1730             len = (guint) (segment_info[i].offset - segment_info[i - 1].offset - segment_info[i - 1].size);
1731 
1732             ti = proto_tree_add_uint_format(blackhole_tree, hf_elf_blackhole_size, tvb, value_guard(segment_info[i].offset - len), 1, len,
1733                     "Blackhole between: %s and %s, size: %u", segment_info[i - 1].name, segment_info[i].name, len);
1734             proto_item_set_len(ti, len);
1735 
1736         } else if (segment_info[i - 1].offset + segment_info[i - 1].size > segment_info[i].offset) {
1737             /* overlapping */
1738             len = (guint) (segment_info[i - 1].offset + segment_info[i - 1].size - segment_info[i].offset);
1739 
1740             ti = proto_tree_add_uint_format(overlapping_tree, hf_elf_overlapping_size, tvb, value_guard(segment_info[i - 1].offset + segment_info[i - 1].size - len), 1, len,
1741                     "Overlapping between: %s and %s, size: %u", segment_info[i - 1].name, segment_info[i].name, len);
1742             proto_item_set_len(ti, len);
1743 
1744             file_size -= len;
1745         }
1746     }
1747 
1748     if (segment_info[area_counter - 1].offset + segment_info[area_counter - 1].size < tvb_captured_length(tvb)) {
1749             len = tvb_captured_length(tvb) - (guint) (segment_info[area_counter - 1].offset - segment_info[area_counter - 1].size);
1750 
1751             ti = proto_tree_add_uint_format(blackhole_tree, hf_elf_blackhole_size, tvb,
1752                     value_guard(segment_info[area_counter - 1].offset +
1753                     segment_info[area_counter - 1].size), 1,
1754                     len, "Blackhole between: %s and <EOF>, size: %u",
1755                     segment_info[area_counter - 1].name, len);
1756             proto_item_set_len(ti, len);
1757     }
1758 
1759     proto_tree_add_uint(generated_tree, hf_elf_file_size, tvb, 0, 0, tvb_captured_length(tvb));
1760     proto_tree_add_uint(generated_tree, hf_elf_header_segment_size, tvb, 0, 0, (guint)file_size);
1761     proto_tree_add_uint(generated_tree, hf_elf_blackholes_size, tvb, 0, 0, tvb_captured_length(tvb) - (guint)file_size);
1762 
1763     col_clear(pinfo->cinfo, COL_INFO);
1764     col_add_str(pinfo->cinfo, COL_INFO, "(ELF)");
1765 
1766     /* We jumping around offsets, so treat as bytes as read */
1767     return tvb_captured_length(tvb);
1768 }
1769 
1770 static gboolean
dissect_elf_heur(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)1771 dissect_elf_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1772 {
1773     return dissect_elf(tvb, pinfo, tree, NULL) > 0;
1774 }
1775 
1776 void
proto_register_elf(void)1777 proto_register_elf(void)
1778 {
1779     module_t         *module;
1780     expert_module_t  *expert_module;
1781 
1782     static hf_register_info hf[] = {
1783         /* Header */
1784         { &hf_elf_magic_bytes,
1785             { "Magic Bytes",                               "elf.magic_bytes",
1786             FT_BYTES, BASE_NONE, NULL, 0x00,
1787             NULL, HFILL }
1788         },
1789         { &hf_elf_file_size,
1790             { "File size",                                 "elf.file_size",
1791             FT_UINT32, BASE_DEC, NULL, 0x00,
1792             NULL, HFILL }
1793         },
1794         { &hf_elf_header_segment_size,
1795             { "Header size + all segment size",            "elf.header_segment_size",
1796             FT_UINT32, BASE_DEC, NULL, 0x00,
1797             NULL, HFILL }
1798         },
1799         { &hf_elf_blackholes_size,
1800             { "Total blackholes size",                     "elf.blackholes_size",
1801             FT_UINT32, BASE_DEC, NULL, 0x00,
1802             NULL, HFILL }
1803         },
1804         { &hf_elf_blackhole_size,
1805             { "Blackhole size",                            "elf.blackhole_size",
1806             FT_UINT32, BASE_DEC, NULL, 0x00,
1807             "Blackhole size between sections or program headers", HFILL }
1808         },
1809         { &hf_elf_overlapping_size,
1810             { "Overlapping size",                          "elf.overlapping_size",
1811             FT_UINT32, BASE_DEC, NULL, 0x00,
1812             "Overlapping size between sections or program headers", HFILL }
1813         },
1814         { &hf_elf_segment,
1815             { "Segment",                                   "elf.segment",
1816             FT_BYTES, BASE_NONE, NULL, 0x00,
1817             NULL, HFILL }
1818         },
1819         { &hf_elf_entry_bytes,
1820             { "Entry",                                   "elf.entry_bytes",
1821             FT_BYTES, BASE_NONE, NULL, 0x00,
1822             NULL, HFILL }
1823         },
1824         { &hf_elf_file_class,
1825             { "File Class",                                "elf.file_class",
1826             FT_UINT8, BASE_HEX, VALS(class_vals), 0x00,
1827             NULL, HFILL }
1828         },
1829         { &hf_elf_data_encoding,
1830             { "Data Encoding",                             "elf.data_encoding",
1831             FT_UINT8, BASE_HEX, VALS(data_encoding_vals), 0x00,
1832             NULL, HFILL }
1833         },
1834         { &hf_elf_file_version,
1835             { "File Version",                              "elf.file_version",
1836             FT_UINT8, BASE_HEX, VALS(version_vals), 0x00,
1837             NULL, HFILL }
1838         },
1839         { &hf_elf_os_abi,
1840             { "OS ABI",                                    "elf.os_abi",
1841             FT_UINT8, BASE_HEX | BASE_EXT_STRING, &os_abi_vals_ext, 0x00,
1842             NULL, HFILL }
1843         },
1844         { &hf_elf_abi_version,
1845             { "ABI Version",                               "elf.abi_version",
1846             FT_UINT8, BASE_HEX_DEC, NULL, 0x00,
1847             NULL, HFILL }
1848         },
1849         { &hf_elf_file_padding,
1850             { "File Padding",                              "elf.file_padding",
1851             FT_BYTES, BASE_NONE, NULL, 0x00,
1852             NULL, HFILL }
1853         },
1854         { &hf_elf_type,
1855             { "Type",                                      "elf.type",
1856             FT_UINT16, BASE_HEX, VALS(type_vals), 0x00,
1857             NULL, HFILL }
1858         },
1859         { &hf_elf_machine,
1860             { "Machine",                                   "elf.machine",
1861             FT_UINT16, BASE_HEX | BASE_EXT_STRING, &machine_vals_ext, 0x00,
1862             NULL, HFILL }
1863         },
1864         { &hf_elf_version,
1865             { "Version",                                   "elf.version",
1866             FT_UINT32, BASE_HEX, VALS(version_vals), 0x00,
1867             NULL, HFILL }
1868         },
1869         { &hf_elf_entry,
1870             { "Entry",                                     "elf.entry",
1871             FT_UINT32, BASE_HEX, NULL, 0x00,
1872             "This member gives the virtual address to which the system first transfers control, thus starting the process. If the file has no associated entry point, this member holds zero. ", HFILL }
1873         },
1874         { &hf_elf64_entry,
1875             { "Entry",                                     "elf.entry64",
1876             FT_UINT64, BASE_HEX, NULL, 0x00,
1877             "This member gives the virtual address to which the system first transfers control, thus starting the process. If the file has no associated entry point, this member holds zero. ", HFILL }
1878         },
1879         { &hf_elf_phoff,
1880             { "Program Header Table File Offset",          "elf.phoff",
1881             FT_UINT32, BASE_DEC_HEX, NULL, 0x00,
1882             "This member holds the program header table's file offset in bytes. If the file has no program header table, this member holds zero.", HFILL }
1883         },
1884         { &hf_elf64_phoff,
1885             { "Program Header Table File Offset",          "elf.phoff64",
1886             FT_UINT64, BASE_DEC_HEX, NULL, 0x00,
1887             "This member holds the program header table's file offset in bytes. If the file has no program header table, this member holds zero.", HFILL }
1888         },
1889         { &hf_elf_shoff,
1890             { "Section Header Table File Offset",          "elf.shoff",
1891             FT_UINT32, BASE_DEC_HEX, NULL, 0x00,
1892             "This member holds the section header table's file offset in bytes. If the file has no section header table, this member holds zero.", HFILL }
1893         },
1894         { &hf_elf64_shoff,
1895             { "Section Header Table File Offset",          "elf.shoff64",
1896             FT_UINT64, BASE_DEC_HEX, NULL, 0x00,
1897             "This member holds the section header table's file offset in bytes. If the file has no section header table, this member holds zero.", HFILL }
1898         },
1899         { &hf_elf_flags, /* TODO: dissect flags */
1900             { "Flags",                                     "elf.flags",
1901             FT_UINT32, BASE_HEX, NULL, 0x00,
1902             "This member holds processor-specific flags associated with the file. Flag names take the form EF_machine_flag.", HFILL }
1903         },
1904         { &hf_elf_ehsize,
1905             { "ELF Header Size",                           "elf.ehsize",
1906             FT_UINT16, BASE_DEC_HEX, NULL, 0x00,
1907             "This member holds the ELF header's size in bytes.", HFILL }
1908         },
1909         { &hf_elf_phentsize,
1910             { "Entry Size in Program Header Table",        "elf.phentsize",
1911             FT_UINT16, BASE_DEC_HEX, NULL, 0x00,
1912             "This member holds the size in bytes of one entry in the file's program header table; all entries are the same size.", HFILL }
1913         },
1914         { &hf_elf_phnum,
1915             { "Number of Entries in the Program Header Table",  "elf.phnum",
1916             FT_UINT16, BASE_DEC_HEX, NULL, 0x00,
1917             "This member holds the number of entries in the program header table. Thus the product of e_phentsize and e_phnum gives the table's size in bytes. If a file has no program header table, e_phnum holds the value zero.", HFILL }
1918         },
1919         { &hf_elf_shentsize,
1920             { "Entry Size in Section Header Table",        "elf.shentsize",
1921             FT_UINT16, BASE_DEC_HEX, NULL, 0x00,
1922             "This member holds a section header's size in bytes. A section header is one entry in the section header table; all entries are the same size.", HFILL }
1923         },
1924         { &hf_elf_shnum,
1925             { "Number of Entries in the Section Header Table",  "elf.shnum",
1926             FT_UINT16, BASE_DEC_HEX, NULL, 0x00,
1927             "This member holds the number of entries in the section header table. Thus the product of e_shentsize and e_shnum gives the section header table's size in bytes. If a file has no section header table, e_shnum holds the value zero.", HFILL }
1928         },
1929         { &hf_elf_shstrndx,
1930             { "Section Header Table String Index",         "elf.shstrndx",
1931             FT_UINT16, BASE_DEC_HEX, NULL, 0x00,
1932             "This member holds the section header table index of the entry associated with the section name string table. If the file has no section name string table, this member holds the value SHN_UNDEF.", HFILL }
1933         },
1934         /* Program Header */
1935         { &hf_elf_p_type,
1936             { "Element Type",                              "elf.p_type",
1937             FT_UINT32, BASE_HEX_DEC, VALS(p_type_vals), 0x00,
1938             "This member tells what kind of segment this array element describes or how to interpret the array element's information.", HFILL }
1939         },
1940         { &hf_elf_p_type_operating_system_specific,
1941             { "Element Type: Operating System Specific",   "elf.p_type",
1942             FT_UINT32, BASE_HEX_DEC, NULL, 0x00,
1943             "This member tells what kind of segment this array element describes or how to interpret the array element's information.", HFILL }
1944         },
1945         { &hf_elf_p_type_processor_specific,
1946             { "Element Type: Processor Specific",          "elf.p_type",
1947             FT_UINT32, BASE_HEX_DEC, NULL, 0x00,
1948             "This member tells what kind of segment this array element describes or how to interpret the array element's information.", HFILL }
1949         },
1950         { &hf_elf_p_offset,
1951             { "File Offset",                               "elf.p_offset",
1952             FT_UINT32, BASE_DEC_HEX, NULL, 0x00,
1953             "This member gives the offset from the beginning of the file at which the first byte of the segment resides.", HFILL }
1954         },
1955         { &hf_elf64_p_offset,
1956             { "File Offset",                               "elf.p_offset64",
1957             FT_UINT64, BASE_DEC_HEX, NULL, 0x00,
1958             "This member gives the offset from the beginning of the file at which the first byte of the segment resides.", HFILL }
1959         },
1960         { &hf_elf_p_vaddr,
1961             { "Virtual Address",                           "elf.p_vaddr",
1962             FT_UINT32, BASE_HEX, NULL, 0x00,
1963             "This member gives the virtual address at which the first byte of the segment resides in memory.", HFILL }
1964         },
1965         { &hf_elf64_p_vaddr,
1966             { "Virtual Address",                           "elf.p_vaddr64",
1967             FT_UINT64, BASE_HEX, NULL, 0x00,
1968             "This member gives the virtual address at which the first byte of the segment resides in memory.", HFILL }
1969         },
1970         { &hf_elf_p_paddr,
1971             { "Physical Address",                          "elf.p_paddr",
1972             FT_UINT32, BASE_HEX, NULL, 0x00,
1973             "On systems for which physical addressing is relevant, this member is reserved for the segment's physical address. Because System V ignores physical addressing for application programs, this member has unspecified contents for executable files and shared objects.", HFILL }
1974         },
1975         { &hf_elf64_p_paddr,
1976             { "Physical Address",                          "elf.p_paddr64",
1977             FT_UINT64, BASE_HEX, NULL, 0x00,
1978             "On systems for which physical addressing is relevant, this member is reserved for the segment's physical address. Because System V ignores physical addressing for application programs, this member has unspecified contents for executable files and shared objects.", HFILL }
1979         },
1980         { &hf_elf_p_filesz,
1981             { "File Image Size",                           "elf.p_filesz",
1982             FT_UINT32, BASE_DEC_HEX, NULL, 0x00,
1983             "This member gives the number of bytes in the file image of the segment; it may be zero.", HFILL }
1984         },
1985         { &hf_elf64_p_filesz,
1986             { "File Image Size",                           "elf.p_filesz64",
1987             FT_UINT64, BASE_DEC_HEX, NULL, 0x00,
1988             "This member gives the number of bytes in the file image of the segment; it may be zero.", HFILL }
1989         },
1990         { &hf_elf_p_memsz,
1991             { "Memory Image Size",                         "elf.p_memsz",
1992             FT_UINT32, BASE_DEC_HEX, NULL, 0x00,
1993             "This member gives the number of bytes in the memory image of the segment; it may be zero.", HFILL }
1994         },
1995         { &hf_elf64_p_memsz,
1996             { "Memory Image Size",                         "elf.p_memsz64",
1997             FT_UINT64, BASE_DEC_HEX, NULL, 0x00,
1998             "This member gives the number of bytes in the memory image of the segment; it may be zero.", HFILL }
1999         },
2000         { &hf_elf_p_flags_processor_specific,
2001             { "Processor Specific Flags",                  "elf.p_flags.maskproc",
2002             FT_BOOLEAN, 32, NULL, 0xF0000000,
2003             NULL, HFILL }
2004         },
2005         { &hf_elf_p_flags_operating_system_specific,
2006             { "Operating System Specific Flags",           "elf.p_flags.maskos",
2007             FT_BOOLEAN, 32, NULL, 0x0FF00000,
2008             NULL, HFILL }
2009         },
2010         { &hf_elf_p_flags_reserved,
2011             { "Reserved Flags",                            "elf.p_flags.reserved",
2012             FT_BOOLEAN, 32, NULL, 0x000FFFF8,
2013             NULL, HFILL }
2014         },
2015         { &hf_elf_p_flags_read,
2016             { "Read Flag",                                 "elf.p_flags.read",
2017             FT_BOOLEAN, 32, NULL, 0x00000004,
2018             NULL, HFILL }
2019         },
2020         { &hf_elf_p_flags_write,
2021             { "Write Flag",                                "elf.p_flags.write",
2022             FT_BOOLEAN, 32, NULL, 0x00000002,
2023             NULL, HFILL }
2024         },
2025         { &hf_elf_p_flags_execute,
2026             { "Execute Flag",                              "elf.p_flags.execute",
2027             FT_BOOLEAN, 32, NULL, 0x00000001,
2028             NULL, HFILL }
2029         },
2030         { &hf_elf_p_align,
2031             { "Align",                                     "elf.p_align",
2032             FT_UINT32, BASE_DEC_HEX, NULL, 0x00,
2033             "This member gives the value to which the segments are aligned in memory and in the file. Values 0 and 1 mean no alignment is required. Otherwise, p_align should be a positive, integral power of 2, and p_vaddr should equal p_offset, modulo p_align.", HFILL }
2034         },
2035         { &hf_elf64_p_align,
2036             { "Align",                                     "elf.p_align64",
2037             FT_UINT64, BASE_DEC_HEX, NULL, 0x00,
2038             "This member gives the value to which the segments are aligned in memory and in the file. Values 0 and 1 mean no alignment is required. Otherwise, p_align should be a positive, integral power of 2, and p_vaddr should equal p_offset, modulo p_align.", HFILL }
2039         },
2040         /* Section Header */
2041         { &hf_elf_sh_name,
2042             { "Name Index",                                "elf.sh_name",
2043             FT_UINT32, BASE_DEC_HEX, NULL, 0x00,
2044             "Section Name. Its value is an index into the section header string table section, giving the location of a null-terminated string.", HFILL }
2045         },
2046         { &hf_elf_sh_type,
2047             { "Type",                                      "elf.sh_type",
2048             FT_UINT32, BASE_HEX_DEC | BASE_EXT_STRING, &sh_type_vals_ext, 0x00,
2049             "This member categorizes the section's contents and semantics.", HFILL }
2050         },
2051         { &hf_elf_sh_type_operating_system_specific,
2052             { "Type: Operating System Specific",           "elf.sh_type",
2053             FT_UINT32, BASE_HEX_DEC, NULL, 0x00,
2054             "This member categorizes the section's contents and semantics.", HFILL }
2055         },
2056         { &hf_elf_sh_type_processor_specific,
2057             { "Type: Processor Specific",                  "elf.sh_type",
2058             FT_UINT32, BASE_HEX_DEC, NULL, 0x00,
2059             "This member categorizes the section's contents and semantics.", HFILL }
2060         },
2061         { &hf_elf_sh_type_user_specific,
2062             { "Type: User Specific",                       "elf.sh_type",
2063             FT_UINT32, BASE_HEX_DEC, NULL, 0x00,
2064             "This member categorizes the section's contents and semantics.", HFILL }
2065         },
2066         { &hf_elf_sh_flags_processor_specific,
2067             { "Processor Specific Flags",                  "elf.sh_flags.maskproc",
2068             FT_BOOLEAN, 32, NULL, 0xF0000000,
2069             NULL, HFILL }
2070         },
2071         { &hf_elf_sh_flags_operating_system_specific,
2072             { "Operating System Specific Flags",           "elf.sh_flags.maskos",
2073             FT_BOOLEAN, 32, NULL, 0x0FF00000,
2074             NULL, HFILL }
2075         },
2076         { &hf_elf_sh_flags_reserved,
2077             { "Reserved",                                  "elf.sh_flags.reserved",
2078             FT_BOOLEAN, 32, NULL, 0x000FF800,
2079             NULL, HFILL }
2080         },
2081         { &hf_elf_sh_flags_tls,
2082             { "TLS Flag",                                  "elf.sh_flags.tls",
2083             FT_BOOLEAN, 32, NULL, 0x00000400,
2084             "This section holds Thread-Local Storage, meaning that each separate execution flow has its own distinct instance of this data. Implementations need not support this flag.", HFILL }
2085         },
2086         { &hf_elf_sh_flags_group,
2087             { "Group Flag",                                "elf.sh_flags.group",
2088             FT_BOOLEAN, 32, NULL, 0x00000200,
2089             "This section is a member (perhaps the only one) of a section group.", HFILL }
2090         },
2091         { &hf_elf_sh_flags_os_nonconforming,
2092             { "OS NonConforming Flag",                     "elf.sh_flags.os_nonconforming",
2093             FT_BOOLEAN, 32, NULL, 0x00000100,
2094             "This section requires special OS-specific processing to avoid incorrect behavior.", HFILL }
2095         },
2096         { &hf_elf_sh_flags_link_order,
2097             { "Link Order Flag",                           "elf.sh_flags.link_order",
2098             FT_BOOLEAN, 32, NULL, 0x00000080,
2099             "This flag adds special ordering requirements for link editors.", HFILL }
2100         },
2101         { &hf_elf_sh_flags_info_link,
2102             { "Info Link Flag",                            "elf.sh_flags.info_link",
2103             FT_BOOLEAN, 32, NULL, 0x00000040,
2104             "The sh_info field of this section header holds a section header table index.", HFILL }
2105         },
2106         { &hf_elf_sh_flags_strings,
2107             { "Strings Flag",                              "elf.sh_flags.strings",
2108             FT_BOOLEAN, 32, NULL, 0x00000020,
2109             "The data elements in the section consist of null-terminated character strings. The size of each character is specified in the section header's sh_entsize field.", HFILL }
2110         },
2111         { &hf_elf_sh_flags_merge,
2112             { "Merge Flag",                                "elf.sh_flags.merge",
2113             FT_BOOLEAN, 32, NULL, 0x00000010,
2114             "The data in the section may be merged to eliminate duplication.", HFILL }
2115         },
2116         { &hf_elf_sh_flags_reserved_8,
2117             { "Reserved",                                  "elf.sh_flags.reserved.8",
2118             FT_BOOLEAN, 32, NULL, 0x00000008,
2119             NULL, HFILL }
2120         },
2121         { &hf_elf_sh_flags_exec_instr,
2122             { "Exec Instr Flag",                           "elf.sh_flags.exec_instr",
2123             FT_BOOLEAN, 32, NULL, 0x00000004,
2124             "The section contains executable machine instructions.", HFILL }
2125         },
2126         { &hf_elf_sh_flags_alloc,
2127             { "Alloc Flag",                                "elf.sh_flags.alloc",
2128             FT_BOOLEAN, 32, NULL, 0x00000002,
2129             "The section occupies memory during process execution. Some control sections do not reside in the memory image of an object file; this attribute is off for those sections.", HFILL }
2130         },
2131         { &hf_elf_sh_flags_write,
2132             { "Write Flag",                                "elf.sh_flags.write",
2133             FT_BOOLEAN, 32, NULL, 0x00000001,
2134             "The section contains data that should be writable during process execution.", HFILL }
2135         },
2136         { &hf_elf_sh_addr,
2137             { "Address",                                   "elf.sh_addr",
2138             FT_UINT32, BASE_HEX, NULL, 0x00,
2139             "If the section will appear in the memory image of a process, this member gives the address at which the section's first byte should reside. Otherwise, the member contains 0.", HFILL }
2140         },
2141         { &hf_elf64_sh_addr,
2142             { "Address",                                   "elf.sh_addr64",
2143             FT_UINT64, BASE_HEX, NULL, 0x00,
2144             "If the section will appear in the memory image of a process, this member gives the address at which the section's first byte should reside. Otherwise, the member contains 0.", HFILL }
2145         },
2146         { &hf_elf_sh_offset,
2147             { "File Offset",                               "elf.sh_offset",
2148             FT_UINT32, BASE_DEC_HEX, NULL, 0x00,
2149             "This member's value gives the byte offset from the beginning of the file to the first byte in the section. One section type, SHT_NOBITS, occupies no space in the file, and its sh_offset member locates the conceptual placement in the file.", HFILL }
2150         },
2151         { &hf_elf64_sh_offset,
2152             { "File Offset",                               "elf.sh_offset64",
2153             FT_UINT64, BASE_DEC_HEX, NULL, 0x00,
2154             "This member's value gives the byte offset from the beginning of the file to the first byte in the section. One section type, SHT_NOBITS, occupies no space in the file, and its sh_offset member locates the conceptual placement in the file.", HFILL }
2155         },
2156         { &hf_elf_sh_size,
2157             { "Size",                                      "elf.sh_size",
2158             FT_UINT32, BASE_DEC_HEX, NULL, 0x00,
2159             "This member gives the section's size in bytes.", HFILL }
2160         },
2161         { &hf_elf64_sh_size,
2162             { "Size",                                      "elf.sh_size64",
2163             FT_UINT64, BASE_DEC_HEX, NULL, 0x00,
2164             "This member gives the section's size in bytes.", HFILL }
2165         },
2166 
2167         { &hf_elf_sh_link,
2168             { "Link Index",                                "elf.sh_link",
2169             FT_UINT32, BASE_DEC_HEX, NULL, 0x00,
2170             "This member holds a section header table index link, whose interpretation depends on the section type.", HFILL }
2171         },
2172         { &hf_elf_sh_info,
2173             { "Info",                                      "elf.sh_info",
2174             FT_UINT32, BASE_DEC_HEX, NULL, 0x00,
2175             "This member holds extra information, whose interpretation depends on the section type.", HFILL }
2176         },
2177         { &hf_elf_sh_addralign,
2178             { "Address Alignment",                         "elf.sh_addralign",
2179             FT_UINT32, BASE_HEX, NULL, 0x00,
2180             "Some sections have address alignment constraints. Currently, only 0 and positive integral powers of two are allowed. Values 0 and 1 mean the section has no alignment constraints.", HFILL }
2181         },
2182         { &hf_elf64_sh_addralign,
2183             { "Address Alignment",                         "elf.sh_addralign64",
2184             FT_UINT64, BASE_HEX, NULL, 0x00,
2185             "Some sections have address alignment constraints. Currently, only 0 and positive integral powers of two are allowed. Values 0 and 1 mean the section has no alignment constraints.", HFILL }
2186         },
2187         { &hf_elf_sh_entsize,
2188             { "Entry Size",                                "elf.sh_entsize",
2189             FT_UINT32, BASE_DEC_HEX, NULL, 0x00,
2190             "Some sections hold a table of fixed-size entries, such as a symbol table. For such a section, this member gives the size in bytes of each entry. The member contains 0 if the section does not hold a table of fixed-size entries.", HFILL }
2191         },
2192         { &hf_elf64_sh_entsize,
2193             { "Entry Size",                                "elf.sh_entsize64",
2194             FT_UINT64, BASE_DEC_HEX, NULL, 0x00,
2195             "Some sections hold a table of fixed-size entries, such as a symbol table. For such a section, this member gives the size in bytes of each entry. The member contains 0 if the section does not hold a table of fixed-size entries.", HFILL }
2196         },
2197         /* .eh_frame */
2198         { &hf_elf_eh_frame_length,
2199             { "Length",                                    "elf.eh_frame.length",
2200             FT_UINT32, BASE_DEC_HEX, NULL, 0x00,
2201             "Length of CIE. Zero indicates a terminator, 0xffffffff means that "
2202             "the Extended Length field contains the actual length.", HFILL }
2203         },
2204         { &hf_elf_eh_frame_extended_length,
2205             { "Extended Length",                           "elf.eh_frame.extended_length",
2206             FT_UINT64, BASE_DEC_HEX, NULL, 0x00,
2207             "Extended Length of CIE.", HFILL }
2208         },
2209         { &hf_elf_eh_frame_cie_id,
2210             { "CIE ID",                                    "elf.eh_frame.cie_id",
2211             FT_UINT32, BASE_DEC_HEX, NULL, 0x00,
2212             "A 4 byte unsigned value that is used to distinguish CIE records from FDE records. This value shall always be 0, which indicates this record is a CIE.", HFILL }
2213         },
2214         { &hf_elf_eh_frame_version,
2215             { "Version",                                   "elf.eh_frame.version",
2216             FT_UINT8, BASE_DEC_HEX, NULL, 0x00,
2217             "A 1 byte value that identifies the version number of the frame information structure. This value shall be 1.", HFILL }
2218         },
2219         { &hf_elf_eh_frame_augmentation_string,
2220             { "Augmentation String",                       "elf.eh_frame.augmentation_string",
2221             FT_STRINGZ, BASE_NONE, NULL, 0x00,
2222             "This value is a NUL terminated string that identifies the augmentation to the CIE or to the FDEs associated with this CIE. A zero length string indicates that no augmentation data is present. The augmentation string is case sensitive.", HFILL }
2223         },
2224         { &hf_elf_eh_frame_code_alignment_factor,
2225             { "Code Alignment Factor",                     "elf.eh_frame.code_alignment_factor",
2226             FT_UINT64, BASE_DEC, NULL, 0x00,
2227             "An unsigned LEB128 encoded value that is factored out of all advance location instructions that are associated with this CIE or its FDEs. This value shall be multiplied by the delta argument of an adavance location instruction to obtain the new location value.", HFILL }
2228         },
2229         { &hf_elf_eh_frame_data_alignment_factor,
2230             { "Data Alignment Factor",                     "elf.eh_frame.data_alignment_factor",
2231             FT_INT64, BASE_DEC, NULL, 0x00,
2232             "A signed LEB128 encoded value that is factored out of all offset instructions that are associated with this CIE or its FDEs. This value shall be multiplied by the register offset argument of an offset instruction to obtain the new offset value.", HFILL }
2233         },
2234         { &hf_elf_eh_frame_return_address_register,
2235             { "Return Address Register",                   "elf.eh_frame.return_address_register",
2236             FT_UINT64, BASE_DEC, NULL, 0x00,
2237             "An unsigned LEB128 constant that indicates which column in the rule table represents the return address of the function. Note that this column might not correspond to an actual machine register.", HFILL }
2238         },
2239         { &hf_elf_eh_frame_augmentation_length,
2240             { "Augmentation Length",                       "elf.eh_frame.augmentation_length",
2241             FT_UINT64, BASE_DEC, NULL, 0x00,
2242             "An unsigned LEB128 encoded value indicating the length in bytes of the Augmentation Data. This field is only present if the Augmentation String contains the character 'z'.", HFILL }
2243         },
2244         { &hf_elf_eh_frame_augmentation_data,
2245             { "Augmentation Data",                         "elf.eh_frame.augmentation_data",
2246             FT_BYTES, BASE_NONE, NULL, 0x00,
2247             "A block of data whose contents are defined by the contents of the Augmentation String as described below. This field is only present if the Augmentation String contains the character 'z'.", HFILL }
2248         },
2249         { &hf_elf_eh_frame_initial_instructions,
2250             { "Initial Instructions",                      "elf.eh_frame.initial_instructions",
2251             FT_BYTES, BASE_NONE, NULL, 0x00,
2252             "Initial set of Call Frame Instructions.", HFILL }
2253         },
2254         /* .eh_frame fde */
2255         { &hf_elf_eh_frame_fde_length,
2256             { "Length",                                    "elf.eh_frame.fde.length",
2257             FT_UINT32, BASE_DEC_HEX, NULL, 0x00,
2258             "Length of FDE. Zero indicates a terminator, 0xffffffff means that "
2259             "the Extended Length field contains the actual length.", HFILL }
2260         },
2261         { &hf_elf_eh_frame_fde_extended_length,
2262             { "Extended Length",                           "elf.eh_frame.fde.extended_length",
2263             FT_UINT64, BASE_DEC_HEX, NULL, 0x00,
2264             "Extended Length of FDE.", HFILL }
2265         },
2266         { &hf_elf_eh_frame_fde_cie_pointer,
2267             { "CIE Pointer",                               "elf.eh_frame.fde.cie_pointer",
2268             FT_UINT32, BASE_DEC_HEX, NULL, 0x00,
2269             "A 4 byte unsigned value that when subtracted from the offset of the the CIE Pointer in the current FDE yields the offset of the start of the associated CIE. This value shall never be 0.", HFILL }
2270         },
2271         { &hf_elf_eh_frame_fde_pc_begin,
2272             { "PC Begin",                                  "elf.eh_frame.fde.pc_begin",
2273             FT_UINT32, BASE_HEX, NULL, 0x00,
2274             "An encoded value that indicates the address of the initial location associated with this FDE. The encoding format is specified in the Augmentation Data.", HFILL }
2275         },
2276         { &hf_elf_eh_frame_fde_pc_range,
2277             { "PC Range",                                  "elf.eh_frame.fde.pc_range",
2278             FT_UINT32, BASE_DEC_HEX, NULL, 0x00,
2279             "An absolute value that indicates the number of bytes of instructions associated with this FDE.", HFILL }
2280         },
2281         { &hf_elf_eh_frame_fde_augmentation_length,
2282             { "Augmentation Length",                       "elf.eh_frame.fde.augmentation_length",
2283             FT_UINT64, BASE_DEC, NULL, 0x00,
2284             "An unsigned LEB128 encoded value indicating the length in bytes of the Augmentation Data.", HFILL }
2285         },
2286         { &hf_elf_eh_frame_fde_augmentation_data,
2287             { "Augmentation Data",                         "elf.eh_frame.fde.augmentation_data",
2288             FT_BYTES, BASE_NONE, NULL, 0x00,
2289             "Data as described by the Augmentation String in the CIE.", HFILL }
2290         },
2291         { &hf_elf_eh_frame_fde_call_frame_instructions,
2292             { "Call Frame Instructions",                   "elf.eh_frame.fde.call_frame_instructions",
2293             FT_BYTES, BASE_NONE, NULL, 0x00,
2294             "A set of Call Frame Instructions.", HFILL }
2295         },
2296         /* .eh_frame_hdr */
2297         { &hf_elf_eh_frame_hdr_version,
2298             { "Version",                                   "elf.eh_frame_hdr.version",
2299             FT_UINT8, BASE_DEC_HEX, NULL, 0x00,
2300             "Version of the .eh_frame_hdr format. This value shall be 1.", HFILL }
2301         },
2302         { &hf_elf_eh_frame_hdr_exception_frame_pointer_encoding,
2303             { "Exception Frame Pointer Encoding",           "elf.eh_frame_hdr.eh_frame_ptr_enc",
2304             FT_UINT8, BASE_DEC_HEX, NULL, 0x00,
2305             "The encoding format of the eh_frame_ptr field.", HFILL }
2306         },
2307         { &hf_elf_eh_frame_hdr_fde_count_encoding,
2308             { "FDE Count Encoding",                        "elf.eh_frame_hdr.fde_count_enc",
2309             FT_UINT8, BASE_DEC_HEX, NULL, 0x00,
2310             "The encoding format of the fde_count field. A value of DW_EH_PE_omit indicates the binary search table is not present.", HFILL }
2311         },
2312         { &hf_elf_eh_frame_hdr_binary_search_table_encoding,
2313             { "Binary Search Table Encoding",              "elf.eh_frame_hdr.binary_search_table_encoding",
2314             FT_UINT8, BASE_DEC_HEX, NULL, 0x00,
2315             "The encoding format of the entries in the binary search table. A value of DW_EH_PE_omit indicates the binary search table is not present.", HFILL }
2316         },
2317 
2318 
2319         { &hf_elf_eh_frame_hdr_eh_frame_ptr,
2320             { "Exception Frame Pointer",                    "elf.eh_frame_hdr.eh_frame_ptr",
2321             FT_BYTES, BASE_NONE, NULL, 0x00,
2322             "Start of .eh_frame pointer", HFILL }
2323         },
2324         { &hf_elf_eh_frame_hdr_fde_count,
2325             { "Number of FDE entries",                     "elf.eh_frame_hdr.fde_count",
2326             FT_UINT64, BASE_DEC, NULL, 0x00,
2327             NULL, HFILL }
2328         },
2329         { &hf_elf_eh_frame_hdr_binary_search_table_entry_initial_location,
2330             { "Initial location",                          "elf.eh_frame_hdr.binary_search_table_entry.initial_location",
2331             FT_BYTES, BASE_NONE, NULL, 0x00,
2332             NULL, HFILL }
2333         },
2334         { &hf_elf_eh_frame_hdr_binary_search_table_entry_address,
2335             { "Address",                                   "elf.eh_frame_hdr.binary_search_table_entry.address",
2336             FT_BYTES, BASE_NONE, NULL, 0x00,
2337             NULL, HFILL }
2338         },
2339 
2340         /* symbol_table */
2341         { &hf_elf_symbol_table_name_index,
2342             { "Name Index",                               "elf.symbol_table.name_index",
2343             FT_UINT32, BASE_DEC, NULL, 0x00,
2344             NULL, HFILL }
2345         },
2346         { &hf_elf_symbol_table_info,
2347             { "Info",                                      "elf.symbol_table.info",
2348             FT_UINT8, BASE_HEX, NULL, 0x00,
2349             NULL, HFILL }
2350         },
2351         { &hf_elf_symbol_table_info_bind,
2352             { "Bind",                                      "elf.symbol_table.info.bind",
2353             FT_UINT8, BASE_HEX, VALS(symbol_table_info_bind_vals), 0xF0,
2354             NULL, HFILL }
2355         },
2356         { &hf_elf_symbol_table_info_type,
2357             { "Type",                                      "elf.symbol_table.info.type",
2358             FT_UINT8, BASE_HEX | BASE_EXT_STRING, &symbol_table_info_type_vals_ext, 0x0F,
2359             NULL, HFILL }
2360         },
2361         { &hf_elf_symbol_table_other,
2362             { "Other",                                     "elf.symbol_table.other",
2363             FT_UINT8, BASE_HEX, VALS(symbol_table_other_vals), 0x00,
2364             NULL, HFILL }
2365         },
2366         { &hf_elf_symbol_table_shndx,
2367             { "Related Section Header Index",             "elf.symbol_table.shndx",
2368             FT_UINT16, BASE_HEX | BASE_RANGE_STRING, RVALS(symbol_table_shndx_rvals), 0x00,
2369             NULL, HFILL }
2370         },
2371         { &hf_elf_symbol_table_value,
2372             { "Value",                                     "elf.symbol_table.value",
2373             FT_UINT32, BASE_HEX, NULL, 0x00,
2374             NULL, HFILL }
2375         },
2376         { &hf_elf64_symbol_table_value,
2377             { "Value",                                     "elf.symbol_table.value64",
2378             FT_UINT64, BASE_HEX, NULL, 0x00,
2379             NULL, HFILL }
2380         },
2381         { &hf_elf_symbol_table_size,
2382             { "Size",                                      "elf.symbol_table.size",
2383             FT_UINT32, BASE_DEC_HEX, NULL, 0x00,
2384             NULL, HFILL }
2385         },
2386         { &hf_elf64_symbol_table_size,
2387             { "Size",                                      "elf.symbol_table.size64",
2388             FT_UINT64, BASE_DEC_HEX, NULL, 0x00,
2389             NULL, HFILL }
2390         },
2391 
2392         /* dynamic */
2393         { &hf_elf_dynamic_tag,
2394             { "Tag",                                       "elf.dynamic.tag",
2395             FT_UINT32, BASE_HEX | BASE_RANGE_STRING, RVALS(dynamic_tag_rvals), 0x00,
2396             NULL, HFILL }
2397         },
2398         { &hf_elf_dynamic_value,
2399             { "Value",                                     "elf.dynamic.value",
2400             FT_UINT32, BASE_DEC_HEX, NULL, 0x00,
2401             NULL, HFILL }
2402         },
2403         { &hf_elf_dynamic_pointer,
2404             { "Pointer",                                   "elf.dynamic.pointer",
2405             FT_UINT32, BASE_HEX, NULL, 0x00,
2406             NULL, HFILL }
2407         },
2408         { &hf_elf_dynamic_ignored,
2409             { "Ignored",                                   "elf.dynamic.ignored",
2410             FT_UINT32, BASE_HEX, NULL, 0x00,
2411             NULL, HFILL }
2412         },
2413         { &hf_elf_dynamic_unspecified,
2414             { "Unspecified",                               "elf.dynamic.unspecified",
2415             FT_UINT32, BASE_DEC_HEX, NULL, 0x00,
2416             NULL, HFILL }
2417         },
2418         { &hf_elf64_dynamic_tag,
2419             { "Tag",                                       "elf.dynamic.tag64",
2420             FT_UINT64, BASE_HEX /*| BASE_RANGE_STRING*/, NULL /*RVALS(dynamic_tag_rvals)*/, 0x00,
2421             NULL, HFILL }
2422         },
2423         { &hf_elf64_dynamic_value,
2424             { "Value",                                     "elf.dynamic.value64",
2425             FT_UINT64, BASE_DEC_HEX, NULL, 0x00,
2426             NULL, HFILL }
2427         },
2428         { &hf_elf64_dynamic_pointer,
2429             { "Pointer",                                   "elf.dynamic.pointer64",
2430             FT_UINT64, BASE_HEX, NULL, 0x00,
2431             NULL, HFILL }
2432         },
2433         { &hf_elf64_dynamic_ignored,
2434             { "Ignored",                                   "elf.dynamic.ignored64",
2435             FT_UINT64, BASE_HEX, NULL, 0x00,
2436             NULL, HFILL }
2437         },
2438         { &hf_elf64_dynamic_unspecified,
2439             { "Unspecified",                               "elf.dynamic.unspecified64",
2440             FT_UINT64, BASE_DEC_HEX, NULL, 0x00,
2441             NULL, HFILL }
2442         },
2443 
2444         /* dwarf */
2445         { &hf_dwarf_omit,
2446             { "DW_EH_PE_omit",                             "elf.dwarf.omit",
2447             FT_UINT8, BASE_HEX, NULL, 0x00,
2448             "Used to indicate that no value is present.", HFILL }
2449         },
2450         { &hf_dwarf_upper,
2451             { "DWARF Exception Header application",        "elf.dwarf.upper",
2452             FT_UINT8, BASE_HEX, VALS(eh_dwarf_upper), 0xF0,
2453             "The upper 4 bits indicate how the value is to be applied.", HFILL }
2454         },
2455         { &hf_dwarf_format,
2456             { "DWARF Exception Header value format",       "elf.dwarf.format",
2457             FT_UINT8, BASE_HEX, VALS(eh_dwarf_format), 0x0F,
2458             "The lower 4 bits indicate the format of the data.", HFILL }
2459         },
2460         { &hf_elf_string,
2461             { "String",                                    "elf.string",
2462             FT_STRINGZ, BASE_NONE, NULL, 0x00,
2463             NULL, HFILL }
2464         }
2465     };
2466 
2467     static ei_register_info ei[] = {
2468         { &ei_invalid_segment_size, { "elf.invalid_segment_size", PI_PROTOCOL, PI_WARN, "Segment size is different then currently parsed bytes", EXPFILL }},
2469         { &ei_invalid_entry_size,   { "elf.invalid_entry_size", PI_PROTOCOL, PI_WARN, "Entry size is different then currently parsed bytes", EXPFILL }},
2470         { &ei_cfi_extraneous_data,  { "elf.cfi_extraneous_data", PI_PROTOCOL, PI_WARN, "Segment size is larger than CFI records combined", EXPFILL }},
2471         { &ei_invalid_cie_length,   { "elf.invalid_cie_length", PI_PROTOCOL, PI_ERROR, "CIE length is too small or larger than segment size", EXPFILL }},
2472     };
2473 
2474     static gint *ett[] = {
2475         &ett_elf,
2476         &ett_elf_header,
2477         &ett_elf_program_header,
2478         &ett_elf_program_header_entry,
2479         &ett_elf_section_header,
2480         &ett_elf_section_header_entry,
2481         &ett_elf_segment,
2482         &ett_elf_cfi_record,
2483         &ett_elf_cie_entry,
2484         &ett_elf_fde_entry,
2485         &ett_elf_cie_terminator,
2486         &ett_elf_info,
2487         &ett_elf_black_holes,
2488         &ett_elf_overlapping,
2489         &ett_dwarf_encoding,
2490         &ett_binary_table,
2491         &ett_binary_table_entry,
2492         &ett_symbol_table_entry,
2493         &ett_symbol_table_info
2494     };
2495 
2496     proto_elf = proto_register_protocol("Executable and Linkable Format", "ELF", "elf");
2497     proto_register_field_array(proto_elf, hf, array_length(hf));
2498     proto_register_subtree_array(ett, array_length(ett));
2499 
2500     elf_handle = register_dissector("elf", dissect_elf, proto_elf);
2501 
2502     module = prefs_register_protocol(proto_elf, NULL);
2503     prefs_register_static_text_preference(module, "version",
2504             "ELF version: 4.1 DRAFT",
2505             "Version of file-format supported by this dissector.");
2506 
2507     expert_module = expert_register_protocol(proto_elf);
2508     expert_register_field_array(expert_module, ei, array_length(ei));
2509 }
2510 
2511 void
proto_reg_handoff_elf(void)2512 proto_reg_handoff_elf(void)
2513 {
2514     dissector_add_string("media_type", "application/x-executable", elf_handle);
2515     dissector_add_string("media_type", "application/x-coredump", elf_handle);
2516     dissector_add_string("media_type", "application/x-object", elf_handle);
2517     dissector_add_string("media_type", "application/x-sharedlib", elf_handle);
2518 
2519     /* XXX - TEMPORARY HACK */
2520     dissector_add_uint("ftap_encap", 1234, elf_handle);
2521 
2522     heur_dissector_add("wtap_file", dissect_elf_heur, "ELF file", "elf_wtap", proto_elf, HEURISTIC_ENABLE);
2523 }
2524 
2525 /*
2526  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
2527  *
2528  * Local variables:
2529  * c-basic-offset: 4
2530  * tab-width: 8
2531  * indent-tabs-mode: nil
2532  * End:
2533  *
2534  * vi: set shiftwidth=4 tabstop=8 expandtab:
2535  * :indentSize=4:tabSize=8:noTabs=true:
2536  */
2537