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