-
Notifications
You must be signed in to change notification settings - Fork 11.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[clang] inherit GD to let the codegen add kcfi type for ifunc #96400
Conversation
@llvm/pr-subscribers-clang-codegen @llvm/pr-subscribers-clang Author: None (aokblast) ChangesIn FreeBSD, we use ifunc to select best performance function in load time. However, the resolver is also a function itself but not been tagged kcfi by clang. The problems is caused by
called by CodeGenModule::GetOrCreateLLVMFunction where D is empty originally. Full diff: https://github.com/llvm/llvm-project/pull/96400.diff 1 Files Affected:
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index c8898ce196c1e..3e1f650884a7a 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -5995,7 +5995,7 @@ void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) {
llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType());
llvm::Type *ResolverTy = llvm::GlobalIFunc::getResolverFunctionType(DeclTy);
llvm::Constant *Resolver =
- GetOrCreateLLVMFunction(IFA->getResolver(), ResolverTy, {},
+ GetOrCreateLLVMFunction(IFA->getResolver(), ResolverTy, GD,
/*ForVTable=*/false);
llvm::GlobalIFunc *GIF =
llvm::GlobalIFunc::create(DeclTy, 0, llvm::Function::ExternalLinkage,
|
Please fix buildbot failure (it looks like clang/test/CodeGen/ifunc.c is failing). |
I think it is not the correct way to fix this issue. GD is type for ifunc not for resolver. So the CI brokes if we do things like this. |
Probably you want a dedicated codepath for computing the right kcfi type for resolvers. |
I think the calculation has nothing wrong. The problem is !kcfi_type function attribute is not appear in IR. The problem happens because ifunc can refer resolver that havn't been defined before ifunc attribute. But LLVM Function only add attribute when it constructed first time. So there are two possible path: In the under case, no_sanitize cannot be add because it happens at ifunc("resolver") so the unit test failed func_t resolver() {
}
int foo(int) __attribute__ ((ifunc("resolver"))); In the under case, kcfi attribute failed to add because it happens at function definition: int foo(int) __attribute__ ((ifunc("resolver")));
func_t resolver() {
} I try to fix it but other error happens, here is the patch file. |
Oh, hmm, I see. Maybe the right strategy here is to delay attaching the resolver to the ifunc until the end of the translation unit, when we know the definition is already emitted. That way, it should already have the right attributes. (We already do some delayed checking on aliases/ifuncs anyway, in checkAliasedGlobal().) |
@efriedma-quic I've tried your suggestion: move int foo(int) __attribute__ ((ifunc("resolver")));
static void *resolver(void) { return 0; } // MustBeEmitted(Global) return false |
The usual mechanism for emitting deferred definitions involves CodeGenModule::EmitDeferred(): declarations get added to the list by addDeferredDeclToEmit(), then it goes through to emit all the declarations on the list. So it's a matter of making sure the resolver ends up on the list. You should be able to look up the GlobalDecl from the mangled name using CodeGenModule::DeferredDecls, I think? |
Add ifunc-after-resolver tests to inprove coverage and demonstrate the -fsanitize=kcfi issue reported at #96400.
Created #98832 , which shall fix the problem. This problem is less about deferred emission, but a normal |
Wow, it helps me alot. I make the thing too complicate. I think I can close this PR. Thanks you two very much! |
In FreeBSD, we use ifunc to select best performance function in load time. However, the resolver is also a function itself but not been tagged kcfi by clang. The problems is caused by
called by CodeGenModule::GetOrCreateLLVMFunction where D is empty originally.