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
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
# 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):
--- /dev/null
+#-------------------------------------------------------------------------------
+# 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
+
+
+
+++ /dev/null
-#-------------------------------------------------------------------------------
-# 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
-
-
-
--- /dev/null
+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()
+
+
+++ /dev/null
-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()
-
-