LLDB  mainline
HostInfoBase.cpp
Go to the documentation of this file.
1 //===-- HostInfoBase.cpp ----------------------------------------*- C++ -*-===//
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 #include "lldb/Host/FileSystem.h"
12 #include "lldb/Host/Host.h"
13 #include "lldb/Host/HostInfo.h"
14 #include "lldb/Host/HostInfoBase.h"
15 #include "lldb/Utility/ArchSpec.h"
16 #include "lldb/Utility/Log.h"
18 
19 #include "llvm/ADT/StringExtras.h"
20 #include "llvm/ADT/Triple.h"
21 #include "llvm/Support/Host.h"
22 #include "llvm/Support/Path.h"
23 #include "llvm/Support/ScopedPrinter.h"
24 #include "llvm/Support/Threading.h"
25 #include "llvm/Support/raw_ostream.h"
26 
27 #include <mutex>
28 #include <thread>
29 
30 using namespace lldb;
31 using namespace lldb_private;
32 
33 namespace {
34 // The HostInfoBaseFields is a work around for windows not supporting static
35 // variables correctly in a thread safe way. Really each of the variables in
36 // HostInfoBaseFields should live in the functions in which they are used and
37 // each one should be static, but the work around is in place to avoid this
38 // restriction. Ick.
39 
40 struct HostInfoBaseFields {
41  ~HostInfoBaseFields() {
42  if (FileSystem::Instance().Exists(m_lldb_process_tmp_dir)) {
43  // Remove the LLDB temporary directory if we have one. Set "recurse" to
44  // true to all files that were created for the LLDB process can be
45  // cleaned up.
46  llvm::sys::fs::remove_directories(m_lldb_process_tmp_dir.GetPath());
47  }
48  }
49 
50  std::string m_host_triple;
51 
52  ArchSpec m_host_arch_32;
53  ArchSpec m_host_arch_64;
54 
55  FileSpec m_lldb_so_dir;
56  FileSpec m_lldb_support_exe_dir;
57  FileSpec m_lldb_headers_dir;
58  FileSpec m_lldb_clang_resource_dir;
59  FileSpec m_lldb_system_plugin_dir;
60  FileSpec m_lldb_user_plugin_dir;
61  FileSpec m_lldb_process_tmp_dir;
62  FileSpec m_lldb_global_tmp_dir;
63 };
64 
65 HostInfoBaseFields *g_fields = nullptr;
66 }
67 
68 void HostInfoBase::Initialize() { g_fields = new HostInfoBaseFields(); }
69 
70 void HostInfoBase::Terminate() {
71  delete g_fields;
72  g_fields = nullptr;
73 }
74 
75 llvm::StringRef HostInfoBase::GetTargetTriple() {
76  static llvm::once_flag g_once_flag;
77  llvm::call_once(g_once_flag, []() {
78  g_fields->m_host_triple =
79  HostInfo::GetArchitecture().GetTriple().getTriple();
80  });
81  return g_fields->m_host_triple;
82 }
83 
84 const ArchSpec &HostInfoBase::GetArchitecture(ArchitectureKind arch_kind) {
85  static llvm::once_flag g_once_flag;
86  llvm::call_once(g_once_flag, []() {
87  HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32,
88  g_fields->m_host_arch_64);
89  });
90 
91  // If an explicit 32 or 64-bit architecture was requested, return that.
92  if (arch_kind == eArchKind32)
93  return g_fields->m_host_arch_32;
94  if (arch_kind == eArchKind64)
95  return g_fields->m_host_arch_64;
96 
97  // Otherwise prefer the 64-bit architecture if it is valid.
98  return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64
99  : g_fields->m_host_arch_32;
100 }
101 
102 llvm::Optional<HostInfoBase::ArchitectureKind> HostInfoBase::ParseArchitectureKind(llvm::StringRef kind) {
103  return llvm::StringSwitch<llvm::Optional<ArchitectureKind>>(kind)
104  .Case(LLDB_ARCH_DEFAULT, eArchKindDefault)
105  .Case(LLDB_ARCH_DEFAULT_32BIT, eArchKind32)
106  .Case(LLDB_ARCH_DEFAULT_64BIT, eArchKind64)
107  .Default(llvm::None);
108 }
109 
110 FileSpec HostInfoBase::GetShlibDir() {
111  static llvm::once_flag g_once_flag;
112  static bool success = false;
113  llvm::call_once(g_once_flag, []() {
114  success = HostInfo::ComputeSharedLibraryDirectory(g_fields->m_lldb_so_dir);
116  LLDB_LOG(log, "shlib dir -> `{0}`", g_fields->m_lldb_so_dir);
117  });
118  return success ? g_fields->m_lldb_so_dir : FileSpec();
119 }
120 
121 FileSpec HostInfoBase::GetSupportExeDir() {
122  static llvm::once_flag g_once_flag;
123  static bool success = false;
124  llvm::call_once(g_once_flag, []() {
125  success =
126  HostInfo::ComputeSupportExeDirectory(g_fields->m_lldb_support_exe_dir);
128  LLDB_LOG(log, "support exe dir -> `{0}`", g_fields->m_lldb_support_exe_dir);
129  });
130  return success ? g_fields->m_lldb_support_exe_dir : FileSpec();
131 }
132 
133 FileSpec HostInfoBase::GetHeaderDir() {
134  static llvm::once_flag g_once_flag;
135  static bool success = false;
136  llvm::call_once(g_once_flag, []() {
137  success = HostInfo::ComputeHeaderDirectory(g_fields->m_lldb_headers_dir);
139  LLDB_LOG(log, "header dir -> `{0}`", g_fields->m_lldb_headers_dir);
140  });
141  return success ? g_fields->m_lldb_headers_dir : FileSpec();
142 }
143 
144 FileSpec HostInfoBase::GetSystemPluginDir() {
145  static llvm::once_flag g_once_flag;
146  static bool success = false;
147  llvm::call_once(g_once_flag, []() {
148  success = HostInfo::ComputeSystemPluginsDirectory(
149  g_fields->m_lldb_system_plugin_dir);
151  LLDB_LOG(log, "system plugin dir -> `{0}`",
152  g_fields->m_lldb_system_plugin_dir);
153  });
154  return success ? g_fields->m_lldb_system_plugin_dir : FileSpec();
155 }
156 
157 FileSpec HostInfoBase::GetUserPluginDir() {
158  static llvm::once_flag g_once_flag;
159  static bool success = false;
160  llvm::call_once(g_once_flag, []() {
161  success =
162  HostInfo::ComputeUserPluginsDirectory(g_fields->m_lldb_user_plugin_dir);
164  LLDB_LOG(log, "user plugin dir -> `{0}`", g_fields->m_lldb_user_plugin_dir);
165  });
166  return success ? g_fields->m_lldb_user_plugin_dir : FileSpec();
167 }
168 
169 FileSpec HostInfoBase::GetProcessTempDir() {
170  static llvm::once_flag g_once_flag;
171  static bool success = false;
172  llvm::call_once(g_once_flag, []() {
173  success = HostInfo::ComputeProcessTempFileDirectory(
174  g_fields->m_lldb_process_tmp_dir);
176  LLDB_LOG(log, "process temp dir -> `{0}`",
177  g_fields->m_lldb_process_tmp_dir);
178  });
179  return success ? g_fields->m_lldb_process_tmp_dir : FileSpec();
180 }
181 
182 FileSpec HostInfoBase::GetGlobalTempDir() {
183  static llvm::once_flag g_once_flag;
184  static bool success = false;
185  llvm::call_once(g_once_flag, []() {
186  success = HostInfo::ComputeGlobalTempFileDirectory(
187  g_fields->m_lldb_global_tmp_dir);
189  LLDB_LOG(log, "global temp dir -> `{0}`", g_fields->m_lldb_global_tmp_dir);
190  });
191  return success ? g_fields->m_lldb_global_tmp_dir : FileSpec();
192 }
193 
194 ArchSpec HostInfoBase::GetAugmentedArchSpec(llvm::StringRef triple) {
195  if (triple.empty())
196  return ArchSpec();
197  llvm::Triple normalized_triple(llvm::Triple::normalize(triple));
198  if (!ArchSpec::ContainsOnlyArch(normalized_triple))
199  return ArchSpec(triple);
200 
201  if (auto kind = HostInfo::ParseArchitectureKind(triple))
202  return HostInfo::GetArchitecture(*kind);
203 
204  llvm::Triple host_triple(llvm::sys::getDefaultTargetTriple());
205 
206  if (normalized_triple.getVendorName().empty())
207  normalized_triple.setVendor(host_triple.getVendor());
208  if (normalized_triple.getOSName().empty())
209  normalized_triple.setOS(host_triple.getOS());
210  if (normalized_triple.getEnvironmentName().empty())
211  normalized_triple.setEnvironment(host_triple.getEnvironment());
212  return ArchSpec(normalized_triple);
213 }
214 
215 bool HostInfoBase::ComputePathRelativeToLibrary(FileSpec &file_spec,
216  llvm::StringRef dir) {
218 
219  FileSpec lldb_file_spec = GetShlibDir();
220  if (!lldb_file_spec)
221  return false;
222 
223  std::string raw_path = lldb_file_spec.GetPath();
224  if (log)
225  log->Printf("HostInfo::%s() attempting to "
226  "derive the path %s relative to liblldb install path: %s",
227  __FUNCTION__, dir.data(), raw_path.c_str());
228 
229  // Drop bin (windows) or lib
230  llvm::StringRef parent_path = llvm::sys::path::parent_path(raw_path);
231  if (parent_path.empty()) {
232  if (log)
233  log->Printf("HostInfo::%s() failed to find liblldb within the shared "
234  "lib path",
235  __FUNCTION__);
236  return false;
237  }
238 
239  raw_path = (parent_path + dir).str();
240  if (log)
241  log->Printf("HostInfo::%s() derived the path as: %s", __FUNCTION__,
242  raw_path.c_str());
243  file_spec.GetDirectory().SetString(raw_path);
244  return (bool)file_spec.GetDirectory();
245 }
246 
247 bool HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) {
248  // To get paths related to LLDB we get the path to the executable that
249  // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB".
250  // On other posix systems, we will get .../lib(64|32)?/liblldb.so.
251 
252  FileSpec lldb_file_spec(Host::GetModuleFileSpecForHostAddress(
253  reinterpret_cast<void *>(reinterpret_cast<intptr_t>(
254  HostInfoBase::ComputeSharedLibraryDirectory))));
255 
256  // This is necessary because when running the testsuite the shlib might be a
257  // symbolic link inside the Python resource dir.
258  FileSystem::Instance().ResolveSymbolicLink(lldb_file_spec, lldb_file_spec);
259 
260  // Remove the filename so that this FileSpec only represents the directory.
261  file_spec.GetDirectory() = lldb_file_spec.GetDirectory();
262 
263  return (bool)file_spec.GetDirectory();
264 }
265 
266 bool HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec) {
267  file_spec = GetShlibDir();
268  return bool(file_spec);
269 }
270 
271 bool HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec) {
272  FileSpec temp_file_spec;
273  if (!HostInfo::ComputeGlobalTempFileDirectory(temp_file_spec))
274  return false;
275 
276  std::string pid_str{llvm::to_string(Host::GetCurrentProcessID())};
277  temp_file_spec.AppendPathComponent(pid_str);
278  if (llvm::sys::fs::create_directory(temp_file_spec.GetPath()))
279  return false;
280 
281  file_spec.GetDirectory().SetCString(temp_file_spec.GetCString());
282  return true;
283 }
284 
285 bool HostInfoBase::ComputeTempFileBaseDirectory(FileSpec &file_spec) {
286  llvm::SmallVector<char, 16> tmpdir;
287  llvm::sys::path::system_temp_directory(/*ErasedOnReboot*/ true, tmpdir);
288  file_spec = FileSpec(std::string(tmpdir.data(), tmpdir.size()));
289  FileSystem::Instance().Resolve(file_spec);
290  return true;
291 }
292 
293 bool HostInfoBase::ComputeGlobalTempFileDirectory(FileSpec &file_spec) {
294  file_spec.Clear();
295 
296  FileSpec temp_file_spec;
297  if (!HostInfo::ComputeTempFileBaseDirectory(temp_file_spec))
298  return false;
299 
300  temp_file_spec.AppendPathComponent("lldb");
301  if (llvm::sys::fs::create_directory(temp_file_spec.GetPath()))
302  return false;
303 
304  file_spec.GetDirectory().SetCString(temp_file_spec.GetCString());
305  return true;
306 }
307 
308 bool HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec) {
309  // TODO(zturner): Figure out how to compute the header directory for all
310  // platforms.
311  return false;
312 }
313 
314 bool HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec) {
315  // TODO(zturner): Figure out how to compute the system plugins directory for
316  // all platforms.
317  return false;
318 }
319 
320 bool HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec) {
321  // TODO(zturner): Figure out how to compute the user plugins directory for
322  // all platforms.
323  return false;
324 }
325 
326 void HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32,
327  ArchSpec &arch_64) {
328  llvm::Triple triple(llvm::sys::getProcessTriple());
329 
330  arch_32.Clear();
331  arch_64.Clear();
332 
333  switch (triple.getArch()) {
334  default:
335  arch_32.SetTriple(triple);
336  break;
337 
338  case llvm::Triple::aarch64:
339  case llvm::Triple::ppc64:
340  case llvm::Triple::ppc64le:
341  case llvm::Triple::x86_64:
342  arch_64.SetTriple(triple);
343  arch_32.SetTriple(triple.get32BitArchVariant());
344  break;
345 
346  case llvm::Triple::mips64:
347  case llvm::Triple::mips64el:
348  case llvm::Triple::sparcv9:
349  case llvm::Triple::systemz:
350  arch_64.SetTriple(triple);
351  break;
352  }
353 }
void SetString(const llvm::StringRef &s)
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
bool SetTriple(const llvm::Triple &triple)
Architecture triple setter.
Definition: ArchSpec.cpp:797
A file utility class.
Definition: FileSpec.h:55
An architecture specification class.
Definition: ArchSpec.h:32
#define LLDB_ARCH_DEFAULT_64BIT
Definition: lldb-defines.h:103
#define LLDB_ARCH_DEFAULT
CPU Type definitions.
Definition: lldb-defines.h:101
void Clear()
Clears the object state.
Definition: FileSpec.cpp:285
#define LLDB_LOG(log,...)
Definition: Log.h:209
void Clear()
Clears the object state.
Definition: ArchSpec.cpp:580
#define LIBLLDB_LOG_HOST
Definition: Logging.h:28
ArchitectureKind
Gets the host architecture.
Definition: HostInfoBase.h:47
void AppendPathComponent(llvm::StringRef component)
Definition: FileSpec.cpp:463
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:57
const char * GetCString(bool denormalize=true) const
Definition: FileSpec.cpp:392
#define LLDB_ARCH_DEFAULT_32BIT
Definition: lldb-defines.h:102
ConstString & GetDirectory()
Directory string get accessor.
Definition: FileSpec.cpp:363
Definition: SBAddress.h:15
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:376
void Printf(const char *format,...) __attribute__((format(printf
Definition: Log.cpp:113
void SetCString(const char *cstr)
Set the C string value.