[clang] 3b1fd19 - [CodeGen] Diagnose and reject non-function ifunc resolvers
Itay Bookstein via cfe-commits
cfe-commits at lists.llvm.org
Tue Nov 9 13:51:46 PST 2021
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 <ibookstein at 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 at -1 {{ifunc must point to a defined function}}
-void *f2_a() __attribute__((ifunc("f2_b")));
-// expected-error at -1 {{ifunc definition is part of a cycle}}
+void *f2_a() __attribute__((alias("f2_b")));
void *f2_b() __attribute__((ifunc("f2_a")));
// expected-error at -1 {{ifunc definition is part of a cycle}}
@@ -27,6 +26,15 @@ void f4_ifunc() {}
void f4() __attribute__((ifunc("f4_ifunc")));
// expected-error at -1 {{ifunc resolver function must return a pointer}}
+int f5_resolver_gvar;
+void f5() __attribute__((ifunc("f5_resolver_gvar")));
+// expected-error at -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 at -1 {{ifunc must point to a defined function}}
+
#else
void f1a() __asm("f1");
void f1a() {}
More information about the cfe-commits
mailing list