forked from OSchip/llvm-project
[llvm-objcopy] Implement support for section groups
This diff adds support for SHT_GROUP sections to llvm-objcopy. Some sections are interrelated and comprise a group. For example, a definition of an inline function might require, in addition to the section containing its instructions, a read-only data section containing literals referenced inside the function. A section of the type SHT_GROUP contains the indices of the group members, therefore, it needs to be updated whenever the indices change. Similarly, the fields sh_link, sh_info should be recalculated as well. Test plan: make check-all Differential revision: https://reviews.llvm.org/D43996 llvm-svn: 328012
This commit is contained in:
parent
a3f2e483dd
commit
43b8acdfd7
Binary file not shown.
|
@ -0,0 +1,56 @@
|
|||
# RUN: yaml2obj %s > %t
|
||||
# RUN: llvm-objcopy -remove-section=.text.bar %t %t2
|
||||
# RUN: llvm-readobj -elf-section-groups %t2 | FileCheck %s
|
||||
|
||||
# In this test the section .text.bar is getting removed, since this section
|
||||
# goes after all the sections comprising a group, the content of the
|
||||
# section .group doesn't change.
|
||||
|
||||
# CHECK: Name: .group
|
||||
# CHECK-NEXT: Index: 1
|
||||
# CHECK-NEXT: Link: 3
|
||||
# CHECK-NEXT: Info: 2
|
||||
# CHECK-NEXT: Type: COMDAT (0x1)
|
||||
# CHECK-NEXT: Signature: foo
|
||||
# CHECK: .text.foo (2)
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .group
|
||||
Type: SHT_GROUP
|
||||
Link: .symtab
|
||||
AddressAlign: 0x0000000000000004
|
||||
Info: foo
|
||||
Members:
|
||||
- SectionOrType: GRP_COMDAT
|
||||
- SectionOrType: .text.foo
|
||||
- Name: .text.foo
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
|
||||
AddressAlign: 0x0000000000000010
|
||||
- Name: .text.bar
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
|
||||
AddressAlign: 0x0000000000000010
|
||||
Symbols:
|
||||
Local:
|
||||
- Name: .text.foo
|
||||
Type: STT_SECTION
|
||||
Section: .text.foo
|
||||
- Name: .text.bar
|
||||
Type: STT_SECTION
|
||||
Section: .text.bar
|
||||
Weak:
|
||||
- Name: foo
|
||||
Type: STT_FUNC
|
||||
Section: .text.foo
|
||||
Size: 0x0000000000000000
|
||||
- Name: bar
|
||||
Type: STT_FUNC
|
||||
Section: .text.bar
|
||||
Size: 0x0000000000000000
|
|
@ -0,0 +1,56 @@
|
|||
# RUN: yaml2obj %s > %t
|
||||
# RUN: llvm-objcopy -remove-section=.text.bar %t %t2
|
||||
# RUN: llvm-readobj -elf-section-groups %t2 | FileCheck %s
|
||||
|
||||
# In this test the section .text.bar is getting removed, as a result,
|
||||
# the indices of the sections which go after .text.bar will change,
|
||||
# thus the fields Link, Info and the content of .group should be updated.
|
||||
|
||||
# CHECK: Name: .group
|
||||
# CHECK-NEXT: Index: 1
|
||||
# CHECK-NEXT: Link: 3
|
||||
# CHECK-NEXT: Info: 2
|
||||
# CHECK-NEXT: Type: COMDAT (0x1)
|
||||
# CHECK-NEXT: Signature: foo
|
||||
# CHECK: .text.foo (2)
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .group
|
||||
Type: SHT_GROUP
|
||||
Link: .symtab
|
||||
AddressAlign: 0x0000000000000004
|
||||
Info: foo
|
||||
Members:
|
||||
- SectionOrType: GRP_COMDAT
|
||||
- SectionOrType: .text.foo
|
||||
- Name: .text.bar
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
|
||||
AddressAlign: 0x0000000000000010
|
||||
- Name: .text.foo
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
|
||||
AddressAlign: 0x0000000000000010
|
||||
Symbols:
|
||||
Local:
|
||||
- Name: .text.bar
|
||||
Type: STT_SECTION
|
||||
Section: .text.bar
|
||||
- Name: .text.foo
|
||||
Type: STT_SECTION
|
||||
Section: .text.foo
|
||||
Weak:
|
||||
- Name: bar
|
||||
Type: STT_FUNC
|
||||
Section: .text.bar
|
||||
Size: 0x0000000000000000
|
||||
- Name: foo
|
||||
Type: STT_FUNC
|
||||
Section: .text.foo
|
||||
Size: 0x0000000000000000
|
|
@ -0,0 +1,40 @@
|
|||
# RUN: cp %p/Inputs/groups.o %t
|
||||
# RUN: llvm-objcopy -strip-dwo %t
|
||||
# RUN: llvm-readobj -elf-section-groups %t | FileCheck %s
|
||||
|
||||
// Source code of groups.o:
|
||||
//
|
||||
// template <class T>
|
||||
// struct S {
|
||||
// static constexpr T X = T(1);
|
||||
// T getX() { return X; }
|
||||
// };
|
||||
// void f() {
|
||||
// S<int> A;
|
||||
// S<double> B;
|
||||
// int a = A.getX();
|
||||
// int b = B.getX();
|
||||
// }
|
||||
//
|
||||
// clang -g -gsplit-dwarf -std=c++11 -c groups.cpp -o groups.o
|
||||
|
||||
// `llvm-objcopy -strip-dwo` strips out dwo sections, as a result, the index of
|
||||
// the symbol table, the indices of the symbols and the indices of the sections
|
||||
// which go after the removed ones will change. Consequently, the fields
|
||||
// Link, Info and the content of .group need to be updated. In the past
|
||||
// `llvm-objcopy -strip-dwo` used to produce invalid binaries with
|
||||
// broken .group section, this test verifies the correctness of
|
||||
// Link, Info and the content of this section.
|
||||
|
||||
CHECK: Name: .group (179)
|
||||
CHECK-NEXT: Index: 17
|
||||
CHECK-NEXT: Link: 19
|
||||
CHECK-NEXT: Info: 14
|
||||
CHECK: .text._ZN1SIiE4getXEv (2)
|
||||
|
||||
CHECK: Name: .group (179)
|
||||
CHECK-NEXT: Index: 18
|
||||
CHECK-NEXT: Link: 19
|
||||
CHECK-NEXT: Info: 13
|
||||
CHECK: .text._ZN1SIdE4getXEv (4)
|
||||
CHECK-NEXT: .rela.text._ZN1SIdE4getXEv (21)
|
|
@ -77,7 +77,11 @@ void BinarySectionWriter::visit(const RelocationSection &Sec) {
|
|||
}
|
||||
|
||||
void BinarySectionWriter::visit(const GnuDebugLinkSection &Sec) {
|
||||
error("Cannot write '.gnu_debuglink' out to binary");
|
||||
error("Cannot write '" + Sec.Name + "' out to binary");
|
||||
}
|
||||
|
||||
void BinarySectionWriter::visit(const GroupSection &Sec) {
|
||||
error("Cannot write '" + Sec.Name + "' out to binary");
|
||||
}
|
||||
|
||||
void SectionWriter::visit(const Section &Sec) {
|
||||
|
@ -155,6 +159,12 @@ uint16_t Symbol::getShndx() const {
|
|||
llvm_unreachable("Symbol with invalid ShndxType encountered");
|
||||
}
|
||||
|
||||
void SymbolTableSection::assignIndices() {
|
||||
uint32_t Index = 0;
|
||||
for (auto &Sym : Symbols)
|
||||
Sym->Index = Index++;
|
||||
}
|
||||
|
||||
void SymbolTableSection::addSymbol(StringRef Name, uint8_t Bind, uint8_t Type,
|
||||
SectionBase *DefinedIn, uint64_t Value,
|
||||
uint8_t Visibility, uint16_t Shndx,
|
||||
|
@ -189,6 +199,7 @@ void SymbolTableSection::removeSectionReferences(const SectionBase *Sec) {
|
|||
[=](const SymPtr &Sym) { return Sym->DefinedIn == Sec; });
|
||||
Size -= (std::end(Symbols) - Iter) * this->EntrySize;
|
||||
Symbols.erase(Iter, std::end(Symbols));
|
||||
assignIndices();
|
||||
}
|
||||
|
||||
void SymbolTableSection::localize(
|
||||
|
@ -203,11 +214,7 @@ void SymbolTableSection::localize(
|
|||
std::stable_partition(
|
||||
std::begin(Symbols), std::end(Symbols),
|
||||
[](const SymPtr &Sym) { return Sym->Binding == STB_LOCAL; });
|
||||
|
||||
// Lastly we fix the symbol indexes.
|
||||
uint32_t Index = 0;
|
||||
for (auto &Sym : Symbols)
|
||||
Sym->Index = Index++;
|
||||
assignIndices();
|
||||
}
|
||||
|
||||
void SymbolTableSection::initialize(SectionTableRef SecTable) {
|
||||
|
@ -274,9 +281,10 @@ template <class SymTabType>
|
|||
void RelocSectionWithSymtabBase<SymTabType>::removeSectionReferences(
|
||||
const SectionBase *Sec) {
|
||||
if (Symbols == Sec) {
|
||||
error("Symbol table " + Symbols->Name + " cannot be removed because it is "
|
||||
"referenced by the relocation "
|
||||
"section " +
|
||||
error("Symbol table " + Symbols->Name +
|
||||
" cannot be removed because it is "
|
||||
"referenced by the relocation "
|
||||
"section " +
|
||||
this->Name);
|
||||
}
|
||||
}
|
||||
|
@ -291,9 +299,9 @@ void RelocSectionWithSymtabBase<SymTabType>::initialize(
|
|||
" is not a symbol table"));
|
||||
|
||||
if (Info != SHN_UNDEF)
|
||||
setSection(SecTable.getSection(Info,
|
||||
"Info field value " + Twine(Info) +
|
||||
" in section " + Name + " is invalid"));
|
||||
setSection(SecTable.getSection(Info, "Info field value " + Twine(Info) +
|
||||
" in section " + Name +
|
||||
" is invalid"));
|
||||
else
|
||||
setSection(nullptr);
|
||||
}
|
||||
|
@ -347,20 +355,49 @@ void DynamicRelocationSection::accept(SectionVisitor &Visitor) const {
|
|||
|
||||
void SectionWithStrTab::removeSectionReferences(const SectionBase *Sec) {
|
||||
if (StrTab == Sec) {
|
||||
error("String table " + StrTab->Name + " cannot be removed because it is "
|
||||
"referenced by the section " +
|
||||
error("String table " + StrTab->Name +
|
||||
" cannot be removed because it is "
|
||||
"referenced by the section " +
|
||||
this->Name);
|
||||
}
|
||||
}
|
||||
|
||||
void GroupSection::initialize(SectionTableRef SecTable) {
|
||||
SymTab = SecTable.getSectionOfType<SymbolTableSection>(
|
||||
Link,
|
||||
"Link field value " + Twine(Link) + " in section " + Name + " is invalid",
|
||||
"Link field value " + Twine(Link) + " in section " + Name +
|
||||
" is not a symbol table");
|
||||
Sym = SymTab->getSymbolByIndex(Info);
|
||||
if (!Sym)
|
||||
error("Info field value " + Twine(Info) + " in section " + Name +
|
||||
" is not a valid symbol index");
|
||||
if (Contents.size() % sizeof(ELF::Elf32_Word) || Contents.empty())
|
||||
error("The content of the section " + Name + " is malformed");
|
||||
const ELF::Elf32_Word *Word =
|
||||
reinterpret_cast<const ELF::Elf32_Word *>(Contents.data());
|
||||
const ELF::Elf32_Word *End = Word + Contents.size() / sizeof(ELF::Elf32_Word);
|
||||
FlagWord = *Word++;
|
||||
for (; Word != End; ++Word) {
|
||||
GroupMembers.push_back(
|
||||
SecTable.getSection(*Word, "Group member index " + Twine(*Word) +
|
||||
" in section " + Name + " is invalid"));
|
||||
}
|
||||
}
|
||||
|
||||
void GroupSection::finalize() {
|
||||
this->Info = Sym->Index;
|
||||
this->Link = SymTab->Index;
|
||||
}
|
||||
|
||||
bool SectionWithStrTab::classof(const SectionBase *S) {
|
||||
return isa<DynamicSymbolTableSection>(S) || isa<DynamicSection>(S);
|
||||
}
|
||||
|
||||
void SectionWithStrTab::initialize(SectionTableRef SecTable) {
|
||||
auto StrTab = SecTable.getSection(Link,
|
||||
"Link field value " + Twine(Link) +
|
||||
" in section " + Name + " is invalid");
|
||||
auto StrTab =
|
||||
SecTable.getSection(Link, "Link field value " + Twine(Link) +
|
||||
" in section " + Name + " is invalid");
|
||||
if (StrTab->Type != SHT_STRTAB) {
|
||||
error("Link field value " + Twine(Link) + " in section " + Name +
|
||||
" is not a string table");
|
||||
|
@ -416,6 +453,19 @@ void GnuDebugLinkSection::accept(SectionVisitor &Visitor) const {
|
|||
Visitor.visit(*this);
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void ELFSectionWriter<ELFT>::visit(const GroupSection &Sec) {
|
||||
ELF::Elf32_Word *Buf =
|
||||
reinterpret_cast<ELF::Elf32_Word *>(Out.getBufferStart() + Sec.Offset);
|
||||
*Buf++ = Sec.FlagWord;
|
||||
for (const auto *S : Sec.GroupMembers)
|
||||
*Buf++ = S->Index;
|
||||
}
|
||||
|
||||
void GroupSection::accept(SectionVisitor &Visitor) const {
|
||||
Visitor.visit(*this);
|
||||
}
|
||||
|
||||
// Returns true IFF a section is wholly inside the range of a segment
|
||||
static bool sectionWithinSegment(const SectionBase &Section,
|
||||
const Segment &Segment) {
|
||||
|
@ -455,8 +505,7 @@ static bool compareSegmentsByPAddr(const Segment *A, const Segment *B) {
|
|||
return A->Index < B->Index;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void ELFBuilder<ELFT>::setParentSegment(Segment &Child) {
|
||||
template <class ELFT> void ELFBuilder<ELFT>::setParentSegment(Segment &Child) {
|
||||
for (auto &Parent : Obj.segments()) {
|
||||
// Every segment will overlap with itself but we don't want a segment to
|
||||
// be it's own parent so we avoid that situation.
|
||||
|
@ -522,7 +571,7 @@ template <class ELFT> void ELFBuilder<ELFT>::readProgramHeaders() {
|
|||
PrHdr.OriginalOffset = PrHdr.Offset = PrHdr.VAddr = Ehdr.e_phoff;
|
||||
PrHdr.PAddr = 0;
|
||||
PrHdr.FileSize = PrHdr.MemSize = Ehdr.e_phentsize * Ehdr.e_phnum;
|
||||
// The spec requires us to naturally align all the fields.
|
||||
// The spec requires us to naturally align all the fields.
|
||||
PrHdr.Align = sizeof(Elf_Addr);
|
||||
PrHdr.Index = Index++;
|
||||
|
||||
|
@ -552,9 +601,9 @@ void ELFBuilder<ELFT>::initSymbolTable(SymbolTableSection *SymTab) {
|
|||
}
|
||||
} else if (Sym.st_shndx != SHN_UNDEF) {
|
||||
DefSection = Obj.sections().getSection(
|
||||
Sym.st_shndx,
|
||||
"Symbol '" + Name + "' is defined in invalid section with index " +
|
||||
Twine(Sym.st_shndx));
|
||||
Sym.st_shndx, "Symbol '" + Name +
|
||||
"' is defined in invalid section with index " +
|
||||
Twine(Sym.st_shndx));
|
||||
}
|
||||
|
||||
SymTab->addSymbol(Name, Sym.getBinding(), Sym.getType(), DefSection,
|
||||
|
@ -623,6 +672,9 @@ SectionBase &ELFBuilder<ELFT>::makeSection(const Elf_Shdr &Shdr) {
|
|||
// Because of this we don't need to mess with the hash tables either.
|
||||
Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
|
||||
return Obj.addSection<Section>(Data);
|
||||
case SHT_GROUP:
|
||||
Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
|
||||
return Obj.addSection<GroupSection>(Data);
|
||||
case SHT_DYNSYM:
|
||||
Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
|
||||
return Obj.addSection<DynamicSymbolTableSection>(Data);
|
||||
|
|
|
@ -35,17 +35,17 @@ class SymbolTableSection;
|
|||
class RelocationSection;
|
||||
class DynamicRelocationSection;
|
||||
class GnuDebugLinkSection;
|
||||
class GroupSection;
|
||||
class Segment;
|
||||
class Object;
|
||||
|
||||
class SectionTableRef {
|
||||
private:
|
||||
MutableArrayRef<std::unique_ptr<SectionBase>> Sections;
|
||||
|
||||
public:
|
||||
using iterator = pointee_iterator<std::unique_ptr<SectionBase> *>;
|
||||
|
||||
SectionTableRef(MutableArrayRef<std::unique_ptr<SectionBase>> Secs)
|
||||
explicit SectionTableRef(MutableArrayRef<std::unique_ptr<SectionBase>> Secs)
|
||||
: Sections(Secs) {}
|
||||
SectionTableRef(const SectionTableRef &) = default;
|
||||
|
||||
|
@ -71,6 +71,7 @@ public:
|
|||
virtual void visit(const RelocationSection &Sec) = 0;
|
||||
virtual void visit(const DynamicRelocationSection &Sec) = 0;
|
||||
virtual void visit(const GnuDebugLinkSection &Sec) = 0;
|
||||
virtual void visit(const GroupSection &Sec) = 0;
|
||||
};
|
||||
|
||||
class SectionWriter : public SectionVisitor {
|
||||
|
@ -87,6 +88,7 @@ public:
|
|||
virtual void visit(const SymbolTableSection &Sec) override = 0;
|
||||
virtual void visit(const RelocationSection &Sec) override = 0;
|
||||
virtual void visit(const GnuDebugLinkSection &Sec) override = 0;
|
||||
virtual void visit(const GroupSection &Sec) override = 0;
|
||||
|
||||
SectionWriter(FileOutputBuffer &Buf) : Out(Buf) {}
|
||||
};
|
||||
|
@ -102,6 +104,7 @@ public:
|
|||
void visit(const SymbolTableSection &Sec) override;
|
||||
void visit(const RelocationSection &Sec) override;
|
||||
void visit(const GnuDebugLinkSection &Sec) override;
|
||||
void visit(const GroupSection &Sec) override;
|
||||
|
||||
ELFSectionWriter(FileOutputBuffer &Buf) : SectionWriter(Buf) {}
|
||||
};
|
||||
|
@ -117,6 +120,8 @@ public:
|
|||
void visit(const SymbolTableSection &Sec) override;
|
||||
void visit(const RelocationSection &Sec) override;
|
||||
void visit(const GnuDebugLinkSection &Sec) override;
|
||||
void visit(const GroupSection &Sec) override;
|
||||
|
||||
BinarySectionWriter(FileOutputBuffer &Buf) : SectionWriter(Buf) {}
|
||||
};
|
||||
|
||||
|
@ -237,7 +242,7 @@ public:
|
|||
uint64_t OriginalOffset;
|
||||
Segment *ParentSegment = nullptr;
|
||||
|
||||
Segment(ArrayRef<uint8_t> Data) : Contents(Data) {}
|
||||
explicit Segment(ArrayRef<uint8_t> Data) : Contents(Data) {}
|
||||
Segment() {}
|
||||
|
||||
const SectionBase *firstSection() const {
|
||||
|
@ -253,11 +258,10 @@ public:
|
|||
class Section : public SectionBase {
|
||||
MAKE_SEC_WRITER_FRIEND
|
||||
|
||||
private:
|
||||
ArrayRef<uint8_t> Contents;
|
||||
|
||||
public:
|
||||
Section(ArrayRef<uint8_t> Data) : Contents(Data) {}
|
||||
explicit Section(ArrayRef<uint8_t> Data) : Contents(Data) {}
|
||||
|
||||
void accept(SectionVisitor &Visitor) const override;
|
||||
};
|
||||
|
@ -265,7 +269,6 @@ public:
|
|||
class OwnedDataSection : public SectionBase {
|
||||
MAKE_SEC_WRITER_FRIEND
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> Data;
|
||||
|
||||
public:
|
||||
|
@ -291,7 +294,6 @@ public:
|
|||
class StringTableSection : public SectionBase {
|
||||
MAKE_SEC_WRITER_FRIEND
|
||||
|
||||
private:
|
||||
StringTableBuilder StrTabBuilder;
|
||||
|
||||
public:
|
||||
|
@ -344,6 +346,7 @@ class SymbolTableSection : public SectionBase {
|
|||
MAKE_SEC_WRITER_FRIEND
|
||||
|
||||
void setStrTab(StringTableSection *StrTab) { SymbolNames = StrTab; }
|
||||
void assignIndices();
|
||||
|
||||
protected:
|
||||
std::vector<std::unique_ptr<Symbol>> Symbols;
|
||||
|
@ -402,7 +405,6 @@ public:
|
|||
// that code between the two symbol table types.
|
||||
template <class SymTabType>
|
||||
class RelocSectionWithSymtabBase : public RelocationSectionBase {
|
||||
private:
|
||||
SymTabType *Symbols = nullptr;
|
||||
void setSymTab(SymTabType *SymTab) { Symbols = SymTab; }
|
||||
|
||||
|
@ -419,7 +421,6 @@ class RelocationSection
|
|||
: public RelocSectionWithSymtabBase<SymbolTableSection> {
|
||||
MAKE_SEC_WRITER_FRIEND
|
||||
|
||||
private:
|
||||
std::vector<Relocation> Relocations;
|
||||
|
||||
public:
|
||||
|
@ -433,14 +434,37 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class SectionWithStrTab : public Section {
|
||||
private:
|
||||
const SectionBase *StrTab = nullptr;
|
||||
// TODO: The way stripping and groups interact is complicated
|
||||
// and still needs to be worked on.
|
||||
|
||||
class GroupSection : public SectionBase {
|
||||
MAKE_SEC_WRITER_FRIEND
|
||||
// TODO: Contents is present in several classes of the hierarchy.
|
||||
// This needs to be refactored to avoid duplication.
|
||||
ArrayRef<uint8_t> Contents;
|
||||
ELF::Elf32_Word FlagWord;
|
||||
SmallVector<SectionBase *, 3> GroupMembers;
|
||||
const SymbolTableSection *SymTab = nullptr;
|
||||
const Symbol *Sym = nullptr;
|
||||
|
||||
public:
|
||||
SectionWithStrTab(ArrayRef<uint8_t> Data) : Section(Data) {}
|
||||
explicit GroupSection(ArrayRef<uint8_t> Data) : Contents(Data) {}
|
||||
|
||||
void initialize(SectionTableRef SecTable) override;
|
||||
void accept(SectionVisitor &) const override;
|
||||
void finalize() override;
|
||||
|
||||
static bool classof(const SectionBase *S) {
|
||||
return S->Type == ELF::SHT_GROUP;
|
||||
}
|
||||
};
|
||||
|
||||
class SectionWithStrTab : public Section {
|
||||
const SectionBase *StrTab = nullptr;
|
||||
void setStrTab(const SectionBase *StringTable) { StrTab = StringTable; }
|
||||
|
||||
public:
|
||||
explicit SectionWithStrTab(ArrayRef<uint8_t> Data) : Section(Data) {}
|
||||
void removeSectionReferences(const SectionBase *Sec) override;
|
||||
void initialize(SectionTableRef SecTable) override;
|
||||
void finalize() override;
|
||||
|
@ -449,7 +473,8 @@ public:
|
|||
|
||||
class DynamicSymbolTableSection : public SectionWithStrTab {
|
||||
public:
|
||||
DynamicSymbolTableSection(ArrayRef<uint8_t> Data) : SectionWithStrTab(Data) {}
|
||||
explicit DynamicSymbolTableSection(ArrayRef<uint8_t> Data)
|
||||
: SectionWithStrTab(Data) {}
|
||||
|
||||
static bool classof(const SectionBase *S) {
|
||||
return S->Type == ELF::SHT_DYNSYM;
|
||||
|
@ -458,7 +483,7 @@ public:
|
|||
|
||||
class DynamicSection : public SectionWithStrTab {
|
||||
public:
|
||||
DynamicSection(ArrayRef<uint8_t> Data) : SectionWithStrTab(Data) {}
|
||||
explicit DynamicSection(ArrayRef<uint8_t> Data) : SectionWithStrTab(Data) {}
|
||||
|
||||
static bool classof(const SectionBase *S) {
|
||||
return S->Type == ELF::SHT_DYNAMIC;
|
||||
|
@ -473,7 +498,7 @@ private:
|
|||
ArrayRef<uint8_t> Contents;
|
||||
|
||||
public:
|
||||
DynamicRelocationSection(ArrayRef<uint8_t> Data) : Contents(Data) {}
|
||||
explicit DynamicRelocationSection(ArrayRef<uint8_t> Data) : Contents(Data) {}
|
||||
|
||||
void accept(SectionVisitor &) const override;
|
||||
|
||||
|
@ -488,7 +513,6 @@ class GnuDebugLinkSection : public SectionBase {
|
|||
MAKE_SEC_WRITER_FRIEND
|
||||
|
||||
private:
|
||||
|
||||
StringRef FileName;
|
||||
uint32_t CRC32;
|
||||
|
||||
|
@ -496,7 +520,7 @@ private:
|
|||
|
||||
public:
|
||||
// If we add this section from an external source we can use this ctor.
|
||||
GnuDebugLinkSection(StringRef File);
|
||||
explicit GnuDebugLinkSection(StringRef File);
|
||||
void accept(SectionVisitor &Visitor) const override;
|
||||
};
|
||||
|
||||
|
@ -506,10 +530,10 @@ public:
|
|||
virtual std::unique_ptr<Object> create() const = 0;
|
||||
};
|
||||
|
||||
using object::OwningBinary;
|
||||
using object::Binary;
|
||||
using object::ELFFile;
|
||||
using object::ELFObjectFile;
|
||||
using object::OwningBinary;
|
||||
|
||||
template <class ELFT> class ELFBuilder {
|
||||
private:
|
||||
|
@ -582,7 +606,8 @@ public:
|
|||
StringTableSection *SectionNames = nullptr;
|
||||
SymbolTableSection *SymbolTable = nullptr;
|
||||
|
||||
Object(std::shared_ptr<MemoryBuffer> Data) : OwnedData(Data) {}
|
||||
explicit Object(std::shared_ptr<MemoryBuffer> Data)
|
||||
: OwnedData(std::move(Data)) {}
|
||||
virtual ~Object() = default;
|
||||
|
||||
void sortSections();
|
||||
|
|
Loading…
Reference in New Issue