[llvm] 135df21 - [llvm-readelf] Print raw ELF note contents if we can't parse it

Alex Richardson via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 9 08:59:51 PST 2021


Author: Alex Richardson
Date: 2021-02-09T16:59:22Z
New Revision: 135df21248985579710e0cd3013d369de52dd354

URL: https://github.com/llvm/llvm-project/commit/135df21248985579710e0cd3013d369de52dd354
DIFF: https://github.com/llvm/llvm-project/commit/135df21248985579710e0cd3013d369de52dd354.diff

LOG: [llvm-readelf] Print raw ELF note contents if we can't parse it

Currently, if the note name is known, but the value isn't we don't print
the contents.

Reviewed By: jhenderson

Differential Revision: https://reviews.llvm.org/D74367

Added: 
    

Modified: 
    llvm/test/tools/llvm-readobj/ELF/gnu-note-size.test
    llvm/test/tools/llvm-readobj/ELF/gnu-notes.test
    llvm/test/tools/llvm-readobj/ELF/note-amd.s
    llvm/test/tools/llvm-readobj/ELF/note-amdgpu-invalid.s
    llvm/test/tools/llvm-readobj/ELF/note-amdgpu.test
    llvm/tools/llvm-readobj/ELFDumper.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/tools/llvm-readobj/ELF/gnu-note-size.test b/llvm/test/tools/llvm-readobj/ELF/gnu-note-size.test
index 1166acd3416b..2f131a6cb347 100644
--- 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:     <corrupt GNU_ABI_TAG>
+# 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: <corrupt GNU_ABI_TAG>
+# 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
index 83b5be8ac57d..e73238e6093a 100644
--- 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 @@ Sections:
     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 @@ ProgramHeaders:
 # 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 @@ Sections:
 # 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 @@ ProgramHeaders:
 # 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
index 8130ee575335..c54ebd7aa32c 100644
--- 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 @@ end.isa:
 	.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
index 3f9665e0cd49..25e0d3fc6ab1 100644
--- 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 @@ Sections:
   - 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
index 0a92ae5903f5..f2d89d103a3d 100644
--- 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 @@ Sections:
   - 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
index 81f79393c3a8..f800b650330e 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -4877,11 +4877,12 @@ static StringRef getGNUGoldVersion(ArrayRef<uint8_t> Desc) {
 }
 
 template <typename ELFT>
-static void printGNUNote(raw_ostream &OS, uint32_t NoteType,
+static bool printGNUNote(raw_ostream &OS, uint32_t NoteType,
                          ArrayRef<uint8_t> 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<ELFT>(Desc);
     if (!AbiTag.IsValid)
@@ -4904,6 +4905,7 @@ static void printGNUNote(raw_ostream &OS, uint32_t NoteType,
     break;
   }
   OS << '\n';
+  return true;
 }
 
 struct AMDNote {
@@ -4942,7 +4944,7 @@ static AMDGPUNote getAMDGPUNote(uint32_t NoteType, ArrayRef<uint8_t> Desc) {
         StringRef(reinterpret_cast<const char *>(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 @@ static AMDGPUNote getAMDGPUNote(uint32_t NoteType, ArrayRef<uint8_t> Desc) {
       HSAMetadataString = "Invalid AMDGPU Metadata\n";
 
     raw_string_ostream StrOS(HSAMetadataString);
+    if (MsgPackDoc.getRoot().isScalar()) {
+      // TODO: passing a scalar root to toYAML() asserts:
+      // (PolymorphicTraits<T>::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 @@ template <class ELFT> void GNUELFDumper<ELFT>::printNotes() {
       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<ELFT>(OS, Type, Descriptor);
+      if (printGNUNote<ELFT>(OS, Type, Descriptor))
+        return Error::success();
     } else if (Name == "AMD") {
       const AMDNote N = getAMDNote<ELFT>(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<ELFT>(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<CoreNote> NoteOrErr = readCoreNote(DescExtractor))
+        if (Expected<CoreNote> NoteOrErr = readCoreNote(DescExtractor)) {
           printCoreNote<ELFT>(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 <class ELFT> void LLVMELFDumper<ELFT>::printAddrsig() {
 }
 
 template <typename ELFT>
-static void printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,
+static bool printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> 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<ELFT>(Desc);
     if (!AbiTag.IsValid) {
       W.printString("ABI", "<corrupt GNU_ABI_TAG>");
+      return false;
     } else {
       W.printString("OS", AbiTag.OSName);
       W.printString("ABI", AbiTag.ABI);
@@ -6484,6 +6502,7 @@ static void printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,
       W.printString(Property);
     break;
   }
+  return true;
 }
 
 static void printCoreNoteLLVMStyle(const CoreNote &Note, ScopedPrinter &W) {
@@ -6531,28 +6550,36 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printNotes() {
                     "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<ELFT>(Type, Descriptor, W);
+      if (printGNUNoteLLVMStyle<ELFT>(Type, Descriptor, W))
+        return Error::success();
     } else if (Name == "AMD") {
       const AMDNote N = getAMDNote<ELFT>(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<ELFT>(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<CoreNote> Note = readCoreNote(DescExtractor))
-          printCoreNoteLLVMStyle(*Note, W);
-        else
-          return Note.takeError();
+        if (Expected<CoreNote> 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();


        


More information about the llvm-commits mailing list