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;
35 CleanupProcessSpecificLLDBTempDir()
37 // Get the process specific LLDB temporary directory and delete it.
38 FileSpec tmpdir_file_spec;
39 if (!HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
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);
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 //----------------------------------------------------------------------
55 struct HostInfoBaseFields
57 uint32_t m_number_cpus;
58 std::string m_vendor_string;
59 std::string m_os_string;
60 std::string m_host_triple;
62 ArchSpec m_host_arch_32;
63 ArchSpec m_host_arch_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;
76 HostInfoBaseFields *g_fields = nullptr;
80 HostInfoBase::Initialize()
82 g_fields = new HostInfoBaseFields();
86 HostInfoBase::GetNumberCPUS()
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();
92 return g_fields->m_number_cpus;
96 HostInfoBase::GetMaxThreadNameLength()
102 HostInfoBase::GetVendorString()
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();
108 return g_fields->m_vendor_string;
112 HostInfoBase::GetOSString()
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());
118 return g_fields->m_os_string;
122 HostInfoBase::GetTargetTriple()
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();
128 return g_fields->m_host_triple;
132 HostInfoBase::GetArchitecture(ArchitectureKind arch_kind)
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);
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;
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;
150 HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec)
154 #if defined(LLDB_DISABLE_PYTHON)
155 if (type == lldb::ePathTypePythonDir)
159 FileSpec *result = nullptr;
162 case lldb::ePathTypeLLDBShlibDir:
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);
170 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", g_fields->m_lldb_so_dir.GetPath().c_str());
173 result = &g_fields->m_lldb_so_dir;
176 case lldb::ePathTypeSupportExecutableDir:
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);
184 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'",
185 g_fields->m_lldb_support_exe_dir.GetPath().c_str());
188 result = &g_fields->m_lldb_support_exe_dir;
191 case lldb::ePathTypeHeaderDir:
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);
199 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'", g_fields->m_lldb_headers_dir.GetPath().c_str());
202 result = &g_fields->m_lldb_headers_dir;
205 case lldb::ePathTypePythonDir:
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);
213 log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'", g_fields->m_lldb_python_dir.GetPath().c_str());
216 result = &g_fields->m_lldb_python_dir;
219 case lldb::ePathTypeClangDir:
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);
227 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeClangResourceDir) => '%s'", g_fields->m_lldb_clang_resource_dir.GetPath().c_str());
230 result = &g_fields->m_lldb_clang_resource_dir;
233 case lldb::ePathTypeLLDBSystemPlugins:
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);
241 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'",
242 g_fields->m_lldb_system_plugin_dir.GetPath().c_str());
245 result = &g_fields->m_lldb_system_plugin_dir;
248 case lldb::ePathTypeLLDBUserPlugins:
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);
256 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'",
257 g_fields->m_lldb_user_plugin_dir.GetPath().c_str());
260 result = &g_fields->m_lldb_user_plugin_dir;
263 case lldb::ePathTypeLLDBTempSystemDir:
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);
271 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", g_fields->m_lldb_process_tmp_dir.GetPath().c_str());
274 result = &g_fields->m_lldb_process_tmp_dir;
277 case lldb::ePathTypeGlobalLLDBTempSystemDir:
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);
285 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeGlobalLLDBTempSystemDir) => '%s'", g_fields->m_lldb_global_tmp_dir.GetPath().c_str());
288 result = &g_fields->m_lldb_global_tmp_dir;
300 HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec)
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".
308 FileSpec lldb_file_spec(
309 Host::GetModuleFileSpecForHostAddress(reinterpret_cast<void *>(reinterpret_cast<intptr_t>(HostInfoBase::GetLLDBPath))));
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);
314 // Remove the filename so that this FileSpec only represents the directory.
315 file_spec.GetDirectory() = lldb_file_spec.GetDirectory();
317 return (bool)file_spec.GetDirectory();
321 HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec)
323 return GetLLDBPath(lldb::ePathTypeLLDBShlibDir, file_spec);
327 HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec)
329 FileSpec temp_file_spec;
330 if (!HostInfo::ComputeGlobalTempFileDirectory(temp_file_spec))
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())
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());
346 HostInfoBase::ComputeTempFileBaseDirectory(FileSpec &file_spec)
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);
355 HostInfoBase::ComputeGlobalTempFileDirectory(FileSpec &file_spec)
359 FileSpec temp_file_spec;
360 if (!HostInfo::ComputeTempFileBaseDirectory(temp_file_spec))
363 temp_file_spec.AppendPathComponent("lldb");
364 if (!FileSystem::MakeDirectory(temp_file_spec, eFilePermissionsDirectoryDefault).Success())
367 file_spec.GetDirectory().SetCString(temp_file_spec.GetCString());
372 HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec)
374 // TODO(zturner): Figure out how to compute the header directory for all platforms.
379 HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec)
381 // TODO(zturner): Figure out how to compute the system plugins directory for all platforms.
386 HostInfoBase::ComputeClangDirectory(FileSpec &file_spec)
392 HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec)
394 // TODO(zturner): Figure out how to compute the user plugins directory for all platforms.
399 HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64)
401 llvm::Triple triple(llvm::sys::getProcessTriple());
406 switch (triple.getArch())
409 arch_32.SetTriple(triple);
412 case llvm::Triple::ppc64:
413 case llvm::Triple::x86_64:
414 arch_64.SetTriple(triple);
415 arch_32.SetTriple(triple.get32BitArchVariant());
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);