/* Low level interface to ptrace, for the remote server for GDB.
Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006
- Free Software Foundation, Inc.
+ 2006, 2007 Free Software Foundation, Inc.
This file is part of GDB.
# define PTRACE_SETSIGINFO 0x4203
#endif
+#ifdef __UCLIBC__
+#if !(defined(__UCLIBC_HAS_MMU__) || defined(__ARCH_HAS_MMU__))
+#define HAS_NOMMU
+#endif
+#endif
+
/* ``all_threads'' is keyed by the LWP ID - it should be the thread ID instead,
however. This requires changing the ID in place when we go from !using_threads
to using_threads, immediately.
static int use_regsets_p = 1;
#endif
-int debug_threads = 0;
-
#define pid_of(proc) ((proc)->head.id)
/* FIXME: Delete eventually. */
void *new_process;
int pid;
-#if defined(__UCLIBC__) && !defined(__UCLIBC_HAS_MMU__)
+#if defined(__UCLIBC__) && defined(HAS_NOMMU)
pid = vfork ();
#else
pid = fork ();
setpgid (0, 0);
- execv (program, allargs);
+ execvp (program, allargs);
fprintf (stderr, "Cannot exec %s: %s.\n", program,
strerror (errno));
linux_kill (void)
{
struct thread_info *thread = (struct thread_info *) all_threads.head;
- struct process_info *process = get_thread_process (thread);
+ struct process_info *process;
int wstat;
+ if (thread == NULL)
+ return;
+
for_each_inferior (&all_threads, linux_kill_one_process);
/* See the comment in linux_kill_one_process. We did not kill the first
thread in the list, so do so now. */
+ process = get_thread_process (thread);
do
{
ptrace (PTRACE_KILL, pid_of (process), 0, 0);
ptrace (PTRACE_DETACH, pid_of (process), 0, 0);
}
-static void
+static int
linux_detach (void)
{
for_each_inferior (&all_threads, linux_detach_one_process);
+ return 0;
+}
+
+static void
+linux_join (void)
+{
+ extern unsigned long signal_pid;
+ int status, ret;
+
+ do {
+ ret = waitpid (signal_pid, &status, 0);
+ if (WIFEXITED (status) || WIFSIGNALED (status))
+ break;
+ } while (ret != -1 || errno != ECHILD);
}
/* Return nonzero if the given thread is still alive. */
}
static void
-linux_send_signal (int signum)
+linux_request_interrupt (void)
{
extern unsigned long signal_pid;
struct process_info *process;
process = get_thread_process (current_inferior);
- kill_lwp (process->lwpid, signum);
+ kill_lwp (process->lwpid, SIGINT);
}
else
- kill_lwp (signal_pid, signum);
+ kill_lwp (signal_pid, SIGINT);
}
/* Copy LEN bytes from inferior's auxiliary vector starting at OFFSET
return 0;
}
-#if defined(__UCLIBC__) && !defined(__UCLIBC_HAS_MMU__)
+#if defined(__UCLIBC__) && defined(HAS_NOMMU)
#if defined(__mcoldfire__)
/* These should really be defined in the kernel's ptrace.h header. */
#define PT_TEXT_ADDR 49*4
}
#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,
linux_kill,
linux_detach,
+ linux_join,
linux_thread_alive,
linux_resume,
linux_wait,
linux_read_memory,
linux_write_memory,
linux_look_up_symbols,
- linux_send_signal,
+ linux_request_interrupt,
linux_read_auxv,
linux_insert_watchpoint,
linux_remove_watchpoint,
linux_stopped_by_watchpoint,
linux_stopped_data_address,
-#if defined(__UCLIBC__) && !defined(__UCLIBC_HAS_MMU__)
+#if defined(__UCLIBC__) && defined(HAS_NOMMU)
linux_read_offsets,
#else
NULL,
#else
NULL,
#endif
+ linux_arch_string,
};
static void