Unify ptrace options discovery code and make both GDB and

gdbserver use it.

	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_ptrace_test_ret_to_nx): Use type casts for ptrace
	parameters.
	(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_traceclone): 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_traceclone): 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_traceclone.
	(initialize_low): Remove call to linux_test_for_tracefork.
	* linux-low.h (PTRACE_TYPE_ARG3): Move to
	common/linux-ptrace.h.
	(PTRACE_TYPE_ARG4): Likewise.
	Include linux-ptrace.h.
This commit is contained in:
Luis Machado 2013-08-22 23:46:30 +00:00
parent a5829458a1
commit 96d7229d2a
34 changed files with 715 additions and 577 deletions

View File

@ -1,3 +1,84 @@
2013-08-22 Luis Machado <lgustavo@codesourcery.com>
* 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_ptrace_test_ret_to_nx): Use type casts for ptrace
parameters.
(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_traceclone): 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_traceclone): 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.
2013-08-22 Samuel Bronson <naesten@gmail.com>
ARM Linux support for `catch syscall'.

View File

@ -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
#

View File

@ -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. */
@ -97,7 +103,8 @@ linux_ptrace_test_ret_to_nx (void)
return;
case 0:
l = ptrace (PTRACE_TRACEME, 0, NULL, NULL);
l = ptrace (PTRACE_TRACEME, 0, (PTRACE_TYPE_ARG3) NULL,
(PTRACE_TYPE_ARG4) NULL);
if (l != 0)
warning (_("linux_ptrace_test_ret_to_nx: Cannot PTRACE_TRACEME: %s"),
strerror (errno));
@ -163,9 +170,11 @@ linux_ptrace_test_ret_to_nx (void)
errno = 0;
#if defined __i386__
l = ptrace (PTRACE_PEEKUSER, child, (void *) (uintptr_t) (EIP * 4), NULL);
l = ptrace (PTRACE_PEEKUSER, child, (PTRACE_TYPE_ARG3) (uintptr_t) (EIP * 4),
(PTRACE_TYPE_ARG4) NULL);
#elif defined __x86_64__
l = ptrace (PTRACE_PEEKUSER, child, (void *) (uintptr_t) (RIP * 8), NULL);
l = ptrace (PTRACE_PEEKUSER, child, (PTRACE_TYPE_ARG3) (uintptr_t) (RIP * 8),
(PTRACE_TYPE_ARG4) NULL);
#else
# error "!__i386__ && !__x86_64__"
#endif
@ -178,7 +187,8 @@ linux_ptrace_test_ret_to_nx (void)
pc = (void *) (uintptr_t) l;
kill (child, SIGKILL);
ptrace (PTRACE_KILL, child, NULL, NULL);
ptrace (PTRACE_KILL, child, (PTRACE_TYPE_ARG3) NULL,
(PTRACE_TYPE_ARG4) NULL);
errno = 0;
got_pid = waitpid (child, &kill_status, 0);
@ -222,6 +232,292 @@ 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 CHILD_STACK as parameter.
For MMU-less targets, clone is used instead of fork, and
CHILD_STACK is used as stack space for the cloned child. If NULL,
stack space is allocated via malloc (and subsequently passed to
FUNCTION). For MMU targets, CHILD_STACK is ignored. */
static int
linux_fork_to_function (gdb_byte *child_stack, void (*function) (gdb_byte *))
{
int child_pid;
/* Sanity check the function pointer. */
gdb_assert (function != NULL);
#if defined(__UCLIBC__) && defined(HAS_NOMMU)
#define STACK_SIZE 4096
if (child_stack == NULL)
child_stack = xmalloc (STACK_SIZE * 4);
/* Use CLONE_VM instead of fork, to support uClinux (no MMU). */
#ifdef __ia64__
child_pid = __clone2 (function, child_stack, STACK_SIZE,
CLONE_VM | SIGCHLD, child_stack + STACK_SIZE * 2);
#else /* !__ia64__ */
child_pid = clone (function, child_stack + STACK_SIZE,
CLONE_VM | SIGCHLD, child_stack + STACK_SIZE * 2);
#endif /* !__ia64__ */
#else /* !defined(__UCLIBC) && defined(HAS_NOMMU) */
child_pid = fork ();
if (child_pid == 0)
function (NULL);
#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 (gdb_byte *child_stack)
{
/* Free any allocated stack. */
xfree (child_stack);
/* 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 (gdb_byte *child_stack)
{
ptrace (PTRACE_TRACEME, 0, (PTRACE_TYPE_ARG3) 0, (PTRACE_TYPE_ARG4) 0);
kill (getpid (), SIGSTOP);
/* Fork a grandchild. */
linux_fork_to_function (child_stack, 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_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_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_TYPE_ARG4) 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_TYPE_ARG4) (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,
(PTRACE_TYPE_ARG4) (uintptr_t) 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_TRACEFORK);
}
/* Returns non-zero if PTRACE_EVENT_CLONE is supported by ptrace,
0 otherwise. Note that if PTRACE_EVENT_CLONE is supported so is
PTRACE_EVENT_FORK, PTRACE_EVENT_EXEC and PTRACE_EVENT_VFORK,
since they were all added to the kernel at the same time. */
int
linux_supports_traceclone (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. */

View File

@ -22,6 +22,22 @@ 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
#if !defined(PTRACE_TYPE_ARG3)
#define PTRACE_TYPE_ARG3 void *
#endif
#if !defined(PTRACE_TYPE_ARG4)
#define PTRACE_TYPE_ARG4 void *
#endif
#ifndef PTRACE_GETSIGINFO
# define PTRACE_GETSIGINFO 0x4202
# define PTRACE_SETSIGINFO 0x4203
@ -69,5 +85,10 @@ 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_traceclone (void);
extern int linux_supports_tracevforkdone (void);
extern int linux_supports_tracesysgood (void);
#endif /* COMMON_LINUX_PTRACE_H */

View File

@ -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

View File

@ -21,7 +21,7 @@
NAT_FILE= config/nm-linux.h
NATDEPFILES= 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
linux-procfs.o linux-ptrace.o linux-osdata.o linux-waitpid.o
NAT_CDEPS = $(srcdir)/proc-service.list
LOADLIBES= -ldl $(RDYNAMIC)

View File

@ -2,7 +2,8 @@
NAT_FILE= config/nm-linux.h
NATDEPFILES= 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
linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
linux-waitpid.o
NAT_CDEPS = $(srcdir)/proc-service.list
# The dynamically loaded libthread_db needs access to symbols in the

View File

@ -3,7 +3,8 @@
NAT_FILE= config/nm-linux.h
NATDEPFILES= 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
linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
linux-waitpid.o
NAT_CDEPS = $(srcdir)/proc-service.list
LOADLIBES= -ldl $(RDYNAMIC)

View File

@ -5,7 +5,7 @@ NATDEPFILES= 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 \
linux-btrace.o
linux-btrace.o linux-waitpid.o
NAT_CDEPS = $(srcdir)/proc-service.list
# The dynamically loaded libthread_db needs access to symbols in the

View File

@ -3,7 +3,8 @@ NATDEPFILES= 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 \
linux-procfs.o linux-ptrace.o linux-btrace.o
linux-procfs.o linux-ptrace.o linux-btrace.o \
linux-waitpid.o
NAT_FILE= config/nm-linux.h
NAT_CDEPS = $(srcdir)/proc-service.list

View File

@ -5,7 +5,7 @@ NATDEPFILES= 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 \
linux-procfs.o linux-ptrace.o
linux-procfs.o linux-ptrace.o linux-waitpid.o
NAT_CDEPS = $(srcdir)/proc-service.list
LOADLIBES = -ldl $(RDYNAMIC)

View File

@ -3,7 +3,8 @@
NAT_FILE= config/nm-linux.h
NATDEPFILES= 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
linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
linux-waitpid.o
NAT_CDEPS = $(srcdir)/proc-service.list
LOADLIBES= -ldl $(RDYNAMIC)

View File

@ -4,7 +4,8 @@ NAT_FILE= config/nm-linux.h
NATDEPFILES= 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
linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
linux-waitpid.o
NAT_CDEPS = $(srcdir)/proc-service.list
# The dynamically loaded libthread_db needs access to symbols in the

View File

@ -3,7 +3,8 @@ NAT_FILE= config/nm-linux.h
NATDEPFILES= 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
linux-procfs.o linux-ptrace.o linux-waitpid.o \
mips-linux-watch.o
NAT_CDEPS = $(srcdir)/proc-service.list
LOADLIBES = -ldl $(RDYNAMIC)

View File

@ -3,7 +3,7 @@ NAT_FILE= config/nm-linux.h
NATDEPFILES= 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
linux-procfs.o linux-ptrace.o linux-waitpid.o
NAT_CDEPS = $(srcdir)/proc-service.list
LOADLIBES = -ldl $(RDYNAMIC)

View File

@ -5,7 +5,8 @@ XM_CLIBS=
NAT_FILE= config/nm-linux.h
NATDEPFILES= 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
linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
linux-waitpid.o
NAT_CDEPS = $(srcdir)/proc-service.list
LOADLIBES = -ldl $(RDYNAMIC)

View File

@ -5,7 +5,8 @@ XM_CLIBS=
NAT_FILE= config/nm-linux.h
NATDEPFILES= 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
linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
linux-waitpid.o
NAT_CDEPS = $(srcdir)/proc-service.list
# The PowerPC has severe limitations on TOC size, and uses them even

View File

@ -4,5 +4,5 @@
# PPU side of the Cell BE and debugging the SPU side.
NATDEPFILES = spu-linux-nat.o fork-child.o inf-ptrace.o \
linux-procfs.o linux-ptrace.o
linux-procfs.o linux-ptrace.o linux-waitpid.o

View File

@ -4,7 +4,7 @@ NATDEPFILES= sparc-nat.o sparc-linux-nat.o \
core-regset.o fork-child.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
linux-procfs.o linux-ptrace.o linux-waitpid.o
NAT_CDEPS = $(srcdir)/proc-service.list
# The dynamically loaded libthread_db needs access to symbols in the

View File

@ -5,7 +5,7 @@ NATDEPFILES= sparc-nat.o sparc64-nat.o sparc64-linux-nat.o \
fork-child.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
linux-procfs.o linux-ptrace.o linux-waitpid.o
NAT_CDEPS = $(srcdir)/proc-service.list
# The dynamically loaded libthread_db needs access to symbols in the

View File

@ -5,7 +5,7 @@ NATDEPFILES= 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 \
linux-procfs.o linux-ptrace.o
linux-procfs.o linux-ptrace.o linux-waitpid.o
# The dynamically loaded libthread_db needs access to symbols in the
# gdb executable.

View File

@ -4,7 +4,8 @@ NAT_FILE= config/nm-linux.h
NATDEPFILES= 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
linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
linux-waitpid.o
NAT_CDEPS = $(srcdir)/proc-service.list
LOADLIBES = -ldl $(RDYNAMIC)

7
gdb/configure vendored
View File

@ -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

View File

@ -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.])

View File

@ -1,3 +1,30 @@
2013-08-22 Luis Machado <lgustavo@codesourcery.com>
* 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_traceclone.
(initialize_low): Remove call to linux_test_for_tracefork.
* linux-low.h (PTRACE_TYPE_ARG3): Move to
common/linux-ptrace.h.
(PTRACE_TYPE_ARG4): Likewise.
Include linux-ptrace.h.
2013-08-21 Pedro Alves <palves@redhat.com>
* config.in: Renegerate.

View File

@ -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

View File

@ -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_linux_obj="linux-low.o linux-osdata.o linux-procfs.o linux-ptrace.o linux-waitpid.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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_linux_obj linux-osdata.o"
srv_linux_regsets=yes
srv_linux_thread_db=yes
;;

View File

@ -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). */
@ -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)
{
@ -4830,10 +4586,10 @@ linux_look_up_symbols (void)
if (proc->private->thread_db != NULL)
return;
/* 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);
/* If the kernel supports tracing clones, then we don't need to
use the magic thread event breakpoint to learn about
threads. */
thread_db_init (!linux_supports_traceclone ());
#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;

View File

@ -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

View File

@ -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;
}
/* A helper function for linux_test_for_tracefork, called after fork (). */
/* Initialize ptrace warnings and check for supported ptrace
features given PID. */
static void
linux_tracefork_child (void)
linux_init_ptrace (pid_t pid)
{
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. */
static void
linux_test_for_tracefork (int original_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);
}
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,

View File

@ -127,9 +127,6 @@ extern void lin_thread_get_thread_signals (sigset_t *mask);
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);

28
gdb/nat/linux-nat.h Normal file
View File

@ -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 */

120
gdb/nat/linux-waitpid.c Normal file
View File

@ -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;
}

27
gdb/nat/linux-waitpid.h Normal file
View File

@ -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 */