88sys .path .insert (1 , os .path .abspath (sys .path [0 ]+ '/..' ))
99from elfesteem import elf_init , elf
1010
11+ import subprocess
12+ def popen_read_out_err (cmd ):
13+ p = subprocess .Popen (cmd , stdin = subprocess .PIPE , stdout = subprocess .PIPE , stderr = subprocess .PIPE )
14+ p .wait ()
15+ p .stdin .close ()
16+ return p .stdout .read () + p .stderr .read ()
17+
18+ import re
19+ def get_readelf_version ():
20+ readelf_v = popen_read_out_err (["readelf" , "--version" ])
21+ if type (readelf_v ) != str : readelf_v = str (readelf_v , encoding = 'latin1' )
22+ r = re .search (r'GNU readelf .* (\d+\.\d+)' , readelf_v )
23+ if r :
24+ sys .stderr .write ("readelf version %s\n " % float (r .groups ()[0 ]))
25+ return float (r .groups ()[0 ])
26+ else :
27+ sys .stderr .write ("Could not detect readelf version\n " )
28+ sys .stderr .write (readelf_v )
29+ return None
30+
1131et_strings = {
1232 elf .ET_REL : 'REL (Relocatable file)' ,
1333 elf .ET_EXEC : 'EXEC (Executable file)' ,
@@ -18,11 +38,26 @@ def expand_code(table, val):
1838 if val in table : return table [val ]
1939 return '<unknown>: %#x' % val
2040
41+ def is_pie (e ):
42+ # binutils 2.37
43+ # 2021-06-15 https://github.com/bminor/binutils-gdb/commit/93df3340fd5ad32f784214fc125de71811da72ff
44+ for i , sh in enumerate (e .sh ):
45+ if sh .sh .type != elf .SHT_DYNAMIC :
46+ continue
47+ if e .wsize == 32 :
48+ dyntab = sh .dyntab [:- 2 ]
49+ elif e .wsize == 64 :
50+ dyntab = sh .dyntab [:- 1 ]
51+ for d in dyntab :
52+ if d .type == elf .DT_FLAGS_1 and d .name & elf .DF_1_PIE :
53+ return True
54+ return False
55+
2156def display_headers (e ):
2257 print ("ELF Header:" )
2358 import struct
2459 ident = struct .unpack ('16B' , e .Ehdr .ident )
25- print (" Magic: %s" % ' ' .join (['%02x' % _ for _ in ident ]))
60+ print (" Magic: %s " % ' ' .join (['%02x' % _ for _ in ident ]))
2661 print (" Class: %s" % expand_code ({
2762 elf .ELFCLASS32 : 'ELF32' ,
2863 elf .ELFCLASS64 : 'ELF64' ,
@@ -38,7 +73,10 @@ def display_headers(e):
3873 0 : 'UNIX - System V' ,
3974 }, ident [elf .EI_OSABI ]))
4075 print (" ABI Version: %d" % ident [elf .EI_ABIVERSION ])
41- print (" Type: %s" % expand_code (et_strings , e .Ehdr .type ))
76+ elf_file_type = expand_code (et_strings , e .Ehdr .type )
77+ if e .Ehdr .type == elf .ET_DYN and elf .is_pie (e ):
78+ elf_file_type = 'DYN (Position-Independent Executable file)'
79+ print (" Type: %s" % elf_file_type )
4280 machine_code = dict (elf .constants ['EM' ])
4381 # Same textual output as readelf, from readelf.c
4482 machine_code [elf .EM_M32 ] = 'ME32100'
@@ -72,21 +110,19 @@ def display_headers(e):
72110 machine_code [elf .EM_IA_64 ] = 'Intel IA-64'
73111 machine_code [elf .EM_MIPS_X ] = 'Stanford MIPS-X'
74112 machine_code [elf .EM_COLDFIRE ] = 'Motorola Coldfire'
113+ machine_code [elf .EM_X86_64 ] = 'Advanced Micro Devices X86-64'
75114 print (" Machine: %s" % expand_code (machine_code , e .Ehdr .machine ))
76- """
77- TO BE CONTINUED
78- ("version","u32"),
79- ("entry","ptr"),
80- ("phoff","ptr"),
81- ("shoff","ptr"),
82- ("flags","u32"),
83- ("ehsize","u16"),
84- ("phentsize","u16"),
85- ("phnum","u16"),
86- ("shentsize","u16"),
87- ("shnum","u16"),
88- ("shstrndx","u16") ]
89- """
115+ print (" Version: %#x" % e .Ehdr .version )
116+ print (" Entry point address: %#x" % e .Ehdr .entry )
117+ print (" Start of program headers: %d (bytes into file)" % e .Ehdr .phoff )
118+ print (" Start of section headers: %d (bytes into file)" % e .Ehdr .shoff )
119+ print (" Flags: %#x" % e .Ehdr .flags )
120+ print (" Size of this header: %d (bytes)" % e .Ehdr .ehsize )
121+ print (" Size of program headers: %d (bytes)" % e .Ehdr .phentsize )
122+ print (" Number of program headers: %d" % e .Ehdr .phnum )
123+ print (" Size of section headers: %d (bytes)" % e .Ehdr .shentsize )
124+ print (" Number of section headers: %d" % e .Ehdr .shnum )
125+ print (" Section header string table index: %d" % e .Ehdr .shstrndx )
90126
91127def display_program_headers (e ):
92128 # Output format similar to readelf -l
@@ -199,11 +235,86 @@ def display_symbols(sections):
199235 parser .add_argument ('-d' , '--dynamic' , dest = 'options' , action = 'append_const' , const = 'dynamic' , help = 'Display the dynamic section (if present)' )
200236 parser .add_argument ('-l' , '--program-headers' , '--segments' , dest = 'options' , action = 'append_const' , const = 'program' , help = 'Display the program headers' )
201237 parser .add_argument ('-g' , '--section-groups' , dest = 'options' , action = 'append_const' , const = 'groups' , help = 'Display the section groups' )
238+ parser .add_argument ('--readelf' , dest = 'readelf_version' , action = 'append' , help = 'Simulate the output of a given version of readelf' )
202239 parser .add_argument ('file' , nargs = '+' , help = 'ELF file(s)' )
203240 args = parser .parse_args ()
204241 if args .options is None :
205242 args .options = []
206243
244+ elf .is_pie = lambda _ : False
245+ if args .readelf_version :
246+ for readelf in args .readelf_version :
247+ if 'native' in readelf :
248+ readelf_version = get_readelf_version ()
249+ else :
250+ readelf_version = float (readelf )
251+ if True :
252+ # TODO: readelf has a different output if "do_section_details" or "do_wide"
253+ elf .Shdr .header64 = [" [Nr] Name Type Address Offset" ,
254+ " Size EntSize Flags Link Info Align" ]
255+ elf .Shdr .format64 = (" [%(idx)2d] %(name17)-17s %(type_txt)-15s %(addr)016x %(offset)08x\n "
256+ " %(size)016x %(entsize)016x %(flags_txt)3s %(link)2d %(info)2d %(addralign)d" )
257+ if readelf_version >= 2.26 :
258+ # 2016-01-20 https://github.com/bminor/binutils-gdb/commit/9fb71ee49fc37163697e4f34e16097928eb83d66
259+ elf .Shdr .footer = property (lambda _ : [
260+ "Key to Flags:" ,
261+ " W (write), A (alloc), X (execute), M (merge), S (strings), I (info)," ,
262+ " L (link order), O (extra OS processing required), G (group), T (TLS)," ,
263+ " C (compressed), x (unknown), o (OS specific), E (exclude)," ,
264+ " %sp (processor specific)" % (
265+ "l (large), " if e .Ehdr .machine in (elf .EM_X86_64 , elf .EM_L10M , elf .EM_K10M ) else
266+ "y (noread), " if e .Ehdr .machine == elf .EM_ARM else
267+ "" ),
268+ ])
269+ if readelf_version >= 2.27 :
270+ # 2016-07-05 https://github.com/bminor/binutils-gdb/commit/f0728ee368f217f2473798ad7ccfe9feae4412ce
271+ elf .Shdr .footer = property (lambda _ : [
272+ "Key to Flags:" ,
273+ " W (write), A (alloc), X (execute), M (merge), S (strings), I (info)," ,
274+ " L (link order), O (extra OS processing required), G (group), T (TLS)," ,
275+ " C (compressed), x (unknown), o (OS specific), E (exclude)," ,
276+ " %sp (processor specific)" % (
277+ "l (large), " if e .Ehdr .machine in (elf .EM_X86_64 , elf .EM_L10M , elf .EM_K10M ) else
278+ "y (purecode), " if e .Ehdr .machine == elf .EM_ARM else
279+ "" ),
280+ ])
281+ if readelf_version >= 2.29 : # more precisely 2.29.1
282+ # 2017-09-05 https://github.com/bminor/binutils-gdb/commit/83eef883581525d04df3a8e53a82c01d0d12b56a
283+ elf .Shdr .footer = property (lambda _ : [
284+ "Key to Flags:" ,
285+ " W (write), A (alloc), X (execute), M (merge), S (strings), I (info)," ,
286+ " L (link order), O (extra OS processing required), G (group), T (TLS)," ,
287+ " C (compressed), x (unknown), o (OS specific), E (exclude)," ,
288+ " %sp (processor specific)" % (
289+ "l (large), " if e .Ehdr .machine in (elf .EM_X86_64 , elf .EM_L10M , elf .EM_K10M ) else
290+ "y (purecode), " if e .Ehdr .machine == elf .EM_ARM else
291+ "v (VLE), " if e .Ehdr .machine == elf .EM_PPC else
292+ "" ),
293+ ])
294+ if readelf_version >= 2.36 : # more precisely 2.36.1
295+ # 2021-02-02 https://github.com/bminor/binutils-gdb/commit/5424d7ed94cf5a7ca24636ab9f4e6d5c353fc0d3
296+ elf .Shdr .footer = property (lambda _ : [
297+ "Key to Flags:" ,
298+ " W (write), A (alloc), X (execute), M (merge), S (strings), I (info)," ,
299+ " L (link order), O (extra OS processing required), G (group), T (TLS)," ,
300+ " C (compressed), x (unknown), o (OS specific), E (exclude)," ,
301+ " %s%sp (processor specific)" % (
302+ "R (retain), D (mbind), " if e .Ehdr .ident [elf .EI_OSABI ] in (elf .ELFOSABI_GNU , elf .ELFOSABI_FREEBSD ) else
303+ "D (mbind), " if e .Ehdr .ident [elf .EI_OSABI ] == elf .ELFOSABI_NONE else
304+ ""
305+ ,
306+ "l (large), " if e .Ehdr .machine in (elf .EM_X86_64 , elf .EM_L10M , elf .EM_K10M ) else
307+ "y (noread), " if e .Ehdr .machine == elf .EM_ARM else
308+ "" ),
309+ ])
310+ if readelf_version >= 2.35 :
311+ # 2020-07-02 https://github.com/bminor/binutils-gdb/commit/0942c7ab94e554657c3e11ab85ae7f15373ee80d
312+ elf .Shdr .name17 = property (lambda _ : _ .name [:12 ]+ "[...]" if len (_ .name ) > 17 else _ .name )
313+ if readelf_version >= 2.37 :
314+ # 2021-06-15 https://github.com/bminor/binutils-gdb/commit/93df3340fd5ad32f784214fc125de71811da72ff
315+ elf .is_pie = is_pie
316+
317+
207318 for file in args .file :
208319 if len (args .file ) > 1 :
209320 print ("\n File: %s" % file )
0 commit comments