summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins')
-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