[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