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"
13*42ff0ad8SZachary Turner #include "lldb/Core/Log.h"
14*42ff0ad8SZachary Turner #include "lldb/Core/StreamString.h"
15*42ff0ad8SZachary 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 
28*42ff0ad8SZachary Turner namespace
29*42ff0ad8SZachary Turner {
30*42ff0ad8SZachary Turner void
31*42ff0ad8SZachary Turner CleanupProcessSpecificLLDBTempDir()
32*42ff0ad8SZachary Turner {
33*42ff0ad8SZachary Turner     // Get the process specific LLDB temporary directory and delete it.
34*42ff0ad8SZachary Turner     FileSpec tmpdir_file_spec;
35*42ff0ad8SZachary Turner     if (!HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
36*42ff0ad8SZachary Turner         return;
37*42ff0ad8SZachary Turner 
38*42ff0ad8SZachary Turner     // Remove the LLDB temporary directory if we have one. Set "recurse" to
39*42ff0ad8SZachary Turner     // true to all files that were created for the LLDB process can be cleaned up.
40*42ff0ad8SZachary Turner     FileSystem::DeleteDirectory(tmpdir_file_spec.GetDirectory().GetCString(), true);
41*42ff0ad8SZachary Turner }
42*42ff0ad8SZachary Turner }
43*42ff0ad8SZachary Turner 
44*42ff0ad8SZachary Turner #define COMPUTE_LLDB_PATH(compute_function, member_var)                                                                                    \
45*42ff0ad8SZachary Turner     {                                                                                                                                      \
46*42ff0ad8SZachary Turner         static bool is_initialized = false;                                                                                                \
47*42ff0ad8SZachary Turner         static bool success = false;                                                                                                       \
48*42ff0ad8SZachary Turner         if (!is_initialized)                                                                                                               \
49*42ff0ad8SZachary Turner         {                                                                                                                                  \
50*42ff0ad8SZachary Turner             is_initialized = true;                                                                                                         \
51*42ff0ad8SZachary Turner             success = HostInfo::compute_function(member_var);                                                                              \
52*42ff0ad8SZachary Turner         }                                                                                                                                  \
53*42ff0ad8SZachary Turner         if (success)                                                                                                                       \
54*42ff0ad8SZachary Turner             result = &member_var;                                                                                                          \
55*42ff0ad8SZachary Turner     }
56*42ff0ad8SZachary Turner 
5775172a95SZachary Turner uint32_t HostInfoBase::m_number_cpus = 0;
5875172a95SZachary Turner std::string HostInfoBase::m_vendor_string;
5975172a95SZachary Turner std::string HostInfoBase::m_os_string;
6075172a95SZachary Turner std::string HostInfoBase::m_host_triple;
6175172a95SZachary Turner ArchSpec HostInfoBase::m_host_arch_32;
6275172a95SZachary Turner ArchSpec HostInfoBase::m_host_arch_64;
6397a14e60SZachary Turner 
64*42ff0ad8SZachary Turner FileSpec HostInfoBase::m_lldb_so_dir;
65*42ff0ad8SZachary Turner FileSpec HostInfoBase::m_lldb_support_exe_dir;
66*42ff0ad8SZachary Turner FileSpec HostInfoBase::m_lldb_headers_dir;
67*42ff0ad8SZachary Turner FileSpec HostInfoBase::m_lldb_python_dir;
68*42ff0ad8SZachary Turner FileSpec HostInfoBase::m_lldb_system_plugin_dir;
69*42ff0ad8SZachary Turner FileSpec HostInfoBase::m_lldb_user_plugin_dir;
70*42ff0ad8SZachary Turner FileSpec HostInfoBase::m_lldb_tmp_dir;
71*42ff0ad8SZachary Turner 
7297a14e60SZachary Turner uint32_t
7397a14e60SZachary Turner HostInfoBase::GetNumberCPUS()
7497a14e60SZachary Turner {
7597a14e60SZachary Turner     static bool is_initialized = false;
7697a14e60SZachary Turner     if (!is_initialized)
7797a14e60SZachary Turner     {
7875172a95SZachary Turner         m_number_cpus = std::thread::hardware_concurrency();
7997a14e60SZachary Turner         is_initialized = true;
8097a14e60SZachary Turner     }
8197a14e60SZachary Turner 
8275172a95SZachary Turner     return m_number_cpus;
8397a14e60SZachary Turner }
8497a14e60SZachary Turner 
8597a14e60SZachary Turner llvm::StringRef
8697a14e60SZachary Turner HostInfoBase::GetVendorString()
8797a14e60SZachary Turner {
8897a14e60SZachary Turner     static bool is_initialized = false;
8997a14e60SZachary Turner     if (!is_initialized)
9097a14e60SZachary Turner     {
9113b18261SZachary Turner         const ArchSpec &host_arch = HostInfo::GetArchitecture();
9297a14e60SZachary Turner         const llvm::StringRef &str_ref = host_arch.GetTriple().getVendorName();
9375172a95SZachary Turner         m_vendor_string.assign(str_ref.begin(), str_ref.end());
9497a14e60SZachary Turner         is_initialized = true;
9597a14e60SZachary Turner     }
9675172a95SZachary Turner     return m_vendor_string;
9797a14e60SZachary Turner }
9897a14e60SZachary Turner 
9997a14e60SZachary Turner llvm::StringRef
10097a14e60SZachary Turner HostInfoBase::GetOSString()
10197a14e60SZachary Turner {
10297a14e60SZachary Turner     static bool is_initialized = false;
10397a14e60SZachary Turner     if (!is_initialized)
10497a14e60SZachary Turner     {
10513b18261SZachary Turner         const ArchSpec &host_arch = HostInfo::GetArchitecture();
10697a14e60SZachary Turner         const llvm::StringRef &str_ref = host_arch.GetTriple().getOSName();
10775172a95SZachary Turner         m_os_string.assign(str_ref.begin(), str_ref.end());
10897a14e60SZachary Turner         is_initialized = true;
10997a14e60SZachary Turner     }
11075172a95SZachary Turner     return m_os_string;
11197a14e60SZachary Turner }
11297a14e60SZachary Turner 
11397a14e60SZachary Turner llvm::StringRef
11497a14e60SZachary Turner HostInfoBase::GetTargetTriple()
11597a14e60SZachary Turner {
11697a14e60SZachary Turner     static bool is_initialized = false;
11797a14e60SZachary Turner     if (!is_initialized)
11897a14e60SZachary Turner     {
11913b18261SZachary Turner         const ArchSpec &host_arch = HostInfo::GetArchitecture();
12075172a95SZachary Turner         m_host_triple = host_arch.GetTriple().getTriple();
12197a14e60SZachary Turner         is_initialized = true;
12297a14e60SZachary Turner     }
12375172a95SZachary Turner     return m_host_triple;
12497a14e60SZachary Turner }
12513b18261SZachary Turner 
12613b18261SZachary Turner const ArchSpec &
12713b18261SZachary Turner HostInfoBase::GetArchitecture(ArchitectureKind arch_kind)
12813b18261SZachary Turner {
12913b18261SZachary Turner     static bool is_initialized = false;
13013b18261SZachary Turner     if (!is_initialized)
13113b18261SZachary Turner     {
13275172a95SZachary Turner         HostInfo::ComputeHostArchitectureSupport(m_host_arch_32, m_host_arch_64);
13313b18261SZachary Turner         is_initialized = true;
13413b18261SZachary Turner     }
13513b18261SZachary Turner 
13613b18261SZachary Turner     // If an explicit 32 or 64-bit architecture was requested, return that.
13713b18261SZachary Turner     if (arch_kind == eArchKind32)
13875172a95SZachary Turner         return m_host_arch_32;
13913b18261SZachary Turner     if (arch_kind == eArchKind64)
14075172a95SZachary Turner         return m_host_arch_64;
14113b18261SZachary Turner 
14213b18261SZachary Turner     // Otherwise prefer the 64-bit architecture if it is valid.
14375172a95SZachary Turner     return (m_host_arch_64.IsValid()) ? m_host_arch_64 : m_host_arch_32;
14413b18261SZachary Turner }
14513b18261SZachary Turner 
146*42ff0ad8SZachary Turner bool
147*42ff0ad8SZachary Turner HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec)
148*42ff0ad8SZachary Turner {
149*42ff0ad8SZachary Turner     file_spec.Clear();
150*42ff0ad8SZachary Turner 
151*42ff0ad8SZachary Turner #if defined(LLDB_DISABLE_PYTHON)
152*42ff0ad8SZachary Turner     if (type == lldb::ePathTypePythonDir)
153*42ff0ad8SZachary Turner         return false;
154*42ff0ad8SZachary Turner #endif
155*42ff0ad8SZachary Turner 
156*42ff0ad8SZachary Turner     Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
157*42ff0ad8SZachary Turner     FileSpec *result = nullptr;
158*42ff0ad8SZachary Turner     switch (type)
159*42ff0ad8SZachary Turner     {
160*42ff0ad8SZachary Turner         case lldb::ePathTypeLLDBShlibDir:
161*42ff0ad8SZachary Turner             COMPUTE_LLDB_PATH(ComputeSharedLibraryDirectory, m_lldb_so_dir)
162*42ff0ad8SZachary Turner             if (log)
163*42ff0ad8SZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", m_lldb_so_dir.GetPath().c_str());
164*42ff0ad8SZachary Turner             break;
165*42ff0ad8SZachary Turner         case lldb::ePathTypeSupportExecutableDir:
166*42ff0ad8SZachary Turner             COMPUTE_LLDB_PATH(ComputeSupportExeDirectory, m_lldb_support_exe_dir)
167*42ff0ad8SZachary Turner             if (log)
168*42ff0ad8SZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'", m_lldb_support_exe_dir.GetPath().c_str());
169*42ff0ad8SZachary Turner             break;
170*42ff0ad8SZachary Turner         case lldb::ePathTypeHeaderDir:
171*42ff0ad8SZachary Turner             COMPUTE_LLDB_PATH(ComputeHeaderDirectory, m_lldb_headers_dir)
172*42ff0ad8SZachary Turner             if (log)
173*42ff0ad8SZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'", m_lldb_headers_dir.GetPath().c_str());
174*42ff0ad8SZachary Turner             break;
175*42ff0ad8SZachary Turner         case lldb::ePathTypePythonDir:
176*42ff0ad8SZachary Turner             COMPUTE_LLDB_PATH(ComputePythonDirectory, m_lldb_python_dir)
177*42ff0ad8SZachary Turner             if (log)
178*42ff0ad8SZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'", m_lldb_python_dir.GetPath().c_str());
179*42ff0ad8SZachary Turner             break;
180*42ff0ad8SZachary Turner         case lldb::ePathTypeLLDBSystemPlugins:
181*42ff0ad8SZachary Turner             COMPUTE_LLDB_PATH(ComputeSystemPluginsDirectory, m_lldb_system_plugin_dir)
182*42ff0ad8SZachary Turner             if (log)
183*42ff0ad8SZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'", m_lldb_system_plugin_dir.GetPath().c_str());
184*42ff0ad8SZachary Turner             break;
185*42ff0ad8SZachary Turner         case lldb::ePathTypeLLDBUserPlugins:
186*42ff0ad8SZachary Turner             COMPUTE_LLDB_PATH(ComputeUserPluginsDirectory, m_lldb_user_plugin_dir)
187*42ff0ad8SZachary Turner             if (log)
188*42ff0ad8SZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'", m_lldb_user_plugin_dir.GetPath().c_str());
189*42ff0ad8SZachary Turner             break;
190*42ff0ad8SZachary Turner         case lldb::ePathTypeLLDBTempSystemDir:
191*42ff0ad8SZachary Turner             COMPUTE_LLDB_PATH(ComputeTempFileDirectory, m_lldb_tmp_dir)
192*42ff0ad8SZachary Turner             if (log)
193*42ff0ad8SZachary Turner                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", m_lldb_tmp_dir.GetPath().c_str());
194*42ff0ad8SZachary Turner             break;
195*42ff0ad8SZachary Turner     }
196*42ff0ad8SZachary Turner 
197*42ff0ad8SZachary Turner     if (!result)
198*42ff0ad8SZachary Turner         return false;
199*42ff0ad8SZachary Turner     file_spec = *result;
200*42ff0ad8SZachary Turner     return true;
201*42ff0ad8SZachary Turner }
202*42ff0ad8SZachary Turner 
203*42ff0ad8SZachary Turner bool
204*42ff0ad8SZachary Turner HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec)
205*42ff0ad8SZachary Turner {
206*42ff0ad8SZachary Turner     // To get paths related to LLDB we get the path to the executable that
207*42ff0ad8SZachary Turner     // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB",
208*42ff0ad8SZachary Turner     // on linux this is assumed to be the "lldb" main executable. If LLDB on
209*42ff0ad8SZachary Turner     // linux is actually in a shared library (liblldb.so) then this function will
210*42ff0ad8SZachary Turner     // need to be modified to "do the right thing".
211*42ff0ad8SZachary Turner 
212*42ff0ad8SZachary Turner     FileSpec lldb_file_spec(
213*42ff0ad8SZachary Turner         Host::GetModuleFileSpecForHostAddress(reinterpret_cast<void *>(reinterpret_cast<intptr_t>(HostInfoBase::GetLLDBPath))));
214*42ff0ad8SZachary Turner 
215*42ff0ad8SZachary Turner     // Remove the filename so that this FileSpec only represents the directory.
216*42ff0ad8SZachary Turner     file_spec.SetFile(lldb_file_spec.GetDirectory().AsCString(), true);
217*42ff0ad8SZachary Turner 
218*42ff0ad8SZachary Turner     return (bool)file_spec.GetDirectory();
219*42ff0ad8SZachary Turner }
220*42ff0ad8SZachary Turner 
221*42ff0ad8SZachary Turner bool
222*42ff0ad8SZachary Turner HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec)
223*42ff0ad8SZachary Turner {
224*42ff0ad8SZachary Turner     return GetLLDBPath(lldb::ePathTypeLLDBShlibDir, file_spec);
225*42ff0ad8SZachary Turner }
226*42ff0ad8SZachary Turner 
227*42ff0ad8SZachary Turner bool
228*42ff0ad8SZachary Turner HostInfoBase::ComputeTempFileDirectory(FileSpec &file_spec)
229*42ff0ad8SZachary Turner {
230*42ff0ad8SZachary Turner     const char *tmpdir_cstr = getenv("TMPDIR");
231*42ff0ad8SZachary Turner     if (tmpdir_cstr == NULL)
232*42ff0ad8SZachary Turner     {
233*42ff0ad8SZachary Turner         tmpdir_cstr = getenv("TMP");
234*42ff0ad8SZachary Turner         if (tmpdir_cstr == NULL)
235*42ff0ad8SZachary Turner             tmpdir_cstr = getenv("TEMP");
236*42ff0ad8SZachary Turner     }
237*42ff0ad8SZachary Turner     if (!tmpdir_cstr)
238*42ff0ad8SZachary Turner         return false;
239*42ff0ad8SZachary Turner 
240*42ff0ad8SZachary Turner     StreamString pid_tmpdir;
241*42ff0ad8SZachary Turner     pid_tmpdir.Printf("%s/lldb", tmpdir_cstr);
242*42ff0ad8SZachary Turner     if (!FileSystem::MakeDirectory(pid_tmpdir.GetString().c_str(), eFilePermissionsDirectoryDefault).Success())
243*42ff0ad8SZachary Turner         return false;
244*42ff0ad8SZachary Turner 
245*42ff0ad8SZachary Turner     pid_tmpdir.Printf("/%" PRIu64, Host::GetCurrentProcessID());
246*42ff0ad8SZachary Turner     if (!FileSystem::MakeDirectory(pid_tmpdir.GetString().c_str(), eFilePermissionsDirectoryDefault).Success())
247*42ff0ad8SZachary Turner         return false;
248*42ff0ad8SZachary Turner 
249*42ff0ad8SZachary Turner     // Make an atexit handler to clean up the process specify LLDB temp dir
250*42ff0ad8SZachary Turner     // and all of its contents.
251*42ff0ad8SZachary Turner     ::atexit(CleanupProcessSpecificLLDBTempDir);
252*42ff0ad8SZachary Turner     file_spec.SetFile(pid_tmpdir.GetString().c_str(), false);
253*42ff0ad8SZachary Turner     return true;
254*42ff0ad8SZachary Turner }
255*42ff0ad8SZachary Turner 
256*42ff0ad8SZachary Turner bool
257*42ff0ad8SZachary Turner HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec)
258*42ff0ad8SZachary Turner {
259*42ff0ad8SZachary Turner     // TODO(zturner): Figure out how to compute the header directory for all platforms.
260*42ff0ad8SZachary Turner     return false;
261*42ff0ad8SZachary Turner }
262*42ff0ad8SZachary Turner 
263*42ff0ad8SZachary Turner bool
264*42ff0ad8SZachary Turner HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec)
265*42ff0ad8SZachary Turner {
266*42ff0ad8SZachary Turner     // TODO(zturner): Figure out how to compute the system plugins directory for all platforms.
267*42ff0ad8SZachary Turner     return false;
268*42ff0ad8SZachary Turner }
269*42ff0ad8SZachary Turner 
270*42ff0ad8SZachary Turner bool
271*42ff0ad8SZachary Turner HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec)
272*42ff0ad8SZachary Turner {
273*42ff0ad8SZachary Turner     // TODO(zturner): Figure out how to compute the user plugins directory for all platforms.
274*42ff0ad8SZachary Turner     return false;
275*42ff0ad8SZachary Turner }
276*42ff0ad8SZachary Turner 
27713b18261SZachary Turner void
27813b18261SZachary Turner HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64)
27913b18261SZachary Turner {
28013b18261SZachary Turner     llvm::Triple triple(llvm::sys::getDefaultTargetTriple());
28113b18261SZachary Turner 
28213b18261SZachary Turner     arch_32.Clear();
28313b18261SZachary Turner     arch_64.Clear();
28413b18261SZachary Turner 
28513b18261SZachary Turner     switch (triple.getArch())
28613b18261SZachary Turner     {
28713b18261SZachary Turner         default:
28813b18261SZachary Turner             arch_32.SetTriple(triple);
28913b18261SZachary Turner             break;
29013b18261SZachary Turner 
29113b18261SZachary Turner         case llvm::Triple::x86_64:
29213b18261SZachary Turner             arch_64.SetTriple(triple);
29313b18261SZachary Turner             arch_32.SetTriple(triple.get32BitArchVariant());
29413b18261SZachary Turner             break;
29513b18261SZachary Turner 
29613b18261SZachary Turner         case llvm::Triple::mips64:
29713b18261SZachary Turner         case llvm::Triple::sparcv9:
29813b18261SZachary Turner         case llvm::Triple::ppc64:
29913b18261SZachary Turner             arch_64.SetTriple(triple);
30013b18261SZachary Turner             break;
30113b18261SZachary Turner     }
30213b18261SZachary Turner }
303