From 080495bb84cf76f549a79b27957b561453452695 Mon Sep 17 00:00:00 2001 From: Mark Rowe Date: Tue, 8 Apr 2025 21:32:56 -0700 Subject: [PATCH] [MachO] Handle chained imports with addends They show up in some macOS system executables. --- view/macho/machoview.cpp | 71 ++++++++++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 24 deletions(-) diff --git a/view/macho/machoview.cpp b/view/macho/machoview.cpp index 440d27979f..2a04b7ed80 100644 --- a/view/macho/machoview.cpp +++ b/view/macho/machoview.cpp @@ -3118,6 +3118,32 @@ void MachoView::ParseChainedFixups(MachOHeader& header, linkedit_data_command ch std::vector importTable; parentReader.Seek(importsAddress); + auto processChainedImport = + [symbolsAddress, &importTable]( + uint64_t ordinal, uint64_t addend, uint32_t nameOffset, bool weak, auto& reader) { + import_entry entry; + entry.lib_ordinal = ordinal; + entry.addend = addend; + entry.weak = weak; + + auto nextEntryAddress = reader.GetOffset(); + size_t symNameAddr = symbolsAddress + nameOffset; + + reader.Seek(symNameAddr); + try + { + string symbolName = reader.ReadCString(); + entry.name = symbolName; + } + catch (ReadException& ex) + { + entry.name = ""; + } + + importTable.push_back(entry); + reader.Seek(nextEntryAddress); + }; + switch (fixupsHeader.imports_format) { case DYLD_CHAINED_IMPORT: @@ -3125,38 +3151,34 @@ void MachoView::ParseChainedFixups(MachOHeader& header, linkedit_data_command ch for (size_t i = 0; i < fixupsHeader.imports_count; i++) { uint32_t importEntry = parentReader.Read32(); - uint64_t nextEntryAddress = parentReader.GetOffset(); - dyld_chained_import import = *(reinterpret_cast(&importEntry)); - - import_entry entry; - - entry.lib_ordinal = (uint64_t)import.lib_ordinal; - entry.addend = 0; - entry.weak = (import.weak_import == 1); - - size_t symNameAddr = symbolsAddress + import.name_offset; - - parentReader.Seek(symNameAddr); - try { - string symbolName = parentReader.ReadCString(); - entry.name = symbolName; - } - catch (ReadException& ex) - { - entry.name = ""; - } - - importTable.push_back(entry); - parentReader.Seek(nextEntryAddress); + processChainedImport(import.lib_ordinal, 0, import.name_offset, import.weak_import, parentReader); } break; } case DYLD_CHAINED_IMPORT_ADDEND: + { + for (size_t i = 0; i < fixupsHeader.imports_count; i++) + { + dyld_chained_import_addend import; + parentReader.Read(&import, sizeof(import)); + processChainedImport(import.lib_ordinal, import.addend, import.name_offset, import.weak_import, parentReader); + } + break; + } case DYLD_CHAINED_IMPORT_ADDEND64: + { + for (size_t i = 0; i < fixupsHeader.imports_count; i++) + { + dyld_chained_import_addend64 import; + parentReader.Read(&import, sizeof(import)); + processChainedImport(import.lib_ordinal, import.addend, import.name_offset, import.weak_import, parentReader); + } + break; + } default: { - m_logger->LogWarn("Chained Fixups: Unknown import binding format"); + m_logger->LogWarn("Chained Fixups: Unknown import binding format %d", fixupsHeader.imports_format); processBinds = false; // We can still handle rebases. break; } @@ -3392,6 +3414,7 @@ void MachoView::ParseChainedFixups(MachOHeader& header, linkedit_data_command ch externReloc.size = m_addressSize; externReloc.pcRelative = false; externReloc.external = true; + externReloc.addend = entry.addend; header.externalRelocations.emplace_back(externReloc, entry.name); } else