diff --git a/elftools/elf/enums.py b/elftools/elf/enums.py index 7be69d31..59e527b9 100644 --- a/elftools/elf/enums.py +++ b/elftools/elf/enums.py @@ -788,6 +788,68 @@ _default_=Pass, ) +# https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#reloc-table +ENUM_RELOC_TYPE_RISCV = dict( + R_RISCV_NONE = 0, + R_RISCV_32 = 1, + R_RISCV_64 = 2, + R_RISCV_RELATIVE = 3, + R_RISCV_COPY = 4, + R_RISCV_JUMP_SLOT = 5, + R_RISCV_TLS_DTPMOD32 = 6, + R_RISCV_TLS_DTPMOD64 = 7, + R_RISCV_TLS_DTPREL32 = 8, + R_RISCV_TLS_DTPREL64 = 9, + R_RISCV_TLS_TPREL32 = 10, + R_RISCV_TLS_TPREL64 = 11, + R_RISCV_TLSDESC = 12, + R_RISCV_BRANCH = 16, + R_RISCV_JAL = 17, + R_RISCV_CALL = 18, + R_RISCV_CALL_PLT = 19, + R_RISCV_GOT_HI20 = 20, + R_RISCV_TLS_GOT_HI20 = 21, + R_RISCV_TLS_GD_HI20 = 22, + R_RISCV_PCREL_HI20 = 23, + R_RISCV_PCREL_LO12_I = 24, + R_RISCV_PCREL_LO12_S = 25, + R_RISCV_HI20 = 26, + R_RISCV_LO12_I = 27, + R_RISCV_LO12_S = 28, + R_RISCV_TPREL_HI20 = 29, + R_RISCV_TPREL_LO12_I = 30, + R_RISCV_TPREL_LO12_S = 31, + R_RISCV_TPREL_ADD = 32, + R_RISCV_ADD8 = 33, + R_RISCV_ADD16 = 34, + R_RISCV_ADD32 = 35, + R_RISCV_ADD64 = 36, + R_RISCV_SUB8 = 37, + R_RISCV_SUB16 = 38, + R_RISCV_SUB32 = 39, + R_RISCV_SUB64 = 40, + R_RISCV_GOT32_PCREL = 41, + R_RISCV_ALIGN = 43, + R_RISCV_RVC_BRANCH = 44, + R_RISCV_RVC_JUMP = 45, + R_RISCV_RELAX = 51, + R_RISCV_SUB6 = 52, + R_RISCV_SET6 = 53, + R_RISCV_SET8 = 54, + R_RISCV_SET16 = 55, + R_RISCV_SET32 = 56, + R_RISCV_32_PCREL = 57, + R_RISCV_IRELATIVE = 58, + R_RISCV_PLT32 = 59, + R_RISCV_SET_ULEB128 = 60, + R_RISCV_SUB_ULEB128 = 61, + R_RISCV_TLSDESC_HI20 = 62, + R_RISCV_TLSDESC_LOAD_LO12 = 63, + R_RISCV_TLSDESC_ADD_LO12 = 64, + R_RISCV_TLSDESC_CALL = 65, + _default_=Pass, +) + ENUM_RELOC_TYPE_x64 = dict( R_X86_64_NONE=0, R_X86_64_64=1, diff --git a/elftools/elf/relocation.py b/elftools/elf/relocation.py index 7011cf9e..984ca0aa 100644 --- a/elftools/elf/relocation.py +++ b/elftools/elf/relocation.py @@ -12,7 +12,7 @@ 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_RISCV, ENUM_RELOC_TYPE_i386, ENUM_RELOC_TYPE_x64, ENUM_RELOC_TYPE_MIPS, ENUM_RELOC_TYPE_ARM, ENUM_RELOC_TYPE_AARCH64, ENUM_RELOC_TYPE_PPC64, ENUM_RELOC_TYPE_S390X, ENUM_RELOC_TYPE_BPF, ENUM_RELOC_TYPE_LOONGARCH) from ..construct import Container @@ -234,6 +234,12 @@ def _arm_reloc_calc_sym_plus_value_pcrel(value, sym_value, offset, addend=0): def _bpf_64_32_reloc_calc_sym_plus_addend(value, sym_value, offset, addend=0): return (sym_value + addend) // 8 - 1 +def _reloc_calc_value_plus_sym_6(value, sym_value, offset, addend=0): + return ((sym_value + addend) & 0x3F) | (value & 0xC0) + +def _reloc_calc_value_minus_sym_addend_6(value, sym_value, offset, addend=0): + return (((value & 0x3F) - sym_value - addend) & 0x3F) | (value & 0xC0) + class RelocationHandler: """ Handles the logic of relocations in ELF files. @@ -319,6 +325,8 @@ def _do_apply_relocation(self, stream, reloc, symtab): raise ELFRelocationError( 'Unexpected REL relocation for LoongArch: %s' % reloc) recipe = self._RELOCATION_RECIPES_LOONGARCH.get(reloc_type, None) + elif self.elffile.get_machine_arch() == 'RISC-V': + recipe = self._RELOCATION_RECIPES_RISCV.get(reloc_type, None) if recipe is None: raise ELFRelocationError( @@ -509,5 +517,42 @@ def _do_apply_relocation(self, stream, reloc, symtab): ENUM_RELOC_TYPE_S390X['R_390_64']: _RELOCATION_RECIPE_TYPE( bytesize=8, has_addend=True, calc_func=_reloc_calc_sym_plus_addend), } + + # https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#reloc-table + _RELOCATION_RECIPES_RISCV = { + ENUM_RELOC_TYPE_RISCV['R_RISCV_NONE']: _RELOCATION_RECIPE_TYPE( + bytesize=8, has_addend=False, calc_func=_reloc_calc_identity), + ENUM_RELOC_TYPE_RISCV['R_RISCV_32']: _RELOCATION_RECIPE_TYPE( + bytesize=4, has_addend=True, calc_func=_reloc_calc_sym_plus_addend), + ENUM_RELOC_TYPE_RISCV['R_RISCV_64']: _RELOCATION_RECIPE_TYPE( + bytesize=8, has_addend=True, calc_func=_reloc_calc_sym_plus_addend), + ENUM_RELOC_TYPE_RISCV['R_RISCV_ADD8']: _RELOCATION_RECIPE_TYPE( + bytesize=1, has_addend=True, calc_func=_reloc_calc_sym_plus_value), + ENUM_RELOC_TYPE_RISCV['R_RISCV_ADD16']: _RELOCATION_RECIPE_TYPE( + bytesize=2, has_addend=True, calc_func=_reloc_calc_sym_plus_value), + ENUM_RELOC_TYPE_RISCV['R_RISCV_ADD32']: _RELOCATION_RECIPE_TYPE( + bytesize=4, has_addend=True, calc_func=_reloc_calc_sym_plus_value), + ENUM_RELOC_TYPE_RISCV['R_RISCV_ADD64']: _RELOCATION_RECIPE_TYPE( + bytesize=8, has_addend=True, calc_func=_reloc_calc_sym_plus_value), + ENUM_RELOC_TYPE_RISCV['R_RISCV_SUB8']: _RELOCATION_RECIPE_TYPE( + bytesize=1, has_addend=True, calc_func=_reloc_calc_value_minus_sym_addend), + ENUM_RELOC_TYPE_RISCV['R_RISCV_SUB16']: _RELOCATION_RECIPE_TYPE( + bytesize=2, has_addend=True, calc_func=_reloc_calc_value_minus_sym_addend), + ENUM_RELOC_TYPE_RISCV['R_RISCV_SUB32']: _RELOCATION_RECIPE_TYPE( + bytesize=4, has_addend=True, calc_func=_reloc_calc_value_minus_sym_addend), + ENUM_RELOC_TYPE_RISCV['R_RISCV_SUB64']: _RELOCATION_RECIPE_TYPE( + bytesize=8, has_addend=True, calc_func=_reloc_calc_value_minus_sym_addend), + ENUM_RELOC_TYPE_RISCV['R_RISCV_SUB6']: _RELOCATION_RECIPE_TYPE( + bytesize=1, has_addend=True, calc_func=_reloc_calc_value_minus_sym_addend_6), + ENUM_RELOC_TYPE_RISCV['R_RISCV_SET6']: _RELOCATION_RECIPE_TYPE( + bytesize=1, has_addend=True, calc_func=_reloc_calc_value_plus_sym_6), + ENUM_RELOC_TYPE_RISCV['R_RISCV_SET8']: _RELOCATION_RECIPE_TYPE( + bytesize=1, has_addend=True, calc_func=_reloc_calc_sym_plus_addend), + ENUM_RELOC_TYPE_RISCV['R_RISCV_SET16']: _RELOCATION_RECIPE_TYPE( + bytesize=2, has_addend=True, calc_func=_reloc_calc_sym_plus_addend), + ENUM_RELOC_TYPE_RISCV['R_RISCV_SET32']: _RELOCATION_RECIPE_TYPE( + bytesize=4, has_addend=True, calc_func=_reloc_calc_sym_plus_addend), + } +