diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/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(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(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. diff --git a/clang/test/CodeGenCXX/dso-handle-custom.cpp b/clang/test/CodeGenCXX/dso-handle-custom.cpp new file mode 100644 --- /dev/null +++ b/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); +}