Merge of David's ptrace branch. Summary:

o Support for ptrace T_ATTACH/T_DETACH and T_SYSCALL
o PM signal handling logic should now work properly, even with debuggers
  being present
o Asynchronous PM/VFS protocol, full IPC support for senda(), and
  AMF_NOREPLY senda() flag

DETAILS

Process stop and delay call handling of PM:
o Added sys_runctl() kernel call with sys_stop() and sys_resume()
  aliases, for PM to stop and resume a process
o Added exception for sending/syscall-traced processes to sys_runctl(),
  and matching SIGKREADY pseudo-signal to PM
o Fixed PM signal logic to deal with requests from a process after
  stopping it (so-called "delay calls"), using the SIGKREADY facility
o Fixed various PM panics due to race conditions with delay calls versus
  VFS calls
o Removed special PRIO_STOP priority value
o Added SYS_LOCK RTS kernel flag, to stop an individual process from
  running while modifying its process structure

Signal and debugger handling in PM:
o Fixed debugger signals being dropped if a second signal arrives when
  the debugger has not retrieved the first one
o Fixed debugger signals being sent to the debugger more than once
o Fixed debugger signals unpausing process in VFS; removed PM_UNPAUSE_TR
  protocol message
o Detached debugger signals from general signal logic and from being
  blocked on VFS calls, meaning that even VFS can now be traced
o Fixed debugger being unable to receive more than one pending signal in
  one process stop
o Fixed signal delivery being delayed needlessly when multiple signals
  are pending
o Fixed wait test for tracer, which was returning for children that were
  not waited for
o Removed second parallel pending call from PM to VFS for any process
o Fixed process becoming runnable between exec() and debugger trap
o Added support for notifying the debugger before the parent when a
  debugged child exits
o Fixed debugger death causing child to remain stopped forever
o Fixed consistently incorrect use of _NSIG

Extensions to ptrace():
o Added T_ATTACH and T_DETACH ptrace request, to attach and detach a
  debugger to and from a process
o Added T_SYSCALL ptrace request, to trace system calls
o Added T_SETOPT ptrace request, to set trace options
o Added TO_TRACEFORK trace option, to attach automatically to children
  of a traced process
o Added TO_ALTEXEC trace option, to send SIGSTOP instead of SIGTRAP upon
  a successful exec() of the tracee
o Extended T_GETUSER ptrace support to allow retrieving a process's priv
  structure
o Removed T_STOP ptrace request again, as it does not help implementing
  debuggers properly
o Added MINIX3-specific ptrace test (test42)
o Added proper manual page for ptrace(2)

Asynchronous PM/VFS interface:
o Fixed asynchronous messages not being checked when receive() is called
  with an endpoint other than ANY
o Added AMF_NOREPLY senda() flag, preventing such messages from
  satisfying the receive part of a sendrec()
o Added asynsend3() that takes optional flags; asynsend() is now a
  #define passing in 0 as third parameter
o Made PM/VFS protocol asynchronous; reintroduced tell_fs()
o Made PM_BASE request/reply number range unique
o Hacked in a horrible temporary workaround into RS to deal with newly
  revealed RS-PM-VFS race condition triangle until VFS is asynchronous

System signal handling:
o Fixed shutdown logic of device drivers; removed old SIGKSTOP signal
o Removed is-superuser check from PM's do_procstat() (aka getsigset())
o Added sigset macros to allow system processes to deal with the full
  signal set, rather than just the POSIX subset

Miscellaneous PM fixes:
o Split do_getset into do_get and do_set, merging common code and making
  structure clearer
o Fixed setpriority() being able to put to sleep processes using an
  invalid parameter, or revive zombie processes
o Made find_proc() global; removed obsolete proc_from_pid()
o Cleanup here and there

Also included:
o Fixed false-positive boot order kernel warning
o Removed last traces of old NOTIFY_FROM code

THINGS OF POSSIBLE INTEREST

