[Lldb-commits] [lldb] r335912 - Add a way to load an image using a library name and list of paths.

Jim Ingham via lldb-commits lldb-commits at lists.llvm.org
Thu Jun 28 13:02:12 PDT 2018


Author: jingham
Date: Thu Jun 28 13:02:11 2018
New Revision: 335912

URL: http://llvm.org/viewvc/llvm-project?rev=335912&view=rev
Log:
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>

Added:
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/.categories
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/Makefile
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/TestLoadUsingPaths.py
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/hidden/
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/hidden/Makefile
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/hidden/d.cpp
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/main.cpp
Modified:
    lldb/trunk/include/lldb/API/SBProcess.h
    lldb/trunk/include/lldb/Target/Platform.h
    lldb/trunk/scripts/interface/SBProcess.i
    lldb/trunk/source/API/SBProcess.cpp
    lldb/trunk/source/Expression/FunctionCaller.cpp
    lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
    lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.h
    lldb/trunk/source/Target/Platform.cpp

Modified: lldb/trunk/include/lldb/API/SBProcess.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBProcess.h?rev=335912&r1=335911&r2=335912&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBProcess.h (original)
+++ lldb/trunk/include/lldb/API/SBProcess.h Thu Jun 28 13:02:11 2018
@@ -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);

Modified: lldb/trunk/include/lldb/Target/Platform.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Platform.h?rev=335912&r1=335911&r2=335912&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Platform.h (original)
+++ lldb/trunk/include/lldb/Target/Platform.h Thu Jun 28 13:02:11 2018
@@ -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);

Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/.categories
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/.categories?rev=335912&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/.categories (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/.categories Thu Jun 28 13:02:11 2018
@@ -0,0 +1 @@
+basic_process

Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/Makefile?rev=335912&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/Makefile (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/Makefile Thu Jun 28 13:02:11 2018
@@ -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

Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/TestLoadUsingPaths.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/TestLoadUsingPaths.py?rev=335912&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/TestLoadUsingPaths.py (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/TestLoadUsingPaths.py Thu Jun 28 13:02:11 2018
@@ -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
+
+
+ at 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")
+
+                                        

Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/hidden/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/hidden/Makefile?rev=335912&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/hidden/Makefile (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/hidden/Makefile Thu Jun 28 13:02:11 2018
@@ -0,0 +1,7 @@
+LEVEL := ../../../make
+
+DYLIB_NAME := loadunload
+DYLIB_CXX_SOURCES := d.cpp
+DYLIB_ONLY := YES
+
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/hidden/d.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/hidden/d.cpp?rev=335912&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/hidden/d.cpp (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/hidden/d.cpp Thu Jun 28 13:02:11 2018
@@ -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;
+}

Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/main.cpp?rev=335912&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/main.cpp (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/load_using_paths/main.cpp Thu Jun 28 13:02:11 2018
@@ -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;
+}

Modified: lldb/trunk/scripts/interface/SBProcess.i
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/interface/SBProcess.i?rev=335912&r1=335911&r2=335912&view=diff
==============================================================================
--- lldb/trunk/scripts/interface/SBProcess.i (original)
+++ lldb/trunk/scripts/interface/SBProcess.i Thu Jun 28 13:02:11 2018
@@ -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);
     

Modified: lldb/trunk/source/API/SBProcess.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBProcess.cpp?rev=335912&r1=335911&r2=335912&view=diff
==============================================================================
--- lldb/trunk/source/API/SBProcess.cpp (original)
+++ lldb/trunk/source/API/SBProcess.cpp Thu Jun 28 13:02:11 2018
@@ -1187,6 +1187,57 @@ uint32_t SBProcess::LoadImage(const lldb
   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());

Modified: lldb/trunk/source/Expression/FunctionCaller.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/FunctionCaller.cpp?rev=335912&r1=335911&r2=335912&view=diff
==============================================================================
--- lldb/trunk/source/Expression/FunctionCaller.cpp (original)
+++ lldb/trunk/source/Expression/FunctionCaller.cpp Thu Jun 28 13:02:11 2018
@@ -91,8 +91,12 @@ bool FunctionCaller::WriteFunctionWrappe
       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());

Modified: lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp?rev=335912&r1=335911&r2=335912&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp (original)
+++ lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp Thu Jun 28 13:02:11 2018
@@ -945,13 +945,40 @@ PlatformPOSIX::MakeLoadImageUtilityFunct
     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::MakeLoadImageUtilityFunct
   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::MakeLoadImageUtilityFunct
 
 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
       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<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() = return_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
   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
   }
   
   // 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;

Modified: lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.h?rev=335912&r1=335911&r2=335912&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.h (original)
+++ lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.h Thu Jun 28 13:02:11 2018
@@ -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;

Modified: lldb/trunk/source/Target/Platform.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Platform.cpp?rev=335912&r1=335911&r2=335912&view=diff
==============================================================================
--- lldb/trunk/source/Target/Platform.cpp (original)
+++ lldb/trunk/source/Target/Platform.cpp Thu Jun 28 13:02:11 2018
@@ -1738,7 +1738,7 @@ uint32_t Platform::LoadImage(lldb_privat
       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_privat
       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_privat
 
 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");




More information about the lldb-commits mailing list