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 }
42*673b6e4fSZachary Turner 
43*673b6e4fSZachary Turner struct HostInfoBaseFields
44*673b6e4fSZachary Turner {
45*673b6e4fSZachary Turner     uint32_t m_number_cpus;
46*673b6e4fSZachary Turner     std::string m_vendor_string;
47*673b6e4fSZachary Turner     std::string m_os_string;
48*673b6e4fSZachary Turner     std::string m_host_triple;
49*673b6e4fSZachary Turner 
50*673b6e4fSZachary Turner     ArchSpec m_host_arch_32;
51*673b6e4fSZachary Turner     ArchSpec m_host_arch_64;
52*673b6e4fSZachary Turner 
53*673b6e4fSZachary Turner     FileSpec m_lldb_so_dir;
54*673b6e4fSZachary Turner     FileSpec m_lldb_support_exe_dir;
55*673b6e4fSZachary Turner     FileSpec m_lldb_headers_dir;
56*673b6e4fSZachary Turner     FileSpec m_lldb_python_dir;
57*673b6e4fSZachary Turner     FileSpec m_lldb_system_plugin_dir;
58*673b6e4fSZachary Turner     FileSpec m_lldb_user_plugin_dir;
59*673b6e4fSZachary Turner     FileSpec m_lldb_tmp_dir;
60*673b6e4fSZachary Turner };
61*673b6e4fSZachary Turner 
62*673b6e4fSZachary Turner HostInfoBaseFields *g_fields = nullptr;
6342ff0ad8SZachary Turner }
6442ff0ad8SZachary Turner 
6542ff0ad8SZachary Turner #define COMPUTE_LLDB_PATH(compute_function, member_var)                                                                                    \
6642ff0ad8SZachary Turner     {                                                                                                                                      \
6742ff0ad8SZachary Turner         static bool is_initialized = false;                                                                                                \
6842ff0ad8SZachary Turner         static bool success = false;                                                                                                       \
6942ff0ad8SZachary Turner         if (!is_initialized)                                                                                                               \
7042ff0ad8SZachary Turner         {                                                                                                                                  \
7142ff0ad8SZachary Turner             is_initialized = true;                                                                                                         \
7242ff0ad8SZachary Turner             success = HostInfo::compute_function(member_var);                                                                              \
7342ff0ad8SZachary Turner         }                                                                                                                                  \
7442ff0ad8SZachary Turner         if (success)                                                                                                                       \
7542ff0ad8SZachary Turner             result = &member_var;                                                                                                          \
7642ff0ad8SZachary Turner     }
7742ff0ad8SZachary Turner 
78*673b6e4fSZachary Turner void
79*673b6e4fSZachary Turner HostInfoBase::Initialize()
80*673b6e4fSZachary Turner {
81*673b6e4fSZachary Turner     g_fields = new HostInfoBaseFields();
82*673b6e4fSZachary Turner }
8342ff0ad8SZachary Turner 
8497a14e60SZachary Turner uint32_t
8597a14e60SZachary Turner HostInfoBase::GetNumberCPUS()
8697a14e60SZachary Turner {
8797a14e60SZachary Turner     static bool is_initialized = false;
8897a14e60SZachary Turner     if (!is_initialized)
8997a14e60SZachary Turner     {
90*673b6e4fSZachary Turner         g_fields->m_number_cpus = std::thread::hardware_concurrency();
9197a14e60SZachary Turner         is_initialized = true;
9297a14e60SZachary Turner     }
9397a14e60SZachary Turner 
94*673b6e4fSZachary Turner     return g_fields->m_number_cpus;
9597a14e60SZachary Turner }
9697a14e60SZachary Turner 
9797a14e60SZachary Turner llvm::StringRef
9897a14e60SZachary Turner HostInfoBase::GetVendorString()
9997a14e60SZachary Turner {
10097a14e60SZachary Turner     static bool is_initialized = false;
10197a14e60SZachary Turner     if (!is_initialized)
10297a14e60SZachary Turner     {
10313b18261SZachary Turner         const ArchSpec &host_arch = HostInfo::GetArchitecture();
10497a14e60SZachary Turner         const llvm::StringRef &str_ref = host_arch.GetTriple().getVendorName();
105*673b6e4fSZachary Turner         g_fields->m_vendor_string.assign(str_ref.begin(), str_ref.end());
10697a14e60SZachary Turner         is_initialized = true;
10797a14e60SZachary Turner     }
108*673b6e4fSZachary Turner     return g_fields->m_vendor_string;
10997a14e60SZachary Turner }
11097a14e60SZachary Turner 
11197a14e60SZachary Turner llvm::StringRef
11297a14e60SZachary Turner HostInfoBase::GetOSString()
11397a14e60SZachary Turner {
11497a14e60SZachary Turner     static bool is_initialized = false;
11597a14e60SZachary Turner     if (!is_initialized)
11697a14e60SZachary Turner     {
11713b18261SZachary Turner         const ArchSpec &host_arch = HostInfo::GetArchitecture();
11897a14e60SZachary Turner         const llvm::StringRef &str_ref = host_arch.GetTriple().getOSName();
119*673b6e4fSZachary Turner         g_fields->m_os_string.assign(str_ref.begin(), str_ref.end());
12097a14e60SZachary Turner         is_initialized = true;
12197a14e60SZachary Turner     }
122*673b6e4fSZachary Turner     return g_fields->m_os_string;
12397a14e60SZachary Turner }
12497a14e60SZachary Turner 
12597a14e60SZachary Turner llvm::StringRef
12697a14e60SZachary Turner HostInfoBase::GetTargetTriple()
12797a14e60SZachary Turner {
12897a14e60SZachary Turner     static bool is_initialized = false;
12997a14e60SZachary Turner     if (!is_initialized)
13097a14e60SZachary Turner     {
13113b18261SZachary Turner         const ArchSpec &host_arch = HostInfo::GetArchitecture();
132*673b6e4fSZachary Turner         g_fields->m_host_triple = host_arch.GetTriple().getTriple();
13397a14e60SZachary Turner         is_initialized = true;
13497a14e60SZachary Turner     }
135*673b6e4fSZachary Turner     return g_fields->m_host_triple;
13697a14e60SZachary Turner }
13713b18261SZachary Turner 
13813b18261SZachary Turner const ArchSpec &
13913b18261SZachary Turner HostInfoBase::GetArchitecture(ArchitectureKind arch_kind)
14013b18261SZachary Turner {
14113b18261SZachary Turner     static bool is_initialized = false;
14213b18261SZachary Turner     if (!is_initialized)
14313b18261SZachary Turner     {
144*673b6e4fSZachary Turner         HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32, g_fields->m_host_arch_64);
14513b18261SZachary Turner         is_initialized = true;
14613b18261SZachary Turner     }
14713b18261SZachary Turner 
14813b18261SZachary Turner     // If an explicit 32 or 64-bit architecture was requested, return that.
14913b18261SZachary Turner     if (arch_kind == eArchKind32)
150*673b6e4fSZachary Turner         return g_fields->m_host_arch_32;
15113b18261SZachary Turner     if (arch_kind == eArchKind64)
152*673b6e4fSZachary Turner         return g_fields->m_host_arch_64;
15313b18261SZachary Turner 
15413b18261SZachary Turner     // Otherwise prefer the 64-bit architecture if it is valid.
155*673b6e4fSZachary Turner     return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64 : g_fields->m_host_arch_32;
15613b18261SZachary Turner }
15713b18261SZachary Turner 
15842ff0ad8SZachary Turner bool
15942ff0ad8SZachary Turner HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec)
16042ff0ad8SZachary Turner {
16142ff0ad8SZachary Turner     file_spec.Clear();
16242ff0ad8SZachary Turner 
16342ff0ad8SZachary Turner #if defined(LLDB_DISABLE_PYTHON)
16442ff0ad8SZachary Turner     if (type == lldb::ePathTypePythonDir)
16542ff0ad8SZachary Turner         return false;
16642ff0ad8SZachary Turner #endif
16742ff0ad8SZachary Turner 
16842ff0ad8SZachary Turner     Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
16942ff0ad8SZachary Turner     FileSpec *result = nullptr;
17042ff0ad8SZachary Turner     switch (type)
17142ff0ad8SZachary Turner     {
17242ff0ad8SZachary Turner         case lldb::ePathTypeLLDBShlibDir:
173*673b6e4fSZachary Turner             COMPUTE_LLDB_PATH(ComputeSharedLibraryDirectory, g_fields->m_lldb_so_dir)
17442ff0ad8SZachary Turner             if (log)
175*673b6e4fSZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", g_fields->m_lldb_so_dir.GetPath().c_str());
17642ff0ad8SZachary Turner             break;
17742ff0ad8SZachary Turner         case lldb::ePathTypeSupportExecutableDir:
178*673b6e4fSZachary Turner             COMPUTE_LLDB_PATH(ComputeSupportExeDirectory, g_fields->m_lldb_support_exe_dir)
17942ff0ad8SZachary Turner             if (log)
180*673b6e4fSZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'",
181*673b6e4fSZachary Turner                             g_fields->m_lldb_support_exe_dir.GetPath().c_str());
18242ff0ad8SZachary Turner             break;
18342ff0ad8SZachary Turner         case lldb::ePathTypeHeaderDir:
184*673b6e4fSZachary Turner             COMPUTE_LLDB_PATH(ComputeHeaderDirectory, g_fields->m_lldb_headers_dir)
18542ff0ad8SZachary Turner             if (log)
186*673b6e4fSZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'", g_fields->m_lldb_headers_dir.GetPath().c_str());
18742ff0ad8SZachary Turner             break;
18842ff0ad8SZachary Turner         case lldb::ePathTypePythonDir:
189*673b6e4fSZachary Turner             COMPUTE_LLDB_PATH(ComputePythonDirectory, g_fields->m_lldb_python_dir)
19042ff0ad8SZachary Turner             if (log)
191*673b6e4fSZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'", g_fields->m_lldb_python_dir.GetPath().c_str());
19242ff0ad8SZachary Turner             break;
19342ff0ad8SZachary Turner         case lldb::ePathTypeLLDBSystemPlugins:
194*673b6e4fSZachary Turner             COMPUTE_LLDB_PATH(ComputeSystemPluginsDirectory, g_fields->m_lldb_system_plugin_dir)
19542ff0ad8SZachary Turner             if (log)
196*673b6e4fSZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'",
197*673b6e4fSZachary Turner                             g_fields->m_lldb_system_plugin_dir.GetPath().c_str());
19842ff0ad8SZachary Turner             break;
19942ff0ad8SZachary Turner         case lldb::ePathTypeLLDBUserPlugins:
200*673b6e4fSZachary Turner             COMPUTE_LLDB_PATH(ComputeUserPluginsDirectory, g_fields->m_lldb_user_plugin_dir)
20142ff0ad8SZachary Turner             if (log)
202*673b6e4fSZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'",
203*673b6e4fSZachary Turner                             g_fields->m_lldb_user_plugin_dir.GetPath().c_str());
20442ff0ad8SZachary Turner             break;
20542ff0ad8SZachary Turner         case lldb::ePathTypeLLDBTempSystemDir:
206*673b6e4fSZachary Turner             COMPUTE_LLDB_PATH(ComputeTempFileDirectory, g_fields->m_lldb_tmp_dir)
20742ff0ad8SZachary Turner             if (log)
208*673b6e4fSZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", g_fields->m_lldb_tmp_dir.GetPath().c_str());
20942ff0ad8SZachary Turner             break;
21042ff0ad8SZachary Turner     }
21142ff0ad8SZachary Turner 
21242ff0ad8SZachary Turner     if (!result)
21342ff0ad8SZachary Turner         return false;
21442ff0ad8SZachary Turner     file_spec = *result;
21542ff0ad8SZachary Turner     return true;
21642ff0ad8SZachary Turner }
21742ff0ad8SZachary Turner 
21842ff0ad8SZachary Turner bool
21942ff0ad8SZachary Turner HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec)
22042ff0ad8SZachary Turner {
22142ff0ad8SZachary Turner     // To get paths related to LLDB we get the path to the executable that
22242ff0ad8SZachary Turner     // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB",
22342ff0ad8SZachary Turner     // on linux this is assumed to be the "lldb" main executable. If LLDB on
22442ff0ad8SZachary Turner     // linux is actually in a shared library (liblldb.so) then this function will
22542ff0ad8SZachary Turner     // need to be modified to "do the right thing".
22642ff0ad8SZachary Turner 
22742ff0ad8SZachary Turner     FileSpec lldb_file_spec(
22842ff0ad8SZachary Turner         Host::GetModuleFileSpecForHostAddress(reinterpret_cast<void *>(reinterpret_cast<intptr_t>(HostInfoBase::GetLLDBPath))));
22942ff0ad8SZachary Turner 
23042ff0ad8SZachary Turner     // Remove the filename so that this FileSpec only represents the directory.
23142ff0ad8SZachary Turner     file_spec.SetFile(lldb_file_spec.GetDirectory().AsCString(), true);
23242ff0ad8SZachary Turner 
23342ff0ad8SZachary Turner     return (bool)file_spec.GetDirectory();
23442ff0ad8SZachary Turner }
23542ff0ad8SZachary Turner 
23642ff0ad8SZachary Turner bool
23742ff0ad8SZachary Turner HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec)
23842ff0ad8SZachary Turner {
23942ff0ad8SZachary Turner     return GetLLDBPath(lldb::ePathTypeLLDBShlibDir, file_spec);
24042ff0ad8SZachary Turner }
24142ff0ad8SZachary Turner 
24242ff0ad8SZachary Turner bool
24342ff0ad8SZachary Turner HostInfoBase::ComputeTempFileDirectory(FileSpec &file_spec)
24442ff0ad8SZachary Turner {
24542ff0ad8SZachary Turner     const char *tmpdir_cstr = getenv("TMPDIR");
24642ff0ad8SZachary Turner     if (tmpdir_cstr == NULL)
24742ff0ad8SZachary Turner     {
24842ff0ad8SZachary Turner         tmpdir_cstr = getenv("TMP");
24942ff0ad8SZachary Turner         if (tmpdir_cstr == NULL)
25042ff0ad8SZachary Turner             tmpdir_cstr = getenv("TEMP");
25142ff0ad8SZachary Turner     }
25242ff0ad8SZachary Turner     if (!tmpdir_cstr)
25342ff0ad8SZachary Turner         return false;
25442ff0ad8SZachary Turner 
25542ff0ad8SZachary Turner     StreamString pid_tmpdir;
25642ff0ad8SZachary Turner     pid_tmpdir.Printf("%s/lldb", tmpdir_cstr);
25742ff0ad8SZachary Turner     if (!FileSystem::MakeDirectory(pid_tmpdir.GetString().c_str(), eFilePermissionsDirectoryDefault).Success())
25842ff0ad8SZachary Turner         return false;
25942ff0ad8SZachary Turner 
26042ff0ad8SZachary Turner     pid_tmpdir.Printf("/%" PRIu64, Host::GetCurrentProcessID());
26142ff0ad8SZachary Turner     if (!FileSystem::MakeDirectory(pid_tmpdir.GetString().c_str(), eFilePermissionsDirectoryDefault).Success())
26242ff0ad8SZachary Turner         return false;
26342ff0ad8SZachary Turner 
26442ff0ad8SZachary Turner     // Make an atexit handler to clean up the process specify LLDB temp dir
26542ff0ad8SZachary Turner     // and all of its contents.
26642ff0ad8SZachary Turner     ::atexit(CleanupProcessSpecificLLDBTempDir);
26742ff0ad8SZachary Turner     file_spec.SetFile(pid_tmpdir.GetString().c_str(), false);
26842ff0ad8SZachary Turner     return true;
26942ff0ad8SZachary Turner }
27042ff0ad8SZachary Turner 
27142ff0ad8SZachary Turner bool
27242ff0ad8SZachary Turner HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec)
27342ff0ad8SZachary Turner {
27442ff0ad8SZachary Turner     // TODO(zturner): Figure out how to compute the header directory for all platforms.
27542ff0ad8SZachary Turner     return false;
27642ff0ad8SZachary Turner }
27742ff0ad8SZachary Turner 
27842ff0ad8SZachary Turner bool
27942ff0ad8SZachary Turner HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec)
28042ff0ad8SZachary Turner {
28142ff0ad8SZachary Turner     // TODO(zturner): Figure out how to compute the system plugins directory for all platforms.
28242ff0ad8SZachary Turner     return false;
28342ff0ad8SZachary Turner }
28442ff0ad8SZachary Turner 
28542ff0ad8SZachary Turner bool
28642ff0ad8SZachary Turner HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec)
28742ff0ad8SZachary Turner {
28842ff0ad8SZachary Turner     // TODO(zturner): Figure out how to compute the user plugins directory for all platforms.
28942ff0ad8SZachary Turner     return false;
29042ff0ad8SZachary Turner }
29142ff0ad8SZachary Turner 
29213b18261SZachary Turner void
29313b18261SZachary Turner HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64)
29413b18261SZachary Turner {
29513b18261SZachary Turner     llvm::Triple triple(llvm::sys::getDefaultTargetTriple());
29613b18261SZachary Turner 
29713b18261SZachary Turner     arch_32.Clear();
29813b18261SZachary Turner     arch_64.Clear();
29913b18261SZachary Turner 
30013b18261SZachary Turner     switch (triple.getArch())
30113b18261SZachary Turner     {
30213b18261SZachary Turner         default:
30313b18261SZachary Turner             arch_32.SetTriple(triple);
30413b18261SZachary Turner             break;
30513b18261SZachary Turner 
30613b18261SZachary Turner         case llvm::Triple::x86_64:
30713b18261SZachary Turner             arch_64.SetTriple(triple);
30813b18261SZachary Turner             arch_32.SetTriple(triple.get32BitArchVariant());
30913b18261SZachary Turner             break;
31013b18261SZachary Turner 
31113b18261SZachary Turner         case llvm::Triple::mips64:
31213b18261SZachary Turner         case llvm::Triple::sparcv9:
31313b18261SZachary Turner         case llvm::Triple::ppc64:
31413b18261SZachary Turner             arch_64.SetTriple(triple);
31513b18261SZachary Turner             break;
31613b18261SZachary Turner     }
31713b18261SZachary Turner }
318