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