1275072Semaste//===-- HostInfoBase.cpp ----------------------------------------*- C++ -*-===// 2275072Semaste// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6275072Semaste// 7275072Semaste//===----------------------------------------------------------------------===// 8275072Semaste 9275072Semaste#include "lldb/Host/Config.h" 10275072Semaste 11275072Semaste#include "lldb/Host/FileSystem.h" 12275072Semaste#include "lldb/Host/Host.h" 13275072Semaste#include "lldb/Host/HostInfo.h" 14275072Semaste#include "lldb/Host/HostInfoBase.h" 15327952Sdim#include "lldb/Utility/ArchSpec.h" 16321369Sdim#include "lldb/Utility/Log.h" 17321369Sdim#include "lldb/Utility/StreamString.h" 18275072Semaste 19314564Sdim#include "llvm/ADT/StringExtras.h" 20275072Semaste#include "llvm/ADT/Triple.h" 21275072Semaste#include "llvm/Support/Host.h" 22296417Sdim#include "llvm/Support/Path.h" 23314564Sdim#include "llvm/Support/ScopedPrinter.h" 24321369Sdim#include "llvm/Support/Threading.h" 25280031Sdim#include "llvm/Support/raw_ostream.h" 26275072Semaste 27321369Sdim#include <mutex> 28275072Semaste#include <thread> 29275072Semaste 30275072Semasteusing namespace lldb; 31275072Semasteusing namespace lldb_private; 32275072Semaste 33314564Sdimnamespace { 34341825Sdim// The HostInfoBaseFields is a work around for windows not supporting static 35341825Sdim// variables correctly in a thread safe way. Really each of the variables in 36341825Sdim// HostInfoBaseFields should live in the functions in which they are used and 37341825Sdim// each one should be static, but the work around is in place to avoid this 38341825Sdim// restriction. Ick. 39275072Semaste 40314564Sdimstruct HostInfoBaseFields { 41314564Sdim ~HostInfoBaseFields() { 42344779Sdim if (FileSystem::Instance().Exists(m_lldb_process_tmp_dir)) { 43314564Sdim // Remove the LLDB temporary directory if we have one. Set "recurse" to 44341825Sdim // true to all files that were created for the LLDB process can be 45341825Sdim // cleaned up. 46321369Sdim llvm::sys::fs::remove_directories(m_lldb_process_tmp_dir.GetPath()); 47314564Sdim } 48314564Sdim } 49309124Sdim 50360784Sdim llvm::once_flag m_host_triple_once; 51360784Sdim llvm::Triple m_host_triple; 52275072Semaste 53360784Sdim llvm::once_flag m_host_arch_once; 54314564Sdim ArchSpec m_host_arch_32; 55314564Sdim ArchSpec m_host_arch_64; 56275072Semaste 57360784Sdim llvm::once_flag m_lldb_so_dir_once; 58314564Sdim FileSpec m_lldb_so_dir; 59360784Sdim llvm::once_flag m_lldb_support_exe_dir_once; 60314564Sdim FileSpec m_lldb_support_exe_dir; 61360784Sdim llvm::once_flag m_lldb_headers_dir_once; 62314564Sdim FileSpec m_lldb_headers_dir; 63360784Sdim llvm::once_flag m_lldb_clang_resource_dir_once; 64314564Sdim FileSpec m_lldb_clang_resource_dir; 65360784Sdim llvm::once_flag m_lldb_system_plugin_dir_once; 66314564Sdim FileSpec m_lldb_system_plugin_dir; 67360784Sdim llvm::once_flag m_lldb_user_plugin_dir_once; 68314564Sdim FileSpec m_lldb_user_plugin_dir; 69360784Sdim llvm::once_flag m_lldb_process_tmp_dir_once; 70314564Sdim FileSpec m_lldb_process_tmp_dir; 71360784Sdim llvm::once_flag m_lldb_global_tmp_dir_once; 72314564Sdim FileSpec m_lldb_global_tmp_dir; 73314564Sdim}; 74275072Semaste 75314564SdimHostInfoBaseFields *g_fields = nullptr; 76275072Semaste} 77275072Semaste 78314564Sdimvoid HostInfoBase::Initialize() { g_fields = new HostInfoBaseFields(); } 79309124Sdim 80314564Sdimvoid HostInfoBase::Terminate() { 81314564Sdim delete g_fields; 82314564Sdim g_fields = nullptr; 83275072Semaste} 84275072Semaste 85360784Sdimllvm::Triple HostInfoBase::GetTargetTriple() { 86360784Sdim llvm::call_once(g_fields->m_host_triple_once, []() { 87314564Sdim g_fields->m_host_triple = 88360784Sdim HostInfo::GetArchitecture().GetTriple(); 89314564Sdim }); 90314564Sdim return g_fields->m_host_triple; 91275072Semaste} 92275072Semaste 93314564Sdimconst ArchSpec &HostInfoBase::GetArchitecture(ArchitectureKind arch_kind) { 94360784Sdim llvm::call_once(g_fields->m_host_arch_once, []() { 95314564Sdim HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32, 96314564Sdim g_fields->m_host_arch_64); 97314564Sdim }); 98275072Semaste 99314564Sdim // If an explicit 32 or 64-bit architecture was requested, return that. 100314564Sdim if (arch_kind == eArchKind32) 101314564Sdim return g_fields->m_host_arch_32; 102314564Sdim if (arch_kind == eArchKind64) 103314564Sdim return g_fields->m_host_arch_64; 104275072Semaste 105314564Sdim // Otherwise prefer the 64-bit architecture if it is valid. 106314564Sdim return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64 107314564Sdim : g_fields->m_host_arch_32; 108275072Semaste} 109275072Semaste 110327952Sdimllvm::Optional<HostInfoBase::ArchitectureKind> HostInfoBase::ParseArchitectureKind(llvm::StringRef kind) { 111327952Sdim return llvm::StringSwitch<llvm::Optional<ArchitectureKind>>(kind) 112327952Sdim .Case(LLDB_ARCH_DEFAULT, eArchKindDefault) 113327952Sdim .Case(LLDB_ARCH_DEFAULT_32BIT, eArchKind32) 114327952Sdim .Case(LLDB_ARCH_DEFAULT_64BIT, eArchKind64) 115327952Sdim .Default(llvm::None); 116327952Sdim} 117327952Sdim 118341825SdimFileSpec HostInfoBase::GetShlibDir() { 119360784Sdim llvm::call_once(g_fields->m_lldb_so_dir_once, []() { 120360784Sdim if (!HostInfo::ComputeSharedLibraryDirectory(g_fields->m_lldb_so_dir)) 121360784Sdim g_fields->m_lldb_so_dir = FileSpec(); 122341825Sdim Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 123341825Sdim LLDB_LOG(log, "shlib dir -> `{0}`", g_fields->m_lldb_so_dir); 124341825Sdim }); 125360784Sdim return g_fields->m_lldb_so_dir; 126341825Sdim} 127275072Semaste 128341825SdimFileSpec HostInfoBase::GetSupportExeDir() { 129360784Sdim llvm::call_once(g_fields->m_lldb_support_exe_dir_once, []() { 130360784Sdim if (!HostInfo::ComputeSupportExeDirectory(g_fields->m_lldb_support_exe_dir)) 131360784Sdim g_fields->m_lldb_support_exe_dir = FileSpec(); 132341825Sdim Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 133341825Sdim LLDB_LOG(log, "support exe dir -> `{0}`", g_fields->m_lldb_support_exe_dir); 134341825Sdim }); 135360784Sdim return g_fields->m_lldb_support_exe_dir; 136341825Sdim} 137275072Semaste 138341825SdimFileSpec HostInfoBase::GetHeaderDir() { 139360784Sdim llvm::call_once(g_fields->m_lldb_headers_dir_once, []() { 140360784Sdim if (!HostInfo::ComputeHeaderDirectory(g_fields->m_lldb_headers_dir)) 141360784Sdim g_fields->m_lldb_headers_dir = FileSpec(); 142341825Sdim Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 143341825Sdim LLDB_LOG(log, "header dir -> `{0}`", g_fields->m_lldb_headers_dir); 144341825Sdim }); 145360784Sdim return g_fields->m_lldb_headers_dir; 146341825Sdim} 147275072Semaste 148341825SdimFileSpec HostInfoBase::GetSystemPluginDir() { 149360784Sdim llvm::call_once(g_fields->m_lldb_system_plugin_dir_once, []() { 150360784Sdim if (!HostInfo::ComputeSystemPluginsDirectory(g_fields->m_lldb_system_plugin_dir)) 151360784Sdim g_fields->m_lldb_system_plugin_dir = FileSpec(); 152341825Sdim Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 153341825Sdim LLDB_LOG(log, "system plugin dir -> `{0}`", 154341825Sdim g_fields->m_lldb_system_plugin_dir); 155341825Sdim }); 156360784Sdim return g_fields->m_lldb_system_plugin_dir; 157275072Semaste} 158275072Semaste 159341825SdimFileSpec HostInfoBase::GetUserPluginDir() { 160360784Sdim llvm::call_once(g_fields->m_lldb_user_plugin_dir_once, []() { 161360784Sdim if (!HostInfo::ComputeUserPluginsDirectory(g_fields->m_lldb_user_plugin_dir)) 162360784Sdim g_fields->m_lldb_user_plugin_dir = FileSpec(); 163341825Sdim Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 164341825Sdim LLDB_LOG(log, "user plugin dir -> `{0}`", g_fields->m_lldb_user_plugin_dir); 165341825Sdim }); 166360784Sdim return g_fields->m_lldb_user_plugin_dir; 167341825Sdim} 168341825Sdim 169341825SdimFileSpec HostInfoBase::GetProcessTempDir() { 170360784Sdim llvm::call_once(g_fields->m_lldb_process_tmp_dir_once, []() { 171360784Sdim if (!HostInfo::ComputeProcessTempFileDirectory( g_fields->m_lldb_process_tmp_dir)) 172360784Sdim g_fields->m_lldb_process_tmp_dir = FileSpec(); 173341825Sdim Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 174341825Sdim LLDB_LOG(log, "process temp dir -> `{0}`", 175341825Sdim g_fields->m_lldb_process_tmp_dir); 176341825Sdim }); 177360784Sdim return g_fields->m_lldb_process_tmp_dir; 178341825Sdim} 179341825Sdim 180341825SdimFileSpec HostInfoBase::GetGlobalTempDir() { 181360784Sdim llvm::call_once(g_fields->m_lldb_global_tmp_dir_once, []() { 182360784Sdim if (!HostInfo::ComputeGlobalTempFileDirectory( g_fields->m_lldb_global_tmp_dir)) 183360784Sdim g_fields->m_lldb_global_tmp_dir = FileSpec(); 184360784Sdim 185341825Sdim Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 186341825Sdim LLDB_LOG(log, "global temp dir -> `{0}`", g_fields->m_lldb_global_tmp_dir); 187341825Sdim }); 188360784Sdim return g_fields->m_lldb_global_tmp_dir; 189341825Sdim} 190341825Sdim 191327952SdimArchSpec HostInfoBase::GetAugmentedArchSpec(llvm::StringRef triple) { 192327952Sdim if (triple.empty()) 193327952Sdim return ArchSpec(); 194327952Sdim llvm::Triple normalized_triple(llvm::Triple::normalize(triple)); 195327952Sdim if (!ArchSpec::ContainsOnlyArch(normalized_triple)) 196327952Sdim return ArchSpec(triple); 197327952Sdim 198327952Sdim if (auto kind = HostInfo::ParseArchitectureKind(triple)) 199327952Sdim return HostInfo::GetArchitecture(*kind); 200327952Sdim 201327952Sdim llvm::Triple host_triple(llvm::sys::getDefaultTargetTriple()); 202327952Sdim 203327952Sdim if (normalized_triple.getVendorName().empty()) 204327952Sdim normalized_triple.setVendor(host_triple.getVendor()); 205327952Sdim if (normalized_triple.getOSName().empty()) 206327952Sdim normalized_triple.setOS(host_triple.getOS()); 207327952Sdim if (normalized_triple.getEnvironmentName().empty()) 208327952Sdim normalized_triple.setEnvironment(host_triple.getEnvironment()); 209327952Sdim return ArchSpec(normalized_triple); 210327952Sdim} 211327952Sdim 212353358Sdimbool HostInfoBase::ComputePathRelativeToLibrary(FileSpec &file_spec, 213353358Sdim llvm::StringRef dir) { 214353358Sdim Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 215353358Sdim 216353358Sdim FileSpec lldb_file_spec = GetShlibDir(); 217353358Sdim if (!lldb_file_spec) 218353358Sdim return false; 219353358Sdim 220353358Sdim std::string raw_path = lldb_file_spec.GetPath(); 221360784Sdim LLDB_LOGF(log, 222360784Sdim "HostInfo::%s() attempting to " 223360784Sdim "derive the path %s relative to liblldb install path: %s", 224360784Sdim __FUNCTION__, dir.data(), raw_path.c_str()); 225353358Sdim 226353358Sdim // Drop bin (windows) or lib 227353358Sdim llvm::StringRef parent_path = llvm::sys::path::parent_path(raw_path); 228353358Sdim if (parent_path.empty()) { 229360784Sdim LLDB_LOGF(log, 230360784Sdim "HostInfo::%s() failed to find liblldb within the shared " 231360784Sdim "lib path", 232360784Sdim __FUNCTION__); 233353358Sdim return false; 234353358Sdim } 235353358Sdim 236353358Sdim raw_path = (parent_path + dir).str(); 237360784Sdim LLDB_LOGF(log, "HostInfo::%s() derived the path as: %s", __FUNCTION__, 238360784Sdim raw_path.c_str()); 239353358Sdim file_spec.GetDirectory().SetString(raw_path); 240353358Sdim return (bool)file_spec.GetDirectory(); 241353358Sdim} 242353358Sdim 243314564Sdimbool HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) { 244314564Sdim // To get paths related to LLDB we get the path to the executable that 245341825Sdim // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB". 246341825Sdim // On other posix systems, we will get .../lib(64|32)?/liblldb.so. 247275072Semaste 248341825Sdim FileSpec lldb_file_spec(Host::GetModuleFileSpecForHostAddress( 249360784Sdim reinterpret_cast<void *>( 250360784Sdim HostInfoBase::ComputeSharedLibraryDirectory))); 251275072Semaste 252314564Sdim // This is necessary because when running the testsuite the shlib might be a 253314564Sdim // symbolic link inside the Python resource dir. 254344779Sdim FileSystem::Instance().ResolveSymbolicLink(lldb_file_spec, lldb_file_spec); 255314564Sdim 256314564Sdim // Remove the filename so that this FileSpec only represents the directory. 257314564Sdim file_spec.GetDirectory() = lldb_file_spec.GetDirectory(); 258314564Sdim 259314564Sdim return (bool)file_spec.GetDirectory(); 260275072Semaste} 261275072Semaste 262314564Sdimbool HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec) { 263341825Sdim file_spec = GetShlibDir(); 264341825Sdim return bool(file_spec); 265275072Semaste} 266275072Semaste 267314564Sdimbool HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec) { 268314564Sdim FileSpec temp_file_spec; 269314564Sdim if (!HostInfo::ComputeGlobalTempFileDirectory(temp_file_spec)) 270314564Sdim return false; 271288943Sdim 272314564Sdim std::string pid_str{llvm::to_string(Host::GetCurrentProcessID())}; 273314564Sdim temp_file_spec.AppendPathComponent(pid_str); 274321369Sdim if (llvm::sys::fs::create_directory(temp_file_spec.GetPath())) 275314564Sdim return false; 276288943Sdim 277314564Sdim file_spec.GetDirectory().SetCString(temp_file_spec.GetCString()); 278314564Sdim return true; 279288943Sdim} 280288943Sdim 281314564Sdimbool HostInfoBase::ComputeTempFileBaseDirectory(FileSpec &file_spec) { 282314564Sdim llvm::SmallVector<char, 16> tmpdir; 283314564Sdim llvm::sys::path::system_temp_directory(/*ErasedOnReboot*/ true, tmpdir); 284344779Sdim file_spec = FileSpec(std::string(tmpdir.data(), tmpdir.size())); 285344779Sdim FileSystem::Instance().Resolve(file_spec); 286314564Sdim return true; 287288943Sdim} 288288943Sdim 289314564Sdimbool HostInfoBase::ComputeGlobalTempFileDirectory(FileSpec &file_spec) { 290314564Sdim file_spec.Clear(); 291288943Sdim 292314564Sdim FileSpec temp_file_spec; 293314564Sdim if (!HostInfo::ComputeTempFileBaseDirectory(temp_file_spec)) 294314564Sdim return false; 295275072Semaste 296314564Sdim temp_file_spec.AppendPathComponent("lldb"); 297321369Sdim if (llvm::sys::fs::create_directory(temp_file_spec.GetPath())) 298314564Sdim return false; 299275072Semaste 300314564Sdim file_spec.GetDirectory().SetCString(temp_file_spec.GetCString()); 301314564Sdim return true; 302275072Semaste} 303275072Semaste 304314564Sdimbool HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec) { 305314564Sdim // TODO(zturner): Figure out how to compute the header directory for all 306314564Sdim // platforms. 307314564Sdim return false; 308275072Semaste} 309275072Semaste 310314564Sdimbool HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec) { 311314564Sdim // TODO(zturner): Figure out how to compute the system plugins directory for 312314564Sdim // all platforms. 313314564Sdim return false; 314275072Semaste} 315275072Semaste 316314564Sdimbool HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec) { 317341825Sdim // TODO(zturner): Figure out how to compute the user plugins directory for 318341825Sdim // all platforms. 319314564Sdim return false; 320275072Semaste} 321275072Semaste 322314564Sdimvoid HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, 323314564Sdim ArchSpec &arch_64) { 324314564Sdim llvm::Triple triple(llvm::sys::getProcessTriple()); 325275072Semaste 326314564Sdim arch_32.Clear(); 327314564Sdim arch_64.Clear(); 328275072Semaste 329314564Sdim switch (triple.getArch()) { 330314564Sdim default: 331314564Sdim arch_32.SetTriple(triple); 332314564Sdim break; 333275072Semaste 334314564Sdim case llvm::Triple::aarch64: 335314564Sdim case llvm::Triple::ppc64: 336341825Sdim case llvm::Triple::ppc64le: 337314564Sdim case llvm::Triple::x86_64: 338314564Sdim arch_64.SetTriple(triple); 339314564Sdim arch_32.SetTriple(triple.get32BitArchVariant()); 340314564Sdim break; 341275072Semaste 342314564Sdim case llvm::Triple::mips64: 343314564Sdim case llvm::Triple::mips64el: 344314564Sdim case llvm::Triple::sparcv9: 345314564Sdim case llvm::Triple::systemz: 346314564Sdim arch_64.SetTriple(triple); 347314564Sdim break; 348314564Sdim } 349275072Semaste} 350