aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
authorBodo Stroesser <bstroesser@fujitsu-siemens.com>2005-05-07 00:30:46 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-05-07 01:09:29 -0400
commit82c1c11bdd92d94f8fd620a3ea6c894eba37d4ed (patch)
treebc2ac7e025e250678261695a19e171f2991746c6 /arch/um
parent16c11163019879c0e1e69d3ec7d4574a80e9c77e (diff)
[PATCH] uml: S390 preparation, peekusr/pokeusr defined by subarch
s390 needs to change some parts of arch/um/kernel/ptrace.c. Thus, the code regarding PEEKUSER and POKEUSER are shifted to arch/um/sys-<subarch>/ptrace.c. Also s390 debug registers need to be updated, when singlestepping is switched on / off. Thus, setting/resetting of singlestepping is centralized in the new function set_singlestep(), which also inserts the macro SUBARCH_SET_SINGLESTEP(mode), if defined. Finally, s390 has the "ieee_instruction_pointer" in its registers, which also is allowed to be read via ptrace( PTRACE_PEEKUSER, getpid(), PT_IEEE_IP, 0); To implement this feature, sys_ptrace inserts the macro SUBARCH_PTRACE_SPECIAL, if defined. Signed-off-by: Bodo Stroesser <bstroesser@fujitsu-siemens.com> Signed-off-by: Jeff Dike <jdike@addtoit.com> Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/kernel/ptrace.c79
-rw-r--r--arch/um/sys-i386/ptrace.c40
-rw-r--r--arch/um/sys-ppc/ptrace.c40
-rw-r--r--arch/um/sys-x86_64/ptrace.c44
4 files changed, 153 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);
diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c
index e470d28cdf84..e839ce65ad28 100644
--- a/arch/um/sys-i386/ptrace.c
+++ b/arch/um/sys-i386/ptrace.c
@@ -73,6 +73,25 @@ int putreg(struct task_struct *child, int regno, unsigned long value)
73 return 0; 73 return 0;
74} 74}
75 75
76int poke_user(struct task_struct *child, long addr, long data)
77{
78 if ((addr & 3) || addr < 0)
79 return -EIO;
80
81 if (addr < MAX_REG_OFFSET)
82 return putreg(child, addr, data);
83
84 else if((addr >= offsetof(struct user, u_debugreg[0])) &&
85 (addr <= offsetof(struct user, u_debugreg[7]))){
86 addr -= offsetof(struct user, u_debugreg[0]);
87 addr = addr >> 2;
88 if((addr == 4) || (addr == 5)) return -EIO;
89 child->thread.arch.debugregs[addr] = data;
90 return 0;
91 }
92 return -EIO;
93}
94
76unsigned long getreg(struct task_struct *child, int regno) 95unsigned long getreg(struct task_struct *child, int regno)
77{ 96{
78 unsigned long retval = ~0UL; 97 unsigned long retval = ~0UL;
@@ -93,6 +112,27 @@ unsigned long getreg(struct task_struct *child, int regno)
93 return retval; 112 return retval;
94} 113}
95 114
115int peek_user(struct task_struct *child, long addr, long data)
116{
117/* read the word at location addr in the USER area. */
118 unsigned long tmp;
119
120 if ((addr & 3) || addr < 0)
121 return -EIO;
122
123 tmp = 0; /* Default return condition */
124 if(addr < MAX_REG_OFFSET){
125 tmp = getreg(child, addr);
126 }
127 else if((addr >= offsetof(struct user, u_debugreg[0])) &&
128 (addr <= offsetof(struct user, u_debugreg[7]))){
129 addr -= offsetof(struct user, u_debugreg[0]);
130 addr = addr >> 2;
131 tmp = child->thread.arch.debugregs[addr];
132 }
133 return put_user(tmp, (unsigned long *) data);
134}
135
96struct i387_fxsave_struct { 136struct i387_fxsave_struct {
97 unsigned short cwd; 137 unsigned short cwd;
98 unsigned short swd; 138 unsigned short swd;
diff --git a/arch/um/sys-ppc/ptrace.c b/arch/um/sys-ppc/ptrace.c
index a971366d3277..8e71b47f2b8e 100644
--- a/arch/um/sys-ppc/ptrace.c
+++ b/arch/um/sys-ppc/ptrace.c
@@ -8,6 +8,25 @@ int putreg(struct task_struct *child, unsigned long regno,
8 return 0; 8 return 0;
9} 9}
10 10
11int poke_user(struct task_struct *child, long addr, long data)
12{
13 if ((addr & 3) || addr < 0)
14 return -EIO;
15
16 if (addr < MAX_REG_OFFSET)
17 return putreg(child, addr, data);
18
19 else if((addr >= offsetof(struct user, u_debugreg[0])) &&
20 (addr <= offsetof(struct user, u_debugreg[7]))){
21 addr -= offsetof(struct user, u_debugreg[0]);
22 addr = addr >> 2;
23 if((addr == 4) || (addr == 5)) return -EIO;
24 child->thread.arch.debugregs[addr] = data;
25 return 0;
26 }
27 return -EIO;
28}
29
11unsigned long getreg(struct task_struct *child, unsigned long regno) 30unsigned long getreg(struct task_struct *child, unsigned long regno)
12{ 31{
13 unsigned long retval = ~0UL; 32 unsigned long retval = ~0UL;
@@ -16,6 +35,27 @@ unsigned long getreg(struct task_struct *child, unsigned long regno)
16 return retval; 35 return retval;
17} 36}
18 37
38int peek_user(struct task_struct *child, long addr, long data)
39{
40 /* read the word at location addr in the USER area. */
41 unsigned long tmp;
42
43 if ((addr & 3) || addr < 0)
44 return -EIO;
45
46 tmp = 0; /* Default return condition */
47 if(addr < MAX_REG_OFFSET){
48 tmp = getreg(child, addr);
49 }
50 else if((addr >= offsetof(struct user, u_debugreg[0])) &&
51 (addr <= offsetof(struct user, u_debugreg[7]))){
52 addr -= offsetof(struct user, u_debugreg[0]);
53 addr = addr >> 2;
54 tmp = child->thread.arch.debugregs[addr];
55 }
56 return put_user(tmp, (unsigned long *) data);
57}
58
19/* 59/*
20 * Overrides for Emacs so that we follow Linus's tabbing style. 60 * Overrides for Emacs so that we follow Linus's tabbing style.
21 * Emacs will notice this stuff at the end of the file and automatically 61 * Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c
index 8c146b2a1e00..b593bb256f2c 100644
--- a/arch/um/sys-x86_64/ptrace.c
+++ b/arch/um/sys-x86_64/ptrace.c
@@ -62,6 +62,27 @@ int putreg(struct task_struct *child, int regno, unsigned long value)
62 return 0; 62 return 0;
63} 63}
64 64
65int poke_user(struct task_struct *child, long addr, long data)
66{
67 if ((addr & 3) || addr < 0)
68 return -EIO;
69
70 if (addr < MAX_REG_OFFSET)
71 return putreg(child, addr, data);
72
73#if 0 /* Need x86_64 debugregs handling */
74 else if((addr >= offsetof(struct user, u_debugreg[0])) &&
75 (addr <= offsetof(struct user, u_debugreg[7]))){
76 addr -= offsetof(struct user, u_debugreg[0]);
77 addr = addr >> 2;
78 if((addr == 4) || (addr == 5)) return -EIO;
79 child->thread.arch.debugregs[addr] = data;
80 return 0;
81 }
82#endif
83 return -EIO;
84}
85
65unsigned long getreg(struct task_struct *child, int regno) 86unsigned long getreg(struct task_struct *child, int regno)
66{ 87{
67 unsigned long retval = ~0UL; 88 unsigned long retval = ~0UL;
@@ -84,6 +105,29 @@ unsigned long getreg(struct task_struct *child, int regno)
84 return retval; 105 return retval;
85} 106}
86 107
108int peek_user(struct task_struct *child, long addr, long data)
109{
110 /* read the word at location addr in the USER area. */
111 unsigned long tmp;
112
113 if ((addr & 3) || addr < 0)
114 return -EIO;
115
116 tmp = 0; /* Default return condition */
117 if(addr < MAX_REG_OFFSET){
118 tmp = getreg(child, addr);
119 }
120#if 0 /* Need x86_64 debugregs handling */
121 else if((addr >= offsetof(struct user, u_debugreg[0])) &&
122 (addr <= offsetof(struct user, u_debugreg[7]))){
123 addr -= offsetof(struct user, u_debugreg[0]);
124 addr = addr >> 2;
125 tmp = child->thread.arch.debugregs[addr];
126 }
127#endif
128 return put_user(tmp, (unsigned long *) data);
129}
130
87void arch_switch(void) 131void arch_switch(void)
88{ 132{
89/* XXX 133/* XXX