393 lines · cpp
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-exception6//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 32using namespace lldb;33using namespace lldb_private;34 35namespace {36/// Contains the state of the HostInfoBase plugin.37struct HostInfoBaseFields {38 ~HostInfoBaseFields() {39 if (FileSystem::Instance().Exists(m_lldb_process_tmp_dir)) {40 // Remove the LLDB temporary directory if we have one. Set "recurse" to41 // true to all files that were created for the LLDB process can be42 // cleaned up.43 llvm::sys::fs::remove_directories(m_lldb_process_tmp_dir.GetPath());44 }45 }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_home_dir_once;65 FileSpec m_lldb_user_home_dir;66 llvm::once_flag m_lldb_user_lldb_dir_once;67 FileSpec m_lldb_user_lldb_dir;68 llvm::once_flag m_lldb_user_plugin_dir_once;69 FileSpec m_lldb_user_plugin_dir;70 llvm::once_flag m_lldb_process_tmp_dir_once;71 FileSpec m_lldb_process_tmp_dir;72 llvm::once_flag m_lldb_global_tmp_dir_once;73 FileSpec m_lldb_global_tmp_dir;74};75} // namespace76 77static HostInfoBaseFields *g_fields = nullptr;78static HostInfoBase::SharedLibraryDirectoryHelper *g_shlib_dir_helper = nullptr;79 80void HostInfoBase::Initialize(SharedLibraryDirectoryHelper *helper) {81 g_shlib_dir_helper = helper;82 g_fields = new HostInfoBaseFields();83 LogChannelSystem::Initialize();84}85 86void HostInfoBase::Terminate() {87 LogChannelSystem::Terminate();88 g_shlib_dir_helper = nullptr;89 delete g_fields;90 g_fields = nullptr;91}92 93llvm::Triple HostInfoBase::GetTargetTriple() {94 llvm::call_once(g_fields->m_host_triple_once, []() {95 g_fields->m_host_triple = HostInfo::GetArchitecture().GetTriple();96 });97 return g_fields->m_host_triple;98}99 100const ArchSpec &HostInfoBase::GetArchitecture(ArchitectureKind arch_kind) {101 llvm::call_once(g_fields->m_host_arch_once, []() {102 HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32,103 g_fields->m_host_arch_64);104 });105 106 // If an explicit 32 or 64-bit architecture was requested, return that.107 if (arch_kind == eArchKind32)108 return g_fields->m_host_arch_32;109 if (arch_kind == eArchKind64)110 return g_fields->m_host_arch_64;111 112 // Otherwise prefer the 64-bit architecture if it is valid.113 return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64114 : g_fields->m_host_arch_32;115}116 117std::optional<HostInfoBase::ArchitectureKind>118HostInfoBase::ParseArchitectureKind(llvm::StringRef kind) {119 return llvm::StringSwitch<std::optional<ArchitectureKind>>(kind)120 .Case(LLDB_ARCH_DEFAULT, eArchKindDefault)121 .Case(LLDB_ARCH_DEFAULT_32BIT, eArchKind32)122 .Case(LLDB_ARCH_DEFAULT_64BIT, eArchKind64)123 .Default(std::nullopt);124}125 126FileSpec HostInfoBase::GetShlibDir() {127 llvm::call_once(g_fields->m_lldb_so_dir_once, []() {128 if (!HostInfo::ComputeSharedLibraryDirectory(g_fields->m_lldb_so_dir))129 g_fields->m_lldb_so_dir = FileSpec();130 Log *log = GetLog(LLDBLog::Host);131 LLDB_LOG(log, "shlib dir -> `{0}`", g_fields->m_lldb_so_dir);132 });133 return g_fields->m_lldb_so_dir;134}135 136FileSpec HostInfoBase::GetSupportExeDir() {137 llvm::call_once(g_fields->m_lldb_support_exe_dir_once, []() {138 if (!HostInfo::ComputeSupportExeDirectory(g_fields->m_lldb_support_exe_dir))139 g_fields->m_lldb_support_exe_dir = FileSpec();140 Log *log = GetLog(LLDBLog::Host);141 LLDB_LOG(log, "support exe dir -> `{0}`", g_fields->m_lldb_support_exe_dir);142 });143 return g_fields->m_lldb_support_exe_dir;144}145 146FileSpec HostInfoBase::GetHeaderDir() {147 llvm::call_once(g_fields->m_lldb_headers_dir_once, []() {148 if (!HostInfo::ComputeHeaderDirectory(g_fields->m_lldb_headers_dir))149 g_fields->m_lldb_headers_dir = FileSpec();150 Log *log = GetLog(LLDBLog::Host);151 LLDB_LOG(log, "header dir -> `{0}`", g_fields->m_lldb_headers_dir);152 });153 return g_fields->m_lldb_headers_dir;154}155 156FileSpec HostInfoBase::GetSystemPluginDir() {157 llvm::call_once(g_fields->m_lldb_system_plugin_dir_once, []() {158 if (!HostInfo::ComputeSystemPluginsDirectory(159 g_fields->m_lldb_system_plugin_dir))160 g_fields->m_lldb_system_plugin_dir = FileSpec();161 Log *log = GetLog(LLDBLog::Host);162 LLDB_LOG(log, "system plugin dir -> `{0}`",163 g_fields->m_lldb_system_plugin_dir);164 });165 return g_fields->m_lldb_system_plugin_dir;166}167 168FileSpec HostInfoBase::GetUserHomeDir() {169 llvm::call_once(g_fields->m_lldb_user_home_dir_once, []() {170 if (!HostInfo::ComputeUserHomeDirectory(g_fields->m_lldb_user_home_dir))171 g_fields->m_lldb_user_home_dir = FileSpec();172 LLDB_LOG(GetLog(LLDBLog::Host), "user home dir -> `{0}`",173 g_fields->m_lldb_user_home_dir);174 });175 return g_fields->m_lldb_user_home_dir;176}177 178FileSpec HostInfoBase::GetUserLLDBDir() {179 llvm::call_once(g_fields->m_lldb_user_lldb_dir_once, []() {180 if (!HostInfo::ComputeUserLLDBHomeDirectory(g_fields->m_lldb_user_lldb_dir))181 g_fields->m_lldb_user_lldb_dir = FileSpec();182 LLDB_LOG(GetLog(LLDBLog::Host), "user lldb home dir -> `{0}`",183 g_fields->m_lldb_user_lldb_dir);184 });185 return g_fields->m_lldb_user_lldb_dir;186}187 188FileSpec HostInfoBase::GetUserPluginDir() {189 llvm::call_once(g_fields->m_lldb_user_plugin_dir_once, []() {190 if (!HostInfo::ComputeUserPluginsDirectory(191 g_fields->m_lldb_user_plugin_dir))192 g_fields->m_lldb_user_plugin_dir = FileSpec();193 Log *log = GetLog(LLDBLog::Host);194 LLDB_LOG(log, "user plugin dir -> `{0}`", g_fields->m_lldb_user_plugin_dir);195 });196 return g_fields->m_lldb_user_plugin_dir;197}198 199FileSpec HostInfoBase::GetProcessTempDir() {200 llvm::call_once(g_fields->m_lldb_process_tmp_dir_once, []() {201 if (!HostInfo::ComputeProcessTempFileDirectory(202 g_fields->m_lldb_process_tmp_dir))203 g_fields->m_lldb_process_tmp_dir = FileSpec();204 Log *log = GetLog(LLDBLog::Host);205 LLDB_LOG(log, "process temp dir -> `{0}`",206 g_fields->m_lldb_process_tmp_dir);207 });208 return g_fields->m_lldb_process_tmp_dir;209}210 211FileSpec HostInfoBase::GetGlobalTempDir() {212 llvm::call_once(g_fields->m_lldb_global_tmp_dir_once, []() {213 if (!HostInfo::ComputeGlobalTempFileDirectory(214 g_fields->m_lldb_global_tmp_dir))215 g_fields->m_lldb_global_tmp_dir = FileSpec();216 217 Log *log = GetLog(LLDBLog::Host);218 LLDB_LOG(log, "global temp dir -> `{0}`", g_fields->m_lldb_global_tmp_dir);219 });220 return g_fields->m_lldb_global_tmp_dir;221}222 223ArchSpec HostInfoBase::GetAugmentedArchSpec(llvm::StringRef triple) {224 if (triple.empty())225 return ArchSpec();226 llvm::Triple normalized_triple(llvm::Triple::normalize(triple));227 if (!ArchSpec::ContainsOnlyArch(normalized_triple))228 return ArchSpec(triple);229 230 if (auto kind = HostInfo::ParseArchitectureKind(triple))231 return HostInfo::GetArchitecture(*kind);232 233 llvm::Triple host_triple(llvm::sys::getDefaultTargetTriple());234 235 if (normalized_triple.getVendorName().empty())236 normalized_triple.setVendor(host_triple.getVendor());237 if (normalized_triple.getOSName().empty())238 normalized_triple.setOS(host_triple.getOS());239 if (normalized_triple.getEnvironmentName().empty() &&240 !host_triple.getEnvironmentName().empty())241 normalized_triple.setEnvironment(host_triple.getEnvironment());242 return ArchSpec(normalized_triple);243}244 245bool HostInfoBase::ComputePathRelativeToLibrary(FileSpec &file_spec,246 llvm::StringRef dir) {247 Log *log = GetLog(LLDBLog::Host);248 249 FileSpec lldb_file_spec = GetShlibDir();250 if (!lldb_file_spec)251 return false;252 253 std::string raw_path = lldb_file_spec.GetPath();254 LLDB_LOG(255 log,256 "Attempting to derive the path {0} relative to liblldb install path: {1}",257 dir, raw_path);258 259 // Drop bin (windows) or lib260 llvm::StringRef parent_path = llvm::sys::path::parent_path(raw_path);261 if (parent_path.empty()) {262 LLDB_LOG(log, "Failed to find liblldb within the shared lib path");263 return false;264 }265 266 raw_path = (parent_path + dir).str();267 LLDB_LOG(log, "Derived the path as: {0}", raw_path);268 file_spec.SetDirectory(raw_path);269 return (bool)file_spec.GetDirectory();270}271 272bool HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) {273 // To get paths related to LLDB we get the path to the executable that274 // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB".275 // On other posix systems, we will get .../lib(64|32)?/liblldb.so.276 277 FileSpec lldb_file_spec(Host::GetModuleFileSpecForHostAddress(278 reinterpret_cast<void *>(HostInfoBase::ComputeSharedLibraryDirectory)));279 280 if (g_shlib_dir_helper)281 g_shlib_dir_helper(lldb_file_spec);282 283 // Remove the filename so that this FileSpec only represents the directory.284 file_spec.SetDirectory(lldb_file_spec.GetDirectory());285 286 return (bool)file_spec.GetDirectory();287}288 289bool HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec) {290 file_spec = GetShlibDir();291 return bool(file_spec);292}293 294bool HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec) {295 FileSpec temp_file_spec;296 if (!HostInfo::ComputeGlobalTempFileDirectory(temp_file_spec))297 return false;298 299 std::string pid_str{llvm::to_string(Host::GetCurrentProcessID())};300 temp_file_spec.AppendPathComponent(pid_str);301 if (llvm::sys::fs::create_directory(temp_file_spec.GetPath()))302 return false;303 304 file_spec.SetDirectory(temp_file_spec.GetPathAsConstString());305 return true;306}307 308bool HostInfoBase::ComputeTempFileBaseDirectory(FileSpec &file_spec) {309 llvm::SmallVector<char, 16> tmpdir;310 llvm::sys::path::system_temp_directory(/*ErasedOnReboot*/ true, tmpdir);311 file_spec = FileSpec(std::string(tmpdir.data(), tmpdir.size()));312 FileSystem::Instance().Resolve(file_spec);313 return true;314}315 316bool HostInfoBase::ComputeGlobalTempFileDirectory(FileSpec &file_spec) {317 file_spec.Clear();318 319 FileSpec temp_file_spec;320 if (!HostInfo::ComputeTempFileBaseDirectory(temp_file_spec))321 return false;322 323 temp_file_spec.AppendPathComponent("lldb");324 if (llvm::sys::fs::create_directory(temp_file_spec.GetPath()))325 return false;326 327 file_spec.SetDirectory(temp_file_spec.GetPathAsConstString());328 return true;329}330 331bool HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec) {332 // TODO(zturner): Figure out how to compute the header directory for all333 // platforms.334 return false;335}336 337bool HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec) {338 // TODO(zturner): Figure out how to compute the system plugins directory for339 // all platforms.340 return false;341}342 343bool HostInfoBase::ComputeUserHomeDirectory(FileSpec &file_spec) {344 FileSpec temp_file("~");345 FileSystem::Instance().Resolve(temp_file);346 file_spec.SetDirectory(temp_file.GetPathAsConstString());347 return true;348}349 350bool HostInfoBase::ComputeUserLLDBHomeDirectory(FileSpec &file_spec) {351 FileSpec home_dir_spec = GetUserHomeDir();352 home_dir_spec.AppendPathComponent(".lldb");353 file_spec.SetDirectory(home_dir_spec.GetPathAsConstString());354 return true;355}356 357bool HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec) {358 // TODO(zturner): Figure out how to compute the user plugins directory for359 // all platforms.360 return false;361}362 363void HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32,364 ArchSpec &arch_64) {365 llvm::Triple triple(llvm::sys::getProcessTriple());366 367 arch_32.Clear();368 arch_64.Clear();369 370 switch (triple.getArch()) {371 default:372 arch_32.SetTriple(triple);373 break;374 375 case llvm::Triple::aarch64:376 case llvm::Triple::ppc64:377 case llvm::Triple::ppc64le:378 case llvm::Triple::x86_64:379 case llvm::Triple::riscv64:380 case llvm::Triple::loongarch64:381 arch_64.SetTriple(triple);382 arch_32.SetTriple(triple.get32BitArchVariant());383 break;384 385 case llvm::Triple::mips64:386 case llvm::Triple::mips64el:387 case llvm::Triple::sparcv9:388 case llvm::Triple::systemz:389 arch_64.SetTriple(triple);390 break;391 }392}393