From: Eli Bendersky Date: Wed, 7 Dec 2011 12:43:47 +0000 (+0200) Subject: renamed 'location expression' to the more general 'dwarf expression' X-Git-Tag: v0.10~51 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6c17c05e14d28f529de06ef5ba8ed553b20b7a99;p=pyelftools.git renamed 'location expression' to the more general 'dwarf expression' --- diff --git a/elftools/dwarf/descriptions.py b/elftools/dwarf/descriptions.py index 57df8a4..4f88bf3 100644 --- a/elftools/dwarf/descriptions.py +++ b/elftools/dwarf/descriptions.py @@ -9,7 +9,7 @@ from collections import defaultdict from .constants import * -from .location_expr import LocationExpressionDumper +from .dwarf_expr import ExprDumper from .die import DIE from ..common.utils import preserve_stream_pos @@ -214,7 +214,7 @@ def _make_extra_string(s=''): return extra -_LOCATION_EXPR_DUMPER_CACHE = {} +_DWARF_EXPR_DUMPER_CACHE = {} def _location_list_extra(attr, die, section_offset): # According to section 2.6 of the DWARF spec v3, class loclistptr means @@ -228,13 +228,13 @@ def _location_list_extra(attr, die, section_offset): # caching scheme is in place to create only one such dumper per # processed CU. cache_key = id(die.cu.structs) - if cache_key not in _LOCATION_EXPR_DUMPER_CACHE: - _LOCATION_EXPR_DUMPER_CACHE[cache_key] = \ - LocationExpressionDumper(die.cu.structs) - location_expr_dumper = _LOCATION_EXPR_DUMPER_CACHE[cache_key] - location_expr_dumper.clear() - location_expr_dumper.process_expr(attr.value) - return '(' + location_expr_dumper.get_str() + ')' + if cache_key not in _DWARF_EXPR_DUMPER_CACHE: + _DWARF_EXPR_DUMPER_CACHE[cache_key] = \ + ExprDumper(die.cu.structs) + dwarf_expr_dumper = _DWARF_EXPR_DUMPER_CACHE[cache_key] + dwarf_expr_dumper.clear() + dwarf_expr_dumper.process_expr(attr.value) + return '(' + dwarf_expr_dumper.get_str() + ')' def _import_extra(attr, die, section_offset): diff --git a/elftools/dwarf/dwarf_expr.py b/elftools/dwarf/dwarf_expr.py new file mode 100644 index 0000000..6140d20 --- /dev/null +++ b/elftools/dwarf/dwarf_expr.py @@ -0,0 +1,297 @@ +#------------------------------------------------------------------------------- +# elftools: dwarf/dwarf_expr.py +# +# Decoding DWARF expressions +# +# Eli Bendersky (eliben@gmail.com) +# This code is in the public domain +#------------------------------------------------------------------------------- +from cStringIO import StringIO + +from ..common.utils import struct_parse, bytelist2string + + +# DWARF expression opcodes. name -> opcode mapping +DW_OP_name2opcode = dict( + DW_OP_addr=0x03, + DW_OP_deref=0x06, + DW_OP_const1u=0x08, + DW_OP_const1s=0x09, + DW_OP_const2u=0x0a, + DW_OP_const2s=0x0b, + DW_OP_const4u=0x0c, + DW_OP_const4s=0x0d, + DW_OP_const8u=0x0e, + DW_OP_const8s=0x0f, + DW_OP_constu=0x10, + DW_OP_consts=0x11, + DW_OP_dup=0x12, + DW_OP_drop=0x13, + DW_OP_over=0x14, + DW_OP_pick=0x15, + DW_OP_swap=0x16, + DW_OP_rot=0x17, + DW_OP_xderef=0x18, + DW_OP_abs=0x19, + DW_OP_and=0x1a, + DW_OP_div=0x1b, + DW_OP_minus=0x1c, + DW_OP_mod=0x1d, + DW_OP_mul=0x1e, + DW_OP_neg=0x1f, + DW_OP_not=0x20, + DW_OP_or=0x21, + DW_OP_plus=0x22, + DW_OP_plus_uconst=0x23, + DW_OP_shl=0x24, + DW_OP_shr=0x25, + DW_OP_shra=0x26, + DW_OP_xor=0x27, + DW_OP_bra=0x28, + DW_OP_eq=0x29, + DW_OP_ge=0x2a, + DW_OP_gt=0x2b, + DW_OP_le=0x2c, + DW_OP_lt=0x2d, + DW_OP_ne=0x2e, + DW_OP_skip=0x2f, + DW_OP_regx=0x90, + DW_OP_fbreg=0x91, + DW_OP_bregx=0x92, + DW_OP_piece=0x93, + DW_OP_deref_size=0x94, + DW_OP_xderef_size=0x95, + DW_OP_nop=0x96, + DW_OP_push_object_address=0x97, + DW_OP_call2=0x98, + DW_OP_call4=0x99, + DW_OP_call_ref=0x9a, + DW_OP_form_tls_address=0x9b, + DW_OP_call_frame_cfa=0x9c, + DW_OP_bit_piece=0x9d, +) + +def _generate_dynamic_values(map, prefix, index_start, index_end, value_start): + """ Generate values in a map (dict) dynamically. Each key starts with + a (string) prefix, followed by an index in the inclusive range + [index_start, index_end]. The values start at value_start. + """ + for index in range(index_start, index_end + 1): + name = '%s%s' % (prefix, index) + value = value_start + index - index_start + map[name] = value + +_generate_dynamic_values(DW_OP_name2opcode, 'DW_OP_lit', 0, 31, 0x30) +_generate_dynamic_values(DW_OP_name2opcode, 'DW_OP_reg', 0, 31, 0x50) +_generate_dynamic_values(DW_OP_name2opcode, 'DW_OP_breg', 0, 31, 0x70) + +# opcode -> name mapping +DW_OP_opcode2name = dict((v, k) for k, v in DW_OP_name2opcode.iteritems()) + + +class GenericExprVisitor(object): + def __init__(self, structs): + self.structs = structs + self._init_dispatch_table() + self.stream = None + self._cur_opcode = None + self._cur_opcode_name = None + self._cur_args = [] + + def process_expr(self, loc_expr): + """ Process (visit) a DWARF expression. Currently two possible + types are supported for expr: + + 1. File-like stream object + 2. List of byte values (the result of parsed DW_FORM_block* + attributes). + """ + if hasattr(loc_expr, 'read') and hasattr(loc_expr, 'seek'): + # looks like a stream + self.stream = loc_expr + else: + self.stream = StringIO(bytelist2string(loc_expr)) + + while True: + # Get the next opcode from the stream. If nothing is left in the + # stream, we're done. + byte = self.stream.read(1) + if len(byte) == 0: + break + + # Decode the opcode and its name + self._cur_opcode = ord(byte) + self._cur_opcode_name = DW_OP_opcode2name.get( + self._cur_opcode, 'OP:0x%x' % self._cur_opcode) + # Will be filled in by visitors + self._cur_args = [] + + # Dispatch to a visitor function + visitor = self._dispatch_table.get( + self._cur_opcode, + self._default_visitor) + visitor(self._cur_opcode, self._cur_opcode_name) + + # Finally call the post-visit function + self._after_visit( + self._cur_opcode, self._cur_opcode_name, self._cur_args) + + def _after_visit(self, opcode, opcode_name, args): + pass + + def _default_visitor(self, opcode, opcode_name): + pass + + def _visit_OP_with_no_args(self, opcode, opcode_name): + self._cur_args = [] + + def _visit_OP_addr(self, opcode, opcode_name): + 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(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(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_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_struct2( + self.structs.Dwarf_uint32(''), + self.structs.Dwarf_uint32(''))) + add('DW_OP_const8s', + self._make_visitor_arg_struct2( + self.structs.Dwarf_int32(''), + self.structs.Dwarf_int32(''))) + 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']: + 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_fbreg', + 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_struct2( + 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_struct2( + 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(''))) + + +class ExprDumper(GenericExprVisitor): + def __init__(self, structs): + super(ExprDumper, self).__init__(structs) + self._init_lookups() + self._str_parts = [] + + def clear(self): + self._str_parts = [] + + def get_str(self): + return '; '.join(self._str_parts) + + def _init_lookups(self): + self._ops_with_decimal_arg = set([ + 'DW_OP_const1u', 'DW_OP_const1s', 'DW_OP_const2u', 'DW_OP_const2s', + 'DW_OP_const4u', 'DW_OP_const4s', 'DW_OP_constu', 'DW_OP_consts', + 'DW_OP_pick', 'DW_OP_plus_uconst', 'DW_OP_bra', 'DW_OP_skip', + 'DW_OP_fbreg', 'DW_OP_piece', 'DW_OP_deref_size', + 'DW_OP_xderef_size', 'DW_OP_regx',]) + + for n in range(0, 32): + self._ops_with_decimal_arg.add('DW_OP_breg%s' % n) + + self._ops_with_two_decimal_args = set([ + 'DW_OP_const8u', 'DW_OP_const8s', 'DW_OP_bregx', 'DW_OP_bit_piece']) + + self._ops_with_hex_arg = set( + ['DW_OP_addr', 'DW_OP_call2', 'DW_OP_call4', 'DW_OP_call_ref']) + + def _after_visit(self, opcode, opcode_name, args): + self._str_parts.append(self._dump_to_string(opcode, opcode_name, args)) + + def _dump_to_string(self, opcode, opcode_name, args): + if len(args) == 0: + return opcode_name + elif opcode_name in self._ops_with_decimal_arg: + return '%s: %s' % (opcode_name, args[0]) + elif opcode_name in self._ops_with_hex_arg: + return '%s: %x' % (opcode_name, args[0]) + elif opcode_name in self._ops_with_two_decimal_args: + return '%s: %s %s' % (opcode_name, args[0], args[1]) + else: + return '' % opcode_name + + + diff --git a/elftools/dwarf/location_expr.py b/elftools/dwarf/location_expr.py deleted file mode 100644 index 1d92da3..0000000 --- a/elftools/dwarf/location_expr.py +++ /dev/null @@ -1,297 +0,0 @@ -#------------------------------------------------------------------------------- -# elftools: dwarf/location_expr.py -# -# Decoding DWARF location expressions -# -# Eli Bendersky (eliben@gmail.com) -# This code is in the public domain -#------------------------------------------------------------------------------- -from cStringIO import StringIO - -from ..common.utils import struct_parse, bytelist2string - - -# Location expression opcodes. name -> opcode mapping -DW_OP_name2opcode = dict( - DW_OP_addr=0x03, - DW_OP_deref=0x06, - DW_OP_const1u=0x08, - DW_OP_const1s=0x09, - DW_OP_const2u=0x0a, - DW_OP_const2s=0x0b, - DW_OP_const4u=0x0c, - DW_OP_const4s=0x0d, - DW_OP_const8u=0x0e, - DW_OP_const8s=0x0f, - DW_OP_constu=0x10, - DW_OP_consts=0x11, - DW_OP_dup=0x12, - DW_OP_drop=0x13, - DW_OP_over=0x14, - DW_OP_pick=0x15, - DW_OP_swap=0x16, - DW_OP_rot=0x17, - DW_OP_xderef=0x18, - DW_OP_abs=0x19, - DW_OP_and=0x1a, - DW_OP_div=0x1b, - DW_OP_minus=0x1c, - DW_OP_mod=0x1d, - DW_OP_mul=0x1e, - DW_OP_neg=0x1f, - DW_OP_not=0x20, - DW_OP_or=0x21, - DW_OP_plus=0x22, - DW_OP_plus_uconst=0x23, - DW_OP_shl=0x24, - DW_OP_shr=0x25, - DW_OP_shra=0x26, - DW_OP_xor=0x27, - DW_OP_bra=0x28, - DW_OP_eq=0x29, - DW_OP_ge=0x2a, - DW_OP_gt=0x2b, - DW_OP_le=0x2c, - DW_OP_lt=0x2d, - DW_OP_ne=0x2e, - DW_OP_skip=0x2f, - DW_OP_regx=0x90, - DW_OP_fbreg=0x91, - DW_OP_bregx=0x92, - DW_OP_piece=0x93, - DW_OP_deref_size=0x94, - DW_OP_xderef_size=0x95, - DW_OP_nop=0x96, - DW_OP_push_object_address=0x97, - DW_OP_call2=0x98, - DW_OP_call4=0x99, - DW_OP_call_ref=0x9a, - DW_OP_form_tls_address=0x9b, - DW_OP_call_frame_cfa=0x9c, - DW_OP_bit_piece=0x9d, -) - -def _generate_dynamic_values(map, prefix, index_start, index_end, value_start): - """ Generate values in a map (dict) dynamically. Each key starts with - a (string) prefix, followed by an index in the inclusive range - [index_start, index_end]. The values start at value_start. - """ - for index in range(index_start, index_end + 1): - name = '%s%s' % (prefix, index) - value = value_start + index - index_start - map[name] = value - -_generate_dynamic_values(DW_OP_name2opcode, 'DW_OP_lit', 0, 31, 0x30) -_generate_dynamic_values(DW_OP_name2opcode, 'DW_OP_reg', 0, 31, 0x50) -_generate_dynamic_values(DW_OP_name2opcode, 'DW_OP_breg', 0, 31, 0x70) - -# opcode -> name mapping -DW_OP_opcode2name = dict((v, k) for k, v in DW_OP_name2opcode.iteritems()) - - -class GenericLocationExprVisitor(object): - def __init__(self, structs): - self.structs = structs - self._init_dispatch_table() - self.stream = None - self._cur_opcode = None - self._cur_opcode_name = None - self._cur_args = [] - - def process_expr(self, loc_expr): - """ Process (visit) a location expression. Currently two possible - types are supported for expr: - - 1. File-like stream object - 2. List of byte values (the result of parsed DW_FORM_block* - attributes). - """ - if hasattr(loc_expr, 'read') and hasattr(loc_expr, 'seek'): - # looks like a stream - self.stream = loc_expr - else: - self.stream = StringIO(bytelist2string(loc_expr)) - - while True: - # Get the next opcode from the stream. If nothing is left in the - # stream, we're done. - byte = self.stream.read(1) - if len(byte) == 0: - break - - # Decode the opcode and its name - self._cur_opcode = ord(byte) - self._cur_opcode_name = DW_OP_opcode2name.get( - self._cur_opcode, 'OP:0x%x' % self._cur_opcode) - # Will be filled in by visitors - self._cur_args = [] - - # Dispatch to a visitor function - visitor = self._dispatch_table.get( - self._cur_opcode, - self._default_visitor) - visitor(self._cur_opcode, self._cur_opcode_name) - - # Finally call the post-visit function - self._after_visit( - self._cur_opcode, self._cur_opcode_name, self._cur_args) - - def _after_visit(self, opcode, opcode_name, args): - pass - - def _default_visitor(self, opcode, opcode_name): - pass - - def _visit_OP_with_no_args(self, opcode, opcode_name): - self._cur_args = [] - - def _visit_OP_addr(self, opcode, opcode_name): - 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(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(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_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_struct2( - self.structs.Dwarf_uint32(''), - self.structs.Dwarf_uint32(''))) - add('DW_OP_const8s', - self._make_visitor_arg_struct2( - self.structs.Dwarf_int32(''), - self.structs.Dwarf_int32(''))) - 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']: - 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_fbreg', - 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_struct2( - 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_struct2( - 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(''))) - - -class LocationExpressionDumper(GenericLocationExprVisitor): - def __init__(self, structs): - super(LocationExpressionDumper, self).__init__(structs) - self._init_lookups() - self._str_parts = [] - - def clear(self): - self._str_parts = [] - - def get_str(self): - return '; '.join(self._str_parts) - - def _init_lookups(self): - self._ops_with_decimal_arg = set([ - 'DW_OP_const1u', 'DW_OP_const1s', 'DW_OP_const2u', 'DW_OP_const2s', - 'DW_OP_const4u', 'DW_OP_const4s', 'DW_OP_constu', 'DW_OP_consts', - 'DW_OP_pick', 'DW_OP_plus_uconst', 'DW_OP_bra', 'DW_OP_skip', - 'DW_OP_fbreg', 'DW_OP_piece', 'DW_OP_deref_size', - 'DW_OP_xderef_size', 'DW_OP_regx',]) - - for n in range(0, 32): - self._ops_with_decimal_arg.add('DW_OP_breg%s' % n) - - self._ops_with_two_decimal_args = set([ - 'DW_OP_const8u', 'DW_OP_const8s', 'DW_OP_bregx', 'DW_OP_bit_piece']) - - self._ops_with_hex_arg = set( - ['DW_OP_addr', 'DW_OP_call2', 'DW_OP_call4', 'DW_OP_call_ref']) - - def _after_visit(self, opcode, opcode_name, args): - self._str_parts.append(self._dump_to_string(opcode, opcode_name, args)) - - def _dump_to_string(self, opcode, opcode_name, args): - if len(args) == 0: - return opcode_name - elif opcode_name in self._ops_with_decimal_arg: - return '%s: %s' % (opcode_name, args[0]) - elif opcode_name in self._ops_with_hex_arg: - return '%s: %x' % (opcode_name, args[0]) - elif opcode_name in self._ops_with_two_decimal_args: - return '%s: %s %s' % (opcode_name, args[0], args[1]) - else: - return '' % opcode_name - - - diff --git a/tests/test_dwarf_expr.py b/tests/test_dwarf_expr.py new file mode 100644 index 0000000..4202633 --- /dev/null +++ b/tests/test_dwarf_expr.py @@ -0,0 +1,62 @@ +import sys, unittest +from cStringIO import StringIO + +sys.path.extend(('..', '.')) +from elftools.dwarf.dwarf_expr import ExprDumper +from elftools.dwarf.structs import DWARFStructs + + +class TestExprDumper(unittest.TestCase): + structs32 = DWARFStructs( + little_endian=True, + dwarf_format=32, + address_size=4) + + def setUp(self): + self.visitor = ExprDumper(self.structs32) + + def test_basic_single(self): + self.visitor.process_expr([0x1b]) + self.assertEqual(self.visitor.get_str(), + 'DW_OP_div') + + self.setUp() + self.visitor.process_expr([0x74, 0x82, 0x01]) + self.assertEqual(self.visitor.get_str(), + 'DW_OP_breg4: 130') + + self.setUp() + self.visitor.process_expr([0x91, 0x82, 0x01]) + self.assertEqual(self.visitor.get_str(), + 'DW_OP_fbreg: 130') + + self.setUp() + self.visitor.process_expr([0x9d, 0x8f, 0x0A, 0x90, 0x01]) + self.assertEqual(self.visitor.get_str(), + 'DW_OP_bit_piece: 1295 144') + + def test_basic_sequence(self): + self.visitor.process_expr([0x03, 0x01, 0x02, 0, 0, 0x06, 0x06]) + self.assertEqual(self.visitor.get_str(), + 'DW_OP_addr: 201; DW_OP_deref; DW_OP_deref') + + self.setUp() + self.visitor.process_expr([0x15, 0xFF, 0x0b, 0xf1, 0xff]) + self.assertEqual(self.visitor.get_str(), + 'DW_OP_pick: 255; DW_OP_const2s: -15') + + self.setUp() + self.visitor.process_expr([0x1d, 0x1e, 0x1d, 0x1e, 0x1d, 0x1e]) + self.assertEqual(self.visitor.get_str(), + 'DW_OP_mod; DW_OP_mul; DW_OP_mod; DW_OP_mul; DW_OP_mod; DW_OP_mul') + + def test_stream_input(self): + self.visitor.process_expr(StringIO('\x1b')) + self.assertEqual(self.visitor.get_str(), + 'DW_OP_div') + + +if __name__ == '__main__': + unittest.main() + + diff --git a/tests/test_dwarf_location_expr.py b/tests/test_dwarf_location_expr.py deleted file mode 100644 index d0d6ab0..0000000 --- a/tests/test_dwarf_location_expr.py +++ /dev/null @@ -1,62 +0,0 @@ -import sys, unittest -from cStringIO import StringIO - -sys.path.extend(('..', '.')) -from elftools.dwarf.location_expr import LocationExpressionDumper -from elftools.dwarf.structs import DWARFStructs - - -class TestLocationExpressionDumper(unittest.TestCase): - structs32 = DWARFStructs( - little_endian=True, - dwarf_format=32, - address_size=4) - - def setUp(self): - self.visitor = LocationExpressionDumper(self.structs32) - - def test_basic_single(self): - self.visitor.process_expr([0x1b]) - self.assertEqual(self.visitor.get_str(), - 'DW_OP_div') - - self.setUp() - self.visitor.process_expr([0x74, 0x82, 0x01]) - self.assertEqual(self.visitor.get_str(), - 'DW_OP_breg4: 130') - - self.setUp() - self.visitor.process_expr([0x91, 0x82, 0x01]) - self.assertEqual(self.visitor.get_str(), - 'DW_OP_fbreg: 130') - - self.setUp() - self.visitor.process_expr([0x9d, 0x8f, 0x0A, 0x90, 0x01]) - self.assertEqual(self.visitor.get_str(), - 'DW_OP_bit_piece: 1295 144') - - def test_basic_sequence(self): - self.visitor.process_expr([0x03, 0x01, 0x02, 0, 0, 0x06, 0x06]) - self.assertEqual(self.visitor.get_str(), - 'DW_OP_addr: 201; DW_OP_deref; DW_OP_deref') - - self.setUp() - self.visitor.process_expr([0x15, 0xFF, 0x0b, 0xf1, 0xff]) - self.assertEqual(self.visitor.get_str(), - 'DW_OP_pick: 255; DW_OP_const2s: -15') - - self.setUp() - self.visitor.process_expr([0x1d, 0x1e, 0x1d, 0x1e, 0x1d, 0x1e]) - self.assertEqual(self.visitor.get_str(), - 'DW_OP_mod; DW_OP_mul; DW_OP_mod; DW_OP_mul; DW_OP_mod; DW_OP_mul') - - def test_stream_input(self): - self.visitor.process_expr(StringIO('\x1b')) - self.assertEqual(self.visitor.get_str(), - 'DW_OP_div') - - -if __name__ == '__main__': - unittest.main() - -