Skip to content

Commit

Permalink
[ORC] Switch to singleton pattern for UnwindInfoManager. (llvm#126691)
Browse files Browse the repository at this point in the history
The find-dynamic-unwind-info callback registration APIs in libunwind
limit the number of callbacks that can be registered. If we use multiple
UnwindInfoManager instances, each with their own own callback function
(as was the case prior to this patch) we can quickly exceed this limit
(see llvm#126611).

This patch updates the UnwindInfoManager class to use a singleton
pattern, with the single instance shared between all LLVM JITs in the
process.

This change does _not_ apply to compact unwind info registered through
the ORC runtime (which currently installs its own callbacks).

As a bonus this change eliminates the need to load an IR "bouncer"
module to supply the unique callback for each instance, so support for
compact-unwind can be extended to the llvm-jitlink tools (which does not
support adding IR).
  • Loading branch information
lhames authored and alejandro-alvarez-sonarsource committed Feb 12, 2025
1 parent 612670f commit 58d9660
Show file tree
Hide file tree
Showing 10 changed files with 146 additions and 290 deletions.
4 changes: 0 additions & 4 deletions llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,6 @@ using SPSRunAsIntFunctionSignature = int32_t(shared::SPSExecutorAddr, int32_t);
} // end namespace rt

namespace rt_alt {
extern const char *UnwindInfoManagerInstanceName;
extern const char *UnwindInfoManagerFindSectionsHelperName;
extern const char *UnwindInfoManagerEnableWrapperName;
extern const char *UnwindInfoManagerDisableWrapperName;
extern const char *UnwindInfoManagerRegisterActionName;
extern const char *UnwindInfoManagerDeregisterActionName;
} // end namespace rt_alt
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,13 @@
#define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_UNWINDINFOMANAGER_H

#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
#include "llvm/ExecutionEngine/Orc/TargetProcess/ExecutorBootstrapService.h"
#include "llvm/Support/Error.h"
#include <map>
#include <mutex>

namespace llvm::orc {

class UnwindInfoManager : public ExecutorBootstrapService {
class UnwindInfoManager {
public:
// This struct's layout should match the unw_dynamic_unwind_sections struct
// from libunwind/src/libunwid_ext.h.
Expand All @@ -34,43 +33,40 @@ class UnwindInfoManager : public ExecutorBootstrapService {
size_t compact_unwind_section_length;
};

UnwindInfoManager(UnwindInfoManager &&) = delete;
UnwindInfoManager &operator=(UnwindInfoManager &&) = delete;
~UnwindInfoManager();

/// If the libunwind find-dynamic-unwind-info callback registration APIs are
/// available then this method will return an UnwindInfoManager instance,
/// otherwise it will return nullptr.
static std::unique_ptr<UnwindInfoManager> TryCreate();
/// available then this method will instantiate a global UnwindInfoManager
/// instance suitable for the process and return true. Otherwise it will
/// return false.
static bool TryEnable();

Error shutdown() override;
void addBootstrapSymbols(StringMap<ExecutorAddr> &M) override;
static void addBootstrapSymbols(StringMap<ExecutorAddr> &M);

Error enable(void *FindDynamicUnwindSections);
Error disable(void);
static Error registerSections(ArrayRef<orc::ExecutorAddrRange> CodeRanges,
orc::ExecutorAddr DSOBase,
orc::ExecutorAddrRange DWARFEHFrame,
orc::ExecutorAddrRange CompactUnwind);

Error registerSections(ArrayRef<orc::ExecutorAddrRange> CodeRanges,
orc::ExecutorAddr DSOBase,
orc::ExecutorAddrRange DWARFEHFrame,
orc::ExecutorAddrRange CompactUnwind);
static Error deregisterSections(ArrayRef<orc::ExecutorAddrRange> CodeRanges);

Error deregisterSections(ArrayRef<orc::ExecutorAddrRange> CodeRanges);
private:
UnwindInfoManager() = default;

int findSections(uintptr_t Addr, UnwindSections *Info);
int findSectionsImpl(uintptr_t Addr, UnwindSections *Info);
static int findSections(uintptr_t Addr, UnwindSections *Info);

private:
UnwindInfoManager(int (*AddFindDynamicUnwindSections)(void *),
int (*RemoveFindDynamicUnwindSections)(void *))
: AddFindDynamicUnwindSections(AddFindDynamicUnwindSections),
RemoveFindDynamicUnwindSections(RemoveFindDynamicUnwindSections) {}
Error registerSectionsImpl(ArrayRef<orc::ExecutorAddrRange> CodeRanges,
orc::ExecutorAddr DSOBase,
orc::ExecutorAddrRange DWARFEHFrame,
orc::ExecutorAddrRange CompactUnwind);

static int findSectionsHelper(UnwindInfoManager *Instance, uintptr_t Addr,
UnwindSections *Info);
Error deregisterSectionsImpl(ArrayRef<orc::ExecutorAddrRange> CodeRanges);

std::mutex M;
std::map<uintptr_t, UnwindSections> UWSecs;

int (*AddFindDynamicUnwindSections)(void *) = nullptr;
int (*RemoveFindDynamicUnwindSections)(void *) = nullptr;
void *FindDynamicUnwindSections = nullptr;

static const char *AddFnName, *RemoveFnName;
};

} // namespace llvm::orc
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,17 @@ namespace llvm::orc {

class UnwindInfoRegistrationPlugin : public LinkGraphLinkingLayer::Plugin {
public:
static Expected<std::shared_ptr<UnwindInfoRegistrationPlugin>>
Create(IRLayer &IRL, JITDylib &PlatformJD, ExecutorAddr Instance,
ExecutorAddr FindHelper, ExecutorAddr Enable, ExecutorAddr Disable,
ExecutorAddr Register, ExecutorAddr Deregister);
UnwindInfoRegistrationPlugin(ExecutionSession &ES, ExecutorAddr Register,
ExecutorAddr Deregister)
: ES(ES), Register(Register), Deregister(Deregister) {
DSOBaseName = ES.intern("__jitlink$libunwind_dso_base");
}

static Expected<std::shared_ptr<UnwindInfoRegistrationPlugin>>
Create(IRLayer &IRL, JITDylib &PlatformJD);
Create(ExecutionSession &ES, ExecutorAddr Register, ExecutorAddr Deregister);

~UnwindInfoRegistrationPlugin();
static Expected<std::shared_ptr<UnwindInfoRegistrationPlugin>>
Create(ExecutionSession &ES);

void modifyPassConfig(MaterializationResponsibility &MR,
jitlink::LinkGraph &G,
Expand All @@ -49,20 +51,11 @@ class UnwindInfoRegistrationPlugin : public LinkGraphLinkingLayer::Plugin {
ResourceKey SrcKey) override {}

private:
UnwindInfoRegistrationPlugin(ExecutionSession &ES, ExecutorAddr Instance,
ExecutorAddr Disable, ExecutorAddr Register,
ExecutorAddr Deregister)
: ES(ES), Instance(Instance), Disable(Disable), Register(Register),
Deregister(Deregister) {
DSOBaseName = ES.intern("__jitlink$libunwind_dso_base");
}

static Expected<ThreadSafeModule> makeBouncerModule(ExecutionSession &ES);
Error addUnwindInfoRegistrationActions(jitlink::LinkGraph &G);

ExecutionSession &ES;
SymbolStringPtr DSOBaseName;
ExecutorAddr Instance, Disable, Register, Deregister;
ExecutorAddr Register, Deregister;
};

} // namespace llvm::orc
Expand Down
5 changes: 2 additions & 3 deletions llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,8 @@ SelfExecutorProcessControl::SelfExecutorProcessControl(
// FIXME: Don't add an UnwindInfoManager by default -- it's redundant when
// the ORC runtime is loaded. We'll need a way to document this and
// allow clients to choose.
this->UnwindInfoMgr = UnwindInfoManager::TryCreate();
if (this->UnwindInfoMgr)
this->UnwindInfoMgr->addBootstrapSymbols(this->BootstrapSymbols);
if (UnwindInfoManager::TryEnable())
UnwindInfoManager::addBootstrapSymbols(this->BootstrapSymbols);
#endif // __APPLE__
}

Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1241,8 +1241,8 @@ Expected<JITDylibSP> setUpGenericLLVMIRPlatform(LLJIT &J) {

// If UseEHFrames hasn't been set then we're good to use compact-unwind.
if (!UseEHFrames) {
if (auto UIRP = UnwindInfoRegistrationPlugin::Create(
J.getIRCompileLayer(), PlatformJD)) {
if (auto UIRP =
UnwindInfoRegistrationPlugin::Create(J.getExecutionSession())) {
OLL->addPlugin(std::move(*UIRP));
LLVM_DEBUG(dbgs() << "Enabled compact-unwind support.\n");
} else
Expand Down
8 changes: 0 additions & 8 deletions llvm/lib/ExecutionEngine/Orc/Shared/OrcRTBridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,6 @@ const char *RunAsIntFunctionWrapperName =

} // end namespace rt
namespace rt_alt {
const char *UnwindInfoManagerInstanceName =
"orc_rt_alt_UnwindInfoManager_Instance";
const char *UnwindInfoManagerFindSectionsHelperName =
"orc_rt_alt_UnwindInfoManager_findSectionsHelper";
const char *UnwindInfoManagerEnableWrapperName =
"orc_rt_alt_UnwindInfoManager_enable";
const char *UnwindInfoManagerDisableWrapperName =
"orc_rt_alt_UnwindInfoManager_disable";
const char *UnwindInfoManagerRegisterActionName =
"orc_rt_alt_UnwindInfoManager_register";
const char *UnwindInfoManagerDeregisterActionName =
Expand Down
Loading

0 comments on commit 58d9660

Please sign in to comment.