_exit (0);
}
+static void linux_test_for_tracesysgood (int child_pid);
+static void linux_test_for_tracefork (int child_pid);
+
/* Determine ptrace features available on this target. */
static void
linux_check_ptrace_features (void)
{
int child_pid, ret, status;
- long second_pid;
/* Initialize the options. */
current_ptrace_options = 0;
error (_("linux_check_ptrace_features: waitpid: unexpected status %d."),
status);
- /* First, set the PTRACE_O_TRACEFORK option. If this fails, we
- know for sure that it is not supported. */
- ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0,
- (PTRACE_TYPE_ARG4) PTRACE_O_TRACEFORK);
+ linux_test_for_tracesysgood (child_pid);
- if (ret != 0)
+ linux_test_for_tracefork (child_pid);
+
+ /* Clean things up and kill any pending children. */
+ do
{
ret = ptrace (PTRACE_KILL, child_pid, (PTRACE_TYPE_ARG3) 0,
(PTRACE_TYPE_ARG4) 0);
if (ret != 0)
- {
- warning (_("linux_check_ptrace_features: failed to kill child"));
- return;
- }
-
- ret = my_waitpid (child_pid, &status, 0);
- if (ret != child_pid)
- warning (_("linux_check_ptrace_features: failed "
- "to wait for killed child"));
- else if (!WIFSIGNALED (status))
- warning (_("linux_check_ptrace_features: unexpected "
- "wait status 0x%x from killed child"), status);
-
- return;
+ warning (_("linux_check_ptrace_features: failed to kill child"));
+ my_waitpid (child_pid, &status, 0);
}
+ while (WIFSTOPPED (status));
+}
+
+/* Determine if PTRACE_O_TRACESYSGOOD can be used to catch
+ syscalls. */
+static void
+linux_test_for_tracesysgood (int child_pid)
+{
#ifdef GDBSERVER
- /* gdbserver does not support PTRACE_O_TRACESYSGOOD or
- PTRACE_O_TRACEVFORKDONE yet. */
+ /* gdbserver does not support PTRACE_O_TRACESYSGOOD. */
#else
- /* Check if the target supports PTRACE_O_TRACESYSGOOD. */
+ int ret;
+
ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0,
(PTRACE_TYPE_ARG4) PTRACE_O_TRACESYSGOOD);
if (ret == 0)
current_ptrace_options |= PTRACE_O_TRACESYSGOOD;
+#endif
+}
+
+/* Determine if PTRACE_O_TRACEFORK can be used to follow fork
+ events. */
+static void
+linux_test_for_tracefork (int child_pid)
+{
+ int ret, status;
+ long second_pid;
+
+ /* First, set the PTRACE_O_TRACEFORK option. If this fails, we
+ know for sure that it is not supported. */
+ ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0,
+ (PTRACE_TYPE_ARG4) PTRACE_O_TRACEFORK);
+
+ if (ret != 0)
+ return;
+
+#ifdef GDBSERVER
+ /* gdbserver does not support PTRACE_O_TRACEVFORKDONE yet. */
+#else
/* Check if the target supports PTRACE_O_TRACEVFORKDONE. */
ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0,
(PTRACE_TYPE_ARG4) (PTRACE_O_TRACEFORK
ret = ptrace (PTRACE_CONT, child_pid, (PTRACE_TYPE_ARG3) 0,
(PTRACE_TYPE_ARG4) 0);
if (ret != 0)
- warning (_("linux_check_ptrace_features: failed to resume child"));
+ warning (_("linux_test_for_tracefork: failed to resume child"));
ret = my_waitpid (child_pid, &status, 0);
ret = ptrace (PTRACE_KILL, second_pid, (PTRACE_TYPE_ARG3) 0,
(PTRACE_TYPE_ARG4) 0);
if (ret != 0)
- warning (_("linux_check_ptrace_features: "
+ warning (_("linux_test_for_tracefork: "
"failed to kill second child"));
my_waitpid (second_pid, &status, 0);
}
}
else
- warning (_("linux_check_ptrace_features: unexpected result from waitpid "
+ warning (_("linux_test_for_tracefork: unexpected result from waitpid "
"(%d, status 0x%x)"), ret, status);
-
- /* Clean things up and kill any pending children. */
- do
- {
- ret = ptrace (PTRACE_KILL, child_pid, (PTRACE_TYPE_ARG3) 0,
- (PTRACE_TYPE_ARG4) 0);
- if (ret != 0)
- warning (_("linux_check_ptrace_features: failed to kill child"));
- my_waitpid (child_pid, &status, 0);
- }
- while (WIFSTOPPED (status));
}
/* Enable reporting of all currently supported ptrace events. */