~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/sh/kernel/ptrace.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /arch/sh/kernel/ptrace.c (Architecture i386) and /arch/m68k/kernel/ptrace.c (Architecture m68k)


  1 // SPDX-License-Identifier: GPL-2.0            !!   1 /*
                                                   >>   2  *  linux/arch/m68k/kernel/ptrace.c
                                                   >>   3  *
                                                   >>   4  *  Copyright (C) 1994 by Hamish Macdonald
                                                   >>   5  *  Taken from linux/kernel/ptrace.c and modified for M680x0.
                                                   >>   6  *  linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
                                                   >>   7  *
                                                   >>   8  * This file is subject to the terms and conditions of the GNU General
                                                   >>   9  * Public License.  See the file COPYING in the main directory of
                                                   >>  10  * this archive for more details.
                                                   >>  11  */
                                                   >>  12 
                                                   >>  13 #include <linux/kernel.h>
                                                   >>  14 #include <linux/sched.h>
                                                   >>  15 #include <linux/sched/task_stack.h>
                                                   >>  16 #include <linux/mm.h>
                                                   >>  17 #include <linux/smp.h>
                                                   >>  18 #include <linux/errno.h>
  2 #include <linux/ptrace.h>                          19 #include <linux/ptrace.h>
                                                   >>  20 #include <linux/user.h>
                                                   >>  21 #include <linux/signal.h>
                                                   >>  22 #include <linux/regset.h>
                                                   >>  23 #include <linux/elf.h>
                                                   >>  24 #include <linux/seccomp.h>
                                                   >>  25 #include <linux/uaccess.h>
                                                   >>  26 #include <asm/page.h>
                                                   >>  27 #include <asm/processor.h>
  3                                                    28 
  4 /**                                            !!  29 #include "ptrace.h"
  5  * regs_query_register_offset() - query regist !!  30 
  6  * @name:       the name of a register         !!  31 /*
  7  *                                             !!  32  * does not yet catch signals sent when the child dies.
  8  * regs_query_register_offset() returns the of !!  33  * in exit.c or in signal.c.
  9  * pt_regs from its name. If the name is inval << 
 10  */                                                34  */
 11 int regs_query_register_offset(const char *nam !!  35 
                                                   >>  36 /* determines which bits in the SR the user has access to. */
                                                   >>  37 /* 1 = access 0 = no access */
                                                   >>  38 #define SR_MASK 0x001f
                                                   >>  39 
                                                   >>  40 /* sets the trace bits. */
                                                   >>  41 #define TRACE_BITS 0xC000
                                                   >>  42 #define T1_BIT 0x8000
                                                   >>  43 #define T0_BIT 0x4000
                                                   >>  44 
                                                   >>  45 /* Find the stack offset for a register, relative to thread.esp0. */
                                                   >>  46 #define PT_REG(reg)     ((long)&((struct pt_regs *)0)->reg)
                                                   >>  47 #define SW_REG(reg)     ((long)&((struct switch_stack *)0)->reg \
                                                   >>  48                          - sizeof(struct switch_stack))
                                                   >>  49 /* Mapping from PT_xxx to the stack offset at which the register is
                                                   >>  50    saved.  Notice that usp has no stack-slot and needs to be treated
                                                   >>  51    specially (see get_reg/put_reg below). */
                                                   >>  52 static const int regoff[] = {
                                                   >>  53         [0]     = PT_REG(d1),
                                                   >>  54         [1]     = PT_REG(d2),
                                                   >>  55         [2]     = PT_REG(d3),
                                                   >>  56         [3]     = PT_REG(d4),
                                                   >>  57         [4]     = PT_REG(d5),
                                                   >>  58         [5]     = SW_REG(d6),
                                                   >>  59         [6]     = SW_REG(d7),
                                                   >>  60         [7]     = PT_REG(a0),
                                                   >>  61         [8]     = PT_REG(a1),
                                                   >>  62         [9]     = PT_REG(a2),
                                                   >>  63         [10]    = SW_REG(a3),
                                                   >>  64         [11]    = SW_REG(a4),
                                                   >>  65         [12]    = SW_REG(a5),
                                                   >>  66         [13]    = SW_REG(a6),
                                                   >>  67         [14]    = PT_REG(d0),
                                                   >>  68         [15]    = -1,
                                                   >>  69         [16]    = PT_REG(orig_d0),
                                                   >>  70         [17]    = PT_REG(sr),
                                                   >>  71         [18]    = PT_REG(pc),
                                                   >>  72 };
                                                   >>  73 
                                                   >>  74 /*
                                                   >>  75  * Get contents of register REGNO in task TASK.
                                                   >>  76  */
                                                   >>  77 static inline long get_reg(struct task_struct *task, int regno)
 12 {                                                  78 {
 13         const struct pt_regs_offset *roff;     !!  79         unsigned long *addr;
 14         for (roff = regoffset_table; roff->nam !!  80 
 15                 if (!strcmp(roff->name, name)) !!  81         if (regno == PT_USP)
 16                         return roff->offset;   !!  82                 addr = &task->thread.usp;
 17         return -EINVAL;                        !!  83         else if (regno < ARRAY_SIZE(regoff))
                                                   >>  84                 addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
                                                   >>  85         else
                                                   >>  86                 return 0;
                                                   >>  87         /* Need to take stkadj into account. */
                                                   >>  88         if (regno == PT_SR || regno == PT_PC) {
                                                   >>  89                 long stkadj = *(long *)(task->thread.esp0 + PT_REG(stkadj));
                                                   >>  90                 addr = (unsigned long *) ((unsigned long)addr + stkadj);
                                                   >>  91                 /* The sr is actually a 16 bit register.  */
                                                   >>  92                 if (regno == PT_SR)
                                                   >>  93                         return *(unsigned short *)addr;
                                                   >>  94         }
                                                   >>  95         return *addr;
 18 }                                                  96 }
 19                                                    97 
 20 /**                                            !!  98 /*
 21  * regs_query_register_name() - query register !!  99  * Write contents of register REGNO in task TASK.
 22  * @offset:     the offset of a register in st << 
 23  *                                             << 
 24  * regs_query_register_name() returns the name << 
 25  * offset in struct pt_regs. If the @offset is << 
 26  */                                               100  */
 27 const char *regs_query_register_name(unsigned  !! 101 static inline int put_reg(struct task_struct *task, int regno,
                                                   >> 102                           unsigned long data)
                                                   >> 103 {
                                                   >> 104         unsigned long *addr;
                                                   >> 105 
                                                   >> 106         if (regno == PT_USP)
                                                   >> 107                 addr = &task->thread.usp;
                                                   >> 108         else if (regno < ARRAY_SIZE(regoff))
                                                   >> 109                 addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
                                                   >> 110         else
                                                   >> 111                 return -1;
                                                   >> 112         /* Need to take stkadj into account. */
                                                   >> 113         if (regno == PT_SR || regno == PT_PC) {
                                                   >> 114                 long stkadj = *(long *)(task->thread.esp0 + PT_REG(stkadj));
                                                   >> 115                 addr = (unsigned long *) ((unsigned long)addr + stkadj);
                                                   >> 116                 /* The sr is actually a 16 bit register.  */
                                                   >> 117                 if (regno == PT_SR) {
                                                   >> 118                         *(unsigned short *)addr = data;
                                                   >> 119                         return 0;
                                                   >> 120                 }
                                                   >> 121         }
                                                   >> 122         *addr = data;
                                                   >> 123         return 0;
                                                   >> 124 }
                                                   >> 125 
                                                   >> 126 /*
                                                   >> 127  * Make sure the single step bit is not set.
                                                   >> 128  */
                                                   >> 129 static inline void singlestep_disable(struct task_struct *child)
                                                   >> 130 {
                                                   >> 131         unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS;
                                                   >> 132         put_reg(child, PT_SR, tmp);
                                                   >> 133         clear_tsk_thread_flag(child, TIF_DELAYED_TRACE);
                                                   >> 134 }
                                                   >> 135 
                                                   >> 136 /*
                                                   >> 137  * Called by kernel/ptrace.c when detaching..
                                                   >> 138  */
                                                   >> 139 void ptrace_disable(struct task_struct *child)
                                                   >> 140 {
                                                   >> 141         singlestep_disable(child);
                                                   >> 142 }
                                                   >> 143 
                                                   >> 144 void user_enable_single_step(struct task_struct *child)
                                                   >> 145 {
                                                   >> 146         unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS;
                                                   >> 147         put_reg(child, PT_SR, tmp | T1_BIT);
                                                   >> 148         set_tsk_thread_flag(child, TIF_DELAYED_TRACE);
                                                   >> 149 }
                                                   >> 150 
                                                   >> 151 #ifdef CONFIG_MMU
                                                   >> 152 void user_enable_block_step(struct task_struct *child)
                                                   >> 153 {
                                                   >> 154         unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS;
                                                   >> 155         put_reg(child, PT_SR, tmp | T0_BIT);
                                                   >> 156 }
                                                   >> 157 #endif
                                                   >> 158 
                                                   >> 159 void user_disable_single_step(struct task_struct *child)
                                                   >> 160 {
                                                   >> 161         singlestep_disable(child);
                                                   >> 162 }
                                                   >> 163 
                                                   >> 164 long arch_ptrace(struct task_struct *child, long request,
                                                   >> 165                  unsigned long addr, unsigned long data)
                                                   >> 166 {
                                                   >> 167         unsigned long tmp;
                                                   >> 168         int i, ret = 0;
                                                   >> 169         int regno = addr >> 2; /* temporary hack. */
                                                   >> 170         unsigned long __user *datap = (unsigned long __user *) data;
                                                   >> 171 
                                                   >> 172         switch (request) {
                                                   >> 173         /* read the word at location addr in the USER area. */
                                                   >> 174         case PTRACE_PEEKUSR:
                                                   >> 175                 if (addr & 3)
                                                   >> 176                         goto out_eio;
                                                   >> 177 
                                                   >> 178                 if (regno >= 0 && regno < 19) {
                                                   >> 179                         tmp = get_reg(child, regno);
                                                   >> 180                 } else if (regno >= 21 && regno < 49) {
                                                   >> 181                         tmp = child->thread.fp[regno - 21];
                                                   >> 182                         /* Convert internal fpu reg representation
                                                   >> 183                          * into long double format
                                                   >> 184                          */
                                                   >> 185                         if (FPU_IS_EMU && (regno < 45) && !(regno % 3))
                                                   >> 186                                 tmp = ((tmp & 0xffff0000) << 15) |
                                                   >> 187                                       ((tmp & 0x0000ffff) << 16);
                                                   >> 188 #ifndef CONFIG_MMU
                                                   >> 189                 } else if (regno == 49) {
                                                   >> 190                         tmp = child->mm->start_code;
                                                   >> 191                 } else if (regno == 50) {
                                                   >> 192                         tmp = child->mm->start_data;
                                                   >> 193                 } else if (regno == 51) {
                                                   >> 194                         tmp = child->mm->end_code;
                                                   >> 195 #endif
                                                   >> 196                 } else
                                                   >> 197                         goto out_eio;
                                                   >> 198                 ret = put_user(tmp, datap);
                                                   >> 199                 break;
                                                   >> 200 
                                                   >> 201         case PTRACE_POKEUSR:
                                                   >> 202         /* write the word at location addr in the USER area */
                                                   >> 203                 if (addr & 3)
                                                   >> 204                         goto out_eio;
                                                   >> 205 
                                                   >> 206                 if (regno == PT_SR) {
                                                   >> 207                         data &= SR_MASK;
                                                   >> 208                         data |= get_reg(child, PT_SR) & ~SR_MASK;
                                                   >> 209                 }
                                                   >> 210                 if (regno >= 0 && regno < 19) {
                                                   >> 211                         if (put_reg(child, regno, data))
                                                   >> 212                                 goto out_eio;
                                                   >> 213                 } else if (regno >= 21 && regno < 48) {
                                                   >> 214                         /* Convert long double format
                                                   >> 215                          * into internal fpu reg representation
                                                   >> 216                          */
                                                   >> 217                         if (FPU_IS_EMU && (regno < 45) && !(regno % 3)) {
                                                   >> 218                                 data <<= 15;
                                                   >> 219                                 data = (data & 0xffff0000) |
                                                   >> 220                                        ((data & 0x0000ffff) >> 1);
                                                   >> 221                         }
                                                   >> 222                         child->thread.fp[regno - 21] = data;
                                                   >> 223                 } else
                                                   >> 224                         goto out_eio;
                                                   >> 225                 break;
                                                   >> 226 
                                                   >> 227         case PTRACE_GETREGS:    /* Get all gp regs from the child. */
                                                   >> 228                 for (i = 0; i < 19; i++) {
                                                   >> 229                         tmp = get_reg(child, i);
                                                   >> 230                         ret = put_user(tmp, datap);
                                                   >> 231                         if (ret)
                                                   >> 232                                 break;
                                                   >> 233                         datap++;
                                                   >> 234                 }
                                                   >> 235                 break;
                                                   >> 236 
                                                   >> 237         case PTRACE_SETREGS:    /* Set all gp regs in the child. */
                                                   >> 238                 for (i = 0; i < 19; i++) {
                                                   >> 239                         ret = get_user(tmp, datap);
                                                   >> 240                         if (ret)
                                                   >> 241                                 break;
                                                   >> 242                         if (i == PT_SR) {
                                                   >> 243                                 tmp &= SR_MASK;
                                                   >> 244                                 tmp |= get_reg(child, PT_SR) & ~SR_MASK;
                                                   >> 245                         }
                                                   >> 246                         put_reg(child, i, tmp);
                                                   >> 247                         datap++;
                                                   >> 248                 }
                                                   >> 249                 break;
                                                   >> 250 
                                                   >> 251         case PTRACE_GETFPREGS:  /* Get the child FPU state. */
                                                   >> 252                 if (copy_to_user(datap, &child->thread.fp,
                                                   >> 253                                  sizeof(struct user_m68kfp_struct)))
                                                   >> 254                         ret = -EFAULT;
                                                   >> 255                 break;
                                                   >> 256 
                                                   >> 257         case PTRACE_SETFPREGS:  /* Set the child FPU state. */
                                                   >> 258                 if (copy_from_user(&child->thread.fp, datap,
                                                   >> 259                                    sizeof(struct user_m68kfp_struct)))
                                                   >> 260                         ret = -EFAULT;
                                                   >> 261                 break;
                                                   >> 262 
                                                   >> 263         case PTRACE_GET_THREAD_AREA:
                                                   >> 264                 ret = put_user(task_thread_info(child)->tp_value, datap);
                                                   >> 265                 break;
                                                   >> 266 
                                                   >> 267         default:
                                                   >> 268                 ret = ptrace_request(child, request, addr, data);
                                                   >> 269                 break;
                                                   >> 270         }
                                                   >> 271 
                                                   >> 272         return ret;
                                                   >> 273 out_eio:
                                                   >> 274         return -EIO;
                                                   >> 275 }
                                                   >> 276 
                                                   >> 277 asmlinkage int syscall_trace_enter(void)
                                                   >> 278 {
                                                   >> 279         int ret = 0;
                                                   >> 280 
                                                   >> 281         if (test_thread_flag(TIF_SYSCALL_TRACE))
                                                   >> 282                 ret = ptrace_report_syscall_entry(task_pt_regs(current));
                                                   >> 283 
                                                   >> 284         if (secure_computing() == -1)
                                                   >> 285                 return -1;
                                                   >> 286 
                                                   >> 287         return ret;
                                                   >> 288 }
                                                   >> 289 
                                                   >> 290 asmlinkage void syscall_trace_leave(void)
                                                   >> 291 {
                                                   >> 292         if (test_thread_flag(TIF_SYSCALL_TRACE))
                                                   >> 293                 ptrace_report_syscall_exit(task_pt_regs(current), 0);
                                                   >> 294 }
                                                   >> 295 
                                                   >> 296 #if defined(CONFIG_BINFMT_ELF_FDPIC) && defined(CONFIG_ELF_CORE)
                                                   >> 297 /*
                                                   >> 298  * Currently the only thing that needs to use regsets for m68k is the
                                                   >> 299  * coredump support of the elf_fdpic loader. Implement the minimum
                                                   >> 300  * definitions required for that.
                                                   >> 301  */
                                                   >> 302 static int m68k_regset_get(struct task_struct *target,
                                                   >> 303                            const struct user_regset *regset,
                                                   >> 304                            struct membuf to)
                                                   >> 305 {
                                                   >> 306         struct pt_regs *ptregs = task_pt_regs(target);
                                                   >> 307         u32 uregs[ELF_NGREG];
                                                   >> 308 
                                                   >> 309         ELF_CORE_COPY_REGS(uregs, ptregs);
                                                   >> 310         return membuf_write(&to, uregs, sizeof(uregs));
                                                   >> 311 }
                                                   >> 312 
                                                   >> 313 enum m68k_regset {
                                                   >> 314         REGSET_GPR,
                                                   >> 315 #ifdef CONFIG_FPU
                                                   >> 316         REGSET_FPU,
                                                   >> 317 #endif
                                                   >> 318 };
                                                   >> 319 
                                                   >> 320 static const struct user_regset m68k_user_regsets[] = {
                                                   >> 321         [REGSET_GPR] = {
                                                   >> 322                 .core_note_type = NT_PRSTATUS,
                                                   >> 323                 .n = ELF_NGREG,
                                                   >> 324                 .size = sizeof(u32),
                                                   >> 325                 .align = sizeof(u16),
                                                   >> 326                 .regset_get = m68k_regset_get,
                                                   >> 327         },
                                                   >> 328 #ifdef CONFIG_FPU
                                                   >> 329         [REGSET_FPU] = {
                                                   >> 330                 .core_note_type = NT_PRFPREG,
                                                   >> 331                 .n = sizeof(struct user_m68kfp_struct) / sizeof(u32),
                                                   >> 332                 .size = sizeof(u32),
                                                   >> 333                 .align = sizeof(u32),
                                                   >> 334         }
                                                   >> 335 #endif /* CONFIG_FPU */
                                                   >> 336 };
                                                   >> 337 
                                                   >> 338 static const struct user_regset_view user_m68k_view = {
                                                   >> 339         .name = "m68k",
                                                   >> 340         .e_machine = EM_68K,
                                                   >> 341         .ei_osabi = ELF_OSABI,
                                                   >> 342         .regsets = m68k_user_regsets,
                                                   >> 343         .n = ARRAY_SIZE(m68k_user_regsets)
                                                   >> 344 };
                                                   >> 345 
                                                   >> 346 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
 28 {                                                 347 {
 29         const struct pt_regs_offset *roff;     !! 348         return &user_m68k_view;
 30         for (roff = regoffset_table; roff->nam << 
 31                 if (roff->offset == offset)    << 
 32                         return roff->name;     << 
 33         return NULL;                           << 
 34 }                                                 349 }
                                                   >> 350 #endif /* CONFIG_BINFMT_ELF_FDPIC && CONFIG_ELF_CORE */
 35                                                   351 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php