self._emitline(' ABI Version: %d' %
e_ident['EI_ABIVERSION'])
self._emitline(' Type: %s' %
- describe_e_type(header['e_type']))
+ describe_e_type(header['e_type'], self.elffile))
self._emitline(' Machine: %s' %
describe_e_machine(header['e_machine']))
self._emitline(' Version: %s' %
elfheader = self.elffile.header
if show_heading:
self._emitline('Elf file type is %s' %
- describe_e_type(elfheader['e_type']))
+ describe_e_type(elfheader['e_type'], self.elffile))
self._emitline('Entry point is %s' %
self._format_hex(elfheader['e_entry']))
# readelf weirness - why isn't e_phoff printed as hex? (for section
section.name))
continue
- self._emitline("\nSymbol table '%s' contains %s entries:" % (
- section.name, section.num_symbols()))
+ self._emitline("\nSymbol table '%s' contains %d %s:" % (
+ section.name,
+ section.num_symbols(),
+ 'entry' if section.num_symbols() == 1 else 'entries'))
if self.elffile.elfclass == 32:
self._emitline(' Num: Value Size Type Bind Vis Ndx Name')
else:
version_info = '@@%(name)s' % version
+ symbol_name = symbol.name
+ # Print section names for STT_SECTION symbols as readelf does
+ if (symbol['st_info']['type'] == 'STT_SECTION'
+ and symbol['st_shndx'] < self.elffile.num_sections()
+ and symbol['st_name'] == 0):
+ symbol_name = self.elffile.get_section(symbol['st_shndx']).name
+
# symbol names are truncated to 25 chars, similarly to readelf
self._emitline('%6d: %s %s %-7s %-6s %-7s %4s %.25s%s' % (
nsym,
describe_symbol_shndx(self._get_symbol_shndx(symbol,
nsym,
section_index)),
- symbol.name,
+ symbol_name,
version_info))
def display_dynamic_tags(self):
continue
has_dynamic_sections = True
- self._emitline("\nDynamic section at offset %s contains %s entries:" % (
+ self._emitline("\nDynamic section at offset %s contains %d %s:" % (
self._format_hex(section['sh_offset']),
- section.num_tags()))
+ section.num_tags(),
+ 'entry' if section.num_tags() == 1 else 'entries'))
self._emitline(" Tag Type Name/Value")
padding = 20 + (8 if self.elffile.elfclass == 32 else 0)
continue
has_relocation_sections = True
- self._emitline("\nRelocation section '%.128s' at offset %s contains %s entries:" % (
+ self._emitline("\nRelocation section '%.128s' at offset %s contains %d %s:" % (
section.name,
self._format_hex(section['sh_offset']),
- section.num_relocations()))
+ section.num_relocations(),
+ 'entry' if section.num_relocations() == 1 else 'entries'))
if section.is_RELA():
self._emitline(" Offset Info Type Sym. Value Sym. Name + Addend")
else:
return
for ehabi_info in self.elffile.get_ehabi_infos():
# Unwind section '.ARM.exidx' at offset 0x203e8 contains 1009 entries:
- self._emitline("\nUnwind section '%s' at offset 0x%x contains %d entries" % (
+ self._emitline("\nUnwind section '%s' at offset 0x%x contains %d %s" % (
ehabi_info.section_name(),
ehabi_info.section_offset(),
- ehabi_info.num_entry()
- ))
+ ehabi_info.num_entry(),
+ 'entry' if ehabi_info.num_entry() == 1 else 'entries'))
for i in range(ehabi_info.num_entry()):
entry = ehabi_info.get_entry(i)
for section in self.elffile.iter_sections():
if isinstance(section, GNUVerSymSection):
- self._print_version_section_header(
- section, 'Version symbols', lead0x=False)
-
+ self._print_version_section_header(section, 'Version symbols')
num_symbols = section.num_symbols()
# Symbol version info are printed four by four entries
else:
num_entries = version_section.num_symbols()
- self._emitline("\n%s section '%s' contains %s entries:" %
- (name, version_section.name, num_entries))
+ self._emitline("\n%s section '%s' contains %d %s:" % (
+ name, version_section.name, num_entries,
+ 'entry' if num_entries == 1 else 'entries'))
self._emitline('%sAddr: %s Offset: %s Link: %i (%s)' % (
' ' * indent,
self._format_hex(
"""
if not self._dwarfinfo.has_debug_info:
return
- self._emitline('Decoded dump of debug contents of section %s:\n' % self._dwarfinfo.debug_line_sec.name)
+ self._emitline('Contents of the %s section:' % self._dwarfinfo.debug_line_sec.name)
+ self._emitline()
for cu in self._dwarfinfo.iter_CUs():
lineprogram = self._dwarfinfo.line_program_for_CU(cu)
cu_filename = '%s/%s' % (bytes2str(dir), cu_filename)
self._emitline('CU: %s:' % cu_filename)
- self._emitline('File name Line number Starting address')
+ self._emitline('File name Line number Starting address Stmt')
# Print each state's file, line and address information. For some
# instructions other output is needed to be compatible with
elif entry.command == DW_LNE_define_file:
self._emitline('%s:' % (
bytes2str(lineprogram['include_directory'][entry.args[0].dir_index])))
- elif not state.end_sequence:
- # readelf doesn't print the state after end_sequence
- # instructions. I think it's a bug but to be compatible
- # I don't print them too.
- if lineprogram['version'] < 4 or self.elffile['e_machine'] == 'EM_PPC64':
- self._emitline('%-35s %11d %18s' % (
- bytes2str(lineprogram['file_entry'][state.file - 1].name),
- state.line,
- '0' if state.address == 0 else
- self._format_hex(state.address)))
- else:
- self._emitline('%-35s %11d %18s[%d]' % (
- bytes2str(lineprogram['file_entry'][state.file - 1].name),
- state.line,
- '0' if state.address == 0 else
- self._format_hex(state.address),
- state.op_index))
+ elif lineprogram['version'] < 4 or self.elffile['e_machine'] == 'EM_PPC64':
+ self._emitline('%-35s %11s %18s %s' % (
+ bytes2str(lineprogram['file_entry'][state.file - 1].name),
+ state.line if not state.end_sequence else '-',
+ '0' if state.address == 0 else self._format_hex(state.address),
+ 'x' if state.is_stmt and not state.end_sequence else ''))
+ else:
+ self._emitline('%-35s %11d %18s[%d] %s' % (
+ bytes2str(lineprogram['file_entry'][state.file - 1].name),
+ state.line if not state.end_sequence else '-',
+ '0' if state.address == 0 else self._format_hex(state.address),
+ state.op_index,
+ 'x' if state.is_stmt and not state.end_sequence else ''))
if entry.command == DW_LNS_copy:
# Another readelf oddity...
self._emitline()
lines1 = prepare_lines(s1)
lines2 = prepare_lines(s2)
- flag_after_symtable = False
+ flag_in_debug_line_section = False
if len(lines1) != len(lines2):
return False, 'Number of lines different: %s vs %s' % (
len(lines1), len(lines2))
for i in range(len(lines1)):
- if 'symbol table' in lines1[i]:
- flag_after_symtable = True
+ if lines1[i].endswith('debug_line section:'):
+ # .debug_line or .zdebug_line
+ flag_in_debug_line_section = True
# readelf spelling error for GNU property notes
lines1[i] = lines1[i].replace('procesor-specific type', 'processor-specific type')
sm = SequenceMatcher()
sm.set_seqs(lines1[i], lines2[i])
changes = sm.get_opcodes()
- if flag_after_symtable:
- # Detect readelf's adding @ with lib and version after
- # symbol name.
- if ( len(changes) == 2 and changes[1][0] == 'delete' and
- lines1[i][changes[1][1]] == '@'):
+ if flag_in_debug_line_section:
+ # readelf outputs an additional "View" column: ignore it
+ if len(lines1_parts) >= 2 and lines1_parts[-2] == 'view':
ok = True
+ else:
+ # Fast check special-cased for the only ELF we have which
+ # has this information (dwarf_gnuops4.so.elf)
+ ok = ( lines1_parts[-2:] == ['1', 'x']
+ and lines2_parts[-1] == 'x')
+ elif '[...]' in lines1[i]:
+ # Special case truncations with ellipsis like these:
+ # .note.gnu.bu[...] redelf
+ # .note.gnu.build-i pyelftools
+ # Or more complex for symbols with versions, like these:
+ # _unw[...]@gcc_3.0 readelf
+ # _unwind_resume@gcc_3.0 pyelftools
+ for p1, p2 in zip(lines1_parts, lines2_parts):
+ dots_start = p1.find('[...]')
+ if dots_start != -1:
+ break
+ ok = p1.endswith('[...]') and p1[:dots_start] == p2[:dots_start]
+ if not ok:
+ dots_end = dots_start + 5
+ if len(p1) > dots_end and p1[dots_end] == '@':
+ ok = ( p1[:dots_start] == p2[:dots_start]
+ and p1[p1.rfind('@'):] == p2[p2.rfind('@'):])
elif 'at_const_value' in lines1[i]:
# On 32-bit machines, readelf doesn't correctly represent
# some boundary LEB128 numbers
elif 'os/abi' in lines1[i]:
if 'unix - gnu' in lines1[i] and 'unix - linux' in lines2[i]:
ok = True
- elif ( 'unknown at value' in lines1[i] and
- 'dw_at_apple' in lines2[i]):
- ok = True
- elif 'loos+0x474e553' in lines1[i]:
- # readelf v2.29 does not know about PT_GNU_PROPERTY apparently
- ok = lines2_parts[0] == 'gnu_property'
elif len(lines1_parts) == 3 and lines1_parts[2] == 'nt_gnu_property_type_0':
# readelf does not seem to print a readable description for this
ok = lines1_parts == lines2_parts[:3]
else:
- for s in ('t (tls)', 'l (large)'):
+ for s in ('t (tls)', 'l (large)', 'd (mbind)'):
if s in lines1[i] or s in lines2[i]:
ok = True
break