fix x64 vmmap perf issue

pull/3390/head
jxuanli 1 month ago
parent dfe443ed47
commit 696dc6d0c3

@ -116,9 +116,11 @@ def first_kernel_ro_page() -> pwndbg.lib.memory.Page | None:
if base is None: if base is None:
return None return None
for mapping in pwndbg.aglib.kernel.paging.get_memory_map_raw(): for mapping in pwndbg.aglib.kernel.vmmap.kernel_vmmap_pages():
if mapping.vaddr < base: if mapping.vaddr < base:
continue continue
if not mapping.read or mapping.write or mapping.execute:
continue
result = next(pwndbg.search.search(b"Linux version", mappings=[mapping]), None) result = next(pwndbg.search.search(b"Linux version", mappings=[mapping]), None)
@ -438,13 +440,21 @@ class Aarch64Ops(ArchOps):
return int(pwndbg.aglib.regs.SCTLR) & BIT(0) != 0 return int(pwndbg.aglib.regs.SCTLR) & BIT(0) != 0
_arch_paginginfo: ArchPagingInfo = None
@pwndbg.lib.cache.cache_until("start") @pwndbg.lib.cache.cache_until("start")
def arch_paginginfo() -> ArchPagingInfo | None: def arch_paginginfo() -> ArchPagingInfo:
if pwndbg.aglib.arch.name == "aarch64": _arch_paginginfo = None
return pwndbg.aglib.kernel.paging.Aarch64PagingInfo()
elif pwndbg.aglib.arch.name == "x86-64": if _arch_paginginfo is None:
return pwndbg.aglib.kernel.paging.x86_64PagingInfo() if pwndbg.aglib.arch.name == "aarch64":
return None _arch_paginginfo = pwndbg.aglib.kernel.paging.Aarch64PagingInfo()
elif pwndbg.aglib.arch.name == "x86-64":
_arch_paginginfo = pwndbg.aglib.kernel.paging.x86_64PagingInfo()
return _arch_paginginfo
@pwndbg.lib.cache.cache_until("start") @pwndbg.lib.cache.cache_until("start")

@ -11,6 +11,7 @@ import pwndbg.aglib.vmmap_custom
import pwndbg.color.message as M import pwndbg.color.message as M
import pwndbg.lib.cache import pwndbg.lib.cache
import pwndbg.lib.memory import pwndbg.lib.memory
from pwndbg.aglib.kernel.vmmap import kernel_vmmap_pages
from pwndbg.lib.regs import BitFlags from pwndbg.lib.regs import BitFlags
# don't return None but rather an invalid value for address markers # don't return None but rather an invalid value for address markers
@ -18,14 +19,9 @@ from pwndbg.lib.regs import BitFlags
INVALID_ADDR = 1 << 64 INVALID_ADDR = 1 << 64
@pwndbg.lib.cache.cache_until("stop")
def get_memory_map_raw() -> Tuple[pwndbg.lib.memory.Page, ...]:
return pwndbg.aglib.kernel.vmmap.kernel_vmmap(False)
@pwndbg.lib.cache.cache_until("stop") @pwndbg.lib.cache.cache_until("stop")
def first_kernel_page_start(): def first_kernel_page_start():
for page in get_memory_map_raw(): for page in kernel_vmmap_pages():
if page.start and pwndbg.aglib.memory.is_kernel(page.start): if page.start and pwndbg.aglib.memory.is_kernel(page.start):
return page.start return page.start
return INVALID_ADDR return INVALID_ADDR
@ -95,7 +91,7 @@ class ArchPagingInfo:
raise NotImplementedError() raise NotImplementedError()
def kbase_helper(self, address): def kbase_helper(self, address):
for mapping in get_memory_map_raw(): for mapping in kernel_vmmap_pages():
# should be page aligned -- either from pt-dump or info mem # should be page aligned -- either from pt-dump or info mem
# only search in kernel mappings: # only search in kernel mappings:
@ -215,12 +211,7 @@ class x86_64PagingInfo(ArchPagingInfo):
def physmap(self): def physmap(self):
result = pwndbg.aglib.kernel.symbol.try_usymbol("page_offset_base") result = pwndbg.aglib.kernel.symbol.try_usymbol("page_offset_base")
if result is None: if result is None:
result = INVALID_ADDR result = first_kernel_page_start()
min = 0xFFFF888000000000 if self.paging_level == 4 else 0xFF11000000000000
for page in get_memory_map_raw():
if page.start and page.start >= min:
result = page.start
break
return result return result
@property @property
@ -393,7 +384,7 @@ class Aarch64PagingInfo(ArchPagingInfo):
# this is only used for marking the end of module_start # this is only used for marking the end of module_start
self.module_end = -1 self.module_end = -1
res = None res = None
for page in get_memory_map_raw(): for page in kernel_vmmap_pages():
if page.start >= self.kbase: if page.start >= self.kbase:
break break
if page.execute: if page.execute:
@ -401,7 +392,7 @@ class Aarch64PagingInfo(ArchPagingInfo):
if res is None: if res is None:
return INVALID_ADDR return INVALID_ADDR
prev = None prev = None
for page in get_memory_map_raw(): for page in kernel_vmmap_pages():
if page.start >= res: if page.start >= res:
if prev is not None and page.start > prev + 0x1000: if prev is not None and page.start > prev + 0x1000:
break break

@ -396,7 +396,19 @@ Note that the page-tables method will require the QEMU kernel process to be on t
) )
def kernel_vmmap(process_pages=True) -> Tuple[pwndbg.lib.memory.Page, ...]: @pwndbg.lib.cache.cache_until("stop")
def kernel_vmmap_pages() -> Tuple[pwndbg.lib.memory.Page, ...]:
pages = None
if kernel_vmmap_mode == "page-tables":
pages = kernel_vmmap_via_page_tables()
elif kernel_vmmap_mode == "monitor":
pages = kernel_vmmap_via_monitor_info_mem()
if pages is None:
pages = ()
return pages
def kernel_vmmap() -> Tuple[pwndbg.lib.memory.Page, ...]:
if not pwndbg.aglib.qemu.is_qemu_kernel(): if not pwndbg.aglib.qemu.is_qemu_kernel():
return () return ()
@ -409,23 +421,16 @@ def kernel_vmmap(process_pages=True) -> Tuple[pwndbg.lib.memory.Page, ...]:
): ):
return () return ()
pages = None pages = kernel_vmmap_pages()
if kernel_vmmap_mode == "page-tables": kv = KernelVmmap(pages)
pages = kernel_vmmap_via_page_tables() kv.adjust()
elif kernel_vmmap_mode == "monitor": if kernel_vmmap_mode == "monitor" and pwndbg.aglib.arch.name == "x86-64":
pages = kernel_vmmap_via_monitor_info_mem() # TODO: check version here when QEMU displays the x bit for x64
if pages is None: for page in pages:
return () if page.objfile == kv.pi.ESPSTACK:
if process_pages: continue
kv = KernelVmmap(pages) entry = pwndbg.aglib.kernel.pagewalk(page.start)[0].entry
kv.adjust() if entry and entry >> 63 == 0:
if kernel_vmmap_mode == "monitor" and pwndbg.aglib.arch.name == "x86-64": page.flags |= 1
# TODO: check version here when QEMU displays the x bit for x64
for page in pages:
if page.objfile == kv.pi.ESPSTACK:
continue
entry = pwndbg.aglib.kernel.pagewalk(page.start)[0].entry
if entry and entry >> 63 == 0:
page.flags |= 1
return tuple(pages) return tuple(pages)

Loading…
Cancel
Save