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:
parent
a2eb0c1564
commit
fc47fdd498
@ -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);
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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
|
||||
|
@ -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]]
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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: []
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user