Skip to content

[clang][AArch64] Move initialization of ptrauth-* function attrs #140277

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 20, 2025

Conversation

atrosinenko
Copy link
Contributor

@atrosinenko atrosinenko commented May 16, 2025

Move the initialization of ptrauth-* function attributes near the initialization of branch protection attributes. The semantics of these groups of attributes partially overlaps, so handle both groups in getDefaultFunctionAttributes() and setTargetAttributes() functions to prevent getting them out of sync. This fixes C++ TLS wrappers.

Move the initialization of ptrauth-* function attributes near the
initialization of branch protection attributes. The semantics of these
groups of attributes partially overlaps, so initialize them both in
getTrivialDefaultFunctionAttributes() function to prevent getting them
out of sync. This fixes C++ TLS wrappers.
Copy link
Member

@DanielKristofKiss DanielKristofKiss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.
maybe worth to review the attribute handling for the synthetic function's attributes in llvm too.

Copy link
Contributor

@ojhunt ojhunt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, I may start working on moving the preferences into the targetinfo unless you're working on that already

@atrosinenko
Copy link
Contributor Author

It seems that when I rebased this PR from an older version of main branch, some test failures came up. I'm investigating these now. An example is clang/test/CodeGen/ptrauth-function-lvalue-cast.c, where an attribute was added at call site:

  call void %0() #1 [ "ptrauth"(i32 0, i64 0) ]
;                ^^

maybe worth to review the attribute handling for the synthetic function's attributes in llvm too.

@DanielKristofKiss As far as I know, at least one example of synthetic functions not protected with pac-ret is Function Multi Versioning resolvers. This could be fixed via a separate PR, though.

@atrosinenko
Copy link
Contributor Author

Fixed the tests in 85c21ec:

  • do not add attributes on the call site (something was probably wrong with the way I was running the tests, as this should fail before the rebase as well...)
  • added setPointerAuthFnAttributes as a counterpart of setBranchProtectionFnAttributes (in clang/test/CodeGenCXX/ptrauth.cpp std::terminate() is implemented, but by the time its implementation is emitted, GetOrCreateLLVMFunction was already called without a Decl, thus lazy-initializing a function, but without the attributes)

I may start working on moving the preferences into the targetinfo unless you're working on that already

@ojhunt I'm not working on it, thank you!

@atrosinenko atrosinenko marked this pull request as ready for review May 17, 2025 11:20
@llvmbot llvmbot added clang Clang issues not falling into any other category backend:AArch64 clang:codegen IR generation bugs: mangling, exceptions, etc. labels May 17, 2025
@llvmbot
Copy link
Member

llvmbot commented May 17, 2025

@llvm/pr-subscribers-backend-aarch64

@llvm/pr-subscribers-clang

Author: Anatoly Trosinenko (atrosinenko)

Changes

Move the initialization of ptrauth-* function attributes near the initialization of branch protection attributes. The semantics of these groups of attributes partially overlaps, so initialize them both in getTrivialDefaultFunctionAttributes() function to prevent getting them out of sync. This fixes C++ TLS wrappers.


Full diff: https://github.com/llvm/llvm-project/pull/140277.diff

6 Files Affected:

  • (modified) clang/lib/CodeGen/CGCall.cpp (+5)
  • (modified) clang/lib/CodeGen/CodeGenFunction.cpp (-13)
  • (modified) clang/lib/CodeGen/TargetInfo.cpp (+29)
  • (modified) clang/lib/CodeGen/TargetInfo.h (+9)
  • (modified) clang/lib/CodeGen/Targets/AArch64.cpp (+1)
  • (modified) clang/test/CodeGenCXX/arm64-generated-fn-attr.cpp (+10-3)
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index bcd579454413e..bd920a2e3f2dd 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -2216,6 +2216,11 @@ void CodeGenModule::getDefaultFunctionAttributes(StringRef Name,
                                                  llvm::AttrBuilder &FuncAttrs) {
   getTrivialDefaultFunctionAttributes(Name, HasOptnone, AttrOnCallSite,
                                       FuncAttrs);
+
+  if (!AttrOnCallSite)
+    TargetCodeGenInfo::initPointerAuthFnAttributes(CodeGenOpts.PointerAuth,
+                                                   FuncAttrs);
+
   // If we're just getting the default, get the default values for mergeable
   // attributes.
   if (!AttrOnCallSite)
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index ac40aab97820d..4e79cdf0ef089 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -890,19 +890,6 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
         FD->getBody()->getStmtClass() == Stmt::CoroutineBodyStmtClass)
       SanOpts.Mask &= ~SanitizerKind::Null;
 
-  // Add pointer authentication attributes.
-  const CodeGenOptions &CodeGenOpts = CGM.getCodeGenOpts();
-  if (CodeGenOpts.PointerAuth.ReturnAddresses)
-    Fn->addFnAttr("ptrauth-returns");
-  if (CodeGenOpts.PointerAuth.FunctionPointers)
-    Fn->addFnAttr("ptrauth-calls");
-  if (CodeGenOpts.PointerAuth.AuthTraps)
-    Fn->addFnAttr("ptrauth-auth-traps");
-  if (CodeGenOpts.PointerAuth.IndirectGotos)
-    Fn->addFnAttr("ptrauth-indirect-gotos");
-  if (CodeGenOpts.PointerAuth.AArch64JumpTableHardening)
-    Fn->addFnAttr("aarch64-jump-table-hardening");
-
   // Apply xray attributes to the function (as a string, for now)
   bool AlwaysXRayAttr = false;
   if (const auto *XRayAttr = D ? D->getAttr<XRayInstrumentAttr>() : nullptr) {
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index 75a7d3c7c73f0..7d176e421ac4e 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -258,6 +258,35 @@ void TargetCodeGenInfo::initBranchProtectionFnAttributes(
     FuncAttrs.addAttribute("guarded-control-stack");
 }
 
+void TargetCodeGenInfo::setPointerAuthFnAttributes(
+    const PointerAuthOptions &Opts, llvm::Function &F) {
+  auto UpdateAttr = [&F](bool AttrShouldExist, StringRef AttrName) {
+    if (AttrShouldExist && !F.hasFnAttribute(AttrName))
+      F.addFnAttr(AttrName);
+    if (!AttrShouldExist && F.hasFnAttribute(AttrName))
+      F.removeFnAttr(AttrName);
+  };
+  UpdateAttr(Opts.ReturnAddresses, "ptrauth-returns");
+  UpdateAttr((bool)Opts.FunctionPointers, "ptrauth-calls");
+  UpdateAttr(Opts.AuthTraps, "ptrauth-auth-traps");
+  UpdateAttr(Opts.IndirectGotos, "ptrauth-indirect-gotos");
+  UpdateAttr(Opts.AArch64JumpTableHardening, "aarch64-jump-table-hardening");
+}
+
+void TargetCodeGenInfo::initPointerAuthFnAttributes(
+    const PointerAuthOptions &Opts, llvm::AttrBuilder &FuncAttrs) {
+  if (Opts.ReturnAddresses)
+    FuncAttrs.addAttribute("ptrauth-returns");
+  if (Opts.FunctionPointers)
+    FuncAttrs.addAttribute("ptrauth-calls");
+  if (Opts.AuthTraps)
+    FuncAttrs.addAttribute("ptrauth-auth-traps");
+  if (Opts.IndirectGotos)
+    FuncAttrs.addAttribute("ptrauth-indirect-gotos");
+  if (Opts.AArch64JumpTableHardening)
+    FuncAttrs.addAttribute("aarch64-jump-table-hardening");
+}
+
 namespace {
 class DefaultTargetCodeGenInfo : public TargetCodeGenInfo {
 public:
diff --git a/clang/lib/CodeGen/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h
index dd5dc0c32bd71..e94e2e1aac7ea 100644
--- a/clang/lib/CodeGen/TargetInfo.h
+++ b/clang/lib/CodeGen/TargetInfo.h
@@ -455,6 +455,15 @@ class TargetCodeGenInfo {
   initBranchProtectionFnAttributes(const TargetInfo::BranchProtectionInfo &BPI,
                                    llvm::AttrBuilder &FuncAttrs);
 
+  // Set the ptrauth-* attributes of the Function accordingly to the Opts.
+  // Remove attributes that contradict with current Opts.
+  static void setPointerAuthFnAttributes(const PointerAuthOptions &Opts,
+                                         llvm::Function &F);
+
+  // Add the ptrauth-* Attributes to the FuncAttrs.
+  static void initPointerAuthFnAttributes(const PointerAuthOptions &Opts,
+                                          llvm::AttrBuilder &FuncAttrs);
+
 protected:
   static std::string qualifyWindowsLibrary(StringRef Lib);
 
diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp
index f098f09ebf581..6311d921f3fd6 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -155,6 +155,7 @@ class AArch64TargetCodeGenInfo : public TargetCodeGenInfo {
       }
     }
     setBranchProtectionFnAttributes(BPI, *Fn);
+    setPointerAuthFnAttributes(CGM.getCodeGenOpts().PointerAuth, *Fn);
   }
 
   bool isScalarizableAsmOperand(CodeGen::CodeGenFunction &CGF,
diff --git a/clang/test/CodeGenCXX/arm64-generated-fn-attr.cpp b/clang/test/CodeGenCXX/arm64-generated-fn-attr.cpp
index 18d9da40d469b..630b5edbbc1d7 100644
--- a/clang/test/CodeGenCXX/arm64-generated-fn-attr.cpp
+++ b/clang/test/CodeGenCXX/arm64-generated-fn-attr.cpp
@@ -1,4 +1,9 @@
-// RUN: %clang_cc1 -triple aarch64 -mbranch-target-enforce -msign-return-address=all -fcxx-exceptions -fexceptions -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64 -mbranch-target-enforce -msign-return-address=all \
+// RUN:            -fcxx-exceptions -fexceptions -emit-llvm %s -o - \
+// RUN:   | FileCheck --check-prefixes=CHECK,BTE-SIGNRA %s
+// RUN: %clang_cc1 -triple aarch64 -fptrauth-calls -fptrauth-returns -fptrauth-auth-traps -fptrauth-indirect-gotos \
+// RUN:            -fcxx-exceptions -fexceptions -emit-llvm %s -o - \
+// RUN:   | FileCheck --check-prefixes=CHECK,PAUTHTEST %s
 
 // Check that functions generated by clang have the correct attributes
 
@@ -26,5 +31,7 @@ int testfn() noexcept {
 // CHECK: define {{.*}} @_ZTW4var2() [[ATTR1]]
 // CHECK: define {{.*}} @__tls_init() [[ATTR1]]
 
-// CHECK: attributes [[ATTR1]] = { {{.*}}"branch-target-enforcement" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key"
-// CHECK: attributes [[ATTR2]] = { {{.*}}"branch-target-enforcement" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key"
+// BTE-SIGNRA: attributes [[ATTR1]] = { {{.*}}"branch-target-enforcement" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key"
+// BTE-SIGNRA: attributes [[ATTR2]] = { {{.*}}"branch-target-enforcement" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key"
+// PAUTHTEST: attributes [[ATTR1]] = { {{.*}}"ptrauth-auth-traps" "ptrauth-calls" "ptrauth-indirect-gotos" "ptrauth-returns"
+// PAUTHTEST: attributes [[ATTR2]] = { {{.*}}"ptrauth-auth-traps" "ptrauth-calls" "ptrauth-indirect-gotos" "ptrauth-returns"

@atrosinenko atrosinenko merged commit f10a905 into llvm:main May 20, 2025
16 checks passed
@atrosinenko atrosinenko deleted the tls-wrapper-ptrauth branch May 20, 2025 09:51
@llvm-ci
Copy link
Collaborator

llvm-ci commented May 20, 2025

LLVM Buildbot has detected a new failure on builder openmp-s390x-linux running on systemz-1 while building clang at step 6 "test-openmp".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/88/builds/11818

Here is the relevant piece of the build log for the reference
Step 6 (test-openmp) failure: test (failure)
******************** TEST 'libomp :: tasking/issue-94260-2.c' FAILED ********************
Exit Code: -11

Command Output (stdout):
--
# RUN: at line 1
/home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.build/./bin/clang -fopenmp   -I /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -I /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.src/openmp/runtime/test -L /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.build/runtimes/runtimes-bins/openmp/runtime/src  -fno-omit-frame-pointer -mbackchain -I /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.src/openmp/runtime/test/ompt /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.src/openmp/runtime/test/tasking/issue-94260-2.c -o /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.build/runtimes/runtimes-bins/openmp/runtime/test/tasking/Output/issue-94260-2.c.tmp -lm -latomic && /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.build/runtimes/runtimes-bins/openmp/runtime/test/tasking/Output/issue-94260-2.c.tmp
# executed command: /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.build/./bin/clang -fopenmp -I /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -I /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.src/openmp/runtime/test -L /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -fno-omit-frame-pointer -mbackchain -I /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.src/openmp/runtime/test/ompt /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.src/openmp/runtime/test/tasking/issue-94260-2.c -o /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.build/runtimes/runtimes-bins/openmp/runtime/test/tasking/Output/issue-94260-2.c.tmp -lm -latomic
# executed command: /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.build/runtimes/runtimes-bins/openmp/runtime/test/tasking/Output/issue-94260-2.c.tmp
# note: command had no output on stdout or stderr
# error: command failed with exit status: -11

--

********************


sivan-shani pushed a commit to sivan-shani/llvm-project that referenced this pull request Jun 3, 2025
…m#140277)

Move the initialization of ptrauth-* function attributes near the
initialization of branch protection attributes. The semantics of these
groups of attributes partially overlaps, so handle both groups in
getDefaultFunctionAttributes() and setTargetAttributes() functions to
prevent getting them out of sync. This fixes C++ TLS wrappers.
ajaden-codes pushed a commit to Jaddyen/llvm-project that referenced this pull request Jun 6, 2025
…m#140277)

Move the initialization of ptrauth-* function attributes near the
initialization of branch protection attributes. The semantics of these
groups of attributes partially overlaps, so handle both groups in
getDefaultFunctionAttributes() and setTargetAttributes() functions to
prevent getting them out of sync. This fixes C++ TLS wrappers.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:AArch64 clang:codegen IR generation bugs: mangling, exceptions, etc. clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants