Fix some issues about GDB < 9.x (#1333)

* Fix some issues for GDB < 9.x

* GDB < 9.x doesn't have `gdb.lookup_static_symbol`

* GDB < 9.x doesn't have `gdb.PARAM_ZUINTEGER_UNLIMITED`

* Better error handling for the heap commands

* Inform users to `set exception-* on` when they encounter some error during using some heap commands

* Bug fix for heap region finding of `HeuristicHeap`

* Before this commit, `get_heap_boundaries()` of `HeuristicHeap` will always return the page whose name is `[heap]`, this won't work for multithreaded cases and won't work if the heap region of the main thread is not `[heap]` (e.g., when using QEMU, sometimes the name of heap region is something like: `[anon_deadbeaf]`)

* Fallback to `gdb.lookup_symbol` if we do not have `gdb.lookup_static_symbol`
pull/1353/head
Alan Li 3 years ago committed by GitHub
parent 3b56329acc
commit 41c407036a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -278,10 +278,12 @@ def OnlyWithResolvedHeapSyms(function):
f"You can try to determine the libc symbols addresses manually and set them appropriately. For this, see the `heap_config` command output and set the config about `{err.symbol}`."
)
if (
pwndbg.gdblib.config.exception_verbose.value
or pwndbg.gdblib.config.exception_debugger.value
pwndbg.gdblib.config.exception_verbose
or pwndbg.gdblib.config.exception_debugger
):
raise err
else:
pwndbg.exception.inform_verbose_and_debug()
except Exception as err:
e(f"{function.__name__}: An unknown error occurred when running this command.")
if pwndbg.gdblib.config.resolve_heap_via_heuristic:
@ -295,6 +297,8 @@ def OnlyWithResolvedHeapSyms(function):
or pwndbg.gdblib.config.exception_debugger
):
raise err
else:
pwndbg.exception.inform_verbose_and_debug()
else:
print(message.error(f"{function.__name__}: "), end="")
if not pwndbg.gdblib.config.resolve_heap_via_heuristic:

