Remove support for systems without PTRACE_SETOPTIONS

Assume that the kernel is v2.5.46 or newer, i.e. PTRACE_SETOPTIONS
and PTRACE_O_TRACESYSGOOD|PTRACE_O_TRACEEXEC|PTRACE_O_TRACECLONE
are universally available.

This change removes all code that implemented post-execve SIGTRAP
handling and fork/vfork/clone->CLONE_PTRACE substitution.

* defs.h (TCB_BPTSET, TCB_WAITEXECVE): Remove macros.
(need_fork_exec_workarounds, setbpt, clearbpt): Remove declarations.
* strace.c (need_fork_exec_workarounds,
test_ptrace_setoptions_followfork, test_ptrace_setoptions_for_all):
Remove.
(syscall_trap_sig): Set to (SIGTRAP | 0x80).
(ptrace_setoptions): Set to (PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC).
(detach): Do not test for TCB_BPTSET.
(init): Do not call test_ptrace_setoptions_followfork and
test_ptrace_setoptions_for_all.  Do not test for TCB_BPTSET.
* syscall.c (syscall_fixup_on_sysenter, internal_fork, internal_exec,
syscall_fixup_for_fork_exec, syscall_fixup_on_sysexit): Remove.
(trace_syscall_entering): Do not test for TCB_WAITEXECVE.  Do not call
syscall_fixup_on_sysenter and syscall_fixup_for_fork_exec.
(trace_syscall_exiting): Do not call syscall_fixup_on_sysexit and
syscall_fixup_for_fork_exec.
[IA64] (ia64_ia32mode): Make static.
* linux/ia64/arch_regs.h (ia64_ia32mode): Remove declaration.
* util.c: Do not include "syscall.h".
(arg_setup, get_arg0, get_arg1, set_arg0, set_arg1, restore_arg0,
restore_arg1, arg_finish_change, change_syscall, setbpt, clearbpt):
Remove.
* tests/ptrace_setoptions.test: Remove.
* tests/Makefile.am (TESTS): Remove it.
diff --git a/strace.c b/strace.c
index 0e131a1..fccf4ad 100644
--- a/strace.c
+++ b/strace.c
@@ -74,18 +74,17 @@
 # define fork() vfork()
 #endif
 
+const unsigned int syscall_trap_sig = SIGTRAP | 0x80;
+
 cflag_t cflag = CFLAG_NONE;
 unsigned int followfork = 0;
-unsigned int ptrace_setoptions = 0;
+unsigned int ptrace_setoptions = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC;
 unsigned int xflag = 0;
-bool need_fork_exec_workarounds = 0;
 bool debug_flag = 0;
 bool Tflag = 0;
 bool iflag = 0;
 bool count_wallclock = 0;
 unsigned int qflag = 0;
-/* Which WSTOPSIG(status) value marks syscall traps? */
-static unsigned int syscall_trap_sig = SIGTRAP;
 static unsigned int tflag = 0;
 static bool rflag = 0;
 static bool print_pid_pfx = 0;
@@ -347,7 +346,7 @@
 	int r;
 	if (!use_seize)
 		return ptrace(PTRACE_ATTACH, pid, 0L, 0L);
-	r = ptrace(PTRACE_SEIZE, pid, 0L, (unsigned long)ptrace_setoptions);
+	r = ptrace(PTRACE_SEIZE, pid, 0L, (unsigned long) ptrace_setoptions);
 	if (r)
 		return r;
 	r = ptrace(PTRACE_INTERRUPT, pid, 0L, 0L);
@@ -766,9 +765,6 @@
 	int error;
 	int status;
 
