Blame view

arch/m68knommu/kernel/ptrace.c 5.9 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  /*
   *  linux/arch/m68knommu/kernel/ptrace.c
   *
   *  Copyright (C) 1994 by Hamish Macdonald
   *  Taken from linux/kernel/ptrace.c and modified for M680x0.
   *  linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
   *
   * This file is subject to the terms and conditions of the GNU General
   * Public License.  See the file COPYING in the main directory of
   * this archive for more details.
   */
  
  #include <linux/kernel.h>
  #include <linux/sched.h>
  #include <linux/mm.h>
  #include <linux/smp.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
18
19
  #include <linux/errno.h>
  #include <linux/ptrace.h>
  #include <linux/user.h>
7ed20e1ad   Jesper Juhl   [PATCH] convert t...
20
  #include <linux/signal.h>
55f411de4   Greg Ungerer   m68knommu: conver...
21
  #include <linux/tracehook.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
  
  #include <asm/uaccess.h>
  #include <asm/page.h>
  #include <asm/pgtable.h>
  #include <asm/system.h>
  #include <asm/processor.h>
  
  /*
   * does not yet catch signals sent when the child dies.
   * in exit.c or in signal.c.
   */
  
  /* determines which bits in the SR the user has access to. */
  /* 1 = access 0 = no access */
  #define SR_MASK 0x001f
  
  /* sets the trace bits. */
  #define TRACE_BITS 0x8000
  
  /* Find the stack offset for a register, relative to thread.esp0. */
  #define PT_REG(reg)	((long)&((struct pt_regs *)0)->reg)
  #define SW_REG(reg)	((long)&((struct switch_stack *)0)->reg \
  			 - sizeof(struct switch_stack))
  /* Mapping from PT_xxx to the stack offset at which the register is
     saved.  Notice that usp has no stack-slot and needs to be treated
     specially (see get_reg/put_reg below). */
  static int regoff[] = {
  	PT_REG(d1), PT_REG(d2), PT_REG(d3), PT_REG(d4),
  	PT_REG(d5), SW_REG(d6), SW_REG(d7), PT_REG(a0),
  	PT_REG(a1), PT_REG(a2), SW_REG(a3), SW_REG(a4),
  	SW_REG(a5), SW_REG(a6), PT_REG(d0), -1,
  	PT_REG(orig_d0), PT_REG(sr), PT_REG(pc),
  };
  
  /*
   * Get contents of register REGNO in task TASK.
   */
  static inline long get_reg(struct task_struct *task, int regno)
  {
  	unsigned long *addr;
  
  	if (regno == PT_USP)
  		addr = &task->thread.usp;
bf0059b23   Ahmed S. Darwish   [PATCH] M68KNOMMU...
65
  	else if (regno < ARRAY_SIZE(regoff))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
  		addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
  	else
  		return 0;
  	return *addr;
  }
  
  /*
   * Write contents of register REGNO in task TASK.
   */
  static inline int put_reg(struct task_struct *task, int regno,
  			  unsigned long data)
  {
  	unsigned long *addr;
  
  	if (regno == PT_USP)
  		addr = &task->thread.usp;
bf0059b23   Ahmed S. Darwish   [PATCH] M68KNOMMU...
82
  	else if (regno < ARRAY_SIZE(regoff))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
84
85
86
87
88
  		addr = (unsigned long *) (task->thread.esp0 + regoff[regno]);
  	else
  		return -1;
  	*addr = data;
  	return 0;
  }
f60a55726   Greg Ungerer   m68knommu: define...
89
90
91
92
93
94
95
96
97
98
99
100
101
  void user_enable_single_step(struct task_struct *task)
  {
  	unsigned long srflags;
  	srflags = get_reg(task, PT_SR) | (TRACE_BITS << 16);
  	put_reg(task, PT_SR, srflags);
  }
  
  void user_disable_single_step(struct task_struct *task)
  {
  	unsigned long srflags;
  	srflags = get_reg(task, PT_SR) & ~(TRACE_BITS << 16);
  	put_reg(task, PT_SR, srflags);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
103
104
105
106
107
108
  /*
   * Called by kernel/ptrace.c when detaching..
   *
   * Make sure the single step bit is not set.
   */
  void ptrace_disable(struct task_struct *child)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
  	/* make sure the single step bit is not set. */
f60a55726   Greg Ungerer   m68knommu: define...
110
  	user_disable_single_step(child);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
  }
9b05a69e0   Namhyung Kim   ptrace: change si...
112
113
  long arch_ptrace(struct task_struct *child, long request,
  		 unsigned long addr, unsigned long data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
  	int ret;
bf60ef960   Namhyung Kim   ptrace: cleanup a...
116
117
  	int regno = addr >> 2;
  	unsigned long __user *datap = (unsigned long __user *) data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
  	switch (request) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
121
122
123
124
  		/* read the word at location addr in the USER area. */
  		case PTRACE_PEEKUSR: {
  			unsigned long tmp;
  			
  			ret = -EIO;
bf60ef960   Namhyung Kim   ptrace: cleanup a...
125
  			if ((addr & 3) || addr > sizeof(struct user) - 3)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
127
128
  				break;
  			
  			tmp = 0;  /* Default return condition */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
  			ret = -EIO;
bf60ef960   Namhyung Kim   ptrace: cleanup a...
130
131
132
  			if (regno < 19) {
  				tmp = get_reg(child, regno);
  				if (regno == PT_SR)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
133
  					tmp >>= 16;
bf60ef960   Namhyung Kim   ptrace: cleanup a...
134
135
136
  			} else if (regno >= 21 && regno < 49) {
  				tmp = child->thread.fp[regno - 21];
  			} else if (regno == 49) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
  				tmp = child->mm->start_code;
bf60ef960   Namhyung Kim   ptrace: cleanup a...
138
  			} else if (regno == 50) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
  				tmp = child->mm->start_data;
bf60ef960   Namhyung Kim   ptrace: cleanup a...
140
  			} else if (regno == 51) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
142
143
  				tmp = child->mm->end_code;
  			} else
  				break;
bf60ef960   Namhyung Kim   ptrace: cleanup a...
144
  			ret = put_user(tmp, datap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
146
  			break;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
148
  		case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
  			ret = -EIO;
bf60ef960   Namhyung Kim   ptrace: cleanup a...
149
  			if ((addr & 3) || addr > sizeof(struct user) - 3)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
  				break;
bf60ef960   Namhyung Kim   ptrace: cleanup a...
151
  			if (regno == PT_SR) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
153
154
155
  				data &= SR_MASK;
  				data <<= 16;
  				data |= get_reg(child, PT_SR) & ~(SR_MASK << 16);
  			}
bf60ef960   Namhyung Kim   ptrace: cleanup a...
156
157
  			if (regno < 19) {
  				if (put_reg(child, regno, data))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
160
161
  					break;
  				ret = 0;
  				break;
  			}
bf60ef960   Namhyung Kim   ptrace: cleanup a...
162
  			if (regno >= 21 && regno < 48)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
  			{
bf60ef960   Namhyung Kim   ptrace: cleanup a...
164
  				child->thread.fp[regno - 21] = data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
166
167
  				ret = 0;
  			}
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
169
170
171
172
173
174
  		case PTRACE_GETREGS: { /* Get all gp regs from the child. */
  		  	int i;
  			unsigned long tmp;
  			for (i = 0; i < 19; i++) {
  			    tmp = get_reg(child, i);
  			    if (i == PT_SR)
  				tmp >>= 16;
bf60ef960   Namhyung Kim   ptrace: cleanup a...
175
  			    if (put_user(tmp, datap)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
177
178
  				ret = -EFAULT;
  				break;
  			    }
bf60ef960   Namhyung Kim   ptrace: cleanup a...
179
  			    datap++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
181
182
183
184
185
186
187
188
  			}
  			ret = 0;
  			break;
  		}
  
  		case PTRACE_SETREGS: { /* Set all gp regs in the child. */
  			int i;
  			unsigned long tmp;
  			for (i = 0; i < 19; i++) {
bf60ef960   Namhyung Kim   ptrace: cleanup a...
189
  			    if (get_user(tmp, datap)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
191
192
193
194
195
196
197
198
  				ret = -EFAULT;
  				break;
  			    }
  			    if (i == PT_SR) {
  				tmp &= SR_MASK;
  				tmp <<= 16;
  				tmp |= get_reg(child, PT_SR) & ~(SR_MASK << 16);
  			    }
  			    put_reg(child, i, tmp);
bf60ef960   Namhyung Kim   ptrace: cleanup a...
199
  			    datap++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
201
202
203
204
205
206
207
  			}
  			ret = 0;
  			break;
  		}
  
  #ifdef PTRACE_GETFPREGS
  		case PTRACE_GETFPREGS: { /* Get the child FPU state. */
  			ret = 0;
bf60ef960   Namhyung Kim   ptrace: cleanup a...
208
  			if (copy_to_user(datap, &child->thread.fp,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
210
211
212
213
214
215
216
217
  					 sizeof(struct user_m68kfp_struct)))
  				ret = -EFAULT;
  			break;
  		}
  #endif
  
  #ifdef PTRACE_SETFPREGS
  		case PTRACE_SETFPREGS: { /* Set the child FPU state. */
  			ret = 0;
bf60ef960   Namhyung Kim   ptrace: cleanup a...
218
  			if (copy_from_user(&child->thread.fp, datap,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219
220
221
222
223
  					   sizeof(struct user_m68kfp_struct)))
  				ret = -EFAULT;
  			break;
  		}
  #endif
a58f75349   Maxim Kuvyrkov   m68knommu: NPTL s...
224
  	case PTRACE_GET_THREAD_AREA:
bf60ef960   Namhyung Kim   ptrace: cleanup a...
225
  		ret = put_user(task_thread_info(child)->tp_value, datap);
a58f75349   Maxim Kuvyrkov   m68knommu: NPTL s...
226
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
  		default:
b3c1e01a0   Christoph Hellwig   ptrace: use ptrac...
228
  			ret = ptrace_request(child, request, addr, data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229
230
  			break;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231
232
  	return ret;
  }
55f411de4   Greg Ungerer   m68knommu: conver...
233
  asmlinkage int syscall_trace_enter(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
  {
55f411de4   Greg Ungerer   m68knommu: conver...
235
236
237
238
239
240
241
242
243
244
245
  	int ret = 0;
  
  	if (test_thread_flag(TIF_SYSCALL_TRACE))
  		ret = tracehook_report_syscall_entry(task_pt_regs(current));
  	return ret;
  }
  
  asmlinkage void syscall_trace_leave(void)
  {
  	if (test_thread_flag(TIF_SYSCALL_TRACE))
  		tracehook_report_syscall_exit(task_pt_regs(current), 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
  }