hw-breakpoints: Fix broken a.out format dump
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>
This commit is contained in:
parent
676c0dbe6e
commit
9f6b3c2c30
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include <linux/user.h>
|
#include <linux/user.h>
|
||||||
#include <linux/elfcore.h>
|
#include <linux/elfcore.h>
|
||||||
|
#include <asm/debugreg.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fill in the user structure for an a.out core dump
|
* 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;
|
>> PAGE_SHIFT;
|
||||||
dump->u_dsize -= dump->u_tsize;
|
dump->u_dsize -= dump->u_tsize;
|
||||||
dump->u_ssize = 0;
|
dump->u_ssize = 0;
|
||||||
dump->u_debugreg[0] = current->thread.debugreg[0];
|
aout_dump_debugregs(dump);
|
||||||
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;
|
|
||||||
|
|
||||||
if (dump->start_stack < TASK_SIZE)
|
if (dump->start_stack < TASK_SIZE)
|
||||||
dump->u_ssize = ((unsigned long)(TASK_SIZE - dump->start_stack))
|
dump->u_ssize = ((unsigned long)(TASK_SIZE - dump->start_stack))
|
||||||
|
@ -89,6 +89,8 @@ static inline void hw_breakpoint_disable(void)
|
|||||||
set_debugreg(0UL, 3);
|
set_debugreg(0UL, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void aout_dump_debugregs(struct user *dump);
|
||||||
|
|
||||||
#ifdef CONFIG_KVM
|
#ifdef CONFIG_KVM
|
||||||
extern void hw_breakpoint_restore(void);
|
extern void hw_breakpoint_restore(void);
|
||||||
#endif
|
#endif
|
||||||
|
@ -375,6 +375,41 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp,
|
|||||||
return 0;
|
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 = ¤t->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
|
* Release the user breakpoints used by ptrace
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user