Go to the documentation of this file.
34 #include "llvm/ADT/ScopeExit.h"
35 #include "llvm/Support/ConvertUTF.h"
48 const bool is_host =
false;
51 if (!create && arch && arch->IsValid()) {
52 const llvm::Triple &triple = arch->GetTriple();
53 switch (triple.getVendor()) {
54 case llvm::Triple::PC:
58 case llvm::Triple::UnknownVendor:
59 create = !arch->TripleVendorWasSpecified();
67 switch (triple.getOS()) {
68 case llvm::Triple::Win32:
71 case llvm::Triple::UnknownOS:
72 create = arch->TripleOSWasSpecified();
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.";
91 void PlatformWindows::Initialize() {
92 Platform::Initialize();
98 default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
99 Platform::SetHostPlatform(default_platform_sp);
101 PluginManager::RegisterPlugin(
102 PlatformWindows::GetPluginNameStatic(
false),
103 PlatformWindows::GetPluginDescriptionStatic(
false),
104 PlatformWindows::CreateInstance);
108 void PlatformWindows::Terminate() {
111 PluginManager::UnregisterPlugin(PlatformWindows::CreateInstance);
115 Platform::Terminate();
120 const auto &AddArch = [&](
const ArchSpec &spec) {
122 return spec.IsExactMatch(rhs);
128 AddArch(HostInfo::GetArchitecture(HostInfo::eArchKindDefault));
129 AddArch(HostInfo::GetArchitecture(HostInfo::eArchKind32));
130 AddArch(HostInfo::GetArchitecture(HostInfo::eArchKind64));
136 error.SetErrorStringWithFormatv(
137 "can't connect to the host platform '{0}', always connected",
146 if (
error.Success()) {
150 error.SetErrorString(
151 "\"platform connect\" takes a single argument: <connect-url>");
155 error.SetErrorString(
"failed to create a 'remote-gdb-server' platform");
166 const std::vector<std::string> *paths,
171 loaded_image->
Clear();
175 error.SetErrorString(
"LoadLibrary error: no thread available to invoke LoadLibrary");
180 thread->CalculateExecutionContext(context);
187 if (loader ==
nullptr)
192 error.SetErrorString(
"LoadLibrary error: could not get function caller");
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");
202 name.emplace_back(L
'\0');
207 ePermissionsReadable | ePermissionsWritable,
210 error.SetErrorStringWithFormat(
"LoadLibrary error: unable to allocate memory for name: %s",
215 auto name_cleanup = llvm::make_scope_exit([process, injected_name]() {
220 name.size() *
sizeof(llvm::UTF16), status);
222 error.SetErrorStringWithFormat(
"LoadLibrary error: unable to write name: %s",
229 std::optional<llvm::detail::scope_exit<std::function<void()>>> paths_cleanup;
231 llvm::SmallVector<llvm::UTF16, 261> search_paths;
233 for (
const auto &path : *paths) {
237 llvm::SmallVector<llvm::UTF16, 261> buffer;
238 if (!llvm::convertUTF8ToUTF16String(path, buffer))
241 search_paths.append(std::begin(buffer), std::end(buffer));
242 search_paths.emplace_back(L
'\0');
244 search_paths.emplace_back(L
'\0');
247 process->
AllocateMemory(search_paths.size() *
sizeof(llvm::UTF16),
248 ePermissionsReadable | ePermissionsWritable,
251 error.SetErrorStringWithFormat(
"LoadLibrary error: unable to allocate memory for paths: %s",
256 paths_cleanup.emplace([process, injected_paths]() {
260 process->
WriteMemory(injected_paths, search_paths.data(),
261 search_paths.size() *
sizeof(llvm::UTF16), status);
263 error.SetErrorStringWithFormat(
"LoadLibrary error: unable to write paths: %s",
273 unsigned injected_length = 261;
277 ePermissionsReadable | ePermissionsWritable,
280 error.SetErrorStringWithFormat(
"LoadLibrary error: unable to allocate memory for module location: %s",
285 auto injected_module_path_cleanup =
286 llvm::make_scope_exit([process, injected_module_path]() {
294 ePermissionsReadable | ePermissionsWritable,
297 error.SetErrorStringWithFormat(
"LoadLibrary error: could not allocate memory for result: %s",
302 auto result_cleanup = llvm::make_scope_exit([process, injected_result]() {
307 injected_module_path, status);
309 error.SetErrorStringWithFormat(
"LoadLibrary error: could not initialize result: %s",
316 Scalar{injected_length},
sizeof(unsigned),
319 error.SetErrorStringWithFormat(
"LoadLibrary error: could not initialize result: %s",
333 parameters, diagnostics)) {
334 error.SetErrorStringWithFormat(
"LoadLibrary error: unable to write function parameters: %s",
339 auto parameter_cleanup =
340 llvm::make_scope_exit([invocation, &context, injected_parameters]() {
344 TypeSystemClangSP scratch_ts_sp =
346 if (!scratch_ts_sp) {
347 error.SetErrorString(
"LoadLibrary error: unable to get (clang) type system");
375 error.SetErrorStringWithFormat(
"LoadLibrary error: failed to execute LoadLibrary helper: %s",
383 error.SetErrorStringWithFormat(
"LoadLibrary error: could not read the result: %s",
390 uint64_t error_code =
394 error.SetErrorStringWithFormat(
"LoadLibrary error: could not read error status: %s",
399 error.SetErrorStringWithFormat(
"LoadLibrary Error: %" PRIu64, error_code);
406 error.SetErrorStringWithFormat(
"LoadLibrary error: could not read module path: %s",
412 loaded_image->
SetFile(module_path, llvm::sys::path::Style::native);
419 return Status(
"invalid image token");
422 expression.
Printf(
"FreeLibrary((HMODULE)0x%" PRIx64
")", address);
430 if (value->GetError().Fail())
434 if (value->ResolveValue(scalar)) {
436 return Status(
"expression failed: \"%s\"", expression.
GetData());
447 error.SetErrorStringWithFormatv(
448 "can't disconnect from the host platform '{0}', always connected",
454 error.SetErrorString(
"the platform is not currently connected");
486 error.SetErrorString(
"the platform is not currently connected");
492 return Attach(attach_info, debugger, &target,
error);
495 ProcessSP process_sp =
504 error = process_sp->Launch(launch_info);
513 lldb::ProcessSP process_sp;
519 error.SetErrorString(
"the platform is not currently connected");
523 if (target ==
nullptr) {
524 TargetSP new_target_sp;
530 target = new_target_sp.get();
533 if (!target ||
error.Fail())
542 error = process_sp->Attach(attach_info);
551 llvm::VersionTuple version = HostInfo::GetOSVersion();
552 strm <<
" Host: Windows " << version.getAsString() <<
'\n';
572 const uint8_t *trap_opcode =
nullptr;
573 size_t trap_opcode_size = 0;
576 case llvm::Triple::aarch64: {
577 static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x3e, 0xd4};
578 trap_opcode = g_aarch64_opcode;
579 trap_opcode_size =
sizeof(g_aarch64_opcode);
582 return trap_opcode_size;
586 case llvm::Triple::arm:
587 case llvm::Triple::thumb: {
588 static const uint8_t g_thumb_opcode[] = {0xfe, 0xde};
589 trap_opcode = g_thumb_opcode;
590 trap_opcode_size =
sizeof(g_thumb_opcode);
593 return trap_opcode_size;
602 std::unique_ptr<UtilityFunction>
606 static constexpr
const char kLoaderDecls[] = R
"(
610 // `LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32 | LOAD_LIBRARY_SEARCH_USER_DIRS`
612 // Directories in the standard search path are not searched. This value cannot
613 // be combined with `LOAD_WITH_ALTERED_SEARCH_PATH`.
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
619 // WINBASEAPI DWORD WINAPI GetLastError(VOID);
620 /* __declspec(dllimport) */ uint32_t __stdcall GetLastError();
624 // WINBASEAPI DLL_DIRECTORY_COOKIE WINAPI AddDllDirectory(LPCWSTR);
625 /* __declspec(dllimport) */ void * __stdcall AddDllDirectory(const wchar_t *);
627 // WINBASEAPI BOOL WINAPI FreeModule(HMODULE);
628 /* __declspec(dllimport) */ int __stdcall FreeModule(void *hLibModule);
630 // WINBASEAPI DWORD WINAPI GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize);
631 /* __declspec(dllimport) */ uint32_t GetModuleFileNameA(void *, char *, uint32_t);
633 // WINBASEAPI HMODULE WINAPI LoadLibraryExW(LPCWSTR, HANDLE, DWORD);
634 /* __declspec(dllimport) */ void * __stdcall LoadLibraryExW(const wchar_t *, void *, uint32_t);
638 // _ACRTIMP size_t __cdecl wcslen(wchar_t const *_String);
639 /* __declspec(dllimport) */ size_t __cdecl wcslen(const wchar_t *);
641 // lldb specific code
643 struct __lldb_LoadLibraryResult {
650 _Static_assert(sizeof(struct __lldb_LoadLibraryResult) <= 3 * sizeof(void *),
651 "__lldb_LoadLibraryResult size mismatch");
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;
660 result->ImageBase = LoadLibraryExW(name, nullptr,
661 LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
662 if (result->ImageBase == nullptr)
663 result->ErrorCode = GetLastError();
665 result->Length = GetModuleFileNameA(result->ImageBase, result->ModulePath,
668 return result->ImageBase;
673 static constexpr
const char kName[] =
"__lldb_LoadLibraryHelper";
676 Target &target = process->GetTarget();
688 TypeSystemClangSP scratch_ts_sp =
711 std::unique_ptr<UtilityFunction> utility{std::move(*
function)};
712 utility->MakeFunctionCaller(VoidPtrTy, parameters, context.
GetThreadSP(),
720 if (!utility->GetFunctionCaller()) {
721 status.
SetErrorString(
"LoadLibrary error: could not get function caller");
729 const char *expression,
730 ValueObjectSP &value) {
732 static constexpr
const char kLoaderDecls[] = R
"(
736 // WINBASEAPI DLL_DIRECTORY_COOKIE WINAPI AddDllDirectory(LPCWSTR);
737 /* __declspec(dllimport) */ void * __stdcall AddDllDirectory(const wchar_t *);
739 // WINBASEAPI BOOL WINAPI FreeModule(HMODULE);
740 /* __declspec(dllimport) */ int __stdcall FreeModule(void *);
742 // WINBASEAPI DWORD WINAPI GetModuleFileNameA(HMODULE, LPSTR, DWORD);
743 /* __declspec(dllimport) */ uint32_t GetModuleFileNameA(void *, char *, uint32_t);
745 // WINBASEAPI HMODULE WINAPI LoadLibraryExW(LPCWSTR, HANDLE, DWORD);
746 /* __declspec(dllimport) */ void * __stdcall LoadLibraryExW(const wchar_t *, void *, uint32_t);
751 Status result = loader->CanLoadImage();
758 return Status(
"selected thread is invalid");
760 StackFrameSP frame = thread->GetStackFrameAtIndex(0);
762 return Status(
"frame 0 is invalid");
765 frame->CalculateExecutionContext(context);
780 context, options, expression, kLoaderDecls, value,
error);
784 if (value->GetError().Fail())
785 return value->GetError();
const char * toString(AppleArm64ExceptionClass EC)
FunctionCaller * GetFunctionCaller()
@ Scalar
A raw scalar value.
const lldb::ThreadSP & GetThreadSP() const
Get accessor to get the thread shared pointer.
lldb::addr_t AllocateMemory(size_t size, uint32_t permissions, Status &error)
The public interface to allocating memory in the process.
Status DeallocateMemory(lldb::addr_t ptr)
The public interface to deallocating memory in the process.
#define LLDB_INVALID_PROCESS_ID
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
void SetTimeout(const Timeout< std::micro > &timeout)
void SetLanguage(lldb::LanguageType language)
void SetValueType(ValueType value_type)
ExpressionResults
The results of expression evaluation.
Value * GetValueAtIndex(size_t idx)
std::chrono::seconds GetUtilityExpressionTimeout() const
void SetExecutionPolicy(ExecutionPolicy policy=eExecutionPolicyAlways)
void SetIsForUtilityExpr(bool b)
ThreadList & GetThreadList()
Target & GetTarget()
Get the target object pointer for this module.
static const size_t word_size
void SetTrapExceptions(bool b)
lldb::pid_t GetProcessID() const
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...
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.
size_t WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, Status &error)
Write memory to a process.
const lldb::ProcessSP & CreateProcess(lldb::ListenerSP listener_sp, llvm::StringRef plugin_name, const FileSpec *crash_file, bool can_connect)
llvm::StringRef GetString() const
std::string GetString(char separator='\n')
lldb::ListenerSP GetListenerForProcess(Debugger &debugger)
void SetCompilerType(const CompilerType &compiler_type)
void DeallocateFunctionResults(ExecutionContext &exe_ctx, lldb::addr_t args_addr)
Deallocate the arguments structure.
const Scalar & GetScalar() const
static llvm::raw_ostream & error(Stream &strm)
void PushValue(const Value &value)
bool WriteFunctionArguments(ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, DiagnosticManager &diagnostic_manager)
Insert the default function argument struct.
bool IsEmpty() const
Test for empty string.
ValueType GetError() const
Access the error value.
bool Fail() const
Test for error condition.
const char * GetData() const
int SetErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Set the current error string to a formatted error string.
ValueList GetArgumentValues() const
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.
uint32_t GetAddressByteSize() const
unsigned int UInt(unsigned int fail_value=0) const
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::ListenerSP GetListener() const
virtual DynamicLoader * GetDynamicLoader()
Get the dynamic loader plug-in for this process.
string(SUBSTRING ${p} 10 -1 pStripped) if($
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.
bool IsValid() const
Tests if this ArchSpec is valid.
void SetUnwindOnError(bool unwind=false)
TargetList & GetTargetList()
Get accessor for the target list.
void Clear()
Clears the object state.
void SetIgnoreBreakpoints(bool ignore=false)
const lldb::ProcessSP & GetProcessSP() const
Get accessor to get the process shared pointer.
const char * GetProcessPluginName() const
const ArchSpec & GetArchitecture() const
CompilerType GetPointerType() const
Return a new CompilerType that is a pointer to this type.
#define LLDB_INVALID_IMAGE_TOKEN
size_t AddImageToken(lldb::addr_t image_ptr)
const char * GetProcessPluginName() const
void SetErrorString(llvm::StringRef err_str)
Set the current error string to err_str.
lldb::ListenerSP GetHijackListener() const
bool WritePointerToMemory(lldb::addr_t vm_addr, lldb::addr_t ptr_value, Status &error)
#define LLDB_INVALID_ADDRESS
const char * GetCString() const
Get the string value as a C string.
Generic representation of a type in a programming language.
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
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.
A class that represents a running process on the host machine.
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 SetTrapOpcode(const uint8_t *trap_opcode, uint32_t trap_opcode_size)
Sets the trap opcode.
lldb::addr_t GetImagePtrFromToken(size_t token) const
ValueType Set(ValueType mask)
Set one or more flags by logical OR'ing mask with the current flags.
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.
#define LLDB_PLUGIN_DEFINE(PluginName)
void SetFile(llvm::StringRef path, Style style)
Change the file specified with a new path.
lldb::addr_t ReadPointerFromMemory(lldb::addr_t vm_addr, Status &error)
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
lldb::ListenerSP GetHijackListener() const
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.
lldb::ThreadSP GetExpressionExecutionThread()
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
void ResetImageToken(size_t token)
@ eLanguageTypeC_plus_plus
ISO C++:1998.