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/// Absolute path of \p module, or the running executable when null.
32std::string GetModulePath(HMODULE module) {
33 std::vector<WCHAR> buffer(MAX_PATH);
34 while (buffer.size() <= PATHCCH_MAX_CCH) {
35 DWORD len = ::GetModuleFileNameW(module, buffer.data(), buffer.size());
36 if (len == 0)
37 return "";
38 if (len < buffer.size()) {
39 std::string utf8;
40 if (llvm::convertWideToUTF8(std::wstring(buffer.data(), len), utf8))
41 return utf8;
42 return "";
43 }
44 if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
45 buffer.resize(buffer.size() * 2);
46 }
47 return "";
48}
49
50#ifdef LLDB_PYTHON_DLL_RELATIVE_PATH
51std::string ExeRelativeCandidate() {
52#ifdef LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME
53 std::string exe = GetModulePath(nullptr);
54 if (exe.empty())
55 return "";
56 llvm::SmallString<MAX_PATH> path(exe);
57 llvm::sys::path::remove_filename(path);
58 llvm::sys::path::append(path, LLDB_PYTHON_DLL_RELATIVE_PATH);
59 llvm::sys::path::append(path, LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME);
60 llvm::sys::fs::make_absolute(path);
61 return std::string(path);
62#else
63 return "";
64#endif
65}
66#endif
67
68} // namespace
69
71 llvm::function_ref<bool(const char *)> callback) {
72 // Mapping the DLL by base name first lets the plugin's delay-load thunks
73 // (which LoadLibrary by base name) resolve against the already-mapped
74 // module on first use, bypassing DLL search rules.
75#ifdef LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME
76 if (callback(LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME))
77 return;
78#endif
79
80#ifdef LLDB_PYTHON_DLL_RELATIVE_PATH
81 std::string exe_relative = ExeRelativeCandidate();
82 if (!exe_relative.empty() && callback(exe_relative.c_str()))
83 return;
84#endif
85}
86
87} // namespace lldb_private
88
89#endif // LLDB_ENABLE_PYTHON
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...