From: Dmitry Koltunov Date: Wed, 5 Sep 2018 12:25:28 +0000 (+0300) Subject: Call relocation for ARM V3 (#194) X-Git-Tag: v0.26~41 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f52f66634d1f9419239ce80ce455fea43ecc6aa7;p=pyelftools.git Call relocation for ARM V3 (#194) * Add support for 'R_ARM_CALL' relocation type * Add test script and test files to verify support for 'R_ARM_CALL' Signed-off-by: Koltunov Dmitry --- diff --git a/elftools/elf/relocation.py b/elftools/elf/relocation.py index 6f2c4b4..59b6750 100644 --- a/elftools/elf/relocation.py +++ b/elftools/elf/relocation.py @@ -219,10 +219,16 @@ class RelocationHandler(object): def _reloc_calc_sym_plus_addend_pcrel(value, sym_value, offset, addend=0): return sym_value + addend - offset + def _arm_reloc_calc_sym_plus_value_pcrel(value, sym_value, offset, addend=0): + return sym_value / 4 + value - offset / 4 + _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), + ENUM_RELOC_TYPE_ARM['R_ARM_CALL']: _RELOCATION_RECIPE_TYPE( + bytesize=4, has_addend=False, + calc_func=_arm_reloc_calc_sym_plus_value_pcrel), } # https://dmz-portal.mips.com/wiki/MIPS_relocation_types diff --git a/test/run_arm_reloc_call_test.py b/test/run_arm_reloc_call_test.py new file mode 100755 index 0000000..261949d --- /dev/null +++ b/test/run_arm_reloc_call_test.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python +#------------------------------------------------------------------------------- +# test/run_arm_reloc_call_test.py +# +# Test 'R_ARM_CALL' relocation type support. +# Compare the '.text' section data of ELF file that relocated by elftools +# and ELF file that relocated by linker. +# +# Dmitry Koltunov (koltunov@ispras.ru) +#------------------------------------------------------------------------------- +from os.path import ( + join, + dirname +) +from sys import ( + exit +) + +from elftools.common.py3compat import ( + BytesIO +) +from elftools.elf.elffile import ( + ELFFile +) +from elftools.elf.relocation import ( + RelocationHandler +) + + +def do_relocation(rel_elf): + data = rel_elf.get_section_by_name('.text').data() + rh = RelocationHandler(rel_elf) + + stream = BytesIO() + stream.write(data) + + rel = rel_elf.get_section_by_name('.rel.text') + rh.apply_section_relocations(stream, rel) + + stream.seek(0) + data = stream.readlines() + + return data + + +def main(): + test_dir = join(dirname(__file__) or '.', 'testfiles_for_unittests') + with open(join(test_dir, 'reloc_simple_arm_llvm.o'), 'rb') as rel_f, \ + open(join(test_dir, 'simple_arm_llvm.elf'), 'rb') as f: + rel_elf = ELFFile(rel_f) + elf = ELFFile(f) + + # Comparison of '.text' section data + if do_relocation(rel_elf).pop() != elf.get_section_by_name('.text').data(): + print 'FAIL' + return 1 + print 'OK' + return 0 + + +if __name__ == '__main__': + exit(main()) diff --git a/test/testfiles_for_unittests/reloc_simple_arm_llvm.o b/test/testfiles_for_unittests/reloc_simple_arm_llvm.o new file mode 100644 index 0000000..a1bfbaa Binary files /dev/null and b/test/testfiles_for_unittests/reloc_simple_arm_llvm.o differ diff --git a/test/testfiles_for_unittests/simple.c b/test/testfiles_for_unittests/simple.c new file mode 100644 index 0000000..4ea1c67 --- /dev/null +++ b/test/testfiles_for_unittests/simple.c @@ -0,0 +1,41 @@ +/* Generated by compiling with any LLVM version and +** with any GNU Arm Embedded Toolchain version. +** LLVM 3.8.0/5.0.0 and GNU Arm Embedded Toolchain 2.26 is fine. +** +** clang -O0 --target=arm-none-eabi -emit-llvm -c simple.c -o simple.bc +** llc -O0 -march=arm -filetype=obj simple.bc -o reloc_simple_arm_llvm.o +** arm-none-eabi-ld -e main reloc_simple_arm_llvm.o -o simple_arm_llvm.elf +** +** reloc_simple_arm_llvm.o is ELF file that needs call relocation. +** +** simple_arm_llvm.elf is a relocated ELF file. +*/ + +int add(int a, int b) { + return a + b; +} + +int sub(int a, int b) { + return a - b; +} + +int mul(int a, int b) { + return a * b; +} + +void triple(int a, int b) { + add(a, b); + sub(a, b); + mul(a, b); +} + +int main(void) { + int a = 0xABCD, b = 0x1234; + + add(a, b); + sub(a, b); + mul(a, b); + triple(a, b); + + return 0; +} diff --git a/test/testfiles_for_unittests/simple_arm_llvm.elf b/test/testfiles_for_unittests/simple_arm_llvm.elf new file mode 100755 index 0000000..f1cfbb8 Binary files /dev/null and b/test/testfiles_for_unittests/simple_arm_llvm.elf differ