Index: include/llvm/ObjectYAML/ELFYAML.h =================================================================== --- include/llvm/ObjectYAML/ELFYAML.h +++ include/llvm/ObjectYAML/ELFYAML.h @@ -124,6 +124,12 @@ llvm::yaml::Hex64 Size; }; +struct NoteEntry { + StringRef Name; + yaml::BinaryRef Desc; + llvm::yaml::Hex32 Type; +}; + struct Section { enum class SectionKind { Dynamic, @@ -131,6 +137,7 @@ RawContent, Relocation, NoBits, + Note, Hash, Verdef, Verneed, @@ -222,6 +229,15 @@ } }; +struct NoteSection : Section { + Optional Content; + Optional Size; + Optional> Notes; + + NoteSection() : Section(SectionKind::Note) {} + static bool classof(const Section *S) { return S->Kind == SectionKind::Note; } +}; + struct HashSection : Section { Optional Content; Optional Size; @@ -386,6 +402,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::AddrsigSymbol) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::StackSizeEntry) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::DynamicEntry) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::NoteEntry) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::ProgramHeader) LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Symbol) @@ -528,6 +545,10 @@ static void mapping(IO &IO, ELFYAML::DynamicEntry &Rel); }; +template <> struct MappingTraits { + static void mapping(IO &IO, ELFYAML::NoteEntry &N); +}; + template <> struct MappingTraits { static void mapping(IO &IO, ELFYAML::VerdefEntry &E); }; Index: include/llvm/Support/YAMLTraits.h =================================================================== --- include/llvm/Support/YAMLTraits.h +++ include/llvm/Support/YAMLTraits.h @@ -649,7 +649,8 @@ inline QuotingType needsQuotes(StringRef S) { if (S.empty()) return QuotingType::Single; - if (isspace(S.front()) || isspace(S.back())) + if (isspace(static_cast(S.front())) || + isspace(static_cast(S.back()))) return QuotingType::Single; if (isNull(S)) return QuotingType::Single; Index: lib/ObjectYAML/ELFEmitter.cpp =================================================================== --- lib/ObjectYAML/ELFEmitter.cpp +++ lib/ObjectYAML/ELFEmitter.cpp @@ -36,6 +36,16 @@ SmallVector Buf; raw_svector_ostream OS; +public: + ContiguousBlobAccumulator(uint64_t InitialOffset_) + : InitialOffset(InitialOffset_), Buf(), OS(Buf) {} + + template + raw_ostream &getOSAndAlignedOffset(Integer &Offset, unsigned Align) { + Offset = padToAlignment(Align); + return OS; + } + /// \returns The new offset. uint64_t padToAlignment(unsigned Align) { if (Align == 0) @@ -46,14 +56,6 @@ return AlignedOffset; // == CurrentOffset; } -public: - ContiguousBlobAccumulator(uint64_t InitialOffset_) - : InitialOffset(InitialOffset_), Buf(), OS(Buf) {} - template - raw_ostream &getOSAndAlignedOffset(Integer &Offset, unsigned Align) { - Offset = padToAlignment(Align); - return OS; - } void writeBlobToStream(raw_ostream &Out) { Out << OS.str(); } }; @@ -177,6 +179,9 @@ void writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::AddrsigSection &Section, ContiguousBlobAccumulator &CBA); + void writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::NoteSection &Section, + ContiguousBlobAccumulator &CBA); ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH); @@ -429,6 +434,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"); } @@ -1020,6 +1027,55 @@ } } +template +void ELFState::writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::NoteSection &Section, + ContiguousBlobAccumulator &CBA) { + raw_ostream &OS = + CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); + uint64_t Offset = OS.tell(); + + if (Section.Content || Section.Size) { + SHeader.sh_size = writeContent(OS, Section.Content, Section.Size); + return; + } + + for (const ELFYAML::NoteEntry &NE : *Section.Notes) { + // Write name size. + if (NE.Name.empty()) + support::endian::write(OS, 0, ELFT::TargetEndianness); + else + support::endian::write(OS, NE.Name.size() + 1, + ELFT::TargetEndianness); + + // Write description size. + if (NE.Desc.binary_size() == 0) + support::endian::write(OS, 0, ELFT::TargetEndianness); + else + support::endian::write(OS, NE.Desc.binary_size(), + ELFT::TargetEndianness); + + // Write type. + support::endian::write(OS, NE.Type, ELFT::TargetEndianness); + + // Write name, null terminator and padding. + if (!NE.Name.empty()) { + support::endian::write(OS, arrayRefFromStringRef(NE.Name), + ELFT::TargetEndianness); + support::endian::write(OS, 0, ELFT::TargetEndianness); + CBA.padToAlignment(4); + } + + // Write description and padding. + if (NE.Desc.binary_size() != 0) { + NE.Desc.writeAsBinary(OS); + CBA.padToAlignment(4); + } + } + + SHeader.sh_size = OS.tell() - Offset; +} + template void ELFState::buildSectionIndex() { for (unsigned I = 0, E = Doc.Sections.size(); I != E; ++I) { StringRef Name = Doc.Sections[I]->Name; Index: lib/ObjectYAML/ELFYAML.cpp =================================================================== --- lib/ObjectYAML/ELFYAML.cpp +++ lib/ObjectYAML/ELFYAML.cpp @@ -1032,6 +1032,13 @@ IO.mapOptional("Size", Section.Size); } +static void sectionMapping(IO &IO, ELFYAML::NoteSection &Section) { + commonSectionMapping(IO, Section); + IO.mapOptional("Content", Section.Content); + IO.mapOptional("Size", Section.Size); + IO.mapOptional("Notes", Section.Notes); +} + static void sectionMapping(IO &IO, ELFYAML::NoBitsSection &Section) { commonSectionMapping(IO, Section); IO.mapOptional("Size", Section.Size, Hex64(0)); @@ -1143,6 +1150,11 @@ Section.reset(new ELFYAML::HashSection()); sectionMapping(IO, *cast(Section.get())); break; + case ELF::SHT_NOTE: + if (!IO.outputting()) + Section.reset(new ELFYAML::NoteSection()); + sectionMapping(IO, *cast(Section.get())); + break; case ELF::SHT_MIPS_ABIFLAGS: if (!IO.outputting()) Section.reset(new ELFYAML::MipsABIFlags()); @@ -1270,6 +1282,24 @@ return {}; } + if (const auto *NS = dyn_cast(Section.get())) { + if (!NS->Content && !NS->Size && !NS->Notes) + return "one of \"Content\", \"Size\" or \"Notes\" must be " + "specified"; + + if (!NS->Content && !NS->Size) + return {}; + + if (NS->Size && NS->Content && + (uint64_t)*NS->Size < NS->Content->binary_size()) + return "\"Size\" must be greater than or equal to the content " + "size"; + + if (NS->Notes) + return "\"Notes\" cannot be used with \"Content\" or \"Size\""; + return {}; + } + return {}; } @@ -1313,6 +1343,14 @@ IO.mapRequired("Value", Rel.Val); } +void MappingTraits::mapping(IO &IO, ELFYAML::NoteEntry &N) { + assert(IO.getContext() && "The IO context is not initialized"); + + IO.mapOptional("Name", N.Name); + IO.mapOptional("Desc", N.Desc); + IO.mapRequired("Type", N.Type); +} + void MappingTraits::mapping(IO &IO, ELFYAML::VerdefEntry &E) { assert(IO.getContext() && "The IO context is not initialized"); Index: test/tools/obj2yaml/elf-sht-note.yaml =================================================================== --- /dev/null +++ test/tools/obj2yaml/elf-sht-note.yaml @@ -0,0 +1,113 @@ +## Check how obj2yaml dumps the SHT_NOTE section. + +## Check how we dump the broken case when the content is less than 12 bytes in size. +## (12 is the size of n_namesz, n_descsz and n_type 4-bytes fields that must always present). + +# RUN: yaml2obj --docnum=1 %s -o %t1 +# RUN: obj2yaml %t1 | FileCheck %s --check-prefix=TOO-SHORT + +# TOO-SHORT: --- !ELF +# TOO-SHORT-NEXT: FileHeader: +# TOO-SHORT-NEXT: Class: ELFCLASS64 +# TOO-SHORT-NEXT: Data: ELFDATA2LSB +# TOO-SHORT-NEXT: Type: ET_DYN +# TOO-SHORT-NEXT: Machine: EM_X86_64 +# TOO-SHORT-NEXT: Sections: +# TOO-SHORT-NEXT: - Name: .note.foo +# TOO-SHORT-NEXT: Type: SHT_NOTE +# TOO-SHORT-NEXT: Content: '0000000000000000000000' + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .note.foo + Type: SHT_NOTE + Size: 11 + +## We can dump the Name, Desc and Type fields when SHT_NOTE has data of +## size >= 12 + size of name, size of desc and their paddings. + +# RUN: yaml2obj --docnum=2 %s -o %t2 +# RUN: obj2yaml %t2 | FileCheck %s --check-prefix=VALID + +# VALID: --- !ELF +# VALID-NEXT: FileHeader: +# VALID-NEXT: Class: ELFCLASS64 +# VALID-NEXT: Data: ELFDATA2LSB +# VALID-NEXT: Type: ET_DYN +# VALID-NEXT: Machine: EM_X86_64 +# VALID-NEXT: Sections: +# VALID-NEXT: - Name: .note.foo +# VALID-NEXT: Type: SHT_NOTE +# VALID-NEXT: Notes: +# VALID-NEXT: - Name: '' +# VALID-NEXT: Desc: '' +# VALID-NEXT: Type: 0x00 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .note.foo + Type: SHT_NOTE + Size: 12 + +## We can't dump the Name, Desc and Type fields when SHT_NOTE has data of +## size < 12 + size of name, desc and their paddings. + +# RUN: yaml2obj --docnum=3 %s -o %t3 +# RUN: obj2yaml %t3 | FileCheck %s --check-prefix=TOO-LONG-NAME-SIZE + +# RUN: yaml2obj --docnum=4 %s -o %t4 +# RUN: obj2yaml %t4 | FileCheck %s --check-prefix=TOO-LONG-DESC-SIZE + +# TOO-LONG-NAME-SIZE: --- !ELF +# TOO-LONG-NAME-SIZE-NEXT: FileHeader: +# TOO-LONG-NAME-SIZE-NEXT: Class: ELFCLASS64 +# TOO-LONG-NAME-SIZE-NEXT: Data: ELFDATA2LSB +# TOO-LONG-NAME-SIZE-NEXT: Type: ET_DYN +# TOO-LONG-NAME-SIZE-NEXT: Machine: EM_X86_64 +# TOO-LONG-NAME-SIZE-NEXT: Sections: +# TOO-LONG-NAME-SIZE-NEXT: - Name: .note.foo +# TOO-LONG-NAME-SIZE-NEXT: Type: SHT_NOTE +# TOO-LONG-NAME-SIZE-NEXT: Content: 0100000000000000FF000000 + +# TOO-LONG-DESC-SIZE: --- !ELF +# TOO-LONG-DESC-SIZE: FileHeader: +# TOO-LONG-DESC-SIZE: Class: ELFCLASS64 +# TOO-LONG-DESC-SIZE: Data: ELFDATA2LSB +# TOO-LONG-DESC-SIZE: Type: ET_DYN +# TOO-LONG-DESC-SIZE: Machine: EM_X86_64 +# TOO-LONG-DESC-SIZE: Sections: +# TOO-LONG-DESC-SIZE: - Name: .note.foo +# TOO-LONG-DESC-SIZE: Type: SHT_NOTE +# TOO-LONG-DESC-SIZE: Content: 0000000001000000FF000000 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .note.foo + Type: SHT_NOTE + Content: "0100000000000000ff00000000" + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .note.foo + Type: SHT_NOTE + Content: "0000000001000000ff00000000" Index: test/tools/yaml2obj/elf-sht-note.yaml =================================================================== --- /dev/null +++ test/tools/yaml2obj/elf-sht-note.yaml @@ -0,0 +1,252 @@ +## Check how yaml2obj produces SHT_NOTE sections. + +## Check we can describe SHT_NOTE using the "Notes" tag. We can define +## notes using names, descriptions and types. +## Check we produce a valid name size and description size fields. +## Check we produce valid paddings. + +# RUN: yaml2obj --docnum=1 %s -o %t1 +# RUN: llvm-readobj --sections --section-data %t1 | FileCheck %s --check-prefix=NOTE + +# NOTE: Section { +# NOTE: Index: 1 +# NOTE-NEXT: Name: .note.foo (1) +# NOTE-NEXT: Type: SHT_NOTE (0x7) +# NOTE-NEXT: Flags [ (0x2) +# NOTE-NEXT: SHF_ALLOC (0x2) +# NOTE-NEXT: ] +# NOTE-NEXT: Address: 0x0 +# NOTE-NEXT: Offset: 0x40 +# NOTE-NEXT: Size: 36 +# NOTE-NEXT: Link: 0 +# NOTE-NEXT: Info: 0 +# NOTE-NEXT: AddressAlignment: 0 +# NOTE-NEXT: EntrySize: 0 +# NOTE-NEXT: SectionData ( +## namesz == (0x03000000) == sizeof("AB") + null terminator. +## descsz == (0x00000000) for an empty description. +## Check we produce a valid 2 bytes zeroes padding after the Name. +# NOTE-NEXT: 0000: 03000000 00000000 FF000000 41420000 |............AB..| +## namesz == (0x04000000) == sizeof("ABC") + null terminator. +## descsz == (0x06000000) == sizeof("123456"). +## Check we produce a valid (zero align to 4) 1 byte padding after the Name. +## Check we produce a valid (zero align to 4) 2 bytes padding after the Desc. +# NOTE-NEXT: 0010: 04000000 03000000 FE000000 41424300 |............ABC.| +# NOTE-NEXT: 0020: 12345600 |.4V.| +# NOTE-NEXT: ) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .note.foo + Type: SHT_NOTE + Flags: [ SHF_ALLOC ] + Notes: + - Name: AB + Desc: '' + Type: 0xFF + - Name: ABC + Desc: '123456' + Type: 254 + +## Check that 'Tag' field is mandatory. + +# RUN: not yaml2obj --docnum=2 %s 2>&1 | FileCheck %s --check-prefix=TAG-REQ +# TAG-REQ: error: missing required key 'Type' + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .note.foo + Type: SHT_NOTE + Notes: + - Name: '' + Desc: '' + +## Check that neither `Name` nor `Desc` are mandatory fields. + +# RUN: yaml2obj --docnum=3 %s -o %t3 +# RUN: llvm-readobj --sections --section-data %t3 | FileCheck %s --check-prefix=NAME-DESC + +# NAME-DESC: Name: .note.foo +# NAME-DESC: SectionData ( +# NAME-DESC-NEXT: 0000: 00000000 00000000 FF000000 | +# NAME-DESC-NEXT: ) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .note.foo + Type: SHT_NOTE + Notes: + - Type: 0xFF + +## Check we can use the "Content" tag to specify any data for SHT_NOTE sections. + +# RUN: yaml2obj --docnum=4 %s -o %t4 +# RUN: llvm-readobj --sections --section-data %t4 | FileCheck %s --check-prefix=CONTENT + +# CONTENT: Name: .note.foo +# CONTENT: SectionData ( +# CONTENT-NEXT: 0000: 11223344 55 | +# CONTENT-NEXT: ) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .note.foo + Type: SHT_NOTE + Content: "1122334455" + +## Either "Content", "Size" or "Notes" must be specifed for SHT_NOTE sections. + +# RUN: not yaml2obj --docnum=5 %s 2>&1 | FileCheck %s --check-prefix=NO-TAGS + +# NO-TAGS: error: one of "Content", "Size" or "Notes" must be specified + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .note.foo + Type: SHT_NOTE + +## "Content" and "Notes" cannot be used together to describe the SHT_NOTE section. + +# RUN: not yaml2obj --docnum=6 %s 2>&1 | FileCheck %s --check-prefix=CONTENT-NOTES + +# CONTENT-NOTES: error: "Notes" cannot be used with "Content" or "Size" + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .note.foo + Type: SHT_NOTE + Content: "" + Notes: [] + +## "Size" and "Notes" cannot be used together to describe the SHT_NOTE section. + +# RUN: not yaml2obj --docnum=7 %s 2>&1 | FileCheck %s --check-prefix=CONTENT-NOTES + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .note.foo + Type: SHT_NOTE + Size: 1 + Notes: [] + +## Check we can use only "Size" to create a SHT_NOTE section. + +# RUN: yaml2obj --docnum=8 %s -o %t8 +# RUN: llvm-readobj --sections --section-data %t8 | FileCheck %s --check-prefix=SIZE + +# SIZE: Name: .note.foo +# SIZE: SectionData ( +# SIZE-NEXT: 0000: 00000000 00000000 00000000 00000000 | +# SIZE-NEXT: 0010: 00 | +# SIZE-NEXT: ) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .note.foo + Type: SHT_NOTE + Size: 0x11 + +## Check we can use "Size" and "Content" together to create a SHT_NOTE section. + +# RUN: yaml2obj --docnum=9 %s -o %t9 +# RUN: llvm-readobj --sections --section-data %t9 | FileCheck %s --check-prefix=SIZE-CONTENT + +# SIZE-CONTENT: Name: .note.sizegr +# SIZE-CONTENT: SectionData ( +# SIZE-CONTENT-NEXT: 0000: 11223300 00 | +# SIZE-CONTENT-NEXT: ) + +# SIZE-CONTENT: Name: .note.sizeeq +# SIZE-CONTENT: SectionData ( +# SIZE-CONTENT-NEXT: 0000: 112233 | +# SIZE-CONTENT-NEXT: ) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .note.sizegr + Type: SHT_NOTE + Size: 0x5 + Content: "112233" + - Name: .note.sizeeq + Type: SHT_NOTE + Size: 0x3 + Content: "112233" + +## Check that when "Size" and "Content" are used together, the size +## must be greater than or equal to the content size. + +# RUN: not yaml2obj --docnum=10 %s 2>&1 | FileCheck %s --check-prefix=SIZE-CONTENT-ERR +# SIZE-CONTENT-ERR: error: "Size" must be greater than or equal to the content size + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .note + Type: SHT_NOTE + Size: 0x1 + Content: "1122" + +## Check we can't use "Size" and "Notes" tags together. + +# RUN: not yaml2obj --docnum=11 %s 2>&1 | FileCheck %s --check-prefix=CONTENT-NOTES + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .note + Type: SHT_NOTE + Size: 0x1 + Notes: [] Index: test/tools/yaml2obj/implicit-sections-types.test =================================================================== --- test/tools/yaml2obj/implicit-sections-types.test +++ test/tools/yaml2obj/implicit-sections-types.test @@ -61,6 +61,7 @@ Type: SHT_PROGBITS - Name: .dynsym Type: SHT_NOTE + Size: 0 - Name: .dynstr Type: SHT_NOBITS ## Needed to set the proper content size for .symtab, so Index: tools/obj2yaml/elf2yaml.cpp =================================================================== --- tools/obj2yaml/elf2yaml.cpp +++ tools/obj2yaml/elf2yaml.cpp @@ -27,6 +27,8 @@ typedef typename ELFT::Word Elf_Word; typedef typename ELFT::Rel Elf_Rel; typedef typename ELFT::Rela Elf_Rela; + using Elf_Nhdr = typename ELFT::Nhdr; + using Elf_Note = typename ELFT::Note; ArrayRef Sections; ArrayRef SymTable; @@ -66,6 +68,7 @@ dumpSymtabShndxSection(const Elf_Shdr *Shdr); Expected dumpNoBitsSection(const Elf_Shdr *Shdr); Expected dumpHashSection(const Elf_Shdr *Shdr); + Expected dumpNoteSection(const Elf_Shdr *Shdr); Expected dumpVerdefSection(const Elf_Shdr *Shdr); Expected dumpSymverSection(const Elf_Shdr *Shdr); Expected dumpVerneedSection(const Elf_Shdr *Shdr); @@ -258,6 +261,13 @@ Y->Sections.emplace_back(*SecOrErr); break; } + case ELF::SHT_NOTE: { + Expected SecOrErr = dumpNoteSection(&Sec); + if (!SecOrErr) + return SecOrErr.takeError(); + Y->Sections.emplace_back(*SecOrErr); + break; + } case ELF::SHT_HASH: { Expected SecOrErr = dumpHashSection(&Sec); if (!SecOrErr) @@ -673,6 +683,42 @@ return S.release(); } +template +Expected +ELFDumper::dumpNoteSection(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(); + + std::vector Entries; + ArrayRef Content = *ContentOrErr; + while (!Content.empty()) { + if (Content.size() < sizeof(Elf_Nhdr)) { + S->Content = yaml::BinaryRef(*ContentOrErr); + return S.release(); + } + + const Elf_Nhdr *Header = reinterpret_cast(Content.data()); + if (Content.size() < Header->getSize()) { + S->Content = yaml::BinaryRef(*ContentOrErr); + return S.release(); + } + + Elf_Note Note(*Header); + Entries.push_back( + {Note.getName(), toStringRef(Note.getDesc()), Note.getType()}); + + Content = Content.drop_front(Header->getSize()); + } + + S->Notes = std::move(Entries); + return S.release(); +} + template Expected ELFDumper::dumpHashSection(const Elf_Shdr *Shdr) {