Skip to content

Added support for symbol relocation for RISC-V architecture #613

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
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),
}