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