From ba447bc582d6bb800d0441ab4c52730dd0d16484 Mon Sep 17 00:00:00 2001 From: eliben Date: Sun, 6 Nov 2011 11:29:49 +0200 Subject: [PATCH] added basic visiting of all OPs in location_expr.GenericLocationExprVisitor --- elftools/dwarf/location_expr.py | 104 ++++++++++++++++++++++++++---- elftools/dwarf/structs.py | 11 +++- tests/test_dwarf_location_expr.py | 1 + z.py | 26 ++++---- 4 files changed, 114 insertions(+), 28 deletions(-) diff --git a/elftools/dwarf/location_expr.py b/elftools/dwarf/location_expr.py index 1a2d4f3..da1a819 100644 --- a/elftools/dwarf/location_expr.py +++ b/elftools/dwarf/location_expr.py @@ -70,18 +70,6 @@ DW_OP_name2opcode = dict( DW_OP_form_tls_address=0x9b, DW_OP_call_frame_cfa=0x9c, DW_OP_bit_piece=0x9d, - DW_OP_implicit_value=0x9e, - DW_OP_stack_value=0x9f, - DW_OP_GNU_push_tls_address=0xe0, - DW_OP_GNU_uninit=0xf0, - DW_OP_GNU_encoded_addr=0xf1, - DW_OP_GNU_implicit_pointer=0xf2, - DW_OP_GNU_entry_value=0xf3, - DW_OP_GNU_const_type=0xf4, - DW_OP_GNU_regval_type=0xf5, - DW_OP_GNU_deref_type=0xf6, - DW_OP_GNU_convert=0xf7, - DW_OP_GNU_reinterpret=0xf9, ) def _generate_dynamic_values(map, prefix, index_start, index_end, value_start): @@ -115,11 +103,12 @@ class GenericLocationExprVisitor(object): """ Process (visit) a location expression. Currently two possible types are supported for expr: - 1. file-like stream object + 1. File-like stream object 2. List of byte values (the result of parsed DW_FORM_block* attributes). """ if hasattr(expr, 'read') and hasattr(expr, 'seek'): + # looks like a stream self.stream = expr else: self.stream = StringIO(bytelist2string(expr)) @@ -134,6 +123,8 @@ class GenericLocationExprVisitor(object): # Decode the opcode and its name self._cur_opcode = ord(byte) self._cur_opcode_name = DW_OP_opcode2name[self._cur_opcode] + # Will be filled in by visitors + self._cur_args = [] # Dispatch to a visitor function visitor = self._dispatch_table.get( @@ -158,12 +149,97 @@ class GenericLocationExprVisitor(object): self._cur_args = [ struct_parse(self.structs.Dwarf_target_addr(''), self.stream)] + def _make_visitor_arg_struct(self, struct_arg): + """ Create a visitor method for an opcode that that accepts a single + argument, specified by a struct. + """ + def visitor(self, opcode, opcode_name): + self._cur_args = [struct_parse(struct_arg, self.stream)] + return visitor + + def _make_visitor_arg_struct2(self, struct_arg1, struct_arg2): + """ Create a visitor method for an opcode that that accepts two + arguments, specified by structs. + """ + def visitor(self, opcode, opcode_name): + self._cur_args = [ + struct_parse(struct_arg1, self.stream), + struct_parse(struct_arg2, self.stream)] + return visitor + def _init_dispatch_table(self): self._dispatch_table = {} def add(opcode_name, func): self._dispatch_table[DW_OP_name2opcode[opcode_name]] = func add('DW_OP_addr', self._visit_OP_addr) - add('DW_OP_deref', self._visit_OP_with_no_args) + add('DW_OP_const1u', + self._make_visitor_arg_struct(self.structs.Dwarf_uint8(''))) + add('DW_OP_const1s', + self._make_visitor_arg_struct(self.structs.Dwarf_int8(''))) + add('DW_OP_const2u', + self._make_visitor_arg_struct(self.structs.Dwarf_uint16(''))) + add('DW_OP_const2s', + self._make_visitor_arg_struct(self.structs.Dwarf_int16(''))) + add('DW_OP_const4u', + self._make_visitor_arg_struct(self.structs.Dwarf_uint32(''))) + add('DW_OP_const4s', + self._make_visitor_arg_struct(self.structs.Dwarf_int32(''))) + add('DW_OP_const8u', + self._make_visitor_arg_struct(self.structs.Dwarf_uint64(''))) + add('DW_OP_const8s', + self._make_visitor_arg_struct(self.structs.Dwarf_int64(''))) + add('DW_OP_constu', + self._make_visitor_arg_struct(self.structs.Dwarf_uleb128(''))) + add('DW_OP_consts', + self._make_visitor_arg_struct(self.structs.Dwarf_sleb128(''))) + add('DW_OP_pick', + self._make_visitor_arg_struct(self.structs.Dwarf_uint8(''))) + add('DW_OP_plus_uconst', + self._make_visitor_arg_struct(self.structs.Dwarf_uleb128(''))) + add('DW_OP_bra', + self._make_visitor_arg_struct(self.structs.Dwarf_int16(''))) + add('DW_OP_skip', + self._make_visitor_arg_struct(self.structs.Dwarf_int16(''))) + + for opname in [ 'DW_OP_deref', 'DW_OP_dup', 'DW_OP_drop', 'DW_OP_over', + 'DW_OP_swap', 'DW_OP_swap', 'DW_OP_rot', 'DW_OP_xderef', + 'DW_OP_abs', 'DW_OP_and', 'DW_OP_div', 'DW_OP_minus', + 'DW_OP_mod', 'DW_OP_mul', 'DW_OP_neg', 'DW_OP_not', + 'DW_OP_plus', 'DW_OP_shl', 'DW_OP_shr', 'DW_OP_shra', + 'DW_OP_xor', 'DW_OP_eq', 'DW_OP_ge', 'DW_OP_gt', + 'DW_OP_le', 'DW_OP_lt', 'DW_OP_ne', 'DW_OP_nop', + 'DW_OP_push_object_address', 'DW_OP_form_tls_address', + 'DW_OP_call_frame_cfa', 'DW_OP_stack_value',]: + add(opname, self._visit_OP_with_no_args) + + for n in range(0, 32): + add('DW_OP_lit%s' % n, self._visit_OP_with_no_args) + add('DW_OP_reg%s' % n, self._visit_OP_with_no_args) + add('DW_OP_breg%s' % n, + self._make_visitor_arg_struct(self.structs.Dwarf_sleb128(''))) + + add('DW_OP_regx', + self._make_visitor_arg_struct(self.structs.Dwarf_uleb128(''))) + add('DW_OP_bregx', + self._make_visitor_arg_struct( + self.structs.Dwarf_uleb128(''), + self.structs.Dwarf_sleb128(''))) + add('DW_OP_piece', + self._make_visitor_arg_struct(self.structs.Dwarf_uleb128(''))) + add('DW_OP_bit_piece', + self._make_visitor_arg_struct( + self.structs.Dwarf_uleb128(''), + self.structs.Dwarf_uleb128(''))) + add('DW_OP_deref_size', + self._make_visitor_arg_struct(self.structs.Dwarf_int8(''))) + add('DW_OP_xderef_size', + self._make_visitor_arg_struct(self.structs.Dwarf_int8(''))) + add('DW_OP_call2', + self._make_visitor_arg_struct(self.structs.Dwarf_uint16(''))) + add('DW_OP_call4', + self._make_visitor_arg_struct(self.structs.Dwarf_uint32(''))) + add('DW_OP_call_ref', + self._make_visitor_arg_struct(self.structs.Dwarf_offset(''))) diff --git a/elftools/dwarf/structs.py b/elftools/dwarf/structs.py index 7fbd357..a35f362 100644 --- a/elftools/dwarf/structs.py +++ b/elftools/dwarf/structs.py @@ -9,6 +9,7 @@ #------------------------------------------------------------------------------- from ..construct import ( UBInt8, UBInt16, UBInt32, UBInt64, ULInt8, ULInt16, ULInt32, ULInt64, + SBInt8, SBInt16, SBInt32, SBInt64, SLInt8, SLInt16, SLInt32, SLInt64, Adapter, Struct, ConstructError, If, RepeatUntil, Field, Rename, Enum, PrefixedArray, CString, ) @@ -27,7 +28,7 @@ class DWARFStructs(object): Accessible attributes (mostly as described in chapter 7 of the DWARF spec v3): - Dwarf_uint{8,16,32,64): + Dwarf_[u]int{8,16,32,64): Data chunks of the common sizes Dwarf_offset: @@ -89,6 +90,10 @@ class DWARFStructs(object): self.Dwarf_offset = ULInt32 if self.dwarf_format == 32 else ULInt64 self.Dwarf_target_addr = ( ULInt32 if self.address_size == 4 else ULInt64) + self.Dwarf_int8 = SLInt8 + self.Dwarf_int16 = SLInt16 + self.Dwarf_int32 = SLInt32 + self.Dwarf_int64 = SLInt64 else: self.Dwarf_uint8 = UBInt8 self.Dwarf_uint16 = UBInt16 @@ -97,6 +102,10 @@ class DWARFStructs(object): self.Dwarf_offset = UBInt32 if self.dwarf_format == 32 else UBInt64 self.Dwarf_target_addr = ( UBInt32 if self.address_size == 4 else UBInt64) + self.Dwarf_int8 = SBInt8 + self.Dwarf_int16 = SBInt16 + self.Dwarf_int32 = SBInt32 + self.Dwarf_int64 = SBInt64 self._create_initial_length() self._create_leb128() diff --git a/tests/test_dwarf_location_expr.py b/tests/test_dwarf_location_expr.py index 7653a0b..7949a07 100644 --- a/tests/test_dwarf_location_expr.py +++ b/tests/test_dwarf_location_expr.py @@ -30,3 +30,4 @@ class TestGenericLocationExprVisitor(unittest.TestCase): if __name__ == '__main__': unittest.main() + diff --git a/z.py b/z.py index 34f4bc5..2a492ef 100644 --- a/z.py +++ b/z.py @@ -17,26 +17,26 @@ efile = ELFFile(stream) print efile.elfclass, efile.little_endian print '===> %s sections!' % efile.num_sections() -print efile.has_dwarf_info() +#~ print efile.has_dwarf_info() -dwarfinfo = efile.get_dwarf_info() +#~ dwarfinfo = efile.get_dwarf_info() -cu = dwarfinfo.get_CU(3) -print 'CU header', cu.header -topdie = cu.get_top_DIE() +#~ cu = dwarfinfo.get_CU(3) +#~ print 'CU header', cu.header +#~ topdie = cu.get_top_DIE() -c = topdie.iter_children().next() +#~ c = topdie.iter_children().next() -print c +#~ print c -print 'siblings.....' +#~ print 'siblings.....' -for s in c.iter_siblings(): - print s +#~ for s in c.iter_siblings(): + #~ print s -from elftools.dwarf.location_expr import _DW_OP_name2opcode, _DW_OP_opcode2name +from elftools.dwarf.location_expr import DW_OP_name2opcode, DW_OP_opcode2name -print hex(_DW_OP_name2opcode['DW_OP_lit14']) -print _DW_OP_opcode2name[0x0e] +print hex(DW_OP_name2opcode['DW_OP_lit14']) +print DW_OP_opcode2name[0x0e] -- 2.30.2