diff options
Diffstat (limited to 'gdb/infrun.c')
-rw-r--r-- | gdb/infrun.c | 112 |
1 files changed, 103 insertions, 9 deletions
diff --git a/gdb/infrun.c b/gdb/infrun.c index 2960acb2a8f..e7d1decc65e 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -1360,7 +1360,9 @@ enum inferior_stop_reason /* Inferior exited. */ EXITED, /* Inferior received signal, and user asked to be notified. */ - SIGNAL_RECEIVED + SIGNAL_RECEIVED, + /* Reverse execution -- target ran out of history info. */ + NO_HISTORY }; /* This structure contains what used to be local variables in @@ -1980,6 +1982,12 @@ handle_inferior_event (struct execution_control_state *ecs) stop_signal = ecs->ws.value.sig; break; + case TARGET_WAITKIND_NO_HISTORY: + /* Reverse execution: target ran out of history info. */ + print_stop_reason (NO_HISTORY, 0); + stop_stepping (ecs); + return; + /* We had an event in the inferior, but we are not interested in handling it at this level. The lower layers have already done what needs to be done, if anything. @@ -2687,6 +2695,17 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n"); keep_going (ecs); return; } + if (stop_pc == ecs->stop_func_start && + target_get_execution_direction () == EXEC_REVERSE) + { + /* We are stepping over a function call in reverse, and + just hit the step-resume breakpoint at the start + address of the function. Go back to single-stepping, + which should take us back to the function call. */ + ecs->stepping_over_breakpoint = 1; + keep_going (ecs); + return; + } break; case BPSTAT_WHAT_CHECK_SHLIBS: @@ -2852,7 +2871,22 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n"); fprintf_unfiltered (gdb_stdlog, "infrun: stepping inside range [0x%s-0x%s]\n", paddr_nz (step_range_start), paddr_nz (step_range_end)); - keep_going (ecs); + + /* When stepping backward, stop at beginning of line range + (unles it's the function entry point, in which case + keep going back to the call point). */ + if (stop_pc == step_range_start && + stop_pc != ecs->stop_func_start && + target_get_execution_direction () == EXEC_REVERSE) + { + stop_step = 1; + print_stop_reason (END_STEPPING_RANGE, 0); + stop_stepping (ecs); + } + else + { + keep_going (ecs); + } return; } @@ -2941,10 +2975,31 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n"); if (step_over_calls == STEP_OVER_ALL) { - /* We're doing a "next", set a breakpoint at callee's return - address (the address at which the caller will - resume). */ - insert_step_resume_breakpoint_at_caller (get_current_frame ()); + /* We're doing a "next". + + Normal (forward) execution: set a breakpoint at the + callee's return address (the address at which the caller + will resume). + + Reverse (backward) execution. set the step-resume + breakpoint at the start of the function that we just + stepped into (backwards), and continue to there. When we + get there, we'll need to single-step back to the + caller. */ + + if (target_get_execution_direction () == EXEC_REVERSE) + { + /* FIXME: I'm not sure if we've handled the frame for + recursion. */ + + struct symtab_and_line sr_sal; + init_sal (&sr_sal); + sr_sal.pc = ecs->stop_func_start; + insert_step_resume_breakpoint_at_sal (sr_sal, null_frame_id); + } + else + insert_step_resume_breakpoint_at_caller (get_current_frame ()); + keep_going (ecs); return; } @@ -3006,9 +3061,22 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n"); return; } - /* Set a breakpoint at callee's return address (the address at - which the caller will resume). */ - insert_step_resume_breakpoint_at_caller (get_current_frame ()); + if (target_get_execution_direction () == EXEC_REVERSE) + { + /* Set a breakpoint at callee's start address. + From there we can step once and be back in the caller. */ + /* FIXME: I'm not sure we've handled the frame for recursion. */ + struct symtab_and_line sr_sal; + init_sal (&sr_sal); + sr_sal.pc = ecs->stop_func_start; + insert_step_resume_breakpoint_at_sal (sr_sal, null_frame_id); + } + else + { + /* Set a breakpoint at callee's return address (the address + at which the caller will resume). */ + insert_step_resume_breakpoint_at_caller (get_current_frame ()); + } keep_going (ecs); return; } @@ -3201,6 +3269,28 @@ step_into_function (struct execution_control_state *ecs) ecs->stop_func_start = gdbarch_skip_prologue (current_gdbarch, ecs->stop_func_start); + if (target_get_execution_direction () == EXEC_REVERSE) + { + ecs->sal = find_pc_line (stop_pc, 0); + + /* OK, we're just gonna keep stepping here. */ + if (ecs->sal.pc == stop_pc) + { + /* We're there already. Just stop stepping now. */ + stop_step = 1; + print_stop_reason (END_STEPPING_RANGE, 0); + stop_stepping (ecs); + return; + } + /* Else just reset the step range and keep going. + No step-resume breakpoint, they don't work for + epilogues, which can have multiple entry paths. */ + step_range_start = ecs->sal.pc; + step_range_end = ecs->sal.end; + keep_going (ecs); + return; + } + /* else... */ ecs->sal = find_pc_line (ecs->stop_func_start, 0); /* Use the step_resume_break to step until the end of the prologue, even if that involves jumps (as it seems to on the vax under @@ -3566,6 +3656,10 @@ print_stop_reason (enum inferior_stop_reason stop_reason, int stop_info) annotate_signal_string_end (); ui_out_text (uiout, ".\n"); break; + case NO_HISTORY: + /* Reverse execution: target ran out of history info. */ + ui_out_text (uiout, "\nNo more reverse-execution history.\n"); + break; default: internal_error (__FILE__, __LINE__, _("print_stop_reason: unrecognized enum value")); |