Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions lldb/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@ if (LLDB_ENABLE_PYTHON)
set(LLDB_PYTHON_EXT_SUFFIX "_d${LLDB_PYTHON_EXT_SUFFIX}")
endif()
endif()
if(TARGET Python3::Python)
get_target_property(_Python3_LIB_PATH Python3::Python IMPORTED_LIBRARY_LOCATION)
if(_Python3_LIB_PATH)
get_filename_component(LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME "${_Python3_LIB_PATH}" NAME)
endif()
endif()
endif ()

if (LLDB_ENABLE_LUA)
Expand Down
6 changes: 6 additions & 0 deletions lldb/cmake/modules/AddLLDB.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,12 @@ function(add_lldb_executable name)
)

target_link_libraries(${name} PRIVATE ${ARG_LINK_LIBS})
if(WIN32)
list(FIND ARG_LINK_LIBS liblldb LIBLLDB_INDEX)
if(NOT LIBLLDB_INDEX EQUAL -1)
target_link_options(${name} PRIVATE "/DELAYLOAD:$<TARGET_FILE_BASE_NAME:liblldb>.dll")
endif()
endif()
if(CLANG_LINK_CLANG_DYLIB)
target_link_libraries(${name} PRIVATE clang-cpp)
else()
Expand Down
7 changes: 7 additions & 0 deletions lldb/tools/driver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ add_dependencies(lldb
${tablegen_deps}
)

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_RUNTIME_LIBRARY_FILENAME)
target_compile_definitions(lldb PRIVATE LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME="${LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME}")
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.
Expand Down
96 changes: 96 additions & 0 deletions lldb/tools/driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,21 @@
#include "lldb/Host/MainLoop.h"
#include "lldb/Host/MainLoopBase.h"
#include "lldb/Utility/Status.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"
#include "llvm/Support/Signals.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"

#ifdef _WIN32
#include "llvm/Support/Windows/WindowsSupport.h"
#endif

#include <algorithm>
#include <atomic>
#include <bitset>
Expand Down Expand Up @@ -436,6 +443,91 @@ SBError Driver::ProcessArgs(const opt::InputArgList &args, bool &exiting) {
return error;
}

#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).
std::vector<WCHAR> buffer;
buffer.resize(MAX_PATH /*=260*/);
while (buffer.size() < 32767) {
if (GetModuleFileNameW(NULL, buffer.data(), buffer.size()) < buffer.size())
return std::wstring(buffer.begin(), buffer.end());
buffer.resize(buffer.size() * 2);
}
return L"";
}

/// \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.
/// \return `true` if the library was added to the search path.
/// `false` otherwise.
bool AddPythonDLLToSearchPath() {
std::wstring modulePath = GetPathToExecutableW();
if (modulePath.empty())
return false;

SmallVector<char, MAX_PATH> utf8Path;
if (sys::windows::UTF16ToUTF8(modulePath.c_str(), modulePath.length(),
utf8Path))
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 false;

if (sys::fs::exists(utf8Path))
return SetDllDirectoryW(widePath.data());
return false;
}
#endif

#ifdef LLDB_PYTHON_RUNTIME_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_RUNTIME_LIBRARY_FILENAME), nullptr,
MAX_PATH, foundPath, nullptr);
#undef WIDEN2
#undef WIDEN

return result > 0;
}
#endif

/// Try to setup the DLL search path for the Python Runtime Library
/// (python3xx.dll).
///
/// If `LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME` is set, we first check if
/// python3xx.dll is in the search path. If it's not, we try to add it and
/// check for it a second time.
/// If only `LLDB_PYTHON_DLL_RELATIVE_PATH` is set, we try to add python3xx.dll
/// to the search path python.dll is already in the search path or not.
void SetupPythonRuntimeLibrary() {
#ifdef LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME
if (IsPythonDLLInPath())
return;
#ifdef LLDB_PYTHON_DLL_RELATIVE_PATH
if (AddPythonDLLToSearchPath() && IsPythonDLLInPath())
return;
#endif
llvm::errs() << "error: unable to find '"
<< LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME << "'.\n";
return;
#elif defined(LLDB_PYTHON_DLL_RELATIVE_PATH)
if (!AddPythonDLLToSearchPath())
llvm::errs() << "error: unable to find the Python runtime library.\n";
#endif
}
#endif

std::string EscapeString(std::string arg) {
std::string::size_type pos = 0;
while ((pos = arg.find_first_of("\"\\", pos)) != std::string::npos) {
Expand Down Expand Up @@ -738,6 +830,10 @@ int main(int argc, char const *argv[]) {
"~/Library/Logs/DiagnosticReports/.\n");
#endif

#ifdef _WIN32
SetupPythonRuntimeLibrary();
#endif

// Parse arguments.
LLDBOptTable T;
unsigned MissingArgIndex;
Expand Down