Wed May 21 16:03:25 1997 Michael Snyder <msnyder@cleaver.cygnus.com>
* procfs.c (init_procinfo): new function, abstracts some code shared by create_procinfo and do_attach; (procfs_set_inferior_syscall_traps): new function, abstracts some code needed by procfs_init_inferior, do_attach, and procfs_lwp_creation_handler; (procfs_first_available): new function, find any LWP that's runnable; (procfs_thread_alive): replace stub function with real implementation; (procfs_lwp_creation_handler): fix bug starting new child threads; (info_proc): bug fixes and enhancements for the "INFO PROCESSES" command; (close_procinfo_file): call new function "delete_thread" to cleanup GDB's thread database; (proc_init_failed): add new argument "kill", to control whether process is killed (so this function can be shared by create_procinfo and do_attach); (procfs_exit_handler): handle exit from an attached process, and cleanup procinfo handles when the process exits; (procfs_resume, procfs_wait): cleanup after a thread when it exits; (do_attach, do_detach): handle attached processes with multiple threads; plus some general improvements in the diagnostic output. * sol-thread.c (sol_thread_alive): replace stub with real implementation; (thread_to_lwp, lwp_to_thread): enhance to handle threads that may have exited; (sol_thread_attach): add startup setup stuff; (sol_thread_detach): add unpush_target call; (sol_thread_mourn_inferior): add unpush_target call; (sol_thread_wait, sol_thread_resume): enhance to deal with thread exit cleanly; (sol_thread_new_objfile, sol_thread_pid_to_str): detect unsuccessful startup and don't crash; plus some general cleanup. * thread.c (delete_thread): new function, allows targets to notify gdb when a thread is no longer valid. * infrun.c (wait_for_inferior): don't try to detect a new thread on receiving a TARGET_EXITED event.
This commit is contained in:
parent
b4a4a6dc0f
commit
3780c33708
4 changed files with 745 additions and 410 deletions
|
@ -1,3 +1,43 @@
|
|||
Wed May 21 16:03:25 1997 Michael Snyder <msnyder@cleaver.cygnus.com>
|
||||
|
||||
* procfs.c (init_procinfo): new function, abstracts some code
|
||||
shared by create_procinfo and do_attach;
|
||||
(procfs_set_inferior_syscall_traps): new function, abstracts
|
||||
some code needed by procfs_init_inferior, do_attach, and
|
||||
procfs_lwp_creation_handler; (procfs_first_available): new
|
||||
function, find any LWP that's runnable; (procfs_thread_alive):
|
||||
replace stub function with real implementation;
|
||||
(procfs_lwp_creation_handler): fix bug starting new child
|
||||
threads; (info_proc): bug fixes and enhancements for the
|
||||
"INFO PROCESSES" command; (close_procinfo_file): call new
|
||||
function "delete_thread" to cleanup GDB's thread database;
|
||||
(proc_init_failed): add new argument "kill", to control whether
|
||||
process is killed (so this function can be shared by
|
||||
create_procinfo and do_attach); (procfs_exit_handler): handle
|
||||
exit from an attached process, and cleanup procinfo handles
|
||||
when the process exits; (procfs_resume, procfs_wait): cleanup
|
||||
after a thread when it exits; (do_attach, do_detach): handle
|
||||
attached processes with multiple threads; plus some general
|
||||
improvements in the diagnostic output.
|
||||
* sol-thread.c (sol_thread_alive): replace stub with real
|
||||
implementation; (thread_to_lwp, lwp_to_thread): enhance to
|
||||
handle threads that may have exited; (sol_thread_attach): add
|
||||
startup setup stuff; (sol_thread_detach): add unpush_target
|
||||
call; (sol_thread_mourn_inferior): add unpush_target call;
|
||||
(sol_thread_wait, sol_thread_resume): enhance to deal with
|
||||
thread exit cleanly; (sol_thread_new_objfile,
|
||||
sol_thread_pid_to_str): detect unsuccessful startup and
|
||||
don't crash; plus some general cleanup.
|
||||
* thread.c (delete_thread): new function, allows targets to
|
||||
notify gdb when a thread is no longer valid.
|
||||
* infrun.c (wait_for_inferior): don't try to detect a new
|
||||
thread on receiving a TARGET_EXITED event.
|
||||
|
||||
Tue May 20 09:32:02 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
* remote-sim.c (gdbsim_open): Pass callback struct.
|
||||
(init_callbacks): Remove call to sim_set_callbacks.
|
||||
|
||||
Thu May 15 07:56:50 1997 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
|
||||
|
||||
* config/rs6000/tm-rs6000.h (SIG_FRAME_LR_OFFSET): Define.
|
||||
|
|
598
gdb/procfs.c
598
gdb/procfs.c
|
@ -181,14 +181,15 @@ struct procinfo {
|
|||
struct sig_ctl saved_trace; /* Saved traced signal set */
|
||||
struct sys_ctl saved_exitset; /* Saved traced system call exit set */
|
||||
struct sys_ctl saved_entryset;/* Saved traced system call entry set */
|
||||
int num_syscall_handlers; /* Number of syscall handlers currently installed */
|
||||
struct procfs_syscall_handler *syscall_handlers; /* Pointer to list of syscall trap handlers */
|
||||
int num_syscall_handlers; /* Number of syscall trap handlers
|
||||
currently installed */
|
||||
/* Pointer to list of syscall trap handlers */
|
||||
struct procfs_syscall_handler *syscall_handlers;
|
||||
int new_child; /* Non-zero if it's a new thread */
|
||||
};
|
||||
|
||||
/* List of inferior process information */
|
||||
static struct procinfo *procinfo_list = NULL;
|
||||
|
||||
static struct pollfd *poll_list; /* pollfds used for waiting on /proc */
|
||||
|
||||
static int num_poll_list = 0; /* Number of entries in poll_list */
|
||||
|
@ -247,6 +248,15 @@ static struct trans pr_flag_table[] =
|
|||
#endif
|
||||
#if defined (PR_PCOMPAT)
|
||||
{ PR_PCOMPAT, "PR_PCOMPAT", "Ptrace compatibility mode in effect" },
|
||||
#endif
|
||||
#if defined (PR_MSACCT)
|
||||
{ PR_MSACCT, "PR_MSACCT", "Microstate accounting enabled" },
|
||||
#endif
|
||||
#if defined (PR_BPTADJ)
|
||||
{ PR_BPTADJ, "PR_BPTADJ", "Breakpoint PC adjustment in effect" },
|
||||
#endif
|
||||
#if defined (PR_ASLWP)
|
||||
{ PR_ASLWP, "PR_ASLWP", "Asynchronus signal LWP" },
|
||||
#endif
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
@ -261,9 +271,6 @@ static struct trans pr_why_table[] =
|
|||
#if defined (PR_SIGNALLED)
|
||||
{ PR_SIGNALLED, "PR_SIGNALLED", "Receipt of a traced signal" },
|
||||
#endif
|
||||
#if defined (PR_FAULTED)
|
||||
{ PR_FAULTED, "PR_FAULTED", "Incurred a traced hardware fault" },
|
||||
#endif
|
||||
#if defined (PR_SYSENTRY)
|
||||
{ PR_SYSENTRY, "PR_SYSENTRY", "Entry to a traced system call" },
|
||||
#endif
|
||||
|
@ -273,8 +280,14 @@ static struct trans pr_why_table[] =
|
|||
#if defined (PR_JOBCONTROL)
|
||||
{ PR_JOBCONTROL, "PR_JOBCONTROL", "Default job control stop signal action" },
|
||||
#endif
|
||||
#if defined (PR_FAULTED)
|
||||
{ PR_FAULTED, "PR_FAULTED", "Incurred a traced hardware fault" },
|
||||
#endif
|
||||
#if defined (PR_SUSPENDED)
|
||||
{ PR_SUSPENDED, "PR_SUSPENDED", "Process suspended" },
|
||||
#endif
|
||||
#if defined (PR_CHECKPOINT)
|
||||
{ PR_CHECKPOINT, "PR_CHECKPOINT", "(???)" },
|
||||
#endif
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
@ -502,7 +515,7 @@ static void close_proc_file PARAMS ((struct procinfo *));
|
|||
|
||||
static void unconditionally_kill_inferior PARAMS ((struct procinfo *));
|
||||
|
||||
static NORETURN void proc_init_failed PARAMS ((struct procinfo *, char *)) ATTR_NORETURN;
|
||||
static NORETURN void proc_init_failed PARAMS ((struct procinfo *, char *, int)) ATTR_NORETURN;
|
||||
|
||||
static void info_proc PARAMS ((char *, int));
|
||||
|
||||
|
@ -538,8 +551,8 @@ static void notice_signals PARAMS ((struct procinfo *, struct sig_ctl *));
|
|||
|
||||
static struct procinfo *find_procinfo PARAMS ((pid_t pid, int okfail));
|
||||
|
||||
static int procfs_read_status PARAMS ((struct procinfo *));
|
||||
static int procfs_write_pcwstop PARAMS ((struct procinfo *));
|
||||
static int procfs_read_status PARAMS ((struct procinfo *));
|
||||
static void procfs_write_pckill PARAMS ((struct procinfo *));
|
||||
|
||||
typedef int syscall_func_t PARAMS ((struct procinfo *pi, int syscall_num,
|
||||
|
@ -684,6 +697,22 @@ add_fd (pi)
|
|||
num_poll_list++;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
LOCAL FUNCTION
|
||||
|
||||
remove_fd -- Remove the fd from the poll/select list
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
static void remove_fd (struct procinfo *);
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
Remove the fd of the supplied procinfo from the list of fds used
|
||||
for poll/select operations.
|
||||
*/
|
||||
|
||||
static void
|
||||
remove_fd (pi)
|
||||
struct procinfo *pi;
|
||||
|
@ -859,7 +888,8 @@ wait_fd ()
|
|||
|
||||
for (i = 0; i < num_poll_list && num_fds > 0; i++)
|
||||
{
|
||||
if ((poll_list[i].revents & (POLLWRNORM|POLLPRI|POLLERR|POLLHUP|POLLNVAL)) == 0)
|
||||
if (0 == (poll_list[i].revents &
|
||||
(POLLWRNORM | POLLPRI | POLLERR | POLLHUP | POLLNVAL)))
|
||||
continue;
|
||||
for (pi = procinfo_list; pi; pi = pi->next)
|
||||
{
|
||||
|
@ -867,8 +897,11 @@ wait_fd ()
|
|||
{
|
||||
if (!procfs_read_status(pi))
|
||||
{
|
||||
print_sys_errmsg (pi->pathname, errno);
|
||||
error ("procfs_read_status failed");
|
||||
/* The LWP has apparently terminated. */
|
||||
if (info_verbose)
|
||||
printf_filtered ("LWP %d doesn't respond.\n",
|
||||
(pi->pid >> 16) & 0xffff);
|
||||
/* could call close_proc_file here, but I'm afraid to... */
|
||||
}
|
||||
|
||||
num_fds--;
|
||||
|
@ -1549,23 +1582,23 @@ init_syscall_table ()
|
|||
#if defined (SYS_settimeofday)
|
||||
syscall_table[SYS_settimeofday] = "settimeofday";
|
||||
#endif
|
||||
#if defined (SYS_lwpcreate)
|
||||
syscall_table[SYS_lwpcreate] = "lwpcreate";
|
||||
#if defined (SYS_lwp_create)
|
||||
syscall_table[SYS_lwp_create] = "_lwp_create";
|
||||
#endif
|
||||
#if defined (SYS_lwpexit)
|
||||
syscall_table[SYS_lwpexit] = "lwpexit";
|
||||
#if defined (SYS_lwp_exit)
|
||||
syscall_table[SYS_lwp_exit] = "_lwp_exit";
|
||||
#endif
|
||||
#if defined (SYS_lwpwait)
|
||||
syscall_table[SYS_lwpwait] = "lwpwait";
|
||||
#if defined (SYS_lwp_wait)
|
||||
syscall_table[SYS_lwp_wait] = "_lwp_wait";
|
||||
#endif
|
||||
#if defined (SYS_lwpself)
|
||||
syscall_table[SYS_lwpself] = "lwpself";
|
||||
#if defined (SYS_lwp_self)
|
||||
syscall_table[SYS_lwp_self] = "_lwp_self";
|
||||
#endif
|
||||
#if defined (SYS_lwpinfo)
|
||||
syscall_table[SYS_lwpinfo] = "lwpinfo";
|
||||
#if defined (SYS_lwp_info)
|
||||
syscall_table[SYS_lwp_info] = "_lwp_info";
|
||||
#endif
|
||||
#if defined (SYS_lwpprivate)
|
||||
syscall_table[SYS_lwpprivate] = "lwpprivate";
|
||||
#if defined (SYS_lwp_private)
|
||||
syscall_table[SYS_lwp_private] = "_lwp_private";
|
||||
#endif
|
||||
#if defined (SYS_processor_bind)
|
||||
syscall_table[SYS_processor_bind] = "processor_bind";
|
||||
|
@ -1600,8 +1633,8 @@ init_syscall_table ()
|
|||
#if defined (SYS_ftruncate)
|
||||
syscall_table[SYS_ftruncate] = "ftruncate";
|
||||
#endif
|
||||
#if defined (SYS_lwpkill)
|
||||
syscall_table[SYS_lwpkill] = "lwpkill";
|
||||
#if defined (SYS_lwp_kill)
|
||||
syscall_table[SYS_lwp_kill] = "_lwp_kill";
|
||||
#endif
|
||||
#if defined (SYS_sigwait)
|
||||
syscall_table[SYS_sigwait] = "sigwait";
|
||||
|
@ -1630,11 +1663,11 @@ init_syscall_table ()
|
|||
#if defined (SYS_getksym)
|
||||
syscall_table[SYS_getksym] = "getksym";
|
||||
#endif
|
||||
#if defined (SYS_lwpsuspend)
|
||||
syscall_table[SYS_lwpsuspend] = "lwpsuspend";
|
||||
#if defined (SYS_lwp_suspend)
|
||||
syscall_table[SYS_lwp_suspend] = "_lwp_suspend";
|
||||
#endif
|
||||
#if defined (SYS_lwpcontinue)
|
||||
syscall_table[SYS_lwpcontinue] = "lwpcontinue";
|
||||
#if defined (SYS_lwp_continue)
|
||||
syscall_table[SYS_lwp_continue] = "_lwp_continue";
|
||||
#endif
|
||||
#if defined (SYS_priocntllst)
|
||||
syscall_table[SYS_priocntllst] = "priocntllst";
|
||||
|
@ -1643,10 +1676,10 @@ init_syscall_table ()
|
|||
syscall_table[SYS_sleep] = "sleep";
|
||||
#endif
|
||||
#if defined (SYS_lwp_sema_wait)
|
||||
syscall_table[SYS_lwp_sema_wait] = "lwp_sema_wait";
|
||||
syscall_table[SYS_lwp_sema_wait] = "_lwp_sema_wait";
|
||||
#endif
|
||||
#if defined (SYS_lwp_sema_post)
|
||||
syscall_table[SYS_lwp_sema_post] = "lwp_sema_post";
|
||||
syscall_table[SYS_lwp_sema_post] = "_lwp_sema_post";
|
||||
#endif
|
||||
#if defined (SYS_lwp_sema_trywait)
|
||||
syscall_table[SYS_lwp_sema_trywait] = "lwp_sema_trywait";
|
||||
|
@ -1926,6 +1959,96 @@ procfs_store_registers (regno)
|
|||
|
||||
/*
|
||||
|
||||
LOCAL FUNCTION
|
||||
|
||||
init_procinfo - setup a procinfo struct and connect it to a process
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
struct procinfo * init_procinfo (int pid)
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
Allocate a procinfo structure, open the /proc file and then set up the
|
||||
set of signals and faults that are to be traced. Returns a pointer to
|
||||
the new procinfo structure.
|
||||
|
||||
NOTES
|
||||
|
||||
If proc_init_failed ever gets called, control returns to the command
|
||||
processing loop via the standard error handling code.
|
||||
|
||||
*/
|
||||
|
||||
static struct procinfo *
|
||||
init_procinfo (pid, kill)
|
||||
int pid;
|
||||
int kill;
|
||||
{
|
||||
struct procinfo *pi = (struct procinfo *)
|
||||
xmalloc (sizeof (struct procinfo));
|
||||
|
||||
memset ((char *) pi, 0, sizeof (*pi));
|
||||
if (!open_proc_file (pid, pi, O_RDWR, 1))
|
||||
proc_init_failed (pi, "can't open process file", kill);
|
||||
|
||||
/* open_proc_file may modify pid. */
|
||||
|
||||
pid = pi -> pid;
|
||||
|
||||
/* Add new process to process info list */
|
||||
|
||||
pi->next = procinfo_list;
|
||||
procinfo_list = pi;
|
||||
|
||||
add_fd (pi); /* Add to list for poll/select */
|
||||
|
||||
/* Remember some things about the inferior that we will, or might, change
|
||||
so that we can restore them when we detach. */
|
||||
#ifdef UNIXWARE
|
||||
memcpy ((char *) &pi->saved_trace.sigset,
|
||||
(char *) &pi->prstatus.pr_sigtrace, sizeof (sigset_t));
|
||||
memcpy ((char *) &pi->saved_fltset.fltset,
|
||||
(char *) &pi->prstatus.pr_flttrace, sizeof (fltset_t));
|
||||
memcpy ((char *) &pi->saved_entryset.sysset,
|
||||
(char *) &pi->prstatus.pr_sysentry, sizeof (sysset_t));
|
||||
memcpy ((char *) &pi->saved_exitset.sysset,
|
||||
(char *) &pi->prstatus.pr_sysexit, sizeof (sysset_t));
|
||||
|
||||
/* Set up trace and fault sets, as gdb expects them. */
|
||||
|
||||
prfillset (&sctl.sigset);
|
||||
notice_signals (pi, &sctl);
|
||||
prfillset (&fctl.fltset);
|
||||
prdelset (&fctl.fltset, FLTPAGE);
|
||||
|
||||
#else /* ! UNIXWARE */
|
||||
ioctl (pi->ctl_fd, PIOCGTRACE, &pi->saved_trace.sigset);
|
||||
ioctl (pi->ctl_fd, PIOCGHOLD, &pi->saved_sighold.sigset);
|
||||
ioctl (pi->ctl_fd, PIOCGFAULT, &pi->saved_fltset.fltset);
|
||||
ioctl (pi->ctl_fd, PIOCGENTRY, &pi->saved_entryset.sysset);
|
||||
ioctl (pi->ctl_fd, PIOCGEXIT, &pi->saved_exitset.sysset);
|
||||
|
||||
/* Set up trace and fault sets, as gdb expects them. */
|
||||
|
||||
memset ((char *) &pi->prrun, 0, sizeof (pi->prrun));
|
||||
prfillset (&pi->prrun.pr_trace);
|
||||
procfs_notice_signals (pid);
|
||||
prfillset (&pi->prrun.pr_fault);
|
||||
prdelset (&pi->prrun.pr_fault, FLTPAGE);
|
||||
#ifdef PROCFS_DONT_TRACE_FAULTS
|
||||
premptyset (&pi->prrun.pr_fault);
|
||||
#endif
|
||||
#endif /* UNIXWARE */
|
||||
|
||||
if (!procfs_read_status (pi))
|
||||
proc_init_failed (pi, "procfs_read_status failed", kill);
|
||||
|
||||
return pi;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
LOCAL FUNCTION
|
||||
|
||||
create_procinfo - initialize access to a /proc entry
|
||||
|
@ -1959,59 +2082,23 @@ create_procinfo (pid)
|
|||
if (pi != NULL)
|
||||
return pi; /* All done! It already exists */
|
||||
|
||||
pi = (struct procinfo *) xmalloc (sizeof (struct procinfo));
|
||||
|
||||
if (!open_proc_file (pid, pi, O_RDWR, 1))
|
||||
proc_init_failed (pi, "can't open process file");
|
||||
|
||||
/* open_proc_file may modify pid. */
|
||||
|
||||
pid = pi -> pid;
|
||||
|
||||
/* Add new process to process info list */
|
||||
|
||||
pi->next = procinfo_list;
|
||||
procinfo_list = pi;
|
||||
|
||||
add_fd (pi); /* Add to list for poll/select */
|
||||
|
||||
pi->num_syscall_handlers = 0;
|
||||
pi->syscall_handlers = NULL;
|
||||
#ifdef UNIXWARE
|
||||
prfillset (&sctl.sigset);
|
||||
notice_signals (pi, &sctl);
|
||||
prfillset (&fctl.fltset);
|
||||
prdelset (&fctl.fltset, FLTPAGE);
|
||||
#else /* UNIXWARE */
|
||||
memset ((char *) &pi->prrun, 0, sizeof (pi->prrun));
|
||||
prfillset (&pi->prrun.pr_trace);
|
||||
procfs_notice_signals (pid);
|
||||
prfillset (&pi->prrun.pr_fault);
|
||||
prdelset (&pi->prrun.pr_fault, FLTPAGE);
|
||||
#ifdef PROCFS_DONT_TRACE_FAULTS
|
||||
premptyset (&pi->prrun.pr_fault);
|
||||
#endif
|
||||
#endif /* UNIXWARE */
|
||||
|
||||
if (!procfs_read_status (pi))
|
||||
proc_init_failed (pi, "procfs_read_status failed");
|
||||
|
||||
/* A bug in Solaris (2.5 at least) causes PIOCWSTOP to hang on LWPs that are
|
||||
already stopped, even if they all have PR_ASYNC set. */
|
||||
pi = init_procinfo (pid, 1);
|
||||
|
||||
#ifndef UNIXWARE
|
||||
/* A bug in Solaris (2.5 at least) causes PIOCWSTOP to hang on LWPs that are
|
||||
already stopped, even if they all have PR_ASYNC set. */
|
||||
if (!(pi->prstatus.pr_flags & PR_STOPPED))
|
||||
#endif
|
||||
if (!procfs_write_pcwstop (pi))
|
||||
proc_init_failed (pi, "procfs_write_pcwstop failed");
|
||||
proc_init_failed (pi, "procfs_write_pcwstop failed", 1);
|
||||
|
||||
#ifdef PROCFS_USE_READ_WRITE
|
||||
fctl.cmd = PCSFAULT;
|
||||
if (write (pi->ctl_fd, (char *) &fctl, sizeof (struct flt_ctl)) < 0)
|
||||
proc_init_failed (pi, "PCSFAULT failed");
|
||||
proc_init_failed (pi, "PCSFAULT failed", 1);
|
||||
#else
|
||||
if (ioctl (pi->ctl_fd, PIOCSFAULT, &pi->prrun.pr_fault) < 0)
|
||||
proc_init_failed (pi, "PIOCSFAULT failed");
|
||||
proc_init_failed (pi, "PIOCSFAULT failed", 1);
|
||||
#endif
|
||||
|
||||
return pi;
|
||||
|
@ -2047,15 +2134,37 @@ procfs_exit_handler (pi, syscall_num, why, rtnvalp, statvalp)
|
|||
int *rtnvalp;
|
||||
int *statvalp;
|
||||
{
|
||||
struct procinfo *temp_pi, *next_pi;
|
||||
|
||||
pi->prrun.pr_flags = PRCFAULT;
|
||||
|
||||
if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
|
||||
perror_with_name (pi->pathname);
|
||||
|
||||
if (attach_flag)
|
||||
{
|
||||
/* Claim it exited (don't call wait). */
|
||||
if (info_verbose)
|
||||
printf_filtered ("(attached process has exited)\n");
|
||||
*statvalp = 0;
|
||||
*rtnvalp = inferior_pid;
|
||||
}
|
||||
else
|
||||
{
|
||||
*rtnvalp = wait (statvalp);
|
||||
if (*rtnvalp >= 0)
|
||||
*rtnvalp = pi->pid;
|
||||
}
|
||||
|
||||
/* Close ALL open proc file handles,
|
||||
except the one that called SYS_exit. */
|
||||
for (temp_pi = procinfo_list; temp_pi; temp_pi = next_pi)
|
||||
{
|
||||
next_pi = temp_pi->next;
|
||||
if (temp_pi == pi)
|
||||
continue; /* Handled below */
|
||||
close_proc_file (temp_pi);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -2223,39 +2332,24 @@ procfs_fork_handler (pi, syscall_num, why, rtnvalp, statvalp)
|
|||
|
||||
LOCAL FUNCTION
|
||||
|
||||
procfs_init_inferior - initialize target vector and access to a
|
||||
/proc entry
|
||||
procfs_set_inferior_syscall_traps - setup the syscall traps
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
int procfs_init_inferior (int pid)
|
||||
void procfs_set_inferior_syscall_traps (struct procinfo *pip)
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
When gdb starts an inferior, this function is called in the parent
|
||||
process immediately after the fork. It waits for the child to stop
|
||||
on the return from the exec system call (the child itself takes care
|
||||
of ensuring that this is set up), then sets up the set of signals
|
||||
and faults that are to be traced. Returns the pid, which may have had
|
||||
the thread-id added to it.
|
||||
|
||||
NOTES
|
||||
|
||||
If proc_init_failed ever gets called, control returns to the command
|
||||
processing loop via the standard error handling code.
|
||||
Called for each "procinfo" (process, thread, or LWP) in the
|
||||
inferior, to register for notification of and handlers for
|
||||
syscall traps in the inferior.
|
||||
|
||||
*/
|
||||
|
||||
static int
|
||||
procfs_init_inferior (pid)
|
||||
int pid;
|
||||
{
|
||||
static void
|
||||
procfs_set_inferior_syscall_traps (pip)
|
||||
struct procinfo *pip;
|
||||
|
||||
push_target (&procfs_ops);
|
||||
|
||||
pip = create_procinfo (pid);
|
||||
|
||||
{
|
||||
#ifndef PIOCSSPCACT
|
||||
procfs_set_syscall_trap (pip, SYS_exit, PROCFS_SYSCALL_ENTRY,
|
||||
procfs_exit_handler);
|
||||
|
@ -2297,6 +2391,46 @@ procfs_init_inferior (pid)
|
|||
procfs_set_syscall_trap (pip, SYS_lwp_create, PROCFS_SYSCALL_EXIT,
|
||||
procfs_lwp_creation_handler);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
LOCAL FUNCTION
|
||||
|
||||
procfs_init_inferior - initialize target vector and access to a
|
||||
/proc entry
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
int procfs_init_inferior (int pid)
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
When gdb starts an inferior, this function is called in the parent
|
||||
process immediately after the fork. It waits for the child to stop
|
||||
on the return from the exec system call (the child itself takes care
|
||||
of ensuring that this is set up), then sets up the set of signals
|
||||
and faults that are to be traced. Returns the pid, which may have had
|
||||
the thread-id added to it.
|
||||
|
||||
NOTES
|
||||
|
||||
If proc_init_failed ever gets called, control returns to the command
|
||||
processing loop via the standard error handling code.
|
||||
|
||||
*/
|
||||
|
||||
static int
|
||||
procfs_init_inferior (pid)
|
||||
int pid;
|
||||
{
|
||||
struct procinfo *pip;
|
||||
|
||||
push_target (&procfs_ops);
|
||||
|
||||
pip = create_procinfo (pid);
|
||||
|
||||
procfs_set_inferior_syscall_traps (pip);
|
||||
|
||||
/* create_procinfo may change the pid, so we have to update inferior_pid
|
||||
here before calling other gdb routines that need the right pid. */
|
||||
|
@ -2863,34 +2997,30 @@ do_attach (pid)
|
|||
struct procinfo *pi;
|
||||
struct sig_ctl sctl;
|
||||
struct flt_ctl fctl;
|
||||
int nlwp, *lwps;
|
||||
|
||||
pi = (struct procinfo *) xmalloc (sizeof (struct procinfo));
|
||||
pi = init_procinfo (pid, 0);
|
||||
|
||||
if (!open_proc_file (pid, pi, O_RDWR, 1))
|
||||
{
|
||||
free (pi);
|
||||
perror_with_name (pi->pathname);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
#ifdef PIOCLWPIDS
|
||||
nlwp = pi->prstatus.pr_nlwp;
|
||||
lwps = alloca ((2 * nlwp + 2) * sizeof (id_t));
|
||||
|
||||
pid = pi -> pid;
|
||||
|
||||
/* Add new process to process info list */
|
||||
|
||||
pi->next = procinfo_list;
|
||||
procinfo_list = pi;
|
||||
|
||||
add_fd (pi); /* Add to list for poll/select */
|
||||
|
||||
/* Get current status of process and if it is not already stopped,
|
||||
then stop it. Remember whether or not it was stopped when we first
|
||||
examined it. */
|
||||
if (!procfs_read_status (pi))
|
||||
if (ioctl (pi->ctl_fd, PIOCLWPIDS, lwps))
|
||||
{
|
||||
print_sys_errmsg (pi -> pathname, errno);
|
||||
close_proc_file (pi);
|
||||
error ("procfs_read_status failed");
|
||||
error ("PIOCLWPIDS failed");
|
||||
}
|
||||
#else /* PIOCLWPIDS */
|
||||
nlwp = 1;
|
||||
lwps = alloca ((2 * nlwp + 2) * sizeof *lwps);
|
||||
lwps[0] = 0;
|
||||
#endif
|
||||
for (; nlwp > 0; nlwp--, lwps++)
|
||||
{
|
||||
/* First one has already been created above. */
|
||||
if ((pi = find_procinfo ((*lwps << 16) | pid, 1)) == 0)
|
||||
pi = init_procinfo ((*lwps << 16) | pid, 0);
|
||||
|
||||
#ifdef UNIXWARE
|
||||
if (pi->prstatus.pr_lwp.pr_flags & (PR_STOPPED | PR_ISTOP))
|
||||
#else
|
||||
|
@ -2906,9 +3036,7 @@ do_attach (pid)
|
|||
{
|
||||
long cmd;
|
||||
/* Make it run again when we close it. */
|
||||
|
||||
modify_run_on_last_close_flag (pi->ctl_fd, 1);
|
||||
|
||||
#ifdef PROCFS_USE_READ_WRITE
|
||||
cmd = PCSTOP;
|
||||
if (write (pi->ctl_fd, (char *) &cmd, sizeof (long)) < 0)
|
||||
|
@ -2932,51 +3060,16 @@ do_attach (pid)
|
|||
}
|
||||
else
|
||||
{
|
||||
printf_unfiltered ("Ok, gdb will wait for %s to stop.\n", target_pid_to_str (pid));
|
||||
printf_unfiltered ("Ok, gdb will wait for %s to stop.\n",
|
||||
target_pid_to_str (pi->pid));
|
||||
}
|
||||
}
|
||||
|
||||
/* Remember some things about the inferior that we will, or might, change
|
||||
so that we can restore them when we detach. */
|
||||
#ifdef PROCFS_USE_READ_WRITE
|
||||
memcpy ((char *) &pi->saved_trace.sigset,
|
||||
(char *) &pi->prstatus.pr_sigtrace, sizeof (sigset_t));
|
||||
memcpy ((char *) &pi->saved_fltset.fltset,
|
||||
(char *) &pi->prstatus.pr_flttrace, sizeof (fltset_t));
|
||||
memcpy ((char *) &pi->saved_entryset.sysset,
|
||||
(char *) &pi->prstatus.pr_sysentry, sizeof (sysset_t));
|
||||
memcpy ((char *) &pi->saved_exitset.sysset,
|
||||
(char *) &pi->prstatus.pr_sysexit, sizeof (sysset_t));
|
||||
|
||||
/* Set up trace and fault sets, as gdb expects them. */
|
||||
|
||||
prfillset (&sctl.sigset);
|
||||
notice_signals (pi, &sctl);
|
||||
prfillset (&fctl.fltset);
|
||||
prdelset (&fctl.fltset, FLTPAGE);
|
||||
|
||||
fctl.cmd = PCSFAULT;
|
||||
if (write (pi->ctl_fd, (char *) &fctl, sizeof (struct flt_ctl)) < 0)
|
||||
print_sys_errmsg ("PCSFAULT failed", errno);
|
||||
#else /* PROCFS_USE_READ_WRITE */
|
||||
ioctl (pi->ctl_fd, PIOCGTRACE, &pi->saved_trace.sigset);
|
||||
ioctl (pi->ctl_fd, PIOCGHOLD, &pi->saved_sighold.sigset);
|
||||
ioctl (pi->ctl_fd, PIOCGFAULT, &pi->saved_fltset.fltset);
|
||||
ioctl (pi->ctl_fd, PIOCGENTRY, &pi->saved_entryset.sysset);
|
||||
ioctl (pi->ctl_fd, PIOCGEXIT, &pi->saved_exitset.sysset);
|
||||
|
||||
/* Set up trace and fault sets, as gdb expects them. */
|
||||
|
||||
memset (&pi->prrun, 0, sizeof (pi->prrun));
|
||||
prfillset (&pi->prrun.pr_trace);
|
||||
procfs_notice_signals (pid);
|
||||
prfillset (&pi->prrun.pr_fault);
|
||||
prdelset (&pi->prrun.pr_fault, FLTPAGE);
|
||||
|
||||
#ifdef PROCFS_DONT_TRACE_FAULTS
|
||||
premptyset (&pi->prrun.pr_fault);
|
||||
#endif
|
||||
|
||||
if (ioctl (pi->ctl_fd, PIOCSFAULT, &pi->prrun.pr_fault))
|
||||
{
|
||||
print_sys_errmsg ("PIOCSFAULT failed", errno);
|
||||
|
@ -2985,9 +3078,12 @@ do_attach (pid)
|
|||
{
|
||||
print_sys_errmsg ("PIOCSTRACE failed", errno);
|
||||
}
|
||||
add_thread (pi->pid);
|
||||
procfs_set_inferior_syscall_traps (pi);
|
||||
}
|
||||
#endif /* PROCFS_USE_READ_WRITE */
|
||||
attach_flag = 1;
|
||||
return (pid);
|
||||
return (pi->pid);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3025,8 +3121,8 @@ do_detach (signal)
|
|||
{
|
||||
struct procinfo *pi;
|
||||
|
||||
pi = current_procinfo;
|
||||
|
||||
for (pi = procinfo_list; pi; pi = pi->next)
|
||||
{
|
||||
if (signal)
|
||||
{
|
||||
set_proc_siginfo (pi, signal);
|
||||
|
@ -3125,6 +3221,7 @@ do_detach (signal)
|
|||
}
|
||||
}
|
||||
close_proc_file (pi);
|
||||
}
|
||||
attach_flag = 0;
|
||||
}
|
||||
|
||||
|
@ -3152,7 +3249,6 @@ do_detach (signal)
|
|||
|
||||
FIXME: Investigate why wait() seems to have problems with programs
|
||||
being control by /proc routines. */
|
||||
|
||||
static int
|
||||
procfs_wait (pid, ourstatus)
|
||||
int pid;
|
||||
|
@ -3208,11 +3304,12 @@ procfs_wait (pid, ourstatus)
|
|||
{
|
||||
if (errno == ENOENT)
|
||||
{
|
||||
/* XXX Fixme -- what to do if attached? Can't call wait... */
|
||||
rtnval = wait (&statval);
|
||||
if (rtnval != inferior_pid)
|
||||
if ((rtnval) != (inferior_pid))
|
||||
{
|
||||
print_sys_errmsg (pi->pathname, errno);
|
||||
error ("procfs_write_pcwstop, wait failed, returned %d", rtnval);
|
||||
error ("procfs_wait: wait failed, returned %d", rtnval);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
|
@ -3350,10 +3447,11 @@ procfs_wait (pid, ourstatus)
|
|||
/* Stop all the other threads when any of them stops. */
|
||||
|
||||
{
|
||||
struct procinfo *procinfo;
|
||||
struct procinfo *procinfo, *next_pi;
|
||||
|
||||
for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)
|
||||
for (procinfo = procinfo_list; procinfo; procinfo = next_pi)
|
||||
{
|
||||
next_pi = procinfo->next;
|
||||
if (!procinfo->had_event)
|
||||
{
|
||||
#ifdef PROCFS_USE_READ_WRITE
|
||||
|
@ -3369,15 +3467,20 @@ procfs_wait (pid, ourstatus)
|
|||
order to avoid the hang. */
|
||||
if (!procfs_read_status (procinfo))
|
||||
{
|
||||
print_sys_errmsg (procinfo->pathname, errno);
|
||||
error ("procfs_read_status failed");
|
||||
/* The LWP has apparently terminated. */
|
||||
if (info_verbose)
|
||||
printf_filtered ("LWP %d doesn't respond.\n",
|
||||
(procinfo->pid >> 16) & 0xffff);
|
||||
close_proc_file (procinfo);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(procinfo->prstatus.pr_flags & PR_STOPPED))
|
||||
if (ioctl (procinfo->ctl_fd, PIOCSTOP, &procinfo->prstatus) < 0)
|
||||
if (ioctl (procinfo->ctl_fd, PIOCSTOP, &procinfo->prstatus)
|
||||
< 0)
|
||||
{
|
||||
print_sys_errmsg (procinfo->pathname, errno);
|
||||
error ("PIOCSTOP failed");
|
||||
warning ("PIOCSTOP failed");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -3394,7 +3497,7 @@ procfs_wait (pid, ourstatus)
|
|||
|
||||
if (rtnval == -1) /* No more children to wait for */
|
||||
{
|
||||
fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing.\n");
|
||||
warning ("Child process unexpectedly missing");
|
||||
/* Claim it exited with unknown signal. */
|
||||
ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
|
||||
ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
|
||||
|
@ -3514,7 +3617,7 @@ procfs_resume (pid, step, signo)
|
|||
enum target_signal signo;
|
||||
{
|
||||
int signal_to_pass;
|
||||
struct procinfo *pi, *procinfo;
|
||||
struct procinfo *pi, *procinfo, *next_pi;
|
||||
struct proc_ctl pctl;
|
||||
|
||||
pi = find_procinfo (pid == -1 ? inferior_pid : pid, 0);
|
||||
|
@ -3562,11 +3665,12 @@ procfs_resume (pid, step, signo)
|
|||
else if (signo == TARGET_SIGNAL_TSTP
|
||||
#ifdef UNIXWARE
|
||||
&& pi->prstatus.pr_lwp.pr_cursig == SIGTSTP
|
||||
&& pi->prstatus.pr_lwp.pr_action.sa_handler == SIG_DFL)
|
||||
&& pi->prstatus.pr_lwp.pr_action.sa_handler == SIG_DFL
|
||||
#else
|
||||
&& pi->prstatus.pr_cursig == SIGTSTP
|
||||
&& pi->prstatus.pr_action.sa_handler == SIG_DFL)
|
||||
&& pi->prstatus.pr_action.sa_handler == SIG_DFL
|
||||
#endif
|
||||
)
|
||||
|
||||
/* We are about to pass the inferior a SIGTSTP whose action is
|
||||
SIG_DFL. The SIG_DFL action for a SIGTSTP is to stop
|
||||
|
@ -3607,10 +3711,20 @@ procfs_resume (pid, step, signo)
|
|||
pi->prrun.pr_flags |= PRSTEP;
|
||||
#endif
|
||||
}
|
||||
|
||||
pi->had_event = 0;
|
||||
/* Don't try to start a process unless it's stopped on an
|
||||
`event of interest'. Doing so will cause errors. */
|
||||
|
||||
if (!procfs_read_status (pi))
|
||||
{
|
||||
/* The LWP has apparently terminated. */
|
||||
if (info_verbose)
|
||||
printf_filtered ("LWP %d doesn't respond.\n",
|
||||
(pi->pid >> 16) & 0xffff);
|
||||
close_proc_file (pi);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef PROCFS_USE_READ_WRITE
|
||||
if (write (pi->ctl_fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
|
||||
#else
|
||||
|
@ -3618,29 +3732,37 @@ procfs_resume (pid, step, signo)
|
|||
&& ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
|
||||
#endif
|
||||
{
|
||||
perror_with_name (pi->pathname);
|
||||
/* NOTREACHED */
|
||||
/* The LWP has apparently terminated. */
|
||||
if (info_verbose)
|
||||
printf_filtered ("LWP %d doesn't respond.\n",
|
||||
(pi->pid >> 16) & 0xffff);
|
||||
close_proc_file (pi);
|
||||
}
|
||||
}
|
||||
|
||||
pi->had_event = 0;
|
||||
|
||||
/* Continue all the other threads that haven't had an event of
|
||||
interest. */
|
||||
/* Continue all the other threads that haven't had an event of interest.
|
||||
Also continue them if they have NOPASS_NEXT_SIGSTOP set; this is only
|
||||
set by do_attach, and means this is the first resume after an attach.
|
||||
All threads were CSTOP'd by do_attach, and should be resumed now. */
|
||||
|
||||
if (pid == -1)
|
||||
for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)
|
||||
for (procinfo = procinfo_list; procinfo; procinfo = next_pi)
|
||||
{
|
||||
if (pi != procinfo && !procinfo->had_event)
|
||||
next_pi = procinfo->next;
|
||||
if (pi != procinfo)
|
||||
if (!procinfo->had_event ||
|
||||
(procinfo->nopass_next_sigstop && signo == TARGET_SIGNAL_STOP))
|
||||
{
|
||||
procinfo->had_event = procinfo->nopass_next_sigstop = 0;
|
||||
#ifdef PROCFS_USE_READ_WRITE
|
||||
pctl.data = PRCFAULT | PRCSIG;
|
||||
if (write (procinfo->ctl_fd, (char *) &pctl,
|
||||
sizeof (struct proc_ctl)) < 0)
|
||||
{
|
||||
if (!procfs_read_status (procinfo))
|
||||
{
|
||||
fprintf_unfiltered(gdb_stderr, "procfs_read_status failed, errno=%d\n", errno);
|
||||
}
|
||||
fprintf_unfiltered(gdb_stderr,
|
||||
"procfs_read_status failed, errno=%d\n",
|
||||
errno);
|
||||
print_sys_errmsg (procinfo->pathname, errno);
|
||||
error ("PCRUN failed");
|
||||
}
|
||||
|
@ -3648,7 +3770,15 @@ procfs_resume (pid, step, signo)
|
|||
#else
|
||||
procinfo->prrun.pr_flags &= PRSTEP;
|
||||
procinfo->prrun.pr_flags |= PRCFAULT | PRCSIG;
|
||||
procfs_read_status (procinfo);
|
||||
if (!procfs_read_status (procinfo))
|
||||
{
|
||||
/* The LWP has apparently terminated. */
|
||||
if (info_verbose)
|
||||
printf_filtered ("LWP %d doesn't respond.\n",
|
||||
(procinfo->pid >> 16) & 0xffff);
|
||||
close_proc_file (procinfo);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Don't try to start a process unless it's stopped on an
|
||||
`event of interest'. Doing so will cause errors. */
|
||||
|
@ -3657,17 +3787,17 @@ procfs_resume (pid, step, signo)
|
|||
&& ioctl (procinfo->ctl_fd, PIOCRUN, &procinfo->prrun) < 0)
|
||||
{
|
||||
if (!procfs_read_status (procinfo))
|
||||
{
|
||||
fprintf_unfiltered(gdb_stderr, "procfs_read_status failed, errno=%d\n", errno);
|
||||
}
|
||||
fprintf_unfiltered(gdb_stderr,
|
||||
"procfs_read_status failed, errno=%d\n",
|
||||
errno);
|
||||
print_sys_errmsg (procinfo->pathname, errno);
|
||||
error ("PIOCRUN failed");
|
||||
warning ("PIOCRUN failed");
|
||||
}
|
||||
}
|
||||
procfs_read_status (procinfo);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
|
@ -3721,27 +3851,30 @@ procfs_fetch_registers (regno)
|
|||
|
||||
LOCAL FUNCTION
|
||||
|
||||
proc_init_failed - called whenever /proc access initialization
|
||||
proc_init_failed - called when /proc access initialization fails
|
||||
fails
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
static void proc_init_failed (struct procinfo *pi, char *why)
|
||||
static void proc_init_failed (struct procinfo *pi,
|
||||
char *why, int kill_p)
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
This function is called whenever initialization of access to a /proc
|
||||
entry fails. It prints a suitable error message, does some cleanup,
|
||||
and then invokes the standard error processing routine which dumps
|
||||
us back into the command loop.
|
||||
us back into the command loop. If KILL_P is true, sends SIGKILL.
|
||||
*/
|
||||
|
||||
static void
|
||||
proc_init_failed (pi, why)
|
||||
proc_init_failed (pi, why, kill_p)
|
||||
struct procinfo *pi;
|
||||
char *why;
|
||||
int kill_p;
|
||||
{
|
||||
print_sys_errmsg (pi->pathname, errno);
|
||||
if (kill_p)
|
||||
kill (pi->pid, SIGKILL);
|
||||
close_proc_file (pi);
|
||||
error (why);
|
||||
|
@ -3773,6 +3906,7 @@ close_proc_file (pip)
|
|||
{
|
||||
struct procinfo *procinfo;
|
||||
|
||||
delete_thread (pip->pid); /* remove thread from GDB's thread list */
|
||||
remove_fd (pip); /* Remove fd from poll/select list */
|
||||
|
||||
close (pip->ctl_fd);
|
||||
|
@ -4531,7 +4665,7 @@ info_proc (args, from_tty)
|
|||
char *args;
|
||||
int from_tty;
|
||||
{
|
||||
int pid = inferior_pid;
|
||||
int pid;
|
||||
struct procinfo *pip;
|
||||
struct cleanup *old_chain;
|
||||
char **argv;
|
||||
|
@ -4554,7 +4688,10 @@ info_proc (args, from_tty)
|
|||
/* Default to using the current inferior if no pid specified. Note
|
||||
that inferior_pid may be 0, hence we set okerr. */
|
||||
|
||||
pip = find_procinfo (inferior_pid, 1);
|
||||
pid = inferior_pid & 0x7fffffff; /* strip off sol-thread bit */
|
||||
if (!(pip = find_procinfo (pid, 1))) /* inferior_pid no good? */
|
||||
pip = procinfo_list; /* take first available */
|
||||
pid = pid & 0xffff; /* extract "real" pid */
|
||||
|
||||
if (args != NULL)
|
||||
{
|
||||
|
@ -4652,7 +4789,7 @@ No process. Start debugging a program or specify an explicit process ID.");
|
|||
#ifndef PROCFS_USE_READ_WRITE
|
||||
#ifdef PIOCLWPIDS
|
||||
nlwp = pip->prstatus.pr_nlwp;
|
||||
lwps = alloca ((2 * nlwp + 2) * sizeof (id_t));
|
||||
lwps = alloca ((2 * nlwp + 2) * sizeof (*lwps));
|
||||
|
||||
if (ioctl (pip->ctl_fd, PIOCLWPIDS, lwps))
|
||||
{
|
||||
|
@ -4698,6 +4835,10 @@ No process. Start debugging a program or specify an explicit process ID.");
|
|||
if (summary || all)
|
||||
{
|
||||
info_proc_stop (pip, summary);
|
||||
supply_gregset (&pip->prstatus.pr_reg);
|
||||
printf_filtered ("PC: ");
|
||||
print_address (read_pc (), gdb_stdout);
|
||||
printf_filtered ("\n");
|
||||
}
|
||||
if (summary || all || signals || faults)
|
||||
{
|
||||
|
@ -5157,18 +5298,36 @@ procfs_lwp_creation_handler (pi, syscall_num, why, rtnvalp, statvalp)
|
|||
childpi = create_procinfo (lwp_id);
|
||||
|
||||
/* The new process has actually inherited the lwp_create syscall trap from
|
||||
it's parent, but we still have to call this to register a handler for
|
||||
it's parent, but we still have to call this to register handlers for
|
||||
that child. */
|
||||
|
||||
procfs_set_syscall_trap (childpi, SYS_lwp_create, PROCFS_SYSCALL_EXIT,
|
||||
procfs_lwp_creation_handler);
|
||||
procfs_set_inferior_syscall_traps (childpi);
|
||||
add_thread (lwp_id);
|
||||
printf_filtered ("[New %s]\n", target_pid_to_str (lwp_id));
|
||||
|
||||
/* Continue the parent */
|
||||
|
||||
pi->prrun.pr_flags &= PRSTEP;
|
||||
pi->prrun.pr_flags |= PRCFAULT;
|
||||
if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
|
||||
perror_with_name (pi->pathname);
|
||||
|
||||
/* The new child may have been created in one of two states:
|
||||
SUSPENDED or RUNNABLE. If runnable, we will simply signal it to run.
|
||||
If suspended, we flag it to be continued later, when it has an event. */
|
||||
|
||||
if (childpi->prstatus.pr_why == PR_SUSPENDED)
|
||||
childpi->new_child = 1; /* Flag this as an unseen child process */
|
||||
else
|
||||
{
|
||||
/* Continue the child */
|
||||
childpi->prrun.pr_flags &= PRSTEP;
|
||||
childpi->prrun.pr_flags |= PRCFAULT;
|
||||
|
||||
*rtnvalp = lwp_id; /* the new arrival. */
|
||||
*statvalp = (SIGTRAP << 8) | 0177;
|
||||
|
||||
return 1;
|
||||
if (ioctl (childpi->ctl_fd, PIOCRUN, &childpi->prrun) != 0)
|
||||
perror_with_name (childpi->pathname);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* SYS_lwp_create */
|
||||
|
||||
|
@ -5356,7 +5515,34 @@ static int
|
|||
procfs_thread_alive (pid)
|
||||
int pid;
|
||||
{
|
||||
struct procinfo *pi, *next_pi;
|
||||
|
||||
for (pi = procinfo_list; pi; pi = next_pi)
|
||||
{
|
||||
next_pi = pi->next;
|
||||
if (pi -> pid == pid)
|
||||
if (procfs_read_status (pi)) /* alive */
|
||||
return 1;
|
||||
else /* defunct (exited) */
|
||||
{
|
||||
close_proc_file (pi);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
procfs_first_available ()
|
||||
{
|
||||
struct procinfo *pi;
|
||||
|
||||
for (pi = procinfo_list; pi; pi = pi->next)
|
||||
{
|
||||
if (procfs_read_status (pi))
|
||||
return pi->pid;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Send a SIGINT to the process group. This acts just like the user typed a
|
||||
|
@ -5449,7 +5635,7 @@ _initialize_procfs ()
|
|||
|
||||
add_target (&procfs_ops);
|
||||
|
||||
add_info ("proc", info_proc,
|
||||
add_info ("processes", info_proc,
|
||||
"Show process status information using /proc entry.\n\
|
||||
Specify process id or use current inferior by default.\n\
|
||||
Specify keywords for detailed information; default is summary.\n\
|
||||
|
|
161
gdb/sol-thread.c
161
gdb/sol-thread.c
|
@ -72,6 +72,7 @@ extern struct target_ops sol_thread_ops; /* Forward declaration */
|
|||
|
||||
extern int procfs_suppress_run;
|
||||
extern struct target_ops procfs_ops; /* target vector for procfs.c */
|
||||
extern char *procfs_pid_to_str PARAMS ((int pid));
|
||||
|
||||
/* Note that these prototypes differ slightly from those used in procfs.c
|
||||
for of two reasons. One, we can't use gregset_t, as that's got a whole
|
||||
|
@ -114,6 +115,7 @@ static int thread_to_lwp PARAMS ((int thread_id, int default_lwp));
|
|||
static void sol_thread_resume PARAMS ((int pid, int step,
|
||||
enum target_signal signo));
|
||||
static int lwp_to_thread PARAMS ((int lwp));
|
||||
static int sol_thread_alive PARAMS ((int pid));
|
||||
|
||||
#define THREAD_FLAG 0x80000000
|
||||
#define is_thread(ARG) (((ARG) & THREAD_FLAG) != 0)
|
||||
|
@ -306,24 +308,22 @@ thread_to_lwp (thread_id, default_lwp)
|
|||
td_thrinfo_t ti;
|
||||
td_thrhandle_t th;
|
||||
td_err_e val;
|
||||
int pid;
|
||||
int lwp;
|
||||
|
||||
if (is_lwp (thread_id))
|
||||
return thread_id; /* It's already an LWP id */
|
||||
|
||||
/* It's a thread. Convert to lwp */
|
||||
|
||||
pid = PIDGET (thread_id);
|
||||
thread_id = GET_THREAD(thread_id);
|
||||
|
||||
val = p_td_ta_map_id2thr (main_ta, thread_id, &th);
|
||||
if (val != TD_OK)
|
||||
val = p_td_ta_map_id2thr (main_ta, GET_THREAD (thread_id), &th);
|
||||
if (val == TD_NOTHR)
|
||||
return -1; /* thread must have terminated */
|
||||
else if (val != TD_OK)
|
||||
error ("thread_to_lwp: td_ta_map_id2thr %s", td_err_string (val));
|
||||
|
||||
val = p_td_thr_get_info (&th, &ti);
|
||||
|
||||
if (val != TD_OK)
|
||||
if (val == TD_NOTHR)
|
||||
return -1; /* thread must have terminated */
|
||||
else if (val != TD_OK)
|
||||
error ("thread_to_lwp: td_thr_get_info: %s", td_err_string (val));
|
||||
|
||||
if (ti.ti_state != TD_THR_ACTIVE)
|
||||
|
@ -334,9 +334,7 @@ thread_to_lwp (thread_id, default_lwp)
|
|||
td_state_string (ti.ti_state));
|
||||
}
|
||||
|
||||
lwp = BUILD_LWP (ti.ti_lid, pid);
|
||||
|
||||
return lwp;
|
||||
return BUILD_LWP (ti.ti_lid, PIDGET (thread_id));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -367,29 +365,34 @@ lwp_to_thread (lwp)
|
|||
td_thrinfo_t ti;
|
||||
td_thrhandle_t th;
|
||||
td_err_e val;
|
||||
int pid;
|
||||
int thread_id;
|
||||
|
||||
if (is_thread (lwp))
|
||||
return lwp; /* It's already a thread id */
|
||||
|
||||
/* It's an lwp. Convert it to a thread id. */
|
||||
|
||||
pid = PIDGET (lwp);
|
||||
lwp = GET_LWP (lwp);
|
||||
if (!sol_thread_alive (lwp))
|
||||
return -1; /* defunct lwp */
|
||||
|
||||
val = p_td_ta_map_lwp2thr (main_ta, lwp, &th);
|
||||
if (val != TD_OK)
|
||||
val = p_td_ta_map_lwp2thr (main_ta, GET_LWP (lwp), &th);
|
||||
if (val == TD_NOTHR)
|
||||
return -1; /* thread must have terminated */
|
||||
else if (val != TD_OK)
|
||||
error ("lwp_to_thread: td_thr_get_info: %s.", td_err_string (val));
|
||||
|
||||
val = p_td_thr_validate (&th);
|
||||
if (val == TD_NOTHR)
|
||||
return lwp; /* libthread doesn't know about it, just return lwp */
|
||||
else if (val != TD_OK)
|
||||
error ("lwp_to_thread: td_thr_validate: %s.", td_err_string (val));
|
||||
|
||||
val = p_td_thr_get_info (&th, &ti);
|
||||
|
||||
if (val != TD_OK)
|
||||
if (val == TD_NOTHR)
|
||||
return -1; /* thread must have terminated */
|
||||
else if (val != TD_OK)
|
||||
error ("lwp_to_thread: td_thr_get_info: %s.", td_err_string (val));
|
||||
|
||||
thread_id = BUILD_THREAD (ti.ti_tid, pid);
|
||||
|
||||
return thread_id;
|
||||
return BUILD_THREAD (ti.ti_tid, PIDGET (lwp));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -456,7 +459,19 @@ sol_thread_attach (args, from_tty)
|
|||
int from_tty;
|
||||
{
|
||||
procfs_ops.to_attach (args, from_tty);
|
||||
|
||||
/* Must get symbols from solibs before libthread_db can run! */
|
||||
SOLIB_ADD ((char *)0, from_tty, (struct target_ops *)0);
|
||||
if (sol_thread_active)
|
||||
{
|
||||
printf_filtered ("sol-thread active.\n");
|
||||
main_ph.pid = inferior_pid; /* Save for xfer_memory */
|
||||
push_target (&sol_thread_ops);
|
||||
inferior_pid = lwp_to_thread (inferior_pid);
|
||||
if (inferior_pid == -1)
|
||||
inferior_pid = main_ph.pid;
|
||||
else
|
||||
add_thread (inferior_pid);
|
||||
}
|
||||
/* XXX - might want to iterate over all the threads and register them. */
|
||||
}
|
||||
|
||||
|
@ -473,6 +488,7 @@ sol_thread_detach (args, from_tty)
|
|||
char *args;
|
||||
int from_tty;
|
||||
{
|
||||
unpush_target (&sol_thread_ops);
|
||||
procfs_ops.to_detach (args, from_tty);
|
||||
}
|
||||
|
||||
|
@ -492,12 +508,19 @@ sol_thread_resume (pid, step, signo)
|
|||
old_chain = save_inferior_pid ();
|
||||
|
||||
inferior_pid = thread_to_lwp (inferior_pid, main_ph.pid);
|
||||
if (inferior_pid == -1)
|
||||
inferior_pid = procfs_first_available ();
|
||||
|
||||
if (pid != -1)
|
||||
{
|
||||
int save_pid = pid;
|
||||
|
||||
pid = thread_to_lwp (pid, -2);
|
||||
if (pid == -2) /* Inactive thread */
|
||||
error ("This version of Solaris can't start inactive threads.");
|
||||
if (info_verbose && pid == -1)
|
||||
warning ("Specified thread %d seems to have terminated",
|
||||
GET_THREAD (save_pid));
|
||||
}
|
||||
|
||||
procfs_ops.to_resume (pid, step, signo);
|
||||
|
@ -521,28 +544,44 @@ sol_thread_wait (pid, ourstatus)
|
|||
old_chain = save_inferior_pid ();
|
||||
|
||||
inferior_pid = thread_to_lwp (inferior_pid, main_ph.pid);
|
||||
if (inferior_pid == -1)
|
||||
inferior_pid = procfs_first_available ();
|
||||
|
||||
if (pid != -1)
|
||||
pid = thread_to_lwp (pid, -1);
|
||||
{
|
||||
int save_pid = pid;
|
||||
|
||||
pid = thread_to_lwp (pid, -2);
|
||||
if (pid == -2) /* Inactive thread */
|
||||
error ("This version of Solaris can't start inactive threads.");
|
||||
if (info_verbose && pid == -1)
|
||||
warning ("Specified thread %d seems to have terminated",
|
||||
GET_THREAD (save_pid));
|
||||
}
|
||||
|
||||
rtnval = procfs_ops.to_wait (pid, ourstatus);
|
||||
|
||||
if (rtnval != save_pid
|
||||
if (ourstatus->kind != TARGET_WAITKIND_EXITED)
|
||||
{
|
||||
/* Map the LWP of interest back to the appropriate thread ID */
|
||||
rtnval = lwp_to_thread (rtnval);
|
||||
if (rtnval == -1)
|
||||
rtnval = save_pid;
|
||||
|
||||
/* See if we have a new thread */
|
||||
if (is_thread (rtnval)
|
||||
&& rtnval != save_pid
|
||||
&& !in_thread_list (rtnval))
|
||||
{
|
||||
fprintf_unfiltered (gdb_stderr, "[New %s]\n",
|
||||
target_pid_to_str (rtnval));
|
||||
printf_filtered ("[New %s]\n", target_pid_to_str (rtnval));
|
||||
add_thread (rtnval);
|
||||
}
|
||||
}
|
||||
|
||||
/* During process initialization, we may get here without the thread package
|
||||
being initialized, since that can only happen after we've found the shared
|
||||
libs. */
|
||||
|
||||
/* Map the LWP of interest back to the appropriate thread ID */
|
||||
|
||||
rtnval = lwp_to_thread (rtnval);
|
||||
|
||||
do_cleanups (old_chain);
|
||||
|
||||
return rtnval;
|
||||
|
@ -751,8 +790,6 @@ sol_thread_notice_signals (pid)
|
|||
procfs_ops.to_notice_signals (pid);
|
||||
}
|
||||
|
||||
void target_new_objfile PARAMS ((struct objfile *objfile));
|
||||
|
||||
/* Fork an inferior process, and start debugging it with /proc. */
|
||||
|
||||
static void
|
||||
|
@ -763,13 +800,15 @@ sol_thread_create_inferior (exec_file, allargs, env)
|
|||
{
|
||||
procfs_ops.to_create_inferior (exec_file, allargs, env);
|
||||
|
||||
if (sol_thread_active)
|
||||
if (sol_thread_active && inferior_pid != 0)
|
||||
{
|
||||
main_ph.pid = inferior_pid; /* Save for xfer_memory */
|
||||
|
||||
push_target (&sol_thread_ops);
|
||||
|
||||
inferior_pid = lwp_to_thread (inferior_pid);
|
||||
if (inferior_pid == -1)
|
||||
inferior_pid = main_ph.pid;
|
||||
|
||||
add_thread (inferior_pid);
|
||||
}
|
||||
|
@ -794,6 +833,10 @@ sol_thread_new_objfile (objfile)
|
|||
return;
|
||||
}
|
||||
|
||||
/* don't do anything if init failed to resolve the libthread_db library */
|
||||
if (!procfs_suppress_run)
|
||||
return;
|
||||
|
||||
/* Now, initialize the thread debugging library. This needs to be done after
|
||||
the shared libraries are located because it needs information from the
|
||||
user's thread library. */
|
||||
|
@ -816,6 +859,7 @@ sol_thread_new_objfile (objfile)
|
|||
static void
|
||||
sol_thread_mourn_inferior ()
|
||||
{
|
||||
unpush_target (&sol_thread_ops);
|
||||
procfs_ops.to_mourn_inferior ();
|
||||
}
|
||||
|
||||
|
@ -827,11 +871,40 @@ sol_thread_can_run ()
|
|||
return procfs_suppress_run;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
LOCAL FUNCTION
|
||||
|
||||
sol_thread_alive - test thread for "aliveness"
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
static bool sol_thread_alive (int pid);
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
returns true if thread still active in inferior.
|
||||
|
||||
*/
|
||||
|
||||
static int
|
||||
sol_thread_alive (pid)
|
||||
int pid;
|
||||
{
|
||||
return 1;
|
||||
if (is_thread (pid)) /* non-kernel thread */
|
||||
{
|
||||
td_err_e val;
|
||||
td_thrhandle_t th;
|
||||
|
||||
pid = GET_THREAD (pid);
|
||||
if ((val = p_td_ta_map_id2thr (main_ta, pid, &th)) != TD_OK)
|
||||
return 0; /* thread not found */
|
||||
if ((val = p_td_thr_validate (&th)) != TD_OK)
|
||||
return 0; /* thread not valid */
|
||||
return 1; /* known thread: return true */
|
||||
}
|
||||
else /* kernel thread (LWP): let procfs test it */
|
||||
return procfs_ops.to_thread_alive (pid);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -910,9 +983,9 @@ rw_common (int dowrite, const struct ps_prochandle *ph, paddr_t addr,
|
|||
if (cc < 0)
|
||||
{
|
||||
if (dowrite == 0)
|
||||
print_sys_errmsg ("ps_pdread (): read", errno);
|
||||
print_sys_errmsg ("rw_common (): read", errno);
|
||||
else
|
||||
print_sys_errmsg ("ps_pdread (): write", errno);
|
||||
print_sys_errmsg ("rw_common (): write", errno);
|
||||
|
||||
do_cleanups (old_chain);
|
||||
|
||||
|
@ -1123,19 +1196,27 @@ solaris_pid_to_str (pid)
|
|||
{
|
||||
static char buf[100];
|
||||
|
||||
/* in case init failed to resolve the libthread_db library */
|
||||
if (!procfs_suppress_run)
|
||||
return procfs_pid_to_str (pid);
|
||||
|
||||
if (is_thread (pid))
|
||||
{
|
||||
int lwp;
|
||||
|
||||
lwp = thread_to_lwp (pid, -2);
|
||||
|
||||
if (lwp != -2)
|
||||
if (lwp == -1)
|
||||
sprintf (buf, "Thread %d (defunct)", GET_THREAD (pid));
|
||||
else if (lwp != -2)
|
||||
sprintf (buf, "Thread %d (LWP %d)", GET_THREAD (pid), GET_LWP (lwp));
|
||||
else
|
||||
sprintf (buf, "Thread %d ", GET_THREAD (pid));
|
||||
}
|
||||
else
|
||||
else if (GET_LWP (pid) != 0)
|
||||
sprintf (buf, "LWP %d ", GET_LWP (pid));
|
||||
else
|
||||
sprintf (buf, "process %d ", PIDGET (pid));
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
|
28
gdb/thread.c
28
gdb/thread.c
|
@ -125,6 +125,31 @@ add_thread (pid)
|
|||
thread_list = tp;
|
||||
}
|
||||
|
||||
void
|
||||
delete_thread (pid)
|
||||
int pid;
|
||||
{
|
||||
struct thread_info *tp, *tpprev;
|
||||
|
||||
tpprev = NULL;
|
||||
|
||||
for (tp = thread_list; tp; tpprev = tp, tp = tp->next)
|
||||
if (tp->pid == pid)
|
||||
break;
|
||||
|
||||
if (!tp)
|
||||
return;
|
||||
|
||||
if (tpprev)
|
||||
tpprev->next = tp->next;
|
||||
else
|
||||
thread_list = tp->next;
|
||||
|
||||
free (tp);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static struct thread_info *
|
||||
find_thread_id (num)
|
||||
int num;
|
||||
|
@ -332,7 +357,10 @@ info_threads_command (arg, from_tty)
|
|||
printf_filtered ("%d %s ", tp->num, target_pid_to_str (tp->pid));
|
||||
|
||||
switch_to_thread (tp->pid);
|
||||
if (selected_frame)
|
||||
print_stack_frame (selected_frame, -1, 0);
|
||||
else
|
||||
printf_filtered ("[No stack.]\n");
|
||||
}
|
||||
|
||||
switch_to_thread (current_pid);
|
||||
|
|
Loading…
Reference in a new issue