Slightly improving `buddydump` + deprecating `pcplist` (#3015)

* fixed buddydump behaviours and made test more comprehensive

* handling new name

* changing to tuple instead

* added comment to test
pull/3029/head
jxuanli 7 months ago committed by GitHub
parent 09c8ac6bc6
commit ed8c187691
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -122,7 +122,7 @@ def check_find(counter: int, physmap_addr: int, pba: ParsedBuddyArgs, cbp: Curre
if pba.find is None:
return False
start = physmap_addr
end = physmap_addr + (1 << cbp.order)
end = physmap_addr + 0x1000 * (1 << cbp.order)
return pba.find >= start and pba.find < end
@ -343,5 +343,5 @@ def buddydump(
print_pcp_set(pba, cbp)
if not pcp_only:
print_free_area(pba, cbp)
if not cbp.found:
log.warning("No free pages with specified filters found.")
if not cbp.found:
log.warning("No free pages with specified filters found.")

@ -1431,6 +1431,11 @@ class GDB(pwndbg.dbg_mod.Debugger):
f"alias -a {deprecated_cmd} = echo Use `{fixed_cmd}` instead (Pwndbg changed `_` to `-` in command names)\\n"
)
for deprecated_cmd, new_cmd in (("pcplist", "buddydump"),):
gdb.execute(
f"alias -a {deprecated_cmd} = echo deprecation warning for old name, use `{new_cmd}` instead\\n"
)
# This may throw an exception, see pwndbg/pwndbg#27
try:
gdb.execute("set disassembly-flavor intel")

@ -1,5 +1,8 @@
from __future__ import annotations
import random
import re
import gdb
import pytest
@ -90,8 +93,6 @@ def test_x64_extra_registers_under_kernel_mode():
def get_slab_object_address():
"""helper function to get the address of some kmalloc slab object
and the associated slab cache name"""
import re
caches = pwndbg.aglib.kernel.slab.caches()
for cache in caches:
cache_name = cache.name
@ -135,6 +136,42 @@ def test_command_msr_write():
)
def test_command_buddydump():
res = gdb.execute("buddydump", to_string=True)
assert (
"Order" in res and "Zone" in res and ("per_cpu_pageset" in res or "free_area" in res)
) or res == "WARNING: Symbol 'node_data' not found\n"
NOFREEPAGE = "No free pages with specified filters found.\n"
if res == "WARNING: Symbol 'node_data' not found\n" or NOFREEPAGE == res:
return
# this indicates the buddy allocator contains at least one entry
assert "Order" in res and "Zone" in res and ("per_cpu_pageset" in res or "free_area" in res)
ansi_escape = re.compile(r"\x1b\[[0-9;]*m")
res = ansi_escape.sub("", res)
# find the starting addresses of all entries within the freelists
matches = re.findall(r"\[0x[0-9a-fA-F\-]{2}\] (0x[0-9a-fA-F]{16})", res)
for i in range(0, len(matches), 20):
# check every 20 elements so tests do not take too long
match = int(matches[i], 16)
res = gdb.execute(f"bud -f {hex(match + random.randint(0, 0x1000 - 1))}", to_string=True)
res = ansi_escape.sub("", res)
_matches = re.findall(r"\[0x[0-9a-fA-F\-]{2}\] (0x[0-9a-fA-F]{16})", res)
# asserting `bud -f` behaviour -- should be able to find the corresponding entry to an address
# even if the address is not aligned
assert len(_matches) == 1 and int(_matches[0], 16) == match
# nonexistent node index should not contain any entries
no_output = gdb.execute("buddydump -n 10", to_string=True)
assert NOFREEPAGE == no_output
# below checks are for filters
# for example, if a zone name is specified, other zones should not be present
filter_res = gdb.execute("bud -z DMA", to_string=True)
for name in ["DMA32", "Normal", "HighMem", "Movable", "Device"]:
assert f"Zone {name}" not in filter_res
filter_res = gdb.execute("bud -m Unmovable", to_string=True)
for name in ["Movable", "Reclaimable", "HighAtomic", "CMA", "Isolate"]:
assert f"- {name}" not in filter_res
filter_res = gdb.execute("bud -o 1", to_string=True)
for i in range(11):
if i == 1:
continue
assert f"Order {i}" not in filter_res
filter_res = gdb.execute("bud -p", to_string=True)
assert "free_area" not in filter_res

Loading…
Cancel
Save