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:
Michael Snyder 1997-05-21 23:33:33 +00:00
parent b4a4a6dc0f
commit 3780c33708
4 changed files with 745 additions and 410 deletions

View file

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

View file

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

View file

@ -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;
}

View file

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