mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-28 22:40:24 +00:00
* 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:
parent
fea3fe6407
commit
320f93f714
@ -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.
|
||||
|
@ -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. */
|
||||
|
||||
|
234
gdb/infrun.c
234
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;
|
||||
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
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user