diff --git a/gdb-port/README.md b/gdb-port/README.md index cc3c6514d1fa6efc53ea2f65f848740e6163cfa2..6c28621777ec162ac61bf1b3533e8fc415104dc0 100644 --- a/gdb-port/README.md +++ b/gdb-port/README.md @@ -88,6 +88,17 @@ Steps execution until the "current" parser (the one `h_do_parse()` has been call In terms of call stack navigation, this is roughly analogous to executing `finish` to step out of the current stack frame, followed by stepping into the next function call. (With the difference, that this commands steps between "frames" of the parser stack) +Fair warning, this can get *really* slow with parsers that consume a few bytes at a time. (For example, filters in the pdf parser) + +``` +hammer-parse-apply-and-show-ast +``` + +Same as `hammer-parse-apply`, except once the AST is obtained, the boundaries of the tokens comprising the AST will be graphically displayed. + +Similar to the previous command, this can also get really slow under the same conditions. + + ``` hammer-parse-step-to-result <number> ``` diff --git a/gdb-port/commands.py b/gdb-port/commands.py index a57b68403a6d776791c73b3c91f9bdce8ba1a8b7..bcb548f52d303f475f2c7b29a9845f0ab3e84a75 100644 --- a/gdb-port/commands.py +++ b/gdb-port/commands.py @@ -221,6 +221,34 @@ class HammerParseApply(FlowControlWithPrint): super(HammerParseApply, self).__init__("hammer-parse-apply", gdb.COMMAND_OBSCURE) print(":: hammer-parse-apply") + def invoke(self, arg, from_tty): + #profiler = cProfile.Profile() # DEBUG + #profiler.enable() # DEBUG + with cProfile.Profile() as profiler: # DEBUG + #top_level_parse.setup_ast_stack_index(0) #TODO: is it a problem if this command overwrites it? would it better to use a convenience variable, as with parse-step? + + # HDoParseRetBreakpoint sets hammer_step_counter to 1 after capturing the AST subtree, so this will stop at the first h_do_parse invocation afterwards + if gdb.selected_inferior().pid > 0: + gdb.execute("continue") + + #top_level_parse.clear_ast_stack_index() + + self.conditionally_print_backtrace() + profiler.print_stats(sort='tottime') # DEBUG + #profiler.disable() # DEBUG + #s = io.StringIO() # DEBUG + #sortby = SortKey.CUMULATIVE # DEBUG + #ps = pstats.Stats(pr, stream=s).sort_stats(sortby) # DEBUG + #ps.print_stats() # DEBUG + #print(s.getvalue()) # DEBUG + +HammerParseApply() + +class HammerParseApplyAndShowAST(FlowControlWithPrint): + def __init__(self): + super(HammerParseApplyAndShowAST, self).__init__("hammer-parse-apply-and-show-ast", gdb.COMMAND_OBSCURE) + print(":: hammer-parse-apply-and-show-ast") + def invoke(self, arg, from_tty): #profiler = cProfile.Profile() # DEBUG #profiler.enable() # DEBUG @@ -242,4 +270,4 @@ class HammerParseApply(FlowControlWithPrint): #ps.print_stats() # DEBUG #print(s.getvalue()) # DEBUG -HammerParseApply() +HammerParseApplyAndShowAST() diff --git a/gdb-port/startup_scripts/shell.sh b/gdb-port/startup_scripts/shell.sh index e32a9582741b9228d7952bef9269849b0c1a861e..ecf92014a4412f5858c34f23d6274ea283b7692c 100755 --- a/gdb-port/startup_scripts/shell.sh +++ b/gdb-port/startup_scripts/shell.sh @@ -2,7 +2,7 @@ gdb -ex "set python print-stack full" -ex "source perf-instrumentation/gdb-port/parser.py" -ex "source perf-instrumentation/gdb-port/utility-commands.py" -ex "source perf-instrumentation/gdb-port/commands.py" -ex "source perf-instrumentation/gdb-port/hammer-breakpoints.py" -ex "source perf-instrumentation/gdb-port/ast.py" -ex "source perf-instrumentation/gdb-port/breakpoint-manager.py" -ex "source perf-instrumentation/gdb-port/top-level-parse.py" -ex "hammer-parse-stop-at-pos 50" -ex "source perf-instrumentation/gdb-port/parser-type-instrumentation-gdb.py" -ex "source perf-instrumentation/gdb-port/parser-name-instrumentation-gdb.py" \ -ex "hammer-parse-step 7" \ --ex "python [gdb.execute('hammer-parse-apply') for x in range(8)]" \ +-ex "python [gdb.execute('hammer-parse-apply-and-show-ast') for x in range(8)]" \ --args pdf t/000143.pdf # hammer-parse-step 7 is arbitrary, but happens to get to a location in the file that's convenient for testing token printing