forked from OSchip/llvm-project
Add a way to load an image using a library name and list of paths.
This provides an efficient (at least on Posix platforms) way to offload to the target process the search & loading of a library when all we have are the library name and a set of potential candidate locations. <rdar://problem/40905971> llvm-svn: 335912
This commit is contained in:
parent
3cabf73270
commit
0d231f7161
|
@ -313,6 +313,40 @@ public:
|
|||
const lldb::SBFileSpec &remote_image_spec,
|
||||
lldb::SBError &error);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Load a shared library into this process, starting with a
|
||||
/// library name and a list of paths, searching along the list of
|
||||
/// paths till you find a matching library.
|
||||
///
|
||||
/// @param[in] local_spec
|
||||
/// The name of the shared library that you want to load.
|
||||
/// If local_spec is a relative path, the relative path will be
|
||||
/// appended to the search paths.
|
||||
/// If the local_spec is an absolute path, just the basename is used.
|
||||
///
|
||||
/// @param[in] paths
|
||||
/// A list of paths to search for the library whose basename is
|
||||
/// local_spec.
|
||||
///
|
||||
/// @param[out] loaded_path
|
||||
/// If the library was found along the paths, this will store the
|
||||
/// full path to the found library.
|
||||
///
|
||||
/// @param[out] error
|
||||
/// An error object that gets filled in with any errors that
|
||||
/// might occur when trying to search for the shared library.
|
||||
///
|
||||
/// @return
|
||||
/// A token that represents the shared library that can be
|
||||
/// later passed to UnloadImage. A value of
|
||||
/// LLDB_INVALID_IMAGE_TOKEN will be returned if the shared
|
||||
/// library can't be opened.
|
||||
//------------------------------------------------------------------
|
||||
uint32_t LoadImageUsingPaths(const lldb::SBFileSpec &image_spec,
|
||||
SBStringList &paths,
|
||||
lldb::SBFileSpec &loaded_path,
|
||||
lldb::SBError &error);
|
||||
|
||||
lldb::SBError UnloadImage(uint32_t image_token);
|
||||
|
||||
lldb::SBError SendEventData(const char *data);
|
||||
|
|
|
@ -832,9 +832,45 @@ public:
|
|||
const lldb_private::FileSpec &remote_file,
|
||||
lldb_private::Status &error);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Load a shared library specified by base name into this process,
|
||||
/// looking by hand along a set of paths.
|
||||
///
|
||||
/// @param[in] process
|
||||
/// The process to load the image.
|
||||
///
|
||||
/// @param[in] library_name
|
||||
/// The name of the library to look for.
|
||||
///
|
||||
/// @param[in] path_list
|
||||
/// The list of paths to use to search for the library. First
|
||||
/// match wins.
|
||||
///
|
||||
/// @param[out] error
|
||||
/// An error object that gets filled in with any errors that
|
||||
/// might occur when trying to load the shared library.
|
||||
///
|
||||
/// @param[out] loaded_path
|
||||
/// If non-null, the path to the dylib that was successfully loaded
|
||||
/// is stored in this path.
|
||||
///
|
||||
/// @return
|
||||
/// A token that represents the shared library which can be
|
||||
/// passed to UnloadImage. A value of
|
||||
/// LLDB_INVALID_IMAGE_TOKEN will be returned if the shared
|
||||
/// library can't be opened.
|
||||
//------------------------------------------------------------------
|
||||
uint32_t LoadImageUsingPaths(lldb_private::Process *process,
|
||||
const lldb_private::FileSpec &library_name,
|
||||
const std::vector<std::string> &paths,
|
||||
lldb_private::Status &error,
|
||||
lldb_private::FileSpec *loaded_path);
|
||||
|
||||
virtual uint32_t DoLoadImage(lldb_private::Process *process,
|
||||
const lldb_private::FileSpec &remote_file,
|
||||
lldb_private::Status &error);
|
||||
const std::vector<std::string> *paths,
|
||||
lldb_private::Status &error,
|
||||
lldb_private::FileSpec *loaded_path = nullptr);
|
||||
|
||||
virtual Status UnloadImage(lldb_private::Process *process,
|
||||
uint32_t image_token);
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
basic_process
|
|
@ -0,0 +1,13 @@
|
|||
LEVEL := ../../make
|
||||
|
||||
CXX_SOURCES := main.cpp
|
||||
|
||||
include $(LEVEL)/Makefile.rules
|
||||
|
||||
all: hidden_lib a.out
|
||||
|
||||
hidden_lib:
|
||||
$(MAKE) VPATH=$(SRCDIR)/hidden -I $(SRCDIR)/hidden -C hidden -f $(SRCDIR)/hidden/Makefile
|
||||
|
||||
clean::
|
||||
$(MAKE) -I $(SRCDIR)/hidden -C hidden -f $(SRCDIR)/hidden/Makefile clean
|
|
@ -0,0 +1,126 @@
|
|||
"""
|
||||
Test that SBProcess.LoadImageUsingPaths works correctly.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
|
||||
import os
|
||||
import time
|
||||
import re
|
||||
import lldb
|
||||
from lldbsuite.test.decorators import *
|
||||
from lldbsuite.test.lldbtest import *
|
||||
from lldbsuite.test import lldbutil
|
||||
|
||||
|
||||
@skipIfWindows # The Windows platform doesn't implement DoLoadImage.
|
||||
class LoadUsingPathsTestCase(TestBase):
|
||||
|
||||
mydir = TestBase.compute_mydir(__file__)
|
||||
|
||||
NO_DEBUG_INFO_TESTCASE = True
|
||||
|
||||
def setUp(self):
|
||||
# Call super's setUp().
|
||||
TestBase.setUp(self)
|
||||
# Make the hidden directory in the build hierarchy:
|
||||
lldbutil.mkdir_p(self.getBuildArtifact("hidden"))
|
||||
|
||||
# Invoke the default build rule.
|
||||
self.build()
|
||||
|
||||
ext = 'so'
|
||||
if self.platformIsDarwin():
|
||||
ext = 'dylib'
|
||||
self.lib_name = 'libloadunload.' + ext
|
||||
|
||||
self.wd = self.getBuildDir()
|
||||
self.hidden_dir = os.path.join(self.wd, 'hidden')
|
||||
self.hidden_lib = os.path.join(self.hidden_dir, self.lib_name)
|
||||
|
||||
@skipIfFreeBSD # llvm.org/pr14424 - missing FreeBSD Makefiles/testcase support
|
||||
@not_remote_testsuite_ready
|
||||
@skipIfWindows # Windows doesn't have dlopen and friends, dynamic libraries work differently
|
||||
def test_load_using_paths(self):
|
||||
"""Test that we can load a module by providing a set of search paths."""
|
||||
if self.platformIsDarwin():
|
||||
dylibName = 'libloadunload_d.dylib'
|
||||
else:
|
||||
dylibName = 'libloadunload_d.so'
|
||||
|
||||
# The directory with the dynamic library we did not link to.
|
||||
path_dir = os.path.join(self.getBuildDir(), "hidden")
|
||||
|
||||
(target, process, thread,
|
||||
_) = lldbutil.run_to_source_breakpoint(self,
|
||||
"Break here to do the load using paths",
|
||||
lldb.SBFileSpec("main.cpp"))
|
||||
error = lldb.SBError()
|
||||
lib_spec = lldb.SBFileSpec(self.lib_name)
|
||||
paths = lldb.SBStringList()
|
||||
paths.AppendString(self.wd)
|
||||
paths.AppendString(os.path.join(self.wd, "no_such_dir"))
|
||||
|
||||
out_spec = lldb.SBFileSpec()
|
||||
|
||||
# First try with no correct directories on the path, and make sure that doesn't blow up:
|
||||
token = process.LoadImageUsingPaths(lib_spec, paths, out_spec, error)
|
||||
self.assertEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Only looked on the provided path.")
|
||||
|
||||
# Now add the correct dir to the paths list and try again:
|
||||
paths.AppendString(self.hidden_dir)
|
||||
token = process.LoadImageUsingPaths(lib_spec, paths, out_spec, error)
|
||||
|
||||
self.assertNotEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Got a valid token")
|
||||
self.assertEqual(out_spec, lldb.SBFileSpec(self.hidden_lib), "Found the expected library")
|
||||
|
||||
# Make sure this really is in the image list:
|
||||
loaded_module = target.FindModule(out_spec)
|
||||
|
||||
self.assertTrue(loaded_module.IsValid(), "The loaded module is in the image list.")
|
||||
|
||||
# Now see that we can call a function in the loaded module.
|
||||
value = thread.frames[0].EvaluateExpression("d_function()", lldb.SBExpressionOptions())
|
||||
self.assertTrue(value.GetError().Success(), "Got a value from the expression")
|
||||
ret_val = value.GetValueAsSigned()
|
||||
self.assertEqual(ret_val, 12345, "Got the right value")
|
||||
|
||||
# Make sure the token works to unload it:
|
||||
process.UnloadImage(token)
|
||||
|
||||
# Make sure this really is no longer in the image list:
|
||||
loaded_module = target.FindModule(out_spec)
|
||||
|
||||
self.assertFalse(loaded_module.IsValid(), "The unloaded module is no longer in the image list.")
|
||||
|
||||
# Make sure a relative path also works:
|
||||
paths.Clear()
|
||||
paths.AppendString(os.path.join(self.wd, "no_such_dir"))
|
||||
paths.AppendString(self.wd)
|
||||
relative_spec = lldb.SBFileSpec(os.path.join("hidden", self.lib_name))
|
||||
|
||||
out_spec = lldb.SBFileSpec()
|
||||
token = process.LoadImageUsingPaths(relative_spec, paths, out_spec, error)
|
||||
|
||||
self.assertNotEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Got a valid token")
|
||||
self.assertEqual(out_spec, lldb.SBFileSpec(self.hidden_lib), "Found the expected library")
|
||||
|
||||
process.UnloadImage(token)
|
||||
|
||||
# Finally, passing in an absolute path should work like the basename:
|
||||
# This should NOT work because we've taken hidden_dir off the paths:
|
||||
abs_spec = lldb.SBFileSpec(os.path.join(self.hidden_dir, self.lib_name))
|
||||
|
||||
token = process.LoadImageUsingPaths(lib_spec, paths, out_spec, error)
|
||||
self.assertEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Only looked on the provided path.")
|
||||
|
||||
# But it should work when we add the dir:
|
||||
# Now add the correct dir to the paths list and try again:
|
||||
paths.AppendString(self.hidden_dir)
|
||||
token = process.LoadImageUsingPaths(lib_spec, paths, out_spec, error)
|
||||
|
||||
self.assertNotEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Got a valid token")
|
||||
self.assertEqual(out_spec, lldb.SBFileSpec(self.hidden_lib), "Found the expected library")
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
LEVEL := ../../../make
|
||||
|
||||
DYLIB_NAME := loadunload
|
||||
DYLIB_CXX_SOURCES := d.cpp
|
||||
DYLIB_ONLY := YES
|
||||
|
||||
include $(LEVEL)/Makefile.rules
|
|
@ -0,0 +1,21 @@
|
|||
//===-- c.c -----------------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
int d_init()
|
||||
{
|
||||
return 456;
|
||||
}
|
||||
|
||||
int d_global = d_init();
|
||||
|
||||
int
|
||||
d_function ()
|
||||
{ // Find this line number within d_dunction().
|
||||
return 12345;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
//===-- main.c --------------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
main (int argc, char const *argv[])
|
||||
{
|
||||
printf("Break here to do the load using paths.");
|
||||
return 0;
|
||||
}
|
|
@ -373,6 +373,19 @@ public:
|
|||
uint32_t
|
||||
LoadImage (lldb::SBFileSpec &image_spec, lldb::SBError &error);
|
||||
|
||||
%feature("autodoc", "
|
||||
Load the library whose filename is given by image_spec looking in all the
|
||||
paths supplied in the paths argument. If successful, return a token that
|
||||
can be passed to UnloadImage and fill loaded_path with the path that was
|
||||
successfully loaded. On failure, return
|
||||
lldb.LLDB_INVALID_IMAGE_TOKEN.
|
||||
") LoadImageUsingPaths;
|
||||
uint32_t
|
||||
LoadImageUsingPaths(const lldb::SBFileSpec &image_spec,
|
||||
SBStringList &paths,
|
||||
lldb::SBFileSpec &loaded_path,
|
||||
SBError &error);
|
||||
|
||||
lldb::SBError
|
||||
UnloadImage (uint32_t image_token);
|
||||
|
||||
|
|
|
@ -1187,6 +1187,57 @@ uint32_t SBProcess::LoadImage(const lldb::SBFileSpec &sb_local_image_spec,
|
|||
return LLDB_INVALID_IMAGE_TOKEN;
|
||||
}
|
||||
|
||||
uint32_t SBProcess::LoadImageUsingPaths(const lldb::SBFileSpec &image_spec,
|
||||
SBStringList &paths,
|
||||
lldb::SBFileSpec &loaded_path,
|
||||
lldb::SBError &error) {
|
||||
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
|
||||
ProcessSP process_sp(GetSP());
|
||||
if (process_sp) {
|
||||
Process::StopLocker stop_locker;
|
||||
if (stop_locker.TryLock(&process_sp->GetRunLock())) {
|
||||
if (log)
|
||||
log->Printf("SBProcess(%p)::LoadImageUsingPaths() => "
|
||||
"calling Platform::LoadImageUsingPaths for: %s",
|
||||
static_cast<void *>(process_sp.get()),
|
||||
image_spec.GetFilename());
|
||||
|
||||
std::lock_guard<std::recursive_mutex> guard(
|
||||
process_sp->GetTarget().GetAPIMutex());
|
||||
PlatformSP platform_sp = process_sp->GetTarget().GetPlatform();
|
||||
size_t num_paths = paths.GetSize();
|
||||
std::vector<std::string> paths_vec;
|
||||
paths_vec.reserve(num_paths);
|
||||
for (size_t i = 0; i < num_paths; i++)
|
||||
paths_vec.push_back(paths.GetStringAtIndex(i));
|
||||
FileSpec loaded_spec;
|
||||
|
||||
uint32_t token = platform_sp->LoadImageUsingPaths(process_sp.get(),
|
||||
*image_spec,
|
||||
paths_vec,
|
||||
error.ref(),
|
||||
&loaded_spec);
|
||||
if (token != LLDB_INVALID_IMAGE_TOKEN)
|
||||
loaded_path = loaded_spec;
|
||||
return token;
|
||||
} else {
|
||||
if (log)
|
||||
log->Printf("SBProcess(%p)::LoadImageUsingPaths() => error: "
|
||||
"process is running",
|
||||
static_cast<void *>(process_sp.get()));
|
||||
error.SetErrorString("process is running");
|
||||
}
|
||||
} else {
|
||||
if (log)
|
||||
log->Printf("SBProcess(%p)::LoadImageUsingPaths() => error: "
|
||||
"called with invalid process",
|
||||
static_cast<void *>(process_sp.get()));
|
||||
error.SetErrorString("process is invalid");
|
||||
}
|
||||
|
||||
return LLDB_INVALID_IMAGE_TOKEN;
|
||||
}
|
||||
|
||||
lldb::SBError SBProcess::UnloadImage(uint32_t image_token) {
|
||||
lldb::SBError sb_error;
|
||||
ProcessSP process_sp(GetSP());
|
||||
|
|
|
@ -91,8 +91,12 @@ bool FunctionCaller::WriteFunctionWrapper(
|
|||
m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx,
|
||||
can_interpret, eExecutionPolicyAlways));
|
||||
|
||||
if (!jit_error.Success())
|
||||
if (!jit_error.Success()) {
|
||||
diagnostic_manager.Printf(eDiagnosticSeverityError,
|
||||
"Error in PrepareForExecution: %s.",
|
||||
jit_error.AsCString());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_parser->GetGenerateDebugInfo()) {
|
||||
lldb::ModuleSP jit_module_sp(m_execution_unit_sp->GetJITModule());
|
||||
|
|
|
@ -945,13 +945,40 @@ PlatformPOSIX::MakeLoadImageUtilityFunction(ExecutionContext &exe_ctx,
|
|||
void *image_ptr;
|
||||
const char *error_str;
|
||||
};
|
||||
|
||||
extern void *memcpy(void *, void *, size_t size);
|
||||
extern size_t strlen(const char *);
|
||||
|
||||
|
||||
void * __lldb_dlopen_wrapper (const char *path,
|
||||
void * __lldb_dlopen_wrapper (const char *name,
|
||||
const char *path_strings,
|
||||
char *buffer,
|
||||
__lldb_dlopen_result *result_ptr)
|
||||
{
|
||||
result_ptr->image_ptr = dlopen(path, 2);
|
||||
if (result_ptr->image_ptr == (void *) 0x0)
|
||||
// This is the case where the name is the full path:
|
||||
if (path_strings == (char *) 0x0) {
|
||||
result_ptr->image_ptr = dlopen(name, 2);
|
||||
if (result_ptr->image_ptr != (void *) 0x0)
|
||||
result_ptr->error_str = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// This is the case where we have a list of paths:
|
||||
size_t name_len = strlen(name);
|
||||
while (path_strings != (void *) 0x0 && path_strings[0] != '\0') {
|
||||
size_t path_len = strlen(path_strings);
|
||||
memcpy((void *) buffer, (void *) path_strings, path_len);
|
||||
buffer[path_len] = '/';
|
||||
char *target_ptr = buffer+path_len+1;
|
||||
memcpy((void *) target_ptr, (void *) name, name_len + 1);
|
||||
result_ptr->image_ptr = dlopen(buffer, 2);
|
||||
if (result_ptr->image_ptr != (void *) 0x0) {
|
||||
result_ptr->error_str = nullptr;
|
||||
break;
|
||||
}
|
||||
result_ptr->error_str = dlerror();
|
||||
path_strings = path_strings + path_len + 1;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
)";
|
||||
|
@ -993,13 +1020,16 @@ PlatformPOSIX::MakeLoadImageUtilityFunction(ExecutionContext &exe_ctx,
|
|||
CompilerType clang_char_pointer_type
|
||||
= ast->GetBasicType(eBasicTypeChar).GetPointerType();
|
||||
|
||||
// We are passing two arguments, the path to dlopen, and a pointer to the
|
||||
// storage we've made for the result:
|
||||
// We are passing four arguments, the basename, the list of places to look,
|
||||
// a buffer big enough for all the path + name combos, and
|
||||
// a pointer to the storage we've made for the result:
|
||||
value.SetValueType(Value::eValueTypeScalar);
|
||||
value.SetCompilerType(clang_void_pointer_type);
|
||||
arguments.PushValue(value);
|
||||
value.SetCompilerType(clang_char_pointer_type);
|
||||
arguments.PushValue(value);
|
||||
arguments.PushValue(value);
|
||||
arguments.PushValue(value);
|
||||
|
||||
do_dlopen_function = dlopen_utility_func_up->MakeFunctionCaller(
|
||||
clang_void_pointer_type, arguments, exe_ctx.GetThreadSP(), utility_error);
|
||||
|
@ -1021,7 +1051,12 @@ PlatformPOSIX::MakeLoadImageUtilityFunction(ExecutionContext &exe_ctx,
|
|||
|
||||
uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process,
|
||||
const lldb_private::FileSpec &remote_file,
|
||||
lldb_private::Status &error) {
|
||||
const std::vector<std::string> *paths,
|
||||
lldb_private::Status &error,
|
||||
lldb_private::FileSpec *loaded_image) {
|
||||
if (loaded_image)
|
||||
loaded_image->Clear();
|
||||
|
||||
std::string path;
|
||||
path = remote_file.GetPath();
|
||||
|
||||
|
@ -1100,10 +1135,82 @@ uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process,
|
|||
process->DeallocateMemory(return_addr);
|
||||
});
|
||||
|
||||
// Set the values into our args and write them to the target:
|
||||
arguments.GetValueAtIndex(0)->GetScalar() = path_addr;
|
||||
arguments.GetValueAtIndex(1)->GetScalar() = return_addr;
|
||||
// This will be the address of the storage for paths, if we are using them,
|
||||
// or nullptr to signal we aren't.
|
||||
lldb::addr_t path_array_addr = 0x0;
|
||||
llvm::Optional<CleanUp> path_array_cleanup;
|
||||
|
||||
// This is the address to a buffer large enough to hold the largest path
|
||||
// conjoined with the library name we're passing in. This is a convenience
|
||||
// to avoid having to call malloc in the dlopen function.
|
||||
lldb::addr_t buffer_addr = 0x0;
|
||||
llvm::Optional<CleanUp> buffer_cleanup;
|
||||
|
||||
// Set the values into our args and write them to the target:
|
||||
if (paths != nullptr) {
|
||||
// First insert the paths into the target. This is expected to be a
|
||||
// continuous buffer with the strings laid out null terminated and
|
||||
// end to end with an empty string terminating the buffer.
|
||||
// We also compute the buffer's required size as we go.
|
||||
size_t buffer_size = 0;
|
||||
std::string path_array;
|
||||
for (auto path : *paths) {
|
||||
size_t path_size = path.size();
|
||||
path_array.append(path);
|
||||
path_array.push_back('\0');
|
||||
if (path_size > buffer_size)
|
||||
buffer_size = path_size;
|
||||
}
|
||||
path_array.push_back('\0');
|
||||
|
||||
path_array_addr = process->AllocateMemory(path_array.size(),
|
||||
permissions,
|
||||
utility_error);
|
||||
if (path_array_addr == LLDB_INVALID_ADDRESS) {
|
||||
error.SetErrorStringWithFormat("dlopen error: could not allocate memory"
|
||||
"for path array: %s",
|
||||
utility_error.AsCString());
|
||||
return LLDB_INVALID_IMAGE_TOKEN;
|
||||
}
|
||||
|
||||
// Make sure we deallocate the paths array.
|
||||
path_array_cleanup.emplace([process, path_array_addr] {
|
||||
process->DeallocateMemory(path_array_addr);
|
||||
});
|
||||
|
||||
process->WriteMemory(path_array_addr, path_array.data(),
|
||||
path_array.size(), utility_error);
|
||||
|
||||
if (utility_error.Fail()) {
|
||||
error.SetErrorStringWithFormat("dlopen error: could not write path array:"
|
||||
" %s", utility_error.AsCString());
|
||||
return LLDB_INVALID_IMAGE_TOKEN;
|
||||
}
|
||||
// Now make spaces in the target for the buffer. We need to add one for
|
||||
// the '/' that the utility function will insert and one for the '\0':
|
||||
buffer_size += path.size() + 2;
|
||||
|
||||
buffer_addr = process->AllocateMemory(buffer_size,
|
||||
permissions,
|
||||
utility_error);
|
||||
if (buffer_addr == LLDB_INVALID_ADDRESS) {
|
||||
error.SetErrorStringWithFormat("dlopen error: could not allocate memory"
|
||||
"for buffer: %s",
|
||||
utility_error.AsCString());
|
||||
return LLDB_INVALID_IMAGE_TOKEN;
|
||||
}
|
||||
|
||||
// Make sure we deallocate the buffer memory:
|
||||
buffer_cleanup.emplace([process, buffer_addr] {
|
||||
process->DeallocateMemory(buffer_addr);
|
||||
});
|
||||
}
|
||||
|
||||
arguments.GetValueAtIndex(0)->GetScalar() = path_addr;
|
||||
arguments.GetValueAtIndex(1)->GetScalar() = path_array_addr;
|
||||
arguments.GetValueAtIndex(2)->GetScalar() = buffer_addr;
|
||||
arguments.GetValueAtIndex(3)->GetScalar() = return_addr;
|
||||
|
||||
lldb::addr_t func_args_addr = LLDB_INVALID_ADDRESS;
|
||||
|
||||
diagnostics.Clear();
|
||||
|
@ -1146,7 +1253,7 @@ uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process,
|
|||
ExpressionResults results = do_dlopen_function->ExecuteFunction(
|
||||
exe_ctx, &func_args_addr, options, diagnostics, return_value);
|
||||
if (results != eExpressionCompleted) {
|
||||
error.SetErrorStringWithFormat("dlopen error: could write execute "
|
||||
error.SetErrorStringWithFormat("dlopen error: failed executing "
|
||||
"dlopen wrapper function: %s",
|
||||
diagnostics.GetString().c_str());
|
||||
return LLDB_INVALID_IMAGE_TOKEN;
|
||||
|
@ -1162,8 +1269,19 @@ uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process,
|
|||
}
|
||||
|
||||
// The dlopen succeeded!
|
||||
if (token != 0x0)
|
||||
if (token != 0x0) {
|
||||
if (loaded_image && buffer_addr != 0x0)
|
||||
{
|
||||
// Capture the image which was loaded. We leave it in the buffer on
|
||||
// exit from the dlopen function, so we can just read it from there:
|
||||
std::string name_string;
|
||||
process->ReadCStringFromMemory(buffer_addr, name_string, utility_error);
|
||||
if (utility_error.Success())
|
||||
loaded_image->SetFile(name_string, false,
|
||||
llvm::sys::path::Style::posix);
|
||||
}
|
||||
return process->AddImageToken(token);
|
||||
}
|
||||
|
||||
// We got an error, lets read in the error string:
|
||||
std::string dlopen_error_str;
|
||||
|
|
|
@ -165,7 +165,9 @@ public:
|
|||
|
||||
uint32_t DoLoadImage(lldb_private::Process *process,
|
||||
const lldb_private::FileSpec &remote_file,
|
||||
lldb_private::Status &error) override;
|
||||
const std::vector<std::string> *paths,
|
||||
lldb_private::Status &error,
|
||||
lldb_private::FileSpec *loaded_image) override;
|
||||
|
||||
lldb_private::Status UnloadImage(lldb_private::Process *process,
|
||||
uint32_t image_token) override;
|
||||
|
|
|
@ -1738,7 +1738,7 @@ uint32_t Platform::LoadImage(lldb_private::Process *process,
|
|||
if (error.Fail())
|
||||
return LLDB_INVALID_IMAGE_TOKEN;
|
||||
}
|
||||
return DoLoadImage(process, remote_file, error);
|
||||
return DoLoadImage(process, remote_file, nullptr, error);
|
||||
}
|
||||
|
||||
if (local_file) {
|
||||
|
@ -1751,12 +1751,12 @@ uint32_t Platform::LoadImage(lldb_private::Process *process,
|
|||
if (error.Fail())
|
||||
return LLDB_INVALID_IMAGE_TOKEN;
|
||||
}
|
||||
return DoLoadImage(process, target_file, error);
|
||||
}
|
||||
return DoLoadImage(process, target_file, nullptr, error);
|
||||
}
|
||||
|
||||
if (remote_file) {
|
||||
// Only remote file was specified so we don't have to do any copying
|
||||
return DoLoadImage(process, remote_file, error);
|
||||
return DoLoadImage(process, remote_file, nullptr, error);
|
||||
}
|
||||
|
||||
error.SetErrorString("Neither local nor remote file was specified");
|
||||
|
@ -1765,11 +1765,30 @@ uint32_t Platform::LoadImage(lldb_private::Process *process,
|
|||
|
||||
uint32_t Platform::DoLoadImage(lldb_private::Process *process,
|
||||
const lldb_private::FileSpec &remote_file,
|
||||
lldb_private::Status &error) {
|
||||
const std::vector<std::string> *paths,
|
||||
lldb_private::Status &error,
|
||||
lldb_private::FileSpec *loaded_image) {
|
||||
error.SetErrorString("LoadImage is not supported on the current platform");
|
||||
return LLDB_INVALID_IMAGE_TOKEN;
|
||||
}
|
||||
|
||||
uint32_t Platform::LoadImageUsingPaths(lldb_private::Process *process,
|
||||
const lldb_private::FileSpec &remote_filename,
|
||||
const std::vector<std::string> &paths,
|
||||
lldb_private::Status &error,
|
||||
lldb_private::FileSpec *loaded_path)
|
||||
{
|
||||
FileSpec file_to_use;
|
||||
if (remote_filename.IsAbsolute())
|
||||
file_to_use = FileSpec(remote_filename.GetFilename().GetStringRef(),
|
||||
false,
|
||||
remote_filename.GetPathStyle());
|
||||
else
|
||||
file_to_use = remote_filename;
|
||||
|
||||
return DoLoadImage(process, file_to_use, &paths, error, loaded_path);
|
||||
}
|
||||
|
||||
Status Platform::UnloadImage(lldb_private::Process *process,
|
||||
uint32_t image_token) {
|
||||
return Status("UnloadImage is not supported on the current platform");
|
||||
|
|
Loading…
Reference in New Issue