[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
diff --git a/lldb/include/lldb/Symbol/ObjectFile.h b/lldb/include/lldb/Symbol/ObjectFile.h
index d89314d..874926d 100644
--- a/lldb/include/lldb/Symbol/ObjectFile.h
+++ b/lldb/include/lldb/Symbol/ObjectFile.h
@@ -81,9 +81,14 @@
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 4e356a7..a19322f 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -5599,9 +5599,13 @@
// 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 @@
// 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 @@
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 eef9bd4..281f3a0 100644
--- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp
+++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp
@@ -114,6 +114,7 @@
: 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 @@
} 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 @@
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 @@
"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 @@
"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 @@
}
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;
- } else {
- if (m_dyld_addr != LLDB_INVALID_ADDRESS) {
+ if (m_dyld_addr != LLDB_INVALID_ADDRESS)
return m_dyld_addr;
- }
- return m_mach_kernel_addr;
+ } else {
+ if (m_dyld_addr != LLDB_INVALID_ADDRESS)
+ return m_dyld_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 8996ae1..6ba9f23 100644
--- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h
+++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h
@@ -131,6 +131,7 @@
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;
};