[llvm] [IR] Allow uses of `llvm.global_ctors` and `llvm.global_dtors` (PR #96477)
Daniil Kovalev via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 24 04:27:07 PDT 2024
https://github.com/kovdan01 created https://github.com/llvm/llvm-project/pull/96477
With PAuth enabled, signed function pointers in init/fini arrays are going to be represented with `ptrauth` constants. To support address discrimination for such signed pointers, we need to fill the storage address with `getelementptr` referencing the array (`llvm.global_ctors` or `llvm.global_dtors`) itself.
Such uses of these special arrays were previously disallowed since `appendToGlobal{C|D}tors` did not update uses after construction of a new array (see b67c16ff6af557174e498d6d82df9936e333f3d6). This patch implements such update logic. This will be tested in a follow-up patch introducing PAuth support for function pointers in init/fini arrays since such signed pointers with address discrimination are currently the only entities which have such uses needed to be updated.
>From 219b873992b0a30afa796f61384c4ff26f15a45e Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Mon, 24 Jun 2024 13:39:58 +0300
Subject: [PATCH] [IR] Allow uses of `llvm.global_ctors` and
`llvm.global_dtors`
With PAuth enabled, signed function pointers in init/fini arrays are
going to be represented with `ptrauth` constants. To support address
discrimination for such signed pointers, we need to fill the storage
address with `getelementptr` referencing the array (`llvm.global_ctors`
or `llvm.global_dtors`) itself.
Such uses of these special arrays were previously disallowed since
`appendToGlobal{C|D}tors` did not update uses after construction of a new
array. This patch implements such update logic. This will be tested in a
follow-up patch introducing PAuth support for function pointers in init/fini
arrays since such signed pointers with address discrimination are
currently the only entities which have such uses needed to be updated.
---
llvm/lib/IR/Verifier.cpp | 2 --
llvm/lib/Transforms/Utils/ModuleUtils.cpp | 14 ++++++++++----
llvm/test/Verifier/global-ctors-dtors-uses.ll | 16 ----------------
3 files changed, 10 insertions(+), 22 deletions(-)
delete mode 100644 llvm/test/Verifier/global-ctors-dtors-uses.ll
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 0abd5f76d449c..ee17d266e5057 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -850,8 +850,6 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
GV.getName() == "llvm.global_dtors")) {
Check(!GV.hasInitializer() || GV.hasAppendingLinkage(),
"invalid linkage for intrinsic global variable", &GV);
- Check(GV.materialized_use_empty(),
- "invalid uses of intrinsic global variable", &GV);
// Don't worry about emitting an error for it not being an array,
// visitGlobalValue will complain on appending non-array.
diff --git a/llvm/lib/Transforms/Utils/ModuleUtils.cpp b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
index 122279160cc7e..0656a094dfa65 100644
--- a/llvm/lib/Transforms/Utils/ModuleUtils.cpp
+++ b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
@@ -35,7 +35,8 @@ static void appendToGlobalArray(StringRef ArrayName, Module &M, Function *F,
// to the list.
SmallVector<Constant *, 16> CurrentCtors;
StructType *EltTy;
- if (GlobalVariable *GVCtor = M.getNamedGlobal(ArrayName)) {
+ GlobalVariable *GVCtor = M.getNamedGlobal(ArrayName);
+ if (GVCtor) {
EltTy = cast<StructType>(GVCtor->getValueType()->getArrayElementType());
if (Constant *Init = GVCtor->getInitializer()) {
unsigned n = Init->getNumOperands();
@@ -43,7 +44,7 @@ static void appendToGlobalArray(StringRef ArrayName, Module &M, Function *F,
for (unsigned i = 0; i != n; ++i)
CurrentCtors.push_back(cast<Constant>(Init->getOperand(i)));
}
- GVCtor->eraseFromParent();
+ GVCtor->removeFromParent();
} else {
EltTy = StructType::get(IRB.getInt32Ty(),
PointerType::get(FnTy, F->getAddressSpace()),
@@ -67,8 +68,13 @@ static void appendToGlobalArray(StringRef ArrayName, Module &M, Function *F,
// Create the new global variable and replace all uses of
// the old global variable with the new one.
- (void)new GlobalVariable(M, NewInit->getType(), false,
- GlobalValue::AppendingLinkage, NewInit, ArrayName);
+ auto *NewGVCtor =
+ new GlobalVariable(M, NewInit->getType(), false,
+ GlobalValue::AppendingLinkage, NewInit, ArrayName);
+ if (GVCtor)
+ for (Use &U : make_early_inc_range(GVCtor->uses()))
+ U.set(NewGVCtor);
+ delete GVCtor;
}
void llvm::appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data) {
diff --git a/llvm/test/Verifier/global-ctors-dtors-uses.ll b/llvm/test/Verifier/global-ctors-dtors-uses.ll
deleted file mode 100644
index 1af4fb7ca9c0e..0000000000000
--- a/llvm/test/Verifier/global-ctors-dtors-uses.ll
+++ /dev/null
@@ -1,16 +0,0 @@
-; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
-
-; CHECK: invalid uses of intrinsic global variable
-; CHECK-NEXT: ptr @llvm.global_ctors
- at llvm.global_ctors = appending global [1 x { i32, ptr, ptr } ] [
- { i32, ptr, ptr } { i32 65535, ptr null, ptr null }
-]
-
-; CHECK: invalid uses of intrinsic global variable
-; CHECK-NEXT: ptr @llvm.global_dtors
- at llvm.global_dtors = appending global [1 x { i32, ptr, ptr } ] [
- { i32, ptr, ptr } { i32 65535, ptr null, ptr null }
-]
-
- at ctor_user = global ptr @llvm.global_ctors
- at dtor_user = global ptr @llvm.global_dtors
More information about the llvm-commits
mailing list