From 0337cd05d7a6923257c820217c3c6025abe6136e Mon Sep 17 00:00:00 2001 From: hotislandn Date: Thu, 18 Feb 2021 14:24:39 +0800 Subject: [PATCH] libc:machine:risc-v:unifying elf relocation code. Signed-off-by: hotislandn --- libs/libc/machine/risc-v/Make.defs | 6 + .../risc-v/{rv32 => common}/arch_elf.c | 87 +-- libs/libc/machine/risc-v/rv32/Make.defs | 4 - libs/libc/machine/risc-v/rv64/Make.defs | 8 - libs/libc/machine/risc-v/rv64/arch_elf.c | 510 ------------------ 5 files changed, 61 insertions(+), 554 deletions(-) rename libs/libc/machine/risc-v/{rv32 => common}/arch_elf.c (83%) delete mode 100644 libs/libc/machine/risc-v/rv64/arch_elf.c diff --git a/libs/libc/machine/risc-v/Make.defs b/libs/libc/machine/risc-v/Make.defs index 8db5a2a2d7..1129f41df5 100644 --- a/libs/libc/machine/risc-v/Make.defs +++ b/libs/libc/machine/risc-v/Make.defs @@ -18,6 +18,12 @@ # ############################################################################ +ifeq ($(CONFIG_LIBC_ARCH_ELF),y) +CSRCS += arch_elf.c +DEPPATH += --dep-path machine/risc-v/common +VPATH += :machine/risc-v/common +endif + ifeq ($(CONFIG_ARCH_RV64GC),y) include $(TOPDIR)/libs/libc/machine/risc-v/rv64/Make.defs endif diff --git a/libs/libc/machine/risc-v/rv32/arch_elf.c b/libs/libc/machine/risc-v/common/arch_elf.c similarity index 83% rename from libs/libc/machine/risc-v/rv32/arch_elf.c rename to libs/libc/machine/risc-v/common/arch_elf.c index 7492800dad..46ac192251 100644 --- a/libs/libc/machine/risc-v/rv32/arch_elf.c +++ b/libs/libc/machine/risc-v/common/arch_elf.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libs/libc/machine/risc-v/rv32/arch_elf.c + * libs/libc/machine/risc-v/common/arch_elf.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -42,6 +42,18 @@ #define RVI_OPCODE_MASK 0x7F +/* ELF32 and ELF64 definitions */ + +#ifdef CONFIG_LIBC_ARCH_ELF_64BIT +# define ARCH_ELF_TYP_STR "64" +# define ARCH_ELF_CLASS ELFCLASS64 +# define ARCH_ELF_RELTYPE ELF64_R_TYPE +#else /* !CONFIG_LIBC_ARCH_ELF_64BIT */ +# define ARCH_ELF_TYP_STR "32" +# define ARCH_ELF_CLASS ELFCLASS32 +# define ARCH_ELF_RELTYPE ELF32_R_TYPE +#endif /* CONFIG_LIBC_ARCH_ELF_64BIT */ + /**************************************************************************** * Private Data Types ****************************************************************************/ @@ -60,6 +72,7 @@ static struct rname_code_s _rname_table[] = { {"RELAX", R_RISCV_RELAX}, {"RISCV_32", R_RISCV_32}, + {"RISCV_64", R_RISCV_64}, {"PCREL_LO12_I", R_RISCV_PCREL_LO12_I}, {"PCREL_LO12_S", R_RISCV_PCREL_LO12_S}, {"PCREL_HI20", R_RISCV_PCREL_HI20}, @@ -198,11 +211,12 @@ bool up_checkarch(FAR const Elf_Ehdr *ehdr) return false; } - /* Make sure that 32-bit objects are supported */ + /* Make sure that current objects are supported */ - if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) + if (ehdr->e_ident[EI_CLASS] != ARCH_ELF_CLASS) { - berr("ERROR: Need 32-bit objects: e_ident[EI_CLASS]=%02x\n", + berr("ERROR: Need " ARCH_ELF_TYP_STR "-bit " + "objects: e_ident[EI_CLASS]=%02x\n", ehdr->e_ident[EI_CLASS]); return false; } @@ -224,7 +238,7 @@ bool up_checkarch(FAR const Elf_Ehdr *ehdr) if ((ehdr->e_entry & 1) != 0) { - berr("ERROR: Entry point is not properly aligned: %08" PRIx32 "\n", + berr("ERROR: Entry point is not properly aligned: %08lx\n", ehdr->e_entry); } @@ -270,7 +284,7 @@ int up_relocateadd(FAR const Elf_Rela *rel, FAR const Elf_Sym *sym, /* All relocations depend upon having valid symbol information */ - relotype = ELF32_R_TYPE(rel->r_info); + relotype = ARCH_ELF_RELTYPE(rel->r_info); if (relotype == R_RISCV_RELAX) { @@ -293,9 +307,10 @@ int up_relocateadd(FAR const Elf_Rela *rel, FAR const Elf_Sym *sym, switch (relotype) { case R_RISCV_32: + case R_RISCV_64: { binfo("%s at %08" PRIxPTR " [%08" PRIx32 "] " - "to sym=%p st_value=%08" PRIx32 "\n", + "to sym=%p st_value=%08lx\n", _get_rname(relotype), addr, _get_val((uint16_t *)addr), sym, sym->st_value); @@ -309,7 +324,7 @@ int up_relocateadd(FAR const Elf_Rela *rel, FAR const Elf_Sym *sym, case R_RISCV_PCREL_LO12_S: { binfo("%s at %08" PRIxPTR " [%08" PRIx32 "] " - "to sym=%p st_value=%08" PRIx32 "\n", + "to sym=%p st_value=%08lx\n", _get_rname(relotype), addr, _get_val((uint16_t *)addr), sym, sym->st_value); @@ -323,7 +338,7 @@ int up_relocateadd(FAR const Elf_Rela *rel, FAR const Elf_Sym *sym, case R_RISCV_CALL_PLT: { binfo("%s at %08" PRIxPTR " [%08" PRIx32 "] " - "to sym=%p st_value=%08" PRIx32 "\n", + "to sym=%p st_value=%08lx\n", _get_rname(relotype), addr, _get_val((uint16_t *)addr), sym, sym->st_value); @@ -347,7 +362,8 @@ int up_relocateadd(FAR const Elf_Rela *rel, FAR const Elf_Sym *sym, (((int32_t)imm_lo >> 5) << 25) + (((int32_t)imm_lo & 0x1f) << 7); - binfo("imm_lo=%ld (%lx), val=%lx \n", imm_lo, imm_lo, val); + binfo("imm_lo=%ld (%lx), val=%" PRIx32 "\n", + imm_lo, imm_lo, val); _add_val((uint16_t *)(addr + 4), val); } @@ -362,10 +378,11 @@ int up_relocateadd(FAR const Elf_Rela *rel, FAR const Elf_Sym *sym, case R_RISCV_BRANCH: { - binfo("%s at %08lx [%08lx] to sym=%p st_value=%08lx\n", + binfo("%s at %08" PRIxPTR " [%08" PRIx32 "] " + "to sym=%p st_value=%08lx\n", _get_rname(relotype), - (long)addr, _get_val((uint16_t *)addr), - sym, (long)sym->st_value); + addr, _get_val((uint16_t *)addr), + sym, sym->st_value); /* P.23 Conditinal Branches : B type (imm=12bit) */ @@ -376,17 +393,19 @@ int up_relocateadd(FAR const Elf_Rela *rel, FAR const Elf_Sym *sym, ASSERT(offset && val); - binfo("offset for Bx=%ld (0x%lx) (val=0x%08lx) already set! \n", + binfo("offset for Bx=%ld (0x%lx) (val=0x%08" PRIx32 ") " + "already set! \n", offset, offset, val); } break; case R_RISCV_HI20: { - binfo("%s at %08lx [%08lx] to sym=%p st_value=%08lx\n", + binfo("%s at %08" PRIxPTR " [%08" PRIx32 "] " + "to sym=%p st_value=%08lx\n", _get_rname(relotype), - (long)addr, _get_val((uint16_t *)addr), - sym, (long)sym->st_value); + addr, _get_val((uint16_t *)addr), + sym, sym->st_value); /* P.19 LUI */ @@ -406,10 +425,11 @@ int up_relocateadd(FAR const Elf_Rela *rel, FAR const Elf_Sym *sym, case R_RISCV_LO12_I: { - binfo("%s at %08lx [%08lx] to sym=%p st_value=%08lx\n", + binfo("%s at %08" PRIxPTR " [%08" PRIx32 "] " + "to sym=%p st_value=%08lx\n", _get_rname(relotype), - (long)addr, _get_val((uint16_t *)addr), - sym, (long)sym->st_value); + addr, _get_val((uint16_t *)addr), + sym, sym->st_value); /* ADDI, FLW, LD, ... : I-type */ @@ -427,10 +447,11 @@ int up_relocateadd(FAR const Elf_Rela *rel, FAR const Elf_Sym *sym, case R_RISCV_LO12_S: { - binfo("%s at %08lx [%08lx] to sym=%p st_value=%08lx\n", + binfo("%s at %08" PRIxPTR " [%08" PRIx32 "] " + "to sym=%p st_value=%08lx\n", _get_rname(relotype), - (long)addr, _get_val((uint16_t *)addr), - sym, (long)sym->st_value); + addr, _get_val((uint16_t *)addr), + sym, sym->st_value); /* SW : S-type. * not merge with R_RISCV_HI20 since the compiler @@ -447,7 +468,7 @@ int up_relocateadd(FAR const Elf_Rela *rel, FAR const Elf_Sym *sym, (((int32_t)imm_lo >> 5) << 25) + (((int32_t)imm_lo & 0x1f) << 7); - binfo("imm_lo=%ld (%lx), val=%lx \n", imm_lo, imm_lo, val); + binfo("imm_lo=%ld (%lx), val=%" PRIx32 "\n", imm_lo, imm_lo, val); _add_val((uint16_t *)addr, val); } @@ -455,10 +476,11 @@ int up_relocateadd(FAR const Elf_Rela *rel, FAR const Elf_Sym *sym, case R_RISCV_RVC_JUMP: { - binfo("%s at %08lx [%04lx] to sym=%p st_value=%08lx\n", + binfo("%s at %08" PRIxPTR " [%08" PRIx32 "] " + "to sym=%p st_value=%08lx\n", _get_rname(relotype), - (long)addr, _get_val((uint16_t *)addr), - sym, (long)sym->st_value); + addr, _get_val((uint16_t *)addr), + sym, sym->st_value); /* P.111 Table 16.6 : Instruction listings for RVC */ @@ -478,10 +500,11 @@ int up_relocateadd(FAR const Elf_Rela *rel, FAR const Elf_Sym *sym, case R_RISCV_RVC_BRANCH: { - binfo("%s at %08lx [%04lx] to sym=%p st_value=%08lx\n", + binfo("%s at %08" PRIxPTR " [%08" PRIx32 "] " + "to sym=%p st_value=%08lx\n", _get_rname(relotype), - (long)addr, _get_val((uint16_t *)addr), - sym, (long)sym->st_value); + addr, _get_val((uint16_t *)addr), + sym, sym->st_value); /* P.111 Table 16.6 : Instruction listings for RVC */ @@ -500,8 +523,8 @@ int up_relocateadd(FAR const Elf_Rela *rel, FAR const Elf_Sym *sym, break; default: - berr("ERROR: Unsupported relocation: %" PRId32 "\n", - ELF32_R_TYPE(rel->r_info)); + berr("ERROR: Unsupported relocation: %ld\n", + ARCH_ELF_RELTYPE(rel->r_info)); ASSERT(false); return -EINVAL; } diff --git a/libs/libc/machine/risc-v/rv32/Make.defs b/libs/libc/machine/risc-v/rv32/Make.defs index 543aed9f33..4524949f38 100644 --- a/libs/libc/machine/risc-v/rv32/Make.defs +++ b/libs/libc/machine/risc-v/rv32/Make.defs @@ -22,10 +22,6 @@ ifeq ($(CONFIG_RISCV_MEMCPY),y) ASRCS += arch_memcpy.S endif -ifeq ($(CONFIG_LIBC_ARCH_ELF),y) -CSRCS += arch_elf.c -endif - DEPPATH += --dep-path machine/risc-v/rv32 VPATH += :machine/risc-v/rv32 diff --git a/libs/libc/machine/risc-v/rv64/Make.defs b/libs/libc/machine/risc-v/rv64/Make.defs index a08bd9fb6e..89d11c84b4 100644 --- a/libs/libc/machine/risc-v/rv64/Make.defs +++ b/libs/libc/machine/risc-v/rv64/Make.defs @@ -18,11 +18,3 @@ # ############################################################################ -ifeq ($(CONFIG_LIBC_ARCH_ELF),y) - -CSRCS += arch_elf.c - -DEPPATH += --dep-path machine/risc-v/rv64 -VPATH += :machine/risc-v/rv64 - -endif diff --git a/libs/libc/machine/risc-v/rv64/arch_elf.c b/libs/libc/machine/risc-v/rv64/arch_elf.c deleted file mode 100644 index 647df0044f..0000000000 --- a/libs/libc/machine/risc-v/rv64/arch_elf.c +++ /dev/null @@ -1,510 +0,0 @@ -/**************************************************************************** - * libs/libc/machine/risc-v/rv64/arch_elf.c - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include -#include -#include -#include -#include - -#include -#include - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -#define OPCODE_SW 0x23 -#define OPCODE_LUI 0x37 - -#define RVI_OPCODE_MASK 0x7F - -/**************************************************************************** - * Private Data Types - ****************************************************************************/ - -struct rname_code_s -{ - const char *name; - int type; -}; - -/**************************************************************************** - * Private Data - ****************************************************************************/ - -static struct rname_code_s _rname_table[] = -{ - {"RELAX", R_RISCV_RELAX}, - {"RISCV_64", R_RISCV_64}, - {"PCREL_LO12_I", R_RISCV_PCREL_LO12_I}, - {"PCREL_LO12_S", R_RISCV_PCREL_LO12_S}, - {"PCREL_HI20", R_RISCV_PCREL_HI20}, - {"HI20", R_RISCV_HI20}, - {"LO12_I", R_RISCV_LO12_I}, - {"LO12_S", R_RISCV_LO12_S}, - {"CALL", R_RISCV_CALL}, - {"CALL_PLT", R_RISCV_CALL_PLT}, - {"BRANCH", R_RISCV_BRANCH}, - {"RVC_JUMP", R_RISCV_RVC_JUMP}, - {"RVC_BRANCH", R_RISCV_RVC_BRANCH}, -}; - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -static const char *_get_rname(int type) -{ - int i = 0; - - for (i = 0; i < sizeof(_rname_table) / sizeof(struct rname_code_s); i++) - { - if (_rname_table[i].type == type) - { - return _rname_table[i].name; - } - } - - /* Not found in the table */ - - return "?????"; -} - -/**************************************************************************** - * Name: _get_val, set_val, _add_val - * - * Description: - * These functions are used when relocating an instruction because we can - * not assume the instruction is word-aligned. - * - ****************************************************************************/ - -static uint32_t _get_val(uint16_t *addr) -{ - uint32_t ret; - ret = *addr | (*(addr + 1)) << 16; - return ret; -} - -static void _set_val(uint16_t *addr, uint32_t val) -{ - *addr = (val & 0xffff); - *(addr + 1) = (val >> 16); - - /* NOTE: Ensure relocation before execution */ - - asm volatile ("fence.i"); -} - -static void _add_val(uint16_t *addr, uint32_t val) -{ - uint32_t cur = _get_val(addr); - _set_val(addr, cur + val); -} - -/**************************************************************************** - * Name: _calc_imm - * - * Description: - * Given offset and obtain imm_hi (20bit) and imm_lo (12bit) - * - * Input Parameters: - * offset - signed 64bit - * imm_hi - signed 20bit - * imm_lo - signed 12bit - * - * Returned Value: - * none - * - ****************************************************************************/ - -static void _calc_imm(long offset, long *imm_hi, long *imm_lo) -{ - long lo; - long hi = offset / 4096; - long r = offset % 4096; - - if (2047 < r) - { - hi++; - } - else if (r < -2048) - { - hi--; - } - - lo = offset - (hi * 4096); - - binfo("offset=%ld: hi=%ld lo=%ld \n", - offset, hi, lo); - - ASSERT(-2048 <= lo && lo <= 2047); - - *imm_lo = lo; - *imm_hi = hi; -} - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: up_checkarch - * - * Description: - * Given the ELF header in 'hdr', verify that the ELF file is appropriate - * for the current, configured architecture. Every architecture that uses - * the ELF loader must provide this function. - * - * Input Parameters: - * hdr - The ELF header read from the ELF file. - * - * Returned Value: - * True if the architecture supports this ELF file. - * - ****************************************************************************/ - -bool up_checkarch(FAR const Elf64_Ehdr *ehdr) -{ - /* Make sure it's an RISCV executable */ - - if (ehdr->e_machine != EM_RISCV) - { - berr("ERROR: Not for RISCV: e_machine=%04x\n", ehdr->e_machine); - return false; - } - - /* Make sure that 64-bit objects are supported */ - - if (ehdr->e_ident[EI_CLASS] != ELFCLASS64) - { - berr("ERROR: Need 64-bit objects: e_ident[EI_CLASS]=%02x\n", - ehdr->e_ident[EI_CLASS]); - return false; - } - - /* Verify endian-ness */ - -#ifdef CONFIG_ENDIAN_BIG - if (ehdr->e_ident[EI_DATA] != ELFDATA2MSB) -#else - if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) -#endif - { - berr("ERROR: Wrong endian-ness: e_ident[EI_DATA]=%02x\n", - ehdr->e_ident[EI_DATA]); - return false; - } - - /* Make sure the entry point address is properly aligned */ - - if ((ehdr->e_entry & 1) != 0) - { - berr("ERROR: Entry point is not properly aligned: %08" PRIx64 "\n", - ehdr->e_entry); - } - - /* TODO: Check ABI here. */ - - return true; -} - -/**************************************************************************** - * Name: up_relocate and up_relocateadd - * - * Description: - * Perform on architecture-specific ELF relocation. Every architecture - * that uses the ELF loader must provide this function. - * - * Input Parameters: - * rel - The relocation type - * sym - The ELF symbol structure containing the fully resolved value. - * There are a few relocation types for a few architectures that do - * not require symbol information. For those, this value will be - * NULL. Implementations of these functions must be able to handle - * that case. - * addr - The address that requires the relocation. - * - * Returned Value: - * Zero (OK) if the relocation was successful. Otherwise, a negated errno - * value indicating the cause of the relocation failure. - * - ****************************************************************************/ - -int up_relocate(FAR const Elf64_Rel *rel, FAR const Elf64_Sym *sym, - uintptr_t addr) -{ - berr("Not implemented\n"); - return -ENOSYS; -} - -int up_relocateadd(FAR const Elf64_Rela *rel, FAR const Elf64_Sym *sym, - uintptr_t addr) -{ - long offset; - unsigned int relotype; - - /* All relocations depend upon having valid symbol information */ - - relotype = ELF64_R_TYPE(rel->r_info); - - if (relotype == R_RISCV_RELAX) - { - /* NOTE: RELAX has no symbol, so just return */ - - binfo("%s at %08" PRIxPTR " [%08" PRIx32 "] \n", - _get_rname(relotype), - addr, _get_val((uint16_t *)addr)); - - return OK; - } - - if (sym == NULL && relotype != R_RISCV_NONE) - { - return -EINVAL; - } - - /* Do relocation based on relocation type */ - - switch (relotype) - { - case R_RISCV_64: - { - binfo("%s at %08" PRIxPTR " [%08" PRIx32 "] " - "to sym=%p st_value=%08" PRIx64 "\n", - _get_rname(relotype), - addr, _get_val((uint16_t *)addr), - sym, sym->st_value); - - _set_val((uint16_t *)addr, - (uint32_t)(sym->st_value + rel->r_addend)); - } - break; - - case R_RISCV_PCREL_LO12_I: - case R_RISCV_PCREL_LO12_S: - { - binfo("%s at %08" PRIxPTR " [%08" PRIx32 "] " - "to sym=%p st_value=%08" PRIx64 "\n", - _get_rname(relotype), - addr, _get_val((uint16_t *)addr), - sym, sym->st_value); - - /* NOTE: imm value for mv has been adjusted in previous HI20 */ - } - break; - - case R_RISCV_PCREL_HI20: - case R_RISCV_CALL: - case R_RISCV_CALL_PLT: - { - binfo("%s at %08" PRIxPTR " [%08" PRIx32 "] " - "to sym=%p st_value=%08" PRIx64 "\n", - _get_rname(relotype), - addr, _get_val((uint16_t *)addr), - sym, sym->st_value); - - offset = (long)sym->st_value - (long)addr; - - long imm_hi; - long imm_lo; - - _calc_imm(offset, &imm_hi, &imm_lo); - - /* Adjust auipc (add upper immediate to pc) : 20bit */ - - _add_val((uint16_t *)addr, (imm_hi << 12)); - - if ((_get_val((uint16_t *)(addr + 4)) & 0x7f) == OPCODE_SW) - { - /* Adjust imm for SW : S-type */ - - uint32_t val = - (((int32_t)imm_lo >> 5) << 25) + - (((int32_t)imm_lo & 0x1f) << 7); - - binfo("imm_lo=%ld (%lx), val=%x \n", imm_lo, imm_lo, val); - - _add_val((uint16_t *)(addr + 4), val); - } - else - { - /* Adjust imm for MV(ADDI)/JALR : I-type */ - - _add_val((uint16_t *)(addr + 4), ((int32_t)imm_lo << 20)); - } - } - break; - - case R_RISCV_BRANCH: - { - binfo("%s at %08lx [%08x] to sym=%p st_value=%08lx\n", - _get_rname(relotype), - (long)addr, _get_val((uint16_t *)addr), - sym, (long)sym->st_value); - - /* P.23 Conditinal Branches : B type (imm=12bit) */ - - offset = (long)sym->st_value - (long)addr; - uint32_t val = _get_val((uint16_t *)addr) & 0xfe000f80; - - /* NOTE: we assume that a compiler adds an immediate value */ - - ASSERT(offset && val); - - binfo("offset for Bx=%ld (0x%lx) (val=0x%08x) already set! \n", - offset, offset, val); - } - break; - - case R_RISCV_HI20: - { - binfo("%s at %08lx [%08x] to sym=%p st_value=%08lx\n", - _get_rname(relotype), - (long)addr, _get_val((uint16_t *)addr), - sym, (long)sym->st_value); - - /* P.19 LUI */ - - offset = (long)sym->st_value; - uint32_t insn = _get_val((uint16_t *)addr); - - ASSERT(OPCODE_LUI == (insn & RVI_OPCODE_MASK)); - - long imm_hi; - long imm_lo; - _calc_imm(offset, &imm_hi, &imm_lo); - insn = (insn & 0x00000fff) | (imm_hi << 12); - - _set_val((uint16_t *)addr, insn); - } - break; - - case R_RISCV_LO12_I: - { - binfo("%s at %08lx [%08x] to sym=%p st_value=%08lx\n", - _get_rname(relotype), - (long)addr, _get_val((uint16_t *)addr), - sym, (long)sym->st_value); - - /* ADDI, FLW, LD, ... : I-type */ - - offset = (long)sym->st_value; - uint32_t insn = _get_val((uint16_t *)addr); - - long imm_hi; - long imm_lo; - _calc_imm(offset, &imm_hi, &imm_lo); - insn = (insn & 0x000fffff) | (imm_lo << 20); - - _set_val((uint16_t *)addr, insn); - } - break; - - case R_RISCV_LO12_S: - { - binfo("%s at %08lx [%08x] to sym=%p st_value=%08lx\n", - _get_rname(relotype), - (long)addr, _get_val((uint16_t *)addr), - sym, (long)sym->st_value); - - /* SW : S-type. - * not merge with R_RISCV_HI20 since the compiler - * may not generates these two instructions continuously. - */ - - offset = (long)sym->st_value; - - long imm_hi; - long imm_lo; - _calc_imm(offset, &imm_hi, &imm_lo); - - uint32_t val = - (((int32_t)imm_lo >> 5) << 25) + - (((int32_t)imm_lo & 0x1f) << 7); - - binfo("imm_lo=%ld (%lx), val=%x \n", imm_lo, imm_lo, val); - - _add_val((uint16_t *)addr, val); - } - break; - - case R_RISCV_RVC_JUMP: - { - binfo("%s at %08lx [%04x] to sym=%p st_value=%08lx\n", - _get_rname(relotype), - (long)addr, _get_val((uint16_t *)addr), - sym, (long)sym->st_value); - - /* P.111 Table 16.6 : Instruction listings for RVC */ - - offset = ((long)sym->st_value - (long)addr); - ASSERT(-2048 <= offset && offset <= 2047); - - uint16_t val = (*(uint16_t *)addr) & 0x1ffc; - - /* NOTE: we assume that a compiler adds an immediate value */ - - ASSERT(offset && val); - - binfo("offset for C.J=%ld (0x%lx) (val=0x%04x) already set! \n", - offset, offset, val); - } - break; - - case R_RISCV_RVC_BRANCH: - { - binfo("%s at %08lx [%04x] to sym=%p st_value=%08lx\n", - _get_rname(relotype), - (long)addr, _get_val((uint16_t *)addr), - sym, (long)sym->st_value); - - /* P.111 Table 16.6 : Instruction listings for RVC */ - - offset = ((long)sym->st_value - (long)addr); - ASSERT(-256 <= offset && offset <= 255); - - uint16_t val = (*(uint16_t *)addr) & 0x1c7c; - - /* NOTE: we assume that a compiler adds an immediate value */ - - ASSERT(offset && val); - - binfo("offset for C.Bx=%ld (0x%lx) (val=0x%04x) already set!\n", - offset, offset, val); - } - break; - - default: - berr("ERROR: Unsupported relocation: %" PRId64 "\n", - ELF64_R_TYPE(rel->r_info)); - ASSERT(false); - return -EINVAL; - } - - return OK; -}