]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Host/common/HostInfoBase.cpp
Update tcpdump to 4.9.2
[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/Host/FileSystem.h"
14 #include "lldb/Host/Host.h"
15 #include "lldb/Host/HostInfo.h"
16 #include "lldb/Host/HostInfoBase.h"
17 #include "lldb/Utility/Log.h"
18 #include "lldb/Utility/StreamString.h"
19
20 #include "llvm/ADT/StringExtras.h"
21 #include "llvm/ADT/Triple.h"
22 #include "llvm/Support/Host.h"
23 #include "llvm/Support/Path.h"
24 #include "llvm/Support/ScopedPrinter.h"
25 #include "llvm/Support/Threading.h"
26 #include "llvm/Support/raw_ostream.h"
27
28 #include <mutex>
29 #include <thread>
30
31 using namespace lldb;
32 using namespace lldb_private;
33
34 namespace {
35 //----------------------------------------------------------------------
36 // The HostInfoBaseFields is a work around for windows not supporting
37 // static variables correctly in a thread safe way. Really each of the
38 // variables in HostInfoBaseFields should live in the functions in which
39 // they are used and each one should be static, but the work around is
40 // in place to avoid this restriction. Ick.
41 //----------------------------------------------------------------------
42
43 struct HostInfoBaseFields {
44   ~HostInfoBaseFields() {
45     if (m_lldb_process_tmp_dir.Exists()) {
46       // Remove the LLDB temporary directory if we have one. Set "recurse" to
47       // true to all files that were created for the LLDB process can be cleaned
48       // up.
49       llvm::sys::fs::remove_directories(m_lldb_process_tmp_dir.GetPath());
50     }
51   }
52
53   std::string m_host_triple;
54
55   ArchSpec m_host_arch_32;
56   ArchSpec m_host_arch_64;
57
58   FileSpec m_lldb_so_dir;
59   FileSpec m_lldb_support_exe_dir;
60   FileSpec m_lldb_headers_dir;
61   FileSpec m_lldb_python_dir;
62   FileSpec m_lldb_clang_resource_dir;
63   FileSpec m_lldb_system_plugin_dir;
64   FileSpec m_lldb_user_plugin_dir;
65   FileSpec m_lldb_process_tmp_dir;
66   FileSpec m_lldb_global_tmp_dir;
67 };
68
69 HostInfoBaseFields *g_fields = nullptr;
70 }
71
72 void HostInfoBase::Initialize() { g_fields = new HostInfoBaseFields(); }
73
74 void HostInfoBase::Terminate() {
75   delete g_fields;
76   g_fields = nullptr;
77 }
78
79 llvm::StringRef HostInfoBase::GetTargetTriple() {
80   static llvm::once_flag g_once_flag;
81   llvm::call_once(g_once_flag, []() {
82     g_fields->m_host_triple =
83         HostInfo::GetArchitecture().GetTriple().getTriple();
84   });
85   return g_fields->m_host_triple;
86 }
87
88 const ArchSpec &HostInfoBase::GetArchitecture(ArchitectureKind arch_kind) {
89   static llvm::once_flag g_once_flag;
90   llvm::call_once(g_once_flag, []() {
91     HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32,
92                                              g_fields->m_host_arch_64);
93   });
94
95   // If an explicit 32 or 64-bit architecture was requested, return that.
96   if (arch_kind == eArchKind32)
97     return g_fields->m_host_arch_32;
98   if (arch_kind == eArchKind64)
99     return g_fields->m_host_arch_64;
100
101   // Otherwise prefer the 64-bit architecture if it is valid.
102   return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64
103                                               : g_fields->m_host_arch_32;
104 }
105
106 bool HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) {
107   file_spec.Clear();
108
109 #if defined(LLDB_DISABLE_PYTHON)
110   if (type == lldb::ePathTypePythonDir)
111     return false;
112 #endif
113
114   FileSpec *result = nullptr;
115   switch (type) {
116   case lldb::ePathTypeLLDBShlibDir: {
117     static llvm::once_flag g_once_flag;
118     static bool success = false;
119     llvm::call_once(g_once_flag, []() {
120       success =
121           HostInfo::ComputeSharedLibraryDirectory(g_fields->m_lldb_so_dir);
122       Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
123       if (log)
124         log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'",
125                     g_fields->m_lldb_so_dir.GetPath().c_str());
126     });
127     if (success)
128       result = &g_fields->m_lldb_so_dir;
129   } break;
130   case lldb::ePathTypeSupportExecutableDir: {
131     static llvm::once_flag g_once_flag;
132     static bool success = false;
133     llvm::call_once(g_once_flag, []() {
134       success = HostInfo::ComputeSupportExeDirectory(
135           g_fields->m_lldb_support_exe_dir);
136       Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
137       if (log)
138         log->Printf(
139             "HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'",
140             g_fields->m_lldb_support_exe_dir.GetPath().c_str());
141     });
142     if (success)
143       result = &g_fields->m_lldb_support_exe_dir;
144   } break;
145   case lldb::ePathTypeHeaderDir: {
146     static llvm::once_flag g_once_flag;
147     static bool success = false;
148     llvm::call_once(g_once_flag, []() {
149       success = HostInfo::ComputeHeaderDirectory(g_fields->m_lldb_headers_dir);
150       Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
151       if (log)
152         log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'",
153                     g_fields->m_lldb_headers_dir.GetPath().c_str());
154     });
155     if (success)
156       result = &g_fields->m_lldb_headers_dir;
157   } break;
158   case lldb::ePathTypePythonDir: {
159     static llvm::once_flag g_once_flag;
160     static bool success = false;
161     llvm::call_once(g_once_flag, []() {
162       success = HostInfo::ComputePythonDirectory(g_fields->m_lldb_python_dir);
163       Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
164       if (log)
165         log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'",
166                     g_fields->m_lldb_python_dir.GetPath().c_str());
167     });
168     if (success)
169       result = &g_fields->m_lldb_python_dir;
170   } break;
171   case lldb::ePathTypeClangDir: {
172     static llvm::once_flag g_once_flag;
173     static bool success = false;
174     llvm::call_once(g_once_flag, []() {
175       success =
176           HostInfo::ComputeClangDirectory(g_fields->m_lldb_clang_resource_dir);
177       Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
178       if (log)
179         log->Printf(
180             "HostInfoBase::GetLLDBPath(ePathTypeClangResourceDir) => '%s'",
181             g_fields->m_lldb_clang_resource_dir.GetPath().c_str());
182     });
183     if (success)
184       result = &g_fields->m_lldb_clang_resource_dir;
185   } break;
186   case lldb::ePathTypeLLDBSystemPlugins: {
187     static llvm::once_flag g_once_flag;
188     static bool success = false;
189     llvm::call_once(g_once_flag, []() {
190       success = HostInfo::ComputeSystemPluginsDirectory(
191           g_fields->m_lldb_system_plugin_dir);
192       Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
193       if (log)
194         log->Printf(
195             "HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'",
196             g_fields->m_lldb_system_plugin_dir.GetPath().c_str());
197     });
198     if (success)
199       result = &g_fields->m_lldb_system_plugin_dir;
200   } break;
201   case lldb::ePathTypeLLDBUserPlugins: {
202     static llvm::once_flag g_once_flag;
203     static bool success = false;
204     llvm::call_once(g_once_flag, []() {
205       success = HostInfo::ComputeUserPluginsDirectory(
206           g_fields->m_lldb_user_plugin_dir);
207       Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
208       if (log)
209         log->Printf(
210             "HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'",
211             g_fields->m_lldb_user_plugin_dir.GetPath().c_str());
212     });
213     if (success)
214       result = &g_fields->m_lldb_user_plugin_dir;
215   } break;
216   case lldb::ePathTypeLLDBTempSystemDir: {
217     static llvm::once_flag g_once_flag;
218     static bool success = false;
219     llvm::call_once(g_once_flag, []() {
220       success = HostInfo::ComputeProcessTempFileDirectory(
221           g_fields->m_lldb_process_tmp_dir);
222       Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
223       if (log)
224         log->Printf(
225             "HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'",
226             g_fields->m_lldb_process_tmp_dir.GetPath().c_str());
227     });
228     if (success)
229       result = &g_fields->m_lldb_process_tmp_dir;
230   } break;
231   case lldb::ePathTypeGlobalLLDBTempSystemDir: {
232     static llvm::once_flag g_once_flag;
233     static bool success = false;
234     llvm::call_once(g_once_flag, []() {
235       success = HostInfo::ComputeGlobalTempFileDirectory(
236           g_fields->m_lldb_global_tmp_dir);
237       Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
238       if (log)
239         log->Printf("HostInfoBase::GetLLDBPath("
240                     "ePathTypeGlobalLLDBTempSystemDir) => '%s'",
241                     g_fields->m_lldb_global_tmp_dir.GetPath().c_str());
242     });
243     if (success)
244       result = &g_fields->m_lldb_global_tmp_dir;
245   } break;
246   }
247
248   if (!result)
249     return false;
250   file_spec = *result;
251   return true;
252 }
253
254 bool HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) {
255   // To get paths related to LLDB we get the path to the executable that
256   // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB",
257   // on linux this is assumed to be the "lldb" main executable. If LLDB on
258   // linux is actually in a shared library (liblldb.so) then this function will
259   // need to be modified to "do the right thing".
260
261   FileSpec lldb_file_spec(
262       Host::GetModuleFileSpecForHostAddress(reinterpret_cast<void *>(
263           reinterpret_cast<intptr_t>(HostInfoBase::GetLLDBPath))));
264
265   // This is necessary because when running the testsuite the shlib might be a
266   // symbolic link inside the Python resource dir.
267   FileSystem::ResolveSymbolicLink(lldb_file_spec, lldb_file_spec);
268
269   // Remove the filename so that this FileSpec only represents the directory.
270   file_spec.GetDirectory() = lldb_file_spec.GetDirectory();
271
272   return (bool)file_spec.GetDirectory();
273 }
274
275 bool HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec) {
276   return GetLLDBPath(lldb::ePathTypeLLDBShlibDir, file_spec);
277 }
278
279 bool HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec) {
280   FileSpec temp_file_spec;
281   if (!HostInfo::ComputeGlobalTempFileDirectory(temp_file_spec))
282     return false;
283
284   std::string pid_str{llvm::to_string(Host::GetCurrentProcessID())};
285   temp_file_spec.AppendPathComponent(pid_str);
286   if (llvm::sys::fs::create_directory(temp_file_spec.GetPath()))
287     return false;
288
289   file_spec.GetDirectory().SetCString(temp_file_spec.GetCString());
290   return true;
291 }
292
293 bool HostInfoBase::ComputeTempFileBaseDirectory(FileSpec &file_spec) {
294   llvm::SmallVector<char, 16> tmpdir;
295   llvm::sys::path::system_temp_directory(/*ErasedOnReboot*/ true, tmpdir);
296   file_spec = FileSpec(std::string(tmpdir.data(), tmpdir.size()), true);
297   return true;
298 }
299
300 bool HostInfoBase::ComputeGlobalTempFileDirectory(FileSpec &file_spec) {
301   file_spec.Clear();
302
303   FileSpec temp_file_spec;
304   if (!HostInfo::ComputeTempFileBaseDirectory(temp_file_spec))
305     return false;
306
307   temp_file_spec.AppendPathComponent("lldb");
308   if (llvm::sys::fs::create_directory(temp_file_spec.GetPath()))
309     return false;
310
311   file_spec.GetDirectory().SetCString(temp_file_spec.GetCString());
312   return true;
313 }
314
315 bool HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec) {
316   // TODO(zturner): Figure out how to compute the header directory for all
317   // platforms.
318   return false;
319 }
320
321 bool HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec) {
322   // TODO(zturner): Figure out how to compute the system plugins directory for
323   // all platforms.
324   return false;
325 }
326
327 bool HostInfoBase::ComputeClangDirectory(FileSpec &file_spec) { return false; }
328
329 bool HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec) {
330   // TODO(zturner): Figure out how to compute the user plugins directory for all
331   // platforms.
332   return false;
333 }
334
335 void HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32,
336                                                   ArchSpec &arch_64) {
337   llvm::Triple triple(llvm::sys::getProcessTriple());
338
339   arch_32.Clear();
340   arch_64.Clear();
341
342   switch (triple.getArch()) {
343   default:
344     arch_32.SetTriple(triple);
345     break;
346
347   case llvm::Triple::aarch64:
348   case llvm::Triple::ppc64:
349   case llvm::Triple::x86_64:
350     arch_64.SetTriple(triple);
351     arch_32.SetTriple(triple.get32BitArchVariant());
352     break;
353
354   case llvm::Triple::mips64:
355   case llvm::Triple::mips64el:
356   case llvm::Triple::sparcv9:
357   case llvm::Triple::systemz:
358     arch_64.SetTriple(triple);
359     break;
360   }
361 }