don't suspend the process as a side-effect if
[minix.git] / kernel / system / do_trace.c
blobb13b66b3c3eadfa7d7f4f5f187bbc788a33b671e
1 /* The kernel call implemented in this file:
2 * m_type: SYS_TRACE
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
9 */
11 #include "../system.h"
12 #include <sys/ptrace.h>
14 #if USE_TRACE
16 /*==========================================================================*
17 * do_trace *
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
25 * The commands are:
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
35 * T_EXIT exit
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;
47 unsigned char ub;
48 int i;
50 #define COPYTOPROC(seg, addr, myaddr, length) { \
51 struct vir_addr fromaddr, toaddr; \
52 int r; \
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);\
61 return r;\
62 } \
65 #define COPYFROMPROC(seg, addr, myaddr, length) { \
66 struct vir_addr fromaddr, toaddr; \
67 int r; \
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); \
73 toaddr.segment = D; \
74 if((r=virtual_copy_vmcheck(&fromaddr, &toaddr, length)) != OK) { \
75 printf("Can't copy in sys_trace: %d\n", r);\
76 return r;\
77 } \
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);
85 switch (tr_request) {
86 case T_STOP: /* stop process */
87 RTS_LOCK_SET(rp, P_STOP);
88 rp->p_reg.psw &= ~TRACEBIT; /* clear trace bit */
89 return(OK);
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;
95 break;
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;
102 break;
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))
107 return(EIO);
108 m_ptr->CTL_DATA = *(long *) ((char *) rp + (int) tr_addr);
109 break;
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));
114 m_ptr->CTL_DATA = 0;
115 break;
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));
121 m_ptr->CTL_DATA = 0;
122 break;
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))
127 return(EIO);
128 i = (int) tr_addr;
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
132 * not allow it.
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 ||
137 #if _WORD_SIZE == 4
138 i == (int) &((struct proc *) 0)->p_reg.gs ||
139 i == (int) &((struct proc *) 0)->p_reg.fs ||
140 #endif
141 i == (int) &((struct proc *) 0)->p_reg.ss)
142 return(EIO);
143 #endif
144 if (i == (int) &((struct proc *) 0)->p_reg.psw)
145 /* only selected bits are changeable */
146 SETPSW(rp, tr_data);
147 else
148 *(reg_t *) ((char *) &rp->p_reg + i) = (reg_t) tr_data;
149 m_ptr->CTL_DATA = 0;
150 break;
152 case T_RESUME: /* resume execution */
153 RTS_LOCK_UNSET(rp, P_STOP);
154 m_ptr->CTL_DATA = 0;
155 break;
157 case T_STEP: /* set trace bit */
158 rp->p_reg.psw |= TRACEBIT;
159 RTS_LOCK_UNSET(rp, P_STOP);
160 m_ptr->CTL_DATA = 0;
161 break;
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;
166 break;
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);
170 m_ptr->CTL_DATA = 0;
171 break;
173 default:
174 return(EIO);
176 return(OK);
179 #endif /* USE_TRACE */