Changes from the FSF for Hurd thread support.

This commit is contained in:
Stu Grossman 1996-07-17 06:03:26 +00:00
parent 9498be1a05
commit 647e52ea3a
10 changed files with 773 additions and 244 deletions

View File

@ -498,6 +498,24 @@ Sun May 26 14:14:49 1996 Fred Fish <fnf@cygnus.com>
* alpha-nat.c: When compiling under Linux, include <asm/reg.h> and
<alpha/ptrace.h> instead of <machine/reg.h>
Tue Jul 2 13:58:10 1996 Miles Bader <miles@gnu.ai.mit.edu>
* gnu-nat.c (inf_validate_task_sc):
Give terminal to gdb while asking question.
(inf_resume): Don't validate the task suspend-count while execing.
Thu Jun 13 11:04:52 1996 Miles Bader <miles@gnu.ai.mit.edu>
* gnu-nat.c (inf_validate_task_sc): Query user before clearing any
additional suspend count.
(S_proc_wait_reply, gnu_attach): Don't call inf_validate_task_sc.
(inf_resume): Call inf_validate_task_sc here.
(gnu_resume): Call inf_update_procs to ensure noticing new threads.
Fri Jun 7 17:00:43 1996 Miles Bader <miles@gnu.ai.mit.edu>
* gnu-nat.c (gnu_create_inferior: attach_to_child): Return PID.
Thu May 23 15:13:56 1996 Jeffrey A Law (law@cygnus.com)
* h8300-tdep.c (IS_PUSH): Refine.
@ -1679,6 +1697,163 @@ Wed Feb 28 22:32:18 1996 Stan Shebs <shebs@andros.cygnus.com>
* remote.c (remote_detach): Send a command 'D' to the target
when detaching, update the function's comments.
Thu Jun 6 16:11:38 1996 Miles Bader <miles@gnu.ai.mit.edu>
* gnu-nat.c (thread_cmd_list): New declaration.
(parse_int_arg): New function.
Wed Jun 5 17:28:04 1996 Miles Bader <miles@gnu.ai.mit.edu>
* gnu-nat.h (struct proc): Add DETACH_SC field.
* gnu-nat.c (make_proc): Set DETACH_SC.
(struct inf): Add DETACH_SC & DEFAULT_THREAD_DETACH_SC fields.
(make_inf): Set DETACH_SC & DEFAULT_THREAD_DETACH_SC fields.
(add_thread_commands): Add set/show for detach-suspend-count.
Add takeover-suspend-count cmd.
(inf_detach): Set suspend counts to the detach SC, not 0.
(set_thread_detach_sc_cmd, show_thread_detach_sc_cmd,
set_task_detach_sc_cmd, show_task_detach_sc_cmd,
set_thread_default_thread_detach_sc_cmd,
show_thread_default_thread_detach_sc_cmd): New functions.
(show_task_cmd): Also show detach-suspend-count values.
(thread_takeover_sc_cmd): New function.
Fri May 31 16:49:24 1996 Miles Bader <miles@gnu.ai.mit.edu>
* gnu-nat.c (show_thread_run_cmd): Actually print state.
Thu May 30 10:47:56 1996 Miles Bader <miles@gnu.ai.mit.edu>
* gnu-nat.c (inf_signal): Make unforwardable exceptions an error.
Tue May 28 17:06:36 1996 Miles Bader <miles@gnu.ai.mit.edu>
* gnu-nat.c (inf_validate_stopped): proc_getprocinfo takes a
pointer to the flags now, not the flags themselves.
Mon May 27 13:31:17 1996 Miles Bader <miles@gnu.ai.mit.edu>
* gnu-nat.c (gnu_wait): Print debugging msgs for pending execs.
(gnu_create_inferior): Check return from ptrace.
Sun May 26 16:56:35 1996 Miles Bader <miles@gnu.ai.mit.edu>
* gnu-nat.h (struct proc): Add DEAD field.
* gnu-nat.c (make_proc): Initialize DEAD.
(inf_set_traced, inf_validate_task_sc, inf_validate_procs: Frob it.
(gnu_wait): Only abort for 0 threads if the task isn't dead.
Sat May 25 17:06:05 1996 Miles Bader <miles@gnu.ai.mit.edu>
* gnu-nat.c (inf_signal): Pass SIGCODE when posting a signal.
Wed May 22 18:44:28 1996 Miles Bader <miles@gnu.ai.mit.edu>
* gnu-nat.c (S_proc_wait_reply): Add SIGCODE argument.
(inf_set_traced): Only give no-signal-thread error message if
turning *on* tracing.
Wed May 15 13:03:16 1996 Miles Bader <miles@gnu.ai.mit.edu>
* gnu-nat.c (inf_validate_procs): If INF has no threads, always
set inf->threads_up_to_date to 0.
(inf_signal): Pass in new SIGCODE argument to msg_sig_post_untraced.
(gnu_wait): Pass in new TIMEOUT arg to interrupt_operation.
(proc_update_sc): Cast thread state arg to thread_set_state.
(proc_get_state): Cast thread state arg to thread_get_state.
(inf_validate_task_sc): Cast task_basic_info arg to task_info.
* i386gnu-nat.c (gnu_fetch_registers, gnu_store_registers): Call
inf_update_procs before we lookup the thread.
* config/i386/i386gnu.mh (MH_CFLAGS): New variable.
Tue May 7 17:52:33 1996 Miles Bader <miles@gnu.ai.mit.edu>
* gnu-nat.c (gnu_kill_inferior): Use inf_set_task to clear the task.
Mon May 6 19:06:49 1996 Miles Bader <miles@gnu.ai.mit.edu>
* gnu-nat.c (inf_set_traced): Use msg_set_init_int with
INIT_TRACEMASK instead of setting the exec flags.
Fri May 3 19:10:57 1996 Miles Bader <miles@gnu.ai.mit.edu>
* gnu-nat.c (inf_validate_procs): Don't clear INF->task if we find
the task's died, so others have a chance at it.
(gnu_resume): When single-stepping a single thread, given an error
if there is no such thread. When single-stepping one but running
the others, just given a warning and still run all the threads.
(gnu_wait): If there seem to be no threads, look harder, and
signal an error if there really aren't any.
(gnu_attach): Reset thread numbering to 0.
* i386gnu-nat.c (gnu_fetch_registers, gnu_store_registers): Give
thread name in warning messages.
* gnu-nat.c (active_inf): New function.
(show_sig_thread_cmd, show_stopped_cmd): Use it.
(info_port_rights, info_send_rights_cmd, info_port_sets_cmd,
info_recv_rights_cmd, info_port_rights_cmd, info_port_rights_cmd):
New functions.
(add_task_commands): Add new port-right info commands.
Fri Apr 26 20:42:16 1996 Miles Bader <miles@gnu.ai.mit.edu>
* gnu-nat.c (gnu_wait): Instead of _hurd_intr_rpc_mach_msg, just
use mach_msg with MACH_RCV_INTERRUPT.
(set_noninvasive_cmd): New function.
(add_task_commands): Add command entry for `set noninvasive'.
Mon Mar 4 14:12:02 1996 Miles Bader <miles@gnu.ai.mit.edu>
* gnu-nat.c (gnu_read_inferior): Use hurd_safe_memmove, not safe_bcopy.
(safe_bcopy): Function removed.
Mon Dec 4 14:18:26 1995 Miles Bader <miles@gnu.ai.mit.edu>
* gnu-nat.c (proc_update_sc): Assert only threads can have state.
(make_proc): Initialize state_valid & state_changed fields.
Tue Nov 28 17:51:21 1995 Miles Bader <miles@gnu.ai.mit.edu>
* reply_mig_hack.awk: New file.
Tue Nov 14 14:31:03 1995 Miles Bader <miles@gnu.ai.mit.edu>
* breakpoint.c (breakpoint_1): Print breakpoint thread field.
* lynx-nat.c (child_wait): Return TARGET_WAITKIND_SPURIOUS for new
threads.
Mon Nov 13 18:30:53 1995 Miles Bader <miles@gnu.ai.mit.edu>
* target.c (debug_to_check_threads): New function.
* inflow.c (terminal_init_inferior_with_pgrp): New function.
(terminal_init_inferior): Call terminal_init_inferior_with_pgrp.
* inferior.h (terminal_init_inferior_with_pgrp): New declaration,
but only if PROCESS_GROUP_TYPE is defined.
Mon Nov 6 16:42:09 1995 Miles Bader <miles@gnu.ai.mit.edu>
* target.c (debug_to_thread_alive): Pass through the return value.
Thu Nov 2 18:05:00 1995 Miles Bader <miles@gnu.ai.mit.edu>
* target.c (signals, target_signal_from_host, target_signal_to_host):
Add mach exceptions.
* target.h (enum target_signal): Add mach exceptions.
Mon Oct 30 16:41:04 1995 Miles Bader <miles@gnu.ai.mit.edu>
* gnu-nat.c: New file: gnu native backend.
* i386gnu-nat.c: New file: i386-specific part of gnu native backend.
* gnu-nat.h: New file.
* config/nm-gnu.h: New file.
* config/tm-i386gnu.h: New file.
* config/xm-i386gnu.h: New file.
* config/i386/i386gnu.mh: New file.
* config/i386/i386gnu.mt: New file.
Wed Feb 28 15:50:12 1996 Fred Fish <fnf@cygnus.com>
* Makefile.in (VERSION): Bump version to 4.15.2 to establish

View File

@ -932,6 +932,11 @@ bpstat_do_actions (bsp)
struct cleanup *old_chain;
struct command_line *cmd;
/* Avoid endless recursion if a `source' command is contained
in bs->commands. */
if (executing_breakpoint_commands)
return;
executing_breakpoint_commands = 1;
old_chain = make_cleanup (cleanup_executing_breakpoints, 0);
@ -1665,7 +1670,7 @@ breakpoint_1 (bnum, allflag)
"watchpoint scope", "call dummy",
"shlib events" };
static char *bpdisps[] = {"del", "dstp", "dis", "keep"};
static char bpenables[] = "ny";
static char bpenables[] = "nyn";
char wrap_indent[80];
ALL_BREAKPOINTS (b)
@ -1794,6 +1799,12 @@ breakpoint_1 (bnum, allflag)
printf_filtered ("\n");
}
if (b->thread != -1)
{
/* FIXME should make an annotation for this */
printf_filtered ("\tstop only in thread %d\n", b->thread);
}
if (show_breakpoint_hit_counts && b->hit_count)
{
/* FIXME should make an annotation for this */

View File

@ -49,6 +49,8 @@
#include <hurd/interrupt.h>
#include <hurd/sigpreempt.h>
#include <portinfo.h>
#include "defs.h"
#include "inferior.h"
#include "symtab.h"
@ -217,10 +219,14 @@ struct inf
(pausing individual threads as necessary). */
int pause_sc;
/* The task suspend count left when detaching from a task. */
int detach_sc;
/* The initial values used for the run_sc and pause_sc of newly discovered
threads -- see the definition of those fields in struct proc. */
int default_thread_run_sc;
int default_thread_pause_sc;
int default_thread_detach_sc;
/* True if the process should be traced when started/attached. Newly
started processes *must* be traced at first to exec them properly, but
@ -255,7 +261,7 @@ proc_update_sc (struct proc *proc)
assert (proc_is_thread (proc));
proc_debug (proc, "storing back changed thread state");
err = thread_set_state (proc->port, THREAD_STATE_FLAVOR,
&proc->state, THREAD_STATE_SIZE);
(thread_state_t)&proc->state, THREAD_STATE_SIZE);
if (! err)
proc->state_changed = 0;
}
@ -353,7 +359,7 @@ proc_get_state (struct proc *proc, int will_modify)
mach_msg_type_number_t state_size = THREAD_STATE_SIZE;
error_t err =
thread_get_state (proc->port, THREAD_STATE_FLAVOR,
&proc->state, &state_size);
(thread_state_t)&proc->state, &state_size);
proc_debug (proc, "getting thread state");
proc->state_valid = !err;
}
@ -362,7 +368,7 @@ proc_get_state (struct proc *proc, int will_modify)
{
if (will_modify)
proc->state_changed = 1;
return &proc->state;
return (thread_state_t)&proc->state;
}
else
return 0;
@ -524,12 +530,19 @@ make_proc (struct inf *inf, mach_port_t port, int tid)
proc->next = 0;
proc->saved_exc_port = MACH_PORT_NULL;
proc->exc_port = MACH_PORT_NULL;
proc->sc = 0;
proc->cur_sc = 0;
/* Note that these are all the values for threads; the task simply uses the
corresponding field in INF directly. */
proc->run_sc = inf->default_thread_run_sc;
proc->pause_sc = inf->default_thread_pause_sc;
proc->detach_sc = inf->default_thread_detach_sc;
proc->resume_sc = proc->run_sc;
proc->aborted = 0;
proc->dead = 0;
proc->state_valid = 0;
proc->state_changed = 0;
@ -623,8 +636,10 @@ struct inf *make_inf ()
inf->no_wait = 0;
inf->pending_execs = 0;
inf->pause_sc = 1;
inf->detach_sc = 0;
inf->default_thread_run_sc = 0;
inf->default_thread_pause_sc = 0;
inf->default_thread_detach_sc = 0;
inf->want_signals = 1; /* By default */
inf->want_exceptions = 1; /* By default */
@ -733,8 +748,9 @@ inf_validate_stopped (struct inf *inf)
mach_msg_type_number_t noise_len = 0;
struct procinfo *pi;
mach_msg_type_number_t pi_len = 0;
int info_flags = 0;
error_t err =
proc_getprocinfo (proc_server, inf->pid, 0,
proc_getprocinfo (proc_server, inf->pid, &info_flags,
(procinfo_t *)&pi, &pi_len, &noise, &noise_len);
if (! err)
@ -746,17 +762,31 @@ inf_validate_stopped (struct inf *inf)
}
}
/* Validates INF's task suspend count. */
/* Validates INF's task suspend count. If it's higher than we expect, verify
with the user before `stealing' the extra count. */
static void
inf_validate_task_sc (struct inf *inf)
{
struct task_basic_info info;
mach_msg_type_number_t info_len = TASK_BASIC_INFO_COUNT;
error_t err = task_info (inf->task->port, TASK_BASIC_INFO, &info, &info_len);
if (! err)
error_t err =
task_info (inf->task->port, TASK_BASIC_INFO, (task_info_t)&info, &info_len);
if (err)
inf->task->dead = 1; /* oh well */
else if (inf->task->cur_sc < info.suspend_count)
{
if (inf->task->cur_sc < info.suspend_count)
warning ("Pid %d is suspended; continuing will clear existing suspend count.", inf->pid);
int abort;
target_terminal_ours (); /* Allow I/O. */
abort =
!query ("Pid %d has an additional task suspend count of %d; clear it? ",
inf->pid, info.suspend_count - inf->task->cur_sc);
target_terminal_inferior (); /* Give it back to the child. */
if (abort)
error ("Additional task suspend count left untouched.");
inf->task->cur_sc = info.suspend_count;
}
}
@ -768,16 +798,20 @@ void
inf_set_traced (struct inf *inf, int on)
{
if (on != inf->traced)
if (inf->task)
if (inf->task && !inf->task->dead)
/* Make it take effect immediately. */
{
error_t (*f)(mach_port_t, mach_port_t, int) =
on ? msg_set_some_exec_flags : msg_clear_some_exec_flags;
sigset_t mask = on ? ~(sigset_t)0 : 0;
error_t err =
INF_RESUME_MSGPORT_RPC (inf, (*f)(msgport, refport, EXEC_TRACED));
INF_RESUME_MSGPORT_RPC (inf, msg_set_init_int (msgport, refport,
INIT_TRACEMASK, mask));
if (err == EIEIO)
warning ("Can't modify tracing state for pid %d: No signal thread",
inf->pid);
{
if (on)
warning ("Can't modify tracing state for pid %d: No signal thread",
inf->pid);
inf->traced = on;
}
else if (err)
warning ("Can't modify tracing state for pid %d: %s",
inf->pid, strerror (err));
@ -875,7 +909,11 @@ inf_validate_procs (struct inf *inf)
unsigned num_threads;
struct proc *task = inf->task;
inf->threads_up_to_date = !inf->running;
/* If no threads are currently running, this function will guarantee that
things are up to date. The exception is if there are zero threads --
then it is almost certainly in an odd state, and probably some outside
agent will create threads. */
inf->threads_up_to_date = inf->threads ? !inf->running : 0;
if (task)
{
@ -884,9 +922,8 @@ inf_validate_procs (struct inf *inf)
if (err)
/* TASK must be dead. */
{
task->port = MACH_PORT_NULL;
_proc_free (task);
task = inf->task = 0;
task->dead = 1;
task = 0;
}
}
@ -996,7 +1033,14 @@ inf_resume (struct inf *inf)
thread->sc = thread->resume_sc;
if (inf->task)
inf->task->sc = 0;
{
if (! inf->pending_execs)
/* Try to make sure our task count is correct -- in the case where
we're waiting for an exec though, things are too volatile, so just
assume things will be reasonable (which they usually will be). */
inf_validate_task_sc (inf);
inf->task->sc = 0;
}
inf_update_suspends (inf);
}
@ -1087,12 +1131,12 @@ inf_detach (struct inf *inf)
inf_signal (inf, TARGET_SIGNAL_0);
proc_restore_exc_port (task);
task->sc = 0;
task->sc = inf->detach_sc;
for (thread = inf->threads; thread; thread = thread->next)
{
proc_restore_exc_port (thread);
thread->sc = 0;
thread->sc = thread->detach_sc;
}
inf_update_suspends (inf);
@ -1188,7 +1232,7 @@ inf_signal (struct inf *inf, enum target_signal sig)
e->exception, e->code, e->subcode);
}
else
warning ("Can't forward spontaneous exception (%s).", NAME);
error ("Can't forward spontaneous exception (%s).", NAME);
}
else
/* A Unix signal. */
@ -1202,7 +1246,7 @@ inf_signal (struct inf *inf, enum target_signal sig)
msg_sig_post_untraced_request (msgport,
inf->event_port,
MACH_MSG_TYPE_MAKE_SEND_ONCE,
host_sig,
host_sig, 0,
refport));
if (! err)
/* Posting an untraced signal automatically continues it.
@ -1220,9 +1264,8 @@ inf_signal (struct inf *inf, enum target_signal sig)
{
inf_debug (inf, "sending %s to unstopped process (so resuming signal thread)", NAME);
err =
INF_RESUME_MSGPORT_RPC (inf,
msg_sig_post_untraced (msgport,
host_sig, refport));
INF_RESUME_MSGPORT_RPC (inf, msg_sig_post_untraced (msgport,
host_sig, 0, refport));
}
if (err == EIEIO)
@ -1254,6 +1297,18 @@ gnu_wait (int tid, struct target_waitstatus *status)
struct proc *thread;
struct inf *inf = current_inferior;
assert (inf->task);
if (!inf->threads && !inf->pending_execs)
/* No threads! Assume that maybe some outside agency is frobbing our
task, and really look for new threads. If we can't find any, just tell
the user to try again later. */
{
inf_validate_procs (inf);
if (!inf->threads && !inf->task->dead)
error ("There are no threads; try again later.");
}
waiting_inf = inf;
inf_debug (inf, "waiting for: %d", tid);
@ -1269,7 +1324,7 @@ gnu_wait (int tid, struct target_waitstatus *status)
outstanding wait request, so we have to cancel the previous one. */
{
inf_debug (inf, "cancelling previous wait on pid %d", proc_wait_pid);
interrupt_operation (proc_server);
interrupt_operation (proc_server, 0);
}
err =
@ -1294,14 +1349,14 @@ gnu_wait (int tid, struct target_waitstatus *status)
(3) wait reply from the proc server. */
inf_debug (inf, "waiting for an event...");
err = _hurd_intr_rpc_mach_msg (&msg.hdr, MACH_RCV_MSG, 0,
sizeof (struct msg),
inf->event_port, MACH_PORT_NULL);
err = mach_msg (&msg.hdr, MACH_RCV_MSG | MACH_RCV_INTERRUPT,
0, sizeof (struct msg), inf->event_port,
MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
/* Re-suspend the task. */
inf_suspend (inf);
if (err == EINTR)
if (err == EMACH_RCV_INTERRUPTED)
inf_debug (inf, "interrupted");
else if (err)
error ("Couldn't wait for an event: %s", strerror (err));
@ -1339,17 +1394,25 @@ gnu_wait (int tid, struct target_waitstatus *status)
/* Since gdb is actually counting the number of times the inferior
stops, expecting one stop per exec, we only return major events
while execing. */
w->suppress = 1;
{
w->suppress = 1;
inf_debug (inf, "pending_execs = %d, ignoring minor event",
inf->pending_execs);
}
else if (kind == TARGET_WAITKIND_STOPPED
&& w->status.value.sig == TARGET_SIGNAL_TRAP)
/* Ah hah! A SIGTRAP from the inferior while starting up probably
means we've succesfully completed an exec! */
if (--inf->pending_execs == 0)
/* We're done! */
{
prune_threads (1); /* Get rid of the old shell threads */
renumber_threads (0); /* Give our threads reasonable names. */
}
{
if (--inf->pending_execs == 0)
/* We're done! */
{
prune_threads (1); /* Get rid of the old shell threads */
renumber_threads (0); /* Give our threads reasonable names. */
}
inf_debug (inf, "pending exec completed, pending_execs => %d",
inf->pending_execs);
}
}
if (inf->wait.suppress)
@ -1442,9 +1505,15 @@ S_exception_raise_request (mach_port_t port, mach_port_t reply_port,
/* Record the exception so that we can forward it later. */
{
if (thread->exc_port == port)
inf->wait.exc.handler = thread->saved_exc_port;
{
inf_debug (waiting_inf, "Handler is thread exeption port <%d>",
thread->saved_exc_port);
inf->wait.exc.handler = thread->saved_exc_port;
}
else
{
inf_debug (waiting_inf, "Handler is task exeption port <%d>",
inf->task->saved_exc_port);
inf->wait.exc.handler = inf->task->saved_exc_port;
assert (inf->task->exc_port == port);
}
@ -1484,9 +1553,8 @@ inf_task_died_status (struct inf *inf)
inf->wait.status.kind = TARGET_WAITKIND_SIGNALLED;
inf->wait.status.value.sig = TARGET_SIGNAL_KILL;
}
/* Notify server routines. The only real one is dead name notification. */
/* Notify server routines. The only real one is dead name notification. */
error_t
do_mach_notify_dead_name (mach_port_t notify, mach_port_t dead_port)
{
@ -1522,7 +1590,7 @@ do_mach_notify_dead_name (mach_port_t notify, mach_port_t dead_port)
return 0;
}
static error_t
ill_rpc (char *fun)
{
@ -1564,12 +1632,12 @@ do_mach_notify_send_once (mach_port_t notify)
error_t
S_proc_wait_reply (mach_port_t reply, error_t err,
int status, rusage_t rusage, pid_t pid)
int status, int sigcode, rusage_t rusage, pid_t pid)
{
struct inf *inf = waiting_inf;
inf_debug (inf, "err = %s, pid = %d, status = 0x%x",
err ? strerror (err) : "0", pid, status);
inf_debug (inf, "err = %s, pid = %d, status = 0x%x, sigcode = %d",
err ? strerror (err) : "0", pid, status, sigcode);
if (err && proc_wait_pid && (!inf->task || !inf->task->port))
/* Ack. The task has died, but the task-died notification code didn't
@ -1606,10 +1674,6 @@ S_proc_wait_reply (mach_port_t reply, error_t err,
{
inf_debug (inf, "process has stopped itself");
inf->stopped = 1;
/* We recheck the task suspend count here because the crash server
messes with it in an unfriendly way, right before `stopping'. */
inf_validate_task_sc (inf);
}
}
else
@ -1724,6 +1788,8 @@ gnu_resume (int tid, int step, enum target_signal sig)
the process, as we're just going to stop it right away anyway. */
return;
inf_update_procs (inf);
if (tid < 0)
/* Allow all threads to run, except perhaps single-stepping one. */
{
@ -1735,8 +1801,8 @@ gnu_resume (int tid, int step, enum target_signal sig)
/* Just allow a single thread to run. */
{
struct proc *thread = inf_tid_to_thread (inf, tid);
assert (thread);
if (! thread)
error ("Can't run single thread id %d: no such thread!");
inf_debug (inf, "running one thread: %d/%d", inf->pid, thread->tid);
inf_set_threads_resume_sc (inf, thread, 0);
}
@ -1744,8 +1810,10 @@ gnu_resume (int tid, int step, enum target_signal sig)
if (step)
{
step_thread = inf_tid_to_thread (inf, tid);
assert (step_thread);
inf_debug (inf, "stepping thread: %d/%d", inf->pid, step_thread->tid);
if (! step_thread)
warning ("Can't step thread id %d: no such thread.", tid);
else
inf_debug (inf, "stepping thread: %d/%d", inf->pid, step_thread->tid);
}
if (step_thread != inf->step_thread)
inf_set_step_thread (inf, step_thread);
@ -1762,8 +1830,7 @@ gnu_kill_inferior ()
{
proc_debug (task, "terminating...");
task_terminate (task->port);
task->port = MACH_PORT_NULL;
inf_validate_procs (current_inferior); /* Clear out the thread list &c */
inf_set_task (current_inferior, MACH_PORT_NULL);
}
target_mourn_inferior ();
}
@ -1813,9 +1880,10 @@ gnu_create_inferior (exec_file, allargs, env)
{
/* We're in the child; make this process stop as soon as it execs. */
inf_debug (inf, "tracing self");
ptrace (PTRACE_TRACEME, 0, 0, 0);
if (ptrace (PTRACE_TRACEME) != 0)
error ("ptrace (PTRACE_TRACEME) failed!");
}
void attach_to_child (int pid)
int attach_to_child (int pid)
{
/* Attach to the now stopped child, which is actually a shell... */
inf_debug (inf, "attaching to child: %d", pid);
@ -1834,6 +1902,8 @@ gnu_create_inferior (exec_file, allargs, env)
inf_resume (inf);
startup_inferior (pid, inf->pending_execs);
return pid;
}
inf_debug (inf, "creating inferior");
@ -1912,7 +1982,8 @@ gnu_attach (args, from_tty)
/* If the process was stopped before we attached, make it continue the next
time the user does a continue. */
inf_validate_stopped (inf);
inf_validate_task_sc (inf);
renumber_threads (0); /* Give our threads reasonable names. */
}
/* Take a program previously attached to and detaches it.
@ -2319,6 +2390,19 @@ struct cmd_list_element *show_task_cmd_list = 0;
extern struct cmd_list_element *set_thread_default_cmd_list;
extern struct cmd_list_element *show_thread_default_cmd_list;
static int
parse_int_arg (char *args, char *cmd_prefix)
{
if (args)
{
char *arg_end;
int val = strtoul (args, &arg_end, 10);
if (*args && *arg_end == '\0')
return val;
}
error ("Illegal argument for \"%s\" command, should be an integer.", cmd_prefix);
}
static int
_parse_bool_arg (char *args, char *t_val, char *f_val, char *cmd_prefix)
{
@ -2352,6 +2436,16 @@ cur_thread ()
return thread;
}
/* Returns the current inferior, but signals an error if it has no task. */
static struct inf *
active_inf ()
{
struct inf *inf = cur_inf ();
if (! inf->task)
error ("No current process.");
return inf;
}
static void
set_task_pause_cmd (char *args, int from_tty)
{
@ -2377,6 +2471,20 @@ show_task_pause_cmd (char *args, int from_tty)
: (inf->pause_sc == 0 ? "won't be" : "will be"));
}
static void
set_task_detach_sc_cmd (char *args, int from_tty)
{
cur_inf ()->detach_sc = parse_int_arg (args, "set task detach-suspend-count");
}
static void
show_task_detach_sc_cmd (char *args, int from_tty)
{
check_empty (args, "show task detach-suspend-count");
printf_unfiltered ("The inferior task will be left with a suspend count of %d when detaching.\n",
cur_inf ()->detach_sc);
}
static void
set_thread_default_pause_cmd (char *args, int from_tty)
{
@ -2393,7 +2501,7 @@ show_thread_default_pause_cmd (char *args, int from_tty)
check_empty (args, "show thread default pause");
printf_unfiltered ("New threads %s suspended while gdb has control%s.\n",
sc ? "are" : "aren't",
!sc && inf->pause_sc ? "(but the task is)" : "");
!sc && inf->pause_sc ? " (but the task is)" : "");
}
static void
@ -2413,6 +2521,21 @@ show_thread_default_run_cmd (char *args, int from_tty)
inf->default_thread_run_sc == 0 ? "are" : "aren't");
}
static void
set_thread_default_detach_sc_cmd (char *args, int from_tty)
{
cur_inf ()->default_thread_detach_sc =
parse_int_arg (args, "set thread default detach-suspend-count");
}
static void
show_thread_default_detach_sc_cmd (char *args, int from_tty)
{
check_empty (args, "show thread default detach-suspend-count");
printf_unfiltered ("New threads will get a detach-suspend-count of %d.\n",
cur_inf ()->default_thread_detach_sc);
}
/* Steal a send right called NAME in the inferior task, and make it PROC's
saved exception port. */
static void
@ -2448,7 +2571,7 @@ steal_exc_port (struct proc *proc, mach_port_t name)
proc_string (proc), strerror (err));
}
}
static void
set_task_exc_port_cmd (char *args, int from_tty)
{
@ -2458,30 +2581,6 @@ set_task_exc_port_cmd (char *args, int from_tty)
steal_exc_port (inf->task, parse_and_eval_address (args));
}
static void
set_signals_cmd (char *args, int from_tty)
{
int trace;
struct inf *inf = cur_inf ();
inf->want_signals = parse_bool_arg (args, "set signals");
if (inf->task && inf->want_signals != inf->traced)
/* Make this take effect immediately in a running process. */
inf_set_traced (inf, inf->want_signals);
}
static void
show_signals_cmd (char *args, int from_tty)
{
struct inf *inf = cur_inf ();
check_empty (args, "show signals");
printf_unfiltered ("The inferior process's signals %s intercepted.\n",
inf->task
? (inf->traced ? "are" : "aren't")
: (inf->want_signals ? "will be" : "won't be"));
}
static void
set_stopped_cmd (char *args, int from_tty)
{
@ -2491,10 +2590,8 @@ set_stopped_cmd (char *args, int from_tty)
static void
show_stopped_cmd (char *args, int from_tty)
{
struct inf *inf = cur_inf ();
struct inf *inf = active_inf ();
check_empty (args, "show stopped");
if (! inf->task)
error ("No current process.");
printf_unfiltered ("The inferior process %s stopped.\n",
inf->stopped ? "is" : "isn't");
}
@ -2524,16 +2621,38 @@ set_sig_thread_cmd (char *args, int from_tty)
static void
show_sig_thread_cmd (char *args, int from_tty)
{
struct inf *inf = cur_inf ();
struct inf *inf = active_inf ();
check_empty (args, "show signal-thread");
if (! inf->task)
error ("No current process.");
if (inf->signal_thread)
printf_unfiltered ("The signal thread is %s.\n",
proc_string (inf->signal_thread));
else
printf_unfiltered ("There is no signal thread.\n");
}
static void
set_signals_cmd (char *args, int from_tty)
{
int trace;
struct inf *inf = cur_inf ();
inf->want_signals = parse_bool_arg (args, "set signals");
if (inf->task && inf->want_signals != inf->traced)
/* Make this take effect immediately in a running process. */
inf_set_traced (inf, inf->want_signals);
}
static void
show_signals_cmd (char *args, int from_tty)
{
struct inf *inf = cur_inf ();
check_empty (args, "show signals");
printf_unfiltered ("The inferior process's signals %s intercepted.\n",
inf->task
? (inf->traced ? "are" : "aren't")
: (inf->want_signals ? "will be" : "won't be"));
}
static void
set_exceptions_cmd (char *args, int from_tty)
@ -2558,7 +2677,7 @@ show_exceptions_cmd (char *args, int from_tty)
? (inf->want_exceptions ? "are" : "aren't")
: (inf->want_exceptions ? "will be" : "won't be"));
}
static void
set_task_cmd (char *args, int from_tty)
{
@ -2585,8 +2704,83 @@ show_task_cmd (char *args, int from_tty)
show_stopped_cmd (0, from_tty);
show_sig_thread_cmd (0, from_tty);
}
if (inf->detach_sc != 0)
show_task_detach_sc_cmd (0, from_tty);
if (inf->default_thread_detach_sc != 0)
show_thread_default_detach_sc_cmd (0, from_tty);
}
static void
set_noninvasive_cmd (char *args, int from_tty)
{
/* Invert the sense of the arg for each component. */
char *inv_args = parse_bool_arg (args, "set noninvasive") ? "off" : "on";
set_task_pause_cmd (inv_args, from_tty);
set_signals_cmd (inv_args, from_tty);
set_exceptions_cmd (inv_args, from_tty);
}
static void
info_port_rights (char *args, mach_port_type_t only)
{
struct inf *inf = active_inf ();
value_ptr vmark = value_mark ();
if (args)
/* Explicit list of port rights. */
{
while (*args)
{
value_ptr val = parse_to_comma_and_eval (&args);
long right = value_as_long (val);
error_t err =
print_port_info (right, 0, inf->task->port, PORTINFO_DETAILS,
stdout);
if (err)
error ("%ld: %s.", right, strerror (err));
}
}
else
/* Print all of them. */
{
error_t err =
print_task_ports_info (inf->task->port, only, PORTINFO_DETAILS,
stdout);
if (err)
error ("%s.", strerror (err));
}
value_free_to_mark (vmark);
}
static void
info_send_rights_cmd (char *args, int from_tty)
{
info_port_rights (args, MACH_PORT_TYPE_SEND);
}
static void
info_recv_rights_cmd (char *args, int from_tty)
{
info_port_rights (args, MACH_PORT_TYPE_RECEIVE);
}
static void
info_port_sets_cmd (char *args, int from_tty)
{
info_port_rights (args, MACH_PORT_TYPE_PORT_SET);
}
static void
info_dead_names_cmd (char *args, int from_tty)
{
info_port_rights (args, MACH_PORT_TYPE_DEAD_NAME);
}
static void
info_port_rights_cmd (char *args, int from_tty)
{
info_port_rights (args, ~0);
}
static void add_task_commands ()
{
add_cmd ("pause", class_run, set_thread_default_pause_cmd,
@ -2605,6 +2799,12 @@ static void add_task_commands ()
"Show whether new threads are allowed to run (once gdb has noticed
them).",
&show_thread_default_cmd_list);
add_cmd ("detach-suspend-count", class_run, set_thread_default_detach_sc_cmd,
"Set the default detach-suspend-count value for new threads.",
&set_thread_default_cmd_list);
add_cmd ("detach-suspend-count", no_class, show_thread_default_detach_sc_cmd,
"Show the default detach-suspend-count value for new threads.",
&show_thread_default_cmd_list);
add_cmd ("signals", class_run, set_signals_cmd,
"Set whether the inferior process's signals will be intercepted.\n"
@ -2645,8 +2845,6 @@ them).",
"Show whether exceptions in the inferior process will be trapped.",
&showlist);
add_prefix_cmd ("task", no_class, set_task_cmd,
"Command prefix for setting task attributes.",
&set_task_cmd_list, "set task ", 0, &setlist);
@ -2664,6 +2862,12 @@ them).",
add_cmd ("pause", no_class, show_task_pause_cmd,
"Show whether the task is suspended while gdb has control.",
&show_task_cmd_list);
add_cmd ("detach-suspend-count", class_run, set_task_detach_sc_cmd,
"Set the suspend count will leave on the thread when detaching.",
&set_task_cmd_list);
add_cmd ("detach-suspend-count", no_class, show_task_detach_sc_cmd,
"Show the suspend count will leave on the thread when detaching.",
&show_task_cmd_list);
add_cmd ("exception-port", no_class, set_task_exc_port_cmd,
"Set the task exception port to which we forward exceptions.\n"
@ -2671,12 +2875,41 @@ them).",
&set_task_cmd_list);
add_alias_cmd ("excp", "exception-port", no_class, 1, &set_task_cmd_list);
add_alias_cmd ("exc-port", "exception-port", no_class, 1, &set_task_cmd_list);
/* A convenient way of turning on all options require to noninvasively
debug running tasks. */
add_cmd ("noninvasive", no_class, set_noninvasive_cmd,
"Set task options so that we interfere as little as possible.\n"
"This is the same as setting `task pause', `exceptions', and"
"`signals' to the opposite value.",
&setlist);
/* Commands to show information about the task's ports. */
add_cmd ("send-rights", class_info, info_send_rights_cmd,
"Show information about the task's send rights",
&infolist);
add_cmd ("receive-rights", class_info, info_recv_rights_cmd,
"Show information about the task's receive rights",
&infolist);
add_cmd ("port-rights", class_info, info_send_rights_cmd,
"Show information about the task's port rights",
&infolist);
add_cmd ("port-sets", class_info, info_port_sets_cmd,
"Show information about the task's port sets",
&infolist);
add_cmd ("dead-names", class_info, info_dead_names_cmd,
"Show information about the task's dead names",
&infolist);
add_info_alias ("ports", "port-rights", 1);
add_info_alias ("port", "port-rights", 1);
add_info_alias ("psets", "port-sets", 1);
}
/* User thread commands. */
extern struct cmd_list_element *set_thread_cmd_list;
extern struct cmd_list_element *show_thread_cmd_list;
extern struct cmd_list_element *thread_cmd_list;
static void
set_thread_pause_cmd (char *args, int from_tty)
@ -2699,7 +2932,7 @@ show_thread_pause_cmd (char *args, int from_tty)
printf_unfiltered ("Thread %s %s suspended while gdb has control%s.\n",
proc_string (thread),
sc ? "is" : "isn't",
!sc && thread->inf->pause_sc ? "(but the task is)" : "");
!sc && thread->inf->pause_sc ? " (but the task is)" : "");
}
static void
@ -2714,11 +2947,27 @@ show_thread_run_cmd (char *args, int from_tty)
{
struct proc *thread = cur_thread ();
check_empty (args, "show thread run");
printf_unfiltered ("Thread %s allowed to run.",
printf_unfiltered ("Thread %s %s allowed to run.",
proc_string (thread),
thread->run_sc == 0 ? "is" : "isn't");
}
static void
set_thread_detach_sc_cmd (char *args, int from_tty)
{
cur_thread ()->detach_sc = parse_int_arg (args, "set thread detach-suspend-count");
}
static void
show_thread_detach_sc_cmd (char *args, int from_tty)
{
struct proc *thread = cur_thread ();
check_empty (args, "show thread detach-suspend-count");
printf_unfiltered ("Thread %s will be left with a suspend count of %d when detaching.\n",
proc_string (thread),
thread->detach_sc);
}
static void
set_thread_exc_port_cmd (char *args, int from_tty)
{
@ -2737,9 +2986,30 @@ set_thread_cmd (char *args, int from_tty)
static void
show_thread_cmd (char *args, int from_tty)
{
struct proc *thread = cur_thread ();
check_empty (args, "show thread");
show_thread_run_cmd (0, from_tty);
show_thread_pause_cmd (0, from_tty);
if (thread->detach_sc != 0)
show_thread_detach_sc_cmd (0, from_tty);
}
static void
thread_takeover_sc_cmd (char *args, int from_tty)
{
struct proc *thread = cur_thread ();
thread_basic_info_data_t _info;
thread_basic_info_t info = &_info;
mach_msg_type_number_t info_len = THREAD_BASIC_INFO_COUNT;
error_t err =
thread_info (thread->port, THREAD_BASIC_INFO, (int *)&info, &info_len);
if (err)
error ("%s.", strerror (err));
thread->sc = info->suspend_count;
if (from_tty)
printf_unfiltered ("Suspend count was %d.\n", thread->sc);
if (info != &_info)
vm_deallocate (mach_task_self (), (vm_address_t)info, info_len * sizeof (int));
}
add_thread_commands ()
@ -2763,6 +3033,17 @@ add_thread_commands ()
"Show whether the current thread is allowed to run.",
&show_thread_cmd_list);
add_cmd ("detach-suspend-count", class_run, set_thread_detach_sc_cmd,
"Set the suspend count will leave on the thread when detaching.\n"
"Note that this is relative to suspend count when gdb noticed the thread;\n"
"use the `thread takeover-suspend-count' to force it to an absolute value.",
&set_thread_cmd_list);
add_cmd ("detach-suspend-count", no_class, show_thread_detach_sc_cmd,
"Show the suspend count will leave on the thread when detaching."
"Note that this is relative to suspend count when gdb noticed the thread;\n"
"use the `thread takeover-suspend-count' to force it to an absolute value.",
&show_thread_cmd_list);
add_cmd ("exception-port", no_class, set_thread_exc_port_cmd,
"Set the exception port to which we forward exceptions for the\n"
"current thread, overriding the task exception port.\n"
@ -2770,6 +3051,12 @@ add_thread_commands ()
&set_thread_cmd_list);
add_alias_cmd ("excp", "exception-port", no_class, 1, &set_thread_cmd_list);
add_alias_cmd ("exc-port", "exception-port", no_class, 1, &set_thread_cmd_list);
add_cmd ("takeover-suspend-count", no_class, thread_takeover_sc_cmd,
"Force the threads absolute suspend-count to be gdb's.\n"
"Prior to giving this command, gdb's thread suspend-counts are relative to\n"
"the thread's initial suspend-count when gdb notices the threads.",
&thread_cmd_list);
}
void

