[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
This commit is contained in:
George Rimar 2017-03-17 10:14:53 +00:00
parent 872305e95c
commit 1ab9cf49d0
10 changed files with 98 additions and 59 deletions

View File

@ -31,8 +31,6 @@ using namespace lld;
using namespace lld::elf; using namespace lld::elf;
uint8_t Out::First; uint8_t Out::First;
OutputSection *Out::Bss;
OutputSection *Out::BssRelRo;
OutputSection *Out::Opd; OutputSection *Out::Opd;
uint8_t *Out::OpdBuf; uint8_t *Out::OpdBuf;
PhdrEntry *Out::TlsPhdr; PhdrEntry *Out::TlsPhdr;

View File

@ -95,8 +95,6 @@ public:
// until Writer is initialized. // until Writer is initialized.
struct Out { struct Out {
static uint8_t First; static uint8_t First;
static OutputSection *Bss;
static OutputSection *BssRelRo;
static OutputSection *Opd; static OutputSection *Opd;
static uint8_t *OpdBuf; static uint8_t *OpdBuf;
static PhdrEntry *TlsPhdr; static PhdrEntry *TlsPhdr;

View File

@ -479,23 +479,20 @@ template <class ELFT> static void addCopyRelSymbol(SharedSymbol *SS) {
// See if this symbol is in a read-only segment. If so, preserve the symbol's // 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. // memory protection by reserving space in the .bss.rel.ro section.
bool IsReadOnly = isReadOnly<ELFT>(SS); bool IsReadOnly = isReadOnly<ELFT>(SS);
OutputSection *OSec = IsReadOnly ? Out::BssRelRo : Out::Bss; BssSection *Sec = IsReadOnly ? In<ELFT>::BssRelRo : In<ELFT>::Bss;
uintX_t Off = Sec->reserveSpace(SS->getAlignment<ELFT>(), SymSize);
// Create a SyntheticSection in Out to hold the .bss and the Copy Reloc.
auto *ISec =
make<CopyRelSection<ELFT>>(IsReadOnly, SS->getAlignment<ELFT>(), SymSize);
OSec->addSection(ISec);
// Look through the DSO's dynamic symbol table for aliases and create a // 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 // dynamic symbol for each one. This causes the copy relocation to correctly
// interpose any aliases. // interpose any aliases.
for (SharedSymbol *Sym : getSymbolsAt<ELFT>(SS)) { for (SharedSymbol *Sym : getSymbolsAt<ELFT>(SS)) {
Sym->NeedsCopy = true; Sym->NeedsCopy = true;
Sym->Section = ISec; Sym->CopyRelSec = Sec;
Sym->CopyRelSecOff = Off;
Sym->symbol()->IsUsedInRegularObj = true; Sym->symbol()->IsUsedInRegularObj = true;
} }
In<ELFT>::RelaDyn->addReloc({Target->CopyRel, ISec, 0, false, SS, 0}); In<ELFT>::RelaDyn->addReloc({Target->CopyRel, Sec, Off, false, SS, 0});
} }
template <class ELFT> template <class ELFT>

View File

@ -106,7 +106,8 @@ static typename ELFT::uint getSymVA(const SymbolBody &Body, int64_t &Addend) {
case SymbolBody::SharedKind: { case SymbolBody::SharedKind: {
auto &SS = cast<SharedSymbol>(Body); auto &SS = cast<SharedSymbol>(Body);
if (SS.NeedsCopy) if (SS.NeedsCopy)
return SS.Section->OutSec->Addr + SS.Section->OutSecOff; return SS.CopyRelSec->OutSec->Addr + SS.CopyRelSec->OutSecOff +
SS.CopyRelSecOff;
if (SS.NeedsPltAddr) if (SS.NeedsPltAddr)
return Body.getPltVA<ELFT>(); return Body.getPltVA<ELFT>();
return 0; return 0;
@ -207,7 +208,7 @@ OutputSection *SymbolBody::getOutputSection() const {
if (auto *S = dyn_cast<SharedSymbol>(this)) { if (auto *S = dyn_cast<SharedSymbol>(this)) {
if (S->NeedsCopy) if (S->NeedsCopy)
return S->Section->OutSec; return S->CopyRelSec->OutSec;
return nullptr; return nullptr;
} }

View File

@ -238,8 +238,9 @@ public:
// This field is a pointer to the symbol's version definition. // This field is a pointer to the symbol's version definition.
const void *Verdef; const void *Verdef;
// Section is significant only when NeedsCopy is true. // CopyRelSec and CopyRelSecOff are significant only when NeedsCopy is true.
InputSection *Section = nullptr; InputSection *CopyRelSec;
size_t CopyRelSecOff;
private: private:
template <class ELFT> const typename ELFT::Sym &getSym() const { template <class ELFT> const typename ELFT::Sym &getSym() const {

View File

@ -376,12 +376,15 @@ void BuildIdSection<ELFT>::computeHash(
HashFn(HashBuf, Hashes); HashFn(HashBuf, Hashes);
} }
template <class ELFT> BssSection::BssSection(StringRef Name)
CopyRelSection<ELFT>::CopyRelSection(bool ReadOnly, uint32_t Alignment, : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_NOBITS, 0, Name) {}
size_t S)
: SyntheticSection(SHF_ALLOC, SHT_NOBITS, Alignment, size_t BssSection::reserveSpace(uint32_t Alignment, size_t Size) {
ReadOnly ? ".bss.rel.ro" : ".bss"), OutSec->updateAlignment(Alignment);
Size(S) {} this->Size = alignTo(this->Size, Alignment) + Size;
this->Alignment = std::max<uint32_t>(this->Alignment, Alignment);
return this->Size - Size;
}
template <class ELFT> template <class ELFT>
void BuildIdSection<ELFT>::writeBuildId(ArrayRef<uint8_t> Buf) { void BuildIdSection<ELFT>::writeBuildId(ArrayRef<uint8_t> Buf) {
@ -2260,6 +2263,8 @@ InputSection *ThunkSection::getTargetInputSection() const {
} }
InputSection *InX::ARMAttributes; InputSection *InX::ARMAttributes;
BssSection *InX::Bss;
BssSection *InX::BssRelRo;
InputSection *InX::Common; InputSection *InX::Common;
StringTableSection *InX::DynStrTab; StringTableSection *InX::DynStrTab;
InputSection *InX::Interp; InputSection *InX::Interp;
@ -2312,11 +2317,6 @@ template class elf::BuildIdSection<ELF32BE>;
template class elf::BuildIdSection<ELF64LE>; template class elf::BuildIdSection<ELF64LE>;
template class elf::BuildIdSection<ELF64BE>; template class elf::BuildIdSection<ELF64BE>;
template class elf::CopyRelSection<ELF32LE>;
template class elf::CopyRelSection<ELF32BE>;
template class elf::CopyRelSection<ELF64LE>;
template class elf::CopyRelSection<ELF64BE>;
template class elf::GotSection<ELF32LE>; template class elf::GotSection<ELF32LE>;
template class elf::GotSection<ELF32BE>; template class elf::GotSection<ELF32BE>;
template class elf::GotSection<ELF64LE>; template class elf::GotSection<ELF64LE>;

View File

@ -153,15 +153,19 @@ private:
uint8_t *HashBuf; uint8_t *HashBuf;
}; };
// For each copy relocation, we create an instance of this class to // BssSection is used to reserve space for copy relocations. We create two
// reserve space in .bss or .bss.rel.ro. // instances of this class for .bss and .bss.rel.ro. .bss is used for writable
template <class ELFT> class CopyRelSection final : public SyntheticSection { // symbols, and .bss.rel.ro is used for read-only symbols.
class BssSection final : public SyntheticSection {
public: public:
CopyRelSection(bool ReadOnly, uint32_t Alignment, size_t Size); BssSection(StringRef Name);
void writeTo(uint8_t *) override {} 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 getSize() const override { return Size; }
size_t Size;
private:
size_t Size = 0;
}; };
template <class ELFT> class MipsGotSection final : public SyntheticSection { template <class ELFT> 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. // Linker generated sections which can be used as inputs.
struct InX { struct InX {
static InputSection *ARMAttributes; static InputSection *ARMAttributes;
static BssSection *Bss;
static BssSection *BssRelRo;
static InputSection *Common; static InputSection *Common;
static StringTableSection *DynStrTab; static StringTableSection *DynStrTab;
static InputSection *Interp; static InputSection *Interp;

View File

@ -111,8 +111,8 @@ StringRef elf::getOutputSectionName(StringRef Name) {
} }
for (StringRef V : for (StringRef V :
{".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.", {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.",
".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.", ".bss.", ".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.",
".gcc_except_table.", ".tdata.", ".ARM.exidx."}) { ".gcc_except_table.", ".tdata.", ".ARM.exidx."}) {
StringRef Prefix = V.drop_back(); StringRef Prefix = V.drop_back();
if (Name.startswith(V) || Name == Prefix) if (Name.startswith(V) || Name == Prefix)
@ -327,11 +327,6 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
auto Add = [](InputSectionBase *Sec) { InputSections.push_back(Sec); }; auto Add = [](InputSectionBase *Sec) { InputSections.push_back(Sec); };
// Create singleton output sections.
Out::Bss = make<OutputSection>(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
Out::BssRelRo =
make<OutputSection>(".bss.rel.ro", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
In<ELFT>::DynStrTab = make<StringTableSection>(".dynstr", true); In<ELFT>::DynStrTab = make<StringTableSection>(".dynstr", true);
In<ELFT>::Dynamic = make<DynamicSection<ELFT>>(); In<ELFT>::Dynamic = make<DynamicSection<ELFT>>();
In<ELFT>::RelaDyn = make<RelocationSection<ELFT>>( In<ELFT>::RelaDyn = make<RelocationSection<ELFT>>(
@ -369,6 +364,11 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
Add(Common); Add(Common);
} }
In<ELFT>::Bss = make<BssSection>(".bss");
Add(In<ELFT>::Bss);
In<ELFT>::BssRelRo = make<BssSection>(".bss.rel.ro");
Add(In<ELFT>::BssRelRo);
// Add MIPS-specific sections. // Add MIPS-specific sections.
bool HasDynSymTab = bool HasDynSymTab =
!Symtab<ELFT>::X->getSharedFiles().empty() || Config->pic() || !Symtab<ELFT>::X->getSharedFiles().empty() || Config->pic() ||
@ -617,7 +617,7 @@ template <class ELFT> bool elf::isRelroSection(const OutputSection *Sec) {
return true; return true;
if (In<ELFT>::Got && Sec == In<ELFT>::Got->OutSec) if (In<ELFT>::Got && Sec == In<ELFT>::Got->OutSec)
return true; return true;
if (Sec == Out::BssRelRo) if (Sec == In<ELFT>::BssRelRo->OutSec)
return true; return true;
StringRef S = Sec->Name; StringRef S = Sec->Name;
@ -1163,14 +1163,15 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
// Dynamic section must be the last one in this list and dynamic // Dynamic section must be the last one in this list and dynamic
// symbol table section (DynSymTab) must be the first one. // symbol table section (DynSymTab) must be the first one.
applySynthetic({In<ELFT>::DynSymTab, In<ELFT>::GnuHashTab, In<ELFT>::HashTab, applySynthetic({In<ELFT>::DynSymTab, In<ELFT>::Bss, In<ELFT>::BssRelRo,
In<ELFT>::SymTab, In<ELFT>::ShStrTab, In<ELFT>::StrTab, In<ELFT>::GnuHashTab, In<ELFT>::HashTab, In<ELFT>::SymTab,
In<ELFT>::VerDef, In<ELFT>::DynStrTab, In<ELFT>::GdbIndex, In<ELFT>::ShStrTab, In<ELFT>::StrTab, In<ELFT>::VerDef,
In<ELFT>::Got, In<ELFT>::MipsGot, In<ELFT>::IgotPlt, In<ELFT>::DynStrTab, In<ELFT>::GdbIndex, In<ELFT>::Got,
In<ELFT>::GotPlt, In<ELFT>::RelaDyn, In<ELFT>::RelaIplt, In<ELFT>::MipsGot, In<ELFT>::IgotPlt, In<ELFT>::GotPlt,
In<ELFT>::RelaPlt, In<ELFT>::Plt, In<ELFT>::Iplt, In<ELFT>::RelaDyn, In<ELFT>::RelaIplt, In<ELFT>::RelaPlt,
In<ELFT>::Plt, In<ELFT>::EhFrameHdr, In<ELFT>::VerSym, In<ELFT>::Plt, In<ELFT>::Iplt, In<ELFT>::Plt,
In<ELFT>::VerNeed, In<ELFT>::Dynamic}, In<ELFT>::EhFrameHdr, In<ELFT>::VerSym, In<ELFT>::VerNeed,
In<ELFT>::Dynamic},
[](SyntheticSection *SS) { SS->finalizeContents(); }); [](SyntheticSection *SS) { SS->finalizeContents(); });
// Some architectures use small displacements for jump instructions. // Some architectures use small displacements for jump instructions.
@ -1199,16 +1200,6 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
} }
template <class ELFT> void Writer<ELFT>::addPredefinedSections() { template <class ELFT> void Writer<ELFT>::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. // 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. // We have the terminater synthetic section class. Add that at the end.
auto *OS = dyn_cast_or_null<OutputSection>(findSection(".ARM.exidx")); auto *OS = dyn_cast_or_null<OutputSection>(findSection(".ARM.exidx"));

View File

@ -0,0 +1,7 @@
.data
.global foo
.type foo, @object
.align 8
.size foo, 8
foo:
.quad 0

View File

@ -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