aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Jacobowitz <drow@false.org>2007-11-01 19:19:39 +0000
committerDaniel Jacobowitz <drow@false.org>2007-11-01 19:19:39 +0000
commit51c2684ec132409fcc073686f6eb2574c332b7c6 (patch)
treeddfb5bcab6fa3f1f3dbde954008c193c9b4cf97f
parent7ce189b305dfcd2d0c094d763696f71a67baaab3 (diff)
downloadgdb-51c2684ec132409fcc073686f6eb2574c332b7c6.zip
gdb-51c2684ec132409fcc073686f6eb2574c332b7c6.tar.gz
gdb-51c2684ec132409fcc073686f6eb2574c332b7c6.tar.bz2
* linux-low.c (linux_tracefork_grandchild): New.
(linux_tracefork_child): Use clone. (linux_test_for_tracefork): Use clone; allocate and free a stack.
-rw-r--r--gdb/gdbserver/ChangeLog6
-rw-r--r--gdb/gdbserver/linux-low.c26
2 files changed, 23 insertions, 9 deletions
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 518901e..4c56ce0 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,9 @@
+2007-11-01 Daniel Jacobowitz <dan@codesourcery.com>
+
+ * linux-low.c (linux_tracefork_grandchild): New.
+ (linux_tracefork_child): Use clone.
+ (linux_test_for_tracefork): Use clone; allocate and free a stack.
+
2007-10-31 Joel Brobecker <brobecker@adacore.com>
* Makefile.in: Use $(SHELL) instead of "sh" to call regdat.sh.
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index fb80020..9876491 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -1732,14 +1732,20 @@ linux_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
static int linux_supports_tracefork_flag;
-/* A helper function for linux_test_for_tracefork, called after fork (). */
+/* Helper functions for linux_test_for_tracefork, called via clone (). */
-static void
-linux_tracefork_child (void)
+static int
+linux_tracefork_grandchild (void *arg)
+{
+ _exit (0);
+}
+
+static int
+linux_tracefork_child (void *arg)
{
ptrace (PTRACE_TRACEME, 0, 0, 0);
kill (getpid (), SIGSTOP);
- fork ();
+ clone (linux_tracefork_grandchild, arg, CLONE_VM | SIGCHLD, NULL);
_exit (0);
}
@@ -1767,15 +1773,15 @@ linux_test_for_tracefork (void)
{
int child_pid, ret, status;
long second_pid;
+ char *stack = malloc (8192);
linux_supports_tracefork_flag = 0;
- child_pid = fork ();
+ /* Use CLONE_VM instead of fork, to support uClinux (no MMU). */
+ child_pid = clone (linux_tracefork_child, stack + 2048,
+ CLONE_VM | SIGCHLD, stack + 6144);
if (child_pid == -1)
- perror_with_name ("fork");
-
- if (child_pid == 0)
- linux_tracefork_child ();
+ perror_with_name ("clone");
ret = my_waitpid (child_pid, &status, 0);
if (ret == -1)
@@ -1840,6 +1846,8 @@ linux_test_for_tracefork (void)
my_waitpid (child_pid, &status, 0);
}
while (WIFSTOPPED (status));
+
+ free (stack);
}