Skip to content
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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

aokblast
Copy link
Contributor

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

if (D)
CodeGenModule::SetFunctionAttribute()

called by CodeGenModule::GetOrCreateLLVMFunction where D is empty originally.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:codegen labels Jun 22, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Jun 22, 2024

@llvm/pr-subscribers-clang-codegen

@llvm/pr-subscribers-clang

Author: None (aokblast)

Changes

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

if (D)
CodeGenModule::SetFunctionAttribute()

called by CodeGenModule::GetOrCreateLLVMFunction where D is empty originally.


Full diff: https://github.com/llvm/llvm-project/pull/96400.diff

1 Files Affected:

  • (modified) clang/lib/CodeGen/CodeGenModule.cpp (+1-1)
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,

@efriedma-quic
Copy link
Collaborator

Please fix buildbot failure (it looks like clang/test/CodeGen/ifunc.c is failing).

@aokblast
Copy link
Contributor Author

aokblast commented Jul 2, 2024

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.

@efriedma-quic
Copy link
Collaborator

Probably you want a dedicated codepath for computing the right kcfi type for resolvers.

@aokblast
Copy link
Contributor Author

aokblast commented Jul 3, 2024

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.

@efriedma-quic
Copy link
Collaborator

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().)

@MaskRay
Copy link
Member

MaskRay commented Jul 10, 2024

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 setResolver to checkAliasedGlobal. However, I've run into some difficulty. When EmitGlobal(foo) is called, how to mark resolver as eagerly emitted? (Otherwise, resolver would not be emitted at all.)

int foo(int) __attribute__ ((ifunc("resolver")));
static void *resolver(void) { return 0; }   // MustBeEmitted(Global) return false

@efriedma-quic
Copy link
Collaborator

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?

MaskRay added a commit that referenced this pull request Jul 14, 2024
Add ifunc-after-resolver tests to inprove coverage and demonstrate the
-fsanitize=kcfi issue reported at #96400.
@MaskRay
Copy link
Member

MaskRay commented Jul 14, 2024

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?

Created #98832 , which shall fix the problem.

This problem is less about deferred emission, but a normal GetOrCreateLLVMFunction ForDefinition call prematurely returns due to llvm::Type *ResolverTy = llvm::GlobalIFunc::getResolverFunctionType(DeclTy) and (Entry->getValueType() == Ty)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:codegen clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants