[PATCH] D101156: [Clang] Support a user-defined __dso_handle

Andrew Savonichev via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 23 05:19:24 PDT 2021


asavonic created this revision.
asavonic requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This fixes PR49198: Wrong usage of __dso_handle in user code leads to a compiler
crash.

`__dso_handle` variable is now created with a prefix to avoid a conflict with
the user-defined one which can be emitted later. Once all globals are emitted,
it is renamed back or replaced with a user-defined `__dso_handle`.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D101156

Files:
  clang/lib/CodeGen/ItaniumCXXABI.cpp
  clang/test/CodeGenCXX/dso-handle-custom.cpp


Index: clang/test/CodeGenCXX/dso-handle-custom.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/dso-handle-custom.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fexceptions %s -o - | FileCheck %s
+
+class A {
+public:
+  ~A();
+} a;
+
+// CHECK: @__dso_handle = hidden global i8* bitcast (i8** @__dso_handle to i8*), align 8
+// CHECK: define internal void @__cxx_global_var_init()
+// CHECK:   call i32 @__cxa_atexit({{.*}}, {{.*}}, i8* bitcast (i8** @__dso_handle to i8*))
+
+void *__dso_handle = &__dso_handle;
+
+void use(void *);
+void use_dso_handle() {
+  use(__dso_handle);
+}
Index: clang/lib/CodeGen/ItaniumCXXABI.cpp
===================================================================
--- clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -2531,7 +2531,7 @@
 
   // Create a variable that binds the atexit to this shared object.
   llvm::Constant *handle =
-      CGF.CGM.CreateRuntimeVariable(CGF.Int8Ty, "__dso_handle");
+      CGF.CGM.CreateRuntimeVariable(CGF.Int8Ty, "$__dso_handle");
   auto *GV = cast<llvm::GlobalValue>(handle->stripPointerCasts());
   GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
 
@@ -2685,6 +2685,26 @@
 
   if (getCXXABI().useSinitAndSterm())
     unregisterGlobalDtorsWithUnAtExit();
+
+  // Prefer user-defined __dso_handle over the compiler generated one
+  if (llvm::GlobalValue *GeneratedDSOHandle = GetGlobalValue("$__dso_handle")) {
+    llvm::GlobalValue *CustomDSOHandle = GetGlobalValue("__dso_handle");
+    if (!CustomDSOHandle) {
+      GeneratedDSOHandle->setName("__dso_handle");
+    } else {
+      if (!isa<llvm::GlobalVariable>(CustomDSOHandle))
+        llvm_unreachable("__dso_handle must be a global variable");
+
+      setDSOLocal(CustomDSOHandle);
+      CustomDSOHandle->setLinkage(llvm::GlobalValue::ExternalLinkage);
+      CustomDSOHandle->setVisibility(llvm::GlobalValue::HiddenVisibility);
+
+      llvm::Constant *DSOHandle = llvm::ConstantExpr::getBitCast(
+          CustomDSOHandle, GeneratedDSOHandle->getType());
+      GeneratedDSOHandle->replaceAllUsesWith(DSOHandle);
+      GeneratedDSOHandle->eraseFromParent();
+    }
+  }
 }
 
 /// Register a global destructor as best as we know how.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D101156.339986.patch
Type: text/x-patch
Size: 2311 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20210423/bc3cec98/attachment-0001.bin>


More information about the cfe-commits mailing list