[llvm] [RISCV] Emit .note.gnu.property section for Zicfilp CFI unlabeled scheme (PR #141468)

via llvm-commits llvm-commits at lists.llvm.org
Mon May 26 03:05:27 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-risc-v

Author: Ming-Yi Lai (mylai-mtk)

<details>
<summary>Changes</summary>

RISC-V Zicfilp-based CFI needs to let the linker/loader know if the binary is built with the mechanism enabled to support proper link-time/load-time management of this feature. The information is encoded as a bit in the `.note.gnu.property` section. This patch implements emitting the section for RISC-V targets when Zicfilp-based CFI with the "unlabeled" label scheme is enabled.

When Clang receives the `-fcf-protection=branch` flag, which enables forward-edge CFI protection, it adds the `cf-protection-branch` attribute to the LLVM module. Additionally, if a branch label scheme is needed, another attribute (`cf-branch-label-scheme`) is added to indicate it. For RISC-V targets, the `cf-protection-branch` attribute indicates the adoption of Zicfilp-based forward-edge CFI protection, and the `cf-branch-label-scheme` attribute selects how the "label" operands of the Zicfilp `lpad` insns are produced. This patch emits the proper `.note.gnu.property` feature bit when the RISC-V backend sees that the LLVM module has the `cf-protection-branch` attribute set to `1`, and the `cf-branch-label-scheme` attribute set to `unlabeled`, so linkers/loaders know that the object file is built with Zicfilp-based forward-edge CFI protection with the "unlabeled" scheme.

---
Full diff: https://github.com/llvm/llvm-project/pull/141468.diff


3 Files Affected:

- (modified) llvm/include/llvm/Support/RISCVISAUtils.h (+19) 
- (modified) llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp (+32-3) 
- (added) llvm/test/CodeGen/RISCV/note-gnu-property-zicfilp-unlabeled.ll (+27) 


``````````diff
diff --git a/llvm/include/llvm/Support/RISCVISAUtils.h b/llvm/include/llvm/Support/RISCVISAUtils.h
index 165bb08d66431..e2dd833de74fd 100644
--- a/llvm/include/llvm/Support/RISCVISAUtils.h
+++ b/llvm/include/llvm/Support/RISCVISAUtils.h
@@ -14,7 +14,9 @@
 #define LLVM_SUPPORT_RISCVISAUTILS_H
 
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/Compiler.h"
+#include <cassert>
 #include <map>
 #include <string>
 
@@ -43,6 +45,23 @@ struct ExtensionComparator {
 typedef std::map<std::string, ExtensionVersion, ExtensionComparator>
     OrderedExtensionMap;
 
+enum class ZicfilpLabelSchemeKind {
+  Invalid,
+  Unlabeled,
+  FuncSig,
+};
+
+// See clang::getCFBranchLabelSchemeFlagVal() for possible CFBranchLabelScheme
+inline ZicfilpLabelSchemeKind
+getZicfilpLabelScheme(const StringRef CFBranchLabelScheme) {
+  const auto Ret = StringSwitch<ZicfilpLabelSchemeKind>(CFBranchLabelScheme)
+                       .Case("unlabeled", ZicfilpLabelSchemeKind::Unlabeled)
+                       .Case("func-sig", ZicfilpLabelSchemeKind::FuncSig)
+                       .Default(ZicfilpLabelSchemeKind::Invalid);
+  assert(Ret != ZicfilpLabelSchemeKind::Invalid);
+  return Ret;
+}
+
 } // namespace RISCVISAUtils
 
 } // namespace llvm
