From: Luis Machado <lgustavo@codesourcery.com>
To: Pedro Alves <palves@redhat.com>
Cc: "'gdb-patches@sourceware.org'" <gdb-patches@sourceware.org>,
Tom Tromey <tromey@redhat.com>
Subject: Re: [PATCH, v2] Share ptrace options discovery/linux native code between GDB and gdbserver
Date: Wed, 21 Aug 2013 03:09:00 -0000 [thread overview]
Message-ID: <52142F4B.7030702@codesourcery.com> (raw)
In-Reply-To: <52139BBA.60300@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 11475 bytes --]
Hi,
On 08/20/2013 01:39 PM, Pedro Alves wrote:
> On 08/20/2013 12:27 AM, Luis Machado wrote:
>
>> diff --git a/gdb/common/linux-ptrace.c b/gdb/common/linux-ptrace.c
>> index d5ac061..4198d1d 100644
>> --- a/gdb/common/linux-ptrace.c
>> +++ b/gdb/common/linux-ptrace.c
>> @@ -25,10 +25,16 @@
>>
>> #include "linux-ptrace.h"
>> #include "linux-procfs.h"
>> +#include "nat/linux-waitpid.h"
>> #include "buffer.h"
>> #include "gdb_assert.h"
>> #include "gdb_wait.h"
>>
>> +/* Stores the currently supported ptrace options. A value of
>> + -1 means we did not check for features yet. A value of 0 means
>> + there are no supported features. */
>> +static int current_ptrace_options = -1;
>> +
>> /* Find all possible reasons we could fail to attach PID and append these
>> newline terminated reason strings to initialized BUFFER. '\0' termination
>> of BUFFER must be done by the caller. */
>> @@ -222,6 +228,284 @@ linux_ptrace_test_ret_to_nx (void)
>> #endif /* defined __i386__ || defined __x86_64__ */
>> }
>>
>> +/* Helper function to fork a process and make the child process call
>> + the function FUNCTION passing ARG as parameter. */
>> +
>> +static int
>> +linux_fork_to_function (void *arg, void (*function) (void *))
>
> The describing comment and the function prototype imply some
> sort of generity. But ...
>
>> +{
>> + int child_pid;
>> +
>> + gdb_byte *stack = (gdb_byte *) arg;
>
> The arg has a definite particular use.
>
>> +
>> + /* Sanity check the function pointer. */
>> + gdb_assert (function != NULL);
>> +
>> +#if defined(__UCLIBC__) && defined(HAS_NOMMU)
>> +#define STACK_SIZE 4096
>> +
>> + if (arg == NULL)
>> + stack = xmalloc (STACK_SIZE * 4);
>
> Etc. Something's odd with the abstration.
>
I've improved this now. We have a special case for MMU-less targets
(gdbserver's side), though it is not quite clear due to the lack of
comments in that code.
>> +
>> + /* Use CLONE_VM instead of fork, to support uClinux (no MMU). */
>> + #ifdef __ia64__
>> + child_pid = __clone2 (function, stack, STACK_SIZE,
>> + CLONE_VM | SIGCHLD, stack + STACK_SIZE * 2);
>> + #else /* !__ia64__ */
>> + child_pid = clone (function, stack + STACK_SIZE,
>> + CLONE_VM | SIGCHLD, stack + STACK_SIZE * 2);
>> + #endif /* !__ia64__ */
>> +#else /* !defined(__UCLIBC) && defined(HAS_NOMMU) */
>> + child_pid = fork ();
>> +
>> + if (child_pid == 0)
>> + function (stack);
>> +#endif /* defined(__UCLIBC) && defined(HAS_NOMMU) */
>> +
>> + if (child_pid == -1)
>> + perror_with_name (("fork"));
>> +
>> + return 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;
>> +
>> + /* Fork a child so we can do some testing. The child will call
>> + linux_child_function and will get traced. The child will
>> + eventually fork a grandchild so we can test fork event
>> + reporting. */
>> + child_pid = linux_fork_to_function (NULL, linux_child_function);
>> +
>> + ret = my_waitpid (child_pid, &status, 0);
>> + if (ret == -1)
>> + perror_with_name (("waitpid"));
>> + else if (ret != child_pid)
>> + error (_("linux_check_ptrace_features: waitpid: unexpected result %d."),
>> + ret);
>> + if (! WIFSTOPPED (status))
>> + error (_("linux_check_ptrace_features: waitpid: unexpected status %d."),
>> + status);
>> +
>> +#ifdef GDBSERVER
>> + /* gdbserver does not support PTRACE_O_TRACEFORK yet. */
>
>
> This here doesn't look right ...
>
>> +#else
>> + /* 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_O_TRACEFORK);
>> +#endif
>> +
>> + if (ret != 0)
>
> ... as this looks like will always be reached for gdbserver.
> The PTRACE_O_TRACEFORK testing is being used in gdbserver as
> proxy for close tracing support.
>
I've removed the guards now. gdbserver should be able to run this chunk
of code and lie about not supporting PTRACE_O_TRACEFORK later on.
>> +#ifdef GDBSERVER
>> + /* gdbserver does not support PTRACE_O_TRACESYSGOOD or
>> + PTRACE_O_TRACEVFORKDONE yet. */
>> +#else
>> + /* Check if the target supports PTRACE_O_TRACESYSGOOD. */
>> + ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0,
>> + PTRACE_O_TRACESYSGOOD);
>> + current_ptrace_options |= (ret == 0)? PTRACE_O_TRACESYSGOOD : 0;
>
> Space before '?'.
>
> Arguably,
>
> if (ret == 0)
> current_ptrace_options |= PTRACE_O_TRACESYSGOOD;
>
> would be more straightforward to read.
>
I've used your suggestion now.
>> +/* Enable reporting of all currently supported ptrace events. */
>> +
>> +void
>> +linux_enable_event_reporting (ptid_t ptid)
>
> Could you preserve gdbserver's prototype here, please? That
> is, take a single integer pid rather than a ptid.
>
Done.
>> + /* Check if we have initialized the ptrace features for this
>> + target. If not, do it now. */
>> + if (current_ptrace_options == -1)
>> + linux_check_ptrace_features ();
>> +
>> + /* Do not enable PTRACE_O_TRACEEXIT until GDB is more prepared to
>> + support read-only process state. */
>
> This comment really belongs close to where current_ptrace_options
> is set. That in, in the original code, read it as attached to
> the "current_ptrace_options |= " bits above, not the ptrace call
> below.
>
Moved closer to where it belongs.
>> +/* Returns non-zero if PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK,
>> + PTRACE_O_TRACECLONE and PTRACE_O_TRACEEXEC are supported by
>> + ptrace, 0 otherwise */
>
> Missing period. Given the name of the function, I'd suggest instead:
>
> /* Returns non-zero if PTRACE_EVENT_FORK is supported by ptrace,
> 0 otherwise. Note that if PTRACE_EVENT_FORK is supported so is
> PTRACE_EVENT_CLONE, PTRACE_EVENT_EXEC and PTRACE_EVENT_VFORK,
> since they were all added to the kernel at the same time.
>
Done. Thanks.
>> +
>> +int
>> +linux_supports_tracefork (void)
>> +{
>> + return ptrace_supports_feature (PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK
>> + | PTRACE_O_TRACECLONE | PTRACE_O_TRACEEXEC);
>
> Well, this is now wrong given gdbserver will only set PTRACE_O_TRACECLONE
> in the current_ptrace_options. Given the revised comment above,
> this can all be replaced with:
>
> return ptrace_supports_feature (PTRACE_O_TRACECLONE);
>
> and so it'll work for both gdb and gdbserver. When gdbserver supports
> tracing forks, we can go back here and check PTRACE_O_TRACEFORK instead,
> just for clarity of the code. WDYT?
I don't think it looks great, but it should do the job for the moment
while we teach gdbserver to support the other features. Good enough maybe?
>
> BTW, these function are extern, and the same describing comment is
> duplicated in the declarations in the header file. Best leave only one
> copy, near the declarations.
>
Done.
>> diff --git a/gdb/common/linux-ptrace.h b/gdb/common/linux-ptrace.h
>> index 8f02c82..005da3d 100644
>> --- a/gdb/common/linux-ptrace.h
>> +++ b/gdb/common/linux-ptrace.h
>> @@ -22,6 +22,24 @@ struct buffer;
>>
>
>> +#ifdef GDBSERVER
>> +#if !defined (PTRACE_TYPE_ARG3)
>
> Why the #if !defines if the PTRACE_TYPE_... definitions
> have been removed from linux-low.h ?
>
I've replaced these with a configure-time check in configure.ac as
Tromey hinted at, similar to GDB's. Looks cleaner this way.
Thanks Tom.
>> +#define PTRACE_TYPE_ARG3 void *
>> +#endif
>> +
>> +#if !defined (PTRACE_TYPE_ARG4)
>> +#define PTRACE_TYPE_ARG4 void *
>> +#endif
>> +#endif /* GDBSERVER */
>
>
These are gone now.
>> diff --git a/gdb/config.in b/gdb/config.in
>> index 76abd04..5a80001 100644
>> --- a/gdb/config.in
>> +++ b/gdb/config.in
>> @@ -659,6 +659,9 @@
>> /* Define to the type of arg 3 for ptrace. */
>> #undef PTRACE_TYPE_ARG3
>>
>> +/* Define to the type of arg 3 for ptrace. */
>> +#undef PTRACE_TYPE_ARG4
>
> Off by one in comment...
>
>> +
>> /* Define to the type of arg 5 for ptrace. */
>> #undef PTRACE_TYPE_ARG5
>>
>
>> diff --git a/gdb/configure.ac b/gdb/configure.ac
>> index 667821f..0982cac 100644
>> --- a/gdb/configure.ac
>> +++ b/gdb/configure.ac
>> @@ -1207,7 +1207,7 @@ AC_CACHE_CHECK([types of arguments for ptrace], gdb_cv_func_ptrace_args, [
>> for gdb_arg1 in 'int' 'long'; do
>> for gdb_arg2 in 'pid_t' 'int' 'long'; do
>> for gdb_arg3 in 'int *' 'caddr_t' 'int' 'long' 'void *'; do
>> - for gdb_arg4 in 'int' 'long'; do
>> + for gdb_arg4 in 'int' 'long' 'void *'; do
>> AC_TRY_COMPILE($gdb_ptrace_headers, [
>> extern $gdb_cv_func_ptrace_ret
>> ptrace ($gdb_arg1, $gdb_arg2, $gdb_arg3, $gdb_arg4);
>> @@ -1234,6 +1234,8 @@ IFS=$ac_save_IFS
>> shift
>> AC_DEFINE_UNQUOTED(PTRACE_TYPE_ARG3, $[3],
>> [Define to the type of arg 3 for ptrace.])
>> +AC_DEFINE_UNQUOTED(PTRACE_TYPE_ARG4, $[4],
>> + [Define to the type of arg 4 for ptrace.])
>
> ... but here the comment looks right, so I think you just
> forgot to regenerate config.in.
>
Fixed by regenerating the required files.
>> INCLUDE_CFLAGS = -I. -I${srcdir} -I$(srcdir)/../common \
>> -I$(srcdir)/../regformats -I$(srcdir)/../ -I$(INCLUDE_DIR) \
>> $(INCGNU)
>> @@ -157,8 +162,10 @@ SFILES= $(srcdir)/gdbreplay.c $(srcdir)/inferiors.c $(srcdir)/dll.c \
>> $(srcdir)/common/common-utils.c $(srcdir)/common/xml-utils.c \
>> $(srcdir)/common/linux-osdata.c $(srcdir)/common/ptid.c \
>> $(srcdir)/common/buffer.c $(srcdir)/common/linux-btrace.c \
>> - $(srcdir)/common/filestuff.c $(srcdir)/target/waitstatus.c \
>> - $(srcdir)/common/mips-linux-watch.c
>> + $(srcdir)/common/filestuff.c $(srcdir)/common/linux-ptrace.c \
>> + $(srcdir)/common/mips-linux-watch.c \
>> + $(srcdir)/target/waitstatus.c \
>> + $(srcdir)/nat/linux-waitpid.c \
>
> Hmm, so linux-ptrace.c was missing? (It's a bit harder than expected to
> see what's doing on in this hunk, given the order's been changed.)
> It seems linux-procfs.c is missing too, and probably others. Please do that
> as separate patch... This is penance for forgetting that backslash in the
> last line, and forcing me to look closer. ;-)
>
The identation problem with the mips-linux-watch.c entry bothered me,
but turns out the inclusion of linux-ptrace.c and linux-waitpid.c isn't
needed at all. I have a successful build without any change to SFILES.
>>
>> DEPFILES = @GDBSERVER_DEPFILES@
>>
>> @@ -447,7 +454,8 @@ server_h = $(srcdir)/server.h $(regcache_h) $(srcdir)/target.h \
>> $(generated_files)
>>
>> gdbthread_h = $(srcdir)/gdbthread.h $(target_h) $(srcdir)/server.h
>> -linux_low_h = $(srcdir)/linux-low.h $(gdbthread_h)
>> +linux_low_h = $(srcdir)/linux-low.h $(srcdir)/../nat/linux-nat.h \
>> + $(srcdir)/../nat/linux-waitpid.h $(gdbthread_h)
>
> Is this really necessary, given we now have automatic dependencies
> in gdbserver? $linux_low_h even used anywhere at all. Looks
> like these variables are just waiting to be garbage collected...
>
Probably not. I removed this change now.
I've also included linux-ptrace.o by default in the linux object files
list (in configure.srv).
All the other small nits are hopefully fixed now as well.
Regression-tested again. Results look good.
Thanks!
Luis
[-- Attachment #2: ptrace_share.diff --]
[-- Type: text/x-patch, Size: 71430 bytes --]
2013-08-20 Luis Machado <lgustavo@codesourcery.com>
gdb/
* Makefile.in (HFILES_NO_SRCDIR): Add nat/linux-nat.h and
nat/linux-waitpid.h.
(linux-waitpid.o): New object file rule.
* common/linux-ptrace.c: Include nat/linux-waitpid.h.
(current_ptrace_options): Moved from linux-nat.c.
(linux_fork_to_function): New function.
(linux_grandchild_function): Likewise.
(linux_child_function): Likewise.
(linux_check_ptrace_features): New function, heavily
based on linux-nat.c:linux_test_for_tracefork.
(linux_enable_event_reporting): New function.
(ptrace_supports_feature): Likewise.
(linux_supports_tracefork): Likewise.
(linux_supports_tracevforkdone): Likewise.
(linux_supports_tracesysgood): Likewise.
* common/linux-ptrace.h (HAS_NOMMU): Moved from
gdbserver/linux-low.c.
(linux_enable_event_reporting): New declaration.
(linux_supports_tracefork): Likewise.
(linux_supports_tracevforkdone): Likewise.
(linux_supports_tracesysgood): Likewise.
* config.in (PTRACE_TYPE_ARG4): Regenerate.
* config/aarch64/linux.mh (NATDEPFILES): Add linux-waitpid.o.
* config/alpha/alpha-linux.mh (NATDEPFILES): Likewise.
* config/arm/linux.mh (NATDEPFILES): Likewise.
* config/i386/linux.mh (NATDEPFILES): Likewise.
* config/i386/linux64.mh (NATDEPFILES): Likewise.
* config/ia64/linux.mh (NATDEPFILES): Likewise.
* config/m32r/linux.mh (NATDEPFILES): Likewise.
* config/m68k/linux.mh (NATDEPFILES): Likewise.
* config/mips/linux.mh (NATDEPFILES): Likewise.
* config/pa/linux.mh (NATDEPFILES): Likewise..
* config/powerpc/linux.mh (NATDEPFILES): Likewise..
* config/powerpc/ppc64-linux.mh (NATDEPFILES): Likewise.
* config/powerpc/spu-linux.mh (NATDEPFILES): Likewise.
* config/sparc/linux.mh (NATDEPFILES): Likewise.
* config/sparc/linux64.mh (NATDEPFILES): Likewise.
* config/tilegx/linux.mh (NATDEPFILES): Likewise.
* config/xtensa/linux.mh (NATDEPFILES): Likewise.
* configure.ac (AC_CACHE_CHECK): Add void * to the list of
ptrace's 4th argument's types.
Check the type of PTRACE_TYPE_ARG4.
* configure: Regenerate.
* linux-nat.c: Include nat/linux-nat.h and nat/linux-waitpid.h.
(SYSCALL_SIGTRAP): Moved to nat/linux-nat.h.
(linux_supports_tracefork_flag): Remove.
(linux_supports_tracesysgood_flag): Likewise.
(linux_supports_tracevforkdone_flag): Likewise.
(current_ptrace_options): Moved to
common/linux-ptrace.c.
(linux_tracefork_child): Remove.
(my_waitpid): Remove.
(linux_test_for_tracefork): Renamed to
linux_check_ptrace_features and moved to common/linux-ptrace.c.
(linux_test_for_tracesysgood): Remove.
(linux_supports_tracesysgood): Remove.
(linux_supports_tracefork): Remove.
(linux_supports_tracevforkdone): Remove.
(linux_enable_tracesysgood): Remove.
(linux_enable_event_reporting): Remove.
(linux_init_ptrace): New function.
(linux_child_post_attach): Call linux_init_ptrace.
(linux_child_post_startup_inferior): Call linux_init_ptrace.
(linux_child_follow_fork): Call linux_supports_tracefork
and linux_supports_tracevforkdone.
(linux_child_insert_fork_catchpoint): Call
linux_supports_tracefork.
(linux_child_insert_vfork_catchpoint): Likewise.
(linux_child_set_syscall_catchpoint): Call
linux_supports_tracesysgood.
(lin_lwp_attach_lwp): Call linux_supports_tracefork.
* nat/linux-nat.h: New file.
* nat/linux-waitpid.c: New file.
* nat/linux-waitpid.h: New file.
gdb/gdbserver/
* Makefile.in: Explain why ../target and ../nat are not
listed as include file search paths.
(linux-waitpid.o): New object file rule.
* configure.srv (srv_native_linux_obj): New variable.
Replace all occurrences of linux native object files with
$srv_native_linux_obj.
* linux-low.c: Include nat/linux-nat.h and nat/linux-waitpid.h.
(HAS_NOMMU): Move defining logic to common/linux-ptrace.c.
(linux_enable_event_reporting): Remove declaration.
(my_waitpid): Moved to common/linux-waitpid.c.
(linux_wait_for_event): Pass ptid when calling
linux_enable_event_reporting.
(linux_supports_tracefork_flag): Remove.
(linux_enable_event_reporting): Likewise.
(linux_tracefork_grandchild): Remove.
(STACK_SIZE): Moved to common/linux-ptrace.c.
(linux_tracefork_child): Remove.
(linux_test_for_tracefork): Remove.
(linux_look_up_symbols): Call linux_supports_tracefork.
(initialize_low): Remove call to linux_test_for_tracefork.
* linux-low.h (PTRACE_TYPE_ARG3): Remove.
(PTRACE_TYPE_ARG4): Likewise.
Include linux-ptrace.h.
* configure.ac: Check ptrace return and argument types.
* configure: Regenerate.
* config.in: Regenerate.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 45cddaf..c75ec38 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -855,7 +855,7 @@ common/format.h common/host-defs.h utils.h common/queue.h common/gdb_string.h \
common/linux-osdata.h gdb-dlfcn.h auto-load.h probe.h stap-probe.h \
gdb_bfd.h sparc-ravenscar-thread.h ppc-ravenscar-thread.h common/linux-btrace.h \
ctf.h common/i386-cpuid.h common/i386-gcc-cpuid.h target/resume.h \
-target/wait.h target/waitstatus.h
+target/wait.h target/waitstatus.h nat/linux-nat.h nat/linux-waitpid.h
# Header files that already have srcdir in them, or which are in objdir.
@@ -2037,6 +2037,15 @@ waitstatus.o: ${srcdir}/target/waitstatus.c
$(COMPILE) $(srcdir)/target/waitstatus.c
$(POSTCOMPILE)
+# gdb/nat/ dependencies
+#
+# Need to explicitly specify the compile rule as make will do nothing
+# or try to compile the object file into the sub-directory.
+
+linux-waitpid.o: ${srcdir}/nat/linux-waitpid.c
+ $(COMPILE) $(srcdir)/nat/linux-waitpid.c
+ $(POSTCOMPILE)
+
#
# gdb/tui/ dependencies
#
diff --git a/gdb/common/linux-ptrace.c b/gdb/common/linux-ptrace.c
index d5ac061..bcd3c94 100644
--- a/gdb/common/linux-ptrace.c
+++ b/gdb/common/linux-ptrace.c
@@ -25,10 +25,16 @@
#include "linux-ptrace.h"
#include "linux-procfs.h"
+#include "nat/linux-waitpid.h"
#include "buffer.h"
#include "gdb_assert.h"
#include "gdb_wait.h"
+/* Stores the currently supported ptrace options. A value of
+ -1 means we did not check for features yet. A value of 0 means
+ there are no supported features. */
+static int current_ptrace_options = -1;
+
/* Find all possible reasons we could fail to attach PID and append these
newline terminated reason strings to initialized BUFFER. '\0' termination
of BUFFER must be done by the caller. */
@@ -222,6 +228,283 @@ linux_ptrace_test_ret_to_nx (void)
#endif /* defined __i386__ || defined __x86_64__ */
}
+/* Helper function to fork a process and make the child process call
+ the function FUNCTION passing ARG as parameter.
+
+ For MMU-less targets, if ARG is NULL, stack space is allocated
+ via malloc and passed to FUNCTION. */
+
+static int
+linux_fork_to_function (void *arg, void (*function) (void *))
+{
+ int child_pid;
+#if defined(__UCLIBC__) && defined(HAS_NOMMU)
+ gdb_byte *stack;
+#endif
+
+ /* Sanity check the function pointer. */
+ gdb_assert (function != NULL);
+
+#if defined(__UCLIBC__) && defined(HAS_NOMMU)
+#define STACK_SIZE 4096
+
+ if (arg == NULL)
+ stack = xmalloc (STACK_SIZE * 4);
+ else
+ stack = (gdb_byte *) arg;
+
+ /* Use CLONE_VM instead of fork, to support uClinux (no MMU). */
+ #ifdef __ia64__
+ child_pid = __clone2 (function, stack, STACK_SIZE,
+ CLONE_VM | SIGCHLD, stack + STACK_SIZE * 2);
+ #else /* !__ia64__ */
+ child_pid = clone (function, stack + STACK_SIZE,
+ CLONE_VM | SIGCHLD, stack + STACK_SIZE * 2);
+ #endif /* !__ia64__ */
+#else /* !defined(__UCLIBC) && defined(HAS_NOMMU) */
+ child_pid = fork ();
+
+ if (child_pid == 0)
+ function (arg);
+#endif /* defined(__UCLIBC) && defined(HAS_NOMMU) */
+
+ if (child_pid == -1)
+ perror_with_name (("fork"));
+
+ return child_pid;
+}
+
+/* A helper function for linux_check_ptrace_features, called after
+ the child forks a grandchild. */
+
+static void
+linux_grandchild_function (void *arg)
+{
+ /* Free any allocated stack. */
+ xfree (arg);
+
+ /* This code is only reacheable by the grandchild (child's child)
+ process. */
+ _exit (0);
+}
+
+/* A helper function for linux_check_ptrace_features, called after
+ the parent process forks a child. The child allows itself to
+ be traced by its parent. */
+
+static void
+linux_child_function (void *arg)
+{
+ ptrace (PTRACE_TRACEME, 0, (PTRACE_TYPE_ARG3) 0, (PTRACE_TYPE_ARG4) 0);
+ kill (getpid (), SIGSTOP);
+
+ /* Fork a grandchild. */
+ linux_fork_to_function (arg, linux_grandchild_function);
+
+ /* This code is only reacheable by the child (grandchild's parent)
+ process. */
+ _exit (0);
+}
+
+/* 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;
+
+ /* Fork a child so we can do some testing. The child will call
+ linux_child_function and will get traced. The child will
+ eventually fork a grandchild so we can test fork event
+ reporting. */
+ child_pid = linux_fork_to_function (NULL, linux_child_function);
+
+ ret = my_waitpid (child_pid, &status, 0);
+ if (ret == -1)
+ perror_with_name (("waitpid"));
+ else if (ret != child_pid)
+ error (_("linux_check_ptrace_features: waitpid: unexpected result %d."),
+ ret);
+ if (! WIFSTOPPED (status))
+ 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_O_TRACEFORK);
+
+ if (ret != 0)
+ {
+ 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;
+ }
+
+#ifdef GDBSERVER
+ /* gdbserver does not support PTRACE_O_TRACESYSGOOD or
+ PTRACE_O_TRACEVFORKDONE yet. */
+#else
+ /* Check if the target supports PTRACE_O_TRACESYSGOOD. */
+ ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0,
+ PTRACE_O_TRACESYSGOOD);
+ if (ret == 0)
+ current_ptrace_options |= PTRACE_O_TRACESYSGOOD;
+
+ /* Check if the target supports PTRACE_O_TRACEVFORKDONE. */
+ ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0,
+ PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORKDONE);
+ if (ret == 0)
+ current_ptrace_options |= PTRACE_O_TRACEVFORKDONE;
+#endif
+
+ /* Setting PTRACE_O_TRACEFORK did not cause an error, however we
+ don't know for sure that the feature is available; old
+ versions of PTRACE_SETOPTIONS ignored unknown options.
+ Therefore, we attach to the child process, use PTRACE_SETOPTIONS
+ to enable fork tracing, and let it fork. If the process exits,
+ we assume that we can't use PTRACE_O_TRACEFORK; if we get the
+ fork notification, and we can extract the new child's PID, then
+ we assume that we can.
+
+ We do not explicitly check for vfork tracing here. It is
+ assumed that vfork tracing is available whenever fork tracing
+ is available. */
+ 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"));
+
+ ret = my_waitpid (child_pid, &status, 0);
+
+ /* Check if we received a fork event notification. */
+ if (ret == child_pid && WIFSTOPPED (status)
+ && status >> 16 == PTRACE_EVENT_FORK)
+ {
+ /* We did receive a fork event notification. Make sure its PID
+ is reported. */
+ second_pid = 0;
+ ret = ptrace (PTRACE_GETEVENTMSG, child_pid, (PTRACE_TYPE_ARG3) 0,
+ (PTRACE_TYPE_ARG4) &second_pid);
+ if (ret == 0 && second_pid != 0)
+ {
+ int second_status;
+
+ /* We got the PID from the grandchild, which means fork
+ tracing is supported. */
+#ifdef GDBSERVER
+ /* Do not enable all the options for now since gdbserver does not
+ properly support them. This restriction will be lifted when
+ gdbserver is augmented to support them. */
+ current_ptrace_options |= PTRACE_O_TRACECLONE;
+#else
+ current_ptrace_options |= PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK
+ | PTRACE_O_TRACECLONE | PTRACE_O_TRACEEXEC;
+
+ /* Do not enable PTRACE_O_TRACEEXIT until GDB is more prepared to
+ support read-only process state. */
+#endif
+
+ /* Do some cleanup and kill the grandchild. */
+ my_waitpid (second_pid, &second_status, 0);
+ ret = ptrace (PTRACE_KILL, second_pid, (PTRACE_TYPE_ARG3) 0,
+ (PTRACE_TYPE_ARG4) 0);
+ if (ret != 0)
+ warning (_("linux_check_ptrace_features: "
+ "failed to kill second child"));
+ my_waitpid (second_pid, &status, 0);
+ }
+ }
+ else
+ warning (_("linux_check_ptrace_features: 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. */
+
+void
+linux_enable_event_reporting (pid_t pid)
+{
+ /* Check if we have initialized the ptrace features for this
+ target. If not, do it now. */
+ if (current_ptrace_options == -1)
+ linux_check_ptrace_features ();
+
+ /* Set the options. */
+ ptrace (PTRACE_SETOPTIONS, pid, (PTRACE_TYPE_ARG3) 0,
+ current_ptrace_options);
+}
+
+/* Returns non-zero if PTRACE_OPTIONS is contained within
+ CURRENT_PTRACE_OPTIONS, therefore supported. Returns 0
+ otherwise. */
+
+static int
+ptrace_supports_feature (int ptrace_options)
+{
+ gdb_assert (current_ptrace_options >= 0);
+
+ return ((current_ptrace_options & ptrace_options) == ptrace_options);
+}
+
+/* Returns non-zero if PTRACE_EVENT_FORK is supported by ptrace,
+ 0 otherwise. Note that if PTRACE_EVENT_FORK is supported so is
+ PTRACE_EVENT_CLONE, PTRACE_EVENT_EXEC and PTRACE_EVENT_VFORK,
+ since they were all added to the kernel at the same time. */
+
+int
+linux_supports_tracefork (void)
+{
+ return ptrace_supports_feature (PTRACE_O_TRACECLONE);
+}
+
+/* Returns non-zero if PTRACE_O_TRACEVFORKDONE is supported by
+ ptrace, 0 otherwise */
+
+int
+linux_supports_tracevforkdone (void)
+{
+ return ptrace_supports_feature (PTRACE_O_TRACEVFORKDONE);
+}
+
+/* Returns non-zero if PTRACE_O_TRACESYSGOOD is supported by ptrace,
+ 0 otherwise */
+
+int
+linux_supports_tracesysgood (void)
+{
+ return ptrace_supports_feature (PTRACE_O_TRACESYSGOOD);
+}
+
/* Display possible problems on this system. Display them only once per GDB
execution. */
diff --git a/gdb/common/linux-ptrace.h b/gdb/common/linux-ptrace.h
index 8f02c82..4f7456f 100644
--- a/gdb/common/linux-ptrace.h
+++ b/gdb/common/linux-ptrace.h
@@ -22,6 +22,14 @@ struct buffer;
#include <sys/ptrace.h>
+#ifdef __UCLIBC__
+#if !(defined(__UCLIBC_HAS_MMU__) || defined(__ARCH_HAS_MMU__))
+/* PTRACE_TEXT_ADDR and friends. */
+#include <asm/ptrace.h>
+#define HAS_NOMMU
+#endif
+#endif
+
#ifndef PTRACE_GETSIGINFO
# define PTRACE_GETSIGINFO 0x4202
# define PTRACE_SETSIGINFO 0x4203
@@ -69,5 +77,9 @@ struct buffer;
extern void linux_ptrace_attach_warnings (pid_t pid, struct buffer *buffer);
extern void linux_ptrace_init_warnings (void);
+extern void linux_enable_event_reporting (pid_t pid);
+extern int linux_supports_tracefork (void);
+extern int linux_supports_tracevforkdone (void);
+extern int linux_supports_tracesysgood (void);
#endif /* COMMON_LINUX_PTRACE_H */
diff --git a/gdb/config.in b/gdb/config.in
index 76abd04..03b0972 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -659,6 +659,9 @@
/* Define to the type of arg 3 for ptrace. */
#undef PTRACE_TYPE_ARG3
+/* Define to the type of arg 4 for ptrace. */
+#undef PTRACE_TYPE_ARG4
+
/* Define to the type of arg 5 for ptrace. */
#undef PTRACE_TYPE_ARG5
diff --git a/gdb/config/aarch64/linux.mh b/gdb/config/aarch64/linux.mh
index 2b2202e..55425f6 100644
--- a/gdb/config/aarch64/linux.mh
+++ b/gdb/config/aarch64/linux.mh
@@ -19,7 +19,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
NAT_FILE= config/nm-linux.h
-NATDEPFILES= inf-ptrace.o fork-child.o aarch64-linux-nat.o \
+NATDEPFILES= linux-waitpid.o inf-ptrace.o fork-child.o aarch64-linux-nat.o \
proc-service.o linux-thread-db.o linux-nat.o linux-fork.o \
linux-procfs.o linux-ptrace.o linux-osdata.o
NAT_CDEPS = $(srcdir)/proc-service.list
diff --git a/gdb/config/alpha/alpha-linux.mh b/gdb/config/alpha/alpha-linux.mh
index 9eb9e4b..ba46ec8 100644
--- a/gdb/config/alpha/alpha-linux.mh
+++ b/gdb/config/alpha/alpha-linux.mh
@@ -1,6 +1,6 @@
# Host: Little-endian Alpha running Linux
NAT_FILE= config/nm-linux.h
-NATDEPFILES= inf-ptrace.o alpha-linux-nat.o \
+NATDEPFILES= linux-waitpid.o linux-waitpid.o inf-ptrace.o alpha-linux-nat.o \
fork-child.o proc-service.o linux-thread-db.o \
linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o
NAT_CDEPS = $(srcdir)/proc-service.list
diff --git a/gdb/config/arm/linux.mh b/gdb/config/arm/linux.mh
index c0a1c66..af42783 100644
--- a/gdb/config/arm/linux.mh
+++ b/gdb/config/arm/linux.mh
@@ -1,7 +1,7 @@
# Host: ARM based machine running GNU/Linux
NAT_FILE= config/nm-linux.h
-NATDEPFILES= inf-ptrace.o fork-child.o arm-linux-nat.o \
+NATDEPFILES= linux-waitpid.o inf-ptrace.o fork-child.o arm-linux-nat.o \
proc-service.o linux-thread-db.o \
linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o
NAT_CDEPS = $(srcdir)/proc-service.list
diff --git a/gdb/config/i386/linux.mh b/gdb/config/i386/linux.mh
index 7c64e83..d5f64e5 100644
--- a/gdb/config/i386/linux.mh
+++ b/gdb/config/i386/linux.mh
@@ -1,7 +1,7 @@
# Host: Intel 386 running GNU/Linux.
NAT_FILE= config/nm-linux.h
-NATDEPFILES= inf-ptrace.o fork-child.o \
+NATDEPFILES= linux-waitpid.o inf-ptrace.o fork-child.o \
i386-nat.o i386-linux-nat.o \
proc-service.o linux-thread-db.o \
linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
diff --git a/gdb/config/i386/linux64.mh b/gdb/config/i386/linux64.mh
index 8d782c1..8d35a31 100644
--- a/gdb/config/i386/linux64.mh
+++ b/gdb/config/i386/linux64.mh
@@ -1,5 +1,5 @@
# Host: GNU/Linux x86-64
-NATDEPFILES= inf-ptrace.o fork-child.o \
+NATDEPFILES= linux-waitpid.o inf-ptrace.o fork-child.o \
i386-nat.o amd64-nat.o amd64-linux-nat.o \
linux-nat.o linux-osdata.o \
proc-service.o linux-thread-db.o linux-fork.o \
diff --git a/gdb/config/ia64/linux.mh b/gdb/config/ia64/linux.mh
index 1a4c68e..0917fc3 100644
--- a/gdb/config/ia64/linux.mh
+++ b/gdb/config/ia64/linux.mh
@@ -1,7 +1,7 @@
# Host: Intel IA-64 running GNU/Linux
NAT_FILE= config/nm-linux.h
-NATDEPFILES= inf-ptrace.o fork-child.o \
+NATDEPFILES= linux-waitpid.o inf-ptrace.o fork-child.o \
core-regset.o ia64-linux-nat.o \
proc-service.o linux-thread-db.o \
linux-nat.o linux-osdata.o linux-fork.o \
diff --git a/gdb/config/m32r/linux.mh b/gdb/config/m32r/linux.mh
index b461806..e8c7caa 100644
--- a/gdb/config/m32r/linux.mh
+++ b/gdb/config/m32r/linux.mh
@@ -1,7 +1,7 @@
# Host: M32R based machine running GNU/Linux
NAT_FILE= config/nm-linux.h
-NATDEPFILES= inf-ptrace.o fork-child.o \
+NATDEPFILES= linux-waitpid.o inf-ptrace.o fork-child.o \
m32r-linux-nat.o proc-service.o linux-thread-db.o \
linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o
NAT_CDEPS = $(srcdir)/proc-service.list
diff --git a/gdb/config/m68k/linux.mh b/gdb/config/m68k/linux.mh
index e3aaf38..40405ca 100644
--- a/gdb/config/m68k/linux.mh
+++ b/gdb/config/m68k/linux.mh
@@ -1,7 +1,7 @@
# Host: Motorola m68k running GNU/Linux.
NAT_FILE= config/nm-linux.h
-NATDEPFILES= inf-ptrace.o fork-child.o \
+NATDEPFILES= linux-waitpid.o inf-ptrace.o fork-child.o \
m68klinux-nat.o \
proc-service.o linux-thread-db.o \
linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o
diff --git a/gdb/config/mips/linux.mh b/gdb/config/mips/linux.mh
index a4f23e3..3dca2db 100644
--- a/gdb/config/mips/linux.mh
+++ b/gdb/config/mips/linux.mh
@@ -1,6 +1,6 @@
# Host: Linux/MIPS
NAT_FILE= config/nm-linux.h
-NATDEPFILES= inf-ptrace.o fork-child.o mips-linux-nat.o \
+NATDEPFILES= linux-waitpid.o inf-ptrace.o fork-child.o mips-linux-nat.o \
linux-thread-db.o proc-service.o \
linux-nat.o linux-osdata.o linux-fork.o \
linux-procfs.o linux-ptrace.o mips-linux-watch.o
diff --git a/gdb/config/pa/linux.mh b/gdb/config/pa/linux.mh
index fa46db6..53331e1 100644
--- a/gdb/config/pa/linux.mh
+++ b/gdb/config/pa/linux.mh
@@ -1,6 +1,6 @@
# Host: Hewlett-Packard PA-RISC machine, running Linux
NAT_FILE= config/nm-linux.h
-NATDEPFILES= inf-ptrace.o fork-child.o \
+NATDEPFILES= linux-waitpid.o inf-ptrace.o fork-child.o \
hppa-linux-nat.o proc-service.o linux-thread-db.o \
linux-nat.o linux-osdata.o linux-fork.o \
linux-procfs.o linux-ptrace.o
diff --git a/gdb/config/powerpc/linux.mh b/gdb/config/powerpc/linux.mh
index b0d4ce7..9d4f496 100644
--- a/gdb/config/powerpc/linux.mh
+++ b/gdb/config/powerpc/linux.mh
@@ -3,7 +3,7 @@
XM_CLIBS=
NAT_FILE= config/nm-linux.h
-NATDEPFILES= inf-ptrace.o fork-child.o \
+NATDEPFILES= linux-waitpid.o inf-ptrace.o fork-child.o \
ppc-linux-nat.o proc-service.o linux-thread-db.o \
linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o
NAT_CDEPS = $(srcdir)/proc-service.list
diff --git a/gdb/config/powerpc/ppc64-linux.mh b/gdb/config/powerpc/ppc64-linux.mh
index 367a818..24f3287 100644
--- a/gdb/config/powerpc/ppc64-linux.mh
+++ b/gdb/config/powerpc/ppc64-linux.mh
@@ -3,7 +3,7 @@
XM_CLIBS=
NAT_FILE= config/nm-linux.h
-NATDEPFILES= inf-ptrace.o fork-child.o \
+NATDEPFILES= linux-waitpid.o linux-waitpid.o inf-ptrace.o fork-child.o \
ppc-linux-nat.o proc-service.o linux-thread-db.o \
linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o
NAT_CDEPS = $(srcdir)/proc-service.list
diff --git a/gdb/config/powerpc/spu-linux.mh b/gdb/config/powerpc/spu-linux.mh
index 1bc279a..200fe6b 100644
--- a/gdb/config/powerpc/spu-linux.mh
+++ b/gdb/config/powerpc/spu-linux.mh
@@ -3,6 +3,6 @@
# This implements a 'pseudo-native' GDB running on the
# PPU side of the Cell BE and debugging the SPU side.
-NATDEPFILES = spu-linux-nat.o fork-child.o inf-ptrace.o \
+NATDEPFILES = spu-linux-nat.o fork-child.o linux-waitpid.o linux-waitpid.o inf-ptrace.o \
linux-procfs.o linux-ptrace.o
diff --git a/gdb/config/sparc/linux.mh b/gdb/config/sparc/linux.mh
index 6a2cefd..537ecf7 100644
--- a/gdb/config/sparc/linux.mh
+++ b/gdb/config/sparc/linux.mh
@@ -1,7 +1,7 @@
# Host: GNU/Linux SPARC
NAT_FILE= config/nm-linux.h
NATDEPFILES= sparc-nat.o sparc-linux-nat.o \
- core-regset.o fork-child.o inf-ptrace.o \
+ core-regset.o fork-child.o linux-waitpid.o inf-ptrace.o \
proc-service.o linux-thread-db.o \
linux-nat.o linux-osdata.o linux-fork.o \
linux-procfs.o linux-ptrace.o
diff --git a/gdb/config/sparc/linux64.mh b/gdb/config/sparc/linux64.mh
index d1e1a97..f021864 100644
--- a/gdb/config/sparc/linux64.mh
+++ b/gdb/config/sparc/linux64.mh
@@ -2,7 +2,7 @@
NAT_FILE= config/nm-linux.h
NATDEPFILES= sparc-nat.o sparc64-nat.o sparc64-linux-nat.o \
core-regset.o \
- fork-child.o inf-ptrace.o \
+ fork-child.o linux-waitpid.o inf-ptrace.o \
proc-service.o linux-thread-db.o \
linux-nat.o linux-osdata.o linux-fork.o \
linux-procfs.o linux-ptrace.o
diff --git a/gdb/config/tilegx/linux.mh b/gdb/config/tilegx/linux.mh
index 56ef694..c70b452 100644
--- a/gdb/config/tilegx/linux.mh
+++ b/gdb/config/tilegx/linux.mh
@@ -1,7 +1,7 @@
# Host: Tilera TILE-Gx running GNU/Linux.
NAT_FILE= config/nm-linux.h
-NATDEPFILES= inf-ptrace.o fork-child.o \
+NATDEPFILES= linux-waitpid.o inf-ptrace.o fork-child.o \
tilegx-linux-nat.o \
proc-service.o linux-thread-db.o \
linux-nat.o linux-osdata.o linux-fork.o \
diff --git a/gdb/config/xtensa/linux.mh b/gdb/config/xtensa/linux.mh
index deffe25..afa0043 100644
--- a/gdb/config/xtensa/linux.mh
+++ b/gdb/config/xtensa/linux.mh
@@ -2,7 +2,7 @@
NAT_FILE= config/nm-linux.h
-NATDEPFILES= inf-ptrace.o fork-child.o xtensa-linux-nat.o \
+NATDEPFILES= linux-waitpid.o inf-ptrace.o fork-child.o xtensa-linux-nat.o \
linux-thread-db.o proc-service.o \
linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o
NAT_CDEPS = $(srcdir)/proc-service.list
diff --git a/gdb/configure b/gdb/configure
index 8067825..a722b93 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -10336,7 +10336,7 @@ else
for gdb_arg1 in 'int' 'long'; do
for gdb_arg2 in 'pid_t' 'int' 'long'; do
for gdb_arg3 in 'int *' 'caddr_t' 'int' 'long' 'void *'; do
- for gdb_arg4 in 'int' 'long'; do
+ for gdb_arg4 in 'int' 'long' 'void *'; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$gdb_ptrace_headers
@@ -10399,6 +10399,11 @@ cat >>confdefs.h <<_ACEOF
#define PTRACE_TYPE_ARG3 $3
_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PTRACE_TYPE_ARG4 $4
+_ACEOF
+
if test -n "$5"; then
cat >>confdefs.h <<_ACEOF
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 667821f..0982cac 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -1207,7 +1207,7 @@ AC_CACHE_CHECK([types of arguments for ptrace], gdb_cv_func_ptrace_args, [
for gdb_arg1 in 'int' 'long'; do
for gdb_arg2 in 'pid_t' 'int' 'long'; do
for gdb_arg3 in 'int *' 'caddr_t' 'int' 'long' 'void *'; do
- for gdb_arg4 in 'int' 'long'; do
+ for gdb_arg4 in 'int' 'long' 'void *'; do
AC_TRY_COMPILE($gdb_ptrace_headers, [
extern $gdb_cv_func_ptrace_ret
ptrace ($gdb_arg1, $gdb_arg2, $gdb_arg3, $gdb_arg4);
@@ -1234,6 +1234,8 @@ IFS=$ac_save_IFS
shift
AC_DEFINE_UNQUOTED(PTRACE_TYPE_ARG3, $[3],
[Define to the type of arg 3 for ptrace.])
+AC_DEFINE_UNQUOTED(PTRACE_TYPE_ARG4, $[4],
+ [Define to the type of arg 4 for ptrace.])
if test -n "$[5]"; then
AC_DEFINE_UNQUOTED(PTRACE_TYPE_ARG5, $[5],
[Define to the type of arg 5 for ptrace.])
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 2cdbf47..45e03a2 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -100,6 +100,11 @@ GNULIB_H = $(GNULIB_BUILDDIR)/import/string.h @GNULIB_STDINT_H@
# -I. for config files.
# -I${srcdir} for our headers.
# -I$(srcdir)/../regformats for regdef.h.
+#
+# We do not include ../target or ../nat in here because headers
+# in those directories should be included with the subdirectory.
+# e.g.: "target/wait.h".
+#
INCLUDE_CFLAGS = -I. -I${srcdir} -I$(srcdir)/../common \
-I$(srcdir)/../regformats -I$(srcdir)/../ -I$(INCLUDE_DIR) \
$(INCGNU)
@@ -562,6 +567,12 @@ linux-btrace.o: ../common/linux-btrace.c $(linux_btrace_h) $(server_h)
mips-linux-watch.o: ../common/mips-linux-watch.c $(mips_linux_watch_h) $(server_h)
$(CC) -c $(CPPFLAGS) $(INTERNAL_CFLAGS) $<
+# Native object files rules from ../nat
+
+linux-waitpid.o: ../nat/linux-waitpid.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+
# We build vasprintf with -DHAVE_CONFIG_H because we want that unit to
# include our config.h file. Otherwise, some system headers do not get
# included, and the compiler emits a warning about implicitly defined
diff --git a/gdb/gdbserver/config.in b/gdb/gdbserver/config.in
index dada2fb..c00d0e4 100644
--- a/gdb/gdbserver/config.in
+++ b/gdb/gdbserver/config.in
@@ -26,6 +26,10 @@
*/
#undef HAVE_DECL_PERROR
+/* Define to 1 if you have the declaration of `ptrace', and to 0 if you don't.
+ */
+#undef HAVE_DECL_PTRACE
+
/* Define to 1 if you have the declaration of `strerror', and to 0 if you
don't. */
#undef HAVE_DECL_STRERROR
@@ -76,6 +80,9 @@
/* Define to 1 if you have the `dl' library (-ldl). */
#undef HAVE_LIBDL
+/* Define to 1 if you have the `mcheck' library (-lmcheck). */
+#undef HAVE_LIBMCHECK
+
/* Define if the target supports branch tracing. */
#undef HAVE_LINUX_BTRACE
@@ -256,6 +263,18 @@
/* Additional package description */
#undef PKGVERSION
+/* Define to the type of arg 3 for ptrace. */
+#undef PTRACE_TYPE_ARG3
+
+/* Define to the type of arg 4 for ptrace. */
+#undef PTRACE_TYPE_ARG4
+
+/* Define to the type of arg 5 for ptrace. */
+#undef PTRACE_TYPE_ARG5
+
+/* Define as the return type of ptrace. */
+#undef PTRACE_TYPE_RET
+
/* Bug reporting address */
#undef REPORT_BUGS_TO
diff --git a/gdb/gdbserver/configure b/gdb/gdbserver/configure
index 193aedc..7e61fa9 100755
--- a/gdb/gdbserver/configure
+++ b/gdb/gdbserver/configure
@@ -5222,6 +5222,194 @@ _ACEOF
fi
+#
+# Check the return and argument types of ptrace. No canned test for
+# this, so roll our own.
+#
+gdb_ptrace_headers='
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_PTRACE_H
+# include <sys/ptrace.h>
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+'
+# There is no point in checking if we don't have a prototype.
+ac_fn_c_check_decl "$LINENO" "ptrace" "ac_cv_have_decl_ptrace" "$gdb_ptrace_headers
+"
+if test "x$ac_cv_have_decl_ptrace" = x""yes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_PTRACE $ac_have_decl
+_ACEOF
+if test $ac_have_decl = 1; then :
+
+else
+
+ : ${gdb_cv_func_ptrace_ret='int'}
+ : ${gdb_cv_func_ptrace_args='int,int,long,long'}
+
+fi
+
+# Check return type. Varargs (used on GNU/Linux) conflict with the
+# empty argument list, so check for that explicitly.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking return type of ptrace" >&5
+$as_echo_n "checking return type of ptrace... " >&6; }
+if test "${gdb_cv_func_ptrace_ret+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$gdb_ptrace_headers
+int
+main ()
+{
+extern long ptrace (enum __ptrace_request, ...);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ gdb_cv_func_ptrace_ret='long'
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$gdb_ptrace_headers
+int
+main ()
+{
+extern int ptrace ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ gdb_cv_func_ptrace_ret='int'
+else
+ gdb_cv_func_ptrace_ret='long'
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gdb_cv_func_ptrace_ret" >&5
+$as_echo "$gdb_cv_func_ptrace_ret" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define PTRACE_TYPE_RET $gdb_cv_func_ptrace_ret
+_ACEOF
+
+# Check argument types.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking types of arguments for ptrace" >&5
+$as_echo_n "checking types of arguments for ptrace... " >&6; }
+if test "${gdb_cv_func_ptrace_args+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$gdb_ptrace_headers
+int
+main ()
+{
+extern long ptrace (enum __ptrace_request, ...);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ gdb_cv_func_ptrace_args='int,int,long,long'
+else
+
+for gdb_arg1 in 'int' 'long'; do
+ for gdb_arg2 in 'pid_t' 'int' 'long'; do
+ for gdb_arg3 in 'int *' 'caddr_t' 'int' 'long' 'void *'; do
+ for gdb_arg4 in 'int' 'long' 'void *'; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$gdb_ptrace_headers
+int
+main ()
+{
+
+extern $gdb_cv_func_ptrace_ret
+ ptrace ($gdb_arg1, $gdb_arg2, $gdb_arg3, $gdb_arg4);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ gdb_cv_func_ptrace_args="$gdb_arg1,$gdb_arg2,$gdb_arg3,$gdb_arg4";
+ break 4;
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ for gdb_arg5 in 'int *' 'int' 'long'; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$gdb_ptrace_headers
+int
+main ()
+{
+
+extern $gdb_cv_func_ptrace_ret
+ ptrace ($gdb_arg1, $gdb_arg2, $gdb_arg3, $gdb_arg4, $gdb_arg5);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+gdb_cv_func_ptrace_args="$gdb_arg1,$gdb_arg2,$gdb_arg3,$gdb_arg4,$gdb_arg5";
+ break 5;
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+ done
+ done
+ done
+done
+# Provide a safe default value.
+: ${gdb_cv_func_ptrace_args='int,int,long,long'}
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gdb_cv_func_ptrace_args" >&5
+$as_echo "$gdb_cv_func_ptrace_args" >&6; }
+ac_save_IFS=$IFS; IFS=','
+set dummy `echo "$gdb_cv_func_ptrace_args" | sed 's/\*/\*/g'`
+IFS=$ac_save_IFS
+shift
+
+cat >>confdefs.h <<_ACEOF
+#define PTRACE_TYPE_ARG3 $3
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PTRACE_TYPE_ARG4 $4
+_ACEOF
+
+if test -n "$5"; then
+
+cat >>confdefs.h <<_ACEOF
+#define PTRACE_TYPE_ARG5 $5
+_ACEOF
+
+fi
+#
+# End of ptrace type checks
+#
+
# Check whether --with-pkgversion was given.
diff --git a/gdb/gdbserver/configure.ac b/gdb/gdbserver/configure.ac
index 456a1f7..84ff9ea 100644
--- a/gdb/gdbserver/configure.ac
+++ b/gdb/gdbserver/configure.ac
@@ -214,6 +214,83 @@ AC_CHECK_TYPES([Elf32_auxv_t, Elf64_auxv_t], [], [],
#include <elf.h>
)
+#
+# Check the return and argument types of ptrace. No canned test for
+# this, so roll our own.
+#
+gdb_ptrace_headers='
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_PTRACE_H
+# include <sys/ptrace.h>
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+'
+# There is no point in checking if we don't have a prototype.
+AC_CHECK_DECLS(ptrace, [], [
+ : ${gdb_cv_func_ptrace_ret='int'}
+ : ${gdb_cv_func_ptrace_args='int,int,long,long'}
+], $gdb_ptrace_headers)
+# Check return type. Varargs (used on GNU/Linux) conflict with the
+# empty argument list, so check for that explicitly.
+AC_CACHE_CHECK([return type of ptrace], gdb_cv_func_ptrace_ret,
+ AC_TRY_COMPILE($gdb_ptrace_headers,
+ [extern long ptrace (enum __ptrace_request, ...);],
+ gdb_cv_func_ptrace_ret='long',
+ AC_TRY_COMPILE($gdb_ptrace_headers,
+ [extern int ptrace ();],
+ gdb_cv_func_ptrace_ret='int',
+ gdb_cv_func_ptrace_ret='long')))
+AC_DEFINE_UNQUOTED(PTRACE_TYPE_RET, $gdb_cv_func_ptrace_ret,
+ [Define as the return type of ptrace.])
+# Check argument types.
+AC_CACHE_CHECK([types of arguments for ptrace], gdb_cv_func_ptrace_args, [
+ AC_TRY_COMPILE($gdb_ptrace_headers,
+ [extern long ptrace (enum __ptrace_request, ...);],
+ [gdb_cv_func_ptrace_args='int,int,long,long'],[
+for gdb_arg1 in 'int' 'long'; do
+ for gdb_arg2 in 'pid_t' 'int' 'long'; do
+ for gdb_arg3 in 'int *' 'caddr_t' 'int' 'long' 'void *'; do
+ for gdb_arg4 in 'int' 'long' 'void *'; do
+ AC_TRY_COMPILE($gdb_ptrace_headers, [
+extern $gdb_cv_func_ptrace_ret
+ ptrace ($gdb_arg1, $gdb_arg2, $gdb_arg3, $gdb_arg4);
+], [gdb_cv_func_ptrace_args="$gdb_arg1,$gdb_arg2,$gdb_arg3,$gdb_arg4";
+ break 4;])
+ for gdb_arg5 in 'int *' 'int' 'long'; do
+ AC_TRY_COMPILE($gdb_ptrace_headers, [
+extern $gdb_cv_func_ptrace_ret
+ ptrace ($gdb_arg1, $gdb_arg2, $gdb_arg3, $gdb_arg4, $gdb_arg5);
+], [
+gdb_cv_func_ptrace_args="$gdb_arg1,$gdb_arg2,$gdb_arg3,$gdb_arg4,$gdb_arg5";
+ break 5;])
+ done
+ done
+ done
+ done
+done
+# Provide a safe default value.
+: ${gdb_cv_func_ptrace_args='int,int,long,long'}
+])])
+ac_save_IFS=$IFS; IFS=','
+set dummy `echo "$gdb_cv_func_ptrace_args" | sed 's/\*/\*/g'`
+IFS=$ac_save_IFS
+shift
+AC_DEFINE_UNQUOTED(PTRACE_TYPE_ARG3, $[3],
+ [Define to the type of arg 3 for ptrace.])
+AC_DEFINE_UNQUOTED(PTRACE_TYPE_ARG4, $[4],
+ [Define to the type of arg 4 for ptrace.])
+if test -n "$[5]"; then
+ AC_DEFINE_UNQUOTED(PTRACE_TYPE_ARG5, $[5],
+ [Define to the type of arg 5 for ptrace.])
+fi
+#
+# End of ptrace type checks
+#
+
ACX_PKGVERSION([GDB])
ACX_BUGURL([http://www.gnu.org/software/gdb/bugs/])
AC_DEFINE_UNQUOTED([PKGVERSION], ["$PKGVERSION"], [Additional package description])
diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
index b9dfd6c..29f89c4 100644
--- a/gdb/gdbserver/configure.srv
+++ b/gdb/gdbserver/configure.srv
@@ -39,16 +39,18 @@ srv_amd64_xmlfiles="i386/amd64.xml i386/amd64-avx.xml i386/x32.xml i386/x32-avx.
srv_i386_linux_xmlfiles="i386/i386-linux.xml i386/i386-avx-linux.xml i386/i386-mmx-linux.xml i386/32bit-linux.xml $srv_i386_32bit_xmlfiles"
srv_amd64_linux_xmlfiles="i386/amd64-linux.xml i386/amd64-avx-linux.xml i386/64bit-linux.xml i386/x32-linux.xml i386/x32-avx-linux.xml $srv_i386_64bit_xmlfiles"
+
+# Linux object files. This is so we don't have to repeat
+# these files over and over again.
+srv_native_linux_obj="linux-waitpid.o linux-low.o linux-osdata.o linux-procfs.o linux-ptrace.o"
+
# Input is taken from the "${target}" variable.
case "${target}" in
aarch64*-*-linux*)
srv_regobj="aarch64.o"
srv_tgtobj="linux-aarch64-low.o"
- srv_tgtobj="${srv_tgtobj} linux-low.o"
- srv_tgtobj="${srv_tgtobj} linux-osdata.o"
- srv_tgtobj="${srv_tgtobj} linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="${srv_tgtobj} $srv_native_linux_obj"
srv_xmlfiles="aarch64.xml"
srv_xmlfiles="${srv_xmlfiles} aarch64-core.xml"
srv_xmlfiles="${srv_xmlfiles} aarch64-fpu.xml"
@@ -60,8 +62,7 @@ case "${target}" in
srv_regobj="${srv_regobj} arm-with-vfpv2.o"
srv_regobj="${srv_regobj} arm-with-vfpv3.o"
srv_regobj="${srv_regobj} arm-with-neon.o"
- srv_tgtobj="linux-low.o linux-osdata.o linux-arm-low.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="$srv_native_linux_obj linux-arm-low.o"
srv_xmlfiles="arm-with-iwmmxt.xml"
srv_xmlfiles="${srv_xmlfiles} arm-with-vfpv2.xml"
srv_xmlfiles="${srv_xmlfiles} arm-with-vfpv3.xml"
@@ -83,20 +84,17 @@ case "${target}" in
srv_mingwce=yes
;;
bfin-*-*linux*) srv_regobj=reg-bfin.o
- srv_tgtobj="linux-low.o linux-osdata.o linux-bfin-low.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="$srv_native_linux_obj linux-bfin-low.o"
srv_linux_usrregs=yes
srv_linux_thread_db=yes
;;
crisv32-*-linux*) srv_regobj=reg-crisv32.o
- srv_tgtobj="linux-low.o linux-osdata.o linux-crisv32-low.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="$srv_native_linux_obj linux-crisv32-low.o"
srv_linux_regsets=yes
srv_linux_thread_db=yes
;;
cris-*-linux*) srv_regobj=reg-cris.o
- srv_tgtobj="linux-low.o linux-osdata.o linux-cris-low.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="$srv_native_linux_obj linux-cris-low.o"
srv_linux_usrregs=yes
srv_linux_thread_db=yes
;;
@@ -110,8 +108,8 @@ case "${target}" in
srv_regobj="$srv_regobj $srv_amd64_linux_regobj"
srv_xmlfiles="${srv_xmlfiles} $srv_amd64_linux_xmlfiles"
fi
- srv_tgtobj="linux-low.o linux-osdata.o linux-x86-low.o i386-low.o i387-fp.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o linux-btrace.o"
+ srv_tgtobj="$srv_native_linux_obj linux-x86-low.o i386-low.o i387-fp.o"
+ srv_tgtobj="${srv_tgtobj} linux-btrace.o"
srv_linux_usrregs=yes
srv_linux_regsets=yes
srv_linux_thread_db=yes
@@ -146,13 +144,11 @@ case "${target}" in
srv_qnx="yes"
;;
ia64-*-linux*) srv_regobj=reg-ia64.o
- srv_tgtobj="linux-low.o linux-osdata.o linux-ia64-low.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="$srv_native_linux_obj linux-ia64-low.o"
srv_linux_usrregs=yes
;;
m32r*-*-linux*) srv_regobj=reg-m32r.o
- srv_tgtobj="linux-low.o linux-osdata.o linux-m32r-low.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="$srv_native_linux_obj linux-m32r-low.o"
srv_linux_usrregs=yes
srv_linux_thread_db=yes
;;
@@ -161,8 +157,7 @@ case "${target}" in
else
srv_regobj=reg-m68k.o
fi
- srv_tgtobj="linux-low.o linux-osdata.o linux-m68k-low.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="$srv_native_linux_obj linux-m68k-low.o"
srv_linux_usrregs=yes
srv_linux_regsets=yes
srv_linux_thread_db=yes
@@ -172,8 +167,7 @@ case "${target}" in
else
srv_regobj=reg-m68k.o
fi
- srv_tgtobj="linux-low.o linux-osdata.o linux-m68k-low.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="$srv_native_linux_obj linux-m68k-low.o"
srv_linux_usrregs=yes
srv_linux_regsets=yes
srv_linux_thread_db=yes
@@ -182,8 +176,7 @@ case "${target}" in
srv_regobj="${srv_regobj} mips-dsp-linux.o"
srv_regobj="${srv_regobj} mips64-linux.o"
srv_regobj="${srv_regobj} mips64-dsp-linux.o"
- srv_tgtobj="linux-low.o linux-osdata.o linux-mips-low.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="$srv_native_linux_obj linux-mips-low.o"
srv_tgtobj="${srv_tgtobj} mips-linux-watch.o"
srv_xmlfiles="mips-linux.xml"
srv_xmlfiles="${srv_xmlfiles} mips-dsp-linux.xml"
@@ -202,8 +195,7 @@ case "${target}" in
srv_linux_thread_db=yes
;;
nios2*-*-linux*) srv_regobj="nios2-linux.o"
- srv_tgtobj="linux-low.o linux-osdata.o linux-nios2-low.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="$srv_native_linux_obj linux-nios2-low.o"
srv_xmlfiles="nios2-linux.xml"
srv_xmlfiles="${srv_xmlfiles} nios2-cpu.xml"
srv_linux_regsets=yes
@@ -225,8 +217,7 @@ case "${target}" in
srv_regobj="${srv_regobj} powerpc-isa205-64l.o"
srv_regobj="${srv_regobj} powerpc-isa205-altivec64l.o"
srv_regobj="${srv_regobj} powerpc-isa205-vsx64l.o"
- srv_tgtobj="linux-low.o linux-osdata.o linux-ppc-low.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="$srv_native_linux_obj linux-ppc-low.o"
srv_xmlfiles="rs6000/powerpc-32l.xml"
srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-altivec32l.xml"
srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-cell32l.xml"
@@ -271,8 +262,7 @@ case "${target}" in
srv_regobj="${srv_regobj} s390x-linux64.o"
srv_regobj="${srv_regobj} s390x-linux64v1.o"
srv_regobj="${srv_regobj} s390x-linux64v2.o"
- srv_tgtobj="linux-low.o linux-osdata.o linux-s390-low.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="$srv_native_linux_obj linux-s390-low.o"
srv_xmlfiles="s390-linux32.xml"
srv_xmlfiles="${srv_xmlfiles} s390-linux32v1.xml"
srv_xmlfiles="${srv_xmlfiles} s390-linux32v2.xml"
@@ -292,15 +282,13 @@ case "${target}" in
srv_linux_thread_db=yes
;;
sh*-*-linux*) srv_regobj=reg-sh.o
- srv_tgtobj="linux-low.o linux-osdata.o linux-sh-low.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="$srv_native_linux_obj linux-sh-low.o"
srv_linux_usrregs=yes
srv_linux_regsets=yes
srv_linux_thread_db=yes
;;
sparc*-*-linux*) srv_regobj=reg-sparc64.o
- srv_tgtobj="linux-low.o linux-osdata.o linux-sparc-low.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="$srv_native_linux_obj linux-sparc-low.o"
srv_linux_regsets=yes
srv_linux_thread_db=yes
;;
@@ -316,15 +304,14 @@ case "${target}" in
srv_xmlfiles="${srv_xmlfiles} tic6x-core.xml"
srv_xmlfiles="${srv_xmlfiles} tic6x-gp.xml"
srv_xmlfiles="${srv_xmlfiles} tic6x-c6xp.xml"
- srv_tgtobj="linux-low.o linux-osdata.o linux-tic6x-low.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="$srv_native_linux_obj linux-tic6x-low.o"
srv_linux_regsets=yes
srv_linux_usrregs=yes
srv_linux_thread_db=yes
;;
x86_64-*-linux*) srv_regobj="$srv_amd64_linux_regobj $srv_i386_linux_regobj"
- srv_tgtobj="linux-low.o linux-osdata.o linux-x86-low.o i386-low.o i387-fp.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o linux-btrace.o"
+ srv_tgtobj="$srv_native_linux_obj linux-x86-low.o i386-low.o i387-fp.o"
+ srv_tgtobj="${srv_tgtobj} linux-btrace.o"
srv_xmlfiles="$srv_i386_linux_xmlfiles $srv_amd64_linux_xmlfiles"
srv_linux_usrregs=yes # This is for i386 progs.
srv_linux_regsets=yes
@@ -343,14 +330,12 @@ case "${target}" in
;;
xtensa*-*-linux*) srv_regobj=reg-xtensa.o
- srv_tgtobj="linux-low.o linux-osdata.o linux-xtensa-low.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="$srv_native_linux_obj linux-xtensa-low.o"
srv_linux_regsets=yes
;;
tilegx-*-linux*) srv_regobj=reg-tilegx.o
srv_regobj="${srv_regobj} reg-tilegx32.o"
- srv_tgtobj="linux-low.o linux-tile-low.o linux-osdata.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="$srv_native_linux_obj linux-osdata.o"
srv_linux_regsets=yes
srv_linux_thread_db=yes
;;
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 217cd2e..ffc145e 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -21,6 +21,8 @@
#include "linux-osdata.h"
#include "agent.h"
+#include "nat/linux-nat.h"
+#include "nat/linux-waitpid.h"
#include "gdb_wait.h"
#include <stdio.h>
#include <sys/ptrace.h>
@@ -75,14 +77,6 @@
#define __SIGRTMIN 32
#endif
-#ifdef __UCLIBC__
-#if !(defined(__UCLIBC_HAS_MMU__) || defined(__ARCH_HAS_MMU__))
-/* PTRACE_TEXT_ADDR and friends. */
-#include <asm/ptrace.h>
-#define HAS_NOMMU
-#endif
-#endif
-
/* Some targets did not define these ptrace constants from the start,
so gdbserver defines them locally here. In the future, these may
be removed after they are added to asm/ptrace.h. */
@@ -236,7 +230,6 @@ static void proceed_all_lwps (void);
static int finish_step_over (struct lwp_info *lwp);
static CORE_ADDR get_stop_pc (struct lwp_info *lwp);
static int kill_lwp (unsigned long lwpid, int signo);
-static void linux_enable_event_reporting (int pid);
/* True if the low target can hardware single-step. Such targets
don't need a BREAKPOINT_REINSERT_ADDR callback. */
@@ -376,81 +369,6 @@ linux_add_process (int pid, int attached)
return proc;
}
-/* Wrapper function for waitpid which handles EINTR, and emulates
- __WALL for systems where that is not available. */
-
-static int
-my_waitpid (int pid, int *status, int flags)
-{
- int ret, out_errno;
-
- if (debug_threads)
- fprintf (stderr, "my_waitpid (%d, 0x%x)\n", pid, flags);
-
- if (flags & __WALL)
- {
- sigset_t block_mask, org_mask, wake_mask;
- int wnohang;
-
- wnohang = (flags & WNOHANG) != 0;
- flags &= ~(__WALL | __WCLONE);
- flags |= WNOHANG;
-
- /* Block all signals while here. This avoids knowing about
- LinuxThread's signals. */
- sigfillset (&block_mask);
- sigprocmask (SIG_BLOCK, &block_mask, &org_mask);
-
- /* ... except during the sigsuspend below. */
- sigemptyset (&wake_mask);
-
- while (1)
- {
- /* Since all signals are blocked, there's no need to check
- for EINTR here. */
- ret = waitpid (pid, status, flags);
- out_errno = errno;
-
- if (ret == -1 && out_errno != ECHILD)
- break;
- else if (ret > 0)
- break;
-
- if (flags & __WCLONE)
- {
- /* We've tried both flavors now. If WNOHANG is set,
- there's nothing else to do, just bail out. */
- if (wnohang)
- break;
-
- if (debug_threads)
- fprintf (stderr, "blocking\n");
-
- /* Block waiting for signals. */
- sigsuspend (&wake_mask);
- }
-
- flags ^= __WCLONE;
- }
-
- sigprocmask (SIG_SETMASK, &org_mask, NULL);
- }
- else
- {
- do
- ret = waitpid (pid, status, flags);
- while (ret == -1 && errno == EINTR);
- out_errno = errno;
- }
-
- if (debug_threads)
- fprintf (stderr, "my_waitpid (%d, 0x%x): status(%x), %d\n",
- pid, flags, status ? *status : -1, ret);
-
- errno = out_errno;
- return ret;
-}
-
/* Handle a GNU/Linux extended wait response. If we see a clone
event, we need to add the new LWP to our list (and not report the
trap to higher layers). */
@@ -1998,7 +1916,7 @@ linux_wait_for_event (ptid_t ptid, int *wstat, int options)
if (event_child->must_set_ptrace_flags)
{
- linux_enable_event_reporting (lwpid_of (event_child));
+ linux_enable_event_reporting (pid_of (event_child));
event_child->must_set_ptrace_flags = 0;
}
@@ -4659,168 +4577,6 @@ linux_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
return 0;
}
-/* Non-zero if the kernel supports PTRACE_O_TRACEFORK. */
-static int linux_supports_tracefork_flag;
-
-static void
-linux_enable_event_reporting (int pid)
-{
- if (!linux_supports_tracefork_flag)
- return;
-
- ptrace (PTRACE_SETOPTIONS, pid, (PTRACE_TYPE_ARG3) 0,
- (PTRACE_TYPE_ARG4) PTRACE_O_TRACECLONE);
-}
-
-/* Helper functions for linux_test_for_tracefork, called via clone (). */
-
-static int
-linux_tracefork_grandchild (void *arg)
-{
- _exit (0);
-}
-
-#define STACK_SIZE 4096
-
-static int
-linux_tracefork_child (void *arg)
-{
- ptrace (PTRACE_TRACEME, 0, (PTRACE_TYPE_ARG3) 0, (PTRACE_TYPE_ARG4) 0);
- kill (getpid (), SIGSTOP);
-
-#if !(defined(__UCLIBC__) && defined(HAS_NOMMU))
-
- if (fork () == 0)
- linux_tracefork_grandchild (NULL);
-
-#else /* defined(__UCLIBC__) && defined(HAS_NOMMU) */
-
-#ifdef __ia64__
- __clone2 (linux_tracefork_grandchild, arg, STACK_SIZE,
- CLONE_VM | SIGCHLD, NULL);
-#else
- clone (linux_tracefork_grandchild, (char *) arg + STACK_SIZE,
- CLONE_VM | SIGCHLD, NULL);
-#endif
-
-#endif /* defined(__UCLIBC__) && defined(HAS_NOMMU) */
-
- _exit (0);
-}
-
-/* Determine if PTRACE_O_TRACEFORK can be used to follow fork events. Make
- sure that we can enable the option, and that it had the desired
- effect. */
-
-static void
-linux_test_for_tracefork (void)
-{
- int child_pid, ret, status;
- long second_pid;
-#if defined(__UCLIBC__) && defined(HAS_NOMMU)
- char *stack = xmalloc (STACK_SIZE * 4);
-#endif /* defined(__UCLIBC__) && defined(HAS_NOMMU) */
-
- linux_supports_tracefork_flag = 0;
-
-#if !(defined(__UCLIBC__) && defined(HAS_NOMMU))
-
- child_pid = fork ();
- if (child_pid == 0)
- linux_tracefork_child (NULL);
-
-#else /* defined(__UCLIBC__) && defined(HAS_NOMMU) */
-
- /* Use CLONE_VM instead of fork, to support uClinux (no MMU). */
-#ifdef __ia64__
- child_pid = __clone2 (linux_tracefork_child, stack, STACK_SIZE,
- CLONE_VM | SIGCHLD, stack + STACK_SIZE * 2);
-#else /* !__ia64__ */
- child_pid = clone (linux_tracefork_child, stack + STACK_SIZE,
- CLONE_VM | SIGCHLD, stack + STACK_SIZE * 2);
-#endif /* !__ia64__ */
-
-#endif /* defined(__UCLIBC__) && defined(HAS_NOMMU) */
-
- if (child_pid == -1)
- perror_with_name ("clone");
-
- ret = my_waitpid (child_pid, &status, 0);
- if (ret == -1)
- perror_with_name ("waitpid");
- else if (ret != child_pid)
- error ("linux_test_for_tracefork: waitpid: unexpected result %d.", ret);
- if (! WIFSTOPPED (status))
- error ("linux_test_for_tracefork: waitpid: unexpected status %d.", status);
-
- ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0,
- (PTRACE_TYPE_ARG4) PTRACE_O_TRACEFORK);
- if (ret != 0)
- {
- ret = ptrace (PTRACE_KILL, child_pid, (PTRACE_TYPE_ARG3) 0,
- (PTRACE_TYPE_ARG4) 0);
- if (ret != 0)
- {
- warning ("linux_test_for_tracefork: failed to kill child");
- return;
- }
-
- ret = my_waitpid (child_pid, &status, 0);
- if (ret != child_pid)
- warning ("linux_test_for_tracefork: failed to wait for killed child");
- else if (!WIFSIGNALED (status))
- warning ("linux_test_for_tracefork: unexpected wait status 0x%x from "
- "killed child", status);
-
- return;
- }
-
- ret = ptrace (PTRACE_CONT, child_pid, (PTRACE_TYPE_ARG3) 0,
- (PTRACE_TYPE_ARG4) 0);
- if (ret != 0)
- warning ("linux_test_for_tracefork: failed to resume child");
-
- ret = my_waitpid (child_pid, &status, 0);
-
- if (ret == child_pid && WIFSTOPPED (status)
- && status >> 16 == PTRACE_EVENT_FORK)
- {
- second_pid = 0;
- ret = ptrace (PTRACE_GETEVENTMSG, child_pid, (PTRACE_TYPE_ARG3) 0,
- &second_pid);
- if (ret == 0 && second_pid != 0)
- {
- int second_status;
-
- linux_supports_tracefork_flag = 1;
- my_waitpid (second_pid, &second_status, 0);
- ret = ptrace (PTRACE_KILL, second_pid, (PTRACE_TYPE_ARG3) 0,
- (PTRACE_TYPE_ARG4) 0);
- if (ret != 0)
- warning ("linux_test_for_tracefork: failed to kill second child");
- my_waitpid (second_pid, &status, 0);
- }
- }
- else
- warning ("linux_test_for_tracefork: unexpected result from waitpid "
- "(%d, status 0x%x)", ret, status);
-
- do
- {
- ret = ptrace (PTRACE_KILL, child_pid, (PTRACE_TYPE_ARG3) 0,
- (PTRACE_TYPE_ARG4) 0);
- if (ret != 0)
- warning ("linux_test_for_tracefork: failed to kill child");
- my_waitpid (child_pid, &status, 0);
- }
- while (WIFSTOPPED (status));
-
-#if defined(__UCLIBC__) && defined(HAS_NOMMU)
- free (stack);
-#endif /* defined(__UCLIBC__) && defined(HAS_NOMMU) */
-}
-
-
static void
linux_look_up_symbols (void)
{
@@ -4833,7 +4589,7 @@ linux_look_up_symbols (void)
/* If the kernel supports tracing forks then it also supports tracing
clones, and then we don't need to use the magic thread event breakpoint
to learn about threads. */
- thread_db_init (!linux_supports_tracefork_flag);
+ thread_db_init (!linux_supports_tracefork ());
#endif
}
@@ -6097,7 +5853,6 @@ initialize_low (void)
set_breakpoint_data (the_low_target.breakpoint,
the_low_target.breakpoint_len);
linux_init_signals ();
- linux_test_for_tracefork ();
linux_ptrace_init_warnings ();
sigchld_action.sa_handler = sigchld_handler;
diff --git a/gdb/gdbserver/linux-low.h b/gdb/gdbserver/linux-low.h
index e051ab6..4bf0dc3 100644
--- a/gdb/gdbserver/linux-low.h
+++ b/gdb/gdbserver/linux-low.h
@@ -22,8 +22,9 @@
#include "gdbthread.h"
#include "gdb_proc_service.h"
-#define PTRACE_TYPE_ARG3 void *
-#define PTRACE_TYPE_ARG4 void *
+/* Included for ptrace type definitions. */
+#include "linux-ptrace.h"
+
#define PTRACE_XFER_TYPE long
#ifdef HAVE_LINUX_REGSETS
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index db23433..0aac73a 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -20,6 +20,8 @@
#include "defs.h"
#include "inferior.h"
#include "target.h"
+#include "nat/linux-nat.h"
+#include "nat/linux-waitpid.h"
#include "gdb_string.h"
#include "gdb_wait.h"
#include "gdb_assert.h"
@@ -171,11 +173,6 @@ blocked. */
#define O_LARGEFILE 0
#endif
-/* Unlike other extended result codes, WSTOPSIG (status) on
- PTRACE_O_TRACESYSGOOD syscall events doesn't return SIGTRAP, but
- instead SIGTRAP with bit 7 set. */
-#define SYSCALL_SIGTRAP (SIGTRAP | 0x80)
-
/* The single-threaded native GNU/Linux target_ops. We save a pointer for
the use of the multi-threaded target. */
static struct target_ops *linux_ops;
@@ -226,24 +223,6 @@ struct simple_pid_list
};
struct simple_pid_list *stopped_pids;
-/* This variable is a tri-state flag: -1 for unknown, 0 if PTRACE_O_TRACEFORK
- can not be used, 1 if it can. */
-
-static int linux_supports_tracefork_flag = -1;
-
-/* This variable is a tri-state flag: -1 for unknown, 0 if
- PTRACE_O_TRACESYSGOOD can not be used, 1 if it can. */
-
-static int linux_supports_tracesysgood_flag = -1;
-
-/* If we have PTRACE_O_TRACEFORK, this flag indicates whether we also have
- PTRACE_O_TRACEVFORKDONE. */
-
-static int linux_supports_tracevforkdone_flag = -1;
-
-/* Stores the current used ptrace() options. */
-static int current_ptrace_options = 0;
-
/* Async mode support. */
/* The read/write ends of the pipe registered as waitable file in the
@@ -349,244 +328,26 @@ pull_pid_from_list (struct simple_pid_list **listp, int pid, int *statusp)
return 0;
}
-\f
-/* A helper function for linux_test_for_tracefork, called after fork (). */
-
-static void
-linux_tracefork_child (void)
-{
- ptrace (PTRACE_TRACEME, 0, 0, 0);
- kill (getpid (), SIGSTOP);
- fork ();
- _exit (0);
-}
-
-/* Wrapper function for waitpid which handles EINTR. */
-
-static int
-my_waitpid (int pid, int *statusp, int flags)
-{
- int ret;
-
- do
- {
- ret = waitpid (pid, statusp, flags);
- }
- while (ret == -1 && errno == EINTR);
-
- return ret;
-}
-
-/* Determine if PTRACE_O_TRACEFORK can be used to follow fork events.
-
- First, we try to enable fork tracing on ORIGINAL_PID. If this fails,
- we know that the feature is not available. This may change the tracing
- options for ORIGINAL_PID, but we'll be setting them shortly anyway.
-
- However, if it succeeds, we don't know for sure that the feature is
- available; old versions of PTRACE_SETOPTIONS ignored unknown options. We
- create a child process, attach to it, use PTRACE_SETOPTIONS to enable
- fork tracing, and let it fork. If the process exits, we assume that we
- can't use TRACEFORK; if we get the fork notification, and we can extract
- the new child's PID, then we assume that we can. */
+/* Initialize ptrace warnings and check for supported ptrace
+ features given PTID. */
static void
-linux_test_for_tracefork (int original_pid)
+linux_init_ptrace (pid_t pid)
{
- int child_pid, ret, status;
- long second_pid;
-
- linux_supports_tracefork_flag = 0;
- linux_supports_tracevforkdone_flag = 0;
-
- ret = ptrace (PTRACE_SETOPTIONS, original_pid, 0, PTRACE_O_TRACEFORK);
- if (ret != 0)
- return;
-
- child_pid = fork ();
- if (child_pid == -1)
- perror_with_name (("fork"));
-
- if (child_pid == 0)
- linux_tracefork_child ();
-
- ret = my_waitpid (child_pid, &status, 0);
- if (ret == -1)
- perror_with_name (("waitpid"));
- else if (ret != child_pid)
- error (_("linux_test_for_tracefork: waitpid: unexpected result %d."), ret);
- if (! WIFSTOPPED (status))
- error (_("linux_test_for_tracefork: waitpid: unexpected status %d."),
- status);
-
- ret = ptrace (PTRACE_SETOPTIONS, child_pid, 0, PTRACE_O_TRACEFORK);
- if (ret != 0)
- {
- ret = ptrace (PTRACE_KILL, child_pid, 0, 0);
- if (ret != 0)
- {
- warning (_("linux_test_for_tracefork: failed to kill child"));
- return;
- }
-
- ret = my_waitpid (child_pid, &status, 0);
- if (ret != child_pid)
- warning (_("linux_test_for_tracefork: failed "
- "to wait for killed child"));
- else if (!WIFSIGNALED (status))
- warning (_("linux_test_for_tracefork: unexpected "
- "wait status 0x%x from killed child"), status);
-
- return;
- }
-
- /* Check whether PTRACE_O_TRACEVFORKDONE is available. */
- ret = ptrace (PTRACE_SETOPTIONS, child_pid, 0,
- PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORKDONE);
- linux_supports_tracevforkdone_flag = (ret == 0);
-
- ret = ptrace (PTRACE_CONT, child_pid, 0, 0);
- if (ret != 0)
- warning (_("linux_test_for_tracefork: failed to resume child"));
-
- ret = my_waitpid (child_pid, &status, 0);
-
- if (ret == child_pid && WIFSTOPPED (status)
- && status >> 16 == PTRACE_EVENT_FORK)
- {
- second_pid = 0;
- ret = ptrace (PTRACE_GETEVENTMSG, child_pid, 0, &second_pid);
- if (ret == 0 && second_pid != 0)
- {
- int second_status;
-
- linux_supports_tracefork_flag = 1;
- my_waitpid (second_pid, &second_status, 0);
- ret = ptrace (PTRACE_KILL, second_pid, 0, 0);
- if (ret != 0)
- warning (_("linux_test_for_tracefork: "
- "failed to kill second child"));
- my_waitpid (second_pid, &status, 0);
- }
- }
- else
- warning (_("linux_test_for_tracefork: unexpected result from waitpid "
- "(%d, status 0x%x)"), ret, status);
-
- do
- {
- ret = ptrace (PTRACE_KILL, child_pid, 0, 0);
- if (ret != 0)
- warning ("linux_test_for_tracefork: failed to kill child");
- my_waitpid (child_pid, &status, 0);
- }
- while (WIFSTOPPED (status));
-}
-
-/* Determine if PTRACE_O_TRACESYSGOOD can be used to follow syscalls.
-
- We try to enable syscall tracing on ORIGINAL_PID. If this fails,
- we know that the feature is not available. This may change the tracing
- options for ORIGINAL_PID, but we'll be setting them shortly anyway. */
-
-static void
-linux_test_for_tracesysgood (int original_pid)
-{
- int ret;
-
- linux_supports_tracesysgood_flag = 0;
-
- ret = ptrace (PTRACE_SETOPTIONS, original_pid, 0, PTRACE_O_TRACESYSGOOD);
- if (ret != 0)
- return;
-
- linux_supports_tracesysgood_flag = 1;
-}
-
-/* Determine wether we support PTRACE_O_TRACESYSGOOD option available.
- This function also sets linux_supports_tracesysgood_flag. */
-
-static int
-linux_supports_tracesysgood (int pid)
-{
- if (linux_supports_tracesysgood_flag == -1)
- linux_test_for_tracesysgood (pid);
- return linux_supports_tracesysgood_flag;
-}
-
-/* Return non-zero iff we have tracefork functionality available.
- This function also sets linux_supports_tracefork_flag. */
-
-static int
-linux_supports_tracefork (int pid)
-{
- if (linux_supports_tracefork_flag == -1)
- linux_test_for_tracefork (pid);
- return linux_supports_tracefork_flag;
-}
-
-static int
-linux_supports_tracevforkdone (int pid)
-{
- if (linux_supports_tracefork_flag == -1)
- linux_test_for_tracefork (pid);
- return linux_supports_tracevforkdone_flag;
-}
-
-static void
-linux_enable_tracesysgood (ptid_t ptid)
-{
- int pid = ptid_get_lwp (ptid);
-
- if (pid == 0)
- pid = ptid_get_pid (ptid);
-
- if (linux_supports_tracesysgood (pid) == 0)
- return;
-
- current_ptrace_options |= PTRACE_O_TRACESYSGOOD;
-
- ptrace (PTRACE_SETOPTIONS, pid, 0, current_ptrace_options);
-}
-
-\f
-void
-linux_enable_event_reporting (ptid_t ptid)
-{
- int pid = ptid_get_lwp (ptid);
-
- if (pid == 0)
- pid = ptid_get_pid (ptid);
-
- if (! linux_supports_tracefork (pid))
- return;
-
- current_ptrace_options |= PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK
- | PTRACE_O_TRACEEXEC | PTRACE_O_TRACECLONE;
-
- if (linux_supports_tracevforkdone (pid))
- current_ptrace_options |= PTRACE_O_TRACEVFORKDONE;
-
- /* Do not enable PTRACE_O_TRACEEXIT until GDB is more prepared to support
- read-only process state. */
-
- ptrace (PTRACE_SETOPTIONS, pid, 0, current_ptrace_options);
+ linux_enable_event_reporting (pid);
+ linux_ptrace_init_warnings ();
}
static void
linux_child_post_attach (int pid)
{
- linux_enable_event_reporting (pid_to_ptid (pid));
- linux_enable_tracesysgood (pid_to_ptid (pid));
- linux_ptrace_init_warnings ();
+ linux_init_ptrace (pid);
}
static void
linux_child_post_startup_inferior (ptid_t ptid)
{
- linux_enable_event_reporting (ptid);
- linux_enable_tracesysgood (ptid);
- linux_ptrace_init_warnings ();
+ linux_init_ptrace (ptid_get_pid (ptid));
}
/* Return the number of known LWPs in the tgid given by PID. */
@@ -772,9 +533,9 @@ holding the child stopped. Try \"set detach-on-fork\" or \
parent_inf->pspace->breakpoints_not_allowed = detach_fork;
parent_lp = find_lwp_pid (pid_to_ptid (parent_pid));
- gdb_assert (linux_supports_tracefork_flag >= 0);
+ gdb_assert (linux_supports_tracefork () >= 0);
- if (linux_supports_tracevforkdone (0))
+ if (linux_supports_tracevforkdone ())
{
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
@@ -945,7 +706,7 @@ holding the child stopped. Try \"set detach-on-fork\" or \
static int
linux_child_insert_fork_catchpoint (int pid)
{
- return !linux_supports_tracefork (pid);
+ return !linux_supports_tracefork ();
}
static int
@@ -957,7 +718,7 @@ linux_child_remove_fork_catchpoint (int pid)
static int
linux_child_insert_vfork_catchpoint (int pid)
{
- return !linux_supports_tracefork (pid);
+ return !linux_supports_tracefork ();
}
static int
@@ -969,7 +730,7 @@ linux_child_remove_vfork_catchpoint (int pid)
static int
linux_child_insert_exec_catchpoint (int pid)
{
- return !linux_supports_tracefork (pid);
+ return !linux_supports_tracefork ();
}
static int
@@ -982,7 +743,7 @@ static int
linux_child_set_syscall_catchpoint (int pid, int needed, int any_count,
int table_size, int *table)
{
- if (!linux_supports_tracesysgood (pid))
+ if (!linux_supports_tracesysgood ())
return 1;
/* On GNU/Linux, we ignore the arguments. It means that we only
@@ -1429,7 +1190,7 @@ lin_lwp_attach_lwp (ptid_t ptid)
if (ptrace (PTRACE_ATTACH, lwpid, 0, 0) < 0)
{
- if (linux_supports_tracefork_flag)
+ if (linux_supports_tracefork ())
{
/* If we haven't stopped all threads when we get here,
we may have seen a thread listed in thread_db's list,
diff --git a/gdb/linux-nat.h b/gdb/linux-nat.h
index cb8f1da..855c802 100644
--- a/gdb/linux-nat.h
+++ b/gdb/linux-nat.h
@@ -128,8 +128,6 @@ void linux_proc_pending_signals (int pid, sigset_t *pending,
sigset_t *blocked, sigset_t *ignored);
/* linux-nat functions for handling fork events. */
-extern void linux_enable_event_reporting (ptid_t ptid);
-
extern int lin_lwp_attach_lwp (ptid_t ptid);
extern void linux_stop_lwp (struct lwp_info *lwp);
diff --git a/gdb/nat/linux-nat.h b/gdb/nat/linux-nat.h
new file mode 100644
index 0000000..4d84aa5
--- /dev/null
+++ b/gdb/nat/linux-nat.h
@@ -0,0 +1,28 @@
+/* Code for native debugging support for GNU/Linux (LWP layer).
+
+ Copyright (C) 2000-2013 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef LINUX_NAT_H
+#define LINUX_NAT_H
+
+/* Unlike other extended result codes, WSTOPSIG (status) on
+ PTRACE_O_TRACESYSGOOD syscall events doesn't return SIGTRAP, but
+ instead SIGTRAP with bit 7 set. */
+#define SYSCALL_SIGTRAP (SIGTRAP | 0x80)
+
+#endif /* LINUX_NAT_H */
diff --git a/gdb/nat/linux-waitpid.c b/gdb/nat/linux-waitpid.c
new file mode 100644
index 0000000..2debea4
--- /dev/null
+++ b/gdb/nat/linux-waitpid.c
@@ -0,0 +1,120 @@
+/* Wrapper implementation for waitpid for GNU/Linux (LWP layer).
+
+ Copyright (C) 2001-2013 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef GDBSERVER
+#include "server.h"
+#else
+#include "defs.h"
+#include "signal.h"
+#endif
+
+#include "nat/linux-nat.h"
+#include "nat/linux-waitpid.h"
+#include "gdb_wait.h"
+
+/* Print debugging output based on the format string FORMAT and
+ its parameters. */
+
+static inline void
+linux_debug (const char *format, ...)
+{
+#ifdef GDBSERVER
+ if (debug_threads)
+ {
+ va_list args;
+ va_start (args, format);
+ vfprintf (stderr, format, args);
+ fprintf (stderr, "\n");
+ va_end (args);
+ }
+#else
+ /* GDB-specific debugging output. */
+#endif
+}
+
+/* Wrapper function for waitpid which handles EINTR, and emulates
+ __WALL for systems where that is not available. */
+
+int
+my_waitpid (int pid, int *status, int flags)
+{
+ int ret, out_errno;
+
+ linux_debug ("my_waitpid (%d, 0x%x)\n", pid, flags);
+
+ if (flags & __WALL)
+ {
+ sigset_t block_mask, org_mask, wake_mask;
+ int wnohang;
+
+ wnohang = (flags & WNOHANG) != 0;
+ flags &= ~(__WALL | __WCLONE);
+ flags |= WNOHANG;
+
+ /* Block all signals while here. This avoids knowing about
+ LinuxThread's signals. */
+ sigfillset (&block_mask);
+ sigprocmask (SIG_BLOCK, &block_mask, &org_mask);
+
+ /* ... except during the sigsuspend below. */
+ sigemptyset (&wake_mask);
+
+ while (1)
+ {
+ /* Since all signals are blocked, there's no need to check
+ for EINTR here. */
+ ret = waitpid (pid, status, flags);
+ out_errno = errno;
+
+ if (ret == -1 && out_errno != ECHILD)
+ break;
+ else if (ret > 0)
+ break;
+
+ if (flags & __WCLONE)
+ {
+ /* We've tried both flavors now. If WNOHANG is set,
+ there's nothing else to do, just bail out. */
+ if (wnohang)
+ break;
+
+ linux_debug ("blocking\n");
+
+ /* Block waiting for signals. */
+ sigsuspend (&wake_mask);
+ }
+ flags ^= __WCLONE;
+ }
+
+ sigprocmask (SIG_SETMASK, &org_mask, NULL);
+ }
+ else
+ {
+ do
+ ret = waitpid (pid, status, flags);
+ while (ret == -1 && errno == EINTR);
+ out_errno = errno;
+ }
+
+ linux_debug ("my_waitpid (%d, 0x%x): status(%x), %d\n",
+ pid, flags, status ? *status : -1, ret);
+
+ errno = out_errno;
+ return ret;
+}
diff --git a/gdb/nat/linux-waitpid.h b/gdb/nat/linux-waitpid.h
new file mode 100644
index 0000000..0df29d8
--- /dev/null
+++ b/gdb/nat/linux-waitpid.h
@@ -0,0 +1,27 @@
+/* Wrapper for waitpid for GNU/Linux (LWP layer).
+
+ Copyright (C) 2000-2013 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef LINUX_WAITPID_H
+#define LINUX_WAITPID_H
+
+/* Wrapper function for waitpid which handles EINTR, and emulates
+ __WALL for systems where that is not available. */
+extern int my_waitpid (int pid, int *status, int flags);
+
+#endif /* LINUX_WAITPID_H */
next prev parent reply other threads:[~2013-08-21 3:09 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-08-19 23:27 Luis Machado
2013-08-20 15:38 ` Tom Tromey
2013-08-20 15:46 ` Luis Machado
2013-08-20 16:14 ` Tom Tromey
2013-08-20 16:39 ` Pedro Alves
2013-08-20 16:44 ` Pedro Alves
2013-08-20 16:48 ` Tom Tromey
2013-08-20 17:03 ` Pedro Alves
2013-08-21 3:09 ` Luis Machado [this message]
2013-08-21 21:29 ` Pedro Alves
2013-08-22 2:42 ` Luis Machado
2013-08-22 17:06 ` Pedro Alves
2013-08-22 18:02 ` Luis Machado
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=52142F4B.7030702@codesourcery.com \
--to=lgustavo@codesourcery.com \
--cc=gdb-patches@sourceware.org \
--cc=palves@redhat.com \
--cc=tromey@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox