[Lldb-commits] [lldb] 8d5a600 - Track transition from launch dyld to shared-cache dyld

Jason Molenda via lldb-commits lldb-commits at lists.llvm.org
Tue Jun 7 13:34:41 PDT 2022


Author: Jason Molenda
Date: 2022-06-07T13:34:30-07:00
New Revision: 8d5a6007f9681ded3e6442bafdea87e733d771ea

URL: https://github.com/llvm/llvm-project/commit/8d5a6007f9681ded3e6442bafdea87e733d771ea
DIFF: https://github.com/llvm/llvm-project/commit/8d5a6007f9681ded3e6442bafdea87e733d771ea.diff

LOG: Track transition from launch dyld to shared-cache dyld

On macOS, a process will be launched with /usr/lib/dyld (the
dynamic linker) and the main binary by the kernel.  The
first thing the standalone dyld will do is call into the dyld
in the shared cache image.  This patch tracks the transition
between the dyld's at the very beginning of process startup.

In DynamicLoaderMacOS::NotifyBreakpointHit() there are two new
cases handled:

`dyld_image_dyld_moved` which is the launch /usr/lib/dyld indicating
that it is about call into the shared cache dyld ane evict itself.
lldb will remove the notification breakpoint it set, clear the binary
image list entirely, get the notification function pointer value out
of the dyld_all_image_infos struct (which is the notification fptr
in the to-be-run shared-cache dyld) and put an address breakpoint
there.

`dyld_notify_adding` is then called by shared-cache dyld, and we
detect this case by noticing that we have an empty binary image list,
normally impossibe, and treating this as if we'd just started a
process attach/launch.

Differential Revision: https://reviews.llvm.org/D127247
rdar://84222158

Added: 
    

Modified: 
    lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
    lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h
    lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp
    lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
index 033394bbfe1ed..043504be510aa 100644
--- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
+++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
@@ -611,6 +611,8 @@ ModuleSP DynamicLoaderDarwin::GetDYLDModule() {
   return dyld_sp;
 }
 
