From 3bc9c34566d162240e81350386e3ad75fbf46206 Mon Sep 17 00:00:00 2001 From: eliben Date: Wed, 26 Oct 2011 13:10:58 +0200 Subject: [PATCH] more descriptions added for DWARF info --- elftools/dwarf/constants.py | 78 ++++++++++++++++++++++ elftools/dwarf/descriptions.py | 118 +++++++++++++++++++++++++++++++-- elftools/dwarf/enums.py | 15 ++++- scripts/readelf.py | 3 +- 4 files changed, 204 insertions(+), 10 deletions(-) create mode 100644 elftools/dwarf/constants.py diff --git a/elftools/dwarf/constants.py b/elftools/dwarf/constants.py new file mode 100644 index 0000000..23ed578 --- /dev/null +++ b/elftools/dwarf/constants.py @@ -0,0 +1,78 @@ +#------------------------------------------------------------------------------- +# elftools: dwarf/constants.py +# +# Constants and flags +# +# Eli Bendersky (eliben@gmail.com) +# This code is in the public domain +#------------------------------------------------------------------------------- + +# Inline codes +# +DW_INL_not_inlined=0 +DW_INL_inlined=1 +DW_INL_declared_not_inlined=2 +DW_INL_declared_inlined=3 + + +# Source languages +# +DW_LANG_C89=0x0001 +DW_LANG_C=0x0002 +DW_LANG_Ada83=0x0003 +DW_LANG_C_plus_plus=0x0004 +DW_LANG_Cobol74=0x0005 +DW_LANG_Cobol85=0x0006 +DW_LANG_Fortran77=0x0007 +DW_LANG_Fortran90=0x0008 +DW_LANG_Pascal83=0x0009 +DW_LANG_Modula2=0x000a +DW_LANG_Java=0x000b +DW_LANG_C99=0x000c +DW_LANG_Ada95=0x000d +DW_LANG_Fortran95=0x000e +DW_LANG_PLI=0x000f +DW_LANG_ObjC=0x0010 +DW_LANG_ObjC_plus_plus=0x0011 +DW_LANG_UPC=0x0012 +DW_LANG_D=0x0013 +DW_LANG_Python=0x0014 +DW_LANG_Mips_Assembler=0x8001 +DW_LANG_Upc=0x8765 +DW_LANG_HP_Bliss=0x8003 +DW_LANG_HP_Basic91=0x8004 +DW_LANG_HP_Pascal91=0x8005 +DW_LANG_HP_IMacro=0x8006 +DW_LANG_HP_Assembler=0x8007 + + +# Encoding +# +DW_ATE_void=0x0 +DW_ATE_address=0x1 +DW_ATE_boolean=0x2 +DW_ATE_complex_float=0x3 +DW_ATE_float=0x4 +DW_ATE_signed=0x5 +DW_ATE_signed_char=0x6 +DW_ATE_unsigned=0x7 +DW_ATE_unsigned_char=0x8 +DW_ATE_imaginary_float=0x9 +DW_ATE_packed_decimal=0xa +DW_ATE_numeric_string=0xb +DW_ATE_edited=0xc +DW_ATE_signed_fixed=0xd +DW_ATE_unsigned_fixed=0xe +DW_ATE_decimal_float=0xf +DW_ATE_UTF=0x10 +DW_ATE_lo_user=0x80 +DW_ATE_hi_user=0xff +DW_ATE_HP_float80=0x80 +DW_ATE_HP_complex_float80=0x81 +DW_ATE_HP_float128=0x82 +DW_ATE_HP_complex_float128=0x83 +DW_ATE_HP_floathpintel=0x84 +DW_ATE_HP_imaginary_float80=0x85 +DW_ATE_HP_imaginary_float128=0x86 + + diff --git a/elftools/dwarf/descriptions.py b/elftools/dwarf/descriptions.py index 93cc2eb..7b287fe 100644 --- a/elftools/dwarf/descriptions.py +++ b/elftools/dwarf/descriptions.py @@ -8,10 +8,13 @@ #------------------------------------------------------------------------------- from collections import defaultdict +from .constants import * -def describe_attr_value(attr, die, section_offset): - """ Given an AttributeValue extracted, return the textual representation of - its value, suitable for tools like readelf. + +def describe_attr_value(attrname, attr, die, section_offset): + """ Given an attribute (attrname is the name, attr is the AttributeValue), + return the textual representation of its value, suitable for tools like + readelf. To cover all cases, this function needs some extra arguments: @@ -19,7 +22,12 @@ def describe_attr_value(attr, die, section_offset): 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) + val_description = descr_func(attr, die, section_offset) + + # For some attributes we can display further information + extra_info_func = _EXTRA_INFO_DESCRIPTION_MAP[attrname] + extra_info = extra_info_func(attr, die, section_offset) + return str(val_description) + '\t' + extra_info #------------------------------------------------------------------------------- @@ -44,6 +52,12 @@ def _describe_attr_split_64bit(attr, die, section_offset): def _describe_attr_strp(attr, die, section_offset): return '(indirect string, offset: 0x%x): %s' % (attr.raw_value, attr.value) +def _describe_attr_debool(attr, die, section_offset): + """ To be consistent with readelf, generate 1 for True flags, 0 for False + flags. + """ + return '1' if attr.value else '0' + def _describe_attr_block(attr, die, section_offset): s = '%s byte block: ' % len(attr.value) s += ' '.join('%x' % item for item in attr.value) @@ -63,8 +77,7 @@ _ATTR_DESCRIPTION_MAP = defaultdict( 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_flag=_describe_attr_debool, DW_FORM_data1=_describe_attr_value_passthrough, DW_FORM_data2=_describe_attr_value_passthrough, DW_FORM_sdata=_describe_attr_value_passthrough, @@ -77,3 +90,96 @@ _ATTR_DESCRIPTION_MAP = defaultdict( DW_FORM_block=_describe_attr_block, ) + + +def _describe_empty(attr, die, section_offset): + return '' + +def _describe_dw_inl_extra(attr, die, section_offset): + return _DESCR_DW_INL.get( + attr.value, + ' (Unknown inline attribute value: %x)' % attr.value) + +def _describe_dw_lang_extra(attr, die, section_offset): + return _DESCR_DW_LANG.get( + attr.value, + ' (Unknown: %x)' % attr.value) + +def _describe_dw_ate_extra(attr, die, section_offset): + return _DESCR_DW_ATE.get( + attr.value, + ' (unknown type)') + + +_EXTRA_INFO_DESCRIPTION_MAP = defaultdict( + lambda: _describe_empty, # default_factory + + DW_AT_inline=_describe_dw_inl_extra, + DW_AT_language=_describe_dw_lang_extra, + DW_AT_encoding=_describe_dw_ate_extra, +) + + +_DESCR_DW_INL = { + DW_INL_not_inlined: '(not inlined)', + DW_INL_inlined: '(inlined)', + DW_INL_declared_not_inlined: '(declared as inline but ignored)', + DW_INL_declared_inlined: '(declared as inline and inlined)', +} + +_DESCR_DW_LANG = { + DW_LANG_C89: '(ANSI C)', + DW_LANG_C: '(non-ANSI C)', + DW_LANG_Ada83: '(Ada)', + DW_LANG_C_plus_plus: '(C++)', + DW_LANG_Cobol74: '(Cobol 74)', + DW_LANG_Cobol85: '(Cobol 85)', + DW_LANG_Fortran77: '(FORTRAN 77)', + DW_LANG_Fortran90: '(Fortran 90)', + DW_LANG_Pascal83: '(ANSI Pascal)', + DW_LANG_Modula2: '(Modula 2)', + DW_LANG_Java: '(Java)', + DW_LANG_C99: '(ANSI C99)', + DW_LANG_Ada95: '(ADA 95)', + DW_LANG_Fortran95: '(Fortran 95)', + DW_LANG_PLI: '(PLI)', + DW_LANG_ObjC: '(Objective C)', + DW_LANG_ObjC_plus_plus: '(Objective C++)', + DW_LANG_UPC: '(Unified Parallel C)', + DW_LANG_D: '(D)', + DW_LANG_Python: '(Python)', + DW_LANG_Mips_Assembler: '(MIPS assembler)', + DW_LANG_Upc: '(nified Parallel C)', + DW_LANG_HP_Bliss: '(HP Bliss)', + DW_LANG_HP_Basic91: '(HP Basic 91)', + DW_LANG_HP_Pascal91: '(HP Pascal 91)', + DW_LANG_HP_IMacro: '(HP IMacro)', + DW_LANG_HP_Assembler: '(HP assembler)', +} + +_DESCR_DW_ATE = { + DW_ATE_void: '(void)', + DW_ATE_address: '(machine address)', + DW_ATE_boolean: '(boolean)', + DW_ATE_complex_float: '(complex float)', + DW_ATE_float: '(float)', + DW_ATE_signed: '(signed)', + DW_ATE_signed_char: '(signed char)', + DW_ATE_unsigned: '(unsigned)', + DW_ATE_unsigned_char: '(unsigned char)', + DW_ATE_imaginary_float: '(imaginary float)', + DW_ATE_decimal_float: '(decimal float)', + DW_ATE_packed_decimal: '(packed_decimal)', + DW_ATE_numeric_string: '(numeric_string)', + DW_ATE_edited: '(edited)', + DW_ATE_signed_fixed: '(signed_fixed)', + DW_ATE_unsigned_fixed: '(unsigned_fixed)', + DW_ATE_HP_float80: '(HP_float80)', + DW_ATE_HP_complex_float80: '(HP_complex_float80)', + DW_ATE_HP_float128: '(HP_float128)', + DW_ATE_HP_complex_float128: '(HP_complex_float128)', + DW_ATE_HP_floathpintel: '(HP_floathpintel)', + DW_ATE_HP_imaginary_float80: '(HP_imaginary_float80)', + DW_ATE_HP_imaginary_float128: '(HP_imaginary_float128)', +} + diff --git a/elftools/dwarf/enums.py b/elftools/dwarf/enums.py index 479733e..1338725 100644 --- a/elftools/dwarf/enums.py +++ b/elftools/dwarf/enums.py @@ -185,9 +185,18 @@ ENUM_DW_AT = dict( DW_AT_main_subprogram = 0x6a, DW_AT_data_bit_offset = 0x6b, DW_AT_const_expr = 0x6c, - - DW_AT_lo_user = 0x2000, - DW_AT_hi_user = 0x3fff, + + DW_AT_MIPS_fde = 0x2001, + DW_AT_MIPS_loop_begin = 0x2002, + DW_AT_MIPS_tail_loop_begin = 0x2003, + DW_AT_MIPS_epilog_begin = 0x2004, + DW_AT_MIPS_loop_unroll_factor = 0x2005, + DW_AT_MIPS_software_pipeline_depth = 0x2006, + DW_AT_MIPS_linkage_name = 0x2007, + DW_AT_MIPS_stride = 0x2008, + DW_AT_MIPS_abstract_name = 0x2009, + DW_AT_MIPS_clone_origin = 0x200a, + DW_AT_MIPS_has_inlines = 0x200b, _default_ = Pass, ) diff --git a/scripts/readelf.py b/scripts/readelf.py index 02325f3..0688f40 100755 --- a/scripts/readelf.py +++ b/scripts/readelf.py @@ -523,7 +523,8 @@ class ReadElf(object): self._emitline(' <%2x> %-18s: %s' % ( attr.offset - section_offset, attrname, - describe_attr_value(attr, die, section_offset))) + describe_attr_value( + attrname, attr, die, section_offset))) if die.has_children: die_depth += 1 -- 2.30.2