Skip to content

Commit eee6f47

Browse files
committed
[stable/20221013] WholeProgramDevirt: Fix call target propagation for ptrauth architectures
We can't have a call with a constant target with a ptrauth bundle. Remove the ptrauth bundle operand in such a case rdar://105696396
1 parent 34096e4 commit eee6f47

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,10 @@ struct DevirtModule {
568568
// optimize a call more than once.
569569
SmallPtrSet<CallBase *, 8> OptimizedCalls;
570570

571+
// Store calls that had their ptrauth bundle removed. They are to be deleted
572+
// at the end of the optimization.
573+
SmallVector<CallBase *, 8> CallsWithPtrAuthBundleRemoved;
574+
571575
// This map keeps track of the number of "unsafe" uses of a loaded function
572576
// pointer. The key is the associated llvm.type.test intrinsic call generated
573577
// by this pass. An unsafe use is one that calls the loaded function pointer
@@ -1158,6 +1162,15 @@ void DevirtModule::applySingleImplDevirt(VTableSlotInfo &SlotInfo,
11581162
// !callees metadata.
11591163
CB.setMetadata(LLVMContext::MD_prof, nullptr);
11601164
CB.setMetadata(LLVMContext::MD_callees, nullptr);
1165+
if (CB.getCalledOperand() &&
1166+
CB.getOperandBundle(LLVMContext::OB_ptrauth)) {
1167+
auto *NewCS = CallBase::removeOperandBundle(&CB,
1168+
LLVMContext::OB_ptrauth,
1169+
&CB);
1170+
CB.replaceAllUsesWith(NewCS);
1171+
// Schedule for deletion at the end of pass run.
1172+
CallsWithPtrAuthBundleRemoved.push_back(&CB);
1173+
}
11611174
}
11621175

11631176
// This use is no longer unsafe.
@@ -2323,6 +2336,9 @@ bool DevirtModule::run() {
23232336
for (GlobalVariable &GV : M.globals())
23242337
GV.eraseMetadata(LLVMContext::MD_vcall_visibility);
23252338

2339+
for (auto *CI : CallsWithPtrAuthBundleRemoved)
2340+
CI->eraseFromParent();
2341+
23262342
return true;
23272343
}
23282344

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
; RUN: opt -S -passes=wholeprogramdevirt,verify -whole-program-visibility -pass-remarks=wholeprogramdevirt %s 2>&1 | FileCheck %s
2+
3+
target datalayout = "e-p:64:64"
4+
target triple = "x86_64-unknown-linux-gnu"
5+
6+
; CHECK: remark: <unknown>:0:0: single-impl: devirtualized a call to vf
7+
; CHECK: remark: <unknown>:0:0: devirtualized vf
8+
; CHECK-NOT: devirtualized
9+
10+
@vt1 = constant [1 x ptr] [ptr @vf], !type !0
11+
@vt2 = constant [1 x ptr] [ptr @vf], !type !0
12+
13+
define void @vf(ptr %this) {
14+
ret void
15+
}
16+
17+
; CHECK: define void @call
18+
define void @call(ptr %obj) {
19+
%vtable = load ptr, ptr %obj
20+
%pair = call {ptr, i1} @llvm.type.checked.load(ptr %vtable, i32 0, metadata !"typeid")
21+
%fptr = extractvalue {ptr, i1} %pair, 0
22+
%p = extractvalue {ptr, i1} %pair, 1
23+
; CHECK: br i1 true,
24+
br i1 %p, label %cont, label %trap
25+
26+
cont:
27+
; CHECK: call void @vf(
28+
call void %fptr(ptr %obj) [ "ptrauth"(i32 5, i64 120) ]
29+
ret void
30+
31+
trap:
32+
call void @llvm.trap()
33+
unreachable
34+
}
35+
36+
declare {ptr, i1} @llvm.type.checked.load(ptr, i32, metadata)
37+
declare void @llvm.trap()
38+
39+
!0 = !{i32 0, !"typeid"}

0 commit comments

Comments
 (0)