1/* 2 * arch/s390/kernel/ptrace.c 3 * 4 * S390 version 5 * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation 6 * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), 7 * 8 * Based on PowerPC version 9 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) 10 * 11 * Derived from "arch/m68k/kernel/ptrace.c" 12 * Copyright (C) 1994 by Hamish Macdonald 13 * Taken from linux/kernel/ptrace.c and modified for M680x0. 14 * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds 15 * 16 * Modified by Cort Dougan (cort@cs.nmt.edu) 17 * 18 * 19 * This file is subject to the terms and conditions of the GNU General 20 * Public License. See the file README.legal in the main directory of 21 * this archive for more details. 22 */ 23 24#include <stddef.h> 25#include <linux/kernel.h> 26#include <linux/sched.h> 27#include <linux/mm.h> 28#include <linux/smp.h> 29#include <linux/smp_lock.h> 30#include <linux/errno.h> 31#include <linux/ptrace.h> 32#include <linux/user.h> 33 34#include <asm/segment.h> 35#include <asm/page.h> 36#include <asm/pgtable.h> 37#include <asm/pgalloc.h> 38#include <asm/system.h> 39#include <asm/uaccess.h> 40 41 42void FixPerRegisters(struct task_struct *task) 43{ 44 struct pt_regs *regs = __KSTK_PTREGS(task); 45 per_struct *per_info= 46 (per_struct *)&task->thread.per_info; 47 48 per_info->control_regs.bits.em_instruction_fetch= 49 per_info->single_step|per_info->instruction_fetch; 50 51 if(per_info->single_step) 52 { 53 per_info->control_regs.bits.starting_addr=0; 54 per_info->control_regs.bits.ending_addr=0x7fffffffUL; 55 } 56 else 57 { 58 per_info->control_regs.bits.starting_addr= 59 per_info->starting_addr; 60 per_info->control_regs.bits.ending_addr= 61 per_info->ending_addr; 62 } 63 /* if any of the control reg tracing bits are on 64 we switch on per in the psw */ 65 if(per_info->control_regs.words.cr[0]&PER_EM_MASK) 66 regs->psw.mask |=PSW_PER_MASK; 67 else 68 regs->psw.mask &= ~PSW_PER_MASK; 69 if (per_info->control_regs.bits.em_storage_alteration) 70 { 71 per_info->control_regs.bits.storage_alt_space_ctl=1; 72 //((pgd_t *)__pa(task->mm->pgd))->pgd |= USER_STD_MASK; 73 } 74 else 75 { 76 per_info->control_regs.bits.storage_alt_space_ctl=0; 77 //((pgd_t *)__pa(task->mm->pgd))->pgd &= ~USER_STD_MASK; 78 } 79} 80 81void set_single_step(struct task_struct *task) 82{ 83 per_struct *per_info= 84 (per_struct *)&task->thread.per_info; 85 86 per_info->single_step=1; /* Single step */ 87 FixPerRegisters(task); 88} 89 90void clear_single_step(struct task_struct *task) 91{ 92 per_struct *per_info= 93 (per_struct *)&task->thread.per_info; 94 95 per_info->single_step=0; 96 FixPerRegisters(task); 97} 98 99int ptrace_usercopy(addr_t realuseraddr,addr_t copyaddr,int len,int tofromuser,int writeuser,u32 mask) 100{ 101 u32 tempuser; 102 int retval=0; 103 104 if(writeuser&&realuseraddr==(addr_t)NULL) 105 return(0); 106 if(mask!=0xffffffff) 107 { 108 tempuser=*((u32 *)realuseraddr); 109 if(!writeuser) 110 { 111 tempuser&=mask; 112 realuseraddr=(addr_t)&tempuser; 113 } 114 } 115 if(tofromuser) 116 { 117 if(writeuser) 118 { 119 retval=copy_from_user((void *)realuseraddr,(void *)copyaddr,len); 120 } 121 else 122 { 123 if(realuseraddr==(addr_t)NULL) 124 retval=clear_user((void *)copyaddr,len); 125 else 126 retval=copy_to_user((void *)copyaddr,(void *)realuseraddr,len); 127 } 128 retval = retval ? -EFAULT : 0; 129 } 130 else 131 { 132 if(writeuser) 133 memcpy((void *)realuseraddr,(void *)copyaddr,len); 134 else 135 memcpy((void *)copyaddr,(void *)realuseraddr,len); 136 } 137 if(mask!=0xffffffff&&writeuser) 138 (*((u32 *)realuseraddr))=(((*((u32 *)realuseraddr))&mask)|(tempuser&~mask)); 139 return(retval); 140} 141 142int copy_user(struct task_struct *task,saddr_t useraddr,addr_t copyaddr,int len,int tofromuser,int writingtouser) 143{ 144 int copylen=0,copymax; 145 addr_t realuseraddr; 146 saddr_t enduseraddr=useraddr+len; 147 148 u32 mask; 149 150 if (useraddr < 0 || enduseraddr > sizeof(struct user)|| 151 (useraddr < PT_ENDREGS && (useraddr&3))|| 152 (enduseraddr < PT_ENDREGS && (enduseraddr&3))) 153 return (-EIO); 154 while(len>0) 155 { 156 mask=0xffffffff; 157 if(useraddr<PT_FPC) 158 { 159 realuseraddr=((addr_t) __KSTK_PTREGS(task)) + useraddr; 160 if(useraddr<PT_PSWMASK) 161 { 162 copymax=PT_PSWMASK; 163 } 164 else if(useraddr<(PT_PSWMASK+4)) 165 { 166 copymax=(PT_PSWMASK+4); 167 if(writingtouser) 168 mask=PSW_MASK_DEBUGCHANGE; 169 } 170 else if(useraddr<(PT_PSWADDR+4)) 171 { 172 copymax=PT_PSWADDR+4; 173 mask=PSW_ADDR_DEBUGCHANGE; 174 } 175 else 176 copymax=PT_FPC; 177 178 } 179 else if(useraddr<(PT_FPR15_LO+4)) 180 { 181 copymax=(PT_FPR15_LO+4); 182 realuseraddr=(addr_t)&(((u8 *)&task->thread.fp_regs)[useraddr-PT_FPC]); 183 } 184 else if(useraddr<sizeof(struct user_regs_struct)) 185 { 186 copymax=sizeof(struct user_regs_struct); 187 realuseraddr=(addr_t)&(((u8 *)&task->thread.per_info)[useraddr-PT_CR_9]); 188 } 189 else 190 { 191 copymax=sizeof(struct user); 192 realuseraddr=(addr_t)NULL; 193 } 194 copylen=copymax-useraddr; 195 copylen=(copylen>len ? len:copylen); 196 if(ptrace_usercopy(realuseraddr,copyaddr,copylen,tofromuser,writingtouser,mask)) 197 return (-EIO); 198 copyaddr+=copylen; 199 len-=copylen; 200 useraddr+=copylen; 201 } 202 FixPerRegisters(task); 203 return(0); 204} 205 206/* 207 * Called by kernel/ptrace.c when detaching.. 208 * 209 * Make sure single step bits etc are not set. 210 */ 211void ptrace_disable(struct task_struct *child) 212{ 213 /* make sure the single step bit is not set. */ 214 clear_single_step(child); 215} 216 217asmlinkage int sys_ptrace(long request, long pid, long addr, long data) 218{ 219 struct task_struct *child; 220 int ret = -EPERM; 221 unsigned long tmp; 222 int copied; 223 ptrace_area parea; 224 225 lock_kernel(); 226 if (request == PTRACE_TRACEME) 227 { 228 /* are we already being traced? */ 229 if (current->ptrace & PT_PTRACED) 230 goto out; 231 /* set the ptrace bit in the process flags. */ 232 current->ptrace |= PT_PTRACED; 233 ret = 0; 234 goto out; 235 } 236 ret = -ESRCH; 237 read_lock(&tasklist_lock); 238 child = find_task_by_pid(pid); 239 if (child) 240 get_task_struct(child); 241 read_unlock(&tasklist_lock); 242 if (!child) 243 goto out; 244 ret = -EPERM; 245 if (pid == 1) /* you may not mess with init */ 246 goto out_tsk; 247 if (request == PTRACE_ATTACH) 248 { 249 ret = ptrace_attach(child); 250 goto out_tsk; 251 } 252 ret = -ESRCH; 253 // printk("child=%lX child->flags=%lX",child,child->flags); 254 /* I added child!=current line so we can get the */ 255 /* ieee_instruction_pointer from the user structure DJB */ 256 if(child!=current) 257 { 258 if (!(child->ptrace & PT_PTRACED)) 259 goto out_tsk; 260 if (child->state != TASK_STOPPED) 261 { 262 if (request != PTRACE_KILL) 263 goto out_tsk; 264 } 265 if (child->p_pptr != current) 266 goto out_tsk; 267 } 268 switch (request) 269 { 270 /* If I and D space are separate, these will need to be fixed. */ 271 case PTRACE_PEEKTEXT: /* read word at location addr. */ 272 case PTRACE_PEEKDATA: 273 copied = access_process_vm(child,ADDR_BITS_REMOVE(addr), &tmp, sizeof(tmp), 0); 274 ret = -EIO; 275 if (copied != sizeof(tmp)) 276 break; 277 ret = put_user(tmp,(unsigned long *) data); 278 break; 279 280 /* read the word at location addr in the USER area. */ 281 case PTRACE_PEEKUSR: 282 ret=copy_user(child,addr,data,sizeof(unsigned long),1,0); 283 break; 284 285 /* If I and D space are separate, this will have to be fixed. */ 286 case PTRACE_POKETEXT: /* write the word at location addr. */ 287 case PTRACE_POKEDATA: 288 ret = 0; 289 if (access_process_vm(child,ADDR_BITS_REMOVE(addr), &data, sizeof(data), 1) == sizeof(data)) 290 break; 291 ret = -EIO; 292 break; 293 294 case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ 295 ret=copy_user(child,addr,(addr_t)&data,sizeof(unsigned long),0,1); 296 break; 297 298 case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ 299 case PTRACE_CONT: /* restart after signal. */ 300 ret = -EIO; 301 if ((unsigned long) data >= _NSIG) 302 break; 303 if (request == PTRACE_SYSCALL) 304 child->ptrace |= PT_TRACESYS; 305 else 306 child->ptrace &= ~PT_TRACESYS; 307 child->exit_code = data; 308 /* make sure the single step bit is not set. */ 309 clear_single_step(child); 310 wake_up_process(child); 311 ret = 0; 312 break; 313 314/* 315 * make the child exit. Best I can do is send it a sigkill. 316 * perhaps it should be put in the status that it wants to 317 * exit. 318 */ 319 case PTRACE_KILL: 320 ret = 0; 321 if (child->state == TASK_ZOMBIE) /* already dead */ 322 break; 323 child->exit_code = SIGKILL; 324 clear_single_step(child); 325 wake_up_process(child); 326 /* make sure the single step bit is not set. */ 327 break; 328 329 case PTRACE_SINGLESTEP: /* set the trap flag. */ 330 ret = -EIO; 331 if ((unsigned long) data >= _NSIG) 332 break; 333 child->ptrace &= ~PT_TRACESYS; 334 child->exit_code = data; 335 set_single_step(child); 336 /* give it a chance to run. */ 337 wake_up_process(child); 338 ret = 0; 339 break; 340 341 case PTRACE_DETACH: /* detach a process that was attached. */ 342 ret = ptrace_detach(child, data); 343 break; 344 case PTRACE_PEEKUSR_AREA: 345 case PTRACE_POKEUSR_AREA: 346 if(copy_from_user(&parea,(void *)addr,sizeof(parea))==0) 347 ret=copy_user(child,parea.kernel_addr,parea.process_addr, 348 parea.len,1,(request==PTRACE_POKEUSR_AREA)); 349 else ret = -EFAULT; 350 break; 351 default: 352 ret = -EIO; 353 break; 354 } 355 out_tsk: 356 free_task_struct(child); 357 out: 358 unlock_kernel(); 359 return ret; 360} 361 362asmlinkage void syscall_trace(void) 363{ 364 lock_kernel(); 365 if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) 366 != (PT_PTRACED|PT_TRACESYS)) 367 goto out; 368 current->exit_code = SIGTRAP; 369 set_current_state(TASK_STOPPED); 370 notify_parent(current, SIGCHLD); 371 schedule(); 372 /* 373 * this isn't the same as continuing with a signal, but it will do 374 * for normal use. strace only continues with a signal if the 375 * stopping signal is not SIGTRAP. -brl 376 */ 377 if (current->exit_code) { 378 send_sig(current->exit_code, current, 1); 379 current->exit_code = 0; 380 } 381 out: 382 unlock_kernel(); 383} 384