[9] | 1 | /* This file handles the process manager's part of debugging, using the
|
---|
| 2 | * ptrace system call. Most of the commands are passed on to the system
|
---|
| 3 | * task for completion.
|
---|
| 4 | *
|
---|
| 5 | * The debugging commands available are:
|
---|
| 6 | * T_STOP stop the process
|
---|
| 7 | * T_OK enable tracing by parent for this process
|
---|
| 8 | * T_GETINS return value from instruction space
|
---|
| 9 | * T_GETDATA return value from data space
|
---|
| 10 | * T_GETUSER return value from user process table
|
---|
| 11 | * T_SETINS set value in instruction space
|
---|
| 12 | * T_SETDATA set value in data space
|
---|
| 13 | * T_SETUSER set value in user process table
|
---|
| 14 | * T_RESUME resume execution
|
---|
| 15 | * T_EXIT exit
|
---|
| 16 | * T_STEP set trace bit
|
---|
| 17 | *
|
---|
| 18 | * The T_OK and T_EXIT commands are handled here, and the T_RESUME and
|
---|
| 19 | * T_STEP commands are partially handled here and completed by the system
|
---|
| 20 | * task. The rest are handled entirely by the system task.
|
---|
| 21 | */
|
---|
| 22 |
|
---|
| 23 | #include "pm.h"
|
---|
| 24 | #include <minix/com.h>
|
---|
| 25 | #include <sys/ptrace.h>
|
---|
| 26 | #include <signal.h>
|
---|
| 27 | #include "mproc.h"
|
---|
| 28 | #include "param.h"
|
---|
| 29 |
|
---|
| 30 | #define NIL_MPROC ((struct mproc *) 0)
|
---|
| 31 |
|
---|
| 32 | FORWARD _PROTOTYPE( struct mproc *find_proc, (pid_t lpid) );
|
---|
| 33 |
|
---|
| 34 | /*===========================================================================*
|
---|
| 35 | * do_trace *
|
---|
| 36 | *===========================================================================*/
|
---|
| 37 | PUBLIC int do_trace()
|
---|
| 38 | {
|
---|
| 39 | register struct mproc *child;
|
---|
| 40 | int r;
|
---|
| 41 |
|
---|
| 42 | /* the T_OK call is made by the child fork of the debugger before it execs
|
---|
| 43 | * the process to be traced
|
---|
| 44 | */
|
---|
| 45 | if (m_in.request == T_OK) { /* enable tracing by parent for this proc */
|
---|
| 46 | mp->mp_flags |= TRACED;
|
---|
| 47 | mp->mp_reply.reply_trace = 0;
|
---|
| 48 | return(OK);
|
---|
| 49 | }
|
---|
| 50 | if ((child=find_proc(m_in.pid))==NIL_MPROC || !(child->mp_flags & STOPPED)) {
|
---|
| 51 | return(ESRCH);
|
---|
| 52 | }
|
---|
| 53 | /* all the other calls are made by the parent fork of the debugger to
|
---|
| 54 | * control execution of the child
|
---|
| 55 | */
|
---|
| 56 | switch (m_in.request) {
|
---|
| 57 | case T_EXIT: /* exit */
|
---|
| 58 | pm_exit(child, (int) m_in.data);
|
---|
| 59 | mp->mp_reply.reply_trace = 0;
|
---|
| 60 | return(OK);
|
---|
| 61 | case T_RESUME:
|
---|
| 62 | case T_STEP: /* resume execution */
|
---|
| 63 | if (m_in.data < 0 || m_in.data > _NSIG) return(EIO);
|
---|
| 64 | if (m_in.data > 0) { /* issue signal */
|
---|
| 65 | child->mp_flags &= ~TRACED; /* so signal is not diverted */
|
---|
| 66 | sig_proc(child, (int) m_in.data);
|
---|
| 67 | child->mp_flags |= TRACED;
|
---|
| 68 | }
|
---|
| 69 | child->mp_flags &= ~STOPPED;
|
---|
| 70 | break;
|
---|
| 71 | }
|
---|
| 72 | r= sys_trace(m_in.request,child->mp_endpoint,m_in.taddr,&m_in.data);
|
---|
| 73 | if (r != OK) return(r);
|
---|
| 74 |
|
---|
| 75 | mp->mp_reply.reply_trace = m_in.data;
|
---|
| 76 | return(OK);
|
---|
| 77 | }
|
---|
| 78 |
|
---|
| 79 | /*===========================================================================*
|
---|
| 80 | * find_proc *
|
---|
| 81 | *===========================================================================*/
|
---|
| 82 | PRIVATE struct mproc *find_proc(lpid)
|
---|
| 83 | pid_t lpid;
|
---|
| 84 | {
|
---|
| 85 | register struct mproc *rmp;
|
---|
| 86 |
|
---|
| 87 | for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++)
|
---|
| 88 | if (rmp->mp_flags & IN_USE && rmp->mp_pid == lpid) return(rmp);
|
---|
| 89 | return(NIL_MPROC);
|
---|
| 90 | }
|
---|
| 91 |
|
---|
| 92 | /*===========================================================================*
|
---|
| 93 | * stop_proc *
|
---|
| 94 | *===========================================================================*/
|
---|
| 95 | PUBLIC void stop_proc(rmp, signo)
|
---|
| 96 | register struct mproc *rmp;
|
---|
| 97 | int signo;
|
---|
| 98 | {
|
---|
| 99 | /* A traced process got a signal so stop it. */
|
---|
| 100 |
|
---|
| 101 | register struct mproc *rpmp = mproc + rmp->mp_parent;
|
---|
| 102 | int r;
|
---|
| 103 |
|
---|
| 104 | r= sys_trace(-1, rmp->mp_endpoint, 0L, (long *) 0);
|
---|
| 105 | if (r != OK) panic("pm", "sys_trace failed", r);
|
---|
| 106 |
|
---|
| 107 | rmp->mp_flags |= STOPPED;
|
---|
| 108 | if (rpmp->mp_flags & WAITING) {
|
---|
| 109 | rpmp->mp_flags &= ~WAITING; /* parent is no longer waiting */
|
---|
| 110 | rpmp->mp_reply.reply_res2 = 0177 | (signo << 8);
|
---|
| 111 | setreply(rmp->mp_parent, rmp->mp_pid);
|
---|
| 112 | } else {
|
---|
| 113 | rmp->mp_sigstatus = signo;
|
---|
| 114 | }
|
---|
| 115 | return;
|
---|
| 116 | }
|
---|