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/Module.h" 26 #include "lldb/Core/ModuleSpec.h" 27 #include "lldb/Core/PluginManager.h" 28 #include "lldb/Host/HostInfo.h" 29 #include "lldb/Target/Process.h" 30 #include "lldb/Utility/Status.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::UnknownVendor: 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 Status PlatformWindows::ResolveExecutable( 184 const ModuleSpec &ms, lldb::ModuleSP &exe_module_sp, 185 const FileSpecList *module_search_paths_ptr) { 186 Status 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 (!FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) { 196 resolved_module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path)); 197 resolved_module_spec.GetFileSpec().SetFile(exe_path, 198 FileSpec::Style::native); 199 FileSystem::Instance().Resolve(resolved_module_spec.GetFileSpec()); 200 } 201 202 if (!FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) 203 FileSystem::Instance().ResolveExecutableLocation( 204 resolved_module_spec.GetFileSpec()); 205 206 if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) 207 error.Clear(); 208 else { 209 ms.GetFileSpec().GetPath(exe_path, sizeof(exe_path)); 210 error.SetErrorStringWithFormat("unable to find executable for '%s'", 211 exe_path); 212 } 213 } else { 214 if (m_remote_platform_sp) { 215 error = GetCachedExecutable(resolved_module_spec, exe_module_sp, nullptr, 216 *m_remote_platform_sp); 217 } else { 218 // We may connect to a process and use the provided executable (Don't use 219 // local $PATH). 220 if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) 221 error.Clear(); 222 else 223 error.SetErrorStringWithFormat("the platform is not currently " 224 "connected, and '%s' doesn't exist in " 225 "the system root.", 226 exe_path); 227 } 228 } 229 230 if (error.Success()) { 231 if (resolved_module_spec.GetArchitecture().IsValid()) { 232 error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, 233 nullptr, nullptr, nullptr); 234 235 if (!exe_module_sp || exe_module_sp->GetObjectFile() == nullptr) { 236 exe_module_sp.reset(); 237 error.SetErrorStringWithFormat( 238 "'%s' doesn't contain the architecture %s", 239 resolved_module_spec.GetFileSpec().GetPath().c_str(), 240 resolved_module_spec.GetArchitecture().GetArchitectureName()); 241 } 242 } else { 243 // No valid architecture was specified, ask the platform for the 244 // architectures that we should be using (in the correct order) and see 245 // if we can find a match that way 246 StreamString arch_names; 247 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex( 248 idx, resolved_module_spec.GetArchitecture()); 249 ++idx) { 250 error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, 251 nullptr, nullptr, nullptr); 252 // Did we find an executable using one of the 253 if (error.Success()) { 254 if (exe_module_sp && exe_module_sp->GetObjectFile()) 255 break; 256 else 257 error.SetErrorToGenericError(); 258 } 259 260 if (idx > 0) 261 arch_names.PutCString(", "); 262 arch_names.PutCString( 263 resolved_module_spec.GetArchitecture().GetArchitectureName()); 264 } 265 266 if (error.Fail() || !exe_module_sp) { 267 if (FileSystem::Instance().Readable( 268 resolved_module_spec.GetFileSpec())) { 269 error.SetErrorStringWithFormat( 270 "'%s' doesn't contain any '%s' platform architectures: %s", 271 resolved_module_spec.GetFileSpec().GetPath().c_str(), 272 GetPluginName().GetCString(), arch_names.GetData()); 273 } else { 274 error.SetErrorStringWithFormat( 275 "'%s' is not readable", 276 resolved_module_spec.GetFileSpec().GetPath().c_str()); 277 } 278 } 279 } 280 } 281 282 return error; 283 } 284 285 bool PlatformWindows::GetRemoteOSVersion() { 286 if (m_remote_platform_sp) { 287 m_os_version = m_remote_platform_sp->GetOSVersion(); 288 return !m_os_version.empty(); 289 } 290 return false; 291 } 292 293 bool PlatformWindows::GetRemoteOSBuildString(std::string &s) { 294 if (m_remote_platform_sp) 295 return m_remote_platform_sp->GetRemoteOSBuildString(s); 296 s.clear(); 297 return false; 298 } 299 300 bool PlatformWindows::GetRemoteOSKernelDescription(std::string &s) { 301 if (m_remote_platform_sp) 302 return m_remote_platform_sp->GetRemoteOSKernelDescription(s); 303 s.clear(); 304 return false; 305 } 306 307 // Remote Platform subclasses need to override this function 308 ArchSpec PlatformWindows::GetRemoteSystemArchitecture() { 309 if (m_remote_platform_sp) 310 return m_remote_platform_sp->GetRemoteSystemArchitecture(); 311 return ArchSpec(); 312 } 313 314 const char *PlatformWindows::GetHostname() { 315 if (IsHost()) 316 return Platform::GetHostname(); 317 318 if (m_remote_platform_sp) 319 return m_remote_platform_sp->GetHostname(); 320 return nullptr; 321 } 322 323 bool PlatformWindows::IsConnected() const { 324 if (IsHost()) 325 return true; 326 else if (m_remote_platform_sp) 327 return m_remote_platform_sp->IsConnected(); 328 return false; 329 } 330 331 Status PlatformWindows::ConnectRemote(Args &args) { 332 Status error; 333 if (IsHost()) { 334 error.SetErrorStringWithFormat( 335 "can't connect to the host platform '%s', always connected", 336 GetPluginName().AsCString()); 337 } else { 338 if (!m_remote_platform_sp) 339 m_remote_platform_sp = 340 Platform::Create(ConstString("remote-gdb-server"), error); 341 342 if (m_remote_platform_sp) { 343 if (error.Success()) { 344 if (m_remote_platform_sp) { 345 error = m_remote_platform_sp->ConnectRemote(args); 346 } else { 347 error.SetErrorString( 348 "\"platform connect\" takes a single argument: <connect-url>"); 349 } 350 } 351 } else 352 error.SetErrorString("failed to create a 'remote-gdb-server' platform"); 353 354 if (error.Fail()) 355 m_remote_platform_sp.reset(); 356 } 357 358 return error; 359 } 360 361 Status PlatformWindows::DisconnectRemote() { 362 Status error; 363 364 if (IsHost()) { 365 error.SetErrorStringWithFormat( 366 "can't disconnect from the host platform '%s', always connected", 367 GetPluginName().AsCString()); 368 } else { 369 if (m_remote_platform_sp) 370 error = m_remote_platform_sp->DisconnectRemote(); 371 else 372 error.SetErrorString("the platform is not currently connected"); 373 } 374 return error; 375 } 376 377 bool PlatformWindows::GetProcessInfo(lldb::pid_t pid, 378 ProcessInstanceInfo &process_info) { 379 bool success = false; 380 if (IsHost()) { 381 success = Platform::GetProcessInfo(pid, process_info); 382 } else if (m_remote_platform_sp) { 383 success = m_remote_platform_sp->GetProcessInfo(pid, process_info); 384 } 385 return success; 386 } 387 388 uint32_t 389 PlatformWindows::FindProcesses(const ProcessInstanceInfoMatch &match_info, 390 ProcessInstanceInfoList &process_infos) { 391 uint32_t match_count = 0; 392 if (IsHost()) { 393 // Let the base class figure out the host details 394 match_count = Platform::FindProcesses(match_info, process_infos); 395 } else { 396 // If we are remote, we can only return results if we are connected 397 if (m_remote_platform_sp) 398 match_count = 399 m_remote_platform_sp->FindProcesses(match_info, process_infos); 400 } 401 return match_count; 402 } 403 404 Status PlatformWindows::LaunchProcess(ProcessLaunchInfo &launch_info) { 405 Status error; 406 if (IsHost()) { 407 error = Platform::LaunchProcess(launch_info); 408 } else { 409 if (m_remote_platform_sp) 410 error = m_remote_platform_sp->LaunchProcess(launch_info); 411 else 412 error.SetErrorString("the platform is not currently connected"); 413 } 414 return error; 415 } 416 417 ProcessSP PlatformWindows::DebugProcess(ProcessLaunchInfo &launch_info, 418 Debugger &debugger, Target *target, 419 Status &error) { 420 // Windows has special considerations that must be followed when launching or 421 // attaching to a process. The key requirement is that when launching or 422 // attaching to a process, you must do it from the same the thread that will 423 // go into a permanent loop which will then receive debug events from the 424 // process. In particular, this means we can't use any of LLDB's generic 425 // mechanisms to do it for us, because it doesn't have the special knowledge 426 // required for setting up the background thread or passing the right flags. 427 // 428 // Another problem is that that LLDB's standard model for debugging a process 429 // is to first launch it, have it stop at the entry point, and then attach to 430 // it. In Windows this doesn't quite work, you have to specify as an 431 // argument to CreateProcess() that you're going to debug the process. So we 432 // override DebugProcess here to handle this. Launch operations go directly 433 // to the process plugin, and attach operations almost go directly to the 434 // process plugin (but we hijack the events first). In essence, we 435 // encapsulate all the logic of Launching and Attaching in the process 436 // plugin, and PlatformWindows::DebugProcess is just a pass-through to get to 437 // the process plugin. 438 439 if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) { 440 // This is a process attach. Don't need to launch anything. 441 ProcessAttachInfo attach_info(launch_info); 442 return Attach(attach_info, debugger, target, error); 443 } else { 444 ProcessSP process_sp = 445 target->CreateProcess(launch_info.GetListenerForProcess(debugger), 446 launch_info.GetProcessPluginName(), nullptr); 447 448 // We need to launch and attach to the process. 449 launch_info.GetFlags().Set(eLaunchFlagDebug); 450 if (process_sp) 451 error = process_sp->Launch(launch_info); 452 453 return process_sp; 454 } 455 } 456 457 lldb::ProcessSP PlatformWindows::Attach(ProcessAttachInfo &attach_info, 458 Debugger &debugger, Target *target, 459 Status &error) { 460 error.Clear(); 461 lldb::ProcessSP process_sp; 462 if (!IsHost()) { 463 if (m_remote_platform_sp) 464 process_sp = 465 m_remote_platform_sp->Attach(attach_info, debugger, target, error); 466 else 467 error.SetErrorString("the platform is not currently connected"); 468 return process_sp; 469 } 470 471 if (target == nullptr) { 472 TargetSP new_target_sp; 473 FileSpec emptyFileSpec; 474 ArchSpec emptyArchSpec; 475 476 error = debugger.GetTargetList().CreateTarget( 477 debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp); 478 target = new_target_sp.get(); 479 } 480 481 if (!target || error.Fail()) 482 return process_sp; 483 484 debugger.GetTargetList().SetSelectedTarget(target); 485 486 const char *plugin_name = attach_info.GetProcessPluginName(); 487 process_sp = target->CreateProcess( 488 attach_info.GetListenerForProcess(debugger), plugin_name, nullptr); 489 490 process_sp->HijackProcessEvents(attach_info.GetHijackListener()); 491 if (process_sp) 492 error = process_sp->Attach(attach_info); 493 494 return process_sp; 495 } 496 497 const char *PlatformWindows::GetUserName(uint32_t uid) { 498 // Check the cache in Platform in case we have already looked this uid up 499 const char *user_name = Platform::GetUserName(uid); 500 if (user_name) 501 return user_name; 502 503 if (IsRemote() && m_remote_platform_sp) 504 return m_remote_platform_sp->GetUserName(uid); 505 return nullptr; 506 } 507 508 const char *PlatformWindows::GetGroupName(uint32_t gid) { 509 const char *group_name = Platform::GetGroupName(gid); 510 if (group_name) 511 return group_name; 512 513 if (IsRemote() && m_remote_platform_sp) 514 return m_remote_platform_sp->GetGroupName(gid); 515 return nullptr; 516 } 517 518 Status PlatformWindows::GetFileWithUUID(const FileSpec &platform_file, 519 const UUID *uuid_ptr, 520 FileSpec &local_file) { 521 if (IsRemote()) { 522 if (m_remote_platform_sp) 523 return m_remote_platform_sp->GetFileWithUUID(platform_file, uuid_ptr, 524 local_file); 525 } 526 527 // Default to the local case 528 local_file = platform_file; 529 return Status(); 530 } 531 532 Status PlatformWindows::GetSharedModule( 533 const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp, 534 const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr, 535 bool *did_create_ptr) { 536 Status error; 537 module_sp.reset(); 538 539 if (IsRemote()) { 540 // If we have a remote platform always, let it try and locate the shared 541 // module first. 542 if (m_remote_platform_sp) { 543 error = m_remote_platform_sp->GetSharedModule( 544 module_spec, process, module_sp, module_search_paths_ptr, 545 old_module_sp_ptr, did_create_ptr); 546 } 547 } 548 549 if (!module_sp) { 550 // Fall back to the local platform and find the file locally 551 error = Platform::GetSharedModule(module_spec, process, module_sp, 552 module_search_paths_ptr, 553 old_module_sp_ptr, did_create_ptr); 554 } 555 if (module_sp) 556 module_sp->SetPlatformFileSpec(module_spec.GetFileSpec()); 557 return error; 558 } 559 560 bool PlatformWindows::GetSupportedArchitectureAtIndex(uint32_t idx, 561 ArchSpec &arch) { 562 static SupportedArchList architectures; 563 564 if (idx >= architectures.Count()) 565 return false; 566 arch = architectures[idx]; 567 return true; 568 } 569 570 void PlatformWindows::GetStatus(Stream &strm) { 571 Platform::GetStatus(strm); 572 573 #ifdef _WIN32 574 llvm::VersionTuple version = HostInfo::GetOSVersion(); 575 strm << "Host: Windows " << version.getAsString() << '\n'; 576 #endif 577 } 578 579 bool PlatformWindows::CanDebugProcess() { return true; } 580 581 Environment PlatformWindows::GetEnvironment() { 582 if (IsRemote()) { 583 if (m_remote_platform_sp) 584 return m_remote_platform_sp->GetEnvironment(); 585 return Environment(); 586 } 587 588 return Host::GetEnvironment(); 589 } 590 591 ConstString PlatformWindows::GetFullNameForDylib(ConstString basename) { 592 if (basename.IsEmpty()) 593 return basename; 594 595 StreamString stream; 596 stream.Printf("%s.dll", basename.GetCString()); 597 return ConstString(stream.GetString()); 598 } 599