[llvm] 7ccae2c - [yaml2obj] - Introduce the "Offset" property for sections.
Georgii Rymar via llvm-commits
llvm-commits at lists.llvm.org
Fri May 15 01:30:33 PDT 2020
Author: Georgii Rymar
Date: 2020-05-15T11:23:44+03:00
New Revision: 7ccae2cece72153d2c8210ef916bf0052da216ad
URL: https://github.com/llvm/llvm-project/commit/7ccae2cece72153d2c8210ef916bf0052da216ad
DIFF: https://github.com/llvm/llvm-project/commit/7ccae2cece72153d2c8210ef916bf0052da216ad.diff
LOG: [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
Added:
llvm/test/tools/yaml2obj/ELF/section-offset.yaml
Modified:
llvm/include/llvm/ObjectYAML/ELFYAML.h
llvm/lib/ObjectYAML/ELFEmitter.cpp
llvm/lib/ObjectYAML/ELFYAML.cpp
llvm/test/tools/yaml2obj/ELF/custom-null-section.yaml
Removed:
################################################################################
diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h
index 1b12a9b23130..7165caf531ba 100644
--- a/llvm/include/llvm/ObjectYAML/ELFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h
@@ -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.
diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp
index 531bcf5d8fb4..acdc3078ffb5 100644
--- a/llvm/lib/ObjectYAML/ELFEmitter.cpp
+++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp
@@ -41,17 +41,14 @@ class ContiguousBlobAccumulator {
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);
diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp
index 5adcb25dcec4..a3a0f56c66d8 100644
--- a/llvm/lib/ObjectYAML/ELFYAML.cpp
+++ b/llvm/lib/ObjectYAML/ELFYAML.cpp
@@ -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
diff --git a/llvm/test/tools/yaml2obj/ELF/custom-null-section.yaml b/llvm/test/tools/yaml2obj/ELF/custom-null-section.yaml
index 93346032b795..20ea73ec834e 100644
--- a/llvm/test/tools/yaml2obj/ELF/custom-null-section.yaml
+++ b/llvm/test/tools/yaml2obj/ELF/custom-null-section.yaml
@@ -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]]
diff --git a/llvm/test/tools/yaml2obj/ELF/section-offset.yaml b/llvm/test/tools/yaml2obj/ELF/section-offset.yaml
new file mode 100644
index 000000000000..90312ce273a6
--- /dev/null
+++ b/llvm/test/tools/yaml2obj/ELF/section-offset.yaml
@@ -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
diff erences 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
diff erence 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
More information about the llvm-commits
mailing list