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.
The Darwin kernel has a number of kernel extensions, kexts, akin to solibs to lldb. We find the kext binary on disk, we create a MemoryModule from the in-memory image based on the Mach-O header and Mach-O load commands in memory. The LC_SEGMENT vmaddrs for each segment in memory have been updated with their actual load addresses. DynamicLoaderDarwinKernel uses the MemoryModule's Section "file" addresses to set the load addresses for the on-disk Module in the target. There are some extensions that can be loaded into memory which won't have the Mach-O load commands with their load addresses updated. So the MemoryModule has the original file addresses, instead of the actual in-memory load addresses. The current DynamicLoader code will then set the target section load addresses to the file addresses, which doesn't work. This patch detects this by looking at the MemoryModule's Mach-O header (`__TEXT`) segment, and comparing its actual memory address we used to create the MemoryModule with the vmaddr ("file address") of the MemoryModule Section. If they differ, this is one of those binaries that hasn't had its load commands updated when they were added to memory. When this is detected, we assume all segments slide by a constant value, calculate that slide, and apply it to all the sections. Normal kexts have their load addresses calculated as they always had been. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D145547 Files: lldb/source/Plugins/DynamicLoader/Darwin-Kernel/CMakeLists.txt lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
Index: lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h =================================================================== --- lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h +++ 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, Index: lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp =================================================================== --- lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp +++ 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<ObjectFileMachO>(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; + } } } } Index: lldb/source/Plugins/DynamicLoader/Darwin-Kernel/CMakeLists.txt =================================================================== --- lldb/source/Plugins/DynamicLoader/Darwin-Kernel/CMakeLists.txt +++ lldb/source/Plugins/DynamicLoader/Darwin-Kernel/CMakeLists.txt @@ -17,6 +17,7 @@ lldbSymbol lldbTarget lldbUtility + lldbPluginObjectFileMachO ) add_dependencies(lldbPluginDynamicLoaderDarwinKernel
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits