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