forked from OSchip/llvm-project
[yaml2obj] - Introduce the "Offset" property for sections.
Currently there is no good way to set a physical offset for a section: * We have the `ShOffset` that allows to override the `sh_offset`, but it does not affect the real data written. * We can use a `Filler` to create an artificial gap, but it is more like a hack rather than a proper solution for this problem. This patch adds the `Offset` property which allows setting physical offsets for sections. It also generalizes the code, so that we set sh_offset field in one place Differential revision: https://reviews.llvm.org/D78927
This commit is contained in:
parent
7fc5f28068
commit
7ccae2cece
|
@ -172,6 +172,7 @@ struct Section : public Chunk {
|
|||
StringRef Link;
|
||||
llvm::yaml::Hex64 AddressAlign;
|
||||
Optional<llvm::yaml::Hex64> EntSize;
|
||||
Optional<llvm::yaml::Hex64> Offset;
|
||||
|
||||
// Usually sections are not created implicitly, but loaded from YAML.
|
||||
// When they are, this flag is used to signal about that.
|
||||
|
|
|
@ -41,17 +41,14 @@ public:
|
|||
ContiguousBlobAccumulator(uint64_t InitialOffset_)
|
||||
: InitialOffset(InitialOffset_), Buf(), OS(Buf) {}
|
||||
|
||||
template <class Integer>
|
||||
raw_ostream &getOSAndAlignedOffset(Integer &Offset, unsigned Align) {
|
||||
Offset = padToAlignment(Align);
|
||||
return OS;
|
||||
}
|
||||
uint64_t getOffset() const { return InitialOffset + OS.tell(); }
|
||||
raw_ostream &getOS() { return OS; }
|
||||
|
||||
/// \returns The new offset.
|
||||
uint64_t padToAlignment(unsigned Align) {
|
||||
if (Align == 0)
|
||||
Align = 1;
|
||||
uint64_t CurrentOffset = InitialOffset + OS.tell();
|
||||
uint64_t CurrentOffset = getOffset();
|
||||
uint64_t AlignedOffset = alignTo(CurrentOffset, Align);
|
||||
OS.write_zeros(AlignedOffset - CurrentOffset);
|
||||
return AlignedOffset; // == CurrentOffset;
|
||||
|
@ -221,6 +218,9 @@ template <class ELFT> class ELFState {
|
|||
|
||||
void assignSectionAddress(Elf_Shdr &SHeader, ELFYAML::Section *YAMLSec);
|
||||
|
||||
uint64_t alignToOffset(ContiguousBlobAccumulator &CBA, uint64_t Align,
|
||||
llvm::Optional<llvm::yaml::Hex64> Offset);
|
||||
|
||||
public:
|
||||
static bool writeELF(raw_ostream &OS, ELFYAML::Object &Doc,
|
||||
yaml::ErrorHandler EH);
|
||||
|
@ -300,10 +300,10 @@ void ELFState<ELFT>::writeELFHeader(ContiguousBlobAccumulator &CBA, raw_ostream
|
|||
|
||||
Header.e_shentsize =
|
||||
Doc.Header.SHEntSize ? (uint16_t)*Doc.Header.SHEntSize : sizeof(Elf_Shdr);
|
||||
// Immediately following the ELF header and program headers.
|
||||
// Align the start of the section header and write the ELF header.
|
||||
uint64_t SHOff;
|
||||
CBA.getOSAndAlignedOffset(SHOff, sizeof(typename ELFT::uint));
|
||||
// Align the start of the section header table, which is written after all
|
||||
// other sections to the end of the file.
|
||||
uint64_t SHOff =
|
||||
alignToOffset(CBA, sizeof(typename ELFT::uint), /*Offset=*/None);
|
||||
Header.e_shoff =
|
||||
Doc.Header.SHOff ? typename ELFT::uint(*Doc.Header.SHOff) : SHOff;
|
||||
Header.e_shnum =
|
||||
|
@ -418,6 +418,7 @@ void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
|
|||
size_t SecNdx = -1;
|
||||
for (const std::unique_ptr<ELFYAML::Chunk> &D : Doc.Chunks) {
|
||||
if (auto S = dyn_cast<ELFYAML::Fill>(D.get())) {
|
||||
S->ShOffset = alignToOffset(CBA, /*Align=*/1, /*Offset=*/None);
|
||||
writeFill(*S, CBA);
|
||||
LocationCounter += S->Size;
|
||||
continue;
|
||||
|
@ -447,12 +448,18 @@ void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
|
|||
SHeader.sh_flags = *Sec->Flags;
|
||||
SHeader.sh_addralign = Sec->AddressAlign;
|
||||
|
||||
// Set the offset for all sections, except the SHN_UNDEF section with index
|
||||
// 0 when not explicitly requested.
|
||||
bool IsFirstUndefSection = SecNdx == 0;
|
||||
if (!IsFirstUndefSection || Sec->Offset)
|
||||
SHeader.sh_offset = alignToOffset(CBA, SHeader.sh_addralign, Sec->Offset);
|
||||
|
||||
assignSectionAddress(SHeader, Sec);
|
||||
|
||||
if (!Sec->Link.empty())
|
||||
SHeader.sh_link = toSectionIndex(Sec->Link, Sec->Name);
|
||||
|
||||
if (SecNdx == 0) {
|
||||
if (IsFirstUndefSection) {
|
||||
if (auto RawSec = dyn_cast<ELFYAML::RawContentSection>(Sec)) {
|
||||
// We do not write any content for special SHN_UNDEF section.
|
||||
if (RawSec->Size)
|
||||
|
@ -475,11 +482,9 @@ void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
|
|||
} else if (auto S = dyn_cast<ELFYAML::MipsABIFlags>(Sec)) {
|
||||
writeSectionContent(SHeader, *S, CBA);
|
||||
} else if (auto S = dyn_cast<ELFYAML::NoBitsSection>(Sec)) {
|
||||
// SHT_NOBITS sections do not have any content to write.
|
||||
SHeader.sh_entsize = 0;
|
||||
SHeader.sh_size = S->Size;
|
||||
// SHT_NOBITS section does not have content
|
||||
// so just to setup the section offset.
|
||||
CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
|
||||
} else if (auto S = dyn_cast<ELFYAML::DynamicSection>(Sec)) {
|
||||
writeSectionContent(SHeader, *S, CBA);
|
||||
} else if (auto S = dyn_cast<ELFYAML::SymverSection>(Sec)) {
|
||||
|
@ -663,7 +668,9 @@ void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader,
|
|||
|
||||
assignSectionAddress(SHeader, YAMLSec);
|
||||
|
||||
auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
|
||||
SHeader.sh_offset = alignToOffset(CBA, SHeader.sh_addralign, /*Offset=*/None);
|
||||
raw_ostream &OS = CBA.getOS();
|
||||
|
||||
if (RawSec && (RawSec->Content || RawSec->Size)) {
|
||||
assert(Symbols.empty());
|
||||
SHeader.sh_size = writeContent(OS, RawSec->Content, RawSec->Size);
|
||||
|
@ -689,7 +696,9 @@ void ELFState<ELFT>::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name,
|
|||
ELFYAML::RawContentSection *RawSec =
|
||||
dyn_cast_or_null<ELFYAML::RawContentSection>(YAMLSec);
|
||||
|
||||
auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
|
||||
SHeader.sh_offset = alignToOffset(CBA, SHeader.sh_addralign, /*Offset=*/None);
|
||||
raw_ostream &OS = CBA.getOS();
|
||||
|
||||
if (RawSec && (RawSec->Content || RawSec->Size)) {
|
||||
SHeader.sh_size = writeContent(OS, RawSec->Content, RawSec->Size);
|
||||
} else {
|
||||
|
@ -809,9 +818,7 @@ template <class ELFT>
|
|||
void ELFState<ELFT>::writeSectionContent(
|
||||
Elf_Shdr &SHeader, const ELFYAML::RawContentSection &Section,
|
||||
ContiguousBlobAccumulator &CBA) {
|
||||
raw_ostream &OS =
|
||||
CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
|
||||
SHeader.sh_size = writeContent(OS, Section.Content, Section.Size);
|
||||
SHeader.sh_size = writeContent(CBA.getOS(), Section.Content, Section.Size);
|
||||
|
||||
if (Section.EntSize)
|
||||
SHeader.sh_entsize = *Section.EntSize;
|
||||
|
@ -850,7 +857,7 @@ void ELFState<ELFT>::writeSectionContent(
|
|||
if (!Section.RelocatableSec.empty())
|
||||
SHeader.sh_info = toSectionIndex(Section.RelocatableSec, Section.Name);
|
||||
|
||||
auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
|
||||
raw_ostream &OS = CBA.getOS();
|
||||
for (const auto &Rel : Section.Relocations) {
|
||||
unsigned SymIdx = Rel.Symbol ? toSymbolIndex(*Rel.Symbol, Section.Name,
|
||||
Section.Link == ".dynsym")
|
||||
|
@ -876,11 +883,10 @@ template <class ELFT>
|
|||
void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
|
||||
const ELFYAML::RelrSection &Section,
|
||||
ContiguousBlobAccumulator &CBA) {
|
||||
raw_ostream &OS =
|
||||
CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
|
||||
SHeader.sh_entsize =
|
||||
Section.EntSize ? uint64_t(*Section.EntSize) : sizeof(Elf_Relr);
|
||||
|
||||
raw_ostream &OS = CBA.getOS();
|
||||
if (Section.Content) {
|
||||
SHeader.sh_size = writeContent(OS, Section.Content, None);
|
||||
return;
|
||||
|
@ -903,11 +909,8 @@ template <class ELFT>
|
|||
void ELFState<ELFT>::writeSectionContent(
|
||||
Elf_Shdr &SHeader, const ELFYAML::SymtabShndxSection &Shndx,
|
||||
ContiguousBlobAccumulator &CBA) {
|
||||
raw_ostream &OS =
|
||||
CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
|
||||
|
||||
for (uint32_t E : Shndx.Entries)
|
||||
support::endian::write<uint32_t>(OS, E, ELFT::TargetEndianness);
|
||||
support::endian::write<uint32_t>(CBA.getOS(), E, ELFT::TargetEndianness);
|
||||
|
||||
SHeader.sh_entsize = Shndx.EntSize ? (uint64_t)*Shndx.EntSize : 4;
|
||||
SHeader.sh_size = Shndx.Entries.size() * SHeader.sh_entsize;
|
||||
|
@ -931,9 +934,7 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
|
|||
SHeader.sh_info =
|
||||
toSymbolIndex(*Section.Signature, Section.Name, /*IsDynamic=*/false);
|
||||
|
||||
raw_ostream &OS =
|
||||
CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
|
||||
|
||||
raw_ostream &OS = CBA.getOS();
|
||||
for (const ELFYAML::SectionOrType &Member : Section.Members) {
|
||||
unsigned int SectionIndex = 0;
|
||||
if (Member.sectionNameOrType == "GRP_COMDAT")
|
||||
|
@ -948,8 +949,7 @@ template <class ELFT>
|
|||
void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
|
||||
const ELFYAML::SymverSection &Section,
|
||||
ContiguousBlobAccumulator &CBA) {
|
||||
raw_ostream &OS =
|
||||
CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
|
||||
raw_ostream &OS = CBA.getOS();
|
||||
for (uint16_t Version : Section.Entries)
|
||||
support::endian::write<uint16_t>(OS, Version, ELFT::TargetEndianness);
|
||||
|
||||
|
@ -961,9 +961,7 @@ template <class ELFT>
|
|||
void ELFState<ELFT>::writeSectionContent(
|
||||
Elf_Shdr &SHeader, const ELFYAML::StackSizesSection &Section,
|
||||
ContiguousBlobAccumulator &CBA) {
|
||||
raw_ostream &OS =
|
||||
CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
|
||||
|
||||
raw_ostream &OS = CBA.getOS();
|
||||
if (Section.Content || Section.Size) {
|
||||
SHeader.sh_size = writeContent(OS, Section.Content, Section.Size);
|
||||
return;
|
||||
|
@ -979,9 +977,7 @@ template <class ELFT>
|
|||
void ELFState<ELFT>::writeSectionContent(
|
||||
Elf_Shdr &SHeader, const ELFYAML::LinkerOptionsSection &Section,
|
||||
ContiguousBlobAccumulator &CBA) {
|
||||
raw_ostream &OS =
|
||||
CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
|
||||
|
||||
raw_ostream &OS = CBA.getOS();
|
||||
if (Section.Content) {
|
||||
SHeader.sh_size = writeContent(OS, Section.Content, None);
|
||||
return;
|
||||
|
@ -1003,9 +999,7 @@ template <class ELFT>
|
|||
void ELFState<ELFT>::writeSectionContent(
|
||||
Elf_Shdr &SHeader, const ELFYAML::DependentLibrariesSection &Section,
|
||||
ContiguousBlobAccumulator &CBA) {
|
||||
raw_ostream &OS =
|
||||
CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
|
||||
|
||||
raw_ostream &OS = CBA.getOS();
|
||||
if (Section.Content) {
|
||||
SHeader.sh_size = writeContent(OS, Section.Content, None);
|
||||
return;
|
||||
|
@ -1021,13 +1015,34 @@ void ELFState<ELFT>::writeSectionContent(
|
|||
}
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
uint64_t
|
||||
ELFState<ELFT>::alignToOffset(ContiguousBlobAccumulator &CBA, uint64_t Align,
|
||||
llvm::Optional<llvm::yaml::Hex64> Offset) {
|
||||
uint64_t CurrentOffset = CBA.getOffset();
|
||||
uint64_t AlignedOffset;
|
||||
|
||||
if (Offset) {
|
||||
if ((uint64_t)*Offset < CurrentOffset) {
|
||||
reportError("the 'Offset' value (0x" +
|
||||
Twine::utohexstr((uint64_t)*Offset) + ") goes backward");
|
||||
return CurrentOffset;
|
||||
}
|
||||
|
||||
// We ignore an alignment when an explicit offset has been requested.
|
||||
AlignedOffset = *Offset;
|
||||
} else {
|
||||
AlignedOffset = alignTo(CurrentOffset, std::max(Align, (uint64_t)1));
|
||||
}
|
||||
|
||||
CBA.getOS().write_zeros(AlignedOffset - CurrentOffset);
|
||||
return AlignedOffset;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void ELFState<ELFT>::writeSectionContent(
|
||||
Elf_Shdr &SHeader, const ELFYAML::CallGraphProfileSection &Section,
|
||||
ContiguousBlobAccumulator &CBA) {
|
||||
raw_ostream &OS =
|
||||
CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
|
||||
|
||||
if (Section.EntSize)
|
||||
SHeader.sh_entsize = *Section.EntSize;
|
||||
else
|
||||
|
@ -1037,6 +1052,7 @@ void ELFState<ELFT>::writeSectionContent(
|
|||
if (Section.Link.empty() && SN2I.lookup(".symtab", Link))
|
||||
SHeader.sh_link = Link;
|
||||
|
||||
raw_ostream &OS = CBA.getOS();
|
||||
if (Section.Content) {
|
||||
SHeader.sh_size = writeContent(OS, Section.Content, None);
|
||||
return;
|
||||
|
@ -1060,13 +1076,11 @@ template <class ELFT>
|
|||
void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
|
||||
const ELFYAML::HashSection &Section,
|
||||
ContiguousBlobAccumulator &CBA) {
|
||||
raw_ostream &OS =
|
||||
CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
|
||||
|
||||
unsigned Link = 0;
|
||||
if (Section.Link.empty() && SN2I.lookup(".dynsym", Link))
|
||||
SHeader.sh_link = Link;
|
||||
|
||||
raw_ostream &OS = CBA.getOS();
|
||||
if (Section.Content || Section.Size) {
|
||||
SHeader.sh_size = writeContent(OS, Section.Content, Section.Size);
|
||||
return;
|
||||
|
@ -1093,11 +1107,10 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
|
|||
ContiguousBlobAccumulator &CBA) {
|
||||
typedef typename ELFT::Verdef Elf_Verdef;
|
||||
typedef typename ELFT::Verdaux Elf_Verdaux;
|
||||
raw_ostream &OS =
|
||||
CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
|
||||
|
||||
SHeader.sh_info = Section.Info;
|
||||
|
||||
raw_ostream &OS = CBA.getOS();
|
||||
if (Section.Content) {
|
||||
SHeader.sh_size = writeContent(OS, Section.Content, None);
|
||||
return;
|
||||
|
@ -1146,9 +1159,9 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
|
|||
typedef typename ELFT::Verneed Elf_Verneed;
|
||||
typedef typename ELFT::Vernaux Elf_Vernaux;
|
||||
|
||||
auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
|
||||
SHeader.sh_info = Section.Info;
|
||||
|
||||
raw_ostream &OS = CBA.getOS();
|
||||
if (Section.Content) {
|
||||
SHeader.sh_size = writeContent(OS, Section.Content, None);
|
||||
return;
|
||||
|
@ -1205,7 +1218,6 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
|
|||
SHeader.sh_entsize = sizeof(Flags);
|
||||
SHeader.sh_size = SHeader.sh_entsize;
|
||||
|
||||
auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
|
||||
Flags.version = Section.Version;
|
||||
Flags.isa_level = Section.ISALevel;
|
||||
Flags.isa_rev = Section.ISARevision;
|
||||
|
@ -1217,7 +1229,7 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
|
|||
Flags.ases = Section.ASEs;
|
||||
Flags.flags1 = Section.Flags1;
|
||||
Flags.flags2 = Section.Flags2;
|
||||
OS.write((const char *)&Flags, sizeof(Flags));
|
||||
CBA.getOS().write((const char *)&Flags, sizeof(Flags));
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
|
@ -1241,8 +1253,7 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
|
|||
else
|
||||
SHeader.sh_entsize = sizeof(Elf_Dyn);
|
||||
|
||||
raw_ostream &OS =
|
||||
CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
|
||||
raw_ostream &OS = CBA.getOS();
|
||||
for (const ELFYAML::DynamicEntry &DE : Section.Entries) {
|
||||
support::endian::write<uintX_t>(OS, DE.Tag, ELFT::TargetEndianness);
|
||||
support::endian::write<uintX_t>(OS, DE.Val, ELFT::TargetEndianness);
|
||||
|
@ -1255,13 +1266,11 @@ template <class ELFT>
|
|||
void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
|
||||
const ELFYAML::AddrsigSection &Section,
|
||||
ContiguousBlobAccumulator &CBA) {
|
||||
raw_ostream &OS =
|
||||
CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
|
||||
|
||||
unsigned Link = 0;
|
||||
if (Section.Link.empty() && SN2I.lookup(".symtab", Link))
|
||||
SHeader.sh_link = Link;
|
||||
|
||||
raw_ostream &OS = CBA.getOS();
|
||||
if (Section.Content || Section.Size) {
|
||||
SHeader.sh_size = writeContent(OS, Section.Content, Section.Size);
|
||||
return;
|
||||
|
@ -1276,10 +1285,8 @@ template <class ELFT>
|
|||
void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
|
||||
const ELFYAML::NoteSection &Section,
|
||||
ContiguousBlobAccumulator &CBA) {
|
||||
raw_ostream &OS =
|
||||
CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
|
||||
raw_ostream &OS = CBA.getOS();
|
||||
uint64_t Offset = OS.tell();
|
||||
|
||||
if (Section.Content || Section.Size) {
|
||||
SHeader.sh_size = writeContent(OS, Section.Content, Section.Size);
|
||||
return;
|
||||
|
@ -1325,13 +1332,11 @@ template <class ELFT>
|
|||
void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
|
||||
const ELFYAML::GnuHashSection &Section,
|
||||
ContiguousBlobAccumulator &CBA) {
|
||||
raw_ostream &OS =
|
||||
CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
|
||||
|
||||
unsigned Link = 0;
|
||||
if (Section.Link.empty() && SN2I.lookup(".dynsym", Link))
|
||||
SHeader.sh_link = Link;
|
||||
|
||||
raw_ostream &OS = CBA.getOS();
|
||||
if (Section.Content) {
|
||||
SHeader.sh_size = writeContent(OS, Section.Content, None);
|
||||
return;
|
||||
|
@ -1388,8 +1393,7 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
|
|||
template <class ELFT>
|
||||
void ELFState<ELFT>::writeFill(ELFYAML::Fill &Fill,
|
||||
ContiguousBlobAccumulator &CBA) {
|
||||
raw_ostream &OS = CBA.getOSAndAlignedOffset(Fill.ShOffset, /*Align=*/1);
|
||||
|
||||
raw_ostream &OS = CBA.getOS();
|
||||
size_t PatternSize = Fill.Pattern ? Fill.Pattern->binary_size() : 0;
|
||||
if (!PatternSize) {
|
||||
OS.write_zeros(Fill.Size);
|
||||
|
|
|
@ -1052,6 +1052,7 @@ static void commonSectionMapping(IO &IO, ELFYAML::Section &Section) {
|
|||
IO.mapOptional("Link", Section.Link, StringRef());
|
||||
IO.mapOptional("AddressAlign", Section.AddressAlign, Hex64(0));
|
||||
IO.mapOptional("EntSize", Section.EntSize);
|
||||
IO.mapOptional("Offset", Section.Offset);
|
||||
|
||||
// obj2yaml does not dump these fields. They are expected to be empty when we
|
||||
// are producing YAML, because yaml2obj sets appropriate values for them
|
||||
|
|
|
@ -201,3 +201,28 @@ Sections:
|
|||
Size: 0x2
|
||||
ShOffset: 0x7
|
||||
ShSize: 0x8
|
||||
|
||||
## Check that we can set an offset for the SHT_NULL section explicitly using the "Offset" key.
|
||||
## Check it affects the section header table offset.
|
||||
# RUN: yaml2obj --docnum=10 %s -DOFFSET=0x100 -o %t10
|
||||
# RUN: llvm-readelf --headers --sections %t10 | FileCheck %s --check-prefix=EXPLICIT-OFFSET-A
|
||||
# RUN: yaml2obj --docnum=10 %s -DOFFSET=0x200 -o %t11
|
||||
# RUN: llvm-readelf --headers --sections %t11 | FileCheck %s --check-prefix=EXPLICIT-OFFSET-B
|
||||
|
||||
# EXPLICIT-OFFSET-A: Start of section headers: 280 (bytes into file)
|
||||
# EXPLICIT-OFFSET-A: [Nr] Name Type Address Off
|
||||
# EXPLICIT-OFFSET-A-NEXT: [ 0] NULL 0000000000000000 000100
|
||||
|
||||
# EXPLICIT-OFFSET-B: Start of section headers: 536 (bytes into file)
|
||||
# EXPLICIT-OFFSET-B: [Nr] Name Type Address Off
|
||||
# EXPLICIT-OFFSET-B-NEXT: [ 0] NULL 0000000000000000 000200
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Type: SHT_NULL
|
||||
Offset: [[OFFSET]]
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
## Check we are able to set an offset field for sections using the 'Offset' key.
|
||||
|
||||
## Show how the 'Offset' field key can be used.
|
||||
## Show that it can affect the layout of the rest of the file.
|
||||
|
||||
# RUN: yaml2obj --docnum=1 %s -o %t1
|
||||
# RUN: llvm-readelf --sections %t1 | FileCheck %s --check-prefix=DEFAULT
|
||||
|
||||
# DEFAULT: [Nr] Name Type Address Off
|
||||
# DEFAULT: [ 1] .foo PROGBITS 0000000000000000 000040
|
||||
# DEFAULT-NEXT: [ 2] .bar PROGBITS 0000000000000000 000048
|
||||
# DEFAULT-NEXT: [ 3] .strtab STRTAB 0000000000000000 000058
|
||||
# DEFAULT-NEXT: [ 4] .shstrtab STRTAB 0000000000000000 000059
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .foo
|
||||
Type: SHT_PROGBITS
|
||||
Size: 0x8
|
||||
- Name: .bar
|
||||
Type: SHT_PROGBITS
|
||||
Size: 0x10
|
||||
## It is a no-op. We set it to reduce amount
|
||||
## of differences with the second YAML below.
|
||||
AddressAlign: 0x0
|
||||
|
||||
## The same as previous, but an arbitrary 'Offset' is set for the .bar section.
|
||||
# RUN: yaml2obj --docnum=2 %s -o %t2 -DOFFSET=0x50 -DALIGN=0x0
|
||||
# RUN: llvm-readelf --sections %t2 | FileCheck %s --check-prefix=OFFSET
|
||||
|
||||
# OFFSET: [Nr] Name Type Address Off
|
||||
# OFFSET: [ 1] .foo PROGBITS 0000000000000000 000040
|
||||
# OFFSET-NEXT: [ 2] .bar PROGBITS 0000000000000000 000050
|
||||
# OFFSET-NEXT: [ 3] .strtab STRTAB 0000000000000000 000060
|
||||
# OFFSET-NEXT: [ 4] .shstrtab STRTAB 0000000000000000 000061
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .foo
|
||||
Type: SHT_PROGBITS
|
||||
Size: 0x8
|
||||
- Name: .bar
|
||||
Type: SHT_PROGBITS
|
||||
Size: 0x10
|
||||
Offset: [[OFFSET]]
|
||||
AddressAlign: [[ALIGN]]
|
||||
|
||||
## Set the 'Offset' to the same value as was set by default to show
|
||||
## that there is no difference in the output in this case.
|
||||
# RUN: yaml2obj --docnum=2 %s -o %t3 -DOFFSET=0x48 -DALIGN=0x0
|
||||
# RUN: cmp %t1 %t3
|
||||
|
||||
## Show that we can set an offset and an address alignment independently for a section.
|
||||
# RUN: yaml2obj --docnum=2 %s -o %t4 -DOFFSET=0x48 -DALIGN=0x5
|
||||
# RUN: llvm-readelf --sections %t4 | FileCheck %s --check-prefix=OFFSET-AND-ALIGN
|
||||
|
||||
# OFFSET-AND-ALIGN: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
|
||||
# OFFSET-AND-ALIGN: [ 2] .bar PROGBITS 0000000000000000 000048 000010 00 0 0 5
|
||||
|
||||
## Show we do not allow an 'Offset' to go backward.
|
||||
# RUN: not yaml2obj --docnum=2 %s -DOFFSET=0x47 -DALIGN=0x0 2>&1 | \
|
||||
# RUN: FileCheck %s --check-prefix=ERR-BACKWARD
|
||||
|
||||
# ERR-BACKWARD: error: the 'Offset' value (0x47) goes backward
|
||||
|
||||
## Show that the 'Offset' key can be used together with the 'ShOffset' key.
|
||||
|
||||
## Case 1: set the same value for 'Offset' and 'ShOffset' keys.
|
||||
# RUN: yaml2obj --docnum=3 %s -o %t5 -DSHOFFSET=0x100 -DOFFSET=0x100
|
||||
# RUN: llvm-readelf --headers --sections %t5 | FileCheck %s --check-prefix=BOTH-SAME
|
||||
|
||||
## The same offset as in the Case 3.
|
||||
# BOTH-SAME: Start of section headers: 288 (bytes into file)
|
||||
|
||||
# BOTH-SAME: [Nr] Name Type Address Off
|
||||
# BOTH-SAME: [ 1] .foo PROGBITS 0000000000000000 000100
|
||||
# BOTH-SAME-NEXT: [ 2] .bar PROGBITS 0000000000000000 000101
|
||||
# BOTH-SAME-NEXT: [ 3] .strtab STRTAB 0000000000000000 000102
|
||||
|
||||
## Case 2: set the 'Offset' value to be less than the 'ShOffset'.
|
||||
|
||||
# RUN: yaml2obj --docnum=3 %s -o %t6 -DSHOFFSET=0x100 -DOFFSET=0x90
|
||||
# RUN: llvm-readelf --headers --sections %t6 | FileCheck %s --check-prefix=BOTH-A
|
||||
|
||||
## 176 < 288 (start of section headers in Case 1).
|
||||
# BOTH-A: Start of section headers: 176 (bytes into file)
|
||||
|
||||
## Show that the 'Offset' field sets the physical offset in a file and the `ShOffset`
|
||||
## field only overrides the sh_offset value of the .foo section.
|
||||
# BOTH-A: [Nr] Name Type Address Off
|
||||
# BOTH-A: [ 1] .foo PROGBITS 0000000000000000 000100
|
||||
# BOTH-A-NEXT: [ 2] .bar PROGBITS 0000000000000000 000091
|
||||
# BOTH-A-NEXT: [ 3] .strtab STRTAB 0000000000000000 000092
|
||||
|
||||
## Case 3: set the 'Offset' value to be greater than the 'ShOffset' value.
|
||||
|
||||
# RUN: yaml2obj --docnum=3 %s -o %t7 -DSHOFFSET=0x90 -DOFFSET=0x100
|
||||
# RUN: llvm-readelf --sections --headers %t7 | FileCheck %s --check-prefix=BOTH-B
|
||||
|
||||
## The same offset as in Case 1.
|
||||
# BOTH-B: Start of section headers: 288 (bytes into file)
|
||||
|
||||
## Show that the 'Offset' field sets the physical offset in file and `ShOffset`
|
||||
## field only affects the sh_offset value of the .foo section (overrides it).
|
||||
# BOTH-B: [Nr] Name Type Address Off
|
||||
# BOTH-B: [ 1] .foo PROGBITS 0000000000000000 000090
|
||||
# BOTH-B-NEXT: [ 2] .bar PROGBITS 0000000000000000 000101
|
||||
# BOTH-B-NEXT: [ 3] .strtab STRTAB 0000000000000000 000102
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .foo
|
||||
Type: SHT_PROGBITS
|
||||
Size: 0x1
|
||||
ShOffset: [[SHOFFSET]]
|
||||
Offset: [[OFFSET]]
|
||||
- Name: .bar
|
||||
Type: SHT_PROGBITS
|
||||
Size: 0x1
|
Loading…
Reference in New Issue