diff options
Diffstat (limited to 'source/Plugins/Platform/POSIX')
-rw-r--r-- | source/Plugins/Platform/POSIX/PlatformPOSIX.cpp | 185 | ||||
-rw-r--r-- | source/Plugins/Platform/POSIX/PlatformPOSIX.h | 60 |
2 files changed, 222 insertions, 23 deletions
diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp index b4f841a..c756465 100644 --- a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp +++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp @@ -19,13 +19,18 @@ #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Expression/UserExpression.h" #include "lldb/Host/File.h" #include "lldb/Host/FileCache.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" +#include "lldb/Target/DynamicLoader.h" +#include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/ProcessLaunchInfo.h" +#include "lldb/Target/Thread.h" using namespace lldb; using namespace lldb_private; @@ -673,9 +678,12 @@ PlatformPOSIX::ConnectRemote (Args& args) if (m_options.get()) { OptionGroupOptions* options = m_options.get(); - const OptionGroupPlatformRSync* m_rsync_options = (OptionGroupPlatformRSync*)options->GetGroupWithOption('r'); - const OptionGroupPlatformSSH* m_ssh_options = (OptionGroupPlatformSSH*)options->GetGroupWithOption('s'); - const OptionGroupPlatformCaching* m_cache_options = (OptionGroupPlatformCaching*)options->GetGroupWithOption('c'); + const OptionGroupPlatformRSync *m_rsync_options = + static_cast<const OptionGroupPlatformRSync *>(options->GetGroupWithOption('r')); + const OptionGroupPlatformSSH *m_ssh_options = + static_cast<const OptionGroupPlatformSSH *>(options->GetGroupWithOption('s')); + const OptionGroupPlatformCaching *m_cache_options = + static_cast<const OptionGroupPlatformCaching *>(options->GetGroupWithOption('c')); if (m_rsync_options->m_rsync) { @@ -843,6 +851,175 @@ PlatformPOSIX::DebugProcess (ProcessLaunchInfo &launch_info, void PlatformPOSIX::CalculateTrapHandlerSymbolNames () -{ +{ m_trap_handlers.push_back (ConstString ("_sigtramp")); +} + +Error +PlatformPOSIX::EvaluateLibdlExpression(lldb_private::Process* process, + const char* expr_cstr, + const char* expr_prefix, + lldb::ValueObjectSP& result_valobj_sp) +{ + DynamicLoader *loader = process->GetDynamicLoader(); + if (loader) + { + Error error = loader->CanLoadImage(); + if (error.Fail()) + return error; + } + + ThreadSP thread_sp(process->GetThreadList().GetSelectedThread()); + if (!thread_sp) + return Error("Selected thread isn't valid"); + + StackFrameSP frame_sp(thread_sp->GetStackFrameAtIndex(0)); + if (!frame_sp) + return Error("Frame 0 isn't valid"); + + ExecutionContext exe_ctx; + frame_sp->CalculateExecutionContext(exe_ctx); + EvaluateExpressionOptions expr_options; + expr_options.SetUnwindOnError(true); + expr_options.SetIgnoreBreakpoints(true); + expr_options.SetExecutionPolicy(eExecutionPolicyAlways); + expr_options.SetLanguage(eLanguageTypeC_plus_plus); + + Error expr_error; + UserExpression::Evaluate(exe_ctx, + expr_options, + expr_cstr, + expr_prefix, + result_valobj_sp, + expr_error); + if (result_valobj_sp->GetError().Fail()) + return result_valobj_sp->GetError(); + return Error(); +} + +uint32_t +PlatformPOSIX::DoLoadImage(lldb_private::Process* process, + const lldb_private::FileSpec& remote_file, + lldb_private::Error& error) +{ + char path[PATH_MAX]; + remote_file.GetPath(path, sizeof(path)); + + StreamString expr; + expr.Printf(R"( + struct __lldb_dlopen_result { void *image_ptr; const char *error_str; } the_result; + the_result.image_ptr = dlopen ("%s", 2); + if (the_result.image_ptr == (void *) 0x0) + { + the_result.error_str = dlerror(); + } + else + { + the_result.error_str = (const char *) 0x0; + } + the_result; + )", + path); + const char *prefix = GetLibdlFunctionDeclarations(); + lldb::ValueObjectSP result_valobj_sp; + error = EvaluateLibdlExpression(process, expr.GetData(), prefix, result_valobj_sp); + if (error.Fail()) + return LLDB_INVALID_IMAGE_TOKEN; + + error = result_valobj_sp->GetError(); + if (error.Fail()) + return LLDB_INVALID_IMAGE_TOKEN; + + Scalar scalar; + ValueObjectSP image_ptr_sp = result_valobj_sp->GetChildAtIndex(0, true); + if (!image_ptr_sp || !image_ptr_sp->ResolveValue(scalar)) + { + error.SetErrorStringWithFormat("unable to load '%s'", path); + return LLDB_INVALID_IMAGE_TOKEN; + } + + addr_t image_ptr = scalar.ULongLong(LLDB_INVALID_ADDRESS); + if (image_ptr != 0 && image_ptr != LLDB_INVALID_ADDRESS) + return process->AddImageToken(image_ptr); + + if (image_ptr == 0) + { + ValueObjectSP error_str_sp = result_valobj_sp->GetChildAtIndex(1, true); + if (error_str_sp && error_str_sp->IsCStringContainer(true)) + { + DataBufferSP buffer_sp(new DataBufferHeap(10240,0)); + size_t num_chars = error_str_sp->ReadPointedString (buffer_sp, error, 10240).first; + if (error.Success() && num_chars > 0) + error.SetErrorStringWithFormat("dlopen error: %s", buffer_sp->GetBytes()); + else + error.SetErrorStringWithFormat("dlopen failed for unknown reasons."); + return LLDB_INVALID_IMAGE_TOKEN; + } + } + error.SetErrorStringWithFormat("unable to load '%s'", path); + return LLDB_INVALID_IMAGE_TOKEN; +} + +Error +PlatformPOSIX::UnloadImage (lldb_private::Process* process, uint32_t image_token) +{ + const addr_t image_addr = process->GetImagePtrFromToken(image_token); + if (image_addr == LLDB_INVALID_ADDRESS) + return Error("Invalid image token"); + + StreamString expr; + expr.Printf("dlclose((void *)0x%" PRIx64 ")", image_addr); + const char *prefix = GetLibdlFunctionDeclarations(); + lldb::ValueObjectSP result_valobj_sp; + Error error = EvaluateLibdlExpression(process, expr.GetData(), prefix, result_valobj_sp); + if (error.Fail()) + return error; + + if (result_valobj_sp->GetError().Fail()) + return result_valobj_sp->GetError(); + + Scalar scalar; + if (result_valobj_sp->ResolveValue(scalar)) + { + if (scalar.UInt(1)) + return Error("expression failed: \"%s\"", expr.GetData()); + process->ResetImageToken(image_token); + } + return Error(); } + +lldb::ProcessSP +PlatformPOSIX::ConnectProcess (const char* connect_url, + const char* plugin_name, + lldb_private::Debugger &debugger, + lldb_private::Target *target, + lldb_private::Error &error) +{ + if (m_remote_platform_sp) + return m_remote_platform_sp->ConnectProcess(connect_url, + plugin_name, + debugger, + target, + error); + + return Platform::ConnectProcess(connect_url, plugin_name, debugger, target, error); +} + +const char* +PlatformPOSIX::GetLibdlFunctionDeclarations() const +{ + return R"( + extern "C" void* dlopen(const char*, int); + extern "C" void* dlsym(void*, const char*); + extern "C" int dlclose(void*); + extern "C" char* dlerror(void); + )"; +} + +size_t +PlatformPOSIX::ConnectToWaitingProcesses(Debugger& debugger, Error& error) +{ + if (m_remote_platform_sp) + return m_remote_platform_sp->ConnectToWaitingProcesses(debugger, error); + return Platform::ConnectToWaitingProcesses(debugger, error); +} diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/source/Plugins/Platform/POSIX/PlatformPOSIX.h index 82686dc..60f6207 100644 --- a/source/Plugins/Platform/POSIX/PlatformPOSIX.h +++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.h @@ -12,7 +12,6 @@ // C Includes // C++ Includes - #include <memory> // Other libraries and framework includes @@ -23,11 +22,10 @@ class PlatformPOSIX : public lldb_private::Platform { public: - PlatformPOSIX (bool is_host); - - virtual - ~PlatformPOSIX(); - + PlatformPOSIX(bool is_host); + + ~PlatformPOSIX() override; + //------------------------------------------------------------ // lldb_private::Platform functions //------------------------------------------------------------ @@ -37,9 +35,8 @@ public: const lldb_private::ArchSpec& arch, lldb_private::ModuleSpec &module_spec) override; - lldb_private::OptionGroupOptions - *GetConnectionOptions( - lldb_private::CommandInterpreter &interpreter) override; + lldb_private::OptionGroupOptions* + GetConnectionOptions(lldb_private::CommandInterpreter &interpreter) override; const char * GetHostname () override; @@ -119,11 +116,11 @@ public: IsConnected () const override; lldb_private::Error - RunShellCommand(const char *command, // Shouldn't be NULL + RunShellCommand(const char *command, // Shouldn't be nullptr const lldb_private::FileSpec &working_dir, // Pass empty FileSpec to use the current working directory - int *status_ptr, // Pass NULL if you don't want the process exit status - int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit - std::string *command_output, // Pass NULL if you don't want the command output + int *status_ptr, // Pass nullptr if you don't want the process exit status + int *signo_ptr, // Pass nullptr if you don't want the signal that caused the process to exit + std::string *command_output, // Pass nullptr if you don't want the command output uint32_t timeout_sec) override; // Timeout in seconds to wait for shell program to finish lldb_private::Error @@ -150,13 +147,13 @@ public: lldb::ProcessSP Attach (lldb_private::ProcessAttachInfo &attach_info, lldb_private::Debugger &debugger, - lldb_private::Target *target, // Can be NULL, if NULL create a new target, else use existing one + lldb_private::Target *target, // Can be nullptr, if nullptr create a new target, else use existing one lldb_private::Error &error) override; lldb::ProcessSP DebugProcess (lldb_private::ProcessLaunchInfo &launch_info, lldb_private::Debugger &debugger, - lldb_private::Target *target, // Can be NULL, if NULL create a new target, else use existing one + lldb_private::Target *target, // Can be nullptr, if nullptr create a new target, else use existing one lldb_private::Error &error) override; std::string @@ -176,14 +173,39 @@ public: lldb_private::Error DisconnectRemote () override; + uint32_t + DoLoadImage (lldb_private::Process* process, + const lldb_private::FileSpec& remote_file, + lldb_private::Error& error) override; + + lldb_private::Error + UnloadImage (lldb_private::Process* process, uint32_t image_token) override; + + lldb::ProcessSP + ConnectProcess (const char* connect_url, + const char* plugin_name, + lldb_private::Debugger &debugger, + lldb_private::Target *target, + lldb_private::Error &error) override; + + size_t + ConnectToWaitingProcesses(lldb_private::Debugger& debugger, lldb_private::Error& error) override; + protected: std::unique_ptr<lldb_private::OptionGroupOptions> m_options; - lldb::PlatformSP m_remote_platform_sp; // Allow multiple ways to connect to a remote POSIX-compliant OS - + + lldb_private::Error + EvaluateLibdlExpression(lldb_private::Process* process, + const char *expr_cstr, + const char *expr_prefix, + lldb::ValueObjectSP& result_valobj_sp); + + virtual const char* + GetLibdlFunctionDeclarations() const; + private: DISALLOW_COPY_AND_ASSIGN (PlatformPOSIX); - }; -#endif // liblldb_PlatformPOSIX_h_ +#endif // liblldb_PlatformPOSIX_h_ |