[llvm] 5903263 - [Orc] Support atexit in Orc(JITLink)

via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 8 23:54:27 PDT 2021


Author: luxufan
Date: 2021-10-09T12:25:47+08:00
New Revision: 590326382dad4888111844efa5af0fdeff84c55c

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

LOG: [Orc] Support atexit in Orc(JITLink)

There is a bug reported at https://bugs.llvm.org/show_bug.cgi?id=48938

After looking through the glibc, I found the `atexit(f)` is the same as `__cxa_atexit(f, NULL, NULL)`. In orc runtime, we identify different JITDylib by their dso_handle value, so that a NULL dso_handle is invalid. So in this patch, I added a `PlatformJDDSOHandle` to ELFNixRuntimeState, and functions which are registered by atexit will be registered at PlatformJD.

Reviewed By: lhames

Differential Revision: https://reviews.llvm.org/D111413

Added: 
    compiler-rt/test/orc/TestCases/Linux/x86-64/trivial-atexit.S

Modified: 
    compiler-rt/lib/orc/elfnix_platform.cpp
    compiler-rt/lib/orc/elfnix_platform.h
    llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/orc/elfnix_platform.cpp b/compiler-rt/lib/orc/elfnix_platform.cpp
index fae93b48946c..0352f6c4e853 100644
--- a/compiler-rt/lib/orc/elfnix_platform.cpp
+++ b/compiler-rt/lib/orc/elfnix_platform.cpp
@@ -84,11 +84,12 @@ class ELFNixPlatformRuntimeState {
   };
 
 public:
-  static void initialize();
+  static void initialize(void *DSOHandle);
   static ELFNixPlatformRuntimeState &get();
   static void destroy();
 
-  ELFNixPlatformRuntimeState() = default;
+  ELFNixPlatformRuntimeState(void *DSOHandle)
+      : PlatformJDDSOHandle(DSOHandle) {}
 
   // Delete copy and move constructors.
   ELFNixPlatformRuntimeState(const ELFNixPlatformRuntimeState &) = delete;
@@ -112,6 +113,8 @@ class ELFNixPlatformRuntimeState {
   Expected<std::pair<const char *, size_t>>
   getThreadDataSectionFor(const char *ThreadData);
 
+  void *getPlatformJDDSOHandle() { return PlatformJDDSOHandle; }
+
 private:
   PerJITDylibState *getJITDylibStateByHeaderAddr(void *DSOHandle);
   PerJITDylibState *getJITDylibStateByName(string_view Path);
@@ -136,6 +139,8 @@ class ELFNixPlatformRuntimeState {
   const std::vector<std::pair<const char *, InitSectionHandler>> InitSections =
       {{".init_array", runInitArray}};
 
+  void *PlatformJDDSOHandle;
+
   // FIXME: Move to thread-state.
   std::string DLFcnError;
 
@@ -149,9 +154,9 @@ class ELFNixPlatformRuntimeState {
 
 ELFNixPlatformRuntimeState *ELFNixPlatformRuntimeState::MOPS = nullptr;
 
-void ELFNixPlatformRuntimeState::initialize() {
+void ELFNixPlatformRuntimeState::initialize(void *DSOHandle) {
   assert(!MOPS && "ELFNixPlatformRuntimeState should be null");
-  MOPS = new ELFNixPlatformRuntimeState();
+  MOPS = new ELFNixPlatformRuntimeState(DSOHandle);
 }
 
 ELFNixPlatformRuntimeState &ELFNixPlatformRuntimeState::get() {
@@ -434,8 +439,13 @@ void destroyELFNixTLVMgr(void *ELFNixTLVMgr) {
 
 ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
 __orc_rt_elfnix_platform_bootstrap(char *ArgData, size_t ArgSize) {
-  ELFNixPlatformRuntimeState::initialize();
-  return WrapperFunctionResult().release();
+  return WrapperFunction<void(uint64_t)>::handle(
+             ArgData, ArgSize,
+             [](uint64_t &DSOHandle) {
+               ELFNixPlatformRuntimeState::initialize(
+                   reinterpret_cast<void *>(DSOHandle));
+             })
+      .release();
 }
 
 ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
@@ -511,6 +521,12 @@ int __orc_rt_elfnix_cxa_atexit(void (*func)(void *), void *arg,
                                                           dso_handle);
 }
 
+int __orc_rt_elfnix_atexit(void (*func)(void *)) {
+  auto &PlatformRTState = ELFNixPlatformRuntimeState::get();
+  return ELFNixPlatformRuntimeState::get().registerAtExit(
+      func, NULL, PlatformRTState.getPlatformJDDSOHandle());
+}
+
 void __orc_rt_elfnix_cxa_finalize(void *dso_handle) {
   ELFNixPlatformRuntimeState::get().runAtExits(dso_handle);
 }

diff  --git a/compiler-rt/lib/orc/elfnix_platform.h b/compiler-rt/lib/orc/elfnix_platform.h
index 5afeac55419b..12b9591979b7 100644
--- a/compiler-rt/lib/orc/elfnix_platform.h
+++ b/compiler-rt/lib/orc/elfnix_platform.h
@@ -19,6 +19,7 @@
 // Atexit functions.
 ORC_RT_INTERFACE int __orc_rt_elfnix_cxa_atexit(void (*func)(void *), void *arg,
                                                 void *dso_handle);
+ORC_RT_INTERFACE int __orc_rt_elfnix_atexit(void (*func)(void *));
 ORC_RT_INTERFACE void __orc_rt_elfnix_cxa_finalize(void *dso_handle);
 
 // dlfcn functions.

diff  --git a/compiler-rt/test/orc/TestCases/Linux/x86-64/trivial-atexit.S b/compiler-rt/test/orc/TestCases/Linux/x86-64/trivial-atexit.S
new file mode 100644
index 000000000000..16852c6e1ab4
--- /dev/null
+++ b/compiler-rt/test/orc/TestCases/Linux/x86-64/trivial-atexit.S
@@ -0,0 +1,36 @@
+// Test that the runtime correctly interposes atexit.
+//
+// RUN: %clang -c -o %t %s
+// RUN: %llvm_jitlink %t
+
+	.text
+// OnExit destructor resets the test result override to zero.
+	.section	.text._ZN6OnExitD2Ev,"axG", at progbits,_ZN6OnExitD2Ev,comdat
+	.p2align	4, 0x90
+	.type	_ZN6OnExitD2Ev, at function
+_ZN6OnExitD2Ev:                         # @_ZN6OnExitD2Ev
+	.cfi_startproc
+	xorl	%edi, %edi
+	jmp	llvm_jitlink_setTestResultOverride at PLT # TAILCALL
+	.cfi_endproc
+
+// main registers the atexit and sets the test result to one.
+	.globl main
+	.p2align	4, 0x90                         # -- Begin function main
+	.type	main, at function
+main:              # @main
+	.cfi_startproc
+# %bb.0:
+	movq	_ZN6OnExitD2Ev at GOTPCREL(%rip), %rdi
+	callq	atexit at PLT
+	movl	$1, %edi
+	callq	llvm_jitlink_setTestResultOverride at PLT
+	xorl	%eax, %eax
+	retq
+.Lfunc_end1:
+	.size	main, .Lfunc_end1-main
+	.cfi_endproc
+                                        # -- End function
+	.type	_ZL6onExit, at object              # @_ZL6onExit
+	.local	_ZL6onExit
+	.comm	_ZL6onExit,1,1

diff  --git a/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp
index 94499de30549..79c602d0b01e 100644
--- a/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp
@@ -194,7 +194,8 @@ SymbolAliasMap ELFNixPlatform::standardPlatformAliases(ExecutionSession &ES) {
 ArrayRef<std::pair<const char *, const char *>>
 ELFNixPlatform::requiredCXXAliases() {
   static const std::pair<const char *, const char *> RequiredCXXAliases[] = {
-      {"__cxa_atexit", "__orc_rt_elfnix_cxa_atexit"}};
+      {"__cxa_atexit", "__orc_rt_elfnix_cxa_atexit"},
+      {"atexit", "__orc_rt_elfnix_atexit"}};
 
   return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases);
 }
@@ -474,7 +475,13 @@ Error ELFNixPlatform::bootstrapELFNixRuntime(JITDylib &PlatformJD) {
     KV.second->setValue((*RuntimeSymbolAddrs)[Name].getAddress());
   }
 
-  if (auto Err = ES.callSPSWrapper<void()>(orc_rt_elfnix_platform_bootstrap))
+  auto PJDDSOHandle = ES.lookup(
+      {{&PlatformJD, JITDylibLookupFlags::MatchAllSymbols}}, DSOHandleSymbol);
+  if (!PJDDSOHandle)
+    return PJDDSOHandle.takeError();
+
+  if (auto Err = ES.callSPSWrapper<void(uint64_t)>(
+          orc_rt_elfnix_platform_bootstrap, PJDDSOHandle->getAddress()))
     return Err;
 
   // FIXME: Ordering is fuzzy here. We're probably best off saying


        


More information about the llvm-commits mailing list