-
Notifications
You must be signed in to change notification settings - Fork 14.1k
[RISCV][Zicfilp] Emit .note.gnu.property section for Zicfilp CFI unlabeled scheme #141468
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
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.
@llvm/pr-subscribers-llvm-support @llvm/pr-subscribers-backend-risc-v Author: Ming-Yi Lai (mylai-mtk) ChangesRISC-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 When Clang receives the Full diff: https://github.com/llvm/llvm-project/pull/141468.diff 3 Files Affected:
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","",@progbits
+; ASM-NEXT: .section .note.gnu.property,"a",@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"}
|
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 thecf-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, thecf-protection-branch
attribute indicates the adoption of Zicfilp-based forward-edge CFI protection, and thecf-branch-label-scheme
attribute selects how the "label" operands of the Zicfilplpad
insns are produced. This patch emits the proper.note.gnu.property
feature bit when the RISC-V backend sees that the LLVM module has thecf-protection-branch
attribute set to1
, and thecf-branch-label-scheme
attribute set tounlabeled
, so linkers/loaders know that the object file is built with Zicfilp-based forward-edge CFI protection with the "unlabeled" scheme.