From: Dmitry Koltunov Date: Tue, 30 Jul 2019 03:11:38 +0000 (+0300) Subject: Fix for `CFIEntry.get_decoded()` (#232) X-Git-Tag: v0.26~14 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=678652dd36872b3b736a54a83b9faa7eb03c6bb2;p=pyelftools.git Fix for `CFIEntry.get_decoded()` (#232) * test: test `CFIEntry.get_decoded()` This test detects an error in `CFIEntry.get_decoded()`, that occurs when decodes the `DW_CFA_def_cfa_register` instruction without some CFA definition previously. Signed-off-by: Koltunov Dmitry * add empty `cfa` for fixup decode of the `DW_CFA_def_cfa_register` Signed-off-by: Koltunov Dmitry --- diff --git a/elftools/dwarf/callframe.py b/elftools/dwarf/callframe.py index bcef78d..46116ca 100644 --- a/elftools/dwarf/callframe.py +++ b/elftools/dwarf/callframe.py @@ -467,7 +467,7 @@ class CFIEntry(object): if isinstance(self, CIE): # For a CIE, initialize cur_line to an "empty" line cie = self - cur_line = dict(pc=0, cfa=None) + cur_line = dict(pc=0, cfa=CFARule(reg=None, offset=0)) reg_order = [] else: # FDE # For a FDE, we need to decode the attached CIE first, because its @@ -479,7 +479,7 @@ class CFIEntry(object): last_line_in_CIE = copy.copy(cie_decoded_table.table[-1]) cur_line = copy.copy(last_line_in_CIE) else: - cur_line = dict(cfa=None) + cur_line = dict(cfa=CFARule(reg=None, offset=0)) cur_line['pc'] = self['initial_location'] reg_order = copy.copy(cie_decoded_table.reg_order) @@ -575,7 +575,7 @@ class CFIEntry(object): # The current line is appended to the table after all instructions # have ended, if there were instructions. - if cur_line['cfa'] is not None or len(cur_line) > 2: + if cur_line['cfa'].reg is not None or len(cur_line) > 2: table.append(cur_line) return DecodedCallFrameTable(table=table, reg_order=reg_order) diff --git a/test/test_callframe.py b/test/test_callframe.py index 5be2717..0fb9dde 100644 --- a/test/test_callframe.py +++ b/test/test_callframe.py @@ -9,10 +9,12 @@ import unittest from elftools.common.py3compat import BytesIO from elftools.dwarf.callframe import ( CallFrameInfo, CIE, FDE, instruction_name, CallFrameInstruction, - RegisterRule) + RegisterRule, DecodedCallFrameTable, CFARule) from elftools.dwarf.structs import DWARFStructs from elftools.dwarf.descriptions import (describe_CFI_instructions, set_global_machine_arch) +from elftools.elf.elffile import ELFFile +from os.path import join class TestCallFrame(unittest.TestCase): @@ -145,6 +147,25 @@ class TestCallFrame(unittest.TestCase): ( ' DW_CFA_def_cfa: r7 (edi) ofs 2\n' + ' DW_CFA_expression: r2 (edx) (DW_OP_addr: 201; DW_OP_deref; DW_OP_deref)\n')) + def test_CFIEntry_get_decoded(self): + oracle_decoded = DecodedCallFrameTable( + table = [ + {'pc': 0, 'cfa': CFARule(reg = 29, offset = 0, expr = None)} + ], + reg_order = [] + ) + + test_dir = join('test', 'testfiles_for_unittests') + with open(join(test_dir, 'simple_mipsel.elf'), 'rb') as f: + elf = ELFFile(f) + di = elf.get_dwarf_info() + entries = di.CFI_entries() + decoded = entries[0].get_decoded() + self.assertEqual(oracle_decoded.table[0]['cfa'].reg, + decoded.table[0]['cfa'].reg + ) + self.assertEqual(oracle_decoded.table[0]['cfa'].offset, + decoded.table[0]['cfa'].offset) if __name__ == '__main__': unittest.main() diff --git a/test/testfiles_for_unittests/simple_mipsel.c b/test/testfiles_for_unittests/simple_mipsel.c new file mode 100644 index 0000000..601434b --- /dev/null +++ b/test/testfiles_for_unittests/simple_mipsel.c @@ -0,0 +1,14 @@ +/* Generated by compiling with any GCC version for MIPS Little Endian. +** GCC 5.4.0 is fine. + +/usr/bin/mipsel-linux-gnu-gcc -g -O0 ./simple_mipsel.c -o ./simple_mipsel.elf +*/ + +void main(void) +{ + int a = 1, b = 2, res; + + res = a + b; + + return; +} diff --git a/test/testfiles_for_unittests/simple_mipsel.elf b/test/testfiles_for_unittests/simple_mipsel.elf new file mode 100755 index 0000000..86c2561 Binary files /dev/null and b/test/testfiles_for_unittests/simple_mipsel.elf differ