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