[diffoscope] 01/01: Add support for reading the symbol table to ArFile

Ximin Luo infinity0 at debian.org
Sat Aug 13 16:29:14 CEST 2016


This is an automated email from the git hooks/post-receive script.

infinity0 pushed a commit to branch master
in repository diffoscope.

commit cc3a2ba785e1853282c48bb7468e96ac62103c2f
Author: Ximin Luo <infinity0 at debian.org>
Date:   Sat Aug 13 16:27:27 2016 +0200

    Add support for reading the symbol table to ArFile
---
 diffoscope/__init__.py              |  4 ++++
 diffoscope/comparators/ar.py        | 31 +++++++++++++++++++------------
 tests/comparators/test_rlib.py      | 31 ++++++++++++++++++++-----------
 tests/data/rlib_armap_expected_diff | 12 ++++++++++++
 4 files changed, 55 insertions(+), 23 deletions(-)

diff --git a/diffoscope/__init__.py b/diffoscope/__init__.py
index a72323f..b993682 100644
--- a/diffoscope/__init__.py
+++ b/diffoscope/__init__.py
@@ -131,6 +131,10 @@ class RequiredToolNotFound(Exception):
             'arch': 'gettext',
             'FreeBSD': 'gettext-tools',
         },
+        'nm': {
+            'debian': 'binutils-multiarch',
+            'arch': 'binutils',
+        },
         'objdump': {
             'debian': 'binutils-multiarch',
             'arch': 'binutils',
diff --git a/diffoscope/comparators/ar.py b/diffoscope/comparators/ar.py
index d66f7e4..cc54aec 100644
--- a/diffoscope/comparators/ar.py
+++ b/diffoscope/comparators/ar.py
@@ -18,13 +18,15 @@
 # You should have received a copy of the GNU General Public License
 # along with diffoscope.  If not, see <http://www.gnu.org/licenses/>.
 
-import os.path
 import re
+from diffoscope import tool_required
 from diffoscope.difference import Difference
 from diffoscope.comparators.binary import File
 from diffoscope.comparators.libarchive import LibarchiveContainer, list_libarchive
+from diffoscope.comparators.utils import Command
 from diffoscope import logger
 
+
 # TODO: this would also be useful for Go archives. Currently those are handled
 # by StaticLibFile, but then readelf complains with "Error: Not an ELF file".
 # ArFile gives slightly more reasonable output, e.g. a readable plain diff of
@@ -34,16 +36,20 @@ class ArContainer(LibarchiveContainer):
     def get_members(self):
         members = LibarchiveContainer.get_members(self)
         cls = members.__class__
-        # for some reason libarchive outputs ["/", "//"] as member names for
-        # some archives. for now, let's just filter these out, otherwise they
-        # cause exceptions later. eventually, we should investigate this in
-        # more detail and handle it properly.
-        filtered_out = cls([p for p in members.items() if not os.path.basename(p[0])])
+        known_ignores = {
+            "/" : "this is the symbol table, already accounted for in other output",
+            "//" : "this is the table for GNU long names, already accounted for in the archive filelist",
+        }
+        filtered_out = cls([p for p in members.items() if p[0] in known_ignores])
         if filtered_out:
-            logger.debug("ignored directory ar members %s in %s, don't yet know how to handle these",
-                list(filtered_out.keys()), self.source.path)
-        return cls([p for p in members.items() if os.path.basename(p[0])])
+            for k, v in filtered_out.items():
+                logger.debug("ignored ar member '%s' because %s", k, known_ignores[k])
+        return cls([p for p in members.items() if p[0] not in known_ignores])
 
+class ArSymbolTableDumper(Command):
+    @tool_required('nm')
+    def cmdline(self):
+        return ['nm', '-s', self.path]
 
 class ArFile(File):
     CONTAINER_CLASS = ArContainer
@@ -54,6 +60,7 @@ class ArFile(File):
         return ArFile.RE_FILE_TYPE.search(file.magic_file_type)
 
     def compare_details(self, other, source=None):
-        return [Difference.from_text_readers(list_libarchive(self.path),
-                                        list_libarchive(other.path),
-                                        self.path, other.path, source="file list")]
+        return [Difference.from_command(ArSymbolTableDumper, self.path, other.path),
+                Difference.from_text_readers(list_libarchive(self.path),
+                                             list_libarchive(other.path),
+                                             self.path, other.path, source="file list")]
diff --git a/tests/comparators/test_rlib.py b/tests/comparators/test_rlib.py
index 3bc89c0..5e93a20 100644
--- a/tests/comparators/test_rlib.py
+++ b/tests/comparators/test_rlib.py
@@ -52,22 +52,31 @@ def test_no_differences(rlib1):
 def differences(rlib1, rlib2):
     return rlib1.compare(rlib2).details
 
-def test_item0_elf(differences):
-    assert differences[0].source1 == 'alloc_system-d16b8f0e.0.o'
-    assert differences[0].source2 == 'alloc_system-d16b8f0e.0.o'
+def test_num_items(differences):
+    assert len(differences) == 4
+
+def test_item0_armap(differences):
+    assert differences[0].source1 == 'nm -s {}'
+    assert differences[0].source2 == 'nm -s {}'
+    expected_diff = open(os.path.join(os.path.dirname(__file__), '../data/rlib_armap_expected_diff')).read()
+    assert differences[0].unified_diff == expected_diff
+
+def test_item1_elf(differences):
+    assert differences[1].source1 == 'alloc_system-d16b8f0e.0.o'
+    assert differences[1].source2 == 'alloc_system-d16b8f0e.0.o'
     expected_diff = open(os.path.join(os.path.dirname(__file__), '../data/rlib_elf_expected_diff')).read()
-    assert differences[0].details[0].unified_diff == expected_diff
+    assert differences[1].details[0].unified_diff == expected_diff
 
-def test_item1_rust_metadata_bin(differences):
-    assert differences[1].source1 == 'rust.metadata.bin'
-    assert differences[1].source2 == 'rust.metadata.bin'
+def test_item2_rust_metadata_bin(differences):
+    assert differences[2].source1 == 'rust.metadata.bin'
+    assert differences[2].source2 == 'rust.metadata.bin'
 
 @pytest.mark.skipif(tool_missing('llvm-dis'), reason='missing llvm-dis')
-def test_item2_deflate_llvm_bitcode(differences):
-    assert differences[2].source1 == 'alloc_system-d16b8f0e.0.bytecode.deflate'
-    assert differences[2].source2 == 'alloc_system-d16b8f0e.0.bytecode.deflate'
+def test_item3_deflate_llvm_bitcode(differences):
+    assert differences[3].source1 == 'alloc_system-d16b8f0e.0.bytecode.deflate'
+    assert differences[3].source2 == 'alloc_system-d16b8f0e.0.bytecode.deflate'
     expected_diff = open(os.path.join(os.path.dirname(__file__), '../data/rlib_llvm_dis_expected_diff')).read()
-    actual_diff = differences[2].details[0].details[1].unified_diff
+    actual_diff = differences[3].details[0].details[1].unified_diff
     assert diff_ignore_line_numbers(actual_diff) == diff_ignore_line_numbers(expected_diff)
 
 def test_compare_non_existing(monkeypatch, rlib1):
diff --git a/tests/data/rlib_armap_expected_diff b/tests/data/rlib_armap_expected_diff
new file mode 100644
index 0000000..1c44838
--- /dev/null
+++ b/tests/data/rlib_armap_expected_diff
@@ -0,0 +1,12 @@
+@@ -1,10 +1,10 @@
+ 
+ Archive index:
+-__rust_allocate in alloc_system-d16b8f0e.0.o
++__rust_all0cate in alloc_system-d16b8f0e.0.o
+ __rust_deallocate in alloc_system-d16b8f0e.0.o
+ __rust_reallocate in alloc_system-d16b8f0e.0.o
+ __rust_reallocate_inplace in alloc_system-d16b8f0e.0.o
+ __rust_usable_size in alloc_system-d16b8f0e.0.o
+ 
+ alloc_system-d16b8f0e.0.o:
+ 0000000000000000 T __rust_allocate

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/reproducible/diffoscope.git


More information about the diffoscope mailing list