X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gdb%2Finfrun.c;h=85ebb38f108699b5e3d90290c2ef1786e077e571;hb=100f92e2dea21ccb7de8fb0cb3a9b70d43d55bad;hp=e32d70574a3101f0cbcbed3dbf6e17da7484ba51;hpb=3f0184acb02f2a390e7d7a4c34594a55d5d99963;p=binutils-gdb.git diff --git a/gdb/infrun.c b/gdb/infrun.c index e32d70574a3..85ebb38f108 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -18,90 +18,6 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* Notes on the algorithm used in wait_for_inferior to determine if we - just did a subroutine call when stepping. We have the following - information at that point: - - Current and previous (just before this step) pc. - Current and previous sp. - Current and previous start of current function. - - If the starts of the functions don't match, then - - a) We did a subroutine call. - - In this case, the pc will be at the beginning of a function. - - b) We did a subroutine return. - - Otherwise. - - c) We did a longjmp. - - If we did a longjump, we were doing "nexti", since a next would - have attempted to skip over the assembly language routine in which - the longjmp is coded and would have simply been the equivalent of a - continue. I consider this ok behaivior. We'd like one of two - things to happen if we are doing a nexti through the longjmp() - routine: 1) It behaves as a stepi, or 2) It acts like a continue as - above. Given that this is a special case, and that anybody who - thinks that the concept of sub calls is meaningful in the context - of a longjmp, I'll take either one. Let's see what happens. - - Acts like a subroutine return. I can handle that with no problem - at all. - - -->So: If the current and previous beginnings of the current - function don't match, *and* the pc is at the start of a function, - we've done a subroutine call. If the pc is not at the start of a - function, we *didn't* do a subroutine call. - - -->If the beginnings of the current and previous function do match, - either: - - a) We just did a recursive call. - - In this case, we would be at the very beginning of a - function and 1) it will have a prologue (don't jump to - before prologue, or 2) (we assume here that it doesn't have - a prologue) there will have been a change in the stack - pointer over the last instruction. (Ie. it's got to put - the saved pc somewhere. The stack is the usual place. In - a recursive call a register is only an option if there's a - prologue to do something with it. This is even true on - register window machines; the prologue sets up the new - window. It might not be true on a register window machine - where the call instruction moved the register window - itself. Hmmm. One would hope that the stack pointer would - also change. If it doesn't, somebody send me a note, and - I'll work out a more general theory. - bug-gdb@prep.ai.mit.edu). This is true (albeit slipperly - so) on all machines I'm aware of: - - m68k: Call changes stack pointer. Regular jumps don't. - - sparc: Recursive calls must have frames and therefor, - prologues. - - vax: All calls have frames and hence change the - stack pointer. - - b) We did a return from a recursive call. I don't see that we - have either the ability or the need to distinguish this - from an ordinary jump. The stack frame will be printed - when and if the frame pointer changes; if we are in a - function without a frame pointer, it's the users own - lookout. - - c) We did a jump within a function. We assume that this is - true if we didn't do a recursive call. - - d) We are in no-man's land ("I see no symbols here"). We - don't worry about this; it will make calls look like simple - jumps (and the stack frames will be printed when the frame - pointer moves), which is a reasonably non-violent response. -*/ - #include "defs.h" #include #include @@ -113,6 +29,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "gdbcore.h" #include "gdbcmd.h" #include "target.h" +#include "thread.h" #include @@ -306,7 +223,7 @@ resume (step, sig) /* Install inferior's terminal modes. */ target_terminal_inferior (); - target_resume (inferior_pid, step, sig); + target_resume (-1, step, sig); discard_cleanups (old_cleanups); } @@ -503,7 +420,7 @@ wait_for_inferior () flush_cached_frames (); registers_changed (); - pid = target_wait (&w); + pid = target_wait (-1, &w); #ifdef SIGTRAP_STOP_AFTER_LOAD @@ -559,7 +476,43 @@ wait_for_inferior () #endif break; } - + + stop_signal = WSTOPSIG (w); + + if (pid != inferior_pid) + { + int save_pid = inferior_pid; + + inferior_pid = pid; /* Setup for target memory/regs */ + registers_changed (); + stop_pc = read_pc (); + inferior_pid = save_pid; + registers_changed (); + } + else + stop_pc = read_pc (); + + if (stop_signal == SIGTRAP + && breakpoint_here_p (stop_pc - DECR_PC_AFTER_BREAK)) + if (!breakpoint_thread_match (stop_pc - DECR_PC_AFTER_BREAK, pid)) + { + /* Saw a breakpoint, but it was hit by the wrong thread. Just continue. */ + if (breakpoints_inserted) + { + remove_breakpoints (); + target_resume (pid, 1, 0); /* Single step */ + /* FIXME: What if a signal arrives instead of the single-step + happening? */ + target_wait (pid, NULL); + insert_breakpoints (); + } + target_resume (-1, 0, 0); + continue; + } + else + if (pid != inferior_pid) + goto switch_thread; + if (pid != inferior_pid) { int printed = 0; @@ -569,13 +522,11 @@ wait_for_inferior () fprintf (stderr, "[New %s]\n", target_pid_to_str (pid)); add_thread (pid); - target_resume (pid, 0, 0); + target_resume (-1, 0, 0); continue; } else { - stop_signal = WSTOPSIG (w); - if (stop_signal >= NSIG || signal_print[stop_signal]) { char *signame; @@ -593,8 +544,11 @@ wait_for_inferior () fflush (stdout); } - if (stop_signal >= NSIG || signal_stop[stop_signal]) + if (stop_signal == SIGTRAP + || stop_signal >= NSIG + || signal_stop[stop_signal]) { +switch_thread: inferior_pid = pid; printf_filtered ("[Switching to %s]\n", target_pid_to_str (pid)); @@ -624,7 +578,7 @@ wait_for_inferior () if (signal_program[stop_signal] == 0) stop_signal = 0; - target_resume (pid, 0, stop_signal); + target_resume (-1, 0, stop_signal); continue; } } @@ -644,7 +598,6 @@ wait_for_inferior () continue; } - stop_pc = read_pc (); set_current_frame ( create_new_frame (read_fp (), stop_pc)); stop_frame_address = FRAME_FP (get_current_frame ()); @@ -674,8 +627,6 @@ wait_for_inferior () 3) set random_signal to 1, and the decision between 1 and 2 will be made according to the signal handling tables. */ - stop_signal = WSTOPSIG (w); - /* First, distinguish signals caused by the debugger from signals that have to do with the program's own actions. Note that breakpoint insns may cause SIGTRAP or SIGILL @@ -893,6 +844,9 @@ wait_for_inferior () cleanup chain, so no need to worry about it here. */ goto stop_stepping; + case BPSTAT_WHAT_LAST: + /* Not a real code, but listed here to shut up gcc -Wall. */ + case BPSTAT_WHAT_KEEP_CHECKING: break; } @@ -1015,15 +969,48 @@ wait_for_inferior () SKIP_PROLOGUE (prologue_pc); } - /* ==> See comments at top of file on this algorithm. <==*/ + if ((/* Might be a non-recursive call. If the symbols are missing + enough that stop_func_start == prev_func_start even though + they are really two functions, we will treat some calls as + jumps. */ + stop_func_start != prev_func_start + + /* Might be a recursive call if either we have a prologue + or the call instruction itself saves the PC on the stack. */ + || prologue_pc != stop_func_start + || stop_sp != prev_sp) + && (/* I think this can only happen if stop_func_start is zero + (e.g. stop_pc is in some objfile we don't know about). + If the stop_pc does that (ends up someplace unknown), it + must be some sort of subroutine call. */ + stop_pc < stop_func_start + || stop_pc >= stop_func_end + + /* If we do a call, we will be at the start of a function. */ + || stop_pc == stop_func_start + +#if 0 + /* Not conservative enough for 4.11. FIXME: enable this + after 4.11. */ + /* Except on the Alpha with -O (and perhaps other machines + with similar calling conventions), in which we might + call the address after the load of gp. Since prologues + don't contain calls, we can't return to within one, and + we don't jump back into them, so this check is OK. */ + || stop_pc < prologue_pc +#endif - if ((stop_pc < stop_func_start - || stop_pc >= stop_func_end - || stop_pc == stop_func_start - || IN_SOLIB_TRAMPOLINE (stop_pc, stop_func_name)) - && (stop_func_start != prev_func_start - || prologue_pc != stop_func_start - || stop_sp != prev_sp)) + /* If we end up in certain places, it means we did a subroutine + call. I'm not completely sure this is necessary now that we + have the above checks with stop_func_start (and now that + find_pc_partial_function is pickier). */ + || IN_SOLIB_TRAMPOLINE (stop_pc, stop_func_name) + + /* If none of the above apply, it is a jump within a function, + or a return from a subroutine. The other case is longjmp, + which can no longer happen here as long as the + handling_longjmp stuff is working. */ + )) { /* It's a subroutine call. */ @@ -1598,7 +1585,7 @@ handle_command (args, from_tty) argv++; } - target_notice_signals(); + target_notice_signals(inferior_pid); if (from_tty) {