o It should now be possible to run PM at any priority, even lower than
  user processes
o No assumptions are made about communication speed between PM and VFS,
  although communication must be FIFO
o A debugger will now receive incoming debuggee signals at kill time
  only; the process may not yet be fully stopped
o A first step has been made towards making the SYSTEM task preemptible
This commit is contained in:
David van Moolenbroek
2009-09-30 09:57:22 +00:00
parent 8d9aa1fe4f
commit b423d7b477
70 changed files with 3177 additions and 1446 deletions

View File

@@ -64,20 +64,10 @@
/* FIXME will be is_notify(a) ((a) == NOTIFY_MESSAGE) */
#define is_notify(a) ((a) & NOTIFY_MESSAGE)
#define NOTIFY_FROM(p_nr) (NOTIFY_MESSAGE | ((p_nr) + NR_TASKS))
# define PROC_EVENT NOTIFY_FROM(PM_PROC_NR) /* process status change */
# define SYN_ALARM NOTIFY_FROM(CLOCK) /* synchronous alarm */
# define SYS_SIG NOTIFY_FROM(SYSTEM) /* system signal */
# define HARD_INT NOTIFY_FROM(HARDWARE) /* hardware interrupt */
# define FKEY_PRESSED NOTIFY_FROM(TTY_PROC_NR)/* function key press */
# define DEV_PING NOTIFY_FROM(RS_PROC_NR) /* driver liveness ping */
# define DS_UPDATE NOTIFY_FROM(DS_PROC_NR) /* subscription update */
/* Shorthands for message parameters passed with notifications. */
#define NOTIFY_SOURCE m_source
#define NOTIFY_TYPE m_type
#define NOTIFY_ARG m2_l1
#define NOTIFY_TIMESTAMP m2_l2
#define NOTIFY_FLAGS m2_i1
/*===========================================================================*
* Messages for BUS controller drivers *
@@ -330,8 +320,9 @@
# define SYS_SYSCTL (KERNEL_CALL + 44) /* sys_sysctl() */
# define SYS_VTIMER (KERNEL_CALL + 45) /* sys_vtimer() */
# define SYS_RUNCTL (KERNEL_CALL + 46) /* sys_runctl() */
#define NR_SYS_CALLS 46 /* number of system calls */
#define NR_SYS_CALLS 47 /* number of system calls */
/* Pseudo call for use in kernel/table.c. */
#define SYS_ALL_CALLS (NR_SYS_CALLS)
@@ -621,6 +612,12 @@
#define VT_VALUE m2_l1 /* new/previous value of the timer */
#define VT_ENDPT m2_l2 /* process to set/retrieve the timer for */
/* Field names for SYS_RUNCTL. */
#define RC_ENDPT m1_i1 /* which process to stop or resume */
#define RC_ACTION m1_i2 /* set or clear stop flag */
# define RC_STOP 0 /* stop the process, unless delaying */
# define RC_RESUME 1 /* clear the stop flag */
/*===========================================================================*
* Messages for the Reincarnation Server *
*===========================================================================*/
@@ -696,52 +693,57 @@
#define DIAG_REPL_OLD (DIAG_BASE+0x80+0) /* reply to DIAGNOSTICS(_S) */
#define PM_BASE 0x900
#define PM_GET_WORK (PM_BASE + 1) /* Get work from PM */
#define PM_IDLE (PM_BASE + 2) /* PM doesn't have any more work */
#define PM_BUSY (PM_BASE + 3) /* A reply from FS is needed */
#define PM_SETSID (PM_BASE + 5) /* Tell FS about the session leader */
#define PM_SETSID_PROC m1_i1 /* process */
#define PM_SETGID (PM_BASE + 6) /* Tell FS about the new group IDs */
#define PM_SETGID_PROC m1_i1 /* process */
#define PM_SETGID_EGID m1_i2 /* effective group id */
#define PM_SETGID_RGID m1_i3 /* real group id */
#define PM_SETUID (PM_BASE + 7) /* Tell FS about the new user IDs */
#define PM_SETUID_PROC m1_i1 /* process */
#define PM_SETUID_EGID m1_i2 /* effective user id */
#define PM_SETUID_RGID m1_i3 /* real user id */
#define PM_FORK (PM_BASE + 8) /* Tell FS about the new process */
#define PM_FORK_PPROC m1_i1 /* parent process */
#define PM_FORK_CPROC m1_i2 /* child process */
#define PM_FORK_CPID m1_i3 /* child pid */
#define PM_EXIT (PM_BASE + 9) /* Tell FS about the exiting process */
#define PM_EXIT_PROC m1_i1 /* process */
#define PM_UNPAUSE (PM_BASE + 10) /* interrupted process */
#define PM_UNPAUSE_PROC m1_i1 /* process */
#define PM_REBOOT (PM_BASE + 11) /* Tell FS that we about to reboot */
#define PM_EXEC (PM_BASE + 12) /* Forward exec call to FS */
#define PM_EXEC_PROC m1_i1 /* process */
#define PM_EXEC_PATH m1_p1 /* executable */
#define PM_EXEC_PATH_LEN m1_i2 /* length of path including
* terminating nul
*/
#define PM_EXEC_FRAME m1_p2 /* arguments and environment */
#define PM_EXEC_FRAME_LEN m1_i3 /* size of frame */
#define PM_FORK_NB (PM_BASE + 13) /* Tell FS about the fork_nb call */
#define PM_DUMPCORE (PM_BASE + 14) /* Ask FS to generate a core dump */
#define PM_CORE_PROC m1_i1
#define PM_CORE_SEGPTR m1_p1
#define PM_UNPAUSE_TR (PM_BASE + 15) /* interrupted process (for tracing) */
/*===========================================================================*
* Messages used between PM and VFS *
*===========================================================================*/
/* Replies */
#define PM_EXIT_REPLY (PM_BASE + 20) /* Reply from FS */
#define PM_REBOOT_REPLY (PM_BASE + 21) /* Reply from FS */
#define PM_EXEC_REPLY (PM_BASE + 22) /* Reply from FS */
/* PM_EXEC_PROC m1_i1 */
#define PM_EXEC_STATUS m1_i2 /* OK or failure */
#define PM_CORE_REPLY (PM_BASE + 23) /* Reply from FS */
/* PM_CORE_PROC m1_i1 */
#define PM_CORE_STATUS m1_i2 /* OK or failure */
#define PM_BASE 0xE00
/* Requests from PM to VFS */
#define PM_SETUID (PM_BASE + 1) /* Tell FS about the new user IDs */
#define PM_SETGID (PM_BASE + 2) /* Tell FS about the new group IDs */
#define PM_SETSID (PM_BASE + 3) /* Tell FS about the session leader */
#define PM_EXIT (PM_BASE + 4) /* Tell FS about the exiting process */
#define PM_DUMPCORE (PM_BASE + 5) /* Ask FS to generate a core dump */
#define PM_EXEC (PM_BASE + 6) /* Forward exec call to FS */
#define PM_FORK (PM_BASE + 7) /* Tell FS about the new process */
#define PM_FORK_NB (PM_BASE + 8) /* Tell FS about the fork_nb call */
#define PM_UNPAUSE (PM_BASE + 9) /* interrupted process */
#define PM_REBOOT (PM_BASE + 10) /* Tell FS that we about to reboot */
/* Replies from VFS to PM */
#define PM_SETUID_REPLY (PM_BASE + 21)
#define PM_SETGID_REPLY (PM_BASE + 22)
#define PM_SETSID_REPLY (PM_BASE + 23)
#define PM_EXIT_REPLY (PM_BASE + 24)
#define PM_CORE_REPLY (PM_BASE + 25)
#define PM_EXEC_REPLY (PM_BASE + 26)
#define PM_FORK_REPLY (PM_BASE + 27)
#define PM_FORK_NB_REPLY (PM_BASE + 28)
#define PM_UNPAUSE_REPLY (PM_BASE + 29)
#define PM_REBOOT_REPLY (PM_BASE + 30)
/* Standard parameters for all requests and replies, except PM_REBOOT */
# define PM_PROC m1_i1 /* process */
/* Additional parameters for PM_SETUID and PM_SETGID */
# define PM_EID m1_i2 /* effective user/group id */
# define PM_RID m1_i3 /* real user/group id */
/* Additional parameters for PM_EXEC */
# define PM_PATH m1_p1 /* executable */
# define PM_PATH_LEN m1_i2 /* length of path including
* terminating nul
*/
# define PM_FRAME m1_p2 /* arguments and environment */
# define PM_FRAME_LEN m1_i3 /* size of frame */
/* Additional parameters for PM_EXEC_REPLY and PM_CORE_REPLY */
# define PM_STATUS m1_i2 /* OK or failure */
/* Additional parameters for PM_FORK and PM_FORK_NB */
# define PM_PPROC m1_i2 /* parent process */
# define PM_CPID m1_i3 /* child pid */
/* Parameters for the EXEC_NEWMEM call */
#define EXC_NM_PROC m1_i1 /* process that needs new map */

