From 8807d68aca042ea348ee1fb0f1ef6419c667dd6e Mon Sep 17 00:00:00 2001 From: Charles Zablit Date: Mon, 6 Oct 2025 16:30:14 +0100 Subject: [PATCH] [lldb][windows] delay loading python.dll --- lldb/cmake/modules/AddLLDB.cmake | 6 ++++ lldb/tools/driver/CMakeLists.txt | 4 +++ lldb/tools/driver/Driver.cpp | 61 ++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+) diff --git a/lldb/cmake/modules/AddLLDB.cmake b/lldb/cmake/modules/AddLLDB.cmake index c91b08f371112..d20145536a135 100644 --- a/lldb/cmake/modules/AddLLDB.cmake +++ b/lldb/cmake/modules/AddLLDB.cmake @@ -283,6 +283,12 @@ function(add_lldb_executable name) ) target_link_libraries(${name} PRIVATE ${ARG_LINK_LIBS}) + if(WIN32) + list(FIND ARG_LINK_LIBS liblldb LIBLLD_INDEX) + if(NOT LIBLLD_INDEX EQUAL -1) + target_link_options(${name} PRIVATE "/DELAYLOAD:$.dll") + endif() + endif() if(CLANG_LINK_CLANG_DYLIB) target_link_libraries(${name} PRIVATE clang-cpp) else() diff --git a/lldb/tools/driver/CMakeLists.txt b/lldb/tools/driver/CMakeLists.txt index cd304a047dea6..e393dc84792fc 100644 --- a/lldb/tools/driver/CMakeLists.txt +++ b/lldb/tools/driver/CMakeLists.txt @@ -28,6 +28,10 @@ add_dependencies(lldb ${tablegen_deps} ) +if(DEFINED Python3_VERSION) + target_compile_definitions(lldb PRIVATE Python3_VERSION=${Python3_VERSION}) +endif() + if(LLDB_BUILD_FRAMEWORK) # In the build-tree, we know the exact path to the framework directory. # The installed framework can be in different locations. diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp index 4f9a920e1136b..6a5e6afe819cd 100644 --- a/lldb/tools/driver/Driver.cpp +++ b/lldb/tools/driver/Driver.cpp @@ -20,7 +20,10 @@ #include "lldb/API/SBStructuredData.h" #include "lldb/Host/Config.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/Format.h" #include "llvm/Support/InitLLVM.h" #include "llvm/Support/Path.h" @@ -423,6 +426,60 @@ SBError Driver::ProcessArgs(const opt::InputArgList &args, bool &exiting) { return error; } +#ifdef _WIN32 +inline std::wstring GetPathToExecutableW() { + // Iterate until we max out the Windows max path length (256*2^7 > 32,767). + static const size_t maximumIterations = 7; + std::vector buffer; + DWORD bufferSize = MAX_PATH; + for (size_t i = 0; i < maximumIterations; i++) { + buffer.resize(bufferSize); + if (GetModuleFileNameW(NULL, buffer.data(), buffer.size()) < buffer.size()) + return std::wstring(buffer.begin(), buffer.end()); + bufferSize *= 2; + } + return L""; +} + +// Resolve the Embeddable Python directory bundled with the Swift toolchain. +// If it exists, add it to the list of DLL search directories. +// The installation of Embeddable Python is optional when installing the Swift +// toolchain, therefore the directory might not exist. +void AddPythonDLLToSearchPath() { + std::wstring modulePath = GetPathToExecutableW(); + if (modulePath.empty()) { + WithColor::error() << "Unable to find python: " << GetLastError() << '\n'; + return; + } + + SmallVector utf8Path; + if (sys::windows::UTF16ToUTF8(modulePath.c_str(), modulePath.length(), + utf8Path)) + return; + + SmallString pythonDir(utf8Path.begin(), utf8Path.end()); + // Python-${Version} is located in the Swift directory and lldb.exe is in: + // `Swift/Toolchains/x.x.x/usr/bin/lldb.exe`. + for (int i = 0; i < 5; i++) { + sys::path::remove_filename(pythonDir); + } +#define TO_STRING_IMPL(x) #x +#define TO_STRING(x) TO_STRING_IMPL(x) + std::string pythonDirName = "Python-" TO_STRING(Python3_VERSION); +#undef TO_STRING_IMPL +#undef TO_STRING + + sys::path::append(pythonDir, pythonDirName); + + SmallVector widePythonDir; + if (sys::windows::UTF8ToUTF16(pythonDir.str(), widePythonDir)) + return; + + if (sys::fs::exists(pythonDir)) + SetDllDirectoryW(widePythonDir.data()); +} +#endif + std::string EscapeString(std::string arg) { std::string::size_type pos = 0; while ((pos = arg.find_first_of("\"\\", pos)) != std::string::npos) { @@ -753,6 +810,10 @@ int main(int argc, char const *argv[]) { "~/Library/Logs/DiagnosticReports/.\n"); #endif +#ifdef _WIN32 + AddPythonDLLToSearchPath(); +#endif + // Parse arguments. LLDBOptTable T; unsigned MissingArgIndex;