[llvm] ce4bb08 - [KCFI] Fix hash offset calculation in Thumb mode
Sami Tolvanen via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 12 12:44:27 PDT 2023
Author: Sami Tolvanen
Date: 2023-06-12T19:43:34Z
New Revision: ce4bb083c043d42474cd071bd5149dc5fd4430f6
URL: https://github.com/llvm/llvm-project/commit/ce4bb083c043d42474cd071bd5149dc5fd4430f6
DIFF: https://github.com/llvm/llvm-project/commit/ce4bb083c043d42474cd071bd5149dc5fd4430f6.diff
LOG: [KCFI] Fix hash offset calculation in Thumb mode
ARM stores the Thumb state in the least significant bit of the
function pointers. When compiling for ARM or Thumb, as all
instructions are at least 16-bit aligned, ignore the LSB when
computing the prefix hash location, so we can support both
pure Thumb and mixed ARM/Thumb binaries.
Fixes #62936
Reviewed By: MaskRay, simon_tatham
Differential Revision: https://reviews.llvm.org/D152484
Added:
Modified:
llvm/lib/Transforms/Instrumentation/KCFI.cpp
llvm/test/Transforms/KCFI/kcfi.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Instrumentation/KCFI.cpp b/llvm/lib/Transforms/Instrumentation/KCFI.cpp
index eacbb02828658..b1a26880c7010 100644
--- a/llvm/lib/Transforms/Instrumentation/KCFI.cpp
+++ b/llvm/lib/Transforms/Instrumentation/KCFI.cpp
@@ -73,6 +73,7 @@ PreservedAnalyses KCFIPass::run(Function &F, FunctionAnalysisManager &AM) {
IntegerType *Int32Ty = Type::getInt32Ty(Ctx);
MDNode *VeryUnlikelyWeights =
MDBuilder(Ctx).createBranchWeights(1, (1U << 20) - 1);
+ Triple T(M.getTargetTriple());
for (CallInst *CI : KCFICalls) {
// Get the expected hash value.
@@ -93,8 +94,18 @@ PreservedAnalyses KCFIPass::run(Function &F, FunctionAnalysisManager &AM) {
// Emit a check and trap if the target hash doesn't match.
IRBuilder<> Builder(Call);
- Value *HashPtr = Builder.CreateConstInBoundsGEP1_32(
- Int32Ty, Call->getCalledOperand(), -1);
+ Value *FuncPtr = Call->getCalledOperand();
+ // ARM uses the least significant bit of the function pointer to select
+ // between ARM and Thumb modes for the callee. Instructions are always
+ // at least 16-bit aligned, so clear the LSB before we compute the hash
+ // location.
+ if (T.isARM() || T.isThumb()) {
+ FuncPtr = Builder.CreateIntToPtr(
+ Builder.CreateAnd(Builder.CreatePtrToInt(FuncPtr, Int32Ty),
+ ConstantInt::get(Int32Ty, -2)),
+ FuncPtr->getType());
+ }
+ Value *HashPtr = Builder.CreateConstInBoundsGEP1_32(Int32Ty, FuncPtr, -1);
Value *Test = Builder.CreateICmpNE(Builder.CreateLoad(Int32Ty, HashPtr),
ConstantInt::get(Int32Ty, ExpectedHash));
Instruction *ThenTerm =
diff --git a/llvm/test/Transforms/KCFI/kcfi.ll b/llvm/test/Transforms/KCFI/kcfi.ll
index f6028ae782193..41ef9140358cd 100644
--- a/llvm/test/Transforms/KCFI/kcfi.ll
+++ b/llvm/test/Transforms/KCFI/kcfi.ll
@@ -1,8 +1,13 @@
-; RUN: opt -S -passes=kcfi %s | FileCheck %s
+; RUN: opt -S -passes=kcfi %s | FileCheck --check-prefixes=CHECK,NOARM %s
+; RUN: %if arm-registered-target %{ opt -S -passes=kcfi -mtriple=thumbv7m-unknown-linux-gnu %s | FileCheck --check-prefixes=CHECK,ARM %s %}
; CHECK-LABEL: define void @f1(
define void @f1(ptr noundef %x) {
- ; CHECK: %[[#GEPI:]] = getelementptr inbounds i32, ptr %x, i32 -1
+ ; ARM: %[[#FINT:]] = ptrtoint ptr %x to i32
+ ; ARM-NEXT: %[[#FAND:]] = and i32 %[[#FINT]], -2
+ ; ARM-NEXT: %[[#FPTR:]] = inttoptr i32 %[[#FAND]] to ptr
+ ; ARM-NEXT: %[[#GEPI:]] = getelementptr inbounds i32, ptr %[[#FPTR]], i32 -1
+ ; NOARM: %[[#GEPI:]] = getelementptr inbounds i32, ptr %x, i32 -1
; CHECK-NEXT: %[[#LOAD:]] = load i32, ptr %[[#GEPI]], align 4
; CHECK-NEXT: %[[#ICMP:]] = icmp ne i32 %[[#LOAD]], 12345678
; CHECK-NEXT: br i1 %[[#ICMP]], label %[[#TRAP:]], label %[[#CALL:]], !prof ![[#WEIGHTS:]]
More information about the llvm-commits
mailing list