Please use GitHub pull requests for new patches. Phabricator shutdown timeline
Changeset View
Standalone View
lld/ELF/SyntheticSections.h
Show All 25 Lines | |||||
#include "llvm/ADT/MapVector.h" | #include "llvm/ADT/MapVector.h" | ||||
#include "llvm/MC/StringTableBuilder.h" | #include "llvm/MC/StringTableBuilder.h" | ||||
#include "llvm/Support/Endian.h" | #include "llvm/Support/Endian.h" | ||||
#include <functional> | #include <functional> | ||||
namespace lld { | namespace lld { | ||||
namespace elf { | namespace elf { | ||||
class Defined; | class Defined; | ||||
struct Partition; | struct PhdrEntry; | ||||
class SymbolTableBaseSection; | |||||
class VersionNeedBaseSection; | |||||
class SyntheticSection : public InputSection { | class SyntheticSection : public InputSection { | ||||
public: | public: | ||||
SyntheticSection(uint64_t Flags, uint32_t Type, uint32_t Alignment, | SyntheticSection(uint64_t Flags, uint32_t Type, uint32_t Alignment, | ||||
StringRef Name) | StringRef Name) | ||||
: InputSection(nullptr, Flags, Type, Alignment, {}, Name, | : InputSection(nullptr, Flags, Type, Alignment, {}, Name, | ||||
InputSectionBase::Synthetic) { | InputSectionBase::Synthetic) { | ||||
markLive(); | markLive(); | ||||
▲ Show 20 Lines • Show All 374 Lines • ▼ Show 20 Lines | public: | ||||
// lie inside the output section. | // lie inside the output section. | ||||
DynamicReloc(RelType Type, const InputSectionBase *InputSec, | DynamicReloc(RelType Type, const InputSectionBase *InputSec, | ||||
uint64_t OffsetInSec, const OutputSection *OutputSec, | uint64_t OffsetInSec, const OutputSection *OutputSec, | ||||
int64_t Addend) | int64_t Addend) | ||||
: Type(Type), Sym(nullptr), InputSec(InputSec), OffsetInSec(OffsetInSec), | : Type(Type), Sym(nullptr), InputSec(InputSec), OffsetInSec(OffsetInSec), | ||||
UseSymVA(false), Addend(Addend), OutputSec(OutputSec) {} | UseSymVA(false), Addend(Addend), OutputSec(OutputSec) {} | ||||
uint64_t getOffset() const; | uint64_t getOffset() const; | ||||
uint32_t getSymIndex() const; | uint32_t getSymIndex(SymbolTableBaseSection *SymTab) const; | ||||
// Computes the addend of the dynamic relocation. Note that this is not the | // Computes the addend of the dynamic relocation. Note that this is not the | ||||
// same as the Addend member variable as it also includes the symbol address | // same as the Addend member variable as it also includes the symbol address | ||||
// if UseSymVA is true. | // if UseSymVA is true. | ||||
int64_t computeAddend() const; | int64_t computeAddend() const; | ||||
RelType Type; | RelType Type; | ||||
private: | |||||
Symbol *Sym; | Symbol *Sym; | ||||
const InputSectionBase *InputSec = nullptr; | const InputSectionBase *InputSec = nullptr; | ||||
uint64_t OffsetInSec; | uint64_t OffsetInSec; | ||||
// If this member is true, the dynamic relocation will not be against the | // If this member is true, the dynamic relocation will not be against the | ||||
// symbol but will instead be a relative relocation that simply adds the | // symbol but will instead be a relative relocation that simply adds the | ||||
// load address. This means we need to write the symbol virtual address | // load address. This means we need to write the symbol virtual address | ||||
// plus the original addend as the final relocation addend. | // plus the original addend as the final relocation addend. | ||||
bool UseSymVA; | bool UseSymVA; | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | void addReloc(RelType DynType, InputSectionBase *InputSec, | ||||
uint64_t OffsetInSec, Symbol *Sym, int64_t Addend, RelExpr Expr, | uint64_t OffsetInSec, Symbol *Sym, int64_t Addend, RelExpr Expr, | ||||
RelType Type); | RelType Type); | ||||
void addReloc(const DynamicReloc &Reloc); | void addReloc(const DynamicReloc &Reloc); | ||||
bool isNeeded() const override { return !Relocs.empty(); } | bool isNeeded() const override { return !Relocs.empty(); } | ||||
size_t getSize() const override { return Relocs.size() * this->Entsize; } | size_t getSize() const override { return Relocs.size() * this->Entsize; } | ||||
size_t getRelativeRelocCount() const { return NumRelativeRelocs; } | size_t getRelativeRelocCount() const { return NumRelativeRelocs; } | ||||
void finalizeContents() override; | void finalizeContents() override; | ||||
int32_t DynamicTag, SizeDynamicTag; | int32_t DynamicTag, SizeDynamicTag; | ||||
std::vector<DynamicReloc> Relocs; | |||||
protected: | protected: | ||||
std::vector<DynamicReloc> Relocs; | |||||
size_t NumRelativeRelocs = 0; | size_t NumRelativeRelocs = 0; | ||||
}; | }; | ||||
template <class ELFT> | template <class ELFT> | ||||
class RelocationSection final : public RelocationBaseSection { | class RelocationSection final : public RelocationBaseSection { | ||||
using Elf_Rel = typename ELFT::Rel; | using Elf_Rel = typename ELFT::Rel; | ||||
using Elf_Rela = typename ELFT::Rela; | using Elf_Rela = typename ELFT::Rela; | ||||
▲ Show 20 Lines • Show All 260 Lines • ▼ Show 20 Lines | public: | ||||
VersionDefinitionSection(); | VersionDefinitionSection(); | ||||
void finalizeContents() override; | void finalizeContents() override; | ||||
size_t getSize() const override; | size_t getSize() const override; | ||||
void writeTo(uint8_t *Buf) override; | void writeTo(uint8_t *Buf) override; | ||||
private: | private: | ||||
enum { EntrySize = 28 }; | enum { EntrySize = 28 }; | ||||
void writeOne(uint8_t *Buf, uint32_t Index, StringRef Name, size_t NameOff); | void writeOne(uint8_t *Buf, uint32_t Index, StringRef Name, size_t NameOff); | ||||
StringRef getFileDefName(); | |||||
unsigned FileDefNameOff; | unsigned FileDefNameOff; | ||||
std::vector<unsigned> VerDefNameOffs; | |||||
}; | }; | ||||
// The .gnu.version section specifies the required version of each symbol in the | // The .gnu.version section specifies the required version of each symbol in the | ||||
// dynamic symbol table. It contains one Elf_Versym for each dynamic symbol | // dynamic symbol table. It contains one Elf_Versym for each dynamic symbol | ||||
// table entry. An Elf_Versym is just a 16-bit integer that refers to a version | // table entry. An Elf_Versym is just a 16-bit integer that refers to a version | ||||
// identifier defined in the either .gnu.version_r or .gnu.version_d section. | // identifier defined in the either .gnu.version_r or .gnu.version_d section. | ||||
// The values 0 and 1 are reserved. All other values are used for versions in | // The values 0 and 1 are reserved. All other values are used for versions in | ||||
// the own object or in any of the dependencies. | // the own object or in any of the dependencies. | ||||
▲ Show 20 Lines • Show All 266 Lines • ▼ Show 20 Lines | public: | ||||
bool isNeeded() const override; | bool isNeeded() const override; | ||||
void finalizeContents() override { Finalized = true; } | void finalizeContents() override { Finalized = true; } | ||||
private: | private: | ||||
std::vector<const Symbol *> Entries; | std::vector<const Symbol *> Entries; | ||||
bool Finalized = false; | bool Finalized = false; | ||||
}; | }; | ||||
template <typename ELFT> | |||||
class PartitionElfHeaderSection : public SyntheticSection { | |||||
public: | |||||
PartitionElfHeaderSection(); | |||||
size_t getSize() const override; | |||||
void writeTo(uint8_t *Buf) override; | |||||
}; | |||||
template <typename ELFT> | |||||
class PartitionProgramHeadersSection : public SyntheticSection { | |||||
public: | |||||
PartitionProgramHeadersSection(); | |||||
size_t getSize() const override; | |||||
void writeTo(uint8_t *Buf) override; | |||||
}; | |||||
class PartitionIndexSection : public SyntheticSection { | |||||
public: | |||||
PartitionIndexSection(); | |||||
size_t getSize() const override; | |||||
void finalizeContents() override; | |||||
void writeTo(uint8_t *Buf) override; | |||||
}; | |||||
InputSection *createInterpSection(); | InputSection *createInterpSection(); | ||||
MergeInputSection *createCommentSection(); | MergeInputSection *createCommentSection(); | ||||
template <class ELFT> void splitSections(); | template <class ELFT> void splitSections(); | ||||
void mergeSections(); | void mergeSections(); | ||||
template <typename ELFT> void writeEhdr(uint8_t *Buf, Partition &Part); | |||||
template <typename ELFT> void writePhdrs(uint8_t *Buf, Partition &Part); | |||||
Defined *addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value, | Defined *addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value, | ||||
uint64_t Size, InputSectionBase &Section); | uint64_t Size, InputSectionBase &Section); | ||||
void addVerneed(Symbol *SS); | void addVerneed(Symbol *SS); | ||||
extern std::vector<Partition> Partitions; | |||||
// Linker generated per-partition sections. | // Linker generated per-partition sections. | ||||
struct Partition { | struct Partition { | ||||
StringRef Name; | StringRef Name; | ||||
unsigned getNumber() const { return this - &Partitions[0] + 1; } | uint64_t NameStrTab; | ||||
}; | |||||
SyntheticSection *ElfHeader; | |||||
SyntheticSection *ProgramHeaders; | |||||
std::vector<PhdrEntry *> Phdrs; | |||||
// Linker generated sections which can be used as inputs. | |||||
struct InStruct { | |||||
InputSection *ARMAttributes; | |||||
ARMExidxSyntheticSection *ARMExidx; | ARMExidxSyntheticSection *ARMExidx; | ||||
BssSection *Bss; | |||||
BssSection *BssRelRo; | |||||
BuildIdSection *BuildId; | BuildIdSection *BuildId; | ||||
EhFrameHeader *EhFrameHdr; | |||||
EhFrameSection *EhFrame; | |||||
SyntheticSection *Dynamic; | SyntheticSection *Dynamic; | ||||
StringTableSection *DynStrTab; | StringTableSection *DynStrTab; | ||||
SymbolTableBaseSection *DynSymTab; | SymbolTableBaseSection *DynSymTab; | ||||
EhFrameHeader *EhFrameHdr; | |||||
EhFrameSection *EhFrame; | |||||
GnuHashTableSection *GnuHashTab; | GnuHashTableSection *GnuHashTab; | ||||
HashTableSection *HashTab; | HashTableSection *HashTab; | ||||
RelocationBaseSection *RelaDyn; | |||||
RelrBaseSection *RelrDyn; | |||||
VersionDefinitionSection *VerDef; | |||||
SyntheticSection *VerNeed; | |||||
VersionTableSection *VerSym; | |||||
unsigned getNumber() const { return this - &Partitions[0] + 1; } | |||||
}; | |||||
extern Partition *Main; | |||||
inline Partition &SectionBase::getPartition() const { | |||||
assert(isLive()); | |||||
return Partitions[Partition - 1]; | |||||
} | |||||
grimar: What about having one more global pointer instead.
i.e. after creating all of the partitions do… | |||||
Yeah. Looks like this function doesn't have to be a function. I thought for a while about what kind of name I'd choose, but I didn't come up with a good idea. Calling Partitions[0] as In might not be a bad idea. It's short, and we don't need to update all Ins with mainPartition() which makes this patch much easier to read. ruiu: Yeah. Looks like this function doesn't have to be a function. I thought for a while about what… | |||||
It won't work to name it In because we already have a variable named In. I think that we'll always have a variable for per-file synthetic sections because some sections (such as the static symbol table) will not be duplicated between partitions. In an earlier version of this change I had a global variable static Partition &Main = Partitions[0]; but this won't work now that Partitions is a vector and not an array. That's why I introduced the function. I'm fine with the idea of bringing the variable back (as a pointer rather than a reference) and setting it once all partitions are created. I'll call it Main unless there are any strong objections to that name. pcc: It won't work to name it `In` because we already have a variable named `In`. I think that we'll… | |||||
// Linker generated sections which can be used as inputs and are not specific to | |||||
// a partition. | |||||
struct InStruct { | |||||
InputSection *ARMAttributes; | |||||
BssSection *Bss; | |||||
BssSection *BssRelRo; | |||||
GotSection *Got; | GotSection *Got; | ||||
GotPltSection *GotPlt; | GotPltSection *GotPlt; | ||||
IgotPltSection *IgotPlt; | IgotPltSection *IgotPlt; | ||||
PPC64LongBranchTargetSection *PPC64LongBranchTarget; | PPC64LongBranchTargetSection *PPC64LongBranchTarget; | ||||
MipsGotSection *MipsGot; | MipsGotSection *MipsGot; | ||||
MipsRldMapSection *MipsRldMap; | MipsRldMapSection *MipsRldMap; | ||||
SyntheticSection *PartEnd; | |||||
SyntheticSection *PartIndex; | |||||
PltSection *Plt; | PltSection *Plt; | ||||
PltSection *Iplt; | PltSection *Iplt; | ||||
RelocationBaseSection *RelaDyn; | |||||
RelrBaseSection *RelrDyn; | |||||
RelocationBaseSection *RelaPlt; | RelocationBaseSection *RelaPlt; | ||||
RelocationBaseSection *RelaIplt; | RelocationBaseSection *RelaIplt; | ||||
StringTableSection *ShStrTab; | StringTableSection *ShStrTab; | ||||
StringTableSection *StrTab; | StringTableSection *StrTab; | ||||
SymbolTableBaseSection *SymTab; | SymbolTableBaseSection *SymTab; | ||||
SymtabShndxSection *SymTabShndx; | SymtabShndxSection *SymTabShndx; | ||||
VersionDefinitionSection *VerDef; | |||||
SyntheticSection *VerNeed; | |||||
VersionTableSection *VerSym; | |||||
}; | }; | ||||
extern InStruct In; | extern InStruct In; | ||||
} // namespace elf | } // namespace elf | ||||
} // namespace lld | } // namespace lld | ||||
#endif | #endif |
What about having one more global pointer instead.
i.e. after creating all of the partitions do:
And then use InM everywhere instead of mainPartition.
I wonder what others think though.