hw-breakpoints: Fix broken a.out format dump
authorFrederic Weisbecker <fweisbec@gmail.com>
Mon, 9 Nov 2009 20:03:43 +0000 (21:03 +0100)
committerFrederic Weisbecker <fweisbec@gmail.com>
Tue, 10 Nov 2009 10:23:05 +0000 (11:23 +0100)
Fix the broken a.out format dump. For now we only dump the ptrace
breakpoints.

TODO: Dump every perf breakpoints for the current thread, not only
ptrace based ones.

Reported-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: "K. Prasad" <prasad@linux.vnet.ibm.com>
arch/x86/include/asm/a.out-core.h
arch/x86/include/asm/debugreg.h
arch/x86/kernel/hw_breakpoint.c

index fc4685dd6e4de24a97e2090e597b64ebe4d8946d..7a15588e45d47265391ec508c787d98b374aaeb9 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <linux/user.h>
 #include <linux/elfcore.h>
+#include <asm/debugreg.h>
 
 /*
  * fill in the user structure for an a.out core dump
@@ -32,14 +33,7 @@ static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump)
                        >> PAGE_SHIFT;
        dump->u_dsize -= dump->u_tsize;
        dump->u_ssize = 0;
-       dump->u_debugreg[0] = current->thread.debugreg[0];
-       dump->u_debugreg[1] = current->thread.debugreg[1];
-       dump->u_debugreg[2] = current->thread.debugreg[2];
-       dump->u_debugreg[3] = current->thread.debugreg[3];
-       dump->u_debugreg[4] = 0;
-       dump->u_debugreg[5] = 0;
-       dump->u_debugreg[6] = current->thread.debugreg6;
-       dump->u_debugreg[7] = current->thread.debugreg7;
+       aout_dump_debugregs(dump);
 
        if (dump->start_stack < TASK_SIZE)
                dump->u_ssize = ((unsigned long)(TASK_SIZE - dump->start_stack))
index 9a3333c91f9af826f21c60fa96fd55c5674fea2d..f1b673f0823984134fde2ecb59d8fefa1edab2bc 100644 (file)
@@ -89,6 +89,8 @@ static inline void hw_breakpoint_disable(void)
        set_debugreg(0UL, 3);
 }
 
+extern void aout_dump_debugregs(struct user *dump);
+
 #ifdef CONFIG_KVM
 extern void hw_breakpoint_restore(void);
 #endif
index e622620790bdafa59fd6309edf6f5cb48cd10847..57dcee5fa958425be9be259a11deda5999c379f2 100644 (file)
@@ -375,6 +375,41 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp,
        return 0;
 }
 
+/*
+ * Dump the debug register contents to the user.
+ * We can't dump our per cpu values because it
+ * may contain cpu wide breakpoint, something that
+ * doesn't belong to the current task.
+ *
+ * TODO: include non-ptrace user breakpoints (perf)
+ */
+void aout_dump_debugregs(struct user *dump)
+{
+       int i;
+       int dr7 = 0;
+       struct perf_event *bp;
+       struct arch_hw_breakpoint *info;
+       struct thread_struct *thread = &current->thread;
+
+       for (i = 0; i < HBP_NUM; i++) {
+               bp = thread->ptrace_bps[i];
+
+               if (bp && !bp->attr.disabled) {
+                       dump->u_debugreg[i] = bp->attr.bp_addr;
+                       info = counter_arch_bp(bp);
+                       dr7 |= encode_dr7(i, info->len, info->type);
+               } else {
+                       dump->u_debugreg[i] = 0;
+               }
+       }
+
+       dump->u_debugreg[4] = 0;
+       dump->u_debugreg[5] = 0;
+       dump->u_debugreg[6] = current->thread.debugreg6;
+
+       dump->u_debugreg[7] = dr7;
+}
+
 /*
  * Release the user breakpoints used by ptrace
  */