fix issue in aranges cu_offset_at_addr (#310)
authorPatrick Gordon <pgpatrickgordon@gmail.com>
Sat, 23 May 2020 14:49:28 +0000 (15:49 +0100)
committerGitHub <noreply@github.com>
Sat, 23 May 2020 14:49:28 +0000 (07:49 -0700)
* fix issue in aranges cu_offset_at_addr

if there are aranges for some parts of the binary but not others, incorrect aranges may be returned

* add test suite for absent/partial/complete aranges

elftools/dwarf/aranges.py
test/test_dwarf_aranges.py [new file with mode: 0644]
test/testfiles_for_unittests/aranges_absent.elf [new file with mode: 0755]
test/testfiles_for_unittests/aranges_complete.elf [new file with mode: 0755]
test/testfiles_for_unittests/aranges_partial.elf [new file with mode: 0755]
test/testfiles_for_unittests/aranges_partial_a.c [new file with mode: 0644]
test/testfiles_for_unittests/aranges_partial_b.c [new file with mode: 0644]

index 633edecdf94b2affb3b815823f23e3c94a75c7a6..3f140f44f6590fef1befc75804475450ab79e1ff 100644 (file)
@@ -49,7 +49,10 @@ class ARanges(object):
             'offset' refers to the offset in the .debug_info section.
         """
         tup = self.entries[bisect_right(self.keys, addr) - 1]
-        return tup.info_offset
+        if tup.begin_addr <= addr < tup.begin_addr + tup.length:
+            return tup.info_offset
+        else:
+            return None
 
 
     #------ PRIVATE ------#
diff --git a/test/test_dwarf_aranges.py b/test/test_dwarf_aranges.py
new file mode 100644 (file)
index 0000000..7b7d0cc
--- /dev/null
@@ -0,0 +1,36 @@
+import os
+import unittest
+
+from elftools.elf.elffile import ELFFile
+
+address_a = 0x112f;
+address_b = 0x1154;
+
+class TestRangeLists(unittest.TestCase):
+    def test_arange_absent(self):
+        with open(os.path.join('test', 'testfiles_for_unittests', 'aranges_absent.elf'), 'rb') as f:
+            elffile = ELFFile(f)
+            self.assertTrue(elffile.has_dwarf_info())
+            aranges = elffile.get_dwarf_info().get_aranges()
+            self.assertIsNone(aranges)
+
+    def test_arange_partial(self):
+        with open(os.path.join('test', 'testfiles_for_unittests', 'aranges_partial.elf'), 'rb') as f:
+            elffile = ELFFile(f)
+            self.assertTrue(elffile.has_dwarf_info())
+            aranges = elffile.get_dwarf_info().get_aranges()
+            self.assertIsNotNone(aranges)
+            self.assertIsNone(aranges.cu_offset_at_addr(address_a))
+            self.assertIsNotNone(aranges.cu_offset_at_addr(address_b))
+
+    def test_arange_complete(self):
+        with open(os.path.join('test', 'testfiles_for_unittests', 'aranges_complete.elf'), 'rb') as f:
+            elffile = ELFFile(f)
+            self.assertTrue(elffile.has_dwarf_info())
+            aranges = elffile.get_dwarf_info().get_aranges()
+            self.assertIsNotNone(aranges)
+            self.assertIsNotNone(aranges.cu_offset_at_addr(address_a))
+            self.assertIsNotNone(aranges.cu_offset_at_addr(address_b))
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/test/testfiles_for_unittests/aranges_absent.elf b/test/testfiles_for_unittests/aranges_absent.elf
new file mode 100755 (executable)
index 0000000..5672d2d
Binary files /dev/null and b/test/testfiles_for_unittests/aranges_absent.elf differ
diff --git a/test/testfiles_for_unittests/aranges_complete.elf b/test/testfiles_for_unittests/aranges_complete.elf
new file mode 100755 (executable)
index 0000000..6767fa7
Binary files /dev/null and b/test/testfiles_for_unittests/aranges_complete.elf differ
diff --git a/test/testfiles_for_unittests/aranges_partial.elf b/test/testfiles_for_unittests/aranges_partial.elf
new file mode 100755 (executable)
index 0000000..6ed3ea6
Binary files /dev/null and b/test/testfiles_for_unittests/aranges_partial.elf differ
diff --git a/test/testfiles_for_unittests/aranges_partial_a.c b/test/testfiles_for_unittests/aranges_partial_a.c
new file mode 100644 (file)
index 0000000..47ae2bc
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+clang -g -c aranges_partial_a.c
+clang -g -gdwarf-aranges -c aranges_partial_b.c
+clang -g aranges_partial_{a,b}.o -o aranges_partial.elf
+
+clang -g -gdwarf-aranges -c aranges_partial_a.c
+clang -g -gdwarf-aranges -c aranges_partial_b.c
+clang -g aranges_partial_{a,b}.o -o aranges_complete.elf
+
+clang -g -c aranges_partial_a.c
+clang -g -c aranges_partial_b.c
+clang -g aranges_partial_{a,b}.o -o aranges_absent.elf
+*/
+
+extern int test();
+
+int main() {
+    int a = test();
+    return a;
+}
diff --git a/test/testfiles_for_unittests/aranges_partial_b.c b/test/testfiles_for_unittests/aranges_partial_b.c
new file mode 100644 (file)
index 0000000..496a99d
--- /dev/null
@@ -0,0 +1,4 @@
+int test() {
+    int a = 0;
+    return a;
+}