Skip to content

Commit

Permalink
Add some simple improvements to stack display
Browse files Browse the repository at this point in the history
- Added the option context.grow_stack_down, when enabled the stack will grow up on the display.
- Added the option context.show_saved_ip, when enabled the context shows
  the saved ip and the ebp, it puts ... (XX btyes) between the base
  pointer and where the stack display begins.
  - Both options are disabled by default.
- Changed stack alias and dereference function so that it would work without requiring the L prefix.
  • Loading branch information
etrickel authored and Grazfather committed Jan 10, 2018
1 parent 265ac26 commit c758bb5
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 4 deletions.
28 changes: 28 additions & 0 deletions docs/commands/context.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,34 @@ The size of most sections are also customizable:
* `nb_lines_code` and `nb_lines_code_prev` configure how many lines to show
after and before the PC, respectively.

To have the stack displayed with the largest stack addresses on top (i.e., grow the
stack downward), enable the following setting:
```
gef➤ gef config context.grow_stack_down True
```

To always display the saved instruction pointer in the stack view, enable the following:
```
gef➤ gef config context.show_saved_ip True
```

If the saved instruction pointer is not within the portion of the stack being displayed,
then a section is created that includes the saved ip and depending on the architecture
the frame pointer. Since not all the addresses can be displayed, the missing addresses
are squished into an ellipsis.
```
0x00007fffffffc9e8│+0x00: 0x00007ffff7a2d830 → <__main+240> mov edi, eax ← savedip
0x00007fffffffc9e0│+0x00: 0x00000000004008c0 → <__init+0> push r15 ← $rbp
. . . (440 bytes skipped)
0x00007fffffffc7e8│+0x38: 0x0000000000000000
0x00007fffffffc7e0│+0x30: 0x0000000000000026 ("&"?)
0x00007fffffffc7d8│+0x28: 0x0000000001958ac0
0x00007fffffffc7d0│+0x20: 0x00007ffff7ffa2b0 → 0x5f6f7364765f5f00
0x00007fffffffc7c8│+0x18: 0x00007fff00000000
0x00007fffffffc7c0│+0x10: 0x00007fffffffc950 → 0x0000000000000000
0x00007fffffffc7b8│+0x08: 0x0000000000000000
0x00007fffffffc7b0│+0x00: 0x00007fffffffc7e4 → 0x0000000000000000 ← $rsp
```

### Redirecting context output to another tty/file ###

Expand Down
87 changes: 83 additions & 4 deletions gef.py
Original file line number Diff line number Diff line change
Expand Up @@ -1337,6 +1337,10 @@ def pc(self):
def sp(self):
return get_register("$sp")

@property
def fp(self):
return get_register("$fp")

@property
def ptrsize(self):
return get_memory_alignment()
Expand Down Expand Up @@ -2254,6 +2258,24 @@ def get_info_sections():
return


def get_saved_ip():
"""Retrieves the saved ip using the 'info frame' command."""

lines = gdb.execute("info frame", to_string=True).splitlines()
if lines:
saved_regs = lines[-1].split()
saved_ip_str = saved_regs[-1]

try:
saved_ip = int(saved_ip_str, 16)
return saved_ip
except ValueError:
# ignore
pass

return 0


def get_info_files():
"""Retrieves all the files loaded by debuggee."""
lines = gdb.execute("info files", to_string=True).splitlines()
Expand Down Expand Up @@ -6309,6 +6331,8 @@ def __init__(self):
self.add_setting("show_registers_raw", False, "Show the registers pane with raw values (no dereference)")
self.add_setting("peek_calls", True, "Peek into calls")
self.add_setting("nb_lines_stack", 8, "Number of line in the stack pane")
self.add_setting("show_saved_ip", False, "Show saved IP and EBP even if outside of nb_lines_stack")
self.add_setting("grow_stack_down", False, "Order of stack downward starts at largest down to stack pointer")
self.add_setting("nb_lines_backtrace", 10, "Number of line in the backtrace pane")
self.add_setting("nb_lines_code", 6, "Number of instruction after $pc")
self.add_setting("nb_lines_code_prev", 3, "Number of instruction before $pc")
Expand Down Expand Up @@ -7042,7 +7066,7 @@ def __init__(self):
return

def post_load(self):
GefAlias("stack", "dereference $sp L10")
GefAlias("stack", "dereference $sp")
GefAlias("dps", "dereference", completer_class=gdb.COMPLETE_LOCATION)
return

Expand All @@ -7051,6 +7075,10 @@ def pprint_dereferenced(self, addr, off):
registers_color = get_gef_setting("theme.dereference_register_value")

regs = [(k.strip(), get_register(k)) for k in current_arch.all_registers]

if get_gef_setting("context.show_saved_ip"):
regs.append(("savedip", get_saved_ip()))

sep = " {:s} ".format(right_arrow)
memalign = current_arch.ptrsize

Expand All @@ -7064,6 +7092,7 @@ def pprint_dereferenced(self, addr, off):
sep.join(addrs[1:]), ma=(memalign*2 + 2))

values = []

for regname, regvalue in regs:
if current_address == regvalue:
values.append(regname)
Expand All @@ -7077,18 +7106,68 @@ def pprint_dereferenced(self, addr, off):

@only_if_gdb_running
def do_invoke(self, argv):
grow_stack_down = get_gef_setting("context.grow_stack_down")

if len(argv) < 1:
err("Missing location.")
return

nb = 10
if len(argv)==2 and argv[1][0] in ("l", "L") and argv[1][1:].isdigit():

if len(argv) == 2 and argv[1][0] in ("l", "L") and argv[1][1:].isdigit():
nb = int(argv[1][1:])
elif len(argv) == 2 and argv[0] == "$sp" and argv[1].isdigit():
nb = int(argv[1])

start_address = align_address(long(gdb.parse_and_eval(argv[0])))
largest_addresss_to_be_shown = start_address + (current_arch.ptrsize * nb)

stackoffs = range(0, nb)

# adjusts order of stack so that it grows downward
if grow_stack_down:
stackoffs = reversed(stackoffs)

stack_str = ""
for i in stackoffs:
stack_str += self.pprint_dereferenced(start_address, i) + "\n"
stack_str = stack_str[:-1]

# prints saved instruction pointer
if get_gef_setting("context.show_saved_ip"):

frame_ptr = current_arch.fp
saved_ip = get_saved_ip()

# only add saved_ip if it isn't already shown and we are displaying the stack
if saved_ip > largest_addresss_to_be_shown and start_address == current_arch.sp:
bytes_skipped_label = Color.grayify(". . . ({:d} bytes skipped)".format(saved_ip - largest_addresss_to_be_shown))

saved_ip_str = self.pprint_dereferenced(saved_ip, 0)
out_info_str = saved_ip_str
if abs(frame_ptr - saved_ip) == current_arch.ptrsize:
frame_str = self.pprint_dereferenced(frame_ptr, 0)
if frame_str:
if (saved_ip > frame_ptr and grow_stack_down) or (saved_ip < frame_ptr and not grow_stack_down):
out_info_str += "\n" + frame_str
else:
out_info_str = frame_str + "\n"
out_info_str += saved_ip_str

if grow_stack_down:
print(out_info_str)
print(bytes_skipped_label)
print(stack_str)
else:
print(stack_str)
print(bytes_skipped_label)
print(out_info_str)

else:
print(stack_str)
else:
print(stack_str)

for i in range(0, nb):
print(self.pprint_dereferenced(start_address, i))
return


Expand Down

0 comments on commit c758bb5

Please sign in to comment.