Skip to content

Commit 483c772

Browse files
committed
split KCFI_CHECK into subarch instructions to have Size defined with the PseudoInst
1 parent a463082 commit 483c772

File tree

6 files changed

+57
-46
lines changed

6 files changed

+57
-46
lines changed

llvm/lib/Target/ARM/ARMAsmPrinter.cpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1885,16 +1885,19 @@ void ARMAsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) {
18851885
.getValueAsString()
18861886
.getAsInteger(10, PrefixNops);
18871887

1888-
// Emit ARM32 or Thumb (Thumb1/Thumb2) instruction sequence.
1889-
const ARMSubtarget &STI = MI.getMF()->getSubtarget<ARMSubtarget>();
1890-
if (STI.isThumb()) {
1891-
if (STI.isThumb2()) {
1892-
EmitKCFI_CHECK_Thumb2(AddrReg, Type, Call, PrefixNops);
1893-
} else {
1894-
EmitKCFI_CHECK_Thumb1(AddrReg, Type, Call, PrefixNops);
1895-
}
1896-
} else {
1888+
// Emit the appropriate instruction sequence based on the opcode variant.
1889+
switch (MI.getOpcode()) {
1890+
case ARM::KCFI_CHECK_ARM:
18971891
EmitKCFI_CHECK_ARM32(AddrReg, Type, Call, PrefixNops);
1892+
break;
1893+
case ARM::KCFI_CHECK_Thumb2:
1894+
EmitKCFI_CHECK_Thumb2(AddrReg, Type, Call, PrefixNops);
1895+
break;
1896+
case ARM::KCFI_CHECK_Thumb1:
1897+
EmitKCFI_CHECK_Thumb1(AddrReg, Type, Call, PrefixNops);
1898+
break;
1899+
default:
1900+
llvm_unreachable("Unexpected KCFI_CHECK opcode");
18981901
}
18991902
}
19001903

@@ -1931,7 +1934,9 @@ void ARMAsmPrinter::emitInstruction(const MachineInstr *MI) {
19311934
switch (Opc) {
19321935
case ARM::t2MOVi32imm: llvm_unreachable("Should be lowered by thumb2it pass");
19331936
case ARM::DBG_VALUE: llvm_unreachable("Should be handled by generic printing");
1934-
case ARM::KCFI_CHECK:
1937+
case ARM::KCFI_CHECK_ARM:
1938+
case ARM::KCFI_CHECK_Thumb2:
1939+
case ARM::KCFI_CHECK_Thumb1:
19351940
LowerKCFI_CHECK(*MI);
19361941
return;
19371942
case ARM::LEApcrel:

llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -616,35 +616,6 @@ unsigned ARMBaseInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
616616
// contrast to AArch64 instructions which have a default size of 4 bytes for
617617
// example.
618618
return MCID.getSize();
619-
case ARM::KCFI_CHECK: {
620-
// KCFI_CHECK is a pseudo-instruction that expands to a sequence of
621-
// instructions during AsmPrinter. We need to return the size of the
622-
// expanded sequence so that branch distance calculations are correct.
623-
//
624-
// The expansion depends on the target architecture:
625-
// - ARM32: 7 instructions = 28 bytes
626-
// (bic, ldr, 4x eor, beq, udf)
627-
// - Thumb2: 7-9 instructions = 28-32 bytes
628-
// (optional push, bic, ldr, 4x eor, optional pop, beq.w, udf)
629-
// - Thumb1: 22-25 instructions = 44-50 bytes
630-
// (pushes, bic, movs, lsls, adds, cmp, pops)
631-
//
632-
// We return a conservative estimate to ensure branch distance calculations
633-
// don't underestimate the size.
634-
const ARMSubtarget &STI = MF->getSubtarget<ARMSubtarget>();
635-
if (STI.isThumb()) {
636-
if (STI.isThumb2()) {
637-
// Thumb2 (worst case)
638-
return 32;
639-
} else {
640-
// Thumb1 (worst case)
641-
return 50;
642-
}
643-
} else {
644-
// ARM32
645-
return 28;
646-
}
647-
}
648619
case TargetOpcode::BUNDLE:
649620
return getInstBundleLength(MI);
650621
case ARM::CONSTPOOL_ENTRY:

llvm/lib/Target/ARM/ARMISelLowering.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12058,7 +12058,19 @@ ARMTargetLowering::EmitKCFICheck(MachineBasicBlock &MBB,
1205812058
assert(TargetOp && TargetOp->isReg() && "Invalid target operand");
1205912059
TargetOp->setIsRenamable(false);
1206012060

12061-
return BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(ARM::KCFI_CHECK))
12061+
// Select the appropriate KCFI_CHECK variant based on the instruction set
12062+
unsigned KCFICheckOpcode;
12063+
if (Subtarget->isThumb()) {
12064+
if (Subtarget->isThumb2()) {
12065+
KCFICheckOpcode = ARM::KCFI_CHECK_Thumb2;
12066+
} else {
12067+
KCFICheckOpcode = ARM::KCFI_CHECK_Thumb1;
12068+
}
12069+
} else {
12070+
KCFICheckOpcode = ARM::KCFI_CHECK_ARM;
12071+
}
12072+
12073+
return BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(KCFICheckOpcode))
1206212074
.addReg(TargetOp->getReg())
1206312075
.addImm(MBBI->getCFIType())
1206412076
.getInstr();

llvm/lib/Target/ARM/ARMInstrInfo.td

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6538,9 +6538,32 @@ def : Pat<(atomic_fence (timm), 0), (MEMBARRIER)>;
65386538
//===----------------------------------------------------------------------===//
65396539
// KCFI check pseudo-instruction.
65406540
//===----------------------------------------------------------------------===//
6541-
def KCFI_CHECK
6541+
// KCFI_CHECK pseudo-instruction for Kernel Control-Flow Integrity.
6542+
// Expands to a sequence that verifies the function pointer's type hash.
6543+
// Different sizes for different architectures due to different expansions.
6544+
6545+
def KCFI_CHECK_ARM
6546+
: PseudoInst<(outs), (ins GPR:$ptr, i32imm:$type), NoItinerary, []>,
6547+
Sched<[]>,
6548+
Requires<[IsARM]> {
6549+
let Size = 28; // 7 instructions (bic, ldr, 4x eor, beq, udf)
6550+
}
6551+
6552+
def KCFI_CHECK_Thumb2
65426553
: PseudoInst<(outs), (ins GPR:$ptr, i32imm:$type), NoItinerary, []>,
6543-
Sched<[]>;
6554+
Sched<[]>,
6555+
Requires<[IsThumb2]> {
6556+
let Size =
6557+
32; // worst-case 9 instructions (push, bic, ldr, 4x eor, pop, beq.w, udf)
6558+
}
6559+
6560+
def KCFI_CHECK_Thumb1
6561+
: PseudoInst<(outs), (ins GPR:$ptr, i32imm:$type), NoItinerary, []>,
6562+
Sched<[]>,
6563+
Requires<[IsThumb1Only]> {
6564+
let Size = 50; // worst-case 25 instructions (pushes, bic helper, type
6565+
// building, cmp, pops)
6566+
}
65446567

65456568
//===----------------------------------------------------------------------===//
65466569
// Instructions used for emitting unwind opcodes on Windows.

llvm/test/CodeGen/ARM/kcfi-arm.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
; ISEL: BLX %0, csr_aapcs,{{.*}} cfi-type 12345678
1212

1313
; KCFI: BUNDLE{{.*}} {
14-
; KCFI-NEXT: KCFI_CHECK $r0, 12345678
14+
; KCFI-NEXT: KCFI_CHECK_ARM $r0, 12345678
1515
; KCFI-NEXT: BLX killed $r0, csr_aapcs,{{.*}}
1616
; KCFI-NEXT: }
1717

@@ -21,7 +21,7 @@
2121
; ISEL: TCRETURNri %0, 0, csr_aapcs, implicit $sp, cfi-type 12345678
2222

2323
; KCFI: BUNDLE{{.*}} {
24-
; KCFI-NEXT: KCFI_CHECK $r0, 12345678
24+
; KCFI-NEXT: KCFI_CHECK_ARM $r0, 12345678
2525
; KCFI-NEXT: TAILJMPr killed $r0, csr_aapcs, implicit $sp, implicit $sp
2626
; KCFI-NEXT: }
2727

llvm/test/CodeGen/ARM/kcfi-thumb2.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
; ISEL: tBLXr 14 /* CC::al */, $noreg, %0, csr_aapcs,{{.*}} cfi-type 12345678
1212

1313
; KCFI: BUNDLE{{.*}} {
14-
; KCFI-NEXT: KCFI_CHECK $r0, 12345678
14+
; KCFI-NEXT: KCFI_CHECK_Thumb2 $r0, 12345678
1515
; KCFI-NEXT: tBLXr 14 /* CC::al */, $noreg, {{(killed )?}}$r0, csr_aapcs,{{.*}}
1616
; KCFI-NEXT: }
1717

@@ -21,7 +21,7 @@
2121
; ISEL: TCRETURNri %0, 0, csr_aapcs, implicit $sp, cfi-type 12345678
2222

2323
; KCFI: BUNDLE{{.*}} {
24-
; KCFI-NEXT: KCFI_CHECK $r0, 12345678
24+
; KCFI-NEXT: KCFI_CHECK_Thumb2 $r0, 12345678
2525
; KCFI-NEXT: tTAILJMPr {{(killed )?}}$r0, csr_aapcs, implicit $sp, implicit $sp
2626
; KCFI-NEXT: }
2727

0 commit comments

Comments
 (0)