Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -1692,9 +1692,17 @@ addRelIpltSymbols(); // RISC-V's gp can address +/- 2 KiB, set it to .sdata + 0x800 if not defined. - if (Config->EMachine == EM_RISCV) - if (!dyn_cast_or_null(Symtab->find("__global_pointer$"))) - addOptionalRegular("__global_pointer$", findSection(".sdata"), 0x800); + // If .sdata does not exist, give it an arbitrary section number, because the + // PC relative relocation in lla gp, __global_pointer$ cannot reference an + // absolute symbol. + if (Config->EMachine == EM_RISCV) { + Symbol *S = Symtab->find("__global_pointer$"); + OutputSection *Sec = findSection(".sdata"); + if (S && S->isUndefined()) + S->resolve(Defined{/*File=*/nullptr, S->getName(), STB_GLOBAL, STV_HIDDEN, + STT_NOTYPE, /*Value=*/0x800, 0, + Sec ? Sec : Out::ElfHeader}); + } if (Config->EMachine == EM_X86_64) { // On targets that support TLSDESC, _TLS_MODULE_BASE_ is defined in such a Index: test/ELF/riscv-gp.s =================================================================== --- /dev/null +++ test/ELF/riscv-gp.s @@ -0,0 +1,38 @@ +# REQUIRES: riscv +# RUN: llvm-mc -filetype=obj -triple=riscv32 %s -o %t.32.o +# RUN: ld.lld -pie %t.32.o -o %t.32 +# RUN: llvm-readelf -s %t.32 | FileCheck --check-prefix=SYM0 %s + +# RUN: llvm-mc -filetype=obj -triple=riscv64 %s -o %t.64.o +# RUN: ld.lld -shared %t.64.o -o %t.64 +# RUN: llvm-readelf -s %t.64 | FileCheck --check-prefix=SYM0 %s + +## If .sdata doesn't exist, it does not matter what the section index is, +## as long as it is not SHN_ABS, because a PC relative relocation cannot +## reference an absolute symbol. We arbitrarily set it to 1. + +# SYM0: {{0*}}00000800 0 NOTYPE LOCAL HIDDEN 1 __global_pointer$ + +# RUN: echo '.section .sdata,"aw"' > %t.s +# RUN: llvm-mc -filetype=obj -triple=riscv32 %t.s -o %t1.32.o +# RUN: ld.lld -shared %t.32.o %t1.32.o -o %t.32 +# RUN: llvm-readelf -s %t.32 | FileCheck --check-prefix=SYM %s +# RUN: llvm-readelf -S %t.32 | FileCheck --check-prefix=SEC %s +# RUN: llvm-objdump -d --no-show-raw-insn %t.32 | FileCheck --check-prefix=DIS %s + +# RUN: echo '.section .sdata,"aw"' > %t.s +# RUN: llvm-mc -filetype=obj -triple=riscv64 %t.s -o %t1.64.o +# RUN: ld.lld -pie %t.64.o %t1.64.o -o %t.64 +# RUN: llvm-readelf -s %t.64 | FileCheck --check-prefix=SYM %s +# RUN: llvm-readelf -S %t.64 | FileCheck --check-prefix=SEC %s +# RUN: llvm-objdump -d --no-show-raw-insn %t.64 | FileCheck --check-prefix=DIS %s + +## __global_pointer$ = .sdata+0x800 = 0x3800 +# SEC: [ 7] .sdata PROGBITS {{0*}}00003000 +# SYM: {{0*}}00003800 0 NOTYPE LOCAL HIDDEN 7 __global_pointer$ + +## __global_pointer$ - 0x1000 = 4096*3-2048 +# DIS: 1000: auipc gp, 3 +# DIS-NEXT: addi gp, gp, -2048 + +lla gp, __global_pointer$