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
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
16 * T_STEP set trace bit
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.
24 #include <minix/com.h>
25 #include <sys/ptrace.h>
30 #define NIL_MPROC ((struct mproc *) 0)
32 FORWARD
_PROTOTYPE( struct mproc
*find_proc
, (pid_t lpid
) );
34 /*===========================================================================*
36 *===========================================================================*/
39 register struct mproc
*child
;
42 /* the T_OK call is made by the child fork of the debugger before it execs
43 * the process to be traced
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;
50 if (m_in
.request
== T_READB_INS
)
52 /* Special hack for reading text segments */
53 if (mp
->mp_effuid
!= SUPER_USER
)
55 if ((child
=find_proc(m_in
.pid
))==NIL_MPROC
)
58 r
= sys_trace(m_in
.request
,child
->mp_endpoint
,m_in
.taddr
,&m_in
.data
);
59 if (r
!= OK
) return(r
);
61 mp
->mp_reply
.reply_trace
= m_in
.data
;
64 if (m_in
.request
== T_WRITEB_INS
)
66 /* Special hack for patching text segments */
67 if (mp
->mp_effuid
!= SUPER_USER
)
69 if ((child
=find_proc(m_in
.pid
))==NIL_MPROC
)
72 r
= sys_trace(m_in
.request
,child
->mp_endpoint
,m_in
.taddr
,&m_in
.data
);
73 if (r
!= OK
) return(r
);
75 mp
->mp_reply
.reply_trace
= m_in
.data
;
79 if ((child
=find_proc(m_in
.pid
))==NIL_MPROC
|| !(child
->mp_flags
& STOPPED
)) {
82 /* all the other calls are made by the parent fork of the debugger to
83 * control execution of the child
85 switch (m_in
.request
) {
86 case T_EXIT
: /* exit */
87 pm_exit(child
, (int) m_in
.data
, TRUE
/*for_trace*/);
88 /* Do not reply to the caller until FS has processed the exit
93 case T_STEP
: /* resume execution */
94 if (m_in
.data
< 0 || m_in
.data
> _NSIG
) return(EIO
);
95 if (m_in
.data
> 0) { /* issue signal */
96 child
->mp_flags
&= ~TRACED
; /* so signal is not diverted */
97 sig_proc(child
, (int) m_in
.data
);
98 child
->mp_flags
|= TRACED
;
100 child
->mp_flags
&= ~STOPPED
;
103 r
= sys_trace(m_in
.request
,child
->mp_endpoint
,m_in
.taddr
,&m_in
.data
);
104 if (r
!= OK
) return(r
);
106 mp
->mp_reply
.reply_trace
= m_in
.data
;
110 /*===========================================================================*
112 *===========================================================================*/
113 PRIVATE
struct mproc
*find_proc(lpid
)
116 register struct mproc
*rmp
;
118 for (rmp
= &mproc
[0]; rmp
< &mproc
[NR_PROCS
]; rmp
++)
119 if (rmp
->mp_flags
& IN_USE
&& rmp
->mp_pid
== lpid
) return(rmp
);
123 /*===========================================================================*
125 *===========================================================================*/
126 PUBLIC
void stop_proc(rmp
, signo
)
127 register struct mproc
*rmp
;
130 /* A traced process got a signal so stop it. */
132 register struct mproc
*rpmp
= mproc
+ rmp
->mp_parent
;
135 r
= sys_trace(-1, rmp
->mp_endpoint
, 0L, (long *) 0);
136 if (r
!= OK
) panic("pm", "sys_trace failed", r
);
138 rmp
->mp_flags
|= STOPPED
;
139 if (rpmp
->mp_flags
& WAITING
) {
140 rpmp
->mp_flags
&= ~WAITING
; /* parent is no longer waiting */
141 rpmp
->mp_reply
.reply_res2
= 0177 | (signo
<< 8);
142 setreply(rmp
->mp_parent
, rmp
->mp_pid
);
144 rmp
->mp_sigstatus
= signo
;