# Should be loaded last


print(": Initializing BreakpointManager")
breakpoint_manager = BreakpointManager(H_RULE_FUNCTIONS)


print(": Registering exit handler")
# Clean up by-address breakpoints in hammer when inferior exits.
# Caveat: Assumes there's a single inferior, the debugged parser, so no checking is done
# TODO: where to store breakpoints? TopLevelParse? A BreakpointManager class?i
def exit_handler(event):
	#breakpoints = [ perform_lowlevel_parse_ret, h_packrat_parse_ret ]
	#del_hammer_retq_breakpoints(breakpoints)
	breakpoint_manager.del_hammer_retq_breakpoints()

gdb.events.exited.connect(exit_handler)


print(": Setting PDFMain breakpoint")
# Break on main so that libhammer.so gets to load
main = PDFMainBreakpoint("main")


print(": Setting Hammer library breakpoints")
print(":: Normal breakpoints")
breakpoint_manager.set_hammer_breakpoints()

#TODO: there would be less complaining about pending breakpoints if vtable breakpoints were set after running to main
print(":: Parser vtable breakpoints")
breakpoint_manager.set_parser_virtual_breakpoints()

# run until main
print(": Running until main")
gdb.execute("run")

print(": Setting application breakpoints")
print(":: init_parser breakpoint")
breakpoint_manager.set_init_parser_breakpoint()

print(":: RET breakpoints in functions with H_RULES")
breakpoint_manager.set_h_rule_breakpoints()

# TODO: the RET breakpoints in hammer break when "run" is executed again. figure out a way to automatically replace these

# Run until stop position, if set. Finish parsing otherwise
print(": Continuing execution")
gdb.execute("continue")

print(": Printing memory statistics")
print([(p.name, hex(p.address), p.bytes_used) for p in top_level_parse.parser_objs.values()])