HostInfoBase.cpp revision 327952
1275072Semaste//===-- HostInfoBase.cpp ----------------------------------------*- C++ -*-===//
2275072Semaste//
3275072Semaste//                     The LLVM Compiler Infrastructure
4275072Semaste//
5275072Semaste// This file is distributed under the University of Illinois Open Source
6275072Semaste// License. See LICENSE.TXT for details.
7275072Semaste//
8275072Semaste//===----------------------------------------------------------------------===//
9275072Semaste
10275072Semaste#include "lldb/Host/Config.h"
11275072Semaste
12275072Semaste#include "lldb/Host/FileSystem.h"
13275072Semaste#include "lldb/Host/Host.h"
14275072Semaste#include "lldb/Host/HostInfo.h"
15275072Semaste#include "lldb/Host/HostInfoBase.h"
16327952Sdim#include "lldb/Utility/ArchSpec.h"
17321369Sdim#include "lldb/Utility/Log.h"
18321369Sdim#include "lldb/Utility/StreamString.h"
19275072Semaste
20314564Sdim#include "llvm/ADT/StringExtras.h"
21275072Semaste#include "llvm/ADT/Triple.h"
22275072Semaste#include "llvm/Support/Host.h"
23296417Sdim#include "llvm/Support/Path.h"
24314564Sdim#include "llvm/Support/ScopedPrinter.h"
25321369Sdim#include "llvm/Support/Threading.h"
26280031Sdim#include "llvm/Support/raw_ostream.h"
27275072Semaste
28321369Sdim#include <mutex>
29275072Semaste#include <thread>
30275072Semaste
31275072Semasteusing namespace lldb;
32275072Semasteusing namespace lldb_private;
33275072Semaste
34314564Sdimnamespace {
35314564Sdim//----------------------------------------------------------------------
36314564Sdim// The HostInfoBaseFields is a work around for windows not supporting
37314564Sdim// static variables correctly in a thread safe way. Really each of the
38314564Sdim// variables in HostInfoBaseFields should live in the functions in which
39314564Sdim// they are used and each one should be static, but the work around is
40314564Sdim// in place to avoid this restriction. Ick.
41314564Sdim//----------------------------------------------------------------------
42275072Semaste
43314564Sdimstruct HostInfoBaseFields {
44314564Sdim  ~HostInfoBaseFields() {
45314564Sdim    if (m_lldb_process_tmp_dir.Exists()) {
46314564Sdim      // Remove the LLDB temporary directory if we have one. Set "recurse" to
47314564Sdim      // true to all files that were created for the LLDB process can be cleaned
48314564Sdim      // up.
49321369Sdim      llvm::sys::fs::remove_directories(m_lldb_process_tmp_dir.GetPath());
50314564Sdim    }
51314564Sdim  }
52309124Sdim
53314564Sdim  std::string m_host_triple;
54275072Semaste
55314564Sdim  ArchSpec m_host_arch_32;
56314564Sdim  ArchSpec m_host_arch_64;
57275072Semaste
58314564Sdim  FileSpec m_lldb_so_dir;
59314564Sdim  FileSpec m_lldb_support_exe_dir;
60314564Sdim  FileSpec m_lldb_headers_dir;
61314564Sdim  FileSpec m_lldb_python_dir;
62314564Sdim  FileSpec m_lldb_clang_resource_dir;
63314564Sdim  FileSpec m_lldb_system_plugin_dir;
64314564Sdim  FileSpec m_lldb_user_plugin_dir;
65314564Sdim  FileSpec m_lldb_process_tmp_dir;
66314564Sdim  FileSpec m_lldb_global_tmp_dir;
67314564Sdim};
68275072Semaste
69314564SdimHostInfoBaseFields *g_fields = nullptr;
70275072Semaste}
71275072Semaste
72314564Sdimvoid HostInfoBase::Initialize() { g_fields = new HostInfoBaseFields(); }
73309124Sdim
74314564Sdimvoid HostInfoBase::Terminate() {
75314564Sdim  delete g_fields;
76314564Sdim  g_fields = nullptr;
77275072Semaste}
78275072Semaste
79314564Sdimllvm::StringRef HostInfoBase::GetTargetTriple() {
80321369Sdim  static llvm::once_flag g_once_flag;
81321369Sdim  llvm::call_once(g_once_flag, []() {
82314564Sdim    g_fields->m_host_triple =
83314564Sdim        HostInfo::GetArchitecture().GetTriple().getTriple();
84314564Sdim  });
85314564Sdim  return g_fields->m_host_triple;
86275072Semaste}
87275072Semaste
88314564Sdimconst ArchSpec &HostInfoBase::GetArchitecture(ArchitectureKind arch_kind) {
89321369Sdim  static llvm::once_flag g_once_flag;
90321369Sdim  llvm::call_once(g_once_flag, []() {
91314564Sdim    HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32,
92314564Sdim                                             g_fields->m_host_arch_64);
93314564Sdim  });
94275072Semaste
95314564Sdim  // If an explicit 32 or 64-bit architecture was requested, return that.
96314564Sdim  if (arch_kind == eArchKind32)
97314564Sdim    return g_fields->m_host_arch_32;
98314564Sdim  if (arch_kind == eArchKind64)
99314564Sdim    return g_fields->m_host_arch_64;
100275072Semaste
101314564Sdim  // Otherwise prefer the 64-bit architecture if it is valid.
102314564Sdim  return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64
103314564Sdim                                              : g_fields->m_host_arch_32;
104275072Semaste}
105275072Semaste
106327952Sdimllvm::Optional<HostInfoBase::ArchitectureKind> HostInfoBase::ParseArchitectureKind(llvm::StringRef kind) {
107327952Sdim  return llvm::StringSwitch<llvm::Optional<ArchitectureKind>>(kind)
108327952Sdim      .Case(LLDB_ARCH_DEFAULT, eArchKindDefault)
109327952Sdim      .Case(LLDB_ARCH_DEFAULT_32BIT, eArchKind32)
110327952Sdim      .Case(LLDB_ARCH_DEFAULT_64BIT, eArchKind64)
111327952Sdim      .Default(llvm::None);
112327952Sdim}
113327952Sdim
114314564Sdimbool HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) {
115314564Sdim  file_spec.Clear();
116275072Semaste
117275072Semaste#if defined(LLDB_DISABLE_PYTHON)
118314564Sdim  if (type == lldb::ePathTypePythonDir)
119314564Sdim    return false;
120275072Semaste#endif
121275072Semaste
122314564Sdim  FileSpec *result = nullptr;
123314564Sdim  switch (type) {
124314564Sdim  case lldb::ePathTypeLLDBShlibDir: {
125321369Sdim    static llvm::once_flag g_once_flag;
126314564Sdim    static bool success = false;
127321369Sdim    llvm::call_once(g_once_flag, []() {
128314564Sdim      success =
129314564Sdim          HostInfo::ComputeSharedLibraryDirectory(g_fields->m_lldb_so_dir);
130314564Sdim      Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
131314564Sdim      if (log)
132314564Sdim        log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'",
133314564Sdim                    g_fields->m_lldb_so_dir.GetPath().c_str());
134314564Sdim    });
135314564Sdim    if (success)
136314564Sdim      result = &g_fields->m_lldb_so_dir;
137314564Sdim  } break;
138314564Sdim  case lldb::ePathTypeSupportExecutableDir: {
139321369Sdim    static llvm::once_flag g_once_flag;
140314564Sdim    static bool success = false;
141321369Sdim    llvm::call_once(g_once_flag, []() {
142314564Sdim      success = HostInfo::ComputeSupportExeDirectory(
143314564Sdim          g_fields->m_lldb_support_exe_dir);
144314564Sdim      Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
145314564Sdim      if (log)
146314564Sdim        log->Printf(
147314564Sdim            "HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'",
148314564Sdim            g_fields->m_lldb_support_exe_dir.GetPath().c_str());
149314564Sdim    });
150314564Sdim    if (success)
151314564Sdim      result = &g_fields->m_lldb_support_exe_dir;
152314564Sdim  } break;
153314564Sdim  case lldb::ePathTypeHeaderDir: {
154321369Sdim    static llvm::once_flag g_once_flag;
155314564Sdim    static bool success = false;
156321369Sdim    llvm::call_once(g_once_flag, []() {
157314564Sdim      success = HostInfo::ComputeHeaderDirectory(g_fields->m_lldb_headers_dir);
158314564Sdim      Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
159314564Sdim      if (log)
160314564Sdim        log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'",
161314564Sdim                    g_fields->m_lldb_headers_dir.GetPath().c_str());
162314564Sdim    });
163314564Sdim    if (success)
164314564Sdim      result = &g_fields->m_lldb_headers_dir;
165314564Sdim  } break;
166314564Sdim  case lldb::ePathTypePythonDir: {
167321369Sdim    static llvm::once_flag g_once_flag;
168314564Sdim    static bool success = false;
169321369Sdim    llvm::call_once(g_once_flag, []() {
170314564Sdim      success = HostInfo::ComputePythonDirectory(g_fields->m_lldb_python_dir);
171314564Sdim      Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
172314564Sdim      if (log)
173314564Sdim        log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'",
174314564Sdim                    g_fields->m_lldb_python_dir.GetPath().c_str());
175314564Sdim    });
176314564Sdim    if (success)
177314564Sdim      result = &g_fields->m_lldb_python_dir;
178314564Sdim  } break;
179314564Sdim  case lldb::ePathTypeClangDir: {
180321369Sdim    static llvm::once_flag g_once_flag;
181314564Sdim    static bool success = false;
182321369Sdim    llvm::call_once(g_once_flag, []() {
183314564Sdim      success =
184314564Sdim          HostInfo::ComputeClangDirectory(g_fields->m_lldb_clang_resource_dir);
185314564Sdim      Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
186314564Sdim      if (log)
187314564Sdim        log->Printf(
188314564Sdim            "HostInfoBase::GetLLDBPath(ePathTypeClangResourceDir) => '%s'",
189314564Sdim            g_fields->m_lldb_clang_resource_dir.GetPath().c_str());
190314564Sdim    });
191314564Sdim    if (success)
192314564Sdim      result = &g_fields->m_lldb_clang_resource_dir;
193314564Sdim  } break;
194314564Sdim  case lldb::ePathTypeLLDBSystemPlugins: {
195321369Sdim    static llvm::once_flag g_once_flag;
196314564Sdim    static bool success = false;
197321369Sdim    llvm::call_once(g_once_flag, []() {
198314564Sdim      success = HostInfo::ComputeSystemPluginsDirectory(
199314564Sdim          g_fields->m_lldb_system_plugin_dir);
200314564Sdim      Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
201314564Sdim      if (log)
202314564Sdim        log->Printf(
203314564Sdim            "HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'",
204314564Sdim            g_fields->m_lldb_system_plugin_dir.GetPath().c_str());
205314564Sdim    });
206314564Sdim    if (success)
207314564Sdim      result = &g_fields->m_lldb_system_plugin_dir;
208314564Sdim  } break;
209314564Sdim  case lldb::ePathTypeLLDBUserPlugins: {
210321369Sdim    static llvm::once_flag g_once_flag;
211314564Sdim    static bool success = false;
212321369Sdim    llvm::call_once(g_once_flag, []() {
213314564Sdim      success = HostInfo::ComputeUserPluginsDirectory(
214314564Sdim          g_fields->m_lldb_user_plugin_dir);
215314564Sdim      Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
216314564Sdim      if (log)
217314564Sdim        log->Printf(
218314564Sdim            "HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'",
219314564Sdim            g_fields->m_lldb_user_plugin_dir.GetPath().c_str());
220314564Sdim    });
221314564Sdim    if (success)
222314564Sdim      result = &g_fields->m_lldb_user_plugin_dir;
223314564Sdim  } break;
224314564Sdim  case lldb::ePathTypeLLDBTempSystemDir: {
225321369Sdim    static llvm::once_flag g_once_flag;
226314564Sdim    static bool success = false;
227321369Sdim    llvm::call_once(g_once_flag, []() {
228314564Sdim      success = HostInfo::ComputeProcessTempFileDirectory(
229314564Sdim          g_fields->m_lldb_process_tmp_dir);
230314564Sdim      Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
231314564Sdim      if (log)
232314564Sdim        log->Printf(
233314564Sdim            "HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'",
234314564Sdim            g_fields->m_lldb_process_tmp_dir.GetPath().c_str());
235314564Sdim    });
236314564Sdim    if (success)
237314564Sdim      result = &g_fields->m_lldb_process_tmp_dir;
238314564Sdim  } break;
239314564Sdim  case lldb::ePathTypeGlobalLLDBTempSystemDir: {
240321369Sdim    static llvm::once_flag g_once_flag;
241314564Sdim    static bool success = false;
242321369Sdim    llvm::call_once(g_once_flag, []() {
243314564Sdim      success = HostInfo::ComputeGlobalTempFileDirectory(
244314564Sdim          g_fields->m_lldb_global_tmp_dir);
245314564Sdim      Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
246314564Sdim      if (log)
247314564Sdim        log->Printf("HostInfoBase::GetLLDBPath("
248314564Sdim                    "ePathTypeGlobalLLDBTempSystemDir) => '%s'",
249314564Sdim                    g_fields->m_lldb_global_tmp_dir.GetPath().c_str());
250314564Sdim    });
251314564Sdim    if (success)
252314564Sdim      result = &g_fields->m_lldb_global_tmp_dir;
253314564Sdim  } break;
254314564Sdim  }
255275072Semaste
256314564Sdim  if (!result)
257314564Sdim    return false;
258314564Sdim  file_spec = *result;
259314564Sdim  return true;
260275072Semaste}
261275072Semaste
262327952SdimArchSpec HostInfoBase::GetAugmentedArchSpec(llvm::StringRef triple) {
263327952Sdim  if (triple.empty())
264327952Sdim    return ArchSpec();
265327952Sdim  llvm::Triple normalized_triple(llvm::Triple::normalize(triple));
266327952Sdim  if (!ArchSpec::ContainsOnlyArch(normalized_triple))
267327952Sdim    return ArchSpec(triple);
268327952Sdim
269327952Sdim  if (auto kind = HostInfo::ParseArchitectureKind(triple))
270327952Sdim    return HostInfo::GetArchitecture(*kind);
271327952Sdim
272327952Sdim  llvm::Triple host_triple(llvm::sys::getDefaultTargetTriple());
273327952Sdim
274327952Sdim  if (normalized_triple.getVendorName().empty())
275327952Sdim    normalized_triple.setVendor(host_triple.getVendor());
276327952Sdim  if (normalized_triple.getOSName().empty())
277327952Sdim    normalized_triple.setOS(host_triple.getOS());
278327952Sdim  if (normalized_triple.getEnvironmentName().empty())
279327952Sdim    normalized_triple.setEnvironment(host_triple.getEnvironment());
280327952Sdim  return ArchSpec(normalized_triple);
281327952Sdim}
282327952Sdim
283314564Sdimbool HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) {
284314564Sdim  // To get paths related to LLDB we get the path to the executable that
285314564Sdim  // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB",
286314564Sdim  // on linux this is assumed to be the "lldb" main executable. If LLDB on
287314564Sdim  // linux is actually in a shared library (liblldb.so) then this function will
288314564Sdim  // need to be modified to "do the right thing".
289275072Semaste
290314564Sdim  FileSpec lldb_file_spec(
291314564Sdim      Host::GetModuleFileSpecForHostAddress(reinterpret_cast<void *>(
292314564Sdim          reinterpret_cast<intptr_t>(HostInfoBase::GetLLDBPath))));
293275072Semaste
294314564Sdim  // This is necessary because when running the testsuite the shlib might be a
295314564Sdim  // symbolic link inside the Python resource dir.
296314564Sdim  FileSystem::ResolveSymbolicLink(lldb_file_spec, lldb_file_spec);
297314564Sdim
298314564Sdim  // Remove the filename so that this FileSpec only represents the directory.
299314564Sdim  file_spec.GetDirectory() = lldb_file_spec.GetDirectory();
300314564Sdim
301314564Sdim  return (bool)file_spec.GetDirectory();
302275072Semaste}
303275072Semaste
304314564Sdimbool HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec) {
305314564Sdim  return GetLLDBPath(lldb::ePathTypeLLDBShlibDir, file_spec);
306275072Semaste}
307275072Semaste
308314564Sdimbool HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec) {
309314564Sdim  FileSpec temp_file_spec;
310314564Sdim  if (!HostInfo::ComputeGlobalTempFileDirectory(temp_file_spec))
311314564Sdim    return false;
312288943Sdim
313314564Sdim  std::string pid_str{llvm::to_string(Host::GetCurrentProcessID())};
314314564Sdim  temp_file_spec.AppendPathComponent(pid_str);
315321369Sdim  if (llvm::sys::fs::create_directory(temp_file_spec.GetPath()))
316314564Sdim    return false;
317288943Sdim
318314564Sdim  file_spec.GetDirectory().SetCString(temp_file_spec.GetCString());
319314564Sdim  return true;
320288943Sdim}
321288943Sdim
322314564Sdimbool HostInfoBase::ComputeTempFileBaseDirectory(FileSpec &file_spec) {
323314564Sdim  llvm::SmallVector<char, 16> tmpdir;
324314564Sdim  llvm::sys::path::system_temp_directory(/*ErasedOnReboot*/ true, tmpdir);
325314564Sdim  file_spec = FileSpec(std::string(tmpdir.data(), tmpdir.size()), true);
326314564Sdim  return true;
327288943Sdim}
328288943Sdim
329314564Sdimbool HostInfoBase::ComputeGlobalTempFileDirectory(FileSpec &file_spec) {
330314564Sdim  file_spec.Clear();
331288943Sdim
332314564Sdim  FileSpec temp_file_spec;
333314564Sdim  if (!HostInfo::ComputeTempFileBaseDirectory(temp_file_spec))
334314564Sdim    return false;
335275072Semaste
336314564Sdim  temp_file_spec.AppendPathComponent("lldb");
337321369Sdim  if (llvm::sys::fs::create_directory(temp_file_spec.GetPath()))
338314564Sdim    return false;
339275072Semaste
340314564Sdim  file_spec.GetDirectory().SetCString(temp_file_spec.GetCString());
341314564Sdim  return true;
342275072Semaste}
343275072Semaste
344314564Sdimbool HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec) {
345314564Sdim  // TODO(zturner): Figure out how to compute the header directory for all
346314564Sdim  // platforms.
347314564Sdim  return false;
348275072Semaste}
349275072Semaste
350314564Sdimbool HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec) {
351314564Sdim  // TODO(zturner): Figure out how to compute the system plugins directory for
352314564Sdim  // all platforms.
353314564Sdim  return false;
354275072Semaste}
355275072Semaste
356314564Sdimbool HostInfoBase::ComputeClangDirectory(FileSpec &file_spec) { return false; }
357280031Sdim
358314564Sdimbool HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec) {
359314564Sdim  // TODO(zturner): Figure out how to compute the user plugins directory for all
360314564Sdim  // platforms.
361314564Sdim  return false;
362275072Semaste}
363275072Semaste
364314564Sdimvoid HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32,
365314564Sdim                                                  ArchSpec &arch_64) {
366314564Sdim  llvm::Triple triple(llvm::sys::getProcessTriple());
367275072Semaste
368314564Sdim  arch_32.Clear();
369314564Sdim  arch_64.Clear();
370275072Semaste
371314564Sdim  switch (triple.getArch()) {
372314564Sdim  default:
373314564Sdim    arch_32.SetTriple(triple);
374314564Sdim    break;
375275072Semaste
376314564Sdim  case llvm::Triple::aarch64:
377314564Sdim  case llvm::Triple::ppc64:
378314564Sdim  case llvm::Triple::x86_64:
379314564Sdim    arch_64.SetTriple(triple);
380314564Sdim    arch_32.SetTriple(triple.get32BitArchVariant());
381314564Sdim    break;
382275072Semaste
383314564Sdim  case llvm::Triple::mips64:
384314564Sdim  case llvm::Triple::mips64el:
385314564Sdim  case llvm::Triple::sparcv9:
386314564Sdim  case llvm::Triple::systemz:
387314564Sdim    arch_64.SetTriple(triple);
388314564Sdim    break;
389314564Sdim  }
390275072Semaste}
391