From 8fbe81fb29e5c7f7d5e68e82063d43410121e6c4 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 28 Aug 2019 09:01:03 +0000 Subject: [PATCH] [ELF][RISCV] Assign st_shndx of __global_pointer$ to 1 if .sdata does not exist This essentially reverts the code change of D63132 and switches to a simpler approach. In an executable/shared object, st_shndx of a symbol can be: 1) SHN_UNDEF: undefined symbol (or canonical PLT) 2) SHN_ABS: absolute symbol 3) any other value (usually a regular section index) represents a relative symbol. The actual value does not matter. Many ld.so (musl, all archs except MIPS of FreeBSD rtld-elf) even treat 2) and 3) the same. If .sdata does not exist, it does not matter what value/section __global_pointer$ has, as long as it is relative (otherwise there will be a pedantic lld error. See D63132). Just set the st_shndx arbitrarily to 1. Dummy st_shndx=1 may be used by __rela_iplt_start, linker-script-defined symbols outside a section, __dso_handle, etc. Reviewed By: ruiu Differential Revision: https://reviews.llvm.org/D66798 llvm-svn: 370172 --- lld/ELF/SyntheticSections.cpp | 17 ----------------- lld/ELF/SyntheticSections.h | 10 ---------- lld/ELF/Writer.cpp | 20 +++++++++----------- lld/test/ELF/riscv-gp-dummy-sdata.s | 25 ------------------------- lld/test/ELF/riscv-gp-no-sdata.s | 15 +++++++++++++++ 5 files changed, 24 insertions(+), 63 deletions(-) delete mode 100644 lld/test/ELF/riscv-gp-dummy-sdata.s create mode 100644 lld/test/ELF/riscv-gp-no-sdata.s diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 3a372f5736c6..2bd9dc2d3416 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -3506,23 +3506,6 @@ bool PPC64LongBranchTargetSection::isNeeded() const { 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(base)) - for (InputSection *isec : isd->sections) - if (isec != this) - return false; - return true; -} - static uint8_t getAbiVersion() { // MIPS non-PIC executable gets ABI version 1. if (config->emachine == EM_MIPS) { diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 70ec36c4420d..684639789506 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -1100,15 +1100,6 @@ 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 void splitSections(); @@ -1173,7 +1164,6 @@ struct InStruct { PltSection *plt; PltSection *iplt; PPC32Got2Section *ppc32Got2; - RISCVSdataSection *riscvSdata; RelocationBaseSection *relaPlt; RelocationBaseSection *relaIplt; StringTableSection *shStrTab; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 1be73d6011f9..b4ae1fb00cc0 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -474,11 +474,6 @@ template static void createSyntheticSections() { add(in.ppc64LongBranchTarget); } - if (config->emachine == EM_RISCV) { - in.riscvSdata = make(); - add(in.riscvSdata); - } - in.gotPlt = make(); add(in.gotPlt); in.igotPlt = make(); @@ -1701,12 +1696,16 @@ template void Writer::finalizeSections() { // Define __rel[a]_iplt_{start,end} symbols if needed. addRelIpltSymbols(); - // RISC-V's gp can address +/- 2 KiB, set it to .sdata + 0x800 if not defined. - // This symbol should only be defined in an executable. - if (config->emachine == EM_RISCV && !config->shared) + // RISC-V's gp can address +/- 2 KiB, set it to .sdata + 0x800. This symbol + // should only be defined in an executable. If .sdata does not exist, its + // value/section does not matter but it has to be relative, so set its + // st_shndx arbitrarily to 1 (Out::elfHeader). + if (config->emachine == EM_RISCV && !config->shared) { + OutputSection *sec = findSection(".sdata"); ElfSym::riscvGlobalPointer = - addOptionalRegular("__global_pointer$", findSection(".sdata"), 0x800, - STV_DEFAULT, STB_GLOBAL); + addOptionalRegular("__global_pointer$", sec ? sec : Out::elfHeader, + 0x800, STV_DEFAULT, STB_GLOBAL); + } if (config->emachine == EM_X86_64) { // On targets that support TLSDESC, _TLS_MODULE_BASE_ is defined in such a @@ -1881,7 +1880,6 @@ template void Writer::finalizeSections() { 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 diff --git a/lld/test/ELF/riscv-gp-dummy-sdata.s b/lld/test/ELF/riscv-gp-dummy-sdata.s deleted file mode 100644 index e04b170d5b2b..000000000000 --- a/lld/test/ELF/riscv-gp-dummy-sdata.s +++ /dev/null @@ -1,25 +0,0 @@ -# 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$ diff --git a/lld/test/ELF/riscv-gp-no-sdata.s b/lld/test/ELF/riscv-gp-no-sdata.s new file mode 100644 index 000000000000..ee86438ec4f3 --- /dev/null +++ b/lld/test/ELF/riscv-gp-no-sdata.s @@ -0,0 +1,15 @@ +# 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-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 + +## If there is an undefined reference to __global_pointer$ but .sdata doesn't +## exist, define __global_pointer$ and set its st_shndx arbitrarily to 1. + +# SYM: {{0*}}00000800 0 NOTYPE GLOBAL DEFAULT 1 __global_pointer$ + +lla gp, __global_pointer$