1 //===-- PlatformLinux.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/lldb-python.h" 11 12 #include "PlatformLinux.h" 13 #include "lldb/Host/Config.h" 14 15 // C Includes 16 #include <stdio.h> 17 #ifndef LLDB_DISABLE_POSIX 18 #include <sys/utsname.h> 19 #endif 20 21 // C++ Includes 22 // Other libraries and framework includes 23 // Project includes 24 #include "lldb/Core/Error.h" 25 #include "lldb/Core/Debugger.h" 26 #include "lldb/Core/Module.h" 27 #include "lldb/Core/ModuleList.h" 28 #include "lldb/Core/ModuleSpec.h" 29 #include "lldb/Core/PluginManager.h" 30 #include "lldb/Core/StreamString.h" 31 #include "lldb/Host/FileSpec.h" 32 #include "lldb/Host/Host.h" 33 #include "lldb/Target/Target.h" 34 #include "lldb/Target/Process.h" 35 36 using namespace lldb; 37 using namespace lldb_private; 38 39 static uint32_t g_initialize_count = 0; 40 41 Platform * 42 PlatformLinux::CreateInstance (bool force, const ArchSpec *arch) 43 { 44 bool create = force; 45 if (create == false && arch && arch->IsValid()) 46 { 47 const llvm::Triple &triple = arch->GetTriple(); 48 switch (triple.getVendor()) 49 { 50 case llvm::Triple::PC: 51 create = true; 52 break; 53 54 #if defined(__linux__) 55 // Only accept "unknown" for the vendor if the host is linux and 56 // it "unknown" wasn't specified (it was just returned becasue it 57 // was NOT specified_ 58 case llvm::Triple::UnknownArch: 59 create = !arch->TripleVendorWasSpecified(); 60 break; 61 #endif 62 default: 63 break; 64 } 65 66 if (create) 67 { 68 switch (triple.getOS()) 69 { 70 case llvm::Triple::Linux: 71 break; 72 73 #if defined(__linux__) 74 // Only accept "unknown" for the OS if the host is linux and 75 // it "unknown" wasn't specified (it was just returned becasue it 76 // was NOT specified) 77 case llvm::Triple::UnknownOS: 78 create = !arch->TripleOSWasSpecified(); 79 break; 80 #endif 81 default: 82 create = false; 83 break; 84 } 85 } 86 } 87 if (create) 88 return new PlatformLinux(false); 89 return NULL; 90 } 91 92 93 lldb_private::ConstString 94 PlatformLinux::GetPluginNameStatic (bool is_host) 95 { 96 if (is_host) 97 { 98 static ConstString g_host_name(Platform::GetHostPlatformName ()); 99 return g_host_name; 100 } 101 else 102 { 103 static ConstString g_remote_name("remote-linux"); 104 return g_remote_name; 105 } 106 } 107 108 const char * 109 PlatformLinux::GetPluginDescriptionStatic (bool is_host) 110 { 111 if (is_host) 112 return "Local Linux user platform plug-in."; 113 else 114 return "Remote Linux user platform plug-in."; 115 } 116 117 lldb_private::ConstString 118 PlatformLinux::GetPluginName() 119 { 120 return GetPluginNameStatic(IsHost()); 121 } 122 123 void 124 PlatformLinux::Initialize () 125 { 126 if (g_initialize_count++ == 0) 127 { 128 #if defined(__linux__) 129 PlatformSP default_platform_sp (new PlatformLinux(true)); 130 default_platform_sp->SetSystemArchitecture (Host::GetArchitecture()); 131 Platform::SetDefaultPlatform (default_platform_sp); 132 #endif 133 PluginManager::RegisterPlugin(PlatformLinux::GetPluginNameStatic(false), 134 PlatformLinux::GetPluginDescriptionStatic(false), 135 PlatformLinux::CreateInstance); 136 } 137 } 138 139 void 140 PlatformLinux::Terminate () 141 { 142 if (g_initialize_count > 0) 143 { 144 if (--g_initialize_count == 0) 145 { 146 PluginManager::UnregisterPlugin (PlatformLinux::CreateInstance); 147 } 148 } 149 } 150 151 Error 152 PlatformLinux::ResolveExecutable (const FileSpec &exe_file, 153 const ArchSpec &exe_arch, 154 lldb::ModuleSP &exe_module_sp, 155 const FileSpecList *module_search_paths_ptr) 156 { 157 Error error; 158 // Nothing special to do here, just use the actual file and architecture 159 160 char exe_path[PATH_MAX]; 161 FileSpec resolved_exe_file (exe_file); 162 163 if (IsHost()) 164 { 165 // If we have "ls" as the exe_file, resolve the executable location based on 166 // the current path variables 167 if (!resolved_exe_file.Exists()) 168 { 169 exe_file.GetPath(exe_path, sizeof(exe_path)); 170 resolved_exe_file.SetFile(exe_path, true); 171 } 172 173 if (!resolved_exe_file.Exists()) 174 resolved_exe_file.ResolveExecutableLocation (); 175 176 if (resolved_exe_file.Exists()) 177 error.Clear(); 178 else 179 { 180 exe_file.GetPath(exe_path, sizeof(exe_path)); 181 error.SetErrorStringWithFormat("unable to find executable for '%s'", exe_path); 182 } 183 } 184 else 185 { 186 if (m_remote_platform_sp) 187 { 188 error = m_remote_platform_sp->ResolveExecutable (exe_file, 189 exe_arch, 190 exe_module_sp, 191 NULL); 192 } 193 else 194 { 195 // We may connect to a process and use the provided executable (Don't use local $PATH). 196 197 if (resolved_exe_file.Exists()) 198 error.Clear(); 199 else 200 error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", exe_path); 201 } 202 } 203 204 if (error.Success()) 205 { 206 ModuleSpec module_spec (resolved_exe_file, exe_arch); 207 if (exe_arch.IsValid()) 208 { 209 error = ModuleList::GetSharedModule (module_spec, 210 exe_module_sp, 211 NULL, 212 NULL, 213 NULL); 214 if (error.Fail()) 215 { 216 // If we failed, it may be because the vendor and os aren't known. If that is the 217 // case, try setting them to the host architecture and give it another try. 218 llvm::Triple &module_triple = module_spec.GetArchitecture().GetTriple(); 219 bool is_vendor_specified = (module_triple.getVendor() != llvm::Triple::UnknownVendor); 220 bool is_os_specified = (module_triple.getOS() != llvm::Triple::UnknownOS); 221 if (!is_vendor_specified || !is_os_specified) 222 { 223 const llvm::Triple &host_triple = Host::GetArchitecture (Host::eSystemDefaultArchitecture).GetTriple(); 224 225 if (!is_vendor_specified) 226 module_triple.setVendorName (host_triple.getVendorName()); 227 if (!is_os_specified) 228 module_triple.setOSName (host_triple.getOSName()); 229 230 error = ModuleList::GetSharedModule (module_spec, 231 exe_module_sp, 232 NULL, 233 NULL, 234 NULL); 235 } 236 } 237 238 // TODO find out why exe_module_sp might be NULL 239 if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL) 240 { 241 exe_module_sp.reset(); 242 error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s", 243 exe_file.GetPath().c_str(), 244 exe_arch.GetArchitectureName()); 245 } 246 } 247 else 248 { 249 // No valid architecture was specified, ask the platform for 250 // the architectures that we should be using (in the correct order) 251 // and see if we can find a match that way 252 StreamString arch_names; 253 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, module_spec.GetArchitecture()); ++idx) 254 { 255 error = ModuleList::GetSharedModule (module_spec, 256 exe_module_sp, 257 NULL, 258 NULL, 259 NULL); 260 // Did we find an executable using one of the 261 if (error.Success()) 262 { 263 if (exe_module_sp && exe_module_sp->GetObjectFile()) 264 break; 265 else 266 error.SetErrorToGenericError(); 267 } 268 269 if (idx > 0) 270 arch_names.PutCString (", "); 271 arch_names.PutCString (module_spec.GetArchitecture().GetArchitectureName()); 272 } 273 274 if (error.Fail() || !exe_module_sp) 275 { 276 error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s", 277 exe_file.GetPath().c_str(), 278 GetPluginName().GetCString(), 279 arch_names.GetString().c_str()); 280 } 281 } 282 } 283 284 return error; 285 } 286 287 Error 288 PlatformLinux::GetFileWithUUID (const FileSpec &platform_file, 289 const UUID *uuid_ptr, FileSpec &local_file) 290 { 291 if (IsRemote()) 292 { 293 if (m_remote_platform_sp) 294 return m_remote_platform_sp->GetFileWithUUID (platform_file, uuid_ptr, local_file); 295 } 296 297 // Default to the local case 298 local_file = platform_file; 299 return Error(); 300 } 301 302 303 //------------------------------------------------------------------ 304 /// Default Constructor 305 //------------------------------------------------------------------ 306 PlatformLinux::PlatformLinux (bool is_host) : 307 Platform(is_host), // This is the local host platform 308 m_remote_platform_sp () 309 { 310 } 311 312 //------------------------------------------------------------------ 313 /// Destructor. 314 /// 315 /// The destructor is virtual since this class is designed to be 316 /// inherited from by the plug-in instance. 317 //------------------------------------------------------------------ 318 PlatformLinux::~PlatformLinux() 319 { 320 } 321 322 bool 323 PlatformLinux::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 324 { 325 bool success = false; 326 if (IsHost()) 327 { 328 success = Platform::GetProcessInfo (pid, process_info); 329 } 330 else 331 { 332 if (m_remote_platform_sp) 333 success = m_remote_platform_sp->GetProcessInfo (pid, process_info); 334 } 335 return success; 336 } 337 338 bool 339 PlatformLinux::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) 340 { 341 if (idx == 0) 342 { 343 arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture); 344 return arch.IsValid(); 345 } 346 else if (idx == 1) 347 { 348 // If the default host architecture is 64-bit, look for a 32-bit variant 349 ArchSpec hostArch 350 = Host::GetArchitecture(Host::eSystemDefaultArchitecture); 351 if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit()) 352 { 353 arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture32); 354 return arch.IsValid(); 355 } 356 } 357 return false; 358 } 359 360 void 361 PlatformLinux::GetStatus (Stream &strm) 362 { 363 Platform::GetStatus(strm); 364 365 #ifndef LLDB_DISABLE_POSIX 366 struct utsname un; 367 368 if (uname(&un)) 369 return; 370 371 strm.Printf (" Kernel: %s\n", un.sysname); 372 strm.Printf (" Release: %s\n", un.release); 373 strm.Printf (" Version: %s\n", un.version); 374 #endif 375 } 376 377 size_t 378 PlatformLinux::GetSoftwareBreakpointTrapOpcode (Target &target, 379 BreakpointSite *bp_site) 380 { 381 ArchSpec arch = target.GetArchitecture(); 382 const uint8_t *trap_opcode = NULL; 383 size_t trap_opcode_size = 0; 384 385 switch (arch.GetCore()) 386 { 387 default: 388 assert(false && "CPU type not supported!"); 389 break; 390 391 case ArchSpec::eCore_x86_32_i386: 392 case ArchSpec::eCore_x86_64_x86_64: 393 case ArchSpec::eCore_x86_64_x86_64h: 394 { 395 static const uint8_t g_i386_breakpoint_opcode[] = { 0xCC }; 396 trap_opcode = g_i386_breakpoint_opcode; 397 trap_opcode_size = sizeof(g_i386_breakpoint_opcode); 398 } 399 break; 400 case ArchSpec::eCore_hexagon_generic: 401 return 0; 402 } 403 404 if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size)) 405 return trap_opcode_size; 406 return 0; 407 } 408 409 Error 410 PlatformLinux::LaunchProcess (ProcessLaunchInfo &launch_info) 411 { 412 Error error; 413 414 if (IsHost()) 415 { 416 if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell)) 417 { 418 const bool is_localhost = true; 419 const bool will_debug = launch_info.GetFlags().Test(eLaunchFlagDebug); 420 const bool first_arg_is_full_shell_command = false; 421 uint32_t num_resumes = GetResumeCountForLaunchInfo (launch_info); 422 if (!launch_info.ConvertArgumentsForLaunchingInShell (error, 423 is_localhost, 424 will_debug, 425 first_arg_is_full_shell_command, 426 num_resumes)) 427 return error; 428 } 429 error = Platform::LaunchProcess (launch_info); 430 } 431 else 432 { 433 error.SetErrorString ("the platform is not currently connected"); 434 } 435 return error; 436 } 437 438 lldb::ProcessSP 439 PlatformLinux::Attach(ProcessAttachInfo &attach_info, 440 Debugger &debugger, 441 Target *target, 442 Listener &listener, 443 Error &error) 444 { 445 lldb::ProcessSP process_sp; 446 if (IsHost()) 447 { 448 if (target == NULL) 449 { 450 TargetSP new_target_sp; 451 ArchSpec emptyArchSpec; 452 453 error = debugger.GetTargetList().CreateTarget (debugger, 454 NULL, 455 emptyArchSpec, 456 false, 457 m_remote_platform_sp, 458 new_target_sp); 459 target = new_target_sp.get(); 460 } 461 else 462 error.Clear(); 463 464 if (target && error.Success()) 465 { 466 debugger.GetTargetList().SetSelectedTarget(target); 467 468 process_sp = target->CreateProcess (listener, 469 attach_info.GetProcessPluginName(), 470 NULL); 471 472 if (process_sp) 473 error = process_sp->Attach (attach_info); 474 } 475 } 476 else 477 { 478 if (m_remote_platform_sp) 479 process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error); 480 else 481 error.SetErrorString ("the platform is not currently connected"); 482 } 483 return process_sp; 484 } 485 486 void 487 PlatformLinux::CalculateTrapHandlerSymbolNames () 488 { 489 m_trap_handlers.push_back (ConstString ("_sigtramp")); 490 } 491