[lld] r363351 - [ELF][RISCV] Create dummy .sdata for __global_pointer$ if .sdata does not exist

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 13 19:14:54 PDT 2019


Author: maskray
Date: Thu Jun 13 19:14:53 2019
New Revision: 363351

URL: http://llvm.org/viewvc/llvm-project?rev=363351&view=rev
Log:
[ELF][RISCV] Create dummy .sdata for __global_pointer$ if .sdata does not exist

If .sdata is absent, linker synthesized __global_pointer$ gets a section index of SHN_ABS.
(ld.bfd has a similar issue: binutils PR24678)

Scrt1.o may use `lla gp, __global_pointer$` to reference the symbol PC
relatively. In -pie/-shared mode, lld complains if a PC relative
relocation references an absolute symbol (SHN_ABS) but ld.bfd doesn't:

    ld.lld: error: relocation R_RISCV_PCREL_HI20 cannot refer to lute symbol: __global_pointer$

Let the reference of __global_pointer$ to force creation of .sdata to
fix the problem. This is similar to _GLOBAL_OFFSET_TABLE_, which forces
creation of .got or .got.plt .

Also, change the visibility from STV_HIDDEN to STV_DEFAULT and don't
define the symbol for -shared. This matches ld.bfd, though I don't
understand why it uses STV_DEFAULT.

Reviewed By: ruiu, jrtc27

Differential Revision: https://reviews.llvm.org/D63132

Added:
    lld/trunk/test/ELF/riscv-gp-dummy-sdata.s
    lld/trunk/test/ELF/riscv-gp.s
Modified:
    lld/trunk/ELF/Symbols.cpp
    lld/trunk/ELF/Symbols.h
    lld/trunk/ELF/SyntheticSections.cpp
    lld/trunk/ELF/SyntheticSections.h
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=363351&r1=363350&r2=363351&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Thu Jun 13 19:14:53 2019
@@ -39,6 +39,7 @@ Defined *ElfSym::MipsGpDisp;
 Defined *ElfSym::MipsLocalGp;
 Defined *ElfSym::RelaIpltStart;
 Defined *ElfSym::RelaIpltEnd;
+Defined *ElfSym::RISCVGlobalPointer;
 Defined *ElfSym::TlsModuleBase;
 
 static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) {

Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=363351&r1=363350&r2=363351&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Thu Jun 13 19:14:53 2019
@@ -437,6 +437,9 @@ struct ElfSym {
   static Defined *RelaIpltStart;
   static Defined *RelaIpltEnd;
 
+  // __global_pointer$ for RISC-V.
+  static Defined *RISCVGlobalPointer;
+
   // _TLS_MODULE_BASE_ on targets that support TLSDESC.
   static Defined *TlsModuleBase;
 };

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=363351&r1=363350&r2=363351&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Thu Jun 13 19:14:53 2019
@@ -3386,6 +3386,23 @@ bool PPC64LongBranchTargetSection::isNee
   return !Finalized || !Entries.empty();
 }
 
+RISCVSdataSection::RISCVSdataSection()
+    : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, 1, ".sdata") {}
+
+bool RISCVSdataSection::isNeeded() const {
+  if (!ElfSym::RISCVGlobalPointer)
+    return false;
+
+  // __global_pointer$ is defined relative to .sdata . If the section does not
+  // exist, create a dummy one.
+  for (BaseCommand *Base : getParent()->SectionCommands)
+    if (auto *ISD = dyn_cast<InputSectionDescription>(Base))
+      for (InputSection *IS : ISD->Sections)
+        if (IS != this)
+          return false;
+  return true;
+}
+
 static uint8_t getAbiVersion() {
   // MIPS non-PIC executable gets ABI version 1.
   if (Config->EMachine == EM_MIPS) {

Modified: lld/trunk/ELF/SyntheticSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.h?rev=363351&r1=363350&r2=363351&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.h (original)
+++ lld/trunk/ELF/SyntheticSections.h Thu Jun 13 19:14:53 2019
@@ -1098,6 +1098,15 @@ public:
   void writeTo(uint8_t *Buf) override;
 };
 
+// Create a dummy .sdata for __global_pointer$ if .sdata does not exist.
+class RISCVSdataSection final : public SyntheticSection {
+public:
+  RISCVSdataSection();
+  size_t getSize() const override { return 0; }
+  bool isNeeded() const override;
+  void writeTo(uint8_t *Buf) override {}
+};
+
 InputSection *createInterpSection();
 MergeInputSection *createCommentSection();
 template <class ELFT> void splitSections();
@@ -1162,6 +1171,7 @@ struct InStruct {
   PltSection *Plt;
   PltSection *Iplt;
   PPC32Got2Section *PPC32Got2;
+  RISCVSdataSection *RISCVSdata;
   RelocationBaseSection *RelaPlt;
   RelocationBaseSection *RelaIplt;
   StringTableSection *ShStrTab;

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=363351&r1=363350&r2=363351&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Thu Jun 13 19:14:53 2019
@@ -476,6 +476,11 @@ template <class ELFT> static void create
     Add(In.PPC64LongBranchTarget);
   }
 
+  if (Config->EMachine == EM_RISCV) {
+    In.RISCVSdata = make<RISCVSdataSection>();
+    Add(In.RISCVSdata);
+  }
+
   In.GotPlt = make<GotPltSection>();
   Add(In.GotPlt);
   In.IgotPlt = make<IgotPltSection>();
@@ -1692,9 +1697,11 @@ template <class ELFT> void Writer<ELFT>:
   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<Defined>(Symtab->find("__global_pointer$")))
