ProcessMachCore scans through the core file pages looking for a
user process dyld binary and/or a mach kernel binary image. By
default, it prefers the kernel if it finds both.
But if it finds two kernel binary images (which can happen when
random things are mapped into memory), it may pick the wrong
kernel image.
DynamicLoaderDarwinKernel has heuristics to find a kernel in memory;
once we've established that there is a kernel binary in memory,
call over to that class to see if it can find a kernel address via
its search methods. If it does, use that.
Some minor cleanups to DynamicLoaderDarwinKernel while I was at it.
<rdar://problem/24446112>
llvm-svn: 259983
diff --git a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
index 6ac210a..4c2b02f 100644
--- a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
+++ b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
@@ -254,37 +254,29 @@
Error read_err;
addr_t addr = LLDB_INVALID_ADDRESS;
- if (process->GetTarget().GetArchitecture().GetAddressByteSize() == 8)
+ addr_t kernel_addresses_64[] = { 0xffffff8000002010ULL, 0xffffff8000004010ULL,
+ 0xfffffff000002010ULL, 0xfffffff000004010ULL,
+ LLDB_INVALID_ADDRESS };
+ addr_t kernel_addresses_32[] = { 0xffff0110,
+ LLDB_INVALID_ADDRESS };
+ for (size_t i = 0; kernel_addresses_64[i] != LLDB_INVALID_ADDRESS; i++)
{
- addr = process->ReadUnsignedIntegerFromMemory (0xffffff8000002010ULL, 8, LLDB_INVALID_ADDRESS, read_err);
- if (CheckForKernelImageAtAddress (addr, process).IsValid())
- {
- return addr;
- }
- addr = process->ReadUnsignedIntegerFromMemory (0xffffff8000004010ULL, 8, LLDB_INVALID_ADDRESS, read_err);
- if (CheckForKernelImageAtAddress (addr, process).IsValid())
- {
- return addr;
- }
- addr = process->ReadUnsignedIntegerFromMemory (0xfffffff000002010ULL, 8, LLDB_INVALID_ADDRESS, read_err);
- if (CheckForKernelImageAtAddress (addr, process).IsValid())
- {
- return addr;
- }
- addr = process->ReadUnsignedIntegerFromMemory (0xfffffff000004010ULL, 8, LLDB_INVALID_ADDRESS, read_err);
+ addr = process->ReadUnsignedIntegerFromMemory (kernel_addresses_64[i], 8, LLDB_INVALID_ADDRESS, read_err);
if (CheckForKernelImageAtAddress (addr, process).IsValid())
{
return addr;
}
}
- else
+
+ for (size_t i = 0; kernel_addresses_32[i] != LLDB_INVALID_ADDRESS; i++)
{
- addr = process->ReadUnsignedIntegerFromMemory (0xffff0110, 4, LLDB_INVALID_ADDRESS, read_err);
+ addr = process->ReadUnsignedIntegerFromMemory (kernel_addresses_32[i], 4, LLDB_INVALID_ADDRESS, read_err);
if (CheckForKernelImageAtAddress (addr, process).IsValid())
{
return addr;
}
}
+
return LLDB_INVALID_ADDRESS;
}
@@ -311,28 +303,14 @@
if (pc == LLDB_INVALID_ADDRESS)
return LLDB_INVALID_ADDRESS;
- addr_t kernel_range_low;
- if (process->GetTarget().GetArchitecture().GetAddressByteSize() == 8)
- {
- kernel_range_low = 1ULL << 63;
- }
- else
- {
- kernel_range_low = 1ULL << 31;
- }
-
- // Outside the normal kernel address range, this is probably userland code running right now
- if (pc < kernel_range_low)
- 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, depending on the device.
+ // 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;
- int i = 0;
- while (i < 32 && pc >= kernel_range_low)
+ // 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)
{
if (CheckForKernelImageAtAddress (addr, process).IsValid())
return addr;
@@ -342,8 +320,6 @@
return addr + 0x2000;
if (CheckForKernelImageAtAddress (addr + 0x4000, process).IsValid())
return addr + 0x4000;
- i++;
- addr -= 0x100000;
}
return LLDB_INVALID_ADDRESS;
@@ -429,19 +405,19 @@
// Read the mach header and see whether it looks like a kernel
llvm::MachO::mach_header header;
- if (process->DoReadMemory (addr, &header, sizeof(header), read_error) != sizeof(header))
+ if (process->DoReadMemory (addr, &header, sizeof (header), read_error) != sizeof (header))
return UUID();
if (header.magic == llvm::MachO::MH_CIGAM ||
header.magic == llvm::MachO::MH_CIGAM_64)
{
- header.magic = llvm::ByteSwap_32(header.magic);
- header.cputype = llvm::ByteSwap_32(header.cputype);
- header.cpusubtype = llvm::ByteSwap_32(header.cpusubtype);
- header.filetype = llvm::ByteSwap_32(header.filetype);
- header.ncmds = llvm::ByteSwap_32(header.ncmds);
- header.sizeofcmds = llvm::ByteSwap_32(header.sizeofcmds);
- header.flags = llvm::ByteSwap_32(header.flags);
+ header.magic = llvm::ByteSwap_32 (header.magic);
+ header.cputype = llvm::ByteSwap_32 (header.cputype);
+ header.cpusubtype = llvm::ByteSwap_32 (header.cpusubtype);
+ header.filetype = llvm::ByteSwap_32 (header.filetype);
+ header.ncmds = llvm::ByteSwap_32 (header.ncmds);
+ header.sizeofcmds = llvm::ByteSwap_32 (header.sizeofcmds);
+ header.flags = llvm::ByteSwap_32 (header.flags);
}
// A kernel is an executable which does not have the dynamic link object flag set.