Skip to content

Commit c7a0db1

Browse files
authored
[CFI][annotation] Leave alone function pointers in function annotations (llvm#80173)
Function annotation, as part of llvm.metadata, is for the function itself and doesn't apply to its corresponding jump table entry, so with CFI we shouldn't replace function pointer in function annotation with pointer to its corresponding jump table entry.
1 parent 1d0f86b commit c7a0db1

File tree

2 files changed

+94
-2
lines changed

2 files changed

+94
-2
lines changed

llvm/lib/Transforms/IPO/LowerTypeTests.cpp

+26-2
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,9 @@ class LowerTypeTestsModule {
470470

471471
Function *WeakInitializerFn = nullptr;
472472

473+
GlobalVariable *GlobalAnnotation;
474+
DenseSet<Value *> FunctionAnnotations;
475+
473476
bool shouldExportConstantsAsAbsoluteSymbols();
474477
uint8_t *exportTypeId(StringRef TypeId, const TypeIdLowering &TIL);
475478
TypeIdLowering importTypeId(StringRef TypeId);
@@ -531,6 +534,10 @@ class LowerTypeTestsModule {
531534
/// replace each use, which is a direct function call.
532535
void replaceDirectCalls(Value *Old, Value *New);
533536

537+
bool isFunctionAnnotation(Value *V) const {
538+
return FunctionAnnotations.contains(V);
539+
}
540+
534541
public:
535542
LowerTypeTestsModule(Module &M, ModuleAnalysisManager &AM,
536543
ModuleSummaryIndex *ExportSummary,
@@ -1377,8 +1384,11 @@ void LowerTypeTestsModule::replaceWeakDeclarationWithJumpTablePtr(
13771384
// (all?) targets. Switch to a runtime initializer.
13781385
SmallSetVector<GlobalVariable *, 8> GlobalVarUsers;
13791386
findGlobalVariableUsersOf(F, GlobalVarUsers);
1380-
for (auto *GV : GlobalVarUsers)
1387+
for (auto *GV : GlobalVarUsers) {
1388+
if (GV == GlobalAnnotation)
1389+
continue;
13811390
moveInitializerToModuleConstructor(GV);
1391+
}
13821392

13831393
// Can not RAUW F with an expression that uses F. Replace with a temporary
13841394
// placeholder first.
@@ -1837,6 +1847,16 @@ LowerTypeTestsModule::LowerTypeTestsModule(
18371847
}
18381848
OS = TargetTriple.getOS();
18391849
ObjectFormat = TargetTriple.getObjectFormat();
1850+
1851+
// Function annotation describes or applies to function itself, and
1852+
// shouldn't be associated with jump table thunk generated for CFI.
1853+
GlobalAnnotation = M.getGlobalVariable("llvm.global.annotations");
1854+
if (GlobalAnnotation && GlobalAnnotation->hasInitializer()) {
1855+
const ConstantArray *CA =
1856+
cast<ConstantArray>(GlobalAnnotation->getInitializer());
1857+
for (Value *Op : CA->operands())
1858+
FunctionAnnotations.insert(Op);
1859+
}
18401860
}
18411861

18421862
bool LowerTypeTestsModule::runForTesting(Module &M, ModuleAnalysisManager &AM) {
@@ -1896,10 +1916,14 @@ void LowerTypeTestsModule::replaceCfiUses(Function *Old, Value *New,
18961916
if (isa<BlockAddress, NoCFIValue>(U.getUser()))
18971917
continue;
18981918

1899-
// Skip direct calls to externally defined or non-dso_local functions
1919+
// Skip direct calls to externally defined or non-dso_local functions.
19001920
if (isDirectCall(U) && (Old->isDSOLocal() || !IsJumpTableCanonical))
19011921
continue;
19021922

1923+
// Skip function annotation.
1924+
if (isFunctionAnnotation(U.getUser()))
1925+
continue;
1926+
19031927
// Must handle Constants specially, we cannot call replaceUsesOfWith on a
19041928
// constant because they are uniqued.
19051929
if (auto *C = dyn_cast<Constant>(U.getUser())) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
; REQUIRES: aarch64-registered-target
2+
3+
; RUN: opt -passes=lowertypetests %s -o %t.o
4+
; RUN: llvm-dis %t.o -o - | FileCheck %s --check-prefix=CHECK-foobar
5+
; CHECK-foobar: {{llvm.global.annotations = .*[foo|bar], .*[foo|bar],}}
6+
; RUN: llvm-dis %t.o -o - | FileCheck %s --check-prefix=CHECK-cfi
7+
; CHECK-cfi-NOT: {{llvm.global.annotations = .*cfi.*}}
8+
9+
target triple = "aarch64-none-linux-gnu"
10+
11+
@.src = private unnamed_addr constant [7 x i8] c"test.c\00", align 1
12+
@.str = private unnamed_addr constant [30 x i8] c"annotation_string_literal_bar\00", section "llvm.metadata"
13+
@.str.1 = private unnamed_addr constant [7 x i8] c"test.c\00", section "llvm.metadata"
14+
@.str.2 = private unnamed_addr constant [30 x i8] c"annotation_string_literal_foo\00", section "llvm.metadata"
15+
@llvm.global.annotations = appending global [2 x { ptr, ptr, ptr, i32, ptr }] [{ ptr, ptr, ptr, i32, ptr } { ptr @bar, ptr @.str, ptr @.str.1, i32 2, ptr null }, { ptr, ptr, ptr, i32, ptr } { ptr @foo, ptr @.str.2, ptr @.str.1, i32 1, ptr null }], section "llvm.metadata"
16+
17+
define i32 @bar(i32 noundef %0) #0 !type !8 !type !9 {
18+
%2 = alloca i32, align 4
19+
store i32 %0, ptr %2, align 4
20+
%3 = load i32, ptr %2, align 4
21+
%4 = call i32 @foo(i32 noundef %3)
22+
ret i32 %4
23+
}
24+
25+
declare !type !8 !type !9 i32 @foo(i32 noundef) #1
26+
27+
define i32 @test(i32 noundef %0) #0 !type !8 !type !9 {
28+
%2 = alloca i32, align 4
29+
%3 = alloca ptr, align 8
30+
store i32 %0, ptr %2, align 4
31+
%4 = load i32, ptr %2, align 4
32+
%5 = icmp sgt i32 %4, 0
33+
%6 = zext i1 %5 to i64
34+
%7 = select i1 %5, ptr @foo, ptr @bar
35+
store ptr %7, ptr %3, align 8
36+
%8 = load ptr, ptr %3, align 8
37+
%9 = call i1 @llvm.type.test(ptr %8, metadata !"_ZTSFiiE"), !nosanitize !10
38+
br i1 %9, label %11, label %10, !nosanitize !10
39+
40+
10:
41+
call void @llvm.ubsantrap(i8 2) #4, !nosanitize !10
42+
unreachable, !nosanitize !10
43+
44+
11:
45+
%12 = load i32, ptr %2, align 4
46+
%13 = call i32 %8(i32 noundef %12)
47+
ret i32 %13
48+
}
49+
50+
declare i1 @llvm.type.test(ptr, metadata)
51+
declare void @llvm.ubsantrap(i8 immarg)
52+
53+
attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="non-leaf" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+fp-armv8,+neon,+v8a,-fmv" }
54+
attributes #1 = { "frame-pointer"="non-leaf" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+fp-armv8,+neon,+v8a,-fmv" }
55+
attributes #4 = { noreturn nounwind }
56+
57+
!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6}
58+
59+
!0 = !{i32 1, !"wchar_size", i32 4}
60+
!1 = !{i32 4, !"CFI Canonical Jump Tables", i32 0}
61+
!2 = !{i32 8, !"PIC Level", i32 2}
62+
!3 = !{i32 7, !"uwtable", i32 2}
63+
!4 = !{i32 7, !"frame-pointer", i32 1}
64+
!5 = !{i32 1, !"ThinLTO", i32 0}
65+
!6 = !{i32 1, !"EnableSplitLTOUnit", i32 1}
66+
!8 = !{i64 0, !"_ZTSFiiE"}
67+
!9 = !{i64 0, !"_ZTSFiiE.generalized"}
68+
!10 = !{}

0 commit comments

Comments
 (0)