Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+39 -8
+2 -8
arch/x86/include/asm/a.out-core.h
··· 17 17 18 18 #include <linux/user.h> 19 19 #include <linux/elfcore.h> 20 + #include <asm/debugreg.h> 20 21 21 22 /* 22 23 * fill in the user structure for an a.out core dump ··· 33 32 >> PAGE_SHIFT; 34 33 dump->u_dsize -= dump->u_tsize; 35 34 dump->u_ssize = 0; 36 - dump->u_debugreg[0] = current->thread.debugreg[0]; 37 - dump->u_debugreg[1] = current->thread.debugreg[1]; 38 - dump->u_debugreg[2] = current->thread.debugreg[2]; 39 - dump->u_debugreg[3] = current->thread.debugreg[3]; 40 - dump->u_debugreg[4] = 0; 41 - dump->u_debugreg[5] = 0; 42 - dump->u_debugreg[6] = current->thread.debugreg6; 43 - dump->u_debugreg[7] = current->thread.debugreg7; 35 + aout_dump_debugregs(dump); 44 36 45 37 if (dump->start_stack < TASK_SIZE) 46 38 dump->u_ssize = ((unsigned long)(TASK_SIZE - dump->start_stack))
+2
arch/x86/include/asm/debugreg.h
··· 89 89 set_debugreg(0UL, 3); 90 90 } 91 91 92 + extern void aout_dump_debugregs(struct user *dump); 93 + 92 94 #ifdef CONFIG_KVM 93 95 extern void hw_breakpoint_restore(void); 94 96 #endif
+35
arch/x86/kernel/hw_breakpoint.c
··· 376 376 } 377 377 378 378 /* 379 + * Dump the debug register contents to the user. 380 + * We can't dump our per cpu values because it 381 + * may contain cpu wide breakpoint, something that 382 + * doesn't belong to the current task. 383 + * 384 + * TODO: include non-ptrace user breakpoints (perf) 385 + */ 386 + void aout_dump_debugregs(struct user *dump) 387 + { 388 + int i; 389 + int dr7 = 0; 390 + struct perf_event *bp; 391 + struct arch_hw_breakpoint *info; 392 + struct thread_struct *thread = &current->thread; 393 + 394 + for (i = 0; i < HBP_NUM; i++) { 395 + bp = thread->ptrace_bps[i]; 396 + 397 + if (bp && !bp->attr.disabled) { 398 + dump->u_debugreg[i] = bp->attr.bp_addr; 399 + info = counter_arch_bp(bp); 400 + dr7 |= encode_dr7(i, info->len, info->type); 401 + } else { 402 + dump->u_debugreg[i] = 0; 403 + } 404 + } 405 + 406 + dump->u_debugreg[4] = 0; 407 + dump->u_debugreg[5] = 0; 408 + dump->u_debugreg[6] = current->thread.debugreg6; 409 + 410 + dump->u_debugreg[7] = dr7; 411 + } 412 + 413 + /* 379 414 * Release the user breakpoints used by ptrace 380 415 */ 381 416 void flush_ptrace_hw_breakpoint(struct task_struct *tsk)