View File

@@ -133,6 +133,7 @@ typedef struct asynmsg
* result is stored in 'result'
*/
#define AMF_NOTIFY 4 /* Send a notification when AMF_DONE is set */
#define AMF_NOREPLY 8 /* Not a reply message for a SENDREC */
/* Hide names to avoid name space pollution. */
#define echo _echo

View File

@@ -40,6 +40,11 @@ _PROTOTYPE( int sys_newmap, (endpoint_t proc_ep, struct mem_map *ptr));
_PROTOTYPE( int sys_exit, (endpoint_t proc_ep));
_PROTOTYPE( int sys_trace, (int req, endpoint_t proc_ep, long addr, long *data_p));
/* Shorthands for sys_runctl() system call. */
#define sys_stop(proc_ep) sys_runctl(proc_ep, RC_STOP)
#define sys_resume(proc_ep) sys_runctl(proc_ep, RC_RESUME)
_PROTOTYPE( int sys_runctl, (endpoint_t proc_ep, int action));
_PROTOTYPE( int sys_privctl, (endpoint_t proc_ep, int req, void *p));
_PROTOTYPE( int sys_setgrant, (cp_grant_t *grants, int ngrants));
_PROTOTYPE( int sys_nice, (endpoint_t proc_ep, int priority));

View File

