linux/arch/mips/kernel/ptrace32.c
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * Copyright (C) 1992 Ross Biro
   7 * Copyright (C) Linus Torvalds
   8 * Copyright (C) 1994, 95, 96, 97, 98, 2000 Ralf Baechle
   9 * Copyright (C) 1996 David S. Miller
  10 * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
  11 * Copyright (C) 1999 MIPS Technologies, Inc.
  12 * Copyright (C) 2000 Ulf Carlsson
  13 *
  14 * At this time Linux/MIPS64 only supports syscall tracing, even for 32-bit
  15 * binaries.
  16 */
  17#include <linux/compiler.h>
  18#include <linux/compat.h>
  19#include <linux/kernel.h>
  20#include <linux/sched.h>
  21#include <linux/sched/task_stack.h>
  22#include <linux/mm.h>
  23#include <linux/errno.h>
  24#include <linux/ptrace.h>
  25#include <linux/smp.h>
  26#include <linux/security.h>
  27
  28#include <asm/cpu.h>
  29#include <asm/dsp.h>
  30#include <asm/fpu.h>
  31#include <asm/mipsregs.h>
  32#include <asm/mipsmtregs.h>
  33#include <asm/pgtable.h>
  34#include <asm/page.h>
  35#include <asm/reg.h>
  36#include <linux/uaccess.h>
  37#include <asm/bootinfo.h>
  38
  39/*
  40 * Tracing a 32-bit process with a 64-bit strace and vice versa will not
  41 * work.  I don't know how to fix this.
  42 */
  43long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
  44                        compat_ulong_t caddr, compat_ulong_t cdata)
  45{
  46        int addr = caddr;
  47        int data = cdata;
  48        int ret;
  49
  50        switch (request) {
  51
  52        /*
  53         * Read 4 bytes of the other process' storage
  54         *  data is a pointer specifying where the user wants the
  55         *      4 bytes copied into
  56         *  addr is a pointer in the user's storage that contains an 8 byte
  57         *      address in the other process of the 4 bytes that is to be read
  58         * (this is run in a 32-bit process looking at a 64-bit process)
  59         * when I and D space are separate, these will need to be fixed.
  60         */
  61        case PTRACE_PEEKTEXT_3264:
  62        case PTRACE_PEEKDATA_3264: {
  63                u32 tmp;
  64                int copied;
  65                u32 __user * addrOthers;
  66
  67                ret = -EIO;
  68
  69                /* Get the addr in the other process that we want to read */
  70                if (get_user(addrOthers, (u32 __user * __user *) (unsigned long) addr) != 0)
  71                        break;
  72
  73                copied = ptrace_access_vm(child, (u64)addrOthers, &tmp,
  74                                sizeof(tmp), FOLL_FORCE);
  75                if (copied != sizeof(tmp))
  76                        break;
  77                ret = put_user(tmp, (u32 __user *) (unsigned long) data);
  78                break;
  79        }
  80
  81        /* Read the word at location addr in the USER area. */
  82        case PTRACE_PEEKUSR: {
  83                struct pt_regs *regs;
  84                union fpureg *fregs;
  85                unsigned int tmp;
  86
  87                regs = task_pt_regs(child);
  88                ret = 0;  /* Default return value. */
  89
  90                switch (addr) {
  91                case 0 ... 31:
  92                        tmp = regs->regs[addr];
  93                        break;
  94                case FPR_BASE ... FPR_BASE + 31:
  95                        if (!tsk_used_math(child)) {
  96                                /* FP not yet used */
  97                                tmp = -1;
  98                                break;
  99                        }
 100                        fregs = get_fpu_regs(child);
 101                        if (test_thread_flag(TIF_32BIT_FPREGS)) {
 102                                /*
 103                                 * The odd registers are actually the high
 104                                 * order bits of the values stored in the even
 105                                 * registers - unless we're using r2k_switch.S.
 106                                 */
 107                                tmp = get_fpr32(&fregs[(addr & ~1) - FPR_BASE],
 108                                                addr & 1);
 109                                break;
 110                        }
 111                        tmp = get_fpr32(&fregs[addr - FPR_BASE], 0);
 112                        break;
 113                case PC:
 114                        tmp = regs->cp0_epc;
 115                        break;
 116                case CAUSE:
 117                        tmp = regs->cp0_cause;
 118                        break;
 119                case BADVADDR:
 120                        tmp = regs->cp0_badvaddr;
 121                        break;
 122                case MMHI:
 123                        tmp = regs->hi;
 124                        break;
 125                case MMLO:
 126                        tmp = regs->lo;
 127                        break;
 128                case FPC_CSR:
 129                        tmp = child->thread.fpu.fcr31;
 130                        break;
 131                case FPC_EIR:
 132                        /* implementation / version register */
 133                        tmp = boot_cpu_data.fpu_id;
 134                        break;
 135                case DSP_BASE ... DSP_BASE + 5: {
 136                        dspreg_t *dregs;
 137
 138                        if (!cpu_has_dsp) {
 139                                tmp = 0;
 140                                ret = -EIO;
 141                                goto out;
 142                        }
 143                        dregs = __get_dsp_regs(child);
 144                        tmp = (unsigned long) (dregs[addr - DSP_BASE]);
 145                        break;
 146                }
 147                case DSP_CONTROL:
 148                        if (!cpu_has_dsp) {
 149                                tmp = 0;
 150                                ret = -EIO;
 151                                goto out;
 152                        }
 153                        tmp = child->thread.dsp.dspcontrol;
 154                        break;
 155                default:
 156                        tmp = 0;
 157                        ret = -EIO;
 158                        goto out;
 159                }
 160                ret = put_user(tmp, (unsigned __user *) (unsigned long) data);
 161                break;
 162        }
 163
 164        /*
 165         * Write 4 bytes into the other process' storage
 166         *  data is the 4 bytes that the user wants written
 167         *  addr is a pointer in the user's storage that contains an
 168         *      8 byte address in the other process where the 4 bytes
 169         *      that is to be written
 170         * (this is run in a 32-bit process looking at a 64-bit process)
 171         * when I and D space are separate, these will need to be fixed.
 172         */
 173        case PTRACE_POKETEXT_3264:
 174        case PTRACE_POKEDATA_3264: {
 175                u32 __user * addrOthers;
 176
 177                /* Get the addr in the other process that we want to write into */
 178                ret = -EIO;
 179                if (get_user(addrOthers, (u32 __user * __user *) (unsigned long) addr) != 0)
 180                        break;
 181                ret = 0;
 182                if (ptrace_access_vm(child, (u64)addrOthers, &data,
 183                                        sizeof(data),
 184                                        FOLL_FORCE | FOLL_WRITE) == sizeof(data))
 185                        break;
 186                ret = -EIO;
 187                break;
 188        }
 189
 190        case PTRACE_POKEUSR: {
 191                struct pt_regs *regs;
 192                ret = 0;
 193                regs = task_pt_regs(child);
 194
 195                switch (addr) {
 196                case 0 ... 31:
 197                        regs->regs[addr] = data;
 198                        break;
 199                case FPR_BASE ... FPR_BASE + 31: {
 200                        union fpureg *fregs = get_fpu_regs(child);
 201
 202                        if (!tsk_used_math(child)) {
 203                                /* FP not yet used  */
 204                                memset(&child->thread.fpu, ~0,
 205                                       sizeof(child->thread.fpu));
 206                                child->thread.fpu.fcr31 = 0;
 207                        }
 208                        if (test_thread_flag(TIF_32BIT_FPREGS)) {
 209                                /*
 210                                 * The odd registers are actually the high
 211                                 * order bits of the values stored in the even
 212                                 * registers - unless we're using r2k_switch.S.
 213                                 */
 214                                set_fpr32(&fregs[(addr & ~1) - FPR_BASE],
 215                                          addr & 1, data);
 216                                break;
 217                        }
 218                        set_fpr64(&fregs[addr - FPR_BASE], 0, data);
 219                        break;
 220                }
 221                case PC:
 222                        regs->cp0_epc = data;
 223                        break;
 224                case MMHI:
 225                        regs->hi = data;
 226                        break;
 227                case MMLO:
 228                        regs->lo = data;
 229                        break;
 230                case FPC_CSR:
 231                        child->thread.fpu.fcr31 = data;
 232                        break;
 233                case DSP_BASE ... DSP_BASE + 5: {
 234                        dspreg_t *dregs;
 235
 236                        if (!cpu_has_dsp) {
 237                                ret = -EIO;
 238                                break;
 239                        }
 240
 241                        dregs = __get_dsp_regs(child);
 242                        dregs[addr - DSP_BASE] = data;
 243                        break;
 244                }
 245                case DSP_CONTROL:
 246                        if (!cpu_has_dsp) {
 247                                ret = -EIO;
 248                                break;
 249                        }
 250                        child->thread.dsp.dspcontrol = data;
 251                        break;
 252                default:
 253                        /* The rest are not allowed. */
 254                        ret = -EIO;
 255                        break;
 256                }
 257                break;
 258                }
 259
 260        case PTRACE_GETREGS:
 261                ret = ptrace_getregs(child,
 262                                (struct user_pt_regs __user *) (__u64) data);
 263                break;
 264
 265        case PTRACE_SETREGS:
 266                ret = ptrace_setregs(child,
 267                                (struct user_pt_regs __user *) (__u64) data);
 268                break;
 269
 270        case PTRACE_GETFPREGS:
 271                ret = ptrace_getfpregs(child, (__u32 __user *) (__u64) data);
 272                break;
 273
 274        case PTRACE_SETFPREGS:
 275                ret = ptrace_setfpregs(child, (__u32 __user *) (__u64) data);
 276                break;
 277
 278        case PTRACE_GET_THREAD_AREA:
 279                ret = put_user(task_thread_info(child)->tp_value,
 280                                (unsigned int __user *) (unsigned long) data);
 281                break;
 282
 283        case PTRACE_GET_THREAD_AREA_3264:
 284                ret = put_user(task_thread_info(child)->tp_value,
 285                                (unsigned long __user *) (unsigned long) data);
 286                break;
 287
 288        case PTRACE_GET_WATCH_REGS:
 289                ret = ptrace_get_watch_regs(child,
 290                        (struct pt_watch_regs __user *) (unsigned long) addr);
 291                break;
 292
 293        case PTRACE_SET_WATCH_REGS:
 294                ret = ptrace_set_watch_regs(child,
 295                        (struct pt_watch_regs __user *) (unsigned long) addr);
 296                break;
 297
 298        default:
 299                ret = compat_ptrace_request(child, request, addr, data);
 300                break;
 301        }
 302out:
 303        return ret;
 304}
 305