HostInfoBase.cpp revision 353358
1275072Semaste//===-- HostInfoBase.cpp ----------------------------------------*- C++ -*-===//
2275072Semaste//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6275072Semaste//
7275072Semaste//===----------------------------------------------------------------------===//
8275072Semaste
9275072Semaste#include "lldb/Host/Config.h"
10275072Semaste
11275072Semaste#include "lldb/Host/FileSystem.h"
12275072Semaste#include "lldb/Host/Host.h"
13275072Semaste#include "lldb/Host/HostInfo.h"
14275072Semaste#include "lldb/Host/HostInfoBase.h"
15327952Sdim#include "lldb/Utility/ArchSpec.h"
16321369Sdim#include "lldb/Utility/Log.h"
17321369Sdim#include "lldb/Utility/StreamString.h"
18275072Semaste
19314564Sdim#include "llvm/ADT/StringExtras.h"
20275072Semaste#include "llvm/ADT/Triple.h"
21275072Semaste#include "llvm/Support/Host.h"
22296417Sdim#include "llvm/Support/Path.h"
23314564Sdim#include "llvm/Support/ScopedPrinter.h"
24321369Sdim#include "llvm/Support/Threading.h"
25280031Sdim#include "llvm/Support/raw_ostream.h"
26275072Semaste
27321369Sdim#include <mutex>
28275072Semaste#include <thread>
29275072Semaste
30275072Semasteusing namespace lldb;
31275072Semasteusing namespace lldb_private;
32275072Semaste
33314564Sdimnamespace {
34341825Sdim// The HostInfoBaseFields is a work around for windows not supporting static
35341825Sdim// variables correctly in a thread safe way. Really each of the variables in
36341825Sdim// HostInfoBaseFields should live in the functions in which they are used and
37341825Sdim// each one should be static, but the work around is in place to avoid this
38341825Sdim// restriction. Ick.
39275072Semaste
40314564Sdimstruct HostInfoBaseFields {
41314564Sdim  ~HostInfoBaseFields() {
42344779Sdim    if (FileSystem::Instance().Exists(m_lldb_process_tmp_dir)) {
43314564Sdim      // Remove the LLDB temporary directory if we have one. Set "recurse" to
44341825Sdim      // true to all files that were created for the LLDB process can be
45341825Sdim      // cleaned up.
46321369Sdim      llvm::sys::fs::remove_directories(m_lldb_process_tmp_dir.GetPath());
47314564Sdim    }
48314564Sdim  }
49309124Sdim
50314564Sdim  std::string m_host_triple;
51275072Semaste
52314564Sdim  ArchSpec m_host_arch_32;
53314564Sdim  ArchSpec m_host_arch_64;
54275072Semaste
55314564Sdim  FileSpec m_lldb_so_dir;
56314564Sdim  FileSpec m_lldb_support_exe_dir;
57314564Sdim  FileSpec m_lldb_headers_dir;
58314564Sdim  FileSpec m_lldb_clang_resource_dir;
59314564Sdim  FileSpec m_lldb_system_plugin_dir;
60314564Sdim  FileSpec m_lldb_user_plugin_dir;
61314564Sdim  FileSpec m_lldb_process_tmp_dir;
62314564Sdim  FileSpec m_lldb_global_tmp_dir;
63314564Sdim};
64275072Semaste
65314564SdimHostInfoBaseFields *g_fields = nullptr;
66275072Semaste}
67275072Semaste
68314564Sdimvoid HostInfoBase::Initialize() { g_fields = new HostInfoBaseFields(); }
69309124Sdim
70314564Sdimvoid HostInfoBase::Terminate() {
71314564Sdim  delete g_fields;
72314564Sdim  g_fields = nullptr;
73275072Semaste}
74275072Semaste
75314564Sdimllvm::StringRef HostInfoBase::GetTargetTriple() {
76321369Sdim  static llvm::once_flag g_once_flag;
77321369Sdim  llvm::call_once(g_once_flag, []() {
78314564Sdim    g_fields->m_host_triple =
79314564Sdim        HostInfo::GetArchitecture().GetTriple().getTriple();
80314564Sdim  });
81314564Sdim  return g_fields->m_host_triple;
82275072Semaste}
83275072Semaste
84314564Sdimconst ArchSpec &HostInfoBase::GetArchitecture(ArchitectureKind arch_kind) {
85321369Sdim  static llvm::once_flag g_once_flag;
86321369Sdim  llvm::call_once(g_once_flag, []() {
87314564Sdim    HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32,
88314564Sdim                                             g_fields->m_host_arch_64);
89314564Sdim  });
90275072Semaste
91314564Sdim  // If an explicit 32 or 64-bit architecture was requested, return that.
92314564Sdim  if (arch_kind == eArchKind32)
93314564Sdim    return g_fields->m_host_arch_32;
94314564Sdim  if (arch_kind == eArchKind64)
95314564Sdim    return g_fields->m_host_arch_64;
96275072Semaste
97314564Sdim  // Otherwise prefer the 64-bit architecture if it is valid.
98314564Sdim  return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64
99314564Sdim                                              : g_fields->m_host_arch_32;
100275072Semaste}
101275072Semaste
102327952Sdimllvm::Optional<HostInfoBase::ArchitectureKind> HostInfoBase::ParseArchitectureKind(llvm::StringRef kind) {
103327952Sdim  return llvm::StringSwitch<llvm::Optional<ArchitectureKind>>(kind)
104327952Sdim      .Case(LLDB_ARCH_DEFAULT, eArchKindDefault)
105327952Sdim      .Case(LLDB_ARCH_DEFAULT_32BIT, eArchKind32)
106327952Sdim      .Case(LLDB_ARCH_DEFAULT_64BIT, eArchKind64)
107327952Sdim      .Default(llvm::None);
108327952Sdim}
109327952Sdim
110341825SdimFileSpec HostInfoBase::GetShlibDir() {
111341825Sdim  static llvm::once_flag g_once_flag;
112341825Sdim  static bool success = false;
113341825Sdim  llvm::call_once(g_once_flag, []() {
114341825Sdim    success = HostInfo::ComputeSharedLibraryDirectory(g_fields->m_lldb_so_dir);
115341825Sdim    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
116341825Sdim    LLDB_LOG(log, "shlib dir -> `{0}`", g_fields->m_lldb_so_dir);
117341825Sdim  });
118341825Sdim  return success ? g_fields->m_lldb_so_dir : FileSpec();
119341825Sdim}
120275072Semaste
121341825SdimFileSpec HostInfoBase::GetSupportExeDir() {
122341825Sdim  static llvm::once_flag g_once_flag;
123341825Sdim  static bool success = false;
124341825Sdim  llvm::call_once(g_once_flag, []() {
125341825Sdim    success =
126341825Sdim        HostInfo::ComputeSupportExeDirectory(g_fields->m_lldb_support_exe_dir);
127341825Sdim    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
128341825Sdim    LLDB_LOG(log, "support exe dir -> `{0}`", g_fields->m_lldb_support_exe_dir);
129341825Sdim  });
130341825Sdim  return success ? g_fields->m_lldb_support_exe_dir : FileSpec();
131341825Sdim}
132275072Semaste
133341825SdimFileSpec HostInfoBase::GetHeaderDir() {
134341825Sdim  static llvm::once_flag g_once_flag;
135341825Sdim  static bool success = false;
136341825Sdim  llvm::call_once(g_once_flag, []() {
137341825Sdim    success = HostInfo::ComputeHeaderDirectory(g_fields->m_lldb_headers_dir);
138341825Sdim    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
139341825Sdim    LLDB_LOG(log, "header dir -> `{0}`", g_fields->m_lldb_headers_dir);
140341825Sdim  });
141341825Sdim  return success ? g_fields->m_lldb_headers_dir : FileSpec();
142341825Sdim}
143275072Semaste
144341825SdimFileSpec HostInfoBase::GetSystemPluginDir() {
145341825Sdim  static llvm::once_flag g_once_flag;
146341825Sdim  static bool success = false;
147341825Sdim  llvm::call_once(g_once_flag, []() {
148341825Sdim    success = HostInfo::ComputeSystemPluginsDirectory(
149341825Sdim        g_fields->m_lldb_system_plugin_dir);
150341825Sdim    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
151341825Sdim    LLDB_LOG(log, "system plugin dir -> `{0}`",
152341825Sdim             g_fields->m_lldb_system_plugin_dir);
153341825Sdim  });
154341825Sdim  return success ? g_fields->m_lldb_system_plugin_dir : FileSpec();
155275072Semaste}
156275072Semaste
157341825SdimFileSpec HostInfoBase::GetUserPluginDir() {
158341825Sdim  static llvm::once_flag g_once_flag;
159341825Sdim  static bool success = false;
160341825Sdim  llvm::call_once(g_once_flag, []() {
161341825Sdim    success =
162341825Sdim        HostInfo::ComputeUserPluginsDirectory(g_fields->m_lldb_user_plugin_dir);
163341825Sdim    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
164341825Sdim    LLDB_LOG(log, "user plugin dir -> `{0}`", g_fields->m_lldb_user_plugin_dir);
165341825Sdim  });
166341825Sdim  return success ? g_fields->m_lldb_user_plugin_dir : FileSpec();
167341825Sdim}
168341825Sdim
169341825SdimFileSpec HostInfoBase::GetProcessTempDir() {
170341825Sdim  static llvm::once_flag g_once_flag;
171341825Sdim  static bool success = false;
172341825Sdim  llvm::call_once(g_once_flag, []() {
173341825Sdim    success = HostInfo::ComputeProcessTempFileDirectory(
174341825Sdim        g_fields->m_lldb_process_tmp_dir);
175341825Sdim    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
176341825Sdim    LLDB_LOG(log, "process temp dir -> `{0}`",
177341825Sdim             g_fields->m_lldb_process_tmp_dir);
178341825Sdim  });
179341825Sdim  return success ? g_fields->m_lldb_process_tmp_dir : FileSpec();
180341825Sdim}
181341825Sdim
182341825SdimFileSpec HostInfoBase::GetGlobalTempDir() {
183341825Sdim  static llvm::once_flag g_once_flag;
184341825Sdim  static bool success = false;
185341825Sdim  llvm::call_once(g_once_flag, []() {
186341825Sdim    success = HostInfo::ComputeGlobalTempFileDirectory(
187341825Sdim        g_fields->m_lldb_global_tmp_dir);
188341825Sdim    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
189341825Sdim    LLDB_LOG(log, "global temp dir -> `{0}`", g_fields->m_lldb_global_tmp_dir);
190341825Sdim  });
191341825Sdim  return success ? g_fields->m_lldb_global_tmp_dir : FileSpec();
192341825Sdim}
193341825Sdim
194327952SdimArchSpec HostInfoBase::GetAugmentedArchSpec(llvm::StringRef triple) {
195327952Sdim  if (triple.empty())
196327952Sdim    return ArchSpec();
197327952Sdim  llvm::Triple normalized_triple(llvm::Triple::normalize(triple));
198327952Sdim  if (!ArchSpec::ContainsOnlyArch(normalized_triple))
199327952Sdim    return ArchSpec(triple);
200327952Sdim
201327952Sdim  if (auto kind = HostInfo::ParseArchitectureKind(triple))
202327952Sdim    return HostInfo::GetArchitecture(*kind);
203327952Sdim
204327952Sdim  llvm::Triple host_triple(llvm::sys::getDefaultTargetTriple());
205327952Sdim
206327952Sdim  if (normalized_triple.getVendorName().empty())
207327952Sdim    normalized_triple.setVendor(host_triple.getVendor());
208327952Sdim  if (normalized_triple.getOSName().empty())
209327952Sdim    normalized_triple.setOS(host_triple.getOS());
210327952Sdim  if (normalized_triple.getEnvironmentName().empty())
211327952Sdim    normalized_triple.setEnvironment(host_triple.getEnvironment());
212327952Sdim  return ArchSpec(normalized_triple);
213327952Sdim}
214327952Sdim
215353358Sdimbool HostInfoBase::ComputePathRelativeToLibrary(FileSpec &file_spec,
216353358Sdim                                                llvm::StringRef dir) {
217353358Sdim  Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
218353358Sdim
219353358Sdim  FileSpec lldb_file_spec = GetShlibDir();
220353358Sdim  if (!lldb_file_spec)
221353358Sdim    return false;
222353358Sdim
223353358Sdim  std::string raw_path = lldb_file_spec.GetPath();
224353358Sdim  if (log)
225353358Sdim    log->Printf("HostInfo::%s() attempting to "
226353358Sdim                "derive the path %s relative to liblldb install path: %s",
227353358Sdim                __FUNCTION__, dir.data(), raw_path.c_str());
228353358Sdim
229353358Sdim  // Drop bin (windows) or lib
230353358Sdim  llvm::StringRef parent_path = llvm::sys::path::parent_path(raw_path);
231353358Sdim  if (parent_path.empty()) {
232353358Sdim    if (log)
233353358Sdim      log->Printf("HostInfo::%s() failed to find liblldb within the shared "
234353358Sdim                  "lib path",
235353358Sdim                  __FUNCTION__);
236353358Sdim    return false;
237353358Sdim  }
238353358Sdim
239353358Sdim  raw_path = (parent_path + dir).str();
240353358Sdim  if (log)
241353358Sdim    log->Printf("HostInfo::%s() derived the path as: %s", __FUNCTION__,
242353358Sdim                raw_path.c_str());
243353358Sdim  file_spec.GetDirectory().SetString(raw_path);
244353358Sdim  return (bool)file_spec.GetDirectory();
245353358Sdim}
246353358Sdim
247314564Sdimbool HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) {
248314564Sdim  // To get paths related to LLDB we get the path to the executable that
249341825Sdim  // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB".
250341825Sdim  // On other posix systems, we will get .../lib(64|32)?/liblldb.so.
251275072Semaste
252341825Sdim  FileSpec lldb_file_spec(Host::GetModuleFileSpecForHostAddress(
253341825Sdim      reinterpret_cast<void *>(reinterpret_cast<intptr_t>(
254341825Sdim          HostInfoBase::ComputeSharedLibraryDirectory))));
255275072Semaste
256314564Sdim  // This is necessary because when running the testsuite the shlib might be a
257314564Sdim  // symbolic link inside the Python resource dir.
258344779Sdim  FileSystem::Instance().ResolveSymbolicLink(lldb_file_spec, lldb_file_spec);
259314564Sdim
260314564Sdim  // Remove the filename so that this FileSpec only represents the directory.
261314564Sdim  file_spec.GetDirectory() = lldb_file_spec.GetDirectory();
262314564Sdim
263314564Sdim  return (bool)file_spec.GetDirectory();
264275072Semaste}
265275072Semaste
266314564Sdimbool HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec) {
267341825Sdim  file_spec = GetShlibDir();
268341825Sdim  return bool(file_spec);
269275072Semaste}
270275072Semaste
271314564Sdimbool HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec) {
272314564Sdim  FileSpec temp_file_spec;
273314564Sdim  if (!HostInfo::ComputeGlobalTempFileDirectory(temp_file_spec))
274314564Sdim    return false;
275288943Sdim
276314564Sdim  std::string pid_str{llvm::to_string(Host::GetCurrentProcessID())};
277314564Sdim  temp_file_spec.AppendPathComponent(pid_str);
278321369Sdim  if (llvm::sys::fs::create_directory(temp_file_spec.GetPath()))
279314564Sdim    return false;
280288943Sdim
281314564Sdim  file_spec.GetDirectory().SetCString(temp_file_spec.GetCString());
282314564Sdim  return true;
283288943Sdim}
284288943Sdim
285314564Sdimbool HostInfoBase::ComputeTempFileBaseDirectory(FileSpec &file_spec) {
286314564Sdim  llvm::SmallVector<char, 16> tmpdir;
287314564Sdim  llvm::sys::path::system_temp_directory(/*ErasedOnReboot*/ true, tmpdir);
288344779Sdim  file_spec = FileSpec(std::string(tmpdir.data(), tmpdir.size()));
289344779Sdim  FileSystem::Instance().Resolve(file_spec);
290314564Sdim  return true;
291288943Sdim}
292288943Sdim
293314564Sdimbool HostInfoBase::ComputeGlobalTempFileDirectory(FileSpec &file_spec) {
294314564Sdim  file_spec.Clear();
295288943Sdim
296314564Sdim  FileSpec temp_file_spec;
297314564Sdim  if (!HostInfo::ComputeTempFileBaseDirectory(temp_file_spec))
298314564Sdim    return false;
299275072Semaste
300314564Sdim  temp_file_spec.AppendPathComponent("lldb");
301321369Sdim  if (llvm::sys::fs::create_directory(temp_file_spec.GetPath()))
302314564Sdim    return false;
303275072Semaste
304314564Sdim  file_spec.GetDirectory().SetCString(temp_file_spec.GetCString());
305314564Sdim  return true;
306275072Semaste}
307275072Semaste
308314564Sdimbool HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec) {
309314564Sdim  // TODO(zturner): Figure out how to compute the header directory for all
310314564Sdim  // platforms.
311314564Sdim  return false;
312275072Semaste}
313275072Semaste
314314564Sdimbool HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec) {
315314564Sdim  // TODO(zturner): Figure out how to compute the system plugins directory for
316314564Sdim  // all platforms.
317314564Sdim  return false;
318275072Semaste}
319275072Semaste
320314564Sdimbool HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec) {
321341825Sdim  // TODO(zturner): Figure out how to compute the user plugins directory for
322341825Sdim  // all platforms.
323314564Sdim  return false;
324275072Semaste}
325275072Semaste
326314564Sdimvoid HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32,
327314564Sdim                                                  ArchSpec &arch_64) {
328314564Sdim  llvm::Triple triple(llvm::sys::getProcessTriple());
329275072Semaste
330314564Sdim  arch_32.Clear();
331314564Sdim  arch_64.Clear();
332275072Semaste
333314564Sdim  switch (triple.getArch()) {
334314564Sdim  default:
335314564Sdim    arch_32.SetTriple(triple);
336314564Sdim    break;
337275072Semaste
338314564Sdim  case llvm::Triple::aarch64:
339314564Sdim  case llvm::Triple::ppc64:
340341825Sdim  case llvm::Triple::ppc64le:
341314564Sdim  case llvm::Triple::x86_64:
342314564Sdim    arch_64.SetTriple(triple);
343314564Sdim    arch_32.SetTriple(triple.get32BitArchVariant());
344314564Sdim    break;
345275072Semaste
346314564Sdim  case llvm::Triple::mips64:
347314564Sdim  case llvm::Triple::mips64el:
348314564Sdim  case llvm::Triple::sparcv9:
349314564Sdim  case llvm::Triple::systemz:
350314564Sdim    arch_64.SetTriple(triple);
351314564Sdim    break;
352314564Sdim  }
353275072Semaste}
354