Index: ELF/Arch/RISCV.cpp =================================================================== --- ELF/Arch/RISCV.cpp +++ ELF/Arch/RISCV.cpp @@ -7,7 +7,10 @@ // //===----------------------------------------------------------------------===// +#include "Bits.h" #include "InputFiles.h" +#include "Symbols.h" +#include "SyntheticSections.h" #include "Target.h" using namespace llvm; @@ -26,11 +29,35 @@ RelExpr getRelExpr(RelType Type, const Symbol &S, const uint8_t *Loc) const override; void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; + + void writeGotPltHeader(uint8_t *Buf) const override; + void writeGotHeader(uint8_t *Buf) const override; + void writeGotPlt(uint8_t *Buf, const Symbol &S) const override; + + void writePltHeader(uint8_t *Buf) const override; + + void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr, + int32_t Index, unsigned RelOff) const override; + + bool usesOnlyLowPageBits(RelType Type) const override; }; } // end anonymous namespace -RISCV::RISCV() { NoneRel = R_RISCV_NONE; } +RISCV::RISCV() { + NoneRel = R_RISCV_NONE; + CopyRel = R_RISCV_COPY; + RelativeRel = R_RISCV_RELATIVE; + GotRel = Config->Is64 ? R_RISCV_64 : R_RISCV_32; + PltRel = R_RISCV_JUMP_SLOT; + GotEntrySize = Config->Wordsize; + GotPltEntrySize = Config->Wordsize; + PltEntrySize = 16; + PltHeaderSize = 32; + GotHeaderEntriesNum = 1; + GotPltHeaderEntriesNum = 2; + GotBaseSymInGotPlt = false; +} static uint32_t getEFlags(InputFile *F) { if (Config->Is64) @@ -60,6 +87,85 @@ return Target; } +bool RISCV::usesOnlyLowPageBits(RelType 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; +} + +void RISCV::writeGotPltHeader(uint8_t *Buf) const { + // These entries are used by the plt header and will be filled by the dynamic + // linker. Write placeholder values as same as ld.bfd. + writeUint(Buf, -1); // _dl_runtime_resolve + writeUint(Buf + GotPltEntrySize, 0); // link_map +} + +void RISCV::writeGotHeader(uint8_t *Buf) const { + // _GLOBAL_OFFSET_TABLE_ points to the start of .got section which contains + // the address of .dynamic section. + if (ElfSym::GlobalOffsetTable) + writeUint(Buf, In.Dynamic->getVA()); +} + +void RISCV::writeGotPlt(uint8_t *Buf, const Symbol &S) const { + writeUint(Buf, In.Plt->getVA()); +} + +void RISCV::writePltHeader(uint8_t *Buf) const { + if (Config->EFlags & EF_RISCV_RVE) + fatal("PLT is not supported with RVE ABI"); + + uint64_t PcRelGotPlt = In.GotPlt->getVA() - In.Plt->getVA(); + + write32le(Buf + 0, 0x00000397); // 1: auipc t2, %pcrel_hi(.got.plt) + relocateOne(Buf + 0, R_RISCV_PCREL_HI20, PcRelGotPlt); + write32le(Buf + 4, 0x41c30333); // sub t1, t1, t3 + if (Config->Is64) { + write32le(Buf + 8, 0x0003be03); // ld t3, %pcrel_lo(1b)(t2) + } else { + write32le(Buf + 8, 0x0003ae03); // lw t3, %pcrel_lo(1b)(t2) + } + relocateOne(Buf + 8, R_RISCV_PCREL_LO12_I, PcRelGotPlt); + write32le(Buf + 12, 0xfd430313); // addi t1, t1, -44 + write32le(Buf + 16, 0x00038293); // addi t0, t2, %pcrel_lo(1b) + relocateOne(Buf + 16, R_RISCV_PCREL_LO12_I, PcRelGotPlt); + if (Config->Is64) { + write32le(Buf + 20, 0x00135313); // srli t1, t1, 1 + write32le(Buf + 24, 0x0082b283); // ld t0, 8(t0) + } else { + write32le(Buf + 20, 0x00235313); // srli t1, t1, 2 + write32le(Buf + 24, 0x0042a283); // lw t0, 4(t0) + } + write32le(Buf + 28, 0x000e0067); // jr t3 +} + +void RISCV::writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr, + int32_t Index, unsigned RelOff) const { + if (Config->EFlags & EF_RISCV_RVE) + fatal("PLT is not supported with RVE ABI"); + + write32le(Buf + 0, 0x00000e17); // auipc t3, %pcrel_hi(f@.got.plt) + if (Config->Is64) { + write32le(Buf + 4, 0x000e3e03); // ld t3, %pcrel_lo(-4)(t3) + } else { + write32le(Buf + 4, 0x000e2e03); // lw t3, %pcrel_lo(-4)(t3) + } + write32le(Buf + 8, 0x000e0367); // jalr t1, t3 + write32le(Buf + 12, 0x00000013); // nop + + relocateOne(Buf + 0, R_RISCV_PCREL_HI20, GotEntryAddr - PltEntryAddr); + relocateOne(Buf + 4, R_RISCV_PCREL_LO12_I, GotEntryAddr - PltEntryAddr); +} + RelExpr RISCV::getRelExpr(const RelType Type, const Symbol &S, const uint8_t *Loc) const { switch (Type) { @@ -71,11 +177,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 +284,7 @@ } // auipc + jalr pair + case R_RISCV_CALL_PLT: case R_RISCV_CALL: { checkInt(Loc, Val, 32, Type); if (isInt<32>(Val)) { @@ -184,6 +295,7 @@ } case R_RISCV_PCREL_HI20: + case R_RISCV_GOT_HI20: case R_RISCV_HI20: { checkInt(Loc, Val, 32, Type); uint32_t Hi = Val + 0x800; Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -558,7 +558,7 @@ auto Range = std::equal_range(IS->Relocations.begin(), IS->Relocations.end(), D->Value, RelocationOffsetComparator{}); for (auto It = std::get<0>(Range); It != std::get<1>(Range); ++It) - if (isRelExprOneOf(It->Expr)) + if (isRelExprOneOf(It->Expr)) return &*It; error("R_RISCV_PCREL_LO12 relocation points to " + IS->getObjMsg(D->Value) + Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -341,7 +341,7 @@ static bool isRelExpr(RelExpr Expr) { return isRelExprOneOf(Expr); + R_RELAX_GOT_PC, R_RISCV_PC_INDIRECT>(Expr); } // Returns true if a given relocation can be computed at link-time. 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 -z norelro +# 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 -z norelro +# 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 -z norelro +# 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 +...