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"
21*270e99abSZachary Turner #include "llvm/ADT/StringExtras.h"
2213b18261SZachary Turner #include "llvm/Support/Host.h"
23*270e99abSZachary Turner #include "llvm/Support/raw_ostream.h"
2497a14e60SZachary Turner 
2597a14e60SZachary Turner #include <thread>
2697a14e60SZachary Turner 
2797a14e60SZachary Turner using namespace lldb;
2897a14e60SZachary Turner using namespace lldb_private;
2997a14e60SZachary Turner 
3042ff0ad8SZachary Turner namespace
3142ff0ad8SZachary Turner {
3242ff0ad8SZachary Turner void
3342ff0ad8SZachary Turner CleanupProcessSpecificLLDBTempDir()
3442ff0ad8SZachary Turner {
3542ff0ad8SZachary Turner     // Get the process specific LLDB temporary directory and delete it.
3642ff0ad8SZachary Turner     FileSpec tmpdir_file_spec;
3742ff0ad8SZachary Turner     if (!HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
3842ff0ad8SZachary Turner         return;
3942ff0ad8SZachary Turner 
4042ff0ad8SZachary Turner     // Remove the LLDB temporary directory if we have one. Set "recurse" to
4142ff0ad8SZachary Turner     // true to all files that were created for the LLDB process can be cleaned up.
4242ff0ad8SZachary Turner     FileSystem::DeleteDirectory(tmpdir_file_spec.GetDirectory().GetCString(), true);
4342ff0ad8SZachary Turner }
44673b6e4fSZachary Turner 
45673b6e4fSZachary Turner struct HostInfoBaseFields
46673b6e4fSZachary Turner {
47673b6e4fSZachary Turner     uint32_t m_number_cpus;
48673b6e4fSZachary Turner     std::string m_vendor_string;
49673b6e4fSZachary Turner     std::string m_os_string;
50673b6e4fSZachary Turner     std::string m_host_triple;
51673b6e4fSZachary Turner 
52673b6e4fSZachary Turner     ArchSpec m_host_arch_32;
53673b6e4fSZachary Turner     ArchSpec m_host_arch_64;
54673b6e4fSZachary Turner 
55673b6e4fSZachary Turner     FileSpec m_lldb_so_dir;
56673b6e4fSZachary Turner     FileSpec m_lldb_support_exe_dir;
57673b6e4fSZachary Turner     FileSpec m_lldb_headers_dir;
58673b6e4fSZachary Turner     FileSpec m_lldb_python_dir;
59b1e1c62fSSean Callanan     FileSpec m_lldb_clang_resource_dir;
60673b6e4fSZachary Turner     FileSpec m_lldb_system_plugin_dir;
61673b6e4fSZachary Turner     FileSpec m_lldb_user_plugin_dir;
62673b6e4fSZachary Turner     FileSpec m_lldb_tmp_dir;
63673b6e4fSZachary Turner };
64673b6e4fSZachary Turner 
65673b6e4fSZachary Turner HostInfoBaseFields *g_fields = nullptr;
6642ff0ad8SZachary Turner }
6742ff0ad8SZachary Turner 
6842ff0ad8SZachary Turner #define COMPUTE_LLDB_PATH(compute_function, member_var)                                                                                    \
6942ff0ad8SZachary Turner     {                                                                                                                                      \
7042ff0ad8SZachary Turner         static bool is_initialized = false;                                                                                                \
7142ff0ad8SZachary Turner         static bool success = false;                                                                                                       \
7242ff0ad8SZachary Turner         if (!is_initialized)                                                                                                               \
7342ff0ad8SZachary Turner         {                                                                                                                                  \
7442ff0ad8SZachary Turner             is_initialized = true;                                                                                                         \
7542ff0ad8SZachary Turner             success = HostInfo::compute_function(member_var);                                                                              \
7642ff0ad8SZachary Turner         }                                                                                                                                  \
7742ff0ad8SZachary Turner         if (success)                                                                                                                       \
7842ff0ad8SZachary Turner             result = &member_var;                                                                                                          \
7942ff0ad8SZachary Turner     }
8042ff0ad8SZachary Turner 
81673b6e4fSZachary Turner void
82673b6e4fSZachary Turner HostInfoBase::Initialize()
83673b6e4fSZachary Turner {
84673b6e4fSZachary Turner     g_fields = new HostInfoBaseFields();
85673b6e4fSZachary Turner }
8642ff0ad8SZachary Turner 
8797a14e60SZachary Turner uint32_t
8897a14e60SZachary Turner HostInfoBase::GetNumberCPUS()
8997a14e60SZachary Turner {
9097a14e60SZachary Turner     static bool is_initialized = false;
9197a14e60SZachary Turner     if (!is_initialized)
9297a14e60SZachary Turner     {
93673b6e4fSZachary Turner         g_fields->m_number_cpus = std::thread::hardware_concurrency();
9497a14e60SZachary Turner         is_initialized = true;
9597a14e60SZachary Turner     }
9697a14e60SZachary Turner 
97673b6e4fSZachary Turner     return g_fields->m_number_cpus;
9897a14e60SZachary Turner }
9997a14e60SZachary Turner 
10039de3110SZachary Turner uint32_t
10139de3110SZachary Turner HostInfoBase::GetMaxThreadNameLength()
10239de3110SZachary Turner {
10339de3110SZachary Turner     return 0;
10439de3110SZachary Turner }
10539de3110SZachary Turner 
10697a14e60SZachary Turner llvm::StringRef
10797a14e60SZachary Turner HostInfoBase::GetVendorString()
10897a14e60SZachary Turner {
10997a14e60SZachary Turner     static bool is_initialized = false;
11097a14e60SZachary Turner     if (!is_initialized)
11197a14e60SZachary Turner     {
11213b18261SZachary Turner         const ArchSpec &host_arch = HostInfo::GetArchitecture();
11397a14e60SZachary Turner         const llvm::StringRef &str_ref = host_arch.GetTriple().getVendorName();
114673b6e4fSZachary Turner         g_fields->m_vendor_string.assign(str_ref.begin(), str_ref.end());
11597a14e60SZachary Turner         is_initialized = true;
11697a14e60SZachary Turner     }
117673b6e4fSZachary Turner     return g_fields->m_vendor_string;
11897a14e60SZachary Turner }
11997a14e60SZachary Turner 
12097a14e60SZachary Turner llvm::StringRef
12197a14e60SZachary Turner HostInfoBase::GetOSString()
12297a14e60SZachary Turner {
12397a14e60SZachary Turner     static bool is_initialized = false;
12497a14e60SZachary Turner     if (!is_initialized)
12597a14e60SZachary Turner     {
12613b18261SZachary Turner         const ArchSpec &host_arch = HostInfo::GetArchitecture();
12797a14e60SZachary Turner         const llvm::StringRef &str_ref = host_arch.GetTriple().getOSName();
128673b6e4fSZachary Turner         g_fields->m_os_string.assign(str_ref.begin(), str_ref.end());
12997a14e60SZachary Turner         is_initialized = true;
13097a14e60SZachary Turner     }
131673b6e4fSZachary Turner     return g_fields->m_os_string;
13297a14e60SZachary Turner }
13397a14e60SZachary Turner 
13497a14e60SZachary Turner llvm::StringRef
13597a14e60SZachary Turner HostInfoBase::GetTargetTriple()
13697a14e60SZachary Turner {
13797a14e60SZachary Turner     static bool is_initialized = false;
13897a14e60SZachary Turner     if (!is_initialized)
13997a14e60SZachary Turner     {
14013b18261SZachary Turner         const ArchSpec &host_arch = HostInfo::GetArchitecture();
141673b6e4fSZachary Turner         g_fields->m_host_triple = host_arch.GetTriple().getTriple();
14297a14e60SZachary Turner         is_initialized = true;
14397a14e60SZachary Turner     }
144673b6e4fSZachary Turner     return g_fields->m_host_triple;
14597a14e60SZachary Turner }
14613b18261SZachary Turner 
14713b18261SZachary Turner const ArchSpec &
14813b18261SZachary Turner HostInfoBase::GetArchitecture(ArchitectureKind arch_kind)
14913b18261SZachary Turner {
15013b18261SZachary Turner     static bool is_initialized = false;
15113b18261SZachary Turner     if (!is_initialized)
15213b18261SZachary Turner     {
153673b6e4fSZachary Turner         HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32, g_fields->m_host_arch_64);
15413b18261SZachary Turner         is_initialized = true;
15513b18261SZachary Turner     }
15613b18261SZachary Turner 
15713b18261SZachary Turner     // If an explicit 32 or 64-bit architecture was requested, return that.
15813b18261SZachary Turner     if (arch_kind == eArchKind32)
159673b6e4fSZachary Turner         return g_fields->m_host_arch_32;
16013b18261SZachary Turner     if (arch_kind == eArchKind64)
161673b6e4fSZachary Turner         return g_fields->m_host_arch_64;
16213b18261SZachary Turner 
16313b18261SZachary Turner     // Otherwise prefer the 64-bit architecture if it is valid.
164673b6e4fSZachary Turner     return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64 : g_fields->m_host_arch_32;
16513b18261SZachary Turner }
16613b18261SZachary Turner 
16742ff0ad8SZachary Turner bool
16842ff0ad8SZachary Turner HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec)
16942ff0ad8SZachary Turner {
17042ff0ad8SZachary Turner     file_spec.Clear();
17142ff0ad8SZachary Turner 
17242ff0ad8SZachary Turner #if defined(LLDB_DISABLE_PYTHON)
17342ff0ad8SZachary Turner     if (type == lldb::ePathTypePythonDir)
17442ff0ad8SZachary Turner         return false;
17542ff0ad8SZachary Turner #endif
17642ff0ad8SZachary Turner 
17742ff0ad8SZachary Turner     Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
17842ff0ad8SZachary Turner     FileSpec *result = nullptr;
17942ff0ad8SZachary Turner     switch (type)
18042ff0ad8SZachary Turner     {
18142ff0ad8SZachary Turner         case lldb::ePathTypeLLDBShlibDir:
182673b6e4fSZachary Turner             COMPUTE_LLDB_PATH(ComputeSharedLibraryDirectory, g_fields->m_lldb_so_dir)
18342ff0ad8SZachary Turner             if (log)
184673b6e4fSZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", g_fields->m_lldb_so_dir.GetPath().c_str());
18542ff0ad8SZachary Turner             break;
18642ff0ad8SZachary Turner         case lldb::ePathTypeSupportExecutableDir:
187673b6e4fSZachary Turner             COMPUTE_LLDB_PATH(ComputeSupportExeDirectory, g_fields->m_lldb_support_exe_dir)
18842ff0ad8SZachary Turner             if (log)
189673b6e4fSZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'",
190673b6e4fSZachary Turner                             g_fields->m_lldb_support_exe_dir.GetPath().c_str());
19142ff0ad8SZachary Turner             break;
19242ff0ad8SZachary Turner         case lldb::ePathTypeHeaderDir:
193673b6e4fSZachary Turner             COMPUTE_LLDB_PATH(ComputeHeaderDirectory, g_fields->m_lldb_headers_dir)
19442ff0ad8SZachary Turner             if (log)
195673b6e4fSZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'", g_fields->m_lldb_headers_dir.GetPath().c_str());
19642ff0ad8SZachary Turner             break;
19742ff0ad8SZachary Turner         case lldb::ePathTypePythonDir:
198673b6e4fSZachary Turner             COMPUTE_LLDB_PATH(ComputePythonDirectory, g_fields->m_lldb_python_dir)
19942ff0ad8SZachary Turner             if (log)
200673b6e4fSZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'", g_fields->m_lldb_python_dir.GetPath().c_str());
20142ff0ad8SZachary Turner             break;
202b1e1c62fSSean Callanan         case lldb::ePathTypeClangDir:
203b1e1c62fSSean Callanan             COMPUTE_LLDB_PATH(ComputeClangDirectory, g_fields->m_lldb_clang_resource_dir)
204b1e1c62fSSean Callanan             if (log)
205b1e1c62fSSean Callanan                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeClangResourceDir) => '%s'", g_fields->m_lldb_clang_resource_dir.GetPath().c_str());
206b1e1c62fSSean Callanan             break;
20742ff0ad8SZachary Turner         case lldb::ePathTypeLLDBSystemPlugins:
208673b6e4fSZachary Turner             COMPUTE_LLDB_PATH(ComputeSystemPluginsDirectory, g_fields->m_lldb_system_plugin_dir)
20942ff0ad8SZachary Turner             if (log)
210673b6e4fSZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'",
211673b6e4fSZachary Turner                             g_fields->m_lldb_system_plugin_dir.GetPath().c_str());
21242ff0ad8SZachary Turner             break;
21342ff0ad8SZachary Turner         case lldb::ePathTypeLLDBUserPlugins:
214673b6e4fSZachary Turner             COMPUTE_LLDB_PATH(ComputeUserPluginsDirectory, g_fields->m_lldb_user_plugin_dir)
21542ff0ad8SZachary Turner             if (log)
216673b6e4fSZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'",
217673b6e4fSZachary Turner                             g_fields->m_lldb_user_plugin_dir.GetPath().c_str());
21842ff0ad8SZachary Turner             break;
21942ff0ad8SZachary Turner         case lldb::ePathTypeLLDBTempSystemDir:
220673b6e4fSZachary Turner             COMPUTE_LLDB_PATH(ComputeTempFileDirectory, g_fields->m_lldb_tmp_dir)
22142ff0ad8SZachary Turner             if (log)
222673b6e4fSZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", g_fields->m_lldb_tmp_dir.GetPath().c_str());
22342ff0ad8SZachary Turner             break;
22442ff0ad8SZachary Turner     }
22542ff0ad8SZachary Turner 
22642ff0ad8SZachary Turner     if (!result)
22742ff0ad8SZachary Turner         return false;
22842ff0ad8SZachary Turner     file_spec = *result;
22942ff0ad8SZachary Turner     return true;
23042ff0ad8SZachary Turner }
23142ff0ad8SZachary Turner 
23242ff0ad8SZachary Turner bool
23342ff0ad8SZachary Turner HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec)
23442ff0ad8SZachary Turner {
23542ff0ad8SZachary Turner     // To get paths related to LLDB we get the path to the executable that
23642ff0ad8SZachary Turner     // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB",
23742ff0ad8SZachary Turner     // on linux this is assumed to be the "lldb" main executable. If LLDB on
23842ff0ad8SZachary Turner     // linux is actually in a shared library (liblldb.so) then this function will
23942ff0ad8SZachary Turner     // need to be modified to "do the right thing".
24042ff0ad8SZachary Turner 
24142ff0ad8SZachary Turner     FileSpec lldb_file_spec(
24242ff0ad8SZachary Turner         Host::GetModuleFileSpecForHostAddress(reinterpret_cast<void *>(reinterpret_cast<intptr_t>(HostInfoBase::GetLLDBPath))));
24342ff0ad8SZachary Turner 
24442ff0ad8SZachary Turner     // Remove the filename so that this FileSpec only represents the directory.
2450d8400c8SGreg Clayton     file_spec.GetDirectory() = lldb_file_spec.GetDirectory();
24642ff0ad8SZachary Turner 
24742ff0ad8SZachary Turner     return (bool)file_spec.GetDirectory();
24842ff0ad8SZachary Turner }
24942ff0ad8SZachary Turner 
25042ff0ad8SZachary Turner bool
25142ff0ad8SZachary Turner HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec)
25242ff0ad8SZachary Turner {
25342ff0ad8SZachary Turner     return GetLLDBPath(lldb::ePathTypeLLDBShlibDir, file_spec);
25442ff0ad8SZachary Turner }
25542ff0ad8SZachary Turner 
25642ff0ad8SZachary Turner bool
25742ff0ad8SZachary Turner HostInfoBase::ComputeTempFileDirectory(FileSpec &file_spec)
25842ff0ad8SZachary Turner {
25942ff0ad8SZachary Turner     const char *tmpdir_cstr = getenv("TMPDIR");
26042ff0ad8SZachary Turner     if (tmpdir_cstr == NULL)
26142ff0ad8SZachary Turner     {
26242ff0ad8SZachary Turner         tmpdir_cstr = getenv("TMP");
26342ff0ad8SZachary Turner         if (tmpdir_cstr == NULL)
26442ff0ad8SZachary Turner             tmpdir_cstr = getenv("TEMP");
26542ff0ad8SZachary Turner     }
26642ff0ad8SZachary Turner     if (!tmpdir_cstr)
26742ff0ad8SZachary Turner         return false;
26842ff0ad8SZachary Turner 
269*270e99abSZachary Turner     FileSpec temp_file_spec(tmpdir_cstr, false);
270*270e99abSZachary Turner     temp_file_spec.AppendPathComponent("lldb");
271*270e99abSZachary Turner     if (!FileSystem::MakeDirectory(temp_file_spec.GetPath().c_str(), eFilePermissionsDirectoryDefault).Success())
27242ff0ad8SZachary Turner         return false;
27342ff0ad8SZachary Turner 
274*270e99abSZachary Turner     std::string pid_str;
275*270e99abSZachary Turner     llvm::raw_string_ostream pid_stream(pid_str);
276*270e99abSZachary Turner     pid_stream << Host::GetCurrentProcessID();
277*270e99abSZachary Turner     temp_file_spec.AppendPathComponent(pid_stream.str().c_str());
278*270e99abSZachary Turner     std::string final_path = temp_file_spec.GetPath();
279*270e99abSZachary Turner     if (!FileSystem::MakeDirectory(final_path.c_str(), eFilePermissionsDirectoryDefault).Success())
28042ff0ad8SZachary Turner         return false;
28142ff0ad8SZachary Turner 
28242ff0ad8SZachary Turner     // Make an atexit handler to clean up the process specify LLDB temp dir
28342ff0ad8SZachary Turner     // and all of its contents.
28442ff0ad8SZachary Turner     ::atexit(CleanupProcessSpecificLLDBTempDir);
285*270e99abSZachary Turner     file_spec.GetDirectory().SetCStringWithLength(final_path.c_str(), final_path.size());
28642ff0ad8SZachary Turner     return true;
28742ff0ad8SZachary Turner }
28842ff0ad8SZachary Turner 
28942ff0ad8SZachary Turner bool
29042ff0ad8SZachary Turner HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec)
29142ff0ad8SZachary Turner {
29242ff0ad8SZachary Turner     // TODO(zturner): Figure out how to compute the header directory for all platforms.
29342ff0ad8SZachary Turner     return false;
29442ff0ad8SZachary Turner }
29542ff0ad8SZachary Turner 
29642ff0ad8SZachary Turner bool
29742ff0ad8SZachary Turner HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec)
29842ff0ad8SZachary Turner {
29942ff0ad8SZachary Turner     // TODO(zturner): Figure out how to compute the system plugins directory for all platforms.
30042ff0ad8SZachary Turner     return false;
30142ff0ad8SZachary Turner }
30242ff0ad8SZachary Turner 
30342ff0ad8SZachary Turner bool
304b1e1c62fSSean Callanan HostInfoBase::ComputeClangDirectory(FileSpec &file_spec)
305b1e1c62fSSean Callanan {
306b1e1c62fSSean Callanan     return false;
307b1e1c62fSSean Callanan }
308b1e1c62fSSean Callanan 
309b1e1c62fSSean Callanan bool
31042ff0ad8SZachary Turner HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec)
31142ff0ad8SZachary Turner {
31242ff0ad8SZachary Turner     // TODO(zturner): Figure out how to compute the user plugins directory for all platforms.
31342ff0ad8SZachary Turner     return false;
31442ff0ad8SZachary Turner }
31542ff0ad8SZachary Turner 
31613b18261SZachary Turner void
31713b18261SZachary Turner HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64)
31813b18261SZachary Turner {
31913b18261SZachary Turner     llvm::Triple triple(llvm::sys::getDefaultTargetTriple());
32013b18261SZachary Turner 
32113b18261SZachary Turner     arch_32.Clear();
32213b18261SZachary Turner     arch_64.Clear();
32313b18261SZachary Turner 
32413b18261SZachary Turner     switch (triple.getArch())
32513b18261SZachary Turner     {
32613b18261SZachary Turner         default:
32713b18261SZachary Turner             arch_32.SetTriple(triple);
32813b18261SZachary Turner             break;
32913b18261SZachary Turner 
33013b18261SZachary Turner         case llvm::Triple::x86_64:
33113b18261SZachary Turner             arch_64.SetTriple(triple);
33213b18261SZachary Turner             arch_32.SetTriple(triple.get32BitArchVariant());
33313b18261SZachary Turner             break;
33413b18261SZachary Turner 
335e4d6922cSTodd Fiala         case llvm::Triple::aarch64:
33613b18261SZachary Turner         case llvm::Triple::mips64:
33713b18261SZachary Turner         case llvm::Triple::sparcv9:
33813b18261SZachary Turner         case llvm::Triple::ppc64:
33913b18261SZachary Turner             arch_64.SetTriple(triple);
34013b18261SZachary Turner             break;
34113b18261SZachary Turner     }
34213b18261SZachary Turner }
343