X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Finfrun.c;h=d6075770ac6ec9ce92092788651a40df4bc449a2;hb=43841e9116d121fa81a351b66ec9e0821a1b4be8;hp=9a8ee54e8601cb6a40f6ab8194d2209b2fb42092;hpb=dfcd3bfb6f8a213007c20e60060b4e9ec9205205;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/infrun.c b/gdb/infrun.c index 9a8ee54e86..d6075770ac 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -25,7 +25,7 @@ #include "frame.h" #include "inferior.h" #include "breakpoint.h" -#include "wait.h" +#include "gdb_wait.h" #include "gdbcore.h" #include "gdbcmd.h" #include "target.h" @@ -46,7 +46,7 @@ static void sig_print_info (enum target_signal); static void sig_print_header (void); -static void resume_cleanups (int); +static void resume_cleanups (void *); static int hook_stop_stub (void *); @@ -296,6 +296,13 @@ a command like `return' or `jump' to continue execution.\n"); #define HAVE_CONTINUABLE_WATCHPOINT 1 #endif +#ifndef CANNOT_STEP_HW_WATCHPOINTS +#define CANNOT_STEP_HW_WATCHPOINTS 0 +#else +#undef CANNOT_STEP_HW_WATCHPOINTS +#define CANNOT_STEP_HW_WATCHPOINTS 1 +#endif + /* Tables of how to react to signals; the user sets them. */ static unsigned char *signal_stop; @@ -429,13 +436,13 @@ static int follow_vfork_when_exec; static char *follow_fork_mode_kind_names[] = { -/* ??rehrauer: The "both" option is broken, by what may be a 10.20 - kernel problem. It's also not terribly useful without a GUI to - help the user drive two debuggers. So for now, I'm disabling - the "both" option. - "parent", "child", "both", "ask" }; - */ - "parent", "child", "ask"}; + /* ??rehrauer: The "both" option is broken, by what may be a 10.20 + kernel problem. It's also not terribly useful without a GUI to + help the user drive two debuggers. So for now, I'm disabling the + "both" option. */ + /* "parent", "child", "both", "ask" */ + "parent", "child", "ask", NULL +}; static char *follow_fork_mode_string = NULL; @@ -745,7 +752,7 @@ static int singlestep_breakpoints_inserted_p = 0; /* Things to clean up if we QUIT out of resume (). */ /* ARGSUSED */ static void -resume_cleanups (int arg) +resume_cleanups (void *ignore) { normal_stop (); } @@ -755,7 +762,12 @@ static char schedlock_on[] = "on"; static char schedlock_step[] = "step"; static char *scheduler_mode = schedlock_off; static char *scheduler_enums[] = -{schedlock_off, schedlock_on, schedlock_step}; +{ + schedlock_off, + schedlock_on, + schedlock_step, + NULL +}; static void set_schedlock_func (char *args, int from_tty, struct cmd_list_element *c) @@ -784,8 +796,7 @@ void resume (int step, enum target_signal sig) { int should_resume = 1; - struct cleanup *old_cleanups = make_cleanup ((make_cleanup_func) - resume_cleanups, 0); + struct cleanup *old_cleanups = make_cleanup (resume_cleanups, 0); QUIT; #ifdef CANNOT_STEP_BREAKPOINT @@ -796,6 +807,18 @@ resume (int step, enum target_signal sig) step = 0; #endif + /* Some targets (e.g. Solaris x86) have a kernel bug when stepping + over an instruction that causes a page fault without triggering + a hardware watchpoint. The kernel properly notices that it shouldn't + stop, because the hardware watchpoint is not triggered, but it forgets + the step request and continues the program normally. + Work around the problem by removing hardware watchpoints if a step is + requested, GDB will check for a hardware watchpoint trigger after the + step anyway. */ + if (CANNOT_STEP_HW_WATCHPOINTS && step && breakpoints_inserted) + remove_hw_watchpoints (); + + /* Normally, by the time we reach `resume', the breakpoints are either removed or inserted, as appropriate. The exception is if we're sitting at a permanent breakpoint; we need to step over it, but permanent @@ -1025,9 +1048,11 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step) int temp = insert_breakpoints (); if (temp) { - print_sys_errmsg ("ptrace", temp); + print_sys_errmsg ("insert_breakpoints", temp); error ("Cannot insert breakpoints.\n\ -The same program may be running in another process."); +The same program may be running in another process,\n\ +or you may have requested too many hardware\n\ +breakpoints and/or watchpoints.\n"); } breakpoints_inserted = 1; @@ -1536,12 +1561,12 @@ handle_inferior_event (struct execution_control_state *ecs) stop_signal = ecs->ws.value.sig; target_terminal_ours (); /* Must do this before mourn anyway */ - /* This looks pretty bogus to me. Doesn't TARGET_WAITKIND_SIGNALLED - mean it is already dead? This has been here since GDB 2.8, so - perhaps it means rms didn't understand unix waitstatuses? - For the moment I'm just kludging around this in remote.c - rather than trying to change it here --kingdon, 5 Dec 1994. */ - target_kill (); /* kill mourns as well */ + /* Note: By definition of TARGET_WAITKIND_SIGNALLED, we shouldn't + reach here unless the inferior is dead. However, for years + target_kill() was called here, which hints that fatal signals aren't + really fatal on some systems. If that's true, then some changes + may be needed. */ + target_mourn_inferior (); print_stop_reason (SIGNAL_EXITED, stop_signal); singlestep_breakpoints_inserted_p = 0; /*SOFTWARE_SINGLE_STEP_P */ @@ -2248,6 +2273,8 @@ handle_inferior_event (struct execution_control_state *ecs) the HP-UX maintainer to furnish a fix that doesn't break other platforms. --JimB, 20 May 1999 */ check_sigtramp2 (ecs); + keep_going (ecs); + return; } /* Handle cases caused by hitting a breakpoint. */ @@ -2719,6 +2746,20 @@ handle_inferior_event (struct execution_control_state *ecs) if (step_over_calls > 0 || IGNORE_HELPER_CALL (stop_pc)) { /* We're doing a "next". */ + + if (IN_SIGTRAMP (stop_pc, ecs->stop_func_name) + && INNER_THAN (step_frame_address, read_sp())) + /* We stepped out of a signal handler, and into its + calling trampoline. This is misdetected as a + subroutine call, but stepping over the signal + trampoline isn't such a bad idea. In order to do + that, we have to ignore the value in + step_frame_address, since that doesn't represent the + frame that'll reach when we return from the signal + trampoline. Otherwise we'll probably continue to the + end of the program. */ + step_frame_address = 0; + step_over_function (ecs); keep_going (ecs); return; @@ -3019,7 +3060,7 @@ step_over_function (struct execution_control_state *ecs) step_resume_breakpoint = set_momentary_breakpoint (sr_sal, get_current_frame (), bp_step_resume); - if (!IN_SOLIB_DYNSYM_RESOLVE_CODE (sr_sal.pc)) + if (step_frame_address && !IN_SOLIB_DYNSYM_RESOLVE_CODE (sr_sal.pc)) step_resume_breakpoint->frame = step_frame_address; if (breakpoints_inserted) @@ -3223,6 +3264,13 @@ print_stop_reason (enum inferior_stop_reason stop_reason, int stop_info) case END_STEPPING_RANGE: /* We are done with a step/next/si/ni command. */ /* For now print nothing. */ +#ifdef UI_OUT + /* Print a message only if not in the middle of doing a "step n" + operation for n > 1 */ + if (!step_multi || !stop_step) + if (interpreter_p && strcmp (interpreter_p, "mi") == 0) + ui_out_field_string (uiout, "reason", "end-stepping-range"); +#endif break; case BREAKPOINT_HIT: /* We found a breakpoint. */ @@ -3232,6 +3280,8 @@ print_stop_reason (enum inferior_stop_reason stop_reason, int stop_info) /* The inferior was terminated by a signal. */ #ifdef UI_OUT annotate_signalled (); + if (interpreter_p && strcmp (interpreter_p, "mi") == 0) + ui_out_field_string (uiout, "reason", "exited-signalled"); ui_out_text (uiout, "\nProgram terminated with signal "); annotate_signal_name (); ui_out_field_string (uiout, "signal-name", target_signal_to_name (stop_info)); @@ -3264,12 +3314,16 @@ print_stop_reason (enum inferior_stop_reason stop_reason, int stop_info) annotate_exited (stop_info); if (stop_info) { + if (interpreter_p && strcmp (interpreter_p, "mi") == 0) + ui_out_field_string (uiout, "reason", "exited"); ui_out_text (uiout, "\nProgram exited with code "); ui_out_field_fmt (uiout, "exit-code", "0%o", (unsigned int) stop_info); ui_out_text (uiout, ".\n"); } else { + if (interpreter_p && strcmp (interpreter_p, "mi") == 0) + ui_out_field_string (uiout, "reason", "exited-normally"); ui_out_text (uiout, "\nProgram exited normally.\n"); } #else @@ -3351,9 +3405,11 @@ normal_stop (void) if (breakpoints_failed) { target_terminal_ours_for_output (); - print_sys_errmsg ("ptrace", breakpoints_failed); + print_sys_errmsg ("While inserting breakpoints", breakpoints_failed); printf_filtered ("Stopped; cannot insert breakpoints.\n\ -The same program may be running in another process.\n"); +The same program may be running in another process,\n\ +or you may have requested too many hardware breakpoints\n\ +and/or watchpoints.\n"); } if (target_has_execution && breakpoints_inserted) @@ -3416,7 +3472,8 @@ The same program may be running in another process.\n"); bpstat_print() contains the logic deciding in detail what to print, based on the event(s) that just occurred. */ - if (stop_print_frame) + if (stop_print_frame + && selected_frame) { int bpstat_ret; int source_flag; @@ -3445,7 +3502,17 @@ The same program may be running in another process.\n"); default: internal_error ("Unknown value."); } +#ifdef UI_OUT + /* For mi, have the same behavior every time we stop: + print everything but the source line. */ + if (interpreter_p && strcmp (interpreter_p, "mi") == 0) + source_flag = LOC_AND_ADDRESS; +#endif +#ifdef UI_OUT + if (interpreter_p && strcmp (interpreter_p, "mi") == 0) + ui_out_field_int (uiout, "thread-id", pid_to_thread_id (inferior_pid)); +#endif /* The behavior of this routine with respect to the source flag is: SRC_LINE: Print only source line @@ -4046,6 +4113,18 @@ restore_inferior_status (struct inferior_status *inf_status) free_inferior_status (inf_status); } +static void +do_restore_inferior_status_cleanup (void *sts) +{ + restore_inferior_status (sts); +} + +struct cleanup * +make_cleanup_restore_inferior_status (struct inferior_status *inf_status) +{ + return make_cleanup (do_restore_inferior_status_cleanup, inf_status); +} + void discard_inferior_status (struct inferior_status *inf_status) { @@ -4199,7 +4278,7 @@ to the user would be loading/unloading of a new library.\n", c = add_set_enum_cmd ("follow-fork-mode", class_run, follow_fork_mode_kind_names, - (char *) &follow_fork_mode_string, + &follow_fork_mode_string, /* ??rehrauer: The "both" option is broken, by what may be a 10.20 kernel problem. It's also not terribly useful without a GUI to help the user drive two debuggers. So for now, I'm disabling @@ -4234,7 +4313,7 @@ By default, the debugger will follow the parent process.", c = add_set_enum_cmd ("scheduler-locking", class_run, scheduler_enums, /* array of string names */ - (char *) &scheduler_mode, /* current mode */ + &scheduler_mode, /* current mode */ "Set mode for locking scheduler during execution.\n\ off == no locking (threads may preempt at any time)\n\ on == full locking (no thread except the current thread may run)\n\