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