1 /* The kernel call implemented in this file:
4 * The parameters for this kernel call are:
5 * m2_i1: CTL_ENDPT process that is traced
6 * m2_i2: CTL_REQUEST trace request
7 * m2_l1: CTL_ADDRESS address at traced process' space
8 * m2_l2: CTL_DATA data to be written or returned here
11 #include "../system.h"
12 #include <sys/ptrace.h>
16 /*==========================================================================*
18 *==========================================================================*/
19 #define TR_VLSIZE ((vir_bytes) sizeof(long))
21 PUBLIC
int do_trace(m_ptr
)
22 register message
*m_ptr
;
24 /* Handle the debugging commands supported by the ptrace system call
26 * T_STOP stop the process
27 * T_OK enable tracing by parent for this process
28 * T_GETINS return value from instruction space
29 * T_GETDATA return value from data space
30 * T_GETUSER return value from user process table
31 * T_SETINS set value from instruction space
32 * T_SETDATA set value from data space
33 * T_SETUSER set value in user process table
34 * T_RESUME resume execution
36 * T_STEP set trace bit
38 * The T_OK and T_EXIT commands are handled completely by the process manager,
39 * all others come here.
42 register struct proc
*rp
;
43 vir_bytes tr_addr
= (vir_bytes
) m_ptr
->CTL_ADDRESS
;
44 long tr_data
= m_ptr
->CTL_DATA
;
45 int tr_request
= m_ptr
->CTL_REQUEST
;
46 int tr_proc_nr_e
= m_ptr
->CTL_ENDPT
, tr_proc_nr
;
50 #define COPYTOPROC(seg, addr, myaddr, length) { \
51 struct vir_addr fromaddr, toaddr; \
53 fromaddr.proc_nr_e = SYSTEM; \
54 toaddr.proc_nr_e = tr_proc_nr_e; \
55 fromaddr.offset = (myaddr); \
56 toaddr.offset = (addr); \
57 fromaddr.segment = D; \
58 toaddr.segment = (seg); \
59 if((r=virtual_copy_vmcheck(&fromaddr, &toaddr, length)) != OK) { \
60 printf("Can't copy in sys_trace: %d\n", r);\
65 #define COPYFROMPROC(seg, addr, myaddr, length) { \
66 struct vir_addr fromaddr, toaddr; \
68 fromaddr.proc_nr_e = tr_proc_nr_e; \
69 toaddr.proc_nr_e = SYSTEM; \
70 fromaddr.offset = (addr); \
71 toaddr.offset = (myaddr); \
72 fromaddr.segment = (seg); \
74 if((r=virtual_copy_vmcheck(&fromaddr, &toaddr, length)) != OK) { \
75 printf("Can't copy in sys_trace: %d\n", r);\
80 if(!isokendpt(tr_proc_nr_e
, &tr_proc_nr
)) return(EINVAL
);
81 if (iskerneln(tr_proc_nr
)) return(EPERM
);
83 rp
= proc_addr(tr_proc_nr
);
84 if (isemptyp(rp
)) return(EIO
);
86 case T_STOP
: /* stop process */
87 RTS_LOCK_SET(rp
, P_STOP
);
88 rp
->p_reg
.psw
&= ~TRACEBIT
; /* clear trace bit */
91 case T_GETINS
: /* return value from instruction space */
92 if (rp
->p_memmap
[T
].mem_len
!= 0) {
93 COPYFROMPROC(T
, tr_addr
, (vir_bytes
) &tr_data
, sizeof(long));
94 m_ptr
->CTL_DATA
= tr_data
;
97 /* Text space is actually data space - fall through. */
99 case T_GETDATA
: /* return value from data space */
100 COPYFROMPROC(D
, tr_addr
, (vir_bytes
) &tr_data
, sizeof(long));
101 m_ptr
->CTL_DATA
= tr_data
;
104 case T_GETUSER
: /* return value from process table */
105 if ((tr_addr
& (sizeof(long) - 1)) != 0 ||
106 tr_addr
> sizeof(struct proc
) - sizeof(long))
108 m_ptr
->CTL_DATA
= *(long *) ((char *) rp
+ (int) tr_addr
);
111 case T_SETINS
: /* set value in instruction space */
112 if (rp
->p_memmap
[T
].mem_len
!= 0) {
113 COPYTOPROC(T
, tr_addr
, (vir_bytes
) &tr_data
, sizeof(long));
117 /* Text space is actually data space - fall through. */
119 case T_SETDATA
: /* set value in data space */
120 COPYTOPROC(D
, tr_addr
, (vir_bytes
) &tr_data
, sizeof(long));
124 case T_SETUSER
: /* set value in process table */
125 if ((tr_addr
& (sizeof(reg_t
) - 1)) != 0 ||
126 tr_addr
> sizeof(struct stackframe_s
) - sizeof(reg_t
))
129 #if (_MINIX_CHIP == _CHIP_INTEL)
130 /* Altering segment registers might crash the kernel when it
131 * tries to load them prior to restarting a process, so do
134 if (i
== (int) &((struct proc
*) 0)->p_reg
.cs
||
135 i
== (int) &((struct proc
*) 0)->p_reg
.ds
||
136 i
== (int) &((struct proc
*) 0)->p_reg
.es
||
138 i
== (int) &((struct proc
*) 0)->p_reg
.gs
||
139 i
== (int) &((struct proc
*) 0)->p_reg
.fs
||
141 i
== (int) &((struct proc
*) 0)->p_reg
.ss
)
144 if (i
== (int) &((struct proc
*) 0)->p_reg
.psw
)
145 /* only selected bits are changeable */
148 *(reg_t
*) ((char *) &rp
->p_reg
+ i
) = (reg_t
) tr_data
;
152 case T_RESUME
: /* resume execution */
153 RTS_LOCK_UNSET(rp
, P_STOP
);
157 case T_STEP
: /* set trace bit */
158 rp
->p_reg
.psw
|= TRACEBIT
;
159 RTS_LOCK_UNSET(rp
, P_STOP
);
163 case T_READB_INS
: /* get value from instruction space */
164 COPYFROMPROC(rp
->p_memmap
[T
].mem_len
> 0 ? T
: D
, tr_addr
, (vir_bytes
) &ub
, 1);
165 m_ptr
->CTL_DATA
= ub
;
168 case T_WRITEB_INS
: /* set value in instruction space */
169 COPYTOPROC(rp
->p_memmap
[T
].mem_len
> 0 ? T
: D
,tr_addr
, (vir_bytes
) &tr_data
, 1);
179 #endif /* USE_TRACE */