/*
 * simple example ptrace() code to help build basis for other tests
 *
 * Copyright (c) 2009 Analog Devices Inc.
 *
 * Licensed under the GPL-2 or later
 */

#define _GNU_SOURCE

#include <config.h>

#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/syscall.h>
#include "ptrace.h"

#include "test.h"
#include "usctest.h"
#include "spawn_ptrace_child.h"

#include "syscalls.h"

char *TCID = "simple_tracer";
int TST_TOTAL = 0;

#define _decode(name, val) \
({ \
	if (sizeof(long) == 4) \
		printf(name ":%08lx ", val); \
	else if (sizeof(long) == 8) \
		printf(name ":%016lx ", val); \
	else \
		printf(name ":%lx ", val); \
	val; \
})
#define decode(reg) _decode(#reg, pt->reg)
#define decode_user(name, offset) \
	_decode(name, vptrace(PTRACE_PEEKUSER, pid, offset, NULL));
#define decode_sysnum(nr) printf("%s ", get_sysnum(nr))
static void decode_regs(struct pt_regs *pt)
{
#if defined(__bfin__)
	long nr = decode_user("orig_p0", PT_ORIG_P0);
	decode(p0);
	decode(r0);
	decode(r1);
	decode(r2);
	decode(r3);
	decode(r4);
	decode(r5);
	decode_sysnum(nr);
	puts("");
#elif defined(__i386__)
	long nr = decode_user("orig_eax", 4 * ORIG_EAX);
	decode(eax);
	decode(ebx);
	decode(ecx);
	decode(edx);
	decode(esi);
	decode(edi);
	decode(ebp);
	decode_sysnum(nr);
	puts("");
#elif defined(__x86_64__)
	long nr = decode_user("orig_rax", 8 * ORIG_RAX);
	decode(rax);
	decode(rbx);
	decode(rcx);
	decode(rdx);
	decode(rsi);
	decode(rdi);
	decode(rbp);
	decode_sysnum(nr);
	puts("");
#elif defined(__sparc__)
#define G1 u_regs[0]
#define G2 u_regs[1]
#define G3 u_regs[2]
#define G4 u_regs[3]
#define G5 u_regs[4]
#define G6 u_regs[5]
#define G7 u_regs[6]
#define O0 u_regs[7]
#define O1 u_regs[8]
#define O2 u_regs[9]
#define O3 u_regs[10]
#define O4 u_regs[11]
#define O5 u_regs[12]
#define O6 u_regs[13]
#define O7 u_regs[14]
	decode(G1);
	decode(G2);
	decode(G3);
	decode(G4);
	decode(G5);
	decode(G6);
	decode(G7);
	decode(O0);
	decode(O1);
	decode(O2);
	decode(O3);
	decode(O4);
	decode(O5);
	decode(O6);
	decode(O7);
	decode_sysnum(pt->G1);
	puts("");
#else
#warning "no idea how to decode your arch"
	puts("no idea how to decode your arch");
#endif
}

int main(int argc, char *argv[])
{
	struct pt_regs pt_regs;
	long ret;
	int status;

	make_a_baby(argc, argv);

	while (1) {
		ret = vptrace(PTRACE_GETREGS, pid, NULL, &pt_regs);
		if (ret)
			break;
		decode_regs(&pt_regs);

		ret = vptrace(PTRACE_SYSCALL, pid, NULL, NULL);
		if (ret)
			break;

		if (waitpid(pid, &status, 0) == -1)
			break;
	}

	/* hopefully this worked */
	vptrace(PTRACE_KILL, pid, NULL, NULL);

	tst_exit();
}
