mirror of
https://github.com/JakeHillion/drgn.git
synced 2024-12-25 18:23:07 +00:00
0cb3876900
Instead, make a mock DwarfIndex and CompilationUnit and construct Dies directly.
782 lines
32 KiB
Python
782 lines
32 KiB
Python
import os.path
|
|
from unittest.mock import Mock
|
|
|
|
from drgn.internal.dwarf import (
|
|
Die,
|
|
DieAttrib,
|
|
DwarfAttribNotFoundError,
|
|
DW_AT,
|
|
DW_FORM,
|
|
DW_TAG,
|
|
)
|
|
from drgn.internal.dwarfindex import DwarfIndex
|
|
from drgn.internal.dwarftypeindex import DwarfTypeIndex
|
|
from drgn.type import (
|
|
ArrayType,
|
|
BitFieldType,
|
|
BoolType,
|
|
EnumType,
|
|
FloatType,
|
|
FunctionType,
|
|
IntType,
|
|
PointerType,
|
|
StructType,
|
|
TypedefType,
|
|
UnionType,
|
|
VoidType,
|
|
)
|
|
from tests.test_type import (
|
|
anonymous_color_type,
|
|
anonymous_point_type,
|
|
color_type,
|
|
line_segment_type,
|
|
pointer_size,
|
|
point_type,
|
|
TypeTestCase,
|
|
)
|
|
|
|
|
|
class MockDwarfIndex:
|
|
def __init__(self, dies):
|
|
self._dies = dies
|
|
self.address_size = 8
|
|
|
|
def find(self, name, tag=0):
|
|
result = []
|
|
for die in self._dies:
|
|
try:
|
|
if (tag == 0 or die.tag == tag) and die.name() == name:
|
|
result.append(die)
|
|
except DwarfAttribNotFoundError:
|
|
continue
|
|
if not result:
|
|
raise ValueError()
|
|
return result
|
|
|
|
|
|
class TestDwarfTypeIndex(TypeTestCase):
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.dies = []
|
|
self.dwarf_index = MockDwarfIndex(self.dies)
|
|
|
|
self.type_index = DwarfTypeIndex(self.dwarf_index)
|
|
self.cu = Mock()
|
|
self.cu.die = self.dies.__getitem__
|
|
|
|
def tearDown(self):
|
|
super().tearDown()
|
|
|
|
def assertFromDwarfType(self, offset, type_):
|
|
self.assertEqual(self.type_index._from_dwarf_type(self.cu.die(offset)),
|
|
type_)
|
|
|
|
def test_void(self):
|
|
self.assertEqual(self.type_index.find('void'), VoidType())
|
|
self.assertEqual(self.type_index.find('const void'),
|
|
VoidType({'const'}))
|
|
|
|
def test_char(self):
|
|
self.dies[:] = [
|
|
# char
|
|
Die(self.cu, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x01'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x06'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'char'),
|
|
]),
|
|
# signed char
|
|
Die(self.cu, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x01'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x06'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'signed char'),
|
|
]),
|
|
# unsigned char
|
|
Die(self.cu, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x01'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x08'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'unsigned char'),
|
|
]),
|
|
]
|
|
|
|
self.assertFromDwarfType(0, IntType('char', 1, True))
|
|
self.assertFromDwarfType(1, IntType('signed char', 1, True))
|
|
self.assertFromDwarfType(2, IntType('unsigned char', 1, False))
|
|
|
|
self.assertEqual(self.type_index.find('char'),
|
|
IntType('char', 1, True))
|
|
|
|
def test_short(self):
|
|
self.dies[:] = [
|
|
# short
|
|
Die(self.cu, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x02'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x05'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'short'),
|
|
]),
|
|
# signed short
|
|
Die(self.cu, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x02'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x05'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'signed short'),
|
|
]),
|
|
# unsigned short
|
|
Die(self.cu, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x02'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x07'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'unsigned short'),
|
|
]),
|
|
]
|
|
|
|
self.assertFromDwarfType(0, IntType('short', 2, True))
|
|
self.assertFromDwarfType(1, IntType('short', 2, True))
|
|
self.assertFromDwarfType(2, IntType('unsigned short', 2, False))
|
|
|
|
def test_int(self):
|
|
self.dies[:] = [
|
|
# int
|
|
Die(self.cu, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x04'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x05'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'int'),
|
|
]),
|
|
# signed int
|
|
Die(self.cu, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x04'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x05'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'signed int'),
|
|
]),
|
|
# unsigned int
|
|
Die(self.cu, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x04'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x07'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'unsigned int'),
|
|
]),
|
|
]
|
|
|
|
self.assertFromDwarfType(0, IntType('int', 4, True))
|
|
self.assertFromDwarfType(1, IntType('int', 4, True))
|
|
self.assertFromDwarfType(2, IntType('unsigned int', 4, False))
|
|
|
|
def test_long(self):
|
|
self.dies[:] = [
|
|
# long
|
|
Die(self.cu, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x08'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x05'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'long'),
|
|
]),
|
|
# signed long
|
|
Die(self.cu, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x08'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x05'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'signed long'),
|
|
]),
|
|
# unsigned long
|
|
Die(self.cu, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x08'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x07'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'unsigned long'),
|
|
]),
|
|
]
|
|
|
|
self.assertFromDwarfType(0, IntType('long', 8, True))
|
|
self.assertFromDwarfType(1, IntType('long', 8, True))
|
|
self.assertFromDwarfType(2, IntType('unsigned long', 8, False))
|
|
|
|
def test_long_long(self):
|
|
self.dies[:] = [
|
|
# long long
|
|
Die(self.cu, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x08'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x05'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'long long'),
|
|
]),
|
|
# signed long long
|
|
Die(self.cu, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x08'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x05'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'signed long long'),
|
|
]),
|
|
# unsigned long long
|
|
Die(self.cu, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x08'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x07'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'unsigned long long'),
|
|
]),
|
|
]
|
|
|
|
self.assertFromDwarfType(0, IntType('long long', 8, True))
|
|
self.assertFromDwarfType(1, IntType('long long', 8, True))
|
|
self.assertFromDwarfType(2, IntType('unsigned long long', 8, False))
|
|
|
|
def test_float(self):
|
|
self.dies[:] = [
|
|
# float
|
|
Die(None, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x04'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x04'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'float'),
|
|
]),
|
|
# double
|
|
Die(None, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x08'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x04'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'double'),
|
|
]),
|
|
# long double
|
|
Die(None, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x10'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x04'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'long double'),
|
|
]),
|
|
# double long
|
|
Die(None, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x10'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x04'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'double long'),
|
|
]),
|
|
]
|
|
|
|
self.assertFromDwarfType(0, FloatType('float', 4))
|
|
self.assertFromDwarfType(1, FloatType('double', 8))
|
|
self.assertFromDwarfType(2, FloatType('long double', 16))
|
|
self.assertFromDwarfType(3, FloatType('long double', 16))
|
|
|
|
def test_bool(self):
|
|
self.dies[:] = [
|
|
# _Bool
|
|
Die(None, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x01'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x02'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'_Bool'),
|
|
]),
|
|
]
|
|
self.assertFromDwarfType(0, BoolType('_Bool', 1))
|
|
|
|
def test_qualifiers(self):
|
|
self.dies[:] = [
|
|
# int
|
|
Die(self.cu, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x04'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x05'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'int'),
|
|
]),
|
|
# const int
|
|
Die(self.cu, DW_TAG.const_type, [
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
]),
|
|
# volatile int
|
|
Die(self.cu, DW_TAG.volatile_type, [
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
]),
|
|
# volatile const int
|
|
Die(self.cu, DW_TAG.volatile_type, [
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 1),
|
|
]),
|
|
# _Atomic volatile const int
|
|
Die(self.cu, DW_TAG.atomic_type, [
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 3),
|
|
]),
|
|
# restrict int
|
|
Die(self.cu, DW_TAG.restrict_type, [
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
]),
|
|
# const void
|
|
Die(self.cu, DW_TAG.const_type, []),
|
|
]
|
|
|
|
self.assertFromDwarfType(1, IntType('int', 4, True, {'const'}))
|
|
self.assertFromDwarfType(2, IntType('int', 4, True, {'volatile'}))
|
|
self.assertFromDwarfType(3, IntType('int', 4, True, {'const', 'volatile'}))
|
|
self.assertFromDwarfType(4, IntType('int', 4, True, {'_Atomic', 'const', 'volatile'}))
|
|
self.assertFromDwarfType(5, IntType('int', 4, True, {'restrict'}))
|
|
self.assertFromDwarfType(6, VoidType({'const'}))
|
|
|
|
self.assertEqual(self.type_index._from_dwarf_type(self.cu.die(1),
|
|
frozenset({'volatile'})),
|
|
IntType('int', 4, True, {'const', 'volatile'}))
|
|
self.assertEqual(self.type_index._from_dwarf_type(self.cu.die(6),
|
|
frozenset({'volatile'})),
|
|
VoidType({'const', 'volatile'}))
|
|
|
|
def test_typedef(self):
|
|
self.dies[:] = [
|
|
# int
|
|
Die(self.cu, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x04'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x05'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'int'),
|
|
]),
|
|
# const int
|
|
Die(self.cu, DW_TAG.const_type, [
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
]),
|
|
# typedef int INT
|
|
Die(self.cu, DW_TAG.typedef, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'INT'),
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
]),
|
|
# const INT
|
|
Die(self.cu, DW_TAG.const_type, [
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 2),
|
|
]),
|
|
# typedef const int CINT
|
|
Die(self.cu, DW_TAG.typedef, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'CINT'),
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 1),
|
|
]),
|
|
]
|
|
|
|
typedef_type = TypedefType('INT', IntType('int', 4, True))
|
|
|
|
self.assertFromDwarfType(2, typedef_type)
|
|
self.assertFromDwarfType(3, TypedefType('INT', IntType('int', 4, True), {'const'}))
|
|
self.assertFromDwarfType(4, TypedefType('CINT', IntType('int', 4, True, {'const'})))
|
|
|
|
self.assertEqual(self.type_index.find('INT'), typedef_type)
|
|
|
|
def test_struct(self):
|
|
self.dies[:] = [
|
|
# int
|
|
Die(self.cu, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x04'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x05'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'int'),
|
|
]),
|
|
# struct point {
|
|
# int x, y;
|
|
# };
|
|
Die(self.cu, DW_TAG.structure_type, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'point'),
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x08'),
|
|
], lambda: [
|
|
Die(self.cu, DW_TAG.member, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'x'),
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
DieAttrib(DW_AT.data_member_location, DW_FORM.data1, b'\x00'),
|
|
]),
|
|
Die(self.cu, DW_TAG.member, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'y'),
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
DieAttrib(DW_AT.data_member_location, DW_FORM.data1, b'\x04'),
|
|
]),
|
|
]),
|
|
# struct line_segment {
|
|
# struct point a, b;
|
|
# };
|
|
Die(self.cu, DW_TAG.structure_type, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'line_segment'),
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x10'),
|
|
], lambda: [
|
|
Die(self.cu, DW_TAG.member, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'a'),
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 1),
|
|
DieAttrib(DW_AT.data_member_location, DW_FORM.data1, b'\x00'),
|
|
]),
|
|
Die(self.cu, DW_TAG.member, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'b'),
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 1),
|
|
DieAttrib(DW_AT.data_member_location, DW_FORM.data1, b'\x08'),
|
|
]),
|
|
]),
|
|
# struct {
|
|
# int x, y;
|
|
# };
|
|
Die(self.cu, DW_TAG.structure_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x08'),
|
|
], lambda: [
|
|
Die(self.cu, DW_TAG.member, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'x'),
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
DieAttrib(DW_AT.data_member_location, DW_FORM.data1, b'\x00'),
|
|
]),
|
|
Die(self.cu, DW_TAG.member, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'y'),
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
DieAttrib(DW_AT.data_member_location, DW_FORM.data1, b'\x04'),
|
|
]),
|
|
]),
|
|
# struct foo;
|
|
Die(self.cu, DW_TAG.structure_type, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'foo'),
|
|
DieAttrib(DW_AT.declaration, DW_FORM.flag_present, 1),
|
|
]),
|
|
]
|
|
|
|
self.assertFromDwarfType(1, point_type)
|
|
self.assertFromDwarfType(2, line_segment_type)
|
|
self.assertFromDwarfType(3, anonymous_point_type)
|
|
self.assertFromDwarfType(4, StructType('foo', None, None))
|
|
|
|
self.assertEqual(self.type_index.find('struct point'),
|
|
point_type)
|
|
|
|
def test_bit_field(self):
|
|
self.dies[:] = [
|
|
# int
|
|
Die(self.cu, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x04'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x05'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'int'),
|
|
]),
|
|
# const int
|
|
Die(self.cu, DW_TAG.const_type, [
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
]),
|
|
# struct {
|
|
# int x : 4;
|
|
# const int y : 28;
|
|
# int z : 5;
|
|
# };
|
|
Die(self.cu, DW_TAG.structure_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x08'),
|
|
], lambda: [
|
|
Die(self.cu, DW_TAG.member, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'x'),
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x04'),
|
|
DieAttrib(DW_AT.bit_size, DW_FORM.data1, b'\x04'),
|
|
DieAttrib(DW_AT.bit_offset, DW_FORM.data1, b'\x1c'),
|
|
DieAttrib(DW_AT.data_member_location, DW_FORM.data1, b'\x00'),
|
|
]),
|
|
Die(self.cu, DW_TAG.member, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'y'),
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 1),
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x04'),
|
|
DieAttrib(DW_AT.bit_size, DW_FORM.data1, b'\x1c'),
|
|
DieAttrib(DW_AT.bit_offset, DW_FORM.data1, b'\x00'),
|
|
DieAttrib(DW_AT.data_member_location, DW_FORM.data1, b'\x00'),
|
|
]),
|
|
Die(self.cu, DW_TAG.member, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'z'),
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x04'),
|
|
DieAttrib(DW_AT.bit_size, DW_FORM.data1, b'\x05'),
|
|
DieAttrib(DW_AT.bit_offset, DW_FORM.data1, b'\x1b'),
|
|
DieAttrib(DW_AT.data_member_location, DW_FORM.data1, b'\x04'),
|
|
]),
|
|
]),
|
|
]
|
|
|
|
self.assertFromDwarfType(2, StructType(None, 8, [
|
|
('x', 0, lambda: BitFieldType(IntType('int', 4, True), 0, 4)),
|
|
('y', 0, lambda: BitFieldType(IntType('int', 4, True, {'const'}), 4, 28)),
|
|
('z', 4, lambda: BitFieldType(IntType('int', 4, True), 0, 5)),
|
|
]))
|
|
|
|
def test_union(self):
|
|
self.dies[:] = [
|
|
# int
|
|
Die(self.cu, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x04'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x05'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'int'),
|
|
]),
|
|
# float
|
|
Die(None, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x04'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x04'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'float'),
|
|
]),
|
|
# union value {
|
|
# int i;
|
|
# float f;
|
|
# };
|
|
Die(self.cu, DW_TAG.union_type, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'value'),
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x04'),
|
|
], lambda: [
|
|
Die(self.cu, DW_TAG.member, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'i'),
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
DieAttrib(DW_AT.data_member_location, DW_FORM.data1, b'\x00'),
|
|
]),
|
|
Die(self.cu, DW_TAG.member, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'f'),
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 1),
|
|
DieAttrib(DW_AT.data_member_location, DW_FORM.data1, b'\x00'),
|
|
]),
|
|
]),
|
|
# union foo;
|
|
Die(self.cu, DW_TAG.union_type, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'foo'),
|
|
DieAttrib(DW_AT.declaration, DW_FORM.flag_present, 1),
|
|
]),
|
|
]
|
|
|
|
value_type = UnionType('value', 4, [
|
|
('i', 0, lambda: IntType('int', 4, True)),
|
|
('f', 0, lambda: FloatType('float', 4)),
|
|
])
|
|
|
|
self.assertFromDwarfType(2, value_type)
|
|
self.assertFromDwarfType(3, UnionType('foo', None, None))
|
|
|
|
self.assertEqual(self.type_index.find('union value'), value_type)
|
|
|
|
def test_enum(self):
|
|
self.dies[:] = [
|
|
# int
|
|
Die(self.cu, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x04'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x05'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'int'),
|
|
]),
|
|
# unsigned int
|
|
Die(self.cu, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x04'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x07'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'unsigned int'),
|
|
]),
|
|
# enum color {
|
|
# RED,
|
|
# GREEN,
|
|
# BLUE,
|
|
# };
|
|
Die(self.cu, DW_TAG.enumeration_type, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'color'),
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 1),
|
|
], lambda: [
|
|
Die(self.cu, DW_TAG.enumerator, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'RED'),
|
|
DieAttrib(DW_AT.const_value, DW_FORM.data1, b'\x00'),
|
|
]),
|
|
Die(self.cu, DW_TAG.enumerator, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'GREEN'),
|
|
DieAttrib(DW_AT.const_value, DW_FORM.data1, b'\x01'),
|
|
]),
|
|
Die(self.cu, DW_TAG.enumerator, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'BLUE'),
|
|
DieAttrib(DW_AT.const_value, DW_FORM.data1, b'\x02'),
|
|
]),
|
|
]),
|
|
# enum {
|
|
# RED = 0,
|
|
# GREEN = -1,
|
|
# BLUE = -2,
|
|
# };
|
|
Die(self.cu, DW_TAG.enumeration_type, [
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
], lambda: [
|
|
Die(self.cu, DW_TAG.enumerator, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'RED'),
|
|
DieAttrib(DW_AT.const_value, DW_FORM.sdata, 0),
|
|
]),
|
|
Die(self.cu, DW_TAG.enumerator, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'GREEN'),
|
|
DieAttrib(DW_AT.const_value, DW_FORM.sdata, -1),
|
|
]),
|
|
Die(self.cu, DW_TAG.enumerator, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'BLUE'),
|
|
DieAttrib(DW_AT.const_value, DW_FORM.sdata, -2),
|
|
]),
|
|
]),
|
|
# These two are the same as the two above, but without DW_AT_type,
|
|
# like generated by GCC before 5.1.
|
|
Die(self.cu, DW_TAG.enumeration_type, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'color'),
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x04'),
|
|
], lambda: [
|
|
Die(self.cu, DW_TAG.enumerator, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'RED'),
|
|
DieAttrib(DW_AT.const_value, DW_FORM.data1, b'\x00'),
|
|
]),
|
|
Die(self.cu, DW_TAG.enumerator, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'GREEN'),
|
|
DieAttrib(DW_AT.const_value, DW_FORM.data1, b'\x01'),
|
|
]),
|
|
Die(self.cu, DW_TAG.enumerator, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'BLUE'),
|
|
DieAttrib(DW_AT.const_value, DW_FORM.data1, b'\x02'),
|
|
]),
|
|
]),
|
|
Die(self.cu, DW_TAG.enumeration_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x04'),
|
|
], lambda: [
|
|
Die(self.cu, DW_TAG.enumerator, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'RED'),
|
|
DieAttrib(DW_AT.const_value, DW_FORM.sdata, 0),
|
|
]),
|
|
Die(self.cu, DW_TAG.enumerator, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'GREEN'),
|
|
DieAttrib(DW_AT.const_value, DW_FORM.sdata, -1),
|
|
]),
|
|
Die(self.cu, DW_TAG.enumerator, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'BLUE'),
|
|
DieAttrib(DW_AT.const_value, DW_FORM.sdata, -2),
|
|
]),
|
|
]),
|
|
Die(self.cu, DW_TAG.enumeration_type, [
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'foo'),
|
|
DieAttrib(DW_AT.declaration, DW_FORM.flag_present, 1),
|
|
]),
|
|
]
|
|
|
|
self.assertFromDwarfType(2, color_type)
|
|
self.assertFromDwarfType(3, anonymous_color_type)
|
|
self.assertFromDwarfType(4, EnumType('color', IntType('', 4, False), [
|
|
('RED', 0),
|
|
('GREEN', 1),
|
|
('BLUE', 2)
|
|
]))
|
|
self.assertFromDwarfType(5, EnumType(None, IntType('', 4, True), [
|
|
('RED', 0),
|
|
('GREEN', -1),
|
|
('BLUE', -2)
|
|
]))
|
|
self.assertFromDwarfType(6, EnumType('foo', None, None))
|
|
|
|
self.assertEqual(self.type_index.find('enum color'), color_type)
|
|
|
|
def test_pointer(self):
|
|
self.dies[:] = [
|
|
# int
|
|
Die(self.cu, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x04'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x05'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'int'),
|
|
]),
|
|
# const int
|
|
Die(self.cu, DW_TAG.const_type, [
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
]),
|
|
# int *
|
|
Die(self.cu, DW_TAG.pointer_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x08'),
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
]),
|
|
# int * const
|
|
Die(self.cu, DW_TAG.const_type, [
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 2),
|
|
]),
|
|
# void *
|
|
Die(self.cu, DW_TAG.pointer_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x08'),
|
|
]),
|
|
]
|
|
|
|
self.assertFromDwarfType(2, PointerType(8, IntType('int', 4, True)))
|
|
self.assertFromDwarfType(3, PointerType(8, IntType('int', 4, True), {'const'}))
|
|
self.assertFromDwarfType(4, PointerType(8, VoidType()))
|
|
|
|
self.assertEqual(self.type_index.find('void *'), PointerType(8, VoidType()))
|
|
|
|
def test_array(self):
|
|
self.dies[:] = [
|
|
# int
|
|
Die(self.cu, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x04'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x05'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'int'),
|
|
]),
|
|
# int [2]
|
|
Die(self.cu, DW_TAG.array_type, [
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
], lambda: [
|
|
Die(self.cu, DW_TAG.subrange_type, [
|
|
DieAttrib(DW_AT.upper_bound, DW_FORM.data1, b'\x01'),
|
|
]),
|
|
]),
|
|
# int [2][3]
|
|
Die(self.cu, DW_TAG.array_type, [
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
], lambda: [
|
|
Die(self.cu, DW_TAG.subrange_type, [
|
|
DieAttrib(DW_AT.upper_bound, DW_FORM.data1, b'\x01'),
|
|
]),
|
|
Die(self.cu, DW_TAG.subrange_type, [
|
|
DieAttrib(DW_AT.upper_bound, DW_FORM.data1, b'\x02'),
|
|
]),
|
|
]),
|
|
# int [2][3][4]
|
|
Die(self.cu, DW_TAG.array_type, [
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
], lambda: [
|
|
Die(self.cu, DW_TAG.subrange_type, [
|
|
DieAttrib(DW_AT.upper_bound, DW_FORM.data1, b'\x01'),
|
|
]),
|
|
Die(self.cu, DW_TAG.subrange_type, [
|
|
DieAttrib(DW_AT.upper_bound, DW_FORM.data1, b'\x02'),
|
|
]),
|
|
Die(self.cu, DW_TAG.subrange_type, [
|
|
DieAttrib(DW_AT.upper_bound, DW_FORM.data1, b'\x03'),
|
|
]),
|
|
]),
|
|
# int []
|
|
Die(self.cu, DW_TAG.array_type, [
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
], lambda: [
|
|
Die(self.cu, DW_TAG.subrange_type, []),
|
|
]),
|
|
# int [][2]
|
|
Die(self.cu, DW_TAG.array_type, [
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
], lambda: [
|
|
Die(self.cu, DW_TAG.subrange_type, []),
|
|
Die(self.cu, DW_TAG.subrange_type, [
|
|
DieAttrib(DW_AT.upper_bound, DW_FORM.data1, b'\x01'),
|
|
]),
|
|
]),
|
|
]
|
|
|
|
self.assertFromDwarfType(1, ArrayType(IntType('int', 4, True), 2, 8))
|
|
self.assertFromDwarfType(2, ArrayType(ArrayType(IntType('int', 4, True), 3, 8), 2, 8))
|
|
self.assertFromDwarfType(3, ArrayType(ArrayType(ArrayType(IntType('int', 4, True), 4, 8), 3, 8), 2, 8))
|
|
self.assertFromDwarfType(4, ArrayType(IntType('int', 4, True), None, 8))
|
|
self.assertFromDwarfType(5, ArrayType(ArrayType(IntType('int', 4, True), 2, 8), None, 8))
|
|
|
|
self.assertEqual(self.type_index.find('int []'),
|
|
ArrayType(IntType('int', 4, True), None, 8))
|
|
|
|
def test_function(self):
|
|
self.dies[:] = [
|
|
# int
|
|
Die(self.cu, DW_TAG.base_type, [
|
|
DieAttrib(DW_AT.byte_size, DW_FORM.data1, b'\x04'),
|
|
DieAttrib(DW_AT.encoding, DW_FORM.data1, b'\x05'),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'int'),
|
|
]),
|
|
# int foo(int)
|
|
Die(self.cu, DW_TAG.subroutine_type, [
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
], lambda: [
|
|
Die(self.cu, DW_TAG.formal_parameter, [
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
]),
|
|
]),
|
|
# int foo(int x)
|
|
Die(self.cu, DW_TAG.subroutine_type, [
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
], lambda: [
|
|
Die(self.cu, DW_TAG.formal_parameter, [
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
DieAttrib(DW_AT.name, DW_FORM.string, b'x'),
|
|
]),
|
|
]),
|
|
# int foo(int, ...)
|
|
Die(self.cu, DW_TAG.subroutine_type, [
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
], lambda: [
|
|
Die(self.cu, DW_TAG.formal_parameter, [
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
]),
|
|
Die(self.cu, DW_TAG.unspecified_parameters, []),
|
|
]),
|
|
# int foo()
|
|
Die(self.cu, DW_TAG.subroutine_type, [
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
], lambda: [
|
|
Die(self.cu, DW_TAG.unspecified_parameters, []),
|
|
]),
|
|
# int foo(void)
|
|
Die(self.cu, DW_TAG.subroutine_type, [
|
|
DieAttrib(DW_AT.type, DW_FORM.ref4, 0),
|
|
]),
|
|
]
|
|
|
|
self.assertFromDwarfType(1, FunctionType(8, IntType('int', 4, True), [(IntType('int', 4, True), None)]))
|
|
self.assertFromDwarfType(2, FunctionType(8, IntType('int', 4, True), [(IntType('int', 4, True), 'x')]))
|
|
self.assertFromDwarfType(3, FunctionType(8, IntType('int', 4, True), [(IntType('int', 4, True), None)], variadic=True))
|
|
self.assertFromDwarfType(4, FunctionType(8, IntType('int', 4, True), None))
|
|
self.assertFromDwarfType(5, FunctionType(8, IntType('int', 4, True), []))
|