From: Audrey Dutcher Date: Fri, 23 Feb 2018 13:30:52 +0000 (-0800) Subject: Choose members of the dynamic tag enum based on the current machine (#183) X-Git-Tag: v0.25~10 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=505e5c6de7909457a3b621e7bb148999453325bf;p=pyelftools.git Choose members of the dynamic tag enum based on the current machine (#183) * Only use processor/os specific dynamic tags if that processor or os is in use * Add testcase for machine-specific dynamic tags * Clarify layout of ENUM_D_TAG --- diff --git a/elftools/elf/elffile.py b/elftools/elf/elffile.py index a1509ee..289a5f9 100644 --- a/elftools/elf/elffile.py +++ b/elftools/elf/elffile.py @@ -71,7 +71,10 @@ class ELFFile(object): self.structs.create_basic_structs() self.header = self._parse_elf_header() - self.structs.create_advanced_structs(self['e_type'], self['e_machine']) + self.structs.create_advanced_structs( + self['e_type'], + self['e_machine'], + self['e_ident']['EI_OSABI']) self.stream.seek(0) self.e_ident_raw = self.stream.read(16) diff --git a/elftools/elf/enums.py b/elftools/elf/enums.py index 48ef99a..e37effa 100644 --- a/elftools/elf/enums.py +++ b/elftools/elf/enums.py @@ -468,7 +468,7 @@ ENUM_ST_SHNDX = dict( ) # d_tag -ENUM_D_TAG = dict( +ENUM_D_TAG_COMMON = dict( DT_NULL=0, DT_NEEDED=1, DT_PLTRELSZ=2, @@ -505,24 +505,6 @@ ENUM_D_TAG = dict( DT_PREINIT_ARRAYSZ=33, DT_NUM=34, DT_LOOS=0x6000000d, - DT_SUNW_AUXILIARY=0x6000000d, - DT_SUNW_RTLDINF=0x6000000e, - DT_SUNW_FILTER=0x6000000f, - DT_SUNW_CAP=0x60000010, - DT_SUNW_SYMTAB=0x60000011, - DT_SUNW_SYMSZ=0x60000012, - DT_SUNW_ENCODING=0x60000013, - DT_SUNW_SORTENT=0x60000013, - DT_SUNW_SYMSORT=0x60000014, - DT_SUNW_SYMSORTSZ=0x60000015, - DT_SUNW_TLSSORT=0x60000016, - DT_SUNW_TLSSORTSZ=0x60000017, - DT_SUNW_CAPINFO=0x60000018, - DT_SUNW_STRPAD=0x60000019, - DT_SUNW_CAPCHAIN=0x6000001a, - DT_SUNW_LDMACH=0x6000001b, - DT_SUNW_CAPCHAINENT=0x6000001d, - DT_SUNW_CAPCHAINSZ=0x6000001f, DT_HIOS=0x6ffff000, DT_LOPROC=0x70000000, DT_HIPROC=0x7fffffff, @@ -556,6 +538,36 @@ ENUM_D_TAG = dict( DT_VERDEFNUM=0x6ffffffd, DT_VERNEED=0x6ffffffe, DT_VERNEEDNUM=0x6fffffff, + DT_AUXILIARY=0x7ffffffd, + DT_FILTER=0x7fffffff, + _default_=Pass, +) + +# Above are the dynamic tags which are valid always. +# Below are the dynamic tags which are only valid in certain contexts. + +ENUM_D_TAG_SOLARIS = dict( + DT_SUNW_AUXILIARY=0x6000000d, + DT_SUNW_RTLDINF=0x6000000e, + DT_SUNW_FILTER=0x6000000f, + DT_SUNW_CAP=0x60000010, + DT_SUNW_SYMTAB=0x60000011, + DT_SUNW_SYMSZ=0x60000012, + DT_SUNW_ENCODING=0x60000013, + DT_SUNW_SORTENT=0x60000013, + DT_SUNW_SYMSORT=0x60000014, + DT_SUNW_SYMSORTSZ=0x60000015, + DT_SUNW_TLSSORT=0x60000016, + DT_SUNW_TLSSORTSZ=0x60000017, + DT_SUNW_CAPINFO=0x60000018, + DT_SUNW_STRPAD=0x60000019, + DT_SUNW_CAPCHAIN=0x6000001a, + DT_SUNW_LDMACH=0x6000001b, + DT_SUNW_CAPCHAINENT=0x6000001d, + DT_SUNW_CAPCHAINSZ=0x6000001f, +) + +ENUM_D_TAG_MIPS = dict( DT_MIPS_RLD_VERSION=0x70000001, DT_MIPS_TIME_STAMP=0x70000002, DT_MIPS_ICHECKSUM=0x70000003, @@ -573,11 +585,26 @@ ENUM_D_TAG = dict( DT_MIPS_HIPAGENO=0x70000014, DT_MIPS_RLD_MAP=0x70000016, DT_MIPS_RLD_MAP_REL=0x70000035, - DT_AUXILIARY=0x7ffffffd, - DT_FILTER=0x7fffffff, - _default_=Pass, ) +# Here is the mapping from e_machine enum to the extra dynamic tags which it +# validates. Solaris is missing from this list because its inclusion is not +# controlled by e_machine but rather e_ident[EI_OSABI]. +# TODO: add the rest of the machine-specific dynamic tags, not just mips and +# solaris + +ENUMMAP_EXTRA_D_TAG_MACHINE = dict( + EM_MIPS=ENUM_D_TAG_MIPS, + EM_MIPS_RS3_LE=ENUM_D_TAG_MIPS, +) + +# Here is the full combined mapping from tag name to value + +ENUM_D_TAG = dict(ENUM_D_TAG_COMMON) +ENUM_D_TAG.update(ENUM_D_TAG_SOLARIS) +for k in ENUMMAP_EXTRA_D_TAG_MACHINE: + ENUM_D_TAG.update(ENUMMAP_EXTRA_D_TAG_MACHINE[k]) + ENUM_RELOC_TYPE_MIPS = dict( R_MIPS_NONE=0, R_MIPS_16=1, diff --git a/elftools/elf/structs.py b/elftools/elf/structs.py index a89bfed..660f687 100644 --- a/elftools/elf/structs.py +++ b/elftools/elf/structs.py @@ -72,7 +72,7 @@ class ELFStructs(object): self._create_leb128() self._create_ntbs() - def create_advanced_structs(self, e_type=None, e_machine=None): + def create_advanced_structs(self, e_type=None, e_machine=None, e_ident_osabi=None): """ Create all ELF structs except the ehdr. They may possibly depend on provided e_type and/or e_machine parsed from ehdr. """ @@ -81,7 +81,7 @@ class ELFStructs(object): self._create_chdr() self._create_sym() self._create_rel() - self._create_dyn() + self._create_dyn(e_machine, e_ident_osabi) self._create_sunw_syminfo() self._create_gnu_verneed() self._create_gnu_verdef() @@ -225,9 +225,15 @@ class ELFStructs(object): self.Elf_sxword('r_addend'), ) - def _create_dyn(self): + def _create_dyn(self, e_machine=None, e_ident_osabi=None): + d_tag_dict = dict(ENUM_D_TAG_COMMON) + if e_machine in ENUMMAP_EXTRA_D_TAG_MACHINE: + d_tag_dict.update(ENUMMAP_EXTRA_D_TAG_MACHINE[e_machine]) + elif e_ident_osabi == 'ELFOSABI_SOLARIS': + d_tag_dict.update(ENUM_D_TAG_SOLARIS) + self.Elf_Dyn = Struct('Elf_Dyn', - Enum(self.Elf_sxword('d_tag'), **ENUM_D_TAG), + Enum(self.Elf_sxword('d_tag'), **d_tag_dict), self.Elf_xword('d_val'), Value('d_ptr', lambda ctx: ctx['d_val']), ) diff --git a/test/test_dynamic.py b/test/test_dynamic.py index 9b242f0..1ef0080 100644 --- a/test/test_dynamic.py +++ b/test/test_dynamic.py @@ -68,6 +68,26 @@ class TestDynamic(unittest.TestCase): exp = [b'', b'__libc_start_main', b'__gmon_start__', b'abort'] self.assertEqual(symbol_names, exp) + def test_sunw_tags(self): + def extract_sunw(filename): + with open(filename, 'rb') as f: + elf = ELFFile(f) + dyn = elf.get_section_by_name('.dynamic') + + seen = set() + for tag in dyn.iter_tags(): + if type(tag.entry.d_tag) is str and \ + tag.entry.d_tag.startswith("DT_SUNW"): + seen.add(tag.entry.d_tag) + + return seen + + f1 = extract_sunw(os.path.join('test', 'testfiles_for_unittests', + 'exe_solaris32_cc.sparc.elf')) + f2 = extract_sunw(os.path.join('test', 'testfiles_for_unittests', + 'android_dyntags.elf')) + self.assertEqual(f1, {'DT_SUNW_STRPAD', 'DT_SUNW_LDMACH'}) + self.assertEqual(f2, set()) if __name__ == '__main__': unittest.main() diff --git a/test/testfiles_for_unittests/android_dyntags.elf b/test/testfiles_for_unittests/android_dyntags.elf new file mode 100644 index 0000000..f93d7f4 Binary files /dev/null and b/test/testfiles_for_unittests/android_dyntags.elf differ