[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