1/* 2 * Kernel support for the ptrace() and syscall tracing interfaces. 3 * 4 * Copyright (C) 2000 Hewlett-Packard Co, Linuxcare Inc. 5 * Copyright (C) 2000 Matthew Wilcox <matthew@wil.cx> 6 * Copyright (C) 2000 David Huggins-Daines <dhd@debian.org> 7 */ 8 9#include <linux/kernel.h> 10#include <linux/sched.h> 11#include <linux/mm.h> 12#include <linux/smp.h> 13#include <linux/smp_lock.h> 14#include <linux/errno.h> 15#include <linux/ptrace.h> 16#include <linux/user.h> 17#include <linux/personality.h> 18 19#include <asm/uaccess.h> 20#include <asm/pgtable.h> 21#include <asm/system.h> 22#include <asm/processor.h> 23#include <asm/offset.h> 24 25/* These are used in entry.S, syscall_restore_rfi. We need to record the 26 * current stepping mode somewhere other than in PSW, because there is no 27 * concept of saving and restoring the users PSW over a syscall. We choose 28 * to use these two bits in task->ptrace. These bits must not clash with 29 * any PT_* defined in include/linux/sched.h, and must match with the bit 30 * tests in entry.S 31 */ 32#define PT_SINGLESTEP 0x10000 33#define PT_BLOCKSTEP 0x20000 34 35/* PSW bits we allow the debugger to modify */ 36#define USER_PSW_BITS (PSW_N | PSW_V | PSW_CB) 37 38#undef DEBUG_PTRACE 39 40#ifdef DEBUG_PTRACE 41#define DBG(x) printk x 42#else 43#define DBG(x) 44#endif 45 46#ifdef __LP64__ 47 48#define CHILD_IS_32BIT (child->personality == PER_LINUX_32BIT) 49 50/* This function is needed to translate 32 bit pt_regs offsets in to 51 * 64 bit pt_regs offsets. For example, a 32 bit gdb under a 64 bit kernel 52 * will request offset 12 if it wants gr3, but the lower 32 bits of 53 * the 64 bit kernels view of gr3 will be at offset 28 (3*8 + 4). 54 * This code relies on a 32 bit pt_regs being comprised of 32 bit values 55 * except for the fp registers which (a) are 64 bits, and (b) follow 56 * the gr registers at the start of pt_regs. The 32 bit pt_regs should 57 * be half the size of the 64 bit pt_regs, plus 32*4 to allow for fr[] 58 * being 64 bit in both cases. 59 */ 60 61static long translate_usr_offset(long offset) 62{ 63 if (offset < 0) 64 return -1; 65 else if (offset <= 32*4) /* gr[0..31] */ 66 return offset * 2 + 4; 67 else if (offset <= 32*4+32*8) /* gr[0..31] + fr[0..31] */ 68 return offset + 32*4; 69 else if (offset < sizeof(struct pt_regs)/2 + 32*4) 70 return offset * 2 + 4 - 32*8; 71 else 72 return -1; 73} 74#endif 75 76/* 77 * Called by kernel/ptrace.c when detaching.. 78 * 79 * Make sure single step bits etc are not set. 80 */ 81void ptrace_disable(struct task_struct *child) 82{ 83 /* make sure the trap bits are not set */ 84 pa_psw(child)->r = 0; 85 pa_psw(child)->t = 0; 86 pa_psw(child)->h = 0; 87 pa_psw(child)->l = 0; 88} 89 90long sys_ptrace(long request, pid_t pid, long addr, long data) 91{ 92 struct task_struct *child; 93 long ret; 94#ifdef DEBUG_PTRACE 95 long oaddr=addr, odata=data; 96#endif 97 98 lock_kernel(); 99 ret = -EPERM; 100 if (request == PTRACE_TRACEME) { 101 /* are we already being traced? */ 102 if (current->ptrace & PT_PTRACED) 103 goto out; 104 /* set the ptrace bit in the process flags. */ 105 current->ptrace |= PT_PTRACED; 106 ret = 0; 107 goto out; 108 } 109 110 ret = -ESRCH; 111 read_lock(&tasklist_lock); 112 child = find_task_by_pid(pid); 113 if (child) 114 get_task_struct(child); 115 read_unlock(&tasklist_lock); 116 if (!child) 117 goto out; 118 ret = -EPERM; 119 if (pid == 1) /* no messing around with init! */ 120 goto out_tsk; 121 122 if (request == PTRACE_ATTACH) { 123 ret = ptrace_attach(child); 124 goto out_tsk; 125 } 126 ret = -ESRCH; 127 if (!(child->ptrace & PT_PTRACED)) 128 goto out_tsk; 129 if (child->state != TASK_STOPPED) { 130 if (request != PTRACE_KILL) 131 goto out_tsk; 132 } 133 if (child->p_pptr != current) 134 goto out_tsk; 135 136 switch (request) { 137 case PTRACE_PEEKTEXT: /* read word at location addr. */ 138 case PTRACE_PEEKDATA: { 139 int copied; 140 141#ifdef __LP64__ 142 if (CHILD_IS_32BIT) { 143 unsigned int tmp; 144 145 addr &= 0xffffffffL; 146 copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); 147 ret = -EIO; 148 if (copied != sizeof(tmp)) 149 goto out_tsk; 150 ret = put_user(tmp,(unsigned int *) data); 151 DBG(("sys_ptrace(PEEK%s, %d, %lx, %lx) returning %ld, data %x\n", 152 request == PTRACE_PEEKTEXT ? "TEXT" : "DATA", 153 pid, oaddr, odata, ret, tmp)); 154 } 155 else 156#endif 157 { 158 unsigned long tmp; 159 160 copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); 161 ret = -EIO; 162 if (copied != sizeof(tmp)) 163 goto out_tsk; 164 ret = put_user(tmp,(unsigned long *) data); 165 } 166 goto out_tsk; 167 } 168 169 /* when I and D space are separate, this will have to be fixed. */ 170 case PTRACE_POKETEXT: /* write the word at location addr. */ 171 case PTRACE_POKEDATA: 172 ret = 0; 173#ifdef __LP64__ 174 if (CHILD_IS_32BIT) { 175 unsigned int tmp = (unsigned int)data; 176 DBG(("sys_ptrace(POKE%s, %d, %lx, %lx)\n", 177 request == PTRACE_POKETEXT ? "TEXT" : "DATA", 178 pid, oaddr, odata)); 179 addr &= 0xffffffffL; 180 if (access_process_vm(child, addr, &tmp, sizeof(tmp), 1) == sizeof(tmp)) 181 goto out_tsk; 182 } 183 else 184#endif 185 { 186 if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) 187 goto out_tsk; 188 } 189 ret = -EIO; 190 goto out_tsk; 191 192 /* Read the word at location addr in the USER area. For ptraced 193 processes, the kernel saves all regs on a syscall. */ 194 case PTRACE_PEEKUSR: { 195 ret = -EIO; 196#ifdef __LP64__ 197 if (CHILD_IS_32BIT) { 198 unsigned int tmp; 199 200 if (addr & (sizeof(int)-1)) 201 goto out_tsk; 202 if ((addr = translate_usr_offset(addr)) < 0) 203 goto out_tsk; 204 205 tmp = *(unsigned int *) ((char *) task_regs(child) + addr); 206 ret = put_user(tmp, (unsigned int *) data); 207 DBG(("sys_ptrace(PEEKUSR, %d, %lx, %lx) returning %ld, addr %lx, data %x\n", 208 pid, oaddr, odata, ret, addr, tmp)); 209 } 210 else 211#endif 212 { 213 unsigned long tmp; 214 215 if ((addr & (sizeof(long)-1)) || (unsigned long) addr >= sizeof(struct pt_regs)) 216 goto out_tsk; 217 tmp = *(unsigned long *) ((char *) task_regs(child) + addr); 218 ret = put_user(tmp, (unsigned long *) data); 219 } 220 goto out_tsk; 221 } 222 223 case PTRACE_POKEUSR: 224 ret = -EIO; 225 /* Some register values written here may be ignored in 226 * entry.S:syscall_restore_rfi; e.g. iaoq is written with 227 * r31/r31+4, and not with the values in pt_regs. 228 */ 229 /* PT_PSW=0, so this is valid for 32 bit processes under 64 230 * bit kernels. 231 */ 232 if (addr == PT_PSW) { 233 /* PT_PSW=0, so this is valid for 32 bit processes 234 * under 64 bit kernels. 235 * 236 * Allow writing to Nullify, Divide-step-correction, 237 * and carry/borrow bits. 238 * BEWARE, if you set N, and then single step, it wont 239 * stop on the nullified instruction. 240 */ 241 DBG(("sys_ptrace(POKEUSR, %d, %lx, %lx)\n", 242 pid, oaddr, odata)); 243 data &= USER_PSW_BITS; 244 task_regs(child)->gr[0] &= ~USER_PSW_BITS; 245 task_regs(child)->gr[0] |= data; 246 ret = 0; 247 goto out_tsk; 248 } 249#ifdef __LP64__ 250 if (CHILD_IS_32BIT) { 251 if (addr & (sizeof(int)-1)) 252 goto out_tsk; 253 if ((addr = translate_usr_offset(addr)) < 0) 254 goto out_tsk; 255 DBG(("sys_ptrace(POKEUSR, %d, %lx, %lx) addr %lx\n", 256 pid, oaddr, odata, addr)); 257 if (addr >= PT_FR0 && addr <= PT_FR31) { 258 /* Special case, fp regs are 64 bits anyway */ 259 *(unsigned int *) ((char *) task_regs(child) + addr) = data; 260 ret = 0; 261 } 262 else if ((addr >= PT_GR1+4 && addr <= PT_GR31+4) || 263 addr == PT_IAOQ0+4 || addr == PT_IAOQ1+4 || 264 addr == PT_SAR+4) { 265 /* Zero the top 32 bits */ 266 *(unsigned int *) ((char *) task_regs(child) + addr - 4) = 0; 267 *(unsigned int *) ((char *) task_regs(child) + addr) = data; 268 ret = 0; 269 } 270 goto out_tsk; 271 } 272 else 273#endif 274 { 275 if ((addr & (sizeof(long)-1)) || (unsigned long) addr >= sizeof(struct pt_regs)) 276 goto out_tsk; 277 if ((addr >= PT_GR1 && addr <= PT_GR31) || 278 addr == PT_IAOQ0 || addr == PT_IAOQ1 || 279 (addr >= PT_FR0 && addr <= PT_FR31) || 280 addr == PT_SAR) { 281 *(unsigned long *) ((char *) task_regs(child) + addr) = data; 282 ret = 0; 283 } 284 goto out_tsk; 285 } 286 287 case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ 288 case PTRACE_CONT: 289 ret = -EIO; 290 DBG(("sys_ptrace(%s)\n", 291 request == PTRACE_SYSCALL ? "SYSCALL" : "CONT")); 292 if ((unsigned long) data > _NSIG) 293 goto out_tsk; 294 child->ptrace &= ~(PT_SINGLESTEP|PT_BLOCKSTEP); 295 if (request == PTRACE_SYSCALL) 296 child->ptrace |= PT_TRACESYS; 297 else 298 child->ptrace &= ~PT_TRACESYS; 299 child->exit_code = data; 300 goto out_wake_notrap; 301 302 case PTRACE_KILL: 303 /* 304 * make the child exit. Best I can do is send it a 305 * sigkill. perhaps it should be put in the status 306 * that it wants to exit. 307 */ 308 DBG(("sys_ptrace(KILL)\n")); 309 if (child->state == TASK_ZOMBIE) /* already dead */ 310 goto out_tsk; 311 child->exit_code = SIGKILL; 312 goto out_wake_notrap; 313 314 case PTRACE_SINGLEBLOCK: 315 DBG(("sys_ptrace(SINGLEBLOCK)\n")); 316 ret = -EIO; 317 if ((unsigned long) data > _NSIG) 318 goto out_tsk; 319 child->ptrace &= ~(PT_TRACESYS|PT_SINGLESTEP); 320 child->ptrace |= PT_BLOCKSTEP; 321 child->exit_code = data; 322 323 /* Enable taken branch trap. */ 324 pa_psw(child)->r = 0; 325 pa_psw(child)->t = 1; 326 pa_psw(child)->h = 0; 327 pa_psw(child)->l = 0; 328 goto out_wake; 329 330 case PTRACE_SINGLESTEP: 331 DBG(("sys_ptrace(SINGLESTEP)\n")); 332 ret = -EIO; 333 if ((unsigned long) data > _NSIG) 334 goto out_tsk; 335 child->ptrace &= ~(PT_TRACESYS|PT_BLOCKSTEP); 336 child->ptrace |= PT_SINGLESTEP; 337 child->exit_code = data; 338 339 if (pa_psw(child)->n) { 340 struct siginfo si; 341 342 /* Nullified, just crank over the queue. */ 343 task_regs(child)->iaoq[0] = task_regs(child)->iaoq[1]; 344 task_regs(child)->iasq[0] = task_regs(child)->iasq[1]; 345 task_regs(child)->iaoq[1] = task_regs(child)->iaoq[0] + 4; 346 pa_psw(child)->n = 0; 347 pa_psw(child)->x = 0; 348 pa_psw(child)->y = 0; 349 pa_psw(child)->z = 0; 350 pa_psw(child)->b = 0; 351 ptrace_disable(child); 352 /* Don't wake up the child, but let the 353 parent know something happened. */ 354 si.si_code = TRAP_TRACE; 355 si.si_addr = (void *) (task_regs(child)->iaoq[0] & ~3); 356 si.si_signo = SIGTRAP; 357 si.si_errno = 0; 358 force_sig_info(SIGTRAP, &si, child); 359 //notify_parent(child, SIGCHLD); 360 //ret = 0; 361 goto out_wake; 362 } 363 364 /* Enable recovery counter traps. The recovery counter 365 * itself will be set to zero on a task switch. If the 366 * task is suspended on a syscall then the syscall return 367 * path will overwrite the recovery counter with a suitable 368 * value such that it traps once back in user space. We 369 * disable interrupts in the childs PSW here also, to avoid 370 * interrupts while the recovery counter is decrementing. 371 */ 372 pa_psw(child)->r = 1; 373 pa_psw(child)->t = 0; 374 pa_psw(child)->h = 0; 375 pa_psw(child)->l = 0; 376 /* give it a chance to run. */ 377 goto out_wake; 378 379 case PTRACE_DETACH: 380 ret = ptrace_detach(child, data); 381 goto out_tsk; 382 383 default: 384 ret = -EIO; 385 goto out_tsk; 386 } 387 388out_wake_notrap: 389 ptrace_disable(child); 390out_wake: 391 wake_up_process(child); 392 ret = 0; 393out_tsk: 394 free_task_struct(child); 395out: 396 unlock_kernel(); 397 DBG(("sys_ptrace(%ld, %d, %lx, %lx) returning %ld\n", 398 request, pid, oaddr, odata, ret)); 399 return ret; 400} 401 402void syscall_trace(void) 403{ 404 if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) != 405 (PT_PTRACED|PT_TRACESYS)) 406 return; 407 current->exit_code = SIGTRAP; 408 current->state = TASK_STOPPED; 409 notify_parent(current, SIGCHLD); 410 schedule(); 411 /* 412 * this isn't the same as continuing with a signal, but it will do 413 * for normal use. strace only continues with a signal if the 414 * stopping signal is not SIGTRAP. -brl 415 */ 416 if (current->exit_code) { 417 send_sig(current->exit_code, current, 1); 418 current->exit_code = 0; 419 } 420} 421