renamed 'location expression' to the more general 'dwarf expression'
authorEli Bendersky <eliben@gmail.com>
Wed, 7 Dec 2011 12:43:47 +0000 (14:43 +0200)
committerEli Bendersky <eliben@gmail.com>
Wed, 7 Dec 2011 12:43:47 +0000 (14:43 +0200)
elftools/dwarf/descriptions.py
elftools/dwarf/dwarf_expr.py [new file with mode: 0644]
elftools/dwarf/location_expr.py [deleted file]
tests/test_dwarf_expr.py [new file with mode: 0644]
tests/test_dwarf_location_expr.py [deleted file]

index 57df8a4a323686ae49aff27d70eb2c3e790a07bc..4f88bf371e9cf715c92a70f08d2e62763ba2087f 100644 (file)
@@ -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 (file)
index 0000000..6140d20
--- /dev/null
@@ -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 '<unknown %s>' % opcode_name
+
+
+
diff --git a/elftools/dwarf/location_expr.py b/elftools/dwarf/location_expr.py
deleted file mode 100644 (file)
index 1d92da3..0000000
+++ /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 '<unknown %s>' % opcode_name
-
-
-
diff --git a/tests/test_dwarf_expr.py b/tests/test_dwarf_expr.py
new file mode 100644 (file)
index 0000000..4202633
--- /dev/null
@@ -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 (file)
index d0d6ab0..0000000
+++ /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()
-
-