Don't include 'meta-tag' markers in descriptions of ENUM_D_TAG (#176)
authorAudrey Dutcher <audrey@rhelmot.io>
Fri, 5 Jan 2018 21:54:59 +0000 (13:54 -0800)
committerEli Bendersky <eliben@users.noreply.github.com>
Fri, 5 Jan 2018 21:54:59 +0000 (13:54 -0800)
Fixes #150

elftools/elf/descriptions.py
test/test_dynamic.py

index f8b6f9bee4e875194404b589961bef26ca422944..8dc641407b92616fc4800d23a67619c5e0478bbf 100644 (file)
@@ -463,30 +463,39 @@ _DESCR_NOTE_ABI_TAG_OS = dict(
     ELF_NOTE_OS_SYLLABLE='Syllable',
 )
 
-
-_DESCR_RELOC_TYPE_i386 = dict(
-        (v, k) for k, v in iteritems(ENUM_RELOC_TYPE_i386))
-
-
-_DESCR_RELOC_TYPE_x64 = dict(
-        (v, k) for k, v in iteritems(ENUM_RELOC_TYPE_x64))
-
-
-_DESCR_RELOC_TYPE_ARM = dict(
-        (v, k) for k, v in iteritems(ENUM_RELOC_TYPE_ARM))
-
-
-_DESCR_RELOC_TYPE_AARCH64 = dict(
-        (v, k) for k, v in iteritems(ENUM_RELOC_TYPE_AARCH64))
-
-
-_DESCR_RELOC_TYPE_MIPS = dict(
-        (v, k) for k, v in iteritems(ENUM_RELOC_TYPE_MIPS))
-
-
-_DESCR_D_TAG = dict(
-        (v, k) for k, v in iteritems(ENUM_D_TAG))
-
+def _reverse_dict(d, low_priority=()):
+    """
+    This is a tiny helper function to "reverse" the keys/values of a dictionary
+    provided in the first argument, i.e. {k: v} becomes {v: k}.
+
+    The second argument (optional) provides primitive control over what to do in
+    the case of conflicting values - if a value is present in this list, it will
+    not override any other entries of the same value.
+    """
+    out = {}
+    for k, v in iteritems(d):
+        if v in out and k in low_priority:
+            continue
+        out[v] = k
+    return out
+
+_DESCR_RELOC_TYPE_i386 = _reverse_dict(ENUM_RELOC_TYPE_i386)
+_DESCR_RELOC_TYPE_x64 = _reverse_dict(ENUM_RELOC_TYPE_x64)
+_DESCR_RELOC_TYPE_ARM = _reverse_dict(ENUM_RELOC_TYPE_ARM)
+_DESCR_RELOC_TYPE_AARCH64 = _reverse_dict(ENUM_RELOC_TYPE_AARCH64)
+_DESCR_RELOC_TYPE_MIPS = _reverse_dict(ENUM_RELOC_TYPE_MIPS)
+
+_low_priority_D_TAG = (
+    # these are 'meta-tags' marking semantics of numeric ranges of the enum
+    # they should not override other tags with the same numbers
+    # see https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-42444.html
+    'DT_LOOS',
+    'DT_HIOS',
+    'DT_LOPROC',
+    'DT_HIPROC',
+    'DT_ENCODING',
+)
+_DESCR_D_TAG = _reverse_dict(ENUM_D_TAG, low_priority=_low_priority_D_TAG)
 
 _DESCR_ATTR_TAG_ARM = dict(
     TAG_FILE='File Attributes',
index 5284a1cfbbde312e9c6a293348a12048a42711a8..9b242f04a94daa46a8ba256820f52f0813913585 100644 (file)
@@ -10,6 +10,8 @@ import os
 from elftools.elf.elffile import ELFFile
 from elftools.common.exceptions import ELFError
 from elftools.elf.dynamic import DynamicTag
+from elftools.elf.enums import ENUM_D_TAG
+from elftools.elf.descriptions import _DESCR_D_TAG, _low_priority_D_TAG
 
 
 class TestDynamicTag(unittest.TestCase):
@@ -19,6 +21,17 @@ class TestDynamicTag(unittest.TestCase):
         with self.assertRaises(ELFError):
             dt = DynamicTag('', None)
 
+    def test_tag_priority(self):
+        for tag in _low_priority_D_TAG:
+            val = ENUM_D_TAG[tag]
+            # if the low priority tag is present in the descriptions,
+            # assert that it has not overridden any other tag
+            if _DESCR_D_TAG[val] == tag:
+                for tag2 in ENUM_D_TAG:
+                    if tag2 == tag:
+                        continue
+                    self.assertNotEqual(ENUM_D_TAG[tag2], val)
+
 
 class TestDynamic(unittest.TestCase):
     """Tests for the Dynamic class."""