2 * arch/ubicom32/kernel/ptrace.c
3 * Ubicom32 architecture ptrace implementation.
5 * (C) Copyright 2009, Ubicom, Inc.
6 * (C) 1994 by Hamish Macdonald
7 * Taken from linux/kernel/ptrace.c and modified for M680x0.
8 * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
10 * This file is part of the Ubicom32 Linux Kernel Port.
12 * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13 * it and/or modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, either version 2 of the
15 * License, or (at your option) any later version.
17 * The Ubicom32 Linux Kernel Port is distributed in the hope that it
18 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
19 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
20 * the GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with the Ubicom32 Linux Kernel Port. If not,
24 * see <http://www.gnu.org/licenses/>.
26 * Ubicom32 implementation derived from (with many thanks):
32 #include <linux/module.h>
33 #include <linux/kernel.h>
34 #include <linux/sched.h>
36 #include <linux/smp.h>
37 #include <linux/errno.h>
38 #include <linux/ptrace.h>
39 #include <linux/user.h>
40 #include <linux/signal.h>
41 #include <linux/uaccess.h>
44 #include <asm/pgtable.h>
45 #include <asm/system.h>
46 #include <asm/cacheflush.h>
47 #include <asm/processor.h>
52 * Get all user integer registers.
54 static inline int ptrace_getregs(struct task_struct
*task
, void __user
*uregs
)
56 struct pt_regs
*regs
= task_pt_regs(task
);
57 return copy_to_user(uregs
, regs
, sizeof(struct pt_regs
)) ? -EFAULT
: 0;
63 * Get contents of register REGNO in task TASK.
65 static unsigned long ptrace_get_reg(struct task_struct
*task
, int regno
)
67 if (regno
< sizeof(struct pt_regs
)) {
68 struct pt_regs
*pt_regs
= task_pt_regs(task
);
69 return *(unsigned long *)((long) pt_regs
+ regno
);
77 * Write contents of register REGNO in task TASK.
79 static int ptrace_put_reg(struct task_struct
*task
, int regno
,
82 if (regno
<= sizeof(struct pt_regs
) && regno
!= PT_FRAME_TYPE
) {
83 struct pt_regs
*pt_regs
= task_pt_regs(task
);
84 *(unsigned long *)((long) pt_regs
+ regno
) = data
;
91 * ptrace_disable_single_step()
94 static int ptrace_disable_single_step(struct task_struct
*task
)
97 * Single Step not yet implemented, so must always be disabled
104 * Make sure the single step bit is not set.
105 * Called by kernel/ptrace.c when detaching..
107 void ptrace_disable(struct task_struct
*child
)
109 ptrace_disable_single_step(child
);
114 * architecture specific ptrace routine.
116 long arch_ptrace(struct task_struct
*child
, long request
, long addr
, long data
)
120 /* when I and D space are separate, these will need to be fixed. */
121 case PTRACE_PEEKTEXT
: /* read word at location addr. */
122 case PTRACE_PEEKDATA
:
123 ret
= generic_ptrace_peekdata(child
, addr
, data
);
126 /* read the word at location addr in the USER area. */
127 case PTRACE_PEEKUSR
: {
131 if (((unsigned long) addr
> PT_INTERP_FDPIC_LOADMAP
)
135 tmp
= 0; /* Default return condition */
138 if (addr
< sizeof(struct pt_regs
)) {
139 tmp
= ptrace_get_reg(child
, addr
);
140 } else if (addr
== PT_TEXT_ADDR
) {
141 tmp
= child
->mm
->start_code
;
142 } else if (addr
== PT_TEXT_END_ADDR
) {
143 tmp
= child
->mm
->end_code
;
144 } else if (addr
== PT_DATA_ADDR
) {
145 tmp
= child
->mm
->start_data
;
146 } else if (addr
== PT_EXEC_FDPIC_LOADMAP
) {
147 #ifdef CONFIG_BINFMT_ELF_FDPIC
148 tmp
= child
->mm
->context
.exec_fdpic_loadmap
;
150 } else if (addr
== PT_INTERP_FDPIC_LOADMAP
) {
151 #ifdef CONFIG_BINFMT_ELF_FDPIC
152 tmp
= child
->mm
->context
.interp_fdpic_loadmap
;
158 ret
= put_user(tmp
, (unsigned long *)data
);
162 case PTRACE_POKETEXT
: /* write the word at location addr. */
163 case PTRACE_POKEDATA
:
164 ret
= generic_ptrace_pokedata(child
, addr
, data
);
167 * If we just changed some code so we need to
170 if (request
== PTRACE_POKETEXT
&& ret
== 0) {
171 flush_icache_range(addr
, addr
+ 4);
175 case PTRACE_POKEUSR
: /* write the word at location addr
176 * in the USER area */
179 if (((unsigned long) addr
> PT_DATA_ADDR
) || (addr
& 3))
182 if (addr
< sizeof(struct pt_regs
)) {
183 ret
= ptrace_put_reg(child
, addr
, data
);
187 case PTRACE_SYSCALL
: /* continue and stop at next (return from)
189 case PTRACE_CONT
: { /* restart after signal. */
192 if (!valid_signal(data
))
194 if (request
== PTRACE_SYSCALL
)
195 set_tsk_thread_flag(child
, TIF_SYSCALL_TRACE
);
197 clear_tsk_thread_flag(child
, TIF_SYSCALL_TRACE
);
198 child
->exit_code
= data
;
199 /* make sure the single step bit is not set. */
200 ptrace_disable_single_step(child
);
201 wake_up_process(child
);
207 * make the child exit. Best I can do is send it a sigkill.
208 * perhaps it should be put in the status that it wants to exit.
212 if (child
->exit_state
== EXIT_ZOMBIE
) /* already dead */
214 child
->exit_code
= SIGKILL
;
215 /* make sure the single step bit is not set. */
216 ptrace_disable_single_step(child
);
217 wake_up_process(child
);
221 case PTRACE_DETACH
: /* detach a process that was attached. */
222 ret
= ptrace_detach(child
, data
);
225 case PTRACE_GETREGS
: /* Get all gp regs from the child. */
226 ptrace_getregs(child
, (unsigned long *)data
);
230 case PTRACE_SETREGS
: { /* Set all gp regs in the child. */
233 int count
= sizeof(struct pt_regs
) / sizeof(unsigned long);
234 for (i
= 0; i
< count
; i
++) {
235 if (get_user(tmp
, (unsigned long *) data
)) {
239 ptrace_put_reg(child
, sizeof(unsigned long) * i
, tmp
);
240 data
+= sizeof(long);
247 return ptrace_request(child
, request
, addr
, data
);
255 * called by syscall enter/exit when the TIF_SYSCALL_TRACE bit is set.
257 asmlinkage
void syscall_trace(void)
259 struct task_struct
*cur
= current
;
260 if (!test_thread_flag(TIF_SYSCALL_TRACE
))
262 if (!(cur
->ptrace
& PT_PTRACED
))
264 ptrace_notify(SIGTRAP
| ((cur
->ptrace
& PT_TRACESYSGOOD
)
267 * this isn't the same as continuing with a signal, but it will do
268 * for normal use. strace only continues with a signal if the
269 * stopping signal is not SIGTRAP. -brl
271 if (cur
->exit_code
) {
272 send_sig(cur
->exit_code
, current
, 1);
273 current
->exit_code
= 0;