mirror of
https://github.com/JakeHillion/drgn.git
synced 2024-12-23 09:43:06 +00:00
Store CU and parent in DIE
Back-references from the DIE to the CU and the parent DIE will make it much easier to implement several features.
This commit is contained in:
parent
64f66f747f
commit
e6a58f533a
@ -19,12 +19,12 @@ def dump_cu(dwarf_file, cu, cu_name, *, indent=0):
|
||||
print(f'{prefix} is_64_bit = {cu.is_64_bit}')
|
||||
|
||||
|
||||
def dump_die(dwarf_file, cu, die, *, indent=0, recurse=False):
|
||||
def dump_die(dwarf_file, die, *, indent=0, recurse=False):
|
||||
prefix = ' ' * indent
|
||||
print(f'{prefix}<{die.cu_offset}> {tag_name(die.tag)}')
|
||||
for name, form, value in die:
|
||||
if form == DW_FORM.string or form == DW_FORM.strp:
|
||||
value = repr(dwarf_file.at_string(cu, form, value))[1:]
|
||||
value = repr(dwarf_file.at_string(die.cu, form, value))[1:]
|
||||
elif form in {DW_FORM.data1, DW_FORM.data2, DW_FORM.data4, DW_FORM.data8}:
|
||||
value = repr(value)[1:]
|
||||
print(f'{prefix} {at_name(name)} ({form_name(form)}) = {value}')
|
||||
@ -36,7 +36,7 @@ def dump_die(dwarf_file, cu, die, *, indent=0, recurse=False):
|
||||
else:
|
||||
if children is not None:
|
||||
for child in children:
|
||||
dump_die(dwarf_file, cu, child, indent=indent + 2, recurse=True)
|
||||
dump_die(dwarf_file, child, indent=indent + 2, recurse=True)
|
||||
|
||||
|
||||
def dump_lnp_include_directories(lnp, *, indent=0):
|
||||
@ -152,8 +152,8 @@ def dump_cus(dwarf_file, args):
|
||||
if args.die:
|
||||
die = dwarf_file.cu_die(cu)
|
||||
if args.recursive:
|
||||
dwarf_file.parse_die_children(cu, die, recurse=True)
|
||||
dump_die(dwarf_file, cu, die, indent=2, recurse=args.recursive)
|
||||
dwarf_file.parse_die_children(die, recurse=True)
|
||||
dump_die(dwarf_file, die, indent=2, recurse=args.recursive)
|
||||
if (args.include_directories or args.file_names or args.lines or
|
||||
args.line_number_program):
|
||||
lnp = dwarf_file.cu_line_number_program_header(cu)
|
||||
|
@ -143,7 +143,7 @@ class DwarfFile:
|
||||
|
||||
def cu_name(self, cu: lldwarf.CompilationUnitHeader) -> bytes:
|
||||
try:
|
||||
return self.die_name(cu, self.cu_die(cu))
|
||||
return self.die_name(self.cu_die(cu))
|
||||
except KeyError:
|
||||
return b''
|
||||
|
||||
@ -159,18 +159,19 @@ class DwarfFile:
|
||||
debug_info = self.section('.debug_info')
|
||||
abbrev_table = self.abbrev_table(cu.debug_abbrev_offset)
|
||||
die_offset = cu.offset + (23 if cu.is_64_bit else 11)
|
||||
die = lldwarf.parse_die(cu, abbrev_table, cu.offset, self._mmap,
|
||||
die = lldwarf.parse_die(cu, None, abbrev_table, cu.offset, self._mmap,
|
||||
die_offset, recurse=recurse)
|
||||
cu.die = die
|
||||
return die
|
||||
|
||||
def parse_die_children(self, cu: lldwarf.CompilationUnitHeader,
|
||||
die: lldwarf.DwarfDie, *, recurse: bool=False) -> None:
|
||||
def parse_die_children(self, die: lldwarf.DwarfDie, *,
|
||||
recurse: bool=False) -> None:
|
||||
if not hasattr(die, 'children'):
|
||||
cu = die.cu
|
||||
debug_info = self.section('.debug_info')
|
||||
abbrev_table = self.abbrev_table(cu.debug_abbrev_offset)
|
||||
offset = cu.offset + die.cu_offset + die.die_length
|
||||
die.children = lldwarf.parse_die_siblings(cu, abbrev_table,
|
||||
die.children = lldwarf.parse_die_siblings(cu, die, abbrev_table,
|
||||
cu.offset, self._mmap,
|
||||
offset=offset,
|
||||
recurse=recurse)
|
||||
@ -196,10 +197,9 @@ class DwarfFile:
|
||||
high_pc = high_pc_value
|
||||
return low_pc <= address < high_pc
|
||||
|
||||
def die_name(self, cu: lldwarf.CompilationUnitHeader,
|
||||
die: lldwarf.DwarfDie) -> bytes:
|
||||
def die_name(self, die: lldwarf.DwarfDie) -> bytes:
|
||||
form, value = die.find(DW_AT.name)
|
||||
return self.at_string(cu, form, value)
|
||||
return self.at_string(die.cu, form, value)
|
||||
|
||||
def die_address(self, die: lldwarf.DwarfDie) -> int:
|
||||
try:
|
||||
|
@ -51,10 +51,10 @@ class DwarfProgram:
|
||||
symbol = dwarf_file.symbol(name)
|
||||
dwarf_file, cu = self.find_cu_by_addr(symbol.st_value)
|
||||
die = self._file.cu_die(cu)
|
||||
dwarf_file.parse_die_children(cu, die)
|
||||
dwarf_file.parse_die_children(die)
|
||||
for child in die.children:
|
||||
if (child.tag == DW_TAG.subprogram and
|
||||
dwarf_file.die_name(cu, child).decode() == name):
|
||||
dwarf_file.die_name(child).decode() == name):
|
||||
return child
|
||||
else:
|
||||
raise ValueError('subprogram not found')
|
||||
@ -84,7 +84,7 @@ class DwarfProgram:
|
||||
cu: lldwarf.CompilationUnitHeader,
|
||||
addr: int) -> lldwarf.DwarfDie:
|
||||
die = dwarf_file.cu_die(cu)
|
||||
dwarf_file.parse_die_children(cu, die)
|
||||
dwarf_file.parse_die_children(die)
|
||||
for child in die.children:
|
||||
if (child.tag == DW_TAG.subprogram and
|
||||
dwarf_file.die_contains_address(child, addr)):
|
||||
@ -99,7 +99,7 @@ class DwarfProgram:
|
||||
row = self._best_breakpoint_row(dwarf_file, cu, lnp, matrix, filename, lineno)
|
||||
|
||||
subprogram = self._find_subprogram_containing_address(dwarf_file, cu, row.address)
|
||||
subprogram_name = dwarf_file.die_name(cu, subprogram).decode()
|
||||
subprogram_name = dwarf_file.die_name(subprogram).decode()
|
||||
subprogram_address = dwarf_file.die_address(subprogram)
|
||||
assert row.address >= subprogram_address
|
||||
return f'{subprogram_name}+0x{row.address - subprogram_address:x}'
|
||||
|
@ -99,8 +99,10 @@ static PyObject *DwarfDie_new(PyTypeObject *subtype, PyObject *args,
|
||||
PyObject *kwds)
|
||||
{
|
||||
static char *keywords[] = {
|
||||
"cu_offset", "die_length", "tag", "children", "attributes", NULL
|
||||
"cu", "parent", "cu_offset", "die_length", "tag", "children", "attributes", NULL
|
||||
};
|
||||
PyObject *cu;
|
||||
PyObject *parent;
|
||||
PyObject *cu_offset;
|
||||
PyObject *die_length;
|
||||
PyObject *tag;
|
||||
@ -109,9 +111,9 @@ static PyObject *DwarfDie_new(PyTypeObject *subtype, PyObject *args,
|
||||
DwarfDie *die = NULL;
|
||||
Py_ssize_t i, len;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOO:DwarfDie", keywords,
|
||||
&cu_offset, &die_length, &tag, &children,
|
||||
&attribs))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOOOO:DwarfDie", keywords,
|
||||
&cu, &parent, &cu_offset, &die_length,
|
||||
&tag, &children, &attribs))
|
||||
return NULL;
|
||||
|
||||
tmp = PySequence_Tuple(attribs);
|
||||
@ -125,6 +127,10 @@ static PyObject *DwarfDie_new(PyTypeObject *subtype, PyObject *args,
|
||||
die->dict = PyDict_New();
|
||||
if (!die->dict)
|
||||
goto err;
|
||||
die->cu = cu;
|
||||
Py_INCREF(cu);
|
||||
die->parent = parent;
|
||||
Py_INCREF(parent);
|
||||
die->cu_offset = PyLong_AsSsize_t(cu_offset);
|
||||
if (PyErr_Occurred()) {
|
||||
if (PyErr_ExceptionMatches(PyExc_OverflowError))
|
||||
@ -214,8 +220,9 @@ static PyObject *DwarfDie_repr(DwarfDie *self)
|
||||
goto out;
|
||||
|
||||
/* XXX: children = NULL? */
|
||||
ret = PyUnicode_FromFormat("DwarfDie(cu_offset=%zd, die_length=%zd, tag=%llu, children=%R, attributes=%R)",
|
||||
self->cu_offset, self->die_length,
|
||||
ret = PyUnicode_FromFormat("DwarfDie(cu=%R, parent=%R, cu_offset=%zd, die_length=%zd, tag=%llu, children=%R, attributes=%R)",
|
||||
self->cu, self->parent, self->cu_offset,
|
||||
self->die_length,
|
||||
(unsigned long long)self->tag,
|
||||
self->children, tmp);
|
||||
|
||||
@ -506,7 +513,7 @@ block:
|
||||
}
|
||||
|
||||
PyObject *LLDwarf_ParseDieSiblings(Py_buffer *buffer, Py_ssize_t *offset,
|
||||
CompilationUnitHeader *cu,
|
||||
CompilationUnitHeader *cu, PyObject *parent,
|
||||
PyObject *abbrev_table, Py_ssize_t cu_offset,
|
||||
bool recurse)
|
||||
{
|
||||
@ -519,8 +526,9 @@ PyObject *LLDwarf_ParseDieSiblings(Py_buffer *buffer, Py_ssize_t *offset,
|
||||
for (;;) {
|
||||
PyObject *child;
|
||||
|
||||
child = LLDwarf_ParseDie(buffer, offset, cu, abbrev_table,
|
||||
cu_offset, recurse, true);
|
||||
child = LLDwarf_ParseDie(buffer, offset, cu, parent,
|
||||
abbrev_table, cu_offset, recurse,
|
||||
true);
|
||||
if (PyErr_Occurred())
|
||||
goto err;
|
||||
if (!child)
|
||||
@ -540,9 +548,9 @@ err:
|
||||
}
|
||||
|
||||
PyObject *LLDwarf_ParseDie(Py_buffer *buffer, Py_ssize_t *offset,
|
||||
CompilationUnitHeader *cu, PyObject *abbrev_table,
|
||||
Py_ssize_t cu_offset, bool recurse,
|
||||
bool jump_to_sibling)
|
||||
CompilationUnitHeader *cu, PyObject *parent,
|
||||
PyObject *abbrev_table, Py_ssize_t cu_offset,
|
||||
bool recurse, bool jump_to_sibling)
|
||||
{
|
||||
Py_ssize_t orig_offset;
|
||||
DwarfDie *die;
|
||||
@ -579,6 +587,12 @@ PyObject *LLDwarf_ParseDie(Py_buffer *buffer, Py_ssize_t *offset,
|
||||
if (!die->dict)
|
||||
goto err;
|
||||
|
||||
die->cu = (PyObject *)cu;
|
||||
Py_INCREF(cu);
|
||||
|
||||
die->parent = parent;
|
||||
Py_INCREF(parent);
|
||||
|
||||
die->cu_offset = orig_offset - cu_offset;
|
||||
die->tag = decl->tag;
|
||||
die->children = NULL;
|
||||
@ -601,6 +615,7 @@ PyObject *LLDwarf_ParseDie(Py_buffer *buffer, Py_ssize_t *offset,
|
||||
die->children = Py_None;
|
||||
} else if (recurse || (jump_to_sibling && !sibling)) {
|
||||
die->children = LLDwarf_ParseDieSiblings(buffer, offset, cu,
|
||||
(PyObject *)die,
|
||||
abbrev_table,
|
||||
cu_offset, true);
|
||||
if (!die->children)
|
||||
@ -635,6 +650,10 @@ static PyMethodDef DwarfDie_methods[] = {
|
||||
};
|
||||
|
||||
static PyMemberDef DwarfDie_members[] = {
|
||||
{"cu", T_OBJECT, offsetof(DwarfDie, cu), 0,
|
||||
"CU this DIE was parsed from"},
|
||||
{"parent", T_OBJECT, offsetof(DwarfDie, parent), 0,
|
||||
"the parent DIE of this DIE"},
|
||||
{"cu_offset", T_UINT64T, offsetof(DwarfDie, cu_offset), 0,
|
||||
"offset from the beginning of the CU where this DIE starts"},
|
||||
{"die_length", T_UINT64T, offsetof(DwarfDie, die_length), 0,
|
||||
@ -648,10 +667,13 @@ static PyMemberDef DwarfDie_members[] = {
|
||||
};
|
||||
|
||||
#define DwarfDie_DOC \
|
||||
"DwarfDie(cu_offset, die_length, tag, children, attribs) -> new debugging information entry\n\n" \
|
||||
"DwarfDie(cu, parent, cu_offset, die_length, tag, children,\n" \
|
||||
" attribs) -> new debugging information entry\n\n" \
|
||||
"Create a new DWARF debugging information entry. len(die) is the\n" \
|
||||
"number of attributes and die[i] is the ith attribute.\n\n" \
|
||||
"Arguments:\n" \
|
||||
"cu -- CompilationUnitHeader\n" \
|
||||
"parent -- DwarfDie or None\n" \
|
||||
"cu_offset -- integer offset\n" \
|
||||
"die_length -- intger length\n" \
|
||||
"tag -- integer tag of the DIE\n" \
|
||||
|
@ -88,6 +88,8 @@ struct DwarfAttrib {
|
||||
typedef struct {
|
||||
PyObject_VAR_HEAD
|
||||
PyObject *dict;
|
||||
PyObject *cu;
|
||||
PyObject *parent;
|
||||
Py_ssize_t cu_offset;
|
||||
Py_ssize_t die_length;
|
||||
uint64_t tag;
|
||||
@ -155,13 +157,13 @@ PyObject *LLDwarf_ParseArangeTableHeader(Py_buffer *buffer, Py_ssize_t *offset);
|
||||
PyObject *LLDwarf_ParseCompilationUnitHeader(Py_buffer *buffer,
|
||||
Py_ssize_t *offset);
|
||||
PyObject *LLDwarf_ParseDie(Py_buffer *buffer, Py_ssize_t *offset,
|
||||
CompilationUnitHeader *cu, PyObject *abbrev_table,
|
||||
Py_ssize_t cu_offset, bool recurse,
|
||||
bool jump_to_sibling);
|
||||
CompilationUnitHeader *cu, PyObject *parent,
|
||||
PyObject *abbrev_table, Py_ssize_t cu_offset,
|
||||
bool recurse, bool jump_to_sibling);
|
||||
PyObject *LLDwarf_ParseDieSiblings(Py_buffer *buffer, Py_ssize_t *offset,
|
||||
CompilationUnitHeader *cu,
|
||||
PyObject *abbrev_table,
|
||||
Py_ssize_t cu_offset, bool recurse);
|
||||
CompilationUnitHeader *cu, PyObject *parent,
|
||||
PyObject *abbrev_table, Py_ssize_t cu_offset,
|
||||
bool recurse);
|
||||
PyObject *LLDwarf_ParseLineNumberProgramHeader(Py_buffer *buffer,
|
||||
Py_ssize_t *offset);
|
||||
PyObject *LLDwarf_ExecuteLineNumberProgram(Py_buffer *buffer,
|
||||
|
@ -254,21 +254,22 @@ static PyObject *parse_compilation_unit_header(PyObject *self, PyObject *args,
|
||||
static PyObject *parse_die(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *keywords[] = {
|
||||
"cu", "abbrev_table", "cu_offset", "buffer", "offset", "recurse", NULL,
|
||||
"cu", "parent", "abbrev_table", "cu_offset", "buffer", "offset",
|
||||
"recurse", NULL,
|
||||
};
|
||||
PyObject *cu, *abbrev_table;
|
||||
PyObject *cu, *parent, *abbrev_table;
|
||||
Py_ssize_t cu_offset;
|
||||
Py_buffer buffer;
|
||||
Py_ssize_t offset = 0;
|
||||
int recurse = 0;
|
||||
PyObject *ret;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!ny*|np:parse_die",
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!OO!ny*|np:parse_die",
|
||||
keywords,
|
||||
(PyObject *)&CompilationUnitHeader_type, &cu,
|
||||
(PyObject *)&PyDict_Type, &abbrev_table,
|
||||
&cu_offset, &buffer, &offset,
|
||||
&recurse))
|
||||
&parent, (PyObject *)&PyDict_Type,
|
||||
&abbrev_table, &cu_offset, &buffer,
|
||||
&offset, &recurse))
|
||||
return NULL;
|
||||
|
||||
if (offset < 0) {
|
||||
@ -278,7 +279,7 @@ static PyObject *parse_die(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
}
|
||||
|
||||
ret = LLDwarf_ParseDie(&buffer, &offset, (CompilationUnitHeader *)cu,
|
||||
abbrev_table, cu_offset, recurse, false);
|
||||
parent, abbrev_table, cu_offset, recurse, false);
|
||||
if (!ret && !PyErr_Occurred()) {
|
||||
Py_INCREF(Py_None);
|
||||
ret = Py_None;
|
||||
@ -291,21 +292,22 @@ static PyObject *parse_die_siblings(PyObject *self, PyObject *args,
|
||||
PyObject *kwds)
|
||||
{
|
||||
static char *keywords[] = {
|
||||
"cu", "abbrev_table", "cu_offset", "buffer", "offset", "recurse", NULL,
|
||||
"cu", "parent", "abbrev_table", "cu_offset", "buffer", "offset",
|
||||
"recurse", NULL,
|
||||
};
|
||||
PyObject *cu, *abbrev_table;
|
||||
PyObject *cu, *parent, *abbrev_table;
|
||||
Py_ssize_t cu_offset;
|
||||
Py_buffer buffer;
|
||||
Py_ssize_t offset = 0;
|
||||
int recurse = 0;
|
||||
PyObject *ret;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!ny*|np:parse_die_siblings",
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!OO!ny*|np:parse_die_siblings",
|
||||
keywords,
|
||||
(PyObject *)&CompilationUnitHeader_type, &cu,
|
||||
(PyObject *)&PyDict_Type, &abbrev_table,
|
||||
&cu_offset, &buffer, &offset,
|
||||
&recurse))
|
||||
(PyObject *)&CompilationUnitHeader_type,
|
||||
&cu, &parent, (PyObject *)&PyDict_Type,
|
||||
&abbrev_table, &cu_offset, &buffer,
|
||||
&offset, &recurse))
|
||||
return NULL;
|
||||
|
||||
if (offset < 0) {
|
||||
@ -315,7 +317,7 @@ static PyObject *parse_die_siblings(PyObject *self, PyObject *args,
|
||||
}
|
||||
|
||||
ret = LLDwarf_ParseDieSiblings(&buffer, &offset, (CompilationUnitHeader *)cu,
|
||||
abbrev_table, cu_offset, recurse);
|
||||
parent, abbrev_table, cu_offset, recurse);
|
||||
PyBuffer_Release(&buffer);
|
||||
return ret;
|
||||
}
|
||||
|
@ -5,101 +5,101 @@ import unittest
|
||||
|
||||
class TestDieObject(unittest.TestCase):
|
||||
def test_find(self):
|
||||
die = lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.sdata, -99),))
|
||||
die = lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.sdata, -99),))
|
||||
self.assertEqual(die.find(DW_AT.lo_user), (DW_FORM.sdata, -99))
|
||||
with self.assertRaises(KeyError):
|
||||
die.find(DW_AT.name)
|
||||
|
||||
def test_init_errors(self):
|
||||
with self.assertRaises(TypeError):
|
||||
lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, None)
|
||||
lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, None)
|
||||
with self.assertRaises(TypeError):
|
||||
lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, (None,))
|
||||
lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, (None,))
|
||||
with self.assertRaises(TypeError):
|
||||
lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, ((None, None, None),))
|
||||
lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, ((None, None, None),))
|
||||
with self.assertRaisesRegex(ValueError, 'triple'):
|
||||
lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, ((1, 2, 3, 4),))
|
||||
lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, ((1, 2, 3, 4),))
|
||||
|
||||
def test_init_overflow(self):
|
||||
with self.assertRaisesRegex(OverflowError, 'offset'):
|
||||
lldwarf.DwarfDie(2**63, 10, DW_TAG.lo_user, None, ())
|
||||
lldwarf.DwarfDie(None, None, 2**63, 10, DW_TAG.lo_user, None, ())
|
||||
with self.assertRaisesRegex(OverflowError, 'die_length'):
|
||||
lldwarf.DwarfDie(0, 2**63, DW_TAG.lo_user, None, ())
|
||||
lldwarf.DwarfDie(None, None, 0, 2**63, DW_TAG.lo_user, None, ())
|
||||
with self.assertRaisesRegex(OverflowError, 'tag'):
|
||||
lldwarf.DwarfDie(0, 10, 2**64, None, ())
|
||||
lldwarf.DwarfDie(None, None, 0, 10, 2**64, None, ())
|
||||
with self.assertRaisesRegex(OverflowError, 'name'):
|
||||
lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, ((2**64, DW_FORM.flag_present, True),))
|
||||
lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, ((2**64, DW_FORM.flag_present, True),))
|
||||
with self.assertRaisesRegex(OverflowError, 'form'):
|
||||
lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, 2**64, True),))
|
||||
lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, 2**64, True),))
|
||||
|
||||
def test_udata(self):
|
||||
die = lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.udata, 2**33),))
|
||||
die = lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.udata, 2**33),))
|
||||
self.assertEqual(die[0], (DW_AT.lo_user, DW_FORM.udata, 2**33))
|
||||
with self.assertRaises(OverflowError):
|
||||
lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.udata, 2**64),))
|
||||
lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.udata, 2**64),))
|
||||
with self.assertRaises(TypeError):
|
||||
lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.udata, 'foo'),))
|
||||
lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.udata, 'foo'),))
|
||||
|
||||
def test_sdata(self):
|
||||
die = lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.sdata, -2**33),))
|
||||
die = lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.sdata, -2**33),))
|
||||
self.assertEqual(die[0], (DW_AT.lo_user, DW_FORM.sdata, -2**33))
|
||||
with self.assertRaises(OverflowError):
|
||||
lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.sdata, 2**63),))
|
||||
lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.sdata, 2**63),))
|
||||
with self.assertRaises(TypeError):
|
||||
lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.sdata, 'foo'),))
|
||||
lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.sdata, 'foo'),))
|
||||
|
||||
def test_string(self):
|
||||
die = lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.string, (0, 20)),))
|
||||
die = lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.string, (0, 20)),))
|
||||
self.assertEqual(die[0], (DW_AT.lo_user, DW_FORM.string, (0, 20)))
|
||||
with self.assertRaises(TypeError):
|
||||
lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.string, None),))
|
||||
lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.string, None),))
|
||||
with self.assertRaises(TypeError):
|
||||
lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.string, (None, None)),))
|
||||
lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.string, (None, None)),))
|
||||
with self.assertRaises(ValueError):
|
||||
lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.string, (1, 2, 3)),))
|
||||
lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.string, (1, 2, 3)),))
|
||||
with self.assertRaisesRegex(OverflowError, 'offset'):
|
||||
lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.string, (2**63, 1)),))
|
||||
lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.string, (2**63, 1)),))
|
||||
with self.assertRaisesRegex(OverflowError, 'length'):
|
||||
lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.string, (0, 2**63)),))
|
||||
lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.string, (0, 2**63)),))
|
||||
|
||||
def test_data(self):
|
||||
with self.assertRaises(TypeError):
|
||||
lldwarf.DwarfDie(0, 0, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.data1, 64),))
|
||||
lldwarf.DwarfDie(None, None, 0, 0, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.data1, 64),))
|
||||
with self.assertRaises(ValueError):
|
||||
lldwarf.DwarfDie(0, 0, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.data1, b'aa'),))
|
||||
lldwarf.DwarfDie(None, None, 0, 0, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.data1, b'aa'),))
|
||||
with self.assertRaises(ValueError):
|
||||
lldwarf.DwarfDie(0, 0, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.data2, b'aaa'),))
|
||||
lldwarf.DwarfDie(None, None, 0, 0, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.data2, b'aaa'),))
|
||||
with self.assertRaises(ValueError):
|
||||
lldwarf.DwarfDie(0, 0, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.data4, b'aaa'),))
|
||||
lldwarf.DwarfDie(None, None, 0, 0, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.data4, b'aaa'),))
|
||||
with self.assertRaises(ValueError):
|
||||
lldwarf.DwarfDie(0, 0, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.data8, b''),))
|
||||
lldwarf.DwarfDie(None, None, 0, 0, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.data8, b''),))
|
||||
|
||||
def test_flag(self):
|
||||
die = lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.flag, True),))
|
||||
die = lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.flag, True),))
|
||||
self.assertEqual(die[0], (DW_AT.lo_user, DW_FORM.flag, True))
|
||||
die = lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.flag, 0),))
|
||||
die = lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.flag, 0),))
|
||||
self.assertEqual(die[0], (DW_AT.lo_user, DW_FORM.flag, False))
|
||||
|
||||
def test_flag_present(self):
|
||||
die = lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.flag_present, True),))
|
||||
die = lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.flag_present, True),))
|
||||
self.assertEqual(die[0], (DW_AT.lo_user, DW_FORM.flag_present, True))
|
||||
die = lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.flag_present, 0),))
|
||||
die = lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.flag_present, 0),))
|
||||
self.assertEqual(die[0], (DW_AT.lo_user, DW_FORM.flag_present, True))
|
||||
|
||||
def test_unknown_form(self):
|
||||
with self.assertRaisesRegex(ValueError, f'unknown form {2**64 - 1}'):
|
||||
lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, 2**64 - 1, None),))
|
||||
lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, 2**64 - 1, None),))
|
||||
|
||||
def test_repr(self):
|
||||
die = lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, ())
|
||||
self.assertEqual(repr(die), f'DwarfDie(cu_offset=0, die_length=10, tag={DW_TAG.lo_user.value}, children=None, attributes=())')
|
||||
die = lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.flag, True),))
|
||||
self.assertEqual(repr(die), f'DwarfDie(cu_offset=0, die_length=10, tag={DW_TAG.lo_user.value}, children=None, attributes=(({DW_AT.lo_user.value}, {DW_FORM.flag.value}, True),))')
|
||||
die = lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, ())
|
||||
self.assertEqual(repr(die), f'DwarfDie(cu=None, parent=None, cu_offset=0, die_length=10, tag={DW_TAG.lo_user.value}, children=None, attributes=())')
|
||||
die = lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.flag, True),))
|
||||
self.assertEqual(repr(die), f'DwarfDie(cu=None, parent=None, cu_offset=0, die_length=10, tag={DW_TAG.lo_user.value}, children=None, attributes=(({DW_AT.lo_user.value}, {DW_FORM.flag.value}, True),))')
|
||||
|
||||
def test_recursive_repr(self):
|
||||
die = lldwarf.DwarfDie(0, 10, DW_TAG.lo_user, None, ())
|
||||
die = lldwarf.DwarfDie(None, None, 0, 10, DW_TAG.lo_user, None, ())
|
||||
die.children = [die]
|
||||
self.assertEqual(repr(die), f'DwarfDie(cu_offset=0, die_length=10, tag={DW_TAG.lo_user.value}, children=[DwarfDie(...)], attributes=())')
|
||||
self.assertEqual(repr(die), f'DwarfDie(cu=None, parent=None, cu_offset=0, die_length=10, tag={DW_TAG.lo_user.value}, children=[DwarfDie(...)], attributes=())')
|
||||
|
||||
|
||||
header = lldwarf.CompilationUnitHeader(
|
||||
@ -131,30 +131,30 @@ header64 = lldwarf.CompilationUnitHeader(
|
||||
class TestParseDie(unittest.TestCase):
|
||||
def test_negative_offset(self):
|
||||
with self.assertRaises(ValueError):
|
||||
lldwarf.parse_die(header, {}, 0, b'', -1)
|
||||
lldwarf.parse_die(header, None, {}, 0, b'', -1)
|
||||
with self.assertRaises(ValueError):
|
||||
lldwarf.parse_die_siblings(header, {}, 0, b'', -1)
|
||||
lldwarf.parse_die_siblings(header, None, {}, 0, b'', -1)
|
||||
|
||||
def test_bad_cu(self):
|
||||
with self.assertRaises(TypeError):
|
||||
lldwarf.parse_die(None, {}, 0, b'')
|
||||
lldwarf.parse_die(None, None, {}, 0, b'')
|
||||
|
||||
def test_bad_abbrev_table(self):
|
||||
with self.assertRaises(TypeError):
|
||||
lldwarf.parse_die(header, None, 0, b'')
|
||||
lldwarf.parse_die(header, None, None, 0, b'')
|
||||
|
||||
def test_null(self):
|
||||
self.assertIsNone(lldwarf.parse_die(header, {}, 0, b'\0'))
|
||||
self.assertIsNone(lldwarf.parse_die(header, None, {}, 0, b'\0'))
|
||||
|
||||
def test_unknown_abbreviation(self):
|
||||
with self.assertRaisesRegex(ValueError, 'unknown abbreviation code'):
|
||||
lldwarf.parse_die(header, {}, 0, b'\x01\xff')
|
||||
lldwarf.parse_die(header, None, {}, 0, b'\x01\xff')
|
||||
|
||||
def assertDie(self, header, abbrev_table, buf, die_args):
|
||||
tag, children, attribs = die_args
|
||||
die = lldwarf.DwarfDie(0, len(buf), tag, children, attribs)
|
||||
die = lldwarf.DwarfDie(header, None, 0, len(buf), tag, children, attribs)
|
||||
self.assertEqual(tuple(die), tuple(attribs))
|
||||
self.assertEqual(lldwarf.parse_die(header, abbrev_table, 0, buf), die)
|
||||
self.assertEqual(lldwarf.parse_die(header, None, abbrev_table, 0, buf), die)
|
||||
|
||||
def test_address(self):
|
||||
abbrev_table = {
|
||||
@ -174,7 +174,7 @@ class TestParseDie(unittest.TestCase):
|
||||
is_64_bit=False,
|
||||
)
|
||||
with self.assertRaisesRegex(ValueError, 'unsupported address size'):
|
||||
lldwarf.parse_die(bogus_header, abbrev_table, 0, b'\x01\xff')
|
||||
lldwarf.parse_die(bogus_header, None, abbrev_table, 0, b'\x01\xff')
|
||||
|
||||
def test_block(self):
|
||||
abbrev_table = {
|
||||
@ -196,7 +196,7 @@ class TestParseDie(unittest.TestCase):
|
||||
self.assertDie(header, abbrev_table, b'\x05\x0f012345678901234',
|
||||
(DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.exprloc, (2, 15)),)))
|
||||
with self.assertRaisesRegex(ValueError, 'attribute length too big'):
|
||||
lldwarf.parse_die(header, abbrev_table, 0, b'\x05\x80\x80\x80\x80\x80\x80\x80\x80\x80\x01')
|
||||
lldwarf.parse_die(header, None, abbrev_table, 0, b'\x05\x80\x80\x80\x80\x80\x80\x80\x80\x80\x01')
|
||||
|
||||
def test_data(self):
|
||||
abbrev_table = {
|
||||
@ -231,11 +231,11 @@ class TestParseDie(unittest.TestCase):
|
||||
(DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.sdata, -1),)))
|
||||
|
||||
with self.assertRaises(OverflowError):
|
||||
lldwarf.DwarfDie(0, 0, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.udata, 2**64),))
|
||||
lldwarf.DwarfDie(None, None, 0, 0, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.udata, 2**64),))
|
||||
with self.assertRaises(OverflowError):
|
||||
lldwarf.DwarfDie(0, 0, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.sdata, 2**63),))
|
||||
lldwarf.DwarfDie(None, None, 0, 0, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.sdata, 2**63),))
|
||||
with self.assertRaises(OverflowError):
|
||||
lldwarf.DwarfDie(0, 0, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.sdata, -2**63 - 1),))
|
||||
lldwarf.DwarfDie(None, None, 0, 0, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.sdata, -2**63 - 1),))
|
||||
|
||||
def test_flag(self):
|
||||
abbrev_table = {
|
||||
@ -306,17 +306,19 @@ class TestParseDie(unittest.TestCase):
|
||||
(DW_AT.lo_user, DW_FORM.string, (5, 4)))))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, 'unterminated string'):
|
||||
lldwarf.parse_die(header, abbrev_table, 0, b'\x01foo')
|
||||
lldwarf.parse_die(header, None, abbrev_table, 0, b'\x01foo')
|
||||
|
||||
@unittest.skip('recursive ==')
|
||||
def test_recursive(self):
|
||||
abbrev_table = {
|
||||
1: lldwarf.AbbrevDecl(DW_TAG.lo_user, True, ((DW_AT.lo_user, DW_FORM.udata),)),
|
||||
2: lldwarf.AbbrevDecl(DW_TAG.lo_user + 1, False, ((DW_AT.lo_user + 1, DW_FORM.sdata),)),
|
||||
}
|
||||
die = lldwarf.parse_die(header, abbrev_table, 0, b'\x01\x01\x02\x02\x00', recurse=True)
|
||||
die = lldwarf.parse_die(header, None, abbrev_table, 0, b'\x01\x01\x02\x02\x00', recurse=True)
|
||||
|
||||
child = lldwarf.DwarfDie(2, 2, DW_TAG.lo_user + 1, None, ((DW_AT.lo_user + 1, DW_FORM.sdata, 2),))
|
||||
parent = lldwarf.DwarfDie(0, 2, DW_TAG.lo_user, [child], ((DW_AT.lo_user, DW_FORM.udata, 1),))
|
||||
child = lldwarf.DwarfDie(header, None, 2, 2, DW_TAG.lo_user + 1, None, ((DW_AT.lo_user + 1, DW_FORM.sdata, 2),))
|
||||
parent = lldwarf.DwarfDie(header, None, 0, 2, DW_TAG.lo_user, [child], ((DW_AT.lo_user, DW_FORM.udata, 1),))
|
||||
child.parent = parent
|
||||
|
||||
self.assertEqual(die, parent)
|
||||
|
||||
@ -325,10 +327,10 @@ class TestParseDie(unittest.TestCase):
|
||||
1: lldwarf.AbbrevDecl(DW_TAG.lo_user, False, ((DW_AT.lo_user, DW_FORM.udata),)),
|
||||
2: lldwarf.AbbrevDecl(DW_TAG.lo_user + 1, False, ((DW_AT.lo_user + 1, DW_FORM.sdata),)),
|
||||
}
|
||||
siblings = lldwarf.parse_die_siblings(header, abbrev_table, 0, b'\x01\x01\x02\x02\x00')
|
||||
siblings = lldwarf.parse_die_siblings(header, None, abbrev_table, 0, b'\x01\x01\x02\x02\x00')
|
||||
self.assertEqual(siblings, [
|
||||
lldwarf.DwarfDie(0, 2, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.udata, 1),)),
|
||||
lldwarf.DwarfDie(2, 2, DW_TAG.lo_user + 1, None, ((DW_AT.lo_user + 1, DW_FORM.sdata, 2),)),
|
||||
lldwarf.DwarfDie(header, None, 0, 2, DW_TAG.lo_user, None, ((DW_AT.lo_user, DW_FORM.udata, 1),)),
|
||||
lldwarf.DwarfDie(header, None, 2, 2, DW_TAG.lo_user + 1, None, ((DW_AT.lo_user + 1, DW_FORM.sdata, 2),)),
|
||||
])
|
||||
|
||||
def test_siblings_skip(self):
|
||||
@ -336,10 +338,10 @@ class TestParseDie(unittest.TestCase):
|
||||
1: lldwarf.AbbrevDecl(DW_TAG.lo_user, True, ((DW_AT.sibling, DW_FORM.udata),)),
|
||||
2: lldwarf.AbbrevDecl(DW_TAG.lo_user + 1, False, ((DW_AT.lo_user + 1, DW_FORM.sdata),)),
|
||||
}
|
||||
siblings = lldwarf.parse_die_siblings(header, abbrev_table, 0, b'\x01\x04\x02\x02\x02\x03\x00')
|
||||
parent_die = lldwarf.DwarfDie(0, 2, DW_TAG.lo_user, None, ((DW_AT.sibling, DW_FORM.udata, 4),))
|
||||
siblings = lldwarf.parse_die_siblings(header, None, abbrev_table, 0, b'\x01\x04\x02\x02\x02\x03\x00')
|
||||
parent_die = lldwarf.DwarfDie(header, None, 0, 2, DW_TAG.lo_user, None, ((DW_AT.sibling, DW_FORM.udata, 4),))
|
||||
del parent_die.children
|
||||
self.assertEqual(siblings, [
|
||||
parent_die,
|
||||
lldwarf.DwarfDie(4, 2, DW_TAG.lo_user + 1, None, ((DW_AT.lo_user + 1, DW_FORM.sdata, 3),)),
|
||||
lldwarf.DwarfDie(header, None, 4, 2, DW_TAG.lo_user + 1, None, ((DW_AT.lo_user + 1, DW_FORM.sdata, 3),)),
|
||||
])
|
||||
|
Loading…
Reference in New Issue
Block a user