1 /* 1 2 * ptrace for 32-bit processes running on a 64 3 * 4 * PowerPC version 5 * Copyright (C) 1995-1996 Gary Thomas (gdt 6 * 7 * Derived from "arch/m68k/kernel/ptrace.c" 8 * Copyright (C) 1994 by Hamish Macdonald 9 * Taken from linux/kernel/ptrace.c and modif 10 * linux/kernel/ptrace.c is by Ross Biro 1/23 11 * 12 * Modified by Cort Dougan (cort@hq.fsmlabs.co 13 * and Paul Mackerras (paulus@samba.org). 14 * 15 * This file is subject to the terms and condi 16 * Public License. See the file COPYING in th 17 * this archive for more details. 18 */ 19 20 #include <linux/ptrace.h> 21 #include <linux/regset.h> 22 #include <linux/compat.h> 23 24 #include <asm/switch_to.h> 25 26 #include "ptrace-decl.h" 27 28 /* 29 * does not yet catch signals sent when the ch 30 * in exit.c or in signal.c. 31 */ 32 33 /* Macros to workout the correct index for the 34 #define FPRNUMBER(i) (((i) - PT_FPR0) >> 1) 35 #define FPRHALF(i) (((i) - PT_FPR0) & 1) 36 #define FPRINDEX(i) TS_FPRWIDTH * FPRNUMBER(i) 37 38 long compat_arch_ptrace(struct task_struct *ch 39 compat_ulong_t caddr, 40 { 41 unsigned long addr = caddr; 42 unsigned long data = cdata; 43 int ret; 44 45 switch (request) { 46 /* 47 * Read 4 bytes of the other process' 48 * data is a pointer specifying where 49 * 4 bytes copied into 50 * addr is a pointer in the user's st 51 * address in the other process o 52 * (this is run in a 32-bit process lo 53 * when I and D space are separate, th 54 */ 55 case PPC_PTRACE_PEEKTEXT_3264: 56 case PPC_PTRACE_PEEKDATA_3264: { 57 u32 tmp; 58 int copied; 59 u32 __user * addrOthers; 60 61 ret = -EIO; 62 63 /* Get the addr in the other p 64 if (get_user(addrOthers, (u32 65 break; 66 67 copied = ptrace_access_vm(chil 68 sizeof(tmp), F 69 if (copied != sizeof(tmp)) 70 break; 71 ret = put_user(tmp, (u32 __use 72 break; 73 } 74 75 /* Read a register (specified by ADDR) 76 case PTRACE_PEEKUSR: { 77 int index; 78 unsigned long tmp; 79 80 ret = -EIO; 81 /* convert to index and check 82 index = (unsigned long) addr > 83 if ((addr & 3) || (index > PT_ 84 break; 85 86 if (index < PT_FPR0) { 87 ret = ptrace_get_reg(c 88 if (ret) 89 break; 90 } else { 91 flush_fp_to_thread(chi 92 /* 93 * the user space code 94 * to be an array of u 95 * index passed in is 96 */ 97 tmp = ((unsigned int * 98 [FPRINDEX(inde 99 } 100 ret = put_user((unsigned int)t 101 break; 102 } 103 104 /* 105 * Read 4 bytes out of the other proce 106 * data is a pointer specifying where 107 * 4 bytes copied into 108 * addr is the offset into the other 109 * that is to be read 110 * (this is run in a 32-bit process lo 111 */ 112 case PPC_PTRACE_PEEKUSR_3264: { 113 u32 index; 114 u32 reg32bits; 115 u64 tmp; 116 u32 numReg; 117 u32 part; 118 119 ret = -EIO; 120 /* Determine which register th 121 index = (u64)addr >> 2; 122 numReg = index / 2; 123 /* Determine which part of the 124 if (index % 2) 125 part = 1; /* want the 126 else 127 part = 0; /* want the 128 129 /* Validate the input - check 130 * or beyond the end of the us 131 */ 132 if ((addr & 3) || numReg > PT_ 133 break; 134 135 if (numReg >= PT_FPR0) { 136 flush_fp_to_thread(chi 137 /* get 64 bit FPR */ 138 tmp = child->thread.fp 139 } else { /* register within PT 140 unsigned long tmp2; 141 ret = ptrace_get_reg(c 142 if (ret) 143 break; 144 tmp = tmp2; 145 } 146 reg32bits = ((u32*)&tmp)[part] 147 ret = put_user(reg32bits, (u32 148 break; 149 } 150 151 /* 152 * Write 4 bytes into the other proces 153 * data is the 4 bytes that the user 154 * addr is a pointer in the user's st 155 * 8 byte address in the other pr 156 * that is to be written 157 * (this is run in a 32-bit process lo 158 * when I and D space are separate, th 159 */ 160 case PPC_PTRACE_POKETEXT_3264: 161 case PPC_PTRACE_POKEDATA_3264: { 162 u32 tmp = data; 163 u32 __user * addrOthers; 164 165 /* Get the addr in the other p 166 ret = -EIO; 167 if (get_user(addrOthers, (u32 168 break; 169 ret = 0; 170 if (ptrace_access_vm(child, (u 171 sizeof 172 FOLL_F 173 break; 174 ret = -EIO; 175 break; 176 } 177 178 /* write the word at location addr in 179 case PTRACE_POKEUSR: { 180 unsigned long index; 181 182 ret = -EIO; 183 /* convert to index and check 184 index = (unsigned long) addr > 185 if ((addr & 3) || (index > PT_ 186 break; 187 188 if (index < PT_FPR0) { 189 ret = ptrace_put_reg(c 190 } else { 191 flush_fp_to_thread(chi 192 /* 193 * the user space code 194 * to be an array of u 195 * index passed in is 196 */ 197 ((unsigned int *)child 198 [FPRINDEX(inde 199 ret = 0; 200 } 201 break; 202 } 203 204 /* 205 * Write 4 bytes into the other proces 206 * data is the 4 bytes that the user 207 * addr is the offset into the other 208 * that is to be written into 209 * (this is run in a 32-bit process lo 210 */ 211 case PPC_PTRACE_POKEUSR_3264: { 212 u32 index; 213 u32 numReg; 214 215 ret = -EIO; 216 /* Determine which register th 217 index = (u64)addr >> 2; 218 numReg = index / 2; 219 220 /* 221 * Validate the input - check 222 * wrong boundary or beyond th 223 */ 224 if ((addr & 3) || (numReg > PT 225 break; 226 if (numReg < PT_FPR0) { 227 unsigned long freg; 228 ret = ptrace_get_reg(c 229 if (ret) 230 break; 231 if (index % 2) 232 freg = (freg & 233 else 234 freg = (freg & 235 ret = ptrace_put_reg(c 236 } else { 237 u64 *tmp; 238 flush_fp_to_thread(chi 239 /* get 64 bit FPR ... 240 tmp = &child->thread.f 241 /* ... write the 32 bi 242 ((u32 *)tmp)[index % 2 243 ret = 0; 244 } 245 break; 246 } 247 248 case PTRACE_GET_DEBUGREG: { 249 #ifndef CONFIG_PPC_ADV_DEBUG_REGS 250 unsigned long dabr_fake; 251 #endif 252 ret = -EINVAL; 253 /* We only support one DABR an 254 if (addr > 0) 255 break; 256 #ifdef CONFIG_PPC_ADV_DEBUG_REGS 257 ret = put_user(child->thread.d 258 #else 259 dabr_fake = ( 260 (child->thread.hw_brk[ 261 (child->thread.hw_brk[ 262 ret = put_user(dabr_fake, (u32 263 #endif 264 break; 265 } 266 267 case PTRACE_GETREGS: /* Get all pt_ 268 return copy_regset_to_user( 269 child, task_user_regse 270 0, PT_REGS_COUNT * siz 271 compat_ptr(data)); 272 273 case PTRACE_SETREGS: /* Set all gp 274 return copy_regset_from_user( 275 child, task_user_regse 276 0, PT_REGS_COUNT * siz 277 compat_ptr(data)); 278 279 case PTRACE_GETFPREGS: 280 case PTRACE_SETFPREGS: 281 case PTRACE_GETVRREGS: 282 case PTRACE_SETVRREGS: 283 case PTRACE_GETVSRREGS: 284 case PTRACE_SETVSRREGS: 285 case PTRACE_GETREGS64: 286 case PTRACE_SETREGS64: 287 case PTRACE_KILL: 288 case PTRACE_SINGLESTEP: 289 case PTRACE_DETACH: 290 case PTRACE_SET_DEBUGREG: 291 case PTRACE_SYSCALL: 292 case PTRACE_CONT: 293 case PPC_PTRACE_GETHWDBGINFO: 294 case PPC_PTRACE_SETHWDEBUG: 295 case PPC_PTRACE_DELHWDEBUG: 296 ret = arch_ptrace(child, reque 297 break; 298 299 default: 300 ret = compat_ptrace_request(ch 301 break; 302 } 303 304 return ret; 305 } 306
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.