-      addOptionalRegular("__global_pointer$", findSection(".sdata"), 0x800);
+  // This symbol should only be defined in an executable.
+  if (Config->EMachine == EM_RISCV && !Config->Shared)
+    ElfSym::RISCVGlobalPointer =
+        addOptionalRegular("__global_pointer$", findSection(".sdata"), 0x800,
+                           STV_DEFAULT, STB_GLOBAL);
 
   if (Config->EMachine == EM_X86_64) {
     // On targets that support TLSDESC, _TLS_MODULE_BASE_ is defined in such a
@@ -1871,6 +1878,7 @@ template <class ELFT> void Writer<ELFT>:
   finalizeSynthetic(In.Plt);
   finalizeSynthetic(In.Iplt);
   finalizeSynthetic(In.PPC32Got2);
+  finalizeSynthetic(In.RISCVSdata);
   finalizeSynthetic(In.PartIndex);
 
   // Dynamic section must be the last one in this list and dynamic

Added: lld/trunk/test/ELF/riscv-gp-dummy-sdata.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/riscv-gp-dummy-sdata.s?rev=363351&view=auto
==============================================================================
--- lld/trunk/test/ELF/riscv-gp-dummy-sdata.s (added)
+++ lld/trunk/test/ELF/riscv-gp-dummy-sdata.s Thu Jun 13 19:14:53 2019
@@ -0,0 +1,25 @@
+# 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=SEC %s
+# RUN: llvm-readelf -s %t.32 | FileCheck --check-prefix=SYM %s
+
+# RUN: llvm-mc -filetype=obj -triple=riscv64 %s -o %t.64.o
+# RUN: ld.lld -pie %t.64.o -o %t.64
+# RUN: llvm-readelf -S %t.64 | FileCheck --check-prefix=SEC %s
+# RUN: llvm-readelf -s %t.64 | FileCheck --check-prefix=SYM %s
+
+## If there is an undefined reference to __global_pointer$ but .sdata doesn't
+## exist, create a dummy one.
+
+## __global_pointer$ = .sdata+0x800
+# SEC: [ 7] .sdata PROGBITS {{0*}}00003000
+# SYM: {{0*}}00003800 0 NOTYPE GLOBAL DEFAULT 7 __global_pointer$
+
+## If __global_pointer$ is not used, don't create .sdata .
+
+# RUN: llvm-mc -filetype=obj -triple=riscv32 /dev/null -o %t.32.o
+# RUN: ld.lld -pie %t.32.o -o %t.32
+# RUN: llvm-readelf -S %t.32 | FileCheck --implicit-check-not=.sdata /dev/null
+
+lla gp, __global_pointer$

Added: lld/trunk/test/ELF/riscv-gp.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/riscv-gp.s?rev=363351&view=auto
==============================================================================
--- lld/trunk/test/ELF/riscv-gp.s (added)
+++ lld/trunk/test/ELF/riscv-gp.s Thu Jun 13 19:14:53 2019
@@ -0,0 +1,26 @@
+# 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=SYM %s
+# RUN: llvm-readelf -S %t.32 | FileCheck --check-prefix=SEC %s
+# RUN: not ld.lld -shared %t.32.o -o /dev/null 2>&1 | FileCheck --check-prefix=ERR %s
+
+# RUN: llvm-mc -filetype=obj -triple=riscv64 %s -o %t.64.o
+# RUN: ld.lld -pie %t.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: not ld.lld -shared %t.64.o -o /dev/null 2>&1 | FileCheck --check-prefix=ERR %s
+
+## __global_pointer$ = .sdata+0x800 = 0x3800
+# SEC: [ 7] .sdata PROGBITS {{0*}}00003000
+# SYM: {{0*}}00003800 0 NOTYPE GLOBAL DEFAULT 7 __global_pointer$
+
+## __global_pointer$ - 0x1000 = 4096*3-2048
+# DIS:      1000: auipc gp, 3
+# DIS-NEXT:       addi gp, gp, -2048
+
+# ERR: error: relocation R_RISCV_PCREL_HI20 cannot be used against symbol __global_pointer$; recompile with -fPIC
+
+lla gp, __global_pointer$
+
+.section .sdata,"aw"




More information about the llvm-commits mailing list