aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStu Grossman <grossman@cygnus>1994-06-28 23:36:52 +0000
committerStu Grossman <grossman@cygnus>1994-06-28 23:36:52 +0000
commit320f93f7149cbeffb23b93e16ddb92e18f577f16 (patch)
tree76ff6320389d3d9bd471c218fdffa73e0547849c
parentfea3fe6407ef6bb3239c5ff8b91e89b66db45e33 (diff)
downloadgdb-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.
-rw-r--r--gdb/ChangeLog11
-rw-r--r--gdb/dbxread.c44
-rw-r--r--gdb/infrun.c234
-rw-r--r--gdb/lynx-nat.c46
4 files changed, 186 insertions, 149 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 4d84f37..2a65fb5 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,14 @@
+Tue Jun 28 15:28:01 1994 Stu Grossman (grossman@cygnus.com)
+
+ * 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.
+
Mon Jun 27 09:57:23 1994 Steve Chamberlain (sac@cirdan.cygnus.com)
* ser-go32.c: Rewrite to run under windows.
diff --git a/gdb/dbxread.c b/gdb/dbxread.c
index a77f646..5445c8a 100644
--- a/gdb/dbxread.c
+++ b/gdb/dbxread.c
@@ -1903,11 +1903,16 @@ process_one_symbol (type, desc, valu, name, section_offsets, objfile)
end_symtab (valu, 0, 0, objfile, SECT_OFF_TEXT);
end_stabs ();
}
+
+ /* Null name means this just marks the end of text for this .o file.
+ Don't start a new symtab in this case. */
+ if (*name == '\000')
+ break;
+
start_stabs ();
start_symtab (name, NULL, valu);
break;
-
case N_SOL:
/* This type of symbol indicates the start of data for
a sub-source-file, one whose contents were copied or
@@ -2358,12 +2363,13 @@ elfstab_build_psymtabs (objfile, section_offsets, mainline,
void
stabsect_build_psymtabs (objfile, section_offsets, mainline, stab_name,
- stabstr_name)
+ stabstr_name, text_name)
struct objfile *objfile;
struct section_offsets *section_offsets;
int mainline;
char *stab_name;
char *stabstr_name;
+ char *text_name;
{
int val;
bfd *sym_bfd = objfile->obfd;
@@ -2384,9 +2390,9 @@ stabsect_build_psymtabs (objfile, section_offsets, mainline, stab_name,
objfile->sym_stab_info = (PTR) xmalloc (sizeof (struct dbx_symfile_info));
memset (DBX_SYMFILE_INFO (objfile), 0, sizeof (struct dbx_symfile_info));
- DBX_TEXT_SECT (objfile) = bfd_get_section_by_name (sym_bfd, ".text");
+ DBX_TEXT_SECT (objfile) = bfd_get_section_by_name (sym_bfd, text_name);
if (!DBX_TEXT_SECT (objfile))
- error ("Can't find .text section in symbol file");
+ error ("Can't find %s section in symbol file", text_name);
DBX_SYMBOL_SIZE (objfile) = sizeof (struct external_nlist);
DBX_SYMCOUNT (objfile) = bfd_section_size (sym_bfd, stabsect)
@@ -2422,36 +2428,6 @@ stabsect_build_psymtabs (objfile, section_offsets, mainline, stab_name,
dbx_symfile_read (objfile, section_offsets, 0);
}
-/* Scan and build partial symbols for a SOM symbol file.
- This SOM file has already been processed to get its minimal symbols.
-
- OBJFILE is the object file we are reading symbols from.
- ADDR is the address relative to which the symbols are (e.g.
- the base address of the text segment).
- MAINLINE is true if we are reading the main symbol
- table (as opposed to a shared lib or dynamically loaded file).
-
- */
-
-void
-somstab_build_psymtabs (objfile, section_offsets, mainline)
- struct objfile *objfile;
- struct section_offsets *section_offsets;
- int mainline;
-{
- free_header_files ();
- init_header_files ();
-
- /* This is needed to debug objects assembled with gas2. */
- processing_acc_compilation = 1;
-
- /* In a SOM file, we've already installed the minimal symbols that came
- from the SOM (non-stab) symbol table, so always act like an
- incremental load here. */
-
- dbx_symfile_read (objfile, section_offsets, mainline);
-}
-
/* Parse the user's idea of an offset for dynamic linking, into our idea
of how to represent it for fast symbol reading. */
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
diff --git a/gdb/lynx-nat.c b/gdb/lynx-nat.c
index 49f361d..3d7c92d 100644
--- a/gdb/lynx-nat.c
+++ b/gdb/lynx-nat.c
@@ -597,7 +597,7 @@ child_wait (pid, ourstatus)
{
int save_errno;
int thread;
- int status;
+ union wait status;
while (1)
{
@@ -632,8 +632,7 @@ child_wait (pid, ourstatus)
if (pid != PIDGET (inferior_pid)) /* Some other process?!? */
continue;
-/* thread = WIFTID (status);*/
- thread = status >> 16;
+ thread = status.w_tid; /* Get thread id from status */
/* Initial thread value can only be acquired via wait, so we have to
resort to this hack. */
@@ -646,7 +645,26 @@ child_wait (pid, ourstatus)
pid = BUILDPID (pid, thread);
- store_waitstatus (ourstatus, status);
+ if (WIFSTOPPED(status)
+ && WSTOPSIG(status) == SIGTRAP
+ && !in_thread_list (pid))
+ {
+ int realsig;
+
+ realsig = ptrace (PTRACE_GETTRACESIG, pid, 0);
+
+ if (realsig == SIGNEWTHREAD)
+ {
+ /* Simply ignore new thread notification, as we can't do anything
+ useful with such threads. All ptrace calls at this point just
+ fail for no apparent reason. The thread will eventually get a
+ real signal when it becomes real. */
+ child_resume (pid, 0, TARGET_SIGNAL_0);
+ continue;
+ }
+ }
+
+ store_waitstatus (ourstatus, status.w_status);
return pid;
}
@@ -662,13 +680,18 @@ child_resume (pid, step, signal)
int step;
enum target_signal signal;
{
+ int func;
+
errno = 0;
if (pid == -1)
- /* Resume all threads. */
- /* I think this only gets used in the non-threaded case, where "resume
- all threads" and "resume inferior_pid" are the same. */
- pid = inferior_pid;
+ {
+ /* Resume all threads. */
+
+ pid = inferior_pid;
+ }
+
+ func = step ? PTRACE_SINGLESTEP_ONE : PTRACE_CONT;
/* An address of (PTRACE_ARG3_TYPE)1 tells ptrace to continue from where
it was. (If GDB wanted it to start some other way, we have already
@@ -679,12 +702,7 @@ child_resume (pid, step, signal)
continue request (by setting breakpoints on all possible successor
instructions), so we don't have to worry about that here. */
- if (step)
- ptrace (PTRACE_SINGLESTEP_ONE, pid, (PTRACE_ARG3_TYPE) 1,
- target_signal_to_host (signal));
- else
- ptrace (PTRACE_CONT_ONE, pid, (PTRACE_ARG3_TYPE) 1,
- target_signal_to_host (signal));
+ ptrace (func, pid, (PTRACE_ARG3_TYPE) 1, target_signal_to_host (signal));
if (errno)
perror_with_name ("ptrace");