aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CodeGenModule.cpp
diff options
context:
space:
mode:
authorFangrui Song <i@maskray.me>2024-07-15 11:27:01 -0700
committerGitHub <noreply@github.com>2024-07-15 11:27:01 -0700
commit148d90729e9fa132f170ba0627bcfb9ee90a0f38 (patch)
tree25efe0f8784de9a4fa6ff7f4aff2acce90d3d599 /clang/lib/CodeGen/CodeGenModule.cpp
parent56ee6a172a8c17944c3b776159b45e15b31444ef (diff)
downloadllvm-148d90729e9fa132f170ba0627bcfb9ee90a0f38.zip
llvm-148d90729e9fa132f170ba0627bcfb9ee90a0f38.tar.gz
llvm-148d90729e9fa132f170ba0627bcfb9ee90a0f38.tar.bz2
[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: https://github.com/llvm/llvm-project/pull/98832
Diffstat (limited to 'clang/lib/CodeGen/CodeGenModule.cpp')
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp17
1 files changed, 11 insertions, 6 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 08cfa69..ee05cdd 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -721,6 +721,11 @@ void CodeGenModule::checkAliases() {
cast<llvm::GlobalAlias>(Alias)->setAliasee(Aliasee);
}
}
+ // ifunc resolvers are usually implemented to run before sanitizer
+ // initialization. Disable instrumentation to prevent the ordering issue.
+ if (IsIFunc)
+ cast<llvm::Function>(Aliasee)->addFnAttr(
+ llvm::Attribute::DisableSanitizerInstrumentation);
}
if (!Error)
return;
@@ -6106,11 +6111,14 @@ void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) {
Aliases.push_back(GD);
- llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType());
- llvm::Type *ResolverTy = llvm::GlobalIFunc::getResolverFunctionType(DeclTy);
+ // The resolver might not be visited yet. Specify a dummy non-function type to
+ // indicate IsIncompleteFunction. Either the type is ignored (if the resolver
+ // was emitted) or the whole function will be replaced (if the resolver has
+ // not been emitted).
llvm::Constant *Resolver =
- GetOrCreateLLVMFunction(IFA->getResolver(), ResolverTy, {},
+ GetOrCreateLLVMFunction(IFA->getResolver(), VoidTy, {},
/*ForVTable=*/false);
+ llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType());
llvm::GlobalIFunc *GIF =
llvm::GlobalIFunc::create(DeclTy, 0, llvm::Function::ExternalLinkage,
"", Resolver, &getModule());
@@ -6134,9 +6142,6 @@ void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) {
Entry->eraseFromParent();
} else
GIF->setName(MangledName);
- if (auto *F = dyn_cast<llvm::Function>(Resolver)) {
- F->addFnAttr(llvm::Attribute::DisableSanitizerInstrumentation);
- }
SetCommonAttributes(GD, GIF);
}