diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -856,10 +856,11 @@ SHT_LLVM_ADDRSIG = 0x6fff4c03, // List of address-significant symbols // for safe ICF. SHT_LLVM_DEPENDENT_LIBRARIES = - 0x6fff4c04, // LLVM Dependent Library Specifiers. - SHT_LLVM_SYMPART = 0x6fff4c05, // Symbol partition specification. - SHT_LLVM_PART_EHDR = 0x6fff4c06, // ELF header for loadable partition. - SHT_LLVM_PART_PHDR = 0x6fff4c07, // Phdrs for loadable partition. + 0x6fff4c04, // LLVM Dependent Library Specifiers. + SHT_LLVM_SYMPART = 0x6fff4c05, // Symbol partition specification. + SHT_LLVM_PART_EHDR = 0x6fff4c06, // ELF header for loadable partition. + SHT_LLVM_PART_PHDR = 0x6fff4c07, // Phdrs for loadable partition. + SHT_LLVM_BB_ADDR_MAP = 0x6fff4c08, // LLVM Basic Block Address Map. // Android's experimental support for SHT_RELR sections. // https://android.googlesource.com/platform/bionic/+/b7feec74547f84559a1467aca02708ff61346d2a/libc/include/elf.h#512 SHT_ANDROID_RELR = 0x6fffff00, // Relocation entries; only offsets. 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 @@ -126,6 +126,17 @@ llvm::yaml::Hex64 Val; }; +struct BBAddrMapEntry { + struct BBEntry { + llvm::yaml::Hex32 AddressOffset; + llvm::yaml::Hex32 Size; + llvm::yaml::Hex32 Metadata; + }; + llvm::yaml::Hex64 Address; + llvm::yaml::Hex32 NumBlocks; + Optional> BBEntries; +}; + struct StackSizeEntry { llvm::yaml::Hex64 Address; llvm::yaml::Hex64 Size; @@ -159,7 +170,8 @@ Fill, LinkerOptions, DependentLibraries, - CallGraphProfile + CallGraphProfile, + BBAddrMap }; ChunkKind Kind; @@ -227,6 +239,17 @@ static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Fill; } }; +struct BBAddrMapSection : Section { + Optional Content; + Optional> Entries; + + BBAddrMapSection() : Section(ChunkKind::BBAddrMap) {} + + static bool classof(const Chunk *S) { + return S->Kind == ChunkKind::BBAddrMap; + } +}; + struct StackSizesSection : Section { Optional Content; Optional Size; @@ -579,6 +602,8 @@ } // end namespace llvm LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::StackSizeEntry) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::BBAddrMapEntry) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::BBAddrMapEntry::BBEntry) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::DynamicEntry) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::LinkerOption) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::CallGraphEntry) @@ -740,6 +765,14 @@ static void mapping(IO &IO, ELFYAML::StackSizeEntry &Rel); }; +template <> struct MappingTraits { + static void mapping(IO &IO, ELFYAML::BBAddrMapEntry &Rel); +}; + +template <> struct MappingTraits { + static void mapping(IO &IO, ELFYAML::BBAddrMapEntry::BBEntry &Rel); +}; + template <> struct MappingTraits { static void mapping(IO &IO, ELFYAML::GnuHashHeader &Rel); }; diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1023,9 +1023,10 @@ MCConstantExpr::create(FrameOffset, OutContext)); } -/// Returns the BB metadata to be emitted in the bb_addr_map section for a given -/// basic block. This can be used to capture more precise profile information. -/// We use the last 3 bits (LSBs) to ecnode the following information: +/// Returns the BB metadata to be emitted in the __llvm_bb_addr_map section for +/// a given basic block. This can be used to capture more precise profile +/// information. We use the last 3 bits (LSBs) to ecnode the following +/// information: /// * (1): set if return block (ret or tail call). /// * (2): set if ends with a tail call. /// * (3): set if exception handling (EH) landing pad. @@ -1040,7 +1041,7 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) { MCSection *BBAddrMapSection = getObjFileLowering().getBBAddrMapSection(*MF.getSection()); - assert(BBAddrMapSection && ".bb_addr_map section is not initialized."); + assert(BBAddrMapSection && "__llvm_bb_addr_map section is not initialized."); const MCSymbol *FunctionSymbol = getFunctionBegin(); diff --git a/llvm/lib/CodeGen/BasicBlockSections.cpp b/llvm/lib/CodeGen/BasicBlockSections.cpp --- a/llvm/lib/CodeGen/BasicBlockSections.cpp +++ b/llvm/lib/CodeGen/BasicBlockSections.cpp @@ -49,9 +49,9 @@ // ================== // // With -fbasic-block-sections=labels, we emit the offsets of BB addresses of -// every function into a .bb_addr_map section. Along with the function symbols, -// this allows for mapping of virtual addresses in PMU profiles back to the -// corresponding basic blocks. This logic is implemented in AsmPrinter. This +// every function into the __llvm_bb_addr_map section. Along with the function +// symbols, this allows for mapping of virtual addresses in PMU profiles back to +// the corresponding basic blocks. This logic is implemented in AsmPrinter. This // pass only assigns the BBSectionType of every function to ``labels``. // //===----------------------------------------------------------------------===// diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp --- a/llvm/lib/MC/MCObjectFileInfo.cpp +++ b/llvm/lib/MC/MCObjectFileInfo.cpp @@ -1002,7 +1002,7 @@ Flags |= ELF::SHF_GROUP; } - return Ctx->getELFSection(".bb_addr_map", ELF::SHT_PROGBITS, Flags, 0, - GroupName, MCSection::NonUniqueID, + return Ctx->getELFSection("__llvm_bb_addr_map", ELF::SHT_LLVM_BB_ADDR_MAP, + Flags, 0, GroupName, MCSection::NonUniqueID, cast(TextSec.getBeginSymbol())); } diff --git a/llvm/lib/MC/MCParser/ELFAsmParser.cpp b/llvm/lib/MC/MCParser/ELFAsmParser.cpp --- a/llvm/lib/MC/MCParser/ELFAsmParser.cpp +++ b/llvm/lib/MC/MCParser/ELFAsmParser.cpp @@ -626,6 +626,8 @@ Type = ELF::SHT_LLVM_DEPENDENT_LIBRARIES; else if (TypeName == "llvm_sympart") Type = ELF::SHT_LLVM_SYMPART; + else if (TypeName == "llvm_bb_addr_map") + Type = ELF::SHT_LLVM_BB_ADDR_MAP; else if (TypeName.getAsInteger(0, Type)) return TokError("unknown section type"); } diff --git a/llvm/lib/MC/MCSectionELF.cpp b/llvm/lib/MC/MCSectionELF.cpp --- a/llvm/lib/MC/MCSectionELF.cpp +++ b/llvm/lib/MC/MCSectionELF.cpp @@ -156,6 +156,8 @@ OS << "llvm_dependent_libraries"; else if (Type == ELF::SHT_LLVM_SYMPART) OS << "llvm_sympart"; + else if (Type == ELF::SHT_LLVM_BB_ADDR_MAP) + OS << "llvm_bb_addr_map"; else report_fatal_error("unsupported type 0x" + Twine::utohexstr(Type) + " for section " + getName()); diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp --- a/llvm/lib/Object/ELF.cpp +++ b/llvm/lib/Object/ELF.cpp @@ -276,6 +276,7 @@ STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_SYMPART); STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_PART_EHDR); STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_PART_PHDR); + STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_BB_ADDR_MAP); STRINGIFY_ENUM_CASE(ELF, SHT_GNU_ATTRIBUTES); STRINGIFY_ENUM_CASE(ELF, SHT_GNU_HASH); STRINGIFY_ENUM_CASE(ELF, SHT_GNU_verdef); 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 @@ -271,6 +271,9 @@ void writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::StackSizesSection &Section, ContiguousBlobAccumulator &CBA); + void writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::BBAddrMapSection &Section, + ContiguousBlobAccumulator &CBA); void writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::HashSection &Section, ContiguousBlobAccumulator &CBA); @@ -729,6 +732,8 @@ writeSectionContent(SHeader, *S, CBA); } else if (auto S = dyn_cast(Sec)) { writeSectionContent(SHeader, *S, CBA); + } else if (auto S = dyn_cast(Sec)) { + writeSectionContent(SHeader, *S, CBA); } else { llvm_unreachable("Unknown section type"); } @@ -1290,6 +1295,28 @@ } } +template +void ELFState::writeSectionContent( + Elf_Shdr &SHeader, const ELFYAML::BBAddrMapSection &Section, + ContiguousBlobAccumulator &CBA) { + if (Section.Content) { + SHeader.sh_size = writeContent(CBA, Section.Content, None); + return; + } + + for (const ELFYAML::BBAddrMapEntry &E : *Section.Entries) { + CBA.write(E.Address, ELFT::TargetEndianness); + SHeader.sh_size += sizeof(uintX_t) + CBA.writeULEB128(E.NumBlocks); + if (!E.BBEntries.hasValue()) + continue; + for (const ELFYAML::BBAddrMapEntry::BBEntry &BBE : *E.BBEntries) { + SHeader.sh_size += CBA.writeULEB128(BBE.AddressOffset) + + CBA.writeULEB128(BBE.Size) + + CBA.writeULEB128(BBE.Metadata); + } + } +} + template void ELFState::writeSectionContent( Elf_Shdr &SHeader, const ELFYAML::LinkerOptionsSection &Section, 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 @@ -486,6 +486,7 @@ ECase(SHT_LLVM_SYMPART); ECase(SHT_LLVM_PART_EHDR); ECase(SHT_LLVM_PART_PHDR); + ECase(SHT_LLVM_BB_ADDR_MAP); ECase(SHT_GNU_ATTRIBUTES); ECase(SHT_GNU_HASH); ECase(SHT_GNU_verdef); @@ -1140,6 +1141,12 @@ IO.mapOptional("Info", Section.Info); } +static void sectionMapping(IO &IO, ELFYAML::BBAddrMapSection &Section) { + commonSectionMapping(IO, Section); + IO.mapOptional("Content", Section.Content); + IO.mapOptional("Entries", Section.Entries); +} + static void sectionMapping(IO &IO, ELFYAML::StackSizesSection &Section) { commonSectionMapping(IO, Section); IO.mapOptional("Content", Section.Content); @@ -1417,6 +1424,11 @@ Section.reset(new ELFYAML::CallGraphProfileSection()); sectionMapping(IO, *cast(Section.get())); break; + case ELF::SHT_LLVM_BB_ADDR_MAP: + if (!IO.outputting()) + Section.reset(new ELFYAML::BBAddrMapSection()); + sectionMapping(IO, *cast(Section.get())); + break; default: if (!IO.outputting()) { StringRef Name; @@ -1649,6 +1661,22 @@ IO.mapRequired("Size", E.Size); } +void MappingTraits::mapping( + IO &IO, ELFYAML::BBAddrMapEntry &E) { + assert(IO.getContext() && "The IO context is not initialized"); + IO.mapOptional("Address", E.Address, Hex64(0)); + IO.mapRequired("NumBlocks", E.NumBlocks); + IO.mapOptional("BBEntries", E.BBEntries); +} + +void MappingTraits::mapping( + IO &IO, ELFYAML::BBAddrMapEntry::BBEntry &E) { + assert(IO.getContext() && "The IO context is not initialized"); + IO.mapRequired("AddressOffset", E.AddressOffset); + IO.mapRequired("Size", E.Size); + IO.mapRequired("Metadata", E.Metadata); +} + void MappingTraits::mapping(IO &IO, ELFYAML::GnuHashHeader &E) { assert(IO.getContext() && "The IO context is not initialized"); diff --git a/llvm/test/CodeGen/X86/basic-block-sections-labels-functions-sections.ll b/llvm/test/CodeGen/X86/basic-block-sections-labels-functions-sections.ll --- a/llvm/test/CodeGen/X86/basic-block-sections-labels-functions-sections.ll +++ b/llvm/test/CodeGen/X86/basic-block-sections-labels-functions-sections.ll @@ -5,11 +5,11 @@ define dso_local i32 @_Z3barv() { ret i32 0 } -;; Check we add SHF_LINK_ORDER for .bb_addr_map and link it with the corresponding .text sections. +;; Check we add SHF_LINK_ORDER for __llvm_bb_addr_map and link it with the corresponding .text sections. ; CHECK: .section .text._Z3barv,"ax",@progbits ; CHECK-LABEL: _Z3barv: ; CHECK-NEXT: [[BAR_BEGIN:.Lfunc_begin[0-9]+]]: -; CHECK: .section .bb_addr_map,"o",@progbits,.text._Z3barv{{$}} +; CHECK: .section __llvm_bb_addr_map,"o",@llvm_bb_addr_map,.text._Z3barv{{$}} ; CHECK-NEXT: .quad [[BAR_BEGIN]] @@ -20,16 +20,16 @@ ; CHECK: .section .text._Z3foov,"ax",@progbits ; CHECK-LABEL: _Z3foov: ; CHECK-NEXT: [[FOO_BEGIN:.Lfunc_begin[0-9]+]]: -; CHECK: .section .bb_addr_map,"o",@progbits,.text._Z3foov{{$}} +; CHECK: .section __llvm_bb_addr_map,"o",@llvm_bb_addr_map,.text._Z3foov{{$}} ; CHECK-NEXT: .quad [[FOO_BEGIN]] define linkonce_odr dso_local i32 @_Z4fooTIiET_v() comdat { ret i32 0 } -;; Check we add .bb_addr_map section to a COMDAT group with the corresponding .text section if such a COMDAT exists. +;; Check we add __llvm_bb_addr_map section to a COMDAT group with the corresponding .text section if such a COMDAT exists. ; CHECK: .section .text._Z4fooTIiET_v,"axG",@progbits,_Z4fooTIiET_v,comdat ; CHECK-LABEL: _Z4fooTIiET_v: ; CHECK-NEXT: [[FOOCOMDAT_BEGIN:.Lfunc_begin[0-9]+]]: -; CHECK: .section .bb_addr_map,"Go",@progbits,_Z4fooTIiET_v,comdat,.text._Z4fooTIiET_v{{$}} +; CHECK: .section __llvm_bb_addr_map,"Go",@llvm_bb_addr_map,_Z4fooTIiET_v,comdat,.text._Z4fooTIiET_v{{$}} ; CHECK-NEXT: .quad [[FOOCOMDAT_BEGIN]] diff --git a/llvm/test/CodeGen/X86/basic-block-sections-labels.ll b/llvm/test/CodeGen/X86/basic-block-sections-labels.ll --- a/llvm/test/CodeGen/X86/basic-block-sections-labels.ll +++ b/llvm/test/CodeGen/X86/basic-block-sections-labels.ll @@ -39,7 +39,7 @@ ; CHECK-LABEL: .LBB_END0_3: ; CHECK-LABEL: .Lfunc_end0: -; CHECK: .section .bb_addr_map,"o",@progbits,.text +; CHECK: .section __llvm_bb_addr_map,"o",@llvm_bb_addr_map,.text ; CHECK-NEXT: .quad .Lfunc_begin0 ; CHECK-NEXT: .byte 4 ; CHECK-NEXT: .uleb128 .Lfunc_begin0-.Lfunc_begin0 diff --git a/llvm/test/MC/AsmParser/llvm_section_types.s b/llvm/test/MC/AsmParser/llvm_section_types.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/AsmParser/llvm_section_types.s @@ -0,0 +1,27 @@ +## Verify that LLVM-specific section types are correctly inferred from assembly input. +# RUN: llvm-mc -triple i386-pc-linux-gnu -filetype=obj -o %t %s +# RUN: llvm-readobj -S - < %t | FileCheck %s +.section .section1,"",@llvm_bb_addr_map +.byte 1 +.section .section2,"",@llvm_call_graph_profile +.byte 1 +.section .section3,"",@llvm_odrtab +.byte 1 +.section .section4,"",@llvm_linker_options +.byte 1 +.section .section5,"",@llvm_sympart +.byte 1 +.section .section6,"",@llvm_dependent_libraries +.byte 1 +# CHECK: Name: .section1 +# CHECK-NEXT: Type: SHT_LLVM_BB_ADDR_MAP +# CHECK: Name: .section2 +# CHECK-NEXT: Type: SHT_LLVM_CALL_GRAPH_PROFILE +# CHECK: Name: .section3 +# CHECK-NEXT: Type: SHT_LLVM_ODRTAB +# CHECK: Name: .section4 +# CHECK-NEXT: Type: SHT_LLVM_LINKER_OPTIONS +# CHECK: Name: .section5 +# CHECK-NEXT: Type: SHT_LLVM_SYMPART +# CHECK: Name: .section6 +# CHECK-NEXT: Type: SHT_LLVM_DEPENDENT_LIBRARIES diff --git a/llvm/test/tools/obj2yaml/ELF/bb-addr-map.yaml b/llvm/test/tools/obj2yaml/ELF/bb-addr-map.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/tools/obj2yaml/ELF/bb-addr-map.yaml @@ -0,0 +1,62 @@ +## Check how obj2yaml produces YAML .llvm_bb_addr_map descriptions. + +## Check that obj2yaml uses the "Entries" tag to describe a .llvm_bb_addr_map section. + +# 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: Sections: +# VALID-NEXT: - Name: .llvm_bb_addr_map +# VALID-NEXT: Type: SHT_LLVM_BB_ADDR_MAP +# VALID-NEXT: Entries: +# VALID-NEXT: - Address: 0x0000000000000010 +# VALID-NEXT: NumBlocks: 0x00000003 +# VALID-NEXT: BBEntries: +# VALID-NEXT: - AddressOffset: 0x00000001 +# VALID-NEXT: Size: 0x00000002 +# VALID-NEXT: Metadata: 0x00000003 +# VALID-NEXT: - AddressOffset: 0x00000004 +# VALID-NEXT: Size: 0x00000005 +# VALID-NEXT: Metadata: 0x00000006 +# VALID-NEXT: - AddressOffset: 0x00000007 +# VALID-NEXT: Size: 0x00000008 +# VALID-NEXT: Metadata: 0x00000009 +# VALID-NEXT: - Address: 0x0000000000000020 +# VALID-NEXT: NumBlocks: 0x00000001 +# VALID-NEXT: BBEntries: +# VALID-NEXT: - AddressOffset: 0x0000000A +# VALID-NEXT: Size: 0x0000000B +# VALID-NEXT: Metadata: 0x0000000C + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC +Sections: + - Name: .llvm_bb_addr_map + Type: SHT_LLVM_BB_ADDR_MAP + Entries: + - Address: 0x0000000000000010 + NumBlocks: 0x00000003 + BBEntries: + - AddressOffset: 0x00000001 + Size: 0x00000002 + Metadata: 0x00000003 + - AddressOffset: 0x00000004 + Size: 0x00000005 + Metadata: 0x00000006 + - AddressOffset: 0x00000007 + Size: 0x00000008 + Metadata: 0x00000009 + - Address: 0x0000000000000020 + NumBlocks: 0x00000001 + BBEntries: + - AddressOffset: 0x0000000A + Size: 0x0000000B + Metadata: 0x0000000C diff --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp --- a/llvm/tools/obj2yaml/elf2yaml.cpp +++ b/llvm/tools/obj2yaml/elf2yaml.cpp @@ -100,6 +100,8 @@ Expected dumpMipsABIFlags(const Elf_Shdr *Shdr); Expected dumpStackSizesSection(const Elf_Shdr *Shdr); + Expected + dumpBBAddrMapSection(const Elf_Shdr *Shdr); Expected dumpPlaceholderSection(const Elf_Shdr *Shdr); @@ -506,6 +508,9 @@ case ELF::SHT_LLVM_CALL_GRAPH_PROFILE: return [this](const Elf_Shdr *S) { return dumpCallGraphProfileSection(S); }; + + case ELF::SHT_LLVM_BB_ADDR_MAP: + return [this](const Elf_Shdr *S) { return dumpBBAddrMapSection(S); }; case ELF::SHT_STRTAB: case ELF::SHT_SYMTAB: case ELF::SHT_DYNSYM: @@ -761,6 +766,47 @@ return S.release(); } +template +Expected +ELFDumper::dumpBBAddrMapSection(const Elf_Shdr *Shdr) { + auto S = std::make_unique(); + if (Error E = dumpCommonSection(Shdr, *S)) + return std::move(E); + + auto ContentOrErr = Obj.getSectionContents(*Shdr); + if (!ContentOrErr) + return ContentOrErr.takeError(); + + ArrayRef Content = *ContentOrErr; + DataExtractor Data(Content, Obj.isLE(), ELFT::Is64Bits ? 8 : 4); + + std::vector Entries; + DataExtractor::Cursor Cur(0); + while (Cur && Cur.tell() < Content.size()) { + uint64_t Address = Data.getAddress(Cur); + uint32_t NumBlocks = Data.getULEB128(Cur); + std::vector BBEntries; + for (uint32_t BlockID = 0; + Cur && Cur.tell() < Content.size() && BlockID < NumBlocks; ++BlockID) { + uint32_t Offset = Data.getULEB128(Cur); + uint32_t Size = Data.getULEB128(Cur); + uint32_t Metadata = Data.getULEB128(Cur); + BBEntries.push_back({Offset, Size, Metadata}); + } + Entries.push_back({Address, NumBlocks, BBEntries}); + } + + if (Content.empty() || !Cur) { + // If the section 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 Expected ELFDumper::dumpAddrsigSection(const Elf_Shdr *Shdr) {