Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9f6b3c2c authored by Frederic Weisbecker's avatar Frederic Weisbecker
Browse files

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: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarFrederic Weisbecker <fweisbec@gmail.com>
Cc: "K. Prasad" <prasad@linux.vnet.ibm.com>
parent 676c0dbe
Loading
Loading
Loading
Loading
+2 −8
Original line number Diff line number Diff line
@@ -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))
+2 −0
Original line number Diff line number Diff line
@@ -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
+35 −0
Original line number Diff line number Diff line
@@ -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
 */