Move symbol.py to gdblib (#1259)

* Move symbol.py to gdblib

* Renamed private methods

* Renamed pwndbg.symbol to pwndbg.gdblib.symbol

* Cleanup symbol.py

* Fix lint issues

* Handle tls error on symbol lookup

* Fix merge conflicts

* Remove old way of looking up symbols
pull/1267/head
Gulshan Singh 3 years ago committed by GitHub
parent ec8addd602
commit bfbb2b8652
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,5 +1,5 @@
:mod:`pwndbg.symbol` --- pwndbg.symbol
:mod:`pwndbg.gdblib.symbol` --- pwndbg.gdblib.symbol
=============================================
.. automodule:: pwndbg.symbol
.. automodule:: pwndbg.gdblib.symbol
:members:

@ -13,12 +13,12 @@ import pwndbg.disasm
import pwndbg.gdblib.arch
import pwndbg.gdblib.memory
import pwndbg.gdblib.regs
import pwndbg.gdblib.symbol
import pwndbg.gdblib.typeinfo
import pwndbg.ida
import pwndbg.lib.abi
import pwndbg.lib.funcparser
import pwndbg.lib.functions
import pwndbg.symbol
ida_replacements = {
"__int64": "signed long long int",
@ -94,7 +94,7 @@ def get(instruction):
if not target:
return []
name = pwndbg.symbol.get(target)
name = pwndbg.gdblib.symbol.get(target)
if not name:
return []
elif CS_GRP_INT in instruction.groups:

@ -6,8 +6,8 @@ import pwndbg.color.theme as theme
import pwndbg.enhance
import pwndbg.gdblib.abi
import pwndbg.gdblib.memory
import pwndbg.gdblib.symbol
import pwndbg.gdblib.typeinfo
import pwndbg.symbol
import pwndbg.vmmap
LIMIT = pwndbg.config.Parameter(
@ -108,7 +108,7 @@ def format(value, limit=LIMIT, code=True, offset=0, hard_stop=None, hard_end=0,
# Colorize the chain
rest = []
for link in chain:
symbol = pwndbg.symbol.get(link) or None
symbol = pwndbg.gdblib.symbol.get(link) or None
if symbol:
symbol = "%#x (%s)" % (link, symbol)
rest.append(M.get(link, symbol))

@ -38,7 +38,7 @@ def instruction(ins):
# tl;dr is a branch?
if ins.target not in (None, ins.address + ins.size):
sym = pwndbg.symbol.get(ins.target) or None
sym = pwndbg.gdblib.symbol.get(ins.target) or None
target = M.get(ins.target)
const = ins.target_const
hextarget = hex(ins.target)

@ -14,8 +14,8 @@ import pwndbg.enhance
import pwndbg.exception
import pwndbg.gdblib.memory
import pwndbg.gdblib.regs
import pwndbg.gdblib.symbol
import pwndbg.hexdump
import pwndbg.symbol
import pwndbg.ui
from pwndbg.heap.ptmalloc import SymbolUnresolvableError

@ -22,9 +22,9 @@ import pwndbg.config
import pwndbg.disasm
import pwndbg.gdblib.events
import pwndbg.gdblib.regs
import pwndbg.gdblib.symbol
import pwndbg.ghidra
import pwndbg.ida
import pwndbg.symbol
import pwndbg.ui
import pwndbg.vmmap
from pwndbg.color import message
@ -321,7 +321,7 @@ def context_ghidra(target=sys.stdout, with_banner=True, width=None):
return []
if config_context_ghidra == "if-no-source":
source_filename = pwndbg.symbol.selected_frame_source_absolute_filename()
source_filename = pwndbg.gdblib.symbol.selected_frame_source_absolute_filename()
if source_filename and os.path.exists(source_filename):
return []
@ -768,7 +768,7 @@ def context_backtrace(with_banner=True, target=sys.stdout, width=None):
prefix = bt_prefix if frame == this_frame else " " * len(bt_prefix)
prefix = " %s" % B.prefix(prefix)
addrsz = B.address(pwndbg.ui.addrsz(frame.pc()))
symbol = B.symbol(pwndbg.symbol.get(frame.pc()))
symbol = B.symbol(pwndbg.gdblib.symbol.get(frame.pc()))
if symbol:
addrsz = addrsz + " " + symbol
line = map(str, (prefix, B.frame_label("%s%i" % (backtrace_frame_label, i)), addrsz))

@ -77,7 +77,7 @@ def get_symbols_in_region(start, end, filter_text=""):
ptr_size = pwndbg.gdblib.typeinfo.pvoid.sizeof
addr = start
while addr < end:
name = pwndbg.symbol.get(addr)
name = pwndbg.gdblib.symbol.get(addr)
if name != "" and "+" not in name and filter_text in name:
symbols.append((name, addr))
addr += ptr_size

@ -791,7 +791,7 @@ def try_free(addr):
addr = int(addr)
# check hook
free_hook = pwndbg.symbol.address("__free_hook")
free_hook = pwndbg.gdblib.symbol.address("__free_hook")
if free_hook is not None:
if pwndbg.gdblib.memory.pvoid(free_hook) != 0:
print(message.success("__libc_free: will execute __free_hook"))

@ -6,7 +6,7 @@ import gdb
import pwndbg.auxv
import pwndbg.commands
import pwndbg.gdblib.regs
import pwndbg.symbol
import pwndbg.gdblib.symbol
errno.errorcode[0] = "OK" # type: ignore # manually add error code 0 for "OK"
@ -37,7 +37,7 @@ def errno_(err):
# We can't simply call __errno_location because its .plt.got entry may be uninitialized
# (e.g. if the binary was just started with `starti` command)
# So we have to check the got.plt entry first before calling it
errno_loc_gotplt = pwndbg.symbol.address("__errno_location@got.plt")
errno_loc_gotplt = pwndbg.gdblib.symbol.address("__errno_location@got.plt")
# If the got.plt entry is not there (is None), it means the symbol is not used by the binary
if errno_loc_gotplt is None or pwndbg.vmmap.find(

@ -14,9 +14,9 @@ import pwndbg.config
import pwndbg.disasm
import pwndbg.gdblib.regs
import pwndbg.gdblib.strings
import pwndbg.gdblib.symbol
import pwndbg.ida
import pwndbg.lib.functions
import pwndbg.symbol
import pwndbg.ui
import pwndbg.vmmap
from pwndbg.color import message
@ -123,7 +123,7 @@ def nearpc(pc=None, lines=None, to_string=False, emulate=False):
pwndbg.vmmap.find(pc)
# Gather all addresses and symbols for each instruction
symbols = [pwndbg.symbol.get(i.address) for i in instructions]
symbols = [pwndbg.gdblib.symbol.get(i.address) for i in instructions]
addresses = ["%#x" % i.address for i in instructions]
nearpc.next_pc = instructions[-1].address + instructions[-1].size if instructions else 0

@ -151,7 +151,7 @@ def probeleak(address=None, count=0x40, max_distance=0x0, point_to=None, max_ptr
p_text = "0x%0*x" % (int(ptrsize * 2), p)
text = "%s: %s = %s" % (offset_text, M.get(p, text=p_text), M.get(p, text=right_text))
symbol = pwndbg.symbol.get(p)
symbol = pwndbg.gdblib.symbol.get(p)
if symbol:
text += " (%s)" % symbol
print(text)

@ -11,7 +11,7 @@ import gdb
import pwndbg.commands
import pwndbg.gdblib.elf
import pwndbg.gdblib.events
import pwndbg.symbol
import pwndbg.gdblib.symbol
break_on_first_instruction = False
@ -61,7 +61,7 @@ def start(args=None):
symbols = ["main", "_main", "start", "_start", "init", "_init"]
for symbol in symbols:
address = pwndbg.symbol.address(symbol, allow_unmapped=True)
address = pwndbg.gdblib.symbol.address(symbol)
if not address:
continue

@ -13,8 +13,8 @@ import pwndbg.commands
import pwndbg.gdblib.arch
import pwndbg.gdblib.memory
import pwndbg.gdblib.strings
import pwndbg.gdblib.symbol
import pwndbg.gdblib.typeinfo
import pwndbg.symbol
def get_type(size):
@ -511,7 +511,7 @@ def ln(value=None):
if value is None:
value = pwndbg.gdblib.regs.pc
value = int(value)
x = pwndbg.symbol.get(value)
x = pwndbg.gdblib.symbol.get(value)
if x:
result = "(%#x) %s" % (value, x)
print(result)

@ -12,9 +12,9 @@ from capstone import * # noqa: F403
import pwndbg.disasm.arch
import pwndbg.gdblib.arch
import pwndbg.gdblib.memory
import pwndbg.gdblib.symbol
import pwndbg.ida
import pwndbg.lib.memoize
import pwndbg.symbol
try:
import pwndbg.emu.emulator

@ -1,8 +1,8 @@
import gdb
from capstone import * # noqa: F403
import pwndbg.gdblib.symbol
import pwndbg.lib.memoize
import pwndbg.symbol
debug = False
@ -197,7 +197,7 @@ class DisassemblyAssistant:
op.str = self.op_names.get(op.type, lambda *a: None)(instruction, op)
if op.int:
op.symbol = pwndbg.symbol.get(op.int)
op.symbol = pwndbg.gdblib.symbol.get(op.int)
def immediate(self, instruction, operand):
return operand.value.imm

@ -16,9 +16,9 @@ import pwndbg.disasm
import pwndbg.gdblib.arch
import pwndbg.gdblib.memory
import pwndbg.gdblib.strings
import pwndbg.gdblib.symbol
import pwndbg.gdblib.typeinfo
import pwndbg.lib.memoize
import pwndbg.symbol
from pwndbg.color.syntax_highlight import syntax_highlight
bad_instrs = [".byte", ".long", "rex.R", "rex.XB", ".inst", "(bad)"]
@ -59,7 +59,7 @@ def enhance(value, code=True, safe_linking=False):
"""
value = int(value)
name = pwndbg.symbol.get(value) or None
name = pwndbg.gdblib.symbol.get(value) or None
page = pwndbg.vmmap.find(value)
# If it's not in a page we know about, try to dereference

@ -23,4 +23,5 @@ def load_gdblib():
import pwndbg.gdblib.memory
import pwndbg.gdblib.prompt
import pwndbg.gdblib.regs
import pwndbg.gdblib.symbol
import pwndbg.gdblib.typeinfo

@ -208,7 +208,7 @@ def entry():
# Try common names
for name in ["_start", "start", "__start", "main"]:
try:
return pwndbg.symbol.address(name)
return pwndbg.gdblib.symbol.address(name)
except gdb.error:
pass

@ -28,7 +28,7 @@ import pwndbg.lib.memoize
import pwndbg.vmmap
def get_directory():
def _get_debug_file_directory():
"""
Retrieve the debug file directory path.
@ -46,29 +46,33 @@ def get_directory():
return ""
def set_directory(d):
def _set_debug_file_directory(d):
gdb.execute("set debug-file-directory %s" % d, to_string=True, from_tty=False)
def add_directory(d):
current = get_directory()
def _add_debug_file_directory(d):
current = _get_debug_file_directory()
if current:
set_directory("%s:%s" % (current, d))
_set_debug_file_directory("%s:%s" % (current, d))
else:
set_directory(d)
_set_debug_file_directory(d)
remote_files = {}
if "/usr/lib/debug" not in _get_debug_file_directory():
_add_debug_file_directory("/usr/lib/debug")
_remote_files = {}
@pwndbg.gdblib.events.exit
def reset_remote_files():
global remote_files
remote_files = {}
def _reset_remote_files():
global _remote_files
_remote_files = {}
@pwndbg.gdblib.events.new_objfile
def autofetch():
def _autofetch():
""" """
if not pwndbg.gdblib.remote.is_remote():
return
@ -80,8 +84,8 @@ def autofetch():
return
remote_files_dir = pwndbg.gdblib.file.remote_files_dir()
if remote_files_dir not in get_directory().split(":"):
add_directory(remote_files_dir)
if remote_files_dir not in _get_debug_file_directory().split(":"):
_add_debug_file_directory(remote_files_dir)
for mapping in pwndbg.vmmap.get():
objfile = mapping.objfile
@ -91,7 +95,7 @@ def autofetch():
continue
# Don't re-download things that we have already downloaded
if not objfile or objfile in remote_files:
if not objfile or objfile in _remote_files:
continue
msg = "Downloading %r from the remote server" % objfile
@ -111,7 +115,7 @@ def autofetch():
with open(local_path, "wb+") as f:
f.write(data)
remote_files[objfile] = local_path
_remote_files[objfile] = local_path
base = None
for mapping in pwndbg.vmmap.get():
@ -144,9 +148,9 @@ def autofetch():
@pwndbg.lib.memoize.reset_on_objfile
def get(address, gdb_only=False):
def get(address: int, gdb_only=False) -> str:
"""
Retrieve the textual name for a symbol
Retrieve the name for the symbol located at `address`
"""
# Fast path
if address < pwndbg.gdblib.memory.MMAP_MIN_ADDR or address >= ((1 << 64) - 1):
@ -184,40 +188,36 @@ def get(address, gdb_only=False):
@pwndbg.lib.memoize.reset_on_objfile
def address(symbol, allow_unmapped=False):
if isinstance(symbol, int):
return symbol
try:
return int(symbol, 0)
except Exception:
pass
def address(symbol: str) -> int:
"""
Get the address for `symbol`
"""
try:
symbol_obj = gdb.lookup_symbol(symbol)[0]
if symbol_obj:
return int(symbol_obj.value().address)
except Exception:
pass
try:
result = gdb.execute("info address %s" % symbol, to_string=True, from_tty=False)
address = int(re.search("0x[0-9a-fA-F]+", result).group(), 0)
# The address found should lie in one of the memory maps
# There are cases when GDB shows offsets e.g.:
# pwndbg> info address tcache
# Symbol "tcache" is a thread-local variable at offset 0x40
# in the thread-local storage for `/lib/x86_64-linux-gnu/libc.so.6'.
if not allow_unmapped and not pwndbg.vmmap.find(address):
return None
return address
except gdb.error:
return None
except gdb.error as e:
# Symbol lookup only throws exceptions on errors, not if it failed to
# lookup a symbol. We want to raise these errors so we can handle them
# properly, but there are some we haven't figured out how to fix yet, so
# we ignore those here
skipped_exceptions = []
# This is exception is being thrown by the Go typeinfo tests, we should
# investigate why this is happening and see if we can explicitly check
# for it with `gdb.selected_frame()`
skipped_exceptions.append("No frame selected")
# If we try to look up a TLS variable when there is no TLS, this
# exception occurs. Ideally we should come up with a way to check for
# this case before calling `gdb.lookup_symbol`
skipped_exceptions.append("Cannot find thread-local variables")
if all(x not in str(e) for x in skipped_exceptions):
raise e
try:
# TODO: We should properly check if we have a connection to the IDA server first
address = pwndbg.ida.LocByName(symbol)
if address:
return address
@ -244,7 +244,7 @@ def static_linkage_symbol_address(symbol):
@pwndbg.gdblib.events.stop
@pwndbg.lib.memoize.reset_on_start
def add_main_exe_to_symbols():
def _add_main_exe_to_symbols():
if not pwndbg.gdblib.remote.is_remote():
return
@ -300,7 +300,3 @@ def selected_frame_source_absolute_filename():
return None
return symtab.fullname()
if "/usr/lib/debug" not in get_directory():
set_directory(get_directory() + ":/usr/lib/debug")

@ -10,7 +10,7 @@ import pwndbg.disasm
import pwndbg.gdblib.arch
import pwndbg.gdblib.memory
import pwndbg.gdblib.regs
import pwndbg.symbol
import pwndbg.gdblib.symbol
import pwndbg.vmmap
@ -39,7 +39,7 @@ class module(ModuleType):
if not self._errno_offset:
__errno_location_instr = pwndbg.disasm.near(
pwndbg.symbol.address("__errno_location"), 5, show_prev_insns=False
pwndbg.gdblib.symbol.address("__errno_location"), 5, show_prev_insns=False
)
if pwndbg.gdblib.arch.current == "x86-64":
for instr in __errno_location_instr:

@ -66,7 +66,7 @@ def decompile(func=None):
if pwndbg.config.syntax_highlight:
# highlighting depends on the file extension to guess the language, so try to get one...
src_filename = pwndbg.symbol.selected_frame_source_absolute_filename()
src_filename = pwndbg.gdblib.symbol.selected_frame_source_absolute_filename()
if not src_filename:
filename = gdb.current_progspace().filename
src_filename = filename + ".c" if os.path.basename(filename).find(".") < 0 else filename

@ -10,10 +10,10 @@ import gdb
import pwndbg.config
import pwndbg.gdblib.memory
import pwndbg.gdblib.proc
import pwndbg.gdblib.symbol
import pwndbg.heap
import pwndbg.lib.memoize
import pwndbg.search
import pwndbg.symbol
safe_lnk = pwndbg.config.Parameter(
"safe-linking", "auto", "whether glibc use safe-linking (on/off/auto)"
@ -41,7 +41,7 @@ def get_version():
@pwndbg.lib.memoize.reset_on_objfile
def _get_version():
if pwndbg.heap.current.libc_has_debug_syms():
addr = pwndbg.symbol.address(b"__libc_version")
addr = pwndbg.gdblib.symbol.address("__libc_version")
if addr is not None:
ver = pwndbg.gdblib.memory.string(addr)
return tuple([int(_) for _ in ver.split(b".")])

@ -1,7 +1,7 @@
import pwndbg.color.message as message
import pwndbg.config
import pwndbg.gdblib.symbol
import pwndbg.heap.heap
import pwndbg.symbol
current = None

@ -7,11 +7,11 @@ import pwndbg.color.memory as M
import pwndbg.config
import pwndbg.disasm
import pwndbg.gdblib.events
import pwndbg.gdblib.symbol
import pwndbg.gdblib.tls
import pwndbg.gdblib.typeinfo
import pwndbg.glibc
import pwndbg.search
import pwndbg.symbol
import pwndbg.vmmap
from pwndbg.color import message
from pwndbg.constants import ptmalloc
@ -377,7 +377,7 @@ class Heap(pwndbg.heap.heap.BaseHeap):
@pwndbg.lib.memoize.reset_on_objfile
def multithreaded(self):
"""Is malloc operating within a multithreaded environment."""
addr = pwndbg.symbol.address("__libc_multiple_threads")
addr = pwndbg.gdblib.symbol.address("__libc_multiple_threads")
if addr:
return pwndbg.gdblib.memory.s32(addr) > 0
return len(gdb.execute("info threads", to_string=True).split("\n")) > 3
@ -697,7 +697,7 @@ class Heap(pwndbg.heap.heap.BaseHeap):
The `struct malloc_chunk` comes from debugging symbols and it will not be there
for statically linked binaries
"""
return pwndbg.gdblib.typeinfo.load("struct malloc_chunk") and pwndbg.symbol.address(
return pwndbg.gdblib.typeinfo.load("struct malloc_chunk") and pwndbg.gdblib.symbol.address(
"global_max_fast"
)
@ -707,9 +707,9 @@ class DebugSymsHeap(Heap):
@property
def main_arena(self):
self._main_arena_addr = pwndbg.symbol.static_linkage_symbol_address(
self._main_arena_addr = pwndbg.gdblib.symbol.static_linkage_symbol_address(
"main_arena"
) or pwndbg.symbol.address("main_arena")
) or pwndbg.gdblib.symbol.address("main_arena")
if self._main_arena_addr is not None:
self._main_arena = pwndbg.gdblib.memory.poi(self.malloc_state, self._main_arena_addr)
@ -727,8 +727,8 @@ class DebugSymsHeap(Heap):
tcache = self.mp["sbrk_base"] + 0x10
if self.multithreaded:
tcache_addr = pwndbg.gdblib.memory.pvoid(
pwndbg.symbol.static_linkage_symbol_address("tcache")
or pwndbg.symbol.address("tcache")
pwndbg.gdblib.symbol.static_linkage_symbol_address("tcache")
or pwndbg.gdblib.symbol.address("tcache")
)
if tcache_addr != 0:
tcache = tcache_addr
@ -752,9 +752,9 @@ class DebugSymsHeap(Heap):
@property
def mp(self):
self._mp_addr = pwndbg.symbol.static_linkage_symbol_address("mp_") or pwndbg.symbol.address(
self._mp_addr = pwndbg.gdblib.symbol.static_linkage_symbol_address(
"mp_"
)
) or pwndbg.gdblib.symbol.address("mp_")
if self._mp_addr is not None:
self._mp = pwndbg.gdblib.memory.poi(self.malloc_par, self._mp_addr)
@ -762,9 +762,9 @@ class DebugSymsHeap(Heap):
@property
def global_max_fast(self):
self._global_max_fast_addr = pwndbg.symbol.static_linkage_symbol_address(
self._global_max_fast_addr = pwndbg.gdblib.symbol.static_linkage_symbol_address(
"global_max_fast"
) or pwndbg.symbol.address("global_max_fast")
) or pwndbg.gdblib.symbol.address("global_max_fast")
if self._global_max_fast_addr is not None:
self._global_max_fast = pwndbg.gdblib.memory.u(self._global_max_fast_addr)
@ -823,8 +823,8 @@ class DebugSymsHeap(Heap):
if arena_addr is None:
if self.multithreaded:
arena_addr = pwndbg.gdblib.memory.u(
pwndbg.symbol.static_linkage_symbol_address("thread_arena")
or pwndbg.symbol.address("thread_arena")
pwndbg.gdblib.symbol.static_linkage_symbol_address("thread_arena")
or pwndbg.gdblib.symbol.address("thread_arena")
)
if arena_addr > 0:
return pwndbg.gdblib.memory.poi(self.malloc_state, arena_addr)
@ -862,9 +862,9 @@ class DebugSymsHeap(Heap):
return region
def is_initialized(self):
addr = pwndbg.symbol.address("__libc_malloc_initialized")
addr = pwndbg.gdblib.symbol.address("__libc_malloc_initialized")
if addr is None:
addr = pwndbg.symbol.address("__malloc_initialized")
addr = pwndbg.gdblib.symbol.address("__malloc_initialized")
return pwndbg.gdblib.memory.s32(addr) > 0
@ -902,9 +902,9 @@ class HeuristicHeap(Heap):
self._possible_page_of_symbols = pwndbg.vmmap.find(
pwndbg.glibc.get_got_plt_address()
)
elif pwndbg.symbol.address("_IO_list_all"):
elif pwndbg.gdblib.symbol.address("_IO_list_all"):
self._possible_page_of_symbols = pwndbg.vmmap.find(
pwndbg.symbol.address("_IO_list_all")
pwndbg.gdblib.symbol.address("_IO_list_all")
)
return self._possible_page_of_symbols
@ -913,10 +913,10 @@ class HeuristicHeap(Heap):
def is_glibc_symbol(self, addr):
# If addr is in the same region as `_IO_list_all` and its address is greater than it, we trust it is a symbol of glibc.
# Note: We should only use this when we can not find the symbol via `pwndbg.symbol.static_linkage_symbol_address()`.
# Note: We should only use this when we can not find the symbol via `pwndbg.gdblib.symbol.static_linkage_symbol_address()`.
if addr is None:
return False
_IO_list_all_addr = pwndbg.symbol.address("_IO_list_all")
_IO_list_all_addr = pwndbg.gdblib.symbol.address("_IO_list_all")
if _IO_list_all_addr:
return addr in pwndbg.vmmap.find(_IO_list_all_addr) and addr > _IO_list_all_addr
# We trust that symbol is from GLIBC :)
@ -925,23 +925,23 @@ class HeuristicHeap(Heap):
@property
def main_arena(self):
main_arena_via_config = int(str(pwndbg.config.main_arena), 0)
main_arena_via_symbol = pwndbg.symbol.static_linkage_symbol_address(
main_arena_via_symbol = pwndbg.gdblib.symbol.static_linkage_symbol_address(
"main_arena"
) or pwndbg.symbol.address("main_arena")
) or pwndbg.gdblib.symbol.address("main_arena")
if main_arena_via_config > 0:
self._main_arena_addr = main_arena_via_config
elif pwndbg.symbol.static_linkage_symbol_address("main_arena") or self.is_glibc_symbol(
main_arena_via_symbol
):
elif pwndbg.gdblib.symbol.static_linkage_symbol_address(
"main_arena"
) or self.is_glibc_symbol(main_arena_via_symbol):
self._main_arena_addr = main_arena_via_symbol
# TODO/FIXME: These are quite dirty, we should find a better way to do this
if not self._main_arena_addr:
if (
pwndbg.glibc.get_version() < (2, 34)
and pwndbg.gdblib.arch.current != "arm"
and pwndbg.symbol.address("__malloc_hook")
and pwndbg.gdblib.symbol.address("__malloc_hook")
):
malloc_hook_addr = pwndbg.symbol.address("__malloc_hook")
malloc_hook_addr = pwndbg.gdblib.symbol.address("__malloc_hook")
# Credit: This tricks is modified from
# https://github.com/hugsy/gef/blob/c530aa518ac96dff6fc810a5552ecf54fd1b3581/gef.py#L1189-L1196
# Thank @_hugsy_ and all the contributors of gef! (But somehow, gef's strategy for arm doesn't seem
@ -955,10 +955,10 @@ class HeuristicHeap(Heap):
malloc_hook_addr - pwndbg.gdblib.arch.ptrsize * 2 - self.malloc_state.sizeof
)
# If we can not find the main_arena via offset trick, we try to find its reference in malloc_trim
elif pwndbg.symbol.address("malloc_trim"):
elif pwndbg.gdblib.symbol.address("malloc_trim"):
# try to find `mstate ar_ptr = &main_arena;` in malloc_trim instructions
malloc_trim_instructions = pwndbg.disasm.near(
pwndbg.symbol.address("malloc_trim"), 10, show_prev_insns=False
pwndbg.gdblib.symbol.address("malloc_trim"), 10, show_prev_insns=False
)
if pwndbg.gdblib.arch.current == "x86-64":
for instr in malloc_trim_instructions:
@ -1003,8 +1003,8 @@ class HeuristicHeap(Heap):
# Try to search main_arena in .data of libc if we can't find it via above trick
if not self._main_arena_addr or pwndbg.vmmap.find(self._main_arena_addr) is None:
start = pwndbg.symbol.address("_IO_2_1_stdin_")
end = pwndbg.symbol.address("_IO_list_all")
start = pwndbg.gdblib.symbol.address("_IO_2_1_stdin_")
end = pwndbg.gdblib.symbol.address("_IO_list_all")
# If we didn't have these symbols, we try to find them in the possible page
if self.possible_page_of_symbols:
start = start or self.possible_page_of_symbols.vaddr
@ -1013,7 +1013,7 @@ class HeuristicHeap(Heap):
end -= self.malloc_state.sizeof
while start < end:
start += pwndbg.gdblib.arch.ptrsize
if not pwndbg.symbol.get(start).startswith("_IO"):
if not pwndbg.gdblib.symbol.get(start).startswith("_IO"):
break
# main_arena is between _IO_2_1_stdin and _IO_list_all
for addr in range(start, end, pwndbg.gdblib.arch.ptrsize):
@ -1052,13 +1052,13 @@ class HeuristicHeap(Heap):
@property
def thread_arena(self):
thread_arena_via_config = int(str(pwndbg.config.thread_arena), 0)
thread_arena_via_symbol = pwndbg.symbol.static_linkage_symbol_address(
thread_arena_via_symbol = pwndbg.gdblib.symbol.static_linkage_symbol_address(
"thread_arena"
) or pwndbg.symbol.address("thread_arena")
) or pwndbg.gdblib.symbol.address("thread_arena")
if thread_arena_via_config > 0:
return thread_arena_via_config
elif thread_arena_via_symbol:
if pwndbg.symbol.static_linkage_symbol_address("thread_arena"):
if pwndbg.gdblib.symbol.static_linkage_symbol_address("thread_arena"):
# If the symbol is static-linkage symbol, we trust it.
return pwndbg.gdblib.memory.u(thread_arena_via_symbol)
# Check &thread_arena is nearby TLS base or not to avoid false positive.
@ -1079,10 +1079,10 @@ class HeuristicHeap(Heap):
if pwndbg.vmmap.find(thread_arena_struct_addr):
return thread_arena_struct_addr
if not self._thread_arena_offset and pwndbg.symbol.address("__libc_calloc"):
if not self._thread_arena_offset and pwndbg.gdblib.symbol.address("__libc_calloc"):
# TODO/FIXME: This method should be updated if we find a better way to find the target assembly code
__libc_calloc_instruction = pwndbg.disasm.near(
pwndbg.symbol.address("__libc_calloc"), 100, show_prev_insns=False
pwndbg.gdblib.symbol.address("__libc_calloc"), 100, show_prev_insns=False
)
# try to find the reference to thread_arena in arena_get in __libc_calloc ( ptr = thread_arena; )
if pwndbg.gdblib.arch.current == "x86-64":
@ -1212,14 +1212,14 @@ class HeuristicHeap(Heap):
and if that fails, we guess it's at the first chunk of the heap.
"""
thread_cache_via_config = int(str(pwndbg.config.tcache), 0)
thread_cache_via_symbol = pwndbg.symbol.static_linkage_symbol_address(
thread_cache_via_symbol = pwndbg.gdblib.symbol.static_linkage_symbol_address(
"tcache"
) or pwndbg.symbol.address("tcache")
) or pwndbg.gdblib.symbol.address("tcache")
if thread_cache_via_config > 0:
self._thread_cache = self.tcache_perthread_struct(thread_cache_via_config)
return self._thread_cache
elif thread_cache_via_symbol:
if pwndbg.symbol.static_linkage_symbol_address("tcache"):
if pwndbg.gdblib.symbol.static_linkage_symbol_address("tcache"):
# If the symbol is static-linkage symbol, we trust it.
thread_cache_struct_addr = pwndbg.gdblib.memory.u(thread_cache_via_symbol)
self._thread_cache = self.tcache_perthread_struct(thread_cache_struct_addr)
@ -1247,10 +1247,10 @@ class HeuristicHeap(Heap):
# Each thread has a tcache struct, and the address of the tcache struct is stored in the TLS.
# Try to find tcache in TLS, so first we need to find the offset of tcache to TLS base
if not self._thread_cache_offset and pwndbg.symbol.address("__libc_malloc"):
if not self._thread_cache_offset and pwndbg.gdblib.symbol.address("__libc_malloc"):
# TODO/FIXME: This method should be updated if we find a better way to find the target assembly code
__libc_malloc_instruction = pwndbg.disasm.near(
pwndbg.symbol.address("__libc_malloc"), 100, show_prev_insns=False
pwndbg.gdblib.symbol.address("__libc_malloc"), 100, show_prev_insns=False
)[10:]
# Try to find the reference to tcache in __libc_malloc, the target C code is like this:
# `if (tc_idx < mp_.tcache_bins && tcache && ......`
@ -1447,20 +1447,20 @@ class HeuristicHeap(Heap):
@property
def mp(self):
mp_via_config = int(str(pwndbg.config.mp_), 0)
mp_via_symbol = pwndbg.symbol.static_linkage_symbol_address("mp_") or pwndbg.symbol.address(
mp_via_symbol = pwndbg.gdblib.symbol.static_linkage_symbol_address(
"mp_"
)
) or pwndbg.gdblib.symbol.address("mp_")
if mp_via_config > 0:
self._mp_addr = mp_via_config
elif pwndbg.symbol.static_linkage_symbol_address("mp_") or self.is_glibc_symbol(
elif pwndbg.gdblib.symbol.static_linkage_symbol_address("mp_") or self.is_glibc_symbol(
mp_via_symbol
):
self._mp_addr = mp_via_symbol
if not self._mp_addr and pwndbg.symbol.address("__libc_free"):
if not self._mp_addr and pwndbg.gdblib.symbol.address("__libc_free"):
# try to find mp_ referenced in __libc_free
# TODO/FIXME: This method should be updated if we find a better way to find the target assembly code
__libc_free_instructions = pwndbg.disasm.near(
pwndbg.symbol.address("__libc_free"), 100, show_prev_insns=False
pwndbg.gdblib.symbol.address("__libc_free"), 100, show_prev_insns=False
)
if pwndbg.gdblib.arch.current == "x86-64":
iter_possible_match = (
@ -1594,22 +1594,22 @@ class HeuristicHeap(Heap):
@property
def global_max_fast(self):
global_max_fast_via_config = int(str(pwndbg.config.global_max_fast), 0)
global_max_fast_via_symbol = pwndbg.symbol.static_linkage_symbol_address(
global_max_fast_via_symbol = pwndbg.gdblib.symbol.static_linkage_symbol_address(
"global_max_fast"
) or pwndbg.symbol.address("global_max_fast")
) or pwndbg.gdblib.symbol.address("global_max_fast")
if global_max_fast_via_config > 0:
self._global_max_fast_addr = global_max_fast_via_config
elif pwndbg.symbol.static_linkage_symbol_address("global_max_fast") or self.is_glibc_symbol(
global_max_fast_via_symbol
):
elif pwndbg.gdblib.symbol.static_linkage_symbol_address(
"global_max_fast"
) or self.is_glibc_symbol(global_max_fast_via_symbol):
self._global_max_fast_addr = global_max_fast_via_symbol
# TODO/FIXME: This method should be updated if we find a better way to find the target assembly code
if not self._global_max_fast_addr and pwndbg.symbol.address("__libc_malloc"):
if not self._global_max_fast_addr and pwndbg.gdblib.symbol.address("__libc_malloc"):
# `__libc_malloc` will call `_int_malloc`, so we try to find the reference to `_int_malloc`
# because there is a reference to global_max_fast in _int_malloc, which is:
# `if ((unsigned long) (nb) <= (unsigned long) (get_max_fast ()))`
__libc_malloc_instructions = pwndbg.disasm.near(
pwndbg.symbol.address("__libc_malloc"), 25, show_prev_insns=False
pwndbg.gdblib.symbol.address("__libc_malloc"), 25, show_prev_insns=False
)
if pwndbg.gdblib.arch.current == "x86-64":
_int_malloc_addr = (

@ -1,8 +1,8 @@
import gdb
import pwndbg.gdblib.memory
import pwndbg.gdblib.symbol
import pwndbg.heap
import pwndbg.symbol
import pwndbg.vmmap
import tests
@ -21,21 +21,21 @@ def test_heap_bins(start_binary):
gdb.execute("continue")
allocator = pwndbg.heap.current
addr = pwndbg.symbol.address("tcache_size")
addr = pwndbg.gdblib.symbol.address("tcache_size")
tcache_size = allocator._request2size(pwndbg.gdblib.memory.u64(addr))
addr = pwndbg.symbol.address("tcache_count")
addr = pwndbg.gdblib.symbol.address("tcache_count")
tcache_count = pwndbg.gdblib.memory.u64(addr)
addr = pwndbg.symbol.address("fastbin_size")
addr = pwndbg.gdblib.symbol.address("fastbin_size")
fastbin_size = allocator._request2size(pwndbg.gdblib.memory.u64(addr))
addr = pwndbg.symbol.address("fastbin_count")
addr = pwndbg.gdblib.symbol.address("fastbin_count")
fastbin_count = pwndbg.gdblib.memory.u64(addr)
addr = pwndbg.symbol.address("smallbin_size")
addr = pwndbg.gdblib.symbol.address("smallbin_size")
smallbin_size = allocator._request2size(pwndbg.gdblib.memory.u64(addr))
addr = pwndbg.symbol.address("smallbin_count")
addr = pwndbg.gdblib.symbol.address("smallbin_count")
smallbin_count = pwndbg.gdblib.memory.u64(addr)
addr = pwndbg.symbol.address("largebin_size")
addr = pwndbg.gdblib.symbol.address("largebin_size")
largebin_size = allocator._request2size(pwndbg.gdblib.memory.u64(addr))
addr = pwndbg.symbol.address("largebin_count")
addr = pwndbg.gdblib.symbol.address("largebin_count")
largebin_count = pwndbg.gdblib.memory.u64(addr)
result = allocator.tcachebins()

@ -14,7 +14,9 @@ def test_find_fake_fast_command(start_binary):
gdb.execute("continue")
# Ensure memory at fake_chunk's heap_info struct isn't mapped.
unmapped_heap_info = pwndbg.heap.ptmalloc.heap_for_ptr(pwndbg.symbol.address("fake_chunk"))
unmapped_heap_info = pwndbg.heap.ptmalloc.heap_for_ptr(
pwndbg.gdblib.symbol.address("fake_chunk")
)
assert pwndbg.gdblib.memory.peek(unmapped_heap_info) is None
# A gdb.MemoryError raised here indicates a regression from PR #1145

Loading…
Cancel
Save