You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
pwndbg/pwndbg/commands/context.py

141 lines
3.8 KiB
Python

import gdb
import pwndbg.chain
import pwndbg.color
import pwndbg.commands
import pwndbg.commands.nearpc
import pwndbg.commands.telescope
import pwndbg.disasm
import pwndbg.events
import pwndbg.ida
import pwndbg.regs
import pwndbg.symbol
import pwndbg.ui
import pwndbg.vmmap
@pwndbg.commands.ParsedCommand
@pwndbg.commands.OnlyWhenRunning
def context(*args):
if len(args) == 0:
args = ['reg','code','stack','backtrace']
args = [a[0] for a in args]
result = []
result.append(pwndbg.color.legend())
if 'r' in args: result.extend(context_regs())
if 'c' in args: result.extend(context_code())
if 's' in args: result.extend(context_stack())
if 'b' in args: result.extend(context_backtrace())
if 'b' in args: result.extend(context_signal())
print('\n'.join(map(str, result)))
def context_regs():
result = []
result.append(pwndbg.color.blue(pwndbg.ui.banner("registers")))
for reg in pwndbg.regs.gpr + (pwndbg.regs.frame, pwndbg.regs.stack, '$pc'):
if reg is None:
continue
value = pwndbg.regs[reg]
# Make the register stand out
regname = pwndbg.color.bold(reg.ljust(4).upper())
result.append("%s %s" % (regname, pwndbg.chain.format(value)))
return result
def context_code():
banner = [pwndbg.color.blue(pwndbg.ui.banner("code"))]
result = pwndbg.commands.nearpc.nearpc(to_string=True)
# If we didn't disassemble backward, try to make sure
# that the amount of screen space taken is roughly constant.
while len(result) < 11:
result.insert(0, '')
return banner + result
def context_stack():
result = []
result.append(pwndbg.color.blue(pwndbg.ui.banner("stack")))
telescope = pwndbg.commands.telescope.telescope(pwndbg.regs.sp, to_string=True)
if telescope:
result.extend(telescope)
return result
def context_backtrace(frame_count=10, with_banner=True):
result = []
if with_banner:
result.append(pwndbg.color.blue(pwndbg.ui.banner("backtrace")))
this_frame = gdb.selected_frame()
newest_frame = this_frame
oldest_frame = this_frame
for i in range(frame_count):
try:
candidate = oldest_frame.older()
except gdb.MemoryError:
break
if not candidate:
break
oldest_frame = candidate
for i in range(frame_count):
candidate = newest_frame.newer()
if not candidate:
break
newest_frame = candidate
frame = newest_frame
i = 0
while True:
prefix = '> ' if frame == this_frame else ' '
addrsz = pwndbg.ui.addrsz(frame.pc())
symbol = pwndbg.symbol.get(frame.pc())
if symbol:
addrsz = addrsz + ' ' + symbol
line = map(str, (prefix, 'f', i, addrsz))
line = ' '.join(line)
result.append(line)
if frame == oldest_frame:
break
frame = frame.older()
i += 1
return result
last_signal = None
def save_signal(signal):
global last_signal
last_signal = result = []
if isinstance(signal, gdb.ExitedEvent):
# Booooo old gdb
if hasattr(signal, 'exit_code'):
result.append(pwndbg.color.red('Exited: %r' % signal.exit_code))
elif isinstance(signal, gdb.SignalEvent):
msg = 'Program received signal %s' % signal.stop_signal
msg = pwndbg.color.red(msg)
msg = pwndbg.color.bold(msg)
result.append(msg)
elif isinstance(signal, gdb.BreakpointEvent):
for bkpt in signal.breakpoints:
result.append(pwndbg.color.yellow('Breakpoint %s' % (bkpt.location)))
gdb.events.cont.connect(save_signal)
gdb.events.stop.connect(save_signal)
gdb.events.exited.connect(save_signal)
def context_signal():
return last_signal