jasonmolenda created this revision.
jasonmolenda added reviewers: JDevlieghere, jingham.
jasonmolenda added a project: LLDB.
Herald added a subscriber: mgorny.
Herald added a project: All.
jasonmolenda requested review of this revision.
Herald added a subscriber: lldb-commits.

In an internal development environment, lldb will attach to a gdb stub that can 
provide the address of a Mach-O fileset including the kernel binary.  I added 
some preliminary support for the `binary-addresses` key in `qProcessInfo` in 
https://reviews.llvm.org/D130813; this patch fixes that support now that we 
have a live stub to run against, and passes the addr_t it gets through the 
PlatformList to see if any Platform knows how to handle it.

PlatformDarwinKernel will test the addr_t to see if it is a Mach-O Fileset, 
using Jonas' mach-o fileset plugin (https://reviews.llvm.org/D132433 et al).  
If it is a fileset, it will search for a com.apple.kernel entry, and if found, 
it will set the Process DynamicLoader to be DynamicLoaderDarwinKernel, and 
register the address of the com.apple.kernel entry in the fileset, to be loaded 
later by the DynamicLoader plugin.

The big trick with this is that I needed to do several Darwin specific things 
-- parse a Mach-O fileset in memory, detect if this is a Darwin kernel, set the 
Process DynamicLoader -- when I'm given only an addr_t in ProcessGDBRemote.  
Going through the Platform plugins and asking them if they can do these things 
given the addr_t was a way of accomplishing this from generic code.

This does mean that I introduced cross-platform dependencies in 
PlatformDarwinKernel.  It needs to directly create a 
`ObjectContainerMachOFileset` object to use the `FindEntry` methods which are 
only available to the subclass.  I need to instantiate a 
DynamicLoaderDarwinKernel object and set the Process to use it as the `m_dyld`. 
 I like isolating all of this very-darwin-specific logic down in 
PlatformDarwinKernel, but I didn't see a good way of working around the 
dependencies.

Testing this is a trick I haven't figured out yet; I'd need a remote stub that 
will return the `qProcessInfo` `binary-addresses` key, have a Mach-O fileset 
there with a com.apple.kernel entry pointing to a binary that is structured 
like a Darwin kernel binary enough to trick lldb into loading it.  It's 
possible to hand-test against a live environment, but faking enough of that to 
create a test would be a lot.

There will be a second patch dealing with corefiles, where I ended up making a 
lot of changes to ProcessMachCore so it's a rather large diff, and it was 
possible to separate the two halves, so I did.

Any feedback appreciated, I've been working on this one for a little bit now & 
a fresh set of eyes is welcome.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D133534

Files:
  lldb/include/lldb/Target/Platform.h
  lldb/include/lldb/Target/Process.h
  lldb/source/Core/DynamicLoader.cpp
  lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
  lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
  lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
  lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
  lldb/source/Target/Platform.cpp
  lldb/source/Target/Process.cpp
  lldb/unittests/Core/CMakeLists.txt
  lldb/unittests/Interpreter/CMakeLists.txt
  lldb/unittests/Platform/CMakeLists.txt
  lldb/unittests/Process/CMakeLists.txt
  lldb/unittests/SymbolFile/DWARF/CMakeLists.txt

Index: lldb/unittests/SymbolFile/DWARF/CMakeLists.txt
===================================================================
--- lldb/unittests/SymbolFile/DWARF/CMakeLists.txt
+++ lldb/unittests/SymbolFile/DWARF/CMakeLists.txt
@@ -10,10 +10,12 @@
     lldbCore
     lldbHost
     lldbSymbol
+    lldbPluginDynamicLoaderDarwinKernel
     lldbPluginObjectFilePECOFF
     lldbPluginSymbolFileDWARF
     lldbPluginSymbolFilePDB
     lldbPluginTypeSystemClang
+    lldbPluginObjectContainerMachOFileset
     lldbPluginPlatformMacOSX
     lldbUtilityHelpers
     lldbSymbolHelpers