@@ -56,10 +56,11 @@ _PROTOTYPE( void util_nstrcat, (char *str, unsigned long n) );
_PROTOTYPE( void util_stacktrace_strcat, (char *));
_PROTOTYPE( int micro_delay, (u32_t micros));
_PROTOTYPE( u32_t micros_to_ticks, (u32_t micros));
_PROTOTYPE( int asynsend, (endpoint_t ep, message *msg));
_PROTOTYPE( void ser_putc, (char c));
_PROTOTYPE( void get_randomness, (struct k_randomness *, int));
#define asynsend(ep, msg) asynsend3(ep, msg, 0)
_PROTOTYPE( int asynsend3, (endpoint_t ep, message *msg, int flags));
#define ASSERT(c) if(!(c)) { panic(__FILE__, "assert " #c " failed at line", __LINE__); }

View File

@@ -7,7 +7,7 @@
#include <minix/endpoint.h>
_PROTOTYPE( int vm_exit, (endpoint_t ep));
_PROTOTYPE( int vm_fork, (endpoint_t ep, int slotno, int *child_ep));
_PROTOTYPE( int vm_fork, (endpoint_t ep, int slotno, endpoint_t *child_ep));
_PROTOTYPE( int vm_brk, (endpoint_t ep, char *newaddr));
_PROTOTYPE( int vm_exec_newmem, (endpoint_t ep, struct exec_newmem *args,
int args_bytes, char **ret_stack_top, int *ret_flags));

