/* =================== END, TARGET_OPS "MODULE" =================== */
-/* World Unification:
-
- Put any typedefs, defines etc. here that are required for the
- unification of code that handles different versions of /proc. */
-
-enum { READ_WATCHFLAG = WA_READ,
- WRITE_WATCHFLAG = WA_WRITE,
- EXEC_WATCHFLAG = WA_EXEC,
- AFTER_WATCHFLAG = WA_TRAPAFTER
-};
-
-
/* =================== STRUCT PROCINFO "MODULE" =================== */
/* FIXME: this comment will soon be out of date W.R.T. threads. */
inferior's procinfo information. */
/* format strings for /proc paths */
-#define MAIN_PROC_NAME_FMT "/proc/%d"
#define CTL_PROC_NAME_FMT "/proc/%d/ctl"
#define AS_PROC_NAME_FMT "/proc/%d/as"
#define MAP_PROC_NAME_FMT "/proc/%d/map"
several. Here is some rationale:
There are several file descriptors that may need to be open
- for any given process or LWP. The ones we're interested in are:
+ for any given process or LWP. The ones we're interested in are:
- control (ctl) write-only change the state
- status (status) read-only query the state
- address space (as) read/write access memory
- map (map) read-only virtual addr map
- Most of these are opened lazily as they are needed.
- The pathnames for the 'files' for an LWP look slightly
- different from those of a first-class process:
+ Most of these are opened lazily as they are needed.
+ The pathnames for the 'files' for an LWP look slightly
+ different from those of a first-class process:
Pathnames for a process (<proc-id>):
/proc/<proc-id>/ctl
/proc/<proc-id>/status
Pathnames for an LWP (lwp-id):
/proc/<proc-id>/lwp/<lwp-id>/lwpctl
/proc/<proc-id>/lwp/<lwp-id>/lwpstatus
- An LWP has no map or address space file descriptor, since
- the memory map and address space are shared by all LWPs. */
+ An LWP has no map or address space file descriptor, since
+ the memory map and address space are shared by all LWPs. */
/* In this case, there are several different file descriptors that
we might be asked to open. The control file descriptor will be
/* Chain into list. */
if (tid == 0)
{
- xsnprintf (pi->pathname, sizeof (pi->pathname), MAIN_PROC_NAME_FMT, pid);
+ xsnprintf (pi->pathname, sizeof (pi->pathname), "/proc/%d", pid);
pi->next = procinfo_list;
procinfo_list = pi;
}
/* =================== END, STRUCT PROCINFO "MODULE" =================== */
-/* =================== /proc "MODULE" =================== */
+/* =================== /proc "MODULE" =================== */
/* This "module" is the interface layer between the /proc system API
and the gdb target vector functions. This layer consists of access
need to use from the /proc API.
The main motivation for this layer is to hide the fact that there
- are two very different implementations of the /proc API. Rather
- than have a bunch of #ifdefs all thru the gdb target vector
- functions, we do our best to hide them all in here. */
+ were two very different implementations of the /proc API. */
static long proc_flags (procinfo *pi);
static int proc_why (procinfo *pi);
- clear current signal
- abort the current system call
- stop as soon as finished with system call
- - (ioctl): set traced signal set
- - (ioctl): set held signal set
- - (ioctl): set traced fault set
- - (ioctl): set start pc (vaddr)
Always clears the current fault. PI is the process or LWP to
operate on. If STEP is true, set the process or LWP to trap after
/* =================== Thread "MODULE" =================== */
-/* NOTE: you'll see more ifdefs and duplication of functions here,
- since there is a different way to do threads on every OS. */
-
/* Returns the number of threads for the process. */
static int
return pi->prstatus.pr_nlwp;
}
-/* LWP version.
-
- Return the ID of the thread that had an event of interest.
+/* Return the ID of the thread that had an event of interest.
(ie. the one that hit a breakpoint or other traced event). All
other things being equal, this should be the ID of a thread that is
currently executing. */
}
/* Discover the IDs of all the threads within the process, and create
- a procinfo for each of them (chained to the parent). This
- unfortunately requires a different method on every OS. Returns
+ a procinfo for each of them (chained to the parent). Returns
non-zero for success, zero for failure. */
static int
return __LINE__;
/* Method for tracing exec syscalls. */
- /* GW: Rationale...
- Not all systems with /proc have all the exec* syscalls with the same
- names. On the SGI, for example, there is no SYS_exec, but there
- *is* a SYS_execv. So, we try to account for that. */
-
traced_syscall_exits = XNEW (sysset_t);
premptyset (traced_syscall_exits);
-#ifdef SYS_exec
- praddset (traced_syscall_exits, SYS_exec);
-#endif
praddset (traced_syscall_exits, SYS_execve);
praddset (traced_syscall_exits, SYS_lwp_create);
praddset (traced_syscall_exits, SYS_lwp_exit);
/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
for all registers.
- ??? Is the following note still relevant? We can't get individual
- registers with the PT_GETREGS ptrace(2) request either, yet we
- don't bother with caching at all in that case.
-
NOTE: Since the /proc interface cannot give us individual
registers, we pay no attention to REGNUM, and just fetch them all.
This results in the possibility that we will do unnecessarily many
}
}
-static int
-syscall_is_lwp_exit (procinfo *pi, int scall)
-{
- if (scall == SYS_lwp_exit)
- return 1;
- return 0;
-}
-
-static int
-syscall_is_exit (procinfo *pi, int scall)
-{
- if (scall == SYS_exit)
- return 1;
- return 0;
-}
-
-static int
-syscall_is_exec (procinfo *pi, int scall)
-{
-#ifdef SYS_exec
- if (scall == SYS_exec)
- return 1;
-#endif
- if (scall == SYS_execve)
- return 1;
- return 0;
-}
-
-static int
-syscall_is_lwp_create (procinfo *pi, int scall)
-{
- if (scall == SYS_lwp_create)
- return 1;
- return 0;
-}
-
/* Retrieve the next stop event from the child process. If child has
not stopped yet, wait for it to stop. Translate /proc eventcodes
(or possibly wait eventcodes) into gdb internal event codes.
wstat = (what << 8) | 0177;
break;
case PR_SYSENTRY:
- if (syscall_is_lwp_exit (pi, what))
+ if (what == SYS_lwp_exit)
{
if (print_thread_events)
printf_unfiltered (_("[%s exited]\n"),
status->kind = TARGET_WAITKIND_SPURIOUS;
return retval;
}
- else if (syscall_is_exit (pi, what))
+ else if (what == SYS_exit)
{
struct inferior *inf;
}
break;
case PR_SYSEXIT:
- if (syscall_is_exec (pi, what))
+ if (what == SYS_execve)
{
/* Hopefully this is our own "fork-child" execing
the real child. Hoax this event into a trap, and
address. */
wstat = (SIGTRAP << 8) | 0177;
}
- else if (syscall_is_lwp_create (pi, what))
+ else if (what == SYS_lwp_create)
{
/* This syscall is somewhat like fork/exec. We
will get the event twice: once for the parent
status->kind = TARGET_WAITKIND_SPURIOUS;
return inferior_ptid;
}
- else if (syscall_is_lwp_exit (pi, what))
+ else if (what == SYS_lwp_exit)
{
if (print_thread_events)
printf_unfiltered (_("[%s exited]\n"),
status->kind = TARGET_WAITKIND_SPURIOUS;
return retval;
}
- else if (0)
- {
- /* FIXME: Do we need to handle SYS_sproc,
- SYS_fork, or SYS_vfork here? The old procfs
- seemed to use this event to handle threads on
- older (non-LWP) systems, where I'm assuming
- that threads were actually separate processes.
- Irix, maybe? Anyway, low priority for now. */
- }
else
{
printf_filtered (_("procfs: trapped on exit from "));
/* About to run the child; invalidate caches and do any other
cleanup. */
-#if 0
- if (pi->gregs_dirty)
- if (parent == NULL || proc_get_current_thread (parent) != pi->tid)
- if (!proc_set_gregs (pi)) /* flush gregs cache */
- proc_warn (pi, "target_resume, set_gregs",
- __LINE__);
- if (gdbarch_fp0_regnum (target_gdbarch ()) >= 0)
- if (pi->fpregs_dirty)
- if (parent == NULL || proc_get_current_thread (parent) != pi->tid)
- if (!proc_set_fpregs (pi)) /* flush fpregs cache */
- proc_warn (pi, "target_resume, set_fpregs",
- __LINE__);
-#endif
-
if (parent != NULL)
{
/* The presence of a parent indicates that this is an LWP.
}
pi->gregs_valid = 0;
pi->fpregs_valid = 0;
-#if 0
- pi->gregs_dirty = 0;
- pi->fpregs_dirty = 0;
-#endif
pi->status_valid = 0;
pi->threads_valid = 0;
return 0;
}
-#if 0
-/* A callback function for iterate_over_threads. Find the
- asynchronous signal thread, and make it runnable. See if that
- helps matters any. */
-
-static int
-make_signal_thread_runnable (procinfo *process, procinfo *pi, void *ptr)
-{
-#ifdef PR_ASLWP
- if (proc_flags (pi) & PR_ASLWP)
- {
- if (!proc_run_process (pi, 0, -1))
- proc_error (pi, "make_signal_thread_runnable", __LINE__);
- return 1;
- }
-#endif
- return 0;
-}
-#endif
-
/* Make the child process runnable. Normally we will then call
procfs_wait and wait for it to stop again (unless gdb is async).
procinfo *pi, *thread;
int native_signo;
- /* 2.1:
- prrun.prflags |= PRSVADDR;
- prrun.pr_vaddr = $PC; set resume address
- prrun.prflags |= PRSTRACE; trace signals in pr_trace (all)
- prrun.prflags |= PRSFAULT; trace faults in pr_fault (all but PAGE)
- prrun.prflags |= PRCFAULT; clear current fault.
-
- PRSTRACE and PRSFAULT can be done by other means
- (proc_trace_signals, proc_trace_faults)
- PRSVADDR is unnecessary.
- PRCFAULT may be replaced by a PIOCCFAULT call (proc_clear_current_fault)
+ /* FIXME: Check/reword. */
+
+ /* prrun.prflags |= PRCFAULT; clear current fault.
+ PRCFAULT may be replaced by a PCCFAULT call (proc_clear_current_fault)
This basically leaves PRSTEP and PRCSIG.
- PRCSIG is like PIOCSSIG (proc_clear_current_signal).
+ PRCSIG is like PCSSIG (proc_clear_current_signal).
So basically PR_STEP is the sole argument that must be passed
- to proc_run_process (for use in the prrun struct by ioctl). */
+ to proc_run_process. */
/* Find procinfo for main process. */
pi = find_procinfo_or_die (inferior_ptid.pid (), 0);
others. Set the child process's PR_ASYNC flag. */
if (!proc_set_async (pi))
proc_error (pi, "target_resume, set_async", __LINE__);
-#if 0
- proc_iterate_over_threads (pi,
- make_signal_thread_runnable,
- NULL);
-#endif
pi = thread; /* Substitute the thread's procinfo
for run. */
}
procfs_notice_signals
prfillset (fault)
prdelset (FLTPAGE)
- PIOCWSTOP
- PIOCSFAULT
*/
/* If not stopped yet, wait for it to stop. */
_exit (127);
}
- /* Method for tracing exec syscalls. */
- /* GW: Rationale...
- Not all systems with /proc have all the exec* syscalls with the same
- names. On the SGI, for example, there is no SYS_exec, but there
- *is* a SYS_execv. So, we try to account for that. */
-
exitset = XNEW (sysset_t);
premptyset (exitset);
-#ifdef SYS_exec
- praddset (exitset, SYS_exec);
-#endif
praddset (exitset, SYS_execve);
if (!proc_set_traced_sysexit (pi, exitset))
{
switch (rwflag) { /* FIXME: need an enum! */
case hw_write: /* default watchpoint (write) */
- pflags = WRITE_WATCHFLAG;
+ pflags = WA_WRITE;
break;
case hw_read: /* read watchpoint */
- pflags = READ_WATCHFLAG;
+ pflags = WA_READ;
break;
case hw_access: /* access watchpoint */
- pflags = READ_WATCHFLAG | WRITE_WATCHFLAG;
+ pflags = WA_READ | WA_WRITE;
break;
case hw_execute: /* execution HW breakpoint */
- pflags = EXEC_WATCHFLAG;
+ pflags = WA_EXEC;
break;
default: /* Something weird. Return error. */
return -1;
}
if (after) /* Stop after r/w access is completed. */
- pflags |= AFTER_WATCHFLAG;
+ pflags |= WA_TRAPAFTER;
}
if (!proc_set_watchpoint (pi, addr, len, pflags))
/* Return non-zero if we can set a hardware watchpoint of type TYPE. TYPE
is one of bp_hardware_watchpoint, bp_read_watchpoint, bp_write_watchpoint,
or bp_hardware_watchpoint. CNT is the number of watchpoints used so
- far.
-
- Note: procfs_can_use_hw_breakpoint() is not yet used by all
- procfs.c targets due to the fact that some of them still define
- target_can_use_hardware_watchpoint. */
+ far. */
int
procfs_target::can_use_hw_breakpoint (enum bptype type, int cnt, int othertype)