#include <sys/wait.h>
#include <stdio.h>
#include <sys/param.h>
-#include <sys/dir.h>
#include <sys/ptrace.h>
-#include <sys/user.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <fcntl.h>
static int must_set_ptrace_flags;
+/* This flag is true iff we've just created or attached to a new inferior
+ but it has not stopped yet. As soon as it does, we need to call the
+ low target's arch_setup callback. */
+static int new_inferior;
+
static void linux_resume_one_process (struct inferior_list_entry *entry,
int step, int signal, siginfo_t *info);
static void linux_resume (struct thread_resume *resume_info);
#define PTRACE_XFER_TYPE long
#ifdef HAVE_LINUX_REGSETS
-static int use_regsets_p = 1;
+static char *disabled_regsets;
+static int num_regsets;
#endif
#define pid_of(proc) ((proc)->head.id)
if (event == PTRACE_EVENT_CLONE)
{
unsigned long new_pid;
- int ret, status;
+ int ret, status = W_STOPCODE (SIGSTOP);
ptrace (PTRACE_GETEVENTMSG, inferior_pid, 0, &new_pid);
new_process = add_process (pid);
add_thread (pid, new_process, pid);
must_set_ptrace_flags = 1;
+ new_inferior = 1;
return pid;
}
if (ptrace (PTRACE_ATTACH, pid, 0, 0) != 0)
{
- fprintf (stderr, "Cannot attach to process %ld: %s (%d)\n", pid,
+ if (all_threads.head != NULL)
+ {
+ /* If we fail to attach to an LWP, just warn. */
+ fprintf (stderr, "Cannot attach to process %ld: %s (%d)\n", pid,
+ strerror (errno), errno);
+ fflush (stderr);
+ return;
+ }
+ else
+ /* If we fail to attach to a process, report an error. */
+ error ("Cannot attach to process %ld: %s (%d)\n", pid,
strerror (errno), errno);
- fflush (stderr);
-
- /* If we fail to attach to an LWP, just return. */
- if (all_threads.head == NULL)
- _exit (0177);
- return;
}
ptrace (PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACECLONE);
process = (struct process_info *) find_inferior_id (&all_processes, pid);
process->stop_expected = 0;
+ new_inferior = 1;
+
return 0;
}
/* Make sure it died. The loop is most likely unnecessary. */
wstat = linux_wait_for_event (thread);
} while (WIFSTOPPED (wstat));
+
+ clear_inferiors ();
+ free (all_processes.head);
+ all_processes.head = all_processes.tail = NULL;
}
static void
delete_all_breakpoints ();
for_each_inferior (&all_threads, linux_detach_one_process);
clear_inferiors ();
+ free (all_processes.head);
+ all_processes.head = all_processes.tail = NULL;
return 0;
}
(*childp)->last_status = *wstatp;
+ /* Architecture-specific setup after inferior is running.
+ This needs to happen after we have attached to the inferior
+ and it is stopped for the first time, but before we access
+ any inferior registers. */
+ if (new_inferior)
+ {
+ the_low_target.arch_setup ();
+#ifdef HAVE_LINUX_REGSETS
+ memset (disabled_regsets, 0, num_regsets);
+#endif
+ new_inferior = 0;
+ }
+
if (debug_threads
&& WIFSTOPPED (*wstatp))
{
goto error_exit;
}
}
- if (the_low_target.left_pad_xfer
- && register_size (regno) < sizeof (PTRACE_XFER_TYPE))
- supply_register (regno, (buf + sizeof (PTRACE_XFER_TYPE)
- - register_size (regno)));
+
+ if (the_low_target.supply_ptrace_register)
+ the_low_target.supply_ptrace_register (regno, buf);
else
supply_register (regno, buf);
& - sizeof (PTRACE_XFER_TYPE);
buf = alloca (size);
memset (buf, 0, size);
- if (the_low_target.left_pad_xfer
- && register_size (regno) < sizeof (PTRACE_XFER_TYPE))
- collect_register (regno, (buf + sizeof (PTRACE_XFER_TYPE)
- - register_size (regno)));
+
+ if (the_low_target.collect_ptrace_register)
+ the_low_target.collect_ptrace_register (regno, buf);
else
collect_register (regno, buf);
+
for (i = 0; i < size; i += sizeof (PTRACE_XFER_TYPE))
{
errno = 0;
void *buf;
int res;
- if (regset->size == 0)
+ if (regset->size == 0 || disabled_regsets[regset - target_regsets])
{
regset ++;
continue;
{
if (errno == EIO)
{
- /* If we get EIO on the first regset, do not try regsets again.
- If we get EIO on a later regset, disable that regset. */
- if (regset == target_regsets)
- {
- use_regsets_p = 0;
- return -1;
- }
- else
- {
- regset->size = 0;
- continue;
- }
+ /* If we get EIO on a regset, do not try it again for
+ this process. */
+ disabled_regsets[regset - target_regsets] = 1;
+ continue;
}
else
{
void *buf;
int res;
- if (regset->size == 0)
+ if (regset->size == 0 || disabled_regsets[regset - target_regsets])
{
regset ++;
continue;
{
if (errno == EIO)
{
- /* If we get EIO on the first regset, do not try regsets again.
- If we get EIO on a later regset, disable that regset. */
- if (regset == target_regsets)
- {
- use_regsets_p = 0;
- return -1;
- }
- else
- {
- regset->size = 0;
- continue;
- }
+ /* If we get EIO on a regset, do not try it again for
+ this process. */
+ disabled_regsets[regset - target_regsets] = 1;
+ continue;
}
else
{
linux_fetch_registers (int regno)
{
#ifdef HAVE_LINUX_REGSETS
- if (use_regsets_p)
- {
- if (regsets_fetch_inferior_registers () == 0)
- return;
- }
+ if (regsets_fetch_inferior_registers () == 0)
+ return;
#endif
#ifdef HAVE_LINUX_USRREGS
usr_fetch_inferior_registers (regno);
linux_store_registers (int regno)
{
#ifdef HAVE_LINUX_REGSETS
- if (use_regsets_p)
- {
- if (regsets_store_inferior_registers () == 0)
- return;
- }
+ if (regsets_store_inferior_registers () == 0)
+ return;
#endif
#ifdef HAVE_LINUX_USRREGS
usr_store_inferior_registers (regno);
= (((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1) / sizeof (PTRACE_XFER_TYPE);
/* Allocate buffer of that many longwords. */
register PTRACE_XFER_TYPE *buffer = (PTRACE_XFER_TYPE *) alloca (count * sizeof (PTRACE_XFER_TYPE));
- extern int errno;
if (debug_threads)
{
}
#endif
-static const char *
-linux_arch_string (void)
-{
- return the_low_target.arch_string;
-}
-
static struct target_ops linux_target_ops = {
linux_create_inferior,
linux_attach,
#else
NULL,
#endif
- linux_arch_string,
+ NULL,
+ hostio_last_error_from_errno,
};
static void
set_target_ops (&linux_target_ops);
set_breakpoint_data (the_low_target.breakpoint,
the_low_target.breakpoint_len);
- init_registers ();
linux_init_signals ();
linux_test_for_tracefork ();
+#ifdef HAVE_LINUX_REGSETS
+ for (num_regsets = 0; target_regsets[num_regsets].size >= 0; num_regsets++)
+ ;
+ disabled_regsets = malloc (num_regsets);
+#endif
}