36#include "llvm/ADT/ScopeExit.h"
59 std::unique_ptr<lldb_private::OptionGroupOptions> options(
64 m_options[&interpreter] = std::move(options);
73 if (!platform || !path || *path == 0)
84 command.
Printf(
":%d", gid);
85 command.
Printf(
"%s", path);
88 nullptr, std::chrono::seconds(10));
99 if (source == destination)
103 std::string src_path(source.
GetPath());
104 if (src_path.empty())
105 return Status(
"unable to get file path for source");
106 std::string dst_path(destination.
GetPath());
107 if (dst_path.empty())
108 return Status(
"unable to get file path for destination");
110 command.
Printf(
"cp %s %s", src_path.c_str(), dst_path.c_str());
113 std::chrono::seconds(10));
115 return Status(
"unable to perform copy");
118 if (
chown_file(
this, dst_path.c_str(), uid, gid) != 0)
119 return Status(
"unable to perform chown");
123 std::string src_path(source.
GetPath());
124 if (src_path.empty())
125 return Status(
"unable to get file path for source");
126 std::string dst_path(destination.
GetPath());
127 if (dst_path.empty())
128 return Status(
"unable to get file path for destination");
143 nullptr, std::chrono::minutes(1));
164 std::string src_path(source.
GetPath());
165 if (src_path.empty())
166 return Status(
"unable to get file path for source");
167 std::string dst_path(destination.
GetPath());
168 if (dst_path.empty())
169 return Status(
"unable to get file path for destination");
171 if (source == destination)
172 return Status(
"local scenario->source and destination are the same file "
173 "path: no operation performed");
176 cp_command.
Printf(
"cp %s %s", src_path.c_str(), dst_path.c_str());
179 std::chrono::seconds(10));
181 return Status(
"unable to perform copy");
192 src_path.c_str(), dst_path.c_str());
200 nullptr, std::chrono::minutes(1));
210 LLDB_LOGF(log,
"[GetFile] Using block by block transfer....\n");
213 lldb::eFilePermissionsFileDefault,
error);
216 return Status(
"unable to open source file");
221 if (permissions == 0)
222 permissions = lldb::eFilePermissionsFileDefault;
231 error.SetErrorString(
"unable to open destination file");
234 if (
error.Success()) {
235 lldb::WritableDataBufferSP buffer_sp(
new DataBufferHeap(1024, 0));
238 while (
error.Success()) {
239 const uint64_t n_read =
ReadFile(fd_src, offset, buffer_sp->GetBytes(),
240 buffer_sp->GetByteSize(),
error);
246 buffer_sp->GetBytes(), n_read,
249 error.SetErrorString(
"unable to write to destination file");
262 error.SetErrorString(
"unable to close destination file");
275 stream.
Printf(
", options: ");
278 stream.
Printf(
", prefix: ");
282 stream.
Printf(
"ignore remote-hostname ");
301 return unix_signals_sp;
304 return unix_signals_sp;
311 error.SetErrorStringWithFormatv(
312 "can't connect to the host platform '{0}', always connected",
323 error.SetErrorString(
"failed to create a 'remote-gdb-server' platform");
356 error.SetErrorStringWithFormatv(
357 "can't disconnect from the host platform '{0}', always connected",
363 error.SetErrorString(
"the platform is not currently connected");
371 lldb::ProcessSP process_sp;
375 if (target ==
nullptr) {
376 TargetSP new_target_sp;
380 target = new_target_sp.get();
381 LLDB_LOGF(log,
"PlatformPOSIX::%s created new target", __FUNCTION__);
384 LLDB_LOGF(log,
"PlatformPOSIX::%s target already existed, setting target",
388 if (target &&
error.Success()) {
391 LLDB_LOGF(log,
"PlatformPOSIX::%s set selected target to %p %s",
392 __FUNCTION__, (
void *)target,
393 exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str()
399 "gdb-remote",
nullptr,
true);
403 if (listener_sp ==
nullptr) {
408 process_sp->HijackProcessEvents(listener_sp);
409 error = process_sp->Attach(attach_info);
417 error.SetErrorString(
"the platform is not currently connected");
426 LLDB_LOG(log,
"target {0}", &target);
428 ProcessSP process_sp;
435 error.SetErrorString(
"the platform is not currently connected");
453 LLDB_LOG(log,
"having target create process with gdb-remote plugin");
458 error.SetErrorString(
"CreateProcess() failed for gdb-remote process");
463 LLDB_LOG(log,
"successfully created process");
469 LLDB_LOG(log,
"launching process with the following file actions:");
474 file_action->
Dump(stream);
481 error = process_sp->Launch(launch_info);
482 if (
error.Success()) {
487 process_sp->SetSTDIOFileDescriptor(pty_fd);
488 LLDB_LOG(log,
"hooked up STDIO pty to process");
490 LLDB_LOG(log,
"not using process STDIO pty");
506 llvm::StringRef expr_prefix, lldb::ValueObjectSP &result_valobj_sp) {
516 return Status(
"Selected thread isn't valid");
518 StackFrameSP frame_sp(thread_sp->GetStackFrameAtIndex(0));
520 return Status(
"Frame 0 isn't valid");
523 frame_sp->CalculateExecutionContext(exe_ctx);
536 result_valobj_sp, expr_error);
540 if (result_valobj_sp->GetError().Fail())
541 return result_valobj_sp->
GetError();
545std::unique_ptr<UtilityFunction>
563 static const char *dlopen_wrapper_code = R
"(
564 const int RTLD_LAZY = 1;
566 struct __lldb_dlopen_result {
568 const char *error_str;
571 extern "C" void *memcpy(void *, const void *, size_t size);
572 extern "C" size_t strlen(const char *);
575 void * __lldb_dlopen_wrapper (const char *name,
576 const char *path_strings,
578 __lldb_dlopen_result *result_ptr)
580 // This is the case where the name is the full path:
582 result_ptr->image_ptr = dlopen(name, RTLD_LAZY);
583 if (result_ptr->image_ptr)
584 result_ptr->error_str = nullptr;
586 result_ptr->error_str = dlerror();
590 // This is the case where we have a list of paths:
591 size_t name_len = strlen(name);
592 while (path_strings && path_strings[0] != '\0') {
593 size_t path_len = strlen(path_strings);
594 memcpy((void *) buffer, (void *) path_strings, path_len);
595 buffer[path_len] = '/';
596 char *target_ptr = buffer+path_len+1;
597 memcpy((void *) target_ptr, (void *) name, name_len + 1);
598 result_ptr->image_ptr = dlopen(buffer, RTLD_LAZY);
599 if (result_ptr->image_ptr) {
600 result_ptr->error_str = nullptr;
603 result_ptr->error_str = dlerror();
604 path_strings = path_strings + path_len + 1;
610 static const char *dlopen_wrapper_name =
"__lldb_dlopen_wrapper";
614 expr.append(dlopen_wrapper_code);
620 if (!utility_fn_or_error) {
621 std::string error_str = llvm::toString(utility_fn_or_error.takeError());
622 error.SetErrorStringWithFormat(
623 "dlopen error: could not create utility function: %s",
627 std::unique_ptr<UtilityFunction> dlopen_utility_func_up =
628 std::move(*utility_fn_or_error);
635 TypeSystemClangSP scratch_ts_sp =
656 do_dlopen_function = dlopen_utility_func_up->MakeFunctionCaller(
657 clang_void_pointer_type, arguments, exe_ctx.
GetThreadSP(), utility_error);
658 if (utility_error.
Fail()) {
659 error.SetErrorStringWithFormat(
660 "dlopen error: could not make function caller: %s",
665 do_dlopen_function = dlopen_utility_func_up->GetFunctionCaller();
666 if (!do_dlopen_function) {
667 error.SetErrorString(
"dlopen error: could not get function caller.");
672 return dlopen_utility_func_up;
677 const std::vector<std::string> *paths,
681 loaded_image->
Clear();
688 error.SetErrorString(
"dlopen error: no thread available to call dlopen.");
695 thread_sp->CalculateExecutionContext(exe_ctx);
705 this, [&]() -> std::unique_ptr<UtilityFunction> {
709 if (!dlopen_utility_func)
713 if (!do_dlopen_function) {
714 error.SetErrorString(
"dlopen error: could not get function caller.");
721 uint32_t permissions = ePermissionsReadable|ePermissionsWritable;
722 size_t path_len = path.size() + 1;
727 error.SetErrorStringWithFormat(
728 "dlopen error: could not allocate memory for path: %s",
734 auto path_cleanup = llvm::make_scope_exit([process, path_addr] {
739 process->
WriteMemory(path_addr, path.c_str(), path_len, utility_error);
740 if (utility_error.
Fail()) {
741 error.SetErrorStringWithFormat(
742 "dlopen error: could not write path string: %s",
753 if (utility_error.
Fail()) {
754 error.SetErrorStringWithFormat(
755 "dlopen error: could not allocate memory for path: %s",
761 auto return_cleanup = llvm::make_scope_exit([process, return_addr] {
769 std::optional<llvm::detail::scope_exit<std::function<void()>>>
776 std::optional<llvm::detail::scope_exit<std::function<void()>>> buffer_cleanup;
779 if (paths !=
nullptr) {
784 size_t buffer_size = 0;
785 std::string path_array;
786 for (
auto path : *paths) {
791 size_t path_size = path.size();
792 path_array.append(path);
793 path_array.push_back(
'\0');
794 if (path_size > buffer_size)
795 buffer_size = path_size;
797 path_array.push_back(
'\0');
803 error.SetErrorStringWithFormat(
804 "dlopen error: could not allocate memory for path array: %s",
810 path_array_cleanup.emplace([process, path_array_addr]() {
815 process->
WriteMemory(path_array_addr, path_array.data(),
816 path_array.size(), utility_error);
818 if (utility_error.
Fail()) {
819 error.SetErrorStringWithFormat(
820 "dlopen error: could not write path array: %s",
826 buffer_size += path.size() + 2;
832 error.SetErrorStringWithFormat(
833 "dlopen error: could not allocate memory for buffer: %s",
839 buffer_cleanup.emplace([process, buffer_addr]() {
857 error.SetErrorStringWithFormat(
858 "dlopen error: could not write function arguments: %s",
867 llvm::make_scope_exit([do_dlopen_function, &exe_ctx, func_args_addr] {
875 options.SetIgnoreBreakpoints(
true);
876 options.SetUnwindOnError(
true);
877 options.SetTrapExceptions(
false);
880 options.SetIsForUtilityExpr(
true);
884 TypeSystemClangSP scratch_ts_sp =
886 if (!scratch_ts_sp) {
887 error.SetErrorString(
"dlopen error: Unable to get TypeSystemClang");
897 exe_ctx, &func_args_addr, options, diagnostics, return_value);
899 error.SetErrorStringWithFormat(
900 "dlopen error: failed executing dlopen wrapper function: %s",
908 if (utility_error.
Fail()) {
909 error.SetErrorStringWithFormat(
910 "dlopen error: could not read the return struct: %s",
917 if (loaded_image && buffer_addr != 0x0)
921 std::string name_string;
924 loaded_image->
SetFile(name_string, llvm::sys::path::Style::posix);
930 std::string dlopen_error_str;
933 if (utility_error.
Fail()) {
934 error.SetErrorStringWithFormat(
935 "dlopen error: could not read error string: %s",
943 if (utility_error.
Success() && num_chars > 0)
944 error.SetErrorStringWithFormat(
"dlopen error: %s",
945 dlopen_error_str.c_str());
947 error.SetErrorStringWithFormat(
"dlopen failed for unknown reasons.");
956 return Status(
"Invalid image token");
959 expr.
Printf(
"dlclose((void *)0x%" PRIx64
")", image_addr);
961 lldb::ValueObjectSP result_valobj_sp;
967 if (result_valobj_sp->GetError().Fail())
968 return result_valobj_sp->GetError();
971 if (result_valobj_sp->ResolveValue(scalar)) {
982 extern "C" void* dlopen(const char*, int);
983 extern "C" void* dlsym(void*, const char*);
984 extern "C" int dlclose(void*);
985 extern "C" char* dlerror(void);
999 return std::make_shared<UnixSignals>();
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
#define LLDB_LOGF(log,...)
A command line argument class.
Generic representation of a type in a programming language.
CompilerType GetPointerType() const
Return a new CompilerType that is a pointer to this type.
A uniqued constant string class.
bool IsEmpty() const
Test for empty string.
const char * GetCString() const
Get the string value as a C string.
A subclass of DataBuffer that stores a data buffer on the heap.
A class to manage flag bits.
TargetList & GetTargetList()
Get accessor for the target list.
std::string GetString(char separator='\n')
A plug-in interface definition class for dynamic loaders.
virtual Status CanLoadImage()=0
Ask if it is ok to try and load or unload an shared library (image).
void SetLanguage(lldb::LanguageType language)
void SetUnwindOnError(bool unwind=false)
void SetExecutionPolicy(ExecutionPolicy policy=eExecutionPolicyAlways)
void SetTrapExceptions(bool b)
void SetTimeout(const Timeout< std::micro > &timeout)
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 Dump(Stream &stream) const
lldb::user_id_t OpenFile(const FileSpec &file_spec, File::OpenOptions flags, uint32_t mode, Status &error)
static FileCache & GetInstance()
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 Status RunShellCommand(llvm::StringRef command, const FileSpec &working_dir, int *status_ptr, int *signo_ptr, std::string *command_output, const Timeout< std::micro > &timeout, bool run_in_shell=true, bool hide_stderr=false)
Run a shell command.
static lldb::ListenerSP MakeListener(const char *name)
virtual llvm::StringRef GetPluginName()=0
void SetHijackListener(const lldb::ListenerSP &listener_sp)
lldb::ListenerSP GetHijackListener() const
lldb::ListenerSP GetListenerForProcess(Debugger &debugger)
PseudoTerminal & GetPTY()
const FileAction * GetFileActionAtIndex(size_t idx) const
lldb::ListenerSP GetHijackListener() const
void SetLaunchInSeparateProcessGroup(bool separate)
lldb::ListenerSP GetListener() 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)
lldb::addr_t CallocateMemory(size_t size, uint32_t permissions, Status &error)
The public interface to allocating memory in the process, this also clears the allocated memory.
ThreadList & GetThreadList()
lldb::addr_t AllocateMemory(size_t size, uint32_t permissions, Status &error)
The public interface to allocating memory in the process.
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 AddImageToken(lldb::addr_t image_ptr)
lldb::addr_t ReadPointerFromMemory(lldb::addr_t vm_addr, Status &error)
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.
Target & GetTarget()
Get the target object pointer for this module.
int ReleasePrimaryFileDescriptor()
Release the primary file descriptor.
@ invalid_fd
Invalid file descriptor value.
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.
ValueType GetError() const
Access the error value.
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.
bool Success() const
Test for success condition.
const char * GetData() const
llvm::StringRef GetString() const
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
size_t PutCString(llvm::StringRef cstr)
Output a C string 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.
lldb::ModuleSP GetExecutableModule()
Gets the module for the main executable.
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.
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, 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...
"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
void SetCompilerType(const CompilerType &compiler_type)
void SetValueType(ValueType value_type)
#define LLDB_INVALID_IMAGE_TOKEN
#define LLDB_INVALID_ADDRESS
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.
@ eLanguageTypeC_plus_plus
ISO C++:1998.
ExpressionResults
The results of expression evaluation.