[llvm] Add support to YAML for program headers with content. (PR #192364)
Greg Clayton via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 16 13:48:26 PDT 2026
https://github.com/clayborg updated https://github.com/llvm/llvm-project/pull/192364
>From 0540a43b8232df6753110836b343202bc02b5b2c Mon Sep 17 00:00:00 2001
From: Greg Clayton <clayborg at gmail.com>
Date: Wed, 15 Apr 2026 17:20:51 -0700
Subject: [PATCH 1/2] Add support to YAML for program headers with content.
This patch adds the ability to convert ELF core files to/from yaml with obj2yaml and yaml2obj. ELF core files do not typically have sections, they only contain program headers and those program headers have contents. This patch allows program headers to have "Content:" like section headers can have:
ProgramHeaders:
- Type: PT_NOTE
Align: 0x4
MemSize: 0x0
Offset: 0x120
Content: 040000000800000001000000434F524500000000DEADBEEF11223344
- Type: PT_LOAD
Flags: [ PF_R ]
VAddr: 0x1000
PAddr: 0x0
Align: 0x4
Offset: 0x13C
Content: 0102030405060708090A0B0C0D0E0F10
The obj2yaml and yaml2obj will error out if a program header contains sections that have content. So only a program header can have content, or it can have sections that contain contents.
This will allow minimal core files to be created from YAML files easily for testing.
---
llvm/include/llvm/ObjectYAML/ELFYAML.h | 3 +
llvm/lib/ObjectYAML/ELFEmitter.cpp | 51 ++++++++-
llvm/lib/ObjectYAML/ELFYAML.cpp | 3 +
llvm/test/ObjectYAML/ELF/core-file.yaml | 146 ++++++++++++++++++++++++
llvm/tools/obj2yaml/elf2yaml.cpp | 89 +++++++++++----
5 files changed, 266 insertions(+), 26 deletions(-)
create mode 100644 llvm/test/ObjectYAML/ELF/core-file.yaml
diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h
index a8236ca37b5ed..51db4e0ab6186 100644
--- a/llvm/include/llvm/ObjectYAML/ELFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h
@@ -734,6 +734,9 @@ struct ProgramHeader {
std::optional<StringRef> FirstSec;
std::optional<StringRef> LastSec;
+ // Raw content for segments not backed by sections (e.g., core files).
+ std::optional<yaml::BinaryRef> Content;
+
// This vector contains all chunks from [FirstSec, LastSec].
std::vector<Chunk *> Chunks;
};
diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp
index 8530785d07c93..287ffebe30b79 100644
--- a/llvm/lib/ObjectYAML/ELFEmitter.cpp
+++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp
@@ -240,6 +240,8 @@ template <class ELFT> class ELFState {
void initDWARFSectionHeader(Elf_Shdr &SHeader, StringRef Name,
ContiguousBlobAccumulator &CBA,
ELFYAML::Section *YAMLSec);
+ void writeProgramHeaderContent(std::vector<Elf_Phdr> &PHeaders,
+ ContiguousBlobAccumulator &CBA);
void setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders,
std::vector<Elf_Shdr> &SHeaders);
@@ -419,10 +421,13 @@ ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH)
"DWARF output");
ImplicitSections.insert(StringRef(SecName).copy(StringAlloc));
}
- // TODO: Only create the .strtab here if any symbols have been requested.
- ImplicitSections.insert(".strtab");
- if (!SecHdrTable || !SecHdrTable->NoHeaders.value_or(false))
+ // Don't create implicit string table sections when there are no section
+ // headers (e.g., core files). The .strtab is only needed for symbols.
+ if (!SecHdrTable || !SecHdrTable->NoHeaders.value_or(false)) {
+ // TODO: Only create the .strtab here if any symbols have been requested.
+ ImplicitSections.insert(".strtab");
ImplicitSections.insert(SectionHeaderStringTableName);
+ }
// Insert placeholders for implicit sections that are not
// defined explicitly in YAML.
@@ -1174,12 +1179,46 @@ ELFState<ELFT>::getPhdrFragments(const ELFYAML::ProgramHeader &Phdr,
return Ret;
}
+template <class ELFT>
+void ELFState<ELFT>::writeProgramHeaderContent(
+ std::vector<Elf_Phdr> &PHeaders, ContiguousBlobAccumulator &CBA) {
+ uint32_t PhdrIdx = 0;
+ for (auto &YamlPhdr : Doc.ProgramHeaders) {
+ Elf_Phdr &PHeader = PHeaders[PhdrIdx++];
+ if (!YamlPhdr.Content)
+ continue;
+
+ uint64_t ContentSize = YamlPhdr.Content->binary_size();
+ // Pad to the explicit offset if specified, otherwise use current position.
+ if (YamlPhdr.Offset) {
+ uint64_t CurrentOffset = CBA.getOffset();
+ if (*YamlPhdr.Offset >= CurrentOffset)
+ CBA.writeZeros(*YamlPhdr.Offset - CurrentOffset);
+ }
+ uint64_t Offset = CBA.getOffset();
+ CBA.writeAsBinary(*YamlPhdr.Content);
+
+ PHeader.p_offset = YamlPhdr.Offset ? uint64_t(*YamlPhdr.Offset) : Offset;
+ PHeader.p_filesz =
+ YamlPhdr.FileSize ? uint64_t(*YamlPhdr.FileSize) : ContentSize;
+ PHeader.p_memsz = YamlPhdr.MemSize ? uint64_t(*YamlPhdr.MemSize)
+ : PHeader.p_filesz;
+ PHeader.p_align = YamlPhdr.Align ? uint64_t(*YamlPhdr.Align) : 1;
+ }
+}
+
template <class ELFT>
void ELFState<ELFT>::setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders,
std::vector<Elf_Shdr> &SHeaders) {
uint32_t PhdrIdx = 0;
for (auto &YamlPhdr : Doc.ProgramHeaders) {
Elf_Phdr &PHeader = PHeaders[PhdrIdx++];
+
+ // Program headers with Content were already handled by
+ // writeProgramHeaderContent().
+ if (YamlPhdr.Content)
+ continue;
+
std::vector<Fragment> Fragments = getPhdrFragments(YamlPhdr, SHeaders);
if (!llvm::is_sorted(Fragments, [](const Fragment &A, const Fragment &B) {
return A.Offset < B.Offset;
@@ -2124,10 +2163,14 @@ bool ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc,
// option to change this limitation.
ContiguousBlobAccumulator CBA(SectionContentBeginOffset, MaxSize);
+ // Write raw Content for program headers before section content so that
+ // the content ends up at the expected file offsets (e.g., core files).
+ State.writeProgramHeaderContent(PHeaders, CBA);
+
std::vector<Elf_Shdr> SHeaders;
State.initSectionHeaders(SHeaders, CBA);
- // Now we can decide segment offsets.
+ // Now we can decide segment offsets for section-based program headers.
State.setProgramHeaderLayout(PHeaders, SHeaders);
// Override section fields, if requested. This needs to happen after program
diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp
index f61ad8089c71b..7fa73f3d45152 100644
--- a/llvm/lib/ObjectYAML/ELFYAML.cpp
+++ b/llvm/lib/ObjectYAML/ELFYAML.cpp
@@ -1142,6 +1142,7 @@ void MappingTraits<ELFYAML::ProgramHeader>::mapping(
IO.mapOptional("FileSize", Phdr.FileSize);
IO.mapOptional("MemSize", Phdr.MemSize);
IO.mapOptional("Offset", Phdr.Offset);
+ IO.mapOptional("Content", Phdr.Content);
}
std::string MappingTraits<ELFYAML::ProgramHeader>::validate(
@@ -1150,6 +1151,8 @@ std::string MappingTraits<ELFYAML::ProgramHeader>::validate(
return "the \"LastSec\" key can't be used without the \"FirstSec\" key";
if (FileHdr.FirstSec && !FileHdr.LastSec)
return "the \"FirstSec\" key can't be used without the \"LastSec\" key";
+ if (FileHdr.Content && (FileHdr.FirstSec || FileHdr.LastSec))
+ return "\"Content\" can't be used with \"FirstSec\" or \"LastSec\"";
return "";
}
diff --git a/llvm/test/ObjectYAML/ELF/core-file.yaml b/llvm/test/ObjectYAML/ELF/core-file.yaml
new file mode 100644
index 0000000000000..ea158eaa6f711
--- /dev/null
+++ b/llvm/test/ObjectYAML/ELF/core-file.yaml
@@ -0,0 +1,146 @@
+# Test that yaml2obj can create ELF core files with program header Content
+# and that obj2yaml can round-trip them back to YAML.
+
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-readobj --file-header --program-headers %t | FileCheck -check-prefix=OBJ %s
+# RUN: obj2yaml %t | FileCheck -check-prefix=YAML %s
+# RUN: obj2yaml %t | yaml2obj - -o %t2
+# RUN: cmp %t %t2
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_CORE
+ Machine: EM_X86_64
+ EShEntSize: 0x0
+ EShNum: 0x0
+ProgramHeaders:
+ - Type: PT_NOTE
+ Align: 0x4
+ MemSize: 0x0
+ Offset: 0x120
+ Content: 040000000800000001000000434F524500000000DEADBEEF11223344
+ - Type: PT_LOAD
+ Flags: [ PF_R ]
+ VAddr: 0x1000
+ PAddr: 0x0
+ Align: 0x4
+ Offset: 0x13C
+ Content: '0102030405060708090A0B0C0D0E0F10'
+ - Type: PT_LOAD
+ Flags: [ PF_R, PF_W ]
+ VAddr: 0x2000
+ PAddr: 0x0
+ Align: 0x4
+ FileSize: 0x0
+ MemSize: 0x1000
+ Offset: 0x0
+ - Type: PT_LOAD
+ Flags: [ PF_R, PF_X ]
+ VAddr: 0x3000
+ PAddr: 0x0
+ Align: 0x4
+ Offset: 0x14C
+ Content: AABBCCDD
+Sections:
+ - Type: SectionHeaderTable
+ NoHeaders: true
+
+# OBJ: ElfHeader {
+# OBJ: Type: Core (0x4)
+# OBJ: Machine: EM_X86_64 (0x3E)
+# OBJ: SectionHeaderOffset: 0x0
+# OBJ: ProgramHeaderCount: 4
+# OBJ: SectionHeaderEntrySize: 0
+# OBJ: SectionHeaderCount: 0
+# OBJ: }
+# OBJ: ProgramHeaders [
+# OBJ: ProgramHeader {
+# OBJ: Type: PT_NOTE (0x4)
+# OBJ-NEXT: Offset: 0x120
+# OBJ-NEXT: VirtualAddress: 0x0
+# OBJ-NEXT: PhysicalAddress: 0x0
+# OBJ-NEXT: FileSize: 28
+# OBJ-NEXT: MemSize: 0
+# OBJ-NEXT: Flags [ (0x0)
+# OBJ-NEXT: ]
+# OBJ-NEXT: Alignment: 4
+# OBJ-NEXT: }
+# OBJ: ProgramHeader {
+# OBJ: Type: PT_LOAD (0x1)
+# OBJ-NEXT: Offset: 0x13C
+# OBJ-NEXT: VirtualAddress: 0x1000
+# OBJ-NEXT: PhysicalAddress: 0x0
+# OBJ-NEXT: FileSize: 16
+# OBJ-NEXT: MemSize: 16
+# OBJ-NEXT: Flags [ (0x4)
+# OBJ-NEXT: PF_R (0x4)
+# OBJ-NEXT: ]
+# OBJ-NEXT: Alignment: 4
+# OBJ-NEXT: }
+# OBJ: ProgramHeader {
+# OBJ: Type: PT_LOAD (0x1)
+# OBJ-NEXT: Offset: 0x0
+# OBJ-NEXT: VirtualAddress: 0x2000
+# OBJ-NEXT: PhysicalAddress: 0x0
+# OBJ-NEXT: FileSize: 0
+# OBJ-NEXT: MemSize: 4096
+# OBJ-NEXT: Flags [ (0x6)
+# OBJ-NEXT: PF_R (0x4)
+# OBJ-NEXT: PF_W (0x2)
+# OBJ-NEXT: ]
+# OBJ-NEXT: Alignment: 4
+# OBJ-NEXT: }
+# OBJ: ProgramHeader {
+# OBJ: Type: PT_LOAD (0x1)
+# OBJ-NEXT: Offset: 0x14C
+# OBJ-NEXT: VirtualAddress: 0x3000
+# OBJ-NEXT: PhysicalAddress: 0x0
+# OBJ-NEXT: FileSize: 4
+# OBJ-NEXT: MemSize: 4
+# OBJ-NEXT: Flags [ (0x5)
+# OBJ-NEXT: PF_R (0x4)
+# OBJ-NEXT: PF_X (0x1)
+# OBJ-NEXT: ]
+# OBJ-NEXT: Alignment: 4
+# OBJ-NEXT: }
+# OBJ-NEXT: ]
+
+# YAML: FileHeader:
+# YAML-NEXT: Class: ELFCLASS64
+# YAML-NEXT: Data: ELFDATA2LSB
+# YAML-NEXT: Type: ET_CORE
+# YAML-NEXT: Machine: EM_X86_64
+# YAML-NEXT: EShEntSize: 0x0
+# YAML-NEXT: ProgramHeaders:
+# YAML-NEXT: - Type: PT_NOTE
+# YAML-NEXT: Align: 0x4
+# YAML-NEXT: MemSize: 0x0
+# YAML-NEXT: Offset: 0x120
+# YAML-NEXT: Content: 040000000800000001000000434F524500000000DEADBEEF11223344
+# YAML-NEXT: - Type: PT_LOAD
+# YAML-NEXT: Flags: [ PF_R ]
+# YAML-NEXT: VAddr: 0x1000
+# YAML-NEXT: PAddr: 0x0
+# YAML-NEXT: Align: 0x4
+# YAML-NEXT: Offset: 0x13C
+# YAML-NEXT: Content: 0102030405060708090A0B0C0D0E0F10
+# YAML-NEXT: - Type: PT_LOAD
+# YAML-NEXT: Flags: [ PF_W, PF_R ]
+# YAML-NEXT: VAddr: 0x2000
+# YAML-NEXT: PAddr: 0x0
+# YAML-NEXT: Align: 0x4
+# YAML-NEXT: FileSize: 0x0
+# YAML-NEXT: MemSize: 0x1000
+# YAML-NEXT: Offset: 0x0
+# YAML-NEXT: - Type: PT_LOAD
+# YAML-NEXT: Flags: [ PF_X, PF_R ]
+# YAML-NEXT: VAddr: 0x3000
+# YAML-NEXT: PAddr: 0x0
+# YAML-NEXT: Align: 0x4
+# YAML-NEXT: Offset: 0x14C
+# YAML-NEXT: Content: AABBCCDD
+# YAML-NEXT: Sections:
+# YAML-NEXT: - Type: SectionHeaderTable
+# YAML-NEXT: NoHeaders: true
diff --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp
index a69fd1b2d0695..8baa443b84803 100644
--- a/llvm/tools/obj2yaml/elf2yaml.cpp
+++ b/llvm/tools/obj2yaml/elf2yaml.cpp
@@ -285,6 +285,8 @@ template <class ELFT> Expected<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
Y->Header.Flags = ELFYAML::ELF_EF(Obj.getHeader().e_flags);
Y->Header.Entry = Obj.getHeader().e_entry;
+ const bool HasSectionHeaders = Obj.getHeader().e_shoff != 0;
+
// Dump sections
auto SectionsOrErr = Obj.sections();
if (!SectionsOrErr)
@@ -304,9 +306,21 @@ template <class ELFT> Expected<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
// header table is larger than or equal to SHN_LORESERVE (0xff00). In this
// case the real number of entries is held in the sh_size member of the
// initial entry. We have a section header table when `e_shoff` is not 0.
- if (Obj.getHeader().e_shoff != 0 && Obj.getHeader().e_shnum == 0)
+ if (HasSectionHeaders && Obj.getHeader().e_shnum == 0)
Y->Header.EShNum = 0;
+ // For files without a section header table (e.g., core files), preserve the
+ // ELF header fields that differ from the defaults yaml2obj would produce.
+ // yaml2obj defaults e_shentsize to sizeof(Elf_Shdr), so we must always set
+ // it explicitly when there are no section headers.
+ if (!HasSectionHeaders) {
+ Y->Header.EShEntSize = Obj.getHeader().e_shentsize;
+ if (Obj.getHeader().e_shnum != 0)
+ Y->Header.EShNum = Obj.getHeader().e_shnum;
+ if (Obj.getHeader().e_shstrndx != 0)
+ Y->Header.EShStrNdx = Obj.getHeader().e_shstrndx;
+ }
+
// Dump symbols. We need to do this early because other sections might want
// to access the deduplicated symbol names that we also create here.
const Elf_Shdr *SymTab = nullptr;
@@ -377,37 +391,51 @@ template <class ELFT> Expected<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
return PhdrsOrErr.takeError();
Y->ProgramHeaders = std::move(*PhdrsOrErr);
- dumpSectionOffsets<ELFT>(Obj.getHeader(), Y->ProgramHeaders, Chunks,
- Sections);
+ if (!Chunks.empty())
+ dumpSectionOffsets<ELFT>(Obj.getHeader(), Y->ProgramHeaders, Chunks,
+ Sections);
// Dump DWARF sections.
- Y->DWARF = dumpDWARFSections(Chunks);
+ if (!Chunks.empty())
+ Y->DWARF = dumpDWARFSections(Chunks);
// We emit the "SectionHeaderTable" key when the order of sections in the
// sections header table doesn't match the file order.
- const bool SectionsSorted =
- llvm::is_sorted(Chunks, [&](const std::unique_ptr<ELFYAML::Chunk> &A,
- const std::unique_ptr<ELFYAML::Chunk> &B) {
- return cast<ELFYAML::Section>(A.get())->OriginalSecNdx <
- cast<ELFYAML::Section>(B.get())->OriginalSecNdx;
- });
- if (!SectionsSorted) {
+ if (!Chunks.empty()) {
+ const bool SectionsSorted =
+ llvm::is_sorted(Chunks, [&](const std::unique_ptr<ELFYAML::Chunk> &A,
+ const std::unique_ptr<ELFYAML::Chunk> &B) {
+ return cast<ELFYAML::Section>(A.get())->OriginalSecNdx <
+ cast<ELFYAML::Section>(B.get())->OriginalSecNdx;
+ });
+ if (!SectionsSorted) {
+ std::unique_ptr<ELFYAML::SectionHeaderTable> SHT =
+ std::make_unique<ELFYAML::SectionHeaderTable>(/*IsImplicit=*/false);
+ SHT->Sections.emplace();
+ for (ELFYAML::Section *S : OriginalOrder)
+ 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))
+ return false;
+
+ const ELFYAML::Section &S = cast<ELFYAML::Section>(*C);
+ return !shouldPrintSection(S, Sections[S.OriginalSecNdx], Y->DWARF);
+ });
+ }
+
+ // For files without section headers, add a SectionHeaderTable with
+ // NoHeaders: true so that yaml2obj does not generate section headers.
+ if (!HasSectionHeaders) {
std::unique_ptr<ELFYAML::SectionHeaderTable> SHT =
std::make_unique<ELFYAML::SectionHeaderTable>(/*IsImplicit=*/false);
- SHT->Sections.emplace();
- for (ELFYAML::Section *S : OriginalOrder)
- SHT->Sections->push_back({S->Name});
+ SHT->NoHeaders = true;
Chunks.push_back(std::move(SHT));
}
- llvm::erase_if(Chunks, [this, &Y](const std::unique_ptr<ELFYAML::Chunk> &C) {
- if (isa<ELFYAML::SectionHeaderTable>(*C))
- return false;
-
- const ELFYAML::Section &S = cast<ELFYAML::Section>(*C);
- return !shouldPrintSection(S, Sections[S.OriginalSecNdx], Y->DWARF);
- });
-
// The section header string table by default is assumed to be called
// ".shstrtab" and be in its own unique section. However, it's possible for it
// to be called something else and shared with another section. If the name
@@ -504,6 +532,23 @@ ELFDumper<ELFT>::dumpProgramHeaders(
}
}
+ // If no sections matched this segment and it has file data, dump the raw
+ // content. This handles core files and other ELF files where segments
+ // are not backed by section headers.
+ if (!PH.FirstSec && Phdr.p_filesz > 0) {
+ ArrayRef<uint8_t> Content(Obj.base() + Phdr.p_offset, Phdr.p_filesz);
+ PH.Content = yaml::BinaryRef(Content);
+ // Set MemSize explicitly only when it differs from FileSize.
+ if (Phdr.p_memsz != Phdr.p_filesz)
+ PH.MemSize = Phdr.p_memsz;
+ // Set FileSize explicitly only when it differs from content size.
+ // yaml2obj will derive it from Content by default.
+ } else if (!PH.FirstSec && Phdr.p_filesz == 0 && Phdr.p_memsz > 0) {
+ // Memory-only segment with no file content (e.g., BSS-like).
+ PH.FileSize = static_cast<llvm::yaml::Hex64>(0);
+ PH.MemSize = Phdr.p_memsz;
+ }
+
Ret.push_back(PH);
}
>From 0057af99a203e81c446e1d32201492266157f77b Mon Sep 17 00:00:00 2001
From: Greg Clayton <clayborg at gmail.com>
Date: Thu, 16 Apr 2026 13:47:55 -0700
Subject: [PATCH 2/2] Fix failing tets.
---
llvm/lib/ObjectYAML/ELFEmitter.cpp | 21 ++++++++++++++++++---
llvm/tools/obj2yaml/elf2yaml.cpp | 19 +++++++++----------
2 files changed, 27 insertions(+), 13 deletions(-)
diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp
index 287ffebe30b79..31737b97f37c6 100644
--- a/llvm/lib/ObjectYAML/ELFEmitter.cpp
+++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp
@@ -421,12 +421,27 @@ ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH)
"DWARF output");
ImplicitSections.insert(StringRef(SecName).copy(StringAlloc));
}
+ // Check if there are any real sections (not just SectionHeaderTable or the
+ // implicit SHT_NULL section at index 0).
+ bool HasRealSections = llvm::any_of(Doc.Chunks, [](const auto &C) {
+ if (isa<ELFYAML::SectionHeaderTable>(C.get()))
+ return false;
+ if (auto *Sec = dyn_cast<ELFYAML::Section>(C.get()))
+ return !Sec->IsImplicit;
+ return true;
+ });
+
// Don't create implicit string table sections when there are no section
- // headers (e.g., core files). The .strtab is only needed for symbols.
- if (!SecHdrTable || !SecHdrTable->NoHeaders.value_or(false)) {
+ // headers and no real sections (e.g., core files with only program header
+ // content). When there are real sections, .strtab is still needed even
+ // with NoHeaders.
+ bool SuppressImplicitSections =
+ SecHdrTable && SecHdrTable->NoHeaders.value_or(false) && !HasRealSections;
+ if (!SuppressImplicitSections) {
// TODO: Only create the .strtab here if any symbols have been requested.
ImplicitSections.insert(".strtab");
- ImplicitSections.insert(SectionHeaderStringTableName);
+ if (!SecHdrTable || !SecHdrTable->NoHeaders.value_or(false))
+ ImplicitSections.insert(SectionHeaderStringTableName);
}
// Insert placeholders for implicit sections that are not
diff --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp
index 8baa443b84803..14f88cabfa6f0 100644
--- a/llvm/tools/obj2yaml/elf2yaml.cpp
+++ b/llvm/tools/obj2yaml/elf2yaml.cpp
@@ -309,16 +309,15 @@ template <class ELFT> Expected<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
if (HasSectionHeaders && Obj.getHeader().e_shnum == 0)
Y->Header.EShNum = 0;
- // For files without a section header table (e.g., core files), preserve the
- // ELF header fields that differ from the defaults yaml2obj would produce.
- // yaml2obj defaults e_shentsize to sizeof(Elf_Shdr), so we must always set
- // it explicitly when there are no section headers.
- if (!HasSectionHeaders) {
- Y->Header.EShEntSize = Obj.getHeader().e_shentsize;
+ // For core files without a section header table, preserve the ELF header
+ // fields that differ from the defaults yaml2obj would produce.
+ if (!HasSectionHeaders && Obj.getHeader().e_type == ELF::ET_CORE) {
+ // yaml2obj defaults e_shentsize to sizeof(Elf_Shdr), so only set it when
+ // the value differs from that default.
+ if (Obj.getHeader().e_shentsize != sizeof(Elf_Shdr))
+ Y->Header.EShEntSize = Obj.getHeader().e_shentsize;
if (Obj.getHeader().e_shnum != 0)
Y->Header.EShNum = Obj.getHeader().e_shnum;
- if (Obj.getHeader().e_shstrndx != 0)
- Y->Header.EShStrNdx = Obj.getHeader().e_shstrndx;
}
// Dump symbols. We need to do this early because other sections might want
@@ -427,9 +426,9 @@ template <class ELFT> Expected<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
});
}
- // For files without section headers, add a SectionHeaderTable with
+ // For core files without section headers, add a SectionHeaderTable with
// NoHeaders: true so that yaml2obj does not generate section headers.
- if (!HasSectionHeaders) {
+ if (!HasSectionHeaders && Obj.getHeader().e_type == ELF::ET_CORE) {
std::unique_ptr<ELFYAML::SectionHeaderTable> SHT =
std::make_unique<ELFYAML::SectionHeaderTable>(/*IsImplicit=*/false);
SHT->NoHeaders = true;
More information about the llvm-commits
mailing list