extern bool not_failing_only;
extern bool show_fd_path;
extern bool tracing_paths;
+extern bool need_fork_exec_workarounds;
extern unsigned int xflag;
extern unsigned int followfork;
extern unsigned int ptrace_setoptions;
unsigned int followfork = 0;
unsigned int ptrace_setoptions = 0;
unsigned int xflag = 0;
+bool need_fork_exec_workarounds = 0;
bool debug_flag = 0;
bool Tflag = 0;
bool qflag = 0;
* First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
* and then see which options are supported by the kernel.
*/
-static void
+static int
test_ptrace_setoptions_followfork(void)
{
int pid, expected_grandchild = 0, found_grandchild = 0;
if (debug_flag)
fprintf(stderr, "ptrace_setoptions = %#x\n",
ptrace_setoptions);
- return;
+ return 0;
}
error_msg("Test for PTRACE_O_TRACECLONE failed, "
"giving up using this feature.");
+ return 1;
}
/*
* int $0x80
* (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
*/
-static void
+static int
test_ptrace_setoptions_for_all(void)
{
const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
int it_worked = 0;
/* this fork test doesn't work on no-mmu systems */
+ /* FIXME: isn't it better to assume we *succeed*? */
if (strace_vforked)
- return;
+ return 1;
pid = fork();
if (pid < 0)
if (debug_flag)
fprintf(stderr, "ptrace_setoptions = %#x\n",
ptrace_setoptions);
- return;
+ return 0;
}
error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
"giving up using this feature.");
+ return 1;
}
#ifdef USE_SEIZE
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)
- test_ptrace_setoptions_followfork();
- test_ptrace_setoptions_for_all();
+ need_fork_exec_workarounds = test_ptrace_setoptions_followfork();
+ need_fork_exec_workarounds |= test_ptrace_setoptions_for_all();
test_ptrace_seize();
/* Check if they want to redirect the output. */
#endif
static void
-internal_syscall(struct tcb *tcp)
+syscall_fixup_for_fork_exec(struct tcb *tcp)
{
/*
* We must always trace a few critical system calls in order to
}
#endif /* SYS_socket_subcall || SYS_ipc_subcall */
- internal_syscall(tcp);
+ if (need_fork_exec_workarounds)
+ syscall_fixup_for_fork_exec(tcp);
if ((SCNO_IN_RANGE(tcp->scno) &&
!(qual_flags[tcp->scno] & QUAL_TRACE)) ||
syscall_fixup_on_sysexit(tcp); /* never fails */
res = get_error(tcp); /* returns 1 or -1 */
if (res == 1) {
- internal_syscall(tcp);
+ if (need_fork_exec_workarounds)
+ syscall_fixup_for_fork_exec(tcp);
if (filtered(tcp)) {
goto ret;
}