Index: ELF/Arch/RISCV.cpp =================================================================== --- ELF/Arch/RISCV.cpp +++ ELF/Arch/RISCV.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "Bits.h" #include "InputFiles.h" #include "InputSection.h" #include "Memory.h" @@ -39,9 +40,21 @@ template class RISCV final : public TargetInfo { public: + RISCV(); RelExpr getRelExpr(RelType Type, const SymbolBody &S, const uint8_t *Loc) const override; void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; + + virtual void writeGotPltHeader(uint8_t *Buf) const override; + virtual void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override; + + virtual void writePltHeader(uint8_t *Buf) const override; + + virtual void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, + uint64_t PltEntryAddr, int32_t Index, + unsigned RelOff) const override; + + virtual bool usesOnlyLowPageBits(uint32_t Type) const override; }; } // end anonymous namespace @@ -58,6 +71,89 @@ return read16(Buf) | static_cast(read16(Buf + 2)) << 16; } +template RISCV::RISCV() { + CopyRel = R_RISCV_COPY; + RelativeRel = R_RISCV_RELATIVE; + GotRel = ELFT::Is64Bits ? R_RISCV_64 : R_RISCV_32; + PltRel = R_RISCV_JUMP_SLOT; + GotEntrySize = Config->Wordsize; + GotPltEntrySize = Config->Wordsize; + PltEntrySize = 16; + PltHeaderSize = 32; + GotPltHeaderEntriesNum = 2; +} + +template +bool RISCV::usesOnlyLowPageBits(uint32_t Type) const { + return Type == R_RISCV_LO12_I || Type == R_RISCV_PCREL_LO12_I || + Type == R_RISCV_LO12_S || Type == R_RISCV_PCREL_LO12_S || + // These are used in a pair to calculate relative address in debug + // sections, so they aren't really absolute. We list those here as a + // hack so the linker doesn't try to create dynamic relocations. + Type == R_RISCV_ADD8 || Type == R_RISCV_ADD16 || + Type == R_RISCV_ADD32 || Type == R_RISCV_ADD64 || + Type == R_RISCV_SUB8 || Type == R_RISCV_SUB16 || + Type == R_RISCV_SUB32 || Type == R_RISCV_SUB64 || + Type == R_RISCV_SUB6 || + Type == R_RISCV_SET6 || Type == R_RISCV_SET8 || + Type == R_RISCV_SET16 || Type == R_RISCV_SET32; +} + +template void RISCV::writeGotPltHeader(uint8_t *Buf) const { + writeUint(Buf, -1); + writeUint(Buf + GotPltEntrySize, 0); +} + +template +void RISCV::writeGotPlt(uint8_t *Buf, const SymbolBody &S) const { + writeUint(Buf, InX::Plt->getVA()); +} + +template void RISCV::writePltHeader(uint8_t *Buf) const { + constexpr endianness E = ELFT::TargetEndianness; + const uint64_t PcRelGotPlt = InX::GotPlt->getVA() - InX::Plt->getVA(); + + writeInsn32(Buf + 0, 0x00000397); // 1: auipc t2, %pcrel_hi(.got.plt) + relocateOne(Buf + 0, R_RISCV_PCREL_HI20, PcRelGotPlt); + writeInsn32(Buf + 4, 0x41c30333); // sub t1, t1, t3 + if (ELFT::Is64Bits) { + writeInsn32(Buf + 8, 0x0003be03); // ld t3, %pcrel_lo(1b)(t2) + } else { + writeInsn32(Buf + 8, 0x0003ae03); // lw t3, %pcrel_lo(1b)(t2) + } + relocateOne(Buf + 8, R_RISCV_PCREL_LO12_I, PcRelGotPlt); + writeInsn32(Buf + 12, 0xfd430313); // addi t1, t1, -44 + writeInsn32(Buf + 16, 0x00038293); // addi t0, t2, %pcrel_lo(1b) + relocateOne(Buf + 16, R_RISCV_PCREL_LO12_I, PcRelGotPlt); + if (ELFT::Is64Bits) { + writeInsn32(Buf + 20, 0x00135313); // srli t1, t1, 1 + writeInsn32(Buf + 24, 0x0082b283); // ld t0, 8(t0) + } else { + writeInsn32(Buf + 20, 0x00235313); // srli t1, t1, 2 + writeInsn32(Buf + 24, 0x0042a283); // lw t0, 4(t0) + } + writeInsn32(Buf + 28, 0x000e0067); // jr t3 +} + +template +void RISCV::writePlt(uint8_t *Buf, uint64_t GotEntryAddr, + uint64_t PltEntryAddr, int32_t Index, + unsigned RelOff) const { + constexpr endianness E = ELFT::TargetEndianness; + + writeInsn32(Buf + 0, 0x00000e17); // auipc t3, %pcrel_hi(f@.got.plt) + if (ELFT::Is64Bits) { + writeInsn32(Buf + 4, 0x000e3e03); // ld t3, %pcrel_lo(-4)(t3) + } else { + writeInsn32(Buf + 4, 0x000e2e03); // lw t3, %pcrel_lo(-4)(t3) + } + writeInsn32(Buf + 8, 0x000e0367); // jalr t1, t3 + writeInsn32(Buf + 12, 0x00000013); // nop + + relocateOne(Buf + 0, R_RISCV_PCREL_HI20, GotEntryAddr - PltEntryAddr); + relocateOne(Buf + 4, R_RISCV_PCREL_LO12_I, GotEntryAddr - PltEntryAddr); +} + template RelExpr RISCV::getRelExpr(const RelType Type, const SymbolBody &S, const uint8_t *Loc) const { @@ -70,11 +166,15 @@ case R_RISCV_RVC_JUMP: case R_RISCV_32_PCREL: return R_PC; + case R_RISCV_CALL_PLT: + return R_PLT_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_GOT_HI20: + return R_GOT_PC; case R_RISCV_ALIGN: + case R_RISCV_RELAX: return R_HINT; default: return R_ABS; @@ -174,6 +274,7 @@ return; } // auipc + jalr pair + case R_RISCV_CALL_PLT: case R_RISCV_CALL: { checkInt<32>(Loc, Val, Type); uint32_t Hi = Val + 0x800; @@ -185,6 +286,7 @@ } case R_RISCV_PCREL_HI20: + case R_RISCV_GOT_HI20: case R_RISCV_HI20: { checkInt<32>(Loc, Val, Type); uint32_t Hi = Val + 0x800; Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -575,7 +575,8 @@ 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)) { + if (Label == HiAddrLoc && + isRelExprOneOf(HiRel.Expr)) { return getRelocTargetVA(HiRel.Type, HiRel.Addend, HiAddrLoc, *HiRel.Sym, HiRel.Expr); } Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -356,7 +356,7 @@ // file (PC, or GOT for example). static bool isRelExpr(RelExpr Expr) { return isRelExprOneOf(Expr); + R_PAGE_PC, R_RELAX_GOT_PC, R_RISCV_PC_INDIRECT>(Expr); } // Returns true if a given relocation can be computed at link-time. @@ -413,6 +413,11 @@ if (Body.isUndefWeak()) return true; + // __global_pointer$ is defined as absolute but will be set to .sdata + 0x800 + // by Writer during finalization, so we white-list it here. + if (Config->Pie && &Body == ElfSym::RISCVGlobalPointer) + return true; + error("relocation " + toString(Type) + " cannot refer to absolute symbol: " + toString(Body) + getLocation(S, Body, RelOff)); return true; Index: test/ELF/Inputs/riscv-shared.yaml =================================================================== --- /dev/null +++ test/ELF/Inputs/riscv-shared.yaml @@ -0,0 +1,42 @@ +--- !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: 2A000000 + - 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 + Global: + - Name: f + Type: STT_FUNC + Section: .text + - Name: x + Type: STT_OBJECT + Section: .data + Size: 0x0000000000000004 +... Index: test/ELF/riscv-copy.test =================================================================== --- /dev/null +++ test/ELF/riscv-copy.test @@ -0,0 +1,78 @@ +# .option norelax +# .global _start +# +# .section .text, "ax", @progbits +# _start: +# la a0, x +# +# REQUIRES: riscv +# RUN: yaml2obj %s -o %t.o +# RUN: yaml2obj %p/Inputs/riscv-shared.yaml -o %t2.o +# RUN: ld.lld -shared %t2.o -o %t3.so +# RUN: ld.lld %t.o %t3.so -o %t -Tbss=0x13000 -Ttext=0x10000 +# RUN: llvm-readelf -r %t | FileCheck -check-prefix=READELF %s +# RUN: obj2yaml %t | FileCheck %s +# +# READELF: Relocation section '.rela.dyn' +# READELF: 00013000 00000104 R_RISCV_COPY 00013000 x + 0 +# +# CHECK: - Name: .text +# CHECK: Content: '1735000013050500' +# CHECK: - Name: .bss +# +# 10000: 00003517 auipc a0,0x3 +# 10004: 00050513 mv a0,a0 + +--- !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: x + Type: R_RISCV_PCREL_HI20 + - Offset: 0x0000000000000004 + Symbol: '.L0 ' + 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 +Symbols: + Local: + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .data + Type: STT_SECTION + Section: .data + - Name: .bss + Type: STT_SECTION + Section: .bss + - Name: '.L0 ' + Section: .text + Global: + - Name: _start + Section: .text + - Name: x +... Index: test/ELF/riscv-fpic-got.test =================================================================== --- /dev/null +++ test/ELF/riscv-fpic-got.test @@ -0,0 +1,80 @@ +# .option norelax +# .option pic +# .global _start +# +# .section .text, "ax", @progbits +# _start: +# la a0, x +# +# REQUIRES: riscv +# RUN: yaml2obj %s -o %t.o +# RUN: yaml2obj %p/Inputs/riscv-shared.yaml -o %t2.o +# RUN: ld.lld -shared %t2.o -o %t3.so +# RUN: ld.lld %t.o %t3.so -o %t --section-start .got=0x20000 --section-start .text=0x10000 +# RUN: llvm-readelf -r %t | FileCheck -check-prefix=READELF %s +# RUN: obj2yaml %t | FileCheck %s +# +# READELF: Relocation section '.rela.dyn' +# READELF: 00020000 00000101 R_RISCV_32 00000000 x + 0 +# +# CHECK: - Name: .text +# CHECK: Content: '1705010003250500' +# +# 10000: 00010517 auipc a0,0x10 +# 10004: 00052503 lw a0,0(a0) # 20000 <_start+0x10000> +# +# CHECK: - Name: .got + +--- !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: '1705000003250500' + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000000 + Symbol: x + Type: R_RISCV_GOT_HI20 + - Offset: 0x0000000000000004 + Symbol: '.L0 ' + 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 +Symbols: + Local: + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .data + Type: STT_SECTION + Section: .data + - Name: .bss + Type: STT_SECTION + Section: .bss + - Name: '.L0 ' + Section: .text + Global: + - Name: _start + Section: .text + - Name: x +... Index: test/ELF/riscv-fpic-pie.test =================================================================== --- /dev/null +++ test/ELF/riscv-fpic-pie.test @@ -0,0 +1,77 @@ +# .option norelax +# .option pic +# .global _start +# +# .section .text, "ax", @progbits +# _start: +# la a0, _start +# +# REQUIRES: riscv +# RUN: yaml2obj %s -o %t.o +# RUN: ld.lld %t.o -o %t -pie --section-start .got=0x20000 --section-start .text=0x10000 +# RUN: llvm-readelf -r %t | FileCheck -check-prefix=READELF %s +# RUN: obj2yaml %t | FileCheck %s +# +# READELF: Relocation section '.rela.dyn' +# READELF: 00020000 00000003 R_RISCV_RELATIVE 10000 +# +# CHECK: - Name: .text +# CHECK: Content: '1705010003250500' +# +# 10000: 00010517 auipc a0,0x10 +# 10004: 00052503 lw a0,0(a0) # 20000 <_start+0x10000> +# +# CHECK: - Name: .got + +--- !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: '1705000003250500' + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000000 + Symbol: _start + Type: R_RISCV_GOT_HI20 + - Offset: 0x0000000000000004 + Symbol: '.L0 ' + 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 +Symbols: + Local: + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .data + Type: STT_SECTION + Section: .data + - Name: .bss + Type: STT_SECTION + Section: .bss + - Name: '.L0 ' + Section: .text + Global: + - Name: _start + Section: .text +... Index: test/ELF/riscv-fpic-plt.test =================================================================== --- /dev/null +++ test/ELF/riscv-fpic-plt.test @@ -0,0 +1,86 @@ +# .option norelax +# .option pic +# .global _start +# +# .section .text, "ax", @progbits +# _start: +# call f@plt +# +# REQUIRES: riscv +# RUN: yaml2obj %s -o %t.o +# RUN: yaml2obj %p/Inputs/riscv-shared.yaml -o %t2.o +# RUN: ld.lld -shared %t2.o -o %t3.so +# RUN: ld.lld %t.o %t3.so -o %t --section-start .text=0x10000 --section-start .got.plt=0x20000 --section-start .plt=0x21000 +# RUN: llvm-readelf -r %t | FileCheck -check-prefix=READELF %s +# RUN: obj2yaml %t | FileCheck %s +# +# READELF: Relocation section '.rela.plt' +# READELF: 00020008 00000105 R_RISCV_JUMP_SLOT 00000000 f + 0 +# +# CHECK: - Name: .text +# CHECK: Content: '97100100E7800002' +# 10000: 00011097 auipc ra,0x11 +# 10004: 020080e7 jalr 32(ra) # 21020 +# +# CHECK: - Name: .got.plt +# CHECK: Content: FFFFFFFF0000000000100200 +# +# CHECK: - Name: .plt +# CHECK: Content: 97F3FFFF3303C34103AE0300130343FD938203001353230083A2420067000E0017FEFFFF032E8EFE67030E0013000000 +# 21000: fffff397 auipc t2,0xfffff +# 21004: 41c30333 sub t1,t1,t3 +# 21008: 0003ae03 lw t3,0(t2) # 20000 <_start+0x10000> +# 2100c: fd430313 addi t1,t1,-44 +# 21010: 00038293 mv t0,t2 +# 21014: 00235313 srli t1,t1,0x2 +# 21018: 0042a283 lw t0,4(t0) +# 2101c: 000e0067 jr t3 + +--- !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: f + Type: R_RISCV_CALL_PLT + - 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 + Global: + - Name: _start + Section: .text + - Name: f +...