Index: ELF/Arch/RISCV.cpp =================================================================== --- /dev/null +++ ELF/Arch/RISCV.cpp @@ -0,0 +1,299 @@ +//===- RISCV.cpp ----------------------------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Error.h" +#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 "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Statistic.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 lld { +namespace elf { + +template +class RISCV final : public TargetInfo { +public: + RISCV() {} + RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, + const uint8_t *Loc) const override; + void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; +}; + +// RISC-V instructions are stored as 16-bit parcels starting with lower bits; +// each parcel is stored according to implementation's endianness. +template +static void writeInsn32(uint8_t* const Buf, const uint32_t Insn) { + write16(Buf, Insn & 0xFFFF); + write16(Buf + 2, Insn >> 16); +} + +template +static uint32_t readInsn32(const uint8_t* const Buf) { + return read16(Buf) | static_cast(read16(Buf + 2)) << 16; +} + +template +RelExpr RISCV::getRelExpr(const uint32_t 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; + } +} + +// FIXME: Is this defined somewhere in llvm that we can use? +uint32_t bitsExtraction(const uint64_t V, const uint32_t Begin, + const uint32_t End, const uint32_t LShift) { + return ((V >> End) & ((0xFFFFFFFF) >> (32 - (Begin - End + 1)))) << LShift; +} + +// Reference: +// https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md +template +void RISCV::relocateOne(uint8_t *Loc, const uint32_t Type, + const uint64_t Val) const { + constexpr endianness E = ELFT::TargetEndianness; + + switch (Type) { + case R_RISCV_32: + write32(Loc, Val); + return; + case R_RISCV_64: + write64(Loc, Val); + return; + + case R_RISCV_RVC_BRANCH: { + checkInt<8>(Loc, static_cast(Val) >> 1, Type); + checkAlignment<2>(Loc, Val, Type); + const uint16_t Inst = read16(Loc) & 0xE383; + const uint16_t Imm8 = bitsExtraction(Val, 8, 8, 12); + const uint16_t Imm4_3 = bitsExtraction(Val, 4, 3, 10); + const uint16_t Imm7_6 = bitsExtraction(Val, 7, 6, 5); + const uint16_t Imm2_1 = bitsExtraction(Val, 2, 1, 3); + const uint16_t Imm5 = bitsExtraction(Val, 5, 5, 2); + write16(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); + const uint16_t Inst = read16(Loc) & 0xE003; + const uint16_t Imm11 = bitsExtraction(Val, 11, 11, 12); + const uint16_t Imm4 = bitsExtraction(Val, 4, 4, 11); + const uint16_t Imm9_8 = bitsExtraction(Val, 9, 8, 9); + const uint16_t Imm10 = bitsExtraction(Val, 10, 10, 8); + const uint16_t Imm6 = bitsExtraction(Val, 6, 6, 7); + const uint16_t Imm7 = bitsExtraction(Val, 7, 7, 6);; + const uint16_t Imm3_1 = bitsExtraction(Val, 3, 1, 3); + const uint16_t Imm5 = bitsExtraction(Val, 5, 5, 2); + write16(Loc, + Inst | Imm11 | Imm4 | Imm9_8 | Imm10 | Imm6 | Imm7 | Imm3_1 | Imm5); + return; + } + + case R_RISCV_RVC_LUI: { + const 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` + write16(Loc, (read16(Loc) & 0x0F83) | 0x4000); + } else { + const uint16_t Imm17 = bitsExtraction(Val + 0x800, 17, 17, 12); + const uint16_t Imm16_12 = bitsExtraction(Val + 0x800, 16, 12, 2); + write16(Loc, (read16(Loc) & 0xEF83) | Imm17 | Imm16_12); + } + return; + } + + case R_RISCV_JAL: { + checkInt<20>(Loc, static_cast(Val) >> 1, Type); + checkAlignment<2>(Loc, Val, Type); + + const uint32_t Inst = readInsn32(Loc) & 0xFFF; + const uint32_t Imm20 = bitsExtraction(Val, 20, 20, 31); + const uint32_t Imm10_1 = bitsExtraction(Val, 10, 1, 21); + const uint32_t Imm11 = bitsExtraction(Val, 11, 11, 20); + const uint32_t Imm19_12 = bitsExtraction(Val, 19, 12, 12); + const 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); + + const uint32_t Inst = readInsn32(Loc) & 0x1FFF07F; + const uint32_t Imm12 = bitsExtraction(Val, 12, 12, 31); + const uint32_t Imm10_5 = bitsExtraction(Val, 10, 5, 25); + const uint32_t Imm4_1 = bitsExtraction(Val, 4, 1, 8); + const uint32_t Imm11 = bitsExtraction(Val, 11, 11, 7); + const 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, static_cast(Val), Type); + const uint32_t Hi = Val + 0x800; + const 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, static_cast(Val), Type); + const 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, static_cast(Val), Type); + const uint32_t Hi = Val + 0x800; + const 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, static_cast(Val), Type); + const uint32_t Hi = Val + 0x800; + const uint32_t Lo = Val - (Hi & 0xFFFFF000); + const uint32_t Imm11_5 = bitsExtraction(Lo, 11, 5, 25); + const uint32_t Imm4_0 = bitsExtraction(Lo, 4, 0, 7); + writeInsn32(Loc, (readInsn32(Loc) & 0x1FFF07F) | Imm11_5 | Imm4_0); + return; + } + + case R_RISCV_ADD8: + *Loc = *Loc + Val; + return; + case R_RISCV_ADD16: + write16(Loc, read16(Loc) + Val); + return; + case R_RISCV_ADD32: + write32(Loc, read32(Loc) + Val); + return; + case R_RISCV_ADD64: + write64(Loc, read64(Loc) + Val); + return; + case R_RISCV_SUB6: + *Loc = (*Loc & 0xc0) | (((*Loc & 0x3f) - Val) & 0x3f); + return; + case R_RISCV_SUB8: + *Loc = *Loc - Val; + return; + case R_RISCV_SUB16: + write16(Loc, read16(Loc) - Val); + return; + case R_RISCV_SUB32: + write32(Loc, read32(Loc) - Val); + return; + case R_RISCV_SUB64: + write64(Loc, read64(Loc) - Val); + return; + case R_RISCV_SET6: + *Loc = (*Loc & 0xc0) | (Val & 0x3f); + return; + case R_RISCV_SET8: + *Loc = Val; + return; + case R_RISCV_SET16: + write16(Loc, Val); + return; + case R_RISCV_SET32: + case R_RISCV_32_PCREL: + write32(Loc, Val); + return; + + // These are handled by the dynamic linker + case R_RISCV_RELATIVE: + case R_RISCV_COPY: + case R_RISCV_JUMP_SLOT: + goto unimp; + + // 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: + goto unimp; + + case R_RISCV_ALIGN: + case R_RISCV_RELAX: + return; // Ignored (for now) + case R_RISCV_NONE: + return; // Do nothing +unimp: + default: + error(getErrorLocation(Loc) + + "unimplemented relocation type: " + Twine(Type)); + return; + } +} + +template TargetInfo *getRISCVTargetInfo() { + static RISCV Target; + return &Target; +} + +template RISCV::RISCV(); +template RISCV::RISCV(); +template RISCV::RISCV(); +template RISCV::RISCV(); + +template TargetInfo *getRISCVTargetInfo(); +template TargetInfo *getRISCVTargetInfo(); +template TargetInfo *getRISCVTargetInfo(); +template TargetInfo *getRISCVTargetInfo(); + +} // namespace elf +} // namespace lld 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 @@ -128,6 +128,8 @@ .Cases("elf_amd64", "elf_x86_64", {ELF64LEKind, EM_X86_64}) .Case("elf_i386", {ELF32LEKind, EM_386}) .Case("elf_iamcu", {ELF32LEKind, EM_IAMCU}) + .Case("elf32lriscv", {ELF32LEKind, EM_RISCV}) + .Case("elf64lriscv", {ELF64LEKind, EM_RISCV}) .Default({ELFNoneKind, EM_NONE}); if (Ret.first == ELFNoneKind) @@ -828,7 +830,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 @@ -566,6 +566,26 @@ Dest = getAArch64Page(Body.getVA(A)); return Dest - getAArch64Page(P); } + // 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. + case R_RISCV_PC_INDIRECT: { + const uint64_t Label = Body.getVA(); + const InputSection* IS = + cast(cast(Body).Section); + for (const Relocation& HiRel: IS->Relocations) { + const uint64_t HiOffset = IS->getOffset(HiRel.Offset); + const 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 @@ -349,6 +349,8 @@ static DefinedRegular *MipsGp; static DefinedRegular *MipsGpDisp; static DefinedRegular *MipsLocalGp; + + 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 @@ -128,6 +128,7 @@ TargetInfo *getX86TargetInfo(); TargetInfo *getX86_64TargetInfo(); template TargetInfo *getMipsTargetInfo(); +template TargetInfo *getRISCVTargetInfo(); std::string getErrorLocation(const uint8_t *Loc); Index: ELF/Target.cpp =================================================================== --- ELF/Target.cpp +++ ELF/Target.cpp @@ -77,6 +77,19 @@ return getPPCTargetInfo(); case EM_PPC64: return getPPC64TargetInfo(); + case EM_RISCV: + switch (Config->EKind) { + case ELF32LEKind: + return getRISCVTargetInfo(); + case ELF32BEKind: + return getRISCVTargetInfo(); + case ELF64LEKind: + return getRISCVTargetInfo(); + case ELF64BEKind: + return getRISCVTargetInfo(); + default: + fatal("unsupported RISC-V target"); + } case EM_SPARCV9: return getSPARCV9TargetInfo(); case EM_X86_64: Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -780,6 +780,10 @@ Symtab->addAbsolute("__gnu_local_gp", STV_HIDDEN, STB_LOCAL); } + 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 @@ -945,6 +949,15 @@ } } } + + // 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'}) ])