@ -42,6 +42,16 @@ def inform_report_issue(exception_msg):
)
def inform_verbose_and_debug():
print(
message.notice("For more info invoke `")
+ message.hint("set exception-verbose on")
+ message.notice("` and rerun the command\nor debug it by yourself with `")
+ message.hint("set exception-debugger on")
+ message.notice("`")
)
def handle(name="Error"):
"""Displays an exception to the user, optionally displaying a full traceback
and spawning an interactive post-moretem debugger.
@ -69,13 +79,7 @@ def handle(name="Error"):
print(message.error("Exception occurred: {}: {} ({})".format(name, exc_value, exc_type)))
print(
message.notice("For more info invoke `")
+ message.hint("set exception-verbose on")
+ message.notice("` and rerun the command\nor debug it by yourself with `")
+ message.hint("set exception-debugger on")
+ message.notice("`")
)
inform_verbose_and_debug()
# Break into the interactive debugger
if debug:

@ -243,17 +243,20 @@ def address(symbol: str) -> int:
@pwndbg.lib.memoize.reset_on_objfile
@pwndbg.lib.memoize.reset_on_thread
def static_linkage_symbol_address(symbol):
if isinstance(symbol, int):
return symbol
try:
return int(symbol, 0)
except Exception:
pass
def static_linkage_symbol_address(symbol: str) -> int:
"""
Get the address for static linkage `symbol`
"""
try:
symbol_obj = gdb.lookup_static_symbol(symbol)
if hasattr(gdb, "lookup_static_symbol"):
symbol_obj = gdb.lookup_static_symbol(symbol)
else:
# GDB < 9.x does not have `gdb.lookup_static_symbol`
# We will fallback to `gdb.lookup_symbol` here, but the drawback is that we might find incorrect symbol if there is a symbol with the same name which is not static linkage
# But this is better than just returning None
# TODO/FIXME: Find a way to get the static linkage symbol's address in GDB < 9.x
symbol_obj = gdb.lookup_symbol(symbol)[0]
return int(symbol_obj.value().address) if symbol_obj else None
except gdb.error:
return None

@ -2130,13 +2130,15 @@ class HeuristicHeap(GlibcMemoryAllocator):
"""Find the boundaries of the heap containing `addr`, default to the
boundaries of the heap containing the top chunk for the thread's arena.
"""
region = None
try:
region = self.get_region(addr) if addr else self.get_region(self.get_arena()["top"])
except Exception:
# Although `self.get_arena` should only raise `SymbolUnresolvableError`, we catch all exceptions here to avoid some bugs in main_arena's heuristics break this function :)
pass
# If we can't use arena to find the heap region, we use vmmap to find the heap region
region = next((p for p in pwndbg.gdblib.vmmap.get() if "[heap]" == p.objfile), None)
if region is None and not self.multithreaded:
region = next((p for p in pwndbg.gdblib.vmmap.get() if "[heap]" == p.objfile), None)
if region is not None and addr is not None:
region = None if addr not in region else region

@ -179,7 +179,7 @@ class mock_for_heuristic:
mock_symbols # every symbol's address in the list will be mocked to `None`
)
self.mock_all = mock_all # all symbols will be mocked to `None`
# Save `pwndbg.gdblib.symbol.address` and `pwndbg.gdblib.symbol.addresses` before mocking
# Save `pwndbg.gdblib.symbol.address` and `pwndbg.gdblib.symbol.static_linkage_symbol_address` before mocking
self.saved_address_func = pwndbg.gdblib.symbol.address
self.saved_static_linkage_symbol_address_func = (
pwndbg.gdblib.symbol.static_linkage_symbol_address
@ -203,7 +203,7 @@ class mock_for_heuristic:
return _mock
# Mock `pwndbg.gdblib.symbol.address` and `pwndbg.gdblib.symbol.addresses`
# Mock `pwndbg.gdblib.symbol.address` and `pwndbg.gdblib.symbol.static_linkage_symbol_address`
pwndbg.gdblib.symbol.address = mock(pwndbg.gdblib.symbol.address)
pwndbg.gdblib.symbol.static_linkage_symbol_address = mock(
pwndbg.gdblib.symbol.static_linkage_symbol_address
@ -213,7 +213,7 @@ class mock_for_heuristic:
pwndbg.gdblib.memory.write(self.page.vaddr, b"\xff" * self.page.memsz)
def __exit__(self, exc_type, exc_value, traceback):
# Restore `pwndbg.gdblib.symbol.address` and `pwndbg.gdblib.symbol.addresses`
# Restore `pwndbg.gdblib.symbol.address` and `pwndbg.gdblib.symbol.static_linkage_symbol_address`
pwndbg.gdblib.symbol.address = self.saved_address_func
pwndbg.gdblib.symbol.static_linkage_symbol_address = (
self.saved_static_linkage_symbol_address_func

@ -14,7 +14,10 @@ import pwndbg.gdblib.config
("auto-bool", None, "auto", {"param_class": gdb.PARAM_AUTO_BOOLEAN}),
("unlimited-uint", 0, "unlimited", {"param_class": gdb.PARAM_UINTEGER}),
("unlimited-int", 0, "unlimited", {"param_class": gdb.PARAM_INTEGER}),
("unlimited-zuint", -1, "unlimited", {"param_class": gdb.PARAM_ZUINTEGER_UNLIMITED}),
# GDB < 9.x does not support PARAM_ZUINTEGER_UNLIMITED
("unlimited-zuint", -1, "unlimited", {"param_class": gdb.PARAM_ZUINTEGER_UNLIMITED})
if hasattr(gdb, "PARAM_ZUINTEGER_UNLIMITED")
else (),
(
"enum",
"enum1",
@ -24,6 +27,9 @@ import pwndbg.gdblib.config
),
)
def test_gdb_parameter_default_value_works(start_binary, params):
if not params:
pytest.skip("Current GDB version does not support this testcase")
name_suffix, default_value, displayed_value, optional_kwargs = params
param_name = f"test-param-{name_suffix}"

Loading…
Cancel
Save