[Lldb-commits] [lldb] r355476 - Change the scanning algorithm in DynamicLoaderDarwinKernel::SearchForKernelNearPC.

Jason Molenda via lldb-commits lldb-commits at lists.llvm.org
Tue Mar 5 18:45:27 PST 2019


Author: jmolenda
Date: Tue Mar  5 18:45:27 2019
New Revision: 355476

URL: http://llvm.org/viewvc/llvm-project?rev=355476&view=rev
Log:
Change the scanning algorithm in DynamicLoaderDarwinKernel::SearchForKernelNearPC.
Currently when lldb might be doing a kernel debug session, it scans through
memory by taking the current pc value and looking for a kernel at megabyte
boundaries, up to 32MB behind $pc.  This adjusts the algorithm to
scan back at every 16k page boundary and to stop scanning as soon
as we hit a memory read error.  The addition of stopping at a memory read
error saves us from tons of unnecessary packet traffic on generic 
targets where lldb might look for a kernel binary.

I've been trying to think of how to construct a test for this; it's a bit
tricky.  A gdb-remote protocol test with the contents of a fake tiny kernel
mach-o binary would satisify part of it, but this kernel path also directly
calls over to dsymForUUID or DebugSymbols framework lookups to find the 
kernel binary as well.  I'll keep thinking about this one, but it's so
intertangled with these two external systems that it may be hard to do.

<rdar://problem/48578197> 


Modified:
    lldb/trunk/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
    lldb/trunk/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h

Modified: lldb/trunk/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp?rev=355476&r1=355475&r2=355476&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp (original)
+++ lldb/trunk/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp Tue Mar  5 18:45:27 2019
@@ -294,9 +294,11 @@ DynamicLoaderDarwinKernel::SearchForKern
     return LLDB_INVALID_ADDRESS;
   addr_t pc = thread->GetRegisterContext()->GetPC(LLDB_INVALID_ADDRESS);
 
+  int ptrsize = process->GetTarget().GetArchitecture().GetAddressByteSize();
+
   // The kernel is always loaded in high memory, if the top bit is zero,
   // this isn't a kernel.
-  if (process->GetTarget().GetArchitecture().GetAddressByteSize() == 8) {
+  if (ptrsize == 8) {
     if ((pc & (1ULL << 63)) == 0) {
       return LLDB_INVALID_ADDRESS;
     }
@@ -309,26 +311,26 @@ DynamicLoaderDarwinKernel::SearchForKern
   if (pc == LLDB_INVALID_ADDRESS)
     return LLDB_INVALID_ADDRESS;
 
-  // The kernel will load at at one megabyte boundary (0x100000), or at that
-  // boundary plus an offset of one page (0x1000) or two, or four (0x4000),
-  // depending on the device.
-
-  // Round the current pc down to the nearest one megabyte boundary - the place
-  // where we will start searching.
-  addr_t addr = pc & ~0xfffff;
-
-  // Search backwards 32 megabytes, looking for the start of the kernel at each
-  // one-megabyte boundary.
-  for (int i = 0; i < 32; i++, addr -= 0x100000) {
-    // x86_64 kernels are at offset 0
-    if (CheckForKernelImageAtAddress(addr, process).IsValid())
+  int pagesize = 0x4000;  // 16k pages on 64-bit targets
+  if (ptrsize == 4)
+    pagesize = 0x1000;    // 4k pages on 32-bit targets
+
+  // The kernel will be loaded on a page boundary.
+  // Round the current pc down to the nearest page boundary.
+  addr_t addr = pc & ~(pagesize - 1ULL);
+
+  // Search backwards for 32 megabytes, or first memory read error.
+  while (pc - addr < 32 * 0x100000) {
+    bool read_error;
+    if (CheckForKernelImageAtAddress(addr, process, &read_error).IsValid())
       return addr;
-    // 32-bit arm kernels are at offset 0x1000 (one 4k page)
-    if (CheckForKernelImageAtAddress(addr + 0x1000, process).IsValid())
-      return addr + 0x1000;
-    // 64-bit arm kernels are at offset 0x4000 (one 16k page)
-    if (CheckForKernelImageAtAddress(addr + 0x4000, process).IsValid())
-      return addr + 0x4000;
+
+    // Stop scanning on the first read error we encounter; we've walked
+    // past this executable block of memory.
+    if (read_error == true)
+      break;
+
+    addr -= pagesize;
   }
 
   return LLDB_INVALID_ADDRESS;
@@ -387,13 +389,19 @@ lldb::addr_t DynamicLoaderDarwinKernel::
 //----------------------------------------------------------------------
 
 bool
-DynamicLoaderDarwinKernel::ReadMachHeader(addr_t addr, Process *process, llvm::MachO::mach_header &header) {
-  Status read_error;
+DynamicLoaderDarwinKernel::ReadMachHeader(addr_t addr, Process *process, llvm::MachO::mach_header &header,
+                                          bool *read_error) {
+  Status error;
+  if (read_error)
+    *read_error = false;
 
   // Read the mach header and see whether it looks like a kernel
-  if (process->DoReadMemory (addr, &header, sizeof(header), read_error) !=
-      sizeof(header))
+  if (process->DoReadMemory (addr, &header, sizeof(header), error) !=
+      sizeof(header)) {
+    if (read_error)
+      *read_error = true;
     return false;
+  }
 
   const uint32_t magicks[] = { llvm::MachO::MH_MAGIC_64, llvm::MachO::MH_MAGIC, llvm::MachO::MH_CIGAM, llvm::MachO::MH_CIGAM_64};
 
@@ -427,10 +435,14 @@ DynamicLoaderDarwinKernel::ReadMachHeade
 //----------------------------------------------------------------------
 lldb_private::UUID
 DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress(lldb::addr_t addr,
-                                                        Process *process) {
+                                                        Process *process,
+                                                        bool *read_error) {
   Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
-  if (addr == LLDB_INVALID_ADDRESS)
+  if (addr == LLDB_INVALID_ADDRESS) {
+    if (read_error)
+      *read_error = true;
     return UUID();
+  }
 
   if (log)
     log->Printf("DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress: "
@@ -439,7 +451,7 @@ DynamicLoaderDarwinKernel::CheckForKerne
 
   llvm::MachO::mach_header header;
 
-  if (!ReadMachHeader(addr, process, header))
+  if (!ReadMachHeader(addr, process, header, read_error))
     return UUID();
 
   // First try a quick test -- read the first 4 bytes and see if there is a

Modified: lldb/trunk/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h?rev=355476&r1=355475&r2=355476&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h (original)
+++ lldb/trunk/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h Tue Mar  5 18:45:27 2019
@@ -283,11 +283,13 @@ protected:
   SearchForKernelViaExhaustiveSearch(lldb_private::Process *process);
 
   static bool
-  ReadMachHeader(lldb::addr_t addr, lldb_private::Process *process, llvm::MachO::mach_header &mh);
+  ReadMachHeader(lldb::addr_t addr, lldb_private::Process *process, llvm::MachO::mach_header &mh,
+                 bool *read_error = nullptr);
 
   static lldb_private::UUID
   CheckForKernelImageAtAddress(lldb::addr_t addr,
-                               lldb_private::Process *process);
+                               lldb_private::Process *process,
+                               bool *read_error = nullptr);
 
   lldb::addr_t m_kernel_load_address;
   KextImageInfo m_kernel; // Info about the current kernel image being used




More information about the lldb-commits mailing list