9#include "lldb/Host/Config.h"
15#include "llvm/ADT/SmallString.h"
16#include "llvm/Support/DynamicLibrary.h"
17#include "llvm/Support/ErrorExtras.h"
18#include "llvm/Support/Path.h"
19#include "llvm/Support/Threading.h"
27#include "llvm/Support/Windows/WindowsSupport.h"
37#ifndef LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
38#define LOAD_LIBRARY_SEARCH_DEFAULT_DIRS 0x00001000
41using SetDefaultDllDirectoriesFn = BOOL(WINAPI *)(DWORD);
42using AddDllDirectoryFn = PVOID(WINAPI *)(PCWSTR);
46void RegisterDllSearchDirectory(llvm::StringRef path) {
47 llvm::StringRef dir = llvm::sys::path::parent_path(path);
53 if (!add_dll_directory)
56 static llvm::once_flag opt_in_once;
57 llvm::call_once(opt_in_once, [] {
59 L
"Kernel32.dll",
"SetDefaultDllDirectories"};
60 if (set_default_dll_directories)
61 (*set_default_dll_directories)(LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
64 llvm::SmallVector<wchar_t, MAX_PATH> wide_dir;
65 if (llvm::sys::windows::widenPath(dir, wide_dir))
67 (*add_dll_directory)(wide_dir.data());
75bool IsPythonAlreadyLoaded() {
77 HMODULE main = ::GetModuleHandleW(
nullptr);
78 return ::GetProcAddress(main,
"Py_IsInitialized") !=
nullptr &&
79 ::GetProcAddress(main,
"Py_InitializeFromConfig") !=
nullptr;
81 return ::dlsym(RTLD_DEFAULT,
"Py_IsInitialized") !=
nullptr &&
82 ::dlsym(RTLD_DEFAULT,
"Py_InitializeFromConfig") !=
nullptr;
86llvm::Error TryLoad(
const char *path) {
88 RegisterDllSearchDirectory(path);
91 llvm::sys::DynamicLibrary lib =
92 llvm::sys::DynamicLibrary::getPermanentLibrary(path, &err_msg);
94 return llvm::createStringErrorV(
"could not load '{0}': {1}", path, err_msg);
98 if (!lib.getAddressOfSymbol(
"Py_IsInitialized"))
99 return llvm::createStringErrorV(
100 "'{0}' does not export Py_IsInitialized; not a Python runtime", path);
102 return llvm::Error::success();
105llvm::Expected<std::string> LoadPythonRuntime() {
106 if (IsPythonAlreadyLoaded())
107 return std::string();
109 llvm::Error failures =
110 llvm::createStringError(
"could not locate the Python runtime library");
113 auto try_path = [&](
const char *path) ->
bool {
114 if (llvm::Error err = TryLoad(path)) {
115 failures = llvm::joinErrors(std::move(failures), std::move(err));
122 if (
const char *override_path = std::getenv(
"LLDB_PYTHON_LIBRARY");
123 override_path && *override_path) {
124 if (try_path(override_path)) {
125 consumeError(std::move(failures));
130#ifdef LLDB_PYTHON_RUNTIME_LIBRARY_BUILD_PATH
133 if (try_path(LLDB_PYTHON_RUNTIME_LIBRARY_BUILD_PATH)) {
134 consumeError(std::move(failures));
141 [&](
const char *candidate) {
return found = try_path(candidate); });
144 consumeError(std::move(failures));
147 return std::move(failures);
152 llvm::Error
Load()
override {
154 if (m_error_message.empty())
155 return llvm::Error::success();
156 return llvm::createStringError(m_error_message);
159 llvm::Expected<llvm::StringRef> GetLoadedPath()
override {
161 if (!m_error_message.empty())
162 return llvm::createStringError(m_error_message);
163 return llvm::StringRef(m_path);
166 bool IsLoaded()
override {
return IsPythonAlreadyLoaded(); }
169 void EnsureLoaded() {
170 llvm::call_once(m_once, [
this] {
171 if (llvm::Expected<std::string> result = LoadPythonRuntime()) {
172 m_path = std::move(*result);
179 llvm::SmallString<256> stable_abi_path(m_path);
180 llvm::sys::path::remove_filename(stable_abi_path);
181#if defined(__MINGW32__)
182 llvm::sys::path::append(stable_abi_path,
"libpython3.dll");
184 llvm::sys::path::append(stable_abi_path,
"python3.dll");
187 llvm::sys::DynamicLibrary::getPermanentLibrary(stable_abi_path.c_str(),
191 m_error_message = llvm::toString(result.takeError());
198 llvm::once_flag m_once;
200 std::string m_error_message;
205llvm::Expected<ScriptInterpreterRuntimeLoader &>
209 static PythonRuntimeLoader instance;
215 return llvm::createStringError(
216 "no runtime loader for the requested script language");
218 llvm_unreachable(
"unhandled ScriptLanguage");
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Loads a script-interpreter runtime into the current process before its plugin is dlopened.
static llvm::Expected< ScriptInterpreterRuntimeLoader & > Get(lldb::ScriptLanguage language)
Returns the loader for language.
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
void ForEachPythonRuntimeCandidate(llvm::function_ref< bool(const char *)> callback)
Visits candidate Python runtime paths in priority order, stopping at the first call that returns true...
static std::enable_if_t< is_load< I >, bool > Load(EmulateInstructionRISCV &emulator, I inst, uint64_t(*extend)(E))
ScriptLanguage
Script interpreter types.