aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/kernel/ptrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/kernel/ptrace.c')
-rw-r--r--arch/um/kernel/ptrace.c79
1 files changed, 29 insertions, 50 deletions
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 3efa59a941a4..2b75d8d9ba73 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -19,15 +19,30 @@
19#include "skas_ptrace.h" 19#include "skas_ptrace.h"
20#include "sysdep/ptrace.h" 20#include "sysdep/ptrace.h"
21 21
22static inline void set_singlestepping(struct task_struct *child, int on)
23{
24 if (on)
25 child->ptrace |= PT_DTRACE;
26 else
27 child->ptrace &= ~PT_DTRACE;
28 child->thread.singlestep_syscall = 0;
29
30#ifdef SUBARCH_SET_SINGLESTEPPING
31 SUBARCH_SET_SINGLESTEPPING(child, on)
32#endif
33 }
34
22/* 35/*
23 * Called by kernel/ptrace.c when detaching.. 36 * Called by kernel/ptrace.c when detaching..
24 */ 37 */
25void ptrace_disable(struct task_struct *child) 38void ptrace_disable(struct task_struct *child)
26{ 39{
27 child->ptrace &= ~PT_DTRACE; 40 set_singlestepping(child,0);
28 child->thread.singlestep_syscall = 0;
29} 41}
30 42
43extern int peek_user(struct task_struct * child, long addr, long data);
44extern int poke_user(struct task_struct * child, long addr, long data);
45
31long sys_ptrace(long request, long pid, long addr, long data) 46long sys_ptrace(long request, long pid, long addr, long data)
32{ 47{
33 struct task_struct *child; 48 struct task_struct *child;
@@ -67,6 +82,10 @@ long sys_ptrace(long request, long pid, long addr, long data)
67 goto out_tsk; 82 goto out_tsk;
68 } 83 }
69 84
85#ifdef SUBACH_PTRACE_SPECIAL
86 SUBARCH_PTRACE_SPECIAL(child,request,addr,data)
87#endif
88
70 ret = ptrace_check_attach(child, request == PTRACE_KILL); 89 ret = ptrace_check_attach(child, request == PTRACE_KILL);
71 if (ret < 0) 90 if (ret < 0)
72 goto out_tsk; 91 goto out_tsk;
@@ -87,28 +106,9 @@ long sys_ptrace(long request, long pid, long addr, long data)
87 } 106 }
88 107
89 /* read the word at location addr in the USER area. */ 108 /* read the word at location addr in the USER area. */
90 case PTRACE_PEEKUSR: { 109 case PTRACE_PEEKUSR:
91 unsigned long tmp; 110 ret = peek_user(child, addr, data);
92 111 break;
93 ret = -EIO;
94 if ((addr & 3) || addr < 0)
95 break;
96
97 tmp = 0; /* Default return condition */
98 if(addr < MAX_REG_OFFSET){
99 tmp = getreg(child, addr);
100 }
101#if defined(CONFIG_UML_X86) && !defined(CONFIG_64BIT)
102 else if((addr >= offsetof(struct user, u_debugreg[0])) &&
103 (addr <= offsetof(struct user, u_debugreg[7]))){
104 addr -= offsetof(struct user, u_debugreg[0]);
105 addr = addr >> 2;
106 tmp = child->thread.arch.debugregs[addr];
107 }
108#endif
109 ret = put_user(tmp, (unsigned long __user *) data);
110 break;
111 }
112 112
113 /* when I and D space are separate, this will have to be fixed. */ 113 /* when I and D space are separate, this will have to be fixed. */
114 case PTRACE_POKETEXT: /* write the word at location addr. */ 114 case PTRACE_POKETEXT: /* write the word at location addr. */
@@ -121,26 +121,8 @@ long sys_ptrace(long request, long pid, long addr, long data)
121 break; 121 break;
122 122
123 case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ 123 case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
124 ret = -EIO; 124 ret = poke_user(child, addr, data);
125 if ((addr & 3) || addr < 0) 125 break;
126 break;
127
128 if (addr < MAX_REG_OFFSET) {
129 ret = putreg(child, addr, data);
130 break;
131 }
132#if defined(CONFIG_UML_X86) && !defined(CONFIG_64BIT)
133 else if((addr >= offsetof(struct user, u_debugreg[0])) &&
134 (addr <= offsetof(struct user, u_debugreg[7]))){
135 addr -= offsetof(struct user, u_debugreg[0]);
136 addr = addr >> 2;
137 if((addr == 4) || (addr == 5)) break;
138 child->thread.arch.debugregs[addr] = data;
139 ret = 0;
140 }
141#endif
142
143 break;
144 126
145 case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ 127 case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
146 case PTRACE_CONT: { /* restart after signal. */ 128 case PTRACE_CONT: { /* restart after signal. */
@@ -148,8 +130,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
148 if (!valid_signal(data)) 130 if (!valid_signal(data))
149 break; 131 break;
150 132
151 child->ptrace &= ~PT_DTRACE; 133 set_singlestepping(child, 0);
152 child->thread.singlestep_syscall = 0;
153 if (request == PTRACE_SYSCALL) { 134 if (request == PTRACE_SYSCALL) {
154 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 135 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
155 } 136 }
@@ -172,8 +153,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
172 if (child->exit_state == EXIT_ZOMBIE) /* already dead */ 153 if (child->exit_state == EXIT_ZOMBIE) /* already dead */
173 break; 154 break;
174 155
175 child->ptrace &= ~PT_DTRACE; 156 set_singlestepping(child, 0);
176 child->thread.singlestep_syscall = 0;
177 child->exit_code = SIGKILL; 157 child->exit_code = SIGKILL;
178 wake_up_process(child); 158 wake_up_process(child);
179 break; 159 break;
@@ -184,8 +164,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
184 if (!valid_signal(data)) 164 if (!valid_signal(data))
185 break; 165 break;
186 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 166 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
187 child->ptrace |= PT_DTRACE; 167 set_singlestepping(child, 1);
188 child->thread.singlestep_syscall = 0;
189 child->exit_code = data; 168 child->exit_code = data;
190 /* give it a chance to run. */ 169 /* give it a chance to run. */
191 wake_up_process(child); 170 wake_up_process(child);