/*
 * Final probe matrix for the sys_xsyscall recursion.
 * usage: probe <n>   (each probe in its own process run)
 *  P1: raw  rax=0,   rdi=20    indirect getpid (clean asm)
 *  P2: raw  rax=0,   rdi=0     indirect syscall(0)   <-- recursion theory
 *  P3: raw  rax=198, rdi=198   indirect __syscall(198) <-- recursion theory
 *  P4: libc syscall(SYS_syscall, 20)
 *  P5: libc syscall(SYS_syscall, 197, 0,4096,3,0x1002,-1,0)  (stage-5 replay)
 *  P6: libc syscall(0, 0)
 *  P7: libc syscall(198, 198)
 *  P8: libc syscall(SYS___syscall, 20)
 */
#include <sys/syscall.h>
#include <sys/mman.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

static long rawsc(long raxv, long rdiv, long rsi, long rdx, long rcx,
		  long r8, long r9)
{
	register long out __asm__("rax");
	register long a_rax __asm__("rax") = raxv;
	register long a_rdi __asm__("rdi") = rdiv;
	register long a_rsi __asm__("rsi") = rsi;
	register long a_rdx __asm__("rdx") = rdx;
	register long a_rcx __asm__("rcx") = rcx;
	register long a_r8  __asm__("r8")  = r8;
	register long a_r9  __asm__("r9")  = r9;

	__asm__ volatile("syscall"
	    : "=r"(out)
	    : "0"(a_rax), "r"(a_rdi), "r"(a_rsi), "r"(a_rdx),
	      "r"(a_rcx), "r"(a_r8), "r"(a_r9)
	    : "r11", "memory");
	return out;
}

int main(int argc, char **argv)
{
	int n = argc > 1 ? atoi(argv[1]) : 0;
	long r = -99;

	switch (n) {
	case 1: r = rawsc(0, 20, 0, 0, 0, 0, 0); break;
	case 2: r = rawsc(0, 0, 0, 0, 0, 0, 0); break;
	case 3: r = rawsc(198, 198, 0, 0, 0, 0, 0); break;
	case 4: r = syscall(SYS_syscall, 20); break;
	case 5: r = syscall(SYS_syscall, 197, 0, 4096,
			   PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
		break;
	case 6: r = syscall(0, 0); break;
	case 7: r = syscall(198, 198); break;
	case 8: r = syscall(SYS___syscall, 20); break;
	default: printf("usage: probe 1..8\n"); return 2;
	}
	printf("P%d returned 0x%lx (%ld)\n", n, (unsigned long)r, r);
	return 0;
}
