0001
0002
0003
0004
0005
0006 #include <linux/ptrace.h>
0007 #include <linux/sched/task_stack.h>
0008 #include <linux/regset.h>
0009 #include <linux/unistd.h>
0010 #include <linux/elf.h>
0011
0012 #define CREATE_TRACE_POINTS
0013 #include <trace/events/syscalls.h>
0014
0015 struct pt_regs_offset {
0016 const char *name;
0017 int offset;
0018 };
0019
0020 #define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)}
0021 #define REG_OFFSET_END {.name = NULL, .offset = 0}
0022
0023 #ifdef CONFIG_ISA_ARCOMPACT
0024 static const struct pt_regs_offset regoffset_table[] = {
0025 REG_OFFSET_NAME(bta),
0026 REG_OFFSET_NAME(lp_start),
0027 REG_OFFSET_NAME(lp_end),
0028 REG_OFFSET_NAME(lp_count),
0029 REG_OFFSET_NAME(status32),
0030 REG_OFFSET_NAME(ret),
0031 REG_OFFSET_NAME(blink),
0032 REG_OFFSET_NAME(fp),
0033 REG_OFFSET_NAME(r26),
0034 REG_OFFSET_NAME(r12),
0035 REG_OFFSET_NAME(r11),
0036 REG_OFFSET_NAME(r10),
0037 REG_OFFSET_NAME(r9),
0038 REG_OFFSET_NAME(r8),
0039 REG_OFFSET_NAME(r7),
0040 REG_OFFSET_NAME(r6),
0041 REG_OFFSET_NAME(r5),
0042 REG_OFFSET_NAME(r4),
0043 REG_OFFSET_NAME(r3),
0044 REG_OFFSET_NAME(r2),
0045 REG_OFFSET_NAME(r1),
0046 REG_OFFSET_NAME(r0),
0047 REG_OFFSET_NAME(sp),
0048 REG_OFFSET_NAME(orig_r0),
0049 REG_OFFSET_NAME(event),
0050 REG_OFFSET_NAME(user_r25),
0051 REG_OFFSET_END,
0052 };
0053
0054 #else
0055
0056 static const struct pt_regs_offset regoffset_table[] = {
0057 REG_OFFSET_NAME(orig_r0),
0058 REG_OFFSET_NAME(event),
0059 REG_OFFSET_NAME(bta),
0060 REG_OFFSET_NAME(user_r25),
0061 REG_OFFSET_NAME(r26),
0062 REG_OFFSET_NAME(fp),
0063 REG_OFFSET_NAME(sp),
0064 REG_OFFSET_NAME(r12),
0065 REG_OFFSET_NAME(r30),
0066 #ifdef CONFIG_ARC_HAS_ACCL_REGS
0067 REG_OFFSET_NAME(r58),
0068 REG_OFFSET_NAME(r59),
0069 #endif
0070 #ifdef CONFIG_ARC_DSP_SAVE_RESTORE_REGS
0071 REG_OFFSET_NAME(DSP_CTRL),
0072 #endif
0073 REG_OFFSET_NAME(r0),
0074 REG_OFFSET_NAME(r1),
0075 REG_OFFSET_NAME(r2),
0076 REG_OFFSET_NAME(r3),
0077 REG_OFFSET_NAME(r4),
0078 REG_OFFSET_NAME(r5),
0079 REG_OFFSET_NAME(r6),
0080 REG_OFFSET_NAME(r7),
0081 REG_OFFSET_NAME(r8),
0082 REG_OFFSET_NAME(r9),
0083 REG_OFFSET_NAME(r10),
0084 REG_OFFSET_NAME(r11),
0085 REG_OFFSET_NAME(blink),
0086 REG_OFFSET_NAME(lp_end),
0087 REG_OFFSET_NAME(lp_start),
0088 REG_OFFSET_NAME(lp_count),
0089 REG_OFFSET_NAME(ei),
0090 REG_OFFSET_NAME(ldi),
0091 REG_OFFSET_NAME(jli),
0092 REG_OFFSET_NAME(ret),
0093 REG_OFFSET_NAME(status32),
0094 REG_OFFSET_END,
0095 };
0096 #endif
0097
0098 static struct callee_regs *task_callee_regs(struct task_struct *tsk)
0099 {
0100 struct callee_regs *tmp = (struct callee_regs *)tsk->thread.callee_reg;
0101 return tmp;
0102 }
0103
0104 static int genregs_get(struct task_struct *target,
0105 const struct user_regset *regset,
0106 struct membuf to)
0107 {
0108 const struct pt_regs *ptregs = task_pt_regs(target);
0109 const struct callee_regs *cregs = task_callee_regs(target);
0110 unsigned int stop_pc_val;
0111
0112 membuf_zero(&to, 4);
0113 membuf_store(&to, ptregs->bta);
0114 membuf_store(&to, ptregs->lp_start);
0115 membuf_store(&to, ptregs->lp_end);
0116 membuf_store(&to, ptregs->lp_count);
0117 membuf_store(&to, ptregs->status32);
0118 membuf_store(&to, ptregs->ret);
0119 membuf_store(&to, ptregs->blink);
0120 membuf_store(&to, ptregs->fp);
0121 membuf_store(&to, ptregs->r26);
0122 membuf_store(&to, ptregs->r12);
0123 membuf_store(&to, ptregs->r11);
0124 membuf_store(&to, ptregs->r10);
0125 membuf_store(&to, ptregs->r9);
0126 membuf_store(&to, ptregs->r8);
0127 membuf_store(&to, ptregs->r7);
0128 membuf_store(&to, ptregs->r6);
0129 membuf_store(&to, ptregs->r5);
0130 membuf_store(&to, ptregs->r4);
0131 membuf_store(&to, ptregs->r3);
0132 membuf_store(&to, ptregs->r2);
0133 membuf_store(&to, ptregs->r1);
0134 membuf_store(&to, ptregs->r0);
0135 membuf_store(&to, ptregs->sp);
0136 membuf_zero(&to, 4);
0137 membuf_store(&to, cregs->r25);
0138 membuf_store(&to, cregs->r24);
0139 membuf_store(&to, cregs->r23);
0140 membuf_store(&to, cregs->r22);
0141 membuf_store(&to, cregs->r21);
0142 membuf_store(&to, cregs->r20);
0143 membuf_store(&to, cregs->r19);
0144 membuf_store(&to, cregs->r18);
0145 membuf_store(&to, cregs->r17);
0146 membuf_store(&to, cregs->r16);
0147 membuf_store(&to, cregs->r15);
0148 membuf_store(&to, cregs->r14);
0149 membuf_store(&to, cregs->r13);
0150 membuf_store(&to, target->thread.fault_address);
0151
0152 if (in_brkpt_trap(ptregs)) {
0153 stop_pc_val = target->thread.fault_address;
0154 pr_debug("\t\tstop_pc (brk-pt)\n");
0155 } else {
0156 stop_pc_val = ptregs->ret;
0157 pr_debug("\t\tstop_pc (others)\n");
0158 }
0159
0160 return membuf_store(&to, stop_pc_val);
0161 }
0162
0163 static int genregs_set(struct task_struct *target,
0164 const struct user_regset *regset,
0165 unsigned int pos, unsigned int count,
0166 const void *kbuf, const void __user *ubuf)
0167 {
0168 const struct pt_regs *ptregs = task_pt_regs(target);
0169 const struct callee_regs *cregs = task_callee_regs(target);
0170 int ret = 0;
0171
0172 #define REG_IN_CHUNK(FIRST, NEXT, PTR) \
0173 if (!ret) \
0174 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, \
0175 (void *)(PTR), \
0176 offsetof(struct user_regs_struct, FIRST), \
0177 offsetof(struct user_regs_struct, NEXT));
0178
0179 #define REG_IN_ONE(LOC, PTR) \
0180 if (!ret) \
0181 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, \
0182 (void *)(PTR), \
0183 offsetof(struct user_regs_struct, LOC), \
0184 offsetof(struct user_regs_struct, LOC) + 4);
0185
0186 #define REG_IGNORE_ONE(LOC) \
0187 if (!ret) \
0188 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, \
0189 offsetof(struct user_regs_struct, LOC), \
0190 offsetof(struct user_regs_struct, LOC) + 4);
0191
0192 REG_IGNORE_ONE(pad);
0193
0194 REG_IN_ONE(scratch.bta, &ptregs->bta);
0195 REG_IN_ONE(scratch.lp_start, &ptregs->lp_start);
0196 REG_IN_ONE(scratch.lp_end, &ptregs->lp_end);
0197 REG_IN_ONE(scratch.lp_count, &ptregs->lp_count);
0198
0199 REG_IGNORE_ONE(scratch.status32);
0200
0201 REG_IN_ONE(scratch.ret, &ptregs->ret);
0202 REG_IN_ONE(scratch.blink, &ptregs->blink);
0203 REG_IN_ONE(scratch.fp, &ptregs->fp);
0204 REG_IN_ONE(scratch.gp, &ptregs->r26);
0205 REG_IN_ONE(scratch.r12, &ptregs->r12);
0206 REG_IN_ONE(scratch.r11, &ptregs->r11);
0207 REG_IN_ONE(scratch.r10, &ptregs->r10);
0208 REG_IN_ONE(scratch.r9, &ptregs->r9);
0209 REG_IN_ONE(scratch.r8, &ptregs->r8);
0210 REG_IN_ONE(scratch.r7, &ptregs->r7);
0211 REG_IN_ONE(scratch.r6, &ptregs->r6);
0212 REG_IN_ONE(scratch.r5, &ptregs->r5);
0213 REG_IN_ONE(scratch.r4, &ptregs->r4);
0214 REG_IN_ONE(scratch.r3, &ptregs->r3);
0215 REG_IN_ONE(scratch.r2, &ptregs->r2);
0216 REG_IN_ONE(scratch.r1, &ptregs->r1);
0217 REG_IN_ONE(scratch.r0, &ptregs->r0);
0218 REG_IN_ONE(scratch.sp, &ptregs->sp);
0219
0220 REG_IGNORE_ONE(pad2);
0221
0222 REG_IN_ONE(callee.r25, &cregs->r25);
0223 REG_IN_ONE(callee.r24, &cregs->r24);
0224 REG_IN_ONE(callee.r23, &cregs->r23);
0225 REG_IN_ONE(callee.r22, &cregs->r22);
0226 REG_IN_ONE(callee.r21, &cregs->r21);
0227 REG_IN_ONE(callee.r20, &cregs->r20);
0228 REG_IN_ONE(callee.r19, &cregs->r19);
0229 REG_IN_ONE(callee.r18, &cregs->r18);
0230 REG_IN_ONE(callee.r17, &cregs->r17);
0231 REG_IN_ONE(callee.r16, &cregs->r16);
0232 REG_IN_ONE(callee.r15, &cregs->r15);
0233 REG_IN_ONE(callee.r14, &cregs->r14);
0234 REG_IN_ONE(callee.r13, &cregs->r13);
0235
0236 REG_IGNORE_ONE(efa);
0237 REG_IGNORE_ONE(stop_pc);
0238
0239 return ret;
0240 }
0241
0242 #ifdef CONFIG_ISA_ARCV2
0243 static int arcv2regs_get(struct task_struct *target,
0244 const struct user_regset *regset,
0245 struct membuf to)
0246 {
0247 const struct pt_regs *regs = task_pt_regs(target);
0248
0249 if (IS_ENABLED(CONFIG_ARC_HAS_ACCL_REGS))
0250
0251
0252
0253
0254 return membuf_write(&to, ®s->r30, sizeof(struct user_regs_arcv2));
0255
0256
0257 membuf_write(&to, ®s->r30, 4);
0258 return membuf_zero(&to, sizeof(struct user_regs_arcv2) - 4);
0259 }
0260
0261 static int arcv2regs_set(struct task_struct *target,
0262 const struct user_regset *regset,
0263 unsigned int pos, unsigned int count,
0264 const void *kbuf, const void __user *ubuf)
0265 {
0266 const struct pt_regs *regs = task_pt_regs(target);
0267 int ret, copy_sz;
0268
0269 if (IS_ENABLED(CONFIG_ARC_HAS_ACCL_REGS))
0270 copy_sz = sizeof(struct user_regs_arcv2);
0271 else
0272 copy_sz = 4;
0273
0274 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, (void *)®s->r30,
0275 0, copy_sz);
0276
0277 return ret;
0278 }
0279
0280 #endif
0281
0282 enum arc_getset {
0283 REGSET_CMN,
0284 REGSET_ARCV2,
0285 };
0286
0287 static const struct user_regset arc_regsets[] = {
0288 [REGSET_CMN] = {
0289 .core_note_type = NT_PRSTATUS,
0290 .n = ELF_NGREG,
0291 .size = sizeof(unsigned long),
0292 .align = sizeof(unsigned long),
0293 .regset_get = genregs_get,
0294 .set = genregs_set,
0295 },
0296 #ifdef CONFIG_ISA_ARCV2
0297 [REGSET_ARCV2] = {
0298 .core_note_type = NT_ARC_V2,
0299 .n = ELF_ARCV2REG,
0300 .size = sizeof(unsigned long),
0301 .align = sizeof(unsigned long),
0302 .regset_get = arcv2regs_get,
0303 .set = arcv2regs_set,
0304 },
0305 #endif
0306 };
0307
0308 static const struct user_regset_view user_arc_view = {
0309 .name = "arc",
0310 .e_machine = EM_ARC_INUSE,
0311 .regsets = arc_regsets,
0312 .n = ARRAY_SIZE(arc_regsets)
0313 };
0314
0315 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
0316 {
0317 return &user_arc_view;
0318 }
0319
0320 void ptrace_disable(struct task_struct *child)
0321 {
0322 }
0323
0324 long arch_ptrace(struct task_struct *child, long request,
0325 unsigned long addr, unsigned long data)
0326 {
0327 int ret = -EIO;
0328
0329 pr_debug("REQ=%ld: ADDR =0x%lx, DATA=0x%lx)\n", request, addr, data);
0330
0331 switch (request) {
0332 case PTRACE_GET_THREAD_AREA:
0333 ret = put_user(task_thread_info(child)->thr_ptr,
0334 (unsigned long __user *)data);
0335 break;
0336 default:
0337 ret = ptrace_request(child, request, addr, data);
0338 break;
0339 }
0340
0341 return ret;
0342 }
0343
0344 asmlinkage int syscall_trace_entry(struct pt_regs *regs)
0345 {
0346 if (test_thread_flag(TIF_SYSCALL_TRACE))
0347 if (ptrace_report_syscall_entry(regs))
0348 return ULONG_MAX;
0349
0350 #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
0351 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
0352 trace_sys_enter(regs, syscall_get_nr(current, regs));
0353 #endif
0354
0355 return regs->r8;
0356 }
0357
0358 asmlinkage void syscall_trace_exit(struct pt_regs *regs)
0359 {
0360 if (test_thread_flag(TIF_SYSCALL_TRACE))
0361 ptrace_report_syscall_exit(regs, 0);
0362
0363 #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
0364 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
0365 trace_sys_exit(regs, regs_return_value(regs));
0366 #endif
0367 }
0368
0369 int regs_query_register_offset(const char *name)
0370 {
0371 const struct pt_regs_offset *roff;
0372
0373 for (roff = regoffset_table; roff->name != NULL; roff++)
0374 if (!strcmp(roff->name, name))
0375 return roff->offset;
0376 return -EINVAL;
0377 }
0378
0379 const char *regs_query_register_name(unsigned int offset)
0380 {
0381 const struct pt_regs_offset *roff;
0382 for (roff = regoffset_table; roff->name != NULL; roff++)
0383 if (roff->offset == offset)
0384 return roff->name;
0385 return NULL;
0386 }
0387
0388 bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr)
0389 {
0390 return (addr & ~(THREAD_SIZE - 1)) ==
0391 (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1));
0392 }
0393
0394 unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
0395 {
0396 unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
0397
0398 addr += n;
0399 if (regs_within_kernel_stack(regs, (unsigned long)addr))
0400 return *addr;
0401 else
0402 return 0;
0403 }