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