diff options
author | Stu Grossman <grossman@cygnus> | 1994-06-28 23:36:52 +0000 |
---|---|---|
committer | Stu Grossman <grossman@cygnus> | 1994-06-28 23:36:52 +0000 |
commit | 320f93f7149cbeffb23b93e16ddb92e18f577f16 (patch) | |
tree | 76ff6320389d3d9bd471c218fdffa73e0547849c /gdb/infrun.c | |
parent | fea3fe6407ef6bb3239c5ff8b91e89b66db45e33 (diff) | |
download | gdb-320f93f7149cbeffb23b93e16ddb92e18f577f16.zip gdb-320f93f7149cbeffb23b93e16ddb92e18f577f16.tar.gz gdb-320f93f7149cbeffb23b93e16ddb92e18f577f16.tar.bz2 |
* dbxread.c, partial-stab.h (near N_SO): SO stabs with blank
names mean end of .o file.
* infrun.c (wait_for_inferior): Clean up multi-thread logic near
top of routine. Handle new thread notification cleanly.
* lynx-nat.c (child_wait): General cleanups, handle new LynxOS
thread notification scheme.
* (child_resume): General cleanups, handle resumption of all
threads properly.
Diffstat (limited to 'gdb/infrun.c')
-rw-r--r-- | gdb/infrun.c | 234 |
1 files changed, 133 insertions, 101 deletions
diff --git a/gdb/infrun.c b/gdb/infrun.c index 08e3bfd..9a9e35c 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -294,6 +294,24 @@ proceed (addr, siggnal, step) else write_pc (addr); +#ifdef PREPARE_TO_PROCEED + /* In a multi-threaded task we may select another thread and then continue. + + In this case the thread that stopped at a breakpoint will immediately + cause another stop, if it is not stepped over first. On the other hand, + if (ADDR != -1) we only want to single step over the breakpoint if we did + switch to another thread. + + If we are single stepping, don't do any of the above. + (Note that in the current implementation single stepping another + thread after a breakpoint and then continuing will cause the original + breakpoint to be hit again, but you can always continue, so it's not + a big deal.) */ + + if (! step && PREPARE_TO_PROCEED && breakpoint_here_p (read_pc ())) + oneproc = 1; +#endif /* PREPARE_TO_PROCEED */ + if (trap_expected_after_continue) { /* If (step == 0), a trap will be automatically generated after @@ -437,11 +455,25 @@ wait_for_inferior () while (1) { + /* We have to invalidate the registers BEFORE calling target_wait because + they can be loaded from the target while in target_wait. This makes + remote debugging a bit more efficient for those targets that provide + critical registers as part of their normal status mechanism. */ + + registers_changed (); + pid = target_wait (-1, &w); - /* Clean up saved state that will become invalid. */ flush_cached_frames (); - registers_changed (); + + /* If it's a new process, add it to the thread database */ + + if (pid != inferior_pid + && !in_thread_list (pid)) + { + fprintf_unfiltered (gdb_stderr, "[New %s]\n", target_pid_to_str (pid)); + add_thread (pid); + } switch (w.kind) { @@ -507,125 +539,104 @@ wait_for_inferior () stop_signal = w.value.sig; - if (pid != inferior_pid) - { - int save_pid = inferior_pid; + stop_pc = read_pc_pid (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 (); + /* See if a thread hit a thread-specific breakpoint that was meant for + another thread. If so, then step that thread past the breakpoint, + and continue it. */ if (stop_signal == TARGET_SIGNAL_TRAP + && breakpoints_inserted && breakpoint_here_p (stop_pc - DECR_PC_AFTER_BREAK)) { + random_signal = 0; 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) - { - if (pid != inferior_pid) - { - int save_pid = inferior_pid; - - inferior_pid = pid; - registers_changed (); - write_pc (stop_pc - DECR_PC_AFTER_BREAK); - inferior_pid = save_pid; - registers_changed (); - } - else - write_pc (stop_pc - DECR_PC_AFTER_BREAK); - - remove_breakpoints (); - target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */ - /* FIXME: What if a signal arrives instead of the single-step - happening? */ - target_wait (pid, &w); - insert_breakpoints (); - } - target_resume (-1, 0, TARGET_SIGNAL_0); + write_pc (stop_pc - DECR_PC_AFTER_BREAK); + + remove_breakpoints (); + target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */ + /* FIXME: What if a signal arrives instead of the single-step + happening? */ + target_wait (pid, &w); + insert_breakpoints (); + target_resume (pid, 0, TARGET_SIGNAL_0); continue; } - else - if (pid != inferior_pid) - goto switch_thread; } + else + random_signal = 1; + + /* See if something interesting happened to the non-current thread. If + so, then switch to that thread, and eventually give control back to + the user. */ if (pid != inferior_pid) { int printed = 0; - if (!in_thread_list (pid)) + /* If it's a random signal for a non-current thread, notify user + if he's expressed an interest. */ + + if (random_signal + && signal_print[stop_signal]) { - fprintf_unfiltered (gdb_stderr, "[New %s]\n", target_pid_to_str (pid)); - add_thread (pid); + printed = 1; + target_terminal_ours_for_output (); + printf_filtered ("\nProgram received signal %s, %s.\n", + target_signal_to_name (stop_signal), + target_signal_to_string (stop_signal)); + gdb_flush (gdb_stdout); + } + + /* If it's not SIGTRAP and not a signal we want to stop for, then + continue the thread. */ + + if (stop_signal != TARGET_SIGNAL_TRAP + && !signal_stop[stop_signal]) + { + if (printed) + target_terminal_inferior (); - target_resume (-1, 0, TARGET_SIGNAL_0); + /* Clear the signal if it should not be passed. */ + if (signal_program[stop_signal] == 0) + stop_signal = TARGET_SIGNAL_0; + + target_resume (pid, 0, stop_signal); continue; } - else + + /* It's a SIGTRAP or a signal we're interested in. Switch threads, + and fall into the rest of wait_for_inferior(). */ + + inferior_pid = pid; + printf_filtered ("[Switching to %s]\n", target_pid_to_str (pid)); + + flush_cached_frames (); + trap_expected = 0; + if (step_resume_breakpoint) { - if (signal_print[stop_signal]) - { - printed = 1; - target_terminal_ours_for_output (); - printf_filtered ("\nProgram received signal %s, %s.\n", - target_signal_to_name (stop_signal), - target_signal_to_string (stop_signal)); - gdb_flush (gdb_stdout); - } - - if (stop_signal == TARGET_SIGNAL_TRAP - || signal_stop[stop_signal]) - { -switch_thread: - inferior_pid = pid; - printf_filtered ("[Switching to %s]\n", target_pid_to_str (pid)); - - flush_cached_frames (); - registers_changed (); - trap_expected = 0; - if (step_resume_breakpoint) - { - delete_breakpoint (step_resume_breakpoint); - step_resume_breakpoint = NULL; - } - - /* Not sure whether we need to blow this away too, - but probably it is like the step-resume - breakpoint. */ - if (through_sigtramp_breakpoint) - { - delete_breakpoint (through_sigtramp_breakpoint); - through_sigtramp_breakpoint = NULL; - } - prev_pc = 0; - prev_sp = 0; - prev_func_name = NULL; - step_range_start = 0; - step_range_end = 0; - step_frame_address = 0; - handling_longjmp = 0; - another_trap = 0; - } - else - { - if (printed) - target_terminal_inferior (); - - /* Clear the signal if it should not be passed. */ - if (signal_program[stop_signal] == 0) - stop_signal = TARGET_SIGNAL_0; - - target_resume (pid, 0, stop_signal); - continue; - } + delete_breakpoint (step_resume_breakpoint); + step_resume_breakpoint = NULL; } + + /* Not sure whether we need to blow this away too, + but probably it is like the step-resume + breakpoint. */ + if (through_sigtramp_breakpoint) + { + delete_breakpoint (through_sigtramp_breakpoint); + through_sigtramp_breakpoint = NULL; + } + prev_pc = 0; + prev_sp = 0; + prev_func_name = NULL; + step_range_start = 0; + step_range_end = 0; + step_frame_address = 0; + handling_longjmp = 0; + another_trap = 0; } #ifdef NO_SINGLE_STEP @@ -1061,12 +1072,19 @@ switch_thread: goto keep_going; } +#if 1 if (stop_func_start) { + struct symtab *s; + /* Do this after the IN_SIGTRAMP check; it might give an error. */ prologue_pc = stop_func_start; - SKIP_PROLOGUE (prologue_pc); + + /* Don't skip the prologue if this is assembly source */ + s = find_pc_symtab (stop_pc); + if (s && s->language != language_asm) + SKIP_PROLOGUE (prologue_pc); } if ((/* Might be a non-recursive call. If the symbols are missing @@ -1105,6 +1123,14 @@ switch_thread: which can no longer happen here as long as the handling_longjmp stuff is working. */ )) +#else +/* This is experimental code which greatly simplifies the subroutine call + test. I've actually tested on the Alpha, and it works great. -Stu */ + + if (in_prologue (stop_pc, NULL) + || (prev_func_start != 0 + && stop_func_start == 0)) +#endif { /* It's a subroutine call. */ @@ -1166,7 +1192,13 @@ step_over_function: step_into_function: /* Subroutine call with source code we should not step over. Do step to the first line of code in it. */ - SKIP_PROLOGUE (stop_func_start); + { + struct symtab *s; + + s = find_pc_symtab (stop_pc); + if (s && s->language != language_asm) + SKIP_PROLOGUE (stop_func_start); + } sal = find_pc_line (stop_func_start, 0); /* Use the step_resume_break to step until the end of the prologue, even if that involves jumps |