#include "gdbcore.h"
#include "gdbthread.h"
+#if !defined(SYS_lwp_create) && defined(SYS_lwpcreate)
+# define SYS_lwp_create SYS_lwpcreate
+#endif
+
+#if !defined(SYS_lwp_exit) && defined(SYS_lwpexit)
+# define SYS_lwp_exit SYS_lwpexit
+#endif
+
+#if !defined(SYS_lwp_wait) && defined(SYS_lwpwait)
+# define SYS_lwp_wait SYS_lwpwait
+#endif
+
+#if !defined(SYS_lwp_self) && defined(SYS_lwpself)
+# define SYS_lwp_self SYS_lwpself
+#endif
+
+#if !defined(SYS_lwp_info) && defined(SYS_lwpinfo)
+# define SYS_lwp_info SYS_lwpinfo
+#endif
+
+#if !defined(SYS_lwp_private) && defined(SYS_lwpprivate)
+# define SYS_lwp_private SYS_lwpprivate
+#endif
+
+#if !defined(SYS_lwp_kill) && defined(SYS_lwpkill)
+# define SYS_lwp_kill SYS_lwpkill
+#endif
+
+#if !defined(SYS_lwp_suspend) && defined(SYS_lwpsuspend)
+# define SYS_lwp_suspend SYS_lwpsuspend
+#endif
+
+#if !defined(SYS_lwp_continue) && defined(SYS_lwpcontinue)
+# define SYS_lwp_continue SYS_lwpcontinue
+#endif
+
/* the name of the proc status struct depends on the implementation */
#ifdef HAVE_PSTATUS_T
typedef pstatus_t gdb_prstatus_t;
# endif
#endif /* HAVE_MULTIPLE_PROC_FDS */
+
+/* These #ifdefs are for sol2.x in particular. sol2.x has
+ both a "gregset_t" and a "prgregset_t", which have
+ similar uses but different layouts. sol2.x gdb tries to
+ use prgregset_t (and prfpregset_t) everywhere. */
+
+#ifdef GDB_GREGSET_TYPE
+ typedef GDB_GREGSET_TYPE gdb_gregset_t;
+#else
+ typedef gregset_t gdb_gregset_t;
+#endif
+
+#ifdef GDB_FPREGSET_TYPE
+ typedef GDB_FPREGSET_TYPE gdb_fpregset_t;
+#else
+ typedef fpregset_t gdb_fpregset_t;
+#endif
+
+
#define MAX_PROC_NAME_SIZE sizeof("/proc/1234567890/status")
extern struct target_ops procfs_ops; /* Forward declaration */
/* set general registers */
struct greg_ctl {
int cmd;
- gregset_t gregset;
+ gdb_gregset_t gregset;
};
/* set fp registers */
struct fpreg_ctl {
int cmd;
- fpregset_t fpregset;
+ gdb_fpregset_t fpregset;
};
/* set signals to be traced */
currently installed */
/* Pointer to list of syscall trap handlers */
struct procfs_syscall_handler *syscall_handlers;
+ int saved_rtnval; /* return value and status for wait(), */
+ int saved_statval; /* as supplied by a syscall handler. */
int new_child; /* Non-zero if it's a new thread */
};
static void proc_set_exec_trap PARAMS ((void));
-static int procfs_init_inferior PARAMS ((int));
+static void procfs_init_inferior PARAMS ((int));
static struct procinfo *create_procinfo PARAMS ((int));
/* External function prototypes that can't be easily included in any
header file because the args are typedefs in system include files. */
-extern void supply_gregset PARAMS ((gregset_t *));
+extern void supply_gregset PARAMS ((gdb_gregset_t *));
-extern void fill_gregset PARAMS ((gregset_t *, int));
+extern void fill_gregset PARAMS ((gdb_gregset_t *, int));
#ifdef FP0_REGNUM
-extern void supply_fpregset PARAMS ((fpregset_t *));
+extern void supply_fpregset PARAMS ((gdb_fpregset_t *));
-extern void fill_fpregset PARAMS ((fpregset_t *, int));
+extern void fill_fpregset PARAMS ((gdb_fpregset_t *, int));
#endif
/*
if ((poll_list[i].revents & POLLHUP) != 0 ||
!procfs_read_status(pi))
{ /* The LWP has apparently terminated. */
+ if (num_poll_list <= 1)
+ {
+ pi->prstatus.pr_flags = 0;
+ pi->had_event = 1;
+ break;
+ }
if (info_verbose)
printf_filtered ("LWP %d exited.\n",
(pi->pid >> 16) & 0xffff);
#if defined (SYS_lwp_sema_trywait)
syscall_table[SYS_lwp_sema_trywait] = "lwp_sema_trywait";
#endif
+#if defined(SYS_fstatvfs64)
+ syscall_table[SYS_fstatvfs64] = "fstatvfs64";
+#endif
+#if defined(SYS_statvfs64)
+ syscall_table[SYS_statvfs64] = "statvfs64";
+#endif
+#if defined(SYS_ftruncate64)
+ syscall_table[SYS_ftruncate64] = "ftruncate64";
+#endif
+#if defined(SYS_truncate64)
+ syscall_table[SYS_truncate64] = "truncate64";
+#endif
+#if defined(SYS_getrlimit64)
+ syscall_table[SYS_getrlimit64] = "getrlimit64";
+#endif
+#if defined(SYS_setrlimit64)
+ syscall_table[SYS_setrlimit64] = "setrlimit64";
+#endif
+#if defined(SYS_lseek64)
+ syscall_table[SYS_lseek64] = "lseek64";
+#endif
+#if defined(SYS_mmap64)
+ syscall_table[SYS_mmap64] = "mmap64";
+#endif
+#if defined(SYS_pread64)
+ syscall_table[SYS_pread64] = "pread64";
+#endif
+#if defined(SYS_creat64)
+ syscall_table[SYS_creat64] = "creat64";
+#endif
+#if defined(SYS_dshmsys)
+ syscall_table[SYS_dshmsys] = "dshmsys";
+#endif
+#if defined(SYS_invlpg)
+ syscall_table[SYS_invlpg] = "invlpg";
+#endif
+#if defined(SYS_cg_ids)
+ syscall_table[SYS_cg_ids] = "cg_ids";
+#endif
+#if defined(SYS_cg_processors)
+ syscall_table[SYS_cg_processors] = "cg_processors";
+#endif
+#if defined(SYS_cg_info)
+ syscall_table[SYS_cg_info] = "cg_info";
+#endif
+#if defined(SYS_cg_bind)
+ syscall_table[SYS_cg_bind] = "cg_bind";
+#endif
+#if defined(SYS_cg_current)
+ syscall_table[SYS_cg_current] = "cg_current";
+#endif
+#if defined(SYS_cg_memloc)
+ syscall_table[SYS_cg_memloc] = "cg_memloc";
+#endif
}
/*
procfs_read_status (pi);
memcpy ((char *) &greg.gregset,
(char *) &pi->prstatus.pr_lwp.pr_context.uc_mcontext.gregs,
- sizeof (gregset_t));
+ sizeof (gdb_gregset_t));
}
fill_gregset (&greg.gregset, regno);
greg.cmd = PCSREG;
procfs_read_status (pi);
memcpy ((char *) &fpreg.fpregset,
(char *) &pi->prstatus.pr_lwp.pr_context.uc_mcontext.fpregs,
- sizeof (fpregset_t));
+ sizeof (gdb_fpregset_t));
}
fill_fpregset (&fpreg.fpregset, regno);
fpreg.cmd = PCSFPREG;
{
struct procinfo *pi = (struct procinfo *)
xmalloc (sizeof (struct procinfo));
+ struct sig_ctl sctl;
+ struct flt_ctl fctl;
memset ((char *) pi, 0, sizeof (*pi));
if (!open_proc_file (pid, pi, O_RDWR, 1))
int *statvalp;
{
struct procinfo *temp_pi, *next_pi;
+ struct proc_ctl pctl;
+#ifdef UNIXWARE
+ pctl.cmd = PCRUN;
+ pctl.data = PRCFAULT;
+#else
pi->prrun.pr_flags = PRCFAULT;
+#endif
+#ifdef PROCFS_USE_READ_WRITE
+ if (write (pi->ctl_fd, (char *)&pctl, sizeof (struct proc_ctl)) < 0)
+#else
if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
+#endif
perror_with_name (pi->pathname);
if (attach_flag)
SYNOPSIS
- int procfs_init_inferior (int pid)
+ void procfs_init_inferior (int pid)
DESCRIPTION
*/
-static int
+static void
procfs_init_inferior (pid)
int pid;
{
/* One trap to exec the shell, one to exec the program being debugged. */
startup_inferior (2);
#endif
-
- return pid;
}
/*
modify_run_on_last_close_flag (fd, 1);
+#ifndef UNIXWARE /* since this is a solaris-ism, we don't want it */
+ /* NOTE: revisit when doing thread support for UW */
#ifdef PR_ASYNC
{
long pr_flags;
#endif
}
#endif /* PR_ASYNC */
+#endif /* !UNIXWARE */
}
/*
#endif /* 0 */
+#ifndef UNIXWARE
/*
LOCAL FUNCTION
}
return (fd);
}
-
+#endif /* !UNIXWARE */
/* Attach to process PID, then initialize for debugging it
and wait for the trace-trap that results from attaching. */
}
add_thread (pi->pid);
procfs_set_inferior_syscall_traps (pi);
- }
#endif /* PROCFS_USE_READ_WRITE */
+ }
attach_flag = 1;
return (pi->pid);
}
struct procinfo *pi;
struct proc_ctl pctl;
-#ifndef UNIXWARE
- if (pid != -1) /* Non-specific process? */
- pi = NULL;
- else
- for (pi = procinfo_list; pi; pi = pi->next)
- if (pi->had_event)
- break;
+scan_again:
- if (!pi)
+ /* handle all syscall events first, otherwise we might not
+ notice a thread was created until too late. */
+
+ for (pi = procinfo_list; pi; pi = pi->next)
{
- wait_again:
+ if (!pi->had_event)
+ continue;
- if (pi)
- pi->had_event = 0;
+#ifdef UNIXWARE
+ if (! (pi->prstatus.pr_lwp.pr_flags & (PR_STOPPED | PR_ISTOP)) )
+ continue;
- pi = wait_fd ();
- }
+ why = pi->prstatus.pr_lwp.pr_why;
+ what = pi->prstatus.pr_lwp.pr_what;
+#else
+ if (! (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)) )
+ continue;
- if (pid != -1)
- for (pi = procinfo_list; pi; pi = pi->next)
- if (pi->pid == pid && pi->had_event)
- break;
+ why = pi->prstatus.pr_why;
+ what = pi->prstatus.pr_what;
#endif
+ if (why == PR_SYSENTRY || why == PR_SYSEXIT)
+ {
+ int i;
+ int found_handler = 0;
+
+ for (i = 0; i < pi->num_syscall_handlers; i++)
+ if (pi->syscall_handlers[i].syscall_num == what)
+ {
+ found_handler = 1;
+ pi->saved_rtnval = pi->pid;
+ pi->saved_statval = 0;
+ if (!pi->syscall_handlers[i].func
+ (pi, what, why, &pi->saved_rtnval, &pi->saved_statval))
+ pi->had_event = 0;
+ break;
+ }
+
+ if (!found_handler)
+ {
+ if (why == PR_SYSENTRY)
+ error ("PR_SYSENTRY, unhandled system call %d", what);
+ else
+ error ("PR_SYSEXIT, unhandled system call %d", what);
+ }
+ }
+ }
- if (!pi && !checkerr)
- goto wait_again;
+ /* find a relevant process with an event */
+
+ for (pi = procinfo_list; pi; pi = pi->next)
+ if (pi->had_event && (pid == -1 || pi->pid == pid))
+ break;
+
+ if (!pi)
+ {
+ wait_fd ();
+ goto scan_again;
+ }
#ifdef UNIXWARE
if (!checkerr && !(pi->prstatus.pr_lwp.pr_flags & (PR_STOPPED | PR_ISTOP)))
{
/* XXX Fixme -- what to do if attached? Can't call wait... */
rtnval = wait (&statval);
- if ((rtnval) != (inferior_pid))
+ if ((rtnval) != (PIDGET (inferior_pid)))
{
print_sys_errmsg (pi->pathname, errno);
error ("procfs_wait: wait failed, returned %d", rtnval);
/* NOTREACHED */
}
}
+#ifdef UNIXWARE
+ else if (pi->prstatus.pr_lwp.pr_flags & (PR_STOPPED | PR_ISTOP))
+#else
else if (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
+#endif
{
#ifdef UNIXWARE
rtnval = pi->prstatus.pr_pid;
break;
case PR_SYSENTRY:
case PR_SYSEXIT:
- {
- int i;
- int found_handler = 0;
-
- for (i = 0; i < pi->num_syscall_handlers; i++)
- if (pi->syscall_handlers[i].syscall_num == what)
- {
- found_handler = 1;
- if (!pi->syscall_handlers[i].func (pi, what, why,
- &rtnval, &statval))
- goto wait_again;
-
- break;
- }
-
- if (!found_handler)
- if (why == PR_SYSENTRY)
- error ("PR_SYSENTRY, unhandled system call %d", what);
- else
- error ("PR_SYSEXIT, unhandled system call %d", what);
- }
+ rtnval = pi->saved_rtnval;
+ statval = pi->saved_statval;
break;
case PR_REQUESTED:
statval = (SIGSTOP << 8) | 0177;
if (!procinfo->had_event)
{
#ifdef PROCFS_USE_READ_WRITE
- cmd = PCSTOP;
+ long cmd = PCSTOP;
if (write (pi->ctl_fd, (char *) &cmd, sizeof (long)) < 0)
{
print_sys_errmsg (procinfo->pathname, errno);
}
else
{
- error ("PIOCWSTOP, stopped for unknown/unhandled reason, flags %#x",
+ error ("PIOCWSTOP, stopped for unknown/unhandled reason, flags %#x",
+#ifdef UNIXWARE
+ pi->prstatus.pr_lwp.pr_flags);
+#else
pi->prstatus.pr_flags);
+#endif
}
store_waitstatus (ourstatus, statval);
print_sys_errmsg (procinfo->pathname, errno);
error ("PCRUN failed");
}
- procfs_read_status (procinfo);
#else
procinfo->prrun.pr_flags &= PRSTEP;
procinfo->prrun.pr_flags |= PRCFAULT | PRCSIG;
print_sys_errmsg (procinfo->pathname, errno);
warning ("PIOCRUN failed");
}
+#endif
}
procfs_read_status (procinfo);
-#endif
}
}
if (summary || all)
{
info_proc_stop (pip, summary);
+#ifdef UNIXWARE
+ supply_gregset (&pip->prstatus.pr_lwp.pr_context.uc_mcontext.gregs);
+#else
supply_gregset (&pip->prstatus.pr_reg);
+#endif
printf_filtered ("PC: ");
print_address (read_pc (), gdb_stdout);
printf_filtered ("\n");
{
sysset_t sysset;
int goterr, i;
-
+
+#ifndef UNIXWARE
goterr = ioctl (pi->ctl_fd, PIOCGENTRY, &sysset) < 0;
if (goterr && !errok)
error ("PIOCSEXIT failed");
}
}
+#endif
if (!pi->syscall_handlers)
{
{
sysset_t sysset;
+#ifndef UNIXWARE
if (flags & PROCFS_SYSCALL_ENTRY)
{
if (ioctl (pi->ctl_fd, PIOCGENTRY, &sysset) < 0)
error ("PIOCSEXIT failed");
}
}
+#endif
if (!pi->syscall_handlers)
{
{
int lwp_id;
struct procinfo *childpi;
+ struct proc_ctl pctl;
/* We've just detected the completion of an lwp_create system call. Now we
need to setup a procinfo struct for this thread, and notify the thread
/* If lwp_create failed, then nothing interesting happened. Continue the
process and go back to sleep. */
+#ifdef UNIXWARE
+ /* Joel ... can you check this logic out please? JKJ */
+ if (pi->prstatus.pr_lwp.pr_context.uc_mcontext.gregs[R_EFL] & 1)
+ { /* _lwp_create failed */
+ pctl.cmd = PCRUN;
+ pctl.data = PRCFAULT;
+
+ if (write (pi->ctl_fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
+ perror_with_name (pi->pathname);
+
+ return 0;
+ }
+#else /* UNIXWARE */
if (PROCFS_GET_CARRY (pi->prstatus.pr_reg))
{ /* _lwp_create failed */
pi->prrun.pr_flags &= PRSTEP;
return 0;
}
+#endif
/* At this point, the new thread is stopped at it's first instruction, and
the parent is stopped at the exit from lwp_create. */
if (pi->new_child) /* Child? */
{ /* Yes, just continue it */
+#ifdef UNIXWARE
+ pctl.cmd = PCRUN;
+ pctl.data = PRCFAULT;
+
+ if (write(pi->ctl_fd, (char *)&pctl, sizeof (struct proc_ctl)) < 0)
+#else /* !UNIXWARE */
pi->prrun.pr_flags &= PRSTEP;
pi->prrun.pr_flags |= PRCFAULT;
if ((pi->prstatus.pr_flags & PR_ISTOP)
&& ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
+#endif /* !UNIXWARE */
perror_with_name (pi->pathname);
pi->new_child = 0; /* No longer new */
in the child and continue the parent. */
/* Third arg is pointer to new thread id. */
+#ifdef UNIXWARE
+ lwp_id = read_memory_integer (pi->prstatus.pr_lwp.pr_sysarg[2], sizeof (int));
+#else
lwp_id = read_memory_integer (pi->prstatus.pr_sysarg[2], sizeof (int));
+#endif
lwp_id = (lwp_id << 16) | PIDGET (pi->pid);
printf_filtered ("[New %s]\n", target_pid_to_str (lwp_id));
/* Continue the parent */
+#ifdef UNIXWARE
+ pctl.cmd = PCRUN;
+ pctl.data = PRCFAULT;
+ if (write(pi->ctl_fd, (char *)&pctl, sizeof (struct proc_ctl)) < 0)
+#else
pi->prrun.pr_flags &= PRSTEP;
pi->prrun.pr_flags |= PRCFAULT;
if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
+#endif
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. */
+#ifdef UNIXWARE
+ if (childpi->prstatus.pr_lwp.pr_why == PR_SUSPENDED)
+#else
if (childpi->prstatus.pr_why == PR_SUSPENDED)
+#endif
childpi->new_child = 1; /* Flag this as an unseen child process */
else
{
/* Continue the child */
+#ifdef UNIXWARE
+ pctl.cmd = PCRUN;
+ pctl.data = PRCFAULT;
+
+ if (write(pi->ctl_fd, (char *)&pctl, sizeof (struct proc_ctl)) < 0)
+#else
childpi->prrun.pr_flags &= PRSTEP;
childpi->prrun.pr_flags |= PRCFAULT;
if (ioctl (childpi->ctl_fd, PIOCRUN, &childpi->prrun) != 0)
+#endif
perror_with_name (childpi->pathname);
}
return 0;
}
fork_inferior (exec_file, allargs, env,
- proc_set_exec_trap, procfs_init_inferior, shell_file);
+ proc_set_exec_trap, procfs_init_inferior, NULL, shell_file);
/* We are at the first instruction we care about. */
/* Pedal to the metal... */
return !procfs_suppress_run;
}
#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
+#ifndef UNIXWARE
\f
/* Insert a watchpoint */
int
}
return 0;
}
+#endif /* !UNIXWARE */
#endif /* TARGET_HAS_HARDWARE_WATCHPOINTS */
/* Why is this necessary? Shouldn't dead threads just be removed from the
}
#endif /* TIDGET */
\f
-struct target_ops procfs_ops = {
- "procfs", /* to_shortname */
- "Unix /proc child process", /* to_longname */
- "Unix /proc child process (started by the \"run\" command).", /* to_doc */
- procfs_open, /* to_open */
- 0, /* to_close */
- procfs_attach, /* to_attach */
- procfs_detach, /* to_detach */
- procfs_resume, /* to_resume */
- procfs_wait, /* to_wait */
- procfs_fetch_registers, /* to_fetch_registers */
- procfs_store_registers, /* to_store_registers */
- procfs_prepare_to_store, /* to_prepare_to_store */
- procfs_xfer_memory, /* to_xfer_memory */
- procfs_files_info, /* to_files_info */
- memory_insert_breakpoint, /* to_insert_breakpoint */
- memory_remove_breakpoint, /* to_remove_breakpoint */
- terminal_init_inferior, /* to_terminal_init */
- terminal_inferior, /* to_terminal_inferior */
- terminal_ours_for_output, /* to_terminal_ours_for_output */
- terminal_ours, /* to_terminal_ours */
- child_terminal_info, /* to_terminal_info */
- procfs_kill_inferior, /* to_kill */
- 0, /* to_load */
- 0, /* to_lookup_symbol */
- procfs_create_inferior, /* to_create_inferior */
- procfs_mourn_inferior, /* to_mourn_inferior */
- procfs_can_run, /* to_can_run */
- procfs_notice_signals, /* to_notice_signals */
- procfs_thread_alive, /* to_thread_alive */
- procfs_stop, /* to_stop */
- process_stratum, /* to_stratum */
- 0, /* to_next */
- 1, /* to_has_all_memory */
- 1, /* to_has_memory */
- 1, /* to_has_stack */
- 1, /* to_has_registers */
- 1, /* to_has_execution */
- 0, /* sections */
- 0, /* sections_end */
- OPS_MAGIC /* to_magic */
-};
+struct target_ops procfs_ops;
void
_initialize_procfs ()
return;
close (fd);
#endif
+ procfs_ops.to_shortname = "procfs";
+ procfs_ops.to_longname = "Unix /proc child process";
+ procfs_ops.to_doc = "Unix /proc child process (started by the \"run\" command).";
+ procfs_ops.to_open = procfs_open;
+ procfs_ops.to_close = 0;
+ procfs_ops.to_attach = procfs_attach;
+ procfs_ops.to_require_attach = procfs_attach;
+ procfs_ops.to_detach = procfs_detach;
+ procfs_ops.to_require_detach = procfs_detach;
+ procfs_ops.to_resume = procfs_resume;
+ procfs_ops.to_wait = procfs_wait;
+ procfs_ops.to_fetch_registers = procfs_fetch_registers;
+ procfs_ops.to_store_registers = procfs_store_registers;
+ procfs_ops.to_prepare_to_store = procfs_prepare_to_store;
+ procfs_ops.to_xfer_memory = procfs_xfer_memory;
+ procfs_ops.to_files_info = procfs_files_info;
+ procfs_ops.to_insert_breakpoint = memory_insert_breakpoint;
+ procfs_ops.to_remove_breakpoint = memory_remove_breakpoint;
+ procfs_ops.to_terminal_init = terminal_init_inferior;
+ procfs_ops.to_terminal_inferior = terminal_inferior;
+ procfs_ops.to_terminal_ours_for_output = terminal_ours_for_output;
+ procfs_ops.to_terminal_ours = terminal_ours;
+ procfs_ops.to_terminal_info = child_terminal_info;
+ procfs_ops.to_kill = procfs_kill_inferior;
+ procfs_ops.to_load = 0;
+ procfs_ops.to_lookup_symbol = 0;
+ procfs_ops.to_create_inferior = procfs_create_inferior;
+ procfs_ops.to_mourn_inferior = procfs_mourn_inferior;
+ procfs_ops.to_can_run = procfs_can_run;
+ procfs_ops.to_notice_signals = procfs_notice_signals;
+ procfs_ops.to_thread_alive = procfs_thread_alive;
+ procfs_ops.to_stop = procfs_stop;
+ procfs_ops.to_stratum = process_stratum;
+ procfs_ops.to_has_all_memory = 1;
+ procfs_ops.to_has_memory = 1;
+ procfs_ops.to_has_stack = 1;
+ procfs_ops.to_has_registers = 1;
+ procfs_ops.to_has_execution = 1;
+ procfs_ops.to_has_thread_control = tc_none;
+ procfs_ops.to_sections = 0;
+ procfs_ops.to_sections_end = 0;
+ procfs_ops.to_magic = OPS_MAGIC;
add_target (&procfs_ops);