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

Reply via email to