forked from OSchip/llvm-project
[ORC-RT][ORC] Handle dynamic unwind registration for libunwind
This changes the ELFNix platform Orc runtime to use, when available, the __unw_add_dynamic_eh_frame_section interface provided by libunwind for registering .eh_frame sections loaded by JITLink. When libunwind is not being used for unwinding, the ELFNix platform detects this and defaults to the __register_frame interface provided by libgcc_s. Reviewed By: lhames Differential Revision: https://reviews.llvm.org/D114961
This commit is contained in:
parent
509b631f84
commit
981523b2e4
|
@ -29,10 +29,10 @@ ORC_RT_JIT_DISPATCH_TAG(__orc_rt_elfnix_get_initializers_tag)
|
|||
ORC_RT_JIT_DISPATCH_TAG(__orc_rt_elfnix_get_deinitializers_tag)
|
||||
ORC_RT_JIT_DISPATCH_TAG(__orc_rt_elfnix_symbol_lookup_tag)
|
||||
|
||||
// eh-frame registration functions.
|
||||
// We expect these to be available for all processes.
|
||||
extern "C" void __register_frame(const void *);
|
||||
extern "C" void __deregister_frame(const void *);
|
||||
// eh-frame registration functions, made available via aliases
|
||||
// installed by the Platform
|
||||
extern "C" void __orc_rt_register_eh_frame_section(const void *);
|
||||
extern "C" void __orc_rt_deregister_eh_frame_section(const void *);
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -172,7 +172,8 @@ void ELFNixPlatformRuntimeState::destroy() {
|
|||
Error ELFNixPlatformRuntimeState::registerObjectSections(
|
||||
ELFNixPerObjectSectionsToRegister POSR) {
|
||||
if (POSR.EHFrameSection.Start)
|
||||
__register_frame(POSR.EHFrameSection.Start.toPtr<const char *>());
|
||||
__orc_rt_register_eh_frame_section(
|
||||
POSR.EHFrameSection.Start.toPtr<const char *>());
|
||||
|
||||
if (POSR.ThreadDataSection.Start) {
|
||||
if (auto Err = registerThreadDataSection(
|
||||
|
@ -186,7 +187,8 @@ Error ELFNixPlatformRuntimeState::registerObjectSections(
|
|||
Error ELFNixPlatformRuntimeState::deregisterObjectSections(
|
||||
ELFNixPerObjectSectionsToRegister POSR) {
|
||||
if (POSR.EHFrameSection.Start)
|
||||
__deregister_frame(POSR.EHFrameSection.Start.toPtr<const char *>());
|
||||
__orc_rt_deregister_eh_frame_section(
|
||||
POSR.EHFrameSection.Start.toPtr<const char *>());
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
// RUN: %clangxx -fexceptions -fPIC -c -o %t %s
|
||||
// RUN: %llvm_jitlink %t
|
||||
|
||||
extern "C" void llvm_jitlink_setTestResultOverride(long Value);
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
llvm_jitlink_setTestResultOverride(1);
|
||||
try {
|
||||
throw 0;
|
||||
} catch (int X) {
|
||||
llvm_jitlink_setTestResultOverride(X);
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
// REQUIRES: libunwind-available
|
||||
// RUN: %clangxx -fexceptions -fPIC -c -o %t %s
|
||||
// RUN: env LD_PRELOAD=%shared_libunwind %llvm_jitlink %t
|
||||
|
||||
extern "C" void llvm_jitlink_setTestResultOverride(long Value);
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
llvm_jitlink_setTestResultOverride(1);
|
||||
try {
|
||||
throw 0;
|
||||
} catch (int X) {
|
||||
llvm_jitlink_setTestResultOverride(X);
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
// RUN: %clangxx -fexceptions -fPIC -c -o %t %s
|
||||
// RUN: %llvm_jitlink %t
|
||||
|
||||
extern "C" void llvm_jitlink_setTestResultOverride(long Value);
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
llvm_jitlink_setTestResultOverride(1);
|
||||
try {
|
||||
throw 0;
|
||||
} catch (int X) {
|
||||
llvm_jitlink_setTestResultOverride(X);
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
// REQUIRES: libunwind-available
|
||||
// RUN: %clangxx -fexceptions -fPIC -c -o %t %s
|
||||
// RUN: env LD_PRELOAD=%shared_libunwind %llvm_jitlink %t
|
||||
|
||||
extern "C" void llvm_jitlink_setTestResultOverride(long Value);
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
llvm_jitlink_setTestResultOverride(1);
|
||||
try {
|
||||
throw 0;
|
||||
} catch (int X) {
|
||||
llvm_jitlink_setTestResultOverride(X);
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -18,6 +18,11 @@ if config.host_os == 'Darwin':
|
|||
else:
|
||||
orc_rt_path = '%s/libclang_rt.orc%s.a' % (config.compiler_rt_libdir, config.target_suffix)
|
||||
|
||||
if config.libunwind_shared:
|
||||
config.available_features.add('libunwind-available')
|
||||
shared_libunwind_path = os.path.join(config.libunwind_install_dir, 'libunwind.so')
|
||||
config.substitutions.append( ("%shared_libunwind", shared_libunwind_path) )
|
||||
|
||||
config.substitutions.append(
|
||||
('%clang ', build_invocation([config.target_cflags])))
|
||||
config.substitutions.append(
|
||||
|
|
|
@ -6,6 +6,8 @@ config.orc_lit_source_dir = "@ORC_LIT_SOURCE_DIR@"
|
|||
config.target_cflags = "@ORC_TEST_TARGET_CFLAGS@"
|
||||
config.target_arch = "@ORC_TEST_TARGET_ARCH@"
|
||||
config.built_with_llvm = ("@COMPILER_RT_STANDALONE_BUILD@" != "TRUE")
|
||||
config.libunwind_shared = "@LIBUNWIND_ENABLE_SHARED@"
|
||||
config.libunwind_install_dir = "@LLVM_BINARY_DIR@/@LIBUNWIND_INSTALL_LIBRARY_DIR@"
|
||||
|
||||
# Load common config for all compiler-rt lit tests
|
||||
lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")
|
||||
|
|
|
@ -109,7 +109,8 @@ public:
|
|||
/// Returns an AliasMap containing the default aliases for the ELFNixPlatform.
|
||||
/// This can be modified by clients when constructing the platform to add
|
||||
/// or remove aliases.
|
||||
static SymbolAliasMap standardPlatformAliases(ExecutionSession &ES);
|
||||
static Expected<SymbolAliasMap> standardPlatformAliases(ExecutionSession &ES,
|
||||
JITDylib &PlatformJD);
|
||||
|
||||
/// Returns the array of required CXX aliases.
|
||||
static ArrayRef<std::pair<const char *, const char *>> requiredCXXAliases();
|
||||
|
|
|
@ -117,8 +117,12 @@ ELFNixPlatform::Create(ExecutionSession &ES,
|
|||
inconvertibleErrorCode());
|
||||
|
||||
// Create default aliases if the caller didn't supply any.
|
||||
if (!RuntimeAliases)
|
||||
RuntimeAliases = standardPlatformAliases(ES);
|
||||
if (!RuntimeAliases) {
|
||||
auto StandardRuntimeAliases = standardPlatformAliases(ES, PlatformJD);
|
||||
if (!StandardRuntimeAliases)
|
||||
return StandardRuntimeAliases.takeError();
|
||||
RuntimeAliases = std::move(*StandardRuntimeAliases);
|
||||
}
|
||||
|
||||
// Define the aliases.
|
||||
if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases))))
|
||||
|
@ -189,10 +193,53 @@ static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases,
|
|||
}
|
||||
}
|
||||
|
||||
SymbolAliasMap ELFNixPlatform::standardPlatformAliases(ExecutionSession &ES) {
|
||||
Expected<SymbolAliasMap>
|
||||
ELFNixPlatform::standardPlatformAliases(ExecutionSession &ES,
|
||||
JITDylib &PlatformJD) {
|
||||
SymbolAliasMap Aliases;
|
||||
addAliases(ES, Aliases, requiredCXXAliases());
|
||||
addAliases(ES, Aliases, standardRuntimeUtilityAliases());
|
||||
|
||||
// Determine whether or not the libunwind extended-API function for
|
||||
// dynamically registering an entire .eh_frame section is available.
|
||||
// If it is not, we assume that libgcc_s is being used, and alias to
|
||||
// its __register_frame with the same functionality.
|
||||
auto RTRegisterFrame = ES.intern("__orc_rt_register_eh_frame_section");
|
||||
auto LibUnwindRegisterFrame = ES.intern("__unw_add_dynamic_eh_frame_section");
|
||||
auto RTDeregisterFrame = ES.intern("__orc_rt_deregister_eh_frame_section");
|
||||
auto LibUnwindDeregisterFrame =
|
||||
ES.intern("__unw_remove_dynamic_eh_frame_section");
|
||||
auto SM = ES.lookup(makeJITDylibSearchOrder(&PlatformJD),
|
||||
SymbolLookupSet()
|
||||
.add(LibUnwindRegisterFrame,
|
||||
SymbolLookupFlags::WeaklyReferencedSymbol)
|
||||
.add(LibUnwindDeregisterFrame,
|
||||
SymbolLookupFlags::WeaklyReferencedSymbol));
|
||||
if (!SM) { // Weak-ref means no "missing symbol" errors, so this must be
|
||||
// something more serious that we should report.
|
||||
return SM.takeError();
|
||||
} else if (SM->size() == 2) {
|
||||
LLVM_DEBUG({
|
||||
dbgs() << "Using libunwind " << LibUnwindRegisterFrame
|
||||
<< " for unwind info registration\n";
|
||||
});
|
||||
Aliases[std::move(RTRegisterFrame)] = {LibUnwindRegisterFrame,
|
||||
JITSymbolFlags::Exported};
|
||||
Aliases[std::move(RTDeregisterFrame)] = {LibUnwindDeregisterFrame,
|
||||
JITSymbolFlags::Exported};
|
||||
} else {
|
||||
// Since LLVM libunwind is not present, we assume that unwinding
|
||||
// is provided by libgcc
|
||||
LLVM_DEBUG({
|
||||
dbgs() << "Using libgcc __register_frame"
|
||||
<< " for unwind info registration\n";
|
||||
});
|
||||
Aliases[std::move(RTRegisterFrame)] = {ES.intern("__register_frame"),
|
||||
JITSymbolFlags::Exported};
|
||||
Aliases[std::move(RTDeregisterFrame)] = {ES.intern("__deregister_frame"),
|
||||
JITSymbolFlags::Exported};
|
||||
}
|
||||
|
||||
return Aliases;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue