#include "InputFiles.h"
#include "LinkerScript.h"
#include "OutputSections.h"
+#include "SyntheticSections.h"
#include "Target.h"
#include "Thunks.h"
}
template <class ELFT> size_t InputSectionBase<ELFT>::getSize() const {
+ if (auto *S = dyn_cast<SyntheticSection<ELFT>>(this))
+ return S->getSize();
+
if (auto *D = dyn_cast<InputSection<ELFT>>(this))
if (D->getThunksSize() > 0)
return D->getThunkOff() + D->getThunksSize();
+
return Data.size();
}
typename ELFT::uint InputSectionBase<ELFT>::getOffset(uintX_t Offset) const {
switch (kind()) {
case Regular:
+ case Synthetic:
return cast<InputSection<ELFT>>(this)->OutSecOff + Offset;
case EHFrame:
// The file crtbeginT.o has relocations pointing to the start of an empty
template <class ELFT>
InputSection<ELFT>::InputSection(uintX_t Flags, uint32_t Type,
uintX_t Addralign, ArrayRef<uint8_t> Data,
- StringRef Name)
+ StringRef Name, Kind K)
: InputSectionBase<ELFT>(nullptr, Flags, Type,
/*Entsize*/ 0, /*Link*/ 0, /*Info*/ 0, Addralign,
- Data, Name, Base::Regular) {}
+ Data, Name, K) {}
template <class ELFT>
InputSection<ELFT>::InputSection(elf::ObjectFile<ELFT> *F,
template <class ELFT>
bool InputSection<ELFT>::classof(const InputSectionData *S) {
- return S->kind() == Base::Regular;
+ return S->kind() == Base::Regular || S->kind() == Base::Synthetic;
}
template <class ELFT>
return;
}
+ if (auto *S = dyn_cast<SyntheticSection<ELFT>>(this)) {
+ S->writeTo(Buf);
+ return;
+ }
+
// Copy section contents from source object file to output file.
ArrayRef<uint8_t> Data = this->Data;
memcpy(Buf + OutSecOff, Data.data(), Data.size());
// section
class InputSectionData {
public:
- enum Kind { Regular, EHFrame, Merge };
+ enum Kind { Regular, EHFrame, Merge, Synthetic, };
// The garbage collector sets sections' Live bits.
// If GC is disabled, all sections are considered live by default.
typedef typename ELFT::Rel Elf_Rel;
typedef typename ELFT::Sym Elf_Sym;
typedef typename ELFT::uint uintX_t;
+ typedef InputSectionData::Kind Kind;
public:
InputSection();
InputSection(uintX_t Flags, uint32_t Type, uintX_t Addralign,
- ArrayRef<uint8_t> Data, StringRef Name);
+ ArrayRef<uint8_t> Data, StringRef Name,
+ Kind K = InputSectionData::Regular);
InputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header, StringRef Name);
static InputSection<ELFT> Discarded;
}
template <class ELFT>
-GotPltSection<ELFT>::GotPltSection()
- : OutputSectionBase(".got.plt", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE) {
- this->Addralign = Target->GotPltEntrySize;
-}
-
-template <class ELFT> void GotPltSection<ELFT>::addEntry(SymbolBody &Sym) {
- Sym.GotPltIndex = Target->GotPltHeaderEntriesNum + Entries.size();
- Entries.push_back(&Sym);
-}
-
-template <class ELFT> bool GotPltSection<ELFT>::empty() const {
- return Entries.empty();
-}
-
-template <class ELFT> void GotPltSection<ELFT>::finalize() {
- this->Size = (Target->GotPltHeaderEntriesNum + Entries.size()) *
- Target->GotPltEntrySize;
-}
-
-template <class ELFT> void GotPltSection<ELFT>::writeTo(uint8_t *Buf) {
- Target->writeGotPltHeader(Buf);
- Buf += Target->GotPltHeaderEntriesNum * Target->GotPltEntrySize;
- for (const SymbolBody *B : Entries) {
- Target->writeGotPlt(Buf, *B);
- Buf += sizeof(uintX_t);
- }
-}
-
-template <class ELFT>
GotSection<ELFT>::GotSection()
: OutputSectionBase(".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE) {
if (Config->EMachine == EM_MIPS)
Add({DT_JMPREL, Out<ELFT>::RelaPlt});
Add({DT_PLTRELSZ, Out<ELFT>::RelaPlt->Size});
Add({Config->EMachine == EM_MIPS ? DT_MIPS_PLTGOT : DT_PLTGOT,
- Out<ELFT>::GotPlt});
+ In<ELFT>::GotPlt});
Add({DT_PLTREL, uint64_t(Config->Rela ? DT_RELA : DT_REL)});
}
case Entry::SecAddr:
P->d_un.d_ptr = E.OutSec->Addr;
break;
+ case Entry::InSecAddr:
+ P->d_un.d_ptr = E.InSec->OutSec->Addr + E.InSec->OutSecOff;
+ break;
case Entry::SecSize:
P->d_un.d_val = E.OutSec->Size;
break;
uint32_t Type = C->Type;
switch (C->kind()) {
case InputSectionBase<ELFT>::Regular:
+ case InputSectionBase<ELFT>::Synthetic:
Sec = make<OutputSection<ELFT>>(Key.Name, Type, Flags);
break;
case InputSectionBase<ELFT>::EHFrame:
template class EhFrameHeader<ELF64LE>;
template class EhFrameHeader<ELF64BE>;
-template class GotPltSection<ELF32LE>;
-template class GotPltSection<ELF32BE>;
-template class GotPltSection<ELF64LE>;
-template class GotPltSection<ELF64BE>;
-
template class GotSection<ELF32LE>;
template class GotSection<ELF32BE>;
template class GotSection<ELF64LE>;
EHFrameHdr,
GnuHashTable,
Got,
- GotPlt,
HashTable,
Merge,
Plt,
void writeMipsGot(uint8_t *Buf);
};
-template <class ELFT> class GotPltSection final : public OutputSectionBase {
- typedef typename ELFT::uint uintX_t;
-
-public:
- GotPltSection();
- void finalize() override;
- void writeTo(uint8_t *Buf) override;
- void addEntry(SymbolBody &Sym);
- bool empty() const;
- Kind getKind() const override { return GotPlt; }
- static bool classof(const OutputSectionBase *B) {
- return B->getKind() == GotPlt;
- }
-
-private:
- std::vector<const SymbolBody *> Entries;
-};
-
template <class ELFT> class PltSection final : public OutputSectionBase {
typedef typename ELFT::uint uintX_t;
int32_t Tag;
union {
OutputSectionBase *OutSec;
+ InputSection<ELFT> *InSec;
uint64_t Val;
const SymbolBody *Sym;
};
- enum KindT { SecAddr, SecSize, SymAddr, PlainInt } Kind;
+ enum KindT { SecAddr, SecSize, SymAddr, PlainInt, InSecAddr } Kind;
Entry(int32_t Tag, OutputSectionBase *OutSec, KindT Kind = SecAddr)
: Tag(Tag), OutSec(OutSec), Kind(Kind) {}
+ Entry(int32_t Tag, InputSection<ELFT> *Sec)
+ : Tag(Tag), InSec(Sec), Kind(InSecAddr) {}
Entry(int32_t Tag, uint64_t Val) : Tag(Tag), Val(Val), Kind(PlainInt) {}
Entry(int32_t Tag, const SymbolBody *Sym)
: Tag(Tag), Sym(Sym), Kind(SymAddr) {}
static EhOutputSection<ELFT> *EhFrame;
static GdbIndexSection<ELFT> *GdbIndex;
static GnuHashTableSection<ELFT> *GnuHashTab;
- static GotPltSection<ELFT> *GotPlt;
static GotSection<ELFT> *Got;
static HashTableSection<ELFT> *HashTab;
static OutputSection<ELFT> *Bss;
template <class ELFT> EhOutputSection<ELFT> *Out<ELFT>::EhFrame;
template <class ELFT> GdbIndexSection<ELFT> *Out<ELFT>::GdbIndex;
template <class ELFT> GnuHashTableSection<ELFT> *Out<ELFT>::GnuHashTab;
-template <class ELFT> GotPltSection<ELFT> *Out<ELFT>::GotPlt;
template <class ELFT> GotSection<ELFT> *Out<ELFT>::Got;
template <class ELFT> HashTableSection<ELFT> *Out<ELFT>::HashTab;
template <class ELFT> OutputSection<ELFT> *Out<ELFT>::Bss;
#include "Relocations.h"
#include "Config.h"
#include "OutputSections.h"
+#include "Strings.h"
#include "SymbolTable.h"
+#include "SyntheticSections.h"
#include "Target.h"
#include "Thunks.h"
-#include "Strings.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/raw_ostream.h"
else
Rel = Target->PltRel;
- Out<ELFT>::GotPlt->addEntry(Body);
- Out<ELFT>::RelaPlt->addReloc({Rel, Out<ELFT>::GotPlt,
+ In<ELFT>::GotPlt->addEntry(Body);
+ Out<ELFT>::RelaPlt->addReloc({Rel, In<ELFT>::GotPlt,
Body.getGotPltOffset<ELFT>(), !Preemptible,
&Body, 0});
continue;
}
template <class ELFT> typename ELFT::uint SymbolBody::getGotPltVA() const {
- return Out<ELFT>::GotPlt->Addr + getGotPltOffset<ELFT>();
+ return In<ELFT>::GotPlt->getVA() + getGotPltOffset<ELFT>();
}
template <class ELFT> typename ELFT::uint SymbolBody::getGotPltOffset() const {
Config->BuildIdVector.size());
}
+template <class ELFT>
+GotPltSection<ELFT>::GotPltSection()
+ : SyntheticSection<ELFT>(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS,
+ Target->GotPltEntrySize, ".got.plt") {
+ this->Live = true;
+}
+
+template <class ELFT> void GotPltSection<ELFT>::addEntry(SymbolBody &Sym) {
+ Sym.GotPltIndex = Target->GotPltHeaderEntriesNum + Entries.size();
+ Entries.push_back(&Sym);
+}
+
+template <class ELFT> bool GotPltSection<ELFT>::empty() const {
+ return Entries.empty();
+}
+
+template <class ELFT> size_t GotPltSection<ELFT>::getSize() const {
+ return (Target->GotPltHeaderEntriesNum + Entries.size()) *
+ Target->GotPltEntrySize;
+}
+
+template <class ELFT> void GotPltSection<ELFT>::writeTo(uint8_t *Buf) {
+ Target->writeGotPltHeader(Buf);
+ Buf += Target->GotPltHeaderEntriesNum * Target->GotPltEntrySize;
+ for (const SymbolBody *B : Entries) {
+ Target->writeGotPlt(Buf, *B);
+ Buf += sizeof(uintX_t);
+ }
+}
+
template InputSection<ELF32LE> *elf::createCommonSection();
template InputSection<ELF32BE> *elf::createCommonSection();
template InputSection<ELF64LE> *elf::createCommonSection();
template class elf::BuildIdHexstring<ELF32BE>;
template class elf::BuildIdHexstring<ELF64LE>;
template class elf::BuildIdHexstring<ELF64BE>;
+
+template class elf::GotPltSection<ELF32LE>;
+template class elf::GotPltSection<ELF32BE>;
+template class elf::GotPltSection<ELF64LE>;
+template class elf::GotPltSection<ELF64BE>;
Elf_Mips_RegInfo Reginfo = {};
};
+template <class ELFT> class SyntheticSection : public InputSection<ELFT> {
+ typedef typename ELFT::uint uintX_t;
+
+public:
+ SyntheticSection(uintX_t Flags, uint32_t Type, uintX_t Addralign,
+ StringRef Name)
+ : InputSection<ELFT>(Flags, Type, Addralign, ArrayRef<uint8_t>(), Name,
+ InputSectionData::Synthetic) {}
+
+ virtual void writeTo(uint8_t *Buf) {}
+ virtual size_t getSize() const { return this->Data.size(); }
+
+ static bool classof(const InputSectionData *D) {
+ return D->kind() == InputSectionData::Synthetic;
+ }
+
+protected:
+ ~SyntheticSection() = default;
+};
+
// .note.gnu.build-id section.
template <class ELFT> class BuildIdSection : public InputSection<ELFT> {
public:
void writeBuildId(llvm::MutableArrayRef<uint8_t>) override;
};
+template <class ELFT>
+class GotPltSection final : public SyntheticSection<ELFT> {
+ typedef typename ELFT::uint uintX_t;
+
+public:
+ GotPltSection();
+ void addEntry(SymbolBody &Sym);
+ bool empty() const;
+ size_t getSize() const override;
+ void writeTo(uint8_t *Buf) override;
+ uintX_t getVA() { return this->OutSec->Addr + this->OutSecOff; }
+
+private:
+ std::vector<const SymbolBody *> Entries;
+};
+
template <class ELFT> InputSection<ELFT> *createCommonSection();
template <class ELFT> InputSection<ELFT> *createInterpSection();
template <class ELFT> struct In {
static BuildIdSection<ELFT> *BuildId;
static InputSection<ELFT> *Common;
+ static GotPltSection<ELFT> *GotPlt;
static InputSection<ELFT> *Interp;
static MipsAbiFlagsSection<ELFT> *MipsAbiFlags;
static MipsOptionsSection<ELFT> *MipsOptions;
template <class ELFT> BuildIdSection<ELFT> *In<ELFT>::BuildId;
template <class ELFT> InputSection<ELFT> *In<ELFT>::Common;
+template <class ELFT> GotPltSection<ELFT> *In<ELFT>::GotPlt;
template <class ELFT> InputSection<ELFT> *In<ELFT>::Interp;
template <class ELFT> MipsAbiFlagsSection<ELFT> *In<ELFT>::MipsAbiFlags;
template <class ELFT> MipsOptionsSection<ELFT> *In<ELFT>::MipsOptions;
#include "InputFiles.h"
#include "OutputSections.h"
#include "Symbols.h"
+#include "SyntheticSections.h"
#include "Thunks.h"
#include "Writer.h"
0x90, 0x90, 0x90, 0x90 // nop; nop; nop; nop
};
memcpy(Buf, PltData, sizeof(PltData));
- uint32_t Got = Out<ELF32LE>::GotPlt->Addr;
+ uint32_t Got = In<ELF32LE>::GotPlt->getVA();
write32le(Buf + 2, Got + 4);
write32le(Buf + 8, Got + 8);
}
// jmp *foo@GOT(%ebx) or jmp *foo_in_GOT
Buf[1] = Config->Pic ? 0xa3 : 0x25;
- uint32_t Got = Out<ELF32LE>::GotPlt->Addr;
+ uint32_t Got = In<ELF32LE>::GotPlt->getVA();
write32le(Buf + 2, Config->Shared ? GotEntryAddr - Got : GotEntryAddr);
write32le(Buf + 7, RelOff);
write32le(Buf + 12, -Index * PltEntrySize - PltHeaderSize - 16);
0x0f, 0x1f, 0x40, 0x00 // nopl 0x0(rax)
};
memcpy(Buf, PltData, sizeof(PltData));
- uint64_t Got = Out<ELFT>::GotPlt->Addr;
+ uint64_t Got = In<ELFT>::GotPlt->getVA();
uint64_t Plt = Out<ELFT>::Plt->Addr;
write32le(Buf + 2, Got - Plt + 2); // GOT+8
write32le(Buf + 8, Got - Plt + 4); // GOT+16
};
memcpy(Buf, PltData, sizeof(PltData));
- uint64_t Got = Out<ELF64LE>::GotPlt->Addr;
+ uint64_t Got = In<ELF64LE>::GotPlt->getVA();
uint64_t Plt = Out<ELF64LE>::Plt->Addr;
relocateOne(Buf + 4, R_AARCH64_ADR_PREL_PG_HI21,
getAArch64Page(Got + 16) - getAArch64Page(Plt + 4));
0x00, 0x00, 0x00, 0x00, // L2: .word &(.got.plt) - L1 - 8
};
memcpy(Buf, PltData, sizeof(PltData));
- uint64_t GotPlt = Out<ELF32LE>::GotPlt->Addr;
+ uint64_t GotPlt = In<ELF32LE>::GotPlt->getVA();
uint64_t L1 = Out<ELF32LE>::Plt->Addr + 8;
write32le(Buf + 16, GotPlt - L1 - 8);
}
write32<E>(Buf + 20, 0x0018c082); // srl $24, $24, 2
write32<E>(Buf + 24, 0x0320f809); // jalr $25
write32<E>(Buf + 28, 0x2718fffe); // subu $24, $24, 2
- uint64_t Got = Out<ELFT>::GotPlt->Addr;
+ uint64_t Got = In<ELFT>::GotPlt->getVA();
writeMipsHi16<E>(Buf, Got);
writeMipsLo16<E>(Buf + 4, Got);
writeMipsLo16<E>(Buf + 8, Got);
uint32_t TlsModuleIndexRel;
uint32_t TlsOffsetRel;
unsigned GotEntrySize;
- unsigned GotPltEntrySize;
+ unsigned GotPltEntrySize = 0;
unsigned PltEntrySize;
unsigned PltHeaderSize;
if (Config->GdbIndex)
Out<ELFT>::GdbIndex = make<GdbIndexSection<ELFT>>();
- Out<ELFT>::GotPlt = make<GotPltSection<ELFT>>();
Out<ELFT>::RelaPlt = make<RelocationSection<ELFT>>(
Config->Rela ? ".rela.plt" : ".rel.plt", false /*Sort*/);
if (Config->Strip != StripPolicy::All) {
Symtab<ELFT>::X->Sections.push_back(RegSec);
}
}
+
+ In<ELFT>::GotPlt = make<GotPltSection<ELFT>>();
}
template <class ELFT>
if (Type == SHT_INIT_ARRAY || Type == SHT_FINI_ARRAY ||
Type == SHT_PREINIT_ARRAY)
return true;
- if (Sec == Out<ELFT>::GotPlt)
+ if (Sec == In<ELFT>::GotPlt->OutSec)
return Config->ZNow;
if (Sec == Out<ELFT>::Dynamic || Sec == Out<ELFT>::Got)
return true;
// This function adds linker-created Out<ELFT>::* sections.
addPredefinedSections();
+ // We fill .got.plt section in scanRelocs(). This is the
+ // reason we don't add it earlier in createSections().
+ if (!In<ELFT>::GotPlt->empty()) {
+ addInputSec(In<ELFT>::GotPlt);
+ In<ELFT>::GotPlt->OutSec->assignOffsets();
+ }
+
sortSections();
unsigned I = 1;
if (needsGot())
Add(Out<ELFT>::Got);
- if (Out<ELFT>::GotPlt && !Out<ELFT>::GotPlt->empty())
- Add(Out<ELFT>::GotPlt);
if (!Out<ELFT>::Plt->empty())
Add(Out<ELFT>::Plt);
if (!Out<ELFT>::EhFrame->empty())