2 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
9 #include <linux/ptrace.h>
10 #include <linux/tracehook.h>
11 #include <linux/regset.h>
12 #include <linux/unistd.h>
13 #include <linux/elf.h>
15 static struct callee_regs
*task_callee_regs(struct task_struct
*tsk
)
17 struct callee_regs
*tmp
= (struct callee_regs
*)tsk
->thread
.callee_reg
;
21 static int genregs_get(struct task_struct
*target
,
22 const struct user_regset
*regset
,
23 unsigned int pos
, unsigned int count
,
24 void *kbuf
, void __user
*ubuf
)
26 const struct pt_regs
*ptregs
= task_pt_regs(target
);
27 const struct callee_regs
*cregs
= task_callee_regs(target
);
29 unsigned int stop_pc_val
;
31 #define REG_O_CHUNK(START, END, PTR) \
33 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, PTR, \
34 offsetof(struct user_regs_struct, START), \
35 offsetof(struct user_regs_struct, END));
37 #define REG_O_ONE(LOC, PTR) \
39 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, PTR, \
40 offsetof(struct user_regs_struct, LOC), \
41 offsetof(struct user_regs_struct, LOC) + 4);
43 #define REG_O_ZERO(LOC) \
45 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, \
46 offsetof(struct user_regs_struct, LOC), \
47 offsetof(struct user_regs_struct, LOC) + 4);
50 REG_O_CHUNK(scratch
, callee
, ptregs
);
52 REG_O_CHUNK(callee
, efa
, cregs
);
53 REG_O_CHUNK(efa
, stop_pc
, &target
->thread
.fault_address
);
56 if (in_brkpt_trap(ptregs
)) {
57 stop_pc_val
= target
->thread
.fault_address
;
58 pr_debug("\t\tstop_pc (brk-pt)\n");
60 stop_pc_val
= ptregs
->ret
;
61 pr_debug("\t\tstop_pc (others)\n");
64 REG_O_ONE(stop_pc
, &stop_pc_val
);
70 static int genregs_set(struct task_struct
*target
,
71 const struct user_regset
*regset
,
72 unsigned int pos
, unsigned int count
,
73 const void *kbuf
, const void __user
*ubuf
)
75 const struct pt_regs
*ptregs
= task_pt_regs(target
);
76 const struct callee_regs
*cregs
= task_callee_regs(target
);
79 #define REG_IN_CHUNK(FIRST, NEXT, PTR) \
81 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, \
83 offsetof(struct user_regs_struct, FIRST), \
84 offsetof(struct user_regs_struct, NEXT));
86 #define REG_IN_ONE(LOC, PTR) \
88 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, \
90 offsetof(struct user_regs_struct, LOC), \
91 offsetof(struct user_regs_struct, LOC) + 4);
93 #define REG_IGNORE_ONE(LOC) \
95 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, \
96 offsetof(struct user_regs_struct, LOC), \
97 offsetof(struct user_regs_struct, LOC) + 4);
100 /* TBD: disallow updates to STATUS32 etc*/
101 REG_IN_CHUNK(scratch
, pad2
, ptregs
); /* pt_regs[bta..sp] */
102 REG_IGNORE_ONE(pad2
);
103 REG_IN_CHUNK(callee
, efa
, cregs
); /* callee_regs[r25..r13] */
104 REG_IGNORE_ONE(efa
); /* efa update invalid */
105 REG_IGNORE_ONE(stop_pc
); /* PC updated via @ret */
114 static const struct user_regset arc_regsets
[] = {
116 .core_note_type
= NT_PRSTATUS
,
118 .size
= sizeof(unsigned long),
119 .align
= sizeof(unsigned long),
125 static const struct user_regset_view user_arc_view
= {
127 .e_machine
= EM_ARCOMPACT
,
128 .regsets
= arc_regsets
,
129 .n
= ARRAY_SIZE(arc_regsets
)
132 const struct user_regset_view
*task_user_regset_view(struct task_struct
*task
)
134 return &user_arc_view
;
137 void ptrace_disable(struct task_struct
*child
)
141 long arch_ptrace(struct task_struct
*child
, long request
,
142 unsigned long addr
, unsigned long data
)
146 pr_debug("REQ=%ld: ADDR =0x%lx, DATA=0x%lx)\n", request
, addr
, data
);
149 case PTRACE_GET_THREAD_AREA
:
150 ret
= put_user(task_thread_info(child
)->thr_ptr
,
151 (unsigned long __user
*)data
);
154 ret
= ptrace_request(child
, request
, addr
, data
);
161 asmlinkage
int syscall_trace_entry(struct pt_regs
*regs
)
163 if (tracehook_report_syscall_entry(regs
))
169 asmlinkage
void syscall_trace_exit(struct pt_regs
*regs
)
171 tracehook_report_syscall_exit(regs
, 0);