Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

[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>

authored by

Bodo Stroesser and committed by
Linus Torvalds
82c1c11b 16c11163

+153 -50
+29 -50
arch/um/kernel/ptrace.c
··· 19 19 #include "skas_ptrace.h" 20 20 #include "sysdep/ptrace.h" 21 21 22 + static 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 36 * Called by kernel/ptrace.c when detaching.. 24 37 */ 25 38 void ptrace_disable(struct task_struct *child) 26 39 { 27 - child->ptrace &= ~PT_DTRACE; 28 - child->thread.singlestep_syscall = 0; 40 + set_singlestepping(child,0); 29 41 } 42 + 43 + extern int peek_user(struct task_struct * child, long addr, long data); 44 + extern int poke_user(struct task_struct * child, long addr, long data); 30 45 31 46 long sys_ptrace(long request, long pid, long addr, long data) 32 47 { ··· 82 67 goto out_tsk; 83 68 } 84 69 70 + #ifdef SUBACH_PTRACE_SPECIAL 71 + SUBARCH_PTRACE_SPECIAL(child,request,addr,data) 72 + #endif 73 + 85 74 ret = ptrace_check_attach(child, request == PTRACE_KILL); 86 75 if (ret < 0) 87 76 goto out_tsk; ··· 106 87 } 107 88 108 89 /* read the word at location addr in the USER area. */ 109 - case PTRACE_PEEKUSR: { 110 - unsigned long tmp; 111 - 112 - ret = -EIO; 113 - if ((addr & 3) || addr < 0) 114 - break; 115 - 116 - tmp = 0; /* Default return condition */ 117 - if(addr < MAX_REG_OFFSET){ 118 - tmp = getreg(child, addr); 119 - } 120 - #if defined(CONFIG_UML_X86) && !defined(CONFIG_64BIT) 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 - ret = put_user(tmp, (unsigned long __user *) data); 129 - break; 130 - } 90 + case PTRACE_PEEKUSR: 91 + ret = peek_user(child, addr, data); 92 + break; 131 93 132 94 /* when I and D space are separate, this will have to be fixed. */ 133 95 case PTRACE_POKETEXT: /* write the word at location addr. */ ··· 121 121 break; 122 122 123 123 case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ 124 - ret = -EIO; 125 - if ((addr & 3) || addr < 0) 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; 124 + ret = poke_user(child, addr, data); 125 + break; 144 126 145 127 case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ 146 128 case PTRACE_CONT: { /* restart after signal. */ ··· 130 148 if (!valid_signal(data)) 131 149 break; 132 150 133 - child->ptrace &= ~PT_DTRACE; 134 - child->thread.singlestep_syscall = 0; 151 + set_singlestepping(child, 0); 135 152 if (request == PTRACE_SYSCALL) { 136 153 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 137 154 } ··· 153 172 if (child->exit_state == EXIT_ZOMBIE) /* already dead */ 154 173 break; 155 174 156 - child->ptrace &= ~PT_DTRACE; 157 - child->thread.singlestep_syscall = 0; 175 + set_singlestepping(child, 0); 158 176 child->exit_code = SIGKILL; 159 177 wake_up_process(child); 160 178 break; ··· 164 184 if (!valid_signal(data)) 165 185 break; 166 186 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 167 - child->ptrace |= PT_DTRACE; 168 - child->thread.singlestep_syscall = 0; 187 + set_singlestepping(child, 1); 169 188 child->exit_code = data; 170 189 /* give it a chance to run. */ 171 190 wake_up_process(child);
+40
arch/um/sys-i386/ptrace.c
··· 73 73 return 0; 74 74 } 75 75 76 + int 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 + 76 95 unsigned long getreg(struct task_struct *child, int regno) 77 96 { 78 97 unsigned long retval = ~0UL; ··· 110 91 retval &= PT_REG(&child->thread.regs, regno); 111 92 } 112 93 return retval; 94 + } 95 + 96 + int peek_user(struct task_struct *child, long addr, long data) 97 + { 98 + /* read the word at location addr in the USER area. */ 99 + unsigned long tmp; 100 + 101 + if ((addr & 3) || addr < 0) 102 + return -EIO; 103 + 104 + tmp = 0; /* Default return condition */ 105 + if(addr < MAX_REG_OFFSET){ 106 + tmp = getreg(child, addr); 107 + } 108 + else if((addr >= offsetof(struct user, u_debugreg[0])) && 109 + (addr <= offsetof(struct user, u_debugreg[7]))){ 110 + addr -= offsetof(struct user, u_debugreg[0]); 111 + addr = addr >> 2; 112 + tmp = child->thread.arch.debugregs[addr]; 113 + } 114 + return put_user(tmp, (unsigned long *) data); 113 115 } 114 116 115 117 struct i387_fxsave_struct {
+40
arch/um/sys-ppc/ptrace.c
··· 8 8 return 0; 9 9 } 10 10 11 + int 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 + 11 30 unsigned long getreg(struct task_struct *child, unsigned long regno) 12 31 { 13 32 unsigned long retval = ~0UL; 14 33 15 34 retval &= child->thread.process_regs.regs[regno >> 2]; 16 35 return retval; 36 + } 37 + 38 + int 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); 17 57 } 18 58 19 59 /*
+44
arch/um/sys-x86_64/ptrace.c
··· 62 62 return 0; 63 63 } 64 64 65 + int 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 + 65 86 unsigned long getreg(struct task_struct *child, int regno) 66 87 { 67 88 unsigned long retval = ~0UL; ··· 103 82 #endif 104 83 } 105 84 return retval; 85 + } 86 + 87 + int peek_user(struct task_struct *child, long addr, long data) 88 + { 89 + /* read the word at location addr in the USER area. */ 90 + unsigned long tmp; 91 + 92 + if ((addr & 3) || addr < 0) 93 + return -EIO; 94 + 95 + tmp = 0; /* Default return condition */ 96 + if(addr < MAX_REG_OFFSET){ 97 + tmp = getreg(child, addr); 98 + } 99 + #if 0 /* Need x86_64 debugregs handling */ 100 + else if((addr >= offsetof(struct user, u_debugreg[0])) && 101 + (addr <= offsetof(struct user, u_debugreg[7]))){ 102 + addr -= offsetof(struct user, u_debugreg[0]); 103 + addr = addr >> 2; 104 + tmp = child->thread.arch.debugregs[addr]; 105 + } 106 + #endif 107 + return put_user(tmp, (unsigned long *) data); 106 108 } 107 109 108 110 void arch_switch(void)