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(true); 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::GetFile (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->GetFile (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 { 394 static const uint8_t g_i386_breakpoint_opcode[] = { 0xCC }; 395 trap_opcode = g_i386_breakpoint_opcode; 396 trap_opcode_size = sizeof(g_i386_breakpoint_opcode); 397 } 398 break; 399 } 400 401 if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size)) 402 return trap_opcode_size; 403 return 0; 404 } 405 406 Error 407 PlatformLinux::LaunchProcess (ProcessLaunchInfo &launch_info) 408 { 409 Error error; 410 411 if (IsHost()) 412 { 413 if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell)) 414 { 415 const bool is_localhost = true; 416 const bool will_debug = launch_info.GetFlags().Test(eLaunchFlagDebug); 417 const bool first_arg_is_full_shell_command = false; 418 uint32_t num_resumes = GetResumeCountForLaunchInfo (launch_info); 419 if (!launch_info.ConvertArgumentsForLaunchingInShell (error, 420 is_localhost, 421 will_debug, 422 first_arg_is_full_shell_command, 423 num_resumes)) 424 return error; 425 } 426 error = Platform::LaunchProcess (launch_info); 427 } 428 else 429 { 430 error.SetErrorString ("the platform is not currently connected"); 431 } 432 return error; 433 } 434 435 lldb::ProcessSP 436 PlatformLinux::Attach(ProcessAttachInfo &attach_info, 437 Debugger &debugger, 438 Target *target, 439 Listener &listener, 440 Error &error) 441 { 442 lldb::ProcessSP process_sp; 443 if (IsHost()) 444 { 445 if (target == NULL) 446 { 447 TargetSP new_target_sp; 448 ArchSpec emptyArchSpec; 449 450 error = debugger.GetTargetList().CreateTarget (debugger, 451 NULL, 452 emptyArchSpec, 453 false, 454 m_remote_platform_sp, 455 new_target_sp); 456 target = new_target_sp.get(); 457 } 458 else 459 error.Clear(); 460 461 if (target && error.Success()) 462 { 463 debugger.GetTargetList().SetSelectedTarget(target); 464 465 process_sp = target->CreateProcess (listener, 466 attach_info.GetProcessPluginName(), 467 NULL); 468 469 if (process_sp) 470 error = process_sp->Attach (attach_info); 471 } 472 } 473 else 474 { 475 if (m_remote_platform_sp) 476 process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error); 477 else 478 error.SetErrorString ("the platform is not currently connected"); 479 } 480 return process_sp; 481 } 482