diff --git a/gdb-port/gui.py b/gdb-port/gui.py index 32a6ea88d941e007e1a4f99fcc8efe3d510cdc13..34089ef66de717ce9fd79bf01cbc9ee9b4e0a85c 100644 --- a/gdb-port/gui.py +++ b/gdb-port/gui.py @@ -1,6 +1,8 @@ from tkinter import * from tkinter import ttk +# TODO: investigate if tkinter installs a SIGCHLD handler, which can break GDB + class PresentationLayer(): def __init__(self, parser): self.top_parser = parser @@ -11,6 +13,8 @@ class PresentationLayer(): self.top_parser_address = None self.input_chunk = None + self.parser_env = None + def set_top_parser(self,parser): self.top_parser = parser self.top_parser_name.set(self.top_parser.name) @@ -19,6 +23,9 @@ class PresentationLayer(): def set_input_chunk(self, input_chunk): self.input_chunk.set(input_chunk) + def set_parser_env(self, parser_env): + self.parser_env.set(parser_env) + # let's avoid polluting the global namespace def init_gui(self): self.root = Tk() @@ -38,6 +45,8 @@ class PresentationLayer(): #self.set_top_parser(top_level_parse.peek_parser()) #self.set_input_chunk(top_level_parse.get_input_chunk()) + self.parser_env = StringVar() + #"Current parser" widgets ttk.Label(self.frame, text="Current parser").grid(column=1, row=1) ttk.Label(self.frame, textvariable=self.top_parser_name).grid(column=1, row=2) @@ -50,6 +59,7 @@ class PresentationLayer(): # ParserHierarchy widget (sequence members, parsers this one contains, etc) # Showing parser decisions is probably possible by capturing the return value of h_do_parse ttk.Label(self.frame, text="Parser hierarchy").grid(column=2, row=3) + #ttk.Label(self.frame, textvariable=self.parser_env).grid(column=2, row=4) ttk.Label(self.frame, text="[Placeholder, Placeholder, Placeholder]").grid(column=2, row=4) ttk.Button(self.frame, text="Step", command=step).grid(column=1, row=4) diff --git a/gdb-port/parser-type-instrumentation-gdb.py b/gdb-port/parser-type-instrumentation-gdb.py index faf5bec840ab5931569590bf5cbfc5deecb39f8c..039b921478f1c2677ed113a73eb69ab68fe66e2b 100644 --- a/gdb-port/parser-type-instrumentation-gdb.py +++ b/gdb-port/parser-type-instrumentation-gdb.py @@ -3,26 +3,73 @@ # TopLevelParse should be amenable to adding parsers to the dict through here parser_name_defaults = { - 'sequence_vt': '(Unnamed sequence)', - 'ignore_vt': '(Unnamed ignore)', 'action_vt': '(Unnamed action)', - 'and_vt': '(Unnamed and)' - #... + 'and_vt': '(Unnamed and)', + 'attr_bool_vt': '(Unnamed attr_bool)', + 'bind_vt': '(Unnamed bind)', + 'bits_vt': '(Unnamed bits)', + 'butnot_vt': '(Unnamed butnot)', + 'ch_vt': '(Unnamed ch)', + 'charset_vt': '(Unnamed charset)', + 'choice_vt': '(Unnamed choice)', + 'difference_vt': '(Unnamed difference)', + 'end_vt': '(Unnamed end)', + 'endianness_vt': '(Unnamed endianness)', + 'ignore_vt': '(Unnamed ignore)', + 'ignoreseq_vt': '(Unnamed ignoreseq)', + 'indirect_vt': '(Unnamed indirect)', + 'int_range_vt': '(Unnamed int_range)', + 'length_value_vt': '(Unnamed length_value)', + 'many_vt': '(Unnamed many)', + 'not_vt': '(Unnamed not)', + 'nothing_vt': '(Unnamed nothing)', + 'optional_vt': '(Unnamed optional)', + 'permutation_vt': '(Unnamed permutation)', + 'seek_vt': '(Unnamed seek)', + 'skip_vt': '(Unnamed skip)', + 'tell_vt': '(Unnamed tell)', + 'sequence_vt': '(Unnamed sequence)', + 'token_vt': '(Unnamed token)', + 'unimplemented_vt': '(Unnamed unimplemented)', + 'get_vt': '(Unnamed get)', + 'put_vt': '(Unnamed put)', + 'whitespace_vt': '(Unnamed whitespace)', + 'xor_vt': '(Unnamed xor)' } +class VTTypes: + def __init__(self): + self.vt_symbols = {int(gdb.lookup_symbol(key)[0].value().address) : gdb.lookup_symbol(key)[0] for key in parser_name_defaults.keys()} + + # vt_p == vt_symbols[int(parser_vtable_p)].value().address + # name = parser_name_defaults[vt_types.lookup_by_address(parser_vtable_p)].name + # address is expected to be pointer to a parser that can be converted to int() + # e.g. parser.address of a Parser object, integer + def lookup_by_address(self, address): + try: + return self.vt_symbols[int(address)] + except KeyError: + return None + +vt_types = VTTypes() + class HParserEnv: def __init__(self, parser, top_level_parse): print("HParserEnv constructed") # DEBUG + # parser is expected to be a Parser object def name_from_vtable(self, parser): parser_addr = parser.address # TODO: do this without passing a string to gdb.parse_and_eval() # perhaps using gdb.Value would be the best - vtable = gdb.parse_and_eval("((HParser*) " + parser_addr + ")->env->vtable") + vtable_p = gdb.parse_and_eval("((HParser*) " + str(parser_addr) + ")->vtable") try: - name = parser_name_defaults[vtable.name()] + name = parser_name_defaults[vt_types.lookup_by_address(vtable_p).name] + # if lookup_by_address() returns None + except AttributeError: + name = "(Unknown parser type (vtable symbol not found in lookup)" except KeyError: - name = "(Unknown parser type)" + name = "(Unknown parser type (vtable exists but has no default name associated)" return name @@ -31,8 +78,9 @@ class HParserEnv: # parser_array = [top_level_parse.add_or_get_parser(gdb.parse_and_eval("((HSequence*) parser->env)->p_array[" + str(index) +"]")) for index in range(0, num_parsers)] # compare pointers for equality -class SequenceEnv: +class SequenceEnv(HParserEnv): def __init__(self, parser, top_level_parse): + super().__init__(parser, top_level_parse) self.parser = parser self.member_parsers = [] @@ -48,10 +96,11 @@ class SequenceEnv: for index in range(0, num_parsers): parser_p = gdb.parse_and_eval("((HSequence*) parser->env)->p_array[" + str(index) + "]") parser_obj = top_level_parse.add_or_get_parser(parser_p) - #parser_obj.name_parser( self.name_from_vtable(parser_obj) ) + parser_obj.name_parser( self.name_from_vtable(parser_obj) ) self.member_parsers.append(parser_obj) - # TODO + def __str__(self): + return str([str(parser) for parser in self.member_parsers]) class IgnoreEnv: