LLDB  mainline
PlatformWindows.cpp
Go to the documentation of this file.
1 //===-- PlatformWindows.cpp -----------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "PlatformWindows.h"
10 
11 #include <cstdio>
12 #if defined(_WIN32)
14 #include <winsock2.h>
15 #endif
16 
19 #include "lldb/Core/Debugger.h"
20 #include "lldb/Core/Module.h"
22 #include "lldb/Host/HostInfo.h"
23 #include "lldb/Target/Process.h"
24 #include "lldb/Utility/Status.h"
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 
30 
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  if (llvm::any_of(m_archs, [spec](const ArchSpec &rhs) {
51  return spec.IsExactMatch(rhs);
52  }))
53  return;
54  if (spec.IsValid())
55  m_archs.push_back(spec);
56  }
57 
58  std::vector<ArchSpec> m_archs;
59 };
60 } // anonymous namespace
61 
62 PlatformSP PlatformWindows::CreateInstance(bool force,
63  const lldb_private::ArchSpec *arch) {
64  // The only time we create an instance is when we are creating a remote
65  // windows platform
66  const bool is_host = false;
67 
68  bool create = force;
69  if (!create && arch && arch->IsValid()) {
70  const llvm::Triple &triple = arch->GetTriple();
71  switch (triple.getVendor()) {
72  case llvm::Triple::PC:
73  create = true;
74  break;
75 
76  case llvm::Triple::UnknownVendor:
77  create = !arch->TripleVendorWasSpecified();
78  break;
79 
80  default:
81  break;
82  }
83 
84  if (create) {
85  switch (triple.getOS()) {
86  case llvm::Triple::Win32:
87  break;
88 
89  case llvm::Triple::UnknownOS:
90  create = arch->TripleOSWasSpecified();
91  break;
92 
93  default:
94  create = false;
95  break;
96  }
97  }
98  }
99  if (create)
100  return PlatformSP(new PlatformWindows(is_host));
101  return PlatformSP();
102 }
103 
104 llvm::StringRef PlatformWindows::GetPluginDescriptionStatic(bool is_host) {
105  return is_host ? "Local Windows user platform plug-in."
106  : "Remote Windows user platform plug-in.";
107 }
108 
109 void PlatformWindows::Initialize() {
110  Platform::Initialize();
111 
112  if (g_initialize_count++ == 0) {
113 #if defined(_WIN32)
114  // Force a host flag to true for the default platform object.
115  PlatformSP default_platform_sp(new PlatformWindows(true));
116  default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
117  Platform::SetHostPlatform(default_platform_sp);
118 #endif
119  PluginManager::RegisterPlugin(
120  PlatformWindows::GetPluginNameStatic(false),
121  PlatformWindows::GetPluginDescriptionStatic(false),
122  PlatformWindows::CreateInstance);
123  }
124 }
125 
126 void PlatformWindows::Terminate() {
127  if (g_initialize_count > 0) {
128  if (--g_initialize_count == 0) {
129  PluginManager::UnregisterPlugin(PlatformWindows::CreateInstance);
130  }
131  }
132 
133  Platform::Terminate();
134 }
135 
136 /// Default Constructor
137 PlatformWindows::PlatformWindows(bool is_host) : RemoteAwarePlatform(is_host) {}
138 
140  Status error;
141  if (IsHost()) {
142  error.SetErrorStringWithFormatv(
143  "can't connect to the host platform '{0}', always connected",
144  GetPluginName());
145  } else {
148  Platform::Create(ConstString("remote-gdb-server"), error);
149 
150  if (m_remote_platform_sp) {
151  if (error.Success()) {
152  if (m_remote_platform_sp) {
153  error = m_remote_platform_sp->ConnectRemote(args);
154  } else {
155  error.SetErrorString(
156  "\"platform connect\" takes a single argument: <connect-url>");
157  }
158  }
159  } else
160  error.SetErrorString("failed to create a 'remote-gdb-server' platform");
161 
162  if (error.Fail())
163  m_remote_platform_sp.reset();
164  }
165 
166  return error;
167 }
168 
170  Status error;
171 
172  if (IsHost()) {
173  error.SetErrorStringWithFormatv(
174  "can't disconnect from the host platform '{0}', always connected",
175  GetPluginName());
176  } else {
178  error = m_remote_platform_sp->DisconnectRemote();
179  else
180  error.SetErrorString("the platform is not currently connected");
181  }
182  return error;
183 }
184 
186  Debugger &debugger, Target &target,
187  Status &error) {
188  // Windows has special considerations that must be followed when launching or
189  // attaching to a process. The key requirement is that when launching or
190  // attaching to a process, you must do it from the same the thread that will
191  // go into a permanent loop which will then receive debug events from the
192  // process. In particular, this means we can't use any of LLDB's generic
193  // mechanisms to do it for us, because it doesn't have the special knowledge
194  // required for setting up the background thread or passing the right flags.
195  //
196  // Another problem is that that LLDB's standard model for debugging a process
197  // is to first launch it, have it stop at the entry point, and then attach to
198  // it. In Windows this doesn't quite work, you have to specify as an
199  // argument to CreateProcess() that you're going to debug the process. So we
200  // override DebugProcess here to handle this. Launch operations go directly
201  // to the process plugin, and attach operations almost go directly to the
202  // process plugin (but we hijack the events first). In essence, we
203  // encapsulate all the logic of Launching and Attaching in the process
204  // plugin, and PlatformWindows::DebugProcess is just a pass-through to get to
205  // the process plugin.
206 
207  if (IsRemote()) {
209  return m_remote_platform_sp->DebugProcess(launch_info, debugger, target,
210  error);
211  else
212  error.SetErrorString("the platform is not currently connected");
213  }
214 
215  if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) {
216  // This is a process attach. Don't need to launch anything.
217  ProcessAttachInfo attach_info(launch_info);
218  return Attach(attach_info, debugger, &target, error);
219  } else {
220  ProcessSP process_sp = target.CreateProcess(
221  launch_info.GetListener(), launch_info.GetProcessPluginName(), nullptr,
222  false);
223 
224  // We need to launch and attach to the process.
225  launch_info.GetFlags().Set(eLaunchFlagDebug);
226  if (process_sp)
227  error = process_sp->Launch(launch_info);
228 
229  return process_sp;
230  }
231 }
232 
233 lldb::ProcessSP PlatformWindows::Attach(ProcessAttachInfo &attach_info,
234  Debugger &debugger, Target *target,
235  Status &error) {
236  error.Clear();
237  lldb::ProcessSP process_sp;
238  if (!IsHost()) {
240  process_sp =
241  m_remote_platform_sp->Attach(attach_info, debugger, target, error);
242  else
243  error.SetErrorString("the platform is not currently connected");
244  return process_sp;
245  }
246 
247  if (target == nullptr) {
248  TargetSP new_target_sp;
249  FileSpec emptyFileSpec;
250  ArchSpec emptyArchSpec;
251 
252  error = debugger.GetTargetList().CreateTarget(
253  debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp);
254  target = new_target_sp.get();
255  }
256 
257  if (!target || error.Fail())
258  return process_sp;
259 
260  const char *plugin_name = attach_info.GetProcessPluginName();
261  process_sp = target->CreateProcess(
262  attach_info.GetListenerForProcess(debugger), plugin_name, nullptr, false);
263 
264  process_sp->HijackProcessEvents(attach_info.GetHijackListener());
265  if (process_sp)
266  error = process_sp->Attach(attach_info);
267 
268  return process_sp;
269 }
270 
272  ArchSpec &arch) {
273  static SupportedArchList architectures;
274 
275  if (idx >= architectures.Count())
276  return false;
277  arch = architectures[idx];
278  return true;
279 }
280 
282  Platform::GetStatus(strm);
283 
284 #ifdef _WIN32
285  llvm::VersionTuple version = HostInfo::GetOSVersion();
286  strm << " Host: Windows " << version.getAsString() << '\n';
287 #endif
288 }
289 
290 bool PlatformWindows::CanDebugProcess() { return true; }
291 
293  if (basename.IsEmpty())
294  return basename;
295 
296  StreamString stream;
297  stream.Printf("%s.dll", basename.GetCString());
298  return ConstString(stream.GetString());
299 }
300 
301 size_t
303  BreakpointSite *bp_site) {
304  ArchSpec arch = target.GetArchitecture();
305  assert(arch.IsValid());
306  const uint8_t *trap_opcode = nullptr;
307  size_t trap_opcode_size = 0;
308 
309  switch (arch.GetMachine()) {
310  case llvm::Triple::aarch64: {
311  static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x3e, 0xd4}; // brk #0xf000
312  trap_opcode = g_aarch64_opcode;
313  trap_opcode_size = sizeof(g_aarch64_opcode);
314 
315  if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
316  return trap_opcode_size;
317  return 0;
318  } break;
319 
320  case llvm::Triple::arm:
321  case llvm::Triple::thumb: {
322  static const uint8_t g_thumb_opcode[] = {0xfe, 0xde}; // udf #0xfe
323  trap_opcode = g_thumb_opcode;
324  trap_opcode_size = sizeof(g_thumb_opcode);
325 
326  if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
327  return trap_opcode_size;
328  return 0;
329  } break;
330 
331  default:
332  return Platform::GetSoftwareBreakpointTrapOpcode(target, bp_site);
333  }
334 }
lldb_private::ArchSpec
Definition: ArchSpec.h:33
lldb_private::ArchSpec::TripleVendorWasSpecified
bool TripleVendorWasSpecified() const
Definition: ArchSpec.h:347
LLDB_INVALID_PROCESS_ID
#define LLDB_INVALID_PROCESS_ID
Definition: lldb-defines.h:93
lldb_private::ArchSpec::GetMachine
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
Definition: ArchSpec.cpp:667
Module.h
BreakpointLocation.h
lldb_private::PlatformWindows::DisconnectRemote
lldb_private::Status DisconnectRemote() override
Definition: PlatformWindows.cpp:169
lldb_private::ProcessInfo::GetProcessID
lldb::pid_t GetProcessID() const
Definition: ProcessInfo.h:67
lldb_private::ProcessLaunchInfo::GetFlags
Flags & GetFlags()
Definition: ProcessLaunchInfo.h:64
lldb_private::Stream
Definition: Stream.h:28
lldb_private::Args
Definition: Args.h:33
lldb_private::ArchSpec::GetTriple
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:444
Debugger.h
lldb_private::Target
Definition: Target.h:451
lldb_private::PlatformWindows::GetSoftwareBreakpointTrapOpcode
size_t GetSoftwareBreakpointTrapOpcode(Target &target, BreakpointSite *bp_site) override
Definition: PlatformWindows.cpp:302
lldb_private::Target::CreateProcess
const lldb::ProcessSP & CreateProcess(lldb::ListenerSP listener_sp, llvm::StringRef plugin_name, const FileSpec *crash_file, bool can_connect)
Definition: Target.cpp:199
lldb_private::StreamString::GetString
llvm::StringRef GetString() const
Definition: StreamString.cpp:51
Process.h
lldb_private::ProcessAttachInfo::GetListenerForProcess
lldb::ListenerSP GetListenerForProcess(Debugger &debugger)
Definition: Process.cpp:2759
PlatformWindows.h
lldb_private::FileSpec
Definition: FileSpec.h:56
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
g_initialize_count
static uint32_t g_initialize_count
Definition: PlatformWindows.cpp:31
lldb_private::BreakpointSite
Definition: BreakpointSite.h:35
lldb_private::ProcessLaunchInfo
Definition: ProcessLaunchInfo.h:31
lldb_private::ConstString::IsEmpty
bool IsEmpty() const
Test for empty string.
Definition: ConstString.h:304
lldb_private::eLoadDependentsNo
@ eLoadDependentsNo
Definition: Target.h:64
lldb_private::RemoteAwarePlatform::m_remote_platform_sp
lldb::PlatformSP m_remote_platform_sp
Definition: RemoteAwarePlatform.h:104
lldb_private::ConstString
Definition: ConstString.h:40
lldb_private::Platform::GetSoftwareBreakpointTrapOpcode
virtual size_t GetSoftwareBreakpointTrapOpcode(Target &target, BreakpointSite *bp_site)
Definition: Platform.cpp:1849
lldb_private::StreamString
Definition: StreamString.h:23
lldb_private::PlatformWindows::ConnectRemote
lldb_private::Status ConnectRemote(lldb_private::Args &args) override
Definition: PlatformWindows.cpp:139
lldb_private::TargetList::CreateTarget
Status CreateTarget(Debugger &debugger, llvm::StringRef user_exe_path, llvm::StringRef triple_str, LoadDependentFiles get_dependent_modules, const OptionGroupPlatform *platform_options, lldb::TargetSP &target_sp)
Create a new Target.
lldb_private::ProcessLaunchInfo::GetListener
lldb::ListenerSP GetListener() const
Definition: ProcessLaunchInfo.h:128
lldb_private::ArchSpec::TripleOSWasSpecified
bool TripleOSWasSpecified() const
Definition: ArchSpec.h:351
lldb_private::Debugger
Definition: Debugger.h:70
HostInfo.h
lldb_private::ArchSpec::IsValid
bool IsValid() const
Tests if this ArchSpec is valid.
Definition: ArchSpec.h:342
lldb_private::PlatformWindows::GetPluginName
llvm::StringRef GetPluginName() override
Definition: PlatformWindows.h:34
lldb_private::ProcessAttachInfo
Definition: Process.h:113
lldb_private::Debugger::GetTargetList
TargetList & GetTargetList()
Get accessor for the target list.
Definition: Debugger.h:223
lldb_private::Platform::IsRemote
bool IsRemote() const
Definition: Platform.h:439
lldb_private::PlatformWindows::GetFullNameForDylib
ConstString GetFullNameForDylib(ConstString basename) override
Definition: PlatformWindows.cpp:292
lldb_private::ProcessLaunchInfo::GetProcessPluginName
const char * GetProcessPluginName() const
Definition: ProcessLaunchInfo.cpp:132
lldb_private::Target::GetArchitecture
const ArchSpec & GetArchitecture() const
Definition: Target.h:967
lldb_private::Status
Definition: Status.h:44
uint32_t
lldb_private::ProcessAttachInfo::GetProcessPluginName
const char * GetProcessPluginName() const
Definition: Process.h:152
windows.h
PluginManager.h
lldb_private::ConstString::GetCString
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:216
lldb_private::PlatformWindows::GetStatus
void GetStatus(lldb_private::Stream &strm) override
Report the current status for this platform.
Definition: PlatformWindows.cpp:281
lldb_private::Stream::Printf
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:107
Status.h
lldb_private::PlatformWindows::GetSupportedArchitectureAtIndex
bool GetSupportedArchitectureAtIndex(uint32_t idx, lldb_private::ArchSpec &arch) override
Get the platform's supported architectures in the order in which they should be searched.
Definition: PlatformWindows.cpp:271
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::PlatformWindows::Attach
lldb::ProcessSP Attach(lldb_private::ProcessAttachInfo &attach_info, lldb_private::Debugger &debugger, lldb_private::Target *target, lldb_private::Status &error) override
Attach to an existing process using a process ID.
Definition: PlatformWindows.cpp:233
lldb_private::BreakpointSite::SetTrapOpcode
bool SetTrapOpcode(const uint8_t *trap_opcode, uint32_t trap_opcode_size)
Sets the trap opcode.
Definition: BreakpointSite.cpp:104
lldb_private::Flags::Set
ValueType Set(ValueType mask)
Set one or more flags by logical OR'ing mask with the current flags.
Definition: Flags.h:73
lldb_private::Platform::GetStatus
virtual void GetStatus(Stream &strm)
Report the current status for this platform.
Definition: Platform.cpp:400
BreakpointSite.h
LLDB_PLUGIN_DEFINE
#define LLDB_PLUGIN_DEFINE(PluginName)
Definition: PluginManager.h:31
lldb_private::Platform::IsHost
bool IsHost() const
Definition: Platform.h:435
lldb_private::ProcessAttachInfo::GetHijackListener
lldb::ListenerSP GetHijackListener() const
Definition: Process.h:179
lldb_private::RemoteAwarePlatform
A base class for platforms which automatically want to be able to forward operations to a remote plat...
Definition: RemoteAwarePlatform.h:18
lldb
Definition: SBAddress.h:15
lldb_private::PlatformWindows::DebugProcess
lldb::ProcessSP DebugProcess(lldb_private::ProcessLaunchInfo &launch_info, lldb_private::Debugger &debugger, lldb_private::Target &target, lldb_private::Status &error) override
Subclasses do not need to implement this function as it uses the Platform::LaunchProcess() followed b...
Definition: PlatformWindows.cpp:185
lldb_private::ArchSpec::IsExactMatch
bool IsExactMatch(const ArchSpec &rhs) const
Compare an ArchSpec to another ArchSpec, requiring an exact cpu type match between them.
Definition: ArchSpec.cpp:930
lldb_private::PlatformWindows
Definition: PlatformWindows.h:16
lldb_private::PlatformWindows::CanDebugProcess
bool CanDebugProcess() override
Not all platforms will support debugging a process by spawning somehow halted for a debugger (specifi...
Definition: PlatformWindows.cpp:290
lldb_private::Platform::Create
static lldb::PlatformSP Create(ConstString name, Status &error)
Definition: Platform.cpp:289