From d9e74401f377ec17a419fd6df16bf3f3c1817263 Mon Sep 17 00:00:00 2001 From: pompolic <pompolic@special-circumstanc.es> Date: Thu, 17 Jun 2021 00:30:11 +0200 Subject: [PATCH] Rudimentary GUI - left hand side shows the parser about to be invoked (top of current parser stack), as well as its address - right hand side shows the current position in the input + the next 32 bytes - step button executes hammer-parse-step 1 Start the GUI by sourcing gui.py after parser-name-instrumentation-gdb.py and utility-commands.py have been loaded --- gdb-port/gui.py | 55 +++++++++++++++++++++ gdb-port/parser-name-instrumentation-gdb.py | 14 ++++++ 2 files changed, 69 insertions(+) create mode 100644 gdb-port/gui.py diff --git a/gdb-port/gui.py b/gdb-port/gui.py new file mode 100644 index 0000000..e680e9c --- /dev/null +++ b/gdb-port/gui.py @@ -0,0 +1,55 @@ +from tkinter import * +from tkinter import ttk + +class PresentationLayer(): + def __init__(self, parser, name_var, address_var, input_chunk_var): + self.top_parser = parser + self.top_parser_name = name_var + self.top_parser_address = address_var + self.input_chunk = input_chunk_var + + def set_top_parser(self,parser): + self.top_parser = parser + self.top_parser_name.set(self.top_parser.name) + self.top_parser_address.set(hex(self.top_parser.address)) + + def set_input_chunk(self, input_chunk): + self.input_chunk.set(input_chunk) + +def step(*args): + gdb.execute("hammer-parse-step 1") + presentation_layer.set_top_parser(top_level_parse.peek_parser()) + presentation_layer.set_input_chunk(top_level_parse.get_input_chunk()) + +if top_level_parse is None: + print("Please import parser name script") +else: + root = Tk() + root.title("Parser visualization") + + frame = ttk.Frame(root, padding="12 12 12 12") + frame.grid(column=0, row=0, sticky=(N, W, E, S)) + root.columnconfigure(0, weight=1) + root.rowconfigure(0, weight=1) + + parser = StringVar() + parser_addr = StringVar() + input_chunk = StringVar() + presentation_layer = PresentationLayer(top_level_parse.peek_parser(), parser, parser_addr, input_chunk) + presentation_layer.set_top_parser(top_level_parse.peek_parser()) + presentation_layer.set_input_chunk(top_level_parse.get_input_chunk()) + #presentation_layer.top_parser_name = parser + #presentation_layer.top_parser_addr = parser_addr + #presentation_layer.top_parser = top_level_parse.peek_parser() + #presentation_layer.set_top_parser(top_level_parse.peek_parser()) + + #presentation_layer.top_parser = top_level_parse.peek_parser() + ttk.Label(frame, textvariable=presentation_layer.top_parser_name).grid(column=1, row=1) + #ttk.Label(frame, text="Placeholder name").grid(column=1, row=1) + ttk.Label(frame, textvariable=presentation_layer.top_parser_address).grid(column=1, row=2) + #ttk.Label(frame, text="Placeholder address").grid(column=1, row=2) + ttk.Label(frame, textvariable=presentation_layer.input_chunk).grid(column=2, row=1) + ttk.Button(frame, text="Step", command=step).grid(column=1, row=3) + + root.mainloop() + diff --git a/gdb-port/parser-name-instrumentation-gdb.py b/gdb-port/parser-name-instrumentation-gdb.py index 782b4da..999a6da 100644 --- a/gdb-port/parser-name-instrumentation-gdb.py +++ b/gdb-port/parser-name-instrumentation-gdb.py @@ -112,6 +112,8 @@ class TopLevelParse: self.parser_stacks = [] self.parser_objs = {} self.unclaimed_mem_use = 0 + # Holds 32 characters starting at state->input_stream[index], used by the GUI + self.current_input_chunk = '' # Called from h_packrat_parse()'s handler, where the parse state and arena get initialized def enter_h_packrat_parse(self, parser): @@ -207,6 +209,12 @@ class TopLevelParse: else: return None + def set_input_chunk(self, chunk): + self.input_chunk = chunk + + def get_input_chunk(self): + return self.input_chunk + top_level_parse = TopLevelParse() # Approach 1: load the application, set breakpoints, execute stack commands on breakpoint hit, continue @@ -239,13 +247,19 @@ class HDoParseBreakpoint(gdb.Breakpoint): if val.name == 'state': #TODO: rename these variables to make it clear they're pointers state = int(val.value(frame)) + state_obj = val.value(frame) index = val.value(frame).dereference()['input_stream']['index'] + input_ptr = val.value(frame).dereference()['input_stream']['input'] # If you want to printf debug the parse state #print(val.value(frame).dereference()) if val.name == 'arena': arena = int(val.value(frame)) top_level_parse.enter_h_do_parse(state, None, parser) + input_chunk = input_ptr + index + top_level_parse.set_input_chunk(input_chunk.string('UTF-8','replace',32)) + #print(input_chunk.string('ascii','backslashreplace',10)) + # Check if we need to stop after a number of steps step_counter = gdb.convenience_variable("hammer_step_counter") -- GitLab