1 //===-- PlatformWindows.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 "PlatformWindows.h" 11 12 // C Includes 13 #include <stdio.h> 14 #if defined (_WIN32) 15 #include "lldb/Host/windows/windows.h" 16 #include <winsock2.h> 17 #endif 18 19 // C++ Includes 20 // Other libraries and framework includes 21 // Project includes 22 #include "lldb/Core/Error.h" 23 #include "lldb/Core/Debugger.h" 24 #include "lldb/Core/PluginManager.h" 25 #include "lldb/Host/HostInfo.h" 26 #include "lldb/Core/ModuleSpec.h" 27 #include "lldb/Core/Module.h" 28 #include "lldb/Breakpoint/BreakpointLocation.h" 29 30 using namespace lldb; 31 using namespace lldb_private; 32 33 static uint32_t g_initialize_count = 0; 34 35 namespace 36 { 37 class SupportedArchList 38 { 39 public: 40 SupportedArchList() 41 { 42 AddArch(ArchSpec("i686-pc-windows")); 43 AddArch(HostInfo::GetArchitecture(HostInfo::eArchKindDefault)); 44 AddArch(HostInfo::GetArchitecture(HostInfo::eArchKind32)); 45 AddArch(HostInfo::GetArchitecture(HostInfo::eArchKind64)); 46 AddArch(ArchSpec("i386-pc-windows")); 47 } 48 49 size_t Count() const { return m_archs.size(); } 50 51 const ArchSpec& operator[](int idx) { return m_archs[idx]; } 52 53 private: 54 void AddArch(const ArchSpec& spec) 55 { 56 auto iter = std::find_if( 57 m_archs.begin(), m_archs.end(), 58 [spec](const ArchSpec& rhs) { return spec.IsExactMatch(rhs); }); 59 if (iter != m_archs.end()) 60 return; 61 if (spec.IsValid()) 62 m_archs.push_back(spec); 63 } 64 65 std::vector<ArchSpec> m_archs; 66 }; 67 } 68 69 PlatformSP 70 PlatformWindows::CreateInstance (bool force, const lldb_private::ArchSpec *arch) 71 { 72 // The only time we create an instance is when we are creating a remote 73 // windows platform 74 const bool is_host = false; 75 76 bool create = force; 77 if (create == false && arch && arch->IsValid()) 78 { 79 const llvm::Triple &triple = arch->GetTriple(); 80 switch (triple.getVendor()) 81 { 82 case llvm::Triple::PC: 83 create = true; 84 break; 85 86 case llvm::Triple::UnknownArch: 87 create = !arch->TripleVendorWasSpecified(); 88 break; 89 90 default: 91 break; 92 } 93 94 if (create) 95 { 96 switch (triple.getOS()) 97 { 98 case llvm::Triple::Win32: 99 break; 100 101 case llvm::Triple::UnknownOS: 102 create = arch->TripleOSWasSpecified(); 103 break; 104 105 default: 106 create = false; 107 break; 108 } 109 } 110 } 111 if (create) 112 return PlatformSP(new PlatformWindows (is_host)); 113 return PlatformSP(); 114 115 } 116 117 lldb_private::ConstString 118 PlatformWindows::GetPluginNameStatic(bool is_host) 119 { 120 if (is_host) 121 { 122 static ConstString g_host_name(Platform::GetHostPlatformName ()); 123 return g_host_name; 124 } 125 else 126 { 127 static ConstString g_remote_name("remote-windows"); 128 return g_remote_name; 129 } 130 } 131 132 const char * 133 PlatformWindows::GetPluginDescriptionStatic(bool is_host) 134 { 135 return is_host ? 136 "Local Windows user platform plug-in." : 137 "Remote Windows user platform plug-in."; 138 } 139 140 lldb_private::ConstString 141 PlatformWindows::GetPluginName(void) 142 { 143 return GetPluginNameStatic(IsHost()); 144 } 145 146 void 147 PlatformWindows::Initialize(void) 148 { 149 if (g_initialize_count++ == 0) 150 { 151 #if defined (_WIN32) 152 WSADATA dummy; 153 WSAStartup(MAKEWORD(2,2), &dummy); 154 // Force a host flag to true for the default platform object. 155 PlatformSP default_platform_sp (new PlatformWindows(true)); 156 default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); 157 Platform::SetHostPlatform (default_platform_sp); 158 #endif 159 PluginManager::RegisterPlugin(PlatformWindows::GetPluginNameStatic(false), 160 PlatformWindows::GetPluginDescriptionStatic(false), 161 PlatformWindows::CreateInstance); 162 } 163 } 164 165 void 166 PlatformWindows::Terminate( void ) 167 { 168 if (g_initialize_count > 0) 169 { 170 if (--g_initialize_count == 0) 171 { 172 #ifdef _WIN32 173 WSACleanup(); 174 #endif 175 PluginManager::UnregisterPlugin (PlatformWindows::CreateInstance); 176 } 177 } 178 } 179 180 //------------------------------------------------------------------ 181 /// Default Constructor 182 //------------------------------------------------------------------ 183 PlatformWindows::PlatformWindows (bool is_host) : 184 Platform(is_host) 185 { 186 } 187 188 //------------------------------------------------------------------ 189 /// Destructor. 190 /// 191 /// The destructor is virtual since this class is designed to be 192 /// inherited from by the plug-in instance. 193 //------------------------------------------------------------------ 194 PlatformWindows::~PlatformWindows() 195 { 196 } 197 198 Error 199 PlatformWindows::ResolveExecutable (const ModuleSpec &ms, 200 lldb::ModuleSP &exe_module_sp, 201 const FileSpecList *module_search_paths_ptr) 202 { 203 Error error; 204 // Nothing special to do here, just use the actual file and architecture 205 206 char exe_path[PATH_MAX]; 207 ModuleSpec resolved_module_spec(ms); 208 209 if (IsHost()) 210 { 211 // if we cant resolve the executable loation based on the current path variables 212 if (!resolved_module_spec.GetFileSpec().Exists()) 213 { 214 resolved_module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path)); 215 resolved_module_spec.GetFileSpec().SetFile(exe_path, true); 216 } 217 218 if (!resolved_module_spec.GetFileSpec().Exists()) 219 resolved_module_spec.GetFileSpec().ResolveExecutableLocation (); 220 221 if (resolved_module_spec.GetFileSpec().Exists()) 222 error.Clear(); 223 else 224 { 225 ms.GetFileSpec().GetPath(exe_path, sizeof(exe_path)); 226 error.SetErrorStringWithFormat("unable to find executable for '%s'", exe_path); 227 } 228 } 229 else 230 { 231 if (m_remote_platform_sp) 232 { 233 error = m_remote_platform_sp->ResolveExecutable (ms, 234 exe_module_sp, 235 NULL); 236 } 237 else 238 { 239 // We may connect to a process and use the provided executable (Don't use local $PATH). 240 if (resolved_module_spec.GetFileSpec().Exists()) 241 error.Clear(); 242 else 243 error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", exe_path); 244 } 245 } 246 247 if (error.Success()) 248 { 249 if (resolved_module_spec.GetArchitecture().IsValid()) 250 { 251 error = ModuleList::GetSharedModule (resolved_module_spec, 252 exe_module_sp, 253 NULL, 254 NULL, 255 NULL); 256 257 if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL) 258 { 259 exe_module_sp.reset(); 260 error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s", 261 resolved_module_spec.GetFileSpec().GetPath().c_str(), 262 resolved_module_spec.GetArchitecture().GetArchitectureName()); 263 } 264 } 265 else 266 { 267 // No valid architecture was specified, ask the platform for 268 // the architectures that we should be using (in the correct order) 269 // and see if we can find a match that way 270 StreamString arch_names; 271 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx) 272 { 273 error = ModuleList::GetSharedModule (resolved_module_spec, 274 exe_module_sp, 275 NULL, 276 NULL, 277 NULL); 278 // Did we find an executable using one of the 279 if (error.Success()) 280 { 281 if (exe_module_sp && exe_module_sp->GetObjectFile()) 282 break; 283 else 284 error.SetErrorToGenericError(); 285 } 286 287 if (idx > 0) 288 arch_names.PutCString (", "); 289 arch_names.PutCString (resolved_module_spec.GetArchitecture().GetArchitectureName()); 290 } 291 292 if (error.Fail() || !exe_module_sp) 293 { 294 if (resolved_module_spec.GetFileSpec().Readable()) 295 { 296 error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s", 297 resolved_module_spec.GetFileSpec().GetPath().c_str(), 298 GetPluginName().GetCString(), 299 arch_names.GetString().c_str()); 300 } 301 else 302 { 303 error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str()); 304 } 305 } 306 } 307 } 308 309 return error; 310 } 311 312 size_t 313 PlatformWindows::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site) 314 { 315 ArchSpec arch = target.GetArchitecture(); 316 const uint8_t *trap_opcode = NULL; 317 size_t trap_opcode_size = 0; 318 319 switch (arch.GetMachine()) 320 { 321 case llvm::Triple::x86: 322 case llvm::Triple::x86_64: 323 { 324 static const uint8_t g_i386_opcode[] = { 0xCC }; 325 trap_opcode = g_i386_opcode; 326 trap_opcode_size = sizeof(g_i386_opcode); 327 } 328 break; 329 330 case llvm::Triple::hexagon: 331 { 332 static const uint8_t g_hex_opcode[] = { 0x0c, 0xdb, 0x00, 0x54 }; 333 trap_opcode = g_hex_opcode; 334 trap_opcode_size = sizeof(g_hex_opcode); 335 } 336 break; 337 default: 338 llvm_unreachable("Unhandled architecture in PlatformWindows::GetSoftwareBreakpointTrapOpcode()"); 339 break; 340 } 341 342 if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size)) 343 return trap_opcode_size; 344 345 return 0; 346 } 347 348 bool 349 PlatformWindows::GetRemoteOSVersion () 350 { 351 if (m_remote_platform_sp) 352 return m_remote_platform_sp->GetOSVersion (m_major_os_version, 353 m_minor_os_version, 354 m_update_os_version); 355 return false; 356 } 357 358 bool 359 PlatformWindows::GetRemoteOSBuildString (std::string &s) 360 { 361 if (m_remote_platform_sp) 362 return m_remote_platform_sp->GetRemoteOSBuildString (s); 363 s.clear(); 364 return false; 365 } 366 367 bool 368 PlatformWindows::GetRemoteOSKernelDescription (std::string &s) 369 { 370 if (m_remote_platform_sp) 371 return m_remote_platform_sp->GetRemoteOSKernelDescription (s); 372 s.clear(); 373 return false; 374 } 375 376 // Remote Platform subclasses need to override this function 377 ArchSpec 378 PlatformWindows::GetRemoteSystemArchitecture () 379 { 380 if (m_remote_platform_sp) 381 return m_remote_platform_sp->GetRemoteSystemArchitecture (); 382 return ArchSpec(); 383 } 384 385 const char * 386 PlatformWindows::GetHostname () 387 { 388 if (IsHost()) 389 return Platform::GetHostname(); 390 391 if (m_remote_platform_sp) 392 return m_remote_platform_sp->GetHostname (); 393 return NULL; 394 } 395 396 bool 397 PlatformWindows::IsConnected () const 398 { 399 if (IsHost()) 400 return true; 401 else if (m_remote_platform_sp) 402 return m_remote_platform_sp->IsConnected(); 403 return false; 404 } 405 406 Error 407 PlatformWindows::ConnectRemote (Args& args) 408 { 409 Error error; 410 if (IsHost()) 411 { 412 error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().AsCString() ); 413 } 414 else 415 { 416 if (!m_remote_platform_sp) 417 m_remote_platform_sp = Platform::Create (ConstString("remote-gdb-server"), error); 418 419 if (m_remote_platform_sp) 420 { 421 if (error.Success()) 422 { 423 if (m_remote_platform_sp) 424 { 425 error = m_remote_platform_sp->ConnectRemote (args); 426 } 427 else 428 { 429 error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>"); 430 } 431 } 432 } 433 else 434 error.SetErrorString ("failed to create a 'remote-gdb-server' platform"); 435 436 if (error.Fail()) 437 m_remote_platform_sp.reset(); 438 } 439 440 return error; 441 } 442 443 Error 444 PlatformWindows::DisconnectRemote () 445 { 446 Error error; 447 448 if (IsHost()) 449 { 450 error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetPluginName().AsCString() ); 451 } 452 else 453 { 454 if (m_remote_platform_sp) 455 error = m_remote_platform_sp->DisconnectRemote (); 456 else 457 error.SetErrorString ("the platform is not currently connected"); 458 } 459 return error; 460 } 461 462 bool 463 PlatformWindows::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 464 { 465 bool success = false; 466 if (IsHost()) 467 { 468 success = Platform::GetProcessInfo (pid, process_info); 469 } 470 else if (m_remote_platform_sp) 471 { 472 success = m_remote_platform_sp->GetProcessInfo (pid, process_info); 473 } 474 return success; 475 } 476 477 uint32_t 478 PlatformWindows::FindProcesses (const ProcessInstanceInfoMatch &match_info, 479 ProcessInstanceInfoList &process_infos) 480 { 481 uint32_t match_count = 0; 482 if (IsHost()) 483 { 484 // Let the base class figure out the host details 485 match_count = Platform::FindProcesses (match_info, process_infos); 486 } 487 else 488 { 489 // If we are remote, we can only return results if we are connected 490 if (m_remote_platform_sp) 491 match_count = m_remote_platform_sp->FindProcesses (match_info, process_infos); 492 } 493 return match_count; 494 } 495 496 Error 497 PlatformWindows::LaunchProcess (ProcessLaunchInfo &launch_info) 498 { 499 Error error; 500 if (IsHost()) 501 { 502 error = Platform::LaunchProcess (launch_info); 503 } 504 else 505 { 506 if (m_remote_platform_sp) 507 error = m_remote_platform_sp->LaunchProcess (launch_info); 508 else 509 error.SetErrorString ("the platform is not currently connected"); 510 } 511 return error; 512 } 513 514 lldb::ProcessSP 515 PlatformWindows::Attach(ProcessAttachInfo &attach_info, 516 Debugger &debugger, 517 Target *target, 518 Error &error) 519 { 520 lldb::ProcessSP process_sp; 521 if (IsHost()) 522 { 523 if (target == NULL) 524 { 525 TargetSP new_target_sp; 526 FileSpec emptyFileSpec; 527 ArchSpec emptyArchSpec; 528 529 error = debugger.GetTargetList().CreateTarget (debugger, 530 NULL, 531 NULL, 532 false, 533 NULL, 534 new_target_sp); 535 target = new_target_sp.get(); 536 } 537 else 538 error.Clear(); 539 540 if (target && error.Success()) 541 { 542 debugger.GetTargetList().SetSelectedTarget(target); 543 // The Windows platform always currently uses the GDB remote debugger plug-in 544 // so even when debugging locally we are debugging remotely! 545 // Just like the darwin plugin. 546 process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL); 547 548 if (process_sp) 549 error = process_sp->Attach (attach_info); 550 } 551 } 552 else 553 { 554 if (m_remote_platform_sp) 555 process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, error); 556 else 557 error.SetErrorString ("the platform is not currently connected"); 558 } 559 return process_sp; 560 } 561 562 const char * 563 PlatformWindows::GetUserName (uint32_t uid) 564 { 565 // Check the cache in Platform in case we have already looked this uid up 566 const char *user_name = Platform::GetUserName(uid); 567 if (user_name) 568 return user_name; 569 570 if (IsRemote() && m_remote_platform_sp) 571 return m_remote_platform_sp->GetUserName(uid); 572 return NULL; 573 } 574 575 const char * 576 PlatformWindows::GetGroupName (uint32_t gid) 577 { 578 const char *group_name = Platform::GetGroupName(gid); 579 if (group_name) 580 return group_name; 581 582 if (IsRemote() && m_remote_platform_sp) 583 return m_remote_platform_sp->GetGroupName(gid); 584 return NULL; 585 } 586 587 Error 588 PlatformWindows::GetFileWithUUID (const FileSpec &platform_file, 589 const UUID *uuid_ptr, 590 FileSpec &local_file) 591 { 592 if (IsRemote()) 593 { 594 if (m_remote_platform_sp) 595 return m_remote_platform_sp->GetFileWithUUID (platform_file, uuid_ptr, local_file); 596 } 597 598 // Default to the local case 599 local_file = platform_file; 600 return Error(); 601 } 602 603 Error 604 PlatformWindows::GetSharedModule (const ModuleSpec &module_spec, 605 ModuleSP &module_sp, 606 const FileSpecList *module_search_paths_ptr, 607 ModuleSP *old_module_sp_ptr, 608 bool *did_create_ptr) 609 { 610 Error error; 611 module_sp.reset(); 612 613 if (IsRemote()) 614 { 615 // If we have a remote platform always, let it try and locate 616 // the shared module first. 617 if (m_remote_platform_sp) 618 { 619 error = m_remote_platform_sp->GetSharedModule (module_spec, 620 module_sp, 621 module_search_paths_ptr, 622 old_module_sp_ptr, 623 did_create_ptr); 624 } 625 } 626 627 if (!module_sp) 628 { 629 // Fall back to the local platform and find the file locally 630 error = Platform::GetSharedModule (module_spec, 631 module_sp, 632 module_search_paths_ptr, 633 old_module_sp_ptr, 634 did_create_ptr); 635 } 636 if (module_sp) 637 module_sp->SetPlatformFileSpec(module_spec.GetFileSpec()); 638 return error; 639 } 640 641 bool 642 PlatformWindows::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) 643 { 644 static SupportedArchList architectures; 645 646 if (idx >= architectures.Count()) 647 return false; 648 arch = architectures[idx]; 649 return true; 650 } 651 652 void 653 PlatformWindows::GetStatus (Stream &strm) 654 { 655 Platform::GetStatus(strm); 656 657 #ifdef _WIN32 658 uint32_t major; 659 uint32_t minor; 660 uint32_t update; 661 if (!HostInfo::GetOSVersion(major, minor, update)) 662 { 663 strm << "Windows"; 664 return; 665 } 666 667 strm << "Host: Windows " << major 668 << '.' << minor 669 << " Build: " << update << '\n'; 670 #endif 671 } 672