/*
 * Copyright (C) 2011 Red Hat, Inc., Frederic Weisbecker <fweisbec@redhat.com>
 *
 * Licensed under the terms of the GNU GPL License version 2
 *
 * Selftests for breakpoints (and more generally the do_debug() path) in x86.
 */


#include <sys/ptrace.h>
#include <unistd.h>
#include <stddef.h>
#include <sys/user.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>


/* Breakpoint access modes */
enum {
	BP_X = 1,
	BP_RW = 2,
	BP_W = 4,
};

static pid_t child_pid;

/*
 * Ensures the child and parent are always "talking" about
 * the same test sequence. (ie: that we haven't forgotten
 * to call check_trapped() somewhere).
 */
static int nr_tests;

static void set_breakpoint_addr(void *addr, int n)
{
	int ret;

	ret = ptrace(PTRACE_POKEUSER, child_pid,
		     offsetof(struct user, u_debugreg[n]), addr);
	if (ret) {
		perror("Can't set breakpoint addr\n");
		exit(-1);
	}
}

static void toggle_breakpoint(int n, int type, int len,
			      int local, int global, int set)
{
	int ret;

	int xtype, xlen;
	unsigned long vdr7, dr7;

	switch (type) {
	case BP_X:
		xtype = 0;
		break;
	case BP_W:
		xtype = 1;
		break;
	case BP_RW:
		xtype = 3;
		break;
	}

	switch (len) {
	case 1:
		xlen = 0;
		break;
	case 2:
		xlen = 4;
		break;
	case 4:
		xlen = 0xc;
		break;
	case 8:
		xlen = 8;
		break;
	}

	dr7 = ptrace(PTRACE_PEEKUSER, child_pid,
		     offsetof(struct user, u_debugreg[7]), 0);

	vdr7 = (xlen | xtype) << 16;
	vdr7 <<= 4 * n;

	if (local) {
		vdr7 |= 1 << (2 * n);
		vdr7 |= 1 << 8;
	}
	if (global) {
		vdr7 |= 2 << (2 * n);
		vdr7 |= 1 << 9;
	}

	if (set)
		dr7 |= vdr7;
	else
		dr7 &= ~vdr7;

	ret = ptrace(PTRACE_POKEUSER, child_pid,
		     offsetof(struct user, u_debugreg[7]), dr7);
	if (ret) {
		perror("Can't set dr7");
		exit(-1);
	}
}

/* Dummy variables to test read/write accesses */
static unsigned long long dummy_var[4];

/* Dummy functions to test execution accesses */
static void dummy_func(void) { }
static void dummy_func1(void) { }
static void dummy_func2(void) { }
static void dummy_func3(void) { }

static void (*dummy_funcs[])(void) = {
	dummy_func,
	dummy_func1,
	dummy_func2,
	dummy_func3,
};

static int trapped;

static void check_trapped(void)
{
	/*
	 * If we haven't trapped, wake up the parent
	 * so that it notices the failure.
	 */
	if (!trapped)
		kill(getpid(), SIGUSR1);
	trapped = 0;

	nr_tests++;
}

static void write_var(int len)
{
	char *pcval; short *psval; int *pival; long long *plval;
	int i;

	for (i = 0; i < 4; i++) {
		switch (len) {
		case 1:
			pcval = (char *)&dummy_var[i];
			*pcval = 0xff;
			break;
		case 2:
			psval = (short *)&dummy_var[i];
			*psval = 0xffff;
			break;
		case 4:
			pival = (int *)&dummy_var[i];
			*pival = 0xffffffff;
			break;
		case 8:
			plval = (long long *)&dummy_var[i];
			*plval = 0xffffffffffffffffLL;
			break;
		}
		check_trapped();
	}
}

static void read_var(int len)
{
	char cval; short sval; int ival; long long lval;
	int i;

	for (i = 0; i < 4; i++) {
		switch (len) {
		case 1:
			cval = *(char *)&dummy_var[i];
			break;
		case 2:
			sval = *(short *)&dummy_var[i];
			break;
		case 4:
			ival = *(int *)&dummy_var[i];
			break;
		case 8:
			lval = *(long long *)&dummy_var[i];
			break;
		}
		check_trapped();
	}
}

/*
 * Do the r/w/x accesses to trigger the breakpoints. And run
 * the usual traps.
 */
