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