Author: Jason Molenda Date: 2025-02-18T12:40:54-08:00 New Revision: 1f5edb17b23f5ac0576f83a6c122ce38bd5ec18e
URL: https://github.com/llvm/llvm-project/commit/1f5edb17b23f5ac0576f83a6c122ce38bd5ec18e DIFF: https://github.com/llvm/llvm-project/commit/1f5edb17b23f5ac0576f83a6c122ce38bd5ec18e.diff LOG: [lldb][Mach-O] Read dyld_all_image_infos addr from `main bin spec` LC_NOTE (#127156) Mach-O corefiles have LC_NOTE metadata, one LC_NOTE that lldb recognizes is `main bin spec` which can specify that this is a kernel corefile, userland corefile, or firmware/standalone corefile. With a userland corefile, the LC_NOTE would specify the virtual address of the dyld binary's Mach-O header. lldb would create a Module from that in-memory binary, find the `dyld_all_image_infos` object in dyld's DATA segment, and use that object to find all of the binaries present in the corefile. ProcessMachCore takes the metadata from this LC_NOTE and passes the address to the DynamicLoader plugin via its `GetImageInfoAddress()` method, so the DynamicLoader can find all of the binaries and load them in the Target at their correct virtual addresses. We have a corefile creator who would prefer to specify the address of `dyld_all_image_infos` directly, instead of specifying the address of dyld and parsing that to find the object. DynamicLoaderMacOSX, the DynamicLoader plugin being used here, will accept either a dyld virtual address or a `dyld_all_image_infos` virtual address from ProcessMachCore, and do the correct thing with either value. lldb's process save-core mach-o corefile reader will continue to specify the virtual address of the dyld binary. rdar://144322688 Added: Modified: lldb/include/lldb/Symbol/ObjectFile.h lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp lldb/source/Plugins/Process/mach-core/ProcessMachCore.h Removed: ################################################################################ diff --git a/lldb/include/lldb/Symbol/ObjectFile.h b/lldb/include/lldb/Symbol/ObjectFile.h index d89314d44bf67..874926da2ceb7 100644 --- a/lldb/include/lldb/Symbol/ObjectFile.h +++ b/lldb/include/lldb/Symbol/ObjectFile.h @@ -81,9 +81,14 @@ class ObjectFile : public std::enable_shared_from_this<ObjectFile>, enum BinaryType { eBinaryTypeInvalid = 0, eBinaryTypeUnknown, - eBinaryTypeKernel, /// kernel binary - eBinaryTypeUser, /// user process binary - eBinaryTypeStandalone /// standalone binary / firmware + /// kernel binary + eBinaryTypeKernel, + /// user process binary, dyld addr + eBinaryTypeUser, + /// user process binary, dyld_all_image_infos addr + eBinaryTypeUserAllImageInfos, + /// standalone binary / firmware + eBinaryTypeStandalone }; struct LoadableData { diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index 4e356a7c8f5d9..a19322ff1e263 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -5599,9 +5599,13 @@ bool ObjectFileMachO::GetCorefileMainBinaryInfo(addr_t &value, // struct main_bin_spec // { // uint32_t version; // currently 2 - // uint32_t type; // 0 == unspecified, 1 == kernel, + // uint32_t type; // 0 == unspecified, + // // 1 == kernel // // 2 == user process, + // dyld mach-o binary addr // // 3 == standalone binary + // // 4 == user process, + // // dyld_all_image_infos addr // uint64_t address; // UINT64_MAX if address not specified // uint64_t slide; // slide, UINT64_MAX if unspecified // // 0 if no slide needs to be applied to @@ -5652,6 +5656,7 @@ bool ObjectFileMachO::GetCorefileMainBinaryInfo(addr_t &value, // convert the "main bin spec" type into our // ObjectFile::BinaryType enum const char *typestr = "unrecognized type"; + type = eBinaryTypeInvalid; switch (binspec_type) { case 0: type = eBinaryTypeUnknown; @@ -5669,6 +5674,10 @@ bool ObjectFileMachO::GetCorefileMainBinaryInfo(addr_t &value, type = eBinaryTypeStandalone; typestr = "standalone"; break; + case 4: + type = eBinaryTypeUserAllImageInfos; + typestr = "userland dyld_all_image_infos"; + break; } LLDB_LOGF(log, "LC_NOTE 'main bin spec' found, version %d type %d " diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp index eef9bd4a175ec..281f3a0db8f69 100644 --- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp +++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp @@ -114,6 +114,7 @@ ProcessMachCore::ProcessMachCore(lldb::TargetSP target_sp, : PostMortemProcess(target_sp, listener_sp, core_file), m_core_aranges(), m_core_range_infos(), m_core_module_sp(), m_dyld_addr(LLDB_INVALID_ADDRESS), + m_dyld_all_image_infos_addr(LLDB_INVALID_ADDRESS), m_mach_kernel_addr(LLDB_INVALID_ADDRESS) {} // Destructor @@ -320,6 +321,9 @@ bool ProcessMachCore::LoadBinariesViaMetadata() { } else if (type == ObjectFile::eBinaryTypeUser) { m_dyld_addr = objfile_binary_value; m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic(); + } else if (type == ObjectFile::eBinaryTypeUserAllImageInfos) { + m_dyld_all_image_infos_addr = objfile_binary_value; + m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic(); } else { const bool force_symbol_search = true; const bool notify = true; @@ -466,6 +470,7 @@ void ProcessMachCore::LoadBinariesViaExhaustiveSearch() { addr_t saved_user_dyld_addr = m_dyld_addr; m_mach_kernel_addr = LLDB_INVALID_ADDRESS; m_dyld_addr = LLDB_INVALID_ADDRESS; + m_dyld_all_image_infos_addr = LLDB_INVALID_ADDRESS; addr_t better_kernel_address = DynamicLoaderDarwinKernel::SearchForDarwinKernel(this); @@ -507,6 +512,12 @@ void ProcessMachCore::LoadBinariesAndSetDYLD() { "image at 0x%" PRIx64, __FUNCTION__, m_dyld_addr); m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic(); + } else if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS) { + LLDB_LOGF(log, + "ProcessMachCore::%s: Using user process dyld " + "dyld_all_image_infos at 0x%" PRIx64, + __FUNCTION__, m_dyld_all_image_infos_addr); + m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic(); } } else { if (m_dyld_addr != LLDB_INVALID_ADDRESS) { @@ -515,6 +526,11 @@ void ProcessMachCore::LoadBinariesAndSetDYLD() { "image at 0x%" PRIx64, __FUNCTION__, m_dyld_addr); m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic(); + } else if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS) { + LLDB_LOGF(log, + "ProcessMachCore::%s: Using user process dyld " + "dyld_all_image_infos at 0x%" PRIx64, + __FUNCTION__, m_dyld_all_image_infos_addr); } else if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) { LLDB_LOGF(log, "ProcessMachCore::%s: Using kernel " @@ -763,19 +779,32 @@ void ProcessMachCore::Initialize() { } addr_t ProcessMachCore::GetImageInfoAddress() { - // If we found both a user-process dyld and a kernel binary, we need to - // decide which to prefer. + // The DynamicLoader plugin will call back in to this Process + // method to find the virtual address of one of these: + // 1. The xnu mach kernel binary Mach-O header + // 2. The dyld binary Mach-O header + // 3. dyld's dyld_all_image_infos object + // + // DynamicLoaderMacOSX will accept either the dyld Mach-O header + // address or the dyld_all_image_infos interchangably, no need + // to distinguish between them. It disambiguates by the Mach-O + // file magic number at the start. if (GetCorefilePreference() == eKernelCorefile) { - if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) { + if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) return m_mach_kernel_addr; - } - return m_dyld_addr; + if (m_dyld_addr != LLDB_INVALID_ADDRESS) + return m_dyld_addr; } else { - if (m_dyld_addr != LLDB_INVALID_ADDRESS) { + if (m_dyld_addr != LLDB_INVALID_ADDRESS) return m_dyld_addr; - } - return m_mach_kernel_addr; + if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) + return m_mach_kernel_addr; } + + // m_dyld_addr and m_mach_kernel_addr both + // invalid, return m_dyld_all_image_infos_addr + // in case it has a useful value. + return m_dyld_all_image_infos_addr; } lldb_private::ObjectFile *ProcessMachCore::GetCoreObjectFile() { diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h index 8996ae116614b..6ba9f2354edf9 100644 --- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h +++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h @@ -131,6 +131,7 @@ class ProcessMachCore : public lldb_private::PostMortemProcess { VMRangeToPermissions m_core_range_infos; lldb::ModuleSP m_core_module_sp; lldb::addr_t m_dyld_addr; + lldb::addr_t m_dyld_all_image_infos_addr; lldb::addr_t m_mach_kernel_addr; llvm::StringRef m_dyld_plugin_name; }; _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits