ptrace.c (10686B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) 4 */ 5 6#include <linux/ptrace.h> 7#include <linux/sched/task_stack.h> 8#include <linux/regset.h> 9#include <linux/unistd.h> 10#include <linux/elf.h> 11 12#define CREATE_TRACE_POINTS 13#include <trace/events/syscalls.h> 14 15struct pt_regs_offset { 16 const char *name; 17 int offset; 18}; 19 20#define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)} 21#define REG_OFFSET_END {.name = NULL, .offset = 0} 22 23#ifdef CONFIG_ISA_ARCOMPACT 24static const struct pt_regs_offset regoffset_table[] = { 25 REG_OFFSET_NAME(bta), 26 REG_OFFSET_NAME(lp_start), 27 REG_OFFSET_NAME(lp_end), 28 REG_OFFSET_NAME(lp_count), 29 REG_OFFSET_NAME(status32), 30 REG_OFFSET_NAME(ret), 31 REG_OFFSET_NAME(blink), 32 REG_OFFSET_NAME(fp), 33 REG_OFFSET_NAME(r26), 34 REG_OFFSET_NAME(r12), 35 REG_OFFSET_NAME(r11), 36 REG_OFFSET_NAME(r10), 37 REG_OFFSET_NAME(r9), 38 REG_OFFSET_NAME(r8), 39 REG_OFFSET_NAME(r7), 40 REG_OFFSET_NAME(r6), 41 REG_OFFSET_NAME(r5), 42 REG_OFFSET_NAME(r4), 43 REG_OFFSET_NAME(r3), 44 REG_OFFSET_NAME(r2), 45 REG_OFFSET_NAME(r1), 46 REG_OFFSET_NAME(r0), 47 REG_OFFSET_NAME(sp), 48 REG_OFFSET_NAME(orig_r0), 49 REG_OFFSET_NAME(event), 50 REG_OFFSET_NAME(user_r25), 51 REG_OFFSET_END, 52}; 53 54#else 55 56static const struct pt_regs_offset regoffset_table[] = { 57 REG_OFFSET_NAME(orig_r0), 58 REG_OFFSET_NAME(event), 59 REG_OFFSET_NAME(bta), 60 REG_OFFSET_NAME(user_r25), 61 REG_OFFSET_NAME(r26), 62 REG_OFFSET_NAME(fp), 63 REG_OFFSET_NAME(sp), 64 REG_OFFSET_NAME(r12), 65 REG_OFFSET_NAME(r30), 66#ifdef CONFIG_ARC_HAS_ACCL_REGS 67 REG_OFFSET_NAME(r58), 68 REG_OFFSET_NAME(r59), 69#endif 70#ifdef CONFIG_ARC_DSP_SAVE_RESTORE_REGS 71 REG_OFFSET_NAME(DSP_CTRL), 72#endif 73 REG_OFFSET_NAME(r0), 74 REG_OFFSET_NAME(r1), 75 REG_OFFSET_NAME(r2), 76 REG_OFFSET_NAME(r3), 77 REG_OFFSET_NAME(r4), 78 REG_OFFSET_NAME(r5), 79 REG_OFFSET_NAME(r6), 80 REG_OFFSET_NAME(r7), 81 REG_OFFSET_NAME(r8), 82 REG_OFFSET_NAME(r9), 83 REG_OFFSET_NAME(r10), 84 REG_OFFSET_NAME(r11), 85 REG_OFFSET_NAME(blink), 86 REG_OFFSET_NAME(lp_end), 87 REG_OFFSET_NAME(lp_start), 88 REG_OFFSET_NAME(lp_count), 89 REG_OFFSET_NAME(ei), 90 REG_OFFSET_NAME(ldi), 91 REG_OFFSET_NAME(jli), 92 REG_OFFSET_NAME(ret), 93 REG_OFFSET_NAME(status32), 94 REG_OFFSET_END, 95}; 96#endif 97 98static struct callee_regs *task_callee_regs(struct task_struct *tsk) 99{ 100 struct callee_regs *tmp = (struct callee_regs *)tsk->thread.callee_reg; 101 return tmp; 102} 103 104static int genregs_get(struct task_struct *target, 105 const struct user_regset *regset, 106 struct membuf to) 107{ 108 const struct pt_regs *ptregs = task_pt_regs(target); 109 const struct callee_regs *cregs = task_callee_regs(target); 110 unsigned int stop_pc_val; 111 112 membuf_zero(&to, 4); // pad 113 membuf_store(&to, ptregs->bta); 114 membuf_store(&to, ptregs->lp_start); 115 membuf_store(&to, ptregs->lp_end); 116 membuf_store(&to, ptregs->lp_count); 117 membuf_store(&to, ptregs->status32); 118 membuf_store(&to, ptregs->ret); 119 membuf_store(&to, ptregs->blink); 120 membuf_store(&to, ptregs->fp); 121 membuf_store(&to, ptregs->r26); // gp 122 membuf_store(&to, ptregs->r12); 123 membuf_store(&to, ptregs->r11); 124 membuf_store(&to, ptregs->r10); 125 membuf_store(&to, ptregs->r9); 126 membuf_store(&to, ptregs->r8); 127 membuf_store(&to, ptregs->r7); 128 membuf_store(&to, ptregs->r6); 129 membuf_store(&to, ptregs->r5); 130 membuf_store(&to, ptregs->r4); 131 membuf_store(&to, ptregs->r3); 132 membuf_store(&to, ptregs->r2); 133 membuf_store(&to, ptregs->r1); 134 membuf_store(&to, ptregs->r0); 135 membuf_store(&to, ptregs->sp); 136 membuf_zero(&to, 4); // pad2 137 membuf_store(&to, cregs->r25); 138 membuf_store(&to, cregs->r24); 139 membuf_store(&to, cregs->r23); 140 membuf_store(&to, cregs->r22); 141 membuf_store(&to, cregs->r21); 142 membuf_store(&to, cregs->r20); 143 membuf_store(&to, cregs->r19); 144 membuf_store(&to, cregs->r18); 145 membuf_store(&to, cregs->r17); 146 membuf_store(&to, cregs->r16); 147 membuf_store(&to, cregs->r15); 148 membuf_store(&to, cregs->r14); 149 membuf_store(&to, cregs->r13); 150 membuf_store(&to, target->thread.fault_address); // efa 151 152 if (in_brkpt_trap(ptregs)) { 153 stop_pc_val = target->thread.fault_address; 154 pr_debug("\t\tstop_pc (brk-pt)\n"); 155 } else { 156 stop_pc_val = ptregs->ret; 157 pr_debug("\t\tstop_pc (others)\n"); 158 } 159 160 return membuf_store(&to, stop_pc_val); // stop_pc 161} 162 163static int genregs_set(struct task_struct *target, 164 const struct user_regset *regset, 165 unsigned int pos, unsigned int count, 166 const void *kbuf, const void __user *ubuf) 167{ 168 const struct pt_regs *ptregs = task_pt_regs(target); 169 const struct callee_regs *cregs = task_callee_regs(target); 170 int ret = 0; 171 172#define REG_IN_CHUNK(FIRST, NEXT, PTR) \ 173 if (!ret) \ 174 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, \ 175 (void *)(PTR), \ 176 offsetof(struct user_regs_struct, FIRST), \ 177 offsetof(struct user_regs_struct, NEXT)); 178 179#define REG_IN_ONE(LOC, PTR) \ 180 if (!ret) \ 181 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, \ 182 (void *)(PTR), \ 183 offsetof(struct user_regs_struct, LOC), \ 184 offsetof(struct user_regs_struct, LOC) + 4); 185 186#define REG_IGNORE_ONE(LOC) \ 187 if (!ret) \ 188 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, \ 189 offsetof(struct user_regs_struct, LOC), \ 190 offsetof(struct user_regs_struct, LOC) + 4); 191 192 REG_IGNORE_ONE(pad); 193 194 REG_IN_ONE(scratch.bta, &ptregs->bta); 195 REG_IN_ONE(scratch.lp_start, &ptregs->lp_start); 196 REG_IN_ONE(scratch.lp_end, &ptregs->lp_end); 197 REG_IN_ONE(scratch.lp_count, &ptregs->lp_count); 198 199 REG_IGNORE_ONE(scratch.status32); 200 201 REG_IN_ONE(scratch.ret, &ptregs->ret); 202 REG_IN_ONE(scratch.blink, &ptregs->blink); 203 REG_IN_ONE(scratch.fp, &ptregs->fp); 204 REG_IN_ONE(scratch.gp, &ptregs->r26); 205 REG_IN_ONE(scratch.r12, &ptregs->r12); 206 REG_IN_ONE(scratch.r11, &ptregs->r11); 207 REG_IN_ONE(scratch.r10, &ptregs->r10); 208 REG_IN_ONE(scratch.r9, &ptregs->r9); 209 REG_IN_ONE(scratch.r8, &ptregs->r8); 210 REG_IN_ONE(scratch.r7, &ptregs->r7); 211 REG_IN_ONE(scratch.r6, &ptregs->r6); 212 REG_IN_ONE(scratch.r5, &ptregs->r5); 213 REG_IN_ONE(scratch.r4, &ptregs->r4); 214 REG_IN_ONE(scratch.r3, &ptregs->r3); 215 REG_IN_ONE(scratch.r2, &ptregs->r2); 216 REG_IN_ONE(scratch.r1, &ptregs->r1); 217 REG_IN_ONE(scratch.r0, &ptregs->r0); 218 REG_IN_ONE(scratch.sp, &ptregs->sp); 219 220 REG_IGNORE_ONE(pad2); 221 222 REG_IN_ONE(callee.r25, &cregs->r25); 223 REG_IN_ONE(callee.r24, &cregs->r24); 224 REG_IN_ONE(callee.r23, &cregs->r23); 225 REG_IN_ONE(callee.r22, &cregs->r22); 226 REG_IN_ONE(callee.r21, &cregs->r21); 227 REG_IN_ONE(callee.r20, &cregs->r20); 228 REG_IN_ONE(callee.r19, &cregs->r19); 229 REG_IN_ONE(callee.r18, &cregs->r18); 230 REG_IN_ONE(callee.r17, &cregs->r17); 231 REG_IN_ONE(callee.r16, &cregs->r16); 232 REG_IN_ONE(callee.r15, &cregs->r15); 233 REG_IN_ONE(callee.r14, &cregs->r14); 234 REG_IN_ONE(callee.r13, &cregs->r13); 235 236 REG_IGNORE_ONE(efa); /* efa update invalid */ 237 REG_IGNORE_ONE(stop_pc); /* PC updated via @ret */ 238 239 return ret; 240} 241 242#ifdef CONFIG_ISA_ARCV2 243static int arcv2regs_get(struct task_struct *target, 244 const struct user_regset *regset, 245 struct membuf to) 246{ 247 const struct pt_regs *regs = task_pt_regs(target); 248 249 if (IS_ENABLED(CONFIG_ARC_HAS_ACCL_REGS)) 250 /* 251 * itemized copy not needed like above as layout of regs (r30,r58,r59) 252 * is exactly same in kernel (pt_regs) and userspace (user_regs_arcv2) 253 */ 254 return membuf_write(&to, ®s->r30, sizeof(struct user_regs_arcv2)); 255 256 257 membuf_write(&to, ®s->r30, 4); /* r30 only */ 258 return membuf_zero(&to, sizeof(struct user_regs_arcv2) - 4); 259} 260 261static int arcv2regs_set(struct task_struct *target, 262 const struct user_regset *regset, 263 unsigned int pos, unsigned int count, 264 const void *kbuf, const void __user *ubuf) 265{ 266 const struct pt_regs *regs = task_pt_regs(target); 267 int ret, copy_sz; 268 269 if (IS_ENABLED(CONFIG_ARC_HAS_ACCL_REGS)) 270 copy_sz = sizeof(struct user_regs_arcv2); 271 else 272 copy_sz = 4; /* r30 only */ 273 274 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, (void *)®s->r30, 275 0, copy_sz); 276 277 return ret; 278} 279 280#endif 281 282enum arc_getset { 283 REGSET_CMN, 284 REGSET_ARCV2, 285}; 286 287static const struct user_regset arc_regsets[] = { 288 [REGSET_CMN] = { 289 .core_note_type = NT_PRSTATUS, 290 .n = ELF_NGREG, 291 .size = sizeof(unsigned long), 292 .align = sizeof(unsigned long), 293 .regset_get = genregs_get, 294 .set = genregs_set, 295 }, 296#ifdef CONFIG_ISA_ARCV2 297 [REGSET_ARCV2] = { 298 .core_note_type = NT_ARC_V2, 299 .n = ELF_ARCV2REG, 300 .size = sizeof(unsigned long), 301 .align = sizeof(unsigned long), 302 .regset_get = arcv2regs_get, 303 .set = arcv2regs_set, 304 }, 305#endif 306}; 307 308static const struct user_regset_view user_arc_view = { 309 .name = "arc", 310 .e_machine = EM_ARC_INUSE, 311 .regsets = arc_regsets, 312 .n = ARRAY_SIZE(arc_regsets) 313}; 314 315const struct user_regset_view *task_user_regset_view(struct task_struct *task) 316{ 317 return &user_arc_view; 318} 319 320void ptrace_disable(struct task_struct *child) 321{ 322} 323 324long arch_ptrace(struct task_struct *child, long request, 325 unsigned long addr, unsigned long data) 326{ 327 int ret = -EIO; 328 329 pr_debug("REQ=%ld: ADDR =0x%lx, DATA=0x%lx)\n", request, addr, data); 330 331 switch (request) { 332 case PTRACE_GET_THREAD_AREA: 333 ret = put_user(task_thread_info(child)->thr_ptr, 334 (unsigned long __user *)data); 335 break; 336 default: 337 ret = ptrace_request(child, request, addr, data); 338 break; 339 } 340 341 return ret; 342} 343 344asmlinkage int syscall_trace_entry(struct pt_regs *regs) 345{ 346 if (test_thread_flag(TIF_SYSCALL_TRACE)) 347 if (ptrace_report_syscall_entry(regs)) 348 return ULONG_MAX; 349 350#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS 351 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) 352 trace_sys_enter(regs, syscall_get_nr(current, regs)); 353#endif 354 355 return regs->r8; 356} 357 358asmlinkage void syscall_trace_exit(struct pt_regs *regs) 359{ 360 if (test_thread_flag(TIF_SYSCALL_TRACE)) 361 ptrace_report_syscall_exit(regs, 0); 362 363#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS 364 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) 365 trace_sys_exit(regs, regs_return_value(regs)); 366#endif 367} 368 369int regs_query_register_offset(const char *name) 370{ 371 const struct pt_regs_offset *roff; 372 373 for (roff = regoffset_table; roff->name != NULL; roff++) 374 if (!strcmp(roff->name, name)) 375 return roff->offset; 376 return -EINVAL; 377} 378 379const char *regs_query_register_name(unsigned int offset) 380{ 381 const struct pt_regs_offset *roff; 382 for (roff = regoffset_table; roff->name != NULL; roff++) 383 if (roff->offset == offset) 384 return roff->name; 385 return NULL; 386} 387 388bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr) 389{ 390 return (addr & ~(THREAD_SIZE - 1)) == 391 (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)); 392} 393 394unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n) 395{ 396 unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs); 397 398 addr += n; 399 if (regs_within_kernel_stack(regs, (unsigned long)addr)) 400 return *addr; 401 else 402 return 0; 403}