HostInfoBase.cpp revision 341825
1//===-- HostInfoBase.cpp ----------------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "lldb/Host/Config.h" 11 12#include "lldb/Host/FileSystem.h" 13#include "lldb/Host/Host.h" 14#include "lldb/Host/HostInfo.h" 15#include "lldb/Host/HostInfoBase.h" 16#include "lldb/Utility/ArchSpec.h" 17#include "lldb/Utility/Log.h" 18#include "lldb/Utility/StreamString.h" 19 20#include "llvm/ADT/StringExtras.h" 21#include "llvm/ADT/Triple.h" 22#include "llvm/Support/Host.h" 23#include "llvm/Support/Path.h" 24#include "llvm/Support/ScopedPrinter.h" 25#include "llvm/Support/Threading.h" 26#include "llvm/Support/raw_ostream.h" 27 28#include <mutex> 29#include <thread> 30 31using namespace lldb; 32using namespace lldb_private; 33 34namespace { 35//---------------------------------------------------------------------- 36// The HostInfoBaseFields is a work around for windows not supporting static 37// variables correctly in a thread safe way. Really each of the variables in 38// HostInfoBaseFields should live in the functions in which they are used and 39// each one should be static, but the work around is in place to avoid this 40// restriction. Ick. 41//---------------------------------------------------------------------- 42 43struct HostInfoBaseFields { 44 ~HostInfoBaseFields() { 45 if (m_lldb_process_tmp_dir.Exists()) { 46 // Remove the LLDB temporary directory if we have one. Set "recurse" to 47 // true to all files that were created for the LLDB process can be 48 // cleaned up. 49 llvm::sys::fs::remove_directories(m_lldb_process_tmp_dir.GetPath()); 50 } 51 } 52 53 std::string m_host_triple; 54 55 ArchSpec m_host_arch_32; 56 ArchSpec m_host_arch_64; 57 58 FileSpec m_lldb_so_dir; 59 FileSpec m_lldb_support_exe_dir; 60 FileSpec m_lldb_headers_dir; 61 FileSpec m_lldb_clang_resource_dir; 62 FileSpec m_lldb_system_plugin_dir; 63 FileSpec m_lldb_user_plugin_dir; 64 FileSpec m_lldb_process_tmp_dir; 65 FileSpec m_lldb_global_tmp_dir; 66}; 67 68HostInfoBaseFields *g_fields = nullptr; 69} 70 71void HostInfoBase::Initialize() { g_fields = new HostInfoBaseFields(); } 72 73void HostInfoBase::Terminate() { 74 delete g_fields; 75 g_fields = nullptr; 76} 77 78llvm::StringRef HostInfoBase::GetTargetTriple() { 79 static llvm::once_flag g_once_flag; 80 llvm::call_once(g_once_flag, []() { 81 g_fields->m_host_triple = 82 HostInfo::GetArchitecture().GetTriple().getTriple(); 83 }); 84 return g_fields->m_host_triple; 85} 86 87const ArchSpec &HostInfoBase::GetArchitecture(ArchitectureKind arch_kind) { 88 static llvm::once_flag g_once_flag; 89 llvm::call_once(g_once_flag, []() { 90 HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32, 91 g_fields->m_host_arch_64); 92 }); 93 94 // If an explicit 32 or 64-bit architecture was requested, return that. 95 if (arch_kind == eArchKind32) 96 return g_fields->m_host_arch_32; 97 if (arch_kind == eArchKind64) 98 return g_fields->m_host_arch_64; 99 100 // Otherwise prefer the 64-bit architecture if it is valid. 101 return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64 102 : g_fields->m_host_arch_32; 103} 104 105llvm::Optional<HostInfoBase::ArchitectureKind> HostInfoBase::ParseArchitectureKind(llvm::StringRef kind) { 106 return llvm::StringSwitch<llvm::Optional<ArchitectureKind>>(kind) 107 .Case(LLDB_ARCH_DEFAULT, eArchKindDefault) 108 .Case(LLDB_ARCH_DEFAULT_32BIT, eArchKind32) 109 .Case(LLDB_ARCH_DEFAULT_64BIT, eArchKind64) 110 .Default(llvm::None); 111} 112 113FileSpec HostInfoBase::GetShlibDir() { 114 static llvm::once_flag g_once_flag; 115 static bool success = false; 116 llvm::call_once(g_once_flag, []() { 117 success = HostInfo::ComputeSharedLibraryDirectory(g_fields->m_lldb_so_dir); 118 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 119 LLDB_LOG(log, "shlib dir -> `{0}`", g_fields->m_lldb_so_dir); 120 }); 121 return success ? g_fields->m_lldb_so_dir : FileSpec(); 122} 123 124FileSpec HostInfoBase::GetSupportExeDir() { 125 static llvm::once_flag g_once_flag; 126 static bool success = false; 127 llvm::call_once(g_once_flag, []() { 128 success = 129 HostInfo::ComputeSupportExeDirectory(g_fields->m_lldb_support_exe_dir); 130 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 131 LLDB_LOG(log, "support exe dir -> `{0}`", g_fields->m_lldb_support_exe_dir); 132 }); 133 return success ? g_fields->m_lldb_support_exe_dir : FileSpec(); 134} 135 136FileSpec HostInfoBase::GetHeaderDir() { 137 static llvm::once_flag g_once_flag; 138 static bool success = false; 139 llvm::call_once(g_once_flag, []() { 140 success = HostInfo::ComputeHeaderDirectory(g_fields->m_lldb_headers_dir); 141 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 142 LLDB_LOG(log, "header dir -> `{0}`", g_fields->m_lldb_headers_dir); 143 }); 144 return success ? g_fields->m_lldb_headers_dir : FileSpec(); 145} 146 147FileSpec HostInfoBase::GetSystemPluginDir() { 148 static llvm::once_flag g_once_flag; 149 static bool success = false; 150 llvm::call_once(g_once_flag, []() { 151 success = HostInfo::ComputeSystemPluginsDirectory( 152 g_fields->m_lldb_system_plugin_dir); 153 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 154 LLDB_LOG(log, "system plugin dir -> `{0}`", 155 g_fields->m_lldb_system_plugin_dir); 156 }); 157 return success ? g_fields->m_lldb_system_plugin_dir : FileSpec(); 158} 159 160FileSpec HostInfoBase::GetUserPluginDir() { 161 static llvm::once_flag g_once_flag; 162 static bool success = false; 163 llvm::call_once(g_once_flag, []() { 164 success = 165 HostInfo::ComputeUserPluginsDirectory(g_fields->m_lldb_user_plugin_dir); 166 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 167 LLDB_LOG(log, "user plugin dir -> `{0}`", g_fields->m_lldb_user_plugin_dir); 168 }); 169 return success ? g_fields->m_lldb_user_plugin_dir : FileSpec(); 170} 171 172FileSpec HostInfoBase::GetProcessTempDir() { 173 static llvm::once_flag g_once_flag; 174 static bool success = false; 175 llvm::call_once(g_once_flag, []() { 176 success = HostInfo::ComputeProcessTempFileDirectory( 177 g_fields->m_lldb_process_tmp_dir); 178 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 179 LLDB_LOG(log, "process temp dir -> `{0}`", 180 g_fields->m_lldb_process_tmp_dir); 181 }); 182 return success ? g_fields->m_lldb_process_tmp_dir : FileSpec(); 183} 184 185FileSpec HostInfoBase::GetGlobalTempDir() { 186 static llvm::once_flag g_once_flag; 187 static bool success = false; 188 llvm::call_once(g_once_flag, []() { 189 success = HostInfo::ComputeGlobalTempFileDirectory( 190 g_fields->m_lldb_global_tmp_dir); 191 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 192 LLDB_LOG(log, "global temp dir -> `{0}`", g_fields->m_lldb_global_tmp_dir); 193 }); 194 return success ? g_fields->m_lldb_global_tmp_dir : FileSpec(); 195} 196 197ArchSpec HostInfoBase::GetAugmentedArchSpec(llvm::StringRef triple) { 198 if (triple.empty()) 199 return ArchSpec(); 200 llvm::Triple normalized_triple(llvm::Triple::normalize(triple)); 201 if (!ArchSpec::ContainsOnlyArch(normalized_triple)) 202 return ArchSpec(triple); 203 204 if (auto kind = HostInfo::ParseArchitectureKind(triple)) 205 return HostInfo::GetArchitecture(*kind); 206 207 llvm::Triple host_triple(llvm::sys::getDefaultTargetTriple()); 208 209 if (normalized_triple.getVendorName().empty()) 210 normalized_triple.setVendor(host_triple.getVendor()); 211 if (normalized_triple.getOSName().empty()) 212 normalized_triple.setOS(host_triple.getOS()); 213 if (normalized_triple.getEnvironmentName().empty()) 214 normalized_triple.setEnvironment(host_triple.getEnvironment()); 215 return ArchSpec(normalized_triple); 216} 217 218bool HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) { 219 // To get paths related to LLDB we get the path to the executable that 220 // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB". 221 // On other posix systems, we will get .../lib(64|32)?/liblldb.so. 222 223 FileSpec lldb_file_spec(Host::GetModuleFileSpecForHostAddress( 224 reinterpret_cast<void *>(reinterpret_cast<intptr_t>( 225 HostInfoBase::ComputeSharedLibraryDirectory)))); 226 227 // This is necessary because when running the testsuite the shlib might be a 228 // symbolic link inside the Python resource dir. 229 FileSystem::ResolveSymbolicLink(lldb_file_spec, lldb_file_spec); 230 231 // Remove the filename so that this FileSpec only represents the directory. 232 file_spec.GetDirectory() = lldb_file_spec.GetDirectory(); 233 234 return (bool)file_spec.GetDirectory(); 235} 236 237bool HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec) { 238 file_spec = GetShlibDir(); 239 return bool(file_spec); 240} 241 242bool HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec) { 243 FileSpec temp_file_spec; 244 if (!HostInfo::ComputeGlobalTempFileDirectory(temp_file_spec)) 245 return false; 246 247 std::string pid_str{llvm::to_string(Host::GetCurrentProcessID())}; 248 temp_file_spec.AppendPathComponent(pid_str); 249 if (llvm::sys::fs::create_directory(temp_file_spec.GetPath())) 250 return false; 251 252 file_spec.GetDirectory().SetCString(temp_file_spec.GetCString()); 253 return true; 254} 255 256bool HostInfoBase::ComputeTempFileBaseDirectory(FileSpec &file_spec) { 257 llvm::SmallVector<char, 16> tmpdir; 258 llvm::sys::path::system_temp_directory(/*ErasedOnReboot*/ true, tmpdir); 259 file_spec = FileSpec(std::string(tmpdir.data(), tmpdir.size()), true); 260 return true; 261} 262 263bool HostInfoBase::ComputeGlobalTempFileDirectory(FileSpec &file_spec) { 264 file_spec.Clear(); 265 266 FileSpec temp_file_spec; 267 if (!HostInfo::ComputeTempFileBaseDirectory(temp_file_spec)) 268 return false; 269 270 temp_file_spec.AppendPathComponent("lldb"); 271 if (llvm::sys::fs::create_directory(temp_file_spec.GetPath())) 272 return false; 273 274 file_spec.GetDirectory().SetCString(temp_file_spec.GetCString()); 275 return true; 276} 277 278bool HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec) { 279 // TODO(zturner): Figure out how to compute the header directory for all 280 // platforms. 281 return false; 282} 283 284bool HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec) { 285 // TODO(zturner): Figure out how to compute the system plugins directory for 286 // all platforms. 287 return false; 288} 289 290bool HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec) { 291 // TODO(zturner): Figure out how to compute the user plugins directory for 292 // all platforms. 293 return false; 294} 295 296void HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, 297 ArchSpec &arch_64) { 298 llvm::Triple triple(llvm::sys::getProcessTriple()); 299 300 arch_32.Clear(); 301 arch_64.Clear(); 302 303 switch (triple.getArch()) { 304 default: 305 arch_32.SetTriple(triple); 306 break; 307 308 case llvm::Triple::aarch64: 309 case llvm::Triple::ppc64: 310 case llvm::Triple::ppc64le: 311 case llvm::Triple::x86_64: 312 arch_64.SetTriple(triple); 313 arch_32.SetTriple(triple.get32BitArchVariant()); 314 break; 315 316 case llvm::Triple::mips64: 317 case llvm::Triple::mips64el: 318 case llvm::Triple::sparcv9: 319 case llvm::Triple::systemz: 320 arch_64.SetTriple(triple); 321 break; 322 } 323} 324