]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Host/common/HostInfoBase.cpp
Merge clang 7.0.1 and several follow-up changes
[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/Host/FileSystem.h"
13 #include "lldb/Host/Host.h"
14 #include "lldb/Host/HostInfo.h"
15 #include "lldb/Host/HostInfoBase.h"
16 #include "lldb/Utility/ArchSpec.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 static
37 // variables correctly in a thread safe way. Really each of the variables in
38 // HostInfoBaseFields should live in the functions in which they are used and
39 // each one should be static, but the work around is in place to avoid this
40 // 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
48       // cleaned 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_clang_resource_dir;
62   FileSpec m_lldb_system_plugin_dir;
63   FileSpec m_lldb_user_plugin_dir;
64   FileSpec m_lldb_process_tmp_dir;
65   FileSpec m_lldb_global_tmp_dir;
66 };
67
68 HostInfoBaseFields *g_fields = nullptr;
69 }
70
71 void HostInfoBase::Initialize() { g_fields = new HostInfoBaseFields(); }
72
73 void HostInfoBase::Terminate() {
74   delete g_fields;
75   g_fields = nullptr;
76 }
77
78 llvm::StringRef HostInfoBase::GetTargetTriple() {
79   static llvm::once_flag g_once_flag;
80   llvm::call_once(g_once_flag, []() {
81     g_fields->m_host_triple =
82         HostInfo::GetArchitecture().GetTriple().getTriple();
83   });
84   return g_fields->m_host_triple;
85 }
86
87 const ArchSpec &HostInfoBase::GetArchitecture(ArchitectureKind arch_kind) {
88   static llvm::once_flag g_once_flag;
89   llvm::call_once(g_once_flag, []() {
90     HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32,
91                                              g_fields->m_host_arch_64);
92   });
93
94   // If an explicit 32 or 64-bit architecture was requested, return that.
95   if (arch_kind == eArchKind32)
96     return g_fields->m_host_arch_32;
97   if (arch_kind == eArchKind64)
98     return g_fields->m_host_arch_64;
99
100   // Otherwise prefer the 64-bit architecture if it is valid.
101   return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64
102                                               : g_fields->m_host_arch_32;
103 }
104
105 llvm::Optional<HostInfoBase::ArchitectureKind> HostInfoBase::ParseArchitectureKind(llvm::StringRef kind) {
106   return llvm::StringSwitch<llvm::Optional<ArchitectureKind>>(kind)
107       .Case(LLDB_ARCH_DEFAULT, eArchKindDefault)
108       .Case(LLDB_ARCH_DEFAULT_32BIT, eArchKind32)
109       .Case(LLDB_ARCH_DEFAULT_64BIT, eArchKind64)
110       .Default(llvm::None);
111 }
112
113 FileSpec HostInfoBase::GetShlibDir() {
114   static llvm::once_flag g_once_flag;
115   static bool success = false;
116   llvm::call_once(g_once_flag, []() {
117     success = HostInfo::ComputeSharedLibraryDirectory(g_fields->m_lldb_so_dir);
118     Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
119     LLDB_LOG(log, "shlib dir -> `{0}`", g_fields->m_lldb_so_dir);
120   });
121   return success ? g_fields->m_lldb_so_dir : FileSpec();
122 }
123
124 FileSpec HostInfoBase::GetSupportExeDir() {
125   static llvm::once_flag g_once_flag;
126   static bool success = false;
127   llvm::call_once(g_once_flag, []() {
128     success =
129         HostInfo::ComputeSupportExeDirectory(g_fields->m_lldb_support_exe_dir);
130     Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
131     LLDB_LOG(log, "support exe dir -> `{0}`", g_fields->m_lldb_support_exe_dir);
132   });
133   return success ? g_fields->m_lldb_support_exe_dir : FileSpec();
134 }
135
136 FileSpec HostInfoBase::GetHeaderDir() {
137   static llvm::once_flag g_once_flag;
138   static bool success = false;
139   llvm::call_once(g_once_flag, []() {
140     success = HostInfo::ComputeHeaderDirectory(g_fields->m_lldb_headers_dir);
141     Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
142     LLDB_LOG(log, "header dir -> `{0}`", g_fields->m_lldb_headers_dir);
143   });
144   return success ? g_fields->m_lldb_headers_dir : FileSpec();
145 }
146
147 FileSpec HostInfoBase::GetSystemPluginDir() {
148   static llvm::once_flag g_once_flag;
149   static bool success = false;
150   llvm::call_once(g_once_flag, []() {
151     success = HostInfo::ComputeSystemPluginsDirectory(
152         g_fields->m_lldb_system_plugin_dir);
153     Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
154     LLDB_LOG(log, "system plugin dir -> `{0}`",
155              g_fields->m_lldb_system_plugin_dir);
156   });
157   return success ? g_fields->m_lldb_system_plugin_dir : FileSpec();
158 }
159
160 FileSpec HostInfoBase::GetUserPluginDir() {
161   static llvm::once_flag g_once_flag;
162   static bool success = false;
163   llvm::call_once(g_once_flag, []() {
164     success =
165         HostInfo::ComputeUserPluginsDirectory(g_fields->m_lldb_user_plugin_dir);
166     Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
167     LLDB_LOG(log, "user plugin dir -> `{0}`", g_fields->m_lldb_user_plugin_dir);
168   });
169   return success ? g_fields->m_lldb_user_plugin_dir : FileSpec();
170 }
171
172 FileSpec HostInfoBase::GetProcessTempDir() {
173   static llvm::once_flag g_once_flag;
174   static bool success = false;
175   llvm::call_once(g_once_flag, []() {
176     success = HostInfo::ComputeProcessTempFileDirectory(
177         g_fields->m_lldb_process_tmp_dir);
178     Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
179     LLDB_LOG(log, "process temp dir -> `{0}`",
180              g_fields->m_lldb_process_tmp_dir);
181   });
182   return success ? g_fields->m_lldb_process_tmp_dir : FileSpec();
183 }
184
185 FileSpec HostInfoBase::GetGlobalTempDir() {
186   static llvm::once_flag g_once_flag;
187   static bool success = false;
188   llvm::call_once(g_once_flag, []() {
189     success = HostInfo::ComputeGlobalTempFileDirectory(
190         g_fields->m_lldb_global_tmp_dir);
191     Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
192     LLDB_LOG(log, "global temp dir -> `{0}`", g_fields->m_lldb_global_tmp_dir);
193   });
194   return success ? g_fields->m_lldb_global_tmp_dir : FileSpec();
195 }
196
197 ArchSpec HostInfoBase::GetAugmentedArchSpec(llvm::StringRef triple) {
198   if (triple.empty())
199     return ArchSpec();
200   llvm::Triple normalized_triple(llvm::Triple::normalize(triple));
201   if (!ArchSpec::ContainsOnlyArch(normalized_triple))
202     return ArchSpec(triple);
203
204   if (auto kind = HostInfo::ParseArchitectureKind(triple))
205     return HostInfo::GetArchitecture(*kind);
206
207   llvm::Triple host_triple(llvm::sys::getDefaultTargetTriple());
208
209   if (normalized_triple.getVendorName().empty())
210     normalized_triple.setVendor(host_triple.getVendor());
211   if (normalized_triple.getOSName().empty())
212     normalized_triple.setOS(host_triple.getOS());
213   if (normalized_triple.getEnvironmentName().empty())
214     normalized_triple.setEnvironment(host_triple.getEnvironment());
215   return ArchSpec(normalized_triple);
216 }
217
218 bool HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) {
219   // To get paths related to LLDB we get the path to the executable that
220   // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB".
221   // On other posix systems, we will get .../lib(64|32)?/liblldb.so.
222
223   FileSpec lldb_file_spec(Host::GetModuleFileSpecForHostAddress(
224       reinterpret_cast<void *>(reinterpret_cast<intptr_t>(
225           HostInfoBase::ComputeSharedLibraryDirectory))));
226
227   // This is necessary because when running the testsuite the shlib might be a
228   // symbolic link inside the Python resource dir.
229   FileSystem::ResolveSymbolicLink(lldb_file_spec, lldb_file_spec);
230
231   // Remove the filename so that this FileSpec only represents the directory.
232   file_spec.GetDirectory() = lldb_file_spec.GetDirectory();
233
234   return (bool)file_spec.GetDirectory();
235 }
236
237 bool HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec) {
238   file_spec = GetShlibDir();
239   return bool(file_spec);
240 }
241
242 bool HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec) {
243   FileSpec temp_file_spec;
244   if (!HostInfo::ComputeGlobalTempFileDirectory(temp_file_spec))
245     return false;
246
247   std::string pid_str{llvm::to_string(Host::GetCurrentProcessID())};
248   temp_file_spec.AppendPathComponent(pid_str);
249   if (llvm::sys::fs::create_directory(temp_file_spec.GetPath()))
250     return false;
251
252   file_spec.GetDirectory().SetCString(temp_file_spec.GetCString());
253   return true;
254 }
255
256 bool HostInfoBase::ComputeTempFileBaseDirectory(FileSpec &file_spec) {
257   llvm::SmallVector<char, 16> tmpdir;
258   llvm::sys::path::system_temp_directory(/*ErasedOnReboot*/ true, tmpdir);
259   file_spec = FileSpec(std::string(tmpdir.data(), tmpdir.size()), true);
260   return true;
261 }
262
263 bool HostInfoBase::ComputeGlobalTempFileDirectory(FileSpec &file_spec) {
264   file_spec.Clear();
265
266   FileSpec temp_file_spec;
267   if (!HostInfo::ComputeTempFileBaseDirectory(temp_file_spec))
268     return false;
269
270   temp_file_spec.AppendPathComponent("lldb");
271   if (llvm::sys::fs::create_directory(temp_file_spec.GetPath()))
272     return false;
273
274   file_spec.GetDirectory().SetCString(temp_file_spec.GetCString());
275   return true;
276 }
277
278 bool HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec) {
279   // TODO(zturner): Figure out how to compute the header directory for all
280   // platforms.
281   return false;
282 }
283
284 bool HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec) {
285   // TODO(zturner): Figure out how to compute the system plugins directory for
286   // all platforms.
287   return false;
288 }
289
290 bool HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec) {
291   // TODO(zturner): Figure out how to compute the user plugins directory for
292   // all platforms.
293   return false;
294 }
295
296 void HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32,
297                                                   ArchSpec &arch_64) {
298   llvm::Triple triple(llvm::sys::getProcessTriple());
299
300   arch_32.Clear();
301   arch_64.Clear();
302
303   switch (triple.getArch()) {
304   default:
305     arch_32.SetTriple(triple);
306     break;
307
308   case llvm::Triple::aarch64:
309   case llvm::Triple::ppc64:
310   case llvm::Triple::ppc64le:
311   case llvm::Triple::x86_64:
312     arch_64.SetTriple(triple);
313     arch_32.SetTriple(triple.get32BitArchVariant());
314     break;
315
316   case llvm::Triple::mips64:
317   case llvm::Triple::mips64el:
318   case llvm::Triple::sparcv9:
319   case llvm::Triple::systemz:
320     arch_64.SetTriple(triple);
321     break;
322   }
323 }