LLDB mainline
HostInfoBase.cpp
Go to the documentation of this file.
1//===-- HostInfoBase.cpp --------------------------------------------------===//
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
12#include "lldb/Host/Host.h"
13#include "lldb/Host/HostInfo.h"
17#include "lldb/Utility/Log.h"
19
20#include "llvm/ADT/StringExtras.h"
21#include "llvm/Support/Path.h"
22#include "llvm/Support/ScopedPrinter.h"
23#include "llvm/Support/Threading.h"
24#include "llvm/Support/raw_ostream.h"
25#include "llvm/TargetParser/Host.h"
26#include "llvm/TargetParser/Triple.h"
27
28#include <mutex>
29#include <optional>
30#include <thread>
31
32using namespace lldb;
33using namespace lldb_private;
34
35namespace {
36/// Contains the state of the HostInfoBase plugin.
37struct HostInfoBaseFields {
38 ~HostInfoBaseFields() {
39 if (FileSystem::Instance().Exists(m_lldb_process_tmp_dir)) {
40 // Remove the LLDB temporary directory if we have one. Set "recurse" to
41 // true to all files that were created for the LLDB process can be
42 // cleaned up.
43 llvm::sys::fs::remove_directories(m_lldb_process_tmp_dir.GetPath());
44 }
45 }
46
47 llvm::once_flag m_host_triple_once;
48 llvm::Triple m_host_triple;
49
50 llvm::once_flag m_host_arch_once;
51 ArchSpec m_host_arch_32;
52 ArchSpec m_host_arch_64;
53
54 llvm::once_flag m_lldb_so_dir_once;
55 FileSpec m_lldb_so_dir;
56 llvm::once_flag m_lldb_support_exe_dir_once;
57 FileSpec m_lldb_support_exe_dir;
58 llvm::once_flag m_lldb_headers_dir_once;
59 FileSpec m_lldb_headers_dir;
60 llvm::once_flag m_lldb_clang_resource_dir_once;
61 FileSpec m_lldb_clang_resource_dir;
62 llvm::once_flag m_lldb_system_plugin_dir_once;
63 FileSpec m_lldb_system_plugin_dir;
64 llvm::once_flag m_lldb_user_home_dir_once;
65 FileSpec m_lldb_user_home_dir;
66 llvm::once_flag m_lldb_user_lldb_dir_once;
67 FileSpec m_lldb_user_lldb_dir;
68 llvm::once_flag m_lldb_user_plugin_dir_once;
69 FileSpec m_lldb_user_plugin_dir;
70 llvm::once_flag m_lldb_process_tmp_dir_once;
71 FileSpec m_lldb_process_tmp_dir;
72 llvm::once_flag m_lldb_global_tmp_dir_once;
73 FileSpec m_lldb_global_tmp_dir;
74};
75} // namespace
76
77static HostInfoBaseFields *g_fields = nullptr;
79
81 g_shlib_dir_helper = helper;
82 g_fields = new HostInfoBaseFields();
84}
85
88 g_shlib_dir_helper = nullptr;
89 delete g_fields;
90 g_fields = nullptr;
91}
92
94 llvm::call_once(g_fields->m_host_triple_once, []() {
95 g_fields->m_host_triple = HostInfo::GetArchitecture().GetTriple();
96 });
97 return g_fields->m_host_triple;
98}
99
101 llvm::call_once(g_fields->m_host_arch_once, []() {
102 HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32,
103 g_fields->m_host_arch_64);
104 });
105
106 // If an explicit 32 or 64-bit architecture was requested, return that.
107 if (arch_kind == eArchKind32)
108 return g_fields->m_host_arch_32;
109 if (arch_kind == eArchKind64)
110 return g_fields->m_host_arch_64;
111
112 // Otherwise prefer the 64-bit architecture if it is valid.
113 return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64
114 : g_fields->m_host_arch_32;
115}
116
117std::optional<HostInfoBase::ArchitectureKind>
119 return llvm::StringSwitch<std::optional<ArchitectureKind>>(kind)
123 .Default(std::nullopt);
124}
125
127 llvm::call_once(g_fields->m_lldb_so_dir_once, []() {
128 if (!HostInfo::ComputeSharedLibraryDirectory(g_fields->m_lldb_so_dir))
129 g_fields->m_lldb_so_dir = FileSpec();
130 Log *log = GetLog(LLDBLog::Host);
131 LLDB_LOG(log, "shlib dir -> `{0}`", g_fields->m_lldb_so_dir);
132 });
133 return g_fields->m_lldb_so_dir;
134}
135
137 llvm::call_once(g_fields->m_lldb_support_exe_dir_once, []() {
138 if (!HostInfo::ComputeSupportExeDirectory(g_fields->m_lldb_support_exe_dir))
139 g_fields->m_lldb_support_exe_dir = FileSpec();
140 Log *log = GetLog(LLDBLog::Host);
141 LLDB_LOG(log, "support exe dir -> `{0}`", g_fields->m_lldb_support_exe_dir);
142 });
143 return g_fields->m_lldb_support_exe_dir;
144}
145
147 llvm::call_once(g_fields->m_lldb_headers_dir_once, []() {
148 if (!HostInfo::ComputeHeaderDirectory(g_fields->m_lldb_headers_dir))
149 g_fields->m_lldb_headers_dir = FileSpec();
150 Log *log = GetLog(LLDBLog::Host);
151 LLDB_LOG(log, "header dir -> `{0}`", g_fields->m_lldb_headers_dir);
152 });
153 return g_fields->m_lldb_headers_dir;
154}
155
157 llvm::call_once(g_fields->m_lldb_system_plugin_dir_once, []() {
158 if (!HostInfo::ComputeSystemPluginsDirectory(
159 g_fields->m_lldb_system_plugin_dir))
160 g_fields->m_lldb_system_plugin_dir = FileSpec();
161 Log *log = GetLog(LLDBLog::Host);
162 LLDB_LOG(log, "system plugin dir -> `{0}`",
163 g_fields->m_lldb_system_plugin_dir);
164 });
165 return g_fields->m_lldb_system_plugin_dir;
166}
167
169 llvm::call_once(g_fields->m_lldb_user_home_dir_once, []() {
170 if (!HostInfo::ComputeUserHomeDirectory(g_fields->m_lldb_user_home_dir))
171 g_fields->m_lldb_user_home_dir = FileSpec();
172 LLDB_LOG(GetLog(LLDBLog::Host), "user home dir -> `{0}`",
173 g_fields->m_lldb_user_home_dir);
174 });
175 return g_fields->m_lldb_user_home_dir;
176}
177
179 llvm::call_once(g_fields->m_lldb_user_lldb_dir_once, []() {
180 if (!HostInfo::ComputeUserLLDBHomeDirectory(g_fields->m_lldb_user_lldb_dir))
181 g_fields->m_lldb_user_lldb_dir = FileSpec();
182 LLDB_LOG(GetLog(LLDBLog::Host), "user lldb home dir -> `{0}`",
183 g_fields->m_lldb_user_lldb_dir);
184 });
185 return g_fields->m_lldb_user_lldb_dir;
186}
187
189 llvm::call_once(g_fields->m_lldb_user_plugin_dir_once, []() {
190 if (!HostInfo::ComputeUserPluginsDirectory(
191 g_fields->m_lldb_user_plugin_dir))
192 g_fields->m_lldb_user_plugin_dir = FileSpec();
193 Log *log = GetLog(LLDBLog::Host);
194 LLDB_LOG(log, "user plugin dir -> `{0}`", g_fields->m_lldb_user_plugin_dir);
195 });
196 return g_fields->m_lldb_user_plugin_dir;
197}
198
200 llvm::call_once(g_fields->m_lldb_process_tmp_dir_once, []() {
201 if (!HostInfo::ComputeProcessTempFileDirectory(
202 g_fields->m_lldb_process_tmp_dir))
203 g_fields->m_lldb_process_tmp_dir = FileSpec();
204 Log *log = GetLog(LLDBLog::Host);
205 LLDB_LOG(log, "process temp dir -> `{0}`",
206 g_fields->m_lldb_process_tmp_dir);
207 });
208 return g_fields->m_lldb_process_tmp_dir;
209}
210
212 llvm::call_once(g_fields->m_lldb_global_tmp_dir_once, []() {
213 if (!HostInfo::ComputeGlobalTempFileDirectory(
214 g_fields->m_lldb_global_tmp_dir))
215 g_fields->m_lldb_global_tmp_dir = FileSpec();
216
217 Log *log = GetLog(LLDBLog::Host);
218 LLDB_LOG(log, "global temp dir -> `{0}`", g_fields->m_lldb_global_tmp_dir);
219 });
220 return g_fields->m_lldb_global_tmp_dir;
221}
222
224 if (triple.empty())
225 return ArchSpec();
226 llvm::Triple normalized_triple(llvm::Triple::normalize(triple));
227 if (!ArchSpec::ContainsOnlyArch(normalized_triple))
228 return ArchSpec(triple);
229
230 if (auto kind = HostInfo::ParseArchitectureKind(triple))
231 return HostInfo::GetArchitecture(*kind);
232
233 llvm::Triple host_triple(llvm::sys::getDefaultTargetTriple());
234
235 if (normalized_triple.getVendorName().empty())
236 normalized_triple.setVendor(host_triple.getVendor());
237 if (normalized_triple.getOSName().empty())
238 normalized_triple.setOS(host_triple.getOS());
239 if (normalized_triple.getEnvironmentName().empty() &&
240 !host_triple.getEnvironmentName().empty())
241 normalized_triple.setEnvironment(host_triple.getEnvironment());
242 return ArchSpec(normalized_triple);
243}
244
246 llvm::StringRef dir) {
247 Log *log = GetLog(LLDBLog::Host);
248
249 FileSpec lldb_file_spec = GetShlibDir();
250 if (!lldb_file_spec)
251 return false;
252
253 std::string raw_path = lldb_file_spec.GetPath();
254 LLDB_LOG(
255 log,
256 "Attempting to derive the path {0} relative to liblldb install path: {1}",
257 dir, raw_path);
258
259 // Drop bin (windows) or lib
260 llvm::StringRef parent_path = llvm::sys::path::parent_path(raw_path);
261 if (parent_path.empty()) {
262 LLDB_LOG(log, "Failed to find liblldb within the shared lib path");
263 return false;
264 }
265
266 raw_path = (parent_path + dir).str();
267 LLDB_LOG(log, "Derived the path as: {0}", raw_path);
268 file_spec.SetDirectory(raw_path);
269 return (bool)file_spec.GetDirectory();
270}
271
273 // To get paths related to LLDB we get the path to the executable that
274 // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB".
275 // On other posix systems, we will get .../lib(64|32)?/liblldb.so.
276
278 reinterpret_cast<void *>(HostInfoBase::ComputeSharedLibraryDirectory)));
279
281 g_shlib_dir_helper(lldb_file_spec);
282
283 // Remove the filename so that this FileSpec only represents the directory.
284 file_spec.SetDirectory(lldb_file_spec.GetDirectory());
285
286 return (bool)file_spec.GetDirectory();
287}
288
290 file_spec = GetShlibDir();
291 return bool(file_spec);
292}
293
295 FileSpec temp_file_spec;
296 if (!HostInfo::ComputeGlobalTempFileDirectory(temp_file_spec))
297 return false;
298
299 std::string pid_str{llvm::to_string(Host::GetCurrentProcessID())};
300 temp_file_spec.AppendPathComponent(pid_str);
301 if (llvm::sys::fs::create_directory(temp_file_spec.GetPath()))
302 return false;
303
304 file_spec.SetDirectory(temp_file_spec.GetPathAsConstString());
305 return true;
306}
307
309 llvm::SmallVector<char, 16> tmpdir;
310 llvm::sys::path::system_temp_directory(/*ErasedOnReboot*/ true, tmpdir);
311 file_spec = FileSpec(std::string(tmpdir.data(), tmpdir.size()));
312 FileSystem::Instance().Resolve(file_spec);
313 return true;
314}
315
317 file_spec.Clear();
318
319 FileSpec temp_file_spec;
320 if (!HostInfo::ComputeTempFileBaseDirectory(temp_file_spec))
321 return false;
322
323 temp_file_spec.AppendPathComponent("lldb");
324 if (llvm::sys::fs::create_directory(temp_file_spec.GetPath()))
325 return false;
326
327 file_spec.SetDirectory(temp_file_spec.GetPathAsConstString());
328 return true;
329}
330
332 // TODO(zturner): Figure out how to compute the header directory for all
333 // platforms.
334 return false;
335}
336
338 // TODO(zturner): Figure out how to compute the system plugins directory for
339 // all platforms.
340 return false;
341}
342
344 FileSpec temp_file("~");
345 FileSystem::Instance().Resolve(temp_file);
346 file_spec.SetDirectory(temp_file.GetPathAsConstString());
347 return true;
348}
349
351 FileSpec home_dir_spec = GetUserHomeDir();
352 home_dir_spec.AppendPathComponent(".lldb");
353 file_spec.SetDirectory(home_dir_spec.GetPathAsConstString());
354 return true;
355}
356
358 // TODO(zturner): Figure out how to compute the user plugins directory for
359 // all platforms.
360 return false;
361}
362
364 ArchSpec &arch_64) {
365 llvm::Triple triple(llvm::sys::getProcessTriple());
366
367 arch_32.Clear();
368 arch_64.Clear();
369
370 switch (triple.getArch()) {
371 default:
372 arch_32.SetTriple(triple);
373 break;
374
375 case llvm::Triple::aarch64:
376 case llvm::Triple::ppc64:
377 case llvm::Triple::ppc64le:
378 case llvm::Triple::x86_64:
379 case llvm::Triple::riscv64:
380 case llvm::Triple::loongarch64:
381 arch_64.SetTriple(triple);
382 arch_32.SetTriple(triple.get32BitArchVariant());
383 break;
384
385 case llvm::Triple::mips64:
386 case llvm::Triple::mips64el:
387 case llvm::Triple::sparcv9:
388 case llvm::Triple::systemz:
389 arch_64.SetTriple(triple);
390 break;
391 }
392}
static HostInfoBaseFields * g_fields
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition Log.h:369
constexpr lldb_private::HostInfo::SharedLibraryDirectoryHelper * g_shlib_dir_helper
An architecture specification class.
Definition ArchSpec.h:31
void Clear()
Clears the object state.
Definition ArchSpec.cpp:538
bool SetTriple(const llvm::Triple &triple)
Architecture triple setter.
Definition ArchSpec.cpp:741
static bool ContainsOnlyArch(const llvm::Triple &normalized_triple)
Returns true if the OS, vendor and environment fields of the triple are unset.
Definition ArchSpec.cpp:796
A file utility class.
Definition FileSpec.h:57
void AppendPathComponent(llvm::StringRef component)
Definition FileSpec.cpp:454
void SetDirectory(ConstString directory)
Directory string set accessor.
Definition FileSpec.cpp:342
const ConstString & GetDirectory() const
Directory string const get accessor.
Definition FileSpec.h:234
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition FileSpec.cpp:374
void Clear()
Clears the object state.
Definition FileSpec.cpp:259
ConstString GetPathAsConstString(bool denormalize=true) const
Get the full path as a ConstString.
Definition FileSpec.cpp:390
void Resolve(llvm::SmallVectorImpl< char > &path)
Resolve path to make it canonical.
static FileSystem & Instance()
static FileSpec GetGlobalTempDir()
Returns the global temporary directory.
static void ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64)
void(FileSpec &this_file) SharedLibraryDirectoryHelper
A helper function for determining the liblldb location.
static bool ComputeSharedLibraryDirectory(FileSpec &file_spec)
static bool ComputeSupportExeDirectory(FileSpec &file_spec)
static ArchSpec GetAugmentedArchSpec(llvm::StringRef triple)
If the triple does not specify the vendor, os, and environment parts, we "augment" these using inform...
static FileSpec GetHeaderDir()
Returns the directory containing the lldb headers.
static FileSpec GetUserLLDBDir()
Returns the directory containing the users lldb home (e.g.
static bool ComputeUserLLDBHomeDirectory(FileSpec &file_spec)
static const ArchSpec & GetArchitecture(ArchitectureKind arch_kind=eArchKindDefault)
static std::optional< ArchitectureKind > ParseArchitectureKind(llvm::StringRef kind)
static llvm::Triple GetTargetTriple()
Gets the host target triple.
static bool ComputePathRelativeToLibrary(FileSpec &file_spec, llvm::StringRef dir)
static bool ComputeTempFileBaseDirectory(FileSpec &file_spec)
static FileSpec GetSupportExeDir()
Returns the directory containing the support executables (debugserver, ...).
static bool ComputeUserPluginsDirectory(FileSpec &file_spec)
static FileSpec GetProcessTempDir()
Returns the process temporary directory.
static bool ComputeHeaderDirectory(FileSpec &file_spec)
static FileSpec GetShlibDir()
Returns the directory containing the lldb shared library.
static FileSpec GetSystemPluginDir()
Returns the directory containing the system plugins.
static bool ComputeUserHomeDirectory(FileSpec &file_spec)
static bool ComputeGlobalTempFileDirectory(FileSpec &file_spec)
static bool ComputeProcessTempFileDirectory(FileSpec &file_spec)
static FileSpec GetUserHomeDir()
Returns the directory containing the users home (e.g.
static FileSpec GetUserPluginDir()
Returns the directory containing the user plugins.
static bool ComputeSystemPluginsDirectory(FileSpec &file_spec)
static void Initialize(SharedLibraryDirectoryHelper *helper=nullptr)
static lldb::pid_t GetCurrentProcessID()
Get the process ID for the calling process.
static FileSpec GetModuleFileSpecForHostAddress(const void *host_addr)
Given an address in the current process (the process that is running the LLDB code),...
#define LLDB_ARCH_DEFAULT_64BIT
#define LLDB_ARCH_DEFAULT
CPU Type definitions.
#define LLDB_ARCH_DEFAULT_32BIT
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:332