Skip to content
62 changes: 62 additions & 0 deletions elftools/elf/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
47 changes: 46 additions & 1 deletion elftools/elf/relocation.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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),
}