Index: lldb/unittests/Process/CMakeLists.txt
===================================================================
--- lldb/unittests/Process/CMakeLists.txt
+++ lldb/unittests/Process/CMakeLists.txt
@@ -17,5 +17,7 @@
       lldbUtility
       lldbUtilityHelpers
       lldbInterpreter
+      lldbPluginDynamicLoaderDarwinKernel
+      lldbPluginObjectContainerMachOFileset
       lldbPluginPlatformMacOSX
   )
Index: lldb/unittests/Platform/CMakeLists.txt
===================================================================
--- lldb/unittests/Platform/CMakeLists.txt
+++ lldb/unittests/Platform/CMakeLists.txt
@@ -6,6 +6,8 @@
   PlatformTest.cpp
 
   LINK_LIBS
+    lldbPluginDynamicLoaderDarwinKernel
+    lldbPluginObjectContainerMachOFileset
     lldbPluginPlatformFreeBSD
     lldbPluginPlatformLinux
     lldbPluginPlatformMacOSX
Index: lldb/unittests/Interpreter/CMakeLists.txt
===================================================================
--- lldb/unittests/Interpreter/CMakeLists.txt
+++ lldb/unittests/Interpreter/CMakeLists.txt
@@ -14,6 +14,8 @@
       lldbUtility
       lldbUtilityHelpers
       lldbInterpreter
+      lldbPluginDynamicLoaderDarwinKernel
+      lldbPluginObjectContainerMachOFileset
       lldbPluginPlatformMacOSX
       LLVMTestingSupport
 )
Index: lldb/unittests/Core/CMakeLists.txt
===================================================================
--- lldb/unittests/Core/CMakeLists.txt
+++ lldb/unittests/Core/CMakeLists.txt
@@ -14,9 +14,11 @@
   LINK_LIBS
     lldbCore
     lldbHost
+    lldbPluginDynamicLoaderDarwinKernel
     lldbPluginObjectFileELF
     lldbPluginObjectFileMachO
     lldbPluginObjectFilePECOFF
+    lldbPluginObjectContainerMachOFileset
     lldbPluginPlatformMacOSX
     lldbPluginSymbolFileSymtab
     lldbSymbol
Index: lldb/source/Target/Process.cpp
===================================================================
--- lldb/source/Target/Process.cpp
+++ lldb/source/Target/Process.cpp
@@ -2653,6 +2653,10 @@
   return m_dyld_up.get();
 }
 
+void Process::SetDynamicLoader(DynamicLoaderUP dyld_up) {
+  m_dyld_up = std::move(dyld_up);
+}
+
 DataExtractor Process::GetAuxvData() { return DataExtractor(); }
 
 llvm::Expected<bool> Process::SaveCore(llvm::StringRef outfile) {
Index: lldb/source/Target/Platform.cpp
===================================================================
--- lldb/source/Target/Platform.cpp
+++ lldb/source/Target/Platform.cpp
@@ -2079,3 +2079,22 @@
   m_platforms.push_back(platform_sp);
   return platform_sp;
 }
