1/* 2 * arch/ubicom32/kernel/ptrace.c 3 * Ubicom32 architecture ptrace implementation. 4 * 5 * (C) Copyright 2009, Ubicom, Inc. 6 * (C) 1994 by Hamish Macdonald 7 * Taken from linux/kernel/ptrace.c and modified for M680x0. 8 * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds 9 * 10 * This file is part of the Ubicom32 Linux Kernel Port. 11 * 12 * The Ubicom32 Linux Kernel Port is free software: you can redistribute 13 * it and/or modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation, either version 2 of the 15 * License, or (at your option) any later version. 16 * 17 * The Ubicom32 Linux Kernel Port is distributed in the hope that it 18 * will be useful, but WITHOUT ANY WARRANTY; without even the implied 19 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 20 * the GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with the Ubicom32 Linux Kernel Port. If not, 24 * see <http://www.gnu.org/licenses/>. 25 * 26 * Ubicom32 implementation derived from (with many thanks): 27 * arch/m68knommu 28 * arch/blackfin 29 * arch/parisc 30 */ 31 32#include <linux/module.h> 33#include <linux/kernel.h> 34#include <linux/sched.h> 35#include <linux/mm.h> 36#include <linux/smp.h> 37#include <linux/errno.h> 38#include <linux/ptrace.h> 39#include <linux/user.h> 40#include <linux/signal.h> 41#include <linux/uaccess.h> 42 43#include <asm/page.h> 44#include <asm/pgtable.h> 45#include <asm/system.h> 46#include <asm/cacheflush.h> 47#include <asm/processor.h> 48 49/* 50 * ptrace_getregs() 51 * 52 * Get all user integer registers. 53 */ 54static inline int ptrace_getregs(struct task_struct *task, void __user *uregs) 55{ 56 struct pt_regs *regs = task_pt_regs(task); 57 return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0; 58} 59 60/* 61 * ptrace_get_reg() 62 * 63 * Get contents of register REGNO in task TASK. 64 */ 65static unsigned long ptrace_get_reg(struct task_struct *task, int regno) 66{ 67 if (regno < sizeof(struct pt_regs)) { 68 struct pt_regs *pt_regs = task_pt_regs(task); 69 return *(unsigned long *)((long) pt_regs + regno); 70 } 71 72 return -EIO; 73} 74 75/* 76 * ptrace_put_reg() 77 * Write contents of register REGNO in task TASK. 78 */ 79static int ptrace_put_reg(struct task_struct *task, int regno, 80 unsigned long data) 81{ 82 if (regno <= sizeof(struct pt_regs) && regno != PT_FRAME_TYPE) { 83 struct pt_regs *pt_regs = task_pt_regs(task); 84 *(unsigned long *)((long) pt_regs + regno) = data; 85 return 0; 86 } 87 return -EIO; 88} 89 90/* 91 * ptrace_disable_single_step() 92 * Disable Single Step 93 */ 94static int ptrace_disable_single_step(struct task_struct *task) 95{ 96 /* 97 * Single Step not yet implemented, so must always be disabled 98 */ 99 return 0; 100} 101 102/* 103 * ptrace_disable() 104 * Make sure the single step bit is not set. 105 * Called by kernel/ptrace.c when detaching.. 106 */ 107void ptrace_disable(struct task_struct *child) 108{ 109 ptrace_disable_single_step(child); 110} 111 112/* 113 * arch_ptrace() 114 * architecture specific ptrace routine. 115 */ 116long arch_ptrace(struct task_struct *child, long request, long addr, long data) 117{ 118 int ret; 119 switch (request) { 120 /* when I and D space are separate, these will need to be fixed. */ 121 case PTRACE_PEEKTEXT: /* read word at location addr. */ 122 case PTRACE_PEEKDATA: 123 ret = generic_ptrace_peekdata(child, addr, data); 124 break; 125 126 /* read the word at location addr in the USER area. */ 127 case PTRACE_PEEKUSR: { 128 unsigned long tmp; 129 130 ret = -EIO; 131 if (((unsigned long) addr > PT_INTERP_FDPIC_LOADMAP) 132 || (addr & 3)) 133 break; 134 135 tmp = 0; /* Default return condition */ 136 137 ret = -EIO; 138 if (addr < sizeof(struct pt_regs)) { 139 tmp = ptrace_get_reg(child, addr); 140 } else if (addr == PT_TEXT_ADDR) { 141 tmp = child->mm->start_code; 142 } else if (addr == PT_TEXT_END_ADDR) { 143 tmp = child->mm->end_code; 144 } else if (addr == PT_DATA_ADDR) { 145 tmp = child->mm->start_data; 146 } else if (addr == PT_EXEC_FDPIC_LOADMAP) { 147#ifdef CONFIG_BINFMT_ELF_FDPIC 148 tmp = child->mm->context.exec_fdpic_loadmap; 149#endif 150 } else if (addr == PT_INTERP_FDPIC_LOADMAP) { 151#ifdef CONFIG_BINFMT_ELF_FDPIC 152 tmp = child->mm->context.interp_fdpic_loadmap; 153#endif 154 } else { 155 break; 156 } 157 158 ret = put_user(tmp, (unsigned long *)data); 159 break; 160 } 161 162 case PTRACE_POKETEXT: /* write the word at location addr. */ 163 case PTRACE_POKEDATA: 164 ret = generic_ptrace_pokedata(child, addr, data); 165 166 /* 167 * If we just changed some code so we need to 168 * correct the caches 169 */ 170 if (request == PTRACE_POKETEXT && ret == 0) { 171 flush_icache_range(addr, addr + 4); 172 } 173 break; 174 175 case PTRACE_POKEUSR: /* write the word at location addr 176 * in the USER area */ 177 ret = -EIO; 178 179 if (((unsigned long) addr > PT_DATA_ADDR) || (addr & 3)) 180 break; 181 182 if (addr < sizeof(struct pt_regs)) { 183 ret = ptrace_put_reg(child, addr, data); 184 } 185 break; 186 187 case PTRACE_SYSCALL: /* continue and stop at next (return from) 188 * syscall */ 189 case PTRACE_CONT: { /* restart after signal. */ 190 191 ret = -EIO; 192 if (!valid_signal(data)) 193 break; 194 if (request == PTRACE_SYSCALL) 195 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 196 else 197 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 198 child->exit_code = data; 199 /* make sure the single step bit is not set. */ 200 ptrace_disable_single_step(child); 201 wake_up_process(child); 202 ret = 0; 203 break; 204 } 205 206 /* 207 * make the child exit. Best I can do is send it a sigkill. 208 * perhaps it should be put in the status that it wants to exit. 209 */ 210 case PTRACE_KILL: { 211 ret = 0; 212 if (child->exit_state == EXIT_ZOMBIE) /* already dead */ 213 break; 214 child->exit_code = SIGKILL; 215 /* make sure the single step bit is not set. */ 216 ptrace_disable_single_step(child); 217 wake_up_process(child); 218 break; 219 } 220 221 case PTRACE_DETACH: /* detach a process that was attached. */ 222 ret = ptrace_detach(child, data); 223 break; 224 225 case PTRACE_GETREGS: /* Get all gp regs from the child. */ 226 ptrace_getregs(child, (unsigned long *)data); 227 ret = 0; 228 break; 229 230 case PTRACE_SETREGS: { /* Set all gp regs in the child. */ 231 int i; 232 unsigned long tmp; 233 int count = sizeof(struct pt_regs) / sizeof(unsigned long); 234 for (i = 0; i < count; i++) { 235 if (get_user(tmp, (unsigned long *) data)) { 236 ret = -EFAULT; 237 break; 238 } 239 ptrace_put_reg(child, sizeof(unsigned long) * i, tmp); 240 data += sizeof(long); 241 } 242 ret = 0; 243 break; 244 } 245 246 default: 247 return ptrace_request(child, request, addr, data); 248 break; 249 } 250 return ret; 251} 252/* 253 * syscall_trace 254 * 255 * called by syscall enter/exit when the TIF_SYSCALL_TRACE bit is set. 256 */ 257asmlinkage void syscall_trace(void) 258{ 259 struct task_struct *cur = current; 260 if (!test_thread_flag(TIF_SYSCALL_TRACE)) 261 return; 262 if (!(cur->ptrace & PT_PTRACED)) 263 return; 264 ptrace_notify(SIGTRAP | ((cur->ptrace & PT_TRACESYSGOOD) 265 ? 0x80 : 0)); 266 /* 267 * this isn't the same as continuing with a signal, but it will do 268 * for normal use. strace only continues with a signal if the 269 * stopping signal is not SIGTRAP. -brl 270 */ 271 if (cur->exit_code) { 272 send_sig(cur->exit_code, current, 1); 273 current->exit_code = 0; 274 } 275} 276