Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[RISCV] Implement KCFI operand bundle lowering
With `-fsanitize=kcfi` (Kernel Control-Flow Integrity), Clang emits "kcfi" operand bundles to indirect call instructions. Similarly to the target-specific lowering added in D119296, implement KCFI operand bundle lowering for RISC-V. This patch disables the generic KCFI pass for RISC-V in Clang, and adds the KCFI machine function pass in `RISCVPassConfig::addPreSched` to emit target-specific `KCFI_CHECK` pseudo instructions before calls that have KCFI operand bundles. The machine function pass also bundles the instructions to ensure we emit the checks immediately before the calls, which is not possible with the generic pass. `KCFI_CHECK` instructions are lowered in `RISCVAsmPrinter` to a contiguous code sequence that traps if the expected hash in the operand bundle doesn't match the hash before the target function address. This patch emits an `ebreak` instruction for error handling to match the Linux kernel's `BUG()` implementation. Just like for X86, we also emit trap locations to a `.kcfi_traps` section to support error handling, as we cannot embed additional information to the trap instruction itself. Relands commit 62fa708 with fixed tests. Reviewed By: MaskRay Differential Revision: https://reviews.llvm.org/D148385
- Loading branch information
1 parent
4d60c65
commit 83835e2
Showing
14 changed files
with
356 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 2 | ||
; RUN: llc -mtriple=riscv64 -stop-after=finalize-isel -verify-machineinstrs -o - %s | FileCheck %s | ||
define void @f1(ptr noundef %x) !kcfi_type !1 { | ||
; CHECK-LABEL: name: f1 | ||
; CHECK: bb.0 (%ir-block.0): | ||
; CHECK-NEXT: liveins: $x10 | ||
; CHECK-NEXT: {{ $}} | ||
; CHECK-NEXT: [[COPY:%[0-9]+]]:gprjalr = COPY $x10 | ||
; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $x2, implicit $x2 | ||
; CHECK-NEXT: PseudoCALLIndirect [[COPY]], csr_ilp32_lp64, implicit-def dead $x1, implicit-def $x2, cfi-type 12345678 | ||
; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def dead $x2, implicit $x2 | ||
; CHECK-NEXT: PseudoRET | ||
call void %x() [ "kcfi"(i32 12345678) ] | ||
ret void | ||
} | ||
|
||
define void @f2(ptr noundef %x) #0 { | ||
; CHECK-LABEL: name: f2 | ||
; CHECK: bb.0 (%ir-block.0): | ||
; CHECK-NEXT: liveins: $x10 | ||
; CHECK-NEXT: {{ $}} | ||
; CHECK-NEXT: [[COPY:%[0-9]+]]:gprtc = COPY $x10 | ||
; CHECK-NEXT: PseudoTAILIndirect [[COPY]], implicit $x2, cfi-type 12345678 | ||
tail call void %x() [ "kcfi"(i32 12345678) ] | ||
ret void | ||
} | ||
|
||
attributes #0 = { "patchable-function-entry"="2" } | ||
|
||
!llvm.module.flags = !{!0} | ||
|
||
!0 = !{i32 4, !"kcfi", i32 1} | ||
!1 = !{i32 12345678} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 2 | ||
; RUN: llc -mtriple=riscv64 -stop-after=kcfi -verify-machineinstrs -o - %s | FileCheck %s | ||
|
||
define void @f1(ptr noundef %x) !kcfi_type !1 { | ||
; CHECK-LABEL: name: f1 | ||
; CHECK: bb.0 (%ir-block.0): | ||
; CHECK-NEXT: liveins: $x10, $x1 | ||
; CHECK-NEXT: {{ $}} | ||
; CHECK-NEXT: $x2 = frame-setup ADDI $x2, -16 | ||
; CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16 | ||
; CHECK-NEXT: SD killed $x1, $x2, 8 :: (store (s64) into %stack.0) | ||
; CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $x1, -8 | ||
; CHECK-NEXT: BUNDLE implicit-def $x6, implicit-def $x7, implicit-def $x28, implicit-def $x29, implicit-def $x30, implicit-def $x31, implicit-def dead $x1, implicit-def $x2, implicit killed $x10 { | ||
; CHECK-NEXT: KCFI_CHECK $x10, 12345678, implicit-def $x6, implicit-def $x7, implicit-def $x28, implicit-def $x29, implicit-def $x30, implicit-def $x31 | ||
; CHECK-NEXT: PseudoCALLIndirect killed $x10, csr_ilp32_lp64, implicit-def dead $x1, implicit-def $x2 | ||
; CHECK-NEXT: } | ||
; CHECK-NEXT: $x1 = LD $x2, 8 :: (load (s64) from %stack.0) | ||
; CHECK-NEXT: $x2 = frame-destroy ADDI $x2, 16 | ||
; CHECK-NEXT: PseudoRET | ||
call void %x() [ "kcfi"(i32 12345678) ] | ||
ret void | ||
} | ||
|
||
define void @f2(ptr noundef %x) #0 { | ||
; CHECK-LABEL: name: f2 | ||
; CHECK: bb.0 (%ir-block.0): | ||
; CHECK-NEXT: liveins: $x10 | ||
; CHECK-NEXT: {{ $}} | ||
; CHECK-NEXT: BUNDLE implicit-def $x6, implicit-def $x7, implicit-def $x28, implicit-def $x29, implicit-def $x30, implicit-def $x31, implicit killed $x10, implicit $x2 { | ||
; CHECK-NEXT: KCFI_CHECK $x10, 12345678, implicit-def $x6, implicit-def $x7, implicit-def $x28, implicit-def $x29, implicit-def $x30, implicit-def $x31 | ||
; CHECK-NEXT: PseudoTAILIndirect killed $x10, implicit $x2 | ||
; CHECK-NEXT: } | ||
tail call void %x() [ "kcfi"(i32 12345678) ] | ||
ret void | ||
} | ||
|
||
attributes #0 = { "patchable-function-entry"="2" } | ||
|
||
!llvm.module.flags = !{!0} | ||
|
||
!0 = !{i32 4, !"kcfi", i32 1} | ||
!1 = !{i32 12345678} |
Oops, something went wrong.