+
+bool PlatformList::LoadBinaryAndSetDynamicLoader(Process *process,
+                                                 lldb::addr_t addr,
+                                                 bool notify) {
+  std::lock_guard<std::recursive_mutex> guard(m_mutex);
+
+  PlatformCreateInstance create_callback;
+  for (int idx = 0;
+       (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx));
+       ++idx) {
+    ArchSpec arch;
+    PlatformSP platform_sp = create_callback(true, &arch);
+    if (platform_sp) {
+      if (platform_sp->LoadBinaryAndSetDynamicLoader(process, addr, notify))
+        return true;
+    }
+  }
+  return false;
+}
Index: lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -593,8 +593,14 @@
         UUID uuid;
         const bool value_is_slide = false;
         for (addr_t addr : bin_addrs) {
-          const bool force_symbol_search = true;
           const bool notify = true;
+          if (GetTarget()
+                  .GetDebugger()
+                  .GetPlatformList()
+                  .LoadBinaryAndSetDynamicLoader(this, addr, notify))
+            continue;
+
+          const bool force_symbol_search = true;
           DynamicLoader::LoadBinaryWithUUIDAndAddress(
               this, uuid, addr, value_is_slide, force_symbol_search, notify);
         }
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -2206,12 +2206,13 @@
             ++num_keys_decoded;
           }
         } else if (name.equals("binary-addresses")) {
-          addr_t addr;
-          while (!value.empty()) {
-            llvm::StringRef addr_str;
-            std::tie(addr_str, value) = value.split(',');
-            if (!addr_str.getAsInteger(16, addr))
-              m_binary_addresses.push_back(addr);
+          m_binary_addresses.clear();
+          ++num_keys_decoded;
+          for (llvm::StringRef x : llvm::split(value, ',')) {
+            addr_t vmaddr;
+            x.consume_front("0x");
+            if (llvm::to_integer(x, vmaddr, 16))
+              m_binary_addresses.push_back(vmaddr);
           }
         }
       }
Index: lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h
===================================================================
--- lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h
+++ lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h
@@ -154,6 +154,9 @@
                                     const UUID &uuid, const ArchSpec &arch,
                                     lldb::ModuleSP &exe_module_sp);
 
+  bool LoadBinaryAndSetDynamicLoader(Process *process, lldb::addr_t addr,
+                                     bool notify) override;
+
   // Most of the ivars are assembled under FileSystem::EnumerateDirectory calls
   // where the function being called for each file/directory must be static.
   // We'll pass a this pointer as a baton and access the ivars directly.
Index: lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
===================================================================
--- lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
+++ lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
@@ -26,6 +26,7 @@
 #include "lldb/Target/Process.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/DataBufferHeap.h"
 #include "lldb/Utility/FileSpec.h"
 #include "lldb/Utility/LLDBLog.h"
 #include "lldb/Utility/Log.h"
@@ -39,6 +40,8 @@
 #include <memory>
 
 #include "Host/macosx/cfcpp/CFCBundle.h"
+#include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h"
+#include "Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -724,23 +727,28 @@
   // "com.apple.driver.AppleIRController") and search our kext index.
   std::string kext_bundle_id = platform_file.GetPath();
 
