X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Flinux-nat.c;h=b33abb0dce6125241e7704b037480ad36ff835bd;hb=dac804dfa6389b71f50b5e169ffa4e239958e774;hp=22ce84207b0a8e8cbda9385de3aad6f80b390b7f;hpb=492d29ea1c9a8b2c7d5193908119a4e27c045687;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index 22ce84207b..b33abb0dce 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -28,7 +28,7 @@ #include #include #endif -#include +#include "nat/gdb_ptrace.h" #include "linux-nat.h" #include "nat/linux-ptrace.h" #include "nat/linux-procfs.h" @@ -66,6 +66,8 @@ #include "target-descriptions.h" #include "filestuff.h" #include "objfiles.h" +#include "nat/linux-namespaces.h" +#include "fileio.h" #ifndef SPUFS_MAGIC #define SPUFS_MAGIC 0x23c9b64e @@ -163,6 +165,9 @@ blocked. */ #define O_LARGEFILE 0 #endif +/* Does the current host support PTRACE_GETREGSET? */ +enum tribool have_ptrace_getregset = TRIBOOL_UNKNOWN; + /* 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; @@ -281,6 +286,50 @@ static int check_stopped_by_breakpoint (struct lwp_info *lp); static int sigtrap_is_event (int status); static int (*linux_nat_status_is_event) (int status) = sigtrap_is_event; + +/* LWP accessors. */ + +/* See nat/linux-nat.h. */ + +ptid_t +ptid_of_lwp (struct lwp_info *lwp) +{ + return lwp->ptid; +} + +/* See nat/linux-nat.h. */ + +void +lwp_set_arch_private_info (struct lwp_info *lwp, + struct arch_lwp_info *info) +{ + lwp->arch_private = info; +} + +/* See nat/linux-nat.h. */ + +struct arch_lwp_info * +lwp_arch_private_info (struct lwp_info *lwp) +{ + return lwp->arch_private; +} + +/* See nat/linux-nat.h. */ + +int +lwp_is_stopped (struct lwp_info *lwp) +{ + return lwp->stopped; +} + +/* See nat/linux-nat.h. */ + +enum target_stop_reason +lwp_stop_reason (struct lwp_info *lwp) +{ + return lwp->stop_reason; +} + /* Trivial list manipulation functions to keep track of a list of new stopped processes. */ @@ -324,6 +373,25 @@ pull_pid_from_list (struct simple_pid_list **listp, int pid, int *statusp) return 0; } +/* Return the ptrace options that we want to try to enable. */ + +static int +linux_nat_ptrace_options (int attached) +{ + int options = 0; + + if (!attached) + options |= PTRACE_O_EXITKILL; + + options |= (PTRACE_O_TRACESYSGOOD + | PTRACE_O_TRACEVFORKDONE + | PTRACE_O_TRACEVFORK + | PTRACE_O_TRACEFORK + | PTRACE_O_TRACEEXEC); + + return options; +} + /* Initialize ptrace warnings and check for supported ptrace features given PID. @@ -332,7 +400,9 @@ pull_pid_from_list (struct simple_pid_list **listp, int pid, int *statusp) static void linux_init_ptrace (pid_t pid, int attached) { - linux_enable_event_reporting (pid, attached); + int options = linux_nat_ptrace_options (attached); + + linux_enable_event_reporting (pid, options); linux_ptrace_init_warnings (); } @@ -834,14 +904,11 @@ find_lwp_pid (ptid_t ptid) return NULL; } -/* Call CALLBACK with its second argument set to DATA for every LWP in - the list. If CALLBACK returns 1 for a particular LWP, return a - pointer to the structure describing that LWP immediately. - Otherwise return NULL. */ +/* See nat/linux-nat.h. */ struct lwp_info * iterate_over_lwps (ptid_t filter, - int (*callback) (struct lwp_info *, void *), + iterate_over_lwps_ftype callback, void *data) { struct lwp_info *lp, *lpnext; @@ -852,7 +919,7 @@ iterate_over_lwps (ptid_t filter, if (ptid_match (lp->ptid, filter)) { - if ((*callback) (lp, data)) + if ((*callback) (lp, data) != 0) return lp; } } @@ -1300,7 +1367,7 @@ linux_nat_attach (struct target_ops *ops, const char *args, int from_tty) attach_proc_task_lwp_callback); if (target_can_async_p ()) - target_async (inferior_event_handler, 0); + target_async (1); } /* Get pending status of LP. */ @@ -1503,7 +1570,8 @@ linux_nat_detach (struct target_ops *ops, const char *args, int from_tty) single-step it. If SIGNAL is nonzero, give it that signal. */ static void -linux_resume_one_lwp (struct lwp_info *lp, int step, enum gdb_signal signo) +linux_resume_one_lwp_throw (struct lwp_info *lp, int step, + enum gdb_signal signo) { lp->step = step; @@ -1522,11 +1590,68 @@ linux_resume_one_lwp (struct lwp_info *lp, int step, enum gdb_signal signo) if (linux_nat_prepare_to_resume != NULL) linux_nat_prepare_to_resume (lp); linux_ops->to_resume (linux_ops, lp->ptid, step, signo); - lp->stop_reason = TARGET_STOPPED_BY_NO_REASON; + + /* Successfully resumed. Clear state that no longer makes sense, + and mark the LWP as running. Must not do this before resuming + otherwise if that fails other code will be confused. E.g., we'd + later try to stop the LWP and hang forever waiting for a stop + status. Note that we must not throw after this is cleared, + otherwise handle_zombie_lwp_error would get confused. */ lp->stopped = 0; + lp->stop_reason = TARGET_STOPPED_BY_NO_REASON; registers_changed_ptid (lp->ptid); } +/* Called when we try to resume a stopped LWP and that errors out. If + the LWP is no longer in ptrace-stopped state (meaning it's zombie, + or about to become), discard the error, clear any pending status + the LWP may have, and return true (we'll collect the exit status + soon enough). Otherwise, return false. */ + +static int +check_ptrace_stopped_lwp_gone (struct lwp_info *lp) +{ + /* If we get an error after resuming the LWP successfully, we'd + confuse !T state for the LWP being gone. */ + gdb_assert (lp->stopped); + + /* We can't just check whether the LWP is in 'Z (Zombie)' state, + because even if ptrace failed with ESRCH, the tracee may be "not + yet fully dead", but already refusing ptrace requests. In that + case the tracee has 'R (Running)' state for a little bit + (observed in Linux 3.18). See also the note on ESRCH in the + ptrace(2) man page. Instead, check whether the LWP has any state + other than ptrace-stopped. */ + + /* Don't assume anything if /proc/PID/status can't be read. */ + if (linux_proc_pid_is_trace_stopped_nowarn (ptid_get_lwp (lp->ptid)) == 0) + { + lp->stop_reason = TARGET_STOPPED_BY_NO_REASON; + lp->status = 0; + lp->waitstatus.kind = TARGET_WAITKIND_IGNORE; + return 1; + } + return 0; +} + +/* Like linux_resume_one_lwp_throw, but no error is thrown if the LWP + disappears while we try to resume it. */ + +static void +linux_resume_one_lwp (struct lwp_info *lp, int step, enum gdb_signal signo) +{ + TRY + { + linux_resume_one_lwp_throw (lp, step, signo); + } + CATCH (ex, RETURN_MASK_ERROR) + { + if (!check_ptrace_stopped_lwp_gone (lp)) + throw_exception (ex); + } + END_CATCH +} + /* Resume LP. */ static void @@ -1690,7 +1815,7 @@ linux_nat_resume (struct target_ops *ops, if (target_can_async_p ()) { - target_async (inferior_event_handler, 0); + target_async (1); /* Tell the event loop we have something to process. */ async_file_mark (); } @@ -1700,18 +1825,18 @@ linux_nat_resume (struct target_ops *ops, if (resume_many) iterate_over_lwps (ptid, linux_nat_resume_callback, lp); - linux_resume_one_lwp (lp, step, signo); - if (debug_linux_nat) fprintf_unfiltered (gdb_stdlog, "LLR: %s %s, %s (resume event thread)\n", step ? "PTRACE_SINGLESTEP" : "PTRACE_CONT", - target_pid_to_str (ptid), + target_pid_to_str (lp->ptid), (signo != GDB_SIGNAL_0 ? strsignal (gdb_signal_to_host (signo)) : "0")); + linux_resume_one_lwp (lp, step, signo); + if (target_can_async_p ()) - target_async (inferior_event_handler, 0); + target_async (1); } /* Send a signal to an LWP. */ @@ -2010,9 +2135,12 @@ linux_handle_extended_wait (struct lwp_info *lp, int status, add_thread (new_lp->ptid); } + /* Even if we're stopping the thread for some reason + internal to this module, from the user/frontend's + perspective, this new thread is running. */ + set_running (new_lp->ptid, 1); if (!stopping) { - set_running (new_lp->ptid, 1); set_executing (new_lp->ptid, 1); /* thread_db_attach_lwp -> lin_lwp_attach_lwp forced resume_stop. */ @@ -2199,8 +2327,9 @@ wait_lwp (struct lwp_info *lp) if (lp->must_set_ptrace_flags) { struct inferior *inf = find_inferior_pid (ptid_get_pid (lp->ptid)); + int options = linux_nat_ptrace_options (inf->attach_flag); - linux_enable_event_reporting (ptid_get_lwp (lp->ptid), inf->attach_flag); + linux_enable_event_reporting (ptid_get_lwp (lp->ptid), options); lp->must_set_ptrace_flags = 0; } @@ -2519,7 +2648,7 @@ stop_wait_callback (struct lwp_info *lp, void *data) if (debug_linux_nat) fprintf_unfiltered (gdb_stdlog, - "SWC: Delayed SIGSTOP caught for %s.\n", + "SWC: Expected SIGSTOP caught for %s.\n", target_pid_to_str (lp->ptid)); /* Reset SIGNALLED only after the stop_wait_callback call @@ -2543,6 +2672,9 @@ status_callback (struct lwp_info *lp, void *data) if (!lp->resumed) return 0; + if (!lwp_status_pending_p (lp)) + return 0; + if (lp->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT || lp->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT) { @@ -2551,8 +2683,6 @@ status_callback (struct lwp_info *lp, void *data) CORE_ADDR pc; int discard = 0; - gdb_assert (lp->status != 0); - pc = regcache_read_pc (regcache); if (pc != lp->stop_pc) @@ -2590,10 +2720,9 @@ status_callback (struct lwp_info *lp, void *data) linux_resume_one_lwp (lp, lp->step, GDB_SIGNAL_0); return 0; } - return 1; } - return lwp_status_pending_p (lp); + return 1; } /* Return non-zero if LP isn't stopped. */ @@ -2644,7 +2773,7 @@ lwp_status_pending_p (struct lwp_info *lp) return lp->status != 0 || lp->waitstatus.kind != TARGET_WAITKIND_IGNORE; } -/* Select the Nth LWP that has had a SIGTRAP event. */ +/* Select the Nth LWP that has had an event. */ static int select_event_lwp_callback (struct lwp_info *lp, void *data) @@ -2696,8 +2825,8 @@ check_stopped_by_breakpoint (struct lwp_info *lp) { if (debug_linux_nat) fprintf_unfiltered (gdb_stdlog, - "CSBB: Push back software " - "breakpoint for %s\n", + "CSBB: %s stopped by software " + "breakpoint\n", target_pid_to_str (lp->ptid)); /* Back up the PC if necessary. */ @@ -2712,14 +2841,21 @@ check_stopped_by_breakpoint (struct lwp_info *lp) { if (debug_linux_nat) fprintf_unfiltered (gdb_stdlog, - "CSBB: Push back hardware " - "breakpoint/watchpoint for %s\n", + "CSBB: %s stopped by hardware " + "breakpoint/watchpoint\n", target_pid_to_str (lp->ptid)); lp->stop_pc = pc; lp->stop_reason = TARGET_STOPPED_BY_HW_BREAKPOINT; return 1; } + else if (siginfo.si_code == TRAP_TRACE) + { + if (debug_linux_nat) + fprintf_unfiltered (gdb_stdlog, + "CSBB: %s stopped by trace\n", + target_pid_to_str (lp->ptid)); + } } } #else @@ -2731,7 +2867,7 @@ check_stopped_by_breakpoint (struct lwp_info *lp) breakpoint instruction. */ if (debug_linux_nat) fprintf_unfiltered (gdb_stdlog, - "CB: Push back software breakpoint for %s\n", + "CSBB: %s stopped by software breakpoint\n", target_pid_to_str (lp->ptid)); /* Back up the PC if necessary. */ @@ -2747,7 +2883,7 @@ check_stopped_by_breakpoint (struct lwp_info *lp) { if (debug_linux_nat) fprintf_unfiltered (gdb_stdlog, - "CB: Push back hardware breakpoint for %s\n", + "CSBB: stopped by hardware breakpoint %s\n", target_pid_to_str (lp->ptid)); lp->stop_pc = pc; @@ -2841,6 +2977,7 @@ select_event_lwp (ptid_t filter, struct lwp_info **orig_lp, int *status) /* First see how many events we have. */ iterate_over_lwps (filter, count_events_callback, &num_events); + gdb_assert (num_events > 0); /* Now randomly pick a LWP out of those that have had events. */ @@ -2992,8 +3129,9 @@ linux_nat_filter_event (int lwpid, int status) if (WIFSTOPPED (status) && lp->must_set_ptrace_flags) { struct inferior *inf = find_inferior_pid (ptid_get_pid (lp->ptid)); + int options = linux_nat_ptrace_options (inf->attach_flag); - linux_enable_event_reporting (ptid_get_lwp (lp->ptid), inf->attach_flag); + linux_enable_event_reporting (ptid_get_lwp (lp->ptid), options); lp->must_set_ptrace_flags = 0; } @@ -3057,12 +3195,14 @@ linux_nat_filter_event (int lwpid, int status) } } - gdb_assert (lp->resumed); - + /* Note that even if the leader was ptrace-stopped, it can still + exit, if e.g., some other thread brings down the whole + process (calls `exit'). So don't assert that the lwp is + resumed. */ if (debug_linux_nat) fprintf_unfiltered (gdb_stdlog, - "Process %ld exited\n", - ptid_get_lwp (lp->ptid)); + "Process %ld exited (resumed=%d)\n", + ptid_get_lwp (lp->ptid), lp->resumed); /* This was the last lwp in the process. Since events are serialized to GDB core, we may not be able report this one @@ -3106,28 +3246,28 @@ linux_nat_filter_event (int lwpid, int status) if (lp->signalled && WIFSTOPPED (status) && WSTOPSIG (status) == SIGSTOP) { - if (debug_linux_nat) - fprintf_unfiltered (gdb_stdlog, - "LLW: Delayed SIGSTOP caught for %s.\n", - target_pid_to_str (lp->ptid)); - lp->signalled = 0; - if (lp->last_resume_kind != resume_stop) + if (lp->last_resume_kind == resume_stop) + { + if (debug_linux_nat) + fprintf_unfiltered (gdb_stdlog, + "LLW: resume_stop SIGSTOP caught for %s.\n", + target_pid_to_str (lp->ptid)); + } + else { - /* This is a delayed SIGSTOP. */ + /* This is a delayed SIGSTOP. Filter out the event. */ - linux_resume_one_lwp (lp, lp->step, GDB_SIGNAL_0); if (debug_linux_nat) fprintf_unfiltered (gdb_stdlog, - "LLW: %s %s, 0, 0 (discard SIGSTOP)\n", + "LLW: %s %s, 0, 0 (discard delayed SIGSTOP)\n", lp->step ? "PTRACE_SINGLESTEP" : "PTRACE_CONT", target_pid_to_str (lp->ptid)); + linux_resume_one_lwp (lp, lp->step, GDB_SIGNAL_0); gdb_assert (lp->resumed); - - /* Discard the event. */ return NULL; } } @@ -3541,24 +3681,39 @@ resume_stopped_resumed_lwps (struct lwp_info *lp, void *data) { struct regcache *regcache = get_thread_regcache (lp->ptid); struct gdbarch *gdbarch = get_regcache_arch (regcache); - CORE_ADDR pc = regcache_read_pc (regcache); - /* Don't bother if there's a breakpoint at PC that we'd hit - immediately, and we're not waiting for this LWP. */ - if (!ptid_match (lp->ptid, *wait_ptid_p)) + TRY { - if (breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc)) - return 0; - } + CORE_ADDR pc = regcache_read_pc (regcache); + int leave_stopped = 0; - if (debug_linux_nat) - fprintf_unfiltered (gdb_stdlog, - "RSRL: resuming stopped-resumed LWP %s at %s: step=%d\n", - target_pid_to_str (lp->ptid), - paddress (gdbarch, pc), - lp->step); + /* Don't bother if there's a breakpoint at PC that we'd hit + immediately, and we're not waiting for this LWP. */ + if (!ptid_match (lp->ptid, *wait_ptid_p)) + { + if (breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc)) + leave_stopped = 1; + } - linux_resume_one_lwp (lp, lp->step, GDB_SIGNAL_0); + if (!leave_stopped) + { + if (debug_linux_nat) + fprintf_unfiltered (gdb_stdlog, + "RSRL: resuming stopped-resumed LWP %s at " + "%s: step=%d\n", + target_pid_to_str (lp->ptid), + paddress (gdbarch, pc), + lp->step); + + linux_resume_one_lwp_throw (lp, lp->step, GDB_SIGNAL_0); + } + } + CATCH (ex, RETURN_MASK_ERROR) + { + if (!check_ptrace_stopped_lwp_gone (lp)) + throw_exception (ex); + } + END_CATCH } return 0; @@ -3905,6 +4060,23 @@ linux_nat_thread_alive (struct target_ops *ops, ptid_t ptid) return linux_thread_alive (ptid); } +/* Implement the to_update_thread_list target method for this + target. */ + +static void +linux_nat_update_thread_list (struct target_ops *ops) +{ + if (linux_supports_traceclone ()) + { + /* With support for clone events, we add/delete threads from the + list as clone/exit events are processed, so just try deleting + exited threads still in the thread list. */ + delete_exited_threads (); + } + else + prune_threads (); +} + static char * linux_nat_pid_to_str (struct target_ops *ops, ptid_t ptid) { @@ -3964,15 +4136,7 @@ linux_nat_thread_name (struct target_ops *self, struct thread_info *thr) static char * linux_child_pid_to_exec_file (struct target_ops *self, int pid) { - static char buf[PATH_MAX]; - char name[PATH_MAX]; - - xsnprintf (name, PATH_MAX, "/proc/%d/exe", pid); - memset (buf, 0, PATH_MAX); - if (readlink (name, buf, PATH_MAX - 1) <= 0) - strcpy (buf, name); - - return buf; + return linux_proc_pid_to_exec_file (pid); } /* Implement the to_xfer_partial interface for memory reads using the /proc @@ -4503,10 +4667,6 @@ linux_nat_terminal_ours (struct target_ops *self) async_terminal_is_ours = 1; } -static void (*async_client_callback) (enum inferior_event_type event_type, - void *context); -static void *async_client_context; - /* SIGCHLD handler that serves two purposes: In non-stop/async mode, so we notice when any child changes state, and notify the event-loop; it allows us to use sigsuspend in linux_nat_wait_1 @@ -4534,7 +4694,7 @@ sigchld_handler (int signo) static void handle_target_event (int error, gdb_client_data client_data) { - (*async_client_callback) (INF_REG_EVENT, async_client_context); + inferior_event_handler (INF_REG_EVENT, NULL); } /* Create/destroy the target events pipe. Returns previous state. */ @@ -4578,15 +4738,10 @@ linux_async_pipe (int enable) /* target_async implementation. */ static void -linux_nat_async (struct target_ops *ops, - void (*callback) (enum inferior_event_type event_type, - void *context), - void *context) +linux_nat_async (struct target_ops *ops, int enable) { - if (callback != NULL) + if (enable) { - async_client_callback = callback; - async_client_context = context; if (!linux_async_pipe (1)) { add_file_handler (linux_nat_event_pipe[0], @@ -4598,8 +4753,6 @@ linux_nat_async (struct target_ops *ops, } else { - async_client_callback = callback; - async_client_context = context; delete_file_handler (linux_nat_event_pipe[0]); linux_async_pipe (0); } @@ -4667,7 +4820,7 @@ linux_nat_close (struct target_ops *self) { /* Unregister from the event loop. */ if (linux_nat_is_async_p (self)) - linux_nat_async (self, NULL, NULL); + linux_nat_async (self, 0); if (linux_ops->to_close) linux_ops->to_close (linux_ops); @@ -4719,6 +4872,104 @@ linux_nat_core_of_thread (struct target_ops *ops, ptid_t ptid) return -1; } +/* Implementation of to_filesystem_is_local. */ + +static int +linux_nat_filesystem_is_local (struct target_ops *ops) +{ + struct inferior *inf = current_inferior (); + + if (inf->fake_pid_p || inf->pid == 0) + return 1; + + return linux_ns_same (inf->pid, LINUX_NS_MNT); +} + +/* Convert the INF argument passed to a to_fileio_* method + to a process ID suitable for passing to its corresponding + linux_mntns_* function. If INF is non-NULL then the + caller is requesting the filesystem seen by INF. If INF + is NULL then the caller is requesting the filesystem seen + by the GDB. We fall back to GDB's filesystem in the case + that INF is non-NULL but its PID is unknown. */ + +static pid_t +linux_nat_fileio_pid_of (struct inferior *inf) +{ + if (inf == NULL || inf->fake_pid_p || inf->pid == 0) + return getpid (); + else + return inf->pid; +} + +/* Implementation of to_fileio_open. */ + +static int +linux_nat_fileio_open (struct target_ops *self, + struct inferior *inf, const char *filename, + int flags, int mode, int *target_errno) +{ + int nat_flags; + mode_t nat_mode; + int fd; + + if (fileio_to_host_openflags (flags, &nat_flags) == -1 + || fileio_to_host_mode (mode, &nat_mode) == -1) + { + *target_errno = FILEIO_EINVAL; + return -1; + } + + fd = linux_mntns_open_cloexec (linux_nat_fileio_pid_of (inf), + filename, nat_flags, nat_mode); + if (fd == -1) + *target_errno = host_to_fileio_error (errno); + + return fd; +} + +/* Implementation of to_fileio_readlink. */ + +static char * +linux_nat_fileio_readlink (struct target_ops *self, + struct inferior *inf, const char *filename, + int *target_errno) +{ + char buf[PATH_MAX]; + int len; + char *ret; + + len = linux_mntns_readlink (linux_nat_fileio_pid_of (inf), + filename, buf, sizeof (buf)); + if (len < 0) + { + *target_errno = host_to_fileio_error (errno); + return NULL; + } + + ret = xmalloc (len + 1); + memcpy (ret, buf, len); + ret[len] = '\0'; + return ret; +} + +/* Implementation of to_fileio_unlink. */ + +static int +linux_nat_fileio_unlink (struct target_ops *self, + struct inferior *inf, const char *filename, + int *target_errno) +{ + int ret; + + ret = linux_mntns_unlink (linux_nat_fileio_pid_of (inf), + filename); + if (ret == -1) + *target_errno = host_to_fileio_error (errno); + + return ret; +} + void linux_nat_add_target (struct target_ops *t) { @@ -4740,6 +4991,7 @@ linux_nat_add_target (struct target_ops *t) t->to_kill = linux_nat_kill; t->to_mourn_inferior = linux_nat_mourn_inferior; t->to_thread_alive = linux_nat_thread_alive; + t->to_update_thread_list = linux_nat_update_thread_list; t->to_pid_to_str = linux_nat_pid_to_str; t->to_thread_name = linux_nat_thread_name; t->to_has_thread_control = tc_schedlock; @@ -4771,6 +5023,11 @@ linux_nat_add_target (struct target_ops *t) t->to_core_of_thread = linux_nat_core_of_thread; + t->to_filesystem_is_local = linux_nat_filesystem_is_local; + t->to_fileio_open = linux_nat_fileio_open; + t->to_fileio_readlink = linux_nat_fileio_readlink; + t->to_fileio_unlink = linux_nat_fileio_unlink; + /* We don't change the stratum; this target will sit at process_stratum and thread_db will set at thread_stratum. This is a little strange, since this is a multi-threaded-capable @@ -4864,6 +5121,15 @@ linux_nat_get_siginfo (ptid_t ptid, siginfo_t *siginfo) return 1; } +/* See nat/linux-nat.h. */ + +ptid_t +current_lwp_ptid (void) +{ + gdb_assert (ptid_lwp_p (inferior_ptid)); + return inferior_ptid; +} + /* Provide a prototype to silence -Wmissing-prototypes. */ extern initialize_file_ftype _initialize_linux_nat; @@ -4879,6 +5145,15 @@ Enables printf debugging output."), show_debug_linux_nat, &setdebuglist, &showdebuglist); + add_setshow_boolean_cmd ("linux-namespaces", class_maintenance, + &debug_linux_namespaces, _("\ +Set debugging of GNU/Linux namespaces module."), _("\ +Show debugging of GNU/Linux namespaces module."), _("\ +Enables printf debugging output."), + NULL, + NULL, + &setdebuglist, &showdebuglist); + /* Save this mask as the default. */ sigprocmask (SIG_SETMASK, NULL, &normal_mask); @@ -4895,14 +5170,6 @@ Enables printf debugging output."), sigdelset (&suspend_mask, SIGCHLD); sigemptyset (&blocked_mask); - - /* Do not enable PTRACE_O_TRACEEXIT until GDB is more prepared to - support read-only process state. */ - linux_ptrace_set_additional_flags (PTRACE_O_TRACESYSGOOD - | PTRACE_O_TRACEVFORKDONE - | PTRACE_O_TRACEVFORK - | PTRACE_O_TRACEFORK - | PTRACE_O_TRACEEXEC); }