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: 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/llvm-objcopy/ELF/set-section-alignment.test =================================================================== --- test/tools/llvm-objcopy/ELF/set-section-alignment.test +++ test/tools/llvm-objcopy/ELF/set-section-alignment.test @@ -52,3 +52,4 @@ - Name: .baz Type: SHT_NOTE AddressAlign: 4 + Notes: [] Index: test/tools/llvm-readobj/elf-section-types.test =================================================================== --- test/tools/llvm-readobj/elf-section-types.test +++ test/tools/llvm-readobj/elf-section-types.test @@ -155,6 +155,7 @@ Type: SHT_DYNAMIC - Name: note Type: SHT_NOTE + Notes: [] - Name: nobits Type: SHT_NOBITS - Name: rel Index: test/tools/llvm-readobj/gnu-notes.test =================================================================== --- test/tools/llvm-readobj/gnu-notes.test +++ test/tools/llvm-readobj/gnu-notes.test @@ -119,6 +119,7 @@ Sections: - Name: .note Type: SHT_NOTE + Notes: [] ShOffset: 0xffff0000 ## Test tools report an error if a note section has invalid size @@ -140,6 +141,7 @@ - Name: .note Type: SHT_NOTE ShSize: 0xffff0000 + Notes: [] ## Test tools report an error if a note program header has an invalid offset that ## goes past the end of file. @@ -157,8 +159,9 @@ Type: ET_CORE Machine: EM_X86_64 Sections: - - Name: .note - Type: SHT_NOTE + - Name: .note + Type: SHT_NOTE + Notes: [] ProgramHeaders: - Type: PT_NOTE Offset: 0xffff0000 @@ -181,8 +184,9 @@ Type: ET_CORE Machine: EM_X86_64 Sections: - - Name: .note - Type: SHT_NOTE + - Name: .note + Type: SHT_NOTE + Notes: [] ProgramHeaders: - Type: PT_NOTE FileSize: 0xffff0000 Index: test/tools/llvm-size/elf-sysv.test =================================================================== --- test/tools/llvm-size/elf-sysv.test +++ test/tools/llvm-size/elf-sysv.test @@ -74,6 +74,7 @@ Type: SHT_NOTE ShSize: 0x100 Address: 0x4000 + Notes: [] - Name: .nobits Type: SHT_NOBITS ShSize: 0x200 Index: test/tools/obj2yaml/elf-sht-note.yaml =================================================================== --- /dev/null +++ test/tools/obj2yaml/elf-sht-note.yaml @@ -0,0 +1,98 @@ +## Check how obj2yaml dumps SHT_NOTE sections. + +## We can dump the Name, Desc and Type fields when the note section is valid. + +# RUN: yaml2obj --docnum=1 %s -o %t1 +# RUN: obj2yaml %t1 | FileCheck %s --check-prefix=VALID + +# VALID: - Name: .note.foo +# VALID-NEXT: Type: SHT_NOTE +# VALID-NEXT: Notes: +# VALID-NEXT: - Name: '' +# VALID-NEXT: Desc: '' +# VALID-NEXT: Type: 0x00 +# VALID-NEXT: - Name: .note.bar +# VALID-NEXT: Type: SHT_NOTE +# VALID-NEXT: Notes: +# VALID-NEXT: - Name: ABC +# VALID-NEXT: Desc: '001122' +# VALID-NEXT: Type: 0xAABBCCDD + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .note.foo + Type: SHT_NOTE + Size: 12 + - Name: .note.bar + Type: SHT_NOTE + Notes: + - Name: ABC + Desc: '001122' + Type: 0xAABBCCDD + +## Check we dump hex digit pairs if the note section is invalid. + +# RUN: yaml2obj --docnum=2 %s -o %t2 +# RUN: obj2yaml %t2 | FileCheck %s --check-prefix=INVALID + +# INVALID: - Name: .note.tooShortNote +# INVALID-NEXT: Type: SHT_NOTE +# INVALID-NEXT: Content: '0000000000000000000000' +# INVALID-NEXT: - Name: .note.tooLongNameSize +# INVALID-NEXT: Type: SHT_NOTE +# INVALID-NEXT: Content: 0100000000000000FF00000000 +# INVALID-NEXT: - Name: .note.tooLongDescSize +# INVALID-NEXT: Type: SHT_NOTE +# INVALID-NEXT: Content: 0000000001000000FF00000000 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: +## 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). + - Name: .note.tooShortNote + Type: SHT_NOTE + Size: 11 +## We can't dump the Name, Desc and Type fields when the +## content is shorter than the computed size. +## +## Too long name size. + - Name: .note.tooLongNameSize + Type: SHT_NOTE + Content: "0100000000000000ff00000000" +## Too long description size. + - Name: .note.tooLongDescSize + Type: SHT_NOTE + Content: "0000000001000000ff00000000" + +## Check we do not crash when dumping a description that has bytes +## on its bounds that do not fit into signed byte. +## This is a completely normal case, but we had a crash before. + +# RUN: yaml2obj --docnum=3 %s -o %t3 +# RUN: obj2yaml %t3 | FileCheck %s --check-prefix=HEX-DESC + +# HEX-DESC: Desc: FE0000FE + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2MSB + Type: ET_DYN + Machine: EM_MIPS +Sections: + - Name: .note.tag + Type: SHT_NOTE + Flags: [ SHF_ALLOC ] + Notes: + - Desc: 'FE0000FE' + Type: 0 Index: test/tools/yaml2obj/elf-sht-note.yaml =================================================================== --- /dev/null +++ test/tools/yaml2obj/elf-sht-note.yaml @@ -0,0 +1,317 @@ +## 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: +# NOTE-NEXT: Offset: +# 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") + NUL 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") + NUL 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 for 32-bit little-endian case we produce the same section content. + +# RUN: yaml2obj --docnum=2 %s -o %t2 +# RUN: llvm-readobj --sections --section-data %t2 | FileCheck %s --check-prefix=NOTE + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_386 +Sections: + - Name: .note.foo + Type: SHT_NOTE + Flags: [ SHF_ALLOC ] + Notes: + - Name: AB + Desc: '' + Type: 0xFF + - Name: ABC + Desc: '123456' + Type: 254 + +## Check big-endian 32/64 bit cases. +## Check they produce the same content. + +# RUN: yaml2obj --docnum=3 %s -o %t3 +# RUN: llvm-readobj --sections --section-data %t3 | FileCheck %s --check-prefix=NOTE-BE +# RUN: yaml2obj --docnum=4 %s -o %t4 +# RUN: llvm-readobj --sections --section-data %t4 | FileCheck %s --check-prefix=NOTE-BE + +# NOTE-BE: Name: .note.foo +# NOTE-BE: SectionData ( +# NOTE-BE-NEXT: 0000: 00000004 00000003 000000FE 41424300 | +# NOTE-BE-NEXT: 0010: 12345600 | +# NOTE-BE-NEXT: ) + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2MSB + Type: ET_REL + Machine: EM_MIPS +Sections: + - Name: .note.foo + Type: SHT_NOTE + Notes: + - Name: ABC + Desc: '123456' + Type: 254 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2MSB + Type: ET_REL + Machine: EM_MIPS +Sections: + - Name: .note.foo + Type: SHT_NOTE + Notes: + - Name: ABC + Desc: '123456' + Type: 254 + +## Check that 'Type' field is mandatory. + +# RUN: not yaml2obj --docnum=5 %s 2>&1 | FileCheck %s --check-prefix=TYPE-REQ +# TYPE-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=6 %s -o %t6 +# RUN: llvm-readobj --sections --section-data %t6 | 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=7 %s -o %t7 +# RUN: llvm-readobj --sections --section-data %t7 | 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=8 %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=9 %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=10 %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=11 %s -o %t11 +# RUN: llvm-readobj --sections --section-data %t11 | 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=12 %s -o %t12 +# RUN: llvm-readobj --sections --section-data %t12 | 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=13 %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=14 %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(), Note.getDesc(), (llvm::yaml::Hex32)Note.getType()}); + + Content = Content.drop_front(Header->getSize()); + } + + S->Notes = std::move(Entries); + return S.release(); +} + template Expected ELFDumper::dumpHashSection(const Elf_Shdr *Shdr) {