]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/Host/common/HostInfoBase.cpp
Vendor import of lldb trunk r290819:
[FreeBSD/FreeBSD.git] / source / Host / common / HostInfoBase.cpp
1 //===-- HostInfoBase.cpp ----------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/Host/Config.h"
11
12 #include "lldb/Core/ArchSpec.h"
13 #include "lldb/Core/Log.h"
14 #include "lldb/Core/StreamString.h"
15 #include "lldb/Host/FileSystem.h"
16 #include "lldb/Host/Host.h"
17 #include "lldb/Host/HostInfo.h"
18 #include "lldb/Host/HostInfoBase.h"
19
20 #include "llvm/ADT/StringExtras.h"
21 #include "llvm/ADT/Triple.h"
22 #include "llvm/Support/Host.h"
23 #include "llvm/Support/Path.h"
24 #include "llvm/Support/ScopedPrinter.h"
25 #include "llvm/Support/raw_ostream.h"
26
27 #include <mutex> // std::once
28 #include <thread>
29
30 using namespace lldb;
31 using namespace lldb_private;
32
33 namespace {
34 //----------------------------------------------------------------------
35 // The HostInfoBaseFields is a work around for windows not supporting
36 // static variables correctly in a thread safe way. Really each of the
37 // variables in HostInfoBaseFields should live in the functions in which
38 // they are used and each one should be static, but the work around is
39 // in place to avoid this restriction. Ick.
40 //----------------------------------------------------------------------
41
42 struct HostInfoBaseFields {
43   ~HostInfoBaseFields() {
44     if (m_lldb_process_tmp_dir.Exists()) {
45       // Remove the LLDB temporary directory if we have one. Set "recurse" to
46       // true to all files that were created for the LLDB process can be cleaned
47       // up.
48       FileSystem::DeleteDirectory(m_lldb_process_tmp_dir, true);
49     }
50   }
51
52   uint32_t m_number_cpus;
53   std::string m_vendor_string;
54   std::string m_os_string;
55   std::string m_host_triple;
56
57   ArchSpec m_host_arch_32;
58   ArchSpec m_host_arch_64;
59
60   FileSpec m_lldb_so_dir;
61   FileSpec m_lldb_support_exe_dir;
62   FileSpec m_lldb_headers_dir;
63   FileSpec m_lldb_python_dir;
64   FileSpec m_lldb_clang_resource_dir;
65   FileSpec m_lldb_system_plugin_dir;
66   FileSpec m_lldb_user_plugin_dir;
67   FileSpec m_lldb_process_tmp_dir;
68   FileSpec m_lldb_global_tmp_dir;
69 };
70
71 HostInfoBaseFields *g_fields = nullptr;
72 }
73
74 void HostInfoBase::Initialize() { g_fields = new HostInfoBaseFields(); }
75
76 void HostInfoBase::Terminate() {
77   delete g_fields;
78   g_fields = nullptr;
79 }
80
81 uint32_t HostInfoBase::GetNumberCPUS() {
82   static std::once_flag g_once_flag;
83   std::call_once(g_once_flag, []() {
84     g_fields->m_number_cpus = std::thread::hardware_concurrency();
85   });
86   return g_fields->m_number_cpus;
87 }
88
89 uint32_t HostInfoBase::GetMaxThreadNameLength() { return 0; }
90
91 llvm::StringRef HostInfoBase::GetVendorString() {
92   static std::once_flag g_once_flag;
93   std::call_once(g_once_flag, []() {
94     g_fields->m_vendor_string =
95         HostInfo::GetArchitecture().GetTriple().getVendorName().str();
96   });
97   return g_fields->m_vendor_string;
98 }
99
100 llvm::StringRef HostInfoBase::GetOSString() {
101   static std::once_flag g_once_flag;
102   std::call_once(g_once_flag, []() {
103     g_fields->m_os_string =
104         std::move(HostInfo::GetArchitecture().GetTriple().getOSName());
105   });
106   return g_fields->m_os_string;
107 }
108
109 llvm::StringRef HostInfoBase::GetTargetTriple() {
110   static std::once_flag g_once_flag;
111   std::call_once(g_once_flag, []() {
112     g_fields->m_host_triple =
113         HostInfo::GetArchitecture().GetTriple().getTriple();
114   });
115   return g_fields->m_host_triple;
116 }
117
118 const ArchSpec &HostInfoBase::GetArchitecture(ArchitectureKind arch_kind) {
119   static std::once_flag g_once_flag;
120   std::call_once(g_once_flag, []() {
121     HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32,
122                                              g_fields->m_host_arch_64);
123   });
124
125   // If an explicit 32 or 64-bit architecture was requested, return that.
126   if (arch_kind == eArchKind32)
127     return g_fields->m_host_arch_32;
128   if (arch_kind == eArchKind64)
129     return g_fields->m_host_arch_64;
130
131   // Otherwise prefer the 64-bit architecture if it is valid.
132   return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64
133                                               : g_fields->m_host_arch_32;
134 }
135
136 bool HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) {
137   file_spec.Clear();
138
139 #if defined(LLDB_DISABLE_PYTHON)
140   if (type == lldb::ePathTypePythonDir)
141     return false;
142 #endif
143
144   FileSpec *result = nullptr;
145   switch (type) {
146   case lldb::ePathTypeLLDBShlibDir: {
147     static std::once_flag g_once_flag;
148     static bool success = false;
149     std::call_once(g_once_flag, []() {
150       success =
151           HostInfo::ComputeSharedLibraryDirectory(g_fields->m_lldb_so_dir);
152       Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
153       if (log)
154         log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'",
155                     g_fields->m_lldb_so_dir.GetPath().c_str());
156     });
157     if (success)
158       result = &g_fields->m_lldb_so_dir;
159   } break;
160   case lldb::ePathTypeSupportExecutableDir: {
161     static std::once_flag g_once_flag;
162     static bool success = false;
163     std::call_once(g_once_flag, []() {
164       success = HostInfo::ComputeSupportExeDirectory(
165           g_fields->m_lldb_support_exe_dir);
166       Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
167       if (log)
168         log->Printf(
169             "HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'",
170             g_fields->m_lldb_support_exe_dir.GetPath().c_str());
171     });
172     if (success)
173       result = &g_fields->m_lldb_support_exe_dir;
174   } break;
175   case lldb::ePathTypeHeaderDir: {
176     static std::once_flag g_once_flag;
177     static bool success = false;
178     std::call_once(g_once_flag, []() {
179       success = HostInfo::ComputeHeaderDirectory(g_fields->m_lldb_headers_dir);
180       Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
181       if (log)
182         log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'",
183                     g_fields->m_lldb_headers_dir.GetPath().c_str());
184     });
185     if (success)
186       result = &g_fields->m_lldb_headers_dir;
187   } break;
188   case lldb::ePathTypePythonDir: {
189     static std::once_flag g_once_flag;
190     static bool success = false;
191     std::call_once(g_once_flag, []() {
192       success = HostInfo::ComputePythonDirectory(g_fields->m_lldb_python_dir);
193       Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
194       if (log)
195         log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'",
196                     g_fields->m_lldb_python_dir.GetPath().c_str());
197     });
198     if (success)
199       result = &g_fields->m_lldb_python_dir;
200   } break;
201   case lldb::ePathTypeClangDir: {
202     static std::once_flag g_once_flag;
203     static bool success = false;
204     std::call_once(g_once_flag, []() {
205       success =
206           HostInfo::ComputeClangDirectory(g_fields->m_lldb_clang_resource_dir);
207       Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
208       if (log)
209         log->Printf(
210             "HostInfoBase::GetLLDBPath(ePathTypeClangResourceDir) => '%s'",
211             g_fields->m_lldb_clang_resource_dir.GetPath().c_str());
212     });
213     if (success)
214       result = &g_fields->m_lldb_clang_resource_dir;
215   } break;
216   case lldb::ePathTypeLLDBSystemPlugins: {
217     static std::once_flag g_once_flag;
218     static bool success = false;
219     std::call_once(g_once_flag, []() {
220       success = HostInfo::ComputeSystemPluginsDirectory(
221           g_fields->m_lldb_system_plugin_dir);
222       Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
223       if (log)
224         log->Printf(
225             "HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'",
226             g_fields->m_lldb_system_plugin_dir.GetPath().c_str());
227     });
228     if (success)
229       result = &g_fields->m_lldb_system_plugin_dir;
230   } break;
231   case lldb::ePathTypeLLDBUserPlugins: {
232     static std::once_flag g_once_flag;
233     static bool success = false;
234     std::call_once(g_once_flag, []() {
235       success = HostInfo::ComputeUserPluginsDirectory(
236           g_fields->m_lldb_user_plugin_dir);
237       Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
238       if (log)
239         log->Printf(
240             "HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'",
241             g_fields->m_lldb_user_plugin_dir.GetPath().c_str());
242     });
243     if (success)
244       result = &g_fields->m_lldb_user_plugin_dir;
245   } break;
246   case lldb::ePathTypeLLDBTempSystemDir: {
247     static std::once_flag g_once_flag;
248     static bool success = false;
249     std::call_once(g_once_flag, []() {
250       success = HostInfo::ComputeProcessTempFileDirectory(
251           g_fields->m_lldb_process_tmp_dir);
252       Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
253       if (log)
254         log->Printf(
255             "HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'",
256             g_fields->m_lldb_process_tmp_dir.GetPath().c_str());
257     });
258     if (success)
259       result = &g_fields->m_lldb_process_tmp_dir;
260   } break;
261   case lldb::ePathTypeGlobalLLDBTempSystemDir: {
262     static std::once_flag g_once_flag;
263     static bool success = false;
264     std::call_once(g_once_flag, []() {
265       success = HostInfo::ComputeGlobalTempFileDirectory(
266           g_fields->m_lldb_global_tmp_dir);
267       Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
268       if (log)
269         log->Printf("HostInfoBase::GetLLDBPath("
270                     "ePathTypeGlobalLLDBTempSystemDir) => '%s'",
271                     g_fields->m_lldb_global_tmp_dir.GetPath().c_str());
272     });
273     if (success)
274       result = &g_fields->m_lldb_global_tmp_dir;
275   } break;
276   }
277
278   if (!result)
279     return false;
280   file_spec = *result;
281   return true;
282 }
283
284 bool HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) {
285   // To get paths related to LLDB we get the path to the executable that
286   // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB",
287   // on linux this is assumed to be the "lldb" main executable. If LLDB on
288   // linux is actually in a shared library (liblldb.so) then this function will
289   // need to be modified to "do the right thing".
290
291   FileSpec lldb_file_spec(
292       Host::GetModuleFileSpecForHostAddress(reinterpret_cast<void *>(
293           reinterpret_cast<intptr_t>(HostInfoBase::GetLLDBPath))));
294
295   // This is necessary because when running the testsuite the shlib might be a
296   // symbolic link inside the Python resource dir.
297   FileSystem::ResolveSymbolicLink(lldb_file_spec, lldb_file_spec);
298
299   // Remove the filename so that this FileSpec only represents the directory.
300   file_spec.GetDirectory() = lldb_file_spec.GetDirectory();
301
302   return (bool)file_spec.GetDirectory();
303 }
304
305 bool HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec) {
306   return GetLLDBPath(lldb::ePathTypeLLDBShlibDir, file_spec);
307 }
308
309 bool HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec) {
310   FileSpec temp_file_spec;
311   if (!HostInfo::ComputeGlobalTempFileDirectory(temp_file_spec))
312     return false;
313
314   std::string pid_str{llvm::to_string(Host::GetCurrentProcessID())};
315   temp_file_spec.AppendPathComponent(pid_str);
316   if (!FileSystem::MakeDirectory(temp_file_spec,
317                                  eFilePermissionsDirectoryDefault)
318            .Success())
319     return false;
320
321   file_spec.GetDirectory().SetCString(temp_file_spec.GetCString());
322   return true;
323 }
324
325 bool HostInfoBase::ComputeTempFileBaseDirectory(FileSpec &file_spec) {
326   llvm::SmallVector<char, 16> tmpdir;
327   llvm::sys::path::system_temp_directory(/*ErasedOnReboot*/ true, tmpdir);
328   file_spec = FileSpec(std::string(tmpdir.data(), tmpdir.size()), true);
329   return true;
330 }
331
332 bool HostInfoBase::ComputeGlobalTempFileDirectory(FileSpec &file_spec) {
333   file_spec.Clear();
334
335   FileSpec temp_file_spec;
336   if (!HostInfo::ComputeTempFileBaseDirectory(temp_file_spec))
337     return false;
338
339   temp_file_spec.AppendPathComponent("lldb");
340   if (!FileSystem::MakeDirectory(temp_file_spec,
341                                  eFilePermissionsDirectoryDefault)
342            .Success())
343     return false;
344
345   file_spec.GetDirectory().SetCString(temp_file_spec.GetCString());
346   return true;
347 }
348
349 bool HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec) {
350   // TODO(zturner): Figure out how to compute the header directory for all
351   // platforms.
352   return false;
353 }
354
355 bool HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec) {
356   // TODO(zturner): Figure out how to compute the system plugins directory for
357   // all platforms.
358   return false;
359 }
360
361 bool HostInfoBase::ComputeClangDirectory(FileSpec &file_spec) { return false; }
362
363 bool HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec) {
364   // TODO(zturner): Figure out how to compute the user plugins directory for all
365   // platforms.
366   return false;
367 }
368
369 void HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32,
370                                                   ArchSpec &arch_64) {
371   llvm::Triple triple(llvm::sys::getProcessTriple());
372
373   arch_32.Clear();
374   arch_64.Clear();
375
376   switch (triple.getArch()) {
377   default:
378     arch_32.SetTriple(triple);
379     break;
380
381   case llvm::Triple::aarch64:
382   case llvm::Triple::ppc64:
383   case llvm::Triple::x86_64:
384     arch_64.SetTriple(triple);
385     arch_32.SetTriple(triple.get32BitArchVariant());
386     break;
387
388   case llvm::Triple::mips64:
389   case llvm::Triple::mips64el:
390   case llvm::Triple::sparcv9:
391   case llvm::Triple::systemz:
392     arch_64.SetTriple(triple);
393     break;
394   }
395 }