[yaml2obj/obj2yaml] - Add support for .stack_sizes sections.

.stack_sizes is a SHT_PROGBITS section that contains pairs of
<address (4/8 bytes), stack size (uleb128)>.

This patch teach tools to parse and dump it.

Differential revision: https://reviews.llvm.org/D67757

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@372762 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
George Rimar
2019-09-24 14:22:37 +00:00
parent 085daf4687
commit 3a0728c761
8 changed files with 480 additions and 15 deletions
+5 -4
View File
@@ -150,15 +150,16 @@ public:
static Expected<ELFFile> create(StringRef Object);
bool isLE() const {
return getHeader()->getDataEncoding() == ELF::ELFDATA2LSB;
}
bool isMipsELF64() const {
return getHeader()->e_machine == ELF::EM_MIPS &&
getHeader()->getFileClass() == ELF::ELFCLASS64;
}
bool isMips64EL() const {
return isMipsELF64() &&
getHeader()->getDataEncoding() == ELF::ELFDATA2LSB;
}
bool isMips64EL() const { return isMipsELF64() && isLE(); }
Expected<Elf_Shdr_Range> sections() const;
+26
View File
@@ -117,6 +117,11 @@ struct DynamicEntry {
llvm::yaml::Hex64 Val;
};
struct StackSizeEntry {
llvm::yaml::Hex64 Address;
llvm::yaml::Hex64 Size;
};
struct Section {
enum class SectionKind {
Dynamic,
@@ -126,6 +131,7 @@ struct Section {
NoBits,
Verdef,
Verneed,
StackSizes,
SymtabShndxSection,
Symver,
MipsABIFlags
@@ -163,6 +169,21 @@ struct Section {
Optional<llvm::yaml::Hex64> ShSize;
};
struct StackSizesSection : Section {
Optional<yaml::BinaryRef> Content;
Optional<std::vector<StackSizeEntry>> Entries;
StackSizesSection() : Section(SectionKind::StackSizes) {}
static bool classof(const Section *S) {
return S->Kind == SectionKind::StackSizes;
}
static bool nameMatches(StringRef Name) {
return Name == ".stack_sizes";
}
};
struct DynamicSection : Section {
std::vector<DynamicEntry> Entries;
Optional<yaml::BinaryRef> Content;
@@ -326,6 +347,7 @@ struct Object {
} // end namespace ELFYAML
} // end namespace llvm
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::StackSizeEntry)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::DynamicEntry)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::ProgramHeader)
LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::ELFYAML::Section>)
@@ -461,6 +483,10 @@ struct MappingTraits<ELFYAML::Symbol> {
static StringRef validate(IO &IO, ELFYAML::Symbol &Symbol);
};
template <> struct MappingTraits<ELFYAML::StackSizeEntry> {
static void mapping(IO &IO, ELFYAML::StackSizeEntry &Rel);
};
template <> struct MappingTraits<ELFYAML::DynamicEntry> {
static void mapping(IO &IO, ELFYAML::DynamicEntry &Rel);
};
+26
View File
@@ -19,6 +19,7 @@
#include "llvm/ObjectYAML/ELFYAML.h"
#include "llvm/ObjectYAML/yaml2obj.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/YAMLTraits.h"
@@ -167,6 +168,9 @@ template <class ELFT> class ELFState {
void writeSectionContent(Elf_Shdr &SHeader,
const ELFYAML::DynamicSection &Section,
ContiguousBlobAccumulator &CBA);
void writeSectionContent(Elf_Shdr &SHeader,
const ELFYAML::StackSizesSection &Section,
ContiguousBlobAccumulator &CBA);
ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH);
public:
@@ -411,6 +415,8 @@ void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
writeSectionContent(SHeader, *S, CBA);
} else if (auto S = dyn_cast<ELFYAML::VerdefSection>(Sec)) {
writeSectionContent(SHeader, *S, CBA);
} else if (auto S = dyn_cast<ELFYAML::StackSizesSection>(Sec)) {
writeSectionContent(SHeader, *S, CBA);
} else {
llvm_unreachable("Unknown section type");
}
@@ -781,6 +787,26 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
SHeader.sh_size = Section.Entries.size() * SHeader.sh_entsize;
}
template <class ELFT>
void ELFState<ELFT>::writeSectionContent(
Elf_Shdr &SHeader, const ELFYAML::StackSizesSection &Section,
ContiguousBlobAccumulator &CBA) {
using uintX_t = typename ELFT::uint;
raw_ostream &OS =
CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
if (Section.Content) {
Section.Content->writeAsBinary(OS);
SHeader.sh_size = Section.Content->binary_size();
return;
}
for (const ELFYAML::StackSizeEntry &E : *Section.Entries) {
support::endian::write<uintX_t>(OS, E.Address, ELFT::TargetEndianness);
SHeader.sh_size += sizeof(uintX_t) + encodeULEB128(E.Size, OS);
}
}
template <class ELFT>
void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
const ELFYAML::VerdefSection &Section,
+41 -8
View File
@@ -1017,6 +1017,12 @@ static void sectionMapping(IO &IO, ELFYAML::RawContentSection &Section) {
IO.mapOptional("Info", Section.Info);
}
static void sectionMapping(IO &IO, ELFYAML::StackSizesSection &Section) {
commonSectionMapping(IO, Section);
IO.mapOptional("Content", Section.Content);
IO.mapOptional("Entries", Section.Entries);
}
static void sectionMapping(IO &IO, ELFYAML::NoBitsSection &Section) {
commonSectionMapping(IO, Section);
IO.mapOptional("Size", Section.Size, Hex64(0));
@@ -1142,20 +1148,40 @@ void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping(
sectionMapping(IO, *cast<ELFYAML::SymtabShndxSection>(Section.get()));
break;
default:
if (!IO.outputting())
Section.reset(new ELFYAML::RawContentSection());
sectionMapping(IO, *cast<ELFYAML::RawContentSection>(Section.get()));
if (!IO.outputting()) {
StringRef Name;
IO.mapOptional("Name", Name, StringRef());
if (ELFYAML::StackSizesSection::nameMatches(Name))
Section = std::make_unique<ELFYAML::StackSizesSection>();
else
Section = std::make_unique<ELFYAML::RawContentSection>();
}
if (auto S = dyn_cast<ELFYAML::RawContentSection>(Section.get()))
sectionMapping(IO, *S);
else
sectionMapping(IO, *cast<ELFYAML::StackSizesSection>(Section.get()));
}
}
StringRef MappingTraits<std::unique_ptr<ELFYAML::Section>>::validate(
IO &io, std::unique_ptr<ELFYAML::Section> &Section) {
const auto *RawSection = dyn_cast<ELFYAML::RawContentSection>(Section.get());
if (!RawSection)
if (const auto *RawSection =
dyn_cast<ELFYAML::RawContentSection>(Section.get())) {
if (RawSection->Size && RawSection->Content &&
(uint64_t)(*RawSection->Size) < RawSection->Content->binary_size())
return "Section size must be greater than or equal to the content size";
return {};
if (RawSection->Size && RawSection->Content &&
(uint64_t)(*RawSection->Size) < RawSection->Content->binary_size())
return "Section size must be greater than or equal to the content size";
}
if (const auto *SS = dyn_cast<ELFYAML::StackSizesSection>(Section.get())) {
if (SS->Content && SS->Entries)
return ".stack_sizes: Content and Entries cannot be used together";
if (!SS->Content && !SS->Entries)
return ".stack_sizes: either Content or Entries tag must be specified";
return {};
}
return {};
}
@@ -1184,6 +1210,13 @@ struct NormalizedMips64RelType {
} // end anonymous namespace
void MappingTraits<ELFYAML::StackSizeEntry>::mapping(
IO &IO, ELFYAML::StackSizeEntry &E) {
assert(IO.getContext() && "The IO context is not initialized");
IO.mapOptional("Address", E.Address, Hex64(0));
IO.mapRequired("Size", E.Size);
}
void MappingTraits<ELFYAML::DynamicEntry>::mapping(IO &IO,
ELFYAML::DynamicEntry &Rel) {
assert(IO.getContext() && "The IO context is not initialized");
+4 -3
View File
@@ -163,7 +163,7 @@ Sections:
Size: 16
- Name: .stack_sizes
Type: SHT_PROGBITS
Size: 1
Content: "00"
Link: .text
- Name: .rela.stack_sizes
Type: SHT_RELA
@@ -468,7 +468,8 @@ Sections:
Size: 16
- Name: .stack_sizes
Type: SHT_PROGBITS
Size: 9
Entries:
- Size: 0
Link: .text
- Name: .rela.stack_sizes
Type: SHT_RELA
@@ -504,8 +505,8 @@ Sections:
Size: 8
- Name: .stack_sizes
Type: SHT_PROGBITS
Size: 16
Link: .text
Entries: []
- Name: .rela.stack_sizes
Type: SHT_RELA
Info: .stack_sizes
+88
View File
@@ -0,0 +1,88 @@
## Check how obj2yaml produces YAML .stack_sizes descriptions.
## Check that obj2yaml uses the "Entries" tag to describe a .stack_sizes section
## when it can extract <address, size> pairs.
# RUN: yaml2obj --docnum=1 %s -o %t1
# RUN: obj2yaml %t1 | FileCheck %s --check-prefix=VALID
# VALID: --- !ELF
# VALID-NEXT: FileHeader:
# VALID-NEXT: Class: ELFCLASS64
# VALID-NEXT: Data: ELFDATA2LSB
# VALID-NEXT: Type: ET_EXEC
# VALID-NEXT: Machine: EM_X86_64
# VALID-NEXT: Sections:
# VALID-NEXT: - Name: .stack_sizes
# VALID-NEXT: Type: SHT_PROGBITS
# VALID-NEXT: Entries:
# VALID-NEXT: - Address: 0x0000000000000010
# VALID-NEXT: Size: 0x0000000000000020
# VALID-NEXT: - Address: 0x0000000000000030
# VALID-NEXT: Size: 0x0000000000000040
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_X86_64
Sections:
- Name: .stack_sizes
Type: SHT_PROGBITS
Content: "100000000000000020300000000000000040"
## Check that obj2yaml uses the "Content" tag to describe a .stack_sizes section
## when it can't extract the entries, for example, when section data is truncated.
# RUN: yaml2obj --docnum=2 %s -o %t2
# RUN: obj2yaml %t2 | FileCheck %s --check-prefix=INVALID
# INVALID: --- !ELF
# INVALID-NEXT: FileHeader:
# INVALID-NEXT: Class: ELFCLASS64
# INVALID-NEXT: Data: ELFDATA2LSB
# INVALID-NEXT: Type: ET_EXEC
# INVALID-NEXT: Machine: EM_X86_64
# INVALID-NEXT: Sections:
# INVALID-NEXT: - Name: .stack_sizes
# INVALID-NEXT: Type: SHT_PROGBITS
# INVALID-NEXT: Content: '1000000000000000203000000000000000'
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_X86_64
Sections:
- Name: .stack_sizes
Type: SHT_PROGBITS
Content: "1000000000000000203000000000000000"
## Check obj2yaml can dump empty .stack_sizes.
# RUN: yaml2obj --docnum=3 %s -o %t3
# RUN: obj2yaml %t3 | FileCheck %s --check-prefix=EMPTY
# EMPTY: --- !ELF
# EMPTY-NEXT: FileHeader:
# EMPTY-NEXT: Class: ELFCLASS64
# EMPTY-NEXT: Data: ELFDATA2LSB
# EMPTY-NEXT: Type: ET_EXEC
# EMPTY-NEXT: Machine: EM_X86_64
# EMPTY-NEXT: Sections:
# EMPTY-NEXT: - Name: .stack_sizes
# EMPTY-NEXT: Type: SHT_PROGBITS
# EMPTY-NEXT: Content: ''
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_X86_64
Sections:
- Name: .stack_sizes
Type: SHT_PROGBITS
Content: ""
+229
View File
@@ -0,0 +1,229 @@
## Check how yaml2obj produces .stack_sizes sections.
## Test the following cases when the .stack_sizes Content field is specified:
## 1) We can produce a .stack_sizes section from a description with
## a valid section content.
## 2) We can produce an incorrect .stack_sizes section from a description with
## a broken (truncated) section content.
## 3) We can produce an empty .stack_sizes section from a description with
## empty section content.
# RUN: yaml2obj --docnum=1 %s -o %t1
# RUN: llvm-readobj --sections --section-data %t1 | FileCheck %s
## Case 1: valid content.
# CHECK: Section {
# CHECK: Index: 1
# CHECK-NEXT: Name: .stack_sizes (1)
# CHECK-NEXT: Type: SHT_PROGBITS (0x1)
# CHECK-NEXT: Flags [ (0x0)
# CHECK-NEXT: ]
# CHECK-NEXT: Address: 0x0
# CHECK-NEXT: Offset: 0x40
# CHECK-NEXT: Size: 9
# CHECK-NEXT: Link: 0
# CHECK-NEXT: Info: 0
# CHECK-NEXT: AddressAlignment: 0
# CHECK-NEXT: EntrySize: 0
# CHECK-NEXT: SectionData (
# CHECK-NEXT: 0000: 10000000 00000000 20
# CHECK-NEXT: )
# CHECK-NEXT: }
## Case 2: truncated content.
# CHECK: Name: .stack_sizes
# CHECK: Size:
# CHECK-SAME: 8
# CHECK: SectionData (
# CHECK-NEXT: 0000: 10000000 00000000
## Case 3: empty content.
# CHECK: Name: .stack_sizes
# CHECK: Size:
# CHECK-SAME: 0
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_X86_64
Sections:
## Valid.
- Name: '.stack_sizes [1]'
Type: SHT_PROGBITS
Content: "100000000000000020"
## Truncated.
- Name: '.stack_sizes [2]'
Type: SHT_PROGBITS
Content: "1000000000000000"
## Empty.
- Name: '.stack_sizes [3]'
Type: SHT_PROGBITS
Content: ""
## Check we can describe .stack_sizes section using <address, size> pairs.
# RUN: yaml2obj --docnum=2 %s -o %t2
# RUN: llvm-readobj --sections --section-data %t2 | FileCheck %s --check-prefix=ENTRIES-LE64-BOTH
# RUN: yaml2obj --docnum=3 %s -o %t3
# RUN: llvm-readobj --sections --section-data %t3 | FileCheck %s --check-prefix=ENTRIES-BE64-BOTH
# RUN: yaml2obj --docnum=4 %s -o %t4
# RUN: llvm-readobj --sections --section-data %t4 | FileCheck %s --check-prefix=ENTRIES-LE32-BOTH
# RUN: yaml2obj --docnum=5 %s -o %t5
# RUN: llvm-readobj --sections --section-data %t5 | FileCheck %s --check-prefix=ENTRIES-BE32-BOTH
# ENTRIES-LE64-BOTH: Name: .stack_sizes
# ENTRIES-LE64-BOTH: SectionData (
# ENTRIES-LE64-BOTH-NEXT: 0000: 10000000 00000000 20300000 00000000 |
# ENTRIES-LE64-BOTH-NEXT: 0010: 0040 |
# ENTRIES-BE64-BOTH: Name: .stack_sizes
# ENTRIES-BE64-BOTH: SectionData (
# ENTRIES-BE64-BOTH-NEXT: 0000: 00000000 00000010 20000000 00000000 |
# ENTRIES-BE64-BOTH-NEXT: 0010: 3040
# ENTRIES-LE32-BOTH: Name: .stack_sizes
# ENTRIES-LE32-BOTH: SectionData (
# ENTRIES-LE32-BOTH-NEXT: 0000: 10000000 20300000 0040 |
# ENTRIES-BE32-BOTH: Name: .stack_sizes
# ENTRIES-BE32-BOTH: SectionData (
# ENTRIES-BE32-BOTH-NEXT: 0000: 00000010 20000000 3040 |
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_X86_64
Sections:
- Name: .stack_sizes
Type: SHT_PROGBITS
Entries:
- Address: 0x10
Size: 0x20
- Address: 0x30
Size: 0x40
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2MSB
Type: ET_EXEC
Machine: EM_X86_64
Sections:
- Name: .stack_sizes
Type: SHT_PROGBITS
Entries:
- Address: 0x10
Size: 0x20
- Address: 0x30
Size: 0x40
--- !ELF
FileHeader:
Class: ELFCLASS32
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_386
Sections:
- Name: .stack_sizes
Type: SHT_PROGBITS
Entries:
- Address: 0x10
Size: 0x20
- Address: 0x30
Size: 0x40
--- !ELF
FileHeader:
Class: ELFCLASS32
Data: ELFDATA2MSB
Type: ET_EXEC
Machine: EM_386
Sections:
- Name: .stack_sizes
Type: SHT_PROGBITS
Entries:
- Address: 0x10
Size: 0x20
- Address: 0x30
Size: 0x40
## Check we can omit the "Address" tag. In this case the address will be zero.
# RUN: yaml2obj --docnum=6 %s -o %t6
# RUN: llvm-readobj --sections --section-data %t6 | FileCheck %s --check-prefix=ENTRIES-NOADDR
# ENTRIES-NOADDR: Name: .stack_sizes
# ENTRIES-NOADDR: SectionData (
# ENTRIES-NOADDR-NEXT: 0000: 00000000 00000000 10000000 00000000 |
# ENTRIES-NOADDR-NEXT: 0010: 0020 |
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_X86_64
Sections:
- Name: .stack_sizes
Type: SHT_PROGBITS
Entries:
- Size: 0x10
- Size: 0x20
## Check that "Size" tag is mandatory when we describe .stack_sizes using "Entries".
# RUN: not yaml2obj --docnum=7 %s 2>&1 | FileCheck %s --check-prefix=ENTRIES-NOSIZE
# ENTRIES-NOSIZE: error: missing required key 'Size'
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_X86_64
Sections:
- Name: .stack_sizes
Type: SHT_PROGBITS
Entries:
- Address: 0x10
## Check we can't use both "Content" and "Entries" tags at the same time.
# RUN: not yaml2obj --docnum=8 %s 2>&1 | FileCheck %s --check-prefix=ENTRIES-AND-CONTENT
# ENTRIES-AND-CONTENT: error: .stack_sizes: Content and Entries cannot be used together
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_X86_64
Sections:
- Name: .stack_sizes
Type: SHT_PROGBITS
Content: "00"
Entries:
- Address: 0x10
Size: 0x20
## Check we must specify either "Content" or "Entries" tag when describing .stack_sizes.
# RUN: not yaml2obj --docnum=9 %s 2>&1 | FileCheck %s --check-prefix=NO-TAGS
# NO-TAGS: error: .stack_sizes: either Content or Entries tag must be specified
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_X86_64
Sections:
- Name: .stack_sizes
Type: SHT_PROGBITS
+61
View File
@@ -11,6 +11,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/ObjectYAML/ELFYAML.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/YAMLTraits.h"
@@ -67,6 +68,10 @@ class ELFDumper {
Expected<ELFYAML::VerneedSection *> dumpVerneedSection(const Elf_Shdr *Shdr);
Expected<ELFYAML::Group *> dumpGroup(const Elf_Shdr *Shdr);
Expected<ELFYAML::MipsABIFlags *> dumpMipsABIFlags(const Elf_Shdr *Shdr);
Expected<ELFYAML::StackSizesSection *>
dumpStackSizesSection(const Elf_Shdr *Shdr);
Expected<ELFYAML::Section *> dumpSpecialSection(const Elf_Shdr *Shdr);
public:
ELFDumper(const object::ELFFile<ELFT> &O);
@@ -284,6 +289,17 @@ template <class ELFT> Expected<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
LLVM_FALLTHROUGH;
}
default: {
// Recognize some special SHT_PROGBITS sections by name.
if (Sec.sh_type == ELF::SHT_PROGBITS) {
Expected<ELFYAML::Section *> SpecialSecOrErr = dumpSpecialSection(&Sec);
if (!SpecialSecOrErr)
return SpecialSecOrErr.takeError();
if (*SpecialSecOrErr) {
Y->Sections.emplace_back(*SpecialSecOrErr);
break;
}
}
Expected<ELFYAML::RawContentSection *> SecOrErr =
dumpContentSection(&Sec);
if (!SecOrErr)
@@ -432,6 +448,18 @@ Error ELFDumper<ELFT>::dumpCommonSection(const Elf_Shdr *Shdr,
return Error::success();
}
template <class ELFT>
Expected<ELFYAML::Section *>
ELFDumper<ELFT>::dumpSpecialSection(const Elf_Shdr *Shdr) {
auto NameOrErr = getUniquedSectionName(Shdr);
if (!NameOrErr)
return NameOrErr.takeError();
if (ELFYAML::StackSizesSection::nameMatches(*NameOrErr))
return dumpStackSizesSection(Shdr);
return nullptr;
}
template <class ELFT>
Error ELFDumper<ELFT>::dumpCommonRelocationSection(
const Elf_Shdr *Shdr, ELFYAML::RelocationSection &S) {
@@ -450,6 +478,39 @@ Error ELFDumper<ELFT>::dumpCommonRelocationSection(
return Error::success();
}
template <class ELFT>
Expected<ELFYAML::StackSizesSection *>
ELFDumper<ELFT>::dumpStackSizesSection(const Elf_Shdr *Shdr) {
auto S = std::make_unique<ELFYAML::StackSizesSection>();
if (Error E = dumpCommonSection(Shdr, *S))
return std::move(E);
auto ContentOrErr = Obj.getSectionContents(Shdr);
if (!ContentOrErr)
return ContentOrErr.takeError();
ArrayRef<uint8_t> Content = *ContentOrErr;
DataExtractor Data(Content, Obj.isLE(), ELFT::Is64Bits ? 8 : 4);
std::vector<ELFYAML::StackSizeEntry> Entries;
DataExtractor::Cursor Cur(0);
while (Cur && Cur.tell() < Content.size()) {
uint64_t Address = Data.getAddress(Cur);
uint64_t Size = Data.getULEB128(Cur);
Entries.push_back({Address, Size});
}
if (Content.empty() || !Cur) {
// If .stack_sizes cannot be decoded, we dump it as an array of bytes.
consumeError(Cur.takeError());
S->Content = yaml::BinaryRef(Content);
} else {
S->Entries = std::move(Entries);
}
return S.release();
}
template <class ELFT>
Expected<ELFYAML::DynamicSection *>
ELFDumper<ELFT>::dumpDynamicSection(const Elf_Shdr *Shdr) {