/* GNU/Linux native-dependent code common to multiple platforms.
- Copyright (C) 2001-2012 Free Software Foundation, Inc.
+ Copyright (C) 2001-2014 Free Software Foundation, Inc.
This file is part of GDB.
#include "defs.h"
#include "inferior.h"
#include "target.h"
-#include "gdb_string.h"
+#include "nat/linux-nat.h"
+#include "nat/linux-waitpid.h"
+#include <string.h>
#include "gdb_wait.h"
#include "gdb_assert.h"
#ifdef HAVE_TKILL_SYSCALL
#include "gdbcmd.h"
#include "regcache.h"
#include "regset.h"
+#include "inf-child.h"
#include "inf-ptrace.h"
#include "auxv.h"
-#include <sys/param.h> /* for MAXPATHLEN */
#include <sys/procfs.h> /* for elf_gregset etc. */
#include "elf-bfd.h" /* for elfcore_write_* */
#include "gregset.h" /* for gregset */
#include "gdbcore.h" /* for get_exec_file */
#include <ctype.h> /* for isdigit */
#include "gdbthread.h" /* for struct thread_info etc. */
-#include "gdb_stat.h" /* for struct stat */
+#include <sys/stat.h> /* for struct stat */
#include <fcntl.h> /* for O_RDONLY */
#include "inf-loop.h"
#include "event-loop.h"
#include "event-top.h"
#include <pwd.h>
#include <sys/types.h>
-#include "gdb_dirent.h"
+#include <dirent.h>
#include "xml-support.h"
#include "terminal.h"
#include <sys/vfs.h>
#include "symfile.h"
#include "agent.h"
#include "tracepoint.h"
+#include "exceptions.h"
+#include "linux-ptrace.h"
+#include "buffer.h"
+#include "target-descriptions.h"
+#include "filestuff.h"
#ifndef SPUFS_MAGIC
#define SPUFS_MAGIC 0x23c9b64e
#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;
/* The method to call, if any, when a new thread is attached. */
static void (*linux_nat_new_thread) (struct lwp_info *);
+/* The method to call, if any, when a new fork is attached. */
+static linux_nat_new_fork_ftype *linux_nat_new_fork;
+
+/* The method to call, if any, when a process is no longer
+ attached. */
+static linux_nat_forget_process_ftype *linux_nat_forget_process_hook;
+
/* Hook to call prior to resuming a thread. */
static void (*linux_nat_prepare_to_resume) (struct lwp_info *);
/* The method to call, if any, when the siginfo object needs to be
converted between the layout returned by ptrace, and the layout in
the architecture of the inferior. */
-static int (*linux_nat_siginfo_fixup) (struct siginfo *,
+static int (*linux_nat_siginfo_fixup) (siginfo_t *,
gdb_byte *,
int);
/* The saved to_xfer_partial method, inherited from inf-ptrace.c.
Called by our to_xfer_partial. */
-static LONGEST (*super_xfer_partial) (struct target_ops *,
- enum target_object,
- const char *, gdb_byte *,
- const gdb_byte *,
- ULONGEST, LONGEST);
+static target_xfer_partial_ftype *super_xfer_partial;
-static int debug_linux_nat;
+static unsigned int debug_linux_nat;
static void
show_debug_linux_nat (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
};
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
return 0;
}
-\f
-/* A helper function for linux_test_for_tracefork, called after fork (). */
-
-static void
-linux_tracefork_child (void)
-{
- ptrace (PTRACE_TRACEME, 0, 0, 0);
- kill (getpid (), SIGSTOP);
- fork ();
- _exit (0);
-}
-
-/* Wrapper function for waitpid which handles EINTR. */
-
-static int
-my_waitpid (int pid, int *statusp, int flags)
-{
- int ret;
-
- do
- {
- ret = waitpid (pid, statusp, flags);
- }
- while (ret == -1 && errno == EINTR);
-
- return ret;
-}
-
-/* Determine if PTRACE_O_TRACEFORK can be used to follow fork events.
-
- First, we try to enable fork tracing on ORIGINAL_PID. If this fails,
- we know that the feature is not available. This may change the tracing
- options for ORIGINAL_PID, but we'll be setting them shortly anyway.
-
- However, if it succeeds, we don't know for sure that the feature is
- available; old versions of PTRACE_SETOPTIONS ignored unknown options. We
- create a child process, attach to it, use PTRACE_SETOPTIONS to enable
- fork tracing, and let it fork. If the process exits, we assume that we
- can't use TRACEFORK; if we get the fork notification, and we can extract
- the new child's PID, then we assume that we can. */
-
-static void
-linux_test_for_tracefork (int original_pid)
-{
- int child_pid, ret, status;
- long second_pid;
- sigset_t prev_mask;
-
- /* We don't want those ptrace calls to be interrupted. */
- block_child_signals (&prev_mask);
-
- linux_supports_tracefork_flag = 0;
- linux_supports_tracevforkdone_flag = 0;
-
- ret = ptrace (PTRACE_SETOPTIONS, original_pid, 0, PTRACE_O_TRACEFORK);
- if (ret != 0)
- {
- restore_child_signals_mask (&prev_mask);
- 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"));
- restore_child_signals_mask (&prev_mask);
- 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);
-
- restore_child_signals_mask (&prev_mask);
- 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);
-
- 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);
-
- restore_child_signals_mask (&prev_mask);
-}
-
-/* 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;
- sigset_t prev_mask;
-
- /* We don't want those ptrace calls to be interrupted. */
- block_child_signals (&prev_mask);
-
- linux_supports_tracesysgood_flag = 0;
-
- ret = ptrace (PTRACE_SETOPTIONS, original_pid, 0, PTRACE_O_TRACESYSGOOD);
- if (ret != 0)
- goto out;
-
- linux_supports_tracesysgood_flag = 1;
-out:
- restore_child_signals_mask (&prev_mask);
-}
-
-/* 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;
-}
+/* Initialize ptrace warnings and check for supported ptrace
+ features given PID. */
static void
-linux_enable_tracesysgood (ptid_t ptid)
+linux_init_ptrace (pid_t pid)
{
- int pid = ptid_get_lwp (ptid);
-
- if (pid == 0)
- pid = ptid_get_pid (ptid);
-
- if (linux_supports_tracesysgood (pid) == 0)
- return;
-
- current_ptrace_options |= PTRACE_O_TRACESYSGOOD;
-
- ptrace (PTRACE_SETOPTIONS, pid, 0, current_ptrace_options);
-}
-
-\f
-void
-linux_enable_event_reporting (ptid_t ptid)
-{
- int pid = ptid_get_lwp (ptid);
-
- if (pid == 0)
- pid = ptid_get_pid (ptid);
-
- if (! linux_supports_tracefork (pid))
- return;
-
- current_ptrace_options |= PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK
- | PTRACE_O_TRACEEXEC | PTRACE_O_TRACECLONE;
-
- if (linux_supports_tracevforkdone (pid))
- current_ptrace_options |= PTRACE_O_TRACEVFORKDONE;
-
- /* Do not enable PTRACE_O_TRACEEXIT until GDB is more prepared to support
- read-only process state. */
-
- ptrace (PTRACE_SETOPTIONS, pid, 0, current_ptrace_options);
+ linux_enable_event_reporting (pid);
+ linux_ptrace_init_warnings ();
}
static void
linux_child_post_attach (int pid)
{
- linux_enable_event_reporting (pid_to_ptid (pid));
- linux_enable_tracesysgood (pid_to_ptid (pid));
+ linux_init_ptrace (pid);
}
static void
linux_child_post_startup_inferior (ptid_t ptid)
{
- linux_enable_event_reporting (ptid);
- linux_enable_tracesysgood (ptid);
+ linux_init_ptrace (ptid_get_pid (ptid));
}
/* Return the number of known LWPs in the tgid given by PID. */
}
static int
-linux_child_follow_fork (struct target_ops *ops, int follow_child)
+linux_child_follow_fork (struct target_ops *ops, int follow_child,
+ int detach_fork)
{
- sigset_t prev_mask;
int has_vforked;
int parent_pid, child_pid;
- block_child_signals (&prev_mask);
-
has_vforked = (inferior_thread ()->pending_follow.kind
== TARGET_WAITKIND_VFORKED);
parent_pid = ptid_get_lwp (inferior_ptid);
if (parent_pid == 0)
parent_pid = ptid_get_pid (inferior_ptid);
- child_pid = PIDGET (inferior_thread ()->pending_follow.value.related_pid);
-
- if (!detach_fork)
- linux_enable_event_reporting (pid_to_ptid (child_pid));
+ child_pid
+ = ptid_get_pid (inferior_thread ()->pending_follow.value.related_pid);
if (has_vforked
&& !non_stop /* Non-stop always resumes both branches. */
if (has_vforked)
{
/* keep breakpoints list in sync. */
- remove_breakpoints_pid (GET_PID (inferior_ptid));
+ remove_breakpoints_pid (ptid_get_pid (inferior_ptid));
}
if (info_verbose || debug_linux_nat)
child_lp->last_resume_kind = resume_stop;
make_cleanup (delete_lwp_cleanup, child_lp);
- /* CHILD_LP has new PID, therefore linux_nat_new_thread is not called for it.
- See i386_inferior_data_get for the Linux kernel specifics.
- Ensure linux_nat_prepare_to_resume will reset the hardware debug
- registers. It is done by the linux_nat_new_thread call, which is
- being skipped in add_lwp above for the first lwp of a pid. */
- gdb_assert (num_lwps (GET_PID (child_lp->ptid)) == 1);
- if (linux_nat_new_thread != NULL)
- linux_nat_new_thread (child_lp);
-
if (linux_nat_prepare_to_resume != NULL)
linux_nat_prepare_to_resume (child_lp);
ptrace (PTRACE_DETACH, child_pid, 0, 0);
parent_inf = current_inferior ();
child_inf->attach_flag = parent_inf->attach_flag;
copy_terminal_info (child_inf, parent_inf);
+ child_inf->gdbarch = parent_inf->gdbarch;
+ copy_inferior_target_desc_info (child_inf, parent_inf);
old_chain = save_inferior_ptid ();
save_current_program_space ();
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,
parent_inf = current_inferior ();
child_inf->attach_flag = parent_inf->attach_flag;
copy_terminal_info (child_inf, parent_inf);
+ child_inf->gdbarch = parent_inf->gdbarch;
+ copy_inferior_target_desc_info (child_inf, parent_inf);
parent_pspace = parent_inf->pspace;
check_for_thread_db ();
}
- restore_child_signals_mask (&prev_mask);
return 0;
}
static int
linux_child_insert_fork_catchpoint (int pid)
{
- return !linux_supports_tracefork (pid);
+ return !linux_supports_tracefork ();
}
static int
static int
linux_child_insert_vfork_catchpoint (int pid)
{
- return !linux_supports_tracefork (pid);
+ return !linux_supports_tracefork ();
}
static int
static int
linux_child_insert_exec_catchpoint (int pid)
{
- return !linux_supports_tracefork (pid);
+ return !linux_supports_tracefork ();
}
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
for (signo = 1; signo < NSIG; signo++)
{
- int target_signo = target_signal_from_host (signo);
+ int target_signo = gdb_signal_from_host (signo);
if (target_signo < numsigs && pass_signals[target_signo])
sigaddset (&pass_mask, signo);
}
}
}
-/* Add the LWP specified by PID to the list. Return a pointer to the
- structure describing the new LWP. The LWP should already be stopped
- (with an exception for the very first LWP). */
+/* Add the LWP specified by PTID to the list. PTID is the first LWP
+ in the process. Return a pointer to the structure describing the
+ new LWP.
+
+ This differs from add_lwp in that we don't let the arch specific
+ bits know about this new thread. Current clients of this callback
+ take the opportunity to install watchpoints in the new thread, and
+ we shouldn't do that for the first thread. If we're spawning a
+ child ("run"), the thread executes the shell wrapper first, and we
+ shouldn't touch it until it execs the program we want to debug.
+ For "attach", it'd be okay to call the callback, but it's not
+ necessary, because watchpoints can't yet have been inserted into
+ the inferior. */
static struct lwp_info *
-add_lwp (ptid_t ptid)
+add_initial_lwp (ptid_t ptid)
{
struct lwp_info *lp;
- gdb_assert (is_lwp (ptid));
+ gdb_assert (ptid_lwp_p (ptid));
lp = (struct lwp_info *) xmalloc (sizeof (struct lwp_info));
lp->next = lwp_list;
lwp_list = lp;
+ return lp;
+}
+
+/* Add the LWP specified by PID to the list. Return a pointer to the
+ structure describing the new LWP. The LWP should already be
+ stopped. */
+
+static struct lwp_info *
+add_lwp (ptid_t ptid)
+{
+ struct lwp_info *lp;
+
+ lp = add_initial_lwp (ptid);
+
/* Let the arch specific bits know about this new thread. Current
clients of this callback take the opportunity to install
- watchpoints in the new thread. Don't do this for the first
- thread though. If we're spawning a child ("run"), the thread
- executes the shell wrapper first, and we shouldn't touch it until
- it execs the program we want to debug. For "attach", it'd be
- okay to call the callback, but it's not necessary, because
- watchpoints can't yet have been inserted into the inferior. */
- if (num_lwps (GET_PID (ptid)) > 1 && linux_nat_new_thread != NULL)
+ watchpoints in the new thread. We don't do this for the first
+ thread though. See add_initial_lwp. */
+ if (linux_nat_new_thread != NULL)
linux_nat_new_thread (lp);
return lp;
struct lwp_info *lp;
int lwp;
- if (is_lwp (ptid))
- lwp = GET_LWP (ptid);
+ if (ptid_lwp_p (ptid))
+ lwp = ptid_get_lwp (ptid);
else
- lwp = GET_PID (ptid);
+ lwp = ptid_get_pid (ptid);
for (lp = lwp_list; lp; lp = lp->next)
- if (lwp == GET_LWP (lp->ptid))
+ if (lwp == ptid_get_lwp (lp->ptid))
return lp;
return NULL;
return NULL;
}
-/* Iterate like iterate_over_lwps does except when forking-off a child call
- CALLBACK with CALLBACK_DATA specifically only for that new child PID. */
-
-void
-linux_nat_iterate_watchpoint_lwps
- (linux_nat_iterate_watchpoint_lwps_ftype callback, void *callback_data)
-{
- int inferior_pid = ptid_get_pid (inferior_ptid);
- struct inferior *inf = current_inferior ();
-
- if (inf->pid == inferior_pid)
- {
- /* Iterate all the threads of the current inferior. Without specifying
- INFERIOR_PID it would iterate all threads of all inferiors, which is
- inappropriate for watchpoints. */
-
- iterate_over_lwps (pid_to_ptid (inferior_pid), callback, callback_data);
- }
- else
- {
- /* Detaching a new child PID temporarily present in INFERIOR_PID. */
-
- struct lwp_info *child_lp;
- struct cleanup *old_chain;
- pid_t child_pid = GET_PID (inferior_ptid);
- ptid_t child_ptid = ptid_build (child_pid, child_pid, 0);
-
- gdb_assert (!is_lwp (inferior_ptid));
- gdb_assert (find_lwp_pid (child_ptid) == NULL);
- child_lp = add_lwp (child_ptid);
- child_lp->stopped = 1;
- child_lp->last_resume_kind = resume_stop;
- old_chain = make_cleanup (delete_lwp_cleanup, child_lp);
-
- callback (child_lp, callback_data);
-
- do_cleanups (old_chain);
- }
-}
-
/* Update our internal state when changing from one checkpoint to
another indicated by NEW_PTID. We can only switch single-threaded
applications, so we only create one new LWP, and the previous list
{
struct lwp_info *lp;
- purge_lwp_list (GET_PID (inferior_ptid));
+ purge_lwp_list (ptid_get_pid (inferior_ptid));
lp = add_lwp (new_ptid);
lp->stopped = 1;
linux_nat_post_attach_wait (ptid_t ptid, int first, int *cloned,
int *signalled)
{
- pid_t new_pid, pid = GET_LWP (ptid);
+ pid_t new_pid, pid = ptid_get_lwp (ptid);
int status;
if (linux_proc_pid_is_stopped (pid))
lin_lwp_attach_lwp (ptid_t ptid)
{
struct lwp_info *lp;
- sigset_t prev_mask;
int lwpid;
- gdb_assert (is_lwp (ptid));
-
- block_child_signals (&prev_mask);
+ gdb_assert (ptid_lwp_p (ptid));
lp = find_lwp_pid (ptid);
- lwpid = GET_LWP (ptid);
+ lwpid = ptid_get_lwp (ptid);
/* We assume that we're already attached to any LWP that has an id
equal to the overall process id, and to any LWP that is already
and we've had PID wraparound since we last tried to stop all threads,
this assumption might be wrong; fortunately, this is very unlikely
to happen. */
- if (lwpid != GET_PID (ptid) && lp == NULL)
+ if (lwpid != ptid_get_pid (ptid) && lp == NULL)
{
int status, cloned = 0, signalled = 0;
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,
/* We've already seen this thread stop, but we
haven't seen the PTRACE_EVENT_CLONE extended
event yet. */
- restore_child_signals_mask (&prev_mask);
return 0;
}
else
{
if (WIFSTOPPED (status))
add_to_pid_list (&stopped_pids, lwpid, status);
-
- restore_child_signals_mask (&prev_mask);
return 1;
}
}
to create them. */
warning (_("Can't attach %s: %s"), target_pid_to_str (ptid),
safe_strerror (errno));
- restore_child_signals_mask (&prev_mask);
return -1;
}
status = linux_nat_post_attach_wait (ptid, 0, &cloned, &signalled);
if (!WIFSTOPPED (status))
- {
- restore_child_signals_mask (&prev_mask);
- return 1;
- }
+ return 1;
lp = add_lwp (ptid);
lp->stopped = 1;
lp->status = status;
}
- target_post_attach (GET_LWP (lp->ptid));
+ target_post_attach (ptid_get_lwp (lp->ptid));
if (debug_linux_nat)
{
}
lp->last_resume_kind = resume_stop;
- restore_child_signals_mask (&prev_mask);
return 0;
}
struct lwp_info *lp;
int status;
ptid_t ptid;
+ volatile struct gdb_exception ex;
/* Make sure we report all signals during attach. */
linux_nat_pass_signals (0, NULL);
- linux_ops->to_attach (ops, args, from_tty);
+ TRY_CATCH (ex, RETURN_MASK_ERROR)
+ {
+ linux_ops->to_attach (ops, args, from_tty);
+ }
+ if (ex.reason < 0)
+ {
+ pid_t pid = parse_pid_to_attach (args);
+ struct buffer buffer;
+ char *message, *buffer_s;
+
+ message = xstrdup (ex.message);
+ make_cleanup (xfree, message);
+
+ buffer_init (&buffer);
+ linux_ptrace_attach_warnings (pid, &buffer);
+
+ buffer_grow_str0 (&buffer, "");
+ buffer_s = buffer_finish (&buffer);
+ make_cleanup (xfree, buffer_s);
+
+ throw_error (ex.error, "%s%s", buffer_s, message);
+ }
/* The ptrace base target adds the main thread with (pid,0,0)
format. Decorate it with lwp info. */
- ptid = BUILD_LWP (GET_PID (inferior_ptid), GET_PID (inferior_ptid));
+ ptid = ptid_build (ptid_get_pid (inferior_ptid),
+ ptid_get_pid (inferior_ptid),
+ 0);
thread_change_ptid (inferior_ptid, ptid);
/* Add the initial process as the first LWP to the list. */
- lp = add_lwp (ptid);
+ lp = add_initial_lwp (ptid);
status = linux_nat_post_attach_wait (lp->ptid, 1, &lp->cloned,
&lp->signalled);
}
else if (WIFSIGNALED (status))
{
- enum target_signal signo;
+ enum gdb_signal signo;
target_terminal_ours ();
target_mourn_inferior ();
- signo = target_signal_from_host (WTERMSIG (status));
+ signo = gdb_signal_from_host (WTERMSIG (status));
error (_("Unable to attach: program terminated with signal "
"%s, %s."),
- target_signal_to_name (signo),
- target_signal_to_string (signo));
+ gdb_signal_to_name (signo),
+ gdb_signal_to_string (signo));
}
internal_error (__FILE__, __LINE__,
_("unexpected status %d for PID %ld"),
- status, (long) GET_LWP (ptid));
+ status, (long) ptid_get_lwp (ptid));
}
lp->stopped = 1;
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
"LNA: waitpid %ld, saving status %s\n",
- (long) GET_PID (lp->ptid), status_to_str (status));
+ (long) ptid_get_pid (lp->ptid), status_to_str (status));
lp->status = status;
static int
get_pending_status (struct lwp_info *lp, int *status)
{
- enum target_signal signo = TARGET_SIGNAL_0;
+ enum gdb_signal signo = GDB_SIGNAL_0;
/* If we paused threads momentarily, we may have stored pending
events in lp->status or lp->waitstatus (see stop_wait_callback),
stop_signal make sense as a real signal to pass to the inferior.
Some catchpoint related events, like
TARGET_WAITKIND_(V)FORK|EXEC|SYSCALL, have their stop_signal set
- to TARGET_SIGNAL_SIGTRAP when the catchpoint triggers. But,
+ to GDB_SIGNAL_SIGTRAP when the catchpoint triggers. But,
those traps are debug API (ptrace in our case) related and
induced; the inferior wouldn't see them if it wasn't being
traced. Hence, we should never pass them to the inferior, even
this is really a corner case. */
if (lp->waitstatus.kind != TARGET_WAITKIND_IGNORE)
- signo = TARGET_SIGNAL_0; /* a pending ptrace event, not a real signal. */
+ signo = GDB_SIGNAL_0; /* a pending ptrace event, not a real signal. */
else if (lp->status)
- signo = target_signal_from_host (WSTOPSIG (lp->status));
+ signo = gdb_signal_from_host (WSTOPSIG (lp->status));
else if (non_stop && !is_executing (lp->ptid))
{
struct thread_info *tp = find_thread_ptid (lp->ptid);
get_last_target_status (&last_ptid, &last);
- if (GET_LWP (lp->ptid) == GET_LWP (last_ptid))
+ if (ptid_get_lwp (lp->ptid) == ptid_get_lwp (last_ptid))
{
struct thread_info *tp = find_thread_ptid (lp->ptid);
*status = 0;
- if (signo == TARGET_SIGNAL_0)
+ if (signo == GDB_SIGNAL_0)
{
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
"GPT: lwp %s had signal %s, "
"but it is in no pass state\n",
target_pid_to_str (lp->ptid),
- target_signal_to_string (signo));
+ gdb_signal_to_string (signo));
}
else
{
- *status = W_STOPCODE (target_signal_to_host (signo));
+ *status = W_STOPCODE (gdb_signal_to_host (signo));
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
"GPT: lwp %s has pending signal %s\n",
target_pid_to_str (lp->ptid),
- target_signal_to_string (signo));
+ gdb_signal_to_string (signo));
}
return 0;
"DC: Sending SIGCONT to %s\n",
target_pid_to_str (lp->ptid));
- kill_lwp (GET_LWP (lp->ptid), SIGCONT);
+ kill_lwp (ptid_get_lwp (lp->ptid), SIGCONT);
lp->signalled = 0;
}
/* We don't actually detach from the LWP that has an id equal to the
overall process id just yet. */
- if (GET_LWP (lp->ptid) != GET_PID (lp->ptid))
+ if (ptid_get_lwp (lp->ptid) != ptid_get_pid (lp->ptid))
{
int status = 0;
if (linux_nat_prepare_to_resume != NULL)
linux_nat_prepare_to_resume (lp);
errno = 0;
- if (ptrace (PTRACE_DETACH, GET_LWP (lp->ptid), 0,
+ if (ptrace (PTRACE_DETACH, ptid_get_lwp (lp->ptid), 0,
WSTOPSIG (status)) < 0)
error (_("Can't detach %s: %s"), target_pid_to_str (lp->ptid),
safe_strerror (errno));
}
static void
-linux_nat_detach (struct target_ops *ops, char *args, int from_tty)
+linux_nat_detach (struct target_ops *ops, const char *args, int from_tty)
{
int pid;
int status;
struct lwp_info *main_lwp;
- pid = GET_PID (inferior_ptid);
+ pid = ptid_get_pid (inferior_ptid);
- if (target_can_async_p ())
- linux_nat_async (NULL, 0);
+ /* Don't unregister from the event loop, as there may be other
+ inferiors running. */
/* Stop all threads before detaching. ptrace requires that the
thread is stopped to sucessfully detach. */
iterate_over_lwps (pid_to_ptid (pid), detach_callback, NULL);
/* Only the initial process should be left right now. */
- gdb_assert (num_lwps (GET_PID (inferior_ptid)) == 1);
+ gdb_assert (num_lwps (ptid_get_pid (inferior_ptid)) == 1);
main_lwp = find_lwp_pid (pid_to_ptid (pid));
&& get_pending_status (main_lwp, &status) != -1
&& WIFSTOPPED (status))
{
+ char *tem;
+
/* Put the signal number in ARGS so that inf_ptrace_detach will
pass it along with PTRACE_DETACH. */
- args = alloca (8);
- sprintf (args, "%d", (int) WSTOPSIG (status));
+ tem = alloca (8);
+ xsnprintf (tem, 8, "%d", (int) WSTOPSIG (status));
+ args = tem;
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
"LND: Sending signal %s to %s\n",
the current fork, and context-switch to the first
available. */
linux_fork_detach (args, from_tty);
-
- if (non_stop && target_can_async_p ())
- target_async (inferior_event_handler, 0);
}
else
linux_ops->to_detach (ops, args, from_tty);
/* Resume LP. */
static void
-resume_lwp (struct lwp_info *lp, int step)
+resume_lwp (struct lwp_info *lp, int step, enum gdb_signal signo)
{
if (lp->stopped)
{
- struct inferior *inf = find_inferior_pid (GET_PID (lp->ptid));
+ struct inferior *inf = find_inferior_pid (ptid_get_pid (lp->ptid));
if (inf->vfork_child != NULL)
{
{
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
- "RC: PTRACE_CONT %s, 0, 0 (resuming sibling)\n",
- target_pid_to_str (lp->ptid));
+ "RC: Resuming sibling %s, %s, %s\n",
+ target_pid_to_str (lp->ptid),
+ (signo != GDB_SIGNAL_0
+ ? strsignal (gdb_signal_to_host (signo))
+ : "0"),
+ step ? "step" : "resume");
if (linux_nat_prepare_to_resume != NULL)
linux_nat_prepare_to_resume (lp);
linux_ops->to_resume (linux_ops,
- pid_to_ptid (GET_LWP (lp->ptid)),
- step, TARGET_SIGNAL_0);
+ pid_to_ptid (ptid_get_lwp (lp->ptid)),
+ step, signo);
lp->stopped = 0;
lp->step = step;
- memset (&lp->siginfo, 0, sizeof (lp->siginfo));
lp->stopped_by_watchpoint = 0;
}
else
}
}
+/* Resume LWP, with the last stop signal, if it is in pass state. */
+
static int
-resume_callback (struct lwp_info *lp, void *data)
+linux_nat_resume_callback (struct lwp_info *lp, void *data)
{
- resume_lwp (lp, 0);
+ enum gdb_signal signo = GDB_SIGNAL_0;
+
+ if (lp->stopped)
+ {
+ struct thread_info *thread;
+
+ thread = find_thread_ptid (lp->ptid);
+ if (thread != NULL)
+ {
+ if (signal_pass_state (thread->suspend.stop_signal))
+ signo = thread->suspend.stop_signal;
+ thread->suspend.stop_signal = GDB_SIGNAL_0;
+ }
+ }
+
+ resume_lwp (lp, 0, signo);
return 0;
}
static void
linux_nat_resume (struct target_ops *ops,
- ptid_t ptid, int step, enum target_signal signo)
+ ptid_t ptid, int step, enum gdb_signal signo)
{
- sigset_t prev_mask;
struct lwp_info *lp;
int resume_many;
"LLR: Preparing to %s %s, %s, inferior_ptid %s\n",
step ? "step" : "resume",
target_pid_to_str (ptid),
- (signo != TARGET_SIGNAL_0
- ? strsignal (target_signal_to_host (signo)) : "0"),
+ (signo != GDB_SIGNAL_0
+ ? strsignal (gdb_signal_to_host (signo)) : "0"),
target_pid_to_str (inferior_ptid));
- block_child_signals (&prev_mask);
-
/* A specific PTID means `step only this process id'. */
resume_many = (ptid_equal (minus_one_ptid, ptid)
|| ptid_is_pid (ptid));
/* FIXME: What should we do if we are supposed to continue
this thread with a signal? */
- gdb_assert (signo == TARGET_SIGNAL_0);
- signo = target_signal_from_host (WSTOPSIG (lp->status));
+ gdb_assert (signo == GDB_SIGNAL_0);
+ signo = gdb_signal_from_host (WSTOPSIG (lp->status));
lp->status = 0;
}
}
{
/* FIXME: What should we do if we are supposed to continue
this thread with a signal? */
- gdb_assert (signo == TARGET_SIGNAL_0);
+ gdb_assert (signo == GDB_SIGNAL_0);
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
"LLR: Short circuiting for status 0x%x\n",
lp->status);
- restore_child_signals_mask (&prev_mask);
if (target_can_async_p ())
{
target_async (inferior_event_handler, 0);
}
/* Mark LWP as not stopped to prevent it from being continued by
- resume_callback. */
+ linux_nat_resume_callback. */
lp->stopped = 0;
if (resume_many)
- iterate_over_lwps (ptid, resume_callback, NULL);
+ iterate_over_lwps (ptid, linux_nat_resume_callback, NULL);
/* Convert to something the lower layer understands. */
- ptid = pid_to_ptid (GET_LWP (lp->ptid));
+ ptid = pid_to_ptid (ptid_get_lwp (lp->ptid));
if (linux_nat_prepare_to_resume != NULL)
linux_nat_prepare_to_resume (lp);
linux_ops->to_resume (linux_ops, ptid, step, signo);
- memset (&lp->siginfo, 0, sizeof (lp->siginfo));
lp->stopped_by_watchpoint = 0;
if (debug_linux_nat)
"LLR: %s %s, %s (resume event thread)\n",
step ? "PTRACE_SINGLESTEP" : "PTRACE_CONT",
target_pid_to_str (ptid),
- (signo != TARGET_SIGNAL_0
- ? strsignal (target_signal_to_host (signo)) : "0"));
+ (signo != GDB_SIGNAL_0
+ ? strsignal (gdb_signal_to_host (signo)) : "0"));
- restore_child_signals_mask (&prev_mask);
if (target_can_async_p ())
target_async (inferior_event_handler, 0);
}
"for LWP %ld (stopping threads), "
"resuming with PTRACE_CONT for SIGSTOP\n",
syscall_number,
- GET_LWP (lp->ptid));
+ ptid_get_lwp (lp->ptid));
lp->syscall_state = TARGET_WAITKIND_IGNORE;
- ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
+ ptrace (PTRACE_CONT, ptid_get_lwp (lp->ptid), 0, 0);
return 1;
}
== TARGET_WAITKIND_SYSCALL_ENTRY
? "entry" : "return",
syscall_number,
- GET_LWP (lp->ptid));
+ ptid_get_lwp (lp->ptid));
return 0;
}
lp->syscall_state == TARGET_WAITKIND_SYSCALL_ENTRY
? "entry" : "return",
syscall_number,
- GET_LWP (lp->ptid));
+ ptid_get_lwp (lp->ptid));
}
else
{
"with no syscall catchpoints."
" %d for LWP %ld, ignoring\n",
syscall_number,
- GET_LWP (lp->ptid));
+ ptid_get_lwp (lp->ptid));
lp->syscall_state = TARGET_WAITKIND_IGNORE;
}
registers_changed ();
if (linux_nat_prepare_to_resume != NULL)
linux_nat_prepare_to_resume (lp);
- linux_ops->to_resume (linux_ops, pid_to_ptid (GET_LWP (lp->ptid)),
- lp->step, TARGET_SIGNAL_0);
+ linux_ops->to_resume (linux_ops, pid_to_ptid (ptid_get_lwp (lp->ptid)),
+ lp->step, GDB_SIGNAL_0);
return 1;
}
linux_handle_extended_wait (struct lwp_info *lp, int status,
int stopping)
{
- int pid = GET_LWP (lp->ptid);
+ int pid = ptid_get_lwp (lp->ptid);
struct target_waitstatus *ourstatus = &lp->waitstatus;
int event = status >> 16;
ourstatus->value.related_pid = ptid_build (new_pid, new_pid, 0);
+ if (event == PTRACE_EVENT_FORK || event == PTRACE_EVENT_VFORK)
+ {
+ /* The arch-specific native code may need to know about new
+ forks even if those end up never mapped to an
+ inferior. */
+ if (linux_nat_new_fork != NULL)
+ linux_nat_new_fork (lp, new_pid);
+ }
+
if (event == PTRACE_EVENT_FORK
- && linux_fork_checkpointing_p (GET_PID (lp->ptid)))
+ && linux_fork_checkpointing_p (ptid_get_pid (lp->ptid)))
{
/* Handle checkpointing by linux-fork.c here as a special
case. We don't want the follow-fork-mode or 'catch fork'
/* This won't actually modify the breakpoint list, but will
physically remove the breakpoints from the child. */
- detach_breakpoints (new_pid);
+ detach_breakpoints (ptid_build (new_pid, new_pid, 0));
/* Retain child fork in ptrace (stopped) state. */
if (!find_fork_pid (new_pid))
this fork. We're actually doing an infcall in
linux-fork.c. */
ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
- linux_enable_event_reporting (pid_to_ptid (new_pid));
/* Report the stop to the core. */
return 0;
"from LWP %d, new child is LWP %ld\n",
pid, new_pid);
- new_lp = add_lwp (BUILD_LWP (new_pid, GET_PID (lp->ptid)));
+ new_lp = add_lwp (ptid_build (ptid_get_pid (lp->ptid), new_pid, 0));
new_lp->cloned = 1;
new_lp->stopped = 1;
RT signal, it can only be queued once. We need to be
careful to not resume the LWP if we wanted it to
stop. In that case, we'll leave the SIGSTOP pending.
- It will later be reported as TARGET_SIGNAL_0. */
+ It will later be reported as GDB_SIGNAL_0. */
tp = find_thread_ptid (new_lp->ptid);
if (tp != NULL && tp->stop_requested)
new_lp->last_resume_kind = resume_stop;
{
/* We're not using thread_db. Add it to GDB's
list. */
- target_post_attach (GET_LWP (new_lp->ptid));
+ target_post_attach (ptid_get_lwp (new_lp->ptid));
add_thread (new_lp->ptid);
}
fprintf_unfiltered (gdb_stdlog,
"LHEW: waitpid of new LWP %ld, "
"saving status %s\n",
- (long) GET_LWP (new_lp->ptid),
+ (long) ptid_get_lwp (new_lp->ptid),
status_to_str (status));
new_lp->status = status;
}
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
"LHEW: resuming new LWP %ld\n",
- GET_LWP (new_lp->ptid));
+ ptid_get_lwp (new_lp->ptid));
if (linux_nat_prepare_to_resume != NULL)
linux_nat_prepare_to_resume (new_lp);
linux_ops->to_resume (linux_ops, pid_to_ptid (new_pid),
- 0, TARGET_SIGNAL_0);
+ 0, GDB_SIGNAL_0);
new_lp->stopped = 0;
}
}
"LHEW: resuming parent LWP %d\n", pid);
if (linux_nat_prepare_to_resume != NULL)
linux_nat_prepare_to_resume (lp);
- linux_ops->to_resume (linux_ops, pid_to_ptid (GET_LWP (lp->ptid)),
- 0, TARGET_SIGNAL_0);
+ linux_ops->to_resume (linux_ops,
+ pid_to_ptid (ptid_get_lwp (lp->ptid)),
+ 0, GDB_SIGNAL_0);
return 1;
}
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
"LHEW: Got exec event from LWP %ld\n",
- GET_LWP (lp->ptid));
+ ptid_get_lwp (lp->ptid));
ourstatus->kind = TARGET_WAITKIND_EXECD;
ourstatus->value.execd_pathname
fprintf_unfiltered (gdb_stdlog,
"LHEW: Got expected PTRACE_EVENT_"
"VFORK_DONE from LWP %ld: stopping\n",
- GET_LWP (lp->ptid));
+ ptid_get_lwp (lp->ptid));
ourstatus->kind = TARGET_WAITKIND_VFORK_DONE;
return 0;
fprintf_unfiltered (gdb_stdlog,
"LHEW: Got PTRACE_EVENT_VFORK_DONE "
"from LWP %ld: resuming\n",
- GET_LWP (lp->ptid));
- ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
+ ptid_get_lwp (lp->ptid));
+ ptrace (PTRACE_CONT, ptid_get_lwp (lp->ptid), 0, 0);
return 1;
}
/* If my_waitpid returns 0 it means the __WCLONE vs. non-__WCLONE kind
was right and we should just call sigsuspend. */
- pid = my_waitpid (GET_LWP (lp->ptid), &status, WNOHANG);
+ pid = my_waitpid (ptid_get_lwp (lp->ptid), &status, WNOHANG);
if (pid == -1 && errno == ECHILD)
- pid = my_waitpid (GET_LWP (lp->ptid), &status, __WCLONE | WNOHANG);
+ pid = my_waitpid (ptid_get_lwp (lp->ptid), &status, __WCLONE | WNOHANG);
if (pid == -1 && errno == ECHILD)
{
/* The thread has previously exited. We need to delete it
Therefore always use WNOHANG with sigsuspend - it is equivalent to
waiting waitpid but linux_proc_pid_is_zombie is safe this way. */
- if (GET_PID (lp->ptid) == GET_LWP (lp->ptid)
- && linux_proc_pid_is_zombie (GET_LWP (lp->ptid)))
+ if (ptid_get_pid (lp->ptid) == ptid_get_lwp (lp->ptid)
+ && linux_proc_pid_is_zombie (ptid_get_lwp (lp->ptid)))
{
thread_dead = 1;
if (debug_linux_nat)
if (!thread_dead)
{
- gdb_assert (pid == GET_LWP (lp->ptid));
+ gdb_assert (pid == ptid_get_lwp (lp->ptid));
if (debug_linux_nat)
{
return status;
}
-/* Save the most recent siginfo for LP. This is currently only called
- for SIGTRAP; some ports use the si_addr field for
- target_stopped_data_address. In the future, it may also be used to
- restore the siginfo of requeued signals. */
-
-static void
-save_siginfo (struct lwp_info *lp)
-{
- errno = 0;
- ptrace (PTRACE_GETSIGINFO, GET_LWP (lp->ptid),
- (PTRACE_TYPE_ARG3) 0, &lp->siginfo);
-
- if (errno != 0)
- memset (&lp->siginfo, 0, sizeof (lp->siginfo));
-}
-
/* Send a SIGSTOP to LP. */
static int
target_pid_to_str (lp->ptid));
}
errno = 0;
- ret = kill_lwp (GET_LWP (lp->ptid), SIGSTOP);
+ ret = kill_lwp (ptid_get_lwp (lp->ptid), SIGSTOP);
if (debug_linux_nat)
{
fprintf_unfiltered (gdb_stdlog,
if (!lp->ignore_sigint)
return;
- if (!linux_nat_has_pending_sigint (GET_LWP (lp->ptid)))
+ if (!linux_nat_has_pending_sigint (ptid_get_lwp (lp->ptid)))
{
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
static int
stop_wait_callback (struct lwp_info *lp, void *data)
{
- struct inferior *inf = find_inferior_pid (GET_PID (lp->ptid));
+ struct inferior *inf = find_inferior_pid (ptid_get_pid (lp->ptid));
/* If this is a vfork parent, bail out, it is not going to report
any SIGSTOP until the vfork is done with. */
lp->ignore_sigint = 0;
errno = 0;
- ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
+ ptrace (PTRACE_CONT, ptid_get_lwp (lp->ptid), 0, 0);
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
"PTRACE_CONT %s, 0, 0 (%s) "
if (WSTOPSIG (status) != SIGSTOP)
{
- if (linux_nat_status_is_event (status))
- {
- /* If a LWP other than the LWP that we're reporting an
- event for has hit a GDB breakpoint (as opposed to
- some random trap signal), then just arrange for it to
- hit it again later. We don't keep the SIGTRAP status
- and don't forward the SIGTRAP signal to the LWP. We
- will handle the current event, eventually we will
- resume all LWPs, and this one will get its breakpoint
- trap again.
-
- If we do not do this, then we run the risk that the
- user will delete or disable the breakpoint, but the
- thread will have already tripped on it. */
-
- /* Save the trap's siginfo in case we need it later. */
- save_siginfo (lp);
-
- save_sigtrap (lp);
-
- /* Now resume this LWP and get the SIGSTOP event. */
- errno = 0;
- ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
- if (debug_linux_nat)
- {
- fprintf_unfiltered (gdb_stdlog,
- "PTRACE_CONT %s, 0, 0 (%s)\n",
- target_pid_to_str (lp->ptid),
- errno ? safe_strerror (errno) : "OK");
-
- fprintf_unfiltered (gdb_stdlog,
- "SWC: Candidate SIGTRAP event in %s\n",
- target_pid_to_str (lp->ptid));
- }
- /* Hold this event/waitstatus while we check to see if
- there are any more (we still want to get that SIGSTOP). */
- stop_wait_callback (lp, NULL);
-
- /* Hold the SIGTRAP for handling by linux_nat_wait. If
- there's another event, throw it back into the
- queue. */
- if (lp->status)
- {
- if (debug_linux_nat)
- fprintf_unfiltered (gdb_stdlog,
- "SWC: kill %s, %s\n",
- target_pid_to_str (lp->ptid),
- status_to_str ((int) status));
- kill_lwp (GET_LWP (lp->ptid), WSTOPSIG (lp->status));
- }
+ /* The thread was stopped with a signal other than SIGSTOP. */
- /* Save the sigtrap event. */
- lp->status = status;
- return 0;
- }
- else
- {
- /* The thread was stopped with a signal other than
- SIGSTOP, and didn't accidentally trip a breakpoint. */
+ save_sigtrap (lp);
- if (debug_linux_nat)
- {
- fprintf_unfiltered (gdb_stdlog,
- "SWC: Pending event %s in %s\n",
- status_to_str ((int) status),
- target_pid_to_str (lp->ptid));
- }
- /* Now resume this LWP and get the SIGSTOP event. */
- errno = 0;
- ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
- if (debug_linux_nat)
- fprintf_unfiltered (gdb_stdlog,
- "SWC: PTRACE_CONT %s, 0, 0 (%s)\n",
- target_pid_to_str (lp->ptid),
- errno ? safe_strerror (errno) : "OK");
-
- /* Hold this event/waitstatus while we check to see if
- there are any more (we still want to get that SIGSTOP). */
- stop_wait_callback (lp, NULL);
-
- /* If the lp->status field is still empty, use it to
- hold this event. If not, then this event must be
- returned to the event queue of the LWP. */
- if (lp->status)
- {
- if (debug_linux_nat)
- {
- fprintf_unfiltered (gdb_stdlog,
- "SWC: kill %s, %s\n",
- target_pid_to_str (lp->ptid),
- status_to_str ((int) status));
- }
- kill_lwp (GET_LWP (lp->ptid), WSTOPSIG (status));
- }
- else
- lp->status = status;
- return 0;
- }
+ if (debug_linux_nat)
+ fprintf_unfiltered (gdb_stdlog,
+ "SWC: Pending event %s in %s\n",
+ status_to_str ((int) status),
+ target_pid_to_str (lp->ptid));
+
+ /* Save the sigtrap event. */
+ lp->status = status;
+ gdb_assert (!lp->stopped);
+ gdb_assert (lp->signalled);
+ lp->stopped = 1;
}
else
{
/* We caught the SIGSTOP that we intended to catch, so
there's no SIGSTOP pending. */
+
+ if (debug_linux_nat)
+ fprintf_unfiltered (gdb_stdlog,
+ "SWC: Delayed SIGSTOP caught for %s.\n",
+ target_pid_to_str (lp->ptid));
+
lp->stopped = 1;
+
+ /* Reset SIGNALLED only after the stop_wait_callback call
+ above as it does gdb_assert on SIGNALLED. */
lp->signalled = 0;
}
}
fprintf_unfiltered (gdb_stdlog,
"SARC: core wanted LWP %ld stopped "
"(leaving SIGSTOP pending)\n",
- GET_LWP (lp->ptid));
+ ptid_get_lwp (lp->ptid));
lp->status = W_STOPCODE (SIGSTOP);
}
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
"SARC: re-resuming LWP %ld\n",
- GET_LWP (lp->ptid));
- resume_lwp (lp, lp->step);
+ ptid_get_lwp (lp->ptid));
+ resume_lwp (lp, lp->step, GDB_SIGNAL_0);
}
else
{
fprintf_unfiltered (gdb_stdlog,
"SARC: not re-resuming LWP %ld "
"(has pending)\n",
- GET_LWP (lp->ptid));
+ ptid_get_lwp (lp->ptid));
if (new_pending_p)
*new_pending_p = 1;
}
"LLW: Re-adding thread group leader LWP %d.\n",
lwpid);
- lp = add_lwp (BUILD_LWP (lwpid, lwpid));
+ lp = add_lwp (ptid_build (lwpid, lwpid, 0));
lp->stopped = 1;
lp->resumed = 1;
add_thread (lp->ptid);
}
if (linux_nat_status_is_event (status))
- {
- /* Save the trap's siginfo in case we need it later. */
- save_siginfo (lp);
-
- save_sigtrap (lp);
- }
+ save_sigtrap (lp);
/* Check if the thread has exited. */
if ((WIFEXITED (status) || WIFSIGNALED (status))
- && num_lwps (GET_PID (lp->ptid)) > 1)
+ && num_lwps (ptid_get_pid (lp->ptid)) > 1)
{
/* If this is the main thread, we must stop all threads and verify
if they are still alive. This is because in the nptl thread model
should be ignored or whether it means the end of the debugged
application, regardless of which threading model is being
used. */
- if (GET_PID (lp->ptid) == GET_LWP (lp->ptid))
+ if (ptid_get_pid (lp->ptid) == ptid_get_lwp (lp->ptid))
{
lp->stopped = 1;
- iterate_over_lwps (pid_to_ptid (GET_PID (lp->ptid)),
+ iterate_over_lwps (pid_to_ptid (ptid_get_pid (lp->ptid)),
stop_and_resume_callback, new_pending_p);
}
"LLW: %s exited.\n",
target_pid_to_str (lp->ptid));
- if (num_lwps (GET_PID (lp->ptid)) > 1)
+ if (num_lwps (ptid_get_pid (lp->ptid)) > 1)
{
/* If there is at least one more LWP, then the exit signal
was not the end of the debugged application and should be
thread model, LWPs other than the main thread do not issue
signals when they exit so we must check whenever the thread has
stopped. A similar check is made in stop_wait_callback(). */
- if (num_lwps (GET_PID (lp->ptid)) > 1 && !linux_thread_alive (lp->ptid))
+ if (num_lwps (ptid_get_pid (lp->ptid)) > 1 && !linux_thread_alive (lp->ptid))
{
- ptid_t ptid = pid_to_ptid (GET_PID (lp->ptid));
+ ptid_t ptid = pid_to_ptid (ptid_get_pid (lp->ptid));
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
if (linux_nat_prepare_to_resume != NULL)
linux_nat_prepare_to_resume (lp);
- linux_ops->to_resume (linux_ops, pid_to_ptid (GET_LWP (lp->ptid)),
- lp->step, TARGET_SIGNAL_0);
+ linux_ops->to_resume (linux_ops,
+ pid_to_ptid (ptid_get_lwp (lp->ptid)),
+ lp->step, GDB_SIGNAL_0);
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
"LLW: %s %s, 0, 0 (discard SIGSTOP)\n",
registers_changed ();
if (linux_nat_prepare_to_resume != NULL)
linux_nat_prepare_to_resume (lp);
- linux_ops->to_resume (linux_ops, pid_to_ptid (GET_LWP (lp->ptid)),
- lp->step, TARGET_SIGNAL_0);
+ linux_ops->to_resume (linux_ops, pid_to_ptid (ptid_get_lwp (lp->ptid)),
+ lp->step, GDB_SIGNAL_0);
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
"LLW: %s %s, 0, 0 (discard SIGINT)\n",
{
/* Upgrade the main thread's ptid. */
thread_change_ptid (inferior_ptid,
- BUILD_LWP (GET_PID (inferior_ptid),
- GET_PID (inferior_ptid)));
+ ptid_build (ptid_get_pid (inferior_ptid),
+ ptid_get_pid (inferior_ptid), 0));
- lp = add_lwp (inferior_ptid);
+ lp = add_initial_lwp (inferior_ptid);
lp->resumed = 1;
}
- /* Make sure SIGCHLD is blocked. */
+ /* Make sure SIGCHLD is blocked until the sigsuspend below. */
block_child_signals (&prev_mask);
retry:
target_pid_to_str (lp->ptid));
}
}
- else if (is_lwp (ptid))
+ else if (ptid_lwp_p (ptid))
{
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
lp = NULL;
}
- if (lp && lp->signalled && lp->last_resume_kind != resume_stop)
- {
- /* A pending SIGSTOP may interfere with the normal stream of
- events. In a typical case where interference is a problem,
- we have a SIGSTOP signal pending for LWP A while
- single-stepping it, encounter an event in LWP B, and take the
- pending SIGSTOP while trying to stop LWP A. After processing
- the event in LWP B, LWP A is continued, and we'll never see
- the SIGTRAP associated with the last time we were
- single-stepping LWP A. */
-
- /* Resume the thread. It should halt immediately returning the
- pending SIGSTOP. */
- registers_changed ();
- if (linux_nat_prepare_to_resume != NULL)
- linux_nat_prepare_to_resume (lp);
- linux_ops->to_resume (linux_ops, pid_to_ptid (GET_LWP (lp->ptid)),
- lp->step, TARGET_SIGNAL_0);
- if (debug_linux_nat)
- fprintf_unfiltered (gdb_stdlog,
- "LLW: %s %s, 0, 0 (expect SIGSTOP)\n",
- lp->step ? "PTRACE_SINGLESTEP" : "PTRACE_CONT",
- target_pid_to_str (lp->ptid));
- lp->stopped = 0;
- gdb_assert (lp->resumed);
-
- /* Catch the pending SIGSTOP. */
- status = lp->status;
- lp->status = 0;
-
- stop_wait_callback (lp, NULL);
-
- /* If the lp->status field isn't empty, we caught another signal
- while flushing the SIGSTOP. Return it back to the event
- queue of the LWP, as we already have an event to handle. */
- if (lp->status)
- {
- if (debug_linux_nat)
- fprintf_unfiltered (gdb_stdlog,
- "LLW: kill %s, %s\n",
- target_pid_to_str (lp->ptid),
- status_to_str (lp->status));
- kill_lwp (GET_LWP (lp->ptid), WSTOPSIG (lp->status));
- }
-
- lp->status = status;
- }
-
if (!target_can_async_p ())
{
/* Causes SIGINT to be passed on to the attached process. */
if (WIFSTOPPED (status))
{
- enum target_signal signo = target_signal_from_host (WSTOPSIG (status));
+ enum gdb_signal signo = gdb_signal_from_host (WSTOPSIG (status));
/* When using hardware single-step, we need to report every signal.
Otherwise, signals in pass_mask may be short-circuited. */
registers_changed ();
if (linux_nat_prepare_to_resume != NULL)
linux_nat_prepare_to_resume (lp);
- linux_ops->to_resume (linux_ops, pid_to_ptid (GET_LWP (lp->ptid)),
+ linux_ops->to_resume (linux_ops,
+ pid_to_ptid (ptid_get_lwp (lp->ptid)),
lp->step, signo);
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
lp->step ?
"PTRACE_SINGLESTEP" : "PTRACE_CONT",
target_pid_to_str (lp->ptid),
- (signo != TARGET_SIGNAL_0
- ? strsignal (target_signal_to_host (signo))
+ (signo != GDB_SIGNAL_0
+ ? strsignal (gdb_signal_to_host (signo))
: "0"));
lp->stopped = 0;
goto retry;
/* Only do the below in all-stop, as we currently use SIGINT
to implement target_stop (see linux_nat_stop) in
non-stop. */
- if (signo == TARGET_SIGNAL_INT && signal_pass_state (signo) == 0)
+ if (signo == GDB_SIGNAL_INT && signal_pass_state (signo) == 0)
{
/* If ^C/BREAK is typed at the tty/console, SIGINT gets
forwarded to the entire process group, that is, all LWPs
/* A thread that has been requested to stop by GDB with
target_stop, and it stopped cleanly, so report as SIG0. The
use of SIGSTOP is an implementation detail. */
- ourstatus->value.sig = TARGET_SIGNAL_0;
+ ourstatus->value.sig = GDB_SIGNAL_0;
}
if (ourstatus->kind == TARGET_WAITKIND_EXITED
registers_changed ();
if (linux_nat_prepare_to_resume != NULL)
linux_nat_prepare_to_resume (lp);
- linux_ops->to_resume (linux_ops, pid_to_ptid (GET_LWP (lp->ptid)),
- lp->step, TARGET_SIGNAL_0);
+ linux_ops->to_resume (linux_ops, pid_to_ptid (ptid_get_lwp (lp->ptid)),
+ lp->step, GDB_SIGNAL_0);
lp->stopped = 0;
- memset (&lp->siginfo, 0, sizeof (lp->siginfo));
lp->stopped_by_watchpoint = 0;
}
ptid_t event_ptid;
if (debug_linux_nat)
- fprintf_unfiltered (gdb_stdlog,
- "linux_nat_wait: [%s]\n", target_pid_to_str (ptid));
+ {
+ char *options_string;
+
+ options_string = target_options_to_string (target_options);
+ fprintf_unfiltered (gdb_stdlog,
+ "linux_nat_wait: [%s], [%s]\n",
+ target_pid_to_str (ptid),
+ options_string);
+ xfree (options_string);
+ }
/* Flush the async file first. */
if (target_can_async_p ())
/* PTRACE_KILL may resume the inferior. Send SIGKILL first. */
errno = 0;
- kill (GET_LWP (lp->ptid), SIGKILL);
+ kill (ptid_get_lwp (lp->ptid), SIGKILL);
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
"KC: kill (SIGKILL) %s, 0, 0 (%s)\n",
/* Some kernels ignore even SIGKILL for processes under ptrace. */
errno = 0;
- ptrace (PTRACE_KILL, GET_LWP (lp->ptid), 0, 0);
+ ptrace (PTRACE_KILL, ptid_get_lwp (lp->ptid), 0, 0);
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
"KC: PTRACE_KILL %s, 0, 0 (%s)\n",
{
do
{
- pid = my_waitpid (GET_LWP (lp->ptid), NULL, __WCLONE);
+ pid = my_waitpid (ptid_get_lwp (lp->ptid), NULL, __WCLONE);
if (pid != (pid_t) -1)
{
if (debug_linux_nat)
kill_callback (lp, NULL);
}
}
- while (pid == GET_LWP (lp->ptid));
+ while (pid == ptid_get_lwp (lp->ptid));
gdb_assert (pid == -1 && errno == ECHILD);
}
do
{
- pid = my_waitpid (GET_LWP (lp->ptid), NULL, 0);
+ pid = my_waitpid (ptid_get_lwp (lp->ptid), NULL, 0);
if (pid != (pid_t) -1)
{
if (debug_linux_nat)
kill_callback (lp, NULL);
}
}
- while (pid == GET_LWP (lp->ptid));
+ while (pid == ptid_get_lwp (lp->ptid));
gdb_assert (pid == -1 && errno == ECHILD);
return 0;
if (last.kind == TARGET_WAITKIND_FORKED
|| last.kind == TARGET_WAITKIND_VFORKED)
{
- ptrace (PT_KILL, PIDGET (last.value.related_pid), 0, 0);
+ ptrace (PT_KILL, ptid_get_pid (last.value.related_pid), 0, 0);
wait (&status);
+
+ /* Let the arch-specific native code know this process is
+ gone. */
+ linux_nat_forget_process (ptid_get_pid (last.value.related_pid));
}
if (forks_exist_p ())
static void
linux_nat_mourn_inferior (struct target_ops *ops)
{
- purge_lwp_list (ptid_get_pid (inferior_ptid));
+ int pid = ptid_get_pid (inferior_ptid);
+
+ purge_lwp_list (pid);
if (! forks_exist_p ())
/* Normal case, no other forks available. */
there are other viable forks to debug. Delete the exiting
one and context-switch to the first available. */
linux_fork_mourn_inferior ();
+
+ /* Let the arch-specific native code know this process is gone. */
+ linux_nat_forget_process (pid);
}
/* Convert a native/host siginfo object, into/from the siginfo in the
layout of the inferiors' architecture. */
static void
-siginfo_fixup (struct siginfo *siginfo, gdb_byte *inf_siginfo, int direction)
+siginfo_fixup (siginfo_t *siginfo, gdb_byte *inf_siginfo, int direction)
{
int done = 0;
if (!done)
{
if (direction == 1)
- memcpy (siginfo, inf_siginfo, sizeof (struct siginfo));
+ memcpy (siginfo, inf_siginfo, sizeof (siginfo_t));
else
- memcpy (inf_siginfo, siginfo, sizeof (struct siginfo));
+ memcpy (inf_siginfo, siginfo, sizeof (siginfo_t));
}
}
const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
{
int pid;
- struct siginfo siginfo;
- gdb_byte inf_siginfo[sizeof (struct siginfo)];
+ siginfo_t siginfo;
+ gdb_byte inf_siginfo[sizeof (siginfo_t)];
gdb_assert (object == TARGET_OBJECT_SIGNAL_INFO);
gdb_assert (readbuf || writebuf);
- pid = GET_LWP (inferior_ptid);
+ pid = ptid_get_lwp (inferior_ptid);
if (pid == 0)
- pid = GET_PID (inferior_ptid);
+ pid = ptid_get_pid (inferior_ptid);
if (offset > sizeof (siginfo))
return -1;
old_chain = save_inferior_ptid ();
- if (is_lwp (inferior_ptid))
- inferior_ptid = pid_to_ptid (GET_LWP (inferior_ptid));
+ if (ptid_lwp_p (inferior_ptid))
+ inferior_ptid = pid_to_ptid (ptid_get_lwp (inferior_ptid));
xfer = linux_ops->to_xfer_partial (ops, object, annex, readbuf, writebuf,
offset, len);
{
int err, tmp_errno;
- gdb_assert (is_lwp (ptid));
+ gdb_assert (ptid_lwp_p (ptid));
/* Send signal 0 instead of anything ptrace, because ptracing a
running thread errors out claiming that the thread doesn't
exist. */
- err = kill_lwp (GET_LWP (ptid), 0);
+ err = kill_lwp (ptid_get_lwp (ptid), 0);
tmp_errno = errno;
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
{
static char buf[64];
- if (is_lwp (ptid)
- && (GET_PID (ptid) != GET_LWP (ptid)
- || num_lwps (GET_PID (ptid)) > 1))
+ if (ptid_lwp_p (ptid)
+ && (ptid_get_pid (ptid) != ptid_get_lwp (ptid)
+ || num_lwps (ptid_get_pid (ptid)) > 1))
{
- snprintf (buf, sizeof (buf), "LWP %ld", GET_LWP (ptid));
+ snprintf (buf, sizeof (buf), "LWP %ld", ptid_get_lwp (ptid));
return buf;
}
char *result = NULL;
snprintf (buf, sizeof (buf), FORMAT, pid, lwp);
- comm_file = fopen (buf, "r");
+ comm_file = gdb_fopen_cloexec (buf, "r");
if (comm_file)
{
/* Not exported by the kernel, so we define it here. */
{
char *name1, *name2;
- name1 = xmalloc (MAXPATHLEN);
- name2 = xmalloc (MAXPATHLEN);
+ name1 = xmalloc (PATH_MAX);
+ name2 = xmalloc (PATH_MAX);
make_cleanup (xfree, name1);
make_cleanup (xfree, name2);
- memset (name2, 0, MAXPATHLEN);
+ memset (name2, 0, PATH_MAX);
- sprintf (name1, "/proc/%d/exe", pid);
- if (readlink (name1, name2, MAXPATHLEN) > 0)
+ xsnprintf (name1, PATH_MAX, "/proc/%d/exe", pid);
+ if (readlink (name1, name2, PATH_MAX - 1) > 0)
return name2;
else
return name1;
linux_nat_collect_thread_registers (const struct regcache *regcache,
ptid_t ptid, bfd *obfd,
char *note_data, int *note_size,
- enum target_signal stop_signal)
+ enum gdb_signal stop_signal)
{
struct gdbarch *gdbarch = get_regcache_arch (regcache);
const struct regset *regset;
note_data = (char *) elfcore_write_prstatus
(obfd, note_data, note_size, ptid_get_lwp (ptid),
- target_signal_to_host (stop_signal), &gregs);
+ gdb_signal_to_host (stop_signal), &gregs);
if (core_regset_p
&& (regset = gdbarch_regset_from_core_section (gdbarch, ".reg2",
{
/* FIXME: uweigand/2011-10-06: Once all GNU/Linux architectures have been
converted to gdbarch_core_regset_sections, this function can go away. */
- return linux_make_corefile_notes (target_gdbarch, obfd, note_size,
+ return linux_make_corefile_notes (target_gdbarch (), obfd, note_size,
linux_nat_collect_thread_registers);
}
/* We could keep this file open and cache it - possibly one per
thread. That requires some juggling, but is even faster. */
- sprintf (filename, "/proc/%d/mem", PIDGET (inferior_ptid));
- fd = open (filename, O_RDONLY | O_LARGEFILE);
+ xsnprintf (filename, sizeof filename, "/proc/%d/mem",
+ ptid_get_pid (inferior_ptid));
+ fd = gdb_open_cloexec (filename, O_RDONLY | O_LARGEFILE, 0);
if (fd == -1)
return 0;
static LONGEST
spu_enumerate_spu_ids (int pid, gdb_byte *buf, ULONGEST offset, LONGEST len)
{
- enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
+ enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
LONGEST pos = 0;
LONGEST written = 0;
char path[128];
char buf[128];
int fd = 0;
int ret = -1;
- int pid = PIDGET (inferior_ptid);
+ int pid = ptid_get_pid (inferior_ptid);
if (!annex)
{
}
xsnprintf (buf, sizeof buf, "/proc/%d/fd/%s", pid, annex);
- fd = open (buf, writebuf? O_WRONLY : O_RDONLY);
+ fd = gdb_open_cloexec (buf, writebuf? O_WRONLY : O_RDONLY, 0);
if (fd <= 0)
return -1;
sigset_t *blocked, sigset_t *ignored)
{
FILE *procfile;
- char buffer[MAXPATHLEN], fname[MAXPATHLEN];
+ char buffer[PATH_MAX], fname[PATH_MAX];
struct cleanup *cleanup;
sigemptyset (pending);
sigemptyset (blocked);
sigemptyset (ignored);
- sprintf (fname, "/proc/%d/status", pid);
- procfile = fopen (fname, "r");
+ xsnprintf (fname, sizeof fname, "/proc/%d/status", pid);
+ procfile = gdb_fopen_cloexec (fname, "r");
if (procfile == NULL)
error (_("Could not open %s"), fname);
cleanup = make_cleanup_fclose (procfile);
- while (fgets (buffer, MAXPATHLEN, procfile) != NULL)
+ while (fgets (buffer, PATH_MAX, procfile) != NULL)
{
/* Normal queued signals are on the SigPnd line in the status
file. However, 2.6 kernels also have a "shared" pending
if (object == TARGET_OBJECT_MEMORY)
{
- int addr_bit = gdbarch_addr_bit (target_gdbarch);
+ int addr_bit = gdbarch_addr_bit (target_gdbarch ());
if (addr_bit < (sizeof (ULONGEST) * HOST_CHAR_BIT))
offset &= ((ULONGEST) 1 << addr_bit) - 1;
gdb_assert (arg != NULL);
/* Unpause all */
- target_resume (*ptid, 0, TARGET_SIGNAL_0);
+ target_resume (*ptid, 0, GDB_SIGNAL_0);
}
static VEC(static_tracepoint_marker_p) *
memcpy (s, "qTfSTM", sizeof ("qTfSTM"));
s[sizeof ("qTfSTM")] = 0;
- agent_run_command (pid, s);
+ agent_run_command (pid, s, strlen (s) + 1);
old_chain = make_cleanup (free_current_marker, &marker);
make_cleanup (cleanup_target_stop, &ptid);
memcpy (s, "qTsSTM", sizeof ("qTsSTM"));
s[sizeof ("qTsSTM")] = 0;
- agent_run_command (pid, s);
+ agent_run_command (pid, s, strlen (s) + 1);
p = s;
}
{
sigset_t prev_mask;
+ /* Block child signals while we create/destroy the pipe, as
+ their handler writes to it. */
block_child_signals (&prev_mask);
if (enable)
{
- if (pipe (linux_nat_event_pipe) == -1)
+ if (gdb_pipe_cloexec (linux_nat_event_pipe) == -1)
internal_error (__FILE__, __LINE__,
"creating event pipe failed.");
return;
}
-/* Stop an LWP, and push a TARGET_SIGNAL_0 stop status if no other
+/* Stop an LWP, and push a GDB_SIGNAL_0 stop status if no other
event came out. */
static int
{
if (!lwp->stopped)
{
- ptid_t ptid = lwp->ptid;
-
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
"LNSL: running -> suspending %s\n",
}
static void
-linux_nat_close (int quitting)
+linux_nat_close (void)
{
/* Unregister from the event loop. */
if (linux_nat_is_async_p ())
linux_nat_async (NULL, 0);
if (linux_ops->to_close)
- linux_ops->to_close (quitting);
+ linux_ops->to_close ();
}
/* When requests are passed down from the linux-nat layer to the
struct inferior *inf;
int pid;
- pid = GET_LWP (ptid);
- if (GET_LWP (ptid) == 0)
+ pid = ptid_get_lwp (ptid);
+ if (ptid_get_lwp (ptid) == 0)
{
/* An (lwpid,0,0) ptid. Look up the lwp object to get at the
tgid. */
lwp = find_lwp_pid (ptid);
- pid = GET_PID (lwp->ptid);
+ pid = ptid_get_pid (lwp->ptid);
}
else
{
/* A (pid,lwpid,0) ptid. */
- pid = GET_PID (ptid);
+ pid = ptid_get_pid (ptid);
}
inf = find_inferior_pid (pid);
linux_nat_new_thread = new_thread;
}
+/* See declaration in linux-nat.h. */
+
+void
+linux_nat_set_new_fork (struct target_ops *t,
+ linux_nat_new_fork_ftype *new_fork)
+{
+ /* Save the pointer. */
+ linux_nat_new_fork = new_fork;
+}
+
+/* See declaration in linux-nat.h. */
+
+void
+linux_nat_set_forget_process (struct target_ops *t,
+ linux_nat_forget_process_ftype *fn)
+{
+ /* Save the pointer. */
+ linux_nat_forget_process_hook = fn;
+}
+
+/* See declaration in linux-nat.h. */
+
+void
+linux_nat_forget_process (pid_t pid)
+{
+ if (linux_nat_forget_process_hook != NULL)
+ linux_nat_forget_process_hook (pid);
+}
+
/* Register a method that converts a siginfo object between the layout
that ptrace returns, and the layout in the architecture of the
inferior. */
void
linux_nat_set_siginfo_fixup (struct target_ops *t,
- int (*siginfo_fixup) (struct siginfo *,
+ int (*siginfo_fixup) (siginfo_t *,
gdb_byte *,
int))
{
linux_nat_prepare_to_resume = prepare_to_resume;
}
-/* Return the saved siginfo associated with PTID. */
-struct siginfo *
-linux_nat_get_siginfo (ptid_t ptid)
+/* See linux-nat.h. */
+
+int
+linux_nat_get_siginfo (ptid_t ptid, siginfo_t *siginfo)
{
- struct lwp_info *lp = find_lwp_pid (ptid);
+ int pid;
- gdb_assert (lp != NULL);
+ pid = ptid_get_lwp (ptid);
+ if (pid == 0)
+ pid = ptid_get_pid (ptid);
- return &lp->siginfo;
+ errno = 0;
+ ptrace (PTRACE_GETSIGINFO, pid, (PTRACE_TYPE_ARG3) 0, siginfo);
+ if (errno != 0)
+ {
+ memset (siginfo, 0, sizeof (*siginfo));
+ return 0;
+ }
+ return 1;
}
/* Provide a prototype to silence -Wmissing-prototypes. */
void
_initialize_linux_nat (void)
{
- add_setshow_zinteger_cmd ("lin-lwp", class_maintenance,
- &debug_linux_nat, _("\
+ add_setshow_zuinteger_cmd ("lin-lwp", class_maintenance,
+ &debug_linux_nat, _("\
Set debugging of GNU/Linux lwp module."), _("\
Show debugging of GNU/Linux lwp module."), _("\
Enables printf debugging output."),
- NULL,
- show_debug_linux_nat,
- &setdebuglist, &showdebuglist);
+ NULL,
+ show_debug_linux_nat,
+ &setdebuglist, &showdebuglist);
/* Save this mask as the default. */
sigprocmask (SIG_SETMASK, NULL, &normal_mask);