View File

@@ -66,7 +66,7 @@ typedef unsigned long sigset_t;
*/
#define SIGKMESS 29 /* new kernel message */
#define SIGKSIG 30 /* kernel signal pending */
#define SIGKSTOP 31 /* kernel shutting down */
#define SIGKREADY 31 /* ready for signal delivery */
#endif
@@ -113,15 +113,29 @@ _PROTOTYPE( int kill, (pid_t _pid, int _sig) );
_PROTOTYPE( int killpg, (pid_t _pgrp, int _sig) );
_PROTOTYPE( int sigaction,
(int _sig, const struct sigaction *_act, struct sigaction *_oact) );
_PROTOTYPE( int sigpending, (sigset_t *_set) );
_PROTOTYPE( int sigprocmask,
(int _how, const sigset_t *_set, sigset_t *_oset) );
_PROTOTYPE( int sigsuspend, (const sigset_t *_sigmask) );
/* For the sigset functions, only use the library version with error
* checking from user programs. System programs need to be able to use
* nonstanard signals.
*/
#ifndef _SYSTEM
_PROTOTYPE( int sigaddset, (sigset_t *_set, int _sig) );
_PROTOTYPE( int sigdelset, (sigset_t *_set, int _sig) );
_PROTOTYPE( int sigemptyset, (sigset_t *_set) );
_PROTOTYPE( int sigfillset, (sigset_t *_set) );
_PROTOTYPE( int sigismember, (const sigset_t *_set, int _sig) );
_PROTOTYPE( int sigpending, (sigset_t *_set) );
_PROTOTYPE( int sigprocmask,
(int _how, const sigset_t *_set, sigset_t *_oset) );
_PROTOTYPE( int sigsuspend, (const sigset_t *_sigmask) );
#else
#define sigaddset(set, sig) ((int) ((*(set) |= (1 << (sig))) && 0))
#define sigdelset(set, sig) ((int) ((*(set) &= ~(1 << (sig))) && 0))
#define sigemptyset(set) ((int) (*(set) = 0))
#define sigfillset(set) ((int) ((*(set) = ~0) && 0))
#define sigismember(set, sig) ((*(set) & (1 << (sig))) ? 1 : 0)
#endif
#endif
#endif /* _SIGNAL_H */

View File

@@ -5,6 +5,7 @@
#ifndef _PTRACE_H
#define _PTRACE_H
/* Trace requests. */
#define T_STOP -1 /* stop the process */
#define T_OK 0 /* enable tracing by parent for this process */
#define T_GETINS 1 /* return value from instruction space */
@@ -16,6 +17,10 @@
#define T_RESUME 7 /* resume execution */
#define T_EXIT 8 /* exit */
#define T_STEP 9 /* set trace bit */
#define T_SYSCALL 10 /* trace system call */
#define T_ATTACH 11 /* attach to a running process */
#define T_DETACH 12 /* detach from a traced process */
#define T_SETOPT 13 /* set trace options */
#define T_READB_INS 100 /* Read a byte from the text segment of an
* untraced process (only for root)
@@ -24,6 +29,10 @@
* untraced process (only for root)
*/
/* Trace options. */
#define TO_TRACEFORK 0x1 /* automatically attach to forked children */
#define TO_ALTEXEC 0x2 /* send SIGSTOP on successful exec() */
/* Function Prototypes. */
#ifndef _ANSI_H
#include <ansi.h>

View File

@@ -8,9 +8,6 @@
#define PRIO_MIN -20
#define PRIO_MAX 20
/* Magic, invalid priority to stop the process. */
#define PRIO_STOP 76
#define PRIO_PROCESS 0
#define PRIO_PGRP 1
#define PRIO_USER 2