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#ifndef NDEBUG
57 /// Used to assert that the shared library helper isn't set after the shlib
58 /// dir has already been computed.
59 bool m_lldb_so_dir_computed = false;
60#endif
61 HostInfoBase::SharedLibraryDirectoryHelper *g_shlib_dir_helper = nullptr;
62
63 llvm::once_flag m_lldb_support_exe_dir_once;
64 FileSpec m_lldb_support_exe_dir;
65 llvm::once_flag m_lldb_headers_dir_once;
66 FileSpec m_lldb_headers_dir;
67 llvm::once_flag m_lldb_clang_resource_dir_once;
68 FileSpec m_lldb_clang_resource_dir;
69 llvm::once_flag m_lldb_system_plugin_dir_once;
70 FileSpec m_lldb_system_plugin_dir;
71 llvm::once_flag m_lldb_user_home_dir_once;
72 FileSpec m_lldb_user_home_dir;
73 llvm::once_flag m_lldb_user_lldb_dir_once;
74 FileSpec m_lldb_user_lldb_dir;
75 llvm::once_flag m_lldb_user_plugin_dir_once;
76 FileSpec m_lldb_user_plugin_dir;
77 llvm::once_flag m_lldb_process_tmp_dir_once;
78 FileSpec m_lldb_process_tmp_dir;
79 llvm::once_flag m_lldb_global_tmp_dir_once;
80 FileSpec m_lldb_global_tmp_dir;
81};
82} // namespace
83
84static HostInfoBaseFields *g_fields = nullptr;
85
87 g_fields = new HostInfoBaseFields();
89}
90
93 delete g_fields;
94 g_fields = nullptr;
95}
96
98 llvm::call_once(g_fields->m_host_triple_once, []() {
99 g_fields->m_host_triple = HostInfo::GetArchitecture().GetTriple();
100 });
101 return g_fields->m_host_triple;
102}
103
105 llvm::call_once(g_fields->m_host_arch_once, []() {
106 HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32,
107 g_fields->m_host_arch_64);
108 });
109
110 // If an explicit 32 or 64-bit architecture was requested, return that.
111 if (arch_kind == eArchKind32)
112 return g_fields->m_host_arch_32;
113 if (arch_kind == eArchKind64)
114 return g_fields->m_host_arch_64;
115
116 // Otherwise prefer the 64-bit architecture if it is valid.
117 return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64
118 : g_fields->m_host_arch_32;
119}
120
121std::optional<HostInfoBase::ArchitectureKind>
123 return llvm::StringSwitch<std::optional<ArchitectureKind>>(kind)
127 .Default(std::nullopt);
128}
129
131 llvm::call_once(g_fields->m_lldb_so_dir_once, []() {
132 if (!HostInfo::ComputeSharedLibraryDirectory(g_fields->m_lldb_so_dir,
133 g_fields->g_shlib_dir_helper))
134 g_fields->m_lldb_so_dir = FileSpec();
135#ifndef NDEBUG
136 g_fields->m_lldb_so_dir_computed = true;
137#endif
138 Log *log = GetLog(LLDBLog::Host);
139 LLDB_LOG(log, "shlib dir -> `{0}`", g_fields->m_lldb_so_dir);
140 });
141 return g_fields->m_lldb_so_dir;
142}
143
145 llvm::call_once(g_fields->m_lldb_support_exe_dir_once, []() {
146 if (!HostInfo::ComputeSupportExeDirectory(g_fields->m_lldb_support_exe_dir))
147 g_fields->m_lldb_support_exe_dir = FileSpec();
148 Log *log = GetLog(LLDBLog::Host);
149 LLDB_LOG(log, "support exe dir -> `{0}`", g_fields->m_lldb_support_exe_dir);
150 });
151 return g_fields->m_lldb_support_exe_dir;
152}
153
155 llvm::call_once(g_fields->m_lldb_headers_dir_once, []() {
156 if (!HostInfo::ComputeHeaderDirectory(g_fields->m_lldb_headers_dir))
157 g_fields->m_lldb_headers_dir = FileSpec();
158 Log *log = GetLog(LLDBLog::Host);
159 LLDB_LOG(log, "header dir -> `{0}`", g_fields->m_lldb_headers_dir);
160 });
161 return g_fields->m_lldb_headers_dir;
162}
163
165 llvm::call_once(g_fields->m_lldb_system_plugin_dir_once, []() {
166 if (!HostInfo::ComputeSystemPluginsDirectory(
167 g_fields->m_lldb_system_plugin_dir))
168 g_fields->m_lldb_system_plugin_dir = FileSpec();
169 Log *log = GetLog(LLDBLog::Host);
170 LLDB_LOG(log, "system plugin dir -> `{0}`",
171 g_fields->m_lldb_system_plugin_dir);
172 });
173 return g_fields->m_lldb_system_plugin_dir;
174}
175
177 llvm::call_once(g_fields->m_lldb_user_home_dir_once, []() {
178 if (!HostInfo::ComputeUserHomeDirectory(g_fields->m_lldb_user_home_dir))
179 g_fields->m_lldb_user_home_dir = FileSpec();
180 LLDB_LOG(GetLog(LLDBLog::Host), "user home dir -> `{0}`",
181 g_fields->m_lldb_user_home_dir);
182 });
183 return g_fields->m_lldb_user_home_dir;
184}
185
187 llvm::call_once(g_fields->m_lldb_user_lldb_dir_once, []() {
188 if (!HostInfo::ComputeUserLLDBHomeDirectory(g_fields->m_lldb_user_lldb_dir))
189 g_fields->m_lldb_user_lldb_dir = FileSpec();
190 LLDB_LOG(GetLog(LLDBLog::Host), "user lldb home dir -> `{0}`",
191 g_fields->m_lldb_user_lldb_dir);
192 });
193 return g_fields->m_lldb_user_lldb_dir;
194}
195
197 llvm::call_once(g_fields->m_lldb_user_plugin_dir_once, []() {
198 if (!HostInfo::ComputeUserPluginsDirectory(
199 g_fields->m_lldb_user_plugin_dir))
200 g_fields->m_lldb_user_plugin_dir = FileSpec();
201 Log *log = GetLog(LLDBLog::Host);
202 LLDB_LOG(log, "user plugin dir -> `{0}`", g_fields->m_lldb_user_plugin_dir);
203 });
204 return g_fields->m_lldb_user_plugin_dir;
205}
206
208 llvm::call_once(g_fields->m_lldb_process_tmp_dir_once, []() {
209 if (!HostInfo::ComputeProcessTempFileDirectory(
210 g_fields->m_lldb_process_tmp_dir))
211 g_fields->m_lldb_process_tmp_dir = FileSpec();
212 Log *log = GetLog(LLDBLog::Host);
213 LLDB_LOG(log, "process temp dir -> `{0}`",
214 g_fields->m_lldb_process_tmp_dir);
215 });
216 return g_fields->m_lldb_process_tmp_dir;
217}
218
220 llvm::call_once(g_fields->m_lldb_global_tmp_dir_once, []() {
221 if (!HostInfo::ComputeGlobalTempFileDirectory(
222 g_fields->m_lldb_global_tmp_dir))
223 g_fields->m_lldb_global_tmp_dir = FileSpec();
224
225 Log *log = GetLog(LLDBLog::Host);
226 LLDB_LOG(log, "global temp dir -> `{0}`", g_fields->m_lldb_global_tmp_dir);
227 });
228 return g_fields->m_lldb_global_tmp_dir;
229}
230
232 if (triple.empty())
233 return ArchSpec();
234 llvm::Triple normalized_triple(llvm::Triple::normalize(triple));
235 if (!ArchSpec::ContainsOnlyArch(normalized_triple))
236 return ArchSpec(triple);
237
238 if (auto kind = HostInfo::ParseArchitectureKind(triple))
239 return HostInfo::GetArchitecture(*kind);
240
241 llvm::Triple host_triple(llvm::sys::getDefaultTargetTriple());
242
243 if (normalized_triple.getVendorName().empty())
244 normalized_triple.setVendor(host_triple.getVendor());
245 if (normalized_triple.getOSName().empty())
246 normalized_triple.setOS(host_triple.getOS());
247 if (normalized_triple.getEnvironmentName().empty() &&
248 !host_triple.getEnvironmentName().empty())
249 normalized_triple.setEnvironment(host_triple.getEnvironment());
250 return ArchSpec(normalized_triple);
251}
252
254 llvm::StringRef dir) {
255 Log *log = GetLog(LLDBLog::Host);
256
257 FileSpec lldb_file_spec = GetShlibDir();
258 if (!lldb_file_spec)
259 return false;
260
261 std::string raw_path = lldb_file_spec.GetPath();
262 LLDB_LOG(
263 log,
264 "Attempting to derive the path {0} relative to liblldb install path: {1}",
265 dir, raw_path);
266
267 // Drop bin (windows) or lib
268 llvm::StringRef parent_path = llvm::sys::path::parent_path(raw_path);
269 if (parent_path.empty()) {
270 LLDB_LOG(log, "Failed to find liblldb within the shared lib path");
271 return false;
272 }
273
274 raw_path = (parent_path + dir).str();
275 LLDB_LOG(log, "Derived the path as: {0}", raw_path);
276 file_spec.SetDirectory(raw_path);
277 return (bool)file_spec.GetDirectory();
278}
279
282 assert(g_fields &&
283 "SetSharedLibraryDirectoryHelper called before Initialize");
284 assert(!g_fields->m_lldb_so_dir_computed &&
285 "SetSharedLibraryDirectoryHelper called after "
286 "ComputeSharedLibraryDirectory");
287 g_fields->g_shlib_dir_helper = helper;
288}
289
291 FileSpec &file_spec, SharedLibraryDirectoryHelper *helper) {
292 // To get paths related to LLDB we get the path to the executable that
293 // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB".
294 // On other posix systems, we will get .../lib(64|32)?/liblldb.so.
295
297 reinterpret_cast<void *>(HostInfoBase::ComputeSharedLibraryDirectory)));
298
299 if (helper)
300 helper(lldb_file_spec);
301
302 // Remove the filename so that this FileSpec only represents the directory.
303 file_spec.SetDirectory(lldb_file_spec.GetDirectory());
304
305 return (bool)file_spec.GetDirectory();
306}
307
309 file_spec = GetShlibDir();
310 return bool(file_spec);
311}
312
314 FileSpec temp_file_spec;
315 if (!HostInfo::ComputeGlobalTempFileDirectory(temp_file_spec))
316 return false;
317
318 std::string pid_str{llvm::to_string(Host::GetCurrentProcessID())};
319 temp_file_spec.AppendPathComponent(pid_str);
320 if (llvm::sys::fs::create_directory(temp_file_spec.GetPath()))
321 return false;
322
323 file_spec.SetDirectory(temp_file_spec.GetPathAsConstString());
324 return true;
325}
326
328 llvm::SmallVector<char, 16> tmpdir;
329 llvm::sys::path::system_temp_directory(/*ErasedOnReboot*/ true, tmpdir);
330 file_spec = FileSpec(std::string(tmpdir.data(), tmpdir.size()));
331 FileSystem::Instance().Resolve(file_spec);
332 return true;
333}
334
336 file_spec.Clear();
337
338 FileSpec temp_file_spec;
339 if (!HostInfo::ComputeTempFileBaseDirectory(temp_file_spec))
340 return false;
341
342 temp_file_spec.AppendPathComponent("lldb");
343 if (llvm::sys::fs::create_directory(temp_file_spec.GetPath()))
344 return false;
345
346 file_spec.SetDirectory(temp_file_spec.GetPathAsConstString());
347 return true;
348}
349
351 // TODO(zturner): Figure out how to compute the header directory for all
352 // platforms.
353 return false;
354}
355
357 // TODO(zturner): Figure out how to compute the system plugins directory for
358 // all platforms.
359 return false;
360}
361
363 FileSpec temp_file("~");
364 FileSystem::Instance().Resolve(temp_file);
365 file_spec.SetDirectory(temp_file.GetPathAsConstString());
366 return true;
367}
368
370 FileSpec home_dir_spec = GetUserHomeDir();
371 home_dir_spec.AppendPathComponent(".lldb");
372 file_spec.SetDirectory(home_dir_spec.GetPathAsConstString());
373 return true;
374}
375
377 // TODO(zturner): Figure out how to compute the user plugins directory for
378 // all platforms.
379 return false;
380}
381
383 ArchSpec &arch_64) {
384 llvm::Triple triple(llvm::sys::getProcessTriple());
385
386 arch_32.Clear();
387 arch_64.Clear();
388
389 switch (triple.getArch()) {
390 default:
391 arch_32.SetTriple(triple);
392 break;
393
394 case llvm::Triple::aarch64:
395 case llvm::Triple::ppc64:
396 case llvm::Triple::ppc64le:
397 case llvm::Triple::x86_64:
398 case llvm::Triple::riscv64:
399 case llvm::Triple::loongarch64:
400 arch_64.SetTriple(triple);
401 arch_32.SetTriple(triple.get32BitArchVariant());
402 break;
403
404 case llvm::Triple::mips64:
405 case llvm::Triple::mips64el:
406 case llvm::Triple::sparcv9:
407 case llvm::Triple::systemz:
408 arch_64.SetTriple(triple);
409 break;
410 }
411}
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
An architecture specification class.
Definition ArchSpec.h:32
void Clear()
Clears the object state.
Definition ArchSpec.cpp:538
bool SetTriple(const llvm::Triple &triple)
Architecture triple setter.
Definition ArchSpec.cpp:739
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:794
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
static FileSystem & Instance()
void Resolve(llvm::SmallVectorImpl< char > &path, bool force_make_absolute=false)
Resolve path to make it canonical.
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 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 bool ComputeSharedLibraryDirectory(FileSpec &file_spec, SharedLibraryDirectoryHelper *helper)
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 void SetSharedLibraryDirectoryHelper(SharedLibraryDirectoryHelper *helper)
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 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