diff options
author | Jason Molenda <jmolenda@apple.com> | 2019-03-06 02:45:27 +0000 |
---|---|---|
committer | Jason Molenda <jmolenda@apple.com> | 2019-03-06 02:45:27 +0000 |
commit | 4cc9ff12455496e8f415381315872e8ae797e520 (patch) | |
tree | 1f087cfc3acd61f93da9cb5f3d86b836a1e7efc6 | |
parent | 6a8aa0e89807a3c93c4831b10f489dbfb37980fb (diff) | |
download | bcm5719-llvm-4cc9ff12455496e8f415381315872e8ae797e520.tar.gz bcm5719-llvm-4cc9ff12455496e8f415381315872e8ae797e520.zip |
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>
llvm-svn: 355476
-rw-r--r-- | lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp | 62 | ||||
-rw-r--r-- | lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h | 6 |
2 files changed, 41 insertions, 27 deletions
diff --git a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp index c4880fa945b..bae481a031b 100644 --- a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp +++ b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp @@ -294,9 +294,11 @@ DynamicLoaderDarwinKernel::SearchForKernelNearPC(Process *process) { 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::SearchForKernelNearPC(Process *process) { 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. + int pagesize = 0x4000; // 16k pages on 64-bit targets + if (ptrsize == 4) + pagesize = 0x1000; // 4k pages on 32-bit targets - // Round the current pc down to the nearest one megabyte boundary - the place - // where we will start searching. - addr_t addr = pc & ~0xfffff; + // 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 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()) + // 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::SearchForKernelViaExhaustiveSearch( //---------------------------------------------------------------------- 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::ReadMachHeader(addr_t addr, Process *process, llvm::M //---------------------------------------------------------------------- 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::CheckForKernelImageAtAddress(lldb::addr_t addr, 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 diff --git a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h index 894b5521433..edcecd141d3 100644 --- a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h +++ b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h @@ -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 |