HostInfoBase.cpp revision 353358
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 50314564Sdim std::string m_host_triple; 51275072Semaste 52314564Sdim ArchSpec m_host_arch_32; 53314564Sdim ArchSpec m_host_arch_64; 54275072Semaste 55314564Sdim FileSpec m_lldb_so_dir; 56314564Sdim FileSpec m_lldb_support_exe_dir; 57314564Sdim FileSpec m_lldb_headers_dir; 58314564Sdim FileSpec m_lldb_clang_resource_dir; 59314564Sdim FileSpec m_lldb_system_plugin_dir; 60314564Sdim FileSpec m_lldb_user_plugin_dir; 61314564Sdim FileSpec m_lldb_process_tmp_dir; 62314564Sdim FileSpec m_lldb_global_tmp_dir; 63314564Sdim}; 64275072Semaste 65314564SdimHostInfoBaseFields *g_fields = nullptr; 66275072Semaste} 67275072Semaste 68314564Sdimvoid HostInfoBase::Initialize() { g_fields = new HostInfoBaseFields(); } 69309124Sdim 70314564Sdimvoid HostInfoBase::Terminate() { 71314564Sdim delete g_fields; 72314564Sdim g_fields = nullptr; 73275072Semaste} 74275072Semaste 75314564Sdimllvm::StringRef HostInfoBase::GetTargetTriple() { 76321369Sdim static llvm::once_flag g_once_flag; 77321369Sdim llvm::call_once(g_once_flag, []() { 78314564Sdim g_fields->m_host_triple = 79314564Sdim HostInfo::GetArchitecture().GetTriple().getTriple(); 80314564Sdim }); 81314564Sdim return g_fields->m_host_triple; 82275072Semaste} 83275072Semaste 84314564Sdimconst ArchSpec &HostInfoBase::GetArchitecture(ArchitectureKind arch_kind) { 85321369Sdim static llvm::once_flag g_once_flag; 86321369Sdim llvm::call_once(g_once_flag, []() { 87314564Sdim HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32, 88314564Sdim g_fields->m_host_arch_64); 89314564Sdim }); 90275072Semaste 91314564Sdim // If an explicit 32 or 64-bit architecture was requested, return that. 92314564Sdim if (arch_kind == eArchKind32) 93314564Sdim return g_fields->m_host_arch_32; 94314564Sdim if (arch_kind == eArchKind64) 95314564Sdim return g_fields->m_host_arch_64; 96275072Semaste 97314564Sdim // Otherwise prefer the 64-bit architecture if it is valid. 98314564Sdim return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64 99314564Sdim : g_fields->m_host_arch_32; 100275072Semaste} 101275072Semaste 102327952Sdimllvm::Optional<HostInfoBase::ArchitectureKind> HostInfoBase::ParseArchitectureKind(llvm::StringRef kind) { 103327952Sdim return llvm::StringSwitch<llvm::Optional<ArchitectureKind>>(kind) 104327952Sdim .Case(LLDB_ARCH_DEFAULT, eArchKindDefault) 105327952Sdim .Case(LLDB_ARCH_DEFAULT_32BIT, eArchKind32) 106327952Sdim .Case(LLDB_ARCH_DEFAULT_64BIT, eArchKind64) 107327952Sdim .Default(llvm::None); 108327952Sdim} 109327952Sdim 110341825SdimFileSpec HostInfoBase::GetShlibDir() { 111341825Sdim static llvm::once_flag g_once_flag; 112341825Sdim static bool success = false; 113341825Sdim llvm::call_once(g_once_flag, []() { 114341825Sdim success = HostInfo::ComputeSharedLibraryDirectory(g_fields->m_lldb_so_dir); 115341825Sdim Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 116341825Sdim LLDB_LOG(log, "shlib dir -> `{0}`", g_fields->m_lldb_so_dir); 117341825Sdim }); 118341825Sdim return success ? g_fields->m_lldb_so_dir : FileSpec(); 119341825Sdim} 120275072Semaste 121341825SdimFileSpec HostInfoBase::GetSupportExeDir() { 122341825Sdim static llvm::once_flag g_once_flag; 123341825Sdim static bool success = false; 124341825Sdim llvm::call_once(g_once_flag, []() { 125341825Sdim success = 126341825Sdim HostInfo::ComputeSupportExeDirectory(g_fields->m_lldb_support_exe_dir); 127341825Sdim Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 128341825Sdim LLDB_LOG(log, "support exe dir -> `{0}`", g_fields->m_lldb_support_exe_dir); 129341825Sdim }); 130341825Sdim return success ? g_fields->m_lldb_support_exe_dir : FileSpec(); 131341825Sdim} 132275072Semaste 133341825SdimFileSpec HostInfoBase::GetHeaderDir() { 134341825Sdim static llvm::once_flag g_once_flag; 135341825Sdim static bool success = false; 136341825Sdim llvm::call_once(g_once_flag, []() { 137341825Sdim success = HostInfo::ComputeHeaderDirectory(g_fields->m_lldb_headers_dir); 138341825Sdim Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 139341825Sdim LLDB_LOG(log, "header dir -> `{0}`", g_fields->m_lldb_headers_dir); 140341825Sdim }); 141341825Sdim return success ? g_fields->m_lldb_headers_dir : FileSpec(); 142341825Sdim} 143275072Semaste 144341825SdimFileSpec HostInfoBase::GetSystemPluginDir() { 145341825Sdim static llvm::once_flag g_once_flag; 146341825Sdim static bool success = false; 147341825Sdim llvm::call_once(g_once_flag, []() { 148341825Sdim success = HostInfo::ComputeSystemPluginsDirectory( 149341825Sdim g_fields->m_lldb_system_plugin_dir); 150341825Sdim Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 151341825Sdim LLDB_LOG(log, "system plugin dir -> `{0}`", 152341825Sdim g_fields->m_lldb_system_plugin_dir); 153341825Sdim }); 154341825Sdim return success ? g_fields->m_lldb_system_plugin_dir : FileSpec(); 155275072Semaste} 156275072Semaste 157341825SdimFileSpec HostInfoBase::GetUserPluginDir() { 158341825Sdim static llvm::once_flag g_once_flag; 159341825Sdim static bool success = false; 160341825Sdim llvm::call_once(g_once_flag, []() { 161341825Sdim success = 162341825Sdim HostInfo::ComputeUserPluginsDirectory(g_fields->m_lldb_user_plugin_dir); 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 }); 166341825Sdim return success ? g_fields->m_lldb_user_plugin_dir : FileSpec(); 167341825Sdim} 168341825Sdim 169341825SdimFileSpec HostInfoBase::GetProcessTempDir() { 170341825Sdim static llvm::once_flag g_once_flag; 171341825Sdim static bool success = false; 172341825Sdim llvm::call_once(g_once_flag, []() { 173341825Sdim success = HostInfo::ComputeProcessTempFileDirectory( 174341825Sdim g_fields->m_lldb_process_tmp_dir); 175341825Sdim Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 176341825Sdim LLDB_LOG(log, "process temp dir -> `{0}`", 177341825Sdim g_fields->m_lldb_process_tmp_dir); 178341825Sdim }); 179341825Sdim return success ? g_fields->m_lldb_process_tmp_dir : FileSpec(); 180341825Sdim} 181341825Sdim 182341825SdimFileSpec HostInfoBase::GetGlobalTempDir() { 183341825Sdim static llvm::once_flag g_once_flag; 184341825Sdim static bool success = false; 185341825Sdim llvm::call_once(g_once_flag, []() { 186341825Sdim success = HostInfo::ComputeGlobalTempFileDirectory( 187341825Sdim g_fields->m_lldb_global_tmp_dir); 188341825Sdim Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 189341825Sdim LLDB_LOG(log, "global temp dir -> `{0}`", g_fields->m_lldb_global_tmp_dir); 190341825Sdim }); 191341825Sdim return success ? g_fields->m_lldb_global_tmp_dir : FileSpec(); 192341825Sdim} 193341825Sdim 194327952SdimArchSpec HostInfoBase::GetAugmentedArchSpec(llvm::StringRef triple) { 195327952Sdim if (triple.empty()) 196327952Sdim return ArchSpec(); 197327952Sdim llvm::Triple normalized_triple(llvm::Triple::normalize(triple)); 198327952Sdim if (!ArchSpec::ContainsOnlyArch(normalized_triple)) 199327952Sdim return ArchSpec(triple); 200327952Sdim 201327952Sdim if (auto kind = HostInfo::ParseArchitectureKind(triple)) 202327952Sdim return HostInfo::GetArchitecture(*kind); 203327952Sdim 204327952Sdim llvm::Triple host_triple(llvm::sys::getDefaultTargetTriple()); 205327952Sdim 206327952Sdim if (normalized_triple.getVendorName().empty()) 207327952Sdim normalized_triple.setVendor(host_triple.getVendor()); 208327952Sdim if (normalized_triple.getOSName().empty()) 209327952Sdim normalized_triple.setOS(host_triple.getOS()); 210327952Sdim if (normalized_triple.getEnvironmentName().empty()) 211327952Sdim normalized_triple.setEnvironment(host_triple.getEnvironment()); 212327952Sdim return ArchSpec(normalized_triple); 213327952Sdim} 214327952Sdim 215353358Sdimbool HostInfoBase::ComputePathRelativeToLibrary(FileSpec &file_spec, 216353358Sdim llvm::StringRef dir) { 217353358Sdim Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 218353358Sdim 219353358Sdim FileSpec lldb_file_spec = GetShlibDir(); 220353358Sdim if (!lldb_file_spec) 221353358Sdim return false; 222353358Sdim 223353358Sdim std::string raw_path = lldb_file_spec.GetPath(); 224353358Sdim if (log) 225353358Sdim log->Printf("HostInfo::%s() attempting to " 226353358Sdim "derive the path %s relative to liblldb install path: %s", 227353358Sdim __FUNCTION__, dir.data(), raw_path.c_str()); 228353358Sdim 229353358Sdim // Drop bin (windows) or lib 230353358Sdim llvm::StringRef parent_path = llvm::sys::path::parent_path(raw_path); 231353358Sdim if (parent_path.empty()) { 232353358Sdim if (log) 233353358Sdim log->Printf("HostInfo::%s() failed to find liblldb within the shared " 234353358Sdim "lib path", 235353358Sdim __FUNCTION__); 236353358Sdim return false; 237353358Sdim } 238353358Sdim 239353358Sdim raw_path = (parent_path + dir).str(); 240353358Sdim if (log) 241353358Sdim log->Printf("HostInfo::%s() derived the path as: %s", __FUNCTION__, 242353358Sdim raw_path.c_str()); 243353358Sdim file_spec.GetDirectory().SetString(raw_path); 244353358Sdim return (bool)file_spec.GetDirectory(); 245353358Sdim} 246353358Sdim 247314564Sdimbool HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) { 248314564Sdim // To get paths related to LLDB we get the path to the executable that 249341825Sdim // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB". 250341825Sdim // On other posix systems, we will get .../lib(64|32)?/liblldb.so. 251275072Semaste 252341825Sdim FileSpec lldb_file_spec(Host::GetModuleFileSpecForHostAddress( 253341825Sdim reinterpret_cast<void *>(reinterpret_cast<intptr_t>( 254341825Sdim HostInfoBase::ComputeSharedLibraryDirectory)))); 255275072Semaste 256314564Sdim // This is necessary because when running the testsuite the shlib might be a 257314564Sdim // symbolic link inside the Python resource dir. 258344779Sdim FileSystem::Instance().ResolveSymbolicLink(lldb_file_spec, lldb_file_spec); 259314564Sdim 260314564Sdim // Remove the filename so that this FileSpec only represents the directory. 261314564Sdim file_spec.GetDirectory() = lldb_file_spec.GetDirectory(); 262314564Sdim 263314564Sdim return (bool)file_spec.GetDirectory(); 264275072Semaste} 265275072Semaste 266314564Sdimbool HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec) { 267341825Sdim file_spec = GetShlibDir(); 268341825Sdim return bool(file_spec); 269275072Semaste} 270275072Semaste 271314564Sdimbool HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec) { 272314564Sdim FileSpec temp_file_spec; 273314564Sdim if (!HostInfo::ComputeGlobalTempFileDirectory(temp_file_spec)) 274314564Sdim return false; 275288943Sdim 276314564Sdim std::string pid_str{llvm::to_string(Host::GetCurrentProcessID())}; 277314564Sdim temp_file_spec.AppendPathComponent(pid_str); 278321369Sdim if (llvm::sys::fs::create_directory(temp_file_spec.GetPath())) 279314564Sdim return false; 280288943Sdim 281314564Sdim file_spec.GetDirectory().SetCString(temp_file_spec.GetCString()); 282314564Sdim return true; 283288943Sdim} 284288943Sdim 285314564Sdimbool HostInfoBase::ComputeTempFileBaseDirectory(FileSpec &file_spec) { 286314564Sdim llvm::SmallVector<char, 16> tmpdir; 287314564Sdim llvm::sys::path::system_temp_directory(/*ErasedOnReboot*/ true, tmpdir); 288344779Sdim file_spec = FileSpec(std::string(tmpdir.data(), tmpdir.size())); 289344779Sdim FileSystem::Instance().Resolve(file_spec); 290314564Sdim return true; 291288943Sdim} 292288943Sdim 293314564Sdimbool HostInfoBase::ComputeGlobalTempFileDirectory(FileSpec &file_spec) { 294314564Sdim file_spec.Clear(); 295288943Sdim 296314564Sdim FileSpec temp_file_spec; 297314564Sdim if (!HostInfo::ComputeTempFileBaseDirectory(temp_file_spec)) 298314564Sdim return false; 299275072Semaste 300314564Sdim temp_file_spec.AppendPathComponent("lldb"); 301321369Sdim if (llvm::sys::fs::create_directory(temp_file_spec.GetPath())) 302314564Sdim return false; 303275072Semaste 304314564Sdim file_spec.GetDirectory().SetCString(temp_file_spec.GetCString()); 305314564Sdim return true; 306275072Semaste} 307275072Semaste 308314564Sdimbool HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec) { 309314564Sdim // TODO(zturner): Figure out how to compute the header directory for all 310314564Sdim // platforms. 311314564Sdim return false; 312275072Semaste} 313275072Semaste 314314564Sdimbool HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec) { 315314564Sdim // TODO(zturner): Figure out how to compute the system plugins directory for 316314564Sdim // all platforms. 317314564Sdim return false; 318275072Semaste} 319275072Semaste 320314564Sdimbool HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec) { 321341825Sdim // TODO(zturner): Figure out how to compute the user plugins directory for 322341825Sdim // all platforms. 323314564Sdim return false; 324275072Semaste} 325275072Semaste 326314564Sdimvoid HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, 327314564Sdim ArchSpec &arch_64) { 328314564Sdim llvm::Triple triple(llvm::sys::getProcessTriple()); 329275072Semaste 330314564Sdim arch_32.Clear(); 331314564Sdim arch_64.Clear(); 332275072Semaste 333314564Sdim switch (triple.getArch()) { 334314564Sdim default: 335314564Sdim arch_32.SetTriple(triple); 336314564Sdim break; 337275072Semaste 338314564Sdim case llvm::Triple::aarch64: 339314564Sdim case llvm::Triple::ppc64: 340341825Sdim case llvm::Triple::ppc64le: 341314564Sdim case llvm::Triple::x86_64: 342314564Sdim arch_64.SetTriple(triple); 343314564Sdim arch_32.SetTriple(triple.get32BitArchVariant()); 344314564Sdim break; 345275072Semaste 346314564Sdim case llvm::Triple::mips64: 347314564Sdim case llvm::Triple::mips64el: 348314564Sdim case llvm::Triple::sparcv9: 349314564Sdim case llvm::Triple::systemz: 350314564Sdim arch_64.SetTriple(triple); 351314564Sdim break; 352314564Sdim } 353275072Semaste} 354