-	if (tcp->flags & TCB_BPTSET)
-		clearbpt(tcp);
-
 	/*
 	 * Linux wrongly insists the child be stopped
 	 * before detaching.  Arghh.  We go through hoops
@@ -1321,219 +1317,6 @@
 	}
 }
 
-/*
- * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
- * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
- * and then see which options are supported by the kernel.
- */
-static int
-test_ptrace_setoptions_followfork(void)
-{
-	int pid, expected_grandchild = 0, found_grandchild = 0;
-	const unsigned int test_options = PTRACE_O_TRACECLONE |
-					  PTRACE_O_TRACEFORK |
-					  PTRACE_O_TRACEVFORK;
-
-	/* Need fork for test. NOMMU has no forks */
-	if (NOMMU_SYSTEM)
-		goto worked; /* be bold, and pretend that test succeeded */
-
-	pid = fork();
-	if (pid < 0)
-		perror_msg_and_die("fork");
-	if (pid == 0) {
-		pid = getpid();
-		if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
-			perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
-					   __func__);
-		kill_save_errno(pid, SIGSTOP);
-		if (fork() < 0)
-			perror_msg_and_die("fork");
-		_exit(0);
-	}
-
-	while (1) {
-		int status, tracee_pid;
-
-		errno = 0;
-		tracee_pid = wait(&status);
-		if (tracee_pid <= 0) {
-			if (errno == EINTR)
-				continue;
-			if (errno == ECHILD)
-				break;
-			kill_save_errno(pid, SIGKILL);
-			perror_msg_and_die("%s: unexpected wait result %d",
-					   __func__, tracee_pid);
-		}
-		if (WIFEXITED(status)) {
-			if (WEXITSTATUS(status)) {
-				if (tracee_pid != pid)
-					kill_save_errno(pid, SIGKILL);
-				error_msg_and_die("%s: unexpected exit status %u",
-						  __func__, WEXITSTATUS(status));
-			}
-			continue;
-		}
-		if (WIFSIGNALED(status)) {
-			if (tracee_pid != pid)
-				kill_save_errno(pid, SIGKILL);
-			error_msg_and_die("%s: unexpected signal %u",
-					  __func__, WTERMSIG(status));
-		}
-		if (!WIFSTOPPED(status)) {
-			if (tracee_pid != pid)
-				kill_save_errno(tracee_pid, SIGKILL);
-			kill_save_errno(pid, SIGKILL);
-			error_msg_and_die("%s: unexpected wait status %x",
-					  __func__, status);
-		}
-		if (tracee_pid != pid) {
-			found_grandchild = tracee_pid;
-			if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
-				kill_save_errno(tracee_pid, SIGKILL);
-				kill_save_errno(pid, SIGKILL);
-				perror_msg_and_die("PTRACE_CONT doesn't work");
-			}
-			continue;
-		}
-		switch (WSTOPSIG(status)) {
-		case SIGSTOP:
-			if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
-			    && errno != EINVAL && errno != EIO)
-				perror_msg("PTRACE_SETOPTIONS");
-			break;
-		case SIGTRAP:
-			if (status >> 16 == PTRACE_EVENT_FORK) {
-				long msg = 0;
-
-				if (ptrace(PTRACE_GETEVENTMSG, pid,
-					   NULL, (long) &msg) == 0)
-					expected_grandchild = msg;
-			}
-			break;
-		}
-		if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
-			kill_save_errno(pid, SIGKILL);
-			perror_msg_and_die("PTRACE_SYSCALL doesn't work");
-		}
-	}
-	if (expected_grandchild && expected_grandchild == found_grandchild) {
- worked:
-		ptrace_setoptions |= test_options;
-		if (debug_flag)
-			fprintf(stderr, "ptrace_setoptions = %#x\n",
-				ptrace_setoptions);
-		return 0;
-	}
-	error_msg("Test for PTRACE_O_TRACECLONE failed, "
-		  "giving up using this feature.");
-	return 1;
-}
-
-/*
- * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
- * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
- * and then see whether it will stop with (SIGTRAP | 0x80).
- *
- * Use of this option enables correct handling of user-generated SIGTRAPs,
- * and SIGTRAPs generated by special instructions such as int3 on x86:
-
-# compile with: gcc -nostartfiles -nostdlib -o int3 int3.S
-_start:		.globl	_start
-		int3
-		movl	$42, %ebx
-		movl	$1, %eax
-		int	$0x80
- */
-static int
-test_ptrace_setoptions_for_all(void)
-{
-	const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
-					  PTRACE_O_TRACEEXEC;
-	int pid;
-	int it_worked = 0;
-
-	/* Need fork for test. NOMMU has no forks */
-	if (NOMMU_SYSTEM)
-		goto worked; /* be bold, and pretend that test succeeded */
-
-	pid = fork();
-	if (pid < 0)
-		perror_msg_and_die("fork");
-
-	if (pid == 0) {
-		pid = getpid();
-		if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
-			/* Note: exits with exitcode 1 */
-			perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
-					   __func__);
-		kill(pid, SIGSTOP);
-		_exit(0); /* parent should see entry into this syscall */
-	}
-
-	while (1) {
-		int status, tracee_pid;
-
-		errno = 0;
-		tracee_pid = wait(&status);
-		if (tracee_pid <= 0) {
-			if (errno == EINTR)
-				continue;
-			kill_save_errno(pid, SIGKILL);
-			perror_msg_and_die("%s: unexpected wait result %d",
-					   __func__, tracee_pid);
-		}
-		if (WIFEXITED(status)) {
-			if (WEXITSTATUS(status) == 0)
-				break;
-			error_msg_and_die("%s: unexpected exit status %u",
-					  __func__, WEXITSTATUS(status));
-		}
-		if (WIFSIGNALED(status)) {
-			error_msg_and_die("%s: unexpected signal %u",
-					  __func__, WTERMSIG(status));
-		}
-		if (!WIFSTOPPED(status)) {
-			kill(pid, SIGKILL);
-			error_msg_and_die("%s: unexpected wait status %x",
-					  __func__, status);
-		}
-		if (WSTOPSIG(status) == SIGSTOP) {
-			/*
-			 * We don't check "options aren't accepted" error.
-			 * If it happens, we'll never get (SIGTRAP | 0x80),
-			 * and thus will decide to not use the option.
-			 * IOW: the outcome of the test will be correct.
-			 */
-			if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
-			    && errno != EINVAL && errno != EIO)
-				perror_msg("PTRACE_SETOPTIONS");
-		}
-		if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
-			it_worked = 1;
-		}
-		if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
-			kill_save_errno(pid, SIGKILL);
-			perror_msg_and_die("PTRACE_SYSCALL doesn't work");
-		}
-	}
-
-	if (it_worked) {
- worked:
-		syscall_trap_sig = (SIGTRAP | 0x80);
-		ptrace_setoptions |= test_options;
-		if (debug_flag)
-			fprintf(stderr, "ptrace_setoptions = %#x\n",
-				ptrace_setoptions);
-		return 0;
-	}
-
-	error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
-		  "giving up using this feature.");
-	return 1;
-}
-
 #if USE_SEIZE
 static void
 test_ptrace_seize(void)
