forked from OSchip/llvm-project
ELF: Drop the Chunk base class.
With OutputSection being a virtual interface, each concrete OutputSection handles only one type of chunk and we don't need a base Chunk class. So for we have a class that handles input sections and one that handles the string table, but this extends naturally for other outputs (symbol table, merging of SHF_MERGE sections, etc.). llvm-svn: 244972
This commit is contained in:
parent
210ea0b31a
commit
83b0dc6392
|
|
@ -19,51 +19,38 @@ namespace elf2 {
|
||||||
class Defined;
|
class Defined;
|
||||||
template <class ELFT> class ObjectFile;
|
template <class ELFT> class ObjectFile;
|
||||||
|
|
||||||
// A Chunk represents a chunk of data that will occupy space in the
|
|
||||||
// output (if the resolver chose that). It may or may not be backed by
|
|
||||||
// a section of an input file. It could be linker-created data, or
|
|
||||||
// doesn't even have actual data (if common or bss).
|
|
||||||
class Chunk {
|
|
||||||
public:
|
|
||||||
virtual ~Chunk() = default;
|
|
||||||
|
|
||||||
// Returns the size of this chunk (even if this is a common or BSS.)
|
|
||||||
virtual size_t getSize() const = 0;
|
|
||||||
|
|
||||||
// Write this chunk to a mmap'ed file, assuming Buf is pointing to
|
|
||||||
// beginning of the file. Because this function may use VA values
|
|
||||||
// of other chunks for relocations, you need to set them properly
|
|
||||||
// before calling this function.
|
|
||||||
virtual void writeTo(uint8_t *Buf) = 0;
|
|
||||||
|
|
||||||
// The writer sets and uses the addresses.
|
|
||||||
uint64_t getOutputSectionOff() { return OutputSectionOff; }
|
|
||||||
uint32_t getAlign() { return Align; }
|
|
||||||
void setOutputSectionOff(uint64_t V) { OutputSectionOff = V; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// The offset from beginning of the output sections this chunk was assigned
|
|
||||||
// to. The writer sets a value.
|
|
||||||
uint64_t OutputSectionOff = 0;
|
|
||||||
|
|
||||||
// The alignment of this chunk. The writer uses the value.
|
|
||||||
uint32_t Align = 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
// A chunk corresponding a section of an input file.
|
// A chunk corresponding a section of an input file.
|
||||||
template <class ELFT> class SectionChunk : public Chunk {
|
template <class ELFT> class SectionChunk {
|
||||||
typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
|
typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
|
||||||
typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela;
|
typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela;
|
||||||
typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;
|
typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SectionChunk(llvm::object::ELFFile<ELFT> *Obj, const Elf_Shdr *Header);
|
SectionChunk(llvm::object::ELFFile<ELFT> *Obj, const Elf_Shdr *Header);
|
||||||
size_t getSize() const override { return Header->sh_size; }
|
|
||||||
void writeTo(uint8_t *Buf) override;
|
// Returns the size of this chunk (even if this is a common or BSS.)
|
||||||
|
size_t getSize() const { return Header->sh_size; }
|
||||||
|
|
||||||
|
// Write this chunk to a mmap'ed file, assuming Buf is pointing to
|
||||||
|
// beginning of the output section.
|
||||||
|
void writeTo(uint8_t *Buf);
|
||||||
|
|
||||||
StringRef getSectionName() const;
|
StringRef getSectionName() const;
|
||||||
const Elf_Shdr *getSectionHdr() const { return Header; }
|
const Elf_Shdr *getSectionHdr() const { return Header; }
|
||||||
|
|
||||||
|
// The writer sets and uses the addresses.
|
||||||
|
uint64_t getOutputSectionOff() { return OutputSectionOff; }
|
||||||
|
uint32_t getAlign() { return Align; }
|
||||||
|
void setOutputSectionOff(uint64_t V) { OutputSectionOff = V; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// The offset from beginning of the output sections this chunk was assigned
|
||||||
|
// to. The writer sets a value.
|
||||||
|
uint64_t OutputSectionOff = 0;
|
||||||
|
|
||||||
|
// The alignment of this chunk. The writer uses the value.
|
||||||
|
uint32_t Align = 1;
|
||||||
|
|
||||||
// A file this chunk was created from.
|
// A file this chunk was created from.
|
||||||
llvm::object::ELFFile<ELFT> *Obj;
|
llvm::object::ELFFile<ELFT> *Obj;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,18 +66,18 @@ protected:
|
||||||
~OutputSectionBase() = default;
|
~OutputSectionBase() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <bool Is64Bits>
|
template <class ELFT>
|
||||||
class OutputSection final : public OutputSectionBase<Is64Bits> {
|
class OutputSection final : public OutputSectionBase<ELFT::Is64Bits> {
|
||||||
public:
|
public:
|
||||||
typedef typename OutputSectionBase<Is64Bits>::uintX_t uintX_t;
|
typedef typename OutputSectionBase<ELFT::Is64Bits>::uintX_t uintX_t;
|
||||||
OutputSection(StringRef Name, uint32_t sh_type, uintX_t sh_flags)
|
OutputSection(StringRef Name, uint32_t sh_type, uintX_t sh_flags)
|
||||||
: OutputSectionBase<Is64Bits>(Name, sh_type, sh_flags) {}
|
: OutputSectionBase<ELFT::Is64Bits>(Name, sh_type, sh_flags) {}
|
||||||
|
|
||||||
void addChunk(Chunk *C);
|
void addChunk(SectionChunk<ELFT> *C);
|
||||||
void writeTo(uint8_t *Buf) override;
|
void writeTo(uint8_t *Buf) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Chunk *> Chunks;
|
std::vector<SectionChunk<ELFT> *> Chunks;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <bool Is64Bits>
|
template <bool Is64Bits>
|
||||||
|
|
@ -117,7 +117,7 @@ private:
|
||||||
|
|
||||||
SymbolTable *Symtab;
|
SymbolTable *Symtab;
|
||||||
std::unique_ptr<llvm::FileOutputBuffer> Buffer;
|
std::unique_ptr<llvm::FileOutputBuffer> Buffer;
|
||||||
llvm::SpecificBumpPtrAllocator<OutputSection<ELFT::Is64Bits>> CAlloc;
|
llvm::SpecificBumpPtrAllocator<OutputSection<ELFT>> CAlloc;
|
||||||
std::vector<OutputSectionBase<ELFT::Is64Bits> *> OutputSections;
|
std::vector<OutputSectionBase<ELFT::Is64Bits> *> OutputSections;
|
||||||
|
|
||||||
uintX_t FileSize;
|
uintX_t FileSize;
|
||||||
|
|
@ -155,7 +155,8 @@ template <class ELFT> void Writer<ELFT>::run() {
|
||||||
error(Buffer->commit());
|
error(Buffer->commit());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool Is64Bits> void OutputSection<Is64Bits>::addChunk(Chunk *C) {
|
template <class ELFT>
|
||||||
|
void OutputSection<ELFT>::addChunk(SectionChunk<ELFT> *C) {
|
||||||
Chunks.push_back(C);
|
Chunks.push_back(C);
|
||||||
uint32_t Align = C->getAlign();
|
uint32_t Align = C->getAlign();
|
||||||
if (Align > this->Header.sh_addralign)
|
if (Align > this->Header.sh_addralign)
|
||||||
|
|
@ -168,8 +169,8 @@ template <bool Is64Bits> void OutputSection<Is64Bits>::addChunk(Chunk *C) {
|
||||||
this->Header.sh_size = Off;
|
this->Header.sh_size = Off;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool Is64Bits> void OutputSection<Is64Bits>::writeTo(uint8_t *Buf) {
|
template <class ELFT> void OutputSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||||
for (Chunk *C : Chunks)
|
for (SectionChunk<ELFT> *C : Chunks)
|
||||||
C->writeTo(Buf);
|
C->writeTo(Buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -225,18 +226,17 @@ template <bool Is64Bits> struct DenseMapInfo<SectionKey<Is64Bits>> {
|
||||||
|
|
||||||
// Create output section objects and add them to OutputSections.
|
// Create output section objects and add them to OutputSections.
|
||||||
template <class ELFT> void Writer<ELFT>::createSections() {
|
template <class ELFT> void Writer<ELFT>::createSections() {
|
||||||
SmallDenseMap<SectionKey<ELFT::Is64Bits>, OutputSection<ELFT::Is64Bits> *>
|
SmallDenseMap<SectionKey<ELFT::Is64Bits>, OutputSection<ELFT> *> Map;
|
||||||
Map;
|
|
||||||
for (std::unique_ptr<ObjectFileBase> &FileB : Symtab->ObjectFiles) {
|
for (std::unique_ptr<ObjectFileBase> &FileB : Symtab->ObjectFiles) {
|
||||||
auto &File = cast<ObjectFile<ELFT>>(*FileB);
|
auto &File = cast<ObjectFile<ELFT>>(*FileB);
|
||||||
for (SectionChunk<ELFT> *C : File.getChunks()) {
|
for (SectionChunk<ELFT> *C : File.getChunks()) {
|
||||||
const Elf_Shdr *H = C->getSectionHdr();
|
const Elf_Shdr *H = C->getSectionHdr();
|
||||||
SectionKey<ELFT::Is64Bits> Key{C->getSectionName(), H->sh_type,
|
SectionKey<ELFT::Is64Bits> Key{C->getSectionName(), H->sh_type,
|
||||||
H->sh_flags};
|
H->sh_flags};
|
||||||
OutputSection<ELFT::Is64Bits> *&Sec = Map[Key];
|
OutputSection<ELFT> *&Sec = Map[Key];
|
||||||
if (!Sec) {
|
if (!Sec) {
|
||||||
Sec = new (CAlloc.Allocate())
|
Sec = new (CAlloc.Allocate())
|
||||||
OutputSection<ELFT::Is64Bits>(Key.Name, Key.sh_type, Key.sh_flags);
|
OutputSection<ELFT>(Key.Name, Key.sh_type, Key.sh_flags);
|
||||||
OutputSections.push_back(Sec);
|
OutputSections.push_back(Sec);
|
||||||
}
|
}
|
||||||
Sec->addChunk(C);
|
Sec->addChunk(C);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue