* 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.
This commit is contained in:
Stu Grossman 1994-06-28 23:36:52 +00:00
parent fea3fe6407
commit 320f93f714
4 changed files with 186 additions and 149 deletions

View File

@ -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.

View File

@ -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. */

View File

@ -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;
write_pc (stop_pc - DECR_PC_AFTER_BREAK);
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);
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))
{
fprintf_unfiltered (gdb_stderr, "[New %s]\n", target_pid_to_str (pid));
add_thread (pid);
/* If it's a random signal for a non-current thread, notify user
if he's expressed an interest. */
target_resume (-1, 0, TARGET_SIGNAL_0);
if (random_signal
&& 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 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 ();
/* 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

View File

@ -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");