aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbserver/linux-low.c
diff options
context:
space:
mode:
authorLuis Machado <luisgpm@br.ibm.com>2013-08-22 23:46:30 +0000
committerLuis Machado <luisgpm@br.ibm.com>2013-08-22 23:46:30 +0000
commit96d7229d2aa856ef96a420827f3e785081af66ea (patch)
tree8611905663226a3fe25cd6e68e040d795dbbb47c /gdb/gdbserver/linux-low.c
parenta5829458a109d5c8a80bd17ec8c5e5550e94c70c (diff)
downloadgdb-96d7229d2aa856ef96a420827f3e785081af66ea.zip
gdb-96d7229d2aa856ef96a420827f3e785081af66ea.tar.gz
gdb-96d7229d2aa856ef96a420827f3e785081af66ea.tar.bz2
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.
Diffstat (limited to 'gdb/gdbserver/linux-low.c')
-rw-r--r--gdb/gdbserver/linux-low.c257
1 files changed, 6 insertions, 251 deletions
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 217cd2e..12208dc 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -21,6 +21,8 @@
#include "linux-osdata.h"
#include "agent.h"
+#include "nat/linux-nat.h"
+#include "nat/linux-waitpid.h"
#include "gdb_wait.h"
#include <stdio.h>
#include <sys/ptrace.h>
@@ -75,14 +77,6 @@
#define __SIGRTMIN 32
#endif
-#ifdef __UCLIBC__
-#if !(defined(__UCLIBC_HAS_MMU__) || defined(__ARCH_HAS_MMU__))
-/* PTRACE_TEXT_ADDR and friends. */
-#include <asm/ptrace.h>
-#define HAS_NOMMU
-#endif
-#endif
-
/* Some targets did not define these ptrace constants from the start,
so gdbserver defines them locally here. In the future, these may
be removed after they are added to asm/ptrace.h. */
@@ -236,7 +230,6 @@ static void proceed_all_lwps (void);
static int finish_step_over (struct lwp_info *lwp);
static CORE_ADDR get_stop_pc (struct lwp_info *lwp);
static int kill_lwp (unsigned long lwpid, int signo);
-static void linux_enable_event_reporting (int pid);
/* True if the low target can hardware single-step. Such targets
don't need a BREAKPOINT_REINSERT_ADDR callback. */
@@ -376,81 +369,6 @@ linux_add_process (int pid, int attached)
return proc;
}
-/* Wrapper function for waitpid which handles EINTR, and emulates
- __WALL for systems where that is not available. */
-
-static int
-my_waitpid (int pid, int *status, int flags)
-{
- int ret, out_errno;
-
- if (debug_threads)
- fprintf (stderr, "my_waitpid (%d, 0x%x)\n", pid, flags);
-
- if (flags & __WALL)
- {
- sigset_t block_mask, org_mask, wake_mask;
- int wnohang;
-
- wnohang = (flags & WNOHANG) != 0;
- flags &= ~(__WALL | __WCLONE);
- flags |= WNOHANG;
-
- /* Block all signals while here. This avoids knowing about
- LinuxThread's signals. */
- sigfillset (&block_mask);
- sigprocmask (SIG_BLOCK, &block_mask, &org_mask);
-
- /* ... except during the sigsuspend below. */
- sigemptyset (&wake_mask);
-
- while (1)
- {
- /* Since all signals are blocked, there's no need to check
- for EINTR here. */
- ret = waitpid (pid, status, flags);
- out_errno = errno;
-
- if (ret == -1 && out_errno != ECHILD)
- break;
- else if (ret > 0)
- break;
-
- if (flags & __WCLONE)
- {
- /* We've tried both flavors now. If WNOHANG is set,
- there's nothing else to do, just bail out. */
- if (wnohang)
- break;
-
- if (debug_threads)
- fprintf (stderr, "blocking\n");
-
- /* Block waiting for signals. */
- sigsuspend (&wake_mask);
- }
-
- flags ^= __WCLONE;
- }
-
- sigprocmask (SIG_SETMASK, &org_mask, NULL);
- }
- else
- {
- do
- ret = waitpid (pid, status, flags);
- while (ret == -1 && errno == EINTR);
- out_errno = errno;
- }
-
- if (debug_threads)
- fprintf (stderr, "my_waitpid (%d, 0x%x): status(%x), %d\n",
- pid, flags, status ? *status : -1, ret);
-
- errno = out_errno;
- return ret;
-}
-
/* Handle a GNU/Linux extended wait response. If we see a clone
event, we need to add the new LWP to our list (and not report the
trap to higher layers). */
@@ -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;