/* DF-5721 probe 2: PT_STEP over a `syscall` instruction (the cpu artifact
 * case filtered at trap.c:714-718).  Must deliver SIGTRAP to the tracee,
 * never enter DDB. */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#include <sys/wait.h>

int main(void)
{
	pid_t pid = fork();
	int st;

	if (pid == 0) {
		ptrace(PT_TRACE_ME, 0, (caddr_t)1, 0);
		kill(getpid(), SIGTRAP);	/* stop #1 */
		/* next instruction executed is `syscall` (getpid) while TF=1 */
		__asm__ __volatile__(
			"movq $39, %%rax\n\t"	/* SYS_getpid = 39 on DF x86_64 */
			"syscall\n\t"
			"int3"			/* stop #2: end marker */
			: : : "rax", "rcx", "r11");
		_exit(9);
	}
	wait(&st);
	printf("step: initial stop stopped=%d sig=%d\n",
	       WIFSTOPPED(st), WSTOPSIG(st));
	if (ptrace(PT_STEP, pid, (caddr_t)1, 0) < 0) {
		perror("PT_STEP");
		exit(1);
	}
	wait(&st);
	if (WIFSTOPPED(st))
		printf("step: after stepping over syscall: stopped=1 sig=%d\n",
		       WSTOPSIG(st));
	else if (WIFSIGNALED(st))
		printf("step: child DIED sig=%d\n", WTERMSIG(st));
	else
		printf("step: child exited %d\n", WEXITSTATUS(st));
	ptrace(PT_CONTINUE, pid, (caddr_t)1, 0);
	wait(&st);
	printf("step: final stop/exitsig=%d (5=TRAP expected)\n",
	       WIFSTOPPED(st) ? WSTOPSIG(st) :
	       (WIFSIGNALED(st) ? WTERMSIG(st) : -WEXITSTATUS(st)));
	return 0;
}