-  if (!kext_bundle_id.empty() && module_spec.GetUUID().IsValid()) {
-    if (kext_bundle_id == "mach_kernel") {
-      return GetSharedModuleKernel(module_spec, process, module_sp,
-                                   module_search_paths_ptr, old_modules,
-                                   did_create_ptr);
+  if (module_spec.GetUUID().IsValid()) {
+    // DynamicLoaderDarwinKernel uses the magic name mach_kernel,
+    // UUID search can get here with no name - and it may be a kernel.
+    if (kext_bundle_id == "mach_kernel" || kext_bundle_id.empty()) {
+      error = GetSharedModuleKernel(module_spec, process, module_sp,
+                                    module_search_paths_ptr, old_modules,
+                                    did_create_ptr);
+      if (error.Success() && module_sp) {
+        return error;
+      }
     } else {
       return GetSharedModuleKext(module_spec, process, module_sp,
                                  module_search_paths_ptr, old_modules,
                                  did_create_ptr);
     }
-  } else {
-    // Give the generic methods, including possibly calling into  DebugSymbols
-    // framework on macOS systems, a chance.
-    return PlatformDarwin::GetSharedModule(module_spec, process, module_sp,
-                                           module_search_paths_ptr, old_modules,
-                                           did_create_ptr);
   }
+
+  // Give the generic methods, including possibly calling into DebugSymbols
+  // framework on macOS systems, a chance.
+  return PlatformDarwin::GetSharedModule(module_spec, process, module_sp,
+                                         module_search_paths_ptr, old_modules,
+                                         did_create_ptr);
 }
 
 Status PlatformDarwinKernel::GetSharedModuleKext(
@@ -798,7 +806,8 @@
           module_sp->MatchesModuleSpec(kern_spec)) {
         // module_sp is an actual kernel binary we want to add.
         if (process) {
-          process->GetTarget().GetImages().AppendIfNeeded(module_sp);
+          const bool notify = false;
+          process->GetTarget().GetImages().AppendIfNeeded(module_sp, notify);
           error.Clear();
           return error;
         } else {
@@ -830,7 +839,8 @@
           module_sp->MatchesModuleSpec(kern_spec)) {
         // module_sp is an actual kernel binary we want to add.
         if (process) {
-          process->GetTarget().GetImages().AppendIfNeeded(module_sp);
+          const bool notify = false;
+          process->GetTarget().GetImages().AppendIfNeeded(module_sp, notify);
           error.Clear();
           return error;
         } else {
@@ -908,6 +918,57 @@
   return {};
 }
 
+static addr_t find_kernel_in_macho_fileset(Process *process,
+                                           addr_t input_addr) {
+  Status error;
+  WritableDataBufferSP header_data(new DataBufferHeap(512, 0));
+  if (!process->ReadMemory(input_addr, header_data->GetBytes(),
+                           header_data->GetByteSize(), error))
+    return LLDB_INVALID_ADDRESS;
+  ModuleSP module_sp(new Module(ModuleSpec()));
+  ObjectContainerSP container_sp(
+      ObjectContainerMachOFileset::CreateMemoryInstance(
+          module_sp, header_data, process->shared_from_this(), input_addr));
+  if (!container_sp)
+    return LLDB_INVALID_ADDRESS;
+
+  ObjectContainerMachOFileset *fileset_container =
+      static_cast<ObjectContainerMachOFileset *>(container_sp.get());
+  ObjectContainerMachOFileset::Entry *entry =
+      fileset_container->FindEntry("com.apple.kernel");
+  if (entry)
+    return entry->vmaddr;
+  return LLDB_INVALID_ADDRESS;
+}
+
+bool PlatformDarwinKernel::LoadBinaryAndSetDynamicLoader(
+    Process *process, lldb::addr_t input_addr, bool notify) {
+  Log *log =
+      GetLog(LLDBLog::Platform | LLDBLog::DynamicLoader | LLDBLog::Process);
+  addr_t actual_address = find_kernel_in_macho_fileset(process, input_addr);
+
+  LLDB_LOGF(log,
+            "PlatformDarwinKernel::%s check address 0x%" PRIx64 " for "
+            "a macho fileset, got back kernel address 0x%" PRIx64,
+            __FUNCTION__, input_addr, actual_address);
+
+  if (actual_address == LLDB_INVALID_ADDRESS)
+    return false;
+
+  // We have a xnu kernel binary, set the Process' dynamic loader
+  // appropriately and give it the actual address so it can be loaded later
+  // in the attach sequence.
+  DynamicLoaderUP dyld_up(
+      new DynamicLoaderDarwinKernel(process, actual_address));
+  if (!dyld_up)
+    return false;
+
+  // Process owns it now
+  process->SetDynamicLoader(std::move(dyld_up));
+
+  return true;
+}
+
 std::vector<ArchSpec> PlatformDarwinKernel::GetSupportedArchitectures(
     const ArchSpec &process_host_arch) {
   std::vector<ArchSpec> result;
Index: lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
===================================================================
--- lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
+++ lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
@@ -176,7 +176,6 @@
   // At this point if there is an ExecutableModule, it is a kernel and the
   // Target is some variant of an Apple system. If the Process hasn't provided
   // the kernel load address, we need to look around in memory to find it.
-
   const addr_t kernel_load_address = SearchForDarwinKernel(process);
   if (CheckForKernelImageAtAddress(kernel_load_address, process).IsValid()) {
     process->SetCanRunCode(false);
@@ -188,18 +187,15 @@
 lldb::addr_t
 DynamicLoaderDarwinKernel::SearchForDarwinKernel(Process *process) {
   addr_t kernel_load_address = process->GetImageInfoAddress();
-  if (kernel_load_address == LLDB_INVALID_ADDRESS) {
+  if (kernel_load_address == LLDB_INVALID_ADDRESS)
     kernel_load_address = SearchForKernelAtSameLoadAddr(process);
-    if (kernel_load_address == LLDB_INVALID_ADDRESS) {
-      kernel_load_address = SearchForKernelWithDebugHints(process);
-      if (kernel_load_address == LLDB_INVALID_ADDRESS) {
-        kernel_load_address = SearchForKernelNearPC(process);
-        if (kernel_load_address == LLDB_INVALID_ADDRESS) {
-          kernel_load_address = SearchForKernelViaExhaustiveSearch(process);
-        }
-      }
-    }
-  }
+  if (kernel_load_address == LLDB_INVALID_ADDRESS)
+    kernel_load_address = SearchForKernelWithDebugHints(process);
+  if (kernel_load_address == LLDB_INVALID_ADDRESS)
+    kernel_load_address = SearchForKernelNearPC(process);
+  if (kernel_load_address == LLDB_INVALID_ADDRESS)
+    kernel_load_address = SearchForKernelViaExhaustiveSearch(process);
+
   return kernel_load_address;
 }
 
@@ -525,10 +521,10 @@
   LoadKernelModuleIfNeeded();
   SetNotificationBreakpointIfNeeded();
 }
-/// Called after attaching a process.
-///
-/// Allow DynamicLoader plug-ins to execute some code after
-/// attaching to a process.
+
+/// We've attached to a remote connection, or read a corefile.
+/// Now load the kernel binary and potentially the kexts, add
+/// them to the Target.
 void DynamicLoaderDarwinKernel::DidAttach() {
   PrivateInitialize(m_process);
   UpdateIfNeeded();
@@ -720,14 +716,15 @@
     }
     if (m_uuid.IsValid()) {
       ModuleSP exe_module_sp = process->GetTarget().GetExecutableModule();
-      if (exe_module_sp.get() && exe_module_sp->GetUUID().IsValid()) {
+      if (exe_module_sp.get() && exe_module_sp->GetUUID().IsValid() &&
+          exe_module_sp->GetUUID() != m_uuid &&
+          exe_module_sp->GetObjectFile() &&
+          exe_module_sp->GetObjectFile()->GetStrata() ==
+              ObjectFile::eStrataKernel) {
         if (m_uuid != exe_module_sp->GetUUID()) {
           // The user specified a kernel binary that has a different UUID than
           // the kernel actually running in memory.  This never ends well;
           // clear the user specified kernel binary from the Target.
-
-          m_module_sp.reset();
-
           ModuleList user_specified_kernel_list;
           user_specified_kernel_list.Append(exe_module_sp);
           process->GetTarget().GetImages().Remove(user_specified_kernel_list);
@@ -841,10 +838,6 @@
     if (m_module_sp) {
       if (m_uuid.IsValid() && m_module_sp->GetUUID() == m_uuid) {
         target.GetImages().AppendIfNeeded(m_module_sp, false);
-        if (IsKernel() &&
-            target.GetExecutableModulePointer() != m_module_sp.get()) {
-          target.SetExecutableModule(m_module_sp, eLoadDependentsNo);
-        }
       }
     }
   }
@@ -980,8 +973,12 @@
 void DynamicLoaderDarwinKernel::LoadKernelModuleIfNeeded() {
   if (!m_kext_summary_header_ptr_addr.IsValid()) {
     m_kernel.Clear();
-    m_kernel.SetModule(m_process->GetTarget().GetExecutableModule());
-    m_kernel.SetIsKernel(true);
+    ModuleSP module_sp = m_process->GetTarget().GetExecutableModule();
+    if (module_sp && module_sp->GetObjectFile() &&
+        module_sp->GetObjectFile()->GetStrata() == ObjectFile::eStrataKernel) {
+      m_kernel.SetModule(module_sp);
+      m_kernel.SetIsKernel(true);
+    }
 
     ConstString kernel_name("mach_kernel");
     if (m_kernel.GetModule().get() && m_kernel.GetModule()->GetObjectFile() &&
Index: lldb/source/Core/DynamicLoader.cpp
===================================================================
--- lldb/source/Core/DynamicLoader.cpp
+++ lldb/source/Core/DynamicLoader.cpp
@@ -230,6 +230,10 @@
 
   Log *log = GetLog(LLDBLog::DynamicLoader);
   if (module_sp.get()) {
+    // Ensure the Target has an architecture set in case
+    // we need it while processing this binary/eh_frame/debug info.
+    if (!target.GetArchitecture().IsValid())
+      target.SetArchitecture(module_sp->GetArchitecture());
     target.GetImages().AppendIfNeeded(module_sp, false);
 
     bool changed = false;
Index: lldb/include/lldb/Target/Process.h
===================================================================
--- lldb/include/lldb/Target/Process.h
+++ lldb/include/lldb/Target/Process.h
@@ -641,6 +641,8 @@
   /// plug-in.
   virtual DynamicLoader *GetDynamicLoader();
 
+  void SetDynamicLoader(lldb::DynamicLoaderUP dyld);
+
   // Returns AUXV structure found in many ELF-based environments.
   //
   // The default action is to return an empty data buffer.
Index: lldb/include/lldb/Target/Platform.h
===================================================================
--- lldb/include/lldb/Target/Platform.h
+++ lldb/include/lldb/Target/Platform.h
@@ -846,6 +846,32 @@
     return nullptr;
   }
 
+  /// Given an address of a binary, the platform may be able to
+  /// set the correct DynamicLoader plugin that should be used for
+  /// this process, and register this binary with the DynamicLoader
+  /// so it will be loaded properly.  May change the Process
+  /// DynamicLoader.
+  ///
+  /// \param[in] process
+  ///     Process read memory from.
+  ///
+  /// \param[in] addr
+  ///     Address of a binary in memory.
+  ///
+  /// \param[in] notify
+  ///     Whether ModulesDidLoad should be called, if a binary is loaded.
+  ///     Caller may prefer to call ModulesDidLoad for multiple binaries
+  ///     that were loaded at the same time.
+  ///
+  /// \return
+  ///     Returns true if the binary was loaded in the target (or will be
+  ///     via a DynamicLoader).  Returns false if the binary was not
+  ///     loaded/registered, and the caller must load it into the target.
+  virtual bool LoadBinaryAndSetDynamicLoader(Process *process,
+                                             lldb::addr_t addr, bool notify) {
+    return false;
+  }
+
   virtual CompilerType GetSiginfoType(const llvm::Triple &triple);
   
   virtual Args GetExtraStartupCommands();
@@ -1026,6 +1052,30 @@
 
   lldb::PlatformSP Create(llvm::StringRef name);
 
+  /// Given an address of a binary, the platform may be able to
+  /// set the correct DynamicLoader plugin that should be used for
+  /// this process, and register this binary with the DynamicLoader
+  /// so it will be loaded properly.  May change the Process
+  /// DynamicLoader.
+  ///
+  /// \param[in] process
+  ///     Process read memory from.
+  ///
+  /// \param[in] addr
+  ///     Address of a binary in memory.
+  ///
+  /// \param[in] notify
+  ///     Whether ModulesDidLoad should be called, if a binary is loaded.
+  ///     Caller may prefer to call ModulesDidLoad for multiple binaries
+  ///     that were loaded at the same time.
+  ///
+  /// \return
+  ///     Returns true if the binary was loaded in the target (or will be
+  ///     via a DynamicLoader).  Returns false if the binary was not
+  ///     loaded/registered, and the caller must load it into the target.
+  bool LoadBinaryAndSetDynamicLoader(Process *process, lldb::addr_t addr,
+                                     bool notify);
+
 protected:
   typedef std::vector<lldb::PlatformSP> collection;
   mutable std::recursive_mutex m_mutex;
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to