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