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
37using namespace lldb;
38using namespace lldb_private;
39
41
42static uint32_t g_initialize_count = 0;
43
44PlatformSP 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
86llvm::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
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
105 }
106}
107
109 if (g_initialize_count > 0) {
110 if (--g_initialize_count == 0) {
112 }
113 }
114
116}
117
118/// Default Constructor
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
135 if (IsHost()) {
137 "can't connect to the host platform '{0}', always connected",
138 GetPluginName());
139 } else {
143 /*force=*/true, nullptr);
144
146 if (error.Success()) {
148 error = m_remote_platform_sp->ConnectRemote(args);
149 } else {
151 "\"platform connect\" takes a single argument: <connect-url>");
152 }
153 }
154 } else
156 "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
175 if (!thread) {
177 "LoadLibrary error: no thread available to invoke LoadLibrary");
179 }
180
181 ExecutionContext context;
182 thread->CalculateExecutionContext(context);
183
184 Status status;
185 UtilityFunction *loader =
186 process->GetLoadImageUtilityFunction(this, [&]() -> std::unique_ptr<UtilityFunction> {
187 return MakeLoadImageUtilityFunction(context, status);
188 });
189 if (loader == nullptr)
191
192 FunctionCaller *invocation = loader->GetFunctionCaller();
193 if (!invocation) {
195 "LoadLibrary error: could not get function caller");
197 }
198
199 /* Convert name */
200 llvm::SmallVector<llvm::UTF16, 261> name;
201 if (!llvm::convertUTF8ToUTF16String(remote_file.GetPath(), name)) {
203 "LoadLibrary error: could not convert path to UCS2");
205 }
206 name.emplace_back(L'\0');
207
208 /* Inject name paramter into inferior */
209 lldb::addr_t injected_name =
210 process->AllocateMemory(name.size() * sizeof(llvm::UTF16),
211 ePermissionsReadable | ePermissionsWritable,
212 status);
213 if (injected_name == LLDB_INVALID_ADDRESS) {
215 "LoadLibrary error: unable to allocate memory for name: %s",
216 status.AsCString());
218 }
219
220 auto name_cleanup = llvm::make_scope_exit([process, injected_name]() {
221 process->DeallocateMemory(injected_name);
222 });
223
224 process->WriteMemory(injected_name, name.data(),
225 name.size() * sizeof(llvm::UTF16), status);
226 if (status.Fail()) {
228 "LoadLibrary error: unable to write name: %s", status.AsCString());
230 }
231
232 /* Inject paths parameter into inferior */
233 lldb::addr_t injected_paths{0x0};
234 std::optional<llvm::detail::scope_exit<std::function<void()>>> paths_cleanup;
235 if (paths) {
236 llvm::SmallVector<llvm::UTF16, 261> search_paths;
237
238 for (const auto &path : *paths) {
239 if (path.empty())
240 continue;
241
242 llvm::SmallVector<llvm::UTF16, 261> buffer;
243 if (!llvm::convertUTF8ToUTF16String(path, buffer))
244 continue;
245
246 search_paths.append(std::begin(buffer), std::end(buffer));
247 search_paths.emplace_back(L'\0');
248 }
249 search_paths.emplace_back(L'\0');
250
251 injected_paths =
252 process->AllocateMemory(search_paths.size() * sizeof(llvm::UTF16),
253 ePermissionsReadable | ePermissionsWritable,
254 status);
255 if (injected_paths == LLDB_INVALID_ADDRESS) {
257 "LoadLibrary error: unable to allocate memory for paths: %s",
258 status.AsCString());
260 }
261
262 paths_cleanup.emplace([process, injected_paths]() {
263 process->DeallocateMemory(injected_paths);
264 });
265
266 process->WriteMemory(injected_paths, search_paths.data(),
267 search_paths.size() * sizeof(llvm::UTF16), status);
268 if (status.Fail()) {
270 "LoadLibrary error: unable to write paths: %s", status.AsCString());
272 }
273 }
274
275 /* Inject wszModulePath into inferior */
276 // FIXME(compnerd) should do something better for the length?
277 // GetModuleFileNameA is likely limited to PATH_MAX rather than the NT path
278 // limit.
279 unsigned injected_length = 261;
280
281 lldb::addr_t injected_module_path =
282 process->AllocateMemory(injected_length + 1,
283 ePermissionsReadable | ePermissionsWritable,
284 status);
285 if (injected_module_path == LLDB_INVALID_ADDRESS) {
287 "LoadLibrary error: unable to allocate memory for module location: %s",
288 status.AsCString());
290 }
291
292 auto injected_module_path_cleanup =
293 llvm::make_scope_exit([process, injected_module_path]() {
294 process->DeallocateMemory(injected_module_path);
295 });
296
297 /* Inject __lldb_LoadLibraryResult into inferior */
298 const uint32_t word_size = process->GetAddressByteSize();
299 lldb::addr_t injected_result =
300 process->AllocateMemory(3 * word_size,
301 ePermissionsReadable | ePermissionsWritable,
302 status);
303 if (status.Fail()) {
305 "LoadLibrary error: could not allocate memory for result: %s",
306 status.AsCString());
308 }
309
310 auto result_cleanup = llvm::make_scope_exit([process, injected_result]() {
311 process->DeallocateMemory(injected_result);
312 });
313
314 process->WritePointerToMemory(injected_result + word_size,
315 injected_module_path, status);
316 if (status.Fail()) {
318 "LoadLibrary error: could not initialize result: %s",
319 status.AsCString());
321 }
322
323 // XXX(compnerd) should we use the compiler to get the sizeof(unsigned)?
324 process->WriteScalarToMemory(injected_result + 2 * word_size,
325 Scalar{injected_length}, sizeof(unsigned),
326 status);
327 if (status.Fail()) {
329 "LoadLibrary error: could not initialize result: %s",
330 status.AsCString());
332 }
333
334 /* Setup Formal Parameters */
335 ValueList parameters = invocation->GetArgumentValues();
336 parameters.GetValueAtIndex(0)->GetScalar() = injected_name;
337 parameters.GetValueAtIndex(1)->GetScalar() = injected_paths;
338 parameters.GetValueAtIndex(2)->GetScalar() = injected_result;
339
340 lldb::addr_t injected_parameters = LLDB_INVALID_ADDRESS;
341 diagnostics.Clear();
342 if (!invocation->WriteFunctionArguments(context, injected_parameters,
343 parameters, diagnostics)) {
344 error = Status::FromError(diagnostics.GetAsError(
346 "LoadLibrary error: unable to write function parameters:"));
348 }
349
350 auto parameter_cleanup =
351 llvm::make_scope_exit([invocation, &context, injected_parameters]() {
352 invocation->DeallocateFunctionResults(context, injected_parameters);
353 });
354
355 TypeSystemClangSP scratch_ts_sp =
357 if (!scratch_ts_sp) {
359 "LoadLibrary error: unable to get (clang) type system");
361 }
362
363 /* Setup Return Type */
364 CompilerType VoidPtrTy =
365 scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType();
366
367 Value value;
368 value.SetCompilerType(VoidPtrTy);
369
370 /* Invoke expression */
374 options.SetIgnoreBreakpoints(true);
375 options.SetUnwindOnError(true);
376 // LoadLibraryEx{A,W}/FreeLibrary cannot raise exceptions which we can handle.
377 // They may potentially throw SEH exceptions which we do not know how to
378 // handle currently.
379 options.SetTrapExceptions(false);
380 options.SetTimeout(process->GetUtilityExpressionTimeout());
381 options.SetIsForUtilityExpr(true);
382
383 ExpressionResults result =
384 invocation->ExecuteFunction(context, &injected_parameters, options,
385 diagnostics, value);
386 if (result != eExpressionCompleted) {
387 error = Status::FromError(diagnostics.GetAsError(
389 "LoadLibrary error: failed to execute LoadLibrary helper:"));
391 }
392
393 /* Read result */
394 lldb::addr_t token = process->ReadPointerFromMemory(injected_result, status);
395 if (status.Fail()) {
397 "LoadLibrary error: could not read the result: %s", status.AsCString());
399 }
400
401 if (!token) {
402 // XXX(compnerd) should we use the compiler to get the sizeof(unsigned)?
403 uint64_t error_code =
404 process->ReadUnsignedIntegerFromMemory(injected_result + 2 * word_size + sizeof(unsigned),
405 word_size, 0, status);
406 if (status.Fail()) {
408 "LoadLibrary error: could not read error status: %s",
409 status.AsCString());
411 }
412
413 error = Status::FromErrorStringWithFormat("LoadLibrary Error: %" PRIu64,
414 error_code);
416 }
417
418 std::string module_path;
419 process->ReadCStringFromMemory(injected_module_path, module_path, status);
420 if (status.Fail()) {
422 "LoadLibrary error: could not read module path: %s",
423 status.AsCString());
425 }
426
427 if (loaded_image)
428 loaded_image->SetFile(module_path, llvm::sys::path::Style::native);
429 return process->AddImageToken(token);
430}
431
432Status PlatformWindows::UnloadImage(Process *process, uint32_t image_token) {
433 const addr_t address = process->GetImagePtrFromToken(image_token);
434 if (address == LLDB_INVALID_IMAGE_TOKEN)
435 return Status::FromErrorString("invalid image token");
436
437 StreamString expression;
438 expression.Printf("FreeLibrary((HMODULE)0x%" PRIx64 ")", address);
439
440 ValueObjectSP value;
441 Status result =
442 EvaluateLoaderExpression(process, expression.GetData(), value);
443 if (result.Fail())
444 return result;
445
446 if (value->GetError().Fail())
447 return value->GetError().Clone();
448
449 Scalar scalar;
450 if (value->ResolveValue(scalar)) {
451 if (scalar.UInt(1))
452 return Status::FromErrorStringWithFormat("expression failed: \"%s\"",
453 expression.GetData());
454 process->ResetImageToken(image_token);
455 }
456
457 return Status();
458}
459
462
463 if (IsHost()) {
465 "can't disconnect from the host platform '{0}', always connected",
466 GetPluginName());
467 } else {
469 error = m_remote_platform_sp->DisconnectRemote();
470 else
471 error =
472 Status::FromErrorString("the platform is not currently connected");
473 }
474 return error;
475}
476
478 Debugger &debugger, Target &target,
479 Status &error) {
480 // Windows has special considerations that must be followed when launching or
481 // attaching to a process. The key requirement is that when launching or
482 // attaching to a process, you must do it from the same the thread that will
483 // go into a permanent loop which will then receive debug events from the
484 // process. In particular, this means we can't use any of LLDB's generic
485 // mechanisms to do it for us, because it doesn't have the special knowledge
486 // required for setting up the background thread or passing the right flags.
487 //
488 // Another problem is that LLDB's standard model for debugging a process
489 // is to first launch it, have it stop at the entry point, and then attach to
490 // it. In Windows this doesn't quite work, you have to specify as an
491 // argument to CreateProcess() that you're going to debug the process. So we
492 // override DebugProcess here to handle this. Launch operations go directly
493 // to the process plugin, and attach operations almost go directly to the
494 // process plugin (but we hijack the events first). In essence, we
495 // encapsulate all the logic of Launching and Attaching in the process
496 // plugin, and PlatformWindows::DebugProcess is just a pass-through to get to
497 // the process plugin.
498
499 if (IsRemote()) {
501 return m_remote_platform_sp->DebugProcess(launch_info, debugger, target,
502 error);
503 else
504 error =
505 Status::FromErrorString("the platform is not currently connected");
506 }
507
508 if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) {
509 // This is a process attach. Don't need to launch anything.
510 ProcessAttachInfo attach_info(launch_info);
511 return Attach(attach_info, debugger, &target, error);
512 }
513
514 ProcessSP process_sp =
515 target.CreateProcess(launch_info.GetListener(),
516 launch_info.GetProcessPluginName(), nullptr, false);
517
518 process_sp->HijackProcessEvents(launch_info.GetHijackListener());
519
520 // We need to launch and attach to the process.
521 launch_info.GetFlags().Set(eLaunchFlagDebug);
522 if (process_sp)
523 error = process_sp->Launch(launch_info);
524
525 return process_sp;
526}
527
529 Debugger &debugger, Target *target,
530 Status &error) {
531 error.Clear();
532 lldb::ProcessSP process_sp;
533 if (!IsHost()) {
535 process_sp =
536 m_remote_platform_sp->Attach(attach_info, debugger, target, error);
537 else
538 error =
539 Status::FromErrorString("the platform is not currently connected");
540 return process_sp;
541 }
542
543 if (target == nullptr) {
544 TargetSP new_target_sp;
545 FileSpec emptyFileSpec;
546 ArchSpec emptyArchSpec;
547
548 error = debugger.GetTargetList().CreateTarget(
549 debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp);
550 target = new_target_sp.get();
551 }
552
553 if (!target || error.Fail())
554 return process_sp;
555
556 process_sp =
557 target->CreateProcess(attach_info.GetListenerForProcess(debugger),
558 attach_info.GetProcessPluginName(), nullptr, false);
559
560 process_sp->HijackProcessEvents(attach_info.GetHijackListener());
561 if (process_sp)
562 error = process_sp->Attach(attach_info);
563
564 return process_sp;
565}
566
569
570#ifdef _WIN32
571 llvm::VersionTuple version = HostInfo::GetOSVersion();
572 strm << " Host: Windows " << version.getAsString() << '\n';
573#endif
574}
575
576bool PlatformWindows::CanDebugProcess() { return true; }
577
579 if (basename.IsEmpty())
580 return basename;
581
582 StreamString stream;
583 stream.Printf("%s.dll", basename.GetCString());
584 return ConstString(stream.GetString());
585}
586
587size_t
589 BreakpointSite *bp_site) {
590 ArchSpec arch = target.GetArchitecture();
591 assert(arch.IsValid());
592 const uint8_t *trap_opcode = nullptr;
593 size_t trap_opcode_size = 0;
594
595 switch (arch.GetMachine()) {
596 case llvm::Triple::aarch64: {
597 static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x3e, 0xd4}; // brk #0xf000
598 trap_opcode = g_aarch64_opcode;
599 trap_opcode_size = sizeof(g_aarch64_opcode);
600
601 if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
602 return trap_opcode_size;
603 return 0;
604 } break;
605
606 case llvm::Triple::arm:
607 case llvm::Triple::thumb: {
608 static const uint8_t g_thumb_opcode[] = {0xfe, 0xde}; // udf #0xfe
609 trap_opcode = g_thumb_opcode;
610 trap_opcode_size = sizeof(g_thumb_opcode);
611
612 if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
613 return trap_opcode_size;
614 return 0;
615 } break;
616
617 default:
618 return Platform::GetSoftwareBreakpointTrapOpcode(target, bp_site);
619 }
620}
621
622std::unique_ptr<UtilityFunction>
624 Status &status) {
625 // FIXME(compnerd) `-fdeclspec` is not passed to the clang instance?
626 static constexpr const char kLoaderDecls[] = R"(
627extern "C" {
628// errhandlingapi.h
629
630// `LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32 | LOAD_LIBRARY_SEARCH_USER_DIRS`
631//
632// Directories in the standard search path are not searched. This value cannot
633// be combined with `LOAD_WITH_ALTERED_SEARCH_PATH`.
634//
635// This value represents the recommended maximum number of directories an
636// application should include in its DLL search path.
637#define LOAD_LIBRARY_SEARCH_DEFAULT_DIRS 0x00001000
638
639// WINBASEAPI DWORD WINAPI GetLastError(VOID);
640/* __declspec(dllimport) */ uint32_t __stdcall GetLastError();
641
642// libloaderapi.h
643
644// WINBASEAPI DLL_DIRECTORY_COOKIE WINAPI AddDllDirectory(LPCWSTR);
645/* __declspec(dllimport) */ void * __stdcall AddDllDirectory(const wchar_t *);
646
647// WINBASEAPI BOOL WINAPI FreeModule(HMODULE);
648/* __declspec(dllimport) */ int __stdcall FreeModule(void *hLibModule);
649
650// WINBASEAPI DWORD WINAPI GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize);
651/* __declspec(dllimport) */ uint32_t GetModuleFileNameA(void *, char *, uint32_t);
652
653// WINBASEAPI HMODULE WINAPI LoadLibraryExW(LPCWSTR, HANDLE, DWORD);
654/* __declspec(dllimport) */ void * __stdcall LoadLibraryExW(const wchar_t *, void *, uint32_t);
655
656// corecrt_wstring.h
657
658// _ACRTIMP size_t __cdecl wcslen(wchar_t const *_String);
659/* __declspec(dllimport) */ size_t __cdecl wcslen(const wchar_t *);
660
661// lldb specific code
662
663struct __lldb_LoadLibraryResult {
664 void *ImageBase;
665 char *ModulePath;
666 unsigned Length;
667 unsigned ErrorCode;
668};
669
670_Static_assert(sizeof(struct __lldb_LoadLibraryResult) <= 3 * sizeof(void *),
671 "__lldb_LoadLibraryResult size mismatch");
672
673void * __lldb_LoadLibraryHelper(const wchar_t *name, const wchar_t *paths,
674 __lldb_LoadLibraryResult *result) {
675 for (const wchar_t *path = paths; path && *path; ) {
676 (void)AddDllDirectory(path);
677 path += wcslen(path) + 1;
678 }
679
680 result->ImageBase = LoadLibraryExW(name, nullptr,
681 LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
682 if (result->ImageBase == nullptr)
683 result->ErrorCode = GetLastError();
684 else
685 result->Length = GetModuleFileNameA(result->ImageBase, result->ModulePath,
686 result->Length);
687
688 return result->ImageBase;
689}
690}
691 )";
692
693 static constexpr const char kName[] = "__lldb_LoadLibraryHelper";
694
695 ProcessSP process = context.GetProcessSP();
696 Target &target = process->GetTarget();
697
698 auto function = target.CreateUtilityFunction(std::string{kLoaderDecls}, kName,
700 context);
701 if (!function) {
702 std::string error = llvm::toString(function.takeError());
704 "LoadLibrary error: could not create utility function: %s",
705 error.c_str());
706 return nullptr;
707 }
708
709 TypeSystemClangSP scratch_ts_sp =
711 if (!scratch_ts_sp)
712 return nullptr;
713
714 CompilerType VoidPtrTy =
715 scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType();
716 CompilerType WCharPtrTy =
717 scratch_ts_sp->GetBasicType(eBasicTypeWChar).GetPointerType();
718
719 ValueList parameters;
720
721 Value value;
723
724 value.SetCompilerType(WCharPtrTy);
725 parameters.PushValue(value); // name
726 parameters.PushValue(value); // paths
727
728 value.SetCompilerType(VoidPtrTy);
729 parameters.PushValue(value); // result
730
732 std::unique_ptr<UtilityFunction> utility{std::move(*function)};
733 utility->MakeFunctionCaller(VoidPtrTy, parameters, context.GetThreadSP(),
734 error);
735 if (error.Fail()) {
737 "LoadLibrary error: could not create function caller: %s",
738 error.AsCString());
739 return nullptr;
740 }
741
742 if (!utility->GetFunctionCaller()) {
744 "LoadLibrary error: could not get function caller");
745 return nullptr;
746 }
747
748 return utility;
749}
750
752 const char *expression,
753 ValueObjectSP &value) {
754 // FIXME(compnerd) `-fdeclspec` is not passed to the clang instance?
755 static constexpr const char kLoaderDecls[] = R"(
756extern "C" {
757// libloaderapi.h
758
759// WINBASEAPI DLL_DIRECTORY_COOKIE WINAPI AddDllDirectory(LPCWSTR);
760/* __declspec(dllimport) */ void * __stdcall AddDllDirectory(const wchar_t *);
761
762// WINBASEAPI BOOL WINAPI FreeModule(HMODULE);
763/* __declspec(dllimport) */ int __stdcall FreeModule(void *);
764
765// WINBASEAPI DWORD WINAPI GetModuleFileNameA(HMODULE, LPSTR, DWORD);
766/* __declspec(dllimport) */ uint32_t GetModuleFileNameA(void *, char *, uint32_t);
767
768// WINBASEAPI HMODULE WINAPI LoadLibraryExW(LPCWSTR, HANDLE, DWORD);
769/* __declspec(dllimport) */ void * __stdcall LoadLibraryExW(const wchar_t *, void *, uint32_t);
770}
771 )";
772
773 if (DynamicLoader *loader = process->GetDynamicLoader()) {
774 Status result = loader->CanLoadImage();
775 if (result.Fail())
776 return result;
777 }
778
780 if (!thread)
781 return Status::FromErrorString("selected thread is invalid");
782
783 StackFrameSP frame = thread->GetStackFrameAtIndex(0);
784 if (!frame)
785 return Status::FromErrorString("frame 0 is invalid");
786
787 ExecutionContext context;
788 frame->CalculateExecutionContext(context);
789
791 options.SetUnwindOnError(true);
792 options.SetIgnoreBreakpoints(true);
795 // LoadLibraryEx{A,W}/FreeLibrary cannot raise exceptions which we can handle.
796 // They may potentially throw SEH exceptions which we do not know how to
797 // handle currently.
798 options.SetTrapExceptions(false);
799 options.SetTimeout(process->GetUtilityExpressionTimeout());
800
802 context, options, expression, kLoaderDecls, value);
803 if (result != eExpressionCompleted)
804 return value ? value->GetError().Clone() : Status("unknown error");
805
806 if (value && value->GetError().Fail())
807 return value->GetError().Clone();
808
809 return Status();
810}
static const size_t word_size
static llvm::raw_ostream & error(Stream &strm)
static uint32_t g_initialize_count
static uint32_t g_initialize_count
#define LLDB_PLUGIN_DEFINE(PluginName)
Definition: PluginManager.h:32
An architecture specification class.
Definition: ArchSpec.h:31
bool IsValid() const
Tests if this ArchSpec is valid.
Definition: ArchSpec.h:359
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
Definition: ArchSpec.cpp:701
A command line argument class.
Definition: Args.h:33
Class that manages the actual breakpoint that will be inserted into the running program.
bool SetTrapOpcode(const uint8_t *trap_opcode, uint32_t trap_opcode_size)
Sets the trap opcode.
Generic representation of a type in a programming language.
Definition: CompilerType.h:36
CompilerType GetPointerType() const
Return a new CompilerType that is a pointer to this type.
A uniqued constant string class.
Definition: ConstString.h:40
bool IsEmpty() const
Test for empty string.
Definition: ConstString.h:304
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:216
A class to manage flag bits.
Definition: Debugger.h:80
TargetList & GetTargetList()
Get accessor for the target list.
Definition: Debugger.h:198
llvm::Error GetAsError(lldb::ExpressionResults result, llvm::Twine message={}) const
Returns an ExpressionError with arg as error code.
A plug-in interface definition class for dynamic loaders.
Definition: DynamicLoader.h:54
void SetUnwindOnError(bool unwind=false)
Definition: Target.h:359
void SetExecutionPolicy(ExecutionPolicy policy=eExecutionPolicyAlways)
Definition: Target.h:325
void SetLanguage(lldb::LanguageType language_type)
Definition: Target.h:331
void SetTimeout(const Timeout< std::micro > &timeout)
Definition: Target.h:380
void SetIgnoreBreakpoints(bool ignore=false)
Definition: Target.h:363
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
const lldb::ProcessSP & GetProcessSP() const
Get accessor to get the process shared pointer.
const lldb::ThreadSP & GetThreadSP() const
Get accessor to get the thread shared pointer.
A file utility class.
Definition: FileSpec.h:56
void SetFile(llvm::StringRef path, Style style)
Change the file specified with a new path.
Definition: FileSpec.cpp:174
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:367
void Clear()
Clears the object state.
Definition: FileSpec.cpp:259
ValueType Set(ValueType mask)
Set one or more flags by logical OR'ing mask with the current flags.
Definition: Flags.h:73
Encapsulates a function that can be called.
ValueList GetArgumentValues() const
void DeallocateFunctionResults(ExecutionContext &exe_ctx, lldb::addr_t args_addr)
Deallocate the arguments structure.
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.
bool WriteFunctionArguments(ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, DiagnosticManager &diagnostic_manager)
Insert the default function argument struct.
PlatformWindows(bool is_host)
Default Constructor.
lldb_private::Status UnloadImage(lldb_private::Process *process, uint32_t image_token) override
llvm::StringRef GetPluginName() override
std::unique_ptr< lldb_private::UtilityFunction > MakeLoadImageUtilityFunction(lldb_private::ExecutionContext &context, lldb_private::Status &status)
lldb_private::Status DisconnectRemote() override
ConstString GetFullNameForDylib(ConstString basename) override
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.
static llvm::StringRef GetPluginDescriptionStatic(bool is_host)
void GetStatus(lldb_private::Stream &strm) override
Report the current status for this platform.
std::vector< ArchSpec > m_supported_architectures
lldb_private::Status ConnectRemote(lldb_private::Args &args) override
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...
static llvm::StringRef GetPluginNameStatic(bool is_host)
static lldb::PlatformSP CreateInstance(bool force, const lldb_private::ArchSpec *arch)
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
lldb_private::Status EvaluateLoaderExpression(lldb_private::Process *process, const char *expression, lldb::ValueObjectSP &value)
bool CanDebugProcess() override
Not all platforms will support debugging a process by spawning somehow halted for a debugger (specifi...
size_t GetSoftwareBreakpointTrapOpcode(Target &target, BreakpointSite *bp_site) override
virtual size_t GetSoftwareBreakpointTrapOpcode(Target &target, BreakpointSite *bp_site)
Definition: Platform.cpp:1954
static void Terminate()
Definition: Platform.cpp:138
static void SetHostPlatform(const lldb::PlatformSP &platform_sp)
Definition: Platform.cpp:145
virtual void GetStatus(Stream &strm)
Report the current status for this platform.
Definition: Platform.cpp:248
static void Initialize()
Definition: Platform.cpp:136
bool IsRemote() const
Definition: Platform.h:506
bool IsHost() const
Definition: Platform.h:502
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
lldb::ListenerSP GetListenerForProcess(Debugger &debugger)
Definition: Process.cpp:2936
llvm::StringRef GetProcessPluginName() const
Definition: Process.h:158
lldb::ListenerSP GetHijackListener() const
Definition: ProcessInfo.h:108
lldb::pid_t GetProcessID() const
Definition: ProcessInfo.h:68
lldb::ListenerSP GetListener() const
Definition: ProcessInfo.h:102
llvm::StringRef GetProcessPluginName() const
std::chrono::seconds GetUtilityExpressionTimeout() const
Definition: Process.cpp:321
A plug-in interface definition class for debugging a process.
Definition: Process.h:343
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:6350
void ResetImageToken(size_t token)
Definition: Process.cpp:6131
ThreadList & GetThreadList()
Definition: Process.h:2182
lldb::addr_t AllocateMemory(size_t size, uint32_t permissions, Status &error)
The public interface to allocating memory in the process.
Definition: Process.cpp:2417
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:2142
bool WritePointerToMemory(lldb::addr_t vm_addr, lldb::addr_t ptr_value, Status &error)
Definition: Process.cpp:2247
size_t AddImageToken(lldb::addr_t image_ptr)
Definition: Process.cpp:6120
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:2217
lldb::addr_t ReadPointerFromMemory(lldb::addr_t vm_addr, Status &error)
Definition: Process.cpp:2239
Status DeallocateMemory(lldb::addr_t ptr)
The public interface to deallocating memory in the process.
Definition: Process.cpp:2489
lldb::addr_t GetImagePtrFromToken(size_t token) const
Definition: Process.cpp:6125
uint32_t GetAddressByteSize() const
Definition: Process.cpp:3615
size_t WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, Status &error)
Write memory to a process.
Definition: Process.cpp:2275
virtual DynamicLoader * GetDynamicLoader()
Get the dynamic loader plug-in for this process.
Definition: Process.cpp:2830
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:2357
Target & GetTarget()
Get the target object pointer for this module.
Definition: Process.h:1246
A base class for platforms which automatically want to be able to forward operations to a remote plat...
unsigned int UInt(unsigned int fail_value=0) const
Definition: Scalar.cpp:321
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.
An error handling class.
Definition: Status.h:115
ValueType GetError() const
Access the error value.
Definition: Status.cpp:222
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Definition: Status.cpp:106
static Status FromErrorString(const char *str)
Definition: Status.h:138
bool Fail() const
Test for error condition.
Definition: Status.cpp:270
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
Definition: Status.cpp:195
static Status static Status FromErrorStringWithFormatv(const char *format, Args &&...args)
Definition: Status.h:148
static Status FromError(llvm::Error error)
Avoid using this in new code. Migrate APIs to llvm::Expected instead.
Definition: Status.cpp:137
const char * GetData() const
Definition: StreamString.h:45
llvm::StringRef GetString() const
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:134
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.
Definition: TargetList.cpp:45
const lldb::ProcessSP & CreateProcess(lldb::ListenerSP listener_sp, llvm::StringRef plugin_name, const FileSpec *crash_file, bool can_connect)
Definition: Target.cpp:285
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:2706
const ArchSpec & GetArchitecture() const
Definition: Target.h:1039
lldb::ThreadSP GetExpressionExecutionThread()
Definition: ThreadList.cpp:59
static lldb::ExpressionResults Evaluate(ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, llvm::StringRef expr_cstr, llvm::StringRef expr_prefix, lldb::ValueObjectSP &result_valobj_sp, 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...
"lldb/Expression/UtilityFunction.h" Encapsulates a bit of source code that provides a function that i...
FunctionCaller * GetFunctionCaller()
void PushValue(const Value &value)
Definition: Value.cpp:687
Value * GetValueAtIndex(size_t idx)
Definition: Value.cpp:691
const Scalar & GetScalar() const
Definition: Value.h:112
@ Scalar
A raw scalar value.
void SetCompilerType(const CompilerType &compiler_type)
Definition: Value.cpp:268
void SetValueType(ValueType value_type)
Definition: Value.h:89
static lldb::PlatformSP CreateInstance(bool force, const ArchSpec *arch)
#define LLDB_INVALID_IMAGE_TOKEN
Definition: lldb-defines.h:85
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:82
#define LLDB_INVALID_PROCESS_ID
Definition: lldb-defines.h:89
A class that represents a running process on the host machine.
Definition: SBAddress.h:15
std::shared_ptr< lldb_private::StackFrame > StackFrameSP
Definition: lldb-forward.h:424
std::shared_ptr< lldb_private::Thread > ThreadSP
Definition: lldb-forward.h:450
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
Definition: lldb-forward.h:484
std::shared_ptr< lldb_private::Platform > PlatformSP
Definition: lldb-forward.h:388
@ eLanguageTypeC_plus_plus
ISO C++:1998.
ExpressionResults
The results of expression evaluation.
@ eExpressionCompleted
@ eExpressionSetupError
std::shared_ptr< lldb_private::Process > ProcessSP
Definition: lldb-forward.h:389
std::shared_ptr< lldb_private::TypeSystemClang > TypeSystemClangSP
Definition: lldb-forward.h:470
uint64_t addr_t
Definition: lldb-types.h:80
std::shared_ptr< lldb_private::Target > TargetSP
Definition: lldb-forward.h:448