Commit 2c7686ce authored by Hirokazu Takata's avatar Hirokazu Takata Committed by Linus Torvalds

[PATCH] m32r: Update ptrace.c for multithread debugging

This patch updates ptrace.c to support multithread debugging.  So far, only
one breakpoint's location was kept by kernel, however, in the multithreaded
application's debug, it is required to kept multi-point breakpoint locations
by kernel.

In this implementation, maximum number of MAX_TRAPS(=10 (by default))
breakpoint's information will be kept in the "debug_trap" member of the
thread_struct for each thread.

	* include/asm-m32r/processor.h: 
	  Modify debug_trap struct to keep multipoint breakpoint locations
	  for multithread debugging.

	* arch/m32r/kernel/ptrace.c:
	- Update to support multithread debugging.
	- Remove unused functions, withdraw_debug_trap_for_signal() and
	  embed_debug_trap_for_signal().
Signed-off-by: default avatarKei Sakamoto <ksakamot@linux-m32r.org>
Signed-off-by: default avatarHirokazu Takata <takata@linux-m32r.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent cbbcefb7
......@@ -2,7 +2,7 @@
* linux/arch/m32r/kernel/ptrace.c
*
* Copyright (C) 2002 Hirokazu Takata, Takeo Takahashi
* Copyright (C) 2004 Hirokazu Takata <takata at linux-m32r.org>
* Copyright (C) 2004 Hirokazu Takata, Kei Sakamoto
*
* Original x86 implementation:
* By Ross Biro 1/23/92
......@@ -450,13 +450,13 @@ register_debug_trap(struct task_struct *child, unsigned long next_pc,
struct debug_trap *p = &child->thread.debug_trap;
unsigned long addr = next_pc & ~3;
if (p->nr_trap != 0) {
if (p->nr_trap == MAX_TRAPS) {
printk("kernel BUG at %s %d: p->nr_trap = %d\n",
__FILE__, __LINE__, p->nr_trap);
return -1;
}
p->addr = addr;
p->insn = next_insn;
p->addr[p->nr_trap] = addr;
p->insn[p->nr_trap] = next_insn;
p->nr_trap++;
if (next_pc & 3) {
*code = (next_insn & 0xffff0000) | 0x10f1;
......@@ -473,35 +473,34 @@ register_debug_trap(struct task_struct *child, unsigned long next_pc,
return 0;
}
int withdraw_debug_trap_for_signal(struct task_struct *child)
{
struct debug_trap *p = &child->thread.debug_trap;
int nr_trap = p->nr_trap;
if (nr_trap) {
access_process_vm(child, p->addr, &p->insn, sizeof(p->insn), 1);
p->nr_trap = 0;
p->addr = 0;
p->insn = 0;
}
return nr_trap;
}
static int
unregister_debug_trap(struct task_struct *child, unsigned long addr,
unsigned long *code)
{
struct debug_trap *p = &child->thread.debug_trap;
int i;
if (p->nr_trap != 1 || p->addr != addr) {
/* Search debug trap entry. */
for (i = 0; i < p->nr_trap; i++) {
if (p->addr[i] == addr)
break;
}
if (i >= p->nr_trap) {
/* The trap may be requested from debugger.
* ptrace should do nothing in this case.
*/
return 0;
}
*code = p->insn;
p->insn = 0;
p->addr = 0;
/* Recover orignal instruction code. */
*code = p->insn[i];
/* Shift debug trap entries. */
while (i < p->nr_trap - 1) {
p->insn[i] = p->insn[i + 1];
p->addr[i] = p->addr[i + 1];
i++;
}
p->nr_trap--;
return 1;
}
......@@ -510,13 +509,11 @@ static void
unregister_all_debug_traps(struct task_struct *child)
{
struct debug_trap *p = &child->thread.debug_trap;
int i;
if (p->nr_trap) {
access_process_vm(child, p->addr, &p->insn, sizeof(p->insn), 1);
p->addr = 0;
p->insn = 0;
p->nr_trap = 0;
}
for (i = 0; i < p->nr_trap; i++)
access_process_vm(child, p->addr[i], &p->insn[i], sizeof(p->insn[i]), 1);
p->nr_trap = 0;
}
static inline void
......@@ -575,34 +572,6 @@ embed_debug_trap(struct task_struct *child, unsigned long next_pc)
return 0; /* success */
}
void
embed_debug_trap_for_signal(struct task_struct *child)
{
unsigned long next_pc;
unsigned long pc, insn;
int ret;
pc = get_stack_long(child, PT_BPC);
ret = access_process_vm(child, pc&~3, &insn, sizeof(insn), 0);
if (ret != sizeof(insn)) {
printk("kernel BUG at %s %d: access_process_vm returns %d\n",
__FILE__, __LINE__, ret);
return;
}
compute_next_pc(insn, pc, &next_pc, child);
if (next_pc & 0x80000000) {
printk("kernel BUG at %s %d: next_pc = 0x%08x\n",
__FILE__, __LINE__, (int)next_pc);
return;
}
if (embed_debug_trap(child, next_pc)) {
printk("kernel BUG at %s %d: embed_debug_trap error\n",
__FILE__, __LINE__);
return;
}
invalidate_cache();
}
void
withdraw_debug_trap(struct pt_regs *regs)
{
......@@ -621,9 +590,12 @@ static void
init_debug_traps(struct task_struct *child)
{
struct debug_trap *p = &child->thread.debug_trap;
int i;
p->nr_trap = 0;
p->addr = 0;
p->insn = 0;
for (i = 0; i < MAX_TRAPS; i++) {
p->addr[i] = 0;
p->insn[i] = 0;
}
}
......@@ -855,4 +827,3 @@ void do_syscall_trace(void)
current->exit_code = 0;
}
}
......@@ -70,10 +70,12 @@ typedef struct {
unsigned long seg;
} mm_segment_t;
#define MAX_TRAPS 10
struct debug_trap {
int nr_trap;
unsigned long addr;
unsigned long insn;
unsigned long addr[MAX_TRAPS];
unsigned long insn[MAX_TRAPS];
};
struct thread_struct {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment