Skip to content

Commit

Permalink
[WIP] Context watches expressions (Gallopsled#711)
Browse files Browse the repository at this point in the history
* Feature: context watches

* Added expressions to splitting screenshot

* More readable code (review)
  • Loading branch information
jerdna-regeiz authored Mar 17, 2020
1 parent 80e3959 commit a18e751
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 2 deletions.
21 changes: 21 additions & 0 deletions FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ The output of the context may be redirected to a file (including other tty) by u

![](caps/context.png)

### Splitting / Layouting Context

The context sections can be distibuted among different tty by using the `contextoutput` command.
Example: `contextoutput stack /path/to/tty true`

Expand Down Expand Up @@ -67,6 +69,25 @@ import splitmind
end
```

### Watch Expressions

You can add expressions to be watched by the context.
Those expressions are evaluated and shown on every context refresh.

An expression can be added via the `contextwatch` command (aliased `ctx-watch` and `cwatch`).

Per default an expression is parsed and evaluated in the debugged language and can be added with:
```
contextwatch BUF
ctx-watch ITEMS[0]
```

Alternatively one can provide an arbitrary gdb command to be executed and the result printed in the
context by using the optional `cmd` parameter with the value `execute`:
```
contextwatch exectue "ds BUF"
cwatch execute "x/20x $rsp"
```


## Disassembly
Expand Down
Binary file modified caps/context_splitting.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
63 changes: 61 additions & 2 deletions pwndbg/commands/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def clear_screen(out=sys.stdout):
config_clear_screen = pwndbg.config.Parameter('context-clear-screen', False, 'whether to clear the screen before printing the context')
config_output = pwndbg.config.Parameter('context-output', 'stdout', 'where pwndbg should output ("stdout" or file/tty).')
config_context_sections = pwndbg.config.Parameter('context-sections',
'regs disasm code stack backtrace',
'regs disasm code stack backtrace expressions',
'which context sections are displayed (controls order)')

# Storing output configuration per section
Expand Down Expand Up @@ -150,6 +150,64 @@ def contextoutput(section, path, clearing, banner="both", width=None):
banner_top= banner in ["both", "top"],
banner_bottom= banner in ["both", "bottom"])

# Watches
expressions = set()
expression_commands = {
"eval": gdb.parse_and_eval,
"execute": lambda exp: gdb.execute(exp, False, True)
}

parser = argparse.ArgumentParser()
parser.description = """
Adds an expression to be shown on context.
'cmd' controls what command is used to interpret the expression.
eval: the expression is parsed and evaluated as in the debugged language
execute: the expression is executed as an gdb command
"""
parser.add_argument("cmd", type=str, default="eval", nargs="?",
help="Command to be used with the expression. Values are: eval execute")
parser.add_argument("expression", type=str, help="The expression to be evaluated and shown in context")
@pwndbg.commands.ArgparsedCommand(parser, aliases=['ctx-watch', 'cwatch'])
def contextwatch(expression, cmd=None):
expressions.add((expression, expression_commands.get(cmd, gdb.parse_and_eval)))

parser = argparse.ArgumentParser()
parser.description = """Removes an expression previously added to be watched."""
parser.add_argument("expression", type=str, help="The expression to be removed from context")
@pwndbg.commands.ArgparsedCommand(parser, aliases=['ctx-watch', 'cunwatch'])
def contextunwatch(expression):
global expressions
expressions = set((exp,cmd) for exp,cmd in expressions if exp != expression)

def context_expressions(target=sys.stdout, with_banner=True, width=None):
if not expressions:
return []
banner = [pwndbg.ui.banner("expressions", target=target, width=width)]
output = []
if width is None:
_height, width = pwndbg.ui.get_window_size(target=target)
for exp,cmd in sorted(expressions):
try:
# value = gdb.parse_and_eval(exp)
value = str(cmd(exp))
except gdb.error as err:
value = str(err)
value = value.split("\n")
lines = []
for line in value:
if width and len(line)+len(exp)+3 > width:
n = width - (len(exp)+3) - 1 # 1 Padding...
lines.extend(line[i:i+n] for i in range(0, len(line), n))
else:
lines.append(line)

fmt = C.highlight(exp)
lines[0] = "{} = {}".format(fmt, lines[0])
lines[1:] = [" "*(len(exp)+3) + line for line in lines[1:]]
output.extend(lines)
return banner + output if with_banner else output

# @pwndbg.events.stop

parser = argparse.ArgumentParser()
Expand Down Expand Up @@ -498,7 +556,8 @@ def context_signal():
'a': context_args,
'c': context_code,
's': context_stack,
'b': context_backtrace
'b': context_backtrace,
'e': context_expressions,
}


Expand Down

0 comments on commit a18e751

Please sign in to comment.