summaryrefslogtreecommitdiff
path: root/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/Platform/POSIX/PlatformPOSIX.cpp')
-rw-r--r--source/Plugins/Platform/POSIX/PlatformPOSIX.cpp185
1 files changed, 181 insertions, 4 deletions
diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
index b4f841a16dec4..c7564655a11b5 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);
+}