/* GNU/Linux native-dependent code common to multiple platforms.
- Copyright (C) 2001-2013 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 "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 "agent.h"
#include "tracepoint.h"
#include "exceptions.h"
-#include "linux-ptrace.h"
#include "buffer.h"
#include "target-descriptions.h"
#include "filestuff.h"
+#include "objfiles.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 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;
+
+/* The saved to_close method, inherited from inf-ptrace.c.
+ Called by our to_close. */
+static void (*super_close) (struct target_ops *);
static unsigned int debug_linux_nat;
static void
};
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
be awakened anyway. */
}
-static void linux_nat_async (void (*callback)
- (enum inferior_event_type event_type,
- void *context),
- void *context);
static int kill_lwp (int lwpid, int signo);
static int stop_callback (struct lwp_info *lp, void *data);
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;
-
- linux_supports_tracefork_flag = 0;
- linux_supports_tracevforkdone_flag = 0;
-
- ret = ptrace (PTRACE_SETOPTIONS, original_pid, 0, PTRACE_O_TRACEFORK);
- if (ret != 0)
- return;
-
- child_pid = fork ();
- if (child_pid == -1)
- perror_with_name (("fork"));
-
- if (child_pid == 0)
- linux_tracefork_child ();
-
- ret = my_waitpid (child_pid, &status, 0);
- if (ret == -1)
- perror_with_name (("waitpid"));
- else if (ret != child_pid)
- error (_("linux_test_for_tracefork: waitpid: unexpected result %d."), ret);
- if (! WIFSTOPPED (status))
- error (_("linux_test_for_tracefork: waitpid: unexpected status %d."),
- status);
-
- ret = ptrace (PTRACE_SETOPTIONS, child_pid, 0, PTRACE_O_TRACEFORK);
- if (ret != 0)
- {
- ret = ptrace (PTRACE_KILL, child_pid, 0, 0);
- if (ret != 0)
- {
- warning (_("linux_test_for_tracefork: failed to kill child"));
- return;
- }
-
- ret = my_waitpid (child_pid, &status, 0);
- if (ret != child_pid)
- warning (_("linux_test_for_tracefork: failed "
- "to wait for killed child"));
- else if (!WIFSIGNALED (status))
- warning (_("linux_test_for_tracefork: unexpected "
- "wait status 0x%x from killed child"), status);
-
- return;
- }
-
- /* Check whether PTRACE_O_TRACEVFORKDONE is available. */
- ret = ptrace (PTRACE_SETOPTIONS, child_pid, 0,
- PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORKDONE);
- linux_supports_tracevforkdone_flag = (ret == 0);
-
- ret = ptrace (PTRACE_CONT, child_pid, 0, 0);
- if (ret != 0)
- warning (_("linux_test_for_tracefork: failed to resume child"));
-
- ret = my_waitpid (child_pid, &status, 0);
-
- if (ret == child_pid && WIFSTOPPED (status)
- && status >> 16 == PTRACE_EVENT_FORK)
- {
- second_pid = 0;
- ret = ptrace (PTRACE_GETEVENTMSG, child_pid, 0, &second_pid);
- if (ret == 0 && second_pid != 0)
- {
- int second_status;
-
- linux_supports_tracefork_flag = 1;
- my_waitpid (second_pid, &second_status, 0);
- ret = ptrace (PTRACE_KILL, second_pid, 0, 0);
- if (ret != 0)
- warning (_("linux_test_for_tracefork: "
- "failed to kill second child"));
- my_waitpid (second_pid, &status, 0);
- }
- }
- else
- warning (_("linux_test_for_tracefork: unexpected result from waitpid "
- "(%d, status 0x%x)"), ret, status);
-
- do
- {
- ret = ptrace (PTRACE_KILL, child_pid, 0, 0);
- if (ret != 0)
- warning ("linux_test_for_tracefork: failed to kill child");
- my_waitpid (child_pid, &status, 0);
- }
- while (WIFSTOPPED (status));
-}
-
-/* Determine if PTRACE_O_TRACESYSGOOD can be used to follow syscalls.
-
- We try to enable syscall tracing on ORIGINAL_PID. If this fails,
- we know that the feature is not available. This may change the tracing
- options for ORIGINAL_PID, but we'll be setting them shortly anyway. */
-
-static void
-linux_test_for_tracesysgood (int original_pid)
-{
- int ret;
-
- linux_supports_tracesysgood_flag = 0;
-
- ret = ptrace (PTRACE_SETOPTIONS, original_pid, 0, PTRACE_O_TRACESYSGOOD);
- if (ret != 0)
- return;
-
- linux_supports_tracesysgood_flag = 1;
-}
-
-/* Determine wether we support PTRACE_O_TRACESYSGOOD option available.
- This function also sets linux_supports_tracesysgood_flag. */
-
-static int
-linux_supports_tracesysgood (int pid)
-{
- if (linux_supports_tracesysgood_flag == -1)
- linux_test_for_tracesysgood (pid);
- return linux_supports_tracesysgood_flag;
-}
-
-/* Return non-zero iff we have tracefork functionality available.
- This function also sets linux_supports_tracefork_flag. */
-
-static int
-linux_supports_tracefork (int pid)
-{
- if (linux_supports_tracefork_flag == -1)
- linux_test_for_tracefork (pid);
- return linux_supports_tracefork_flag;
-}
-
-static int
-linux_supports_tracevforkdone (int pid)
-{
- if (linux_supports_tracefork_flag == -1)
- linux_test_for_tracefork (pid);
- return linux_supports_tracevforkdone_flag;
-}
+/* 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_child_post_attach (struct target_ops *self, int pid)
{
- linux_enable_event_reporting (pid_to_ptid (pid));
- linux_enable_tracesysgood (pid_to_ptid (pid));
- linux_ptrace_init_warnings ();
+ linux_init_ptrace (pid);
}
static void
-linux_child_post_startup_inferior (ptid_t ptid)
+linux_child_post_startup_inferior (struct target_ops *self, ptid_t ptid)
{
- linux_enable_event_reporting (ptid);
- linux_enable_tracesysgood (ptid);
- linux_ptrace_init_warnings ();
+ linux_init_ptrace (ptid_get_pid (ptid));
}
/* Return the number of known LWPs in the tgid given by PID. */
}
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)
{
int has_vforked;
int parent_pid, child_pid;
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);
+ 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)
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,
\f
static int
-linux_child_insert_fork_catchpoint (int pid)
+linux_child_insert_fork_catchpoint (struct target_ops *self, int pid)
{
- return !linux_supports_tracefork (pid);
+ return !linux_supports_tracefork ();
}
static int
-linux_child_remove_fork_catchpoint (int pid)
+linux_child_remove_fork_catchpoint (struct target_ops *self, int pid)
{
return 0;
}
static int
-linux_child_insert_vfork_catchpoint (int pid)
+linux_child_insert_vfork_catchpoint (struct target_ops *self, int pid)
{
- return !linux_supports_tracefork (pid);
+ return !linux_supports_tracefork ();
}
static int
-linux_child_remove_vfork_catchpoint (int pid)
+linux_child_remove_vfork_catchpoint (struct target_ops *self, int pid)
{
return 0;
}
static int
-linux_child_insert_exec_catchpoint (int pid)
+linux_child_insert_exec_catchpoint (struct target_ops *self, int pid)
{
- return !linux_supports_tracefork (pid);
+ return !linux_supports_tracefork ();
}
static int
-linux_child_remove_exec_catchpoint (int pid)
+linux_child_remove_exec_catchpoint (struct target_ops *self, int pid)
{
return 0;
}
static int
-linux_child_set_syscall_catchpoint (int pid, int needed, int any_count,
+linux_child_set_syscall_catchpoint (struct target_ops *self,
+ 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
/* Update signals to pass to the inferior. */
static void
-linux_nat_pass_signals (int numsigs, unsigned char *pass_signals)
+linux_nat_pass_signals (struct target_ops *self,
+ int numsigs, unsigned char *pass_signals)
{
int signo;
/* Prototypes for local functions. */
static int stop_wait_callback (struct lwp_info *lp, void *data);
static int linux_thread_alive (ptid_t ptid);
-static char *linux_child_pid_to_exec_file (int pid);
+static char *linux_child_pid_to_exec_file (struct target_ops *self, int pid);
\f
-/* Convert wait status STATUS to a string. Used for printing debug
- messages only. */
-
-static char *
-status_to_str (int status)
-{
- static char buf[64];
-
- if (WIFSTOPPED (status))
- {
- if (WSTOPSIG (status) == SYSCALL_SIGTRAP)
- snprintf (buf, sizeof (buf), "%s (stopped at syscall)",
- strsignal (SIGTRAP));
- else
- snprintf (buf, sizeof (buf), "%s (stopped)",
- strsignal (WSTOPSIG (status)));
- }
- else if (WIFSIGNALED (status))
- snprintf (buf, sizeof (buf), "%s (terminated)",
- strsignal (WTERMSIG (status)));
- else
- snprintf (buf, sizeof (buf), "%d (exited)", WEXITSTATUS (status));
-
- return buf;
-}
/* Destroy and free LP. */
{
struct lwp_info *lp;
- gdb_assert (is_lwp (ptid));
+ gdb_assert (ptid_lwp_p (ptid));
lp = (struct lwp_info *) xmalloc (sizeof (struct lwp_info));
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;
{
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))
struct lwp_info *lp;
int lwpid;
- gdb_assert (is_lwp (ptid));
+ 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,
lp->status = status;
}
- target_post_attach (GET_LWP (lp->ptid));
+ target_post_attach (ptid_get_lwp (lp->ptid));
if (debug_linux_nat)
{
#endif /* HAVE_PERSONALITY */
/* Make sure we report all signals during startup. */
- linux_nat_pass_signals (0, NULL);
+ linux_nat_pass_signals (ops, 0, NULL);
linux_ops->to_create_inferior (ops, exec_file, allargs, env, from_tty);
volatile struct gdb_exception ex;
/* Make sure we report all signals during attach. */
- linux_nat_pass_signals (0, NULL);
+ linux_nat_pass_signals (ops, 0, NULL);
TRY_CATCH (ex, RETURN_MASK_ERROR)
{
make_cleanup (xfree, message);
buffer_init (&buffer);
- linux_ptrace_attach_warnings (pid, &buffer);
+ linux_ptrace_attach_fail_reason (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);
+ if (*buffer_s != '\0')
+ throw_error (ex.error, "warning: %s\n%s", buffer_s, message);
+ else
+ throw_error (ex.error, "%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. */
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;
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);
"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);
/* Don't unregister from the event loop, as there may be other
inferiors running. */
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",
{
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 (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)),
+ pid_to_ptid (ptid_get_lwp (lp->ptid)),
step, signo);
lp->stopped = 0;
lp->step = step;
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);
"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)),
+ 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;
}
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'
"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;
{
/* 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),
"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)),
+ 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
- = xstrdup (linux_child_pid_to_exec_file (pid));
+ = xstrdup (linux_child_pid_to_exec_file (NULL, pid));
return 0;
}
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)
{
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,
old_chain = save_inferior_ptid ();
inferior_ptid = lp->ptid;
- lp->stopped_by_watchpoint = linux_ops->to_stopped_by_watchpoint ();
+ lp->stopped_by_watchpoint = linux_ops->to_stopped_by_watchpoint (linux_ops);
if (lp->stopped_by_watchpoint)
{
/* See save_sigtrap. */
static int
-linux_nat_stopped_by_watchpoint (void)
+linux_nat_stopped_by_watchpoint (struct target_ops *ops)
{
struct lwp_info *lp = find_lwp_pid (inferior_ptid);
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) "
struct gdbarch *gdbarch = get_regcache_arch (regcache);
CORE_ADDR pc;
- pc = regcache_read_pc (regcache) - gdbarch_decr_pc_after_break (gdbarch);
+ pc = regcache_read_pc (regcache) - target_decr_pc_after_break (gdbarch);
if (breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc))
{
if (debug_linux_nat)
target_pid_to_str (lp->ptid));
/* Back up the PC if necessary. */
- if (gdbarch_decr_pc_after_break (gdbarch))
+ if (target_decr_pc_after_break (gdbarch))
regcache_write_pc (regcache, pc);
return 1;
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));
+ 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);
/* 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, GDB_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)),
+ 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,
{
/* 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_initial_lwp (inferior_ptid);
lp->resumed = 1;
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,
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,
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, GDB_SIGNAL_0);
lp->stopped = 0;
lp->stopped_by_watchpoint = 0;
/* 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 (PIDGET (last.value.related_pid));
+ linux_nat_forget_process (ptid_get_pid (last.value.related_pid));
}
if (forks_exist_p ())
}
}
-static LONGEST
+static enum target_xfer_status
linux_xfer_siginfo (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
+ const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
int pid;
siginfo_t siginfo;
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;
+ return TARGET_XFER_E_IO;
errno = 0;
ptrace (PTRACE_GETSIGINFO, pid, (PTRACE_TYPE_ARG3) 0, &siginfo);
if (errno != 0)
- return -1;
+ return TARGET_XFER_E_IO;
/* When GDB is built as a 64-bit application, ptrace writes into
SIGINFO an object with 64-bit layout. Since debugging a 32-bit
errno = 0;
ptrace (PTRACE_SETSIGINFO, pid, (PTRACE_TYPE_ARG3) 0, &siginfo);
if (errno != 0)
- return -1;
+ return TARGET_XFER_E_IO;
}
- return len;
+ *xfered_len = len;
+ return TARGET_XFER_OK;
}
-static LONGEST
+static enum target_xfer_status
linux_nat_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
- ULONGEST offset, LONGEST len)
+ ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
struct cleanup *old_chain;
- LONGEST xfer;
+ enum target_xfer_status xfer;
if (object == TARGET_OBJECT_SIGNAL_INFO)
return linux_xfer_siginfo (ops, object, annex, readbuf, writebuf,
- offset, len);
+ offset, len, xfered_len);
/* The target is connected but no live inferior is selected. Pass
this request down to a lower stratum (e.g., the executable
file). */
if (object == TARGET_OBJECT_MEMORY && ptid_equal (inferior_ptid, null_ptid))
- return 0;
+ return TARGET_XFER_EOF;
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);
+ offset, len, xfered_len);
do_cleanups (old_chain);
return xfer;
{
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;
}
}
static char *
-linux_nat_thread_name (struct thread_info *thr)
+linux_nat_thread_name (struct target_ops *self, struct thread_info *thr)
{
int pid = ptid_get_pid (thr->ptid);
long lwp = ptid_get_lwp (thr->ptid);
can be opened to get the symbols for the child process. */
static char *
-linux_child_pid_to_exec_file (int pid)
+linux_child_pid_to_exec_file (struct target_ops *self, int pid)
{
- char *name1, *name2;
+ static char buf[PATH_MAX];
+ char name[PATH_MAX];
- name1 = xmalloc (PATH_MAX);
- name2 = xmalloc (PATH_MAX);
- make_cleanup (xfree, name1);
- make_cleanup (xfree, name2);
- memset (name2, 0, 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);
- sprintf (name1, "/proc/%d/exe", pid);
- if (readlink (name1, name2, PATH_MAX - 1) > 0)
- return name2;
- else
- return name1;
+ return buf;
}
/* Records the thread's register state for the corefile note
section for a corefile, and returns it in a malloc buffer. */
static char *
-linux_nat_make_corefile_notes (bfd *obfd, int *note_size)
+linux_nat_make_corefile_notes (struct target_ops *self,
+ bfd *obfd, int *note_size)
{
/* FIXME: uweigand/2011-10-06: Once all GNU/Linux architectures have been
converted to gdbarch_core_regset_sections, this function can go away. */
can be much more efficient than banging away at PTRACE_PEEKTEXT,
but it doesn't support writes. */
-static LONGEST
+static enum target_xfer_status
linux_proc_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
- ULONGEST offset, LONGEST len)
+ ULONGEST offset, LONGEST len, ULONGEST *xfered_len)
{
LONGEST ret;
int fd;
/* Don't bother for one word. */
if (len < 3 * sizeof (long))
- return 0;
+ return TARGET_XFER_EOF;
/* 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));
+ 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;
+ return TARGET_XFER_EOF;
/* If pread64 is available, use it. It's faster if the kernel
supports it (only one syscall), and it's 64-bit safe even on
ret = len;
close (fd);
- return ret;
+
+ if (ret == 0)
+ return TARGET_XFER_EOF;
+ else
+ {
+ *xfered_len = ret;
+ return TARGET_XFER_OK;
+ }
}
/* Enumerate spufs IDs for process PID. */
static LONGEST
-spu_enumerate_spu_ids (int pid, gdb_byte *buf, ULONGEST offset, LONGEST len)
+spu_enumerate_spu_ids (int pid, gdb_byte *buf, ULONGEST offset, ULONGEST len)
{
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
LONGEST pos = 0;
/* Implement the to_xfer_partial interface for the TARGET_OBJECT_SPU
object type, using the /proc file system. */
-static LONGEST
+
+static enum target_xfer_status
linux_proc_xfer_spu (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
- ULONGEST offset, LONGEST len)
+ ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
char buf[128];
int fd = 0;
int ret = -1;
- int pid = PIDGET (inferior_ptid);
+ int pid = ptid_get_pid (inferior_ptid);
if (!annex)
{
if (!readbuf)
- return -1;
+ return TARGET_XFER_E_IO;
else
- return spu_enumerate_spu_ids (pid, readbuf, offset, len);
+ {
+ LONGEST l = spu_enumerate_spu_ids (pid, readbuf, offset, len);
+
+ if (l < 0)
+ return TARGET_XFER_E_IO;
+ else if (l == 0)
+ return TARGET_XFER_EOF;
+ else
+ {
+ *xfered_len = (ULONGEST) l;
+ return TARGET_XFER_OK;
+ }
+ }
}
xsnprintf (buf, sizeof buf, "/proc/%d/fd/%s", pid, annex);
fd = gdb_open_cloexec (buf, writebuf? O_WRONLY : O_RDONLY, 0);
if (fd <= 0)
- return -1;
+ return TARGET_XFER_E_IO;
if (offset != 0
&& lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset)
{
close (fd);
- return 0;
+ return TARGET_XFER_EOF;
}
if (writebuf)
ret = read (fd, readbuf, (size_t) len);
close (fd);
- return ret;
+
+ if (ret < 0)
+ return TARGET_XFER_E_IO;
+ else if (ret == 0)
+ return TARGET_XFER_EOF;
+ else
+ {
+ *xfered_len = (ULONGEST) ret;
+ return TARGET_XFER_OK;
+ }
}
sigemptyset (pending);
sigemptyset (blocked);
sigemptyset (ignored);
- sprintf (fname, "/proc/%d/status", pid);
+ xsnprintf (fname, sizeof fname, "/proc/%d/status", pid);
procfile = gdb_fopen_cloexec (fname, "r");
if (procfile == NULL)
error (_("Could not open %s"), fname);
do_cleanups (cleanup);
}
-static LONGEST
+static enum target_xfer_status
linux_nat_xfer_osdata (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
+ const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
gdb_assert (object == TARGET_OBJECT_OSDATA);
- return linux_common_xfer_osdata (annex, readbuf, offset, len);
+ *xfered_len = linux_common_xfer_osdata (annex, readbuf, offset, len);
+ if (*xfered_len == 0)
+ return TARGET_XFER_EOF;
+ else
+ return TARGET_XFER_OK;
}
-static LONGEST
+static enum target_xfer_status
linux_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
+ const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
- LONGEST xfer;
+ enum target_xfer_status xfer;
if (object == TARGET_OBJECT_AUXV)
return memory_xfer_auxv (ops, object, annex, readbuf, writebuf,
- offset, len);
+ offset, len, xfered_len);
if (object == TARGET_OBJECT_OSDATA)
return linux_nat_xfer_osdata (ops, object, annex, readbuf, writebuf,
- offset, len);
+ offset, len, xfered_len);
if (object == TARGET_OBJECT_SPU)
return linux_proc_xfer_spu (ops, object, annex, readbuf, writebuf,
- offset, len);
+ offset, len, xfered_len);
/* GDB calculates all the addresses in possibly larget width of the address.
Address width needs to be masked before its final use - either by
}
xfer = linux_proc_xfer_partial (ops, object, annex, readbuf, writebuf,
- offset, len);
- if (xfer != 0)
+ offset, len, xfered_len);
+ if (xfer != TARGET_XFER_EOF)
return xfer;
return super_xfer_partial (ops, object, annex, readbuf, writebuf,
- offset, len);
+ offset, len, xfered_len);
}
static void
}
static VEC(static_tracepoint_marker_p) *
-linux_child_static_tracepoint_markers_by_strid (const char *strid)
+linux_child_static_tracepoint_markers_by_strid (struct target_ops *self,
+ const char *strid)
{
char s[IPA_CMD_BUF_SIZE];
struct cleanup *old_chain;
/* target_is_async_p implementation. */
static int
-linux_nat_is_async_p (void)
+linux_nat_is_async_p (struct target_ops *ops)
{
/* NOTE: palves 2008-03-21: We're only async when the user requests
it explicitly with the "set target-async" command.
/* target_can_async_p implementation. */
static int
-linux_nat_can_async_p (void)
+linux_nat_can_async_p (struct target_ops *ops)
{
/* NOTE: palves 2008-03-21: We're only async when the user requests
it explicitly with the "set target-async" command.
}
static int
-linux_nat_supports_non_stop (void)
+linux_nat_supports_non_stop (struct target_ops *self)
{
return 1;
}
int linux_multi_process = 1;
static int
-linux_nat_supports_multi_process (void)
+linux_nat_supports_multi_process (struct target_ops *self)
{
return linux_multi_process;
}
static int
-linux_nat_supports_disable_randomization (void)
+linux_nat_supports_disable_randomization (struct target_ops *self)
{
#ifdef HAVE_PERSONALITY
return 1;
/* target_terminal_inferior implementation. */
static void
-linux_nat_terminal_inferior (void)
+linux_nat_terminal_inferior (struct target_ops *self)
{
if (!target_is_async_p ())
{
/* Async mode is disabled. */
- terminal_inferior ();
+ child_terminal_inferior (self);
return;
}
- terminal_inferior ();
+ child_terminal_inferior (self);
/* Calls to target_terminal_*() are meant to be idempotent. */
if (!async_terminal_is_ours)
/* target_terminal_ours implementation. */
static void
-linux_nat_terminal_ours (void)
+linux_nat_terminal_ours (struct target_ops *self)
{
if (!target_is_async_p ())
{
/* Async mode is disabled. */
- terminal_ours ();
+ child_terminal_ours (self);
return;
}
/* GDB should never give the terminal to the inferior if the
inferior is running in the background (run&, continue&, etc.),
but claiming it sure should. */
- terminal_ours ();
+ child_terminal_ours (self);
if (async_terminal_is_ours)
return;
/* target_async implementation. */
static void
-linux_nat_async (void (*callback) (enum inferior_event_type event_type,
- void *context), void *context)
+linux_nat_async (struct target_ops *ops,
+ void (*callback) (enum inferior_event_type event_type,
+ void *context),
+ void *context)
{
if (callback != NULL)
{
}
static void
-linux_nat_stop (ptid_t ptid)
+linux_nat_stop (struct target_ops *self, ptid_t ptid)
{
if (non_stop)
iterate_over_lwps (ptid, linux_nat_stop_lwp, NULL);
else
- linux_ops->to_stop (ptid);
+ linux_ops->to_stop (linux_ops, ptid);
}
static void
-linux_nat_close (void)
+linux_nat_close (struct target_ops *self)
{
/* Unregister from the event loop. */
- if (linux_nat_is_async_p ())
- linux_nat_async (NULL, 0);
+ if (linux_nat_is_async_p (NULL))
+ linux_nat_async (NULL, NULL, 0);
if (linux_ops->to_close)
- linux_ops->to_close ();
+ linux_ops->to_close (linux_ops);
+
+ super_close (self);
}
/* 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);
t->to_async = linux_nat_async;
t->to_terminal_inferior = linux_nat_terminal_inferior;
t->to_terminal_ours = linux_nat_terminal_ours;
+
+ super_close = t->to_close;
t->to_close = linux_nat_close;
/* Methods for non-stop support. */
{
int pid;
- pid = GET_LWP (ptid);
+ pid = ptid_get_lwp (ptid);
if (pid == 0)
- pid = GET_PID (ptid);
+ pid = ptid_get_pid (ptid);
errno = 0;
ptrace (PTRACE_GETSIGINFO, pid, (PTRACE_TYPE_ARG3) 0, siginfo);
static int
get_signo (const char *name)
{
- struct minimal_symbol *ms;
+ struct bound_minimal_symbol ms;
int signo;
ms = lookup_minimal_symbol (name, NULL, NULL);
- if (ms == NULL)
+ if (ms.minsym == NULL)
return 0;
- if (target_read_memory (SYMBOL_VALUE_ADDRESS (ms), (gdb_byte *) &signo,
+ if (target_read_memory (BMSYMBOL_VALUE_ADDRESS (ms), (gdb_byte *) &signo,
sizeof (signo)) != 0)
return 0;