[llvm] [llvm-readobj][ELF][RISCV] Dump .note.gnu.property section contents (PR #125642)

Ming-Yi Lai via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 6 01:50:07 PST 2025


https://github.com/mylai-mtk updated https://github.com/llvm/llvm-project/pull/125642

>From 65cc148abdf66411e9073f3bb9fd585ffbd0e963 Mon Sep 17 00:00:00 2001
From: Ming-Yi Lai <ming-yi.lai at mediatek.com>
Date: Fri, 24 Jan 2025 17:53:35 +0800
Subject: [PATCH] [llvm-readobj][ELF][RISCV] Dump .note.gnu.property section
 contents

RISCV Zicfilp/Zicfiss extensions uses the `.note.gnu.property` section to store
flags indicating the adoption of features based on these extensions. This
patch enables the llvm-readobj/llvm-readelf tools to dump these flags with the
`--notes` flag
---
 llvm/include/llvm/BinaryFormat/ELF.h          |  8 +++
 .../ELF/RISCV/note-gnu-property.yaml          | 45 +++++++++++++++
 llvm/tools/llvm-readobj/ELFDumper.cpp         | 55 ++++++++++++++-----
 3 files changed, 95 insertions(+), 13 deletions(-)
 create mode 100644 llvm/test/tools/llvm-readobj/ELF/RISCV/note-gnu-property.yaml

diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index 8853c4a88b0b593..4b826bbf58f177d 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -1798,6 +1798,7 @@ enum : unsigned {
   GNU_PROPERTY_AARCH64_FEATURE_1_AND = 0xc0000000,
   GNU_PROPERTY_AARCH64_FEATURE_PAUTH = 0xc0000001,
   GNU_PROPERTY_X86_FEATURE_1_AND = 0xc0000002,
+  GNU_PROPERTY_RISCV_FEATURE_1_AND = 0xc0000000,
 
   GNU_PROPERTY_X86_UINT32_OR_LO = 0xc0008000,
   GNU_PROPERTY_X86_FEATURE_2_NEEDED = GNU_PROPERTY_X86_UINT32_OR_LO + 1,
@@ -1862,6 +1863,13 @@ enum : unsigned {
   GNU_PROPERTY_X86_ISA_1_V4 = 1 << 3,
 };
 
+// RISC-V processor feature bits.
+enum : unsigned {
+  GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED = 1 << 0,
+  GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS = 1 << 1,
+  GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG = 1 << 2,
+};
+
 // FreeBSD note types.
 enum {
   NT_FREEBSD_ABI_TAG = 1,
diff --git a/llvm/test/tools/llvm-readobj/ELF/RISCV/note-gnu-property.yaml b/llvm/test/tools/llvm-readobj/ELF/RISCV/note-gnu-property.yaml
new file mode 100644
index 000000000000000..878a5a712d404a3
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/ELF/RISCV/note-gnu-property.yaml
@@ -0,0 +1,45 @@
+# RUN: yaml2obj %s -DBITS=32 -DPR_PADDING= -o %t1
+# RUN: llvm-readelf --notes %t1 | FileCheck %s --check-prefix=GNU
+# RUN: llvm-readobj --notes %t1 | FileCheck %s --check-prefix=LLVM
+
+# RUN: yaml2obj %s -DBITS=64 -DPR_PADDING=00000000 -o %t2
+# RUN: llvm-readelf --notes %t2 | FileCheck %s --check-prefix=GNU
+# RUN: llvm-readobj --notes %t2 | FileCheck %s --check-prefix=LLVM
+
+# GNU: Displaying notes found in: .note.gnu.property
+# GNU-NEXT:   Owner                 Data size	Description
+# GNU-NEXT:   GNU                   0x{{([0-9a-z]{8})}}	NT_GNU_PROPERTY_TYPE_0 (property note)
+# GNU-NEXT:     Properties:    riscv feature: ZICFILP-unlabeled, ZICFISS, ZICFILP-func-sig
+
+# LLVM:      NoteSections [
+# LLVM-NEXT:   NoteSection {
+# LLVM-NEXT:     Name: .note.gnu.property
+# LLVM-NEXT:     Offset:
+# LLVM-NEXT:     Size:
+# LLVM-NEXT:     Notes [
+# LLVM-NEXT:       {
+# LLVM-NEXT:         Owner: GNU
+# LLVM-NEXT:         Data size:
+# LLVM-NEXT:         Type: NT_GNU_PROPERTY_TYPE_0 (property note)
+# LLVM-NEXT:         Property [
+# LLVM-NEXT:           riscv feature: ZICFILP-unlabeled, ZICFISS, ZICFILP-func-sig
+# LLVM-NEXT:         ]
+# LLVM-NEXT:       }
+# LLVM-NEXT:	    ]
+# LLVM-NEXT:   }
+# LLVM-NEXT: ]
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS[[BITS]]
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_RISCV
+Sections:
+  - Name:  .note.gnu.property
+    Type:  SHT_NOTE
+    Flags: [ SHF_ALLOC ]
+    Notes:
+      - Name: 'GNU'
+        Desc: '000000c00400000007000000[[PR_PADDING]]'
+        Type: 5 # NT_GNU_PROPERTY_TYPE_0
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index bfca65aad52b443..d1496971d0ef55a 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -5333,7 +5333,8 @@ static bool printAArch64PAuthABICoreInfo(raw_ostream &OS, uint32_t DataSize,
 
 template <typename ELFT>
 static std::string getGNUProperty(uint32_t Type, uint32_t DataSize,
-                                  ArrayRef<uint8_t> Data) {
+                                  ArrayRef<uint8_t> Data,
+                                  typename ELFT::Half EMachine) {
   std::string str;
   raw_string_ostream OS(str);
   uint32_t PrData;
@@ -5366,8 +5367,25 @@ static std::string getGNUProperty(uint32_t Type, uint32_t DataSize,
     return str;
   case GNU_PROPERTY_AARCH64_FEATURE_1_AND:
   case GNU_PROPERTY_X86_FEATURE_1_AND:
-    OS << ((Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) ? "aarch64 feature: "
-                                                        : "x86 feature: ");
+    static_assert(GNU_PROPERTY_AARCH64_FEATURE_1_AND ==
+                      GNU_PROPERTY_RISCV_FEATURE_1_AND,
+                  "GNU_PROPERTY_RISCV_FEATURE_1_AND should equal "
+                  "GNU_PROPERTY_AARCH64_FEATURE_1_AND, otherwise "
+                  "GNU_PROPERTY_RISCV_FEATURE_1_AND would be skipped!");
+
+    if (EMachine == EM_AARCH64 && Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
+      OS << "aarch64 feature: ";
+    } else if (EMachine == EM_RISCV &&
+               Type == GNU_PROPERTY_RISCV_FEATURE_1_AND) {
+      OS << "riscv feature: ";
+    } else if ((EMachine == EM_386 || EMachine == EM_X86_64) &&
+               Type == GNU_PROPERTY_X86_FEATURE_1_AND) {
+      OS << "x86 feature: ";
+    } else {
+      OS << format("<application-specific type 0x%x>", Type);
+      return str;
+    }
+
     if (DataSize != 4) {
       OS << format("<corrupt length: 0x%x>", DataSize);
       return str;
@@ -5377,10 +5395,16 @@ static std::string getGNUProperty(uint32_t Type, uint32_t DataSize,
       OS << "<None>";
       return str;
     }
-    if (Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
+
+    if (EMachine == EM_AARCH64) {
       DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_BTI, "BTI");
       DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_PAC, "PAC");
       DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_GCS, "GCS");
+    } else if (EMachine == EM_RISCV) {
+      DumpBit(GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED,
+              "ZICFILP-unlabeled");
+      DumpBit(GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS, "ZICFISS");
+      DumpBit(GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_FUNC_SIG, "ZICFILP-func-sig");
     } else {
       DumpBit(GNU_PROPERTY_X86_FEATURE_1_IBT, "IBT");
       DumpBit(GNU_PROPERTY_X86_FEATURE_1_SHSTK, "SHSTK");
@@ -5441,7 +5465,8 @@ static std::string getGNUProperty(uint32_t Type, uint32_t DataSize,
 }
 
 template <typename ELFT>
-static SmallVector<std::string, 4> getGNUPropertyList(ArrayRef<uint8_t> Arr) {
+static SmallVector<std::string, 4>
+getGNUPropertyList(ArrayRef<uint8_t> Arr, typename ELFT::Half EMachine) {
   using Elf_Word = typename ELFT::Word;
 
   SmallVector<std::string, 4> Properties;
@@ -5459,8 +5484,8 @@ static SmallVector<std::string, 4> getGNUPropertyList(ArrayRef<uint8_t> Arr) {
       Properties.push_back(str);
       break;
     }
-    Properties.push_back(
-        getGNUProperty<ELFT>(Type, DataSize, Arr.take_front(PaddedSize)));
+    Properties.push_back(getGNUProperty<ELFT>(
+        Type, DataSize, Arr.take_front(PaddedSize), EMachine));
     Arr = Arr.drop_front(PaddedSize);
   }
 
@@ -5512,7 +5537,7 @@ static StringRef getDescAsStringRef(ArrayRef<uint8_t> Desc) {
 
 template <typename ELFT>
 static bool printGNUNote(raw_ostream &OS, uint32_t NoteType,
-                         ArrayRef<uint8_t> Desc) {
+                         ArrayRef<uint8_t> Desc, typename ELFT::Half EMachine) {
   // Return true if we were able to pretty-print the note, false otherwise.
   switch (NoteType) {
   default:
@@ -5534,7 +5559,7 @@ static bool printGNUNote(raw_ostream &OS, uint32_t NoteType,
     break;
   case ELF::NT_GNU_PROPERTY_TYPE_0:
     OS << "    Properties:";
-    for (const std::string &Property : getGNUPropertyList<ELFT>(Desc))
+    for (const std::string &Property : getGNUPropertyList<ELFT>(Desc, EMachine))
       OS << "    " << Property << "\n";
     break;
   }
@@ -6223,10 +6248,12 @@ template <class ELFT> void GNUELFDumper<ELFT>::printNotes() {
     else
       OS << "Unknown note type: (" << format_hex(Type, 10) << ")\n";
 
+    const typename ELFT::Half EMachine = this->Obj.getHeader().e_machine;
+
     // Print the description, or fallback to printing raw bytes for unknown
     // owners/if we fail to pretty-print the contents.
     if (Name == "GNU") {
-      if (printGNUNote<ELFT>(OS, Type, Descriptor))
+      if (printGNUNote<ELFT>(OS, Type, Descriptor, EMachine))
         return Error::success();
     } else if (Name == "FreeBSD") {
       if (std::optional<FreeBSDNote> N =
@@ -7913,7 +7940,8 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printAddrsig() {
 
 template <typename ELFT>
 static bool printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,
-                                  ScopedPrinter &W) {
+                                  ScopedPrinter &W,
+                                  typename ELFT::Half EMachine) {
   // Return true if we were able to pretty-print the note, false otherwise.
   switch (NoteType) {
   default:
@@ -7938,7 +7966,7 @@ static bool printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,
     break;
   case ELF::NT_GNU_PROPERTY_TYPE_0:
     ListScope D(W, "Property");
-    for (const std::string &Property : getGNUPropertyList<ELFT>(Desc))
+    for (const std::string &Property : getGNUPropertyList<ELFT>(Desc, EMachine))
       W.printString(Property);
     break;
   }
@@ -8057,10 +8085,11 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printNotes() {
       W.printString("Type",
                     "Unknown (" + to_string(format_hex(Type, 10)) + ")");
 
+    const typename ELFT::Half EMachine = this->Obj.getHeader().e_machine;
     // Print the description, or fallback to printing raw bytes for unknown
     // owners/if we fail to pretty-print the contents.
     if (Name == "GNU") {
-      if (printGNUNoteLLVMStyle<ELFT>(Type, Descriptor, W))
+      if (printGNUNoteLLVMStyle<ELFT>(Type, Descriptor, W, EMachine))
         return Error::success();
     } else if (Name == "FreeBSD") {
       if (std::optional<FreeBSDNote> N =



More information about the llvm-commits mailing list