https://github.com/charles-zablit created https://github.com/llvm/llvm-project/pull/164893
This is a follow up to https://github.com/llvm/llvm-project/pull/162509. Using the `SearchPathW` API, we can ensure that the correct version of Python is installed before `liblldb` is loaded (and `python.dll` subsequently). If it's not, we try to add it to the search path with the methods introduced in https://github.com/llvm/llvm-project/pull/162509. If that fails or if that method is `#ifdef`'d out, we print an error which will appear before lldb crashes due to the missing dll. Before https://github.com/llvm/llvm-project/pull/162509, when invoked from Powershell, lldb would silently crash (no error message/crash report). After https://github.com/llvm/llvm-project/pull/162509, it crashes without any indications that the root cause is the missing python.dll. With this patch, we print the error before crashing. >From 3d2976b3e251bee88b9dee88fef0dcd9460dded2 Mon Sep 17 00:00:00 2001 From: Charles Zablit <[email protected]> Date: Thu, 23 Oct 2025 13:48:29 -0700 Subject: [PATCH] [lldb][windows] print an error if python.dll is not in the DLL search path --- lldb/CMakeLists.txt | 4 +++ lldb/tools/driver/CMakeLists.txt | 3 +++ lldb/tools/driver/Driver.cpp | 45 +++++++++++++++++++++++++------- 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/lldb/CMakeLists.txt b/lldb/CMakeLists.txt index e3b72e94d4beb..7c85c6fa8b825 100644 --- a/lldb/CMakeLists.txt +++ b/lldb/CMakeLists.txt @@ -61,6 +61,8 @@ if (LLDB_ENABLE_PYTHON) "Path to python interpreter exectuable, relative to python's install prefix") set(cachestring_LLDB_PYTHON_EXT_SUFFIX "Filename extension for native code python modules") + set(cachestring_LLDB_PYTHON_SHARED_LIBRARY_NAME + "Filename of Python's shared library") foreach(var LLDB_PYTHON_RELATIVE_PATH LLDB_PYTHON_EXE_RELATIVE_PATH LLDB_PYTHON_EXT_SUFFIX) if(NOT DEFINED ${var} AND NOT CMAKE_CROSSCOMPILING) @@ -87,6 +89,8 @@ if (LLDB_ENABLE_PYTHON) set(LLDB_PYTHON_EXT_SUFFIX "_d${LLDB_PYTHON_EXT_SUFFIX}") endif() endif() + set(LLDB_PYTHON_SHARED_LIBRARY_FILENAME + "python${Python3_VERSION_MAJOR}${Python3_VERSION_MINOR}${CMAKE_SHARED_LIBRARY_SUFFIX}") endif () if (LLDB_ENABLE_LUA) diff --git a/lldb/tools/driver/CMakeLists.txt b/lldb/tools/driver/CMakeLists.txt index 67956af7fe3fb..467ca9f91b3c1 100644 --- a/lldb/tools/driver/CMakeLists.txt +++ b/lldb/tools/driver/CMakeLists.txt @@ -37,6 +37,9 @@ add_dependencies(lldb if(DEFINED LLDB_PYTHON_DLL_RELATIVE_PATH) target_compile_definitions(lldb PRIVATE LLDB_PYTHON_DLL_RELATIVE_PATH="${LLDB_PYTHON_DLL_RELATIVE_PATH}") endif() +if(DEFINED LLDB_PYTHON_SHARED_LIBRARY_FILENAME) + target_compile_definitions(lldb PRIVATE LLDB_PYTHON_SHARED_LIBRARY_FILENAME="${LLDB_PYTHON_SHARED_LIBRARY_FILENAME}") +endif() if(LLDB_BUILD_FRAMEWORK) # In the build-tree, we know the exact path to the framework directory. diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp index ba0041111045b..96157525f3703 100644 --- a/lldb/tools/driver/Driver.cpp +++ b/lldb/tools/driver/Driver.cpp @@ -433,7 +433,8 @@ SBError Driver::ProcessArgs(const opt::InputArgList &args, bool &exiting) { return error; } -#if defined(_WIN32) && defined(LLDB_PYTHON_DLL_RELATIVE_PATH) +#ifdef _WIN32 +#ifdef LLDB_PYTHON_DLL_RELATIVE_PATH /// Returns the full path to the lldb.exe executable. inline std::wstring GetPathToExecutableW() { // Iterate until we reach the Windows API maximum path length (32,767). @@ -447,32 +448,51 @@ inline std::wstring GetPathToExecutableW() { return L""; } -/// Resolve the full path of the directory defined by +/// \brief Resolve the full path of the directory defined by /// LLDB_PYTHON_DLL_RELATIVE_PATH. If it exists, add it to the list of DLL /// search directories. -void AddPythonDLLToSearchPath() { +/// \return `true` if the library was added to the search path. +/// `false` otherwise. +bool AddPythonDLLToSearchPath() { std::wstring modulePath = GetPathToExecutableW(); if (modulePath.empty()) { - llvm::errs() << "error: unable to find python.dll." << '\n'; - return; + return false; } SmallVector<char, MAX_PATH> utf8Path; if (sys::windows::UTF16ToUTF8(modulePath.c_str(), modulePath.length(), utf8Path)) - return; + return false; sys::path::remove_filename(utf8Path); sys::path::append(utf8Path, LLDB_PYTHON_DLL_RELATIVE_PATH); sys::fs::make_absolute(utf8Path); SmallVector<wchar_t, 1> widePath; if (sys::windows::widenPath(utf8Path.data(), widePath)) - return; + return false; if (sys::fs::exists(utf8Path)) - SetDllDirectoryW(widePath.data()); + return SetDllDirectoryW(widePath.data()); + return false; +} +#endif + +#ifdef LLDB_PYTHON_SHARED_LIBRARY_FILENAME +/// Returns whether `python3x.dll` is in the DLL search path. +bool IsPythonDLLInPath() { +#define WIDEN2(x) L##x +#define WIDEN(x) WIDEN2(x) + WCHAR foundPath[MAX_PATH]; + DWORD result = + SearchPathW(nullptr, WIDEN(LLDB_PYTHON_SHARED_LIBRARY_FILENAME), nullptr, + MAX_PATH, foundPath, nullptr); +#undef WIDEN2 +#undef WIDEN + + return result > 0; } #endif +#endif std::string EscapeString(std::string arg) { std::string::size_type pos = 0; @@ -776,8 +796,13 @@ int main(int argc, char const *argv[]) { "~/Library/Logs/DiagnosticReports/.\n"); #endif -#if defined(_WIN32) && defined(LLDB_PYTHON_DLL_RELATIVE_PATH) - AddPythonDLLToSearchPath(); +#if defined(_WIN32) && defined(LLDB_PYTHON_SHARED_LIBRARY_FILENAME) + if (!IsPythonDLLInPath()) +#ifdef LLDB_PYTHON_DLL_RELATIVE_PATH + if (!AddPythonDLLToSearchPath()) +#endif + llvm::errs() << "error: unable to find " + << LLDB_PYTHON_SHARED_LIBRARY_FILENAME << ".\n"; #endif // Parse arguments. _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
