|
22 | 22 | #include "lldb/Host/MainLoop.h" |
23 | 23 | #include "lldb/Host/MainLoopBase.h" |
24 | 24 | #include "lldb/Utility/Status.h" |
| 25 | +#include "llvm/ADT/SmallString.h" |
25 | 26 | #include "llvm/ADT/StringRef.h" |
| 27 | +#include "llvm/Support/ConvertUTF.h" |
| 28 | +#include "llvm/Support/FileSystem.h" |
26 | 29 | #include "llvm/Support/Format.h" |
27 | 30 | #include "llvm/Support/InitLLVM.h" |
28 | 31 | #include "llvm/Support/Path.h" |
29 | 32 | #include "llvm/Support/Signals.h" |
30 | 33 | #include "llvm/Support/WithColor.h" |
31 | 34 | #include "llvm/Support/raw_ostream.h" |
32 | 35 |
|
| 36 | +#ifdef _WIN32 |
| 37 | +#include "llvm/Support/Windows/WindowsSupport.h" |
| 38 | +#endif |
| 39 | + |
33 | 40 | #include <algorithm> |
34 | 41 | #include <atomic> |
35 | 42 | #include <bitset> |
@@ -436,6 +443,91 @@ SBError Driver::ProcessArgs(const opt::InputArgList &args, bool &exiting) { |
436 | 443 | return error; |
437 | 444 | } |
438 | 445 |
|
| 446 | +#ifdef _WIN32 |
| 447 | +#ifdef LLDB_PYTHON_DLL_RELATIVE_PATH |
| 448 | +/// Returns the full path to the lldb.exe executable. |
| 449 | +inline std::wstring GetPathToExecutableW() { |
| 450 | + // Iterate until we reach the Windows API maximum path length (32,767). |
| 451 | + std::vector<WCHAR> buffer; |
| 452 | + buffer.resize(MAX_PATH /*=260*/); |
| 453 | + while (buffer.size() < 32767) { |
| 454 | + if (GetModuleFileNameW(NULL, buffer.data(), buffer.size()) < buffer.size()) |
| 455 | + return std::wstring(buffer.begin(), buffer.end()); |
| 456 | + buffer.resize(buffer.size() * 2); |
| 457 | + } |
| 458 | + return L""; |
| 459 | +} |
| 460 | + |
| 461 | +/// \brief Resolve the full path of the directory defined by |
| 462 | +/// LLDB_PYTHON_DLL_RELATIVE_PATH. If it exists, add it to the list of DLL |
| 463 | +/// search directories. |
| 464 | +/// \return `true` if the library was added to the search path. |
| 465 | +/// `false` otherwise. |
| 466 | +bool AddPythonDLLToSearchPath() { |
| 467 | + std::wstring modulePath = GetPathToExecutableW(); |
| 468 | + if (modulePath.empty()) |
| 469 | + return false; |
| 470 | + |
| 471 | + SmallVector<char, MAX_PATH> utf8Path; |
| 472 | + if (sys::windows::UTF16ToUTF8(modulePath.c_str(), modulePath.length(), |
| 473 | + utf8Path)) |
| 474 | + return false; |
| 475 | + sys::path::remove_filename(utf8Path); |
| 476 | + sys::path::append(utf8Path, LLDB_PYTHON_DLL_RELATIVE_PATH); |
| 477 | + sys::fs::make_absolute(utf8Path); |
| 478 | + |
| 479 | + SmallVector<wchar_t, 1> widePath; |
| 480 | + if (sys::windows::widenPath(utf8Path.data(), widePath)) |
| 481 | + return false; |
| 482 | + |
| 483 | + if (sys::fs::exists(utf8Path)) |
| 484 | + return SetDllDirectoryW(widePath.data()); |
| 485 | + return false; |
| 486 | +} |
| 487 | +#endif |
| 488 | + |
| 489 | +#ifdef LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME |
| 490 | +/// Returns whether `python3x.dll` is in the DLL search path. |
| 491 | +bool IsPythonDLLInPath() { |
| 492 | +#define WIDEN2(x) L##x |
| 493 | +#define WIDEN(x) WIDEN2(x) |
| 494 | + WCHAR foundPath[MAX_PATH]; |
| 495 | + DWORD result = |
| 496 | + SearchPathW(nullptr, WIDEN(LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME), nullptr, |
| 497 | + MAX_PATH, foundPath, nullptr); |
| 498 | +#undef WIDEN2 |
| 499 | +#undef WIDEN |
| 500 | + |
| 501 | + return result > 0; |
| 502 | +} |
| 503 | +#endif |
| 504 | + |
| 505 | +/// Try to setup the DLL search path for the Python Runtime Library |
| 506 | +/// (python3xx.dll). |
| 507 | +/// |
| 508 | +/// If `LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME` is set, we first check if |
| 509 | +/// python3xx.dll is in the search path. If it's not, we try to add it and |
| 510 | +/// check for it a second time. |
| 511 | +/// If only `LLDB_PYTHON_DLL_RELATIVE_PATH` is set, we try to add python3xx.dll |
| 512 | +/// to the search path python.dll is already in the search path or not. |
| 513 | +void SetupPythonRuntimeLibrary() { |
| 514 | +#ifdef LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME |
| 515 | + if (IsPythonDLLInPath()) |
| 516 | + return; |
| 517 | +#ifdef LLDB_PYTHON_DLL_RELATIVE_PATH |
| 518 | + if (AddPythonDLLToSearchPath() && IsPythonDLLInPath()) |
| 519 | + return; |
| 520 | +#endif |
| 521 | + llvm::errs() << "error: unable to find '" |
| 522 | + << LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME << "'.\n"; |
| 523 | + return; |
| 524 | +#elif defined(LLDB_PYTHON_DLL_RELATIVE_PATH) |
| 525 | + if (!AddPythonDLLToSearchPath()) |
| 526 | + llvm::errs() << "error: unable to find the Python runtime library.\n"; |
| 527 | +#endif |
| 528 | +} |
| 529 | +#endif |
| 530 | + |
439 | 531 | std::string EscapeString(std::string arg) { |
440 | 532 | std::string::size_type pos = 0; |
441 | 533 | while ((pos = arg.find_first_of("\"\\", pos)) != std::string::npos) { |
@@ -738,6 +830,10 @@ int main(int argc, char const *argv[]) { |
738 | 830 | "~/Library/Logs/DiagnosticReports/.\n"); |
739 | 831 | #endif |
740 | 832 |
|
| 833 | +#ifdef _WIN32 |
| 834 | + SetupPythonRuntimeLibrary(); |
| 835 | +#endif |
| 836 | + |
741 | 837 | // Parse arguments. |
742 | 838 | LLDBOptTable T; |
743 | 839 | unsigned MissingArgIndex; |
|
0 commit comments