LLDB mainline
PythonRuntimeLoaderDarwin.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
14#include "llvm/ADT/STLFunctionalExtras.h"
15#include "llvm/ADT/SmallString.h"
16#include "llvm/ADT/StringRef.h"
17#include "llvm/ADT/Twine.h"
18#include "llvm/Support/FileSystem.h"
19#include "llvm/Support/Path.h"
20
21#include <dlfcn.h>
22
23namespace lldb_private {
24
25namespace {
26
27// Xcode and the Command Line Tools ship Python3.framework. Toolchains and
28// python.org ship Python.framework.
29constexpr llvm::StringLiteral kFrameworks[] = {
30 "Python3.framework/Versions/Current/Python3",
31 "Python.framework/Versions/Current/Python",
32};
33
34// The directories relative to LLDB.framework where Python(3).framework could be
35// present.
36constexpr llvm::StringLiteral kLLDBRelativeDirs[] = {
37 "../../../../../Developer/Library/Frameworks",
38 "../../../../Developer/Library/Frameworks",
39 "../../../../Frameworks",
40 "../../..",
41 "../../../../../../AppleInternal/Library/Frameworks",
42};
43
44/// Checks each Python framework in \p dir until one is found and \p callback
45/// returns true.
46bool TryFrameworks(llvm::function_ref<bool(const char *)> callback,
47 const llvm::Twine &dir) {
48 for (llvm::StringRef framework : kFrameworks) {
49 llvm::SmallString<256> path;
50 llvm::sys::path::append(path, dir, framework);
51 if (llvm::sys::fs::exists(path) && callback(path.c_str()))
52 return true;
53 }
54 return false;
55}
56
57} // namespace
58
60 llvm::function_ref<bool(const char *)> callback) {
61
62 // Prefer the Python relative to LLDB. Locate ourself with dladdr because the
63 // alterantive is HostInfo::GetShlibDir which must not run before plugins
64 // register their shared library directory helper.
65 Dl_info info;
66 if (::dladdr(reinterpret_cast<const void *>(&ForEachPythonRuntimeCandidate),
67 &info)) {
68 llvm::StringRef lldb_dir = llvm::sys::path::parent_path(info.dli_fname);
69 for (llvm::StringRef dir : kLLDBRelativeDirs)
70 if (TryFrameworks(callback, lldb_dir + "/" + dir))
71 return;
72 }
73
74 // Fall back to a Python from Python.org.
75 if (TryFrameworks(callback, "/Library/Frameworks"))
76 return;
77
78 // Finally, use a bare dlopen to load it from the dyld shared cache.
79 callback("libpython3.dylib");
80}
81
82} // namespace lldb_private
83
84#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...