diff options
Diffstat (limited to 'include/linux/ptrace.h')
-rw-r--r-- | include/linux/ptrace.h | 48 |
1 files changed, 40 insertions, 8 deletions
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index 7456d7d87a19..e1fb60729979 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h | |||
@@ -27,6 +27,26 @@ | |||
27 | #define PTRACE_GETSIGINFO 0x4202 | 27 | #define PTRACE_GETSIGINFO 0x4202 |
28 | #define PTRACE_SETSIGINFO 0x4203 | 28 | #define PTRACE_SETSIGINFO 0x4203 |
29 | 29 | ||
30 | /* | ||
31 | * Generic ptrace interface that exports the architecture specific regsets | ||
32 | * using the corresponding NT_* types (which are also used in the core dump). | ||
33 | * Please note that the NT_PRSTATUS note type in a core dump contains a full | ||
34 | * 'struct elf_prstatus'. But the user_regset for NT_PRSTATUS contains just the | ||
35 | * elf_gregset_t that is the pr_reg field of 'struct elf_prstatus'. For all the | ||
36 | * other user_regset flavors, the user_regset layout and the ELF core dump note | ||
37 | * payload are exactly the same layout. | ||
38 | * | ||
39 | * This interface usage is as follows: | ||
40 | * struct iovec iov = { buf, len}; | ||
41 | * | ||
42 | * ret = ptrace(PTRACE_GETREGSET/PTRACE_SETREGSET, pid, NT_XXX_TYPE, &iov); | ||
43 | * | ||
44 | * On the successful completion, iov.len will be updated by the kernel, | ||
45 | * specifying how much the kernel has written/read to/from the user's iov.buf. | ||
46 | */ | ||
47 | #define PTRACE_GETREGSET 0x4204 | ||
48 | #define PTRACE_SETREGSET 0x4205 | ||
49 | |||
30 | /* options set using PTRACE_SETOPTIONS */ | 50 | /* options set using PTRACE_SETOPTIONS */ |
31 | #define PTRACE_O_TRACESYSGOOD 0x00000001 | 51 | #define PTRACE_O_TRACESYSGOOD 0x00000001 |
32 | #define PTRACE_O_TRACEFORK 0x00000002 | 52 | #define PTRACE_O_TRACEFORK 0x00000002 |
@@ -105,12 +125,7 @@ static inline int ptrace_reparented(struct task_struct *child) | |||
105 | { | 125 | { |
106 | return child->real_parent != child->parent; | 126 | return child->real_parent != child->parent; |
107 | } | 127 | } |
108 | static inline void ptrace_link(struct task_struct *child, | 128 | |
109 | struct task_struct *new_parent) | ||
110 | { | ||
111 | if (unlikely(child->ptrace)) | ||
112 | __ptrace_link(child, new_parent); | ||
113 | } | ||
114 | static inline void ptrace_unlink(struct task_struct *child) | 129 | static inline void ptrace_unlink(struct task_struct *child) |
115 | { | 130 | { |
116 | if (unlikely(child->ptrace)) | 131 | if (unlikely(child->ptrace)) |
@@ -169,9 +184,9 @@ static inline void ptrace_init_task(struct task_struct *child, bool ptrace) | |||
169 | INIT_LIST_HEAD(&child->ptraced); | 184 | INIT_LIST_HEAD(&child->ptraced); |
170 | child->parent = child->real_parent; | 185 | child->parent = child->real_parent; |
171 | child->ptrace = 0; | 186 | child->ptrace = 0; |
172 | if (unlikely(ptrace)) { | 187 | if (unlikely(ptrace) && (current->ptrace & PT_PTRACED)) { |
173 | child->ptrace = current->ptrace; | 188 | child->ptrace = current->ptrace; |
174 | ptrace_link(child, current->parent); | 189 | __ptrace_link(child, current->parent); |
175 | } | 190 | } |
176 | } | 191 | } |
177 | 192 | ||
@@ -249,6 +264,9 @@ static inline void user_enable_single_step(struct task_struct *task) | |||
249 | static inline void user_disable_single_step(struct task_struct *task) | 264 | static inline void user_disable_single_step(struct task_struct *task) |
250 | { | 265 | { |
251 | } | 266 | } |
267 | #else | ||
268 | extern void user_enable_single_step(struct task_struct *); | ||
269 | extern void user_disable_single_step(struct task_struct *); | ||
252 | #endif /* arch_has_single_step */ | 270 | #endif /* arch_has_single_step */ |
253 | 271 | ||
254 | #ifndef arch_has_block_step | 272 | #ifndef arch_has_block_step |
@@ -276,8 +294,22 @@ static inline void user_enable_block_step(struct task_struct *task) | |||
276 | { | 294 | { |
277 | BUG(); /* This can never be called. */ | 295 | BUG(); /* This can never be called. */ |
278 | } | 296 | } |
297 | #else | ||
298 | extern void user_enable_block_step(struct task_struct *); | ||
279 | #endif /* arch_has_block_step */ | 299 | #endif /* arch_has_block_step */ |
280 | 300 | ||
301 | #ifdef ARCH_HAS_USER_SINGLE_STEP_INFO | ||
302 | extern void user_single_step_siginfo(struct task_struct *tsk, | ||
303 | struct pt_regs *regs, siginfo_t *info); | ||
304 | #else | ||
305 | static inline void user_single_step_siginfo(struct task_struct *tsk, | ||
306 | struct pt_regs *regs, siginfo_t *info) | ||
307 | { | ||
308 | memset(info, 0, sizeof(*info)); | ||
309 | info->si_signo = SIGTRAP; | ||
310 | } | ||
311 | #endif | ||
312 | |||
281 | #ifndef arch_ptrace_stop_needed | 313 | #ifndef arch_ptrace_stop_needed |
282 | /** | 314 | /** |
283 | * arch_ptrace_stop_needed - Decide whether arch_ptrace_stop() should be called | 315 | * arch_ptrace_stop_needed - Decide whether arch_ptrace_stop() should be called |