Skip to content

Commit 148d907

Browse files
authored
[CodeGen] Set attributes on resolvers emitted after ifuncs
Visiting the ifunc calls `GetOrCreateLLVMFunction` with `NotForDefinition` while visiting the resolver calls `GetOrCreateLLVMFunction` with `ForDefinition`. When an ifunc is emitted before its resolver, the `ForDefinition` call does not call `SetFunctionAttributes`, because the function prematurely returns due to `(Entry->getValueType() == Ty)` and `llvm::GlobalIFunc::getResolverFunctionType(DeclTy)`. This leads to missing `!kcfi_type` with -fsanitize=kcfi. ``` extern void ifunc0(void) __attribute__ ((ifunc("resolver0"))); void *resolver0(void) { return 0; } // SetFunctionAttributes not called extern void ifunc1(void) __attribute__ ((ifunc("resolver1"))); static void *resolver1(void) { return 0; } // SetFunctionAttributes not called extern void ifunc2(void) __attribute__ ((ifunc("resolver2"))); static void *resolver2(void*) { return 0; } ``` Ensure `SetFunctionAttributes` is called by calling `GetOrCreateLLVMFunction` with a dummy non-function type. Now that the `F->takeName(Entry)` code path may be taken, the `DisableSanitizerInstrumentation` code (https://reviews.llvm.org/D150262) should be moved to `checkAliases`, when the resolver function is finalized. Pull Request: #98832
1 parent 56ee6a1 commit 148d907

File tree

3 files changed

+25
-21
lines changed

3 files changed

+25
-21
lines changed

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,11 @@ void CodeGenModule::checkAliases() {
721721
cast<llvm::GlobalAlias>(Alias)->setAliasee(Aliasee);
722722
}
723723
}
724+
// ifunc resolvers are usually implemented to run before sanitizer
725+
// initialization. Disable instrumentation to prevent the ordering issue.
726+
if (IsIFunc)
727+
cast<llvm::Function>(Aliasee)->addFnAttr(
728+
llvm::Attribute::DisableSanitizerInstrumentation);
724729
}
725730
if (!Error)
726731
return;
@@ -6106,11 +6111,14 @@ void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) {
61066111

61076112
Aliases.push_back(GD);
61086113

6109-
llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType());
6110-
llvm::Type *ResolverTy = llvm::GlobalIFunc::getResolverFunctionType(DeclTy);
6114+
// The resolver might not be visited yet. Specify a dummy non-function type to
6115+
// indicate IsIncompleteFunction. Either the type is ignored (if the resolver
6116+
// was emitted) or the whole function will be replaced (if the resolver has
6117+
// not been emitted).
61116118
llvm::Constant *Resolver =
6112-
GetOrCreateLLVMFunction(IFA->getResolver(), ResolverTy, {},
6119+
GetOrCreateLLVMFunction(IFA->getResolver(), VoidTy, {},
61136120
/*ForVTable=*/false);
6121+
llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType());
61146122
llvm::GlobalIFunc *GIF =
61156123
llvm::GlobalIFunc::create(DeclTy, 0, llvm::Function::ExternalLinkage,
61166124
"", Resolver, &getModule());
@@ -6134,9 +6142,6 @@ void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) {
61346142
Entry->eraseFromParent();
61356143
} else
61366144
GIF->setName(MangledName);
6137-
if (auto *F = dyn_cast<llvm::Function>(Resolver)) {
6138-
F->addFnAttr(llvm::Attribute::DisableSanitizerInstrumentation);
6139-
}
61406145
SetCommonAttributes(GD, GIF);
61416146
}
61426147

clang/test/CodeGen/ifunc.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,11 @@ extern void hoo(int) __attribute__ ((ifunc("hoo_ifunc")));
5858
// CHECK: call i32 @foo(i32
5959
// CHECK: call void @goo()
6060

61-
// SAN: define internal nonnull {{(noundef )?}}ptr @foo_ifunc() #[[#FOO_IFUNC:]] {
62-
6361
// SAN: define {{(dso_local )?}}noalias {{(noundef )?}}ptr @goo_ifunc() #[[#GOO_IFUNC:]] {
6462

65-
// SAN: define {{(dso_local )?}}noalias {{(noundef )?}}ptr @hoo_ifunc() #[[#HOO_IFUNC:]] {
63+
// SAN: define {{(dso_local )?}}noalias {{(noundef )?}}ptr @hoo_ifunc() #[[#GOO_IFUNC]] {
64+
65+
// SAN: define internal {{(noundef )?}}nonnull ptr @foo_ifunc() #[[#FOO_IFUNC:]] {
6666

67-
// SAN-DAG: attributes #[[#FOO_IFUNC]] = {{{.*}} disable_sanitizer_instrumentation {{.*}}
6867
// SAN-DAG: attributes #[[#GOO_IFUNC]] = {{{.*}} disable_sanitizer_instrumentation {{.*}}
69-
// SAN-DAG: attributes #[[#HOO_IFUNC]] = {{{.*}} disable_sanitizer_instrumentation {{.*}}
68+
// SAN-DAG: attributes #[[#FOO_IFUNC]] = {{{.*}} disable_sanitizer_instrumentation {{.*}}

clang/test/CodeGen/kcfi.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,6 @@ int call(fn_t f) {
3333
return f();
3434
}
3535

36-
#ifndef __cplusplus
37-
// C: define internal ptr @resolver1() #[[#]] {
38-
int ifunc1(int) __attribute__((ifunc("resolver1")));
39-
static void *resolver1(void) { return 0; }
40-
41-
// C: define internal ptr @resolver2() #[[#]] {
42-
static void *resolver2(void) { return 0; }
43-
long ifunc2(long) __attribute__((ifunc("resolver2")));
44-
#endif
45-
4636
// CHECK-DAG: define internal{{.*}} i32 @{{f3|_ZL2f3v}}(){{.*}} !kcfi_type ![[#TYPE]]
4737
static int f3(void) { return 1; }
4838

@@ -58,6 +48,16 @@ static int f5(void) { return 2; }
5848
// CHECK-DAG: declare !kcfi_type ![[#TYPE]]{{.*}} i32 @{{f6|_Z2f6v}}()
5949
extern int f6(void);
6050

51+
#ifndef __cplusplus
52+
// C: define internal ptr @resolver1() #[[#]] !kcfi_type ![[#]] {
53+
int ifunc1(int) __attribute__((ifunc("resolver1")));
54+
static void *resolver1(void) { return 0; }
55+
56+
// C: define internal ptr @resolver2() #[[#]] !kcfi_type ![[#]] {
57+
static void *resolver2(void) { return 0; }
58+
long ifunc2(long) __attribute__((ifunc("resolver2")));
59+
#endif
60+
6161
int test(void) {
6262
return call(f1) +
6363
__call((fn_t)f2) +

0 commit comments

Comments
 (0)