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/Core/ArchSpec.h" 13 #include "lldb/Core/Log.h" 14 #include "lldb/Core/StreamString.h" 15 #include "lldb/Host/FileSystem.h" 16 #include "lldb/Host/Host.h" 17 #include "lldb/Host/HostInfo.h" 18 #include "lldb/Host/HostInfoBase.h" 19 20 #include "llvm/ADT/Triple.h" 21 #include "llvm/ADT/StringExtras.h" 22 #include "llvm/Support/Host.h" 23 #include "llvm/Support/raw_ostream.h" 24 25 #include <thread> 26 #include <mutex> // std::once 27 28 using namespace lldb; 29 using namespace lldb_private; 30 31 namespace 32 { 33 void 34 CleanupProcessSpecificLLDBTempDir() 35 { 36 // Get the process specific LLDB temporary directory and delete it. 37 FileSpec tmpdir_file_spec; 38 if (!HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) 39 return; 40 41 // Remove the LLDB temporary directory if we have one. Set "recurse" to 42 // true to all files that were created for the LLDB process can be cleaned up. 43 FileSystem::DeleteDirectory(tmpdir_file_spec.GetDirectory().GetCString(), true); 44 } 45 46 //---------------------------------------------------------------------- 47 // The HostInfoBaseFields is a work around for windows not supporting 48 // static variables correctly in a thread safe way. Really each of the 49 // variables in HostInfoBaseFields should live in the functions in which 50 // they are used and each one should be static, but the work around is 51 // in place to avoid this restriction. Ick. 52 //---------------------------------------------------------------------- 53 54 struct HostInfoBaseFields 55 { 56 uint32_t m_number_cpus; 57 std::string m_vendor_string; 58 std::string m_os_string; 59 std::string m_host_triple; 60 61 ArchSpec m_host_arch_32; 62 ArchSpec m_host_arch_64; 63 64 FileSpec m_lldb_so_dir; 65 FileSpec m_lldb_support_exe_dir; 66 FileSpec m_lldb_headers_dir; 67 FileSpec m_lldb_python_dir; 68 FileSpec m_lldb_clang_resource_dir; 69 FileSpec m_lldb_system_plugin_dir; 70 FileSpec m_lldb_user_plugin_dir; 71 FileSpec m_lldb_tmp_dir; 72 }; 73 74 HostInfoBaseFields *g_fields = nullptr; 75 } 76 77 void 78 HostInfoBase::Initialize() 79 { 80 g_fields = new HostInfoBaseFields(); 81 } 82 83 uint32_t 84 HostInfoBase::GetNumberCPUS() 85 { 86 static std::once_flag g_once_flag; 87 std::call_once(g_once_flag, []() { 88 g_fields->m_number_cpus = std::thread::hardware_concurrency(); 89 }); 90 return g_fields->m_number_cpus; 91 } 92 93 uint32_t 94 HostInfoBase::GetMaxThreadNameLength() 95 { 96 return 0; 97 } 98 99 llvm::StringRef 100 HostInfoBase::GetVendorString() 101 { 102 static std::once_flag g_once_flag; 103 std::call_once(g_once_flag, []() { 104 g_fields->m_vendor_string = std::move(HostInfo::GetArchitecture().GetTriple().getVendorName().str()); 105 }); 106 return g_fields->m_vendor_string; 107 } 108 109 llvm::StringRef 110 HostInfoBase::GetOSString() 111 { 112 static std::once_flag g_once_flag; 113 std::call_once(g_once_flag, []() { 114 g_fields->m_os_string = std::move(HostInfo::GetArchitecture().GetTriple().getOSName()); 115 }); 116 return g_fields->m_os_string; 117 } 118 119 llvm::StringRef 120 HostInfoBase::GetTargetTriple() 121 { 122 static std::once_flag g_once_flag; 123 std::call_once(g_once_flag, []() { 124 g_fields->m_host_triple = HostInfo::GetArchitecture().GetTriple().getTriple(); 125 }); 126 return g_fields->m_host_triple; 127 } 128 129 const ArchSpec & 130 HostInfoBase::GetArchitecture(ArchitectureKind arch_kind) 131 { 132 static std::once_flag g_once_flag; 133 std::call_once(g_once_flag, []() { 134 HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32, g_fields->m_host_arch_64); 135 }); 136 137 // If an explicit 32 or 64-bit architecture was requested, return that. 138 if (arch_kind == eArchKind32) 139 return g_fields->m_host_arch_32; 140 if (arch_kind == eArchKind64) 141 return g_fields->m_host_arch_64; 142 143 // Otherwise prefer the 64-bit architecture if it is valid. 144 return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64 : g_fields->m_host_arch_32; 145 } 146 147 bool 148 HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) 149 { 150 file_spec.Clear(); 151 152 #if defined(LLDB_DISABLE_PYTHON) 153 if (type == lldb::ePathTypePythonDir) 154 return false; 155 #endif 156 157 FileSpec *result = nullptr; 158 switch (type) 159 { 160 case lldb::ePathTypeLLDBShlibDir: 161 { 162 static std::once_flag g_once_flag; 163 static bool success = false; 164 std::call_once(g_once_flag, []() { 165 success = HostInfo::ComputeSharedLibraryDirectory (g_fields->m_lldb_so_dir); 166 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 167 if (log) 168 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", g_fields->m_lldb_so_dir.GetPath().c_str()); 169 }); 170 if (success) 171 result = &g_fields->m_lldb_so_dir; 172 } 173 break; 174 case lldb::ePathTypeSupportExecutableDir: 175 { 176 static std::once_flag g_once_flag; 177 static bool success = false; 178 std::call_once(g_once_flag, []() { 179 success = HostInfo::ComputeSupportExeDirectory (g_fields->m_lldb_support_exe_dir); 180 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 181 if (log) 182 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'", 183 g_fields->m_lldb_support_exe_dir.GetPath().c_str()); 184 }); 185 if (success) 186 result = &g_fields->m_lldb_support_exe_dir; 187 } 188 break; 189 case lldb::ePathTypeHeaderDir: 190 { 191 static std::once_flag g_once_flag; 192 static bool success = false; 193 std::call_once(g_once_flag, []() { 194 success = HostInfo::ComputeHeaderDirectory (g_fields->m_lldb_headers_dir); 195 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 196 if (log) 197 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'", g_fields->m_lldb_headers_dir.GetPath().c_str()); 198 }); 199 if (success) 200 result = &g_fields->m_lldb_headers_dir; 201 } 202 break; 203 case lldb::ePathTypePythonDir: 204 { 205 static std::once_flag g_once_flag; 206 static bool success = false; 207 std::call_once(g_once_flag, []() { 208 success = HostInfo::ComputePythonDirectory (g_fields->m_lldb_python_dir); 209 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 210 if (log) 211 log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'", g_fields->m_lldb_python_dir.GetPath().c_str()); 212 }); 213 if (success) 214 result = &g_fields->m_lldb_python_dir; 215 } 216 break; 217 case lldb::ePathTypeClangDir: 218 { 219 static std::once_flag g_once_flag; 220 static bool success = false; 221 std::call_once(g_once_flag, []() { 222 success = HostInfo::ComputeClangDirectory (g_fields->m_lldb_clang_resource_dir); 223 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 224 if (log) 225 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeClangResourceDir) => '%s'", g_fields->m_lldb_clang_resource_dir.GetPath().c_str()); 226 }); 227 if (success) 228 result = &g_fields->m_lldb_clang_resource_dir; 229 } 230 break; 231 case lldb::ePathTypeLLDBSystemPlugins: 232 { 233 static std::once_flag g_once_flag; 234 static bool success = false; 235 std::call_once(g_once_flag, []() { 236 success = HostInfo::ComputeSystemPluginsDirectory (g_fields->m_lldb_system_plugin_dir); 237 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 238 if (log) 239 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'", 240 g_fields->m_lldb_system_plugin_dir.GetPath().c_str()); 241 }); 242 if (success) 243 result = &g_fields->m_lldb_system_plugin_dir; 244 } 245 break; 246 case lldb::ePathTypeLLDBUserPlugins: 247 { 248 static std::once_flag g_once_flag; 249 static bool success = false; 250 std::call_once(g_once_flag, []() { 251 success = HostInfo::ComputeUserPluginsDirectory (g_fields->m_lldb_user_plugin_dir); 252 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 253 if (log) 254 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'", 255 g_fields->m_lldb_user_plugin_dir.GetPath().c_str()); 256 }); 257 if (success) 258 result = &g_fields->m_lldb_user_plugin_dir; 259 } 260 break; 261 case lldb::ePathTypeLLDBTempSystemDir: 262 { 263 static std::once_flag g_once_flag; 264 static bool success = false; 265 std::call_once(g_once_flag, []() { 266 success = HostInfo::ComputeTempFileDirectory (g_fields->m_lldb_tmp_dir); 267 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 268 if (log) 269 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", g_fields->m_lldb_tmp_dir.GetPath().c_str()); 270 }); 271 if (success) 272 result = &g_fields->m_lldb_tmp_dir; 273 } 274 break; 275 } 276 277 if (!result) 278 return false; 279 file_spec = *result; 280 return true; 281 } 282 283 bool 284 HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) 285 { 286 // To get paths related to LLDB we get the path to the executable that 287 // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB", 288 // on linux this is assumed to be the "lldb" main executable. If LLDB on 289 // linux is actually in a shared library (liblldb.so) then this function will 290 // need to be modified to "do the right thing". 291 292 FileSpec lldb_file_spec( 293 Host::GetModuleFileSpecForHostAddress(reinterpret_cast<void *>(reinterpret_cast<intptr_t>(HostInfoBase::GetLLDBPath)))); 294 295 // Remove the filename so that this FileSpec only represents the directory. 296 file_spec.GetDirectory() = lldb_file_spec.GetDirectory(); 297 298 return (bool)file_spec.GetDirectory(); 299 } 300 301 bool 302 HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec) 303 { 304 return GetLLDBPath(lldb::ePathTypeLLDBShlibDir, file_spec); 305 } 306 307 bool 308 HostInfoBase::ComputeTempFileDirectory(FileSpec &file_spec) 309 { 310 const char *tmpdir_cstr = getenv("TMPDIR"); 311 if (tmpdir_cstr == NULL) 312 { 313 tmpdir_cstr = getenv("TMP"); 314 if (tmpdir_cstr == NULL) 315 tmpdir_cstr = getenv("TEMP"); 316 } 317 if (!tmpdir_cstr) 318 return false; 319 320 FileSpec temp_file_spec(tmpdir_cstr, false); 321 temp_file_spec.AppendPathComponent("lldb"); 322 if (!FileSystem::MakeDirectory(temp_file_spec.GetPath().c_str(), eFilePermissionsDirectoryDefault).Success()) 323 return false; 324 325 std::string pid_str; 326 llvm::raw_string_ostream pid_stream(pid_str); 327 pid_stream << Host::GetCurrentProcessID(); 328 temp_file_spec.AppendPathComponent(pid_stream.str().c_str()); 329 std::string final_path = temp_file_spec.GetPath(); 330 if (!FileSystem::MakeDirectory(final_path.c_str(), eFilePermissionsDirectoryDefault).Success()) 331 return false; 332 333 // Make an atexit handler to clean up the process specify LLDB temp dir 334 // and all of its contents. 335 ::atexit(CleanupProcessSpecificLLDBTempDir); 336 file_spec.GetDirectory().SetCStringWithLength(final_path.c_str(), final_path.size()); 337 return true; 338 } 339 340 bool 341 HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec) 342 { 343 // TODO(zturner): Figure out how to compute the header directory for all platforms. 344 return false; 345 } 346 347 bool 348 HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec) 349 { 350 // TODO(zturner): Figure out how to compute the system plugins directory for all platforms. 351 return false; 352 } 353 354 bool 355 HostInfoBase::ComputeClangDirectory(FileSpec &file_spec) 356 { 357 return false; 358 } 359 360 bool 361 HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec) 362 { 363 // TODO(zturner): Figure out how to compute the user plugins directory for all platforms. 364 return false; 365 } 366 367 void 368 HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64) 369 { 370 llvm::Triple triple(llvm::sys::getProcessTriple()); 371 372 arch_32.Clear(); 373 arch_64.Clear(); 374 375 switch (triple.getArch()) 376 { 377 default: 378 arch_32.SetTriple(triple); 379 break; 380 381 case llvm::Triple::ppc64: 382 case llvm::Triple::x86_64: 383 arch_64.SetTriple(triple); 384 arch_32.SetTriple(triple.get32BitArchVariant()); 385 break; 386 387 case llvm::Triple::aarch64: 388 case llvm::Triple::mips64: 389 case llvm::Triple::sparcv9: 390 arch_64.SetTriple(triple); 391 break; 392 } 393 } 394