summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Molenda <jmolenda@apple.com>2019-03-06 02:45:27 +0000
committerJason Molenda <jmolenda@apple.com>2019-03-06 02:45:27 +0000
commit4cc9ff12455496e8f415381315872e8ae797e520 (patch)
tree1f087cfc3acd61f93da9cb5f3d86b836a1e7efc6
parent6a8aa0e89807a3c93c4831b10f489dbfb37980fb (diff)
downloadbcm5719-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.cpp62
-rw-r--r--lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h6
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
OpenPOWER on IntegriCloud