1 //===-- HostInfoBase.cpp ----------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/Host/Config.h"
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"
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"
27 #include <mutex> // std::once
30 using namespace lldb_private;
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 //----------------------------------------------------------------------
42 struct HostInfoBaseFields
46 if (m_lldb_process_tmp_dir.Exists())
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);
54 uint32_t m_number_cpus;
55 std::string m_vendor_string;
56 std::string m_os_string;
57 std::string m_host_triple;
59 ArchSpec m_host_arch_32;
60 ArchSpec m_host_arch_64;
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;
73 HostInfoBaseFields *g_fields = nullptr;
77 HostInfoBase::Initialize()
79 g_fields = new HostInfoBaseFields();
83 HostInfoBase::Terminate()
90 HostInfoBase::GetNumberCPUS()
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();
96 return g_fields->m_number_cpus;
100 HostInfoBase::GetMaxThreadNameLength()
106 HostInfoBase::GetVendorString()
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();
112 return g_fields->m_vendor_string;
116 HostInfoBase::GetOSString()
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());
122 return g_fields->m_os_string;
126 HostInfoBase::GetTargetTriple()
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();
132 return g_fields->m_host_triple;
136 HostInfoBase::GetArchitecture(ArchitectureKind arch_kind)
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);
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;
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;
154 HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec)
158 #if defined(LLDB_DISABLE_PYTHON)
159 if (type == lldb::ePathTypePythonDir)
163 FileSpec *result = nullptr;
166 case lldb::ePathTypeLLDBShlibDir:
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);
174 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", g_fields->m_lldb_so_dir.GetPath().c_str());
177 result = &g_fields->m_lldb_so_dir;
180 case lldb::ePathTypeSupportExecutableDir:
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);
188 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'",
189 g_fields->m_lldb_support_exe_dir.GetPath().c_str());
192 result = &g_fields->m_lldb_support_exe_dir;
195 case lldb::ePathTypeHeaderDir:
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);
203 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'", g_fields->m_lldb_headers_dir.GetPath().c_str());
206 result = &g_fields->m_lldb_headers_dir;
209 case lldb::ePathTypePythonDir:
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);
217 log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'", g_fields->m_lldb_python_dir.GetPath().c_str());
220 result = &g_fields->m_lldb_python_dir;
223 case lldb::ePathTypeClangDir:
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);
231 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeClangResourceDir) => '%s'", g_fields->m_lldb_clang_resource_dir.GetPath().c_str());
234 result = &g_fields->m_lldb_clang_resource_dir;
237 case lldb::ePathTypeLLDBSystemPlugins:
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);
245 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'",
246 g_fields->m_lldb_system_plugin_dir.GetPath().c_str());
249 result = &g_fields->m_lldb_system_plugin_dir;
252 case lldb::ePathTypeLLDBUserPlugins:
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);
260 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'",
261 g_fields->m_lldb_user_plugin_dir.GetPath().c_str());
264 result = &g_fields->m_lldb_user_plugin_dir;
267 case lldb::ePathTypeLLDBTempSystemDir:
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);
275 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", g_fields->m_lldb_process_tmp_dir.GetPath().c_str());
278 result = &g_fields->m_lldb_process_tmp_dir;
281 case lldb::ePathTypeGlobalLLDBTempSystemDir:
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);
289 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeGlobalLLDBTempSystemDir) => '%s'", g_fields->m_lldb_global_tmp_dir.GetPath().c_str());
292 result = &g_fields->m_lldb_global_tmp_dir;
304 HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec)
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".
312 FileSpec lldb_file_spec(
313 Host::GetModuleFileSpecForHostAddress(reinterpret_cast<void *>(reinterpret_cast<intptr_t>(HostInfoBase::GetLLDBPath))));
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);
318 // Remove the filename so that this FileSpec only represents the directory.
319 file_spec.GetDirectory() = lldb_file_spec.GetDirectory();
321 return (bool)file_spec.GetDirectory();
325 HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec)
327 return GetLLDBPath(lldb::ePathTypeLLDBShlibDir, file_spec);
331 HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec)
333 FileSpec temp_file_spec;
334 if (!HostInfo::ComputeGlobalTempFileDirectory(temp_file_spec))
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())
342 file_spec.GetDirectory().SetCString(temp_file_spec.GetCString());
347 HostInfoBase::ComputeTempFileBaseDirectory(FileSpec &file_spec)
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);
356 HostInfoBase::ComputeGlobalTempFileDirectory(FileSpec &file_spec)
360 FileSpec temp_file_spec;
361 if (!HostInfo::ComputeTempFileBaseDirectory(temp_file_spec))
364 temp_file_spec.AppendPathComponent("lldb");
365 if (!FileSystem::MakeDirectory(temp_file_spec, eFilePermissionsDirectoryDefault).Success())
368 file_spec.GetDirectory().SetCString(temp_file_spec.GetCString());
373 HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec)
375 // TODO(zturner): Figure out how to compute the header directory for all platforms.
380 HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec)
382 // TODO(zturner): Figure out how to compute the system plugins directory for all platforms.
387 HostInfoBase::ComputeClangDirectory(FileSpec &file_spec)
393 HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec)
395 // TODO(zturner): Figure out how to compute the user plugins directory for all platforms.
400 HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64)
402 llvm::Triple triple(llvm::sys::getProcessTriple());
407 switch (triple.getArch())
410 arch_32.SetTriple(triple);
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());
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);