forked from OSchip/llvm-project
Fix "process load/unload" on android
On android the symbols exposed by libdl (dlopen, dlclose, dlerror) prefixed by "__dl_". This change moves the handling of process load/unload to the platform object and override it for android to handle the special prefix. Differential revision: http://reviews.llvm.org/D11465 llvm-svn: 254504
This commit is contained in:
parent
8b5dc2c94e
commit
3cb132a0f4
|
@ -987,9 +987,41 @@ class ModuleCache;
|
|||
virtual uint32_t
|
||||
GetDefaultMemoryCacheLineSize() { return 0; }
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Load a shared library into this process.
|
||||
///
|
||||
/// Try and load a shared library into the current process. This
|
||||
/// call might fail in the dynamic loader plug-in says it isn't safe
|
||||
/// to try and load shared libraries at the moment.
|
||||
///
|
||||
/// @param[in] process
|
||||
/// The process to load the image.
|
||||
///
|
||||
/// @param[in] image_spec
|
||||
/// The image file spec that points to the shared library that
|
||||
/// you want to load.
|
||||
///
|
||||
/// @param[out] error
|
||||
/// An error object that gets filled in with any errors that
|
||||
/// might occur when trying to load the shared library.
|
||||
///
|
||||
/// @return
|
||||
/// A token that represents the shared library that can be
|
||||
/// later used to unload the shared library. A value of
|
||||
/// LLDB_INVALID_IMAGE_TOKEN will be returned if the shared
|
||||
/// library can't be opened.
|
||||
//------------------------------------------------------------------
|
||||
virtual uint32_t
|
||||
LoadImage (lldb_private::Process* process,
|
||||
const lldb_private::FileSpec& image_spec,
|
||||
lldb_private::Error& error);
|
||||
|
||||
virtual Error
|
||||
UnloadImage (lldb_private::Process* process, uint32_t image_token);
|
||||
|
||||
protected:
|
||||
bool m_is_host;
|
||||
// Set to true when we are able to actually set the OS version while
|
||||
// Set to true when we are able to actually set the OS version while
|
||||
// being connected. For remote platforms, we might set the version ahead
|
||||
// of time before we actually connect and this version might change when
|
||||
// we actually connect to a remote platform. For the host platform this
|
||||
|
|
|
@ -1234,33 +1234,6 @@ public:
|
|||
virtual lldb::addr_t
|
||||
GetImageInfoAddress ();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Load a shared library into this process.
|
||||
///
|
||||
/// Try and load a shared library into the current process. This
|
||||
/// call might fail in the dynamic loader plug-in says it isn't safe
|
||||
/// to try and load shared libraries at the moment.
|
||||
///
|
||||
/// @param[in] image_spec
|
||||
/// The image file spec that points to the shared library that
|
||||
/// you want to load.
|
||||
///
|
||||
/// @param[out] error
|
||||
/// An error object that gets filled in with any errors that
|
||||
/// might occur when trying to load the shared library.
|
||||
///
|
||||
/// @return
|
||||
/// A token that represents the shared library that can be
|
||||
/// later used to unload the shared library. A value of
|
||||
/// LLDB_INVALID_IMAGE_TOKEN will be returned if the shared
|
||||
/// library can't be opened.
|
||||
//------------------------------------------------------------------
|
||||
virtual uint32_t
|
||||
LoadImage (const FileSpec &image_spec, Error &error);
|
||||
|
||||
virtual Error
|
||||
UnloadImage (uint32_t image_token);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Called when the process is about to broadcast a public stop.
|
||||
///
|
||||
|
@ -3160,6 +3133,15 @@ public:
|
|||
return Error("Not supported");
|
||||
}
|
||||
|
||||
size_t
|
||||
AddImageToken(lldb::addr_t image_ptr);
|
||||
|
||||
lldb::addr_t
|
||||
GetImagePtrFromToken(size_t token) const;
|
||||
|
||||
void
|
||||
ResetImageToken(size_t token);
|
||||
|
||||
protected:
|
||||
void
|
||||
SetState (lldb::EventSP &event_sp);
|
||||
|
|
|
@ -182,7 +182,6 @@ class LoadUnloadTestCase(TestBase):
|
|||
|
||||
@skipIfFreeBSD # llvm.org/pr14424 - missing FreeBSD Makefiles/testcase support
|
||||
@skipUnlessListedRemote(['android'])
|
||||
@expectedFailureAndroid # dlopen and dlclose prefixed with "__dl_" on android causing JIT compilation issues
|
||||
@skipIfWindows # Windows doesn't have dlopen and friends, dynamic libraries work differently
|
||||
def test_lldb_process_load_and_unload_commands(self):
|
||||
"""Test that lldb process load/unload command work correctly."""
|
||||
|
@ -205,21 +204,24 @@ class LoadUnloadTestCase(TestBase):
|
|||
shlib_dir = lldb.remote_platform.GetWorkingDirectory()
|
||||
else:
|
||||
shlib_dir = self.mydir
|
||||
# Make sure that a_function does not exist at this point.
|
||||
self.expect("image lookup -n a_function", "a_function should not exist yet",
|
||||
error=True, matching=False,
|
||||
patterns = ["1 match found .* %s" % shlib_dir])
|
||||
|
||||
if lldb.remote_platform:
|
||||
dylibName = os.path.join(shlib_dir, 'libloadunload_a.so')
|
||||
elif self.platformIsDarwin():
|
||||
if self.platformIsDarwin():
|
||||
dylibName = 'libloadunload_a.dylib'
|
||||
else:
|
||||
dylibName = 'libloadunload_a.so'
|
||||
|
||||
if lldb.remote_platform:
|
||||
dylibPath = os.path.join(shlib_dir, dylibName)
|
||||
else:
|
||||
dylibPath = dylibName
|
||||
|
||||
# Make sure that a_function does not exist at this point.
|
||||
self.expect("image lookup -n a_function", "a_function should not exist yet",
|
||||
error=True, matching=False, patterns = ["1 match found"])
|
||||
|
||||
# Use lldb 'process load' to load the dylib.
|
||||
self.expect("process load %s" % dylibName, "%s loaded correctly" % dylibName,
|
||||
patterns = ['Loading "%s".*ok' % dylibName,
|
||||
self.expect("process load %s" % dylibPath, "%s loaded correctly" % dylibPath,
|
||||
patterns = ['Loading "%s".*ok' % dylibPath,
|
||||
'Image [0-9]+ loaded'])
|
||||
|
||||
# Search for and match the "Image ([0-9]+) loaded" pattern.
|
||||
|
@ -234,7 +236,7 @@ class LoadUnloadTestCase(TestBase):
|
|||
|
||||
# Now we should have an entry for a_function.
|
||||
self.expect("image lookup -n a_function", "a_function should now exist",
|
||||
patterns = ["1 match found .*%s" % shlib_dir])
|
||||
patterns = ["1 match found .*%s" % dylibName])
|
||||
|
||||
# Use lldb 'process unload' to unload the dylib.
|
||||
self.expect("process unload %s" % index, "%s unloaded correctly" % dylibName,
|
||||
|
|
|
@ -1297,7 +1297,8 @@ SBProcess::LoadImage (lldb::SBFileSpec &sb_image_spec, lldb::SBError &sb_error)
|
|||
if (stop_locker.TryLock(&process_sp->GetRunLock()))
|
||||
{
|
||||
Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
|
||||
return process_sp->LoadImage (*sb_image_spec, sb_error.ref());
|
||||
PlatformSP platform_sp = process_sp->GetTarget().GetPlatform();
|
||||
return platform_sp->LoadImage (process_sp.get(), *sb_image_spec, sb_error.ref());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1322,7 +1323,8 @@ SBProcess::UnloadImage (uint32_t image_token)
|
|||
if (stop_locker.TryLock(&process_sp->GetRunLock()))
|
||||
{
|
||||
Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
|
||||
sb_error.SetError (process_sp->UnloadImage (image_token));
|
||||
PlatformSP platform_sp = process_sp->GetTarget().GetPlatform();
|
||||
sb_error.SetError (platform_sp->UnloadImage (process_sp.get(), image_token));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1204,8 +1204,9 @@ protected:
|
|||
Error error;
|
||||
const char *image_path = command.GetArgumentAtIndex(i);
|
||||
FileSpec image_spec (image_path, false);
|
||||
process->GetTarget().GetPlatform()->ResolveRemotePath(image_spec, image_spec);
|
||||
uint32_t image_token = process->LoadImage(image_spec, error);
|
||||
PlatformSP platform = process->GetTarget().GetPlatform();
|
||||
platform->ResolveRemotePath(image_spec, image_spec);
|
||||
uint32_t image_token = platform->LoadImage(process, image_spec, error);
|
||||
if (image_token != LLDB_INVALID_IMAGE_TOKEN)
|
||||
{
|
||||
result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token);
|
||||
|
@ -1267,7 +1268,7 @@ protected:
|
|||
}
|
||||
else
|
||||
{
|
||||
Error error (process->UnloadImage(image_token));
|
||||
Error error (process->GetTarget().GetPlatform()->UnloadImage(process, image_token));
|
||||
if (error.Success())
|
||||
{
|
||||
result.AppendMessageWithFormat ("Unloading shared library with index %u...ok\n", image_token);
|
||||
|
|
|
@ -13,7 +13,9 @@
|
|||
#include "lldb/Core/Log.h"
|
||||
#include "lldb/Core/Module.h"
|
||||
#include "lldb/Core/PluginManager.h"
|
||||
#include "lldb/Core/Scalar.h"
|
||||
#include "lldb/Core/Section.h"
|
||||
#include "lldb/Core/ValueObject.h"
|
||||
#include "lldb/Host/HostInfo.h"
|
||||
#include "lldb/Host/StringConvert.h"
|
||||
#include "Utility/UriParser.h"
|
||||
|
@ -374,3 +376,91 @@ PlatformAndroid::GetRemoteOSVersion ()
|
|||
m_update_os_version = 0;
|
||||
return m_major_os_version != 0;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
PlatformAndroid::LoadImage(lldb_private::Process* process, const FileSpec& image_spec, Error& error)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
image_spec.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 = __dl_dlopen ("%s", 2);
|
||||
if (the_result.image_ptr == (void*)0x0)
|
||||
the_result.error_str = __dl_dlerror();
|
||||
else
|
||||
the_result.error_str = (const char*)0x0;
|
||||
the_result;
|
||||
)",
|
||||
path);
|
||||
const char *prefix = R"(
|
||||
extern "C" void* __dl_dlopen(const char* path, int mode);
|
||||
extern "C" const char *__dl_dlerror(void);
|
||||
)";
|
||||
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
|
||||
PlatformAndroid::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("__dl_dlclose((void*)0x%" PRIx64 ")", image_addr);
|
||||
const char *prefix = "extern \"C\" int __dl_dlclose(void* handle);\n";
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -84,6 +84,14 @@ namespace platform_android {
|
|||
uint32_t
|
||||
GetDefaultMemoryCacheLineSize() override;
|
||||
|
||||
uint32_t
|
||||
LoadImage (lldb_private::Process* process,
|
||||
const lldb_private::FileSpec& image_spec,
|
||||
lldb_private::Error& error) override;
|
||||
|
||||
lldb_private::Error
|
||||
UnloadImage (lldb_private::Process* process, uint32_t image_token) override;
|
||||
|
||||
protected:
|
||||
const char *
|
||||
GetCacheHostname () override;
|
||||
|
|
|
@ -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;
|
||||
|
@ -846,6 +851,140 @@ 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::LoadImage(lldb_private::Process* process, const FileSpec& image_spec, Error& error)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
image_spec.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 = R"(
|
||||
extern "C" void* dlopen (const char *path, int mode);
|
||||
extern "C" const char *dlerror (void);
|
||||
)";
|
||||
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 = "extern \"C\" int dlclose(void* handle);\n";
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -173,11 +173,24 @@ public:
|
|||
lldb_private::Error
|
||||
DisconnectRemote () override;
|
||||
|
||||
uint32_t
|
||||
LoadImage (lldb_private::Process* process,
|
||||
const lldb_private::FileSpec& image_spec,
|
||||
lldb_private::Error& error) override;
|
||||
|
||||
lldb_private::Error
|
||||
UnloadImage (lldb_private::Process* process, uint32_t image_token) 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);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN (PlatformPOSIX);
|
||||
};
|
||||
|
|
|
@ -1983,3 +1983,16 @@ Platform::GetUnixSignals()
|
|||
return Host::GetUnixSignals();
|
||||
return GetRemoteUnixSignals();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Platform::LoadImage(lldb_private::Process* process, const FileSpec& image_spec, Error& error)
|
||||
{
|
||||
error.SetErrorString("LoadImage is not supported on the current platform");
|
||||
return LLDB_INVALID_IMAGE_TOKEN;
|
||||
}
|
||||
|
||||
Error
|
||||
Platform::UnloadImage(lldb_private::Process* process, uint32_t image_token)
|
||||
{
|
||||
return Error("UnLoadImage is not supported on the current platform");
|
||||
}
|
||||
|
|
|
@ -1885,223 +1885,6 @@ Process::GetImageInfoAddress()
|
|||
return LLDB_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// LoadImage
|
||||
//
|
||||
// This function provides a default implementation that works for most
|
||||
// unix variants. Any Process subclasses that need to do shared library
|
||||
// loading differently should override LoadImage and UnloadImage and
|
||||
// do what is needed.
|
||||
//----------------------------------------------------------------------
|
||||
uint32_t
|
||||
Process::LoadImage (const FileSpec &image_spec, Error &error)
|
||||
{
|
||||
if (m_finalizing)
|
||||
{
|
||||
error.SetErrorString("process is tearing itself down");
|
||||
return LLDB_INVALID_IMAGE_TOKEN;
|
||||
}
|
||||
|
||||
char path[PATH_MAX];
|
||||
image_spec.GetPath(path, sizeof(path));
|
||||
|
||||
DynamicLoader *loader = GetDynamicLoader();
|
||||
if (loader)
|
||||
{
|
||||
error = loader->CanLoadImage();
|
||||
if (error.Fail())
|
||||
return LLDB_INVALID_IMAGE_TOKEN;
|
||||
}
|
||||
|
||||
if (error.Success())
|
||||
{
|
||||
ThreadSP thread_sp(GetThreadList ().GetSelectedThread());
|
||||
|
||||
if (thread_sp)
|
||||
{
|
||||
StackFrameSP frame_sp (thread_sp->GetStackFrameAtIndex (0));
|
||||
|
||||
if (frame_sp)
|
||||
{
|
||||
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.SetResultIsInternal(true);
|
||||
expr_options.SetLanguage(eLanguageTypeC_plus_plus);
|
||||
|
||||
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 = R"(
|
||||
extern "C" void* dlopen (const char *path, int mode);
|
||||
extern "C" const char *dlerror (void);
|
||||
)";
|
||||
lldb::ValueObjectSP result_valobj_sp;
|
||||
Error expr_error;
|
||||
UserExpression::Evaluate (exe_ctx,
|
||||
expr_options,
|
||||
expr.GetData(),
|
||||
prefix,
|
||||
result_valobj_sp,
|
||||
expr_error);
|
||||
if (expr_error.Success())
|
||||
{
|
||||
error = result_valobj_sp->GetError();
|
||||
if (error.Success())
|
||||
{
|
||||
Scalar scalar;
|
||||
ValueObjectSP image_ptr_sp = result_valobj_sp->GetChildAtIndex(0, true);
|
||||
if (image_ptr_sp && image_ptr_sp->ResolveValue (scalar))
|
||||
{
|
||||
addr_t image_ptr = scalar.ULongLong(LLDB_INVALID_ADDRESS);
|
||||
if (image_ptr != 0 && image_ptr != LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
uint32_t image_token = m_image_tokens.size();
|
||||
m_image_tokens.push_back (image_ptr);
|
||||
return image_token;
|
||||
}
|
||||
else if (image_ptr == 0)
|
||||
{
|
||||
ValueObjectSP error_str_sp = result_valobj_sp->GetChildAtIndex(1, true);
|
||||
if (error_str_sp)
|
||||
{
|
||||
if (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.Clear();
|
||||
error.SetErrorStringWithFormat("dlopen error: %s", buffer_sp->GetBytes());
|
||||
}
|
||||
else
|
||||
{
|
||||
error.Clear();
|
||||
error.SetErrorStringWithFormat("dlopen failed for unknown reasons.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
error = expr_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!error.AsCString())
|
||||
error.SetErrorStringWithFormat("unable to load '%s'", path);
|
||||
return LLDB_INVALID_IMAGE_TOKEN;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// UnloadImage
|
||||
//
|
||||
// This function provides a default implementation that works for most
|
||||
// unix variants. Any Process subclasses that need to do shared library
|
||||
// loading differently should override LoadImage and UnloadImage and
|
||||
// do what is needed.
|
||||
//----------------------------------------------------------------------
|
||||
Error
|
||||
Process::UnloadImage (uint32_t image_token)
|
||||
{
|
||||
Error error;
|
||||
|
||||
if (m_finalizing)
|
||||
{
|
||||
error.SetErrorString("process is tearing itself down");
|
||||
return error;
|
||||
}
|
||||
|
||||
if (image_token < m_image_tokens.size())
|
||||
{
|
||||
const addr_t image_addr = m_image_tokens[image_token];
|
||||
if (image_addr == LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
error.SetErrorString("image already unloaded");
|
||||
}
|
||||
else
|
||||
{
|
||||
DynamicLoader *loader = GetDynamicLoader();
|
||||
if (loader)
|
||||
error = loader->CanLoadImage();
|
||||
|
||||
if (error.Success())
|
||||
{
|
||||
ThreadSP thread_sp(GetThreadList ().GetSelectedThread());
|
||||
|
||||
if (thread_sp)
|
||||
{
|
||||
StackFrameSP frame_sp (thread_sp->GetStackFrameAtIndex (0));
|
||||
|
||||
if (frame_sp)
|
||||
{
|
||||
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);
|
||||
|
||||
StreamString expr;
|
||||
expr.Printf("dlclose ((void *)0x%" PRIx64 ")", image_addr);
|
||||
const char *prefix = "extern \"C\" int dlclose(void* handle);\n";
|
||||
lldb::ValueObjectSP result_valobj_sp;
|
||||
Error expr_error;
|
||||
UserExpression::Evaluate (exe_ctx,
|
||||
expr_options,
|
||||
expr.GetData(),
|
||||
prefix,
|
||||
result_valobj_sp,
|
||||
expr_error);
|
||||
if (result_valobj_sp->GetError().Success())
|
||||
{
|
||||
Scalar scalar;
|
||||
if (result_valobj_sp->ResolveValue (scalar))
|
||||
{
|
||||
if (scalar.UInt(1))
|
||||
{
|
||||
error.SetErrorStringWithFormat("expression failed: \"%s\"", expr.GetData());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_image_tokens[image_token] = LLDB_INVALID_ADDRESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error = result_valobj_sp->GetError();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error.SetErrorString("invalid image token");
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
const lldb::ABISP &
|
||||
Process::GetABI()
|
||||
{
|
||||
|
@ -6723,3 +6506,25 @@ Process::GetModuleSpec(const FileSpec& module_file_spec,
|
|||
module_spec.Clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t
|
||||
Process::AddImageToken(lldb::addr_t image_ptr)
|
||||
{
|
||||
m_image_tokens.push_back(image_ptr);
|
||||
return m_image_tokens.size() - 1;
|
||||
}
|
||||
|
||||
lldb::addr_t
|
||||
Process::GetImagePtrFromToken(size_t token) const
|
||||
{
|
||||
if (token < m_image_tokens.size())
|
||||
return m_image_tokens[token];
|
||||
return LLDB_INVALID_IMAGE_TOKEN;
|
||||
}
|
||||
|
||||
void
|
||||
Process::ResetImageToken(size_t token)
|
||||
{
|
||||
if (token < m_image_tokens.size())
|
||||
m_image_tokens[token] = LLDB_INVALID_IMAGE_TOKEN;
|
||||
}
|
Loading…
Reference in New Issue