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:
parent
a5829458a1
commit
96d7229d2a
34 changed files with 715 additions and 577 deletions
|
@ -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'.
|
||||
|
|
|
@ -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
|
||||
#
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
7
gdb/configure
vendored
|
@ -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
|
||||
|
|
|
@ -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.])
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
;;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
271
gdb/linux-nat.c
271
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;
|
||||
}
|
||||
|
||||
|
||||
/* 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,
|
||||
|
|
|
@ -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
28
gdb/nat/linux-nat.h
Normal 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
120
gdb/nat/linux-waitpid.c
Normal 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
27
gdb/nat/linux-waitpid.h
Normal 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 */
|
Loading…
Reference in a new issue