[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