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