From 3b1fd19357be50cec8a5be8660806e0e02e84aa1 Mon Sep 17 00:00:00 2001 From: Itay Bookstein Date: Sat, 30 Oct 2021 14:27:38 +0300 Subject: [CodeGen] Diagnose and reject non-function ifunc resolvers Signed-off-by: Itay Bookstein Reviewed By: MaskRay, erichkeane Differential Revision: https://reviews.llvm.org/D112868 --- clang/lib/CodeGen/CodeGenModule.cpp | 80 ++++++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 27 deletions(-) (limited to 'clang/lib/CodeGen/CodeGenModule.cpp') 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 Visited; - for (;;) { - if (!GV || !Visited.insert(GV).second) - return nullptr; - - const llvm::Constant *C; - if (auto *GA = dyn_cast(GV)) - C = GA->getAliasee(); - else if (auto *GI = dyn_cast(GV)) - C = GI->getResolver(); - else - return GV; + const llvm::Constant *C; + if (auto *GA = dyn_cast(GV)) + C = GA->getAliasee(); + else if (auto *GI = dyn_cast(GV)) + C = GI->getResolver(); + else + return GV; + + const auto *AliaseeGV = dyn_cast(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(GV); + if (!F) { + Diags.Report(Location, diag::err_alias_to_undefined) + << IsIFunc << IsIFunc; + return false; + } - GV = dyn_cast(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( - GV->getType()->getPointerElementType()); - assert(FTy); - if (!FTy->getReturnType()->isPointerTy()) - Diags.Report(Location, diag::err_ifunc_resolver_return); + continue; } llvm::Constant *Aliasee = -- cgit v1.2.3