[PATCH] D152484: [KCFI] Fix hash offset calculation in Thumb mode

Sami Tolvanen via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 8 16:19:00 PDT 2023


samitolvanen created this revision.
Herald added subscribers: Enna1, hiraditya, kristof.beyls.
Herald added a project: All.
samitolvanen requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D152484

Files:
  llvm/lib/Transforms/Instrumentation/KCFI.cpp
  llvm/test/Transforms/KCFI/kcfi.ll


Index: llvm/test/Transforms/KCFI/kcfi.ll
===================================================================
--- llvm/test/Transforms/KCFI/kcfi.ll
+++ 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:]]
Index: llvm/lib/Transforms/Instrumentation/KCFI.cpp
===================================================================
--- llvm/lib/Transforms/Instrumentation/KCFI.cpp
+++ llvm/lib/Transforms/Instrumentation/KCFI.cpp
@@ -73,6 +73,7 @@
   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 @@
 
     // 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 =


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D152484.529770.patch
Type: text/x-patch
Size: 2684 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230608/31812dd0/attachment.bin>


More information about the llvm-commits mailing list