diff --git a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
index 72f1596d79a02..62d5888e77daa 100644
--- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
+++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
@@ -946,12 +946,41 @@ void RISCVAsmPrinter::EmitHwasanMemaccessSymbols(Module &M) {
 }
 
 void RISCVAsmPrinter::emitNoteGnuProperty(const Module &M) {
+  uint32_t Feature1And = 0;
   if (const Metadata *const Flag = M.getModuleFlag("cf-protection-return");
+      Flag && !mdconst::extract<ConstantInt>(Flag)->isZero())
+    Feature1And |= ELF::GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS;
+
+  if (const Metadata *const Flag = M.getModuleFlag("cf-protection-branch");
       Flag && !mdconst::extract<ConstantInt>(Flag)->isZero()) {
-    RISCVTargetStreamer &RTS =
-        static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
-    RTS.emitNoteGnuPropertySection(ELF::GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS);
+    using namespace llvm::RISCVISAUtils;
+    const Metadata *const CFBranchLabelSchemeFlag =
+        M.getModuleFlag("cf-branch-label-scheme");
+    assert(CFBranchLabelSchemeFlag &&
+           "cf-protection=branch should come with cf-branch-label-scheme=... "
+           "on RISC-V targets");
+    const StringRef CFBranchLabelScheme =
+        cast<MDString>(CFBranchLabelSchemeFlag)->getString();
+    switch (getZicfilpLabelScheme(CFBranchLabelScheme)) {
+    case ZicfilpLabelSchemeKind::Invalid:
+      llvm_unreachable("invalid RISC-V Zicfilp label scheme");
+    case ZicfilpLabelSchemeKind::Unlabeled:
+      Feature1And |= ELF::GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED;
+      break;
+    case ZicfilpLabelSchemeKind::FuncSig:
+      // TODO: Emit the func-sig bit after the feature is implemented
+      report_fatal_error("The complete func-sig label scheme feature had not "
+                         "been implemented yet");
+      break;
+    }
   }
+
+  if (!Feature1And)
+    return;
+
+  RISCVTargetStreamer &RTS =
+      static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
+  RTS.emitNoteGnuPropertySection(Feature1And);
 }
 
 static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
diff --git a/llvm/test/CodeGen/RISCV/note-gnu-property-zicfilp-unlabeled.ll b/llvm/test/CodeGen/RISCV/note-gnu-property-zicfilp-unlabeled.ll
new file mode 100644
index 0000000000000..cfc9ca44c1eb7
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/note-gnu-property-zicfilp-unlabeled.ll
@@ -0,0 +1,27 @@
+; RUN: llc --mtriple=riscv32 --filetype=obj -o - %s | llvm-readelf -n - | FileCheck --check-prefixes=READELF %s
+; RUN: llc --mtriple=riscv64 --filetype=obj -o - %s | llvm-readelf -n - | FileCheck --check-prefixes=READELF %s
+; RUN: llc --mtriple=riscv32 -o - %s | FileCheck --check-prefixes=ASM,ASM32 %s
+; RUN: llc --mtriple=riscv64 -o - %s | FileCheck --check-prefixes=ASM,ASM64 %s
+
+; READELF: Properties: RISC-V feature: ZICFILP-unlabeled
+
+; ASM:                .section        ".note.GNU-stack","", at progbits
+; ASM-NEXT:           .section        .note.gnu.property,"a", at note
+; ASM-NEXT:           .word   4
+; ASM-NEXT:           .word   .Ltmp1-.Ltmp0
+; ASM-NEXT:           .word   5
+; ASM-NEXT:           .asciz  "GNU"
+; ASM-NEXT:   .Ltmp0:
+; ASM32-NEXT:         .p2align        2, 0x0
+; ASM64-NEXT:         .p2align        3, 0x0
+; ASM-NEXT:           .word   3221225472
+; ASM-NEXT:           .word   4
+; ASM-NEXT:           .word   1
+; ASM32-NEXT:         .p2align        2, 0x0
+; ASM64-NEXT:         .p2align        3, 0x0
+; ASM-NEXT:   .Ltmp1:
+
+!llvm.module.flags = !{!0, !1}
+
+!0 = !{i32 8, !"cf-protection-branch", i32 1}
+!1 = !{i32 1, !"cf-branch-label-scheme", !"unlabeled"}

``````````

</details>


https://github.com/llvm/llvm-project/pull/141468


More information about the llvm-commits mailing list