static void trigger_tests(void)
{
	int len, local, global, i;
	char val;
	int ret;

	ret = ptrace(PTRACE_TRACEME, 0, NULL, 0);
	if (ret) {
		perror("Can't be traced?\n");
		return;
	}

	/* Wake up father so that it sets up the first test */
	kill(getpid(), SIGUSR1);

	/* Test instruction breakpoints */
	for (local = 0; local < 2; local++) {
		for (global = 0; global < 2; global++) {
			if (!local && !global)
				continue;

			for (i = 0; i < 4; i++) {
				dummy_funcs[i]();
				check_trapped();
			}
		}
	}

	/* Test write watchpoints */
	for (len = 1; len <= sizeof(long); len <<= 1) {
		for (local = 0; local < 2; local++) {
			for (global = 0; global < 2; global++) {
				if (!local && !global)
					continue;
				write_var(len);
			}
		}
	}

	/* Test read/write watchpoints (on read accesses) */
	for (len = 1; len <= sizeof(long); len <<= 1) {
		for (local = 0; local < 2; local++) {
			for (global = 0; global < 2; global++) {
				if (!local && !global)
					continue;
				read_var(len);
			}
		}
	}

	/* Icebp trap */
	asm(".byte 0xf1\n");
	check_trapped();

	/* Int 3 trap */
	asm("int $3\n");
	check_trapped();

	kill(getpid(), SIGUSR1);
}

static void check_success(const char *msg)
{
	const char *msg2;
	int child_nr_tests;
	int status;

	/* Wait for the child to SIGTRAP */
	wait(&status);

	msg2 = "Failed";

	if (WSTOPSIG(status) == SIGTRAP) {
		child_nr_tests = ptrace(PTRACE_PEEKDATA, child_pid,
					&nr_tests, 0);
		if (child_nr_tests == nr_tests)
			msg2 = "Ok";
		if (ptrace(PTRACE_POKEDATA, child_pid, &trapped, 1)) {
			perror("Can't poke\n");
			exit(-1);
		}
	}

	nr_tests++;

	printf("%s [%s]\n", msg, msg2);
}

static void launch_instruction_breakpoints(char *buf, int local, int global)
{
	int i;

	for (i = 0; i < 4; i++) {
		set_breakpoint_addr(dummy_funcs[i], i);
		toggle_breakpoint(i, BP_X, 1, local, global, 1);
		ptrace(PTRACE_CONT, child_pid, NULL, 0);
		sprintf(buf, "Test breakpoint %d with local: %d global: %d",
			i, local, global);
		check_success(buf);
		toggle_breakpoint(i, BP_X, 1, local, global, 0);
	}
}

static void launch_watchpoints(char *buf, int mode, int len,
			       int local, int global)
{
	const char *mode_str;
	int i;

	if (mode == BP_W)
		mode_str = "write";
	else
		mode_str = "read";

	for (i = 0; i < 4; i++) {
		set_breakpoint_addr(&dummy_var[i], i);
		toggle_breakpoint(i, mode, len, local, global, 1);
		ptrace(PTRACE_CONT, child_pid, NULL, 0);
		sprintf(buf, "Test %s watchpoint %d with len: %d local: "
			"%d global: %d", mode_str, i, len, local, global);
		check_success(buf);
		toggle_breakpoint(i, mode, len, local, global, 0);
	}
}

/* Set the breakpoints and check the child successfully trigger them */
static void launch_tests(void)
{
	char buf[1024];
	int len, local, global, i;

	/* Instruction breakpoints */
	for (local = 0; local < 2; local++) {
		for (global = 0; global < 2; global++) {
			if (!local && !global)
				continue;
			launch_instruction_breakpoints(buf, local, global);
		}
	}

	/* Write watchpoint */
	for (len = 1; len <= sizeof(long); len <<= 1) {
		for (local = 0; local < 2; local++) {
			for (global = 0; global < 2; global++) {
				if (!local && !global)
					continue;
				launch_watchpoints(buf, BP_W, len,
						   local, global);
			}
		}
	}

	/* Read-Write watchpoint */
	for (len = 1; len <= sizeof(long); len <<= 1) {
		for (local = 0; local < 2; local++) {
			for (global = 0; global < 2; global++) {
				if (!local && !global)
					continue;
				launch_watchpoints(buf, BP_RW, len,
						   local, global);
			}
		}
	}

	/* Icebp traps */
	ptrace(PTRACE_CONT, child_pid, NULL, 0);
	check_success("Test icebp");

	/* Int 3 traps */
	ptrace(PTRACE_CONT, child_pid, NULL, 0);
	check_success("Test int 3 trap");

	ptrace(PTRACE_CONT, child_pid, NULL, 0);
}

int main(int argc, char **argv)
{
	pid_t pid;
	int ret;

	pid = fork();
	if (!pid) {
		trigger_tests();
		return 0;
	}

	child_pid = pid;

	wait(NULL);

	launch_tests();

	wait(NULL);

	return 0;
}
