xref: /openbsd-src/gnu/llvm/lldb/source/Host/common/HostInfoBase.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- HostInfoBase.cpp --------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "lldb/Host/Config.h"
10061da546Spatrick 
11061da546Spatrick #include "lldb/Host/FileSystem.h"
12061da546Spatrick #include "lldb/Host/Host.h"
13061da546Spatrick #include "lldb/Host/HostInfo.h"
14061da546Spatrick #include "lldb/Host/HostInfoBase.h"
15061da546Spatrick #include "lldb/Utility/ArchSpec.h"
16*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
17061da546Spatrick #include "lldb/Utility/Log.h"
18061da546Spatrick #include "lldb/Utility/StreamString.h"
19061da546Spatrick 
20061da546Spatrick #include "llvm/ADT/StringExtras.h"
21061da546Spatrick #include "llvm/ADT/Triple.h"
22061da546Spatrick #include "llvm/Support/Host.h"
23061da546Spatrick #include "llvm/Support/Path.h"
24061da546Spatrick #include "llvm/Support/ScopedPrinter.h"
25061da546Spatrick #include "llvm/Support/Threading.h"
26061da546Spatrick #include "llvm/Support/raw_ostream.h"
27061da546Spatrick 
28061da546Spatrick #include <mutex>
29*f6aab3d8Srobert #include <optional>
30061da546Spatrick #include <thread>
31061da546Spatrick 
32061da546Spatrick using namespace lldb;
33061da546Spatrick using namespace lldb_private;
34061da546Spatrick 
35061da546Spatrick namespace {
36be691f3bSpatrick /// Contains the state of the HostInfoBase plugin.
37061da546Spatrick struct HostInfoBaseFields {
~HostInfoBaseFields__anon3ed34a4e0111::HostInfoBaseFields38061da546Spatrick   ~HostInfoBaseFields() {
39061da546Spatrick     if (FileSystem::Instance().Exists(m_lldb_process_tmp_dir)) {
40061da546Spatrick       // Remove the LLDB temporary directory if we have one. Set "recurse" to
41061da546Spatrick       // true to all files that were created for the LLDB process can be
42061da546Spatrick       // cleaned up.
43061da546Spatrick       llvm::sys::fs::remove_directories(m_lldb_process_tmp_dir.GetPath());
44061da546Spatrick     }
45061da546Spatrick   }
46061da546Spatrick 
47061da546Spatrick   llvm::once_flag m_host_triple_once;
48061da546Spatrick   llvm::Triple m_host_triple;
49061da546Spatrick 
50061da546Spatrick   llvm::once_flag m_host_arch_once;
51061da546Spatrick   ArchSpec m_host_arch_32;
52061da546Spatrick   ArchSpec m_host_arch_64;
53061da546Spatrick 
54061da546Spatrick   llvm::once_flag m_lldb_so_dir_once;
55061da546Spatrick   FileSpec m_lldb_so_dir;
56061da546Spatrick   llvm::once_flag m_lldb_support_exe_dir_once;
57061da546Spatrick   FileSpec m_lldb_support_exe_dir;
58061da546Spatrick   llvm::once_flag m_lldb_headers_dir_once;
59061da546Spatrick   FileSpec m_lldb_headers_dir;
60061da546Spatrick   llvm::once_flag m_lldb_clang_resource_dir_once;
61061da546Spatrick   FileSpec m_lldb_clang_resource_dir;
62061da546Spatrick   llvm::once_flag m_lldb_system_plugin_dir_once;
63061da546Spatrick   FileSpec m_lldb_system_plugin_dir;
64061da546Spatrick   llvm::once_flag m_lldb_user_plugin_dir_once;
65061da546Spatrick   FileSpec m_lldb_user_plugin_dir;
66061da546Spatrick   llvm::once_flag m_lldb_process_tmp_dir_once;
67061da546Spatrick   FileSpec m_lldb_process_tmp_dir;
68061da546Spatrick   llvm::once_flag m_lldb_global_tmp_dir_once;
69061da546Spatrick   FileSpec m_lldb_global_tmp_dir;
70061da546Spatrick };
71be691f3bSpatrick } // namespace
72061da546Spatrick 
73be691f3bSpatrick static HostInfoBaseFields *g_fields = nullptr;
74be691f3bSpatrick static HostInfoBase::SharedLibraryDirectoryHelper *g_shlib_dir_helper = nullptr;
75be691f3bSpatrick 
Initialize(SharedLibraryDirectoryHelper * helper)76be691f3bSpatrick void HostInfoBase::Initialize(SharedLibraryDirectoryHelper *helper) {
77be691f3bSpatrick   g_shlib_dir_helper = helper;
78be691f3bSpatrick   g_fields = new HostInfoBaseFields();
79061da546Spatrick }
80061da546Spatrick 
Terminate()81061da546Spatrick void HostInfoBase::Terminate() {
82be691f3bSpatrick   g_shlib_dir_helper = nullptr;
83061da546Spatrick   delete g_fields;
84061da546Spatrick   g_fields = nullptr;
85061da546Spatrick }
86061da546Spatrick 
GetTargetTriple()87061da546Spatrick llvm::Triple HostInfoBase::GetTargetTriple() {
88061da546Spatrick   llvm::call_once(g_fields->m_host_triple_once, []() {
89*f6aab3d8Srobert     g_fields->m_host_triple = HostInfo::GetArchitecture().GetTriple();
90061da546Spatrick   });
91061da546Spatrick   return g_fields->m_host_triple;
92061da546Spatrick }
93061da546Spatrick 
GetArchitecture(ArchitectureKind arch_kind)94061da546Spatrick const ArchSpec &HostInfoBase::GetArchitecture(ArchitectureKind arch_kind) {
95061da546Spatrick   llvm::call_once(g_fields->m_host_arch_once, []() {
96061da546Spatrick     HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32,
97061da546Spatrick                                              g_fields->m_host_arch_64);
98061da546Spatrick   });
99061da546Spatrick 
100061da546Spatrick   // If an explicit 32 or 64-bit architecture was requested, return that.
101061da546Spatrick   if (arch_kind == eArchKind32)
102061da546Spatrick     return g_fields->m_host_arch_32;
103061da546Spatrick   if (arch_kind == eArchKind64)
104061da546Spatrick     return g_fields->m_host_arch_64;
105061da546Spatrick 
106061da546Spatrick   // Otherwise prefer the 64-bit architecture if it is valid.
107061da546Spatrick   return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64
108061da546Spatrick                                               : g_fields->m_host_arch_32;
109061da546Spatrick }
110061da546Spatrick 
111*f6aab3d8Srobert std::optional<HostInfoBase::ArchitectureKind>
ParseArchitectureKind(llvm::StringRef kind)112*f6aab3d8Srobert HostInfoBase::ParseArchitectureKind(llvm::StringRef kind) {
113*f6aab3d8Srobert   return llvm::StringSwitch<std::optional<ArchitectureKind>>(kind)
114061da546Spatrick       .Case(LLDB_ARCH_DEFAULT, eArchKindDefault)
115061da546Spatrick       .Case(LLDB_ARCH_DEFAULT_32BIT, eArchKind32)
116061da546Spatrick       .Case(LLDB_ARCH_DEFAULT_64BIT, eArchKind64)
117*f6aab3d8Srobert       .Default(std::nullopt);
118061da546Spatrick }
119061da546Spatrick 
GetShlibDir()120061da546Spatrick FileSpec HostInfoBase::GetShlibDir() {
121061da546Spatrick   llvm::call_once(g_fields->m_lldb_so_dir_once, []() {
122061da546Spatrick     if (!HostInfo::ComputeSharedLibraryDirectory(g_fields->m_lldb_so_dir))
123061da546Spatrick       g_fields->m_lldb_so_dir = FileSpec();
124*f6aab3d8Srobert     Log *log = GetLog(LLDBLog::Host);
125061da546Spatrick     LLDB_LOG(log, "shlib dir -> `{0}`", g_fields->m_lldb_so_dir);
126061da546Spatrick   });
127061da546Spatrick   return g_fields->m_lldb_so_dir;
128061da546Spatrick }
129061da546Spatrick 
GetSupportExeDir()130061da546Spatrick FileSpec HostInfoBase::GetSupportExeDir() {
131061da546Spatrick   llvm::call_once(g_fields->m_lldb_support_exe_dir_once, []() {
132061da546Spatrick     if (!HostInfo::ComputeSupportExeDirectory(g_fields->m_lldb_support_exe_dir))
133061da546Spatrick       g_fields->m_lldb_support_exe_dir = FileSpec();
134*f6aab3d8Srobert     Log *log = GetLog(LLDBLog::Host);
135061da546Spatrick     LLDB_LOG(log, "support exe dir -> `{0}`", g_fields->m_lldb_support_exe_dir);
136061da546Spatrick   });
137061da546Spatrick   return g_fields->m_lldb_support_exe_dir;
138061da546Spatrick }
139061da546Spatrick 
GetHeaderDir()140061da546Spatrick FileSpec HostInfoBase::GetHeaderDir() {
141061da546Spatrick   llvm::call_once(g_fields->m_lldb_headers_dir_once, []() {
142061da546Spatrick     if (!HostInfo::ComputeHeaderDirectory(g_fields->m_lldb_headers_dir))
143061da546Spatrick       g_fields->m_lldb_headers_dir = FileSpec();
144*f6aab3d8Srobert     Log *log = GetLog(LLDBLog::Host);
145061da546Spatrick     LLDB_LOG(log, "header dir -> `{0}`", g_fields->m_lldb_headers_dir);
146061da546Spatrick   });
147061da546Spatrick   return g_fields->m_lldb_headers_dir;
148061da546Spatrick }
149061da546Spatrick 
GetSystemPluginDir()150061da546Spatrick FileSpec HostInfoBase::GetSystemPluginDir() {
151061da546Spatrick   llvm::call_once(g_fields->m_lldb_system_plugin_dir_once, []() {
152*f6aab3d8Srobert     if (!HostInfo::ComputeSystemPluginsDirectory(
153*f6aab3d8Srobert             g_fields->m_lldb_system_plugin_dir))
154061da546Spatrick       g_fields->m_lldb_system_plugin_dir = FileSpec();
155*f6aab3d8Srobert     Log *log = GetLog(LLDBLog::Host);
156061da546Spatrick     LLDB_LOG(log, "system plugin dir -> `{0}`",
157061da546Spatrick              g_fields->m_lldb_system_plugin_dir);
158061da546Spatrick   });
159061da546Spatrick   return g_fields->m_lldb_system_plugin_dir;
160061da546Spatrick }
161061da546Spatrick 
GetUserPluginDir()162061da546Spatrick FileSpec HostInfoBase::GetUserPluginDir() {
163061da546Spatrick   llvm::call_once(g_fields->m_lldb_user_plugin_dir_once, []() {
164*f6aab3d8Srobert     if (!HostInfo::ComputeUserPluginsDirectory(
165*f6aab3d8Srobert             g_fields->m_lldb_user_plugin_dir))
166061da546Spatrick       g_fields->m_lldb_user_plugin_dir = FileSpec();
167*f6aab3d8Srobert     Log *log = GetLog(LLDBLog::Host);
168061da546Spatrick     LLDB_LOG(log, "user plugin dir -> `{0}`", g_fields->m_lldb_user_plugin_dir);
169061da546Spatrick   });
170061da546Spatrick   return g_fields->m_lldb_user_plugin_dir;
171061da546Spatrick }
172061da546Spatrick 
GetProcessTempDir()173061da546Spatrick FileSpec HostInfoBase::GetProcessTempDir() {
174061da546Spatrick   llvm::call_once(g_fields->m_lldb_process_tmp_dir_once, []() {
175*f6aab3d8Srobert     if (!HostInfo::ComputeProcessTempFileDirectory(
176*f6aab3d8Srobert             g_fields->m_lldb_process_tmp_dir))
177061da546Spatrick       g_fields->m_lldb_process_tmp_dir = FileSpec();
178*f6aab3d8Srobert     Log *log = GetLog(LLDBLog::Host);
179061da546Spatrick     LLDB_LOG(log, "process temp dir -> `{0}`",
180061da546Spatrick              g_fields->m_lldb_process_tmp_dir);
181061da546Spatrick   });
182061da546Spatrick   return g_fields->m_lldb_process_tmp_dir;
183061da546Spatrick }
184061da546Spatrick 
GetGlobalTempDir()185061da546Spatrick FileSpec HostInfoBase::GetGlobalTempDir() {
186061da546Spatrick   llvm::call_once(g_fields->m_lldb_global_tmp_dir_once, []() {
187*f6aab3d8Srobert     if (!HostInfo::ComputeGlobalTempFileDirectory(
188*f6aab3d8Srobert             g_fields->m_lldb_global_tmp_dir))
189061da546Spatrick       g_fields->m_lldb_global_tmp_dir = FileSpec();
190061da546Spatrick 
191*f6aab3d8Srobert     Log *log = GetLog(LLDBLog::Host);
192061da546Spatrick     LLDB_LOG(log, "global temp dir -> `{0}`", g_fields->m_lldb_global_tmp_dir);
193061da546Spatrick   });
194061da546Spatrick   return g_fields->m_lldb_global_tmp_dir;
195061da546Spatrick }
196061da546Spatrick 
GetAugmentedArchSpec(llvm::StringRef triple)197061da546Spatrick ArchSpec HostInfoBase::GetAugmentedArchSpec(llvm::StringRef triple) {
198061da546Spatrick   if (triple.empty())
199061da546Spatrick     return ArchSpec();
200061da546Spatrick   llvm::Triple normalized_triple(llvm::Triple::normalize(triple));
201061da546Spatrick   if (!ArchSpec::ContainsOnlyArch(normalized_triple))
202061da546Spatrick     return ArchSpec(triple);
203061da546Spatrick 
204061da546Spatrick   if (auto kind = HostInfo::ParseArchitectureKind(triple))
205061da546Spatrick     return HostInfo::GetArchitecture(*kind);
206061da546Spatrick 
207061da546Spatrick   llvm::Triple host_triple(llvm::sys::getDefaultTargetTriple());
208061da546Spatrick 
209061da546Spatrick   if (normalized_triple.getVendorName().empty())
210061da546Spatrick     normalized_triple.setVendor(host_triple.getVendor());
211061da546Spatrick   if (normalized_triple.getOSName().empty())
212061da546Spatrick     normalized_triple.setOS(host_triple.getOS());
213*f6aab3d8Srobert   if (normalized_triple.getEnvironmentName().empty() &&
214*f6aab3d8Srobert       !host_triple.getEnvironmentName().empty())
215061da546Spatrick     normalized_triple.setEnvironment(host_triple.getEnvironment());
216061da546Spatrick   return ArchSpec(normalized_triple);
217061da546Spatrick }
218061da546Spatrick 
ComputePathRelativeToLibrary(FileSpec & file_spec,llvm::StringRef dir)219061da546Spatrick bool HostInfoBase::ComputePathRelativeToLibrary(FileSpec &file_spec,
220061da546Spatrick                                                 llvm::StringRef dir) {
221*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Host);
222061da546Spatrick 
223061da546Spatrick   FileSpec lldb_file_spec = GetShlibDir();
224061da546Spatrick   if (!lldb_file_spec)
225061da546Spatrick     return false;
226061da546Spatrick 
227061da546Spatrick   std::string raw_path = lldb_file_spec.GetPath();
228061da546Spatrick   LLDB_LOGF(log,
229061da546Spatrick             "HostInfo::%s() attempting to "
230061da546Spatrick             "derive the path %s relative to liblldb install path: %s",
231061da546Spatrick             __FUNCTION__, dir.data(), raw_path.c_str());
232061da546Spatrick 
233061da546Spatrick   // Drop bin (windows) or lib
234061da546Spatrick   llvm::StringRef parent_path = llvm::sys::path::parent_path(raw_path);
235061da546Spatrick   if (parent_path.empty()) {
236061da546Spatrick     LLDB_LOGF(log,
237061da546Spatrick               "HostInfo::%s() failed to find liblldb within the shared "
238061da546Spatrick               "lib path",
239061da546Spatrick               __FUNCTION__);
240061da546Spatrick     return false;
241061da546Spatrick   }
242061da546Spatrick 
243061da546Spatrick   raw_path = (parent_path + dir).str();
244061da546Spatrick   LLDB_LOGF(log, "HostInfo::%s() derived the path as: %s", __FUNCTION__,
245061da546Spatrick             raw_path.c_str());
246*f6aab3d8Srobert   file_spec.SetDirectory(raw_path);
247061da546Spatrick   return (bool)file_spec.GetDirectory();
248061da546Spatrick }
249061da546Spatrick 
ComputeSharedLibraryDirectory(FileSpec & file_spec)250061da546Spatrick bool HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) {
251061da546Spatrick   // To get paths related to LLDB we get the path to the executable that
252061da546Spatrick   // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB".
253061da546Spatrick   // On other posix systems, we will get .../lib(64|32)?/liblldb.so.
254061da546Spatrick 
255061da546Spatrick   FileSpec lldb_file_spec(Host::GetModuleFileSpecForHostAddress(
256*f6aab3d8Srobert       reinterpret_cast<void *>(HostInfoBase::ComputeSharedLibraryDirectory)));
257061da546Spatrick 
258be691f3bSpatrick   if (g_shlib_dir_helper)
259be691f3bSpatrick     g_shlib_dir_helper(lldb_file_spec);
260061da546Spatrick 
261061da546Spatrick   // Remove the filename so that this FileSpec only represents the directory.
262*f6aab3d8Srobert   file_spec.SetDirectory(lldb_file_spec.GetDirectory());
263061da546Spatrick 
264061da546Spatrick   return (bool)file_spec.GetDirectory();
265061da546Spatrick }
266061da546Spatrick 
ComputeSupportExeDirectory(FileSpec & file_spec)267061da546Spatrick bool HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec) {
268061da546Spatrick   file_spec = GetShlibDir();
269061da546Spatrick   return bool(file_spec);
270061da546Spatrick }
271061da546Spatrick 
ComputeProcessTempFileDirectory(FileSpec & file_spec)272061da546Spatrick bool HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec) {
273061da546Spatrick   FileSpec temp_file_spec;
274061da546Spatrick   if (!HostInfo::ComputeGlobalTempFileDirectory(temp_file_spec))
275061da546Spatrick     return false;
276061da546Spatrick 
277061da546Spatrick   std::string pid_str{llvm::to_string(Host::GetCurrentProcessID())};
278061da546Spatrick   temp_file_spec.AppendPathComponent(pid_str);
279061da546Spatrick   if (llvm::sys::fs::create_directory(temp_file_spec.GetPath()))
280061da546Spatrick     return false;
281061da546Spatrick 
282*f6aab3d8Srobert   file_spec.SetDirectory(temp_file_spec.GetPathAsConstString());
283061da546Spatrick   return true;
284061da546Spatrick }
285061da546Spatrick 
ComputeTempFileBaseDirectory(FileSpec & file_spec)286061da546Spatrick bool HostInfoBase::ComputeTempFileBaseDirectory(FileSpec &file_spec) {
287061da546Spatrick   llvm::SmallVector<char, 16> tmpdir;
288061da546Spatrick   llvm::sys::path::system_temp_directory(/*ErasedOnReboot*/ true, tmpdir);
289061da546Spatrick   file_spec = FileSpec(std::string(tmpdir.data(), tmpdir.size()));
290061da546Spatrick   FileSystem::Instance().Resolve(file_spec);
291061da546Spatrick   return true;
292061da546Spatrick }
293061da546Spatrick 
ComputeGlobalTempFileDirectory(FileSpec & file_spec)294061da546Spatrick bool HostInfoBase::ComputeGlobalTempFileDirectory(FileSpec &file_spec) {
295061da546Spatrick   file_spec.Clear();
296061da546Spatrick 
297061da546Spatrick   FileSpec temp_file_spec;
298061da546Spatrick   if (!HostInfo::ComputeTempFileBaseDirectory(temp_file_spec))
299061da546Spatrick     return false;
300061da546Spatrick 
301061da546Spatrick   temp_file_spec.AppendPathComponent("lldb");
302061da546Spatrick   if (llvm::sys::fs::create_directory(temp_file_spec.GetPath()))
303061da546Spatrick     return false;
304061da546Spatrick 
305*f6aab3d8Srobert   file_spec.SetDirectory(temp_file_spec.GetPathAsConstString());
306061da546Spatrick   return true;
307061da546Spatrick }
308061da546Spatrick 
ComputeHeaderDirectory(FileSpec & file_spec)309061da546Spatrick bool HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec) {
310061da546Spatrick   // TODO(zturner): Figure out how to compute the header directory for all
311061da546Spatrick   // platforms.
312061da546Spatrick   return false;
313061da546Spatrick }
314061da546Spatrick 
ComputeSystemPluginsDirectory(FileSpec & file_spec)315061da546Spatrick bool HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec) {
316061da546Spatrick   // TODO(zturner): Figure out how to compute the system plugins directory for
317061da546Spatrick   // all platforms.
318061da546Spatrick   return false;
319061da546Spatrick }
320061da546Spatrick 
ComputeUserPluginsDirectory(FileSpec & file_spec)321061da546Spatrick bool HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec) {
322061da546Spatrick   // TODO(zturner): Figure out how to compute the user plugins directory for
323061da546Spatrick   // all platforms.
324061da546Spatrick   return false;
325061da546Spatrick }
326061da546Spatrick 
ComputeHostArchitectureSupport(ArchSpec & arch_32,ArchSpec & arch_64)327061da546Spatrick void HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32,
328061da546Spatrick                                                   ArchSpec &arch_64) {
329061da546Spatrick   llvm::Triple triple(llvm::sys::getProcessTriple());
330061da546Spatrick 
331061da546Spatrick   arch_32.Clear();
332061da546Spatrick   arch_64.Clear();
333061da546Spatrick 
334061da546Spatrick   switch (triple.getArch()) {
335061da546Spatrick   default:
336061da546Spatrick     arch_32.SetTriple(triple);
337061da546Spatrick     break;
338061da546Spatrick 
339061da546Spatrick   case llvm::Triple::aarch64:
340061da546Spatrick   case llvm::Triple::ppc64:
341061da546Spatrick   case llvm::Triple::ppc64le:
342061da546Spatrick   case llvm::Triple::x86_64:
343*f6aab3d8Srobert   case llvm::Triple::riscv64:
344*f6aab3d8Srobert   case llvm::Triple::loongarch64:
345061da546Spatrick     arch_64.SetTriple(triple);
346061da546Spatrick     arch_32.SetTriple(triple.get32BitArchVariant());
347061da546Spatrick     break;
348061da546Spatrick 
349061da546Spatrick   case llvm::Triple::mips64:
350061da546Spatrick   case llvm::Triple::mips64el:
351061da546Spatrick   case llvm::Triple::sparcv9:
352061da546Spatrick   case llvm::Triple::systemz:
353061da546Spatrick     arch_64.SetTriple(triple);
354061da546Spatrick     break;
355061da546Spatrick   }
356061da546Spatrick }
357