]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Host/common/HostInfoBase.cpp
MFV r277870
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Host / common / HostInfoBase.cpp
1 //===-- HostInfoBase.cpp ----------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/Host/Config.h"
11
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"
19
20 #include "llvm/ADT/Triple.h"
21 #include "llvm/Support/Host.h"
22
23 #include <thread>
24
25 using namespace lldb;
26 using namespace lldb_private;
27
28 namespace
29 {
30 void
31 CleanupProcessSpecificLLDBTempDir()
32 {
33     // Get the process specific LLDB temporary directory and delete it.
34     FileSpec tmpdir_file_spec;
35     if (!HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
36         return;
37
38     // Remove the LLDB temporary directory if we have one. Set "recurse" to
39     // true to all files that were created for the LLDB process can be cleaned up.
40     FileSystem::DeleteDirectory(tmpdir_file_spec.GetDirectory().GetCString(), true);
41 }
42
43 struct HostInfoBaseFields
44 {
45     uint32_t m_number_cpus;
46     std::string m_vendor_string;
47     std::string m_os_string;
48     std::string m_host_triple;
49
50     ArchSpec m_host_arch_32;
51     ArchSpec m_host_arch_64;
52
53     FileSpec m_lldb_so_dir;
54     FileSpec m_lldb_support_exe_dir;
55     FileSpec m_lldb_headers_dir;
56     FileSpec m_lldb_python_dir;
57     FileSpec m_lldb_system_plugin_dir;
58     FileSpec m_lldb_user_plugin_dir;
59     FileSpec m_lldb_tmp_dir;
60 };
61
62 HostInfoBaseFields *g_fields = nullptr;
63 }
64
65 #define COMPUTE_LLDB_PATH(compute_function, member_var)                                                                                    \
66     {                                                                                                                                      \
67         static bool is_initialized = false;                                                                                                \
68         static bool success = false;                                                                                                       \
69         if (!is_initialized)                                                                                                               \
70         {                                                                                                                                  \
71             is_initialized = true;                                                                                                         \
72             success = HostInfo::compute_function(member_var);                                                                              \
73         }                                                                                                                                  \
74         if (success)                                                                                                                       \
75             result = &member_var;                                                                                                          \
76     }
77
78 void
79 HostInfoBase::Initialize()
80 {
81     g_fields = new HostInfoBaseFields();
82 }
83
84 uint32_t
85 HostInfoBase::GetNumberCPUS()
86 {
87     static bool is_initialized = false;
88     if (!is_initialized)
89     {
90         g_fields->m_number_cpus = std::thread::hardware_concurrency();
91         is_initialized = true;
92     }
93
94     return g_fields->m_number_cpus;
95 }
96
97 llvm::StringRef
98 HostInfoBase::GetVendorString()
99 {
100     static bool is_initialized = false;
101     if (!is_initialized)
102     {
103         const ArchSpec &host_arch = HostInfo::GetArchitecture();
104         const llvm::StringRef &str_ref = host_arch.GetTriple().getVendorName();
105         g_fields->m_vendor_string.assign(str_ref.begin(), str_ref.end());
106         is_initialized = true;
107     }
108     return g_fields->m_vendor_string;
109 }
110
111 llvm::StringRef
112 HostInfoBase::GetOSString()
113 {
114     static bool is_initialized = false;
115     if (!is_initialized)
116     {
117         const ArchSpec &host_arch = HostInfo::GetArchitecture();
118         const llvm::StringRef &str_ref = host_arch.GetTriple().getOSName();
119         g_fields->m_os_string.assign(str_ref.begin(), str_ref.end());
120         is_initialized = true;
121     }
122     return g_fields->m_os_string;
123 }
124
125 llvm::StringRef
126 HostInfoBase::GetTargetTriple()
127 {
128     static bool is_initialized = false;
129     if (!is_initialized)
130     {
131         const ArchSpec &host_arch = HostInfo::GetArchitecture();
132         g_fields->m_host_triple = host_arch.GetTriple().getTriple();
133         is_initialized = true;
134     }
135     return g_fields->m_host_triple;
136 }
137
138 const ArchSpec &
139 HostInfoBase::GetArchitecture(ArchitectureKind arch_kind)
140 {
141     static bool is_initialized = false;
142     if (!is_initialized)
143     {
144         HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32, g_fields->m_host_arch_64);
145         is_initialized = true;
146     }
147
148     // If an explicit 32 or 64-bit architecture was requested, return that.
149     if (arch_kind == eArchKind32)
150         return g_fields->m_host_arch_32;
151     if (arch_kind == eArchKind64)
152         return g_fields->m_host_arch_64;
153
154     // Otherwise prefer the 64-bit architecture if it is valid.
155     return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64 : g_fields->m_host_arch_32;
156 }
157
158 bool
159 HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec)
160 {
161     file_spec.Clear();
162
163 #if defined(LLDB_DISABLE_PYTHON)
164     if (type == lldb::ePathTypePythonDir)
165         return false;
166 #endif
167
168     Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
169     FileSpec *result = nullptr;
170     switch (type)
171     {
172         case lldb::ePathTypeLLDBShlibDir:
173             COMPUTE_LLDB_PATH(ComputeSharedLibraryDirectory, g_fields->m_lldb_so_dir)
174             if (log)
175                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", g_fields->m_lldb_so_dir.GetPath().c_str());
176             break;
177         case lldb::ePathTypeSupportExecutableDir:
178             COMPUTE_LLDB_PATH(ComputeSupportExeDirectory, g_fields->m_lldb_support_exe_dir)
179             if (log)
180                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'",
181                             g_fields->m_lldb_support_exe_dir.GetPath().c_str());
182             break;
183         case lldb::ePathTypeHeaderDir:
184             COMPUTE_LLDB_PATH(ComputeHeaderDirectory, g_fields->m_lldb_headers_dir)
185             if (log)
186                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'", g_fields->m_lldb_headers_dir.GetPath().c_str());
187             break;
188         case lldb::ePathTypePythonDir:
189             COMPUTE_LLDB_PATH(ComputePythonDirectory, g_fields->m_lldb_python_dir)
190             if (log)
191                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'", g_fields->m_lldb_python_dir.GetPath().c_str());
192             break;
193         case lldb::ePathTypeLLDBSystemPlugins:
194             COMPUTE_LLDB_PATH(ComputeSystemPluginsDirectory, g_fields->m_lldb_system_plugin_dir)
195             if (log)
196                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'",
197                             g_fields->m_lldb_system_plugin_dir.GetPath().c_str());
198             break;
199         case lldb::ePathTypeLLDBUserPlugins:
200             COMPUTE_LLDB_PATH(ComputeUserPluginsDirectory, g_fields->m_lldb_user_plugin_dir)
201             if (log)
202                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'",
203                             g_fields->m_lldb_user_plugin_dir.GetPath().c_str());
204             break;
205         case lldb::ePathTypeLLDBTempSystemDir:
206             COMPUTE_LLDB_PATH(ComputeTempFileDirectory, g_fields->m_lldb_tmp_dir)
207             if (log)
208                 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", g_fields->m_lldb_tmp_dir.GetPath().c_str());
209             break;
210     }
211
212     if (!result)
213         return false;
214     file_spec = *result;
215     return true;
216 }
217
218 bool
219 HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec)
220 {
221     // To get paths related to LLDB we get the path to the executable that
222     // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB",
223     // on linux this is assumed to be the "lldb" main executable. If LLDB on
224     // linux is actually in a shared library (liblldb.so) then this function will
225     // need to be modified to "do the right thing".
226
227     FileSpec lldb_file_spec(
228         Host::GetModuleFileSpecForHostAddress(reinterpret_cast<void *>(reinterpret_cast<intptr_t>(HostInfoBase::GetLLDBPath))));
229
230     // Remove the filename so that this FileSpec only represents the directory.
231     file_spec.GetDirectory() = lldb_file_spec.GetDirectory();
232
233     return (bool)file_spec.GetDirectory();
234 }
235
236 bool
237 HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec)
238 {
239     return GetLLDBPath(lldb::ePathTypeLLDBShlibDir, file_spec);
240 }
241
242 bool
243 HostInfoBase::ComputeTempFileDirectory(FileSpec &file_spec)
244 {
245     const char *tmpdir_cstr = getenv("TMPDIR");
246     if (tmpdir_cstr == NULL)
247     {
248         tmpdir_cstr = getenv("TMP");
249         if (tmpdir_cstr == NULL)
250             tmpdir_cstr = getenv("TEMP");
251     }
252     if (!tmpdir_cstr)
253         return false;
254
255     StreamString pid_tmpdir;
256     pid_tmpdir.Printf("%s/lldb", tmpdir_cstr);
257     if (!FileSystem::MakeDirectory(pid_tmpdir.GetString().c_str(), eFilePermissionsDirectoryDefault).Success())
258         return false;
259
260     pid_tmpdir.Printf("/%" PRIu64, Host::GetCurrentProcessID());
261     if (!FileSystem::MakeDirectory(pid_tmpdir.GetString().c_str(), eFilePermissionsDirectoryDefault).Success())
262         return false;
263
264     // Make an atexit handler to clean up the process specify LLDB temp dir
265     // and all of its contents.
266     ::atexit(CleanupProcessSpecificLLDBTempDir);
267     file_spec.GetDirectory().SetCStringWithLength(pid_tmpdir.GetString().c_str(), pid_tmpdir.GetString().size());
268     return true;
269 }
270
271 bool
272 HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec)
273 {
274     // TODO(zturner): Figure out how to compute the header directory for all platforms.
275     return false;
276 }
277
278 bool
279 HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec)
280 {
281     // TODO(zturner): Figure out how to compute the system plugins directory for all platforms.
282     return false;
283 }
284
285 bool
286 HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec)
287 {
288     // TODO(zturner): Figure out how to compute the user plugins directory for all platforms.
289     return false;
290 }
291
292 void
293 HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64)
294 {
295     llvm::Triple triple(llvm::sys::getDefaultTargetTriple());
296
297     arch_32.Clear();
298     arch_64.Clear();
299
300     switch (triple.getArch())
301     {
302         default:
303             arch_32.SetTriple(triple);
304             break;
305
306         case llvm::Triple::x86_64:
307             arch_64.SetTriple(triple);
308             arch_32.SetTriple(triple.get32BitArchVariant());
309             break;
310
311         case llvm::Triple::aarch64:
312         case llvm::Triple::mips64:
313         case llvm::Triple::sparcv9:
314         case llvm::Triple::ppc64:
315             arch_64.SetTriple(triple);
316             break;
317     }
318 }