+void DynamicLoaderDarwin::ClearDYLDModule() { m_dyld_module_wp.reset(); }
+
 bool DynamicLoaderDarwin::AddModulesUsingImageInfos(
     ImageInfo::collection &image_infos) {
   std::lock_guard<std::recursive_mutex> guard(m_mutex);

diff  --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h
index 1b705e9444680..5a72de25e5491 100644
--- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h
+++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h
@@ -71,6 +71,8 @@ class DynamicLoaderDarwin : public lldb_private::DynamicLoader {
 
   lldb::ModuleSP GetDYLDModule();
 
+  void ClearDYLDModule();
+
   class Segment {
   public:
     Segment() : name() {}

diff  --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp
index e6bcc4c00feab..63b0b96e8ea3f 100644
--- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp
+++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp
@@ -14,6 +14,7 @@
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Symbol/SymbolVendor.h"
 #include "lldb/Target/ABI.h"
+#include "lldb/Target/SectionLoadList.h"
 #include "lldb/Target/StackFrame.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Target/Thread.h"
@@ -76,13 +77,16 @@ DynamicLoader *DynamicLoaderMacOS::CreateInstance(Process *process,
 // Constructor
 DynamicLoaderMacOS::DynamicLoaderMacOS(Process *process)
     : DynamicLoaderDarwin(process), m_image_infos_stop_id(UINT32_MAX),
-      m_break_id(LLDB_INVALID_BREAK_ID), m_mutex(),
+      m_break_id(LLDB_INVALID_BREAK_ID),
+      m_dyld_handover_break_id(LLDB_INVALID_BREAK_ID), m_mutex(),
       m_maybe_image_infos_address(LLDB_INVALID_ADDRESS) {}
 
 // Destructor
 DynamicLoaderMacOS::~DynamicLoaderMacOS() {
   if (LLDB_BREAK_ID_IS_VALID(m_break_id))
     m_process->GetTarget().RemoveBreakpointByID(m_break_id);
+  if (LLDB_BREAK_ID_IS_VALID(m_dyld_handover_break_id))
+    m_process->GetTarget().RemoveBreakpointByID(m_dyld_handover_break_id);
 }
 
 bool DynamicLoaderMacOS::ProcessDidExec() {
@@ -135,8 +139,11 @@ void DynamicLoaderMacOS::DoClear() {
 
   if (LLDB_BREAK_ID_IS_VALID(m_break_id))
     m_process->GetTarget().RemoveBreakpointByID(m_break_id);
+  if (LLDB_BREAK_ID_IS_VALID(m_dyld_handover_break_id))
+    m_process->GetTarget().RemoveBreakpointByID(m_dyld_handover_break_id);
 
   m_break_id = LLDB_INVALID_BREAK_ID;
+  m_dyld_handover_break_id = LLDB_INVALID_BREAK_ID;
 }
 
 // Check if we have found DYLD yet
@@ -286,13 +293,50 @@ bool DynamicLoaderMacOS::NotifyBreakpointHit(void *baton,
             }
             if (dyld_mode == 0) {
               // dyld_notify_adding
-              dyld_instance->AddBinaries(image_load_addresses);
+              if (process->GetTarget().GetImages().GetSize() == 0) {
+                // When all images have been removed, we're doing the
+                // dyld handover from a launch-dyld to a shared-cache-dyld,
+                // and we've just hit our one-shot address breakpoint in
+                // the sc-dyld.  Note that the image addresses passed to
+                // this function are inferior sizeof(void*) not uint64_t's
+                // like our normal notification, so don't even look at
+                // image_load_addresses.
+
+                dyld_instance->ClearDYLDHandoverBreakpoint();
+
+                dyld_instance->DoInitialImageFetch();
+                dyld_instance->SetNotificationBreakpoint();
+              } else {
+                dyld_instance->AddBinaries(image_load_addresses);
+              }
             } else if (dyld_mode == 1) {
               // dyld_notify_removing
               dyld_instance->UnloadImages(image_load_addresses);
             } else if (dyld_mode == 2) {
               // dyld_notify_remove_all
               dyld_instance->UnloadAllImages();
+            } else if (dyld_mode == 3 && image_infos_count == 1) {
+              // dyld_image_dyld_moved
+
+              dyld_instance->ClearNotificationBreakpoint();
+              dyld_instance->UnloadAllImages();
+              dyld_instance->ClearDYLDModule();
+              process->GetTarget().GetImages().Clear();
+              process->GetTarget().GetSectionLoadList().Clear();
+
+              addr_t all_image_infos = process->GetImageInfoAddress();
+              int addr_size =
+                  process->GetTarget().GetArchitecture().GetAddressByteSize();
+              addr_t notification_location = all_image_infos + 4 + // version
+                                             4 +        // infoArrayCount
+                                             addr_size; // infoArray
+              Status error;
+              addr_t notification_addr =
+                  process->ReadPointerFromMemory(notification_location, error);
+              if (ABISP abi_sp = process->GetABI())
+                notification_addr = abi_sp->FixCodeAddress(notification_addr);
+
+              dyld_instance->SetDYLDHandoverBreakpoint(notification_addr);
             }
           }
         }
@@ -371,6 +415,26 @@ bool DynamicLoaderMacOS::SetNotificationBreakpoint() {
   return m_break_id != LLDB_INVALID_BREAK_ID;
 }
 
+bool DynamicLoaderMacOS::SetDYLDHandoverBreakpoint(
+    addr_t notification_address) {
+  if (m_dyld_handover_break_id == LLDB_INVALID_BREAK_ID) {
+    BreakpointSP dyld_handover_bp = m_process->GetTarget().CreateBreakpoint(
+        notification_address, true, false);
+    dyld_handover_bp->SetCallback(DynamicLoaderMacOS::NotifyBreakpointHit, this,
+                                  true);
+    dyld_handover_bp->SetOneShot(true);
+    m_dyld_handover_break_id = dyld_handover_bp->GetID();
+    return true;
+  }
+  return false;
+}
+
+void DynamicLoaderMacOS::ClearDYLDHandoverBreakpoint() {
+  if (LLDB_BREAK_ID_IS_VALID(m_dyld_handover_break_id))
+    m_process->GetTarget().RemoveBreakpointByID(m_dyld_handover_break_id);
+  m_dyld_handover_break_id = LLDB_INVALID_BREAK_ID;
+}
+
 addr_t
 DynamicLoaderMacOS::GetDyldLockVariableAddressFromModule(Module *module) {
   SymbolContext sc;

diff  --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h
index a1796794eb467..b6e4ce8e5c37d 100644
--- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h
+++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h
@@ -71,6 +71,10 @@ class DynamicLoaderMacOS : public lldb_private::DynamicLoaderDarwin {
 
   bool DidSetNotificationBreakpoint() override;
 
+  bool SetDYLDHandoverBreakpoint(lldb::addr_t notification_address);
+
+  void ClearDYLDHandoverBreakpoint();
+
   void AddBinaries(const std::vector<lldb::addr_t> &load_addresses);
 
   void DoClear() override;
@@ -94,6 +98,7 @@ class DynamicLoaderMacOS : public lldb_private::DynamicLoaderDarwin {
   uint32_t m_image_infos_stop_id; // The Stop ID the last time we
                                   // loaded/unloaded images
   lldb::user_id_t m_break_id;
+  lldb::user_id_t m_dyld_handover_break_id;
   mutable std::recursive_mutex m_mutex;
   lldb::addr_t m_maybe_image_infos_address; // If dyld is still maintaining the
                                             // all_image_infos address, store it


        


More information about the lldb-commits mailing list