Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[PATCH 1/14] move user_enable_single_step & co prototypes to linux/ptrace.h

1 view
Skip to first unread message

Christoph Hellwig

unread,
Feb 2, 2010, 2:10:02 PM2/2/10
to
While in theory user_enable_single_step/user_disable_single_step/
user_enable_blockstep could also be provided as an inline or macro there's no
good reason to do so, and having the prototype in one places keeps code size
and confusion down.

Signed-off-by: Christoph Hellwig <h...@lst.de>

Index: linux-2.6/arch/frv/include/asm/ptrace.h
===================================================================
--- linux-2.6.orig/arch/frv/include/asm/ptrace.h 2010-02-02 10:16:57.091253546 +0100
+++ linux-2.6/arch/frv/include/asm/ptrace.h 2010-02-02 10:17:30.928005548 +0100
@@ -84,8 +84,6 @@ extern void show_regs(struct pt_regs *);
#define task_pt_regs(task) ((task)->thread.frame0)

#define arch_has_single_step() (1)
-extern void user_enable_single_step(struct task_struct *);
-extern void user_disable_single_step(struct task_struct *);

#endif /* !__ASSEMBLY__ */
#endif /* __KERNEL__ */
Index: linux-2.6/arch/ia64/include/asm/ptrace.h
===================================================================
--- linux-2.6.orig/arch/ia64/include/asm/ptrace.h 2010-02-02 10:16:57.123254478 +0100
+++ linux-2.6/arch/ia64/include/asm/ptrace.h 2010-02-02 10:20:34.530006509 +0100
@@ -319,11 +319,7 @@ static inline unsigned long user_stack_p
ptrace_attach_sync_user_rbs(child)

#define arch_has_single_step() (1)
- extern void user_enable_single_step(struct task_struct *);
- extern void user_disable_single_step(struct task_struct *);
-
#define arch_has_block_step() (1)
- extern void user_enable_block_step(struct task_struct *);

#endif /* !__KERNEL__ */

