dwarf/dwarf_expr: Add support for DW_OP_GNU_push_tls_address (#315)
authorWilliam Woodruff <william@trailofbits.com>
Mon, 1 Jun 2020 13:00:00 +0000 (09:00 -0400)
committerGitHub <noreply@github.com>
Mon, 1 Jun 2020 13:00:00 +0000 (06:00 -0700)
* dwarf/dwarf_expr: Add support for DW_OP_GNU_push_tls_address

* dwarf/dwarf_expr: Use a single 64-bit operand for const8x

DWARFv4 2.5.1.1: this should be consumed as a single 64-bit operand,
not as two 32-bit operands.

* dwarf/descriptions: Fix descriptions for const8{u,s}

* test: Add tests for changed OPs

elftools/dwarf/descriptions.py
elftools/dwarf/dwarf_expr.py
test/test_dwarf_expr.py

index a7a75998e1b16645d05b88f7a130b0588fa9c866..c3fa0788df96aab5073706b4d9d96d04f72c1680 100644 (file)
@@ -559,16 +559,15 @@ class ExprDumper(object):
     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',])
+            'DW_OP_const4u', 'DW_OP_const4s', 'DW_OP_const8u', 'DW_OP_const8s',
+            '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_two_decimal_args = set(['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'])
index c46c9afc90531399b7ec8b3d12e0cdd10fe4bc37..bb85daa00a487c48bdb50bd2926048f81858177c 100644 (file)
@@ -83,6 +83,7 @@ DW_OP_name2opcode = dict(
     DW_OP_convert=0xa8,
     DW_OP_reinterpret=0xa9,
     DW_OP_lo_user=0xe0,
+    DW_OP_GNU_push_tls_address=0xe0,
     DW_OP_GNU_implicit_pointer=0xf2,
     DW_OP_GNU_entry_value=0xf3,
     DW_OP_GNU_const_type=0xf4,
@@ -202,10 +203,8 @@ def _init_dispatch_table(structs):
     add('DW_OP_const2s', parse_arg_struct(structs.Dwarf_int16('')))
     add('DW_OP_const4u', parse_arg_struct(structs.Dwarf_uint32('')))
     add('DW_OP_const4s', parse_arg_struct(structs.Dwarf_int32('')))
-    add('DW_OP_const8u', parse_arg_struct2(structs.Dwarf_uint32(''),
-                                           structs.Dwarf_uint32('')))
-    add('DW_OP_const8s', parse_arg_struct2(structs.Dwarf_int32(''),
-                                           structs.Dwarf_int32('')))
+    add('DW_OP_const8u', parse_arg_struct(structs.Dwarf_uint64('')))
+    add('DW_OP_const8s', parse_arg_struct(structs.Dwarf_int64('')))
     add('DW_OP_constu', parse_arg_struct(structs.Dwarf_uleb128('')))
     add('DW_OP_consts', parse_arg_struct(structs.Dwarf_sleb128('')))
     add('DW_OP_pick', parse_arg_struct(structs.Dwarf_uint8('')))
@@ -221,7 +220,8 @@ def _init_dispatch_table(structs):
                     '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']:
+                    'DW_OP_call_frame_cfa', 'DW_OP_stack_value',
+                    'DW_OP_GNU_push_tls_address']:
         add(opname, parse_noargs())
 
     for n in range(0, 32):
index 1d925f600a32e8c7873a978f9275a8579da38f1f..42186bac38aff194eaa16ac08e4e80903b1d02a7 100644 (file)
@@ -40,6 +40,9 @@ class TestExprDumper(unittest.TestCase):
         self.assertEqual(self.visitor.dump_expr([0x9d, 0x8f, 0x0A, 0x90, 0x01]),
             'DW_OP_bit_piece: 1295 144')
 
+        self.assertEqual(self.visitor.dump_expr([0x0e, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00]),
+            'DW_OP_const8u: 71777214294589695')
+
     def test_basic_sequence(self):
         self.assertEqual(self.visitor.dump_expr([0x03, 0x01, 0x02, 0, 0, 0x06, 0x06]),
             'DW_OP_addr: 201; DW_OP_deref; DW_OP_deref')
@@ -50,6 +53,9 @@ class TestExprDumper(unittest.TestCase):
         self.assertEqual(self.visitor.dump_expr([0x1d, 0x1e, 0x1d, 0x1e, 0x1d, 0x1e]),
             'DW_OP_mod; DW_OP_mul; DW_OP_mod; DW_OP_mul; DW_OP_mod; DW_OP_mul')
 
+        self.assertEqual(self.visitor.dump_expr([0x08, 0x0f, 0xe0]),
+            'DW_OP_const1u: 15; DW_OP_GNU_push_tls_address')
+
 
 class TestParseExpr(unittest.TestCase):
     structs32 = DWARFStructs(
@@ -68,6 +74,9 @@ class TestParseExpr(unittest.TestCase):
         lst = p.parse_expr([0x90, 16])
         self.assertEqual(lst, [DWARFExprOp(op=0x90, op_name='DW_OP_regx', args=[16])])
 
+        lst = p.parse_expr([0xe0])
+        self.assertEqual(lst, [DWARFExprOp(op=0xe0, op_name='DW_OP_GNU_push_tls_address', args=[])])
+
 
 if __name__ == '__main__':
     unittest.main()