jasonmolenda created this revision. jasonmolenda added a reviewer: JDevlieghere. jasonmolenda added a project: LLDB. Herald added a project: All. jasonmolenda requested review of this revision. Herald added a subscriber: lldb-commits.
In macOS Ventura et al, the dynamic linker, dyld, has moved into the shared cache image. A process starts with our normal on-disk /usr/lib/dyld, and the first thing it does is execute into an in-memory-only copy of dyld in the shared cache blob. lldb needs to track this transition as we hand off from one dyld to the other, to get notified about newly added binary images in the process. All of the action happens in DynamicLoaderMacOS::NotifyBreakpointHit(), where we detect two new cases: A new `dyld_image_dyld_moved` which is called when the launch dyld is about to transition over to the shared cache dyld, and we can get the address of the new notification function out of all_image_infos and set an address breakpoint and we clear out the list of known binary images. And a new mode of `dyld_notify_adding` where we have no binary images registered (because it was cleared in the previous step), so we know that this is a new shared cache dyld doing its first notification, and treat it appropriately, setting our normal by-name notification breakpoint. rdar://84222158 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D127247 Files: 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
Index: lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h =================================================================== --- lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h +++ lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h @@ -71,6 +71,10 @@ 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 @@ 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 Index: lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp =================================================================== --- lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp +++ 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 @@ // 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 @@ 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,51 @@ } 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 +416,27 @@ 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; Index: lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h =================================================================== --- lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h +++ lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h @@ -71,6 +71,8 @@ lldb::ModuleSP GetDYLDModule(); + void ClearDYLDModule(); + class Segment { public: Segment() : name() {} Index: lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp =================================================================== --- lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp +++ lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp @@ -611,6 +611,8 @@ 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);
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits