1/* ptrace.c: Sparc process tracing support.
2 *
3 * Copyright (C) 1996 David S. Miller (davem@caipfs.rutgers.edu)
4 *
5 * Based upon code written by Ross Biro, Linus Torvalds, Bob Manson,
6 * and David Mosberger.
7 *
8 * Added Linux support -miguel (weird, eh?, the orignal code was meant
9 * to emulate SunOS).
10 */
11
12#include <linux/kernel.h>
13#include <linux/sched.h>
14#include <linux/mm.h>
15#include <linux/errno.h>
16#include <linux/ptrace.h>
17#include <linux/user.h>
18#include <linux/smp.h>
19#include <linux/smp_lock.h>
20#include <linux/security.h>
21#include <linux/signal.h>
22
23#include <asm/pgtable.h>
24#include <asm/system.h>
25#include <asm/uaccess.h>
26
27#define MAGIC_CONSTANT 0x80000000
28
29
30/* Returning from ptrace is a bit tricky because the syscall return
31 * low level code assumes any value returned which is negative and
32 * is a valid errno will mean setting the condition codes to indicate
33 * an error return.  This doesn't work, so we have this hook.
34 */
35static inline void pt_error_return(struct pt_regs *regs, unsigned long error)
36{
37	regs->u_regs[UREG_I0] = error;
38	regs->psr |= PSR_C;
39	regs->pc = regs->npc;
40	regs->npc += 4;
41}
42
43static inline void pt_succ_return(struct pt_regs *regs, unsigned long value)
44{
45	regs->u_regs[UREG_I0] = value;
46	regs->psr &= ~PSR_C;
47	regs->pc = regs->npc;
48	regs->npc += 4;
49}
50
51static void
52pt_succ_return_linux(struct pt_regs *regs, unsigned long value, long __user *addr)
53{
54	if (put_user(value, addr)) {
55		pt_error_return(regs, EFAULT);
56		return;
57	}
58	regs->u_regs[UREG_I0] = 0;
59	regs->psr &= ~PSR_C;
60	regs->pc = regs->npc;
61	regs->npc += 4;
62}
63
64static void
65pt_os_succ_return (struct pt_regs *regs, unsigned long val, long __user *addr)
66{
67	if (current->personality == PER_SUNOS)
68		pt_succ_return (regs, val);
69	else
70		pt_succ_return_linux (regs, val, addr);
71}
72
73/* Fuck me gently with a chainsaw... */
74static inline void read_sunos_user(struct pt_regs *regs, unsigned long offset,
75				   struct task_struct *tsk, long __user *addr)
76{
77	struct pt_regs *cregs = tsk->thread.kregs;
78	struct thread_info *t = task_thread_info(tsk);
79	int v;
80
81	if(offset >= 1024)
82		offset -= 1024; /* whee... */
83	if(offset & ((sizeof(unsigned long) - 1))) {
84		pt_error_return(regs, EIO);
85		return;
86	}
87	if(offset >= 16 && offset < 784) {
88		offset -= 16; offset >>= 2;
89		pt_os_succ_return(regs, *(((unsigned long *)(&t->reg_window[0]))+offset), addr);
90		return;
91	}
92	if(offset >= 784 && offset < 832) {
93		offset -= 784; offset >>= 2;
94		pt_os_succ_return(regs, *(((unsigned long *)(&t->rwbuf_stkptrs[0]))+offset), addr);
95		return;
96	}
97	switch(offset) {
98	case 0:
99		v = t->ksp;
100		break;
101	case 4:
102		v = t->kpc;
103		break;
104	case 8:
105		v = t->kpsr;
106		break;
107	case 12:
108		v = t->uwinmask;
109		break;
110	case 832:
111		v = t->w_saved;
112		break;
113	case 896:
114		v = cregs->u_regs[UREG_I0];
115		break;
116	case 900:
117		v = cregs->u_regs[UREG_I1];
118		break;
119	case 904:
120		v = cregs->u_regs[UREG_I2];
121		break;
122	case 908:
123		v = cregs->u_regs[UREG_I3];
124		break;
125	case 912:
126		v = cregs->u_regs[UREG_I4];
127		break;
128	case 916:
129		v = cregs->u_regs[UREG_I5];
130		break;
131	case 920:
132		v = cregs->u_regs[UREG_I6];
133		break;
134	case 924:
135		if(tsk->thread.flags & MAGIC_CONSTANT)
136			v = cregs->u_regs[UREG_G1];
137		else
138			v = 0;
139		break;
140	case 940:
141		v = cregs->u_regs[UREG_I0];
142		break;
143	case 944:
144		v = cregs->u_regs[UREG_I1];
145		break;
146
147	case 948:
148		/* Isn't binary compatibility _fun_??? */
149		if(cregs->psr & PSR_C)
150			v = cregs->u_regs[UREG_I0] << 24;
151		else
152			v = 0;
153		break;
154
155		/* Rest of them are completely unsupported. */
156	default:
157		printk("%s [%d]: Wants to read user offset %ld\n",
158		       current->comm, current->pid, offset);
159		pt_error_return(regs, EIO);
160		return;
161	}
162	if (current->personality == PER_SUNOS)
163		pt_succ_return (regs, v);
164	else
165		pt_succ_return_linux (regs, v, addr);
166	return;
167}
168
169static inline void write_sunos_user(struct pt_regs *regs, unsigned long offset,
170				    struct task_struct *tsk)
171{
172	struct pt_regs *cregs = tsk->thread.kregs;
173	struct thread_info *t = task_thread_info(tsk);
174	unsigned long value = regs->u_regs[UREG_I3];
175
176	if(offset >= 1024)
177		offset -= 1024; /* whee... */
178	if(offset & ((sizeof(unsigned long) - 1)))
179		goto failure;
180	if(offset >= 16 && offset < 784) {
181		offset -= 16; offset >>= 2;
182		*(((unsigned long *)(&t->reg_window[0]))+offset) = value;
183		goto success;
184	}
185	if(offset >= 784 && offset < 832) {
186		offset -= 784; offset >>= 2;
187		*(((unsigned long *)(&t->rwbuf_stkptrs[0]))+offset) = value;
188		goto success;
189	}
190	switch(offset) {
191	case 896:
192		cregs->u_regs[UREG_I0] = value;
193		break;
194	case 900:
195		cregs->u_regs[UREG_I1] = value;
196		break;
197	case 904:
198		cregs->u_regs[UREG_I2] = value;
199		break;
200	case 908:
201		cregs->u_regs[UREG_I3] = value;
202		break;
203	case 912:
204		cregs->u_regs[UREG_I4] = value;
205		break;
206	case 916:
207		cregs->u_regs[UREG_I5] = value;
208		break;
209	case 920:
210		cregs->u_regs[UREG_I6] = value;
211		break;
212	case 924:
213		cregs->u_regs[UREG_I7] = value;
214		break;
215	case 940:
216		cregs->u_regs[UREG_I0] = value;
217		break;
218	case 944:
219		cregs->u_regs[UREG_I1] = value;
220		break;
221
222		/* Rest of them are completely unsupported or "no-touch". */
223	default:
224		printk("%s [%d]: Wants to write user offset %ld\n",
225		       current->comm, current->pid, offset);
226		goto failure;
227	}
228success:
229	pt_succ_return(regs, 0);
230	return;
231failure:
232	pt_error_return(regs, EIO);
233	return;
234}
235
236/* #define ALLOW_INIT_TRACING */
237/* #define DEBUG_PTRACE */
238
239#ifdef DEBUG_PTRACE
240char *pt_rq [] = {
241	/* 0  */ "TRACEME", "PEEKTEXT", "PEEKDATA", "PEEKUSR",
242	/* 4  */ "POKETEXT", "POKEDATA", "POKEUSR", "CONT",
243	/* 8  */ "KILL", "SINGLESTEP", "SUNATTACH", "SUNDETACH",
244	/* 12 */ "GETREGS", "SETREGS", "GETFPREGS", "SETFPREGS",
245	/* 16 */ "READDATA", "WRITEDATA", "READTEXT", "WRITETEXT",
246	/* 20 */ "GETFPAREGS", "SETFPAREGS", "unknown", "unknown",
247	/* 24 */ "SYSCALL", ""
248};
249#endif
250
251/*
252 * Called by kernel/ptrace.c when detaching..
253 *
254 * Make sure single step bits etc are not set.
255 */
256void ptrace_disable(struct task_struct *child)
257{
258	/* nothing to do */
259}
260
261asmlinkage void do_ptrace(struct pt_regs *regs)
262{
263	unsigned long request = regs->u_regs[UREG_I0];
264	unsigned long pid = regs->u_regs[UREG_I1];
265	unsigned long addr = regs->u_regs[UREG_I2];
266	unsigned long data = regs->u_regs[UREG_I3];
267	unsigned long addr2 = regs->u_regs[UREG_I4];
268	struct task_struct *child;
269	int ret;
270
271	lock_kernel();
272#ifdef DEBUG_PTRACE
273	{
274		char *s;
275
276		if ((request >= 0) && (request <= 24))
277			s = pt_rq [request];
278		else
279			s = "unknown";
280
281		if (request == PTRACE_POKEDATA && data == 0x91d02001){
282			printk ("do_ptrace: breakpoint pid=%d, addr=%08lx addr2=%08lx\n",
283				pid, addr, addr2);
284		} else
285			printk("do_ptrace: rq=%s(%d) pid=%d addr=%08lx data=%08lx addr2=%08lx\n",
286			       s, (int) request, (int) pid, addr, data, addr2);
287	}
288#endif
289
290	if (request == PTRACE_TRACEME) {
291		ret = ptrace_traceme();
292		if (ret < 0)
293			pt_error_return(regs, -ret);
294		else
295			pt_succ_return(regs, 0);
296		goto out;
297	}
298
299	child = ptrace_get_task_struct(pid);
300	if (IS_ERR(child)) {
301		ret = PTR_ERR(child);
302		pt_error_return(regs, -ret);
303		goto out;
304	}
305
306	if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH)
307	    || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) {
308		if (ptrace_attach(child)) {
309			pt_error_return(regs, EPERM);
310			goto out_tsk;
311		}
312		pt_succ_return(regs, 0);
313		goto out_tsk;
314	}
315
316	ret = ptrace_check_attach(child, request == PTRACE_KILL);
317	if (ret < 0) {
318		pt_error_return(regs, -ret);
319		goto out_tsk;
320	}
321
322	switch(request) {
323	case PTRACE_PEEKTEXT: /* read word at location addr. */
324	case PTRACE_PEEKDATA: {
325		unsigned long tmp;
326
327		if (access_process_vm(child, addr,
328				      &tmp, sizeof(tmp), 0) == sizeof(tmp))
329			pt_os_succ_return(regs, tmp, (long __user *)data);
330		else
331			pt_error_return(regs, EIO);
332		goto out_tsk;
333	}
334
335	case PTRACE_PEEKUSR:
336		read_sunos_user(regs, addr, child, (long __user *) data);
337		goto out_tsk;
338
339	case PTRACE_POKEUSR:
340		write_sunos_user(regs, addr, child);
341		goto out_tsk;
342
343	case PTRACE_POKETEXT: /* write the word at location addr. */
344	case PTRACE_POKEDATA: {
345		if (access_process_vm(child, addr,
346				      &data, sizeof(data), 1) == sizeof(data))
347			pt_succ_return(regs, 0);
348		else
349			pt_error_return(regs, EIO);
350		goto out_tsk;
351	}
352
353	case PTRACE_GETREGS: {
354		struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
355		struct pt_regs *cregs = child->thread.kregs;
356		int rval;
357
358		if (!access_ok(VERIFY_WRITE, pregs, sizeof(struct pt_regs))) {
359			rval = -EFAULT;
360			pt_error_return(regs, -rval);
361			goto out_tsk;
362		}
363		__put_user(cregs->psr, (&pregs->psr));
364		__put_user(cregs->pc, (&pregs->pc));
365		__put_user(cregs->npc, (&pregs->npc));
366		__put_user(cregs->y, (&pregs->y));
367		for(rval = 1; rval < 16; rval++)
368			__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]));
369		pt_succ_return(regs, 0);
370#ifdef DEBUG_PTRACE
371		printk ("PC=%x nPC=%x o7=%x\n", cregs->pc, cregs->npc, cregs->u_regs [15]);
372#endif
373		goto out_tsk;
374	}
375
376	case PTRACE_SETREGS: {
377		struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
378		struct pt_regs *cregs = child->thread.kregs;
379		unsigned long psr, pc, npc, y;
380		int i;
381
382		/* Must be careful, tracing process can only set certain
383		 * bits in the psr.
384		 */
385		if (!access_ok(VERIFY_READ, pregs, sizeof(struct pt_regs))) {
386			pt_error_return(regs, EFAULT);
387			goto out_tsk;
388		}
389		__get_user(psr, (&pregs->psr));
390		__get_user(pc, (&pregs->pc));
391		__get_user(npc, (&pregs->npc));
392		__get_user(y, (&pregs->y));
393		psr &= PSR_ICC;
394		cregs->psr &= ~PSR_ICC;
395		cregs->psr |= psr;
396		if (!((pc | npc) & 3)) {
397			cregs->pc = pc;
398			cregs->npc =npc;
399		}
400		cregs->y = y;
401		for(i = 1; i < 16; i++)
402			__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]));
403		pt_succ_return(regs, 0);
404		goto out_tsk;
405	}
406
407	case PTRACE_GETFPREGS: {
408		struct fps {
409			unsigned long regs[32];
410			unsigned long fsr;
411			unsigned long flags;
412			unsigned long extra;
413			unsigned long fpqd;
414			struct fq {
415				unsigned long *insnaddr;
416				unsigned long insn;
417			} fpq[16];
418		};
419		struct fps __user *fps = (struct fps __user *) addr;
420		int i;
421
422		if (!access_ok(VERIFY_WRITE, fps, sizeof(struct fps))) {
423			i = -EFAULT;
424			pt_error_return(regs, -i);
425			goto out_tsk;
426		}
427		for(i = 0; i < 32; i++)
428			__put_user(child->thread.float_regs[i], (&fps->regs[i]));
429		__put_user(child->thread.fsr, (&fps->fsr));
430		__put_user(child->thread.fpqdepth, (&fps->fpqd));
431		__put_user(0, (&fps->flags));
432		__put_user(0, (&fps->extra));
433		for(i = 0; i < 16; i++) {
434			__put_user(child->thread.fpqueue[i].insn_addr,
435				   (&fps->fpq[i].insnaddr));
436			__put_user(child->thread.fpqueue[i].insn, (&fps->fpq[i].insn));
437		}
438		pt_succ_return(regs, 0);
439		goto out_tsk;
440	}
441
442	case PTRACE_SETFPREGS: {
443		struct fps {
444			unsigned long regs[32];
445			unsigned long fsr;
446			unsigned long flags;
447			unsigned long extra;
448			unsigned long fpqd;
449			struct fq {
450				unsigned long *insnaddr;
451				unsigned long insn;
452			} fpq[16];
453		};
454		struct fps __user *fps = (struct fps __user *) addr;
455		int i;
456
457		if (!access_ok(VERIFY_READ, fps, sizeof(struct fps))) {
458			i = -EFAULT;
459			pt_error_return(regs, -i);
460			goto out_tsk;
461		}
462		copy_from_user(&child->thread.float_regs[0], &fps->regs[0], (32 * sizeof(unsigned long)));
463		__get_user(child->thread.fsr, (&fps->fsr));
464		__get_user(child->thread.fpqdepth, (&fps->fpqd));
465		for(i = 0; i < 16; i++) {
466			__get_user(child->thread.fpqueue[i].insn_addr,
467				   (&fps->fpq[i].insnaddr));
468			__get_user(child->thread.fpqueue[i].insn, (&fps->fpq[i].insn));
469		}
470		pt_succ_return(regs, 0);
471		goto out_tsk;
472	}
473
474	case PTRACE_READTEXT:
475	case PTRACE_READDATA: {
476		int res = ptrace_readdata(child, addr,
477					  (void __user *) addr2, data);
478
479		if (res == data) {
480			pt_succ_return(regs, 0);
481			goto out_tsk;
482		}
483		/* Partial read is an IO failure */
484		if (res >= 0)
485			res = -EIO;
486		pt_error_return(regs, -res);
487		goto out_tsk;
488	}
489
490	case PTRACE_WRITETEXT:
491	case PTRACE_WRITEDATA: {
492		int res = ptrace_writedata(child, (void __user *) addr2,
493					   addr, data);
494
495		if (res == data) {
496			pt_succ_return(regs, 0);
497			goto out_tsk;
498		}
499		/* Partial write is an IO failure */
500		if (res >= 0)
501			res = -EIO;
502		pt_error_return(regs, -res);
503		goto out_tsk;
504	}
505
506	case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */
507		addr = 1;
508
509	case PTRACE_CONT: { /* restart after signal. */
510		if (!valid_signal(data)) {
511			pt_error_return(regs, EIO);
512			goto out_tsk;
513		}
514
515		if (request == PTRACE_SYSCALL)
516			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
517		else
518			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
519
520		child->exit_code = data;
521#ifdef DEBUG_PTRACE
522		printk("CONT: %s [%d]: set exit_code = %x %lx %lx\n",
523			child->comm, child->pid, child->exit_code,
524			child->thread.kregs->pc,
525			child->thread.kregs->npc);
526#endif
527		wake_up_process(child);
528		pt_succ_return(regs, 0);
529		goto out_tsk;
530	}
531
532/*
533 * make the child exit.  Best I can do is send it a sigkill.
534 * perhaps it should be put in the status that it wants to
535 * exit.
536 */
537	case PTRACE_KILL: {
538		if (child->exit_state == EXIT_ZOMBIE) {	/* already dead */
539			pt_succ_return(regs, 0);
540			goto out_tsk;
541		}
542		wake_up_process(child);
543		child->exit_code = SIGKILL;
544		pt_succ_return(regs, 0);
545		goto out_tsk;
546	}
547
548	case PTRACE_SUNDETACH: { /* detach a process that was attached. */
549		int err = ptrace_detach(child, data);
550		if (err) {
551			pt_error_return(regs, EIO);
552			goto out_tsk;
553		}
554		pt_succ_return(regs, 0);
555		goto out_tsk;
556	}
557
558	/* PTRACE_DUMPCORE unsupported... */
559
560	default: {
561		int err = ptrace_request(child, request, addr, data);
562		if (err)
563			pt_error_return(regs, -err);
564		else
565			pt_succ_return(regs, 0);
566		goto out_tsk;
567	}
568	}
569out_tsk:
570	if (child)
571		put_task_struct(child);
572out:
573	unlock_kernel();
574}
575
576asmlinkage void syscall_trace(void)
577{
578#ifdef DEBUG_PTRACE
579	printk("%s [%d]: syscall_trace\n", current->comm, current->pid);
580#endif
581	if (!test_thread_flag(TIF_SYSCALL_TRACE))
582		return;
583	if (!(current->ptrace & PT_PTRACED))
584		return;
585	current->thread.flags ^= MAGIC_CONSTANT;
586	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
587				 ? 0x80 : 0));
588	/*
589	 * this isn't the same as continuing with a signal, but it will do
590	 * for normal use.  strace only continues with a signal if the
591	 * stopping signal is not SIGTRAP.  -brl
592	 */
593#ifdef DEBUG_PTRACE
594	printk("%s [%d]: syscall_trace exit= %x\n", current->comm,
595		current->pid, current->exit_code);
596#endif
597	if (current->exit_code) {
598		send_sig (current->exit_code, current, 1);
599		current->exit_code = 0;
600	}
601}
602