Author: Itay Bookstein Date: 2021-11-09T23:51:36+02:00 New Revision: 3b1fd19357be50cec8a5be8660806e0e02e84aa1
URL: https://github.com/llvm/llvm-project/commit/3b1fd19357be50cec8a5be8660806e0e02e84aa1 DIFF: https://github.com/llvm/llvm-project/commit/3b1fd19357be50cec8a5be8660806e0e02e84aa1.diff LOG: [CodeGen] Diagnose and reject non-function ifunc resolvers Signed-off-by: Itay Bookstein <ibookst...@gmail.com> Reviewed By: MaskRay, erichkeane Differential Revision: https://reviews.llvm.org/D112868 Added: Modified: clang/lib/CodeGen/CodeGenModule.cpp clang/test/CodeGen/attr-ifunc.c Removed: ################################################################################ diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index df5e02e9812f..8e4d9dc751dd 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -313,21 +313,57 @@ void CodeGenModule::applyGlobalValReplacements() { // This is only used in aliases that we created and we know they have a // linear structure. static const llvm::GlobalValue *getAliasedGlobal(const llvm::GlobalValue *GV) { - llvm::SmallPtrSet<const llvm::GlobalValue *, 4> Visited; - for (;;) { - if (!GV || !Visited.insert(GV).second) - return nullptr; - - const llvm::Constant *C; - if (auto *GA = dyn_cast<llvm::GlobalAlias>(GV)) - C = GA->getAliasee(); - else if (auto *GI = dyn_cast<llvm::GlobalIFunc>(GV)) - C = GI->getResolver(); - else - return GV; + const llvm::Constant *C; + if (auto *GA = dyn_cast<llvm::GlobalAlias>(GV)) + C = GA->getAliasee(); + else if (auto *GI = dyn_cast<llvm::GlobalIFunc>(GV)) + C = GI->getResolver(); + else + return GV; + + const auto *AliaseeGV = dyn_cast<llvm::GlobalValue>(C->stripPointerCasts()); + if (!AliaseeGV) + return nullptr; + + const llvm::GlobalValue *FinalGV = AliaseeGV->getAliaseeObject(); + if (FinalGV == GV) + return nullptr; + + return FinalGV; +} + +static bool checkAliasedGlobal(DiagnosticsEngine &Diags, + SourceLocation Location, bool IsIFunc, + const llvm::GlobalValue *Alias, + const llvm::GlobalValue *&GV) { + GV = getAliasedGlobal(Alias); + if (!GV) { + Diags.Report(Location, diag::err_cyclic_alias) << IsIFunc; + return false; + } + + if (GV->isDeclaration()) { + Diags.Report(Location, diag::err_alias_to_undefined) << IsIFunc << IsIFunc; + return false; + } + + if (IsIFunc) { + // Check resolver function type. + const auto *F = dyn_cast<llvm::Function>(GV); + if (!F) { + Diags.Report(Location, diag::err_alias_to_undefined) + << IsIFunc << IsIFunc; + return false; + } - GV = dyn_cast<llvm::GlobalValue>(C->stripPointerCasts()); + llvm::FunctionType *FTy = F->getFunctionType(); + if (!FTy->getReturnType()->isPointerTy()) { + Diags.Report(Location, diag::err_ifunc_resolver_return); + return false; + } } + + return true; } void CodeGenModule::checkAliases() { @@ -344,23 +380,13 @@ void CodeGenModule::checkAliases() { Location = A->getLocation(); else llvm_unreachable("Not an alias or ifunc?"); + StringRef MangledName = getMangledName(GD); llvm::GlobalValue *Alias = GetGlobalValue(MangledName); - const llvm::GlobalValue *GV = getAliasedGlobal(Alias); - if (!GV) { - Error = true; - Diags.Report(Location, diag::err_cyclic_alias) << IsIFunc; - } else if (GV->isDeclaration()) { + const llvm::GlobalValue *GV = nullptr; + if (!checkAliasedGlobal(Diags, Location, IsIFunc, Alias, GV)) { Error = true; - Diags.Report(Location, diag::err_alias_to_undefined) - << IsIFunc << IsIFunc; - } else if (IsIFunc) { - // Check resolver function type. - llvm::FunctionType *FTy = dyn_cast<llvm::FunctionType>( - GV->getType()->getPointerElementType()); - assert(FTy); - if (!FTy->getReturnType()->isPointerTy()) - Diags.Report(Location, diag::err_ifunc_resolver_return); + continue; } llvm::Constant *Aliasee = diff --git a/clang/test/CodeGen/attr-ifunc.c b/clang/test/CodeGen/attr-ifunc.c index 6fac48a5afe2..1a5c38545177 100644 --- a/clang/test/CodeGen/attr-ifunc.c +++ b/clang/test/CodeGen/attr-ifunc.c @@ -13,8 +13,7 @@ void *f1_ifunc(); void f1() __attribute__((ifunc("f1_ifunc"))); // expected-error@-1 {{ifunc must point to a defined function}} -void *f2_a() __attribute__((ifunc("f2_b"))); -// expected-error@-1 {{ifunc definition is part of a cycle}} +void *f2_a() __attribute__((alias("f2_b"))); void *f2_b() __attribute__((ifunc("f2_a"))); // expected-error@-1 {{ifunc definition is part of a cycle}} @@ -27,6 +26,15 @@ void f4_ifunc() {} void f4() __attribute__((ifunc("f4_ifunc"))); // expected-error@-1 {{ifunc resolver function must return a pointer}} +int f5_resolver_gvar; +void f5() __attribute__((ifunc("f5_resolver_gvar"))); +// expected-error@-1 {{ifunc must point to a defined function}} + +void *f6_resolver_resolver() { return 0; } +void *f6_resolver() __attribute__((ifunc("f6_resolver_resolver"))); +void f6() __attribute__((ifunc("f6_resolver"))); +// expected-error@-1 {{ifunc must point to a defined function}} + #else void f1a() __asm("f1"); void f1a() {} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits