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 
21 #include "lldb/Core/Debugger.h"
22 #include "lldb/Core/Module.h"
28 #include "lldb/Host/HostInfo.h"
30 #include "lldb/Target/Process.h"
31 #include "lldb/Utility/Status.h"
32 
33 #include "llvm/ADT/ScopeExit.h"
34 #include "llvm/Support/ConvertUTF.h"
35 
36 using namespace lldb;
37 using namespace lldb_private;
38 
40 
42 
43 PlatformSP PlatformWindows::CreateInstance(bool force,
44  const lldb_private::ArchSpec *arch) {
45  // The only time we create an instance is when we are creating a remote
46  // windows platform
47  const bool is_host = false;
48 
49  bool create = force;
50  if (!create && arch && arch->IsValid()) {
51  const llvm::Triple &triple = arch->GetTriple();
52  switch (triple.getVendor()) {
53  case llvm::Triple::PC:
54  create = true;
55  break;
56 
57  case llvm::Triple::UnknownVendor:
58  create = !arch->TripleVendorWasSpecified();
59  break;
60 
61  default:
62  break;
63  }
64 
65  if (create) {
66  switch (triple.getOS()) {
67  case llvm::Triple::Win32:
68  break;
69 
70  case llvm::Triple::UnknownOS:
71  create = arch->TripleOSWasSpecified();
72  break;
73 
74  default:
75  create = false;
76  break;
77  }
78  }
79  }
80  if (create)
81  return PlatformSP(new PlatformWindows(is_host));
82  return PlatformSP();
83 }
84 
85 llvm::StringRef PlatformWindows::GetPluginDescriptionStatic(bool is_host) {
86  return is_host ? "Local Windows user platform plug-in."
87  : "Remote Windows user platform plug-in.";
88 }
89 
90 void PlatformWindows::Initialize() {
91  Platform::Initialize();
92 
93  if (g_initialize_count++ == 0) {
94 #if defined(_WIN32)
95  // Force a host flag to true for the default platform object.
96  PlatformSP default_platform_sp(new PlatformWindows(true));
97  default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
98  Platform::SetHostPlatform(default_platform_sp);
99 #endif
100  PluginManager::RegisterPlugin(
101  PlatformWindows::GetPluginNameStatic(false),
102  PlatformWindows::GetPluginDescriptionStatic(false),
103  PlatformWindows::CreateInstance);
104  }
105 }
106 
107 void PlatformWindows::Terminate() {
108  if (g_initialize_count > 0) {
109  if (--g_initialize_count == 0) {
110  PluginManager::UnregisterPlugin(PlatformWindows::CreateInstance);
111  }
112  }
113 
114  Platform::Terminate();
115 }
116 
117 /// Default Constructor
118 PlatformWindows::PlatformWindows(bool is_host) : RemoteAwarePlatform(is_host) {
119  const auto &AddArch = [&](const ArchSpec &spec) {
120  if (llvm::any_of(m_supported_architectures, [spec](const ArchSpec &rhs) {
121  return spec.IsExactMatch(rhs);
122  }))
123  return;
124  if (spec.IsValid())
125  m_supported_architectures.push_back(spec);
126  };
127  AddArch(HostInfo::GetArchitecture(HostInfo::eArchKindDefault));
128  AddArch(HostInfo::GetArchitecture(HostInfo::eArchKind32));
129  AddArch(HostInfo::GetArchitecture(HostInfo::eArchKind64));
130 }
131 
133  Status error;
134  if (IsHost()) {
135  error.SetErrorStringWithFormatv(
136  "can't connect to the host platform '{0}', always connected",
137  GetPluginName());
138  } else {
142  /*force=*/true, nullptr);
143 
144  if (m_remote_platform_sp) {
145  if (error.Success()) {
146  if (m_remote_platform_sp) {
147  error = m_remote_platform_sp->ConnectRemote(args);
148  } else {
149  error.SetErrorString(
150  "\"platform connect\" takes a single argument: <connect-url>");
151  }
152  }
153  } else
154  error.SetErrorString("failed to create a 'remote-gdb-server' platform");
155 
156  if (error.Fail())
157  m_remote_platform_sp.reset();
158  }
159 
160  return error;
161 }
162 
164  const FileSpec &remote_file,
165  const std::vector<std::string> *paths,
166  Status &error, FileSpec *loaded_image) {
167  DiagnosticManager diagnostics;
168 
169  if (loaded_image)
170  loaded_image->Clear();
171 
172  ThreadSP thread = process->GetThreadList().GetExpressionExecutionThread();
173  if (!thread) {
174  error.SetErrorString("LoadLibrary error: no thread available to invoke LoadLibrary");
176  }
177 
178  ExecutionContext context;
179  thread->CalculateExecutionContext(context);
180 
181  Status status;
182  UtilityFunction *loader =
183  process->GetLoadImageUtilityFunction(this, [&]() -> std::unique_ptr<UtilityFunction> {
184  return MakeLoadImageUtilityFunction(context, status);
185  });
186  if (loader == nullptr)
188 
189  FunctionCaller *invocation = loader->GetFunctionCaller();
190  if (!invocation) {
191  error.SetErrorString("LoadLibrary error: could not get function caller");
193  }
194 
195  /* Convert name */
196  llvm::SmallVector<llvm::UTF16, 261> name;
197  if (!llvm::convertUTF8ToUTF16String(remote_file.GetPath(), name)) {
198  error.SetErrorString("LoadLibrary error: could not convert path to UCS2");
200  }
201  name.emplace_back(L'\0');
202 
203  /* Inject name paramter into inferior */
204  lldb::addr_t injected_name =
205  process->AllocateMemory(name.size() * sizeof(llvm::UTF16),
206  ePermissionsReadable | ePermissionsWritable,
207  status);
208  if (injected_name == LLDB_INVALID_ADDRESS) {
209  error.SetErrorStringWithFormat("LoadLibrary error: unable to allocate memory for name: %s",
210  status.AsCString());
212  }
213 
214  auto name_cleanup = llvm::make_scope_exit([process, injected_name]() {
215  process->DeallocateMemory(injected_name);
216  });
217 
218  process->WriteMemory(injected_name, name.data(),
219  name.size() * sizeof(llvm::UTF16), status);
220  if (status.Fail()) {
221  error.SetErrorStringWithFormat("LoadLibrary error: unable to write name: %s",
222  status.AsCString());
224  }
225 
226  /* Inject paths parameter into inferior */
227  lldb::addr_t injected_paths{0x0};
228  llvm::Optional<llvm::detail::scope_exit<std::function<void()>>> paths_cleanup;
229  if (paths) {
230  llvm::SmallVector<llvm::UTF16, 261> search_paths;
231 
232  for (const auto &path : *paths) {
233  if (path.empty())
234  continue;
235 
236  llvm::SmallVector<llvm::UTF16, 261> buffer;
237  if (!llvm::convertUTF8ToUTF16String(path, buffer))
238  continue;
239 
240  search_paths.append(std::begin(buffer), std::end(buffer));
241  search_paths.emplace_back(L'\0');
242  }
243  search_paths.emplace_back(L'\0');
244 
245  injected_paths =
246  process->AllocateMemory(search_paths.size() * sizeof(llvm::UTF16),
247  ePermissionsReadable | ePermissionsWritable,
248  status);
249  if (injected_paths == LLDB_INVALID_ADDRESS) {
250  error.SetErrorStringWithFormat("LoadLibrary error: unable to allocate memory for paths: %s",
251  status.AsCString());
253  }
254 
255  paths_cleanup.emplace([process, injected_paths]() {
256  process->DeallocateMemory(injected_paths);
257  });
258 
259  process->WriteMemory(injected_paths, search_paths.data(),
260  search_paths.size() * sizeof(llvm::UTF16), status);
261  if (status.Fail()) {
262  error.SetErrorStringWithFormat("LoadLibrary error: unable to write paths: %s",
263  status.AsCString());
265  }
266  }
267 
268  /* Inject wszModulePath into inferior */
269  // FIXME(compnerd) should do something better for the length?
270  // GetModuleFileNameA is likely limited to PATH_MAX rather than the NT path
271  // limit.
272  unsigned injected_length = 261;
273 
274  lldb::addr_t injected_module_path =
275  process->AllocateMemory(injected_length + 1,
276  ePermissionsReadable | ePermissionsWritable,
277  status);
278  if (injected_module_path == LLDB_INVALID_ADDRESS) {
279  error.SetErrorStringWithFormat("LoadLibrary error: unable to allocate memory for module location: %s",
280  status.AsCString());
282  }
283 
284  auto injected_module_path_cleanup =
285  llvm::make_scope_exit([process, injected_module_path]() {
286  process->DeallocateMemory(injected_module_path);
287  });
288 
289  /* Inject __lldb_LoadLibraryResult into inferior */
290  const uint32_t word_size = process->GetAddressByteSize();
291  lldb::addr_t injected_result =
292  process->AllocateMemory(3 * word_size,
293  ePermissionsReadable | ePermissionsWritable,
294  status);
295  if (status.Fail()) {
296  error.SetErrorStringWithFormat("LoadLibrary error: could not allocate memory for result: %s",
297  status.AsCString());
299  }
300 
301  auto result_cleanup = llvm::make_scope_exit([process, injected_result]() {
302  process->DeallocateMemory(injected_result);
303  });
304 
305  process->WritePointerToMemory(injected_result + word_size,
306  injected_module_path, status);
307  if (status.Fail()) {
308  error.SetErrorStringWithFormat("LoadLibrary error: could not initialize result: %s",
309  status.AsCString());
311  }
312 
313  // XXX(compnerd) should we use the compiler to get the sizeof(unsigned)?
314  process->WriteScalarToMemory(injected_result + 2 * word_size,
315  Scalar{injected_length}, sizeof(unsigned),
316  status);
317  if (status.Fail()) {
318  error.SetErrorStringWithFormat("LoadLibrary error: could not initialize result: %s",
319  status.AsCString());
321  }
322 
323  /* Setup Formal Parameters */
324  ValueList parameters = invocation->GetArgumentValues();
325  parameters.GetValueAtIndex(0)->GetScalar() = injected_name;
326  parameters.GetValueAtIndex(1)->GetScalar() = injected_paths;
327  parameters.GetValueAtIndex(2)->GetScalar() = injected_result;
328 
329  lldb::addr_t injected_parameters = LLDB_INVALID_ADDRESS;
330  diagnostics.Clear();
331  if (!invocation->WriteFunctionArguments(context, injected_parameters,
332  parameters, diagnostics)) {
333  error.SetErrorStringWithFormat("LoadLibrary error: unable to write function parameters: %s",
334  diagnostics.GetString().c_str());
336  }
337 
338  auto parameter_cleanup = llvm::make_scope_exit([invocation, &context, injected_parameters]() {
339  invocation->DeallocateFunctionResults(context, injected_parameters);
340  });
341 
342  TypeSystemClang *ast =
344  if (!ast) {
345  error.SetErrorString("LoadLibrary error: unable to get (clang) type system");
347  }
348 
349  /* Setup Return Type */
350  CompilerType VoidPtrTy = ast->GetBasicType(eBasicTypeVoid).GetPointerType();
351 
352  Value value;
353  value.SetCompilerType(VoidPtrTy);
354 
355  /* Invoke expression */
359  options.SetIgnoreBreakpoints(true);
360  options.SetUnwindOnError(true);
361  // LoadLibraryEx{A,W}/FreeLibrary cannot raise exceptions which we can handle.
362  // They may potentially throw SEH exceptions which we do not know how to
363  // handle currently.
364  options.SetTrapExceptions(false);
365  options.SetTimeout(process->GetUtilityExpressionTimeout());
366  options.SetIsForUtilityExpr(true);
367 
368  ExpressionResults result =
369  invocation->ExecuteFunction(context, &injected_parameters, options,
370  diagnostics, value);
371  if (result != eExpressionCompleted) {
372  error.SetErrorStringWithFormat("LoadLibrary error: failed to execute LoadLibrary helper: %s",
373  diagnostics.GetString().c_str());
375  }
376 
377  /* Read result */
378  lldb::addr_t token = process->ReadPointerFromMemory(injected_result, status);
379  if (status.Fail()) {
380  error.SetErrorStringWithFormat("LoadLibrary error: could not read the result: %s",
381  status.AsCString());
383  }
384 
385  if (!token) {
386  // XXX(compnerd) should we use the compiler to get the sizeof(unsigned)?
387  uint64_t error_code =
388  process->ReadUnsignedIntegerFromMemory(injected_result + 2 * word_size + sizeof(unsigned),
389  word_size, 0, status);
390  if (status.Fail()) {
391  error.SetErrorStringWithFormat("LoadLibrary error: could not read error status: %s",
392  status.AsCString());
394  }
395 
396  error.SetErrorStringWithFormat("LoadLibrary Error: %" PRIu64, error_code);
398  }
399 
400  std::string module_path;
401  process->ReadCStringFromMemory(injected_module_path, module_path, status);
402  if (status.Fail()) {
403  error.SetErrorStringWithFormat("LoadLibrary error: could not read module path: %s",
404  status.AsCString());
406  }
407 
408  if (loaded_image)
409  loaded_image->SetFile(module_path, llvm::sys::path::Style::native);
410  return process->AddImageToken(token);
411 }
412 
414  const addr_t address = process->GetImagePtrFromToken(image_token);
415  if (address == LLDB_INVALID_ADDRESS)
416  return Status("invalid image token");
417 
418  StreamString expression;
419  expression.Printf("FreeLibrary((HMODULE)0x%" PRIx64 ")", address);
420 
421  ValueObjectSP value;
422  Status result =
423  EvaluateLoaderExpression(process, expression.GetData(), value);
424  if (result.Fail())
425  return result;
426 
427  if (value->GetError().Fail())
428  return value->GetError();
429 
430  Scalar scalar;
431  if (value->ResolveValue(scalar)) {
432  if (scalar.UInt(1))
433  return Status("expression failed: \"%s\"", expression.GetData());
434  process->ResetImageToken(image_token);
435  }
436 
437  return Status();
438 }
439 
441  Status error;
442 
443  if (IsHost()) {
444  error.SetErrorStringWithFormatv(
445  "can't disconnect from the host platform '{0}', always connected",
446  GetPluginName());
447  } else {
449  error = m_remote_platform_sp->DisconnectRemote();
450  else
451  error.SetErrorString("the platform is not currently connected");
452  }
453  return error;
454 }
455 
457  Debugger &debugger, Target &target,
458  Status &error) {
459  // Windows has special considerations that must be followed when launching or
460  // attaching to a process. The key requirement is that when launching or
461  // attaching to a process, you must do it from the same the thread that will
462  // go into a permanent loop which will then receive debug events from the
463  // process. In particular, this means we can't use any of LLDB's generic
464  // mechanisms to do it for us, because it doesn't have the special knowledge
465  // required for setting up the background thread or passing the right flags.
466  //
467  // Another problem is that that LLDB's standard model for debugging a process
468  // is to first launch it, have it stop at the entry point, and then attach to
469  // it. In Windows this doesn't quite work, you have to specify as an
470  // argument to CreateProcess() that you're going to debug the process. So we
471  // override DebugProcess here to handle this. Launch operations go directly
472  // to the process plugin, and attach operations almost go directly to the
473  // process plugin (but we hijack the events first). In essence, we
474  // encapsulate all the logic of Launching and Attaching in the process
475  // plugin, and PlatformWindows::DebugProcess is just a pass-through to get to
476  // the process plugin.
477 
478  if (IsRemote()) {
480  return m_remote_platform_sp->DebugProcess(launch_info, debugger, target,
481  error);
482  else
483  error.SetErrorString("the platform is not currently connected");
484  }
485 
486  if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) {
487  // This is a process attach. Don't need to launch anything.
488  ProcessAttachInfo attach_info(launch_info);
489  return Attach(attach_info, debugger, &target, error);
490  }
491 
492  ProcessSP process_sp =
493  target.CreateProcess(launch_info.GetListener(),
494  launch_info.GetProcessPluginName(), nullptr, false);
495 
496  process_sp->HijackProcessEvents(launch_info.GetHijackListener());
497 
498  // We need to launch and attach to the process.
499  launch_info.GetFlags().Set(eLaunchFlagDebug);
500  if (process_sp)
501  error = process_sp->Launch(launch_info);
502 
503  return process_sp;
504 }
505 
506 lldb::ProcessSP PlatformWindows::Attach(ProcessAttachInfo &attach_info,
507  Debugger &debugger, Target *target,
508  Status &error) {
509  error.Clear();
510  lldb::ProcessSP process_sp;
511  if (!IsHost()) {
513  process_sp =
514  m_remote_platform_sp->Attach(attach_info, debugger, target, error);
515  else
516  error.SetErrorString("the platform is not currently connected");
517  return process_sp;
518  }
519 
520  if (target == nullptr) {
521  TargetSP new_target_sp;
522  FileSpec emptyFileSpec;
523  ArchSpec emptyArchSpec;
524 
525  error = debugger.GetTargetList().CreateTarget(
526  debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp);
527  target = new_target_sp.get();
528  }
529 
530  if (!target || error.Fail())
531  return process_sp;
532 
533  const char *plugin_name = attach_info.GetProcessPluginName();
534  process_sp = target->CreateProcess(
535  attach_info.GetListenerForProcess(debugger), plugin_name, nullptr, false);
536 
537  process_sp->HijackProcessEvents(attach_info.GetHijackListener());
538  if (process_sp)
539  error = process_sp->Attach(attach_info);
540 
541  return process_sp;
542 }
543 
545  Platform::GetStatus(strm);
546 
547 #ifdef _WIN32
548  llvm::VersionTuple version = HostInfo::GetOSVersion();
549  strm << " Host: Windows " << version.getAsString() << '\n';
550 #endif
551 }
552 
553 bool PlatformWindows::CanDebugProcess() { return true; }
554 
556  if (basename.IsEmpty())
557  return basename;
558 
559  StreamString stream;
560  stream.Printf("%s.dll", basename.GetCString());
561  return ConstString(stream.GetString());
562 }
563 
564 size_t
566  BreakpointSite *bp_site) {
567  ArchSpec arch = target.GetArchitecture();
568  assert(arch.IsValid());
569  const uint8_t *trap_opcode = nullptr;
570  size_t trap_opcode_size = 0;
571 
572  switch (arch.GetMachine()) {
573  case llvm::Triple::aarch64: {
574  static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x3e, 0xd4}; // brk #0xf000
575  trap_opcode = g_aarch64_opcode;
576  trap_opcode_size = sizeof(g_aarch64_opcode);
577 
578  if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
579  return trap_opcode_size;
580  return 0;
581  } break;
582 
583  case llvm::Triple::arm:
584  case llvm::Triple::thumb: {
585  static const uint8_t g_thumb_opcode[] = {0xfe, 0xde}; // udf #0xfe
586  trap_opcode = g_thumb_opcode;
587  trap_opcode_size = sizeof(g_thumb_opcode);
588 
589  if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
590  return trap_opcode_size;
591  return 0;
592  } break;
593 
594  default:
595  return Platform::GetSoftwareBreakpointTrapOpcode(target, bp_site);
596  }
597 }
598 
599 std::unique_ptr<UtilityFunction>
601  Status &status) {
602  // FIXME(compnerd) `-fdeclspec` is not passed to the clang instance?
603  static constexpr const char kLoaderDecls[] = R"(
604 extern "C" {
605 // errhandlingapi.h
606 
607 // `LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32 | LOAD_LIBRARY_SEARCH_USER_DIRS`
608 //
609 // Directories in the standard search path are not searched. This value cannot
610 // be combined with `LOAD_WITH_ALTERED_SEARCH_PATH`.
611 //
612 // This value represents the recommended maximum number of directories an
613 // application should include in its DLL search path.
614 #define LOAD_LIBRARY_SEARCH_DEFAULT_DIRS 0x00001000
615 
616 // WINBASEAPI DWORD WINAPI GetLastError(VOID);
617 /* __declspec(dllimport) */ uint32_t __stdcall GetLastError();
618 
619 // libloaderapi.h
620 
621 // WINBASEAPI DLL_DIRECTORY_COOKIE WINAPI AddDllDirectory(LPCWSTR);
622 /* __declspec(dllimport) */ void * __stdcall AddDllDirectory(const wchar_t *);
623 
624 // WINBASEAPI BOOL WINAPI FreeModule(HMODULE);
625 /* __declspec(dllimport) */ int __stdcall FreeModule(void *hLibModule);
626 
627 // WINBASEAPI DWORD WINAPI GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize);
628 /* __declspec(dllimport) */ uint32_t GetModuleFileNameA(void *, char *, uint32_t);
629 
630 // WINBASEAPI HMODULE WINAPI LoadLibraryExW(LPCWSTR, HANDLE, DWORD);
631 /* __declspec(dllimport) */ void * __stdcall LoadLibraryExW(const wchar_t *, void *, uint32_t);
632 
633 // corecrt_wstring.h
634 
635 // _ACRTIMP size_t __cdecl wcslen(wchar_t const *_String);
636 /* __declspec(dllimport) */ size_t __cdecl wcslen(const wchar_t *);
637 
638 // lldb specific code
639 
640 struct __lldb_LoadLibraryResult {
641  void *ImageBase;
642  char *ModulePath;
643  unsigned Length;
644  unsigned ErrorCode;
645 };
646 
647 _Static_assert(sizeof(struct __lldb_LoadLibraryResult) <= 3 * sizeof(void *),
648  "__lldb_LoadLibraryResult size mismatch");
649 
650 void * __lldb_LoadLibraryHelper(const wchar_t *name, const wchar_t *paths,
651  __lldb_LoadLibraryResult *result) {
652  for (const wchar_t *path = paths; path && *path; ) {
653  (void)AddDllDirectory(path);
654  path += wcslen(path) + 1;
655  }
656 
657  result->ImageBase = LoadLibraryExW(name, nullptr,
658  LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
659  if (result->ImageBase == nullptr)
660  result->ErrorCode = GetLastError();
661  else
662  result->Length = GetModuleFileNameA(result->ImageBase, result->ModulePath,
663  result->Length);
664 
665  return result->ImageBase;
666 }
667 }
668  )";
669 
670  static constexpr const char kName[] = "__lldb_LoadLibraryHelper";
671 
672  ProcessSP process = context.GetProcessSP();
673  Target &target = process->GetTarget();
674 
675  auto function = target.CreateUtilityFunction(std::string{kLoaderDecls}, kName,
677  context);
678  if (!function) {
679  std::string error = llvm::toString(function.takeError());
680  status.SetErrorStringWithFormat("LoadLibrary error: could not create utility function: %s",
681  error.c_str());
682  return nullptr;
683  }
684 
686  if (!ast)
687  return nullptr;
688 
691 
692  ValueList parameters;
693 
694  Value value;
696 
697  value.SetCompilerType(WCharPtrTy);
698  parameters.PushValue(value); // name
699  parameters.PushValue(value); // paths
700 
701  value.SetCompilerType(VoidPtrTy);
702  parameters.PushValue(value); // result
703 
704  Status error;
705  std::unique_ptr<UtilityFunction> utility{std::move(*function)};
706  utility->MakeFunctionCaller(VoidPtrTy, parameters, context.GetThreadSP(),
707  error);
708  if (error.Fail()) {
709  status.SetErrorStringWithFormat("LoadLibrary error: could not create function caller: %s",
710  error.AsCString());
711  return nullptr;
712  }
713 
714  if (!utility->GetFunctionCaller()) {
715  status.SetErrorString("LoadLibrary error: could not get function caller");
716  return nullptr;
717  }
718 
719  return utility;
720 }
721 
723  const char *expression,
724  ValueObjectSP &value) {
725  // FIXME(compnerd) `-fdeclspec` is not passed to the clang instance?
726  static constexpr const char kLoaderDecls[] = R"(
727 extern "C" {
728 // libloaderapi.h
729 
730 // WINBASEAPI DLL_DIRECTORY_COOKIE WINAPI AddDllDirectory(LPCWSTR);
731 /* __declspec(dllimport) */ void * __stdcall AddDllDirectory(const wchar_t *);
732 
733 // WINBASEAPI BOOL WINAPI FreeModule(HMODULE);
734 /* __declspec(dllimport) */ int __stdcall FreeModule(void *);
735 
736 // WINBASEAPI DWORD WINAPI GetModuleFileNameA(HMODULE, LPSTR, DWORD);
737 /* __declspec(dllimport) */ uint32_t GetModuleFileNameA(void *, char *, uint32_t);
738 
739 // WINBASEAPI HMODULE WINAPI LoadLibraryExW(LPCWSTR, HANDLE, DWORD);
740 /* __declspec(dllimport) */ void * __stdcall LoadLibraryExW(const wchar_t *, void *, uint32_t);
741 }
742  )";
743 
744  if (DynamicLoader *loader = process->GetDynamicLoader()) {
745  Status result = loader->CanLoadImage();
746  if (result.Fail())
747  return result;
748  }
749 
750  ThreadSP thread = process->GetThreadList().GetExpressionExecutionThread();
751  if (!thread)
752  return Status("selected thread is invalid");
753 
754  StackFrameSP frame = thread->GetStackFrameAtIndex(0);
755  if (!frame)
756  return Status("frame 0 is invalid");
757 
758  ExecutionContext context;
759  frame->CalculateExecutionContext(context);
760 
762  options.SetUnwindOnError(true);
763  options.SetIgnoreBreakpoints(true);
766  // LoadLibraryEx{A,W}/FreeLibrary cannot raise exceptions which we can handle.
767  // They may potentially throw SEH exceptions which we do not know how to
768  // handle currently.
769  options.SetTrapExceptions(false);
770  options.SetTimeout(process->GetUtilityExpressionTimeout());
771 
772  Status error;
774  context, options, expression, kLoaderDecls, value, error);
775  if (result != eExpressionCompleted)
776  return error;
777 
778  if (value->GetError().Fail())
779  return value->GetError();
780 
781  return Status();
782 }
lldb_private::toString
const char * toString(AppleArm64ExceptionClass EC)
Definition: AppleArm64ExceptionClass.h:38
lldb_private::UtilityFunction::GetFunctionCaller
FunctionCaller * GetFunctionCaller()
Definition: UtilityFunction.h:111
lldb_private::Value::ValueType::Scalar
@ Scalar
A raw scalar value.
lldb_private::ExecutionContext
Definition: ExecutionContext.h:292
lldb_private::ExecutionContext::GetThreadSP
const lldb::ThreadSP & GetThreadSP() const
Get accessor to get the thread shared pointer.
Definition: ExecutionContext.h:464
lldb_private::Process::AllocateMemory
lldb::addr_t AllocateMemory(size_t size, uint32_t permissions, Status &error)
The public interface to allocating memory in the process.
Definition: Process.cpp:2263
lldb_private::ArchSpec
Definition: ArchSpec.h:32
lldb_private::Process::DeallocateMemory
Status DeallocateMemory(lldb::addr_t ptr)
The public interface to deallocating memory in the process.
Definition: Process.cpp:2334
LLDB_INVALID_PROCESS_ID
#define LLDB_INVALID_PROCESS_ID
Definition: lldb-defines.h:81
FunctionCaller.h
lldb_private::ArchSpec::GetMachine
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
Definition: ArchSpec.cpp:666
lldb_private::EvaluateExpressionOptions::SetTimeout
void SetTimeout(const Timeout< std::micro > &timeout)
Definition: Target.h:345
lldb_private::EvaluateExpressionOptions::SetLanguage
void SetLanguage(lldb::LanguageType language)
Definition: Target.h:305
lldb_private::Value
Definition: Value.h:38
lldb_private::Value::SetValueType
void SetValueType(ValueType value_type)
Definition: Value.h:89
lldb::ExpressionResults
ExpressionResults
The results of expression evaluation.
Definition: lldb-enumerations.h:270
lldb_private::ValueList::GetValueAtIndex
Value * GetValueAtIndex(size_t idx)
Definition: Value.cpp:669
lldb_private::ProcessProperties::GetUtilityExpressionTimeout
std::chrono::seconds GetUtilityExpressionTimeout() const
Definition: Process.cpp:308
lldb_private::Scalar
Definition: Scalar.h:34
lldb_private::Process
Definition: Process.h:338
lldb_private::EvaluateExpressionOptions::SetExecutionPolicy
void SetExecutionPolicy(ExecutionPolicy policy=eExecutionPolicyAlways)
Definition: Target.h:299
lldb_private::EvaluateExpressionOptions::SetIsForUtilityExpr
void SetIsForUtilityExpr(bool b)
Definition: Target.h:432
Module.h
lldb_private::Process::GetThreadList
ThreadList & GetThreadList()
Definition: Process.h:2086
BreakpointLocation.h
lldb_private::Process::GetTarget
Target & GetTarget()
Get the target object pointer for this module.
Definition: Process.h:1219
word_size
static const size_t word_size
Definition: ABISysV_arc.cpp:170
lldb_private::PlatformWindows::EvaluateLoaderExpression
lldb_private::Status EvaluateLoaderExpression(lldb_private::Process *process, const char *expression, lldb::ValueObjectSP &value)
Definition: PlatformWindows.cpp:722
lldb_private::EvaluateExpressionOptions::SetTrapExceptions
void SetTrapExceptions(bool b)
Definition: Target.h:381
lldb_private::EvaluateExpressionOptions
Definition: Target.h:277
PlatformRemoteGDBServer.h
lldb_private::PlatformWindows::DisconnectRemote
lldb_private::Status DisconnectRemote() override
Definition: PlatformWindows.cpp:440
lldb_private::ProcessInfo::GetProcessID
lldb::pid_t GetProcessID() const
Definition: ProcessInfo.h:66
UserExpression.h
lldb_private::ValueList
Definition: Value.h:157
lldb_private::ProcessLaunchInfo::GetFlags
Flags & GetFlags()
Definition: ProcessLaunchInfo.h:64
lldb_private::UserExpression::Evaluate
static lldb::ExpressionResults Evaluate(ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, llvm::StringRef expr_cstr, llvm::StringRef expr_prefix, lldb::ValueObjectSP &result_valobj_sp, Status &error, std::string *fixed_expression=nullptr, ValueObject *ctx_obj=nullptr)
Evaluate one expression in the scratch context of the target passed in the exe_ctx and return its res...
Definition: UserExpression.cpp:146
lldb_private::Stream
Definition: Stream.h:28
lldb_private::Process::ReadCStringFromMemory
size_t ReadCStringFromMemory(lldb::addr_t vm_addr, char *cstr, size_t cstr_max_len, Status &error)
Read a NULL terminated C string from memory.
Definition: Process.cpp:1988
lldb_private::Args
Definition: Args.h:33
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
lldb_private::eExecutionPolicyAlways
@ eExecutionPolicyAlways
Definition: lldb-private-enumerations.h:141
lldb_private::Process::WriteMemory
size_t WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, Status &error)
Write memory to a process.
Definition: Process.cpp:2121
Debugger.h
lldb_private::Target
Definition: Target.h:469
lldb_private::PlatformWindows::GetSoftwareBreakpointTrapOpcode
size_t GetSoftwareBreakpointTrapOpcode(Target &target, BreakpointSite *bp_site) override
Definition: PlatformWindows.cpp:565
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:205
lldb_private::StreamString::GetString
llvm::StringRef GetString() const
Definition: StreamString.cpp:51
lldb_private::DiagnosticManager::GetString
std::string GetString(char separator='\n')
Definition: DiagnosticManager.cpp:47
Process.h
lldb_private::ProcessAttachInfo::GetListenerForProcess
lldb::ListenerSP GetListenerForProcess(Debugger &debugger)
Definition: Process.cpp:2756
PlatformWindows.h
lldb_private::Value::SetCompilerType
void SetCompilerType(const CompilerType &compiler_type)
Definition: Value.cpp:251
lldb_private::FunctionCaller::DeallocateFunctionResults
void DeallocateFunctionResults(ExecutionContext &exe_ctx, lldb::addr_t args_addr)
Deallocate the arguments structure.
Definition: FunctionCaller.cpp:302
lldb_private::Value::GetScalar
const Scalar & GetScalar() const
Definition: Value.h:112
lldb_private::FileSpec
Definition: FileSpec.h:55
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
g_initialize_count
static uint32_t g_initialize_count
Definition: PlatformWindows.cpp:41
lldb_private::ValueList::PushValue
void PushValue(const Value &value)
Definition: Value.cpp:665
lldb_private::BreakpointSite
Definition: BreakpointSite.h:35
lldb_private::FunctionCaller::WriteFunctionArguments
bool WriteFunctionArguments(ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, DiagnosticManager &diagnostic_manager)
Insert the default function argument struct.
Definition: FunctionCaller.cpp:117
lldb_private::ProcessLaunchInfo
Definition: ProcessLaunchInfo.h:31
TypeSystemClang.h
lldb_private::ConstString::IsEmpty
bool IsEmpty() const
Test for empty string.
Definition: ConstString.h:303
lldb_private::eLoadDependentsNo
@ eLoadDependentsNo
Definition: lldb-private-enumerations.h:231
lldb_private::Status::GetError
ValueType GetError() const
Access the error value.
Definition: Status.cpp:174
lldb_private::Status::Fail
bool Fail() const
Test for error condition.
Definition: Status.cpp:181
lldb_private::StreamString::GetData
const char * GetData() const
Definition: StreamString.h:43
lldb::eExpressionCompleted
@ eExpressionCompleted
Definition: lldb-enumerations.h:271
lldb_private::RemoteAwarePlatform::m_remote_platform_sp
lldb::PlatformSP m_remote_platform_sp
Definition: RemoteAwarePlatform.h:104
lldb_private::Status::SetErrorStringWithFormat
int SetErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Set the current error string to a formatted error string.
Definition: Status.cpp:255
lldb_private::FunctionCaller::GetArgumentValues
ValueList GetArgumentValues() const
Definition: FunctionCaller.h:286
lldb_private::Target::CreateUtilityFunction
llvm::Expected< std::unique_ptr< UtilityFunction > > CreateUtilityFunction(std::string expression, std::string name, lldb::LanguageType language, ExecutionContext &exe_ctx)
Creates and installs a UtilityFunction for the given language.
Definition: Target.cpp:2414
lldb_private::Process::GetAddressByteSize
uint32_t GetAddressByteSize() const
Definition: Process.cpp:3366
lldb_private::ConstString
Definition: ConstString.h:39
lldb_private::PlatformWindows::MakeLoadImageUtilityFunction
std::unique_ptr< lldb_private::UtilityFunction > MakeLoadImageUtilityFunction(lldb_private::ExecutionContext &context, lldb_private::Status &status)
Definition: PlatformWindows.cpp:600
lldb_private::Platform::GetSoftwareBreakpointTrapOpcode
virtual size_t GetSoftwareBreakpointTrapOpcode(Target &target, BreakpointSite *bp_site)
Definition: Platform.cpp:1830
lldb_private::StreamString
Definition: StreamString.h:23
lldb_private::PlatformWindows::ConnectRemote
lldb_private::Status ConnectRemote(lldb_private::Args &args) override
Definition: PlatformWindows.cpp:132
lldb_private::Scalar::UInt
unsigned int UInt(unsigned int fail_value=0) const
Definition: Scalar.cpp:320
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:125
lldb_private::DynamicLoader
Definition: DynamicLoader.h:52
lldb::eBasicTypeVoid
@ eBasicTypeVoid
Definition: lldb-enumerations.h:749
lldb_private::Debugger
Definition: Debugger.h:74
HostInfo.h
lldb_private::Process::GetDynamicLoader
virtual DynamicLoader * GetDynamicLoader()
Get the dynamic loader plug-in for this process.
Definition: Process.cpp:2650
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:40
lldb_private::ArchSpec::IsValid
bool IsValid() const
Tests if this ArchSpec is valid.
Definition: ArchSpec.h:352
lldb_private::EvaluateExpressionOptions::SetUnwindOnError
void SetUnwindOnError(bool unwind=false)
Definition: Target.h:324
lldb_private::platform_gdb_server::PlatformRemoteGDBServer::CreateInstance
static lldb::PlatformSP CreateInstance(bool force, const ArchSpec *arch)
Definition: PlatformRemoteGDBServer.cpp:65
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:199
UtilityFunction.h
lldb_private::PlatformWindows::UnloadImage
lldb_private::Status UnloadImage(lldb_private::Process *process, uint32_t image_token) override
Definition: PlatformWindows.cpp:413
lldb_private::Platform::IsRemote
bool IsRemote() const
Definition: Platform.h:424
lldb_private::FileSpec::Clear
void Clear()
Clears the object state.
Definition: FileSpec.cpp:257
lldb_private::EvaluateExpressionOptions::SetIgnoreBreakpoints
void SetIgnoreBreakpoints(bool ignore=false)
Definition: Target.h:328
lldb_private::PlatformWindows::GetFullNameForDylib
ConstString GetFullNameForDylib(ConstString basename) override
Definition: PlatformWindows.cpp:555
lldb_private::ExecutionContext::GetProcessSP
const lldb::ProcessSP & GetProcessSP() const
Get accessor to get the process shared pointer.
Definition: ExecutionContext.h:459
lldb_private::ProcessLaunchInfo::GetProcessPluginName
const char * GetProcessPluginName() const
Definition: ProcessLaunchInfo.cpp:131
lldb_private::Target::GetArchitecture
const ArchSpec & GetArchitecture() const
Definition: Target.h:989
lldb_private::Status
Definition: Status.h:44
lldb_private::CompilerType::GetPointerType
CompilerType GetPointerType() const
Return a new CompilerType that is a pointer to this type.
Definition: CompilerType.cpp:407
uint32_t
LLDB_INVALID_IMAGE_TOKEN
#define LLDB_INVALID_IMAGE_TOKEN
Definition: lldb-defines.h:77
lldb_private::Process::AddImageToken
size_t AddImageToken(lldb::addr_t image_ptr)
Definition: Process.cpp:5809
lldb_private::ProcessAttachInfo::GetProcessPluginName
const char * GetProcessPluginName() const
Definition: Process.h:149
lldb_private::Status::SetErrorString
void SetErrorString(llvm::StringRef err_str)
Set the current error string to err_str.
Definition: Status.cpp:241
lldb_private::DiagnosticManager
Definition: DiagnosticManager.h:93
lldb_private::ScratchTypeSystemClang::GetForTarget
static TypeSystemClang * GetForTarget(Target &target, llvm::Optional< IsolatedASTKind > ast_kind=DefaultAST, bool create_on_demand=true)
Returns the scratch TypeSystemClang for the given target.
Definition: TypeSystemClang.cpp:9851
windows.h
lldb_private::ProcessLaunchInfo::GetHijackListener
lldb::ListenerSP GetHijackListener() const
Definition: ProcessLaunchInfo.h:131
PluginManager.h
lldb_private::Process::WritePointerToMemory
bool WritePointerToMemory(lldb::addr_t vm_addr, lldb::addr_t ptr_value, Status &error)
Definition: Process.cpp:2093
LLDB_INVALID_ADDRESS
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:74
lldb_private::ConstString::GetCString
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:215
lldb_private::PlatformWindows::GetStatus
void GetStatus(lldb_private::Stream &strm) override
Report the current status for this platform.
Definition: PlatformWindows.cpp:544
lldb_private::CompilerType
Generic representation of a type in a programming language.
Definition: CompilerType.h:33
lldb_private::Stream::Printf
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:107
lldb_private::Process::WriteScalarToMemory
size_t WriteScalarToMemory(lldb::addr_t vm_addr, const Scalar &scalar, size_t size, Status &error)
Write all or part of a scalar value to memory.
Definition: Process.cpp:2203
DiagnosticManager.h
lldb_private::DiagnosticManager::Clear
void Clear()
Definition: DiagnosticManager.h:95
Status.h
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:506
lldb_private::FunctionCaller::ExecuteFunction
lldb::ExpressionResults ExecuteFunction(ExecutionContext &exe_ctx, lldb::addr_t *args_addr_ptr, const EvaluateExpressionOptions &options, DiagnosticManager &diagnostic_manager, Value &results)
Run the function this FunctionCaller was created with.
Definition: FunctionCaller.cpp:313
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::Process::GetImagePtrFromToken
lldb::addr_t GetImagePtrFromToken(size_t token) const
Definition: Process.cpp:5814
lldb_private::TypeSystemClang::GetBasicType
CompilerType GetBasicType(lldb::BasicType type)
Definition: TypeSystemClang.cpp:931
lldb_private::PlatformWindows::m_supported_architectures
std::vector< ArchSpec > m_supported_architectures
Definition: PlatformWindows.h:83
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::TypeSystemClang
A TypeSystem implementation based on Clang.
Definition: TypeSystemClang.h:106
lldb_private::PlatformWindows::DoLoadImage
uint32_t DoLoadImage(lldb_private::Process *process, const lldb_private::FileSpec &remote_file, const std::vector< std::string > *paths, lldb_private::Status &error, lldb_private::FileSpec *loaded_path) override
Definition: PlatformWindows.cpp:163
lldb_private::Platform::GetStatus
virtual void GetStatus(Stream &strm)
Report the current status for this platform.
Definition: Platform.cpp:285
BreakpointSite.h
lldb_private::Process::ReadUnsignedIntegerFromMemory
uint64_t ReadUnsignedIntegerFromMemory(lldb::addr_t load_addr, size_t byte_size, uint64_t fail_value, Status &error)
Reads an unsigned integer of the specified byte size from process memory.
Definition: Process.cpp:2063
LLDB_PLUGIN_DEFINE
#define LLDB_PLUGIN_DEFINE(PluginName)
Definition: PluginManager.h:31
lldb_private::FileSpec::SetFile
void SetFile(llvm::StringRef path, Style style)
Change the file specified with a new path.
Definition: FileSpec.cpp:172
lldb_private::Process::ReadPointerFromMemory
lldb::addr_t ReadPointerFromMemory(lldb::addr_t vm_addr, Status &error)
Definition: Process.cpp:2085
lldb_private::Platform::IsHost
bool IsHost() const
Definition: Platform.h:420
lldb_private::FileSpec::GetPath
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:364
lldb_private::ProcessAttachInfo::GetHijackListener
lldb::ListenerSP GetHijackListener() const
Definition: Process.h:176
lldb_private::Process::GetLoadImageUtilityFunction
UtilityFunction * GetLoadImageUtilityFunction(Platform *platform, llvm::function_ref< std::unique_ptr< UtilityFunction >()> factory)
Get the cached UtilityFunction that assists in loading binary images into the process.
Definition: Process.cpp:6036
DynamicLoader.h
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::ThreadList::GetExpressionExecutionThread
lldb::ThreadSP GetExpressionExecutionThread()
Definition: ThreadList.cpp:60
lldb::eBasicTypeWChar
@ eBasicTypeWChar
Definition: lldb-enumerations.h:753
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:456
lldb_private::UtilityFunction
Definition: UtilityFunction.h:30
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:553
lldb_private::Status::AsCString
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
Definition: Status.cpp:130
lldb_private::FunctionCaller
Definition: FunctionCaller.h:56
lldb_private::Process::ResetImageToken
void ResetImageToken(size_t token)
Definition: Process.cpp:5820
lldb::eLanguageTypeC_plus_plus
@ eLanguageTypeC_plus_plus
ISO C++:1998.
Definition: lldb-enumerations.h:441