Index: linux-2.6/arch/m68k/include/asm/ptrace.h
===================================================================
--- linux-2.6.orig/arch/m68k/include/asm/ptrace.h 2010-02-02 10:16:57.149003358 +0100
+++ linux-2.6/arch/m68k/include/asm/ptrace.h 2010-02-02 10:20:48.940276470 +0100
@@ -85,18 +85,10 @@ struct switch_stack {
#define profile_pc(regs) instruction_pointer(regs)
extern void show_regs(struct pt_regs *);

-/*
- * These are defined as per linux/ptrace.h.
- */
-struct task_struct;
-
#define arch_has_single_step() (1)
-extern void user_enable_single_step(struct task_struct *);
-extern void user_disable_single_step(struct task_struct *);

#ifdef CONFIG_MMU
#define arch_has_block_step() (1)
-extern void user_enable_block_step(struct task_struct *);
#endif

#endif /* __KERNEL__ */
Index: linux-2.6/arch/mn10300/include/asm/ptrace.h
===================================================================
--- linux-2.6.orig/arch/mn10300/include/asm/ptrace.h 2010-02-02 10:16:57.189253666 +0100
+++ linux-2.6/arch/mn10300/include/asm/ptrace.h 2010-02-02 10:18:18.940285108 +0100
@@ -99,8 +99,6 @@ struct task_struct;
extern void show_regs(struct pt_regs *);

#define arch_has_single_step() (1)
-extern void user_enable_single_step(struct task_struct *);
-extern void user_disable_single_step(struct task_struct *);

#endif /* !__ASSEMBLY */

Index: linux-2.6/arch/parisc/include/asm/ptrace.h
===================================================================
--- linux-2.6.orig/arch/parisc/include/asm/ptrace.h 2010-02-02 10:16:57.203254052 +0100
+++ linux-2.6/arch/parisc/include/asm/ptrace.h 2010-02-02 10:20:58.226288061 +0100
@@ -47,13 +47,8 @@ struct pt_regs {

#define task_regs(task) ((struct pt_regs *) ((char *)(task) + TASK_REGS))

-struct task_struct;
#define arch_has_single_step() 1
-void user_disable_single_step(struct task_struct *task);
-void user_enable_single_step(struct task_struct *task);
-
#define arch_has_block_step() 1
-void user_enable_block_step(struct task_struct *task);

/* XXX should we use iaoq[1] or iaoq[0] ? */
#define user_mode(regs) (((regs)->iaoq[0] & 3) ? 1 : 0)
Index: linux-2.6/arch/powerpc/include/asm/ptrace.h
===================================================================
--- linux-2.6.orig/arch/powerpc/include/asm/ptrace.h 2010-02-02 10:16:57.215254253 +0100
+++ linux-2.6/arch/powerpc/include/asm/ptrace.h 2010-02-02 10:21:09.750035376 +0100
@@ -131,15 +131,8 @@ do { \
} while (0)
#endif /* __powerpc64__ */

-/*
- * These are defined as per linux/ptrace.h, which see.
- */
#define arch_has_single_step() (1)
#define arch_has_block_step() (!cpu_has_feature(CPU_FTR_601))
-extern void user_enable_single_step(struct task_struct *);
-extern void user_enable_block_step(struct task_struct *);
-extern void user_disable_single_step(struct task_struct *);
-
#define ARCH_HAS_USER_SINGLE_STEP_INFO

#endif /* __ASSEMBLY__ */
Index: linux-2.6/arch/s390/include/asm/ptrace.h
===================================================================
--- linux-2.6.orig/arch/s390/include/asm/ptrace.h 2010-02-02 10:16:57.228253185 +0100
+++ linux-2.6/arch/s390/include/asm/ptrace.h 2010-02-02 10:18:36.397283176 +0100
@@ -489,10 +489,6 @@ struct user_regs_struct
* These are defined as per linux/ptrace.h, which see.
*/
#define arch_has_single_step() (1)
-struct task_struct;
-extern void user_enable_single_step(struct task_struct *);
-extern void user_disable_single_step(struct task_struct *);
-
#define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
#define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN)
#define user_stack_pointer(regs)((regs)->gprs[15])
Index: linux-2.6/arch/score/include/asm/ptrace.h
===================================================================
--- linux-2.6.orig/arch/score/include/asm/ptrace.h 2010-02-02 10:16:57.242254270 +0100
+++ linux-2.6/arch/score/include/asm/ptrace.h 2010-02-02 10:18:48.080256587 +0100
@@ -90,8 +90,7 @@ extern int read_tsk_short(struct task_st
unsigned short *);

#define arch_has_single_step() (1)
-extern void user_enable_single_step(struct task_struct *);
-extern void user_disable_single_step(struct task_struct *);
+
#endif /* __KERNEL__ */

#endif /* _ASM_SCORE_PTRACE_H */
Index: linux-2.6/arch/sh/include/asm/ptrace.h
===================================================================
--- linux-2.6.orig/arch/sh/include/asm/ptrace.h 2010-02-02 10:16:57.255253691 +0100
+++ linux-2.6/arch/sh/include/asm/ptrace.h 2010-02-02 10:18:50.879041468 +0100
@@ -121,8 +121,6 @@ extern void show_regs(struct pt_regs *);
struct task_struct;

#define arch_has_single_step() (1)
-extern void user_enable_single_step(struct task_struct *);
-extern void user_disable_single_step(struct task_struct *);

#define task_pt_regs(task) \
((struct pt_regs *) (task_stack_page(task) + THREAD_SIZE) - 1)
Index: linux-2.6/arch/x86/include/asm/ptrace.h
===================================================================
--- linux-2.6.orig/arch/x86/include/asm/ptrace.h 2010-02-02 10:16:57.309003832 +0100
+++ linux-2.6/arch/x86/include/asm/ptrace.h 2010-02-02 10:21:19.621005835 +0100
@@ -278,14 +278,7 @@ static inline unsigned long regs_get_ker
extern unsigned long regs_get_argument_nth(struct pt_regs *regs,
unsigned int n);

-/*
- * These are defined as per linux/ptrace.h, which see.
- */
#define arch_has_single_step() (1)
-extern void user_enable_single_step(struct task_struct *);
-extern void user_disable_single_step(struct task_struct *);
-
-extern void user_enable_block_step(struct task_struct *);
#ifdef CONFIG_X86_DEBUGCTLMSR
#define arch_has_block_step() (1)
#else
Index: linux-2.6/include/linux/ptrace.h
===================================================================
--- linux-2.6.orig/include/linux/ptrace.h 2010-02-02 10:16:57.003003620 +0100
+++ linux-2.6/include/linux/ptrace.h 2010-02-02 10:21:46.925266509 +0100
@@ -238,6 +238,9 @@ static inline void user_enable_single_st
static inline void user_disable_single_step(struct task_struct *task)
{
}
+#else
+extern void user_enable_single_step(struct task_struct *);
+extern void user_disable_single_step(struct task_struct *);
#endif /* arch_has_single_step */

#ifndef arch_has_block_step
@@ -265,6 +268,8 @@ static inline void user_enable_block_ste
{
BUG(); /* This can never be called. */
}
+#else
+extern void user_enable_block_step(struct task_struct *);
#endif /* arch_has_block_step */

#ifdef ARCH_HAS_USER_SINGLE_STEP_INFO
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majo...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Christoph Hellwig

unread,
Feb 2, 2010, 2:10:01 PM2/2/10
to
Use the generic ptrace_resume code for PTRACE_SYSCALL, PTRACE_CONT and
PTRACE_KILL. This also makes PTRACE_SINGLESTEP return -EIO while it
previously succeeded despite not actually causing any kind of single
stepping.

Also the TIF_SYSCALL_TRACE thread flag is now cleared on PTRACE_KILL
which it previously wasn't which is consistent with all architectures
using the modern ptrace code.

Signed-off-by: Christoph Hellwig <h...@lst.de>

Index: linux-2.6/arch/microblaze/kernel/ptrace.c
===================================================================
--- linux-2.6.orig/arch/microblaze/kernel/ptrace.c 2010-02-02 11:23:56.002003861 +0100
+++ linux-2.6/arch/microblaze/kernel/ptrace.c 2010-02-02 19:20:16.997254566 +0100
@@ -110,43 +110,6 @@ long arch_ptrace(struct task_struct *chi
if (rval == 0 && request == PTRACE_PEEKUSR)
rval = put_user(val, (unsigned long *)data);
break;
- /* Continue and stop at next (return from) syscall */
- case PTRACE_SYSCALL:
- pr_debug("PTRACE_SYSCALL\n");
- case PTRACE_SINGLESTEP:
- pr_debug("PTRACE_SINGLESTEP\n");
- /* Restart after a signal. */
- case PTRACE_CONT:
- pr_debug("PTRACE_CONT\n");
- rval = -EIO;
- if (!valid_signal(data))
- break;
-
- if (request == PTRACE_SYSCALL)
- set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- else
- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-
- child->exit_code = data;
- pr_debug("wakeup_process\n");
- wake_up_process(child);
- rval = 0;
- break;
-
- /*
- * make the child exit. Best I can do is send it a sigkill.
- * perhaps it should be put in the status that it wants to
- * exit.
- */
- case PTRACE_KILL:
- pr_debug("PTRACE_KILL\n");
- rval = 0;
- if (child->exit_state == EXIT_ZOMBIE) /* already dead */
- break;
- child->exit_code = SIGKILL;
- wake_up_process(child);
- break;
-
default:
rval = ptrace_request(child, request, addr, data);

Christoph Hellwig

unread,
Feb 2, 2010, 2:10:02 PM2/2/10
to
Use the generic ptrace_resume code for PTRACE_SYSCALL, PTRACE_CONT,
PTRACE_KILL and PTRACE_SINGLESTEP. This implies defining
arch_has_single_step in <asm/ptrace.h> and implementing the
user_enable_single_step and user_disable_single_step functions, which
also causes the breakpoint information to be cleared on fork, which
could be considered a bug fix.

Also the TIF_SYSCALL_TRACE thread flag is now cleared on PTRACE_KILL
which it previously wasn't which is consistent with all architectures
using the modern ptrace code.

Signed-off-by: Christoph Hellwig <h...@lst.de>


Index: linux-2.6/arch/h8300/kernel/ptrace.c
===================================================================
--- linux-2.6.orig/arch/h8300/kernel/ptrace.c 2010-02-02 11:01:22.072254015 +0100
+++ linux-2.6/arch/h8300/kernel/ptrace.c 2010-02-02 11:20:07.256255344 +0100
@@ -34,8 +34,11 @@
/* cpu depend functions */
extern long h8300_get_reg(struct task_struct *task, int regno);
extern int h8300_put_reg(struct task_struct *task, int regno, unsigned long data);
-extern void h8300_disable_trace(struct task_struct *child);
-extern void h8300_enable_trace(struct task_struct *child);
+
+
+void user_disable_single_step(struct task_struct *child)
+{
+}

/*
* does not yet catch signals sent when the child dies.
@@ -44,7 +47,7 @@ extern void h8300_enable_trace(struct ta

void ptrace_disable(struct task_struct *child)
{
- h8300_disable_trace(child);
+ user_disable_single_step(child);
}

long arch_ptrace(struct task_struct *child, long request, long addr, long data)
@@ -107,49 +110,6 @@ long arch_ptrace(struct task_struct *chi
}
ret = -EIO;
break ;
- case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
- case PTRACE_CONT: { /* restart after signal. */
- ret = -EIO;


- if (!valid_signal(data))
- break ;
- if (request == PTRACE_SYSCALL)
- set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- else
- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- child->exit_code = data;

- wake_up_process(child);
- /* make sure the single step bit is not set. */
- h8300_disable_trace(child);
- ret = 0;
- }
-
-/*


- * make the child exit. Best I can do is send it a sigkill.
- * perhaps it should be put in the status that it wants to
- * exit.
- */
- case PTRACE_KILL: {
-

- ret = 0;


- if (child->exit_state == EXIT_ZOMBIE) /* already dead */
- break;
- child->exit_code = SIGKILL;

- h8300_disable_trace(child);


- wake_up_process(child);
- break;
- }

-
- case PTRACE_SINGLESTEP: { /* set the trap flag. */
- ret = -EIO;


- if (!valid_signal(data))
- break;

- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);


- child->exit_code = data;

- h8300_enable_trace(child);
- wake_up_process(child);
- ret = 0;
- break;
- }

case PTRACE_GETREGS: { /* Get all gp regs from the child. */
int i;
Index: linux-2.6/arch/h8300/platform/h8300h/ptrace_h8300h.c
===================================================================
--- linux-2.6.orig/arch/h8300/platform/h8300h/ptrace_h8300h.c 2010-02-02 11:00:49.957253800 +0100
+++ linux-2.6/arch/h8300/platform/h8300h/ptrace_h8300h.c 2010-02-02 11:19:15.327003827 +0100
@@ -60,7 +60,7 @@ int h8300_put_reg(struct task_struct *ta
}

/* disable singlestep */
-void h8300_disable_trace(struct task_struct *child)
+void user_disable_single_step(struct task_struct *child)
{
if((long)child->thread.breakinfo.addr != -1L) {
*child->thread.breakinfo.addr = child->thread.breakinfo.inst;
@@ -264,7 +264,7 @@ static unsigned short *getnextpc(struct

/* Set breakpoint(s) to simulate a single step from the current PC. */

-void h8300_enable_trace(struct task_struct *child)
+void user_enable_single_step(struct task_struct *child)
{
unsigned short *nextpc;
nextpc = getnextpc(child,(unsigned short *)h8300_get_reg(child, PT_PC));
@@ -276,7 +276,7 @@ void h8300_enable_trace(struct task_stru
asmlinkage void trace_trap(unsigned long bp)
{
if ((unsigned long)current->thread.breakinfo.addr == bp) {
- h8300_disable_trace(current);
+ user_disable_single_step(current);
force_sig(SIGTRAP,current);
} else
force_sig(SIGILL,current);
Index: linux-2.6/arch/h8300/platform/h8s/ptrace_h8s.c
===================================================================
--- linux-2.6.orig/arch/h8300/platform/h8s/ptrace_h8s.c 2010-02-02 11:00:49.968253944 +0100
+++ linux-2.6/arch/h8300/platform/h8s/ptrace_h8s.c 2010-02-02 11:19:15.329011624 +0100
@@ -65,13 +65,13 @@ int h8300_put_reg(struct task_struct *ta
}

/* disable singlestep */
-void h8300_disable_trace(struct task_struct *child)
+void user_disable_single_step(struct task_struct *child)
{
*(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) &= ~EXR_TRACE;
}

/* enable singlestep */
-void h8300_enable_trace(struct task_struct *child)
+void user_enable_single_step(struct task_struct *child)
{
*(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) |= EXR_TRACE;
}
Index: linux-2.6/arch/h8300/include/asm/ptrace.h
===================================================================
--- linux-2.6.orig/arch/h8300/include/asm/ptrace.h 2010-02-02 11:19:24.753253118 +0100
+++ linux-2.6/arch/h8300/include/asm/ptrace.h 2010-02-02 11:19:36.822033076 +0100
@@ -55,6 +55,8 @@ struct pt_regs {
/* Find the stack offset for a register, relative to thread.esp0. */
#define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg)

+#define arch_has_single_step() (1)
+
#define user_mode(regs) (!((regs)->ccr & PS_S))
#define instruction_pointer(regs) ((regs)->pc)
#define profile_pc(regs) instruction_pointer(regs)

Christoph Hellwig

unread,
Feb 2, 2010, 2:10:03 PM2/2/10
to
Use the generic ptrace_resume code for PTRACE_SYSCALL, PTRACE_CONT,
PTRACE_KILL and PTRACE_SINGLESTEP. This implies defining
arch_has_single_step in <asm/ptrace.h> and implementing the
user_enable_single_step and user_disable_single_step functions, which
also causes the breakpoint information to be cleared on fork, which
could be considered a bug fix.

Also the TIF_SYSCALL_TRACE thread flag is now cleared on PTRACE_KILL
which it previously wasn't which is consistent with all architectures
using the modern ptrace code.

Signed-off-by: Christoph Hellwig <h...@lst.de>

Index: linux-2.6/arch/xtensa/kernel/ptrace.c
===================================================================
--- linux-2.6.orig/arch/xtensa/kernel/ptrace.c 2010-02-02 19:18:16.218004699 +0100
+++ linux-2.6/arch/xtensa/kernel/ptrace.c 2010-02-02 19:21:56.730004589 +0100
@@ -30,6 +30,17 @@
#include <asm/elf.h>
#include <asm/coprocessor.h>

+
+void user_enable_single_step(struct task_struct *child)
+{
+ child->ptrace |= PT_SINGLESTEP;


+}
+
+void user_disable_single_step(struct task_struct *child)
+{

+ child->ptrace &= ~PT_SINGLESTEP;
+}
+
/*
* Called by kernel/ptrace.c when detaching to disable single stepping.
*/
@@ -258,51 +269,6 @@ long arch_ptrace(struct task_struct *chi
ret = ptrace_pokeusr(child, addr, data);
break;

- /* continue and stop at next (return from) syscall */
-
- case PTRACE_SYSCALL:


- case PTRACE_CONT: /* restart after signal. */

- {


- ret = -EIO;
- if (!valid_signal(data))
- break;
- if (request == PTRACE_SYSCALL)
- set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- else
- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- child->exit_code = data;

- /* Make sure the single step bit is not set. */
- child->ptrace &= ~PT_SINGLESTEP;


- wake_up_process(child);
- ret = 0;
- break;
- }

-
- /*


- * make the child exit. Best I can do is send it a sigkill.
- * perhaps it should be put in the status that it wants to
- * exit.
- */
- case PTRACE_KILL:
- ret = 0;
- if (child->exit_state == EXIT_ZOMBIE) /* already dead */
- break;
- child->exit_code = SIGKILL;

- child->ptrace &= ~PT_SINGLESTEP;


- wake_up_process(child);
- break;
-

- case PTRACE_SINGLESTEP:


- ret = -EIO;
- if (!valid_signal(data))
- break;
- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);

- child->ptrace |= PT_SINGLESTEP;


- child->exit_code = data;
- wake_up_process(child);

- ret = 0;
- break;
-
case PTRACE_GETREGS:

ret = ptrace_getregs(child, (void __user *) data);
break;
Index: linux-2.6/arch/xtensa/include/asm/ptrace.h
===================================================================
--- linux-2.6.orig/arch/xtensa/include/asm/ptrace.h 2010-02-02 19:18:16.234010089 +0100
+++ linux-2.6/arch/xtensa/include/asm/ptrace.h 2010-02-02 19:21:56.730004589 +0100
@@ -113,6 +113,7 @@ struct pt_regs {

#include <variant/core.h>

+# define arch_has_single_step() (1)
# define task_pt_regs(tsk) ((struct pt_regs*) \
(task_stack_page(tsk) + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4) - 1)
# define user_mode(regs) (((regs)->ps & 0x00000020)!=0)

Christoph Hellwig

unread,
Feb 2, 2010, 2:10:01 PM2/2/10
to
Use the generic ptrace_resume code for PTRACE_SYSCALL, PTRACE_CONT,
PTRACE_KILL and PTRACE_SINGLESTEP. m68knommu already defines the
nessecary user_enable_single_step and user_disable_single_step functions
for this.

Also the TIF_SYSCALL_TRACE thread flag is now cleared on PTRACE_KILL
which it previously wasn't which is consistent with all architectures
using the modern ptrace code.

Signed-off-by: Christoph Hellwig <h...@lst.de>

Index: linux-2.6/arch/m68knommu/kernel/ptrace.c
===================================================================
--- linux-2.6.orig/arch/m68knommu/kernel/ptrace.c 2010-02-02 11:00:49.987254269 +0100
+++ linux-2.6/arch/m68knommu/kernel/ptrace.c 2010-02-02 11:22:17.003259609 +0100
@@ -190,62 +190,6 @@ long arch_ptrace(struct task_struct *chi
}
break;

- case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */


- case PTRACE_CONT: { /* restart after signal. */

- long tmp;


-
- ret = -EIO;
- if (!valid_signal(data))
- break;
- if (request == PTRACE_SYSCALL)
- set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- else
- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- child->exit_code = data;

- /* make sure the single step bit is not set. */
- tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
- put_reg(child, PT_SR, tmp);


- wake_up_process(child);
- ret = 0;
- break;
- }
-
- /*
- * make the child exit. Best I can do is send it a sigkill.
- * perhaps it should be put in the status that it wants to
- * exit.
- */
- case PTRACE_KILL: {

- long tmp;
-


- ret = 0;
- if (child->exit_state == EXIT_ZOMBIE) /* already dead */
- break;
- child->exit_code = SIGKILL;

- /* make sure the single step bit is not set. */
- tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
- put_reg(child, PT_SR, tmp);


- wake_up_process(child);
- break;
- }
-

- case PTRACE_SINGLESTEP: { /* set the trap flag. */

- long tmp;


-
- ret = -EIO;
- if (!valid_signal(data))
- break;

- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16);
- put_reg(child, PT_SR, tmp);
-


- child->exit_code = data;

- /* give it a chance to run. */


- wake_up_process(child);
- ret = 0;
- break;
- }
-

case PTRACE_GETREGS: { /* Get all gp regs from the child. */
int i;

unsigned long tmp;

Christoph Hellwig

unread,
Feb 2, 2010, 2:10:02 PM2/2/10
to
Use the generic ptrace_resume code for PTRACE_SYSCALL, PTRACE_CONT,
PTRACE_KILL and PTRACE_SINGLESTEP. This implies defining
arch_has_single_step in <asm/ptrace.h> and implementing the
user_enable_single_step and user_disable_single_step functions, which
also causes the breakpoint information to be cleared on fork, which
could be considered a bug fix.

Also the TIF_SYSCALL_TRACE thread flag is now cleared on PTRACE_KILL
which it previously wasn't, which is consistent with all architectures


using the modern ptrace code.

The old code only disables the breakpoints on PTRACE_KILL, while after
this patch this also happens for PTRACE_CONT and PTRACE_SYSCALL which
matches the behaviour of the other architetures. I think this is a
bugfixes, but please double verify this is correct.

Signed-off-by: Christoph Hellwig <h...@lst.de>

Index: linux-2.6/arch/m32r/include/asm/ptrace.h
===================================================================
--- linux-2.6.orig/arch/m32r/include/asm/ptrace.h 2010-02-02 19:26:37.456003660 +0100
+++ linux-2.6/arch/m32r/include/asm/ptrace.h 2010-02-02 19:26:49.405264333 +0100
@@ -120,6 +120,8 @@ struct pt_regs {

#include <asm/m32r.h> /* M32R_PSW_BSM, M32R_PSW_BPM */

+#define arch_has_single_step() (1)
+
struct task_struct;
extern void init_debug_traps(struct task_struct *);
#define arch_ptrace_attach(child) \
Index: linux-2.6/arch/m32r/kernel/ptrace.c
===================================================================
--- linux-2.6.orig/arch/m32r/kernel/ptrace.c 2010-02-02 19:26:54.353253780 +0100
+++ linux-2.6/arch/m32r/kernel/ptrace.c 2010-02-02 19:29:39.935253922 +0100
@@ -580,6 +580,35 @@ init_debug_traps(struct task_struct *chi


}
}

+void user_enable_single_step(struct task_struct *child)
+{

+ unsigned long next_pc;
+ unsigned long pc, insn;
+
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+
+ /* Compute next pc. */
+ pc = get_stack_long(child, PT_BPC);
+
+ if (access_process_vm(child, pc&~3, &insn, sizeof(insn), 0)
+ != sizeof(insn))
+ break;
+
+ compute_next_pc(insn, pc, &next_pc, child);
+ if (next_pc & 0x80000000)
+ break;
+
+ if (embed_debug_trap(child, next_pc))
+ break;
+
+ invalidate_cache();


+}
+
+void user_disable_single_step(struct task_struct *child)
+{

+ unregister_all_debug_traps(child);
+ invalidate_cache();
+}

/*
* Called by kernel/ptrace.c when detaching..
@@ -612,74 +641,6 @@ arch_ptrace(struct task_struct *child, l
ret = ptrace_write_user(child, addr, data);
break;

- /*
- * continue/restart and stop at next (return from) syscall
- */


- case PTRACE_SYSCALL:
- case PTRACE_CONT:

- ret = -EIO;
- if (!valid_signal(data))
- break;
- if (request == PTRACE_SYSCALL)
- set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- else
- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- child->exit_code = data;

- wake_up_process(child);
- ret = 0;
- break;
-
- /*
- * make the child exit. Best I can do is send it a sigkill.
- * perhaps it should be put in the status that it wants to
- * exit.
- */
- case PTRACE_KILL: {

- ret = 0;
- unregister_all_debug_traps(child);
- invalidate_cache();


- if (child->exit_state == EXIT_ZOMBIE) /* already dead */
- break;
- child->exit_code = SIGKILL;

- wake_up_process(child);
- break;
- }
-

- /*
- * execute single instruction.
- */
- case PTRACE_SINGLESTEP: {
- unsigned long next_pc;
- unsigned long pc, insn;


-
- ret = -EIO;
- if (!valid_signal(data))
- break;
- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-

- /* Compute next pc. */
- pc = get_stack_long(child, PT_BPC);
-
- if (access_process_vm(child, pc&~3, &insn, sizeof(insn), 0)
- != sizeof(insn))
- break;
-
- compute_next_pc(insn, pc, &next_pc, child);
- if (next_pc & 0x80000000)
- break;
-
- if (embed_debug_trap(child, next_pc))
- break;
-
- invalidate_cache();


- child->exit_code = data;
-

- /* give it a chance to run. */
- wake_up_process(child);
- ret = 0;
- break;
- }
-
case PTRACE_GETREGS:

ret = ptrace_getregs(child, (void __user *)data);
break;

Christoph Hellwig

unread,
Feb 2, 2010, 2:10:02 PM2/2/10
to
Use the generic ptrace_resume code for PTRACE_SYSCALL, PTRACE_CONT and
PTRACE_KILL. This also makes PTRACE_SINGLESTEP return -EIO while it
previously succeeded despite not actually causing any kind of single
stepping.

Also the TIF_SYSCALL_TRACE thread flag is now cleared on PTRACE_KILL
which it previously wasn't which is consistent with all architectures


using the modern ptrace code.

Signed-off-by: Christoph Hellwig <h...@lst.de>

Index: linux-2.6/arch/cris/arch-v10/kernel/ptrace.c
===================================================================
--- linux-2.6.orig/arch/cris/arch-v10/kernel/ptrace.c 2010-02-02 19:23:58.567254756 +0100
+++ linux-2.6/arch/cris/arch-v10/kernel/ptrace.c 2010-02-02 19:24:33.483004794 +0100
@@ -115,57 +115,6 @@ long arch_ptrace(struct task_struct *chi
ret = 0;
break;



- case PTRACE_SYSCALL:
- case PTRACE_CONT:
- ret = -EIO;
-
- if (!valid_signal(data))
- break;
-
- if (request == PTRACE_SYSCALL) {
- set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- }
- else {
- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- }

-

- child->exit_code = data;
-

- /* TODO: make sure any pending breakpoint is killed */


- wake_up_process(child);
- ret = 0;
-

- break;
-
- /* Make the child exit by sending it a sigkill. */


- case PTRACE_KILL:
- ret = 0;
-

- if (child->exit_state == EXIT_ZOMBIE)

- break;
-

- child->exit_code = SIGKILL;
-

- /* TODO: make sure any pending breakpoint is killed */


- wake_up_process(child);
- break;
-

- /* Set the trap flag. */
- case PTRACE_SINGLESTEP:
- ret = -EIO;
-

- if (!valid_signal(data))
- break;
-

- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-
- /* TODO: set some clever breakpoint mechanism... */
-


- child->exit_code = data;
- wake_up_process(child);
- ret = 0;
- break;
-

/* Get all GP registers from the child. */
case PTRACE_GETREGS: {
int i;

Christoph Hellwig

unread,
Feb 2, 2010, 2:10:01 PM2/2/10
to
Use the generic ptrace_resume code for PTRACE_SYSCALL, PTRACE_CONT and
PTRACE_KILL.

Also the TIF_SYSCALL_TRACE thread flag is now cleared on PTRACE_KILL


which it previously wasn't which is consistent with all architectures
using the modern ptrace code.

Signed-off-by: Christoph Hellwig <h...@lst.de>

Index: linux-2.6/arch/mips/kernel/ptrace.c
===================================================================
--- linux-2.6.orig/arch/mips/kernel/ptrace.c 2010-02-02 11:00:50.011010089 +0100
+++ linux-2.6/arch/mips/kernel/ptrace.c 2010-02-02 19:18:27.564005697 +0100
@@ -481,36 +481,6 @@ long arch_ptrace(struct task_struct *chi
ret = ptrace_setfpregs(child, (__u32 __user *) data);


break;

- case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
- case PTRACE_CONT: { /* restart after signal. */

- ret = -EIO;
- if (!valid_signal(data))
- break;
- if (request == PTRACE_SYSCALL) {
- set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- }
- else {
- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- }

- child->exit_code = data;
- wake_up_process(child);
- ret = 0;
- break;
- }

-
- /*
- * make the child exit. Best I can do is send it a sigkill.
- * perhaps it should be put in the status that it wants to
- * exit.

- */


- case PTRACE_KILL:
- ret = 0;

- if (child->exit_state == EXIT_ZOMBIE) /* already dead */
- break;

- child->exit_code = SIGKILL;

- wake_up_process(child);
- break;
-
case PTRACE_GET_THREAD_AREA:
ret = put_user(task_thread_info(child)->tp_value,
(unsigned long __user *) data);

Christoph Hellwig

unread,
Feb 2, 2010, 2:10:02 PM2/2/10
to
Use the generic ptrace_resume code for PTRACE_SYSCALL, PTRACE_CONT,
PTRACE_KILL and PTRACE_SINGLESTEP. This implies defining
arch_has_single_step in <asm/ptrace.h> and implementing the
user_enable_single_step and user_disable_single_step functions, which
also causes the breakpoint information to be cleared on fork, which
could be considered a bug fix.

Also the TIF_SYSCALL_TRACE thread flag is now cleared on PTRACE_KILL


which it previously wasn't which is consistent with all architectures
using the modern ptrace code.

The way breakpoints are disabled is entirely inconsistent
currently, I tried to make some sense of it, but I suspect all of the
content of ptrace_disable should be moved into user_disable_single_step,
this defintively needs some revisting as the current patch changes
behaviour in not quite designed ways.

Signed-off-by: Christoph Hellwig <h...@lst.de>

Index: linux-2.6/arch/cris/arch-v32/kernel/ptrace.c
===================================================================
--- linux-2.6.orig/arch/cris/arch-v32/kernel/ptrace.c 2010-02-02 19:23:12.314003057 +0100
+++ linux-2.6/arch/cris/arch-v32/kernel/ptrace.c 2010-02-02 19:25:27.396253967 +0100
@@ -78,6 +78,35 @@ int put_reg(struct task_struct *task, un
return 0;


}

+void user_enable_single_step(struct task_struct *child)
+{

+ unsigned long tmp;
+
+ /*
+ * Set up SPC if not set already (in which case we have no other
+ * choice but to trust it).
+ */
+ if (!get_reg(child, PT_SPC)) {
+ /* In case we're stopped in a delay slot. */
+ tmp = get_reg(child, PT_ERP) & ~1;
+ put_reg(child, PT_SPC, tmp);
+ }
+ tmp = get_reg(child, PT_CCS) | SBIT_USER;
+ put_reg(child, PT_CCS, tmp);


+}
+
+void user_disable_single_step(struct task_struct *child)
+{

+ put_reg(child, PT_SPC, 0);
+
+ if (!get_debugreg(child->pid, PT_BP_CTRL)) {
+ unsigned long tmp;
+ /* If no h/w bp configured, disable S bit. */
+ tmp = get_reg(child, PT_CCS) & ~SBIT_USER;
+ put_reg(child, PT_CCS, tmp);
+ }
+}


+
/*
* Called by kernel/ptrace.c when detaching.

*
@@ -89,8 +118,7 @@ ptrace_disable(struct task_struct *child
unsigned long tmp;

/* Deconfigure SPC and S-bit. */
- tmp = get_reg(child, PT_CCS) & ~SBIT_USER;
- put_reg(child, PT_CCS, tmp);
+ user_disable_single_step(child);
put_reg(child, PT_SPC, 0);

/* Deconfigure any watchpoints associated with the child. */
@@ -163,83 +191,6 @@ long arch_ptrace(struct task_struct *chi


ret = 0;
break;

- case PTRACE_SYSCALL:
- case PTRACE_CONT:

- ret = -EIO;
-
- if (!valid_signal(data))
- break;
-

- /* Continue means no single-step. */
- put_reg(child, PT_SPC, 0);
-
- if (!get_debugreg(child->pid, PT_BP_CTRL)) {
- unsigned long tmp;
- /* If no h/w bp configured, disable S bit. */
- tmp = get_reg(child, PT_CCS) & ~SBIT_USER;
- put_reg(child, PT_CCS, tmp);
- }
-


- if (request == PTRACE_SYSCALL) {
- set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- }
- else {
- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- }
-
- child->exit_code = data;
-

- /* TODO: make sure any pending breakpoint is killed */

- wake_up_process(child);
- ret = 0;
-

- break;
-
- /* Make the child exit by sending it a sigkill. */


- case PTRACE_KILL:
- ret = 0;
-
- if (child->exit_state == EXIT_ZOMBIE)

- break;
-
- child->exit_code = SIGKILL;
-
- /* Deconfigure single-step and h/w bp. */
- ptrace_disable(child);


-
- /* TODO: make sure any pending breakpoint is killed */

- wake_up_process(child);
- break;
-

- /* Set the trap flag. */
- case PTRACE_SINGLESTEP: {

- unsigned long tmp;


- ret = -EIO;
-

- /* Set up SPC if not set already (in which case we have
- no other choice but to trust it). */
- if (!get_reg(child, PT_SPC)) {
- /* In case we're stopped in a delay slot. */
- tmp = get_reg(child, PT_ERP) & ~1;
- put_reg(child, PT_SPC, tmp);
- }
- tmp = get_reg(child, PT_CCS) | SBIT_USER;
- put_reg(child, PT_CCS, tmp);
-


- if (!valid_signal(data))
- break;
-

- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-


- /* TODO: set some clever breakpoint mechanism... */

-
- child->exit_code = data;
- wake_up_process(child);
- ret = 0;
- break;
-
- }
-

/* Get all GP registers from the child. */
case PTRACE_GETREGS: {
int i;

Index: linux-2.6/arch/cris/include/arch-v32/arch/ptrace.h
===================================================================
--- linux-2.6.orig/arch/cris/include/arch-v32/arch/ptrace.h 2010-02-02 19:25:39.092254418 +0100
+++ linux-2.6/arch/cris/include/arch-v32/arch/ptrace.h 2010-02-02 19:25:46.173254455 +0100
@@ -108,6 +108,7 @@ struct switch_stack {

#ifdef __KERNEL__

+#define arch_has_single_step() (1)
#define user_mode(regs) (((regs)->ccs & (1 << (U_CCS_BITNR + CCS_SHIFT))) != 0)
#define instruction_pointer(regs) ((regs)->erp)


extern void show_regs(struct pt_regs *);

Ralf Baechle

unread,
Feb 2, 2010, 2:20:02 PM2/2/10
to
On Tue, Feb 02, 2010 at 07:59:58PM +0100, Christoph Hellwig wrote:

> Use the generic ptrace_resume code for PTRACE_SYSCALL, PTRACE_CONT and
> PTRACE_KILL.
>
> Also the TIF_SYSCALL_TRACE thread flag is now cleared on PTRACE_KILL
> which it previously wasn't which is consistent with all architectures
> using the modern ptrace code.
>
> Signed-off-by: Christoph Hellwig <h...@lst.de>

Acked-by: Ralf Baechle <ra...@linux-mips.org>

Ralf

Greg Ungerer

unread,
Feb 3, 2010, 2:00:02 AM2/3/10
to
Christoph Hellwig wrote:
> Use the generic ptrace_resume code for PTRACE_SYSCALL, PTRACE_CONT,
> PTRACE_KILL and PTRACE_SINGLESTEP. m68knommu already defines the
> nessecary user_enable_single_step and user_disable_single_step functions
> for this.
>
> Also the TIF_SYSCALL_TRACE thread flag is now cleared on PTRACE_KILL
> which it previously wasn't which is consistent with all architectures
> using the modern ptrace code.
>
> Signed-off-by: Christoph Hellwig <h...@lst.de>

Acked-by: Greg Ungerer <ge...@uclinux.org>


------------------------------------------------------------------------
Greg Ungerer -- Principal Engineer EMAIL: ge...@snapgear.com
SnapGear Group, McAfee PHONE: +61 7 3435 2888
8 Gardner Close FAX: +61 7 3217 5323
Milton, QLD, 4064, Australia WEB: http://www.SnapGear.com

Mike Frysinger

unread,
Feb 3, 2010, 3:50:01 AM2/3/10
to
On Tue, Feb 2, 2010 at 13:57, Christoph Hellwig wrote:
> While in theory user_enable_single_step/user_disable_single_step/
> user_enable_blockstep could also be provided as an inline or macro there's no
> good reason to do so, and having the prototype in one places keeps code size
> and confusion down.

the only annoying thing here is that we currently have to enable both
user_disable_single_step() and ptrace_disable() that do exactly the
same thing. i avoided this somewhat on Blackfin by cheating:
#define user_disable_single_step(child) ptrace_disable(child)

so now there's no code bloat. perhaps this could be moved into common
linux/ptrace.h too ?

> --- linux-2.6/include/linux/ptrace.h
> +++ linux-2.6/include/linux/ptrace.h
> @@ -238,6 +238,9 @@


>  static inline void user_disable_single_step(struct task_struct *task)
>  {
>  }
> +#else
> +extern void user_enable_single_step(struct task_struct *);
> +extern void user_disable_single_step(struct task_struct *);
>  #endif /* arch_has_single_step */

+#define ptrace_disable(child) user_disable_single_step(child)
-mike

Christoph Hellwig

unread,
Feb 3, 2010, 4:00:01 AM2/3/10
to
On Wed, Feb 03, 2010 at 03:42:05AM -0500, Mike Frysinger wrote:
> On Tue, Feb 2, 2010 at 13:57, Christoph Hellwig wrote:
> > While in theory user_enable_single_step/user_disable_single_step/
> > user_enable_blockstep could also be provided as an inline or macro there's no
> > good reason to do so, and having the prototype in one places keeps code size
> > and confusion down.
>
> the only annoying thing here is that we currently have to enable both
> user_disable_single_step() and ptrace_disable() that do exactly the
> same thing. i avoided this somewhat on Blackfin by cheating:
> #define user_disable_single_step(child) ptrace_disable(child)
>
> so now there's no code bloat. perhaps this could be moved into common
> linux/ptrace.h too ?

What is done by most architectures is ptrace_disable simply
calling user_disable_single_step. Long-term I expect ptrace_disable to
go away entirely. While a few architectures do more than just
user_disable_single_step in it that seems at least fishy to me, but
I'll wait with the audit until we have everyone actually using
ptrace_resume.

Michal Simek

unread,
Feb 3, 2010, 6:10:03 AM2/3/10
to
Acked-by: Michal Simek <mon...@monstr.eu>


--
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel 2.6 Microblaze Linux - http://www.monstr.eu/fdt/
Microblaze U-BOOT custodian

David Howells

unread,
Feb 8, 2010, 6:00:03 AM2/8/10
to
Christoph Hellwig <h...@lst.de> wrote:

> While in theory user_enable_single_step/user_disable_single_step/
> user_enable_blockstep could also be provided as an inline or macro there's no
> good reason to do so, and having the prototype in one places keeps code size
> and confusion down.
>
> Signed-off-by: Christoph Hellwig <h...@lst.de>

Acked-by: David Howells <dhow...@redhat.com>

Roland McGrath

unread,
Feb 8, 2010, 3:00:01 PM2/8/10
to
The original thought there was that user_enable_single_step() et al might
well be only an instruction or three on a sane machine (as if we have any
of those!), and since there is only one call site inlining would be
beneficial. But I agree that there is no strong reason to care about
inlining it.

As to the arch changes, there is only one thought I'd add to the record.
It was always my thinking that for an arch where PTRACE_SINGLESTEP does
text-modifying breakpoint insertion, user_enable_single_step() should not
be provided. That is, arch_has_single_step()=>true means that there is an
arch facility with "pure" semantics that does not have any unexpected side
effects. Inserting a breakpoint might do very unexpected strange things in
multi-threaded situations. Aside from that, it is a peculiar side effect
that user_{enable,disable}_single_step() should cause COW de-sharing of
text pages and so forth. For PTRACE_SINGLESTEP, all these peculiarities
are the status quo ante for that arch, so having arch_ptrace() itself do
those is one thing. But for building other things in the future, it is
nicer to have a uniform "pure" semantics that arch-independent code can
expect.

OTOH, all such arch issues are really up to the arch maintainer. As of
today, there is nothing but ptrace using user_enable_single_step() et al so
it's a distinction without a practical difference. If/when there are other
facilities that use user_enable_single_step() and might care, the affected
arch's can revisit the question when someone cares about the quality of the
arch support for said new facility.

So, with those caveats preserved for posteriority, all these changes
are OK with me.


Thanks,
Roland

Christoph Hellwig

unread,
Feb 10, 2010, 5:10:02 PM2/10/10
to
On Mon, Feb 08, 2010 at 11:51:25AM -0800, Roland McGrath wrote:
> The original thought there was that user_enable_single_step() et al might
> well be only an instruction or three on a sane machine (as if we have any
> of those!), and since there is only one call site inlining would be
> beneficial. But I agree that there is no strong reason to care about
> inlining it.

In fact many of the implementations are small enough to inline them, but
not no architecture so far decided to inline them, and in the end it's
not exactly a fast-path. This at least keeps the prototype the same
everywhere.

> As to the arch changes, there is only one thought I'd add to the record.
> It was always my thinking that for an arch where PTRACE_SINGLESTEP does
> text-modifying breakpoint insertion, user_enable_single_step() should not
> be provided. That is, arch_has_single_step()=>true means that there is an
> arch facility with "pure" semantics that does not have any unexpected side
> effects. Inserting a breakpoint might do very unexpected strange things in
> multi-threaded situations. Aside from that, it is a peculiar side effect
> that user_{enable,disable}_single_step() should cause COW de-sharing of
> text pages and so forth. For PTRACE_SINGLESTEP, all these peculiarities
> are the status quo ante for that arch, so having arch_ptrace() itself do
> those is one thing. But for building other things in the future, it is
> nicer to have a uniform "pure" semantics that arch-independent code can
> expect.

For now the ptrace code is the same for real or software singlestepping.
If we grow users that care we can add a arch_has_hw_single_step macro
or just overload arch_has_single_step with different postitive return
values for the exact same type of single stepping supported.

0 new messages