/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Host/common/HostInfoBase.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- HostInfoBase.cpp --------------------------------------------------===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | |
9 | | #include "lldb/Host/Config.h" |
10 | | |
11 | | #include "lldb/Host/FileSystem.h" |
12 | | #include "lldb/Host/Host.h" |
13 | | #include "lldb/Host/HostInfo.h" |
14 | | #include "lldb/Host/HostInfoBase.h" |
15 | | #include "lldb/Utility/ArchSpec.h" |
16 | | #include "lldb/Utility/LLDBLog.h" |
17 | | #include "lldb/Utility/Log.h" |
18 | | #include "lldb/Utility/StreamString.h" |
19 | | |
20 | | #include "llvm/ADT/StringExtras.h" |
21 | | #include "llvm/Support/Path.h" |
22 | | #include "llvm/Support/ScopedPrinter.h" |
23 | | #include "llvm/Support/Threading.h" |
24 | | #include "llvm/Support/raw_ostream.h" |
25 | | #include "llvm/TargetParser/Host.h" |
26 | | #include "llvm/TargetParser/Triple.h" |
27 | | |
28 | | #include <mutex> |
29 | | #include <optional> |
30 | | #include <thread> |
31 | | |
32 | | using namespace lldb; |
33 | | using namespace lldb_private; |
34 | | |
35 | | namespace { |
36 | | /// Contains the state of the HostInfoBase plugin. |
37 | | struct HostInfoBaseFields { |
38 | 4.14k | ~HostInfoBaseFields() { |
39 | 4.14k | if (FileSystem::Instance().Exists(m_lldb_process_tmp_dir)) { |
40 | | // Remove the LLDB temporary directory if we have one. Set "recurse" to |
41 | | // true to all files that were created for the LLDB process can be |
42 | | // cleaned up. |
43 | 985 | llvm::sys::fs::remove_directories(m_lldb_process_tmp_dir.GetPath()); |
44 | 985 | } |
45 | 4.14k | } |
46 | | |
47 | | llvm::once_flag m_host_triple_once; |
48 | | llvm::Triple m_host_triple; |
49 | | |
50 | | llvm::once_flag m_host_arch_once; |
51 | | ArchSpec m_host_arch_32; |
52 | | ArchSpec m_host_arch_64; |
53 | | |
54 | | llvm::once_flag m_lldb_so_dir_once; |
55 | | FileSpec m_lldb_so_dir; |
56 | | llvm::once_flag m_lldb_support_exe_dir_once; |
57 | | FileSpec m_lldb_support_exe_dir; |
58 | | llvm::once_flag m_lldb_headers_dir_once; |
59 | | FileSpec m_lldb_headers_dir; |
60 | | llvm::once_flag m_lldb_clang_resource_dir_once; |
61 | | FileSpec m_lldb_clang_resource_dir; |
62 | | llvm::once_flag m_lldb_system_plugin_dir_once; |
63 | | FileSpec m_lldb_system_plugin_dir; |
64 | | llvm::once_flag m_lldb_user_plugin_dir_once; |
65 | | FileSpec m_lldb_user_plugin_dir; |
66 | | llvm::once_flag m_lldb_process_tmp_dir_once; |
67 | | FileSpec m_lldb_process_tmp_dir; |
68 | | llvm::once_flag m_lldb_global_tmp_dir_once; |
69 | | FileSpec m_lldb_global_tmp_dir; |
70 | | }; |
71 | | } // namespace |
72 | | |
73 | | static HostInfoBaseFields *g_fields = nullptr; |
74 | | static HostInfoBase::SharedLibraryDirectoryHelper *g_shlib_dir_helper = nullptr; |
75 | | |
76 | 4.16k | void HostInfoBase::Initialize(SharedLibraryDirectoryHelper *helper) { |
77 | 4.16k | g_shlib_dir_helper = helper; |
78 | 4.16k | g_fields = new HostInfoBaseFields(); |
79 | 4.16k | } |
80 | | |
81 | 4.15k | void HostInfoBase::Terminate() { |
82 | 4.15k | g_shlib_dir_helper = nullptr; |
83 | 4.15k | delete g_fields; |
84 | 4.15k | g_fields = nullptr; |
85 | 4.15k | } |
86 | | |
87 | 1.30k | llvm::Triple HostInfoBase::GetTargetTriple() { |
88 | 1.30k | llvm::call_once(g_fields->m_host_triple_once, []() { |
89 | 541 | g_fields->m_host_triple = HostInfo::GetArchitecture().GetTriple(); |
90 | 541 | }); |
91 | 1.30k | return g_fields->m_host_triple; |
92 | 1.30k | } |
93 | | |
94 | 147k | const ArchSpec &HostInfoBase::GetArchitecture(ArchitectureKind arch_kind) { |
95 | 147k | llvm::call_once(g_fields->m_host_arch_once, []() { |
96 | 4.04k | HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32, |
97 | 4.04k | g_fields->m_host_arch_64); |
98 | 4.04k | }); |
99 | | |
100 | | // If an explicit 32 or 64-bit architecture was requested, return that. |
101 | 147k | if (arch_kind == eArchKind32) |
102 | 7.79k | return g_fields->m_host_arch_32; |
103 | 139k | if (arch_kind == eArchKind64) |
104 | 7.79k | return g_fields->m_host_arch_64; |
105 | | |
106 | | // Otherwise prefer the 64-bit architecture if it is valid. |
107 | 132k | return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64 |
108 | 132k | : g_fields->m_host_arch_320 ; |
109 | 139k | } |
110 | | |
111 | | std::optional<HostInfoBase::ArchitectureKind> |
112 | 16 | HostInfoBase::ParseArchitectureKind(llvm::StringRef kind) { |
113 | 16 | return llvm::StringSwitch<std::optional<ArchitectureKind>>(kind) |
114 | 16 | .Case(LLDB_ARCH_DEFAULT, eArchKindDefault) |
115 | 16 | .Case(LLDB_ARCH_DEFAULT_32BIT, eArchKind32) |
116 | 16 | .Case(LLDB_ARCH_DEFAULT_64BIT, eArchKind64) |
117 | 16 | .Default(std::nullopt); |
118 | 16 | } |
119 | | |
120 | 15.3k | FileSpec HostInfoBase::GetShlibDir() { |
121 | 15.3k | llvm::call_once(g_fields->m_lldb_so_dir_once, []() { |
122 | 4.02k | if (!HostInfo::ComputeSharedLibraryDirectory(g_fields->m_lldb_so_dir)) |
123 | 0 | g_fields->m_lldb_so_dir = FileSpec(); |
124 | 4.02k | Log *log = GetLog(LLDBLog::Host); |
125 | 4.02k | LLDB_LOG(log, "shlib dir -> `{0}`", g_fields->m_lldb_so_dir); |
126 | 4.02k | }); |
127 | 15.3k | return g_fields->m_lldb_so_dir; |
128 | 15.3k | } |
129 | | |
130 | 1.50k | FileSpec HostInfoBase::GetSupportExeDir() { |
131 | 1.50k | llvm::call_once(g_fields->m_lldb_support_exe_dir_once, []() { |
132 | 809 | if (!HostInfo::ComputeSupportExeDirectory(g_fields->m_lldb_support_exe_dir)) |
133 | 0 | g_fields->m_lldb_support_exe_dir = FileSpec(); |
134 | 809 | Log *log = GetLog(LLDBLog::Host); |
135 | 809 | LLDB_LOG(log, "support exe dir -> `{0}`", g_fields->m_lldb_support_exe_dir); |
136 | 809 | }); |
137 | 1.50k | return g_fields->m_lldb_support_exe_dir; |
138 | 1.50k | } |
139 | | |
140 | 1 | FileSpec HostInfoBase::GetHeaderDir() { |
141 | 1 | llvm::call_once(g_fields->m_lldb_headers_dir_once, []() { |
142 | 1 | if (!HostInfo::ComputeHeaderDirectory(g_fields->m_lldb_headers_dir)) |
143 | 0 | g_fields->m_lldb_headers_dir = FileSpec(); |
144 | 1 | Log *log = GetLog(LLDBLog::Host); |
145 | 1 | LLDB_LOG(log, "header dir -> `{0}`", g_fields->m_lldb_headers_dir); |
146 | 1 | }); |
147 | 1 | return g_fields->m_lldb_headers_dir; |
148 | 1 | } |
149 | | |
150 | 10.0k | FileSpec HostInfoBase::GetSystemPluginDir() { |
151 | 10.0k | llvm::call_once(g_fields->m_lldb_system_plugin_dir_once, []() { |
152 | 3.97k | if (!HostInfo::ComputeSystemPluginsDirectory( |
153 | 3.97k | g_fields->m_lldb_system_plugin_dir)) |
154 | 3.97k | g_fields->m_lldb_system_plugin_dir = FileSpec(); |
155 | 3.97k | Log *log = GetLog(LLDBLog::Host); |
156 | 3.97k | LLDB_LOG(log, "system plugin dir -> `{0}`", |
157 | 3.97k | g_fields->m_lldb_system_plugin_dir); |
158 | 3.97k | }); |
159 | 10.0k | return g_fields->m_lldb_system_plugin_dir; |
160 | 10.0k | } |
161 | | |
162 | 10.0k | FileSpec HostInfoBase::GetUserPluginDir() { |
163 | 10.0k | llvm::call_once(g_fields->m_lldb_user_plugin_dir_once, []() { |
164 | 3.97k | if (!HostInfo::ComputeUserPluginsDirectory( |
165 | 3.97k | g_fields->m_lldb_user_plugin_dir)) |
166 | 0 | g_fields->m_lldb_user_plugin_dir = FileSpec(); |
167 | 3.97k | Log *log = GetLog(LLDBLog::Host); |
168 | 3.97k | LLDB_LOG(log, "user plugin dir -> `{0}`", g_fields->m_lldb_user_plugin_dir); |
169 | 3.97k | }); |
170 | 10.0k | return g_fields->m_lldb_user_plugin_dir; |
171 | 10.0k | } |
172 | | |
173 | 6.85k | FileSpec HostInfoBase::GetProcessTempDir() { |
174 | 6.85k | llvm::call_once(g_fields->m_lldb_process_tmp_dir_once, []() { |
175 | 991 | if (!HostInfo::ComputeProcessTempFileDirectory( |
176 | 991 | g_fields->m_lldb_process_tmp_dir)) |
177 | 0 | g_fields->m_lldb_process_tmp_dir = FileSpec(); |
178 | 991 | Log *log = GetLog(LLDBLog::Host); |
179 | 991 | LLDB_LOG(log, "process temp dir -> `{0}`", |
180 | 991 | g_fields->m_lldb_process_tmp_dir); |
181 | 991 | }); |
182 | 6.85k | return g_fields->m_lldb_process_tmp_dir; |
183 | 6.85k | } |
184 | | |
185 | 0 | FileSpec HostInfoBase::GetGlobalTempDir() { |
186 | 0 | llvm::call_once(g_fields->m_lldb_global_tmp_dir_once, []() { |
187 | 0 | if (!HostInfo::ComputeGlobalTempFileDirectory( |
188 | 0 | g_fields->m_lldb_global_tmp_dir)) |
189 | 0 | g_fields->m_lldb_global_tmp_dir = FileSpec(); |
190 | |
|
191 | 0 | Log *log = GetLog(LLDBLog::Host); |
192 | 0 | LLDB_LOG(log, "global temp dir -> `{0}`", g_fields->m_lldb_global_tmp_dir); |
193 | 0 | }); |
194 | 0 | return g_fields->m_lldb_global_tmp_dir; |
195 | 0 | } |
196 | | |
197 | 5 | ArchSpec HostInfoBase::GetAugmentedArchSpec(llvm::StringRef triple) { |
198 | 5 | if (triple.empty()) |
199 | 0 | return ArchSpec(); |
200 | 5 | llvm::Triple normalized_triple(llvm::Triple::normalize(triple)); |
201 | 5 | if (!ArchSpec::ContainsOnlyArch(normalized_triple)) |
202 | 2 | return ArchSpec(triple); |
203 | | |
204 | 3 | if (auto kind = HostInfo::ParseArchitectureKind(triple)) |
205 | 1 | return HostInfo::GetArchitecture(*kind); |
206 | | |
207 | 2 | llvm::Triple host_triple(llvm::sys::getDefaultTargetTriple()); |
208 | | |
209 | 2 | if (normalized_triple.getVendorName().empty()) |
210 | 2 | normalized_triple.setVendor(host_triple.getVendor()); |
211 | 2 | if (normalized_triple.getOSName().empty()) |
212 | 2 | normalized_triple.setOS(host_triple.getOS()); |
213 | 2 | if (normalized_triple.getEnvironmentName().empty() && |
214 | 2 | !host_triple.getEnvironmentName().empty()) |
215 | 0 | normalized_triple.setEnvironment(host_triple.getEnvironment()); |
216 | 2 | return ArchSpec(normalized_triple); |
217 | 3 | } |
218 | | |
219 | | bool HostInfoBase::ComputePathRelativeToLibrary(FileSpec &file_spec, |
220 | 0 | llvm::StringRef dir) { |
221 | 0 | Log *log = GetLog(LLDBLog::Host); |
222 | |
|
223 | 0 | FileSpec lldb_file_spec = GetShlibDir(); |
224 | 0 | if (!lldb_file_spec) |
225 | 0 | return false; |
226 | | |
227 | 0 | std::string raw_path = lldb_file_spec.GetPath(); |
228 | 0 | LLDB_LOG( |
229 | 0 | log, |
230 | 0 | "Attempting to derive the path {0} relative to liblldb install path: {1}", |
231 | 0 | dir, raw_path); |
232 | | |
233 | | // Drop bin (windows) or lib |
234 | 0 | llvm::StringRef parent_path = llvm::sys::path::parent_path(raw_path); |
235 | 0 | if (parent_path.empty()) { |
236 | 0 | LLDB_LOG(log, "Failed to find liblldb within the shared lib path"); |
237 | 0 | return false; |
238 | 0 | } |
239 | | |
240 | 0 | raw_path = (parent_path + dir).str(); |
241 | 0 | LLDB_LOG(log, "Derived the path as: {0}", raw_path); |
242 | 0 | file_spec.SetDirectory(raw_path); |
243 | 0 | return (bool)file_spec.GetDirectory(); |
244 | 0 | } |
245 | | |
246 | 4.02k | bool HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) { |
247 | | // To get paths related to LLDB we get the path to the executable that |
248 | | // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB". |
249 | | // On other posix systems, we will get .../lib(64|32)?/liblldb.so. |
250 | | |
251 | 4.02k | FileSpec lldb_file_spec(Host::GetModuleFileSpecForHostAddress( |
252 | 4.02k | reinterpret_cast<void *>(HostInfoBase::ComputeSharedLibraryDirectory))); |
253 | | |
254 | 4.02k | if (g_shlib_dir_helper) |
255 | 3.82k | g_shlib_dir_helper(lldb_file_spec); |
256 | | |
257 | | // Remove the filename so that this FileSpec only represents the directory. |
258 | 4.02k | file_spec.SetDirectory(lldb_file_spec.GetDirectory()); |
259 | | |
260 | 4.02k | return (bool)file_spec.GetDirectory(); |
261 | 4.02k | } |
262 | | |
263 | 0 | bool HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec) { |
264 | 0 | file_spec = GetShlibDir(); |
265 | 0 | return bool(file_spec); |
266 | 0 | } |
267 | | |
268 | 991 | bool HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec) { |
269 | 991 | FileSpec temp_file_spec; |
270 | 991 | if (!HostInfo::ComputeGlobalTempFileDirectory(temp_file_spec)) |
271 | 0 | return false; |
272 | | |
273 | 991 | std::string pid_str{llvm::to_string(Host::GetCurrentProcessID())}; |
274 | 991 | temp_file_spec.AppendPathComponent(pid_str); |
275 | 991 | if (llvm::sys::fs::create_directory(temp_file_spec.GetPath())) |
276 | 0 | return false; |
277 | | |
278 | 991 | file_spec.SetDirectory(temp_file_spec.GetPathAsConstString()); |
279 | 991 | return true; |
280 | 991 | } |
281 | | |
282 | 991 | bool HostInfoBase::ComputeTempFileBaseDirectory(FileSpec &file_spec) { |
283 | 991 | llvm::SmallVector<char, 16> tmpdir; |
284 | 991 | llvm::sys::path::system_temp_directory(/*ErasedOnReboot*/ true, tmpdir); |
285 | 991 | file_spec = FileSpec(std::string(tmpdir.data(), tmpdir.size())); |
286 | 991 | FileSystem::Instance().Resolve(file_spec); |
287 | 991 | return true; |
288 | 991 | } |
289 | | |
290 | 991 | bool HostInfoBase::ComputeGlobalTempFileDirectory(FileSpec &file_spec) { |
291 | 991 | file_spec.Clear(); |
292 | | |
293 | 991 | FileSpec temp_file_spec; |
294 | 991 | if (!HostInfo::ComputeTempFileBaseDirectory(temp_file_spec)) |
295 | 0 | return false; |
296 | | |
297 | 991 | temp_file_spec.AppendPathComponent("lldb"); |
298 | 991 | if (llvm::sys::fs::create_directory(temp_file_spec.GetPath())) |
299 | 0 | return false; |
300 | | |
301 | 991 | file_spec.SetDirectory(temp_file_spec.GetPathAsConstString()); |
302 | 991 | return true; |
303 | 991 | } |
304 | | |
305 | 0 | bool HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec) { |
306 | | // TODO(zturner): Figure out how to compute the header directory for all |
307 | | // platforms. |
308 | 0 | return false; |
309 | 0 | } |
310 | | |
311 | 0 | bool HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec) { |
312 | | // TODO(zturner): Figure out how to compute the system plugins directory for |
313 | | // all platforms. |
314 | 0 | return false; |
315 | 0 | } |
316 | | |
317 | 0 | bool HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec) { |
318 | | // TODO(zturner): Figure out how to compute the user plugins directory for |
319 | | // all platforms. |
320 | 0 | return false; |
321 | 0 | } |
322 | | |
323 | | void HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, |
324 | 0 | ArchSpec &arch_64) { |
325 | 0 | llvm::Triple triple(llvm::sys::getProcessTriple()); |
326 | |
|
327 | 0 | arch_32.Clear(); |
328 | 0 | arch_64.Clear(); |
329 | |
|
330 | 0 | switch (triple.getArch()) { |
331 | 0 | default: |
332 | 0 | arch_32.SetTriple(triple); |
333 | 0 | break; |
334 | | |
335 | 0 | case llvm::Triple::aarch64: |
336 | 0 | case llvm::Triple::ppc64: |
337 | 0 | case llvm::Triple::ppc64le: |
338 | 0 | case llvm::Triple::x86_64: |
339 | 0 | case llvm::Triple::riscv64: |
340 | 0 | case llvm::Triple::loongarch64: |
341 | 0 | arch_64.SetTriple(triple); |
342 | 0 | arch_32.SetTriple(triple.get32BitArchVariant()); |
343 | 0 | break; |
344 | | |
345 | 0 | case llvm::Triple::mips64: |
346 | 0 | case llvm::Triple::mips64el: |
347 | 0 | case llvm::Triple::sparcv9: |
348 | 0 | case llvm::Triple::systemz: |
349 | 0 | arch_64.SetTriple(triple); |
350 | 0 | break; |
351 | 0 | } |
352 | 0 | } |