-
Notifications
You must be signed in to change notification settings - Fork 61
Description
Note: This is a low-priority issue, as getting pagewalk to work with KGDB required patching the kernel KGDB module and providing custom GDB target configuration files to expose the system registers (TTBR*_EL1, etc.) to GDB.
While I was trying to get the pagewalk command to work in the kgdb mode, I encountered an issue with the way read_physmem is implemented.
When is_kgdb() == True, read_physmem relies on the monitor mdp command. This command appears to be a part of KDB and not KGDB (at least, it's not implemented when using pure CONFIG_KGDB without CONFIG_KGDB_KDB). AFAIU, KDB is a higher-level debugger built on top of KGDB, and it implements a few custom commands.
Is my understanding that KDB was used when this read_physmem implementation was added correct?
If so, as one option, it might be reasonable to separate the kgdb and the kdb modes. All the commands that work in the kgdb mode right now would work in the kdb mode too. But only the subset of commands that does not rely on read_physmem would work in the kgdb mode.
However, I also see an alternative approach.
The problem is that in the actual kgdb mode (i.e., without KDB), there are no built-in GDB commands read physical memory.
However, with KGDB, physical memory can be read via physmap (aka the direct linear mapping). For example, on Pixel 8, the data at the physical address paddr can be read from the virtual address 0xffffff8000000000 + paddr - 0x80000000 (PAGE_OFFSET + paddr - memstart_addr; PAGE_OFFSET is not even affected by KASLR). On other devices, the address of the physmap might be affected by KASLR, but the values of PAGE_OFFSET and memstart_addr should be easy to obtain via GDB memory read commands.
So the alternative is to drop monitor mdp alltogether and just rely on the physmap instead.
Would that be acceptable?
Surprisingly, this even works reasonably fast. With the dirty patch below (and a few other ones to allow pagewalk to work at all), pagewalking the EL1 page tables over KGDB only takes ~4 minutes on Pixel 8.
diff --git a/gef.py b/gef.py
index 65674b01..b54c8f89 100644
--- a/gef.py
+++ b/gef.py
@@ -11898,6 +11898,10 @@ def read_physmem(paddr, size):
out += b"".join([bytes.fromhex(x)[::-1] for x in line.split()[2:4]])
return out[paddr & 0xf:][:size]
+ def kgdb_use_physmap(paddr, size):
+ vaddr = 0xffffff8000000000 + paddr - 0x80000000
+ return read_memory(vaddr, size)
+
# ----
if size == 0:
@@ -11923,7 +11927,7 @@ def read_physmem(paddr, size):
return transparent_read(paddr, size)
if is_kgdb():
- return kgdb_use_mdp(paddr, size)
+ return kgdb_use_physmap(paddr, size)
return NoneOne concern that I thought of here is what would happen when debugging EL2+ (I see that gef does support it): I assume EL2+ memory would not be readable via physmap. But then with KDB, this memory also should not be readable. So I assume the gef's EL2+ debugging functionality relies on QEMU-provided memory-read commands anyway. And thus, using physmap for KGDB would not cause issues.