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/Support/Host.h" 22 23 #include <thread> 24 25 using namespace lldb; 26 using namespace lldb_private; 27 28 namespace 29 { 30 void 31 CleanupProcessSpecificLLDBTempDir() 32 { 33 // Get the process specific LLDB temporary directory and delete it. 34 FileSpec tmpdir_file_spec; 35 if (!HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) 36 return; 37 38 // Remove the LLDB temporary directory if we have one. Set "recurse" to 39 // true to all files that were created for the LLDB process can be cleaned up. 40 FileSystem::DeleteDirectory(tmpdir_file_spec.GetDirectory().GetCString(), true); 41 } 42 43 struct HostInfoBaseFields 44 { 45 uint32_t m_number_cpus; 46 std::string m_vendor_string; 47 std::string m_os_string; 48 std::string m_host_triple; 49 50 ArchSpec m_host_arch_32; 51 ArchSpec m_host_arch_64; 52 53 FileSpec m_lldb_so_dir; 54 FileSpec m_lldb_support_exe_dir; 55 FileSpec m_lldb_headers_dir; 56 FileSpec m_lldb_python_dir; 57 FileSpec m_lldb_system_plugin_dir; 58 FileSpec m_lldb_user_plugin_dir; 59 FileSpec m_lldb_tmp_dir; 60 }; 61 62 HostInfoBaseFields *g_fields = nullptr; 63 } 64 65 #define COMPUTE_LLDB_PATH(compute_function, member_var) \ 66 { \ 67 static bool is_initialized = false; \ 68 static bool success = false; \ 69 if (!is_initialized) \ 70 { \ 71 is_initialized = true; \ 72 success = HostInfo::compute_function(member_var); \ 73 } \ 74 if (success) \ 75 result = &member_var; \ 76 } 77 78 void 79 HostInfoBase::Initialize() 80 { 81 g_fields = new HostInfoBaseFields(); 82 } 83 84 uint32_t 85 HostInfoBase::GetNumberCPUS() 86 { 87 static bool is_initialized = false; 88 if (!is_initialized) 89 { 90 g_fields->m_number_cpus = std::thread::hardware_concurrency(); 91 is_initialized = true; 92 } 93 94 return g_fields->m_number_cpus; 95 } 96 97 uint32_t 98 HostInfoBase::GetMaxThreadNameLength() 99 { 100 return 0; 101 } 102 103 llvm::StringRef 104 HostInfoBase::GetVendorString() 105 { 106 static bool is_initialized = false; 107 if (!is_initialized) 108 { 109 const ArchSpec &host_arch = HostInfo::GetArchitecture(); 110 const llvm::StringRef &str_ref = host_arch.GetTriple().getVendorName(); 111 g_fields->m_vendor_string.assign(str_ref.begin(), str_ref.end()); 112 is_initialized = true; 113 } 114 return g_fields->m_vendor_string; 115 } 116 117 llvm::StringRef 118 HostInfoBase::GetOSString() 119 { 120 static bool is_initialized = false; 121 if (!is_initialized) 122 { 123 const ArchSpec &host_arch = HostInfo::GetArchitecture(); 124 const llvm::StringRef &str_ref = host_arch.GetTriple().getOSName(); 125 g_fields->m_os_string.assign(str_ref.begin(), str_ref.end()); 126 is_initialized = true; 127 } 128 return g_fields->m_os_string; 129 } 130 131 llvm::StringRef 132 HostInfoBase::GetTargetTriple() 133 { 134 static bool is_initialized = false; 135 if (!is_initialized) 136 { 137 const ArchSpec &host_arch = HostInfo::GetArchitecture(); 138 g_fields->m_host_triple = host_arch.GetTriple().getTriple(); 139 is_initialized = true; 140 } 141 return g_fields->m_host_triple; 142 } 143 144 const ArchSpec & 145 HostInfoBase::GetArchitecture(ArchitectureKind arch_kind) 146 { 147 static bool is_initialized = false; 148 if (!is_initialized) 149 { 150 HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32, g_fields->m_host_arch_64); 151 is_initialized = true; 152 } 153 154 // If an explicit 32 or 64-bit architecture was requested, return that. 155 if (arch_kind == eArchKind32) 156 return g_fields->m_host_arch_32; 157 if (arch_kind == eArchKind64) 158 return g_fields->m_host_arch_64; 159 160 // Otherwise prefer the 64-bit architecture if it is valid. 161 return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64 : g_fields->m_host_arch_32; 162 } 163 164 bool 165 HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) 166 { 167 file_spec.Clear(); 168 169 #if defined(LLDB_DISABLE_PYTHON) 170 if (type == lldb::ePathTypePythonDir) 171 return false; 172 #endif 173 174 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 175 FileSpec *result = nullptr; 176 switch (type) 177 { 178 case lldb::ePathTypeLLDBShlibDir: 179 COMPUTE_LLDB_PATH(ComputeSharedLibraryDirectory, g_fields->m_lldb_so_dir) 180 if (log) 181 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", g_fields->m_lldb_so_dir.GetPath().c_str()); 182 break; 183 case lldb::ePathTypeSupportExecutableDir: 184 COMPUTE_LLDB_PATH(ComputeSupportExeDirectory, g_fields->m_lldb_support_exe_dir) 185 if (log) 186 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'", 187 g_fields->m_lldb_support_exe_dir.GetPath().c_str()); 188 break; 189 case lldb::ePathTypeHeaderDir: 190 COMPUTE_LLDB_PATH(ComputeHeaderDirectory, g_fields->m_lldb_headers_dir) 191 if (log) 192 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'", g_fields->m_lldb_headers_dir.GetPath().c_str()); 193 break; 194 case lldb::ePathTypePythonDir: 195 COMPUTE_LLDB_PATH(ComputePythonDirectory, g_fields->m_lldb_python_dir) 196 if (log) 197 log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'", g_fields->m_lldb_python_dir.GetPath().c_str()); 198 break; 199 case lldb::ePathTypeLLDBSystemPlugins: 200 COMPUTE_LLDB_PATH(ComputeSystemPluginsDirectory, g_fields->m_lldb_system_plugin_dir) 201 if (log) 202 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'", 203 g_fields->m_lldb_system_plugin_dir.GetPath().c_str()); 204 break; 205 case lldb::ePathTypeLLDBUserPlugins: 206 COMPUTE_LLDB_PATH(ComputeUserPluginsDirectory, g_fields->m_lldb_user_plugin_dir) 207 if (log) 208 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'", 209 g_fields->m_lldb_user_plugin_dir.GetPath().c_str()); 210 break; 211 case lldb::ePathTypeLLDBTempSystemDir: 212 COMPUTE_LLDB_PATH(ComputeTempFileDirectory, g_fields->m_lldb_tmp_dir) 213 if (log) 214 log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", g_fields->m_lldb_tmp_dir.GetPath().c_str()); 215 break; 216 } 217 218 if (!result) 219 return false; 220 file_spec = *result; 221 return true; 222 } 223 224 bool 225 HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) 226 { 227 // To get paths related to LLDB we get the path to the executable that 228 // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB", 229 // on linux this is assumed to be the "lldb" main executable. If LLDB on 230 // linux is actually in a shared library (liblldb.so) then this function will 231 // need to be modified to "do the right thing". 232 233 FileSpec lldb_file_spec( 234 Host::GetModuleFileSpecForHostAddress(reinterpret_cast<void *>(reinterpret_cast<intptr_t>(HostInfoBase::GetLLDBPath)))); 235 236 // Remove the filename so that this FileSpec only represents the directory. 237 file_spec.GetDirectory() = lldb_file_spec.GetDirectory(); 238 239 return (bool)file_spec.GetDirectory(); 240 } 241 242 bool 243 HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec) 244 { 245 return GetLLDBPath(lldb::ePathTypeLLDBShlibDir, file_spec); 246 } 247 248 bool 249 HostInfoBase::ComputeTempFileDirectory(FileSpec &file_spec) 250 { 251 const char *tmpdir_cstr = getenv("TMPDIR"); 252 if (tmpdir_cstr == NULL) 253 { 254 tmpdir_cstr = getenv("TMP"); 255 if (tmpdir_cstr == NULL) 256 tmpdir_cstr = getenv("TEMP"); 257 } 258 if (!tmpdir_cstr) 259 return false; 260 261 StreamString pid_tmpdir; 262 pid_tmpdir.Printf("%s/lldb", tmpdir_cstr); 263 if (!FileSystem::MakeDirectory(pid_tmpdir.GetString().c_str(), eFilePermissionsDirectoryDefault).Success()) 264 return false; 265 266 pid_tmpdir.Printf("/%" PRIu64, Host::GetCurrentProcessID()); 267 if (!FileSystem::MakeDirectory(pid_tmpdir.GetString().c_str(), eFilePermissionsDirectoryDefault).Success()) 268 return false; 269 270 // Make an atexit handler to clean up the process specify LLDB temp dir 271 // and all of its contents. 272 ::atexit(CleanupProcessSpecificLLDBTempDir); 273 file_spec.GetDirectory().SetCStringWithLength(pid_tmpdir.GetString().c_str(), pid_tmpdir.GetString().size()); 274 return true; 275 } 276 277 bool 278 HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec) 279 { 280 // TODO(zturner): Figure out how to compute the header directory for all platforms. 281 return false; 282 } 283 284 bool 285 HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec) 286 { 287 // TODO(zturner): Figure out how to compute the system plugins directory for all platforms. 288 return false; 289 } 290 291 bool 292 HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec) 293 { 294 // TODO(zturner): Figure out how to compute the user plugins directory for all platforms. 295 return false; 296 } 297 298 void 299 HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64) 300 { 301 llvm::Triple triple(llvm::sys::getDefaultTargetTriple()); 302 303 arch_32.Clear(); 304 arch_64.Clear(); 305 306 switch (triple.getArch()) 307 { 308 default: 309 arch_32.SetTriple(triple); 310 break; 311 312 case llvm::Triple::x86_64: 313 arch_64.SetTriple(triple); 314 arch_32.SetTriple(triple.get32BitArchVariant()); 315 break; 316 317 case llvm::Triple::aarch64: 318 case llvm::Triple::mips64: 319 case llvm::Triple::sparcv9: 320 case llvm::Triple::ppc64: 321 arch_64.SetTriple(triple); 322 break; 323 } 324 } 325