20#define PATHCCH_MAX_CCH 0x8000
40#include "llvm/ADT/ScopeExit.h"
41#include "llvm/Support/ConvertUTF.h"
42#include "llvm/Support/Error.h"
43#include "llvm/Support/FormatAdapters.h"
44#include "llvm/Support/FormatVariadic.h"
57 constexpr std::chrono::seconds preferred(5);
58 return std::min<std::chrono::microseconds>(
60 std::chrono::microseconds(process->GetUtilityExpressionTimeout()) / 2);
65#define LLDB_PROPERTIES_windows
66#include "PlatformWindowsProperties.inc"
69#define LLDB_PROPERTIES_windows
70#include "PlatformWindowsPropertiesEnum.inc"
76 m_collection_sp = std::make_shared<OptionValueProperties>(
"windows");
77 m_collection_sp->Initialize(g_windows_properties_def);
80 bool DisableDebugHeap()
const {
81 return GetPropertyAtIndexAs<bool>(ePropertyDisableDebugHeap,
true);
86 static PluginProperties g_settings;
96 const bool is_host =
false;
99 if (!create && arch && arch->
IsValid()) {
100 const llvm::Triple &triple = arch->
GetTriple();
101 switch (triple.getVendor()) {
102 case llvm::Triple::PC:
106 case llvm::Triple::UnknownVendor:
115 switch (triple.getOS()) {
116 case llvm::Triple::Win32:
119 case llvm::Triple::UnknownOS:
135 return is_host ?
"Local Windows user platform plug-in."
136 :
"Remote Windows user platform plug-in.";
143 "Properties for the Windows platform plugin.",
155 default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
177 const auto &AddArch = [&](
const ArchSpec &spec) {
179 return spec.IsExactMatch(rhs);
185 AddArch(HostInfo::GetArchitecture(HostInfo::eArchKindDefault));
186 AddArch(HostInfo::GetArchitecture(HostInfo::eArchKind32));
187 AddArch(HostInfo::GetArchitecture(HostInfo::eArchKind64));
193 "can't connect to the host platform '{0}', always connected",
203 "failed to create a 'remote-gdb-server' platform");
214 const std::vector<std::string> *paths,
219 loaded_image->
Clear();
224 "LoadLibrary error: no thread available to invoke LoadLibrary");
229 thread->CalculateExecutionContext(context);
236 if (loader ==
nullptr)
242 "LoadLibrary error: could not get function caller");
247 llvm::SmallVector<llvm::UTF16, 261> name;
248 if (!llvm::convertUTF8ToUTF16String(remote_file.
GetPath(), name)) {
250 "LoadLibrary error: could not convert path to UCS2");
253 name.emplace_back(L
'\0');
258 ePermissionsReadable | ePermissionsWritable,
262 "LoadLibrary error: unable to allocate memory for name: %s",
267 llvm::scope_exit name_cleanup(
271 name.size() *
sizeof(llvm::UTF16), status);
274 "LoadLibrary error: unable to write name: %s", status.
AsCString());
280 std::optional<llvm::scope_exit<std::function<void()>>> paths_cleanup;
282 llvm::SmallVector<llvm::UTF16, 261> search_paths;
284 for (
const auto &path : *paths) {
288 llvm::SmallVector<llvm::UTF16, 261> buffer;
289 if (!llvm::convertUTF8ToUTF16String(path, buffer))
292 search_paths.append(std::begin(buffer), std::end(buffer));
293 search_paths.emplace_back(L
'\0');
295 search_paths.emplace_back(L
'\0');
298 process->
AllocateMemory(search_paths.size() *
sizeof(llvm::UTF16),
299 ePermissionsReadable | ePermissionsWritable,
303 "LoadLibrary error: unable to allocate memory for paths: %s",
308 paths_cleanup.emplace([process, injected_paths]() {
312 process->
WriteMemory(injected_paths, search_paths.data(),
313 search_paths.size() *
sizeof(llvm::UTF16), status);
316 "LoadLibrary error: unable to write paths: %s", status.
AsCString());
325 unsigned injected_length =
MAX_PATH;
328 (injected_length + 1) *
sizeof(llvm::UTF16),
329 ePermissionsReadable | ePermissionsWritable, status);
332 "LoadLibrary error: unable to allocate memory for module location: %s",
337 llvm::scope_exit injected_module_path_cleanup(
338 [process, injected_module_path]() {
346 ePermissionsReadable | ePermissionsWritable,
350 "LoadLibrary error: could not allocate memory for result: %s",
355 llvm::scope_exit result_cleanup([process, injected_result]() {
359 std::vector<lldb::addr_t> grown_path_buffers;
360 llvm::scope_exit grown_path_cleanup([&]() {
368 "LoadLibrary error: could not initialize result: %s",
374 injected_module_path, status);
377 "LoadLibrary error: could not initialize result: %s",
384 Scalar{injected_length},
sizeof(unsigned),
388 "LoadLibrary error: could not initialize result: %s",
402 parameters, diagnostics)) {
405 "LoadLibrary error: unable to write function parameters:"));
409 llvm::scope_exit parameter_cleanup(
410 [invocation, &context, injected_parameters]() {
416 if (!scratch_ts_sp) {
418 "LoadLibrary error: unable to get (clang) type system");
449 llvm::formatv(
"failed to execute LoadLibrary helper "
457 llvm::Expected<lldb::addr_t> token_or_err =
461 "LoadLibrary error: could not read the result: {0}",
462 llvm::fmt_consume(token_or_err.takeError()));
470 injected_result + 2 *
word_size +
sizeof(
unsigned),
sizeof(
unsigned), 0,
474 "LoadLibrary error: could not read error status: %s",
485 unsigned capacity = injected_length;
487 injected_result + 2 *
word_size,
sizeof(
unsigned), 0, status);
488 while (status.
Success() && path_length >= capacity &&
492 (capacity + 1) *
sizeof(llvm::UTF16),
493 ePermissionsReadable | ePermissionsWritable, status);
496 grown_path_buffers.push_back(buffer);
502 Scalar{capacity},
sizeof(unsigned), status);
507 if (invocation->
ExecuteFunction(context, &injected_parameters, options,
510 module_path_addr = buffer;
512 injected_result + 2 *
word_size,
sizeof(
unsigned), 0, status);
515 llvm::SmallVector<llvm::UTF16, MAX_PATH> wide_path(path_length);
517 process->
ReadMemory(module_path_addr, wide_path.data(),
518 path_length *
sizeof(llvm::UTF16), status);
521 "LoadLibrary error: could not read module path: %s",
526 std::string module_path;
527 if (!llvm::convertUTF16ToUTF8String(
528 llvm::ArrayRef<llvm::UTF16>(wide_path.data(), wide_path.size()),
531 "LoadLibrary error: could not convert module path to UTF-8");
536 loaded_image->
SetFile(module_path, llvm::sys::path::Style::native);
546 expression.
Printf(
"FreeLibrary((HMODULE)0x%" PRIx64
")", address);
554 if (value->GetError().Fail())
555 return value->GetError().Clone();
558 if (value->ResolveValue(scalar)) {
573 "can't disconnect from the host platform '{0}', always connected",
619 return Attach(attach_info, debugger, &target,
error);
624 !env.contains(
"_NO_DEBUG_HEAP")) {
625 env.try_emplace(
"_NO_DEBUG_HEAP",
"1");
639 error = process_sp->Launch(launch_info);
641 if (
error.Success()) {
642 process_sp->SetPseudoConsoleHandle();
645 LLDB_LOGF(log,
"Platform::%s LaunchProcess() failed: %s", __FUNCTION__,
668 if (target ==
nullptr) {
672 target = new_target_sp.get();
675 if (!target ||
error.Fail())
685 error = process_sp->Attach(attach_info);
695 llvm::VersionTuple version = HostInfo::GetOSVersion();
696 strm <<
" Host: Windows " << version.getAsString() <<
'\n';
703 if (basename.empty())
704 return basename.str();
706 return llvm::formatv(
"{0}.dll", basename).str();
714 const uint8_t *trap_opcode =
nullptr;
715 size_t trap_opcode_size = 0;
718 case llvm::Triple::aarch64: {
719 static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x3e, 0xd4};
720 trap_opcode = g_aarch64_opcode;
721 trap_opcode_size =
sizeof(g_aarch64_opcode);
724 return trap_opcode_size;
728 case llvm::Triple::arm:
729 case llvm::Triple::thumb: {
730 static const uint8_t g_thumb_opcode[] = {0xfe, 0xde};
731 trap_opcode = g_thumb_opcode;
732 trap_opcode_size =
sizeof(g_thumb_opcode);
735 return trap_opcode_size;
744std::unique_ptr<UtilityFunction>
748 static constexpr const char kLoaderDecls[] = R
"(
752// `LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32 | LOAD_LIBRARY_SEARCH_USER_DIRS`
754// Directories in the standard search path are not searched. This value cannot
755// be combined with `LOAD_WITH_ALTERED_SEARCH_PATH`.
757// This value represents the recommended maximum number of directories an
758// application should include in its DLL search path.
759#define LOAD_LIBRARY_SEARCH_DEFAULT_DIRS 0x00001000
761// If this value is used, and lpFileName specifies an absolute path, the system
762// uses the alternate file search strategy to find associated executable
764#define LOAD_WITH_ALTERED_SEARCH_PATH 0x00000008
766// WINBASEAPI DWORD WINAPI GetLastError(VOID);
767/* __declspec(dllimport) */ uint32_t __stdcall GetLastError();
771// WINBASEAPI DLL_DIRECTORY_COOKIE WINAPI AddDllDirectory(LPCWSTR);
772/* __declspec(dllimport) */ void * __stdcall AddDllDirectory(const wchar_t *);
774// WINBASEAPI BOOL WINAPI FreeModule(HMODULE);
775/* __declspec(dllimport) */ int __stdcall FreeModule(void *hLibModule);
777// WINBASEAPI DWORD WINAPI GetModuleFileNameW(HMODULE hModule, LPWSTR lpFilename, DWORD nSize);
778/* __declspec(dllimport) */ uint32_t GetModuleFileNameW(void *, wchar_t *, uint32_t);
780// WINBASEAPI HMODULE WINAPI LoadLibraryExW(LPCWSTR, HANDLE, DWORD);
781/* __declspec(dllimport) */ void * __stdcall LoadLibraryExW(const wchar_t *, void *, uint32_t);
785// _ACRTIMP size_t __cdecl wcslen(wchar_t const *_String);
786/* __declspec(dllimport) */ size_t __cdecl wcslen(const wchar_t *);
790struct __lldb_LoadLibraryResult {
797_Static_assert(sizeof(struct __lldb_LoadLibraryResult) <= 3 * sizeof(void *),
798 "__lldb_LoadLibraryResult size mismatch");
800void * __lldb_LoadLibraryHelper(const wchar_t *name, const wchar_t *paths,
801 __lldb_LoadLibraryResult *result) {
802 // When the caller presets ImageBase the module is already loaded and we are
803 // only re-querying its path with a larger buffer. Skip LoadLibrary in that
804 // case so we do not take an extra reference on the module.
805 if (result->ImageBase == nullptr) {
806 for (const wchar_t *path = paths; path && *path; ) {
807 (void)AddDllDirectory(path);
808 path += wcslen(path) + 1;
811 result->ImageBase = LoadLibraryExW(name, nullptr,
812 LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
814 // Fallback: if the AddDllDirectory + LOAD_LIBRARY_SEARCH_DEFAULT_DIRS path
815 // failed to find the library, iterate the search paths ourselves and
816 // load by absolute path using LOAD_WITH_ALTERED_SEARCH_PATH, which makes
817 // Windows use the loaded DLL's own directory to resolve its sibling imports.
818 if (result->ImageBase == nullptr) {
820 for (const wchar_t *path = paths; path && *path; path += wcslen(path) + 1) {
821 size_t plen = wcslen(path);
822 size_t nlen = wcslen(name);
823 // Need room for: path + '\\' + name + '\0'
824 if (plen + 1 + nlen + 1 > 4096)
827 for (size_t i = 0; i < plen; ++i)
830 for (size_t i = 0; i <= nlen; ++i) // Copy name including trailing '\0'.
832 result->ImageBase = LoadLibraryExW(full, nullptr,
833 LOAD_WITH_ALTERED_SEARCH_PATH);
834 if (result->ImageBase != nullptr)
840 if (result->ImageBase == nullptr)
841 result->ErrorCode = GetLastError();
843 result->Length = GetModuleFileNameW(result->ImageBase, result->ModulePath,
846 return result->ImageBase;
851 static constexpr const char kName[] =
"__lldb_LoadLibraryHelper";
854 Target &target = process->GetTarget();
860 std::string
error = llvm::toString(function.takeError());
862 "LoadLibrary error: could not create utility function: %s",
890 std::unique_ptr<UtilityFunction> utility{std::move(*function)};
891 utility->MakeFunctionCaller(VoidPtrTy, parameters, context.
GetThreadSP(),
895 "LoadLibrary error: could not create function caller: %s",
900 if (!utility->GetFunctionCaller()) {
902 "LoadLibrary error: could not get function caller");
910 const char *expression,
913 static constexpr const char kLoaderDecls[] = R
"(
917// WINBASEAPI DLL_DIRECTORY_COOKIE WINAPI AddDllDirectory(LPCWSTR);
918/* __declspec(dllimport) */ void * __stdcall AddDllDirectory(const wchar_t *);
920// WINBASEAPI BOOL WINAPI FreeModule(HMODULE);
921/* __declspec(dllimport) */ int __stdcall FreeModule(void *);
923// WINBASEAPI DWORD WINAPI GetModuleFileNameW(HMODULE, LPWSTR, DWORD);
924/* __declspec(dllimport) */ uint32_t GetModuleFileNameW(void *, wchar_t *, uint32_t);
926// WINBASEAPI HMODULE WINAPI LoadLibraryExW(LPCWSTR, HANDLE, DWORD);
927/* __declspec(dllimport) */ void * __stdcall LoadLibraryExW(const wchar_t *, void *, uint32_t);
932 Status result = loader->CanLoadImage();
945 ExecutionContext context;
946 frame->CalculateExecutionContext(context);
948 EvaluateExpressionOptions options;
961 context, options, expression, kLoaderDecls, value);
964 ? value->GetError().Clone()
966 "failed to execute loader helper ({0})",
toString(result));
968 if (value && value->GetError().Fail())
969 return value->GetError().Clone();
static const size_t word_size
static llvm::raw_ostream & error(Stream &strm)
static DynamicLoaderDarwinKernelProperties & GetGlobalProperties()
#define LLDB_LOGF(log,...)
#define LLDB_PLUGIN_DEFINE(PluginName)
static constexpr llvm::StringLiteral kName
An architecture specification class.
bool IsValid() const
Tests if this ArchSpec is valid.
llvm::Triple & GetTriple()
Architecture triple accessor.
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
bool TripleVendorWasSpecified() const
bool TripleOSWasSpecified() const
A command line argument class.
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.
CompilerType GetPointerType() const
Return a new CompilerType that is a pointer to this type.
A class to manage flag bits.
TargetList & GetTargetList()
Get accessor for the target list.
llvm::Error GetAsError(lldb::ExpressionResults result, llvm::Twine message={}) const
Returns an ExpressionError with arg as error code.
void SetOneThreadTimeout(const Timeout< std::micro > &timeout)
void SetUnwindOnError(bool unwind=false)
void SetExecutionPolicy(ExecutionPolicy policy=eExecutionPolicyAlways)
void SetLanguage(lldb::LanguageType language_type)
void SetTrapExceptions(bool b)
void SetTimeout(const Timeout< std::micro > &timeout)
void SetIsForUtilityExpr(bool b)
void SetIgnoreBreakpoints(bool ignore=false)
"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.
void SetFile(llvm::StringRef path, Style style)
Change the file specified with a new path.
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
void Clear()
Clears the object state.
ValueType Set(ValueType mask)
Set one or more flags by logical OR'ing mask with the current flags.
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.
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static lldb::OptionValuePropertiesSP GetSettingForPlatformPlugin(Debugger &debugger, llvm::StringRef setting_name)
static bool CreateSettingForPlatformPlugin(Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, llvm::StringRef description, bool is_global_property)
static bool UnregisterPlugin(ABICreateInstance create_callback)
lldb::ListenerSP GetListenerForProcess(Debugger &debugger)
llvm::StringRef GetProcessPluginName() const
lldb::ListenerSP GetHijackListener() const
lldb::pid_t GetProcessID() const
lldb::ListenerSP GetListener() const
lldb::ListenerSP GetShadowListener() const
Environment & GetEnvironment()
llvm::StringRef GetProcessPluginName() const
std::chrono::seconds GetUtilityExpressionTimeout() const
A plug-in interface definition class for debugging a process.
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.
void ResetImageToken(size_t token)
ThreadList & GetThreadList()
lldb::addr_t AllocateMemory(size_t size, uint32_t permissions, Status &error)
The public interface to allocating memory in the process.
virtual size_t ReadMemory(const ProcessAddress &process_addr, void *buf, size_t size, Status &error)
Read of memory from a process.
bool WritePointerToMemory(lldb::addr_t vm_addr, lldb::addr_t ptr_value, Status &error)
size_t AddImageToken(lldb::addr_t image_ptr)
llvm::Expected< lldb::addr_t > ReadPointerFromMemory(lldb::addr_t vm_addr)
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.
Status DeallocateMemory(lldb::addr_t ptr)
The public interface to deallocating memory in the process.
lldb::addr_t GetImagePtrFromToken(size_t token) const
uint32_t GetAddressByteSize() const
size_t WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, Status &error)
Write memory to a process.
virtual DynamicLoader * GetDynamicLoader()
Get the dynamic loader plug-in for this process.
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.
Target & GetTarget()
Get the target object pointer for this module.
unsigned int UInt(unsigned int fail_value=0) const
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.
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
static Status FromErrorString(const char *str)
bool Fail() const
Test for error condition.
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
static Status static Status FromErrorStringWithFormatv(const char *format, Args &&...args)
static Status FromError(llvm::Error error)
Avoid using this in new code. Migrate APIs to llvm::Expected instead.
bool Success() const
Test for success condition.
const char * GetData() const
A stream class that can stream formatted output to a file.
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
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.
const lldb::ProcessSP & CreateProcess(lldb::ListenerSP listener_sp, llvm::StringRef plugin_name, const FileSpec *crash_file, bool can_connect)
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.
const ArchSpec & GetArchitecture() const
lldb::ThreadSP GetExpressionExecutionThread()
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)
Value * GetValueAtIndex(size_t idx)
const Scalar & GetScalar() const
See comment on m_scalar to understand what GetScalar returns.
@ Scalar
A raw scalar value.
void SetCompilerType(const CompilerType &compiler_type)
void SetValueType(ValueType value_type)
#define LLDB_INVALID_IMAGE_TOKEN
#define LLDB_INVALID_ADDRESS
#define LLDB_INVALID_PROCESS_ID
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
std::string toString(FormatterBytecode::OpCodes op)
std::shared_ptr< lldb_private::StackFrame > StackFrameSP
std::shared_ptr< lldb_private::Thread > ThreadSP
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
std::shared_ptr< lldb_private::Platform > PlatformSP
@ eLanguageTypeC_plus_plus
ISO C++:1998.
ExpressionResults
The results of expression evaluation.
std::shared_ptr< lldb_private::Process > ProcessSP
std::shared_ptr< lldb_private::TypeSystemClang > TypeSystemClangSP
std::shared_ptr< lldb_private::Target > TargetSP