summaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CodeGenModule.cpp
diff options
context:
space:
mode:
authorItay Bookstein <ibookstein@gmail.com>2021-10-30 14:27:38 +0300
committerItay Bookstein <ibookstein@gmail.com>2021-11-09 23:51:36 +0200
commit3b1fd19357be50cec8a5be8660806e0e02e84aa1 (patch)
tree5c778d0164f2eba46a06acd32437bd09c14548e2 /clang/lib/CodeGen/CodeGenModule.cpp
parentce91540beeff08ddef826c0819fbaabfd4aefc86 (diff)
[CodeGen] Diagnose and reject non-function ifunc resolvers
Signed-off-by: Itay Bookstein <ibookstein@gmail.com> Reviewed By: MaskRay, erichkeane Differential Revision: https://reviews.llvm.org/D112868
Diffstat (limited to 'clang/lib/CodeGen/CodeGenModule.cpp')
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp80
1 files changed, 53 insertions, 27 deletions
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 =