def reverse_watch(dbg, s_expr): """Perform 'reverse-watch' command on expression. 'dbg' is the instance of ReversibleDebugger on which to operate.""" s_expr_val = dbg.evaluate_expression(s_expr) fredutil.fred_debug("RW: Starting with expr value '%s'" % s_expr_val) # Find starting checkpoint using binary search: binary_search._binary_search_checkpoints(dbg, s_expr, s_expr_val) # STILL TESTING: When "else" branch works well, it will become permanent, # and the remaining branch of "if" can be removed. if False: dbg.current_checkpoint().set_history( binary_search._binary_search_history(dbg, dbg.copy_current_checkpoint_history(), 0, s_expr, s_expr_val)) else: if dbg.branch.get_num_checkpoints() == 0: fredutil.fred_error("No checkpoints found for reverse-watch.") return l_history_copy = dbg.copy_current_checkpoint_history() try: dbg.current_checkpoint().set_history( binary_search.NEW_binary_search_since_last_checkpoint(dbg, l_history_copy, 0, s_expr, s_expr_val)) except binary_search.BinarySearchTooFarAtStartError: fredutil.fred_debug("BinarySearchTooFarAtStartError handled") fredutil.fred_info( 'reverse-watch failed; expr "%s"\n is same at start and end.' % s_expr ) dbg.update_state() fredutil.fred_debug("Reverse watch finished.")
def reverse_watch(dbg, s_expr): """Perform 'reverse-watch' command on expression. 'dbg' is the instance of ReversibleDebugger on which to operate.""" s_expr_val = dbg.evaluate_expression(s_expr) fredutil.fred_debug("RW: Starting with expr value '%s'" % s_expr_val) # Find starting checkpoint using binary search: binary_search._binary_search_checkpoints(dbg, s_expr, s_expr_val) # STILL TESTING: When "else" branch works well, it will become permanent, # and the remaining branch of "if" can be removed. if False: dbg.current_checkpoint().set_history( binary_search._binary_search_history( dbg, dbg.copy_current_checkpoint_history(), 0, s_expr, s_expr_val)) else: if dbg.branch.get_num_checkpoints() == 0: fredutil.fred_error("No checkpoints found for reverse-watch.") return l_history_copy = dbg.copy_current_checkpoint_history() try: dbg.current_checkpoint().set_history( binary_search.NEW_binary_search_since_last_checkpoint( dbg, l_history_copy, 0, s_expr, s_expr_val)) except binary_search.BinarySearchTooFarAtStartError: fredutil.fred_debug("BinarySearchTooFarAtStartError handled") fredutil.fred_info( 'reverse-watch failed; expr "%s"\n is same at start and end.' % s_expr) dbg.update_state() fredutil.fred_debug("Reverse watch finished.")
def reverse_watch_with_log_support(dbg, s_expr): """Perform 'reverse-watch' with support from fred_command.""" s_expr_val = dbg.evaluate_expression(s_expr) fredutil.fred_debug("RW: Starting with expr value '%s'" % s_expr_val) # Find starting checkpoint using binary search: binary_search._binary_search_checkpoints(dbg, s_expr, s_expr_val) dbg.current_checkpoint().set_history( binary_search._binary_search_with_log(dbg, s_expr, s_expr_val)) dbg.update_state() fredutil.fred_debug("Reverse watch finished.")
def reverse_watch_for_mt(dbg, s_expr): """Perform 'reverse-watch' command on expression, with support for an expression changing in a thread which is not the main thread.""" fredutil.fred_timer_start("reverse-watch") if dbg.branch.get_num_checkpoints() == 0: fredutil.fred_error("No checkpoints found for reverse-watch.") return s_expr_val = dbg.evaluate_expression(s_expr) testIfTooFar = lambda: dbg.test_expression(s_expr, s_expr_val) fredutil.fred_debug("RW: Starting with expr value '%s'" % s_expr_val) # ---------------------------- Binary search of checkpoints if dbg.branch.get_num_checkpoints() > 1: # Find starting checkpoint using binary search: binary_search._binary_search_checkpoints(dbg, s_expr, s_expr_val) # ---------------------------- Binary search on the main thread if _reverse_watch_main_thread(dbg, s_expr, s_expr_val): fredutil.fred_debug("Main thread changed expression.") fredutil.fred_debug("Reverse-watch finished.") fredutil.fred_assert(not testIfTooFar()) return # If we're here, it means a secondary thread caused expr to change. fredutil.fred_debug("Secondary thread caused expr to change. " "Starting binary search of system calls.") # ---------------------------- Binary search through system calls binary_search.binary_search_log_events(dbg, testIfTooFar) # We are now at a point in time where at some point after the next # system call the expression will change. We are guaranteed that # the culprit thread is alive, because a "pthread_create" call is # an event in the system call log, and the binary search will # consider that in determining the lower bound. # ---------------------------- Round-robin search for culprit thread if not _reverse_watch_round_robin(dbg, testIfTooFar): fredutil.fred_error("Reverse-watch failed to determine the thread " "which caused the expression '%s' to change." % s_expr) return # At this point, whatever thread we are currently in is the correct thread. fredutil.fred_debug("Identified thread %d as the one changing expr." % dbg.get_current_thread()) fredutil.fred_assert(not testIfTooFar()) dbg.current_checkpoint().set_history( binary_search._binary_search_regular_next_expansion(dbg, testIfTooFar)) dbg.update_state() fredutil.fred_assert(not testIfTooFar()) fredutil.fred_debug("Reverse watch finished.") fredutil.fred_timer_stop("reverse-watch") dbg.report_timing_statistics() return