Skip to content

Commit

Permalink
final version of changes, squashed commits
Browse files Browse the repository at this point in the history
  • Loading branch information
etrickel committed Jan 9, 2018
1 parent ae72a11 commit 22814bb
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 57 deletions.
28 changes: 28 additions & 0 deletions docs/commands/context.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,34 @@ hexdump version of 0x40 byte of the stack. This command makes it convenient for
tracking the evolution of arbitrary locations in memory. Tracked locations can
be removed one by one using `memory unwatch`, or altogether with `memory reset`.

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
123 changes: 66 additions & 57 deletions gef.py
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -1326,8 +1326,8 @@ def sp(self):
return get_register("$sp")

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

@property
def ptrsize(self):
Expand Down Expand Up @@ -1363,10 +1363,6 @@ def instruction_length(self):
# Thumb instructions have variable-length (2 or 4-byte)
return None if is_arm_thumb() else 4

@property
def get_stack_top(self):
return 0

def is_call(self, insn):
mnemo = insn.mnemo
call_mnemos = {"bl", "blx"}
Expand Down Expand Up @@ -1441,14 +1437,6 @@ def is_call(self, insn):
call_mnemos = {"bl", "blr"}
return mnemo in call_mnemos

@property
def get_stack_top(self):
return 0

@property
def get_stack_address(self):
return 0

def flag_register_to_human(self, val=None):
# http://events.linuxfoundation.org/sites/events/files/slides/KoreaLinuxForum-2014.pdf
reg = self.flag_register
Expand Down Expand Up @@ -1699,10 +1687,6 @@ def flag_register_to_human(self, val=None):
val = get_register(reg)
return flags_to_human(val, self.flags_table)

@property
def get_stack_top(self):
return 0

def is_call(self, insn):
return False

Expand Down Expand Up @@ -1785,10 +1769,6 @@ def flag_register_to_human(self, val=None):
def is_call(self, insn):
return False

@property
def get_stack_top(self):
return 0

def is_conditional_branch(self, insn):
mnemo = insn.mnemo
# http://moss.csc.ncsu.edu/~mueller/codeopt/codeopt00/notes/condbranch.html
Expand Down Expand Up @@ -1865,10 +1845,6 @@ class SPARC64(SPARC):
32: "carry",
}

@property
def get_stack_top(self):
return 0



class MIPS(Architecture):
Expand All @@ -1895,10 +1871,6 @@ def flag_register_to_human(self, val=None):
def is_call(self, insn):
return False

@property
def get_stack_top(self):
return 0

def is_conditional_branch(self, insn):
mnemo = insn.mnemo
branch_mnemos = {"beq", "bne", "beqz", "bnez", "bgtz", "bgez", "bltz", "blez"}
Expand Down Expand Up @@ -2263,6 +2235,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 @@ -6310,7 +6300,7 @@ def __init__(self):
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_up", False, "Order of stack downward starts at largest down to stack pointer")
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", 5, "Number of instruction before and after $pc")
self.add_setting("ignore_registers", "", "Space-separated list of registers not to display (e.g. '$cs $ds $gs')")
Expand Down Expand Up @@ -7028,7 +7018,7 @@ def __init__(self):
return

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

Expand All @@ -7038,8 +7028,8 @@ def pprint_dereferenced(self, addr, off):

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

if (is_x86_32() or is_x86_64() ) and get_gef_setting("context.show_saved_ip"):
regs.append(("savedeip", (get_register("$bp") + (current_arch.ptrsize))))
if get_gef_setting("context.show_saved_ip"):
regs.append(("savedip", get_saved_ip()))

sep = " {:s} ".format(right_arrow)
memalign = current_arch.ptrsize
Expand Down Expand Up @@ -7068,16 +7058,17 @@ def pprint_dereferenced(self, addr, off):

@only_if_gdb_running
def do_invoke(self, argv):
grow_stack_up = get_gef_setting("context.grow_stack_up")
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:])
if len(argv) == 2 and argv[0] == "$sp" and argv[1].isdigit():
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])))
Expand All @@ -7086,30 +7077,48 @@ def do_invoke(self, argv):
stackoffs = range(0, nb)

# adjusts order of stack so that it grows downward
if grow_stack_up:
stackoffs = range(nb - 1, -1, -1)
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 EBP at top of stack
# prints saved instruction pointer
if get_gef_setting("context.show_saved_ip"):
# is saved EIP already shown in stack dereference?

if current_arch.get_stack_top > largest_addresss_to_be_shown and start_address == current_arch.sp:
if grow_stack_up:
gdb.execute('dereference {} L1'.format(current_arch.get_stack_top + current_arch.ptrsize ))
gdb.execute('dereference {} L1'.format(current_arch.get_stack_top ))
print(". . . ({:d} bytes skipped)".format(current_arch.get_stack_top - largest_addresss_to_be_shown))
for i in stackoffs:
print(self.pprint_dereferenced(start_address, i))
else:
for i in stackoffs:
print(self.pprint_dereferenced(start_address, i))
print(". . . ({:d} bytes skipped)".format(get_register("$bp") - get_register("$sp")))
gdb.execute('dereference $bp L2')

return
frame_ptr = current_arch.fp
saved_ip = get_saved_ip()

for i in stackoffs:
print(self.pprint_dereferenced(start_address, i))
# 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)

return

Expand Down

0 comments on commit 22814bb

Please sign in to comment.