View File

@ -1,6 +1,6 @@
/* Common things used by the various *gnu-nat.c files
Copyright (C) 1995 Free Software Foundation, Inc.
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
Written by Miles Bader <miles@gnu.ai.mit.edu>
@ -47,12 +47,14 @@ struct proc
int run_sc; /* Default sc when the program is running. */
int pause_sc; /* Default sc when gdb has control. */
int resume_sc; /* Sc resulting form the last resume. */
int detach_sc; /* SC to leave around when detaching from program. */
thread_state_data_t state; /* Registers, &c. */
int state_valid : 1; /* True if STATE is up to date. */
int state_changed : 1;
int aborted : 1; /* True if thread_abort has been called. */
int dead : 1; /* We happen to know it's actually dead. */
/* Bit mask of registers fetched by gdb. This is used when we re-fetch
STATE after aborting the thread, to detect that gdb may have out-of-date

View File

@ -1,5 +1,5 @@
/* Low level interface to I386 running the GNU Hurd
Copyright (C) 1992 Free Software Foundation, Inc.
Copyright (C) 1992, 1995, 1996 Free Software Foundation, Inc.
This file is part of GDB.
@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "floatformat.h"
#include <stdio.h>
#include <errno.h>
#include <mach.h>
#include <mach/message.h>
@ -81,16 +82,20 @@ static int reg_offset[] =
void
gnu_fetch_registers (int reg)
{
struct proc *thread;
thread_state_t state;
struct proc *thread = inf_tid_to_thread (current_inferior, inferior_pid);
if (!thread)
inf_update_procs (current_inferior); /* Make sure we know about new threads. */
thread = inf_tid_to_thread (current_inferior, inferior_pid);
if (! thread)
error ("fetch inferior registers: %d: Invalid thread", inferior_pid);
state = proc_get_state (thread, 0);
if (! state)
warning ("Couldn't fetch register %s.", reg_names[reg]);
warning ("Couldn't fetch register %s from %s (invalid thread).",
reg_names[reg], proc_string (thread));
else if (reg >= 0)
{
proc_debug (thread, "fetching register: %s", reg_names[reg]);
@ -116,11 +121,14 @@ void
gnu_store_registers (reg)
int reg;
{
struct proc *thread;
int was_aborted, was_valid;
thread_state_t state;
thread_state_data_t old_state;
struct proc *thread = inf_tid_to_thread (current_inferior, inferior_pid);
inf_update_procs (current_inferior); /* Make sure we know about new threads. */
thread = inf_tid_to_thread (current_inferior, inferior_pid);
if (! thread)
error ("store inferior registers: %d: Invalid thread", inferior_pid);
@ -134,7 +142,8 @@ gnu_store_registers (reg)
state = proc_get_state (thread, 1);
if (! state)
warning ("Couldn't store register %s.", reg_names[reg]);
warning ("Couldn't store register %s from %s (invalid thread).",
reg_names[reg], proc_string (thread));
else
{
if (! was_aborted && was_valid)

View File

@ -1,6 +1,6 @@
/* Variables that describe the inferior process running under GDB:
Where it is, why it stopped, and how to step it.
Copyright 1986, 1989, 1992 Free Software Foundation, Inc.
Copyright 1986, 1989, 1992, 1996 Free Software Foundation, Inc.
This file is part of GDB.
@ -16,7 +16,7 @@ GNU General Public License for more details.
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. */
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if !defined (INFERIOR_H)
#define INFERIOR_H 1
@ -24,24 +24,19 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* For bpstat. */
#include "breakpoint.h"
/* For FRAME_ADDR. */
#include "frame.h"
/* For enum target_signal. */
#include "target.h"
/*
* Structure in which to save the status of the inferior. Save
* through "save_inferior_status", restore through
* "restore_inferior_status".
* This pair of routines should be called around any transfer of
* control to the inferior which you don't want showing up in your
* control variables.
*/
/* Structure in which to save the status of the inferior. Save
through "save_inferior_status", restore through
"restore_inferior_status".
This pair of routines should be called around any transfer of
control to the inferior which you don't want showing up in your
control variables. */
struct inferior_status {
enum target_signal stop_signal;
CORE_ADDR stop_pc;
FRAME_ADDR stop_frame_address;
bpstat stop_bpstat;
int stop_step;
int stop_stack_dummy;
@ -49,12 +44,12 @@ struct inferior_status {
int trap_expected;
CORE_ADDR step_range_start;
CORE_ADDR step_range_end;
FRAME_ADDR step_frame_address;
CORE_ADDR step_frame_address;
int step_over_calls;
CORE_ADDR step_resume_break_address;
int stop_after_trap;
int stop_soon_quietly;
FRAME_ADDR selected_frame_address;
CORE_ADDR selected_frame_address;
int selected_level;
char stop_registers[REGISTER_BYTES];
@ -68,16 +63,24 @@ struct inferior_status {
int proceed_to_finish;
};
extern void
save_inferior_status PARAMS ((struct inferior_status *, int));
/* This macro gives the number of registers actually in use by the
inferior. This may be less than the total number of registers,
perhaps depending on the actual CPU in use or program being run. */
extern void
restore_inferior_status PARAMS ((struct inferior_status *));
#ifndef ARCH_NUM_REGS
#define ARCH_NUM_REGS NUM_REGS
#endif
extern void save_inferior_status PARAMS ((struct inferior_status *, int));
extern void restore_inferior_status PARAMS ((struct inferior_status *));
extern void set_sigint_trap PARAMS ((void));
extern void clear_sigint_trap PARAMS ((void));
extern void set_sigio_trap PARAMS ((void));
extern void clear_sigio_trap PARAMS ((void));
/* File name for default use for standard in/out in the inferior. */
@ -88,6 +91,10 @@ extern char *inferior_io_terminal;
extern int inferior_pid;
/* Inferior environment. */
extern struct environ *inferior_environ;
/* Character array containing an image of the inferior programs' registers. */
extern char registers[];
@ -97,149 +104,116 @@ extern char registers[];
extern char register_valid[NUM_REGS];
extern void
clear_proceed_status PARAMS ((void));
extern void clear_proceed_status PARAMS ((void));
extern void
proceed PARAMS ((CORE_ADDR, enum target_signal, int));
extern void proceed PARAMS ((CORE_ADDR, enum target_signal, int));
extern void
kill_inferior PARAMS ((void));
extern void kill_inferior PARAMS ((void));
extern void
generic_mourn_inferior PARAMS ((void));
extern void generic_mourn_inferior PARAMS ((void));
extern void
terminal_ours PARAMS ((void));
extern void terminal_ours PARAMS ((void));
extern int run_stack_dummy PARAMS ((CORE_ADDR, char [REGISTER_BYTES]));
extern CORE_ADDR
read_pc PARAMS ((void));
extern CORE_ADDR read_pc PARAMS ((void));
extern CORE_ADDR
read_pc_pid PARAMS ((int));
extern CORE_ADDR read_pc_pid PARAMS ((int));
extern void
write_pc PARAMS ((CORE_ADDR));
extern void write_pc PARAMS ((CORE_ADDR));
extern CORE_ADDR
read_sp PARAMS ((void));
extern CORE_ADDR read_sp PARAMS ((void));
extern void
write_sp PARAMS ((CORE_ADDR));
extern void write_sp PARAMS ((CORE_ADDR));
extern CORE_ADDR
read_fp PARAMS ((void));
extern CORE_ADDR read_fp PARAMS ((void));
extern void
write_fp PARAMS ((CORE_ADDR));
extern void write_fp PARAMS ((CORE_ADDR));
extern void
wait_for_inferior PARAMS ((void));
extern void wait_for_inferior PARAMS ((void));
extern void
init_wait_for_inferior PARAMS ((void));
extern void init_wait_for_inferior PARAMS ((void));
extern void
close_exec_file PARAMS ((void));
extern void close_exec_file PARAMS ((void));
extern void
reopen_exec_file PARAMS ((void));
extern void reopen_exec_file PARAMS ((void));
/* The `resume' routine should only be called in special circumstances.
Normally, use `proceed', which handles a lot of bookkeeping. */
extern void
resume PARAMS ((int, enum target_signal));
extern void resume PARAMS ((int, enum target_signal));
/* From misc files */
extern void
store_inferior_registers PARAMS ((int));
extern void store_inferior_registers PARAMS ((int));
extern void
fetch_inferior_registers PARAMS ((int));
extern void fetch_inferior_registers PARAMS ((int));
extern void
solib_create_inferior_hook PARAMS ((void));
extern void solib_create_inferior_hook PARAMS ((void));
extern void
child_terminal_info PARAMS ((char *, int));
extern void child_terminal_info PARAMS ((char *, int));
extern void
term_info PARAMS ((char *, int));
extern void term_info PARAMS ((char *, int));
extern void
terminal_ours_for_output PARAMS ((void));
extern void terminal_ours_for_output PARAMS ((void));
extern void
terminal_inferior PARAMS ((void));
extern void terminal_inferior PARAMS ((void));
extern void
terminal_init_inferior PARAMS ((void));
extern void terminal_init_inferior PARAMS ((void));
#ifdef PROCESS_GROUP_TYPE
extern void terminal_init_inferior_with_pgrp PARAMS ((PROCESS_GROUP_TYPE pgrp));
#endif
/* From infptrace.c */
extern int
attach PARAMS ((int));
extern int attach PARAMS ((int));
void
detach PARAMS ((int));
void detach PARAMS ((int));
extern void
child_resume PARAMS ((int, int, enum target_signal));
extern void child_resume PARAMS ((int, int, enum target_signal));
#ifndef PTRACE_ARG3_TYPE
#define PTRACE_ARG3_TYPE int /* Correct definition for most systems. */
#endif
extern int
call_ptrace PARAMS ((int, int, PTRACE_ARG3_TYPE, int));
extern int call_ptrace PARAMS ((int, int, PTRACE_ARG3_TYPE, int));
/* From procfs.c */
extern int
proc_iterate_over_mappings PARAMS ((int (*) (int, CORE_ADDR)));
extern int proc_iterate_over_mappings PARAMS ((int (*) (int, CORE_ADDR)));
/* From fork-child.c */
extern void fork_inferior PARAMS ((char *, char *, char **,
void (*) (void),
void (*) (int), char *));
int (*) (int), char *));
extern void startup_inferior PARAMS ((int));
/* From inflow.c */
extern void
new_tty_prefork PARAMS ((char *));
extern void new_tty_prefork PARAMS ((char *));
extern int gdb_has_a_terminal PARAMS ((void));
/* From infrun.c */
extern void
start_remote PARAMS ((void));
extern void start_remote PARAMS ((void));
extern void
normal_stop PARAMS ((void));
extern void normal_stop PARAMS ((void));
extern int
signal_stop_state PARAMS ((int));
extern int signal_stop_state PARAMS ((int));
extern int
signal_print_state PARAMS ((int));
extern int signal_print_state PARAMS ((int));
extern int
signal_pass_state PARAMS ((int));
extern int signal_pass_state PARAMS ((int));
/* From infcmd.c */
extern void
tty_command PARAMS ((char *, int));
extern void tty_command PARAMS ((char *, int));
extern void
attach_command PARAMS ((char *, int));
extern void attach_command PARAMS ((char *, int));
/* Last signal that the inferior received (why it stopped). */
@ -249,10 +223,6 @@ extern enum target_signal stop_signal;
extern CORE_ADDR stop_pc;
/* Stack frame when program stopped. */
extern FRAME_ADDR stop_frame_address;
/* Chain containing status of breakpoint(s) that we have stopped at. */
extern bpstat stop_bpstat;
@ -291,7 +261,11 @@ extern CORE_ADDR step_range_end; /* Exclusive */
This is how we know when we step into a subroutine call,
and how to set the frame for the breakpoint used to step out. */
extern FRAME_ADDR step_frame_address;
extern CORE_ADDR step_frame_address;
/* Our notion of the current stack pointer. */
extern CORE_ADDR step_sp;
/* 1 means step over all subroutine calls.
-1 means step over calls to undebuggable functions. */

View File

@ -15,7 +15,7 @@ GNU General Public License for more details.
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. */
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "frame.h"
@ -25,18 +25,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "serial.h"
#include "terminal.h"
#include "target.h"
#include "thread.h"
#include "gdbthread.h"
#include "gdb_string.h"
#include <signal.h>
#include <fcntl.h>
#if !defined (HAVE_TERMIOS) && !defined (HAVE_TERMIO) && !defined (HAVE_SGTTY) && !defined (__GO32__) && !defined(WIN32)
#define HAVE_SGTTY
#endif
#if defined (HAVE_TERMIOS)
#include <termios.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@ -161,7 +155,8 @@ static void terminal_ours_1 PARAMS ((int));
before we actually run the inferior. */
void
terminal_init_inferior ()
terminal_init_inferior_with_pgrp (pgrp)
int pgrp;
{
if (gdb_has_a_terminal ())
{
@ -170,18 +165,9 @@ terminal_init_inferior ()
if (inferior_ttystate)
free (inferior_ttystate);
inferior_ttystate = SERIAL_GET_TTY_STATE (stdin_serial);
#ifdef PROCESS_GROUP_TYPE
#ifdef PIDGET
/* This is for Lynx, and should be cleaned up by having Lynx be
a separate debugging target with a version of
target_terminal_init_inferior which passes in the process
group to a generic routine which does all the work (and the
non-threaded child_terminal_init_inferior can just pass in
inferior_pid to the same routine). */
inferior_process_group = PIDGET (inferior_pid);
#else
inferior_process_group = inferior_pid;
#endif
inferior_process_group = pgrp;
#endif
/* Make sure that next time we call terminal_inferior (which will be
@ -191,6 +177,24 @@ terminal_init_inferior ()
}
}
void
terminal_init_inferior ()
{
#ifdef PROCESS_GROUP_TYPE
#ifdef PIDGET
/* This is for Lynx, and should be cleaned up by having Lynx be a separate
debugging target with a version of target_terminal_init_inferior which
passes in the process group to a generic routine which does all the work
(and the non-threaded child_terminal_init_inferior can just pass in
inferior_pid to the same routine). */
terminal_init_inferior_with_pgrp (PIDGET (inferior_pid));
#else
/* By default, we assume INFERIOR_PID is also the child's process group. */
terminal_init_inferior_with_pgrp (inferior_pid);
#endif
#endif /* PROCESS_GROUP_TYPE */
}
/* Put the inferior's terminal settings into effect.
This is preparation for starting or resuming the inferior. */
@ -484,7 +488,7 @@ new_tty ()
if (inferior_thisrun_terminal == 0)
return;
#if !defined(__GO32__) && !defined(WIN32)
#if !defined(__GO32__) && !defined(__WIN32__)
#ifdef TIOCNOTTY
/* Disconnect the child process from our controlling terminal. On some
systems (SVR4 for example), this may cause a SIGTTOU, so temporarily
@ -666,8 +670,7 @@ gdb_setpgid ()
if (job_control)
{
#if defined (NEED_POSIX_SETPGID) || defined (HAVE_TERMIOS)
/* Do all systems with termios have setpgid? I hope so. */
#if defined (NEED_POSIX_SETPGID) || (defined (HAVE_TERMIOS) && defined (HAVE_SETPGID))
/* setpgid (0, 0) is supposed to work and mean the same thing as
this, but on Ultrix 4.2A it fails with EPERM (and
setpgid (getpid (), getpid ()) succeeds). */
@ -707,9 +710,13 @@ _initialize_inflow ()
#ifdef _POSIX_JOB_CONTROL
job_control = 1;
#else
#ifdef _SC_JOB_CONTROL
job_control = sysconf (_SC_JOB_CONTROL);
#endif
#endif /* termios */
#else
job_control = 0; /* have to assume the worst */
#endif /* _SC_JOB_CONTROL */
#endif /* _POSIX_JOB_CONTROL */
#endif /* HAVE_TERMIOS */
#ifdef HAVE_SGTTY
#ifdef TIOCGPGRP

View File

@ -655,13 +655,11 @@ child_wait (pid, ourstatus)
if (realsig == SIGNEWTHREAD)
{
/* It's a new thread notification. Nothing to do here since
the machine independent code in wait_for_inferior will
add the thread to the thread list and restart the thread
when pid != inferior_pid and pid is not in the thread
list. We don't even want to much with realsig -- the
code in wait_for_inferior expects SIGTRAP. */
;
/* It's a new thread notification. We don't want to much with
realsig -- the code in wait_for_inferior expects SIGTRAP. */
ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
ourstatus->value.sig = TARGET_SIGNAL_0;
return pid;
}
else
error ("Signal for unknown thread was not SIGNEWTHREAD");

View File

@ -1028,6 +1028,14 @@ static struct {
{"SIG62", "Real-time event 62"},
{"SIG63", "Real-time event 63"},
/* Mach exceptions */
{"EXC_BAD_ACCESS", "Could not access memory"},
{"EXC_BAD_INSTRUCTION", "Illegal instruction/operand"},
{"EXC_ARITHMETIC", "Arithmetic exception"},
{"EXC_EMULATION", "Emulation instruction"},
{"EXC_SOFTWARE", "Software generated exception"},
{"EXC_BREAKPOINT", "Breakpoint"},
{NULL, "Unknown signal"},
{NULL, "Internal error: printing TARGET_SIGNAL_DEFAULT"},
@ -1225,6 +1233,27 @@ target_signal_from_host (hostsig)
#if defined (SIGPRIO)
if (hostsig == SIGPRIO) return TARGET_SIGNAL_PRIO;
#endif
/* Mach exceptions. Assumes that the values for EXC_ are positive! */
#if defined (EXC_BAD_ACCESS) && defined (_NSIG)
if (hostsig == _NSIG + EXC_BAD_ACCESS) return TARGET_EXC_BAD_ACCESS;
#endif
#if defined (EXC_BAD_INSTRUCTION) && defined (_NSIG)
if (hostsig == _NSIG + EXC_BAD_INSTRUCTION) return TARGET_EXC_BAD_INSTRUCTION;
#endif
#if defined (EXC_ARITHMETIC) && defined (_NSIG)
if (hostsig == _NSIG + EXC_ARITHMETIC) return TARGET_EXC_ARITHMETIC;
#endif
#if defined (EXC_EMULATION) && defined (_NSIG)
if (hostsig == _NSIG + EXC_EMULATION) return TARGET_EXC_EMULATION;
#endif
#if defined (EXC_SOFTWARE) && defined (_NSIG)
if (hostsig == _NSIG + EXC_SOFTWARE) return TARGET_EXC_SOFTWARE;
#endif
#if defined (EXC_BREAKPOINT) && defined (_NSIG)
if (hostsig == _NSIG + EXC_BREAKPOINT) return TARGET_EXC_BREAKPOINT;
#endif
#if defined (REALTIME_LO)
if (hostsig >= REALTIME_LO && hostsig < REALTIME_HI)
return (enum target_signal)
@ -1378,6 +1407,27 @@ target_signal_to_host (oursig)
#if defined (SIGPRIO)
case TARGET_SIGNAL_PRIO: return SIGPRIO;
#endif
/* Mach exceptions. Assumes that the values for EXC_ are positive! */
#if defined (EXC_BAD_ACCESS) && defined (_NSIG)
case TARGET_EXC_BAD_ACCESS: return _NSIG + EXC_BAD_ACCESS;
#endif
#if defined (EXC_BAD_INSTRUCTION) && defined (_NSIG)
case TARGET_EXC_BAD_INSTRUCTION: return _NSIG + EXC_BAD_INSTRUCTION;
#endif
#if defined (EXC_ARITHMETIC) && defined (_NSIG)
case TARGET_EXC_ARITHMETIC: return _NSIG + EXC_ARITHMETIC;
#endif
#if defined (EXC_EMULATION) && defined (_NSIG)
case TARGET_EXC_EMULATION: return _NSIG + EXC_EMULATION;
#endif
#if defined (EXC_SOFTWARE) && defined (_NSIG)
case TARGET_EXC_SOFTWARE: return _NSIG + EXC_SOFTWARE;
#endif
#if defined (EXC_BREAKPOINT) && defined (_NSIG)
case TARGET_EXC_BREAKPOINT: return _NSIG + EXC_BREAKPOINT;
#endif
default:
#if defined (REALTIME_LO)
if (oursig >= TARGET_SIGNAL_REALTIME_33
@ -1609,7 +1659,8 @@ debug_to_xfer_memory (memaddr, myaddr, len, write, target)
retval = debug_target.to_xfer_memory (memaddr, myaddr, len, write, target);
fprintf_unfiltered (stderr, "target_xfer_memory (0x%x, xxx, %d, %s, xxx) = %d",
fprintf_unfiltered (stderr,
"target_xfer_memory (0x%x, xxx, %d, %s, xxx) = %d",
memaddr, len, write ? "write" : "read", retval);
if (retval > 0)
@ -1618,7 +1669,11 @@ debug_to_xfer_memory (memaddr, myaddr, len, write, target)
fputs_unfiltered (", bytes =", gdb_stderr);
for (i = 0; i < retval; i++)
fprintf_unfiltered (stderr, " %02x", myaddr[i] & 0xff);
{
if ((((long) &(myaddr[i])) & 0xf) == 0)
fprintf_unfiltered (stderr, "\n");
fprintf_unfiltered (stderr, " %02x", myaddr[i] & 0xff);
}
}
fputc_unfiltered ('\n', gdb_stderr);
@ -1783,10 +1838,13 @@ static int
debug_to_thread_alive (pid)
int pid;
{
debug_target.to_thread_alive (pid);
int retval;
fprintf_unfiltered (stderr, "target_thread_alive (%d)\n", pid);
return (0);
retval = debug_target.to_thread_alive (pid);
fprintf_unfiltered (stderr, "target_thread_alive (%d) = %d\n", pid, retval);
return retval;
}
static void

View File

@ -178,6 +178,14 @@ enum target_signal {
TARGET_SIGNAL_REALTIME_62 = 74,
TARGET_SIGNAL_REALTIME_63 = 75,
/* Mach exceptions */
TARGET_EXC_BAD_ACCESS = 76,
TARGET_EXC_BAD_INSTRUCTION = 77,
TARGET_EXC_ARITHMETIC = 78,
TARGET_EXC_EMULATION = 79,
TARGET_EXC_SOFTWARE = 80,
TARGET_EXC_BREAKPOINT = 81,
/* Some signal we don't know about. */
TARGET_SIGNAL_UNKNOWN,