diff --git a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/CMakeLists.txt b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/CMakeLists.txt --- a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/CMakeLists.txt +++ b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/CMakeLists.txt @@ -17,6 +17,7 @@ lldbSymbol lldbTarget lldbUtility + lldbPluginObjectFileMachO ) add_dependencies(lldbPluginDynamicLoaderDarwinKernel diff --git a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp --- a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp +++ b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h" #include "Plugins/Platform/MacOSX/PlatformDarwinKernel.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Core/Debugger.h" @@ -713,6 +714,7 @@ bool DynamicLoaderDarwinKernel::KextImageInfo::LoadImageUsingMemoryModule( Process *process) { + Log *log = GetLog(LLDBLog::DynamicLoader); if (IsLoaded()) return true; @@ -837,6 +839,35 @@ // it. const bool ignore_linkedit = !IsKernel(); + // Normally a kext will have its segment load commands + // (LC_SEGMENT vmaddrs) corrected in memory to have their + // actual segment addresses. + // Userland proceses have their libraries updated the same way + // by dyld. The Mach-O load commands in memory are the canonical + // addresses. + // + // If the kernel gives us a binary where the in-memory segment + // vmaddr is incorrect, then this binary was put in memory without + // updating its Mach-O load commands. We should assume a static + // slide value will be applied to every segment; we don't have the + // correct addresses for each individual segment. + addr_t fixed_slide = LLDB_INVALID_ADDRESS; + ObjectFileMachO *memory_module_macho_sp = + llvm::dyn_cast(memory_object_file); + if (memory_module_macho_sp) { + if (Section *header_sect = + memory_module_macho_sp->GetMachHeaderSection()) { + if (header_sect->GetFileAddress() != m_load_address) { + fixed_slide = m_load_address - header_sect->GetFileAddress(); + LLDB_LOGF( + log, + "kext %s in-memory LC_SEGMENT vmaddr is not correct, using a " + "fixed slide of 0x%" PRIx64, + m_name.c_str(), fixed_slide); + } + } + } + SectionList *ondisk_section_list = ondisk_object_file->GetSectionList(); SectionList *memory_section_list = memory_object_file->GetSectionList(); if (memory_section_list && ondisk_section_list) { @@ -865,14 +896,20 @@ ondisk_section_sp->GetName() == g_section_name_LINKEDIT) continue; - const Section *memory_section = - memory_section_list - ->FindSectionByName(ondisk_section_sp->GetName()) - .get(); - if (memory_section) { - target.SetSectionLoadAddress(ondisk_section_sp, - memory_section->GetFileAddress()); - ++num_sections_loaded; + if (fixed_slide != LLDB_INVALID_ADDRESS) { + target.SetSectionLoadAddress( + ondisk_section_sp, + ondisk_section_sp->GetFileAddress() + fixed_slide); + } else { + const Section *memory_section = + memory_section_list + ->FindSectionByName(ondisk_section_sp->GetName()) + .get(); + if (memory_section) { + target.SetSectionLoadAddress( + ondisk_section_sp, memory_section->GetFileAddress()); + ++num_sections_loaded; + } } } } diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h @@ -151,6 +151,8 @@ bool AllowAssemblyEmulationUnwindPlans() override; + lldb_private::Section *GetMachHeaderSection(); + // PluginInterface protocol llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } @@ -193,8 +195,6 @@ /// should not be used. void GetLLDBSharedCacheUUID(lldb::addr_t &base_addir, lldb_private::UUID &uuid); - lldb_private::Section *GetMachHeaderSection(); - lldb::addr_t CalculateSectionLoadAddressForMemoryImage( lldb::addr_t mach_header_load_address, const lldb_private::Section *mach_header_section,