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(ArchSpec("i686-pc-windows"));
128  AddArch(HostInfo::GetArchitecture(HostInfo::eArchKindDefault));
129  AddArch(HostInfo::GetArchitecture(HostInfo::eArchKind32));
130  AddArch(HostInfo::GetArchitecture(HostInfo::eArchKind64));
131  AddArch(ArchSpec("i386-pc-windows"));
132 }
133 
135  Status error;
136  if (IsHost()) {
137  error.SetErrorStringWithFormatv(
138  "can't connect to the host platform '{0}', always connected",
139  GetPluginName());
140  } else {
144  /*force=*/true, nullptr);
145 
146  if (m_remote_platform_sp) {
147  if (error.Success()) {
148  if (m_remote_platform_sp) {
149  error = m_remote_platform_sp->ConnectRemote(args);
150  } else {
151  error.SetErrorString(
152  "\"platform connect\" takes a single argument: <connect-url>");
153  }
154  }
155  } else
156  error.SetErrorString("failed to create a 'remote-gdb-server' platform");
157 
158  if (error.Fail())
159  m_remote_platform_sp.reset();
160  }
161 
162  return error;
163 }
164 
166  const FileSpec &remote_file,
167  const std::vector<std::string> *paths,
168  Status &error, FileSpec *loaded_image) {
169  DiagnosticManager diagnostics;
170 
171  if (loaded_image)
172  loaded_image->Clear();
173 
174  ThreadSP thread = process->GetThreadList().GetExpressionExecutionThread();
175  if (!thread) {
176  error.SetErrorString("LoadLibrary error: no thread available to invoke LoadLibrary");
178  }
179 
180  ExecutionContext context;
181  thread->CalculateExecutionContext(context);
182 
183  Status status;
184  UtilityFunction *loader =
185  process->GetLoadImageUtilityFunction(this, [&]() -> std::unique_ptr<UtilityFunction> {
186  return MakeLoadImageUtilityFunction(context, status);
187  });
188  if (loader == nullptr)
190 
191  FunctionCaller *invocation = loader->GetFunctionCaller();
192  if (!invocation) {
193  error.SetErrorString("LoadLibrary error: could not get function caller");
195  }
196 
197  /* Convert name */
198  llvm::SmallVector<llvm::UTF16, 261> name;
199  if (!llvm::convertUTF8ToUTF16String(remote_file.GetPath(), name)) {
200  error.SetErrorString("LoadLibrary error: could not convert path to UCS2");
202  }
203  name.emplace_back(L'\0');
204 
205  /* Inject name paramter into inferior */
206  lldb::addr_t injected_name =
207  process->AllocateMemory(name.size() * sizeof(llvm::UTF16),
208  ePermissionsReadable | ePermissionsWritable,
209  status);
210  if (injected_name == LLDB_INVALID_ADDRESS) {
211  error.SetErrorStringWithFormat("LoadLibrary error: unable to allocate memory for name: %s",
212  status.AsCString());
214  }
215 
216  auto name_cleanup = llvm::make_scope_exit([process, injected_name]() {
217  process->DeallocateMemory(injected_name);
218  });
219 
220  process->WriteMemory(injected_name, name.data(),
221  name.size() * sizeof(llvm::UTF16), status);
222  if (status.Fail()) {
223  error.SetErrorStringWithFormat("LoadLibrary error: unable to write name: %s",
224  status.AsCString());
226  }
227 
228  /* Inject paths parameter into inferior */
229  lldb::addr_t injected_paths{0x0};
230  llvm::Optional<llvm::detail::scope_exit<std::function<void()>>> paths_cleanup;
231  if (paths) {
232  llvm::SmallVector<llvm::UTF16, 261> search_paths;
233 
234  for (const auto &path : *paths) {
235  if (path.empty())
236  continue;
237 
238  llvm::SmallVector<llvm::UTF16, 261> buffer;
239  if (!llvm::convertUTF8ToUTF16String(path, buffer))
240  continue;
241 
242  search_paths.append(std::begin(buffer), std::end(buffer));
243  search_paths.emplace_back(L'\0');
244  }
245  search_paths.emplace_back(L'\0');
246 
247  injected_paths =
248  process->AllocateMemory(search_paths.size() * sizeof(llvm::UTF16),
249  ePermissionsReadable | ePermissionsWritable,
250  status);
251  if (injected_paths == LLDB_INVALID_ADDRESS) {
252  error.SetErrorStringWithFormat("LoadLibrary error: unable to allocate memory for paths: %s",
253  status.AsCString());
255  }
256 
257  paths_cleanup.emplace([process, injected_paths]() {
258  process->DeallocateMemory(injected_paths);
259  });
260 
261  process->WriteMemory(injected_paths, search_paths.data(),
262  search_paths.size() * sizeof(llvm::UTF16), status);
263  if (status.Fail()) {
264  error.SetErrorStringWithFormat("LoadLibrary error: unable to write paths: %s",
265  status.AsCString());
267  }
268  }
269 
270  /* Inject wszModulePath into inferior */
271  // FIXME(compnerd) should do something better for the length?
272  // GetModuleFileNameA is likely limited to PATH_MAX rather than the NT path
273  // limit.
274  unsigned injected_length = 261;
275 
276  lldb::addr_t injected_module_path =
277  process->AllocateMemory(injected_length + 1,
278  ePermissionsReadable | ePermissionsWritable,
279  status);
280  if (injected_module_path == LLDB_INVALID_ADDRESS) {
281  error.SetErrorStringWithFormat("LoadLibrary error: unable to allocate memory for module location: %s",
282  status.AsCString());
284  }
285 
286  auto injected_module_path_cleanup =
287  llvm::make_scope_exit([process, injected_module_path]() {
288  process->DeallocateMemory(injected_module_path);
289  });
290 
291  /* Inject __lldb_LoadLibraryResult into inferior */
292  const uint32_t word_size = process->GetAddressByteSize();
293  lldb::addr_t injected_result =
294  process->AllocateMemory(3 * word_size,
295  ePermissionsReadable | ePermissionsWritable,
296  status);
297  if (status.Fail()) {
298  error.SetErrorStringWithFormat("LoadLibrary error: could not allocate memory for result: %s",
299  status.AsCString());
301  }
302 
303  auto result_cleanup = llvm::make_scope_exit([process, injected_result]() {
304  process->DeallocateMemory(injected_result);
305  });
306 
307  process->WritePointerToMemory(injected_result + word_size,
308  injected_module_path, status);
309  if (status.Fail()) {
310  error.SetErrorStringWithFormat("LoadLibrary error: could not initialize result: %s",
311  status.AsCString());
313  }
314 
315  // XXX(compnerd) should we use the compiler to get the sizeof(unsigned)?
316  process->WriteScalarToMemory(injected_result + 2 * word_size,
317  Scalar{injected_length}, sizeof(unsigned),
318  status);
319  if (status.Fail()) {
320  error.SetErrorStringWithFormat("LoadLibrary error: could not initialize result: %s",
321  status.AsCString());
323  }
324 
325  /* Setup Formal Parameters */
326  ValueList parameters = invocation->GetArgumentValues();
327  parameters.GetValueAtIndex(0)->GetScalar() = injected_name;
328  parameters.GetValueAtIndex(1)->GetScalar() = injected_paths;
329  parameters.GetValueAtIndex(2)->GetScalar() = injected_result;
330 
331  lldb::addr_t injected_parameters = LLDB_INVALID_ADDRESS;
332  diagnostics.Clear();
333  if (!invocation->WriteFunctionArguments(context, injected_parameters,
334  parameters, diagnostics)) {
335  error.SetErrorStringWithFormat("LoadLibrary error: unable to write function parameters: %s",
336  diagnostics.GetString().c_str());
338  }
339 
340  auto parameter_cleanup = llvm::make_scope_exit([invocation, &context, injected_parameters]() {
341  invocation->DeallocateFunctionResults(context, injected_parameters);
342  });
343 
344  TypeSystemClang *ast =
346  if (!ast) {
347  error.SetErrorString("LoadLibrary error: unable to get (clang) type system");
349  }
350 
351  /* Setup Return Type */
352  CompilerType VoidPtrTy = ast->GetBasicType(eBasicTypeVoid).GetPointerType();
353 
354  Value value;
355  value.SetCompilerType(VoidPtrTy);
356 
357  /* Invoke expression */
361  options.SetIgnoreBreakpoints(true);
362  options.SetUnwindOnError(true);
363  // LoadLibraryEx{A,W}/FreeLibrary cannot raise exceptions which we can handle.
364  // They may potentially throw SEH exceptions which we do not know how to
365  // handle currently.
366  options.SetTrapExceptions(false);
367  options.SetTimeout(process->GetUtilityExpressionTimeout());
368  options.SetIsForUtilityExpr(true);
369 
370  ExpressionResults result =
371  invocation->ExecuteFunction(context, &injected_parameters, options,
372  diagnostics, value);
373  if (result != eExpressionCompleted) {
374  error.SetErrorStringWithFormat("LoadLibrary error: failed to execute LoadLibrary helper: %s",
375  diagnostics.GetString().c_str());
377  }
378 
379  /* Read result */
380  lldb::addr_t token = process->ReadPointerFromMemory(injected_result, status);
381  if (status.Fail()) {
382  error.SetErrorStringWithFormat("LoadLibrary error: could not read the result: %s",
383  status.AsCString());
385  }
386 
387  if (!token) {
388  // XXX(compnerd) should we use the compiler to get the sizeof(unsigned)?
389  uint64_t error_code =
390  process->ReadUnsignedIntegerFromMemory(injected_result + 2 * word_size + sizeof(unsigned),
391  word_size, 0, status);
392  if (status.Fail()) {
393  error.SetErrorStringWithFormat("LoadLibrary error: could not read error status: %s",
394  status.AsCString());
396  }
397 
398  error.SetErrorStringWithFormat("LoadLibrary Error: %" PRIu64, error_code);
400  }
401 
402  std::string module_path;
403  process->ReadCStringFromMemory(injected_module_path, module_path, status);
404  if (status.Fail()) {
405  error.SetErrorStringWithFormat("LoadLibrary error: could not read module path: %s",
406  status.AsCString());
408  }
409 
410  if (loaded_image)
411  loaded_image->SetFile(module_path, llvm::sys::path::Style::native);
412  return process->AddImageToken(token);
413 }
414 
416  const addr_t address = process->GetImagePtrFromToken(image_token);
417  if (address == LLDB_INVALID_ADDRESS)
418  return Status("invalid image token");
419 
420  StreamString expression;
421  expression.Printf("FreeLibrary((HMODULE)0x%" PRIx64 ")", address);
422 
423  ValueObjectSP value;
424  Status result =
425  EvaluateLoaderExpression(process, expression.GetData(), value);
426  if (result.Fail())
427  return result;
428 
429  if (value->GetError().Fail())
430  return value->GetError();
431 
432  Scalar scalar;
433  if (value->ResolveValue(scalar)) {
434  if (scalar.UInt(1))
435  return Status("expression failed: \"%s\"", expression.GetData());
436  process->ResetImageToken(image_token);
437  }
438 
439  return Status();
440 }
441 
443  Status error;
444 
445  if (IsHost()) {
446  error.SetErrorStringWithFormatv(
447  "can't disconnect from the host platform '{0}', always connected",
448  GetPluginName());
449  } else {
451  error = m_remote_platform_sp->DisconnectRemote();
452  else
453  error.SetErrorString("the platform is not currently connected");
454  }
455  return error;
456 }
457 
459  Debugger &debugger, Target &target,
460  Status &error) {
461  // Windows has special considerations that must be followed when launching or
462  // attaching to a process. The key requirement is that when launching or
463  // attaching to a process, you must do it from the same the thread that will
464  // go into a permanent loop which will then receive debug events from the
465  // process. In particular, this means we can't use any of LLDB's generic
466  // mechanisms to do it for us, because it doesn't have the special knowledge
467  // required for setting up the background thread or passing the right flags.
468  //
469  // Another problem is that that LLDB's standard model for debugging a process
470  // is to first launch it, have it stop at the entry point, and then attach to
471  // it. In Windows this doesn't quite work, you have to specify as an
472  // argument to CreateProcess() that you're going to debug the process. So we
473  // override DebugProcess here to handle this. Launch operations go directly
474  // to the process plugin, and attach operations almost go directly to the
475  // process plugin (but we hijack the events first). In essence, we
476  // encapsulate all the logic of Launching and Attaching in the process
477  // plugin, and PlatformWindows::DebugProcess is just a pass-through to get to
478  // the process plugin.
479 
480  if (IsRemote()) {
482  return m_remote_platform_sp->DebugProcess(launch_info, debugger, target,
483  error);
484  else
485  error.SetErrorString("the platform is not currently connected");
486  }
487 
488  if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) {
489  // This is a process attach. Don't need to launch anything.
490  ProcessAttachInfo attach_info(launch_info);
491  return Attach(attach_info, debugger, &target, error);
492  }
493 
494  ProcessSP process_sp =
495  target.CreateProcess(launch_info.GetListener(),
496  launch_info.GetProcessPluginName(), nullptr, false);
497 
498  process_sp->HijackProcessEvents(launch_info.GetHijackListener());
499 
500  // We need to launch and attach to the process.
501  launch_info.GetFlags().Set(eLaunchFlagDebug);
502  if (process_sp)
503  error = process_sp->Launch(launch_info);
504 
505  return process_sp;
506 }
507 
508 lldb::ProcessSP PlatformWindows::Attach(ProcessAttachInfo &attach_info,
509  Debugger &debugger, Target *target,
510  Status &error) {
511  error.Clear();
512  lldb::ProcessSP process_sp;
513  if (!IsHost()) {
515  process_sp =
516  m_remote_platform_sp->Attach(attach_info, debugger, target, error);
517  else
518  error.SetErrorString("the platform is not currently connected");
519  return process_sp;
520  }
521 
522  if (target == nullptr) {
523  TargetSP new_target_sp;
524  FileSpec emptyFileSpec;
525  ArchSpec emptyArchSpec;
526 
527  error = debugger.GetTargetList().CreateTarget(
528  debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp);
529  target = new_target_sp.get();
530  }
531 
532  if (!target || error.Fail())
533  return process_sp;
534 
535  const char *plugin_name = attach_info.GetProcessPluginName();
536  process_sp = target->CreateProcess(
537  attach_info.GetListenerForProcess(debugger), plugin_name, nullptr, false);
538 
539  process_sp->HijackProcessEvents(attach_info.GetHijackListener());
540  if (process_sp)
541  error = process_sp->Attach(attach_info);
542 
543  return process_sp;
544 }
545 
547  Platform::GetStatus(strm);
548 
549 #ifdef _WIN32
550  llvm::VersionTuple version = HostInfo::GetOSVersion();
551  strm << " Host: Windows " << version.getAsString() << '\n';
552 #endif
553 }
554 
555 bool PlatformWindows::CanDebugProcess() { return true; }
556 
558  if (basename.IsEmpty())
559  return basename;
560 
561  StreamString stream;
562  stream.Printf("%s.dll", basename.GetCString());
563  return ConstString(stream.GetString());
564 }
565 
566 size_t
568  BreakpointSite *bp_site) {
569  ArchSpec arch = target.GetArchitecture();
570  assert(arch.IsValid());
571  const uint8_t *trap_opcode = nullptr;
572  size_t trap_opcode_size = 0;
573 
574  switch (arch.GetMachine()) {
575  case llvm::Triple::aarch64: {
576  static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x3e, 0xd4}; // brk #0xf000
577  trap_opcode = g_aarch64_opcode;
578  trap_opcode_size = sizeof(g_aarch64_opcode);
579 
580  if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
581  return trap_opcode_size;
582  return 0;
583  } break;
584 
585  case llvm::Triple::arm:
586  case llvm::Triple::thumb: {
587  static const uint8_t g_thumb_opcode[] = {0xfe, 0xde}; // udf #0xfe
588  trap_opcode = g_thumb_opcode;
589  trap_opcode_size = sizeof(g_thumb_opcode);
590 
591  if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
592  return trap_opcode_size;
593  return 0;
594  } break;
595 
596  default:
597  return Platform::GetSoftwareBreakpointTrapOpcode(target, bp_site);
598  }
599 }
600 
601 std::unique_ptr<UtilityFunction>
603  Status &status) {
604  // FIXME(compnerd) `-fdeclspec` is not passed to the clang instance?
605  static constexpr const char kLoaderDecls[] = R"(
606 extern "C" {
607 // errhandlingapi.h
608 
609 // `LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32 | LOAD_LIBRARY_SEARCH_USER_DIRS`
610 //
611 // Directories in the standard search path are not searched. This value cannot
612 // be combined with `LOAD_WITH_ALTERED_SEARCH_PATH`.
613 //
614 // This value represents the recommended maximum number of directories an
615 // application should include in its DLL search path.
616 #define LOAD_LIBRARY_SEARCH_DEFAULT_DIRS 0x00001000
617 
618 // WINBASEAPI DWORD WINAPI GetLastError(VOID);
619 /* __declspec(dllimport) */ uint32_t __stdcall GetLastError();
620 
621 // libloaderapi.h
622 
623 // WINBASEAPI DLL_DIRECTORY_COOKIE WINAPI AddDllDirectory(LPCWSTR);
624 /* __declspec(dllimport) */ void * __stdcall AddDllDirectory(const wchar_t *);
625 
626 // WINBASEAPI BOOL WINAPI FreeModule(HMODULE);
627 /* __declspec(dllimport) */ int __stdcall FreeModule(void *hLibModule);
628 
629 // WINBASEAPI DWORD WINAPI GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize);
630 /* __declspec(dllimport) */ uint32_t GetModuleFileNameA(void *, char *, uint32_t);
631 
632 // WINBASEAPI HMODULE WINAPI LoadLibraryExW(LPCWSTR, HANDLE, DWORD);
633 /* __declspec(dllimport) */ void * __stdcall LoadLibraryExW(const wchar_t *, void *, uint32_t);
634 
635 // corecrt_wstring.h
636 
637 // _ACRTIMP size_t __cdecl wcslen(wchar_t const *_String);
638 /* __declspec(dllimport) */ size_t __cdecl wcslen(const wchar_t *);
639 
640 // lldb specific code
641 
642 struct __lldb_LoadLibraryResult {
643  void *ImageBase;
644  char *ModulePath;
645  unsigned Length;
646  unsigned ErrorCode;
647 };
648 
649 _Static_assert(sizeof(struct __lldb_LoadLibraryResult) <= 3 * sizeof(void *),
650  "__lldb_LoadLibraryResult size mismatch");
651 
652 void * __lldb_LoadLibraryHelper(const wchar_t *name, const wchar_t *paths,
653  __lldb_LoadLibraryResult *result) {
654  for (const wchar_t *path = paths; path && *path; ) {
655  (void)AddDllDirectory(path);
656  path += wcslen(path) + 1;
657  }
658 
659  result->ImageBase = LoadLibraryExW(name, nullptr,
660  LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
661  if (result->ImageBase == nullptr)
662  result->ErrorCode = GetLastError();
663  else
664  result->Length = GetModuleFileNameA(result->ImageBase, result->ModulePath,
665  result->Length);
666 
667  return result->ImageBase;
668 }
669 }
670  )";
671 
672  static constexpr const char kName[] = "__lldb_LoadLibraryHelper";
673 
674  ProcessSP process = context.GetProcessSP();
675  Target &target = process->GetTarget();
676 
677  auto function = target.CreateUtilityFunction(std::string{kLoaderDecls}, kName,
679  context);
680  if (!function) {
681  std::string error = llvm::toString(function.takeError());
682  status.SetErrorStringWithFormat("LoadLibrary error: could not create utility function: %s",
683  error.c_str());
684  return nullptr;
685  }
686 
688  if (!ast)
689  return nullptr;
690 
693 
694  ValueList parameters;
695 
696  Value value;
698 
699  value.SetCompilerType(WCharPtrTy);
700  parameters.PushValue(value); // name
701  parameters.PushValue(value); // paths
702 
703  value.SetCompilerType(VoidPtrTy);
704  parameters.PushValue(value); // result
705 
706  Status error;
707  std::unique_ptr<UtilityFunction> utility{std::move(*function)};
708  utility->MakeFunctionCaller(VoidPtrTy, parameters, context.GetThreadSP(),
709  error);
710  if (error.Fail()) {
711  status.SetErrorStringWithFormat("LoadLibrary error: could not create function caller: %s",
712  error.AsCString());
713  return nullptr;
714  }
715 
716  if (!utility->GetFunctionCaller()) {
717  status.SetErrorString("LoadLibrary error: could not get function caller");
718  return nullptr;
719  }
720 
721  return utility;
722 }
723 
725  const char *expression,
726  ValueObjectSP &value) {
727  // FIXME(compnerd) `-fdeclspec` is not passed to the clang instance?
728  static constexpr const char kLoaderDecls[] = R"(
729 extern "C" {
730 // libloaderapi.h
731 
732 // WINBASEAPI DLL_DIRECTORY_COOKIE WINAPI AddDllDirectory(LPCWSTR);
733 /* __declspec(dllimport) */ void * __stdcall AddDllDirectory(const wchar_t *);
734 
735 // WINBASEAPI BOOL WINAPI FreeModule(HMODULE);
736 /* __declspec(dllimport) */ int __stdcall FreeModule(void *);
737 
738 // WINBASEAPI DWORD WINAPI GetModuleFileNameA(HMODULE, LPSTR, DWORD);
739 /* __declspec(dllimport) */ uint32_t GetModuleFileNameA(void *, char *, uint32_t);
740 
741 // WINBASEAPI HMODULE WINAPI LoadLibraryExW(LPCWSTR, HANDLE, DWORD);
742 /* __declspec(dllimport) */ void * __stdcall LoadLibraryExW(const wchar_t *, void *, uint32_t);
743 }
744  )";
745 
746  if (DynamicLoader *loader = process->GetDynamicLoader()) {
747  Status result = loader->CanLoadImage();
748  if (result.Fail())
749  return result;
750  }
751 
752  ThreadSP thread = process->GetThreadList().GetExpressionExecutionThread();
753  if (!thread)
754  return Status("selected thread is invalid");
755 
756  StackFrameSP frame = thread->GetStackFrameAtIndex(0);
757  if (!frame)
758  return Status("frame 0 is invalid");
759 
760  ExecutionContext context;
761  frame->CalculateExecutionContext(context);
762 
764  options.SetUnwindOnError(true);
765  options.SetIgnoreBreakpoints(true);
768  // LoadLibraryEx{A,W}/FreeLibrary cannot raise exceptions which we can handle.
769  // They may potentially throw SEH exceptions which we do not know how to
770  // handle currently.
771  options.SetTrapExceptions(false);
772  options.SetTimeout(process->GetUtilityExpressionTimeout());
773 
774  Status error;
776  context, options, expression, kLoaderDecls, value, error);
777  if (result != eExpressionCompleted)
778  return error;
779 
780  if (value->GetError().Fail())
781  return value->GetError();
782 
783  return Status();
784 }
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:2253
lldb_private::ArchSpec
Definition: ArchSpec.h:33
lldb_private::Process::DeallocateMemory
Status DeallocateMemory(lldb::addr_t ptr)
The public interface to deallocating memory in the process.
Definition: Process.cpp:2324
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:668
lldb_private::EvaluateExpressionOptions::SetTimeout
void SetTimeout(const Timeout< std::micro > &timeout)
Definition: Target.h:340
lldb_private::EvaluateExpressionOptions::SetLanguage
void SetLanguage(lldb::LanguageType language)
Definition: Target.h:300
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:294
lldb_private::EvaluateExpressionOptions::SetIsForUtilityExpr
void SetIsForUtilityExpr(bool b)
Definition: Target.h:427
Module.h
lldb_private::Process::GetThreadList
ThreadList & GetThreadList()
Definition: Process.h:2073
BreakpointLocation.h
lldb_private::Process::GetTarget
Target & GetTarget()
Get the target object pointer for this module.
Definition: Process.h:1206
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:724
lldb_private::EvaluateExpressionOptions::SetTrapExceptions
void SetTrapExceptions(bool b)
Definition: Target.h:376
lldb_private::EvaluateExpressionOptions
Definition: Target.h:272
PlatformRemoteGDBServer.h
lldb_private::PlatformWindows::DisconnectRemote
lldb_private::Status DisconnectRemote() override
Definition: PlatformWindows.cpp:442
lldb_private::ProcessInfo::GetProcessID
lldb::pid_t GetProcessID() const
Definition: ProcessInfo.h:67
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:140
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:1984
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:147
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:2114
Debugger.h
lldb_private::Target
Definition: Target.h:464
lldb_private::PlatformWindows::GetSoftwareBreakpointTrapOpcode
size_t GetSoftwareBreakpointTrapOpcode(Target &target, BreakpointSite *bp_site) override
Definition: PlatformWindows.cpp:567
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:202
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:2735
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:301
lldb_private::Value::GetScalar
const Scalar & GetScalar() const
Definition: Value.h:112
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: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:116
lldb_private::ProcessLaunchInfo
Definition: ProcessLaunchInfo.h:31
TypeSystemClang.h
lldb_private::ConstString::IsEmpty
bool IsEmpty() const
Test for empty string.
Definition: ConstString.h:304
lldb_private::eLoadDependentsNo
@ eLoadDependentsNo
Definition: Target.h:65
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:2392
lldb_private::Process::GetAddressByteSize
uint32_t GetAddressByteSize() const
Definition: Process.cpp:3323
lldb_private::ConstString
Definition: ConstString.h:40
lldb_private::PlatformWindows::MakeLoadImageUtilityFunction
std::unique_ptr< lldb_private::UtilityFunction > MakeLoadImageUtilityFunction(lldb_private::ExecutionContext &context, lldb_private::Status &status)
Definition: PlatformWindows.cpp:602
lldb_private::Platform::GetSoftwareBreakpointTrapOpcode
virtual size_t GetSoftwareBreakpointTrapOpcode(Target &target, BreakpointSite *bp_site)
Definition: Platform.cpp:1834
lldb_private::StreamString
Definition: StreamString.h:23
lldb_private::PlatformWindows::ConnectRemote
lldb_private::Status ConnectRemote(lldb_private::Args &args) override
Definition: PlatformWindows.cpp:134
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:743
lldb_private::Debugger
Definition: Debugger.h:72
HostInfo.h
lldb_private::Process::GetDynamicLoader
virtual DynamicLoader * GetDynamicLoader()
Get the dynamic loader plug-in for this process.
Definition: Process.cpp:2633
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:353
lldb_private::EvaluateExpressionOptions::SetUnwindOnError
void SetUnwindOnError(bool unwind=false)
Definition: Target.h:319
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:200
UtilityFunction.h
lldb_private::PlatformWindows::UnloadImage
lldb_private::Status UnloadImage(lldb_private::Process *process, uint32_t image_token) override
Definition: PlatformWindows.cpp:415
lldb_private::Platform::IsRemote
bool IsRemote() const
Definition: Platform.h:424
lldb_private::FileSpec::Clear
void Clear()
Clears the object state.
Definition: FileSpec.cpp:259
lldb_private::EvaluateExpressionOptions::SetIgnoreBreakpoints
void SetIgnoreBreakpoints(bool ignore=false)
Definition: Target.h:323
lldb_private::PlatformWindows::GetFullNameForDylib
ConstString GetFullNameForDylib(ConstString basename) override
Definition: PlatformWindows.cpp:557
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:980
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:5766
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:9797
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:2086
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:216
lldb_private::PlatformWindows::GetStatus
void GetStatus(lldb_private::Stream &strm) override
Report the current status for this platform.
Definition: PlatformWindows.cpp:546
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:2193
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:508
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:312
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:5771
lldb_private::TypeSystemClang::GetBasicType
CompilerType GetBasicType(lldb::BasicType type)
Definition: TypeSystemClang.cpp:930
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:105
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:165
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:2056
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:2078
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:347
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:5993
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:747
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:458
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:555
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:5777
lldb::eLanguageTypeC_plus_plus
@ eLanguageTypeC_plus_plus
ISO C++:1998.
Definition: lldb-enumerations.h:441