LLDB mainline
PythonRuntimeLoaderWindows.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "lldb/Host/Config.h"
10
11#if LLDB_ENABLE_PYTHON
12
15#include "llvm/ADT/STLFunctionalExtras.h"
16#include "llvm/ADT/SmallString.h"
17#include "llvm/ADT/SmallVector.h"
18#include "llvm/ADT/StringRef.h"
19#include "llvm/Support/ConvertUTF.h"
20#include "llvm/Support/FileSystem.h"
21#include "llvm/Support/Path.h"
22#include "llvm/Support/Windows/WindowsSupport.h"
23
24#include <pathcch.h>
25#include <string>
26
27namespace lldb_private {
28
29namespace {
30
31#ifdef LLDB_PYTHON_DLL_RELATIVE_PATH
32#ifdef LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME
33/// Absolute path of \p module, or the running executable when null.
34std::string GetModulePath(HMODULE module) {
35 std::vector<WCHAR> buffer(MAX_PATH);
36 while (buffer.size() <= PATHCCH_MAX_CCH) {
37 DWORD len = ::GetModuleFileNameW(module, buffer.data(), buffer.size());
38 if (len == 0)
39 return "";
40 if (len < buffer.size()) {
41 std::string utf8;
42 if (llvm::convertWideToUTF8(std::wstring(buffer.data(), len), utf8))
43 return utf8;
44 return "";
45 }
46 if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
47 buffer.resize(buffer.size() * 2);
48 }
49 return "";
50}
51#endif // ifdef LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME
52
53std::string ExeRelativeCandidate() {
54#ifdef LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME
55 std::string exe = GetModulePath(nullptr);
56 if (exe.empty())
57 return "";
58 llvm::SmallString<MAX_PATH> path(exe);
59 llvm::sys::path::remove_filename(path);
60 llvm::sys::path::append(path, LLDB_PYTHON_DLL_RELATIVE_PATH);
61 llvm::sys::path::append(path, LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME);
62 llvm::sys::fs::make_absolute(path);
63 return std::string(path);
64#else
65 return "";
66#endif // ifdef LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME
67}
68#endif // ifdef LLDB_PYTHON_DLL_RELATIVE_PATH
69
70} // namespace
71
73 llvm::function_ref<bool(const char *)> callback) {
74 // Mapping the DLL by base name first lets the plugin's delay-load thunks
75 // (which LoadLibrary by base name) resolve against the already-mapped
76 // module on first use, bypassing DLL search rules.
77#ifdef LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME
78 if (callback(LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME))
79 return;
80#endif
81
82#ifdef LLDB_PYTHON_DLL_RELATIVE_PATH
83 std::string exe_relative = ExeRelativeCandidate();
84 if (!exe_relative.empty() && callback(exe_relative.c_str()))
85 return;
86#endif
87}
88
89} // namespace lldb_private
90
91#endif // LLDB_ENABLE_PYTHON
#define PATHCCH_MAX_CCH
#define MAX_PATH
A class that represents a running process on the host machine.
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...