Upstream version 8.36.161.0
[platform/framework/web/crosswalk.git] / src / third_party / pyelftools / elftools / dwarf / dwarf_expr.py
1 #-------------------------------------------------------------------------------
2 # elftools: dwarf/dwarf_expr.py
3 #
4 # Decoding DWARF expressions
5 #
6 # Eli Bendersky (eliben@gmail.com)
7 # This code is in the public domain
8 #-------------------------------------------------------------------------------
9 from ..common.py3compat import BytesIO, iteritems
10 from ..common.utils import struct_parse, bytelist2string
11
12
13 # DWARF expression opcodes. name -> opcode mapping
14 DW_OP_name2opcode = dict(
15     DW_OP_addr=0x03,
16     DW_OP_deref=0x06,
17     DW_OP_const1u=0x08,
18     DW_OP_const1s=0x09,
19     DW_OP_const2u=0x0a,
20     DW_OP_const2s=0x0b,
21     DW_OP_const4u=0x0c,
22     DW_OP_const4s=0x0d,
23     DW_OP_const8u=0x0e,
24     DW_OP_const8s=0x0f,
25     DW_OP_constu=0x10,
26     DW_OP_consts=0x11,
27     DW_OP_dup=0x12,
28     DW_OP_drop=0x13,
29     DW_OP_over=0x14,
30     DW_OP_pick=0x15,
31     DW_OP_swap=0x16,
32     DW_OP_rot=0x17,
33     DW_OP_xderef=0x18,
34     DW_OP_abs=0x19,
35     DW_OP_and=0x1a,
36     DW_OP_div=0x1b,
37     DW_OP_minus=0x1c,
38     DW_OP_mod=0x1d,
39     DW_OP_mul=0x1e,
40     DW_OP_neg=0x1f,
41     DW_OP_not=0x20,
42     DW_OP_or=0x21,
43     DW_OP_plus=0x22,
44     DW_OP_plus_uconst=0x23,
45     DW_OP_shl=0x24,
46     DW_OP_shr=0x25,
47     DW_OP_shra=0x26,
48     DW_OP_xor=0x27,
49     DW_OP_bra=0x28,
50     DW_OP_eq=0x29,
51     DW_OP_ge=0x2a,
52     DW_OP_gt=0x2b,
53     DW_OP_le=0x2c,
54     DW_OP_lt=0x2d,
55     DW_OP_ne=0x2e,
56     DW_OP_skip=0x2f,
57     DW_OP_regx=0x90,
58     DW_OP_fbreg=0x91,
59     DW_OP_bregx=0x92,
60     DW_OP_piece=0x93,
61     DW_OP_deref_size=0x94,
62     DW_OP_xderef_size=0x95,
63     DW_OP_nop=0x96,
64     DW_OP_push_object_address=0x97,
65     DW_OP_call2=0x98,
66     DW_OP_call4=0x99,
67     DW_OP_call_ref=0x9a,
68     DW_OP_form_tls_address=0x9b,
69     DW_OP_call_frame_cfa=0x9c,
70     DW_OP_bit_piece=0x9d,
71 )
72
73 def _generate_dynamic_values(map, prefix, index_start, index_end, value_start):
74     """ Generate values in a map (dict) dynamically. Each key starts with
75         a (string) prefix, followed by an index in the inclusive range
76         [index_start, index_end]. The values start at value_start.
77     """
78     for index in range(index_start, index_end + 1):
79         name = '%s%s' % (prefix, index)
80         value = value_start + index - index_start
81         map[name] = value
82
83 _generate_dynamic_values(DW_OP_name2opcode, 'DW_OP_lit', 0, 31, 0x30)
84 _generate_dynamic_values(DW_OP_name2opcode, 'DW_OP_reg', 0, 31, 0x50)
85 _generate_dynamic_values(DW_OP_name2opcode, 'DW_OP_breg', 0, 31, 0x70)
86
87 # opcode -> name mapping
88 DW_OP_opcode2name = dict((v, k) for k, v in iteritems(DW_OP_name2opcode))
89
90
91 class GenericExprVisitor(object):
92     """ A DWARF expression is a sequence of instructions encoded in a block
93         of bytes. This class decodes the sequence into discrete instructions
94         with their arguments and allows generic "visiting" to process them.
95
96         Usage: subclass this class, and override the needed methods. The
97         easiest way would be to just override _after_visit, which gets passed
98         each decoded instruction (with its arguments) in order. Clients of
99         the visitor then just execute process_expr. The subclass can keep
100         its own internal information updated in _after_visit and provide
101         methods to extract it. For a good example of this usage, see the
102         ExprDumper class in the descriptions module.
103
104         A more complex usage could be to override visiting methods for
105         specific instructions, by placing them into the dispatch table.
106     """
107     def __init__(self, structs):
108         self.structs = structs
109         self._init_dispatch_table()
110         self.stream = None
111         self._cur_opcode = None
112         self._cur_opcode_name = None
113         self._cur_args = []
114
115     def process_expr(self, expr):
116         """ Process (visit) a DWARF expression. expr should be a list of
117             (integer) byte values.
118         """
119         self.stream = BytesIO(bytelist2string(expr))
120
121         while True:
122             # Get the next opcode from the stream. If nothing is left in the
123             # stream, we're done.
124             byte = self.stream.read(1)
125             if len(byte) == 0:
126                 break
127
128             # Decode the opcode and its name
129             self._cur_opcode = ord(byte)
130             self._cur_opcode_name = DW_OP_opcode2name.get(
131                 self._cur_opcode, 'OP:0x%x' % self._cur_opcode)
132             # Will be filled in by visitors
133             self._cur_args = [] 
134
135             # Dispatch to a visitor function
136             visitor = self._dispatch_table.get(
137                     self._cur_opcode,
138                     self._default_visitor)
139             visitor(self._cur_opcode, self._cur_opcode_name)
140
141             # Finally call the post-visit function
142             self._after_visit(
143                     self._cur_opcode, self._cur_opcode_name, self._cur_args)
144
145     def _after_visit(self, opcode, opcode_name, args):
146         pass
147         
148     def _default_visitor(self, opcode, opcode_name):
149         pass
150         
151     def _visit_OP_with_no_args(self, opcode, opcode_name):
152         self._cur_args = []
153
154     def _visit_OP_addr(self, opcode, opcode_name):
155         self._cur_args = [
156                 struct_parse(self.structs.Dwarf_target_addr(''), self.stream)]
157
158     def _make_visitor_arg_struct(self, struct_arg):
159         """ Create a visitor method for an opcode that that accepts a single
160             argument, specified by a struct.
161         """
162         def visitor(opcode, opcode_name):
163             self._cur_args = [struct_parse(struct_arg, self.stream)]
164         return visitor
165
166     def _make_visitor_arg_struct2(self, struct_arg1, struct_arg2):
167         """ Create a visitor method for an opcode that that accepts two
168             arguments, specified by structs.
169         """
170         def visitor(opcode, opcode_name):
171             self._cur_args = [
172                 struct_parse(struct_arg1, self.stream),
173                 struct_parse(struct_arg2, self.stream)]
174         return visitor
175
176     def _init_dispatch_table(self):
177         self._dispatch_table = {}
178         def add(opcode_name, func):
179             self._dispatch_table[DW_OP_name2opcode[opcode_name]] = func
180             
181         add('DW_OP_addr', self._visit_OP_addr)
182         add('DW_OP_const1u', 
183             self._make_visitor_arg_struct(self.structs.Dwarf_uint8('')))
184         add('DW_OP_const1s', 
185             self._make_visitor_arg_struct(self.structs.Dwarf_int8('')))
186         add('DW_OP_const2u', 
187             self._make_visitor_arg_struct(self.structs.Dwarf_uint16('')))
188         add('DW_OP_const2s', 
189             self._make_visitor_arg_struct(self.structs.Dwarf_int16('')))
190         add('DW_OP_const4u', 
191             self._make_visitor_arg_struct(self.structs.Dwarf_uint32('')))
192         add('DW_OP_const4s', 
193             self._make_visitor_arg_struct(self.structs.Dwarf_int32('')))
194         add('DW_OP_const8u', 
195             self._make_visitor_arg_struct2(
196                 self.structs.Dwarf_uint32(''),
197                 self.structs.Dwarf_uint32('')))
198         add('DW_OP_const8s', 
199             self._make_visitor_arg_struct2(
200                 self.structs.Dwarf_int32(''),
201                 self.structs.Dwarf_int32('')))
202         add('DW_OP_constu',
203             self._make_visitor_arg_struct(self.structs.Dwarf_uleb128('')))
204         add('DW_OP_consts',
205             self._make_visitor_arg_struct(self.structs.Dwarf_sleb128('')))
206         add('DW_OP_pick',
207             self._make_visitor_arg_struct(self.structs.Dwarf_uint8('')))
208         add('DW_OP_plus_uconst',
209             self._make_visitor_arg_struct(self.structs.Dwarf_uleb128('')))
210         add('DW_OP_bra', 
211             self._make_visitor_arg_struct(self.structs.Dwarf_int16('')))
212         add('DW_OP_skip', 
213             self._make_visitor_arg_struct(self.structs.Dwarf_int16('')))
214
215         for opname in [ 'DW_OP_deref', 'DW_OP_dup', 'DW_OP_drop', 'DW_OP_over',
216                         'DW_OP_swap', 'DW_OP_swap', 'DW_OP_rot', 'DW_OP_xderef',
217                         'DW_OP_abs', 'DW_OP_and', 'DW_OP_div', 'DW_OP_minus',
218                         'DW_OP_mod', 'DW_OP_mul', 'DW_OP_neg', 'DW_OP_not',
219                         'DW_OP_plus', 'DW_OP_shl', 'DW_OP_shr', 'DW_OP_shra',
220                         'DW_OP_xor', 'DW_OP_eq', 'DW_OP_ge', 'DW_OP_gt',
221                         'DW_OP_le', 'DW_OP_lt', 'DW_OP_ne', 'DW_OP_nop',
222                         'DW_OP_push_object_address', 'DW_OP_form_tls_address',
223                         'DW_OP_call_frame_cfa']:
224             add(opname, self._visit_OP_with_no_args)
225
226         for n in range(0, 32):
227             add('DW_OP_lit%s' % n, self._visit_OP_with_no_args)
228             add('DW_OP_reg%s' % n, self._visit_OP_with_no_args)
229             add('DW_OP_breg%s' % n, 
230                 self._make_visitor_arg_struct(self.structs.Dwarf_sleb128('')))
231
232         add('DW_OP_fbreg',
233             self._make_visitor_arg_struct(self.structs.Dwarf_sleb128('')))
234         add('DW_OP_regx',
235             self._make_visitor_arg_struct(self.structs.Dwarf_uleb128('')))
236         add('DW_OP_bregx',
237             self._make_visitor_arg_struct2(
238                 self.structs.Dwarf_uleb128(''),
239                 self.structs.Dwarf_sleb128('')))
240         add('DW_OP_piece',
241             self._make_visitor_arg_struct(self.structs.Dwarf_uleb128('')))
242         add('DW_OP_bit_piece',
243             self._make_visitor_arg_struct2(
244                 self.structs.Dwarf_uleb128(''),
245                 self.structs.Dwarf_uleb128('')))
246         add('DW_OP_deref_size',
247             self._make_visitor_arg_struct(self.structs.Dwarf_int8('')))
248         add('DW_OP_xderef_size',
249             self._make_visitor_arg_struct(self.structs.Dwarf_int8('')))
250         add('DW_OP_call2',
251             self._make_visitor_arg_struct(self.structs.Dwarf_uint16('')))
252         add('DW_OP_call4',
253             self._make_visitor_arg_struct(self.structs.Dwarf_uint32('')))
254         add('DW_OP_call_ref',
255             self._make_visitor_arg_struct(self.structs.Dwarf_offset('')))
256
257