197a14e60SZachary Turner //===-- HostInfoBase.cpp ----------------------------------------*- C++ -*-===//
297a14e60SZachary Turner //
397a14e60SZachary Turner //                     The LLVM Compiler Infrastructure
497a14e60SZachary Turner //
597a14e60SZachary Turner // This file is distributed under the University of Illinois Open Source
697a14e60SZachary Turner // License. See LICENSE.TXT for details.
797a14e60SZachary Turner //
897a14e60SZachary Turner //===----------------------------------------------------------------------===//
997a14e60SZachary Turner 
1097a14e60SZachary Turner #include "lldb/Host/Config.h"
1197a14e60SZachary Turner 
1297a14e60SZachary Turner #include "lldb/Core/ArchSpec.h"
1342ff0ad8SZachary Turner #include "lldb/Core/Log.h"
1442ff0ad8SZachary Turner #include "lldb/Core/StreamString.h"
1542ff0ad8SZachary Turner #include "lldb/Host/FileSystem.h"
1697a14e60SZachary Turner #include "lldb/Host/Host.h"
1713b18261SZachary Turner #include "lldb/Host/HostInfo.h"
1813b18261SZachary Turner #include "lldb/Host/HostInfoBase.h"
1913b18261SZachary Turner 
2013b18261SZachary Turner #include "llvm/ADT/Triple.h"
2113b18261SZachary Turner #include "llvm/Support/Host.h"
2297a14e60SZachary Turner 
2397a14e60SZachary Turner #include <thread>
2497a14e60SZachary Turner 
2597a14e60SZachary Turner using namespace lldb;
2697a14e60SZachary Turner using namespace lldb_private;
2797a14e60SZachary Turner 
2842ff0ad8SZachary Turner namespace
2942ff0ad8SZachary Turner {
3042ff0ad8SZachary Turner void
3142ff0ad8SZachary Turner CleanupProcessSpecificLLDBTempDir()
3242ff0ad8SZachary Turner {
3342ff0ad8SZachary Turner     // Get the process specific LLDB temporary directory and delete it.
3442ff0ad8SZachary Turner     FileSpec tmpdir_file_spec;
3542ff0ad8SZachary Turner     if (!HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
3642ff0ad8SZachary Turner         return;
3742ff0ad8SZachary Turner 
3842ff0ad8SZachary Turner     // Remove the LLDB temporary directory if we have one. Set "recurse" to
3942ff0ad8SZachary Turner     // true to all files that were created for the LLDB process can be cleaned up.
4042ff0ad8SZachary Turner     FileSystem::DeleteDirectory(tmpdir_file_spec.GetDirectory().GetCString(), true);
4142ff0ad8SZachary Turner }
42673b6e4fSZachary Turner 
43673b6e4fSZachary Turner struct HostInfoBaseFields
44673b6e4fSZachary Turner {
45673b6e4fSZachary Turner     uint32_t m_number_cpus;
46673b6e4fSZachary Turner     std::string m_vendor_string;
47673b6e4fSZachary Turner     std::string m_os_string;
48673b6e4fSZachary Turner     std::string m_host_triple;
49673b6e4fSZachary Turner 
50673b6e4fSZachary Turner     ArchSpec m_host_arch_32;
51673b6e4fSZachary Turner     ArchSpec m_host_arch_64;
52673b6e4fSZachary Turner 
53673b6e4fSZachary Turner     FileSpec m_lldb_so_dir;
54673b6e4fSZachary Turner     FileSpec m_lldb_support_exe_dir;
55673b6e4fSZachary Turner     FileSpec m_lldb_headers_dir;
56673b6e4fSZachary Turner     FileSpec m_lldb_python_dir;
57*b1e1c62fSSean Callanan     FileSpec m_lldb_clang_resource_dir;
58673b6e4fSZachary Turner     FileSpec m_lldb_system_plugin_dir;
59673b6e4fSZachary Turner     FileSpec m_lldb_user_plugin_dir;
60673b6e4fSZachary Turner     FileSpec m_lldb_tmp_dir;
61673b6e4fSZachary Turner };
62673b6e4fSZachary Turner 
63673b6e4fSZachary Turner HostInfoBaseFields *g_fields = nullptr;
6442ff0ad8SZachary Turner }
6542ff0ad8SZachary Turner 
6642ff0ad8SZachary Turner #define COMPUTE_LLDB_PATH(compute_function, member_var)                                                                                    \
6742ff0ad8SZachary Turner     {                                                                                                                                      \
6842ff0ad8SZachary Turner         static bool is_initialized = false;                                                                                                \
6942ff0ad8SZachary Turner         static bool success = false;                                                                                                       \
7042ff0ad8SZachary Turner         if (!is_initialized)                                                                                                               \
7142ff0ad8SZachary Turner         {                                                                                                                                  \
7242ff0ad8SZachary Turner             is_initialized = true;                                                                                                         \
7342ff0ad8SZachary Turner             success = HostInfo::compute_function(member_var);                                                                              \
7442ff0ad8SZachary Turner         }                                                                                                                                  \
7542ff0ad8SZachary Turner         if (success)                                                                                                                       \
7642ff0ad8SZachary Turner             result = &member_var;                                                                                                          \
7742ff0ad8SZachary Turner     }
7842ff0ad8SZachary Turner 
79673b6e4fSZachary Turner void
80673b6e4fSZachary Turner HostInfoBase::Initialize()
81673b6e4fSZachary Turner {
82673b6e4fSZachary Turner     g_fields = new HostInfoBaseFields();
83673b6e4fSZachary Turner }
8442ff0ad8SZachary Turner 
8597a14e60SZachary Turner uint32_t
8697a14e60SZachary Turner HostInfoBase::GetNumberCPUS()
8797a14e60SZachary Turner {
8897a14e60SZachary Turner     static bool is_initialized = false;
8997a14e60SZachary Turner     if (!is_initialized)
9097a14e60SZachary Turner     {
91673b6e4fSZachary Turner         g_fields->m_number_cpus = std::thread::hardware_concurrency();
9297a14e60SZachary Turner         is_initialized = true;
9397a14e60SZachary Turner     }
9497a14e60SZachary Turner 
95673b6e4fSZachary Turner     return g_fields->m_number_cpus;
9697a14e60SZachary Turner }
9797a14e60SZachary Turner 
9839de3110SZachary Turner uint32_t
9939de3110SZachary Turner HostInfoBase::GetMaxThreadNameLength()
10039de3110SZachary Turner {
10139de3110SZachary Turner     return 0;
10239de3110SZachary Turner }
10339de3110SZachary Turner 
10497a14e60SZachary Turner llvm::StringRef
10597a14e60SZachary Turner HostInfoBase::GetVendorString()
10697a14e60SZachary Turner {
10797a14e60SZachary Turner     static bool is_initialized = false;
10897a14e60SZachary Turner     if (!is_initialized)
10997a14e60SZachary Turner     {
11013b18261SZachary Turner         const ArchSpec &host_arch = HostInfo::GetArchitecture();
11197a14e60SZachary Turner         const llvm::StringRef &str_ref = host_arch.GetTriple().getVendorName();
112673b6e4fSZachary Turner         g_fields->m_vendor_string.assign(str_ref.begin(), str_ref.end());
11397a14e60SZachary Turner         is_initialized = true;
11497a14e60SZachary Turner     }
115673b6e4fSZachary Turner     return g_fields->m_vendor_string;
11697a14e60SZachary Turner }
11797a14e60SZachary Turner 
11897a14e60SZachary Turner llvm::StringRef
11997a14e60SZachary Turner HostInfoBase::GetOSString()
12097a14e60SZachary Turner {
12197a14e60SZachary Turner     static bool is_initialized = false;
12297a14e60SZachary Turner     if (!is_initialized)
12397a14e60SZachary Turner     {
12413b18261SZachary Turner         const ArchSpec &host_arch = HostInfo::GetArchitecture();
12597a14e60SZachary Turner         const llvm::StringRef &str_ref = host_arch.GetTriple().getOSName();
126673b6e4fSZachary Turner         g_fields->m_os_string.assign(str_ref.begin(), str_ref.end());
12797a14e60SZachary Turner         is_initialized = true;
12897a14e60SZachary Turner     }
129673b6e4fSZachary Turner     return g_fields->m_os_string;
13097a14e60SZachary Turner }
13197a14e60SZachary Turner 
13297a14e60SZachary Turner llvm::StringRef
13397a14e60SZachary Turner HostInfoBase::GetTargetTriple()
13497a14e60SZachary Turner {
13597a14e60SZachary Turner     static bool is_initialized = false;
13697a14e60SZachary Turner     if (!is_initialized)
13797a14e60SZachary Turner     {
13813b18261SZachary Turner         const ArchSpec &host_arch = HostInfo::GetArchitecture();
139673b6e4fSZachary Turner         g_fields->m_host_triple = host_arch.GetTriple().getTriple();
14097a14e60SZachary Turner         is_initialized = true;
14197a14e60SZachary Turner     }
142673b6e4fSZachary Turner     return g_fields->m_host_triple;
14397a14e60SZachary Turner }
14413b18261SZachary Turner 
14513b18261SZachary Turner const ArchSpec &
14613b18261SZachary Turner HostInfoBase::GetArchitecture(ArchitectureKind arch_kind)
14713b18261SZachary Turner {
14813b18261SZachary Turner     static bool is_initialized = false;
14913b18261SZachary Turner     if (!is_initialized)
15013b18261SZachary Turner     {
151673b6e4fSZachary Turner         HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32, g_fields->m_host_arch_64);
15213b18261SZachary Turner         is_initialized = true;
15313b18261SZachary Turner     }
15413b18261SZachary Turner 
15513b18261SZachary Turner     // If an explicit 32 or 64-bit architecture was requested, return that.
15613b18261SZachary Turner     if (arch_kind == eArchKind32)
157673b6e4fSZachary Turner         return g_fields->m_host_arch_32;
15813b18261SZachary Turner     if (arch_kind == eArchKind64)
159673b6e4fSZachary Turner         return g_fields->m_host_arch_64;
16013b18261SZachary Turner 
16113b18261SZachary Turner     // Otherwise prefer the 64-bit architecture if it is valid.
162673b6e4fSZachary Turner     return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64 : g_fields->m_host_arch_32;
16313b18261SZachary Turner }
16413b18261SZachary Turner 
16542ff0ad8SZachary Turner bool
16642ff0ad8SZachary Turner HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec)
16742ff0ad8SZachary Turner {
16842ff0ad8SZachary Turner     file_spec.Clear();
16942ff0ad8SZachary Turner 
17042ff0ad8SZachary Turner #if defined(LLDB_DISABLE_PYTHON)
17142ff0ad8SZachary Turner     if (type == lldb::ePathTypePythonDir)
17242ff0ad8SZachary Turner         return false;
17342ff0ad8SZachary Turner #endif
17442ff0ad8SZachary Turner 
17542ff0ad8SZachary Turner     Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
17642ff0ad8SZachary Turner     FileSpec *result = nullptr;
17742ff0ad8SZachary Turner     switch (type)
17842ff0ad8SZachary Turner     {
17942ff0ad8SZachary Turner         case lldb::ePathTypeLLDBShlibDir:
180673b6e4fSZachary Turner             COMPUTE_LLDB_PATH(ComputeSharedLibraryDirectory, g_fields->m_lldb_so_dir)
18142ff0ad8SZachary Turner             if (log)
182673b6e4fSZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", g_fields->m_lldb_so_dir.GetPath().c_str());
18342ff0ad8SZachary Turner             break;
18442ff0ad8SZachary Turner         case lldb::ePathTypeSupportExecutableDir:
185673b6e4fSZachary Turner             COMPUTE_LLDB_PATH(ComputeSupportExeDirectory, g_fields->m_lldb_support_exe_dir)
18642ff0ad8SZachary Turner             if (log)
187673b6e4fSZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'",
188673b6e4fSZachary Turner                             g_fields->m_lldb_support_exe_dir.GetPath().c_str());
18942ff0ad8SZachary Turner             break;
19042ff0ad8SZachary Turner         case lldb::ePathTypeHeaderDir:
191673b6e4fSZachary Turner             COMPUTE_LLDB_PATH(ComputeHeaderDirectory, g_fields->m_lldb_headers_dir)
19242ff0ad8SZachary Turner             if (log)
193673b6e4fSZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'", g_fields->m_lldb_headers_dir.GetPath().c_str());
19442ff0ad8SZachary Turner             break;
19542ff0ad8SZachary Turner         case lldb::ePathTypePythonDir:
196673b6e4fSZachary Turner             COMPUTE_LLDB_PATH(ComputePythonDirectory, g_fields->m_lldb_python_dir)
19742ff0ad8SZachary Turner             if (log)
198673b6e4fSZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'", g_fields->m_lldb_python_dir.GetPath().c_str());
19942ff0ad8SZachary Turner             break;
200*b1e1c62fSSean Callanan         case lldb::ePathTypeClangDir:
201*b1e1c62fSSean Callanan             COMPUTE_LLDB_PATH(ComputeClangDirectory, g_fields->m_lldb_clang_resource_dir)
202*b1e1c62fSSean Callanan             if (log)
203*b1e1c62fSSean Callanan                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeClangResourceDir) => '%s'", g_fields->m_lldb_clang_resource_dir.GetPath().c_str());
204*b1e1c62fSSean Callanan             break;
20542ff0ad8SZachary Turner         case lldb::ePathTypeLLDBSystemPlugins:
206673b6e4fSZachary Turner             COMPUTE_LLDB_PATH(ComputeSystemPluginsDirectory, g_fields->m_lldb_system_plugin_dir)
20742ff0ad8SZachary Turner             if (log)
208673b6e4fSZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'",
209673b6e4fSZachary Turner                             g_fields->m_lldb_system_plugin_dir.GetPath().c_str());
21042ff0ad8SZachary Turner             break;
21142ff0ad8SZachary Turner         case lldb::ePathTypeLLDBUserPlugins:
212673b6e4fSZachary Turner             COMPUTE_LLDB_PATH(ComputeUserPluginsDirectory, g_fields->m_lldb_user_plugin_dir)
21342ff0ad8SZachary Turner             if (log)
214673b6e4fSZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'",
215673b6e4fSZachary Turner                             g_fields->m_lldb_user_plugin_dir.GetPath().c_str());
21642ff0ad8SZachary Turner             break;
21742ff0ad8SZachary Turner         case lldb::ePathTypeLLDBTempSystemDir:
218673b6e4fSZachary Turner             COMPUTE_LLDB_PATH(ComputeTempFileDirectory, g_fields->m_lldb_tmp_dir)
21942ff0ad8SZachary Turner             if (log)
220673b6e4fSZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", g_fields->m_lldb_tmp_dir.GetPath().c_str());
22142ff0ad8SZachary Turner             break;
22242ff0ad8SZachary Turner     }
22342ff0ad8SZachary Turner 
22442ff0ad8SZachary Turner     if (!result)
22542ff0ad8SZachary Turner         return false;
22642ff0ad8SZachary Turner     file_spec = *result;
22742ff0ad8SZachary Turner     return true;
22842ff0ad8SZachary Turner }
22942ff0ad8SZachary Turner 
23042ff0ad8SZachary Turner bool
23142ff0ad8SZachary Turner HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec)
23242ff0ad8SZachary Turner {
23342ff0ad8SZachary Turner     // To get paths related to LLDB we get the path to the executable that
23442ff0ad8SZachary Turner     // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB",
23542ff0ad8SZachary Turner     // on linux this is assumed to be the "lldb" main executable. If LLDB on
23642ff0ad8SZachary Turner     // linux is actually in a shared library (liblldb.so) then this function will
23742ff0ad8SZachary Turner     // need to be modified to "do the right thing".
23842ff0ad8SZachary Turner 
23942ff0ad8SZachary Turner     FileSpec lldb_file_spec(
24042ff0ad8SZachary Turner         Host::GetModuleFileSpecForHostAddress(reinterpret_cast<void *>(reinterpret_cast<intptr_t>(HostInfoBase::GetLLDBPath))));
24142ff0ad8SZachary Turner 
24242ff0ad8SZachary Turner     // Remove the filename so that this FileSpec only represents the directory.
2430d8400c8SGreg Clayton     file_spec.GetDirectory() = lldb_file_spec.GetDirectory();
24442ff0ad8SZachary Turner 
24542ff0ad8SZachary Turner     return (bool)file_spec.GetDirectory();
24642ff0ad8SZachary Turner }
24742ff0ad8SZachary Turner 
24842ff0ad8SZachary Turner bool
24942ff0ad8SZachary Turner HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec)
25042ff0ad8SZachary Turner {
25142ff0ad8SZachary Turner     return GetLLDBPath(lldb::ePathTypeLLDBShlibDir, file_spec);
25242ff0ad8SZachary Turner }
25342ff0ad8SZachary Turner 
25442ff0ad8SZachary Turner bool
25542ff0ad8SZachary Turner HostInfoBase::ComputeTempFileDirectory(FileSpec &file_spec)
25642ff0ad8SZachary Turner {
25742ff0ad8SZachary Turner     const char *tmpdir_cstr = getenv("TMPDIR");
25842ff0ad8SZachary Turner     if (tmpdir_cstr == NULL)
25942ff0ad8SZachary Turner     {
26042ff0ad8SZachary Turner         tmpdir_cstr = getenv("TMP");
26142ff0ad8SZachary Turner         if (tmpdir_cstr == NULL)
26242ff0ad8SZachary Turner             tmpdir_cstr = getenv("TEMP");
26342ff0ad8SZachary Turner     }
26442ff0ad8SZachary Turner     if (!tmpdir_cstr)
26542ff0ad8SZachary Turner         return false;
26642ff0ad8SZachary Turner 
26742ff0ad8SZachary Turner     StreamString pid_tmpdir;
26842ff0ad8SZachary Turner     pid_tmpdir.Printf("%s/lldb", tmpdir_cstr);
26942ff0ad8SZachary Turner     if (!FileSystem::MakeDirectory(pid_tmpdir.GetString().c_str(), eFilePermissionsDirectoryDefault).Success())
27042ff0ad8SZachary Turner         return false;
27142ff0ad8SZachary Turner 
27242ff0ad8SZachary Turner     pid_tmpdir.Printf("/%" PRIu64, Host::GetCurrentProcessID());
27342ff0ad8SZachary Turner     if (!FileSystem::MakeDirectory(pid_tmpdir.GetString().c_str(), eFilePermissionsDirectoryDefault).Success())
27442ff0ad8SZachary Turner         return false;
27542ff0ad8SZachary Turner 
27642ff0ad8SZachary Turner     // Make an atexit handler to clean up the process specify LLDB temp dir
27742ff0ad8SZachary Turner     // and all of its contents.
27842ff0ad8SZachary Turner     ::atexit(CleanupProcessSpecificLLDBTempDir);
2790d8400c8SGreg Clayton     file_spec.GetDirectory().SetCStringWithLength(pid_tmpdir.GetString().c_str(), pid_tmpdir.GetString().size());
28042ff0ad8SZachary Turner     return true;
28142ff0ad8SZachary Turner }
28242ff0ad8SZachary Turner 
28342ff0ad8SZachary Turner bool
28442ff0ad8SZachary Turner HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec)
28542ff0ad8SZachary Turner {
28642ff0ad8SZachary Turner     // TODO(zturner): Figure out how to compute the header directory for all platforms.
28742ff0ad8SZachary Turner     return false;
28842ff0ad8SZachary Turner }
28942ff0ad8SZachary Turner 
29042ff0ad8SZachary Turner bool
29142ff0ad8SZachary Turner HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec)
29242ff0ad8SZachary Turner {
29342ff0ad8SZachary Turner     // TODO(zturner): Figure out how to compute the system plugins directory for all platforms.
29442ff0ad8SZachary Turner     return false;
29542ff0ad8SZachary Turner }
29642ff0ad8SZachary Turner 
29742ff0ad8SZachary Turner bool
298*b1e1c62fSSean Callanan HostInfoBase::ComputeClangDirectory(FileSpec &file_spec)
299*b1e1c62fSSean Callanan {
300*b1e1c62fSSean Callanan     return false;
301*b1e1c62fSSean Callanan }
302*b1e1c62fSSean Callanan 
303*b1e1c62fSSean Callanan bool
30442ff0ad8SZachary Turner HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec)
30542ff0ad8SZachary Turner {
30642ff0ad8SZachary Turner     // TODO(zturner): Figure out how to compute the user plugins directory for all platforms.
30742ff0ad8SZachary Turner     return false;
30842ff0ad8SZachary Turner }
30942ff0ad8SZachary Turner 
31013b18261SZachary Turner void
31113b18261SZachary Turner HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64)
31213b18261SZachary Turner {
31313b18261SZachary Turner     llvm::Triple triple(llvm::sys::getDefaultTargetTriple());
31413b18261SZachary Turner 
31513b18261SZachary Turner     arch_32.Clear();
31613b18261SZachary Turner     arch_64.Clear();
31713b18261SZachary Turner 
31813b18261SZachary Turner     switch (triple.getArch())
31913b18261SZachary Turner     {
32013b18261SZachary Turner         default:
32113b18261SZachary Turner             arch_32.SetTriple(triple);
32213b18261SZachary Turner             break;
32313b18261SZachary Turner 
32413b18261SZachary Turner         case llvm::Triple::x86_64:
32513b18261SZachary Turner             arch_64.SetTriple(triple);
32613b18261SZachary Turner             arch_32.SetTriple(triple.get32BitArchVariant());
32713b18261SZachary Turner             break;
32813b18261SZachary Turner 
329e4d6922cSTodd Fiala         case llvm::Triple::aarch64:
33013b18261SZachary Turner         case llvm::Triple::mips64:
33113b18261SZachary Turner         case llvm::Triple::sparcv9:
33213b18261SZachary Turner         case llvm::Triple::ppc64:
33313b18261SZachary Turner             arch_64.SetTriple(triple);
33413b18261SZachary Turner             break;
33513b18261SZachary Turner     }
33613b18261SZachary Turner }
337