1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00

[yaml2obj, obj2yaml] - Implement section header table as a special Chunk.

This was discussed in D93678 thread.
Currently we have one special chunk - Fill.

This patch re implements the "SectionHeaderTable" key to become a special chunk too.
With that we are able to place the section header table at any location,
just like we place sections.

Differential revision: https://reviews.llvm.org/D95140
This commit is contained in:
Georgii Rymar 2021-01-19 17:02:08 +03:00
parent a2eb0c1564
commit fc47fdd498
17 changed files with 578 additions and 344 deletions

View File

@ -128,12 +128,6 @@ struct SectionHeader {
StringRef Name;
};
struct SectionHeaderTable {
Optional<std::vector<SectionHeader>> Sections;
Optional<std::vector<SectionHeader>> Excluded;
Optional<bool> NoHeaders;
};
struct Symbol {
StringRef Name;
ELF_STT Type;
@ -196,18 +190,26 @@ struct Chunk {
ARMIndexTable,
MipsABIFlags,
Addrsig,
Fill,
LinkerOptions,
DependentLibraries,
CallGraphProfile,
BBAddrMap
BBAddrMap,
// Special chunks.
SpecialChunksStart,
Fill = SpecialChunksStart,
SectionHeaderTable,
};
ChunkKind Kind;
StringRef Name;
Optional<llvm::yaml::Hex64> Offset;
Chunk(ChunkKind K) : Kind(K) {}
// Usually chunks are not created implicitly, but rather loaded from YAML.
// This flag is used to signal whether this is the case or not.
bool IsImplicit;
Chunk(ChunkKind K, bool Implicit) : Kind(K), IsImplicit(Implicit) {}
virtual ~Chunk();
};
@ -222,17 +224,14 @@ struct Section : public Chunk {
Optional<yaml::BinaryRef> Content;
Optional<llvm::yaml::Hex64> Size;
// Usually sections are not created implicitly, but loaded from YAML.
// When they are, this flag is used to signal about that.
bool IsImplicit;
// Holds the original section index.
unsigned OriginalSecNdx;
Section(ChunkKind Kind, bool IsImplicit = false)
: Chunk(Kind), IsImplicit(IsImplicit) {}
Section(ChunkKind Kind, bool IsImplicit = false) : Chunk(Kind, IsImplicit) {}
static bool classof(const Chunk *S) { return S->Kind != ChunkKind::Fill; }
static bool classof(const Chunk *S) {
return S->Kind < ChunkKind::SpecialChunksStart;
}
// Some derived sections might have their own special entries. This method
// returns a vector of <entry name, is used> pairs. It is used for section
@ -276,11 +275,34 @@ struct Fill : Chunk {
Optional<yaml::BinaryRef> Pattern;
llvm::yaml::Hex64 Size;
Fill() : Chunk(ChunkKind::Fill) {}
Fill() : Chunk(ChunkKind::Fill, /*Implicit=*/false) {}
static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Fill; }
};
struct SectionHeaderTable : Chunk {
SectionHeaderTable(bool IsImplicit)
: Chunk(ChunkKind::SectionHeaderTable, IsImplicit) {}
static bool classof(const Chunk *S) {
return S->Kind == ChunkKind::SectionHeaderTable;
}
Optional<std::vector<SectionHeader>> Sections;
Optional<std::vector<SectionHeader>> Excluded;
Optional<bool> NoHeaders;
size_t getNumHeaders(size_t SectionsNum) const {
if (IsImplicit)
return SectionsNum;
if (NoHeaders)
return (*NoHeaders) ? 0 : SectionsNum;
return (Sections ? Sections->size() : 0) + /*Null section*/ 1;
}
static constexpr StringRef TypeStr = "SectionHeaderTable";
};
struct BBAddrMapSection : Section {
Optional<std::vector<BBAddrMapEntry>> Entries;
@ -665,7 +687,6 @@ struct ProgramHeader {
struct Object {
FileHeader Header;
Optional<SectionHeaderTable> SectionHeaders;
std::vector<ProgramHeader> ProgramHeaders;
// An object might contain output section descriptions as well as
@ -688,6 +709,13 @@ struct Object {
return Ret;
}
const SectionHeaderTable &getSectionHeaderTable() const {
for (const std::unique_ptr<Chunk> &C : Chunks)
if (auto *S = dyn_cast<ELFYAML::SectionHeaderTable>(C.get()))
return *S;
llvm_unreachable("the section header table chunk must always be present");
}
unsigned getMachine() const;
};
@ -837,11 +865,6 @@ struct MappingTraits<ELFYAML::FileHeader> {
static void mapping(IO &IO, ELFYAML::FileHeader &FileHdr);
};
template <> struct MappingTraits<ELFYAML::SectionHeaderTable> {
static void mapping(IO &IO, ELFYAML::SectionHeaderTable &SecHdrTable);
static std::string validate(IO &IO, ELFYAML::SectionHeaderTable &SecHdrTable);
};
template <> struct MappingTraits<ELFYAML::SectionHeader> {
static void mapping(IO &IO, ELFYAML::SectionHeader &SHdr);
};

View File

@ -124,6 +124,11 @@ public:
if (checkLimit(sizeof(T)))
support::endian::write<T>(OS, Val, E);
}
void updateDataAt(uint64_t Pos, void *Data, size_t Size) {
assert(Pos >= InitialOffset && Pos + Size <= getOffset());
memcpy(&Buf[Pos - InitialOffset], Data, Size);
}
};
// Used to keep track of section and symbol names, so that in the YAML file
@ -224,7 +229,7 @@ template <class ELFT> class ELFState {
ArrayRef<typename ELFT::Shdr> SHeaders);
void finalizeStrings();
void writeELFHeader(raw_ostream &OS, Optional<uint64_t> SHOff);
void writeELFHeader(raw_ostream &OS);
void writeSectionContent(Elf_Shdr &SHeader,
const ELFYAML::NoBitsSection &Section,
ContiguousBlobAccumulator &CBA);
@ -330,12 +335,22 @@ ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH)
std::make_unique<ELFYAML::Section>(
ELFYAML::Chunk::ChunkKind::RawContent, /*IsImplicit=*/true));
// We add a technical suffix for each unnamed section/fill. It does not affect
// the output, but allows us to map them by name in the code and report better
// error messages.
StringSet<> DocSections;
ELFYAML::SectionHeaderTable *SecHdrTable = nullptr;
for (size_t I = 0; I < Doc.Chunks.size(); ++I) {
const std::unique_ptr<ELFYAML::Chunk> &C = Doc.Chunks[I];
// We might have an explicit section header table declaration.
if (auto S = dyn_cast<ELFYAML::SectionHeaderTable>(C.get())) {
if (SecHdrTable)
reportError("multiple section header tables are not allowed");
SecHdrTable = S;
continue;
}
// We add a technical suffix for each unnamed section/fill. It does not
// affect the output, but allows us to map them by name in the code and
// report better error messages.
if (C->Name.empty()) {
std::string NewName = ELFYAML::appendUniqueSuffix(
/*Name=*/"", "index " + Twine(I));
@ -359,7 +374,7 @@ ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH)
ImplicitSections.push_back(StringRef(SecName).copy(StringAlloc));
}
ImplicitSections.insert(ImplicitSections.end(), {".strtab"});
if (!Doc.SectionHeaders || !Doc.SectionHeaders->NoHeaders.getValueOr(false))
if (!SecHdrTable || !SecHdrTable->NoHeaders.getValueOr(false))
ImplicitSections.insert(ImplicitSections.end(), {".shstrtab"});
// Insert placeholders for implicit sections that are not
@ -371,12 +386,27 @@ ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH)
std::unique_ptr<ELFYAML::Chunk> Sec = std::make_unique<ELFYAML::Section>(
ELFYAML::Chunk::ChunkKind::RawContent, true /*IsImplicit*/);
Sec->Name = SecName;
Doc.Chunks.push_back(std::move(Sec));
// When the section header table is explicitly defined at the end of the
// sections list, it is reasonable to assume that the user wants to reorder
// section headers, but still wants to place the section header table after
// all sections, like it normally happens. In this case we want to insert
// other implicit sections right before the section header table.
if (Doc.Chunks.back().get() == SecHdrTable)
Doc.Chunks.insert(Doc.Chunks.end() - 1, std::move(Sec));
else
Doc.Chunks.push_back(std::move(Sec));
}
// Insert the section header table implicitly at the end, when it is not
// explicitly defined.
if (!SecHdrTable)
Doc.Chunks.push_back(
std::make_unique<ELFYAML::SectionHeaderTable>(/*IsImplicit=*/true));
}
template <class ELFT>
void ELFState<ELFT>::writeELFHeader(raw_ostream &OS, Optional<uint64_t> SHOff) {
void ELFState<ELFT>::writeELFHeader(raw_ostream &OS) {
using namespace llvm::ELF;
Elf_Ehdr Header;
@ -426,29 +456,24 @@ void ELFState<ELFT>::writeELFHeader(raw_ostream &OS, Optional<uint64_t> SHOff) {
Header.e_shentsize = Doc.Header.EShEntSize ? (uint16_t)*Doc.Header.EShEntSize
: sizeof(Elf_Shdr);
const ELFYAML::SectionHeaderTable &SectionHeaders =
Doc.getSectionHeaderTable();
if (Doc.Header.EShOff)
Header.e_shoff = *Doc.Header.EShOff;
else if (SHOff)
Header.e_shoff = *SHOff;
else if (SectionHeaders.Offset)
Header.e_shoff = *SectionHeaders.Offset;
else
Header.e_shoff = 0;
if (Doc.Header.EShNum)
Header.e_shnum = *Doc.Header.EShNum;
else if (!Doc.SectionHeaders ||
(Doc.SectionHeaders->NoHeaders && !*Doc.SectionHeaders->NoHeaders))
Header.e_shnum = Doc.getSections().size();
else if (!SHOff)
Header.e_shnum = 0;
else
Header.e_shnum =
(Doc.SectionHeaders->Sections ? Doc.SectionHeaders->Sections->size()
: 0) +
/*Null section*/ 1;
Header.e_shnum = SectionHeaders.getNumHeaders(Doc.getSections().size());
if (Doc.Header.EShStrNdx)
Header.e_shstrndx = *Doc.Header.EShStrNdx;
else if (SHOff && !ExcludedSectionHeaders.count(".shstrtab"))
else if (SectionHeaders.Offset && !ExcludedSectionHeaders.count(".shstrtab"))
Header.e_shstrndx = SN2I.get(".shstrtab");
else
Header.e_shstrndx = 0;
@ -520,14 +545,16 @@ unsigned ELFState<ELFT>::toSectionIndex(StringRef S, StringRef LocSec,
return 0;
}
if (!Doc.SectionHeaders || (Doc.SectionHeaders->NoHeaders &&
!Doc.SectionHeaders->NoHeaders.getValue()))
const ELFYAML::SectionHeaderTable &SectionHeaders =
Doc.getSectionHeaderTable();
if (SectionHeaders.IsImplicit ||
(SectionHeaders.NoHeaders && !SectionHeaders.NoHeaders.getValue()))
return Index;
assert(!Doc.SectionHeaders->NoHeaders.getValueOr(false) ||
!Doc.SectionHeaders->Sections);
assert(!SectionHeaders.NoHeaders.getValueOr(false) ||
!SectionHeaders.Sections);
size_t FirstExcluded =
Doc.SectionHeaders->Sections ? Doc.SectionHeaders->Sections->size() : 0;
SectionHeaders.Sections ? SectionHeaders.Sections->size() : 0;
if (Index >= FirstExcluded) {
if (LocSym.empty())
reportError("unable to link '" + LocSec + "' to excluded section '" + S +
@ -670,8 +697,27 @@ void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
continue;
}
if (ELFYAML::SectionHeaderTable *S =
dyn_cast<ELFYAML::SectionHeaderTable>(D.get())) {
if (S->NoHeaders.getValueOr(false))
continue;
if (!S->Offset)
S->Offset = alignToOffset(CBA, sizeof(typename ELFT::uint),
/*Offset=*/None);
else
S->Offset = alignToOffset(CBA, /*Align=*/1, S->Offset);
uint64_t Size = S->getNumHeaders(SHeaders.size()) * sizeof(Elf_Shdr);
// The full section header information might be not available here, so
// fill the space with zeroes as a placeholder.
CBA.writeZeros(Size);
LocationCounter += Size;
continue;
}
ELFYAML::Section *Sec = cast<ELFYAML::Section>(D.get());
bool IsFirstUndefSection = D == Doc.Chunks.front();
bool IsFirstUndefSection = Sec == Doc.getSections().front();
if (IsFirstUndefSection && Sec->IsImplicit)
continue;
@ -1742,7 +1788,9 @@ void ELFState<ELFT>::writeFill(ELFYAML::Fill &Fill,
template <class ELFT>
DenseMap<StringRef, size_t> ELFState<ELFT>::buildSectionHeaderReorderMap() {
if (!Doc.SectionHeaders || Doc.SectionHeaders->NoHeaders)
const ELFYAML::SectionHeaderTable &SectionHeaders =
Doc.getSectionHeaderTable();
if (SectionHeaders.IsImplicit || SectionHeaders.NoHeaders)
return DenseMap<StringRef, size_t>();
DenseMap<StringRef, size_t> Ret;
@ -1756,12 +1804,12 @@ DenseMap<StringRef, size_t> ELFState<ELFT>::buildSectionHeaderReorderMap() {
Seen.insert(Hdr.Name);
};
if (Doc.SectionHeaders->Sections)
for (const ELFYAML::SectionHeader &Hdr : *Doc.SectionHeaders->Sections)
if (SectionHeaders.Sections)
for (const ELFYAML::SectionHeader &Hdr : *SectionHeaders.Sections)
AddSection(Hdr);
if (Doc.SectionHeaders->Excluded)
for (const ELFYAML::SectionHeader &Hdr : *Doc.SectionHeaders->Excluded)
if (SectionHeaders.Excluded)
for (const ELFYAML::SectionHeader &Hdr : *SectionHeaders.Excluded)
AddSection(Hdr);
for (const ELFYAML::Section *S : Doc.getSections()) {
@ -1790,17 +1838,17 @@ template <class ELFT> void ELFState<ELFT>::buildSectionIndex() {
// Build excluded section headers map.
std::vector<ELFYAML::Section *> Sections = Doc.getSections();
if (Doc.SectionHeaders) {
if (Doc.SectionHeaders->Excluded)
for (const ELFYAML::SectionHeader &Hdr : *Doc.SectionHeaders->Excluded)
if (!ExcludedSectionHeaders.insert(Hdr.Name).second)
llvm_unreachable("buildSectionIndex() failed");
const ELFYAML::SectionHeaderTable &SectionHeaders =
Doc.getSectionHeaderTable();
if (SectionHeaders.Excluded)
for (const ELFYAML::SectionHeader &Hdr : *SectionHeaders.Excluded)
if (!ExcludedSectionHeaders.insert(Hdr.Name).second)
llvm_unreachable("buildSectionIndex() failed");
if (Doc.SectionHeaders->NoHeaders.getValueOr(false))
for (const ELFYAML::Section *S : Sections)
if (!ExcludedSectionHeaders.insert(S->Name).second)
llvm_unreachable("buildSectionIndex() failed");
}
if (SectionHeaders.NoHeaders.getValueOr(false))
for (const ELFYAML::Section *S : Sections)
if (!ExcludedSectionHeaders.insert(S->Name).second)
llvm_unreachable("buildSectionIndex() failed");
size_t SecNdx = -1;
for (const ELFYAML::Section *S : Sections) {
@ -1903,17 +1951,7 @@ bool ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc,
// Now we can decide segment offsets.
State.setProgramHeaderLayout(PHeaders, SHeaders);
// If needed, align the start of the section header table, which is written
// after all section data.
const bool HasSectionHeaders =
!Doc.SectionHeaders || !Doc.SectionHeaders->NoHeaders.getValueOr(false);
Optional<uint64_t> SHOff;
if (HasSectionHeaders)
SHOff = State.alignToOffset(CBA, sizeof(typename ELFT::uint),
/*Offset=*/None);
bool ReachedLimit = SHOff.getValueOr(CBA.getOffset()) +
arrayDataSize(makeArrayRef(SHeaders)) >
MaxSize;
bool ReachedLimit = CBA.getOffset() > MaxSize;
if (Error E = CBA.takeLimitError()) {
// We report a custom error message instead below.
consumeError(std::move(E));
@ -1928,11 +1966,15 @@ bool ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc,
if (State.HasError)
return false;
State.writeELFHeader(OS, SHOff);
State.writeELFHeader(OS);
writeArrayData(OS, makeArrayRef(PHeaders));
const ELFYAML::SectionHeaderTable &SHT = Doc.getSectionHeaderTable();
if (!SHT.NoHeaders.getValueOr(false))
CBA.updateDataAt(*SHT.Offset, SHeaders.data(),
SHT.getNumHeaders(SHeaders.size()) * sizeof(Elf_Shdr));
CBA.writeBlobToStream(OS);
if (HasSectionHeaders)
writeArrayData(OS, makeArrayRef(SHeaders));
return true;
}

View File

@ -860,23 +860,6 @@ void MappingTraits<ELFYAML::SectionHeader>::mapping(
IO.mapRequired("Name", SHdr.Name);
}
void MappingTraits<ELFYAML::SectionHeaderTable>::mapping(
IO &IO, ELFYAML::SectionHeaderTable &SectionHeader) {
IO.mapOptional("Sections", SectionHeader.Sections);
IO.mapOptional("Excluded", SectionHeader.Excluded);
IO.mapOptional("NoHeaders", SectionHeader.NoHeaders);
}
std::string MappingTraits<ELFYAML::SectionHeaderTable>::validate(
IO &IO, ELFYAML::SectionHeaderTable &SecHdrTable) {
if (SecHdrTable.NoHeaders && (SecHdrTable.Sections || SecHdrTable.Excluded))
return "NoHeaders can't be used together with Sections/Excluded";
if (!SecHdrTable.NoHeaders && !SecHdrTable.Sections && !SecHdrTable.Excluded)
return "SectionHeaderTable can't be empty. Use 'NoHeaders' key to drop the "
"section header table";
return "";
}
void MappingTraits<ELFYAML::FileHeader>::mapping(IO &IO,
ELFYAML::FileHeader &FileHdr) {
IO.mapRequired("Class", FileHdr.Class);
@ -1252,6 +1235,14 @@ static void fillMapping(IO &IO, ELFYAML::Fill &Fill) {
IO.mapRequired("Size", Fill.Size);
}
static void sectionHeaderTableMapping(IO &IO,
ELFYAML::SectionHeaderTable &SHT) {
IO.mapOptional("Offset", SHT.Offset);
IO.mapOptional("Sections", SHT.Sections);
IO.mapOptional("Excluded", SHT.Excluded);
IO.mapOptional("NoHeaders", SHT.NoHeaders);
}
static void sectionMapping(IO &IO, ELFYAML::LinkerOptionsSection &Section) {
commonSectionMapping(IO, Section);
IO.mapOptional("Options", Section.Options);
@ -1304,22 +1295,48 @@ static StringRef getStringValue(IO &IO, const char *Key) {
return Val;
}
static void setStringValue(IO &IO, const char *Key, StringRef Val) {
IO.mapRequired(Key, Val);
}
static bool isInteger(StringRef Val) {
APInt Tmp;
return !Val.getAsInteger(0, Tmp);
}
void MappingTraits<std::unique_ptr<ELFYAML::Chunk>>::mapping(
IO &IO, std::unique_ptr<ELFYAML::Chunk> &Section) {
ELFYAML::ELF_SHT Type;
StringRef TypeStr;
if (IO.outputting()) {
Type = cast<ELFYAML::Section>(Section.get())->Type;
if (auto *S = dyn_cast<ELFYAML::Section>(Section.get()))
Type = S->Type;
else if (auto *SHT = dyn_cast<ELFYAML::SectionHeaderTable>(Section.get()))
TypeStr = SHT->TypeStr;
} else {
// When the Type string does not have a "SHT_" prefix, we know it is not a
// description of a regular ELF output section. Currently, we have one
// special type named "Fill". See comments for Fill.
if (getStringValue(IO, "Type") == "Fill") {
Section.reset(new ELFYAML::Fill());
fillMapping(IO, *cast<ELFYAML::Fill>(Section.get()));
return;
}
// description of a regular ELF output section.
TypeStr = getStringValue(IO, "Type");
if (TypeStr.startswith("SHT_") || isInteger(TypeStr))
IO.mapRequired("Type", Type);
}
IO.mapRequired("Type", Type);
if (TypeStr == "Fill") {
assert(!IO.outputting()); // We don't dump fills currently.
Section.reset(new ELFYAML::Fill());
fillMapping(IO, *cast<ELFYAML::Fill>(Section.get()));
return;
}
if (TypeStr == ELFYAML::SectionHeaderTable::TypeStr) {
if (IO.outputting())
setStringValue(IO, "Type", TypeStr);
else
Section.reset(new ELFYAML::SectionHeaderTable(/*IsImplicit=*/false));
sectionHeaderTableMapping(
IO, *cast<ELFYAML::SectionHeaderTable>(Section.get()));
return;
}
const auto &Obj = *static_cast<ELFYAML::Object *>(IO.getContext());
@ -1452,6 +1469,15 @@ std::string MappingTraits<std::unique_ptr<ELFYAML::Chunk>>::validate(
return "";
}
if (const auto *SHT = dyn_cast<ELFYAML::SectionHeaderTable>(C.get())) {
if (SHT->NoHeaders && (SHT->Sections || SHT->Excluded || SHT->Offset))
return "NoHeaders can't be used together with Offset/Sections/Excluded";
if (!SHT->NoHeaders && !SHT->Sections && !SHT->Excluded)
return "SectionHeaderTable can't be empty. Use 'NoHeaders' key to drop "
"the section header table";
return "";
}
const ELFYAML::Section &Sec = *cast<ELFYAML::Section>(C.get());
if (Sec.Size && Sec.Content &&
(uint64_t)(*Sec.Size) < Sec.Content->binary_size())
@ -1656,7 +1682,6 @@ void MappingTraits<ELFYAML::Object>::mapping(IO &IO, ELFYAML::Object &Object) {
IO.mapOptional("Symbols", Object.Symbols);
IO.mapOptional("DynamicSymbols", Object.DynamicSymbols);
IO.mapOptional("DWARF", Object.DWARF);
IO.mapOptional("SectionHeaderTable", Object.SectionHeaders);
if (Object.DWARF) {
Object.DWARF->IsLittleEndian =
Object.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB);

View File

@ -415,6 +415,19 @@
# ELF-MIPSEL-NEXT: - Offset: 0x2C
# ELF-MIPSEL-NEXT: Symbol: SomeOtherFunction
# ELF-MIPSEL-NEXT: Type: R_MIPS_CALL16
# ELF-MIPSEL-NEXT: - Type: SectionHeaderTable
# ELF-MIPSEL-NEXT: Sections:
# ELF-MIPSEL-NEXT: - Name: .text
# ELF-MIPSEL-NEXT: - Name: .rel.text
# ELF-MIPSEL-NEXT: - Name: .data
# ELF-MIPSEL-NEXT: - Name: .bss
# ELF-MIPSEL-NEXT: - Name: .mdebug.abi32
# ELF-MIPSEL-NEXT: - Name: .rodata.str1.1
# ELF-MIPSEL-NEXT: - Name: .reginfo
# ELF-MIPSEL-NEXT: - Name: .MIPS.abiflags
# ELF-MIPSEL-NEXT: - Name: .shstrtab
# ELF-MIPSEL-NEXT: - Name: .symtab
# ELF-MIPSEL-NEXT: - Name: .strtab
# ELF-MIPSEL-NEXT: Symbols:
# ELF-MIPSEL-NEXT: - Name: trivial.ll
# ELF-MIPSEL-NEXT: Type: STT_FILE
@ -460,19 +473,6 @@
# ELF-MIPSEL-NEXT: Binding: STB_GLOBAL
# ELF-MIPSEL-NEXT: - Name: puts
# ELF-MIPSEL-NEXT: Binding: STB_GLOBAL
# ELF-MIPSEL-NEXT: SectionHeaderTable:
# ELF-MIPSEL-NEXT: Sections:
# ELF-MIPSEL-NEXT: - Name: .text
# ELF-MIPSEL-NEXT: - Name: .rel.text
# ELF-MIPSEL-NEXT: - Name: .data
# ELF-MIPSEL-NEXT: - Name: .bss
# ELF-MIPSEL-NEXT: - Name: .mdebug.abi32
# ELF-MIPSEL-NEXT: - Name: .rodata.str1.1
# ELF-MIPSEL-NEXT: - Name: .reginfo
# ELF-MIPSEL-NEXT: - Name: .MIPS.abiflags
# ELF-MIPSEL-NEXT: - Name: .shstrtab
# ELF-MIPSEL-NEXT: - Name: .symtab
# ELF-MIPSEL-NEXT: - Name: .strtab
# ELF-MIPSEL-NEXT: ...
# RUN: obj2yaml %p/Inputs/trivial-object-test.elf-mips64el | FileCheck %s --check-prefix ELF-MIPS64EL
@ -514,6 +514,17 @@
# ELF-MIPS64EL-NEXT: Relocations:
# ELF-MIPS64EL-NEXT: - Symbol: zed
# ELF-MIPS64EL-NEXT: Type: R_MIPS_64
# ELF-MIPS64EL-NEXT: - Type: SectionHeaderTable
# ELF-MIPS64EL-NEXT: Sections:
# ELF-MIPS64EL-NEXT: - Name: .text
# ELF-MIPS64EL-NEXT: - Name: .data
# ELF-MIPS64EL-NEXT: - Name: .rela.data
# ELF-MIPS64EL-NEXT: - Name: .bss
# ELF-MIPS64EL-NEXT: - Name: .MIPS.options
# ELF-MIPS64EL-NEXT: - Name: .pdr
# ELF-MIPS64EL-NEXT: - Name: .shstrtab
# ELF-MIPS64EL-NEXT: - Name: .symtab
# ELF-MIPS64EL-NEXT: - Name: .strtab
# ELF-MIPS64EL-NEXT: Symbols:
# ELF-MIPS64EL-NEXT: - Name: .text
# ELF-MIPS64EL-NEXT: Type: STT_SECTION
@ -534,17 +545,6 @@
# ELF-MIPS64EL-NEXT: Section: .pdr
# ELF-MIPS64EL-NEXT: - Name: zed
# ELF-MIPS64EL-NEXT: Binding: STB_GLOBAL
# ELF-MIPS64EL-NEXT: SectionHeaderTable:
# ELF-MIPS64EL-NEXT: Sections:
# ELF-MIPS64EL-NEXT: - Name: .text
# ELF-MIPS64EL-NEXT: - Name: .data
# ELF-MIPS64EL-NEXT: - Name: .rela.data
# ELF-MIPS64EL-NEXT: - Name: .bss
# ELF-MIPS64EL-NEXT: - Name: .MIPS.options
# ELF-MIPS64EL-NEXT: - Name: .pdr
# ELF-MIPS64EL-NEXT: - Name: .shstrtab
# ELF-MIPS64EL-NEXT: - Name: .symtab
# ELF-MIPS64EL-NEXT: - Name: .strtab
# ELF-MIPS64EL-NEXT: ...
# RUN: yaml2obj %s -o %t-x86-64

View File

@ -447,6 +447,8 @@ Sections:
Flags: [ SHF_ALLOC ]
Address: 0x300
Offset: 0x300
- Type: SectionHeaderTable
NoHeaders: true
DynamicSymbols:
- Name: foo
ProgramHeaders:
@ -457,5 +459,3 @@ ProgramHeaders:
- Type: PT_DYNAMIC
FirstSec: .dynamic
LastSec: .dynamic
SectionHeaderTable:
NoHeaders: true

View File

@ -50,6 +50,8 @@ Sections:
Value: 0x0
- Name: .dynsym
Type: SHT_DYNSYM
- Type: SectionHeaderTable
NoHeaders: true
DynamicSymbols:
- Name: foo
ProgramHeaders:
@ -59,5 +61,3 @@ ProgramHeaders:
- Type: PT_DYNAMIC
FirstSec: .dynamic
LastSec: .dynamic
SectionHeaderTable:
NoHeaders: true

View File

@ -215,8 +215,9 @@ FileHeader:
## The index of the section name string table is too large.
## The section would be past the EOF.
EShStrNdx: [[SHSTRNDX=0x3000]]
SectionHeaderTable:
NoHeaders: true
Sections:
- Type: SectionHeaderTable
NoHeaders: true
## Check we don't dump anything except the file header when the section header table can't be read.

View File

@ -113,8 +113,8 @@ Sections:
Value: 0x0
- Tag: DT_NULL
Value: 0x0
SectionHeaderTable:
NoHeaders: [[NOHEADERS=false]]
- Type: SectionHeaderTable
NoHeaders: [[NOHEADERS=false]]
ProgramHeaders:
- Type: PT_LOAD
FirstSec: .hash

View File

@ -137,10 +137,10 @@ Sections:
Entries:
- Tag: DT_NULL
Value: 0
- Type: SectionHeaderTable
NoHeaders: [[NOHEADERS=false]]
ProgramHeaders:
- Type: PT_DYNAMIC
FileSize: [[FILESIZE=<none>]]
FirstSec: .dynamic
LastSec: .dynamic
SectionHeaderTable:
NoHeaders: [[NOHEADERS=false]]

View File

@ -313,6 +313,8 @@ Sections:
Entries: [ 0, 1 ]
Offset: 0x2000
Address: 0x2000
- Type: SectionHeaderTable
NoHeaders: true
DynamicSymbols:
- Name: dynsym1
Index: SHN_XINDEX
@ -327,5 +329,3 @@ ProgramHeaders:
VAddr: 0x1000
FirstSec: .dynamic
LastSec: .dynamic
SectionHeaderTable:
NoHeaders: true

View File

@ -36,17 +36,17 @@
# BASIC-NEXT: Type: SHT_PROGBITS
# BASIC-NEXT: AddressAlign: 0x100000000
# BASIC-NEXT: Offset: 0x210
# HEADERS-NEXT: SectionHeaderTable:
# HEADERS-NEXT: Sections:
# HEADERS-NEXT: - Name: .bar4
# HEADERS-NEXT: - Name: .bar3
# HEADERS-NEXT: - Name: .bar2
# HEADERS-NEXT: - Name: .bar1
# HEADERS-NEXT: - Name: .foo3
# HEADERS-NEXT: - Name: .foo2
# HEADERS-NEXT: - Name: .foo1
# HEADERS-NEXT: - Name: .strtab
# HEADERS-NEXT: - Name: .shstrtab
# HEADERS-NEXT: - Type: SectionHeaderTable
# HEADERS-NEXT: Sections:
# HEADERS-NEXT: - Name: .bar4
# HEADERS-NEXT: - Name: .bar3
# HEADERS-NEXT: - Name: .bar2
# HEADERS-NEXT: - Name: .bar1
# HEADERS-NEXT: - Name: .foo3
# HEADERS-NEXT: - Name: .foo2
# HEADERS-NEXT: - Name: .foo1
# HEADERS-NEXT: - Name: .strtab
# HEADERS-NEXT: - Name: .shstrtab
# BASIC-NEXT: ...
--- !ELF
@ -103,18 +103,18 @@ Sections:
Type: SHT_PROGBITS
AddressAlign: 0x100000000
Offset: 0x210
SectionHeaderTable:
Sections:
- Type: SectionHeaderTable
Sections:
## By default we have the same order of sections as defined by the "Sections" key.
- Name: [[SEC1=.foo1]]
- Name: [[SEC2=.foo2]]
- Name: [[SEC3=.foo3]]
- Name: [[SEC4=.bar1]]
- Name: [[SEC5=.bar2]]
- Name: [[SEC6=.bar3]]
- Name: [[SEC7=.bar4]]
- Name: .strtab
- Name: .shstrtab
- Name: [[SEC1=.foo1]]
- Name: [[SEC2=.foo2]]
- Name: [[SEC3=.foo3]]
- Name: [[SEC4=.bar1]]
- Name: [[SEC5=.bar2]]
- Name: [[SEC6=.bar3]]
- Name: [[SEC7=.bar4]]
- Name: .strtab
- Name: .shstrtab
## In this case we change the order of sections in the section header table.
## Check that we still dump offsets correctly.

View File

@ -32,13 +32,13 @@ Sections:
Type: SHT_PROGBITS
- Name: .bar
Type: SHT_PROGBITS
SectionHeaderTable:
Sections:
- Name: [[INCLUDED]]
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: [[EXCLUDED]]
- Type: SectionHeaderTable
Sections:
- Name: [[INCLUDED]]
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: [[EXCLUDED]]
## Check we report an error when a section is in both the "Sections" and "Excluded" lists at the same time.
## Also check that we report an error if a section is missing from the lists.
@ -66,13 +66,14 @@ FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
SectionHeaderTable:
Sections:
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: .strtab
- Name: .strtab
Sections:
- Type: SectionHeaderTable
Sections:
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: .strtab
- Name: .strtab
## Check that we are able to exclude all sections, except the implicit
## null section, with the use of the "Excluded" key.
@ -91,11 +92,12 @@ FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
SectionHeaderTable:
Sections: []
Excluded:
- Name: .strtab
- Name: .shstrtab
Sections:
- Type: SectionHeaderTable
Sections: []
Excluded:
- Name: .strtab
- Name: .shstrtab
## Case B: the "Sections" key is not present.
# RUN: yaml2obj %s --docnum=4 -o %t4
@ -106,10 +108,11 @@ FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
SectionHeaderTable:
Excluded:
- Name: .strtab
- Name: .shstrtab
Sections:
- Type: SectionHeaderTable
Excluded:
- Name: .strtab
- Name: .shstrtab
## Check how we handle cases when a section is excluded, but its section index is needed.
## The general rule is: when a section is explicitly linked with another section, which is
@ -134,13 +137,13 @@ Sections:
Link: .bar
- Name: .bar
Type: SHT_PROGBITS
SectionHeaderTable:
Sections:
- Name: .foo
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: .bar
- Type: SectionHeaderTable
Sections:
- Name: .foo
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: .bar
## Case B.1: check we report an error when a symbol table section has a Link field which
## points to an excluded section.
@ -160,13 +163,13 @@ Sections:
Link: .foo
- Name: .foo
Type: SHT_PROGBITS
SectionHeaderTable:
Sections:
- Name: [[NAME]]
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: .foo
- Type: SectionHeaderTable
Sections:
- Name: [[NAME]]
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: .foo
## Case B.2: check we do not link .dynsym with .dynstr implicitly when the latter is excluded.
# RUN: yaml2obj %s --docnum=7 -o %t5
@ -185,13 +188,13 @@ Sections:
Type: SHT_DYNSYM
- Name: .dynstr
Type: SHT_PROGBITS
SectionHeaderTable:
Sections:
- Name: .dynsym
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: .dynstr
- Type: SectionHeaderTable
Sections:
- Name: .dynsym
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: .dynstr
## Case B.3: check we do not link .symtab with .strtab implicitly when the latter is excluded.
# RUN: yaml2obj %s --docnum=8 -o %t6
@ -210,12 +213,12 @@ Sections:
Type: SHT_SYMTAB
- Name: .strtab
Type: SHT_PROGBITS
SectionHeaderTable:
Sections:
- Name: .symtab
- Name: .shstrtab
Excluded:
- Name: .strtab
- Type: SectionHeaderTable
Sections:
- Name: .symtab
- Name: .shstrtab
Excluded:
- Name: .strtab
## Case C: check we report an error when a debug section has a Link field which
## points to an excluded section.
@ -231,12 +234,12 @@ Sections:
- Name: .debug_unknown
Type: SHT_PROGBITS
Link: .strtab
SectionHeaderTable:
Sections:
- Name: .debug_unknown
- Name: .shstrtab
Excluded:
- Name: .strtab
- Type: SectionHeaderTable
Sections:
- Name: .debug_unknown
- Name: .shstrtab
Excluded:
- Name: .strtab
## Case D.1: check we report an error when a relocatable section has an Info field which
## points to an excluded section.
@ -253,12 +256,12 @@ Sections:
Type: SHT_RELA
Info: .strtab
Relocations: []
SectionHeaderTable:
Sections:
- Name: .rela
- Name: .shstrtab
Excluded:
- Name: .strtab
- Type: SectionHeaderTable
Sections:
- Name: .rela
- Name: .shstrtab
Excluded:
- Name: .strtab
## Case D.2: check we report an error when the SHT_REL[A] section is linked
## with an excluded section explicitly.
@ -277,13 +280,13 @@ Sections:
Relocations: []
- Name: .symtab
Type: SHT_PROGBITS
SectionHeaderTable:
Sections:
- Name: .rela
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: .symtab
- Type: SectionHeaderTable
Sections:
- Name: .rela
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: .symtab
## Case E: check we report an error when a symbol references an excluded section.
# RUN: not yaml2obj %s --docnum=12 -o /dev/null 2>&1 | \
@ -299,17 +302,17 @@ FileHeader:
Sections:
- Name: .foo
Type: SHT_PROGBITS
- Type: SectionHeaderTable
Sections:
- Name: .symtab
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: .foo
Symbols:
- Name: foo
Type: STT_OBJECT
Section: .foo
SectionHeaderTable:
Sections:
- Name: .symtab
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: .foo
## Case F.1: check we report an error when a group section
## contains an excluded section member.
@ -326,12 +329,12 @@ Sections:
Type: SHT_GROUP
Members:
- SectionOrType: .strtab
SectionHeaderTable:
Sections:
- Name: .group
- Name: .shstrtab
Excluded:
- Name: .strtab
- Type: SectionHeaderTable
Sections:
- Name: .group
- Name: .shstrtab
Excluded:
- Name: .strtab
## Case F.2: check we report an error when the group section is linked
## to an excluded section explicitly.
@ -350,13 +353,13 @@ Sections:
Members: []
- Name: .symtab
Type: SHT_SYMTAB
SectionHeaderTable:
Sections:
- Name: .group
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: .symtab
- Type: SectionHeaderTable
Sections:
- Name: .group
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: .symtab
## Case G: check we do not link SHT_LLVM_CALL_GRAPH_PROFILE/SHT_LLVM_ADDRSIG/SHT_GROUP/SHT_REL[A] sections
## with .symtab implicitly when the latter is excluded.
@ -389,16 +392,16 @@ Sections:
Relocations: []
- Name: .symtab
Type: SHT_SYMTAB
SectionHeaderTable:
Sections:
- Name: .cgp
- Name: .llvm_addrsig
- Name: .group
- Name: .rela
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: .symtab
- Type: SectionHeaderTable
Sections:
- Name: .cgp
- Name: .llvm_addrsig
- Name: .group
- Name: .rela
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: .symtab
## Case H: check we do not link SHT_HASH/SHT_GNU_HASH sections with .dynsym
## implicitly when the latter is excluded.
@ -423,14 +426,14 @@ Sections:
Content: ""
- Name: .dynsym
Type: SHT_DYNSYM
SectionHeaderTable:
Sections:
- Name: .hash
- Name: .gnu_hash
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: .dynsym
- Type: SectionHeaderTable
Sections:
- Name: .hash
- Name: .gnu_hash
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: .dynsym
## Case I: document the case when an excluded section is explicitly linked to another excluded section.
## We report an error in this case, because:
@ -454,13 +457,13 @@ Sections:
- Name: .bar
Type: SHT_PROGBITS
Link: .foo
SectionHeaderTable:
Sections:
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: .foo
- Name: .bar
- Type: SectionHeaderTable
Sections:
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: .foo
- Name: .bar
## Check we set e_shstrndx field to 0 when the section header string table is excluded.
## Check that the e_shnum field is adjusted properly when a section is removed.
@ -475,22 +478,24 @@ FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
SectionHeaderTable:
Sections:
- Name: .strtab
Excluded:
- Name: .shstrtab
Sections:
- Type: SectionHeaderTable
Sections:
- Name: .strtab
Excluded:
- Name: .shstrtab
## Check we do not allow using "Excluded" together with "NoHeaders".
# RUN: not yaml2obj %s --docnum=19 -DNOHEADERS=true -o /dev/null 2>&1 | FileCheck %s --check-prefix=NOHEADERS
# RUN: not yaml2obj %s --docnum=19 -DNOHEADERS=false -o /dev/null 2>&1 | FileCheck %s --check-prefix=NOHEADERS
# NOHEADERS: NoHeaders can't be used together with Sections/Excluded
# NOHEADERS: NoHeaders can't be used together with Offset/Sections/Excluded
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
SectionHeaderTable:
NoHeaders: [[NOHEADERS]]
Excluded: []
Sections:
- Type: SectionHeaderTable
NoHeaders: [[NOHEADERS]]
Excluded: []

View File

@ -34,13 +34,13 @@ Sections:
- Name: .section.foo
Type: SHT_PROGBITS
Size: 0x40
SectionHeaderTable:
Sections:
- Name: [[SEC1]]
- Name: [[SEC2]]
- Name: [[SEC3]]
- Name: .strtab
- Name: .shstrtab
- Type: SectionHeaderTable
Sections:
- Name: [[SEC1]]
- Name: [[SEC2]]
- Name: [[SEC3]]
- Name: .strtab
- Name: .shstrtab
## Show we are able to reorder sections.
# RUN: yaml2obj %s -o %t2 -DSEC3=".section (1)" -DSEC2=".section (2)" -DSEC1=".section.foo"
@ -93,8 +93,8 @@ FileHeader:
Sections:
- Name: .foo
Type: SHT_PROGBITS
SectionHeaderTable:
Sections: []
- Type: SectionHeaderTable
Sections: []
## Test that we are able to use "NoHeaders" property to produce an empty section header table.
# RUN: yaml2obj %s --docnum=3 -DNOHEADERS=true -o %t3.1
@ -113,8 +113,8 @@ FileHeader:
Sections:
- Name: .foo
Type: SHT_PROGBITS
SectionHeaderTable:
NoHeaders: [[NOHEADERS]]
- Type: SectionHeaderTable
NoHeaders: [[NOHEADERS]]
## Test that we are able to set NoHeaders to false. In this case the tool produces an output
## as if there were no `SectionHeaderTable` key at all.
@ -137,7 +137,7 @@ SectionHeaderTable:
# RUN: not yaml2obj %s --docnum=4 -DNOHEADERS=true -o /dev/null 2>&1 | FileCheck %s --check-prefix=SECTIONS-NO-HEADERS
# RUN: not yaml2obj %s --docnum=4 -DNOHEADERS=false -o /dev/null 2>&1 | FileCheck %s --check-prefix=SECTIONS-NO-HEADERS
# SECTIONS-NO-HEADERS: error: NoHeaders can't be used together with Sections/Excluded
# SECTIONS-NO-HEADERS: error: NoHeaders can't be used together with Offset/Sections/Excluded
--- !ELF
FileHeader:
@ -147,12 +147,12 @@ FileHeader:
Sections:
- Name: .foo
Type: SHT_PROGBITS
SectionHeaderTable:
Sections: []
NoHeaders: [[NOHEADERS]]
- Type: SectionHeaderTable
Sections: []
NoHeaders: [[NOHEADERS]]
## Check that we do not allow an empty SectionHeaderTable tag and suggest to use an explicit syntax instead.
# RUN: not yaml2obj %s --docnum=5 -DVAL="" -o /dev/null 2>&1 | FileCheck %s --check-prefix=NO-VALUE
# RUN: not yaml2obj %s --docnum=5 -o /dev/null 2>&1 | FileCheck %s --check-prefix=NO-VALUE
# NO-VALUE: SectionHeaderTable can't be empty. Use 'NoHeaders' key to drop the section header table
@ -164,12 +164,7 @@ FileHeader:
Sections:
- Name: .foo
Type: SHT_PROGBITS
SectionHeaderTable: [[VAL]]
## An empty mapping is also not allowed for the SectionHeaderTable tag.
# RUN: not yaml2obj %s --docnum=5 -DVAL="[]" -o /dev/null 2>&1 | FileCheck %s --check-prefix=NOT-A-MAPPING
# NOT-A-MAPPING: error: not a mapping
- Type: SectionHeaderTable
## Test that we are still able to override e_shoff, e_shnum and e_shstrndx
## fields even when we do not produce section headers.
@ -188,8 +183,9 @@ FileHeader:
EShOff: 0x2
EShNum: 0x3
EShStrNdx: 0x4
SectionHeaderTable:
NoHeaders: true
Sections:
- Type: SectionHeaderTable
NoHeaders: true
## Check that section indices are updated properly in other places when we
## reorder sections in the section header table.
@ -233,15 +229,15 @@ Sections:
- Name: .another.2
Link: .bar
Type: SHT_PROGBITS
SectionHeaderTable:
Sections:
- Name: [[SEC1]]
- Name: [[SEC2]]
- Name: .another.1
- Name: .another.2
- Name: .symtab
- Name: .strtab
- Name: .shstrtab
- Type: SectionHeaderTable
Sections:
- Name: [[SEC1]]
- Name: [[SEC2]]
- Name: .another.1
- Name: .another.2
- Name: .symtab
- Name: .strtab
- Name: .shstrtab
Symbols:
- Name: foo
Section: .foo
@ -275,5 +271,142 @@ Sections:
## for writing the section header table.
Size: 0xFF
Offset: 0x100
SectionHeaderTable:
NoHeaders: true
- Type: SectionHeaderTable
NoHeaders: true
## Check we do not allow using "Offset" together with "NoHeaders".
# RUN: not yaml2obj %s --docnum=9 -DNOHEADERS=true -o /dev/null 2>&1 | FileCheck %s --check-prefix=NO-HEADERS-OFFSET
# RUN: not yaml2obj %s --docnum=9 -DNOHEADERS=false -o /dev/null 2>&1 | FileCheck %s --check-prefix=NO-HEADERS-OFFSET
# NO-HEADERS-OFFSET: error: NoHeaders can't be used together with Offset/Sections/Excluded
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Sections:
- Name: .foo
Type: SHT_PROGBITS
- Type: SectionHeaderTable
Offset: 0x1000
NoHeaders: [[NOHEADERS]]
## Check we can place the section header table before other sections.
# RUN: yaml2obj %s --docnum=10 -o %t10
# RUN: llvm-readelf --file-headers --sections %t10 | FileCheck %s --check-prefix=PLACE-BEFORE
# PLACE-BEFORE: Start of section headers: 64 (bytes into file)
# PLACE-BEFORE: Size of section headers: 64 (bytes)
# PLACE-BEFORE: Number of section headers: 4
# PLACE-BEFORE: Section Headers:
# PLACE-BEFORE: [Nr] Name Type Address Off Size
## 0x140 == Start of section headers (64) + Size of section headers (64) * Number of section headers (4);
# PLACE-BEFORE: [ 1] .foo PROGBITS 0000000000000000 000140 000000
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Sections:
- Type: SectionHeaderTable
Offset: [[OFFSET=<none>]]
Sections:
- Name: .foo
- Name: .strtab
- Name: .shstrtab
- Name: .foo
Type: SHT_PROGBITS
## Check we can use the Offset key to place the section header table at a different location.
# RUN: yaml2obj %s --docnum=10 -DOFFSET=0x1000 -o %t10.offset
# RUN: llvm-readelf --file-headers --sections %t10.offset | \
# RUN: FileCheck %s --check-prefix=PLACE-BEFORE-OFFSET
# PLACE-BEFORE-OFFSET: Start of section headers: 4096 (bytes into file)
# PLACE-BEFORE-OFFSET: Size of section headers: 64 (bytes)
# PLACE-BEFORE-OFFSET: Number of section headers: 4
# PLACE-BEFORE-OFFSET: Section Headers:
# PLACE-BEFORE-OFFSET: [Nr] Name Type Address Off Size
## 0x1100 == Start of section headers (0x1000) + Size of section headers (64) * Number of section headers (4);
# PLACE-BEFORE-OFFSET: [ 1] .foo PROGBITS 0000000000000000 001100 000000
## Check we can place the section header table somewhere in the middle of the sections list.
# RUN: yaml2obj %s --docnum=11 -o %t11
# RUN: llvm-readelf --sections %t11 | FileCheck %s --check-prefix=PLACE-AT-MIDDLE
# PLACE-AT-MIDDLE: There are 5 section headers, starting at offset 0x140:
# PLACE-AT-MIDDLE: [Nr] Name Type Address Off Size
# PLACE-AT-MIDDLE: [ 1] .foo PROGBITS 0000000000000000 000040 000100
## The section header table is placed here, at 0x40 + 0x100 == 0x140.
## The size of the table is 5 * 64 == 320 == 0x140.
## 0x140 + 0x140 == offset of the .bar section.
# PLACE-AT-MIDDLE-NEXT: [ 2] .bar PROGBITS 0000000000000000 000280 000200
# PLACE-AT-MIDDLE-NEXT: [ 3] .strtab STRTAB 0000000000000000 000480 000001
# PLACE-AT-MIDDLE-NEXT: [ 4] .shstrtab STRTAB 0000000000000000 000481 00001d
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Sections:
- Name: .foo
Type: SHT_PROGBITS
Size: 0x100
- Type: SectionHeaderTable
Sections:
- Name: .foo
- Name: .bar
- Name: .strtab
- Name: .shstrtab
- Name: .bar
Type: SHT_PROGBITS
Size: 0x200
## Check we don`t allow having multiple SectionHeaderTable chunks.
# RUN: not yaml2obj %s --docnum=12 -o /dev/null 2>&1 | FileCheck %s --check-prefix=MULTIPLE
# MULTIPLE: error: multiple section header tables are not allowed
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Sections:
- Type: SectionHeaderTable
Sections: []
- Type: SectionHeaderTable
Sections: []
## Check that we place implicit sections before the section header table
## when it is placed at the end explicitly.
# RUN: yaml2obj %s --docnum=13 -o %t13
# RUN: llvm-readelf --sections %t13 | FileCheck %s --check-prefix=IMPLICIT
# IMPLICIT: There are 3 section headers, starting at offset 0x58:
# IMPLICIT: [Nr] Name Type Address Off Size
# IMPLICIT: [ 1] .strtab STRTAB 0000000000000000 000040 000001
# IMPLICIT-NEXT: [ 2] .shstrtab STRTAB 0000000000000000 000041 000013
## The section header table is placed here, at 0x58.
## alignTo(8, 0x41 + 0x13) == 0x58.
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Sections:
- Type: SectionHeaderTable
Sections:
- Name: .strtab
- Name: .shstrtab

View File

@ -241,10 +241,10 @@ Sections:
Type: SHT_GNU_verdef
- Name: .dynstr
Type: SHT_STRTAB
SectionHeaderTable:
Sections:
- Name: .gnu.version_d
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: .dynstr
- Type: SectionHeaderTable
Sections:
- Name: .gnu.version_d
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: .dynstr

View File

@ -182,10 +182,10 @@ Sections:
Type: SHT_GNU_verneed
- Name: .dynstr
Type: SHT_STRTAB
SectionHeaderTable:
Sections:
- Name: .gnu.version_r
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: .dynstr
- Type: SectionHeaderTable
Sections:
- Name: .gnu.version_r
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: .dynstr

View File

@ -194,10 +194,10 @@ Sections:
Type: SHT_GNU_versym
- Name: .dynsym
Type: SHT_DYNSYM
SectionHeaderTable:
Sections:
- Name: .gnu.version
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: .dynsym
- Type: SectionHeaderTable
Sections:
- Name: .gnu.version
- Name: .strtab
- Name: .shstrtab
Excluded:
- Name: .dynsym

View File

@ -382,13 +382,18 @@ template <class ELFT> Expected<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
cast<ELFYAML::Section>(B.get())->OriginalSecNdx;
});
if (!SectionsSorted) {
Y->SectionHeaders.emplace();
Y->SectionHeaders->Sections.emplace();
std::unique_ptr<ELFYAML::SectionHeaderTable> SHT =
std::make_unique<ELFYAML::SectionHeaderTable>(/*IsImplicit=*/false);
SHT->Sections.emplace();
for (ELFYAML::Section *S : OriginalOrder)
Y->SectionHeaders->Sections->push_back({S->Name});
SHT->Sections->push_back({S->Name});
Chunks.push_back(std::move(SHT));
}
llvm::erase_if(Chunks, [this, &Y](const std::unique_ptr<ELFYAML::Chunk> &C) {
if (isa<ELFYAML::SectionHeaderTable>(*C.get()))
return false;
const ELFYAML::Section &S = cast<ELFYAML::Section>(*C.get());
return !shouldPrintSection(S, Sections[S.OriginalSecNdx], Y->DWARF);
});