diff --git a/llvm/test/tools/llvm-readobj/ELF/gnu-note-size.test b/llvm/test/tools/llvm-readobj/ELF/gnu-note-size.test --- a/llvm/test/tools/llvm-readobj/ELF/gnu-note-size.test +++ b/llvm/test/tools/llvm-readobj/ELF/gnu-note-size.test @@ -1,11 +1,15 @@ +## Check that a malformed NT_GNU_ABI_TAG note can be dumped without crashing. # RUN: yaml2obj %s -o %t # RUN: llvm-readelf --notes %t | FileCheck %s --check-prefix=GNU # RUN: llvm-readobj --elf-output-style LLVM --notes %t | FileCheck %s --check-prefix=LLVM +## GNU binutils does not print the raw description data when encountering an +## invalid NT_GNU_ABI_TAG, but in LLVM style we print it. # GNU: Displaying notes found in: .note.ABI-tag # GNU-NEXT: Owner Data size Description # GNU-NEXT: GNU 0x00000004 NT_GNU_ABI_TAG (ABI version tag) # GNU-NEXT: +# GNU-EMPTY: # LLVM: Notes [ # LLVM-NEXT: NoteSection { @@ -17,6 +21,9 @@ # LLVM-NEXT: Data size: 0x4 # LLVM-NEXT: Type: NT_GNU_ABI_TAG (ABI version tag) # LLVM-NEXT: ABI: +# LLVM-NEXT: Description data ( +# LLVM-NEXT: 0000: 00000000 |....| +# LLVM-NEXT: ) # LLVM-NEXT: } # LLVM-NEXT: } # LLVM-NEXT: ] diff --git a/llvm/test/tools/llvm-readobj/ELF/gnu-notes.test b/llvm/test/tools/llvm-readobj/ELF/gnu-notes.test --- a/llvm/test/tools/llvm-readobj/ELF/gnu-notes.test +++ b/llvm/test/tools/llvm-readobj/ELF/gnu-notes.test @@ -11,16 +11,22 @@ # GNU-NEXT: Owner Data size Description # GNU-NEXT: GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag) # GNU-NEXT: OS: Linux, ABI: 2.6.32 - -# GNU:Displaying notes found in: .note.gnu.build-id +# GNU-EMPTY: +# GNU-NEXT:Displaying notes found in: .note.gnu.build-id # GNU-NEXT: Owner Data size Description # GNU-NEXT: GNU 0x00000010 NT_GNU_BUILD_ID (unique build ID bitstring) # GNU-NEXT: Build ID: 4fcb712aa6387724a9f465a32cd8c14b - -# GNU:Displaying notes found in: .note.gnu.gold-version +# GNU-EMPTY: +# GNU-NEXT:Displaying notes found in: .note.gnu.gold-version # GNU-NEXT: Owner Data size Description # GNU-NEXT: GNU 0x00000009 NT_GNU_GOLD_VERSION (gold version) # GNU-NEXT: Version: gold 1.11 +# GNU-EMPTY: +# GNU-NEXT:Displaying notes found in: .note.gnu.unknown +# GNU-NEXT: Owner Data size Description +# GNU-NEXT: GNU 0x00000004 Unknown note type: (0x0000abcd) +# GNU-NEXT: description data: 61 62 63 64 +# GNU-EMPTY: # LLVM: Notes [ # LLVM-NEXT: NoteSection { @@ -57,6 +63,19 @@ # LLVM-NEXT: Version: gold 1.11 # LLVM-NEXT: } # LLVM-NEXT: } +# LLVM-NEXT: NoteSection { +# LLVM-NEXT: Name: .note.gnu.unknown +# LLVM-NEXT: Offset: 0xD4 +# LLVM-NEXT: Size: 0x14 +# LLVM-NEXT: Note { +# LLVM-NEXT: Owner: GNU +# LLVM-NEXT: Data size: 0x4 +# LLVM-NEXT: Type: Unknown (0x0000abcd) +# LLVM-NEXT: Description data ( +# LLVM-NEXT: 0000: 61626364 |abcd| +# LLVM-NEXT: ) +# LLVM-NEXT: } +# LLVM-NEXT: } # LLVM-NEXT: ] ## Note: the section name is here because the section header table is not present. @@ -103,6 +122,10 @@ Type: SHT_NOTE AddressAlign: 0x0000000000000004 Content: 040000000900000004000000474E5500676F6C6420312E3131000000 + - Name: .note.gnu.unknown + Type: SHT_NOTE + AddressAlign: 0x0000000000000004 + Content: 0400000004000000cdab0000474E550061626364 ProgramHeaders: - Type: PT_NOTE FileSize: 0x20 @@ -119,7 +142,7 @@ # ERR1-GNU: Displaying notes found in: .note # ERR1-GNU-NEXT: Owner Data size Description # ERR1-GNU-NEXT: warning: '[[FILE]]': unable to read notes from the SHT_NOTE section with index 1: invalid offset (0xffff0000) or size (0x0) -# ERR1-GNU-NOT: {{.}} +# ERR1-GNU-EMPTY: # ERR1-LLVM: Notes [ # ERR1-LLVM-NEXT: NoteSection { @@ -152,7 +175,7 @@ # ERR2-GNU: Displaying notes found in: .note # ERR2-GNU-NEXT: Owner Data size Description # ERR2-GNU-NEXT: warning: '[[FILE]]': unable to read notes from the SHT_NOTE section with index 1: invalid offset (0x40) or size (0xffff0000) -# ERR2-GNU-NOT: {{.}} +# ERR2-GNU-EMPTY: # ERR2-LLVM: Notes [ # ERR2-LLVM-NEXT: NoteSection { @@ -204,7 +227,7 @@ # ERR4-GNU: Displaying notes found at file offset 0x00000000 with length 0xffff0000: # ERR4-GNU-NEXT: Owner Data size Description # ERR4-GNU-NEXT: warning: '[[FILE]]': unable to read notes from the PT_NOTE segment with index 0: invalid offset (0x0) or size (0xffff0000) -# ERR4-GNU-NOT: {{.}} +# ERR4-GNU-EMPTY: # ERR4-LLVM: Notes [ # ERR4-LLVM-NEXT: NoteSection { diff --git a/llvm/test/tools/llvm-readobj/ELF/note-amd.s b/llvm/test/tools/llvm-readobj/ELF/note-amd.s --- a/llvm/test/tools/llvm-readobj/ELF/note-amd.s +++ b/llvm/test/tools/llvm-readobj/ELF/note-amd.s @@ -26,6 +26,11 @@ // GNU-NEXT: Owner Data size Description // GNU-NEXT: AMD 0x00000000 NT_AMD_AMDGPU_PAL_METADATA (PAL Metadata) // GNU-EMPTY: +// GNU-NEXT: Displaying notes found in: .note.unknown +// GNU-NEXT: Owner Data size Description +// GNU-NEXT: AMD 0x00000007 Unknown note type: (0x000004d2) +// GNU-NEXT: description data: 61 62 63 64 65 66 00 +// GNU-EMPTY: // LLVM: Notes [ // LLVM-NEXT: NoteSection { @@ -72,6 +77,19 @@ // LLVM-NEXT: Type: NT_AMD_AMDGPU_PAL_METADATA (PAL Metadata) // LLVM-NEXT: } // LLVM-NEXT: } +// LLVM-NEXT: NoteSection { +// LLVM-NEXT: Name: .note.unknown +// LLVM-NEXT: Offset: +// LLVM-NEXT: Size: +// LLVM-NEXT: Note { +// LLVM-NEXT: Owner: AMD +// LLVM-NEXT: Data size: 0x7 +// LLVM-NEXT: Type: Unknown (0x000004d2) +// LLVM-NEXT: Description data ( +// LLVM-NEXT: 0000: 61626364 656600 |abcdef.| +// LLVM-NEXT: ) +// LLVM-NEXT: } +// LLVM-NEXT: } // LLVM-NEXT: ] .section ".note.no.desc", "a" @@ -108,3 +126,13 @@ .long 0 /* descsz */ .long 12 /* type = NT_AMD_AMDGPU_PAL_METADATA */ .asciz "AMD" +.section ".note.unknown", "a" + .align 4 + .long 4 /* namesz */ + .long end.unknown_data - begin.unknown_data /* descsz */ + .long 1234 /* type = unknown */ + .asciz "AMD" +begin.unknown_data: + .asciz "abcdef" +end.unknown_data: + .align 4 diff --git a/llvm/test/tools/llvm-readobj/ELF/note-amdgpu-invalid.s b/llvm/test/tools/llvm-readobj/ELF/note-amdgpu-invalid.s --- a/llvm/test/tools/llvm-readobj/ELF/note-amdgpu-invalid.s +++ b/llvm/test/tools/llvm-readobj/ELF/note-amdgpu-invalid.s @@ -21,6 +21,12 @@ # GNU-NEXT: .wavefront_size: 5 # GNU-NEXT: ... # GNU-EMPTY: +# GNU-EMPTY: +# GNU-NEXT: Displaying notes found in: .note.bar +# GNU-NEXT: Owner Data size Description +# GNU-NEXT: AMDGPU 0x00000003 NT_AMDGPU_METADATA (AMDGPU Metadata) +# GNU-NEXT: description data: 12 34 56 +# GNU-EMPTY: # LLVM: Notes [ # LLVM-NEXT: NoteSection { @@ -48,7 +54,20 @@ # LLVM-EMPTY: # LLVM-NEXT: } # LLVM-NEXT: } -# LLVM-NEXT: ] +# LLVM-NEXT: NoteSection { +# LLVM-NEXT: Name: .note.bar +# LLVM-NEXT: Offset: 0x128 +# LLVM-NEXT: Size: 0x18 +# LLVM-NEXT: Note { +# LLVM-NEXT: Owner: AMDGPU +# LLVM-NEXT: Data size: 0x3 +# LLVM-NEXT: Type: NT_AMDGPU_METADATA (AMDGPU Metadata) +# LLVM-NEXT: Description data ( +# LLVM-NEXT: 0000: 123456 |.4V| +# LLVM-NEXT: ) +# LLVM-NEXT: } +# LLVM-NEXT: } +# LLVM-NEXT:] ## Use yaml2obj instead of llvm-mc for more test portability. This was ## generated by grabbing section data from note-amdgpu.s and removing the amdhsa.version field. @@ -62,3 +81,13 @@ - Name: .note.foo Type: SHT_NOTE Content: 07000000D400000020000000414D44475055000081ae616d646873612e6b65726e656c73918ab92e67726f75705f7365676d656e745f66697865645f73697a6502b62e6b65726e6172675f7365676d656e745f616c69676e04b52e6b65726e6172675f7365676d656e745f73697a6501b82e6d61785f666c61745f776f726b67726f75705f73697a6508a52e6e616d65a3666f6fbb2e707269766174655f7365676d656e745f66697865645f73697a6503ab2e736770725f636f756e7406a72e73796d626f6ca3666f6fab2e766770725f636f756e7407af2e7761766566726f6e745f73697a6505 + - Name: .note.bar + Type: SHT_NOTE + Notes: + - Name: AMDGPU + Type: NT_AMDGPU_METADATA + Desc: '123456' + # TODO: https://bugs.llvm.org/show_bug.cgi?id=49034 + # - Name: AMDGPU + # Type: NT_AMDGPU_METADATA + # Desc: 'abcdef' diff --git a/llvm/test/tools/llvm-readobj/ELF/note-amdgpu.test b/llvm/test/tools/llvm-readobj/ELF/note-amdgpu.test --- a/llvm/test/tools/llvm-readobj/ELF/note-amdgpu.test +++ b/llvm/test/tools/llvm-readobj/ELF/note-amdgpu.test @@ -22,6 +22,13 @@ # GNU-NEXT: - 1 # GNU-NEXT: - 0 # GNU-NEXT: ... +# GNU-EMPTY: +# GNU-EMPTY: +# GNU-NEXT: Displaying notes found in: .note.unknown +# GNU-NEXT: Owner Data size Description +# GNU-NEXT: AMDGPU 0x00000002 Unknown note type: (0x00000101) +# GNU-NEXT: description data: ab cd +# GNU-EMPTY: # LLVM: Notes [ # LLVM-NEXT: NoteSection { @@ -51,6 +58,19 @@ # LLVM-EMPTY: # LLVM-NEXT: } # LLVM-NEXT: } +# LLVM-NEXT: NoteSection { +# LLVM-NEXT: Name: .note.unknown +# LLVM-NEXT: Offset: 0x13C +# LLVM-NEXT: Size: 0x18 +# LLVM-NEXT: Note { +# LLVM-NEXT: Owner: AMDGPU +# LLVM-NEXT: Data size: 0x2 +# LLVM-NEXT: Type: Unknown (0x00000101) +# LLVM-NEXT: Description data ( +# LLVM-NEXT: 0000: ABCD |..| +# LLVM-NEXT: ) +# LLVM-NEXT: } +# LLVM-NEXT: } # LLVM-NEXT: ] ## Use yaml2obj instead of llvm-mc for more test portability. This was @@ -83,3 +103,9 @@ - Name: .note.foo Type: SHT_NOTE Content: 07000000E600000020000000414D44475055000082AE616D646873612E6B65726E656C73918AB92E67726F75705F7365676D656E745F66697865645F73697A6502B62E6B65726E6172675F7365676D656E745F616C69676E04B52E6B65726E6172675F7365676D656E745F73697A6501B82E6D61785F666C61745F776F726B67726F75705F73697A6508A52E6E616D65A3666F6FBB2E707269766174655F7365676D656E745F66697865645F73697A6503AB2E736770725F636F756E7406A72E73796D626F6CA3666F6FAB2E766770725F636F756E7407AF2E7761766566726F6E745F73697A6505AE616D646873612E76657273696F6E9201000000 + - Name: .note.unknown + Type: SHT_NOTE + Notes: + - Name: AMDGPU + Type: NT_GNU_BUILD_ATTRIBUTE_FUNC + Desc: 'abcd' diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -4877,11 +4877,12 @@ } template -static void printGNUNote(raw_ostream &OS, uint32_t NoteType, +static bool printGNUNote(raw_ostream &OS, uint32_t NoteType, ArrayRef Desc) { + // Return true if we were able to pretty-print the note, false otherwise. switch (NoteType) { default: - return; + return false; case ELF::NT_GNU_ABI_TAG: { const GNUAbiTag &AbiTag = getGNUAbiTag(Desc); if (!AbiTag.IsValid) @@ -4904,6 +4905,7 @@ break; } OS << '\n'; + return true; } struct AMDNote { @@ -4942,7 +4944,7 @@ StringRef(reinterpret_cast(Desc.data()), Desc.size()); msgpack::Document MsgPackDoc; if (!MsgPackDoc.readFromBlob(MsgPackString, /*Multi=*/false)) - return {"AMDGPU Metadata", "Invalid AMDGPU Metadata"}; + return {"", ""}; AMDGPU::HSAMD::V3::MetadataVerifier Verifier(true); std::string HSAMetadataString; @@ -4950,8 +4952,14 @@ HSAMetadataString = "Invalid AMDGPU Metadata\n"; raw_string_ostream StrOS(HSAMetadataString); + if (MsgPackDoc.getRoot().isScalar()) { + // TODO: passing a scalar root to toYAML() asserts: + // (PolymorphicTraits::getKind(Val) != NodeKind::Scalar && + // "plain scalar documents are not supported") + // To avoid this crash we print the raw data instead. + return {"", ""}; + } MsgPackDoc.toYAML(StrOS); - return {"AMDGPU Metadata", StrOS.str()}; } } @@ -5271,28 +5279,36 @@ OS << "Unknown note type: (" << format_hex(Type, 10) << ")\n"; // Print the description, or fallback to printing raw bytes for unknown - // owners. + // owners/if we fail to pretty-print the contents. if (Name == "GNU") { - printGNUNote(OS, Type, Descriptor); + if (printGNUNote(OS, Type, Descriptor)) + return Error::success(); } else if (Name == "AMD") { const AMDNote N = getAMDNote(Type, Descriptor); - if (!N.Type.empty()) + if (!N.Type.empty()) { OS << " " << N.Type << ":\n " << N.Value << '\n'; + return Error::success(); + } } else if (Name == "AMDGPU") { const AMDGPUNote N = getAMDGPUNote(Type, Descriptor); - if (!N.Type.empty()) + if (!N.Type.empty()) { OS << " " << N.Type << ":\n " << N.Value << '\n'; + return Error::success(); + } } else if (Name == "CORE") { if (Type == ELF::NT_FILE) { DataExtractor DescExtractor(Descriptor, ELFT::TargetEndianness == support::little, sizeof(Elf_Addr)); - if (Expected NoteOrErr = readCoreNote(DescExtractor)) + if (Expected NoteOrErr = readCoreNote(DescExtractor)) { printCoreNote(OS, *NoteOrErr); - else + return Error::success(); + } else { return NoteOrErr.takeError(); + } } - } else if (!Descriptor.empty()) { + } + if (!Descriptor.empty()) { OS << " description data:"; for (uint8_t B : Descriptor) OS << " " << format("%02x", B); @@ -6456,15 +6472,17 @@ } template -static void printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef Desc, +static bool printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef Desc, ScopedPrinter &W) { + // Return true if we were able to pretty-print the note, false otherwise. switch (NoteType) { default: - return; + return false; case ELF::NT_GNU_ABI_TAG: { const GNUAbiTag &AbiTag = getGNUAbiTag(Desc); if (!AbiTag.IsValid) { W.printString("ABI", ""); + return false; } else { W.printString("OS", AbiTag.OSName); W.printString("ABI", AbiTag.ABI); @@ -6484,6 +6502,7 @@ W.printString(Property); break; } + return true; } static void printCoreNoteLLVMStyle(const CoreNote &Note, ScopedPrinter &W) { @@ -6531,28 +6550,36 @@ "Unknown (" + to_string(format_hex(Type, 10)) + ")"); // Print the description, or fallback to printing raw bytes for unknown - // owners. + // owners/if we fail to pretty-print the contents. if (Name == "GNU") { - printGNUNoteLLVMStyle(Type, Descriptor, W); + if (printGNUNoteLLVMStyle(Type, Descriptor, W)) + return Error::success(); } else if (Name == "AMD") { const AMDNote N = getAMDNote(Type, Descriptor); - if (!N.Type.empty()) + if (!N.Type.empty()) { W.printString(N.Type, N.Value); + return Error::success(); + } } else if (Name == "AMDGPU") { const AMDGPUNote N = getAMDGPUNote(Type, Descriptor); - if (!N.Type.empty()) + if (!N.Type.empty()) { W.printString(N.Type, N.Value); + return Error::success(); + } } else if (Name == "CORE") { if (Type == ELF::NT_FILE) { DataExtractor DescExtractor(Descriptor, ELFT::TargetEndianness == support::little, sizeof(Elf_Addr)); - if (Expected Note = readCoreNote(DescExtractor)) - printCoreNoteLLVMStyle(*Note, W); - else - return Note.takeError(); + if (Expected N = readCoreNote(DescExtractor)) { + printCoreNoteLLVMStyle(*N, W); + return Error::success(); + } else { + return N.takeError(); + } } - } else if (!Descriptor.empty()) { + } + if (!Descriptor.empty()) { W.printBinaryBlock("Description data", Descriptor); } return Error::success();