Index: ELF/Arch/RISCV.cpp =================================================================== --- /dev/null +++ ELF/Arch/RISCV.cpp @@ -0,0 +1,273 @@ +//===- RISCV.cpp ----------------------------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "InputFiles.h" +#include "InputSection.h" +#include "Memory.h" +#include "OutputSections.h" +#include "SymbolTable.h" +#include "Symbols.h" +#include "SyntheticSections.h" +#include "Target.h" +#include "Thunks.h" +#include "Writer.h" +#include "lld/Common/ErrorHandler.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/ELF.h" +#include "llvm/Object/ELF.h" +#include "llvm/Object/ELFTypes.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/raw_ostream.h" + +#include + +using namespace llvm; +using namespace llvm::object; +using namespace llvm::support::endian; +using namespace llvm::ELF; +using namespace lld; +using namespace lld::elf; + +namespace { + +class RISCV final : public TargetInfo { +public: + RelExpr getRelExpr(RelType Type, const SymbolBody &S, + const uint8_t *Loc) const override; + void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; +}; + +} // end anonymous namespace + +// RISC-V instructions are stored as 16-bit parcels starting with lower bits; +// each parcel is stored according to implementation's endianness. +static void writeInsn32(uint8_t *const Buf, const uint32_t Insn) { + write16le(Buf, Insn); + write16le(Buf + 2, Insn >> 16); +} + +static uint32_t readInsn32(const uint8_t *const Buf) { + return read32le(Buf); +} + +RelExpr RISCV::getRelExpr(const RelType Type, const SymbolBody &S, + const uint8_t *Loc) const { + switch (Type) { + case R_RISCV_JAL: + case R_RISCV_BRANCH: + case R_RISCV_CALL: + case R_RISCV_PCREL_HI20: + case R_RISCV_RVC_BRANCH: + case R_RISCV_RVC_JUMP: + case R_RISCV_32_PCREL: + return R_PC; + case R_RISCV_PCREL_LO12_I: + case R_RISCV_PCREL_LO12_S: + return R_RISCV_PC_INDIRECT; + case R_RISCV_RELAX: + case R_RISCV_ALIGN: + return R_HINT; + default: + return R_ABS; + } +} + +// Extract bits V[Begin:End]. +uint32_t extractBits(uint64_t V, uint32_t Begin, uint32_t End) { + return (V & ((static_cast(1) << (Begin + 1)) - 1)) >> End; +} + +// Reference: +// https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md +void RISCV::relocateOne(uint8_t *Loc, const RelType Type, + const uint64_t Val) const { + switch (Type) { + case R_RISCV_32: + write32le(Loc, Val); + return; + case R_RISCV_64: + write64le(Loc, Val); + return; + + case R_RISCV_RVC_BRANCH: { + checkInt<8>(Loc, static_cast(Val) >> 1, Type); + checkAlignment<2>(Loc, Val, Type); + uint16_t Inst = read16le(Loc) & 0xE383; + uint16_t Imm8 = extractBits(Val, 8, 8) << 12; + uint16_t Imm4_3 = extractBits(Val, 4, 3) << 10; + uint16_t Imm7_6 = extractBits(Val, 7, 6) << 5; + uint16_t Imm2_1 = extractBits(Val, 2, 1) << 3; + uint16_t Imm5 = extractBits(Val, 5, 5) << 2; + write16le(Loc, Inst | Imm8 | Imm4_3 | Imm7_6 | Imm2_1 | Imm5); + return; + } + + case R_RISCV_RVC_JUMP: { + checkInt<11>(Loc, static_cast(Val) >> 1, Type); + checkAlignment<2>(Loc, Val, Type); + uint16_t Inst = read16le(Loc) & 0xE003; + uint16_t Imm11 = extractBits(Val, 11, 11) << 12; + uint16_t Imm4 = extractBits(Val, 4, 4) << 11; + uint16_t Imm9_8 = extractBits(Val, 9, 8) << 9; + uint16_t Imm10 = extractBits(Val, 10, 10) << 8; + uint16_t Imm6 = extractBits(Val, 6, 6) << 7; + uint16_t Imm7 = extractBits(Val, 7, 7) << 6; + uint16_t Imm3_1 = extractBits(Val, 3, 1) << 3; + uint16_t Imm5 = extractBits(Val, 5, 5) << 2; + write16le(Loc, + Inst | Imm11 | Imm4 | Imm9_8 | Imm10 | Imm6 | Imm7 | Imm3_1 | Imm5); + return; + } + + case R_RISCV_RVC_LUI: { + int32_t Imm = ((Val + 0x800) >> 12); + checkUInt<6>(Loc, Imm, Type); + if (Imm == 0) { // `c.lui rd, 0` is illegal, convert to `c.li rd, 0` + write16le(Loc, (read16le(Loc) & 0x0F83) | 0x4000); + } else { + uint16_t Imm17 = extractBits(Val + 0x800, 17, 17) << 12; + uint16_t Imm16_12 = extractBits(Val + 0x800, 16, 12) << 2; + write16le(Loc, (read16le(Loc) & 0xEF83) | Imm17 | Imm16_12); + } + return; + } + + case R_RISCV_JAL: { + checkInt<20>(Loc, static_cast(Val) >> 1, Type); + checkAlignment<2>(Loc, Val, Type); + + uint32_t Inst = readInsn32(Loc) & 0xFFF; + uint32_t Imm20 = extractBits(Val, 20, 20) << 31; + uint32_t Imm10_1 = extractBits(Val, 10, 1) << 21; + uint32_t Imm11 = extractBits(Val, 11, 11) << 20; + uint32_t Imm19_12 = extractBits(Val, 19, 12) << 12; + uint32_t Imm20_1 = Imm20 | Imm10_1 | Imm11 | Imm19_12; + + writeInsn32(Loc, Inst | Imm20_1); + return; + } + + case R_RISCV_BRANCH: { + checkInt<12>(Loc, static_cast(Val) >> 1, Type); + checkAlignment<2>(Loc, Val, Type); + + uint32_t Inst = readInsn32(Loc) & 0x1FFF07F; + uint32_t Imm12 = extractBits(Val, 12, 12) << 31; + uint32_t Imm10_5 = extractBits(Val, 10, 5) << 25; + uint32_t Imm4_1 = extractBits(Val, 4, 1) << 8; + uint32_t Imm11 = extractBits(Val, 11, 11) << 7; + uint32_t Imm12_1 = Imm12 | Imm10_5 | Imm4_1 | Imm11; + + writeInsn32(Loc, Inst | Imm12_1); + return; + } + // auipc + jalr pair + case R_RISCV_CALL: { + checkInt<32>(Loc, Val, Type); + uint32_t Hi = Val + 0x800; + uint32_t Lo = Val - (Hi & 0xFFFFF000); + writeInsn32(Loc, (readInsn32(Loc) & 0xFFF) | (Hi & 0xFFFFF000)); + writeInsn32(Loc + 4, + (readInsn32(Loc + 4) & 0xFFFFF) | ((Lo & 0xFFF) << 20)); + return; + } + + case R_RISCV_PCREL_HI20: + case R_RISCV_HI20: { + checkInt<32>(Loc, Val, Type); + uint32_t Hi = Val + 0x800; + writeInsn32(Loc, (readInsn32(Loc) & 0xFFF) | (Hi & 0xFFFFF000)); + return; + } + case R_RISCV_PCREL_LO12_I: + case R_RISCV_LO12_I: { + checkInt<32>(Loc, Val, Type); + uint32_t Hi = Val + 0x800; + uint32_t Lo = Val - (Hi & 0xFFFFF000); + writeInsn32(Loc, (readInsn32(Loc) & 0xFFFFF) | ((Lo & 0xFFF) << 20)); + return; + } + case R_RISCV_PCREL_LO12_S: + case R_RISCV_LO12_S: { + checkInt<32>(Loc, Val, Type); + uint32_t Hi = Val + 0x800; + uint32_t Lo = Val - (Hi & 0xFFFFF000); + uint32_t Imm11_5 = extractBits(Lo, 11, 5) << 25; + uint32_t Imm4_0 = extractBits(Lo, 4, 0) << 7; + writeInsn32(Loc, (readInsn32(Loc) & 0x1FFF07F) | Imm11_5 | Imm4_0); + return; + } + + case R_RISCV_ADD8: + *Loc += Val; + return; + case R_RISCV_ADD16: + write16le(Loc, read16le(Loc) + Val); + return; + case R_RISCV_ADD32: + write32le(Loc, read32le(Loc) + Val); + return; + case R_RISCV_ADD64: + write64le(Loc, read64le(Loc) + Val); + return; + case R_RISCV_SUB6: + *Loc = (*Loc & 0xc0) | (((*Loc & 0x3f) - Val) & 0x3f); + return; + case R_RISCV_SUB8: + *Loc -= Val; + return; + case R_RISCV_SUB16: + write16le(Loc, read16le(Loc) - Val); + return; + case R_RISCV_SUB32: + write32le(Loc, read32le(Loc) - Val); + return; + case R_RISCV_SUB64: + write64le(Loc, read64le(Loc) - Val); + return; + case R_RISCV_SET6: + *Loc = (*Loc & 0xc0) | (Val & 0x3f); + return; + case R_RISCV_SET8: + *Loc = Val; + return; + case R_RISCV_SET16: + write16le(Loc, Val); + return; + case R_RISCV_SET32: + case R_RISCV_32_PCREL: + write32le(Loc, Val); + return; + + case R_RISCV_ALIGN: + case R_RISCV_RELAX: + return; // Ignored (for now) + case R_RISCV_NONE: + return; // Do nothing + + // These are handled by the dynamic linker + case R_RISCV_RELATIVE: + case R_RISCV_COPY: + case R_RISCV_JUMP_SLOT: + // GP-relative relocations are only produced after relaxation, which + // we don't support for now + case R_RISCV_GPREL_I: + case R_RISCV_GPREL_S: + default: + error(getErrorLocation(Loc) + + "unimplemented relocation type: " + Twine(Type)); + return; + } +} + +TargetInfo *elf::getRISCVTargetInfo() { + static RISCV Target; + return &Target; +} Index: ELF/CMakeLists.txt =================================================================== --- ELF/CMakeLists.txt +++ ELF/CMakeLists.txt @@ -15,6 +15,7 @@ Arch/MipsArchTree.cpp Arch/PPC.cpp Arch/PPC64.cpp + Arch/RISCV.cpp Arch/SPARCV9.cpp Arch/X86.cpp Arch/X86_64.cpp Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -121,9 +121,11 @@ .Case("elf32_x86_64", {ELF32LEKind, EM_X86_64}) .Cases("elf32btsmip", "elf32btsmipn32", {ELF32BEKind, EM_MIPS}) .Cases("elf32ltsmip", "elf32ltsmipn32", {ELF32LEKind, EM_MIPS}) + .Case("elf32lriscv", {ELF32LEKind, EM_RISCV}) .Case("elf32ppc", {ELF32BEKind, EM_PPC}) .Case("elf64btsmip", {ELF64BEKind, EM_MIPS}) .Case("elf64ltsmip", {ELF64LEKind, EM_MIPS}) + .Case("elf64lriscv", {ELF64LEKind, EM_RISCV}) .Case("elf64ppc", {ELF64BEKind, EM_PPC64}) .Cases("elf_amd64", "elf_x86_64", {ELF64LEKind, EM_X86_64}) .Case("elf_i386", {ELF32LEKind, EM_386}) @@ -836,7 +838,8 @@ Config->Endianness = Config->IsLE ? support::endianness::little : support::endianness::big; Config->IsMips64EL = (Kind == ELF64LEKind && Machine == EM_MIPS); - Config->IsRela = Config->Is64 || IsX32 || Config->MipsN32Abi; + Config->IsRela = + Config->Is64 || IsX32 || Config->MipsN32Abi || Machine == EM_RISCV; Config->Pic = Config->Pie || Config->Shared; Config->Wordsize = Config->Is64 ? 8 : 4; } Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -565,6 +565,26 @@ Dest = getAArch64Page(Body.getVA(A)); return Dest - getAArch64Page(P); } + case R_RISCV_PC_INDIRECT: { + // For R_RISCV_PC_INDIRECT (R_RISCV_PCREL_LO12_{I,S}), the symbol actually + // points the corresponding R_RISCV_PCREL_HI20 relocation, and the target VA + // is calculated using HI20's symbol. + uint64_t Label = Body.getVA(); + const InputSection *IS = + cast(cast(Body).Section); + for (const Relocation &HiRel : IS->Relocations) { + uint64_t HiOffset = IS->getOffset(HiRel.Offset); + uint64_t HiAddrLoc = IS->getOutputSection()->Addr + HiOffset; + if (Label == HiAddrLoc && isRelExprOneOf(HiRel.Expr)) { + return getRelocTargetVA(HiRel.Type, HiRel.Addend, HiAddrLoc, *HiRel.Sym, + HiRel.Expr); + } + } + + error("PCREL_LO12 relocation to symbol " + Body.getName() + + " without associated HI20 relocation"); + return 0; + } case R_PC: { uint64_t Dest; if (Body.isUndefWeak()) { Index: ELF/Relocations.h =================================================================== --- ELF/Relocations.h +++ ELF/Relocations.h @@ -71,6 +71,7 @@ R_RELAX_TLS_GD_TO_LE_NEG, R_RELAX_TLS_IE_TO_LE, R_RELAX_TLS_LD_TO_LE, + R_RISCV_PC_INDIRECT, R_SIZE, R_TLS, R_TLSDESC, Index: ELF/Symbols.h =================================================================== --- ELF/Symbols.h +++ ELF/Symbols.h @@ -342,6 +342,9 @@ static DefinedRegular *MipsGp; static DefinedRegular *MipsGpDisp; static DefinedRegular *MipsLocalGp; + + // __global_pointer$ in RISC-V. + static DefinedRegular *RISCVGlobalPointer; }; // A real symbol object, SymbolBody, is usually stored within a Symbol. There's Index: ELF/Symbols.cpp =================================================================== --- ELF/Symbols.cpp +++ ELF/Symbols.cpp @@ -39,6 +39,7 @@ DefinedRegular *ElfSym::MipsGp; DefinedRegular *ElfSym::MipsGpDisp; DefinedRegular *ElfSym::MipsLocalGp; +DefinedRegular *ElfSym::RISCVGlobalPointer; static uint64_t getSymVA(const SymbolBody &Body, int64_t &Addend) { switch (Body.kind()) { Index: ELF/Target.h =================================================================== --- ELF/Target.h +++ ELF/Target.h @@ -127,6 +127,7 @@ TargetInfo *getAVRTargetInfo(); TargetInfo *getPPC64TargetInfo(); TargetInfo *getPPCTargetInfo(); +TargetInfo *getRISCVTargetInfo(); TargetInfo *getSPARCV9TargetInfo(); TargetInfo *getX32TargetInfo(); TargetInfo *getX86TargetInfo(); Index: ELF/Target.cpp =================================================================== --- ELF/Target.cpp +++ ELF/Target.cpp @@ -77,6 +77,8 @@ return getPPCTargetInfo(); case EM_PPC64: return getPPC64TargetInfo(); + case EM_RISCV: + return getRISCVTargetInfo(); case EM_SPARCV9: return getSPARCV9TargetInfo(); case EM_X86_64: Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -799,6 +799,12 @@ Symtab->addAbsolute("__gnu_local_gp", STV_HIDDEN, STB_LOCAL); } + // In RISC-V, this is the address the global pointer (gp) register will be + // set to in startup code. + if (Config->EMachine == EM_RISCV) + ElfSym::RISCVGlobalPointer = + Symtab->addAbsolute("__global_pointer$", STV_HIDDEN, STB_LOCAL); + // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention to // be at some offset from the base of the .got section, usually 0 or the end // of the .got @@ -961,6 +967,16 @@ } } } + + // RISC-V's gp can address +/- 2 KiB, so it is set to .sdata or .data + 0x800. + if (ElfSym::RISCVGlobalPointer) { + if (const auto Sdata = findSection(".sdata")) + ElfSym::RISCVGlobalPointer->Section = Sdata; + else if (const auto Data = findSection(".data")) + ElfSym::RISCVGlobalPointer->Section = Data; + + ElfSym::RISCVGlobalPointer->Value = 0x800; + } } // We want to find how similar two ranks are. Index: test/ELF/riscv-branch.test =================================================================== --- /dev/null +++ test/ELF/riscv-branch.test @@ -0,0 +1,119 @@ +# .option norelax +# .global _start +# _start: +# beq x0, x0, _start +# +# .section .reloc_max, "ax", @progbits +# L1: +# beq x0, x0, L1 + 0xffe +# +# .section .reloc_min, "ax", @progbits +# L2: +# beq x0, x0, L2 - 0x1000 +# +# REQUIRES: riscv +# RUN: yaml2obj %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: obj2yaml %t | FileCheck %s +# +# CHECK: - Name: .text +# CHECK: Content: '63000000' +# 11000: 00000063 beqz zero,11000 <_start> +# +# CHECK: - Name: .reloc_max +# CHECK: Content: E30F007E +# 11004: 7e000fe3 beqz zero,12002 +# +# CHECK: - Name: .reloc_min +# CHECK: Content: '63000080' +# 11008: 80000063 beqz zero,10008 + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV + Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000002 + Content: '63000000' + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000000 + Symbol: _start + Type: R_RISCV_BRANCH + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + - Name: .reloc_max + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000001 + Content: E30F007E + - Name: .rela.reloc_max + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .reloc_max + Relocations: + - Offset: 0x0000000000000000 + Symbol: L1 + Type: R_RISCV_BRANCH + Addend: 4094 + - Name: .reloc_min + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000001 + Content: '63000080' + - Name: .rela.reloc_min + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .reloc_min + Relocations: + - Offset: 0x0000000000000000 + Symbol: L2 + Type: R_RISCV_BRANCH + Addend: -4096 +Symbols: + Local: + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .data + Type: STT_SECTION + Section: .data + - Name: .bss + Type: STT_SECTION + Section: .bss + - Name: .reloc_max + Type: STT_SECTION + Section: .reloc_max + - Name: L1 + Section: .reloc_max + - Name: .reloc_min + Type: STT_SECTION + Section: .reloc_min + - Name: L2 + Section: .reloc_min + Global: + - Name: _start + Section: .text +... Index: test/ELF/riscv-call.test =================================================================== --- /dev/null +++ test/ELF/riscv-call.test @@ -0,0 +1,95 @@ +# .option norelax +# .global _start +# _start: +# call _start + 4 +# +# .section .reloc_neg, "ax", @progbits +# L1: +# call L1 - 4 +# +# REQUIRES: riscv +# RUN: yaml2obj %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: obj2yaml %t | FileCheck %s +# +# CHECK: - Name: .text +# CHECK: Content: '97000000E7804000' +# +# 11000: 00000097 auipc ra,0x0 +# 11004: 004080e7 jalr 4(ra) +# +# CHECK: - Name: .reloc_neg +# CHECK: Content: 97000000E780C0FF +# +# 11008: 00000097 auipc ra,0x0 +# 1100c: ffc080e7 jalr -4(ra) + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV + Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000002 + Content: '97000000E7800000' + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000000 + Symbol: _start + Type: R_RISCV_CALL + Addend: 4 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + - Name: .reloc_neg + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000001 + Content: '97000000E7800000' + - Name: .rela.reloc_neg + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .reloc_neg + Relocations: + - Offset: 0x0000000000000000 + Symbol: L1 + Type: R_RISCV_CALL + Addend: -4 +Symbols: + Local: + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .data + Type: STT_SECTION + Section: .data + - Name: .bss + Type: STT_SECTION + Section: .bss + - Name: .reloc_neg + Type: STT_SECTION + Section: .reloc_neg + - Name: L1 + Section: .reloc_neg + Global: + - Name: _start + Section: .text +... Index: test/ELF/riscv-hi20-lo12.test =================================================================== --- /dev/null +++ test/ELF/riscv-hi20-lo12.test @@ -0,0 +1,86 @@ +# .option norelax +# .global _start +# +# .section .reloc_12345678, "ax", @progbits +# _start: +# foo = 0x12345678 +# lui a0, %hi(foo) +# addi a0, a0, %lo(foo) +# lw a0, %lo(foo)(a0) +# +# .section .reloc_fedcba98, "ax", @progbits +# foo = 0xfedcba98 +# lui a0, %hi(foo) +# addi a0, a0, %lo(foo) +# +# REQUIRES: riscv +# RUN: yaml2obj %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: obj2yaml %t | FileCheck %s +# +# CHECK: - Name: .reloc_12345678 +# CHECK: Content: '375534121305856703258567' +# 11000: 12345537 lui a0,0x12345 +# 11004: 67850513 addi a0,a0,1656 # 12345678 <__global_pointer$+0x12332e78> +# 11008: 67852503 lw a0,1656(a0) +# +# CHECK: - Name: .reloc_fedcba98 +# CHECK: Content: 37C5DCFE130585A9 +# 1100c: fedcc537 lui a0,0xfedcc +# 11010: a9850513 addi a0,a0,-1384 # fedcba98 <__global_pointer$+0xfedb9298> + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV + Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000002 + Content: '' + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + - Name: .reloc_12345678 + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000001 + Content: '375534121305856703258567' + - Name: .reloc_fedcba98 + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000001 + Content: 37C5DCFE130585A9 +Symbols: + Local: + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .data + Type: STT_SECTION + Section: .data + - Name: .bss + Type: STT_SECTION + Section: .bss + - Name: .reloc_12345678 + Type: STT_SECTION + Section: .reloc_12345678 + - Name: foo + Value: 0x00000000FEDCBA98 + - Name: .reloc_fedcba98 + Type: STT_SECTION + Section: .reloc_fedcba98 + Global: + - Name: _start + Section: .reloc_12345678 +... Index: test/ELF/riscv-jal-error.test =================================================================== --- /dev/null +++ test/ELF/riscv-jal-error.test @@ -0,0 +1,93 @@ +# .option norelax +# .global _start +# +# _start: +# L1: +# jal x0, L1 + 0x100000 +# L2: +# jal x0, L2 - 0x100002 +# L3: +# jal x0, L3 + 1 +# L4: +# c.jal L4 + 1 +# +# REQUIRES: riscv +# RUN: yaml2obj %s -o %t.o +# RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s +# +# CHECK: {{.*}}(.text+0x0): relocation R_RISCV_JAL out of range +# CHECK: {{.*}}(.text+0x4): relocation R_RISCV_JAL out of range +# CHECK: {{.*}}(.text+0x8): improper alignment for relocation R_RISCV_JAL +# CHECK: {{.*}}(.text+0xC): improper alignment for relocation R_RISCV_RVC_JUMP + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV + Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000002 + Content: 6F0000806FF0FF7F6F0000000120 + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000000 + Symbol: L1 + Type: R_RISCV_JAL + Addend: 1048576 + - Offset: 0x0000000000000004 + Symbol: L2 + Type: R_RISCV_JAL + Addend: -1048578 + - Offset: 0x0000000000000008 + Symbol: L3 + Type: R_RISCV_JAL + Addend: 1 + - Offset: 0x000000000000000C + Symbol: L4 + Type: R_RISCV_RVC_JUMP + Addend: 1 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 +Symbols: + Local: + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .data + Type: STT_SECTION + Section: .data + - Name: .bss + Type: STT_SECTION + Section: .bss + - Name: L1 + Section: .text + - Name: L2 + Section: .text + Value: 0x0000000000000004 + - Name: L3 + Section: .text + Value: 0x0000000000000008 + - Name: L4 + Section: .text + Value: 0x000000000000000C + Global: + - Name: _start + Section: .text +... Index: test/ELF/riscv-jal.test =================================================================== --- /dev/null +++ test/ELF/riscv-jal.test @@ -0,0 +1,161 @@ +# .option norelax +# .global _start +# +# .section .reloc_zero, "ax", @progbits +# _start: +# L1: +# jal x0, L1 +# L2: +# c.jal L2 +# +# .section .reloc_max, "ax", @progbits +# L3: +# jal x0, L3 + 0xffffe +# L4: +# c.jal L4 + 0x7fe +# +# .section .reloc_min, "ax", @progbits +# L5: +# jal x0, L5 - 0x100000 +# L6: +# c.jal L6 - 0x800 +# +# REQUIRES: riscv +# RUN: yaml2obj %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: obj2yaml %t | FileCheck %s +# +# CHECK: - Name: .reloc_zero +# CHECK: Content: 6F0000000120 +# 11000: 0000006f j 11000 +# 11004: 2001 jal 11004 +# +# CHECK: - Name: .reloc_max +# CHECK: Content: 6FF0FF7FFD2F +# 11006: 7ffff06f j 111004 +# 1100a: 2ffd jal 11808 +# +# CHECK: - Name: .reloc_min +# CHECK: Content: 6F0000800130 +# 1100c: 8000006f j fff1100c +# 11010: 3001 jal 10810 + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV + Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000002 + Content: '' + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + - Name: .reloc_zero + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000001 + Content: 6F0000000120 + - Name: .rela.reloc_zero + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .reloc_zero + Relocations: + - Offset: 0x0000000000000000 + Symbol: L1 + Type: R_RISCV_JAL + - Offset: 0x0000000000000004 + Symbol: L2 + Type: R_RISCV_RVC_JUMP + - Name: .reloc_max + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000001 + Content: 6FF0FF7FFD2F + - Name: .rela.reloc_max + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .reloc_max + Relocations: + - Offset: 0x0000000000000000 + Symbol: L3 + Type: R_RISCV_JAL + Addend: 1048574 + - Offset: 0x0000000000000004 + Symbol: L4 + Type: R_RISCV_RVC_JUMP + Addend: 2046 + - Name: .reloc_min + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000001 + Content: 6F0000800130 + - Name: .rela.reloc_min + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .reloc_min + Relocations: + - Offset: 0x0000000000000000 + Symbol: L5 + Type: R_RISCV_JAL + Addend: -1048576 + - Offset: 0x0000000000000004 + Symbol: L6 + Type: R_RISCV_RVC_JUMP + Addend: -2048 +Symbols: + Local: + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .data + Type: STT_SECTION + Section: .data + - Name: .bss + Type: STT_SECTION + Section: .bss + - Name: .reloc_zero + Type: STT_SECTION + Section: .reloc_zero + - Name: L1 + Section: .reloc_zero + - Name: L2 + Section: .reloc_zero + Value: 0x0000000000000004 + - Name: .reloc_max + Type: STT_SECTION + Section: .reloc_max + - Name: L3 + Section: .reloc_max + - Name: L4 + Section: .reloc_max + Value: 0x0000000000000004 + - Name: .reloc_min + Type: STT_SECTION + Section: .reloc_min + - Name: L5 + Section: .reloc_min + - Name: L6 + Section: .reloc_min + Value: 0x0000000000000004 + Global: + - Name: _start + Section: .reloc_zero +... Index: test/ELF/riscv-pcrel-hilo.test =================================================================== --- /dev/null +++ test/ELF/riscv-pcrel-hilo.test @@ -0,0 +1,103 @@ +# .option norelax +# .global _start +# +# _start: +# auipc a0, %pcrel_hi(_start + 4) +# addi a0, a0, %pcrel_lo(_start) +# +# .section .reloc_neg, "ax", @progbits +# L1: +# auipc a0, %pcrel_hi(L1 - 2) +# addi a0, a0, %pcrel_lo(L1) +# +# +# REQUIRES: riscv +# RUN: yaml2obj %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: obj2yaml %t | FileCheck %s +# +# CHECK: - Name: .text +# CHECK: Content: '1705000013054500' +# 11000: 00000517 auipc a0,0x0 +# 11004: 00450513 addi a0,a0,4 # 11004 <_start+0x4> +# +# CHECK: - Name: .reloc_neg +# CHECK: Content: 170500001305E5FF +# 11008: 00000517 auipc a0,0x0 +# 1100c: ffe50513 addi a0,a0,-2 # 11006 <_start+0x6> + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV + Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000002 + Content: '1705000013050500' + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000000 + Symbol: _start + Type: R_RISCV_PCREL_HI20 + Addend: 4 + - Offset: 0x0000000000000004 + Symbol: _start + Type: R_RISCV_PCREL_LO12_I + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + - Name: .reloc_neg + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000001 + Content: '1705000013050500' + - Name: .rela.reloc_neg + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .reloc_neg + Relocations: + - Offset: 0x0000000000000000 + Symbol: L1 + Type: R_RISCV_PCREL_HI20 + Addend: -2 + - Offset: 0x0000000000000004 + Symbol: L1 + Type: R_RISCV_PCREL_LO12_I +Symbols: + Local: + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .data + Type: STT_SECTION + Section: .data + - Name: .bss + Type: STT_SECTION + Section: .bss + - Name: .reloc_neg + Type: STT_SECTION + Section: .reloc_neg + - Name: L1 + Section: .reloc_neg + Global: + - Name: _start + Section: .text +... Index: test/lit.cfg.py =================================================================== --- test/lit.cfg.py +++ test/lit.cfg.py @@ -66,6 +66,7 @@ 'AVR': 'avr', 'Mips': 'mips', 'PowerPC': 'ppc', + 'RISCV': 'riscv', 'Sparc': 'sparc', 'X86': 'x86'}) ])