diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h --- a/llvm/include/llvm/ObjectYAML/ELFYAML.h +++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h @@ -161,6 +161,7 @@ ChunkKind Kind; StringRef Name; + Optional Offset; Chunk(ChunkKind K) : Kind(K) {} virtual ~Chunk(); @@ -173,7 +174,6 @@ StringRef Link; llvm::yaml::Hex64 AddressAlign; Optional EntSize; - Optional Offset; // Usually sections are not created implicitly, but loaded from YAML. // When they are, this flag is used to signal about that. @@ -213,11 +213,6 @@ Optional Pattern; llvm::yaml::Hex64 Size; - // We have to remember the offset of the fill, because it does not have - // a corresponding section header, unlike a section. We might need this - // information when writing the output. - uint64_t ShOffset; - Fill() : Chunk(ChunkKind::Fill) {} static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Fill; } diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp --- a/llvm/lib/ObjectYAML/ELFEmitter.cpp +++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -428,8 +428,8 @@ size_t SecNdx = -1; for (const std::unique_ptr &D : Doc.Chunks) { - if (auto S = dyn_cast(D.get())) { - S->ShOffset = alignToOffset(CBA, /*Align=*/1, /*Offset=*/None); + if (ELFYAML::Fill *S = dyn_cast(D.get())) { + S->Offset = alignToOffset(CBA, /*Align=*/1, S->Offset); writeFill(*S, CBA); LocationCounter += S->Size; continue; @@ -755,7 +755,7 @@ } if (ELFYAML::Fill *Fill = NameToFill.lookup(SecName.Section)) { - Ret.push_back({Fill->ShOffset, Fill->Size, llvm::ELF::SHT_PROGBITS, + Ret.push_back({*Fill->Offset, Fill->Size, llvm::ELF::SHT_PROGBITS, /*ShAddrAlign=*/1}); continue; } diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/llvm/lib/ObjectYAML/ELFYAML.cpp @@ -1174,6 +1174,7 @@ static void fillMapping(IO &IO, ELFYAML::Fill &Fill) { IO.mapOptional("Name", Fill.Name, StringRef()); IO.mapOptional("Pattern", Fill.Pattern); + IO.mapOptional("Offset", Fill.Offset); IO.mapRequired("Size", Fill.Size); } diff --git a/llvm/test/tools/yaml2obj/ELF/custom-fill.yaml b/llvm/test/tools/yaml2obj/ELF/custom-fill.yaml --- a/llvm/test/tools/yaml2obj/ELF/custom-fill.yaml +++ b/llvm/test/tools/yaml2obj/ELF/custom-fill.yaml @@ -294,3 +294,49 @@ - Type: PT_LOAD Sections: - Section: fill + +## Show that we can use the "Offset" key to set an arbitrary offset for a Fill. + +## 0x41 is the minimal possible valid offset for Fill, +## because the .foo section of size 0x1 is placed at 0x40. +# RUN: yaml2obj --docnum=11 -DOFFSET=0x41 -o %t11 %s +# RUN: llvm-readelf --section-headers %t11 | FileCheck %s --check-prefix=OFFSET-MIN + +## 0x123 is an arbitrary offset. +# RUN: yaml2obj --docnum=11 -DOFFSET=0x123 -o %t12 %s +# RUN: llvm-readelf --section-headers %t12 | FileCheck %s --check-prefix=OFFSET + +# OFFSET-MIN: Section Headers: +# OFFSET-MIN-NEXT: [Nr] Name Type Address Off Size +# OFFSET-MIN-NEXT: [ 0] NULL 0000000000000000 000000 000000 +# OFFSET-MIN-NEXT: [ 1] .foo PROGBITS 0000000000000000 000040 000001 +# OFFSET-MIN-NEXT: [ 2] .bar PROGBITS 0000000000000000 000042 000001 + +# OFFSET: Section Headers: +# OFFSET-NEXT: [Nr] Name Type Address Off Size +# OFFSET-NEXT: [ 0] NULL 0000000000000000 000000 000000 +# OFFSET-NEXT: [ 1] .foo PROGBITS 0000000000000000 000040 000001 +# OFFSET-NEXT: [ 2] .bar PROGBITS 0000000000000000 000124 000001 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .foo + Type: SHT_PROGBITS + Size: 1 + - Type: Fill + Pattern: "AA" + Size: 0x1 + Offset: [[OFFSET]] + - Name: .bar + Type: SHT_PROGBITS + Size: 1 + +## Show that the "Offset" value can't go backward. +# RUN: not yaml2obj --docnum=11 -DOFFSET=0x40 2>&1 %s | FileCheck %s --check-prefix=OFFSET-ERR + +# OFFSET-ERR: error: the 'Offset' value (0x40) goes backward