Handle ARM relocations (#121)
authorFrederik Sdun <frederik_sdun@mentor.com>
Mon, 16 Jul 2018 13:22:55 +0000 (15:22 +0200)
committerEli Bendersky <eliben@users.noreply.github.com>
Mon, 16 Jul 2018 13:22:55 +0000 (06:22 -0700)
* relocation: handle ARM binaries

* relocation: handle R_ARM_ABS32 for ARM machines

* testfiles: add reloc_arm_gcc.o.elf

Generated on Ubuntu 14.04 using: arm-linux-gnueabi-gcc-4.7 -c -g -o reloc_armhf_gcc.o.elf hello.c

* testfiles: add reloc_armhf_gcc.o.elf

Generated on Ubuntu 14.04 using: arm-linux-gnueabihf-gcc-4.7 -c -g -o reloc_armhf_gcc.o.elf hello.c

* readelf: print soft-float abi for ARM if EF_ARM_ABI_FLOAT_SOFT in flags

* readelf: print hard-float abi for ARM if EF_ARM_ABI_FLOAT_HARD in flags

* readelf: print BE8 info for armeb binaries

* testfiles: add simple_armhf_gcc.o.elf

    Generated on Ubuntu 14.04 using: arm-linux-gnueabihf-gcc-4.7  -g -o simple_armhf_gcc.o.elf hello.c

* elf: remove unwind from dicts and set ARM_EXIDX description

* testfiles: add  reloc_armsf_gcc.o.elf as soft float testcase taken from binutils 2.30

* testfiles: add reloc_armeb_gcc.o.elf as arm big endian testcase taken from binutils 2.30 testcase arm-be8

* readelf: print endian info LE8 if flag was set in header flags

elftools/elf/descriptions.py
elftools/elf/relocation.py
scripts/readelf.py
test/testfiles_for_readelf/reloc_arm_gcc.o.elf [new file with mode: 0644]
test/testfiles_for_readelf/reloc_armhf_gcc.o.elf [new file with mode: 0644]
test/testfiles_for_readelf/reloc_armsf_gcc.o.elf [new file with mode: 0755]
test/testfiles_for_readelf/simple_armeb_gcc.o.elf [new file with mode: 0755]
test/testfiles_for_readelf/simple_armhf_gcc.o.elf [new file with mode: 0644]

index b76238a19fe60ee276507574f920f5ba8a772d13..022b0745bf43563a5010e661f7d7a0002a74be95 100644 (file)
@@ -319,7 +319,7 @@ _DESCR_SH_TYPE = dict(
     SHT_GNU_verneed='VERNEED',
     SHT_GNU_versym='VERSYM',
     SHT_GNU_LIBLIST='GNU_LIBLIST',
-    SHT_ARM_EXIDX='EXIDX',  # binutils calls this EXIDX, not ARM_EXIDX
+    SHT_ARM_EXIDX='ARM_EXIDX',
     SHT_ARM_PREEMPTMAP='ARM_PREEMPTMAP',
     SHT_ARM_ATTRIBUTES='ARM_ATTRIBUTES',
     SHT_ARM_DEBUGOVERLAY='ARM_DEBUGOVERLAY',
index 633bbf5815cb004505dae93d339ef37299f62ff0..6f2c4b4e979ab84e93402a3a4dd3f92fc7a24587 100644 (file)
@@ -12,7 +12,7 @@ from ..common.exceptions import ELFRelocationError
 from ..common.utils import elf_assert, struct_parse
 from .sections import Section
 from .enums import (
-    ENUM_RELOC_TYPE_i386, ENUM_RELOC_TYPE_x64, ENUM_RELOC_TYPE_MIPS)
+    ENUM_RELOC_TYPE_i386, ENUM_RELOC_TYPE_x64, ENUM_RELOC_TYPE_MIPS, ENUM_RELOC_TYPE_ARM)
 
 
 class Relocation(object):
@@ -151,6 +151,11 @@ class RelocationHandler(object):
                 raise ELFRelocationError(
                     'Unexpected RELA relocation for MIPS: %s' % reloc)
             recipe = self._RELOCATION_RECIPES_MIPS.get(reloc_type, None)
+        elif self.elffile.get_machine_arch() == 'ARM':
+            if reloc.is_RELA():
+                raise ELFRelocationError(
+                    'Unexpected RELA relocation for ARM: %s' % reloc)
+            recipe = self._RELOCATION_RECIPES_ARM.get(reloc_type, None)
 
         if recipe is None:
             raise ELFRelocationError(
@@ -214,6 +219,12 @@ class RelocationHandler(object):
     def _reloc_calc_sym_plus_addend_pcrel(value, sym_value, offset, addend=0):
         return sym_value + addend - offset
 
+    _RELOCATION_RECIPES_ARM = {
+        ENUM_RELOC_TYPE_ARM['R_ARM_ABS32']: _RELOCATION_RECIPE_TYPE(
+            bytesize=4, has_addend=False,
+            calc_func=_reloc_calc_sym_plus_value),
+    }
+
     # https://dmz-portal.mips.com/wiki/MIPS_relocation_types
     _RELOCATION_RECIPES_MIPS = {
         ENUM_RELOC_TYPE_MIPS['R_MIPS_NONE']: _RELOCATION_RECIPE_TYPE(
@@ -247,3 +258,5 @@ class RelocationHandler(object):
         ENUM_RELOC_TYPE_x64['R_X86_64_32S']: _RELOCATION_RECIPE_TYPE(
             bytesize=4, has_addend=True, calc_func=_reloc_calc_sym_plus_addend),
     }
+
+
index d65c385860392b75c7aaa8e1b44a6c85c4b92cb3..8535119fb597f40afdeb0d55d97291c23e790570 100755 (executable)
@@ -131,8 +131,19 @@ class ReadElf(object):
                 flags &= ~E_FLAGS.EF_ARM_RELEXEC
 
             if eabi == E_FLAGS.EF_ARM_EABI_VER5:
+                EF_ARM_KNOWN_FLAGS = E_FLAGS.EF_ARM_ABI_FLOAT_SOFT|E_FLAGS.EF_ARM_ABI_FLOAT_HARD|E_FLAGS.EF_ARM_LE8|E_FLAGS.EF_ARM_BE8
                 description += ', Version5 EABI'
-                if flags:
+                if flags & E_FLAGS.EF_ARM_ABI_FLOAT_SOFT:
+                    description += ", soft-float ABI"
+                elif flags & E_FLAGS.EF_ARM_ABI_FLOAT_HARD:
+                    description += ", hard-float ABI"
+
+                if flags & E_FLAGS.EF_ARM_BE8:
+                    description += ", BE8"
+                elif flags & E_FLAGS.EF_ARM_LE8:
+                    description += ", LE8"
+
+                if flags & ~EF_ARM_KNOWN_FLAGS:
                     description += ', <unknown>'
             else:
                 description += ', <unrecognized EABI>'
diff --git a/test/testfiles_for_readelf/reloc_arm_gcc.o.elf b/test/testfiles_for_readelf/reloc_arm_gcc.o.elf
new file mode 100644 (file)
index 0000000..4d8e4e9
Binary files /dev/null and b/test/testfiles_for_readelf/reloc_arm_gcc.o.elf differ
diff --git a/test/testfiles_for_readelf/reloc_armhf_gcc.o.elf b/test/testfiles_for_readelf/reloc_armhf_gcc.o.elf
new file mode 100644 (file)
index 0000000..320aea3
Binary files /dev/null and b/test/testfiles_for_readelf/reloc_armhf_gcc.o.elf differ
diff --git a/test/testfiles_for_readelf/reloc_armsf_gcc.o.elf b/test/testfiles_for_readelf/reloc_armsf_gcc.o.elf
new file mode 100755 (executable)
index 0000000..04c3849
Binary files /dev/null and b/test/testfiles_for_readelf/reloc_armsf_gcc.o.elf differ
diff --git a/test/testfiles_for_readelf/simple_armeb_gcc.o.elf b/test/testfiles_for_readelf/simple_armeb_gcc.o.elf
new file mode 100755 (executable)
index 0000000..bd0c38b
Binary files /dev/null and b/test/testfiles_for_readelf/simple_armeb_gcc.o.elf differ
diff --git a/test/testfiles_for_readelf/simple_armhf_gcc.o.elf b/test/testfiles_for_readelf/simple_armhf_gcc.o.elf
new file mode 100644 (file)
index 0000000..a5a0233
Binary files /dev/null and b/test/testfiles_for_readelf/simple_armhf_gcc.o.elf differ