source: trunk/minix/kernel/system/do_trace.c@ 20

Last change on this file since 20 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 4.4 KB
RevLine 
[9]1/* The kernel call implemented in this file:
2 * m_type: SYS_TRACE
3 *
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 */
10
11#include "../system.h"
12#include <sys/ptrace.h>
13
14#if USE_TRACE
15
16/*==========================================================================*
17 * do_trace *
18 *==========================================================================*/
19#define TR_VLSIZE ((vir_bytes) sizeof(long))
20
21PUBLIC int do_trace(m_ptr)
22register message *m_ptr;
23{
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
37 *
38 * The T_OK and T_EXIT commands are handled completely by the process manager,
39 * all others come here.
40 */
41
42 register struct proc *rp;
43 phys_bytes src, dst;
44 vir_bytes tr_addr = (vir_bytes) m_ptr->CTL_ADDRESS;
45 long tr_data = m_ptr->CTL_DATA;
46 int tr_request = m_ptr->CTL_REQUEST;
47 int tr_proc_nr_e = m_ptr->CTL_ENDPT, tr_proc_nr;
48 int i;
49
50 if(!isokendpt(tr_proc_nr_e, &tr_proc_nr)) return(EINVAL);
51 if (iskerneln(tr_proc_nr)) return(EPERM);
52
53 rp = proc_addr(tr_proc_nr);
54 if (isemptyp(rp)) return(EIO);
55 switch (tr_request) {
56 case T_STOP: /* stop process */
57 if (rp->p_rts_flags == 0) lock_dequeue(rp);
58 rp->p_rts_flags |= P_STOP;
59 rp->p_reg.psw &= ~TRACEBIT; /* clear trace bit */
60 return(OK);
61
62 case T_GETINS: /* return value from instruction space */
63 if (rp->p_memmap[T].mem_len != 0) {
64 if ((src = umap_local(rp, T, tr_addr, TR_VLSIZE)) == 0) return(EIO);
65 phys_copy(src, vir2phys(&tr_data), (phys_bytes) sizeof(long));
66 m_ptr->CTL_DATA = tr_data;
67 break;
68 }
69 /* Text space is actually data space - fall through. */
70
71 case T_GETDATA: /* return value from data space */
72 if ((src = umap_local(rp, D, tr_addr, TR_VLSIZE)) == 0) return(EIO);
73 phys_copy(src, vir2phys(&tr_data), (phys_bytes) sizeof(long));
74 m_ptr->CTL_DATA= tr_data;
75 break;
76
77 case T_GETUSER: /* return value from process table */
78 if ((tr_addr & (sizeof(long) - 1)) != 0 ||
79 tr_addr > sizeof(struct proc) - sizeof(long))
80 return(EIO);
81 m_ptr->CTL_DATA = *(long *) ((char *) rp + (int) tr_addr);
82 break;
83
84 case T_SETINS: /* set value in instruction space */
85 if (rp->p_memmap[T].mem_len != 0) {
86 if ((dst = umap_local(rp, T, tr_addr, TR_VLSIZE)) == 0) return(EIO);
87 phys_copy(vir2phys(&tr_data), dst, (phys_bytes) sizeof(long));
88 m_ptr->CTL_DATA = 0;
89 break;
90 }
91 /* Text space is actually data space - fall through. */
92
93 case T_SETDATA: /* set value in data space */
94 if ((dst = umap_local(rp, D, tr_addr, TR_VLSIZE)) == 0) return(EIO);
95 phys_copy(vir2phys(&tr_data), dst, (phys_bytes) sizeof(long));
96 m_ptr->CTL_DATA = 0;
97 break;
98
99 case T_SETUSER: /* set value in process table */
100 if ((tr_addr & (sizeof(reg_t) - 1)) != 0 ||
101 tr_addr > sizeof(struct stackframe_s) - sizeof(reg_t))
102 return(EIO);
103 i = (int) tr_addr;
104#if (CHIP == INTEL)
105 /* Altering segment registers might crash the kernel when it
106 * tries to load them prior to restarting a process, so do
107 * not allow it.
108 */
109 if (i == (int) &((struct proc *) 0)->p_reg.cs ||
110 i == (int) &((struct proc *) 0)->p_reg.ds ||
111 i == (int) &((struct proc *) 0)->p_reg.es ||
112#if _WORD_SIZE == 4
113 i == (int) &((struct proc *) 0)->p_reg.gs ||
114 i == (int) &((struct proc *) 0)->p_reg.fs ||
115#endif
116 i == (int) &((struct proc *) 0)->p_reg.ss)
117 return(EIO);
118#endif
119 if (i == (int) &((struct proc *) 0)->p_reg.psw)
120 /* only selected bits are changeable */
121 SETPSW(rp, tr_data);
122 else
123 *(reg_t *) ((char *) &rp->p_reg + i) = (reg_t) tr_data;
124 m_ptr->CTL_DATA = 0;
125 break;
126
127 case T_RESUME: /* resume execution */
128 rp->p_rts_flags &= ~P_STOP;
129 if (rp->p_rts_flags == 0) lock_enqueue(rp);
130 m_ptr->CTL_DATA = 0;
131 break;
132
133 case T_STEP: /* set trace bit */
134 rp->p_reg.psw |= TRACEBIT;
135 rp->p_rts_flags &= ~P_STOP;
136 if (rp->p_rts_flags == 0) lock_enqueue(rp);
137 m_ptr->CTL_DATA = 0;
138 break;
139
140 default:
141 return(EIO);
142 }
143 return(OK);
144}
145
146#endif /* USE_TRACE */
Note: See TracBrowser for help on using the repository browser.