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 |
|
---|
41 | /* the T_OK call is made by the child fork of the debugger before it execs
|
---|
42 | * the process to be traced
|
---|
43 | */
|
---|
44 | if (m_in.request == T_OK) { /* enable tracing by parent for this proc */
|
---|
45 | mp->mp_flags |= TRACED;
|
---|
46 | mp->mp_reply.reply_trace = 0;
|
---|
47 | return(OK);
|
---|
48 | }
|
---|
49 | if ((child=find_proc(m_in.pid))==NIL_MPROC || !(child->mp_flags & STOPPED)) {
|
---|
50 | return(ESRCH);
|
---|
51 | }
|
---|
52 | /* all the other calls are made by the parent fork of the debugger to
|
---|
53 | * control execution of the child
|
---|
54 | */
|
---|
55 | switch (m_in.request) {
|
---|
56 | case T_EXIT: /* exit */
|
---|
57 | pm_exit(child, (int) m_in.data);
|
---|
58 | mp->mp_reply.reply_trace = 0;
|
---|
59 | return(OK);
|
---|
60 | case T_RESUME:
|
---|
61 | case T_STEP: /* resume execution */
|
---|
62 | if (m_in.data < 0 || m_in.data > _NSIG) return(EIO);
|
---|
63 | if (m_in.data > 0) { /* issue signal */
|
---|
64 | child->mp_flags &= ~TRACED; /* so signal is not diverted */
|
---|
65 | sig_proc(child, (int) m_in.data);
|
---|
66 | child->mp_flags |= TRACED;
|
---|
67 | }
|
---|
68 | child->mp_flags &= ~STOPPED;
|
---|
69 | break;
|
---|
70 | }
|
---|
71 | if (sys_trace(m_in.request,(int)(child-mproc),m_in.taddr,&m_in.data) != OK)
|
---|
72 | return(-errno);
|
---|
73 | mp->mp_reply.reply_trace = m_in.data;
|
---|
74 | return(OK);
|
---|
75 | }
|
---|
76 |
|
---|
77 | /*===========================================================================*
|
---|
78 | * find_proc *
|
---|
79 | *===========================================================================*/
|
---|
80 | PRIVATE struct mproc *find_proc(lpid)
|
---|
81 | pid_t lpid;
|
---|
82 | {
|
---|
83 | register struct mproc *rmp;
|
---|
84 |
|
---|
85 | for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++)
|
---|
86 | if (rmp->mp_flags & IN_USE && rmp->mp_pid == lpid) return(rmp);
|
---|
87 | return(NIL_MPROC);
|
---|
88 | }
|
---|
89 |
|
---|
90 | /*===========================================================================*
|
---|
91 | * stop_proc *
|
---|
92 | *===========================================================================*/
|
---|
93 | PUBLIC void stop_proc(rmp, signo)
|
---|
94 | register struct mproc *rmp;
|
---|
95 | int signo;
|
---|
96 | {
|
---|
97 | /* A traced process got a signal so stop it. */
|
---|
98 |
|
---|
99 | register struct mproc *rpmp = mproc + rmp->mp_parent;
|
---|
100 |
|
---|
101 | if (sys_trace(-1, (int) (rmp - mproc), 0L, (long *) 0) != OK) return;
|
---|
102 | rmp->mp_flags |= STOPPED;
|
---|
103 | if (rpmp->mp_flags & WAITING) {
|
---|
104 | rpmp->mp_flags &= ~WAITING; /* parent is no longer waiting */
|
---|
105 | rpmp->mp_reply.reply_res2 = 0177 | (signo << 8);
|
---|
106 | setreply(rmp->mp_parent, rmp->mp_pid);
|
---|
107 | } else {
|
---|
108 | rmp->mp_sigstatus = signo;
|
---|
109 | }
|
---|
110 | return;
|
---|
111 | }
|
---|