[clang] [lld] [llvm] Support .note.gnu.property for enable Zicfiss and Zicfilp extension (PR #77414)

via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 15 00:20:53 PST 2024


https://github.com/SuHo-llrr updated https://github.com/llvm/llvm-project/pull/77414

>From 13841607619f27dd6dcc2289d0380f5b76d99cbe Mon Sep 17 00:00:00 2001
From: SuHsien Ho <su-hsien.ho at mediatek.com>
Date: Thu, 23 Nov 2023 14:36:43 +0800
Subject: [PATCH 1/5] [RISCV][ELF] Add RISCV GNU property label

---
 llvm/include/llvm/BinaryFormat/ELF.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index 8e0356a8efeb61..34c6a2690cbf3f 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -1737,6 +1737,7 @@ enum : unsigned {
   GNU_PROPERTY_NO_COPY_ON_PROTECTED = 2,
   GNU_PROPERTY_AARCH64_FEATURE_1_AND = 0xc0000000,
   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,
@@ -1776,6 +1777,12 @@ enum : unsigned {
   GNU_PROPERTY_X86_ISA_1_V4 = 1 << 3,
 };
 
+// riscv processor feature bits.
+enum : unsigned {
+  GNU_PROPERTY_RISCV_FEATURE_1_ZICFILP = 1 << 0,
+  GNU_PROPERTY_RISCV_FEATURE_1_ZICFISS = 1 << 1,
+};
+
 // FreeBSD note types.
 enum {
   NT_FREEBSD_ABI_TAG = 1,

>From c45570a62ae59848959bb1e99c8df87771b04fe4 Mon Sep 17 00:00:00 2001
From: SuHsien Ho <su-hsien.ho at mediatek.com>
Date: Thu, 23 Nov 2023 14:38:34 +0800
Subject: [PATCH 2/5] [RISCV][ELF] Emit .gnu.note.property for
 Zicfiss/Zicfilip(CFI extension)

---
 .../RISCV/MCTargetDesc/RISCVELFStreamer.cpp   | 43 +++++++++++++++++++
 .../RISCV/MCTargetDesc/RISCVELFStreamer.h     |  1 +
 2 files changed, 44 insertions(+)

diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
index b375e8bb4b8fac..ef1d86624b771d 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
@@ -84,6 +84,35 @@ void RISCVTargetELFStreamer::finishAttributeSection() {
                           ELF::SHT_RISCV_ATTRIBUTES, AttributeSection);
 }
 
+void RISCVTargetELFStreamer::emitNoteSection(unsigned Flags) {
+  if (Flags == 0)
+    return;
+
+  MCStreamer &OutStreamer = getStreamer();
+  MCContext &Context = OutStreamer.getContext();
+  MCSectionELF *Nt = Context.getELFSection(".note.gnu.property", ELF::SHT_NOTE,
+                                           ELF::SHF_ALLOC);
+  MCSection *Cur = OutStreamer.getCurrentSectionOnly();
+  OutStreamer.switchSection(Nt);
+
+  // Emit the note header.
+  OutStreamer.emitValueToAlignment(Align(8));
+  OutStreamer.emitIntValue(4, 4);     // data size for note name
+  OutStreamer.emitIntValue(4 * 4, 4); // data size
+  OutStreamer.emitIntValue(ELF::NT_GNU_PROPERTY_TYPE_0, 4); // note type
+  OutStreamer.emitBytes(StringRef("GNU", 4));               // note name
+
+  // Emit the CFI(ZICFILP/ZICFISS) properties.
+  OutStreamer.emitIntValue(ELF::GNU_PROPERTY_RISCV_FEATURE_1_AND,
+                           4);        // and property
+  OutStreamer.emitIntValue(4, 4);     // data size
+  OutStreamer.emitIntValue(Flags, 4); // data
+  OutStreamer.emitIntValue(0, 4);     // pad
+
+  OutStreamer.endSection(Nt);
+  OutStreamer.switchSection(Cur);
+}
+
 void RISCVTargetELFStreamer::finish() {
   RISCVTargetStreamer::finish();
   MCAssembler &MCA = getStreamer().getAssembler();
@@ -118,6 +147,20 @@ void RISCVTargetELFStreamer::finish() {
   }
 
   MCA.setELFHeaderEFlags(EFlags);
+
+  unsigned GNUNoteFlags = 0;
+
+  // TODO check ZICFILP or ZICFISS with march
+  // should we check with codegen enable ex. -mllvm
+  // -riscv-hardware-shadow-stack=true ?
+  const FeatureBitset &Features = STI.getFeatureBits();
+  if (Features[RISCV::FeatureStdExtZicfilp])
+    GNUNoteFlags |= ELF::GNU_PROPERTY_RISCV_FEATURE_1_ZICFILP;
+
+  if (Features[RISCV::FeatureStdExtZicfiss])
+    GNUNoteFlags |= ELF::GNU_PROPERTY_RISCV_FEATURE_1_ZICFISS;
+
+  emitNoteSection(GNUNoteFlags);
 }
 
 void RISCVTargetELFStreamer::reset() {
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h
index a6f54bf67b5d2b..595dc777c30c4a 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h
@@ -71,6 +71,7 @@ class RISCVTargetELFStreamer : public RISCVTargetStreamer {
   void emitDirectiveVariantCC(MCSymbol &Symbol) override;
 
   void finish() override;
+  void emitNoteSection(unsigned Flags);
 };
 
 MCELFStreamer *createRISCVELFStreamer(MCContext &C,

>From aaff466a9eda11142f558165ad1d5cb87210dcc4 Mon Sep 17 00:00:00 2001
From: SuHsien Ho <su-hsien.ho at mediatek.com>
Date: Thu, 23 Nov 2023 16:37:08 +0800
Subject: [PATCH 3/5] [LLD] Emit .note.gnu.property in RISCV for
 Zicfiss/Zicfilip(CFI extension)

---
 lld/ELF/Driver.cpp            |  2 +-
 lld/ELF/InputFiles.cpp        | 15 ++++++++++++---
 lld/ELF/SyntheticSections.cpp | 15 ++++++++++++---
 3 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 4bb9b7a0b2a983..7f97a3be07ab8f 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -2570,7 +2570,7 @@ static void checkAndReportMissingFeature(StringRef config, uint32_t features,
 // GNU_PROPERTY_AARCH64_FEATURE_1_AND mechanism.
 static uint32_t getAndFeatures() {
   if (config->emachine != EM_386 && config->emachine != EM_X86_64 &&
-      config->emachine != EM_AARCH64)
+      config->emachine != EM_AARCH64 && config->emachine != EM_RISCV)
     return 0;
 
   uint32_t ret = -1;
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 00aebb47640e84..5324c7b95935a8 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -926,9 +926,18 @@ template <class ELFT> static uint32_t readAndFeatures(const InputSection &sec) {
       continue;
     }
 
-    uint32_t featureAndType = config->emachine == EM_AARCH64
-                                  ? GNU_PROPERTY_AARCH64_FEATURE_1_AND
-                                  : GNU_PROPERTY_X86_FEATURE_1_AND;
+    uint32_t featureAndType = 0;
+    switch (config->emachine) {
+    default:
+      featureAndType = GNU_PROPERTY_X86_FEATURE_1_AND;
+      break;
+    case EM_AARCH64:
+      featureAndType = GNU_PROPERTY_AARCH64_FEATURE_1_AND;
+      break;
+    case EM_RISCV:
+      featureAndType = GNU_PROPERTY_RISCV_FEATURE_1_AND;
+      break;
+    }
 
     // Read a body of a NOTE record, which consists of type-length-value fields.
     ArrayRef<uint8_t> desc = note.getDesc(sec.addralign);
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index bada394aa30d7d..1065e5c5be6e14 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -314,9 +314,18 @@ GnuPropertySection::GnuPropertySection()
                        config->wordsize, ".note.gnu.property") {}
 
 void GnuPropertySection::writeTo(uint8_t *buf) {
-  uint32_t featureAndType = config->emachine == EM_AARCH64
-                                ? GNU_PROPERTY_AARCH64_FEATURE_1_AND
-                                : GNU_PROPERTY_X86_FEATURE_1_AND;
+  uint32_t featureAndType = 0;
+  switch (config->emachine) {
+  default:
+    featureAndType = GNU_PROPERTY_X86_FEATURE_1_AND;
+    break;
+  case EM_AARCH64:
+    featureAndType = GNU_PROPERTY_AARCH64_FEATURE_1_AND;
+    break;
+  case EM_RISCV:
+    featureAndType = GNU_PROPERTY_RISCV_FEATURE_1_AND;
+    break;
+  }
 
   write32(buf, 4);                                   // Name size
   write32(buf + 4, config->is64 ? 16 : 12);          // Content size

>From 9b394009151b1932f4d54bde78ee67d46c9b4129 Mon Sep 17 00:00:00 2001
From: SuHsien Ho <su-hsien.ho at mediatek.com>
Date: Thu, 23 Nov 2023 18:21:01 +0800
Subject: [PATCH 4/5] [llvm-readobj] Parse .note.gnu.property in RISCV for
 Zicfiss/Zicfilip(CFI extension)

---
 clang/test/Driver/riscv-cfi-property.c | 32 ++++++++++
 llvm/tools/llvm-readobj/ELFDumper.cpp  | 81 +++++++++++++++++++++-----
 2 files changed, 98 insertions(+), 15 deletions(-)
 create mode 100644 clang/test/Driver/riscv-cfi-property.c

diff --git a/clang/test/Driver/riscv-cfi-property.c b/clang/test/Driver/riscv-cfi-property.c
new file mode 100644
index 00000000000000..f6d97ce52b5506
--- /dev/null
+++ b/clang/test/Driver/riscv-cfi-property.c
@@ -0,0 +1,32 @@
+// When -march with zicfiss0p4 or zicfilp0p4 add GNU property to file object
+
+// RUN: %clang -menable-experimental-extensions -march=rv32gc_zicfiss0p4 -c -o - %s | llvm-readobj -n - | FileCheck -check-prefix=CHECK -check-prefix=CHECK_ZICFISS %s
+// RUN: %clang -menable-experimental-extensions -march=rv64gc_zicfiss0p4 -c -o - %s | llvm-readobj -n - | FileCheck -check-prefix=CHECK -check-prefix=CHECK_ZICFISS %s
+// RUN: %clang -menable-experimental-extensions -march=rv32gc_zicfilp0p4 -c -o - %s | llvm-readobj -n - | FileCheck -check-prefix=CHECK -check-prefix=CHECK_ZICFILP %s
+// RUN: %clang -menable-experimental-extensions -march=rv64gc_zicfilp0p4 -c -o - %s | llvm-readobj -n - | FileCheck -check-prefix=CHECK -check-prefix=CHECK_ZICFILP %s
+// RUN: %clang -menable-experimental-extensions -march=rv32gc_zicfilp0p4_zicfiss0p4 -c -o - %s | llvm-readobj -n - | FileCheck -check-prefix=CHECK -check-prefix=CHECK_ZICFILP_ZICFISS %s
+// RUN: %clang -menable-experimental-extensions -march=rv64gc_zicfilp0p4_zicfiss0p4 -c -o - %s | llvm-readobj -n - | FileCheck -check-prefix=CHECK -check-prefix=CHECK_ZICFILP_ZICFISS %s
+
+
+// CHECK: Name: .note.gnu.property
+// CHECK: Type: NT_GNU_PROPERTY_TYPE_0
+// CHECK: Property [
+// CHECK_ZICFISS: riscv feature: ZICFISS
+// CHECK_ZICFILP: riscv feature: ZICFILP
+// CHECK_ZICFILP_ZICFISS: riscv feature: ZICFILP, ZICFISS
+// CHECK: ]
+
+
+
+
+
+/*.section .note.gnu.property, "a";
+.balign 8;
+.long 0x4;
+.long 0x10;
+.long 0x5
+.asciz "GNU"
+.long 0xc0000000
+.long 4
+.long 3
+.long 0*/
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 50ea63e87a43be..0c058db1ce1e2f 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -5094,7 +5094,7 @@ template <class ELFT> void GNUELFDumper<ELFT>::printAddrsig() {
 
 template <typename ELFT>
 static std::string getGNUProperty(uint32_t Type, uint32_t DataSize,
-                                  ArrayRef<uint8_t> Data) {
+                                  ArrayRef<uint8_t> Data, uint16_t Target) {
   std::string str;
   raw_string_ostream OS(str);
   uint32_t PrData;
@@ -5127,8 +5127,30 @@ static std::string getGNUProperty(uint32_t Type, uint32_t DataSize,
     return OS.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: ");
+
+    if (Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
+      if (Target == ELF::EM_RISCV)
+        OS << "riscv feature: ";
+      else
+        OS << "aarch64 feature: ";
+    } else {
+      OS << "x86 feature: ";
+    }
+    // TODO Should we spilt
+    // GNU_PROPERTY_AARCH64_FEATURE_1_AND and
+    // GNU_PROPERTY_RISCV_FEATURE_1_AND to different label ?
+    /*switch (Type) {
+    default:
+      OS << "x86 feature: ";
+      break;
+    case GNU_PROPERTY_AARCH64_FEATURE_1_AND:
+      OS << "aarch64 feature: ";
+      break;
+    case GNU_PROPERTY_RISCV_FEATURE_1_AND:
+      OS << "riscv feature: ";
+      break;
+    }*/
+
     if (DataSize != 4) {
       OS << format("<corrupt length: 0x%x>", DataSize);
       return OS.str();
@@ -5138,14 +5160,39 @@ static std::string getGNUProperty(uint32_t Type, uint32_t DataSize,
       OS << "<None>";
       return OS.str();
     }
+
     if (Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
-      DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_BTI, "BTI");
-      DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_PAC, "PAC");
-      DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_GCS, "GCS");
+      if (Target == ELF::EM_RISCV) {
+        DumpBit(GNU_PROPERTY_RISCV_FEATURE_1_ZICFILP, "ZICFILP");
+        DumpBit(GNU_PROPERTY_RISCV_FEATURE_1_ZICFISS, "ZICFISS");
+      } else {
+        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 {
       DumpBit(GNU_PROPERTY_X86_FEATURE_1_IBT, "IBT");
       DumpBit(GNU_PROPERTY_X86_FEATURE_1_SHSTK, "SHSTK");
     }
+
+    // TODO Should we spilt
+    // GNU_PROPERTY_AARCH64_FEATURE_1_AND and
+    // GNU_PROPERTY_RISCV_FEATURE_1_AND to different label ?
+    /*switch (Type) {
+    default:
+      DumpBit(GNU_PROPERTY_X86_FEATURE_1_IBT, "IBT");
+      DumpBit(GNU_PROPERTY_X86_FEATURE_1_SHSTK, "SHSTK");
+      break;
+    case GNU_PROPERTY_AARCH64_FEATURE_1_AND:
+      DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_BTI, "BTI");
+      DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_PAC, "PAC");
+      break;
+    case GNU_PROPERTY_RISCV_FEATURE_1_AND:
+      DumpBit(GNU_PROPERTY_RISCV_FEATURE_1_ZICFILP, "ZICFILP");
+      DumpBit(GNU_PROPERTY_RISCV_FEATURE_1_ZICFISS, "ZICFISS");
+      break;
+    }*/
+
     if (PrData)
       OS << format("<unknown flags: 0x%x>", PrData);
     return OS.str();
@@ -5199,7 +5246,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,
+                                                      uint16_t Target) {
   using Elf_Word = typename ELFT::Word;
 
   SmallVector<std::string, 4> Properties;
@@ -5217,8 +5265,8 @@ static SmallVector<std::string, 4> getGNUPropertyList(ArrayRef<uint8_t> Arr) {
       Properties.push_back(OS.str());
       break;
     }
-    Properties.push_back(
-        getGNUProperty<ELFT>(Type, DataSize, Arr.take_front(PaddedSize)));
+    Properties.push_back(getGNUProperty<ELFT>(
+        Type, DataSize, Arr.take_front(PaddedSize), Target));
     Arr = Arr.drop_front(PaddedSize);
   }
 
@@ -5270,7 +5318,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, uint16_t Target) {
   // Return true if we were able to pretty-print the note, false otherwise.
   switch (NoteType) {
   default:
@@ -5292,7 +5340,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, Target))
       OS << "    " << Property << "\n";
     break;
   }
@@ -6012,10 +6060,12 @@ template <class ELFT> void GNUELFDumper<ELFT>::printNotes() {
     else
       OS << "Unknown note type: (" << format_hex(Type, 10) << ")\n";
 
+    uint16_t Target = 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, Target))
         return Error::success();
     } else if (Name == "FreeBSD") {
       if (std::optional<FreeBSDNote> N =
@@ -7642,7 +7692,7 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printAddrsig() {
 
 template <typename ELFT>
 static bool printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,
-                                  ScopedPrinter &W) {
+                                  ScopedPrinter &W, uint16_t Target) {
   // Return true if we were able to pretty-print the note, false otherwise.
   switch (NoteType) {
   default:
@@ -7667,7 +7717,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, Target))
       W.printString(Property);
     break;
   }
@@ -7803,10 +7853,11 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printNotes() {
       W.printString("Type",
                     "Unknown (" + to_string(format_hex(Type, 10)) + ")");
 
+    uint16_t Target = 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, Target))
         return Error::success();
     } else if (Name == "FreeBSD") {
       if (std::optional<FreeBSDNote> N =

>From de7f32f29f9b3b1ae9ae9d7b87b146598f9671a8 Mon Sep 17 00:00:00 2001
From: SuHsien Ho <su-hsien.ho at mediatek.com>
Date: Thu, 23 Nov 2023 19:04:26 +0800
Subject: [PATCH 5/5] [LLD] Add force enable Zicfiss/Zicfilip(CFI extension)
 option

---
 lld/ELF/Config.h                        |  4 +++
 lld/ELF/Driver.cpp                      | 40 ++++++++++++++++++++++++-
 lld/test/ELF/riscv-force-cfi-property.s | 35 ++++++++++++++++++++++
 3 files changed, 78 insertions(+), 1 deletion(-)
 create mode 100644 lld/test/ELF/riscv-force-cfi-property.s

diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index fcca8c42b29b71..552a5060452729 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -187,6 +187,8 @@ struct Config {
   llvm::StringRef cmseOutputLib;
   StringRef zBtiReport = "none";
   StringRef zCetReport = "none";
+  llvm::StringRef zZicfilpReport = "none";
+  llvm::StringRef zZicfissReport = "none";
   bool ltoBBAddrMap;
   llvm::StringRef ltoBasicBlockSections;
   std::pair<llvm::StringRef, llvm::StringRef> thinLTOObjectSuffixReplace;
@@ -324,6 +326,8 @@ struct Config {
   bool zText;
   bool zRetpolineplt;
   bool zWxneeded;
+  bool zForceZicfilp;
+  bool zForceZicfiss;
   DiscardPolicy discard;
   GnuStackKind zGnustack;
   ICFLevel icf;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 7f97a3be07ab8f..1791d275a4d00c 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -463,6 +463,13 @@ static void checkOptions() {
       error("-z bti-report only supported on AArch64");
   }
 
+  if (config->emachine != EM_RISCV) {
+    if (config->zZicfilpReport != "none")
+      error("-z zicfilip-report only support on RISCV32/RISCV64");
+    if (config->zZicfissReport != "none")
+      error("-z zicfiss-report only support on RISCV32/RISCV64");
+  }
+
   if (config->emachine != EM_386 && config->emachine != EM_X86_64 &&
       config->zCetReport != "none")
     error("-z cet-report only supported on X86 and X86_64");
@@ -1455,6 +1462,8 @@ static void readConfigs(opt::InputArgList &args) {
   config->zWxneeded = hasZOption(args, "wxneeded");
   setUnresolvedSymbolPolicy(args);
   config->power10Stubs = args.getLastArgValue(OPT_power10_stubs_eq) != "no";
+  config->zForceZicfilp = hasZOption(args, "force-zicfilp");
+  config->zForceZicfiss = hasZOption(args, "force-zicfiss");
 
   if (opt::Arg *arg = args.getLastArg(OPT_eb, OPT_el)) {
     if (arg->getOption().matches(OPT_eb))
@@ -1497,7 +1506,9 @@ static void readConfigs(opt::InputArgList &args) {
   }
 
   auto reports = {std::make_pair("bti-report", &config->zBtiReport),
-                  std::make_pair("cet-report", &config->zCetReport)};
+                  std::make_pair("cet-report", &config->zCetReport),
+                  std::make_pair("zicfilp-report", &config->zZicfilpReport),
+                  std::make_pair("zicfiss-report", &config->zZicfissReport)};
   for (opt::Arg *arg : args.filtered(OPT_z)) {
     std::pair<StringRef, StringRef> option =
         StringRef(arg->getValue()).split('=');
@@ -2592,6 +2603,16 @@ static uint32_t getAndFeatures() {
         toString(f) + ": -z cet-report: file does not have "
                       "GNU_PROPERTY_X86_FEATURE_1_SHSTK property");
 
+    checkAndReportMissingFeature(
+        config->zZicfilpReport, features, GNU_PROPERTY_RISCV_FEATURE_1_ZICFILP,
+        toString(f) + ": -z zicfilp-report: file does not have "
+                      "GNU_PROPERTY_RISCV_FEATURE_1_ZICFILP property");
+
+    checkAndReportMissingFeature(
+        config->zZicfissReport, features, GNU_PROPERTY_RISCV_FEATURE_1_ZICFISS,
+        toString(f) + ": -z zicfiss-report: file does not have "
+                      "GNU_PROPERTY_RISCV_FEATURE_1_ZICFISS property");
+
     if (config->zForceBti && !(features & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)) {
       features |= GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
       if (config->zBtiReport == "none")
@@ -2604,6 +2625,23 @@ static uint32_t getAndFeatures() {
                            "GNU_PROPERTY_X86_FEATURE_1_IBT property");
       features |= GNU_PROPERTY_X86_FEATURE_1_IBT;
     }
+
+    if (config->zForceZicfilp &&
+        !(features & GNU_PROPERTY_RISCV_FEATURE_1_ZICFILP)) {
+      features |= GNU_PROPERTY_RISCV_FEATURE_1_ZICFILP;
+      if (config->zZicfilpReport == "none")
+        warn(toString(f) + ": -z force-zicfilp: file does not have "
+                           "GNU_PROPERTY_RISCV_FEATURE_1_ZICFILP property");
+    }
+
+    if (config->zForceZicfiss &&
+        !(features & GNU_PROPERTY_RISCV_FEATURE_1_ZICFISS)) {
+      features |= GNU_PROPERTY_RISCV_FEATURE_1_ZICFISS;
+      if (config->zZicfissReport == "none")
+        warn(toString(f) + ": -z force-zicfiss: file does not have "
+                           "GNU_PROPERTY_RISCV_FEATURE_1_ZICFISS property");
+    }
+
     if (config->zPacPlt && !(features & GNU_PROPERTY_AARCH64_FEATURE_1_PAC)) {
       warn(toString(f) + ": -z pac-plt: file does not have "
                          "GNU_PROPERTY_AARCH64_FEATURE_1_PAC property");
diff --git a/lld/test/ELF/riscv-force-cfi-property.s b/lld/test/ELF/riscv-force-cfi-property.s
new file mode 100644
index 00000000000000..65043d1e71261e
--- /dev/null
+++ b/lld/test/ELF/riscv-force-cfi-property.s
@@ -0,0 +1,35 @@
+# REQUIRES: riscv
+
+# RUN: llvm-mc -filetype=obj -triple=riscv32-unknown-elf %s -o %t.rv32_lp.o
+# RUN: ld.lld %t.rv32_lp.o -zforce-zicfilp -o %t.rv32_lp | count 0
+# RUN: llvm-readobj -n %t.rv32_lp | FileCheck -check-prefix=CHECK -check-prefix=CHECK_ZICFILP %s
+
+# RUN: llvm-mc -filetype=obj -triple=riscv64-unknown-elf %s -o %t.rv64_lp.o
+# RUN: ld.lld %t.rv64_lp.o -zforce-zicfilp -o %t.rv64_lp | count 0
+# RUN: llvm-readobj -n %t.rv64_lp | FileCheck -check-prefix=CHECK -check-prefix=CHECK_ZICFILP %s
+
+# RUN: llvm-mc -filetype=obj -triple=riscv32-unknown-elf %s -o %t.rv32_ss.o
+# RUN: ld.lld %t.rv32_ss.o -zforce-zicfiss -o %t.rv32_ss | count 0
+# RUN: llvm-readobj -n %t.rv32_ss | FileCheck -check-prefix=CHECK -check-prefix=CHECK_ZICFISS %s
+
+# RUN: llvm-mc -filetype=obj -triple=riscv64-unknown-elf %s -o %t.rv64_ss.o
+# RUN: ld.lld %t.rv64_ss.o -zforce-zicfiss -o %t.rv64_ss | count 0
+# RUN: llvm-readobj -n %t.rv64_ss | FileCheck -check-prefix=CHECK -check-prefix=CHECK_ZICFISS %s
+
+# RUN: llvm-mc -filetype=obj -triple=riscv32-unknown-elf %s -o %t.rv32_lp_ss.o
+# RUN: ld.lld %t.rv32_lp_ss.o -zforce-zicfilp -zforce-zicfiss -o %t.rv32_lp_ss | count 0
+# RUN: llvm-readobj -n %t.rv32_lp_ss | FileCheck -check-prefix=CHECK -check-prefix=CHECK_ZICFILP_ZICFISS %s
+
+# RUN: llvm-mc -filetype=obj -triple=riscv64-unknown-elf %s -o %t.rv64_lp_ss.o
+# RUN: ld.lld %t.rv64_lp_ss.o -zforce-zicfilp -zforce-zicfiss -o %t.rv64_lp_ss | count 0
+# RUN: llvm-readobj -n %t.rv64_lp_ss | FileCheck -check-prefix=CHECK -check-prefix=CHECK_ZICFILP_ZICFISS %s
+
+
+
+// CHECK: Name: .note.gnu.property
+// CHECK: Type: NT_GNU_PROPERTY_TYPE_0
+// CHECK: Property [
+// CHECK_ZICFISS: riscv feature: ZICFISS
+// CHECK_ZICFILP: riscv feature: ZICFILP
+// CHECK_ZICFILP_ZICFISS: riscv feature: ZICFILP, ZICFISS
+// CHECK: ]



More information about the cfe-commits mailing list