From 1ab9cf49d0bc040bf0bd2869ecb59d95d0192cea Mon Sep 17 00:00:00 2001 From: George Rimar Date: Fri, 17 Mar 2017 10:14:53 +0000 Subject: [PATCH] [ELF] - Recommit "[ELF] - Make Bss and BssRelRo sections to be synthetic (#3)." Was fixed, details on review page. Original commit message: That removes CopyRelSection class completely, making Bss/BssRelRo to be just regular synthetics. This is splitted from D30541 and polished. Difference from D30541 that all logic of SharedSymbol converting to DefinedRegular was removed for now and probably will be posted as separate patch. Differential revision: https://reviews.llvm.org/D30892 llvm-svn: 298062 --- lld/ELF/OutputSections.cpp | 2 - lld/ELF/OutputSections.h | 2 - lld/ELF/Relocations.cpp | 13 +++--- lld/ELF/Symbols.cpp | 5 ++- lld/ELF/Symbols.h | 5 ++- lld/ELF/SyntheticSections.cpp | 22 +++++----- lld/ELF/SyntheticSections.h | 18 +++++--- lld/ELF/Writer.cpp | 43 ++++++++----------- .../ELF/Inputs/relocation-copy-align-common.s | 7 +++ lld/test/ELF/relocation-copy-align-common.s | 40 +++++++++++++++++ 10 files changed, 98 insertions(+), 59 deletions(-) create mode 100644 lld/test/ELF/Inputs/relocation-copy-align-common.s create mode 100644 lld/test/ELF/relocation-copy-align-common.s diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 1c0bdfa07bac3..335b3c9d9c219 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -31,8 +31,6 @@ using namespace lld; using namespace lld::elf; uint8_t Out::First; -OutputSection *Out::Bss; -OutputSection *Out::BssRelRo; OutputSection *Out::Opd; uint8_t *Out::OpdBuf; PhdrEntry *Out::TlsPhdr; diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index 6746afad6e2f5..649d1fa483481 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -95,8 +95,6 @@ class OutputSection final : public SectionBase { // until Writer is initialized. struct Out { static uint8_t First; - static OutputSection *Bss; - static OutputSection *BssRelRo; static OutputSection *Opd; static uint8_t *OpdBuf; static PhdrEntry *TlsPhdr; diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index d8863e56c15bc..b7b6f0298e253 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -479,23 +479,20 @@ template static void addCopyRelSymbol(SharedSymbol *SS) { // See if this symbol is in a read-only segment. If so, preserve the symbol's // memory protection by reserving space in the .bss.rel.ro section. bool IsReadOnly = isReadOnly(SS); - OutputSection *OSec = IsReadOnly ? Out::BssRelRo : Out::Bss; - - // Create a SyntheticSection in Out to hold the .bss and the Copy Reloc. - auto *ISec = - make>(IsReadOnly, SS->getAlignment(), SymSize); - OSec->addSection(ISec); + BssSection *Sec = IsReadOnly ? In::BssRelRo : In::Bss; + uintX_t Off = Sec->reserveSpace(SS->getAlignment(), SymSize); // Look through the DSO's dynamic symbol table for aliases and create a // dynamic symbol for each one. This causes the copy relocation to correctly // interpose any aliases. for (SharedSymbol *Sym : getSymbolsAt(SS)) { Sym->NeedsCopy = true; - Sym->Section = ISec; + Sym->CopyRelSec = Sec; + Sym->CopyRelSecOff = Off; Sym->symbol()->IsUsedInRegularObj = true; } - In::RelaDyn->addReloc({Target->CopyRel, ISec, 0, false, SS, 0}); + In::RelaDyn->addReloc({Target->CopyRel, Sec, Off, false, SS, 0}); } template diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index 081cc5829528a..4b9186557d9e8 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -106,7 +106,8 @@ static typename ELFT::uint getSymVA(const SymbolBody &Body, int64_t &Addend) { case SymbolBody::SharedKind: { auto &SS = cast(Body); if (SS.NeedsCopy) - return SS.Section->OutSec->Addr + SS.Section->OutSecOff; + return SS.CopyRelSec->OutSec->Addr + SS.CopyRelSec->OutSecOff + + SS.CopyRelSecOff; if (SS.NeedsPltAddr) return Body.getPltVA(); return 0; @@ -207,7 +208,7 @@ OutputSection *SymbolBody::getOutputSection() const { if (auto *S = dyn_cast(this)) { if (S->NeedsCopy) - return S->Section->OutSec; + return S->CopyRelSec->OutSec; return nullptr; } diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index 568fe08cfd1c3..e53dacacd500d 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -238,8 +238,9 @@ class SharedSymbol : public Defined { // This field is a pointer to the symbol's version definition. const void *Verdef; - // Section is significant only when NeedsCopy is true. - InputSection *Section = nullptr; + // CopyRelSec and CopyRelSecOff are significant only when NeedsCopy is true. + InputSection *CopyRelSec; + size_t CopyRelSecOff; private: template const typename ELFT::Sym &getSym() const { diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 4a4fa5b6962ae..cb91596f21fd0 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -376,12 +376,15 @@ void BuildIdSection::computeHash( HashFn(HashBuf, Hashes); } -template -CopyRelSection::CopyRelSection(bool ReadOnly, uint32_t Alignment, - size_t S) - : SyntheticSection(SHF_ALLOC, SHT_NOBITS, Alignment, - ReadOnly ? ".bss.rel.ro" : ".bss"), - Size(S) {} +BssSection::BssSection(StringRef Name) + : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_NOBITS, 0, Name) {} + +size_t BssSection::reserveSpace(uint32_t Alignment, size_t Size) { + OutSec->updateAlignment(Alignment); + this->Size = alignTo(this->Size, Alignment) + Size; + this->Alignment = std::max(this->Alignment, Alignment); + return this->Size - Size; +} template void BuildIdSection::writeBuildId(ArrayRef Buf) { @@ -2260,6 +2263,8 @@ InputSection *ThunkSection::getTargetInputSection() const { } InputSection *InX::ARMAttributes; +BssSection *InX::Bss; +BssSection *InX::BssRelRo; InputSection *InX::Common; StringTableSection *InX::DynStrTab; InputSection *InX::Interp; @@ -2312,11 +2317,6 @@ template class elf::BuildIdSection; template class elf::BuildIdSection; template class elf::BuildIdSection; -template class elf::CopyRelSection; -template class elf::CopyRelSection; -template class elf::CopyRelSection; -template class elf::CopyRelSection; - template class elf::GotSection; template class elf::GotSection; template class elf::GotSection; diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 1ae6318e25b2d..b8648de64990f 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -153,15 +153,19 @@ template class BuildIdSection : public SyntheticSection { uint8_t *HashBuf; }; -// For each copy relocation, we create an instance of this class to -// reserve space in .bss or .bss.rel.ro. -template class CopyRelSection final : public SyntheticSection { +// BssSection is used to reserve space for copy relocations. We create two +// instances of this class for .bss and .bss.rel.ro. .bss is used for writable +// symbols, and .bss.rel.ro is used for read-only symbols. +class BssSection final : public SyntheticSection { public: - CopyRelSection(bool ReadOnly, uint32_t Alignment, size_t Size); + BssSection(StringRef Name); void writeTo(uint8_t *) override {} - + bool empty() const override { return getSize() == 0; } + size_t reserveSpace(uint32_t Alignment, size_t Size); size_t getSize() const override { return Size; } - size_t Size; + +private: + size_t Size = 0; }; template class MipsGotSection final : public SyntheticSection { @@ -754,6 +758,8 @@ SymbolBody *addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value, // Linker generated sections which can be used as inputs. struct InX { static InputSection *ARMAttributes; + static BssSection *Bss; + static BssSection *BssRelRo; static InputSection *Common; static StringTableSection *DynStrTab; static InputSection *Interp; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 7f8391080f612..ad3c68b608c35 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -111,8 +111,8 @@ StringRef elf::getOutputSectionName(StringRef Name) { } for (StringRef V : - {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.", - ".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.", + {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.", + ".bss.", ".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.", ".gcc_except_table.", ".tdata.", ".ARM.exidx."}) { StringRef Prefix = V.drop_back(); if (Name.startswith(V) || Name == Prefix) @@ -327,11 +327,6 @@ template void Writer::createSyntheticSections() { auto Add = [](InputSectionBase *Sec) { InputSections.push_back(Sec); }; - // Create singleton output sections. - Out::Bss = make(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); - Out::BssRelRo = - make(".bss.rel.ro", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); - In::DynStrTab = make(".dynstr", true); In::Dynamic = make>(); In::RelaDyn = make>( @@ -369,6 +364,11 @@ template void Writer::createSyntheticSections() { Add(Common); } + In::Bss = make(".bss"); + Add(In::Bss); + In::BssRelRo = make(".bss.rel.ro"); + Add(In::BssRelRo); + // Add MIPS-specific sections. bool HasDynSymTab = !Symtab::X->getSharedFiles().empty() || Config->pic() || @@ -617,7 +617,7 @@ template bool elf::isRelroSection(const OutputSection *Sec) { return true; if (In::Got && Sec == In::Got->OutSec) return true; - if (Sec == Out::BssRelRo) + if (Sec == In::BssRelRo->OutSec) return true; StringRef S = Sec->Name; @@ -1163,14 +1163,15 @@ template void Writer::finalizeSections() { // Dynamic section must be the last one in this list and dynamic // symbol table section (DynSymTab) must be the first one. - applySynthetic({In::DynSymTab, In::GnuHashTab, In::HashTab, - In::SymTab, In::ShStrTab, In::StrTab, - In::VerDef, In::DynStrTab, In::GdbIndex, - In::Got, In::MipsGot, In::IgotPlt, - In::GotPlt, In::RelaDyn, In::RelaIplt, - In::RelaPlt, In::Plt, In::Iplt, - In::Plt, In::EhFrameHdr, In::VerSym, - In::VerNeed, In::Dynamic}, + applySynthetic({In::DynSymTab, In::Bss, In::BssRelRo, + In::GnuHashTab, In::HashTab, In::SymTab, + In::ShStrTab, In::StrTab, In::VerDef, + In::DynStrTab, In::GdbIndex, In::Got, + In::MipsGot, In::IgotPlt, In::GotPlt, + In::RelaDyn, In::RelaIplt, In::RelaPlt, + In::Plt, In::Iplt, In::Plt, + In::EhFrameHdr, In::VerSym, In::VerNeed, + In::Dynamic}, [](SyntheticSection *SS) { SS->finalizeContents(); }); // Some architectures use small displacements for jump instructions. @@ -1199,16 +1200,6 @@ template void Writer::finalizeSections() { } template void Writer::addPredefinedSections() { - // Add BSS sections. - auto Add = [=](OutputSection *Sec) { - if (!Sec->Sections.empty()) { - Sec->assignOffsets(); - OutputSections.push_back(Sec); - } - }; - Add(Out::Bss); - Add(Out::BssRelRo); - // ARM ABI requires .ARM.exidx to be terminated by some piece of data. // We have the terminater synthetic section class. Add that at the end. auto *OS = dyn_cast_or_null(findSection(".ARM.exidx")); diff --git a/lld/test/ELF/Inputs/relocation-copy-align-common.s b/lld/test/ELF/Inputs/relocation-copy-align-common.s new file mode 100644 index 0000000000000..b2fc8fd2bf61b --- /dev/null +++ b/lld/test/ELF/Inputs/relocation-copy-align-common.s @@ -0,0 +1,7 @@ +.data +.global foo +.type foo, @object +.align 8 +.size foo, 8 +foo: +.quad 0 diff --git a/lld/test/ELF/relocation-copy-align-common.s b/lld/test/ELF/relocation-copy-align-common.s new file mode 100644 index 0000000000000..a94c208a8b22d --- /dev/null +++ b/lld/test/ELF/relocation-copy-align-common.s @@ -0,0 +1,40 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux \ +# RUN: %p/Inputs/relocation-copy-align-common.s -o %t2.o +# RUN: ld.lld -shared %t2.o -o %t.so +# RUN: ld.lld %t.o %t.so -o %t3 +# RUN: llvm-readobj -s -r --expand-relocs %t3 | FileCheck %s + +# CHECK: Section { +# CHECK: Index: +# CHECK: Name: .bss +# CHECK-NEXT: Type: SHT_NOBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_WRITE +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x203000 +# CHECK-NEXT: Offset: 0x20B0 +# CHECK-NEXT: Size: 16 +# CHECK-NEXT: Link: 0 +# CHECK-NEXT: Info: 0 +# CHECK-NEXT: AddressAlignment: 8 +# CHECK-NEXT: EntrySize: 0 +# CHECK-NEXT: } + +# CHECK: Relocations [ +# CHECK-NEXT: Section {{.*}} .rela.dyn { +# CHECK-NEXT: Relocation { +# CHECK-NEXT: Offset: 0x203008 +# CHECK-NEXT: Type: R_X86_64_COPY +# CHECK-NEXT: Symbol: foo +# CHECK-NEXT: Addend: 0x0 +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: ] + +.global _start +_start: +.comm sym1,4,4 +movl $5, foo