From aee11d2cd9e3ed25267677bb3747d202e5e1621c Mon Sep 17 00:00:00 2001 From: eliben Date: Wed, 26 Oct 2011 10:42:34 +0200 Subject: [PATCH] added some basic description capabilities for DWARF attributes in debug_info --- README.rst | 2 +- elftools/dwarf/descriptions.py | 79 ++++++++++++++++++++++++++++++++++ elftools/dwarf/die.py | 7 ++- scripts/readelf.py | 15 ++++++- 4 files changed, 96 insertions(+), 7 deletions(-) create mode 100644 elftools/dwarf/descriptions.py diff --git a/README.rst b/README.rst index 920cafc..cb92a07 100644 --- a/README.rst +++ b/README.rst @@ -3,4 +3,4 @@ pyelftools Nice project, heh? -This is **cool**, or is it? + diff --git a/elftools/dwarf/descriptions.py b/elftools/dwarf/descriptions.py new file mode 100644 index 0000000..93cc2eb --- /dev/null +++ b/elftools/dwarf/descriptions.py @@ -0,0 +1,79 @@ +#------------------------------------------------------------------------------- +# elftools: dwarf/descriptions.py +# +# Textual descriptions of the various values and enums of DWARF +# +# Eli Bendersky (eliben@gmail.com) +# This code is in the public domain +#------------------------------------------------------------------------------- +from collections import defaultdict + + +def describe_attr_value(attr, die, section_offset): + """ Given an AttributeValue extracted, return the textual representation of + its value, suitable for tools like readelf. + + To cover all cases, this function needs some extra arguments: + + die: the DIE this attribute was extracted from + section_offset: offset in the stream of the section the DIE belongs to + """ + descr_func = _ATTR_DESCRIPTION_MAP[attr.form] + return descr_func(attr, die, section_offset) + + +#------------------------------------------------------------------------------- + +def _describe_attr_ref(attr, die, section_offset): + return '<0x%x>' % (attr.value + die.cu.cu_offset - section_offset) + +def _describe_attr_value_passthrough(attr, die, section_offset): + return attr.value + +def _describe_attr_hex(attr, die, section_offset): + return '0x%x' % (attr.value) + +def _describe_attr_hex_addr(attr, die, section_offset): + return '<0x%x>' % (attr.value) + +def _describe_attr_split_64bit(attr, die, section_offset): + low_word = attr.value & 0xFFFFFFFF + high_word = (attr.value >> 32) & 0xFFFFFFFF + return '0x%x 0x%x' % (low_word, high_word) + +def _describe_attr_strp(attr, die, section_offset): + return '(indirect string, offset: 0x%x): %s' % (attr.raw_value, attr.value) + +def _describe_attr_block(attr, die, section_offset): + s = '%s byte block: ' % len(attr.value) + s += ' '.join('%x' % item for item in attr.value) + return s + + +_ATTR_DESCRIPTION_MAP = defaultdict( + lambda: _describe_attr_value_passthrough, # default_factory + + DW_FORM_ref1=_describe_attr_ref, + DW_FORM_ref2=_describe_attr_ref, + DW_FORM_ref4=_describe_attr_ref, + DW_FORM_ref8=_describe_attr_split_64bit, + DW_FORM_ref_udata=_describe_attr_ref, + DW_FORM_ref_addr=_describe_attr_hex_addr, + DW_FORM_data4=_describe_attr_hex, + DW_FORM_data8=_describe_attr_split_64bit, + DW_FORM_addr=_describe_attr_hex, + DW_FORM_sec_offset=_describe_attr_hex, + DW_FORM_flag_present=_describe_attr_value_passthrough, + DW_FORM_flag=_describe_attr_value_passthrough, + DW_FORM_data1=_describe_attr_value_passthrough, + DW_FORM_data2=_describe_attr_value_passthrough, + DW_FORM_sdata=_describe_attr_value_passthrough, + DW_FORM_udata=_describe_attr_value_passthrough, + DW_FORM_string=_describe_attr_value_passthrough, + DW_FORM_strp=_describe_attr_strp, + DW_FORM_block1=_describe_attr_block, + DW_FORM_block2=_describe_attr_block, + DW_FORM_block4=_describe_attr_block, + DW_FORM_block=_describe_attr_block, +) + diff --git a/elftools/dwarf/die.py b/elftools/dwarf/die.py index ad81892..f4f422e 100644 --- a/elftools/dwarf/die.py +++ b/elftools/dwarf/die.py @@ -49,8 +49,7 @@ class DIE(object): attributes: An ordered dictionary mapping attribute names to values. It's - ordered to enable both efficient name->value mapping and - preserve the order of attributes in the section + ordered to preserve the order of attributes in the section has_children: Specifies whether this DIE has children @@ -190,5 +189,5 @@ class DIE(object): else: value = raw_value return value - - \ No newline at end of file + + diff --git a/scripts/readelf.py b/scripts/readelf.py index b1fd9c4..02325f3 100755 --- a/scripts/readelf.py +++ b/scripts/readelf.py @@ -34,6 +34,7 @@ from elftools.elf.descriptions import ( describe_symbol_shndx, describe_reloc_type, ) from elftools.dwarf.dwarfinfo import DWARFInfo, DebugSectionLocator +from elftools.dwarf.descriptions import describe_attr_value class ReadElf(object): @@ -512,11 +513,21 @@ class ReadElf(object): if die.is_null(): die_depth -= 1 continue - self._emitline(' <%s><%x>: Abbrev Number: %s' % ( - die_depth, die.offset - section_offset, die.abbrev_code)) + self._emitline(' <%s><%x>: Abbrev Number: %s (%s)' % ( + die_depth, + die.offset - section_offset, + die.abbrev_code, + die.tag)) + + for attrname, attr in die.attributes.iteritems(): + self._emitline(' <%2x> %-18s: %s' % ( + attr.offset - section_offset, + attrname, + describe_attr_value(attr, die, section_offset))) if die.has_children: die_depth += 1 + def _emit(self, s=''): """ Emit an object to output -- 2.30.2