1 // TODO some minor issues 2 /* 3 * This file is subject to the terms and conditions of the GNU General Public 4 * License. See the file "COPYING" in the main directory of this archive 5 * for more details. 6 * 7 * Copyright (C) 2001 - 2007 Tensilica Inc. 8 * 9 * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com> 10 * Chris Zankel <chris@zankel.net> 11 * Scott Foehner<sfoehner@yahoo.com>, 12 * Kevin Chea 13 * Marc Gauthier<marc@tensilica.com> <marc@alumni.uwaterloo.ca> 14 */ 15 16 #include <linux/kernel.h> 17 #include <linux/sched.h> 18 #include <linux/mm.h> 19 #include <linux/errno.h> 20 #include <linux/ptrace.h> 21 #include <linux/smp.h> 22 #include <linux/security.h> 23 #include <linux/signal.h> 24 25 #include <asm/pgtable.h> 26 #include <asm/page.h> 27 #include <asm/system.h> 28 #include <asm/uaccess.h> 29 #include <asm/ptrace.h> 30 #include <asm/elf.h> 31 #include <asm/coprocessor.h> 32 33 /* 34 * Called by kernel/ptrace.c when detaching to disable single stepping. 35 */ 36 37 void ptrace_disable(struct task_struct *child) 38 { 39 /* Nothing to do.. */ 40 } 41 42 int ptrace_getregs(struct task_struct *child, void __user *uregs) 43 { 44 struct pt_regs *regs = task_pt_regs(child); 45 xtensa_gregset_t __user *gregset = uregs; 46 unsigned long wm = regs->wmask; 47 unsigned long wb = regs->windowbase; 48 int live, i; 49 50 if (!access_ok(VERIFY_WRITE, uregs, sizeof(xtensa_gregset_t))) 51 return -EIO; 52 53 __put_user(regs->pc, &gregset->pc); 54 __put_user(regs->ps & ~(1 << PS_EXCM_BIT), &gregset->ps); 55 __put_user(regs->lbeg, &gregset->lbeg); 56 __put_user(regs->lend, &gregset->lend); 57 __put_user(regs->lcount, &gregset->lcount); 58 __put_user(regs->windowstart, &gregset->windowstart); 59 __put_user(regs->windowbase, &gregset->windowbase); 60 61 live = (wm & 2) ? 4 : (wm & 4) ? 8 : (wm & 8) ? 12 : 16; 62 63 for (i = 0; i < live; i++) 64 __put_user(regs->areg[i],gregset->a+((wb*4+i)%XCHAL_NUM_AREGS)); 65 for (i = XCHAL_NUM_AREGS - (wm >> 4) * 4; i < XCHAL_NUM_AREGS; i++) 66 __put_user(regs->areg[i],gregset->a+((wb*4+i)%XCHAL_NUM_AREGS)); 67 68 return 0; 69 } 70 71 int ptrace_setregs(struct task_struct *child, void __user *uregs) 72 { 73 struct pt_regs *regs = task_pt_regs(child); 74 xtensa_gregset_t *gregset = uregs; 75 const unsigned long ps_mask = PS_CALLINC_MASK | PS_OWB_MASK; 76 unsigned long ps; 77 unsigned long wb; 78 79 if (!access_ok(VERIFY_WRITE, uregs, sizeof(xtensa_gregset_t))) 80 return -EIO; 81 82 __get_user(regs->pc, &gregset->pc); 83 __get_user(ps, &gregset->ps); 84 __get_user(regs->lbeg, &gregset->lbeg); 85 __get_user(regs->lend, &gregset->lend); 86 __get_user(regs->lcount, &gregset->lcount); 87 __get_user(regs->windowstart, &gregset->windowstart); 88 __get_user(wb, &gregset->windowbase); 89 90 regs->ps = (regs->ps & ~ps_mask) | (ps & ps_mask) | (1 << PS_EXCM_BIT); 91 92 if (wb >= XCHAL_NUM_AREGS / 4) 93 return -EFAULT; 94 95 regs->windowbase = wb; 96 97 if (wb != 0 && __copy_from_user(regs->areg + XCHAL_NUM_AREGS - wb * 4, 98 gregset->a, wb * 16)) 99 return -EFAULT; 100 101 if (__copy_from_user(regs->areg, gregset->a + wb*4, (WSBITS-wb) * 16)) 102 return -EFAULT; 103 104 return 0; 105 } 106 107 108 int ptrace_getxregs(struct task_struct *child, void __user *uregs) 109 { 110 struct pt_regs *regs = task_pt_regs(child); 111 struct thread_info *ti = task_thread_info(child); 112 elf_xtregs_t __user *xtregs = uregs; 113 int ret = 0; 114 115 if (!access_ok(VERIFY_WRITE, uregs, sizeof(elf_xtregs_t))) 116 return -EIO; 117 118 #if XTENSA_HAVE_COPROCESSORS 119 /* Flush all coprocessor registers to memory. */ 120 coprocessor_flush_all(ti); 121 ret |= __copy_to_user(&xtregs->cp0, &ti->xtregs_cp, 122 sizeof(xtregs_coprocessor_t)); 123 #endif 124 ret |= __copy_to_user(&xtregs->opt, ®s->xtregs_opt, 125 sizeof(xtregs->opt)); 126 ret |= __copy_to_user(&xtregs->user,&ti->xtregs_user, 127 sizeof(xtregs->user)); 128 129 return ret ? -EFAULT : 0; 130 } 131 132 int ptrace_setxregs(struct task_struct *child, void __user *uregs) 133 { 134 struct thread_info *ti = task_thread_info(child); 135 struct pt_regs *regs = task_pt_regs(child); 136 elf_xtregs_t *xtregs = uregs; 137 int ret = 0; 138 139 #if XTENSA_HAVE_COPROCESSORS 140 /* Flush all coprocessors before we overwrite them. */ 141 coprocessor_flush_all(ti); 142 coprocessor_release_all(ti); 143 144 ret |= __copy_from_user(&ti->xtregs_cp, &xtregs->cp0, 145 sizeof(xtregs_coprocessor_t)); 146 #endif 147 ret |= __copy_from_user(®s->xtregs_opt, &xtregs->opt, 148 sizeof(xtregs->opt)); 149 ret |= __copy_from_user(&ti->xtregs_user, &xtregs->user, 150 sizeof(xtregs->user)); 151 152 return ret ? -EFAULT : 0; 153 } 154 155 int ptrace_peekusr(struct task_struct *child, long regno, long __user *ret) 156 { 157 struct pt_regs *regs; 158 unsigned long tmp; 159 160 regs = task_pt_regs(child); 161 tmp = 0; /* Default return value. */ 162 163 switch(regno) { 164 165 case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1: 166 tmp = regs->areg[regno - REG_AR_BASE]; 167 break; 168 169 case REG_A_BASE ... REG_A_BASE + 15: 170 tmp = regs->areg[regno - REG_A_BASE]; 171 break; 172 173 case REG_PC: 174 tmp = regs->pc; 175 break; 176 177 case REG_PS: 178 /* Note: PS.EXCM is not set while user task is running; 179 * its being set in regs is for exception handling 180 * convenience. */ 181 tmp = (regs->ps & ~(1 << PS_EXCM_BIT)); 182 break; 183 184 case REG_WB: 185 break; /* tmp = 0 */ 186 187 case REG_WS: 188 { 189 unsigned long wb = regs->windowbase; 190 unsigned long ws = regs->windowstart; 191 tmp = ((ws>>wb) | (ws<<(WSBITS-wb))) & ((1<<WSBITS)-1); 192 break; 193 } 194 case REG_LBEG: 195 tmp = regs->lbeg; 196 break; 197 198 case REG_LEND: 199 tmp = regs->lend; 200 break; 201 202 case REG_LCOUNT: 203 tmp = regs->lcount; 204 break; 205 206 case REG_SAR: 207 tmp = regs->sar; 208 break; 209 210 case SYSCALL_NR: 211 tmp = regs->syscall; 212 break; 213 214 default: 215 return -EIO; 216 } 217 return put_user(tmp, ret); 218 } 219 220 int ptrace_pokeusr(struct task_struct *child, long regno, long val) 221 { 222 struct pt_regs *regs; 223 regs = task_pt_regs(child); 224 225 switch (regno) { 226 case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1: 227 regs->areg[regno - REG_AR_BASE] = val; 228 break; 229 230 case REG_A_BASE ... REG_A_BASE + 15: 231 regs->areg[regno - REG_A_BASE] = val; 232 break; 233 234 case REG_PC: 235 regs->pc = val; 236 break; 237 238 case SYSCALL_NR: 239 regs->syscall = val; 240 break; 241 242 default: 243 return -EIO; 244 } 245 return 0; 246 } 247 248 long arch_ptrace(struct task_struct *child, long request, long addr, long data) 249 { 250 int ret = -EPERM; 251 252 switch (request) { 253 case PTRACE_PEEKTEXT: /* read word at location addr. */ 254 case PTRACE_PEEKDATA: 255 ret = generic_ptrace_peekdata(child, addr, data); 256 break; 257 258 case PTRACE_PEEKUSR: /* read register specified by addr. */ 259 ret = ptrace_peekusr(child, addr, (void __user *) data); 260 break; 261 262 case PTRACE_POKETEXT: /* write the word at location addr. */ 263 case PTRACE_POKEDATA: 264 ret = generic_ptrace_pokedata(child, addr, data); 265 break; 266 267 case PTRACE_POKEUSR: /* write register specified by addr. */ 268 ret = ptrace_pokeusr(child, addr, data); 269 break; 270 271 /* continue and stop at next (return from) syscall */ 272 273 case PTRACE_SYSCALL: 274 case PTRACE_CONT: /* restart after signal. */ 275 { 276 ret = -EIO; 277 if (!valid_signal(data)) 278 break; 279 if (request == PTRACE_SYSCALL) 280 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 281 else 282 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 283 child->exit_code = data; 284 /* Make sure the single step bit is not set. */ 285 child->ptrace &= ~PT_SINGLESTEP; 286 wake_up_process(child); 287 ret = 0; 288 break; 289 } 290 291 /* 292 * make the child exit. Best I can do is send it a sigkill. 293 * perhaps it should be put in the status that it wants to 294 * exit. 295 */ 296 case PTRACE_KILL: 297 ret = 0; 298 if (child->exit_state == EXIT_ZOMBIE) /* already dead */ 299 break; 300 child->exit_code = SIGKILL; 301 child->ptrace &= ~PT_SINGLESTEP; 302 wake_up_process(child); 303 break; 304 305 case PTRACE_SINGLESTEP: 306 ret = -EIO; 307 if (!valid_signal(data)) 308 break; 309 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 310 child->ptrace |= PT_SINGLESTEP; 311 child->exit_code = data; 312 wake_up_process(child); 313 ret = 0; 314 break; 315 316 case PTRACE_GETREGS: 317 ret = ptrace_getregs(child, (void __user *) data); 318 break; 319 320 case PTRACE_SETREGS: 321 ret = ptrace_setregs(child, (void __user *) data); 322 break; 323 324 case PTRACE_GETXTREGS: 325 ret = ptrace_getxregs(child, (void __user *) data); 326 break; 327 328 case PTRACE_SETXTREGS: 329 ret = ptrace_setxregs(child, (void __user *) data); 330 break; 331 332 default: 333 ret = ptrace_request(child, request, addr, data); 334 break; 335 } 336 337 return ret; 338 } 339 340 void do_syscall_trace(void) 341 { 342 /* 343 * The 0x80 provides a way for the tracing parent to distinguish 344 * between a syscall stop and SIGTRAP delivery 345 */ 346 ptrace_notify(SIGTRAP|((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); 347 348 /* 349 * this isn't the same as continuing with a signal, but it will do 350 * for normal use. strace only continues with a signal if the 351 * stopping signal is not SIGTRAP. -brl 352 */ 353 if (current->exit_code) { 354 send_sig(current->exit_code, current, 1); 355 current->exit_code = 0; 356 } 357 } 358 359 void do_syscall_trace_enter(struct pt_regs *regs) 360 { 361 if (test_thread_flag(TIF_SYSCALL_TRACE) 362 && (current->ptrace & PT_PTRACED)) 363 do_syscall_trace(); 364 365 #if 0 366 if (unlikely(current->audit_context)) 367 audit_syscall_entry(current, AUDIT_ARCH_XTENSA..); 368 #endif 369 } 370 371 void do_syscall_trace_leave(struct pt_regs *regs) 372 { 373 if ((test_thread_flag(TIF_SYSCALL_TRACE)) 374 && (current->ptrace & PT_PTRACED)) 375 do_syscall_trace(); 376 } 377 378