From 0d231f7161272cb46e1ea04326da1cbdfec06923 Mon Sep 17 00:00:00 2001 From: Jim Ingham Date: Thu, 28 Jun 2018 20:02:11 +0000 Subject: [PATCH] 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. llvm-svn: 335912 --- lldb/include/lldb/API/SBProcess.h | 34 +++++ lldb/include/lldb/Target/Platform.h | 38 +++++- .../functionalities/load_using_paths/.categories | 1 + .../test/functionalities/load_using_paths/Makefile | 13 ++ .../load_using_paths/TestLoadUsingPaths.py | 126 +++++++++++++++++++ .../load_using_paths/hidden/Makefile | 7 ++ .../functionalities/load_using_paths/hidden/d.cpp | 21 ++++ .../test/functionalities/load_using_paths/main.cpp | 16 +++ lldb/scripts/interface/SBProcess.i | 13 ++ lldb/source/API/SBProcess.cpp | 51 ++++++++ lldb/source/Expression/FunctionCaller.cpp | 6 +- .../Plugins/Platform/POSIX/PlatformPOSIX.cpp | 138 +++++++++++++++++++-- lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h | 4 +- lldb/source/Target/Platform.cpp | 29 ++++- 14 files changed, 479 insertions(+), 18 deletions(-) create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/.categories create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/TestLoadUsingPaths.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/hidden/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/hidden/d.cpp create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/main.cpp diff --git a/lldb/include/lldb/API/SBProcess.h b/lldb/include/lldb/API/SBProcess.h index 332794f..4ad24f6 100644 --- a/lldb/include/lldb/API/SBProcess.h +++ b/lldb/include/lldb/API/SBProcess.h @@ -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); diff --git a/lldb/include/lldb/Target/Platform.h b/lldb/include/lldb/Target/Platform.h index 047196e..1e0eb6a 100644 --- a/lldb/include/lldb/Target/Platform.h +++ b/lldb/include/lldb/Target/Platform.h @@ -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 &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 *paths, + lldb_private::Status &error, + lldb_private::FileSpec *loaded_path = nullptr); virtual Status UnloadImage(lldb_private::Process *process, uint32_t image_token); diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/.categories b/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/.categories new file mode 100644 index 0000000..c00c258 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/.categories @@ -0,0 +1 @@ +basic_process diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/Makefile new file mode 100644 index 0000000..5ec8f23 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/Makefile @@ -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 diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/TestLoadUsingPaths.py b/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/TestLoadUsingPaths.py new file mode 100644 index 0000000..ba85039 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/TestLoadUsingPaths.py @@ -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") + + diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/hidden/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/hidden/Makefile new file mode 100644 index 0000000..bebfa92 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/hidden/Makefile @@ -0,0 +1,7 @@ +LEVEL := ../../../make + +DYLIB_NAME := loadunload +DYLIB_CXX_SOURCES := d.cpp +DYLIB_ONLY := YES + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/hidden/d.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/hidden/d.cpp new file mode 100644 index 0000000..6a7642c --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/hidden/d.cpp @@ -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; +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/main.cpp new file mode 100644 index 0000000..4b33204 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/load_using_paths/main.cpp @@ -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 + +int +main (int argc, char const *argv[]) +{ + printf("Break here to do the load using paths."); + return 0; +} diff --git a/lldb/scripts/interface/SBProcess.i b/lldb/scripts/interface/SBProcess.i index 55d39f8..24b6756 100644 --- a/lldb/scripts/interface/SBProcess.i +++ b/lldb/scripts/interface/SBProcess.i @@ -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); diff --git a/lldb/source/API/SBProcess.cpp b/lldb/source/API/SBProcess.cpp index f98670e..4d5ddc8 100644 --- a/lldb/source/API/SBProcess.cpp +++ b/lldb/source/API/SBProcess.cpp @@ -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(process_sp.get()), + image_spec.GetFilename()); + + std::lock_guard guard( + process_sp->GetTarget().GetAPIMutex()); + PlatformSP platform_sp = process_sp->GetTarget().GetPlatform(); + size_t num_paths = paths.GetSize(); + std::vector 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(process_sp.get())); + error.SetErrorString("process is running"); + } + } else { + if (log) + log->Printf("SBProcess(%p)::LoadImageUsingPaths() => error: " + "called with invalid process", + static_cast(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()); diff --git a/lldb/source/Expression/FunctionCaller.cpp b/lldb/source/Expression/FunctionCaller.cpp index 622d801..9742ed0 100644 --- a/lldb/source/Expression/FunctionCaller.cpp +++ b/lldb/source/Expression/FunctionCaller.cpp @@ -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()); diff --git a/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp index 9ac1638..d351fcc 100644 --- a/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp +++ b/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp @@ -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 *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); }); + // 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 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 buffer_cleanup; + // Set the values into our args and write them to the target: - arguments.GetValueAtIndex(0)->GetScalar() = path_addr; - arguments.GetValueAtIndex(1)->GetScalar() = return_addr; + 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; diff --git a/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h index 12d6c62..cc6f729 100644 --- a/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h +++ b/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h @@ -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 *paths, + lldb_private::Status &error, + lldb_private::FileSpec *loaded_image) override; lldb_private::Status UnloadImage(lldb_private::Process *process, uint32_t image_token) override; diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp index 9a3eae9..5ae556e 100644 --- a/lldb/source/Target/Platform.cpp +++ b/lldb/source/Target/Platform.cpp @@ -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 *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 &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"); -- 2.7.4