[llvm] d540ebf - [ARM64EC] Avoid emitting unnecessary symbol references with /guard:cf. (#123235)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 21 16:29:26 PST 2025


Author: Eli Friedman
Date: 2025-01-21T16:29:23-08:00
New Revision: d540ebf6cbf97b8bac45af837a741bcb5bd1e1f6

URL: https://github.com/llvm/llvm-project/commit/d540ebf6cbf97b8bac45af837a741bcb5bd1e1f6
DIFF: https://github.com/llvm/llvm-project/commit/d540ebf6cbf97b8bac45af837a741bcb5bd1e1f6.diff

LOG: [ARM64EC] Avoid emitting unnecessary symbol references with /guard:cf. (#123235)

.gfids$y contains a list of indirect calls for Control Flow Guard. This
wasn't working properly for ARM64EC: direct calls were being treated as
indirect calls. Make sure we correctly filter out direct calls.

This improves the protection from Control Flow Guard, and also fixes a
link error when using certain functions from oldnames.lib.

Added: 
    llvm/test/CodeGen/AArch64/cfguard-arm64ec.ll

Modified: 
    llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp b/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp
index 1a1e6f0117e2b8..663be65b7b9a8a 100644
--- a/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp
@@ -49,26 +49,32 @@ static bool isPossibleIndirectCallTarget(const Function *F) {
     const Value *FnOrCast = Users.pop_back_val();
     for (const Use &U : FnOrCast->uses()) {
       const User *FnUser = U.getUser();
-      if (isa<BlockAddress>(FnUser))
+      if (isa<BlockAddress>(FnUser)) {
+        // Block addresses are illegal to call.
         continue;
+      }
       if (const auto *Call = dyn_cast<CallBase>(FnUser)) {
-        if (!Call->isCallee(&U))
+        if ((!Call->isCallee(&U) || U.get() != F) &&
+            !Call->getFunction()->getName().ends_with("$exit_thunk")) {
+          // Passing a function pointer to a call may lead to an indirect
+          // call. As an exception, ignore ARM64EC exit thunks.
           return true;
+        }
       } else if (isa<Instruction>(FnUser)) {
         // Consider any other instruction to be an escape. This has some weird
         // consequences like no-op intrinsics being an escape or a store *to* a
         // function address being an escape.
         return true;
-      } else if (const auto *C = dyn_cast<Constant>(FnUser)) {
-        // If this is a constant pointer cast of the function, don't consider
-        // this escape. Analyze the uses of the cast as well. This ensures that
-        // direct calls with mismatched prototypes don't end up in the CFG
-        // table. Consider other constants, such as vtable initializers, to
-        // escape the function.
-        if (C->stripPointerCasts() == F)
-          Users.push_back(FnUser);
-        else
-          return true;
+      } else if (const auto *G = dyn_cast<GlobalValue>(FnUser)) {
+        // Ignore llvm.arm64ec.symbolmap; it doesn't lower to an actual address.
+        if (G->getName() == "llvm.arm64ec.symbolmap")
+          continue;
+        // Globals (for example, vtables) are escapes.
+        return true;
+      } else if (isa<Constant>(FnUser)) {
+        // Constants which aren't a global are intermediate values; recursively
+        // analyze the users to see if they actually escape.
+        Users.push_back(FnUser);
       }
     }
   }

diff  --git a/llvm/test/CodeGen/AArch64/cfguard-arm64ec.ll b/llvm/test/CodeGen/AArch64/cfguard-arm64ec.ll
new file mode 100644
index 00000000000000..bdbc99e2d98b0a
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/cfguard-arm64ec.ll
@@ -0,0 +1,16 @@
+; RUN: llc < %s -mtriple=arm64ec-pc-windows-msvc | FileCheck %s
+
+declare void @called()
+declare void @escaped()
+define void @f(ptr %dst) {
+  call void @called()
+  store ptr @escaped, ptr %dst
+  ret void
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 2, !"cfguard", i32 1}
+
+; CHECK-LABEL: .section .gfids$y,"dr"
+; CHECK-NEXT:  .symidx escaped
+; CHECK-NOT:   .symidx


        


More information about the llvm-commits mailing list