@@ -1871,14 +1654,12 @@
 		run_gid = getgid();
 	}
 
-	/*
-	 * On any reasonably recent Linux kernel (circa about 2.5.46)
-	 * need_fork_exec_workarounds should stay 0 after these tests:
-	 */
-	/*need_fork_exec_workarounds = 0; - already is */
 	if (followfork)
-		need_fork_exec_workarounds = test_ptrace_setoptions_followfork();
-	need_fork_exec_workarounds |= test_ptrace_setoptions_for_all();
+		ptrace_setoptions |= PTRACE_O_TRACECLONE |
+				     PTRACE_O_TRACEFORK |
+				     PTRACE_O_TRACEVFORK;
+	if (debug_flag)
+		fprintf(stderr, "ptrace_setoptions = %#x\n", ptrace_setoptions);
 	test_ptrace_seize();
 
 	/* Check if they want to redirect the output. */
@@ -2226,20 +2007,7 @@
 
 	tcp->flags &= ~TCB_STARTUP;
 
-	if (tcp->flags & TCB_BPTSET) {
-		/*
-		 * One example is a breakpoint inherited from
-		 * parent through fork().
-		 */
-		if (clearbpt(tcp) < 0) {
-			/* Pretty fatal */
-			droptcb(tcp);
-			exit_code = 1;
-			return false;
-		}
-	}
-
-	if (!use_seize && ptrace_setoptions) {
+	if (!use_seize) {
 		if (debug_flag)
 			fprintf(stderr, "setting opts 0x%x on pid %d\n",
 				ptrace_setoptions, tcp->pid);
@@ -2460,7 +2228,6 @@
 
 	/*
 	 * This should be syscall entry or exit.
-	 * (Or it still can be that pesky post-execve SIGTRAP!)
 	 * Handle it.
 	 */
 	if (trace_syscall(tcp) < 0) {