aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbserver/linux-low.c
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2009-04-01 22:50:24 +0000
committerPedro Alves <palves@redhat.com>2009-04-01 22:50:24 +0000
commit95954743cb49efcc384c378173606fd309b6e6ac (patch)
tree77498746f38b65a313aa42bcbf5db4c6c491c7e5 /gdb/gdbserver/linux-low.c
parentbd99dc858385792aad304d42f4a47791fd8d3272 (diff)
downloadgdb-95954743cb49efcc384c378173606fd309b6e6ac.zip
gdb-95954743cb49efcc384c378173606fd309b6e6ac.tar.gz
gdb-95954743cb49efcc384c378173606fd309b6e6ac.tar.bz2
2009-04-01 Pedro Alves <pedro@codesourcery.com>
Implement the multiprocess extensions, and add linux multiprocess support. * server.h (ULONGEST): Declare. (struct ptid, ptid_t): New. (minus_one_ptid, null_ptid): Declare. (ptid_build, pid_to_ptid, ptid_get_pid, ptid_get_lwp) (ptid_get_tid, ptid_equal, ptid_is_pid): Declare. (struct inferior_list_entry): Change `id' type from unsigned from to ptid_t. (struct sym_cache, struct breakpoint, struct process_info_private): Forward declare. (struct process_info): Declare. (current_process): Declare. (all_processes): Declare. (initialize_inferiors): Declare. (add_thread): Adjust to use ptid_t. (thread_id_to_gdb_id, thread_to_gdb_id, gdb_id_to_thread_id): Ditto. (add_process, remove_process, find_thread_pid): Declare. (find_inferior_id): Adjust to use ptid_t. (cont_thread, general_thread, step_thread): Change type to ptid_t. (multi_process): Declare. (push_event): Adjust to use ptid_t. (read_ptid, write_ptid): Declare. (prepare_resume_reply): Adjust to use ptid_t. (clear_symbol_cache): Declare. * inferiors.c (all_processes): New. (null_ptid, minus_one_ptid): New. (ptid_build, pid_to_ptid, ptid_get_pid, ptid_get_lwp) (ptid_get_tid, ptid_equal, ptid_is_pid): New. (add_thread): Change unsigned long to ptid. Remove gdb_id parameter. Adjust. (thread_id_to_gdb_id, thread_to_gdb_id): Change unsigned long to ptid. (gdb_id_to_thread): Rename to ... (find_thread_pid): ... this. Change unsigned long to ptid. (gdb_id_to_thread_id, find_inferior_id): Change unsigned long to ptid. (loaded_dll, pull_pid_from_list): Adjust. (add_process, remove_process, find_process_pid) (get_thread_process, current_process, initialize_inferiors): New. * target.h (struct thread_resume) <thread>: Change type to ptid_t. (struct target_waitstatus) <related_pid>: Ditto. (struct target_ops) <kill, detach>: Add `pid' argument. Change return type to int. (struct target_ops) <join>: Add `pid' argument. (struct target_ops) <thread_alive>: Change pid's type to ptid_t. (struct target_ops) <wait>: Add `ptid' field. Change return type to ptid. (kill_inferior, detach_inferior, join_inferior): Add `pid' argument. (mywait): Add `ptid' argument. Change return type to ptid_t. (target_pid_to_str): Declare. * target.c (set_desired_inferior): Adjust to use ptids. (mywait): Add new `ptid' argument. Adjust. (target_pid_to_str): New. * mem-break.h (free_all_breakpoints): Declare. * mem-break.c (breakpoints): Delelete. (set_breakpoint_at, delete_breakpoint, find_breakpoint_at) (check_mem_read, check_mem_write, delete_all_breakpoints): Adjust to use per-process breakpoint list. (free_all_breakpoints): New. * remote-utils.c (struct sym_cache) <name>: Drop `const'. (symbol_cache, all_symbols_looked_up): Delete. (hexchars): New. (ishex, unpack_varlen_hex, write_ptid, hex_or_minus_one, read_ptid): New. (prepare_resume_reply): Change ptid argument's type from unsigned long to ptid_t. Adjust. Implement W;process and X;process. (free_sym_cache, clear_symbol_cache): New. (look_up_one_symbol): Adjust to per-process symbol cache. * * server.c (cont_thread, general_thread, step_thread): Change type to ptid_t. (attached): Delete. (multi_process): New. (last_ptid): Change type to ptid_t. (struct vstop_notif) <ptid>: Change type to ptid_t. (queue_stop_reply, push_event): Change `ptid' argument's type to ptid_t. (discard_queued_stop_replies): Add `pid' argument. (start_inferior): Adjust to use ptids. Adjust to mywait interface changes. Don't reference the `attached' global. (attach_inferior): Adjust to mywait interface changes. (handle_query): Adjust to use ptids. Parse GDB's qSupported features. Handle and report "multiprocess+". Handle "qAttached:PID". (handle_v_cont): Adjust to use ptids. Adjust to mywait interface changes. (handle_v_kill): New. (handle_v_stopped): Adjust to use target_pid_to_str. (handle_v_requests): Allow multiple attaches and runs when multiprocess extensions are in effect. Handle "vKill". (myresume): Adjust to use ptids. (queue_stop_reply_callback): Add `arg' parameter. Handle it. (handle_status): Adjust to discard_queued_stop_replies interface change. (first_thread_of, kill_inferior_callback) (detach_or_kill_inferior_callback, join_inferiors_callback): New. (main): Call initialize_inferiors. Adjust to use ptids, killing and detaching from all inferiors. Handle multiprocess packet variants. * linux-low.h: Include gdb_proc_service.h. (struct process_info_private): New. (struct linux_target_ops) <pid_of>: Use ptid_get_pid. <lwpid_of>: Use ptid_get_lwp. (get_lwp_thread): Adjust. (struct lwp_info): Add `dead' member. (find_lwp_pid): Declare. * linux-low.c (thread_db_active): Delete. (new_inferior): Adjust comment. (inferior_pid): Delete. (linux_add_process): New. (handle_extended_wait): Adjust. (add_lwp): Change unsigned long to ptid. (linux_create_inferior): Add process to processes table. Adjust to use ptids. Don't set new_inferior here. (linux_attach_lwp): Rename to ... (linux_attach_lwp_1): ... this. Add `initial' argument. Handle it. Adjust to use ptids. (linux_attach_lwp): New. (linux_attach): Add process to processes table. Don't set new_inferior here. (struct counter): New. (second_thread_of_pid_p, last_thread_of_process_p): New. (linux_kill_one_lwp): Add `args' parameter. Handle it. Adjust to multiple processes. (linux_kill): Add `pid' argument. Handle it. Adjust to multiple processes. Remove process from process table. (linux_detach_one_lwp): Add `args' parameter. Handle it. Adjust to multiple processes. (any_thread_of): New. (linux_detach): Add `pid' argument, and handle it. Remove process from processes table. (linux_join): Add `pid' argument. Handle it. (linux_thread_alive): Change unsighed long argument to ptid_t. Consider dead lwps as not being alive. (status_pending_p): Rename `dummy' argument to `arg'. Filter out threads we're not interested in. (same_lwp, find_lwp_pid): New. (linux_wait_for_lwp): Change `pid' argument's type from int to ptid_t. Adjust. (linux_wait_for_event): Rename to ... (linux_wait_for_event_1): ... this. Change `pid' argument's type from int to ptid_t. Adjust. (linux_wait_for_event): New. (linux_wait_1): Add `ptid' argument. Change return type to ptid_t. Adjust. Use last_thread_of_process_p. Remove processes that exit from the process table. (linux_wait): Add `ptid' argument. Change return type to ptid_t. Adjust. (mark_lwp_dead): New. (wait_for_sigstop): Adjust to use ptids. If a process exits while stopping all threads, mark its main lwp as dead. (linux_set_resume_request, linux_resume_one_thread): Adjust to use ptids. (fetch_register, usr_store_inferior_registers) (regsets_fetch_inferior_registers) (regsets_store_inferior_registers, linux_read_memory) (linux_write_memory): Inline `inferior_pid'. (linux_look_up_symbols): Adjust to use per-process `thread_db_active'. (linux_request_interrupt): Adjust to use ptids. (linux_read_auxv): Inline `inferior_pid'. (initialize_low): Don't reference thread_db_active. * gdb_proc_service.h (struct ps_prochandle) <pid>: Remove. * proc-service.c (ps_lgetregs): Use find_lwp_pid. (ps_getpid): Return the pid of the current inferior. * thread-db.c (proc_handle, thread_agent): Delete. (thread_db_create_event, thread_db_enable_reporting): Adjust to per-process data. (find_one_thread): Change argument type to ptid_t. Adjust to per-process data. (maybe_attach_thread): Adjust to per-process data and ptids. (thread_db_find_new_threads): Ditto. (thread_db_init): Ditto. * spu-low.c (spu_create_inferior, spu_attach): Add process to processes table. Adjust to use ptids. (spu_kill, spu_detach): Adjust interface. Remove process from processes table. (spu_join, spu_thread_alive): Adjust interface. (spu_wait): Adjust interface. Remove process from processes table. Adjust to use ptids. * win32-low.c (current_inferior_tid): Delete. (current_inferior_ptid): New. (debug_event_ptid): New. (thread_rec): Take a ptid. Adjust. (child_add_thread): Add `pid' argument. Adjust to use ptids. (child_delete_thread): Ditto. (do_initial_child_stuff): Add `attached' argument. Add process to processes table. (child_fetch_inferior_registers, child_store_inferior_registers): Adjust. (win32_create_inferior): Pass 0 to do_initial_child_stuff. (win32_attach): Pass 1 to do_initial_child_stuff. (win32_kill): Adjust interface. Remove process from processes table. (win32_detach): Ditto. (win32_join): Adjust interface. (win32_thread_alive): Take a ptid. (win32_resume): Adjust to use ptids. (get_child_debug_event): Ditto. (win32_wait): Adjust interface. Remove exiting process from processes table.
Diffstat (limited to 'gdb/gdbserver/linux-low.c')
-rw-r--r--gdb/gdbserver/linux-low.c539
1 files changed, 395 insertions, 144 deletions
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index ba1d7b4..eccc2e1 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -90,7 +90,10 @@
representation of the thread ID.
``all_lwps'' is keyed by the process ID - which on Linux is (presently)
- the same as the LWP ID. */
+ the same as the LWP ID.
+
+ ``all_processes'' is keyed by the "overall process ID", which
+ GNU/Linux calls tgid, "thread group ID". */
struct inferior_list all_lwps;
@@ -105,24 +108,28 @@ int stopping_threads;
/* FIXME make into a target method? */
int using_threads = 1;
-static int thread_db_active;
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. */
+/* This flag is true iff we've just created or attached to our first
+ inferior but it has not stopped yet. As soon as it does, we need
+ to call the low target's arch_setup callback. Doing this only on
+ the first inferior avoids reinializing the architecture on every
+ inferior, and avoids messing with the register caches of the
+ already running inferiors. NOTE: this assumes all inferiors under
+ control of gdbserver have the same architecture. */
static int new_inferior;
static void linux_resume_one_lwp (struct inferior_list_entry *entry,
int step, int signal, siginfo_t *info);
static void linux_resume (struct thread_resume *resume_info, size_t n);
static void stop_all_lwps (void);
-static int linux_wait_for_event (int pid, int *wstat, int options);
+static int linux_wait_for_event (ptid_t ptid, int *wstat, int options);
static int check_removed_breakpoint (struct lwp_info *event_child);
-static void *add_lwp (unsigned long pid);
+static void *add_lwp (ptid_t ptid);
static int my_waitpid (int pid, int *status, int flags);
static int linux_stopped_by_watchpoint (void);
+static void mark_lwp_dead (struct lwp_info *lwp, int wstat);
struct pending_signals
{
@@ -139,9 +146,6 @@ static char *disabled_regsets;
static int num_regsets;
#endif
-/* FIXME: Delete eventually. */
-#define inferior_pid (lwpid_of (get_thread_lwp (current_inferior)))
-
/* The read/write ends of the pipe registered as waitable file in the
event loop. */
static int linux_event_pipe[2] = { -1, -1 };
@@ -160,6 +164,24 @@ delete_lwp (struct lwp_info *lwp)
free (lwp);
}
+/* Add a process to the common process list, and set its private
+ data. */
+
+static struct process_info *
+linux_add_process (int pid, int attached)
+{
+ struct process_info *proc;
+
+ /* Is this the first process? If so, then set the arch. */
+ if (all_processes.head == NULL)
+ new_inferior = 1;
+
+ proc = add_process (pid, attached);
+ proc->private = xcalloc (1, sizeof (*proc->private));
+
+ return proc;
+}
+
/* Handle a GNU/Linux extended wait response. If we see a clone
event, we need to add the new LWP to our list (and not report the
trap to higher layers). */
@@ -172,6 +194,7 @@ handle_extended_wait (struct lwp_info *event_child, int wstat)
if (event == PTRACE_EVENT_CLONE)
{
+ ptid_t ptid;
unsigned long new_pid;
int ret, status = W_STOPCODE (SIGSTOP);
@@ -195,9 +218,9 @@ handle_extended_wait (struct lwp_info *event_child, int wstat)
ptrace (PTRACE_SETOPTIONS, new_pid, 0, PTRACE_O_TRACECLONE);
- new_lwp = (struct lwp_info *) add_lwp (new_pid);
- add_thread (new_pid, new_lwp, new_pid);
- new_thread_notify (thread_id_to_gdb_id (lwpid_of (new_lwp)));
+ ptid = ptid_build (pid_of (event_child), new_pid, 0);
+ new_lwp = (struct lwp_info *) add_lwp (ptid);
+ add_thread (ptid, new_lwp);
/* Normally we will get the pending SIGSTOP. But in some cases
we might get another signal delivered to the group first.
@@ -266,14 +289,14 @@ get_stop_pc (void)
}
static void *
-add_lwp (unsigned long pid)
+add_lwp (ptid_t ptid)
{
struct lwp_info *lwp;
lwp = (struct lwp_info *) xmalloc (sizeof (*lwp));
memset (lwp, 0, sizeof (*lwp));
- lwp->head.id = pid;
+ lwp->head.id = ptid;
add_inferior_to_list (&all_lwps, &lwp->head);
@@ -288,6 +311,7 @@ linux_create_inferior (char *program, char **allargs)
{
void *new_lwp;
int pid;
+ ptid_t ptid;
#if defined(__UCLIBC__) && defined(HAS_NOMMU)
pid = vfork ();
@@ -315,44 +339,58 @@ linux_create_inferior (char *program, char **allargs)
_exit (0177);
}
- new_lwp = add_lwp (pid);
- add_thread (pid, new_lwp, pid);
+ linux_add_process (pid, 0);
+
+ ptid = ptid_build (pid, pid, 0);
+ new_lwp = add_lwp (ptid);
+ add_thread (ptid, new_lwp);
must_set_ptrace_flags = 1;
- new_inferior = 1;
return pid;
}
/* Attach to an inferior process. */
-void
-linux_attach_lwp (unsigned long pid)
+static void
+linux_attach_lwp_1 (unsigned long lwpid, int initial)
{
+ ptid_t ptid;
struct lwp_info *new_lwp;
- if (ptrace (PTRACE_ATTACH, pid, 0, 0) != 0)
+ if (ptrace (PTRACE_ATTACH, lwpid, 0, 0) != 0)
{
- if (all_threads.head != NULL)
+ if (!initial)
{
/* If we fail to attach to an LWP, just warn. */
- fprintf (stderr, "Cannot attach to lwp %ld: %s (%d)\n", pid,
+ fprintf (stderr, "Cannot attach to lwp %ld: %s (%d)\n", lwpid,
strerror (errno), errno);
fflush (stderr);
return;
}
else
/* If we fail to attach to a process, report an error. */
- error ("Cannot attach to lwp %ld: %s (%d)\n", pid,
+ error ("Cannot attach to lwp %ld: %s (%d)\n", lwpid,
strerror (errno), errno);
}
/* FIXME: This intermittently fails.
We need to wait for SIGSTOP first. */
- ptrace (PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACECLONE);
+ ptrace (PTRACE_SETOPTIONS, lwpid, 0, PTRACE_O_TRACECLONE);
+
+ if (initial)
+ /* NOTE/FIXME: This lwp might have not been the tgid. */
+ ptid = ptid_build (lwpid, lwpid, 0);
+ else
+ {
+ /* Note that extracting the pid from the current inferior is
+ safe, since we're always called in the context of the same
+ process as this new thread. */
+ int pid = pid_of (get_thread_lwp (current_inferior));
+ ptid = ptid_build (pid, lwpid, 0);
+ }
- new_lwp = (struct lwp_info *) add_lwp (pid);
- add_thread (pid, new_lwp, pid);
- new_thread_notify (thread_id_to_gdb_id (lwpid_of (new_lwp)));
+ new_lwp = (struct lwp_info *) add_lwp (ptid);
+ add_thread (ptid, new_lwp);
/* The next time we wait for this LWP we'll see a SIGSTOP as PTRACE_ATTACH
brings it to a halt.
@@ -389,42 +427,89 @@ linux_attach_lwp (unsigned long pid)
new_lwp->stop_expected = 1;
}
+void
+linux_attach_lwp (unsigned long lwpid)
+{
+ linux_attach_lwp_1 (lwpid, 0);
+}
+
int
linux_attach (unsigned long pid)
{
struct lwp_info *lwp;
- linux_attach_lwp (pid);
+ linux_attach_lwp_1 (pid, 1);
+
+ linux_add_process (pid, 1);
if (!non_stop)
{
/* Don't ignore the initial SIGSTOP if we just attached to this
process. It will be collected by wait shortly. */
- lwp = (struct lwp_info *) find_inferior_id (&all_lwps, pid);
+ lwp = (struct lwp_info *) find_inferior_id (&all_lwps,
+ ptid_build (pid, pid, 0));
lwp->stop_expected = 0;
}
- new_inferior = 1;
+ return 0;
+}
+
+struct counter
+{
+ int pid;
+ int count;
+};
+
+static int
+second_thread_of_pid_p (struct inferior_list_entry *entry, void *args)
+{
+ struct counter *counter = args;
+
+ if (ptid_get_pid (entry->id) == counter->pid)
+ {
+ if (++counter->count > 1)
+ return 1;
+ }
return 0;
}
-/* Kill the inferior process. Make us have no inferior. */
+static int
+last_thread_of_process_p (struct thread_info *thread)
+{
+ ptid_t ptid = ((struct inferior_list_entry *)thread)->id;
+ int pid = ptid_get_pid (ptid);
+ struct counter counter = { pid , 0 };
-static void
-linux_kill_one_lwp (struct inferior_list_entry *entry)
+ return (find_inferior (&all_threads,
+ second_thread_of_pid_p, &counter) == NULL);
+}
+
+/* Kill the inferior lwp. */
+
+static int
+linux_kill_one_lwp (struct inferior_list_entry *entry, void *args)
{
struct thread_info *thread = (struct thread_info *) entry;
struct lwp_info *lwp = get_thread_lwp (thread);
- int pid;
int wstat;
+ int pid = * (int *) args;
+
+ if (ptid_get_pid (entry->id) != pid)
+ return 0;
/* We avoid killing the first thread here, because of a Linux kernel (at
least 2.6.0-test7 through 2.6.8-rc4) bug; if we kill the parent before
the children get a chance to be reaped, it will remain a zombie
forever. */
- if (entry == all_threads.head)
- return;
+
+ if (last_thread_of_process_p (thread))
+ {
+ if (debug_threads)
+ fprintf (stderr, "lkop: is last of process %s\n",
+ target_pid_to_str (entry->id));
+ return 0;
+ }
/* If we're killing a running inferior, make sure it is stopped
first, as PTRACE_KILL will not work otherwise. */
@@ -436,29 +521,35 @@ linux_kill_one_lwp (struct inferior_list_entry *entry)
ptrace (PTRACE_KILL, lwpid_of (lwp), 0, 0);
/* Make sure it died. The loop is most likely unnecessary. */
- pid = linux_wait_for_event (lwpid_of (lwp), &wstat, __WALL);
+ pid = linux_wait_for_event (lwp->head.id, &wstat, __WALL);
} while (pid > 0 && WIFSTOPPED (wstat));
+
+ return 0;
}
-static void
-linux_kill (void)
+static int
+linux_kill (int pid)
{
- struct thread_info *thread = (struct thread_info *) all_threads.head;
+ struct process_info *process;
struct lwp_info *lwp;
+ struct thread_info *thread;
int wstat;
- int pid;
+ int lwpid;
- if (thread == NULL)
- return;
+ process = find_process_pid (pid);
+ if (process == NULL)
+ return -1;
- for_each_inferior (&all_threads, linux_kill_one_lwp);
+ find_inferior (&all_threads, linux_kill_one_lwp, &pid);
/* See the comment in linux_kill_one_lwp. We did not kill the first
thread in the list, so do so now. */
- lwp = get_thread_lwp (thread);
+ lwp = find_lwp_pid (pid_to_ptid (pid));
+ thread = get_lwp_thread (lwp);
if (debug_threads)
- fprintf (stderr, "lk_1: killing lwp %ld\n", lwpid_of (lwp));
+ fprintf (stderr, "lk_1: killing lwp %ld, for pid: %d\n",
+ lwpid_of (lwp), pid);
/* If we're killing a running inferior, make sure it is stopped
first, as PTRACE_KILL will not work otherwise. */
@@ -470,24 +561,29 @@ linux_kill (void)
ptrace (PTRACE_KILL, lwpid_of (lwp), 0, 0);
/* Make sure it died. The loop is most likely unnecessary. */
- pid = linux_wait_for_event (lwpid_of (lwp), &wstat, __WALL);
- } while (pid > 0 && WIFSTOPPED (wstat));
+ lwpid = linux_wait_for_event (lwp->head.id, &wstat, __WALL);
+ } while (lwpid > 0 && WIFSTOPPED (wstat));
delete_lwp (lwp);
- clear_inferiors ();
+ remove_process (process);
+ return 0;
}
-static void
-linux_detach_one_lwp (struct inferior_list_entry *entry)
+static int
+linux_detach_one_lwp (struct inferior_list_entry *entry, void *args)
{
struct thread_info *thread = (struct thread_info *) entry;
struct lwp_info *lwp = get_thread_lwp (thread);
+ int pid = * (int *) args;
+
+ if (ptid_get_pid (entry->id) != pid)
+ return 0;
/* If we're detaching from a running inferior, make sure it is
stopped first, as PTRACE_DETACH will not work otherwise. */
if (!lwp->stopped)
{
- int pid = lwpid_of (lwp);
+ int lwpid = lwpid_of (lwp);
stopping_threads = 1;
send_sigstop (&lwp->head);
@@ -500,9 +596,9 @@ linux_detach_one_lwp (struct inferior_list_entry *entry)
/* If LWP exits while we're trying to stop it, there's nothing
left to do. */
- lwp = (struct lwp_info *) find_inferior_id (&all_lwps, pid);
+ lwp = find_lwp_pid (pid_to_ptid (lwpid));
if (lwp == NULL)
- return;
+ return 0;
}
/* Make sure the process isn't stopped at a breakpoint that's
@@ -519,7 +615,7 @@ linux_detach_one_lwp (struct inferior_list_entry *entry)
lwp->stop_expected = 0;
if (lwp->stopped)
linux_resume_one_lwp (&lwp->head, 0, 0, NULL);
- linux_wait_for_event (lwpid_of (lwp), &wstat, __WALL);
+ linux_wait_for_event (lwp->head.id, &wstat, __WALL);
}
/* Flush any pending changes to the process's registers. */
@@ -530,29 +626,50 @@ linux_detach_one_lwp (struct inferior_list_entry *entry)
ptrace (PTRACE_DETACH, lwpid_of (lwp), 0, 0);
delete_lwp (lwp);
+ return 0;
}
static int
-linux_detach (void)
+any_thread_of (struct inferior_list_entry *entry, void *args)
{
+ int *pid_p = args;
+
+ if (ptid_get_pid (entry->id) == *pid_p)
+ return 1;
+
+ return 0;
+}
+
+static int
+linux_detach (int pid)
+{
+ struct process_info *process;
+
+ process = find_process_pid (pid);
+ if (process == NULL)
+ return -1;
+
+ current_inferior =
+ (struct thread_info *) find_inferior (&all_threads, any_thread_of, &pid);
+
delete_all_breakpoints ();
- for_each_inferior (&all_threads, linux_detach_one_lwp);
- clear_inferiors ();
+ find_inferior (&all_threads, linux_detach_one_lwp, &pid);
+ remove_process (process);
return 0;
}
static void
-linux_join (void)
+linux_join (int pid)
{
int status, ret;
- struct thread_info *thread;
- struct lwp_info *lwp;
+ struct process_info *process;
- thread = (struct thread_info *) all_threads.head;
- lwp = get_thread_lwp (thread);
+ process = find_process_pid (pid);
+ if (process == NULL)
+ return;
do {
- ret = my_waitpid (lwpid_of (lwp), &status, 0);
+ ret = my_waitpid (pid, &status, 0);
if (WIFEXITED (status) || WIFSIGNALED (status))
break;
} while (ret != -1 || errno != ECHILD);
@@ -560,10 +677,15 @@ linux_join (void)
/* Return nonzero if the given thread is still alive. */
static int
-linux_thread_alive (unsigned long lwpid)
+linux_thread_alive (ptid_t ptid)
{
- if (find_inferior_id (&all_threads, lwpid) != NULL)
- return 1;
+ struct lwp_info *lwp = find_lwp_pid (ptid);
+
+ /* We assume we always know if a thread exits. If a whole process
+ exited but we still haven't been able to report it to GDB, we'll
+ hold on to the last lwp of the dead process. */
+ if (lwp != NULL)
+ return !lwp->dead;
else
return 0;
}
@@ -633,9 +755,16 @@ check_removed_breakpoint (struct lwp_info *event_child)
/* Return 1 if this lwp has an interesting status pending. This
function may silently resume an inferior lwp. */
static int
-status_pending_p (struct inferior_list_entry *entry, void *dummy)
+status_pending_p (struct inferior_list_entry *entry, void *arg)
{
struct lwp_info *lwp = (struct lwp_info *) entry;
+ ptid_t ptid = * (ptid_t *) arg;
+
+ /* Check if we're only interested in events from a specific process
+ or its lwps. */
+ if (!ptid_equal (minus_one_ptid, ptid)
+ && ptid_get_pid (ptid) != ptid_get_pid (lwp->head.id))
+ return 0;
if (lwp->status_pending_p && !lwp->suspended)
if (check_removed_breakpoint (lwp))
@@ -653,15 +782,43 @@ status_pending_p (struct inferior_list_entry *entry, void *dummy)
return (lwp->status_pending_p && !lwp->suspended);
}
+static int
+same_lwp (struct inferior_list_entry *entry, void *data)
+{
+ ptid_t ptid = *(ptid_t *) data;
+ int lwp;
+
+ if (ptid_get_lwp (ptid) != 0)
+ lwp = ptid_get_lwp (ptid);
+ else
+ lwp = ptid_get_pid (ptid);
+
+ if (ptid_get_lwp (entry->id) == lwp)
+ return 1;
+
+ return 0;
+}
+
+struct lwp_info *
+find_lwp_pid (ptid_t ptid)
+{
+ return (struct lwp_info*) find_inferior (&all_lwps, same_lwp, &ptid);
+}
+
static struct lwp_info *
-linux_wait_for_lwp (int pid, int *wstatp, int options)
+linux_wait_for_lwp (ptid_t ptid, int *wstatp, int options)
{
int ret;
- int to_wait_for = pid;
+ int to_wait_for = -1;
struct lwp_info *child = NULL;
if (debug_threads)
- fprintf (stderr, "linux_wait_for_lwp: %d\n", pid);
+ fprintf (stderr, "linux_wait_for_lwp: %s\n", target_pid_to_str (ptid));
+
+ if (ptid_equal (ptid, minus_one_ptid))
+ to_wait_for = -1; /* any child */
+ else
+ to_wait_for = ptid_get_lwp (ptid); /* this lwp only */
options |= __WALL;
@@ -679,7 +836,7 @@ retry:
&& WSTOPSIG (*wstatp) != 33)))
fprintf (stderr, "Got an event from %d (%x)\n", ret, *wstatp);
- child = (struct lwp_info *) find_inferior_id (&all_lwps, ret);
+ child = find_lwp_pid (pid_to_ptid (ret));
/* If we didn't find a process, one of two things presumably happened:
- A process we started and then detached from has exited. Ignore it.
@@ -716,7 +873,7 @@ retry:
{
struct thread_info *saved_inferior = current_inferior;
current_inferior = (struct thread_info *)
- find_inferior_id (&all_threads, lwpid_of (child));
+ find_inferior_id (&all_threads, child->head.id);
/* For testing only; i386_stop_pc prints out a diagnostic. */
if (the_low_target.get_pc != NULL)
get_stop_pc ();
@@ -733,29 +890,29 @@ retry:
the stopped child otherwise. */
static int
-linux_wait_for_event (int pid, int *wstat, int options)
+linux_wait_for_event_1 (ptid_t ptid, int *wstat, int options)
{
CORE_ADDR stop_pc;
struct lwp_info *event_child = NULL;
int bp_status;
struct lwp_info *requested_child = NULL;
- /* Check for a process with a pending status. */
+ /* Check for a lwp with a pending status. */
/* It is possible that the user changed the pending task's registers since
it stopped. We correctly handle the change of PC if we hit a breakpoint
(in check_removed_breakpoint); signals should be reported anyway. */
- if (pid == -1)
+ if (ptid_equal (ptid, minus_one_ptid)
+ || ptid_equal (pid_to_ptid (ptid_get_pid (ptid)), ptid))
{
event_child = (struct lwp_info *)
- find_inferior (&all_lwps, status_pending_p, NULL);
+ find_inferior (&all_lwps, status_pending_p, &ptid);
if (debug_threads && event_child)
fprintf (stderr, "Got a pending child %ld\n", lwpid_of (event_child));
}
else
{
- requested_child = (struct lwp_info *)
- find_inferior_id (&all_lwps, pid);
+ requested_child = find_lwp_pid (ptid);
if (requested_child->status_pending_p
&& !check_removed_breakpoint (requested_child))
event_child = requested_child;
@@ -779,7 +936,7 @@ linux_wait_for_event (int pid, int *wstat, int options)
events. */
while (1)
{
- event_child = linux_wait_for_lwp (pid, wstat, options);
+ event_child = linux_wait_for_lwp (ptid, wstat, options);
if ((options & WNOHANG) && event_child == NULL)
return 0;
@@ -792,19 +949,18 @@ linux_wait_for_event (int pid, int *wstat, int options)
/* Check for thread exit. */
if (! WIFSTOPPED (*wstat))
{
- int lwpid = lwpid_of (event_child);
if (debug_threads)
- fprintf (stderr, "LWP %d exiting\n", lwpid);
+ fprintf (stderr, "LWP %ld exiting\n", lwpid_of (event_child));
/* If the last thread is exiting, just return. */
- if (all_threads.head == all_threads.tail)
+ if (last_thread_of_process_p (current_inferior))
{
if (debug_threads)
- fprintf (stderr, "LWP %d is last lwp of process\n", lwpid);
+ fprintf (stderr, "LWP %ld is last lwp of process\n",
+ lwpid_of (event_child));
return lwpid_of (event_child);
}
- dead_thread_notify (thread_id_to_gdb_id (lwpid_of (event_child)));
delete_lwp (event_child);
if (!non_stop)
@@ -824,7 +980,7 @@ linux_wait_for_event (int pid, int *wstat, int options)
/* If we were waiting for this particular child to do something...
well, it did something. */
if (requested_child != NULL)
- return lwpid;
+ return lwpid_of (event_child);
/* Wait for a more interesting event. */
continue;
@@ -862,7 +1018,7 @@ linux_wait_for_event (int pid, int *wstat, int options)
&& !event_child->stepping
&& (
#ifdef USE_THREAD_DB
- (thread_db_active
+ (current_process ()->private->thread_db_active
&& (WSTOPSIG (*wstat) == __SIGRTMIN
|| WSTOPSIG (*wstat) == __SIGRTMIN + 1))
||
@@ -1000,16 +1156,56 @@ linux_wait_for_event (int pid, int *wstat, int options)
return 0;
}
+static int
+linux_wait_for_event (ptid_t ptid, int *wstat, int options)
+{
+ ptid_t wait_ptid;
+
+ if (ptid_is_pid (ptid))
+ {
+ /* A request to wait for a specific tgid. This is not possible
+ with waitpid, so instead, we wait for any child, and leave
+ children we're not interested in right now with a pending
+ status to report later. */
+ wait_ptid = minus_one_ptid;
+ }
+ else
+ wait_ptid = ptid;
+
+ while (1)
+ {
+ int event_pid;
+
+ event_pid = linux_wait_for_event_1 (wait_ptid, wstat, options);
+
+ if (event_pid > 0
+ && ptid_is_pid (ptid) && ptid_get_pid (ptid) != event_pid)
+ {
+ struct lwp_info *event_child = find_lwp_pid (pid_to_ptid (event_pid));
+
+ if (! WIFSTOPPED (*wstat))
+ mark_lwp_dead (event_child, *wstat);
+ else
+ {
+ event_child->status_pending_p = 1;
+ event_child->status_pending = *wstat;
+ }
+ }
+ else
+ return event_pid;
+ }
+}
+
/* Wait for process, returns status. */
-static unsigned long
-linux_wait_1 (struct target_waitstatus *ourstatus, int target_options)
+static ptid_t
+linux_wait_1 (ptid_t ptid,
+ struct target_waitstatus *ourstatus, int target_options)
{
int w;
struct thread_info *thread = NULL;
struct lwp_info *lwp = NULL;
int options;
- int wait_pid = -1;
int pid;
/* Translate generic target options into linux options. */
@@ -1026,7 +1222,9 @@ retry:
then we need to make sure we restart the other threads. We could
pick a thread at random or restart all; restarting all is less
arbitrary. */
- if (!non_stop && cont_thread != 0 && cont_thread != -1)
+ if (!non_stop
+ && !ptid_equal (cont_thread, null_ptid)
+ && !ptid_equal (cont_thread, minus_one_ptid))
{
thread = (struct thread_info *) find_inferior_id (&all_threads,
cont_thread);
@@ -1035,18 +1233,18 @@ retry:
if (thread == NULL)
{
struct thread_resume resume_info;
- resume_info.thread = -1;
+ resume_info.thread = minus_one_ptid;
resume_info.kind = resume_continue;
resume_info.sig = 0;
linux_resume (&resume_info, 1);
}
else
- wait_pid = cont_thread;
+ ptid = cont_thread;
}
- pid = linux_wait_for_event (wait_pid, &w, options);
+ pid = linux_wait_for_event (ptid, &w, options);
if (pid == 0) /* only if TARGET_WNOHANG */
- return pid;
+ return null_ptid;
lwp = get_thread_lwp (current_inferior);
@@ -1067,16 +1265,15 @@ retry:
Report the exit status of the last thread to exit. This matches
LinuxThreads' behavior. */
- if (all_threads.head == all_threads.tail)
+ if (last_thread_of_process_p (current_inferior))
{
if (WIFEXITED (w) || WIFSIGNALED (w))
{
- int pid;
-
- pid = pid_of (lwp);
+ int pid = pid_of (lwp);
+ struct process_info *process = find_process_pid (pid);
delete_lwp (lwp);
- clear_inferiors ();
+ remove_process (process);
current_inferior = NULL;
@@ -1098,7 +1295,7 @@ retry:
}
- return pid;
+ return pid_to_ptid (pid);
}
}
else
@@ -1135,12 +1332,12 @@ retry:
}
if (debug_threads)
- fprintf (stderr, "linux_wait ret = %ld, %d, %d\n",
- lwpid_of (lwp),
+ fprintf (stderr, "linux_wait ret = %s, %d, %d\n",
+ target_pid_to_str (lwp->head.id),
ourstatus->kind,
ourstatus->value.sig);
- return lwpid_of (lwp);
+ return lwp->head.id;
}
/* Get rid of any pending event in the pipe. */
@@ -1171,25 +1368,26 @@ async_file_mark (void)
be awakened anyway. */
}
-static unsigned long
-linux_wait (struct target_waitstatus *ourstatus, int target_options)
+static ptid_t
+linux_wait (ptid_t ptid,
+ struct target_waitstatus *ourstatus, int target_options)
{
- unsigned long event_ptid;
+ ptid_t event_ptid;
if (debug_threads)
- fprintf (stderr, "linux_wait\n");
+ fprintf (stderr, "linux_wait: [%s]\n", target_pid_to_str (ptid));
/* Flush the async file first. */
if (target_is_async_p ())
async_file_flush ();
- event_ptid = linux_wait_1 (ourstatus, target_options);
+ event_ptid = linux_wait_1 (ptid, ourstatus, target_options);
/* If at least one stop was reported, there may be more. A single
SIGCHLD can signal more than one child stop. */
if (target_is_async_p ()
&& (target_options & TARGET_WNOHANG) != 0
- && event_ptid != 0)
+ && !ptid_equal (event_ptid, null_ptid))
async_file_mark ();
return event_ptid;
@@ -1251,13 +1449,34 @@ send_sigstop (struct inferior_list_entry *entry)
}
static void
+mark_lwp_dead (struct lwp_info *lwp, int wstat)
+{
+ /* It's dead, really. */
+ lwp->dead = 1;
+
+ /* Store the exit status for later. */
+ lwp->status_pending_p = 1;
+ lwp->status_pending = wstat;
+
+ /* So that check_removed_breakpoint doesn't try to figure out if
+ this is stopped at a breakpoint. */
+ lwp->pending_is_breakpoint = 0;
+
+ /* Prevent trying to stop it. */
+ lwp->stopped = 1;
+
+ /* No further stops are expected from a dead lwp. */
+ lwp->stop_expected = 0;
+}
+
+static void
wait_for_sigstop (struct inferior_list_entry *entry)
{
struct lwp_info *lwp = (struct lwp_info *) entry;
struct thread_info *saved_inferior;
int wstat;
- unsigned long saved_tid;
- unsigned long ptid;
+ ptid_t saved_tid;
+ ptid_t ptid;
if (lwp->stopped)
return;
@@ -1266,9 +1485,9 @@ wait_for_sigstop (struct inferior_list_entry *entry)
if (saved_inferior != NULL)
saved_tid = ((struct inferior_list_entry *) saved_inferior)->id;
else
- saved_tid = 0; /* avoid bogus unused warning */
+ saved_tid = null_ptid; /* avoid bogus unused warning */
- ptid = lwpid_of (lwp);
+ ptid = lwp->head.id;
linux_wait_for_event (ptid, &wstat, __WALL);
@@ -1301,6 +1520,18 @@ wait_for_sigstop (struct inferior_list_entry *entry)
}
lwp->stop_expected = 1;
}
+ else if (!WIFSTOPPED (wstat))
+ {
+ if (debug_threads)
+ fprintf (stderr, "Process %ld exited while stopping LWPs\n",
+ lwpid_of (lwp));
+
+ /* Leave this status pending for the next time we're able to
+ report it. In the mean time, we'll report this lwp as dead
+ to GDB, so GDB doesn't try to read registers and memory from
+ it. */
+ mark_lwp_dead (lwp, wstat);
+ }
if (saved_inferior == NULL || linux_thread_alive (saved_tid))
current_inferior = saved_inferior;
@@ -1474,11 +1705,19 @@ linux_set_resume_request (struct inferior_list_entry *entry, void *arg)
r = arg;
for (ndx = 0; ndx < r->n; ndx++)
- if (r->resume[ndx].thread == -1 || r->resume[ndx].thread == entry->id)
- {
- lwp->resume = &r->resume[ndx];
- return 0;
- }
+ {
+ ptid_t ptid = r->resume[ndx].thread;
+ if (ptid_equal (ptid, minus_one_ptid)
+ || ptid_equal (ptid, entry->id)
+ || (ptid_is_pid (ptid)
+ && (ptid_get_pid (ptid) == pid_of (lwp)))
+ || (ptid_get_lwp (ptid) == -1
+ && (ptid_get_pid (ptid) == pid_of (lwp))))
+ {
+ lwp->resume = &r->resume[ndx];
+ return 0;
+ }
+ }
/* No resume action for this thread. */
lwp->resume = NULL;
@@ -1550,7 +1789,7 @@ linux_resume_one_thread (struct inferior_list_entry *entry, void *arg)
if (!lwp->stopped)
{
if (debug_threads)
- fprintf (stderr, "running -> suspending %ld\n", lwpid_of (lwp));
+ fprintf (stderr, "running -> suspending LWP %ld\n", lwpid_of (lwp));
lwp->suspended = 1;
send_sigstop (&lwp->head);
@@ -1596,7 +1835,7 @@ linux_resume_one_thread (struct inferior_list_entry *entry, void *arg)
if (debug_threads)
fprintf (stderr, "resuming LWP %ld\n", lwpid_of (lwp));
- if (lwp->resume->thread == -1
+ if (ptid_equal (lwp->resume->thread, minus_one_ptid)
&& lwp->stepping
&& lwp->pending_is_breakpoint)
step = 1;
@@ -1685,6 +1924,7 @@ fetch_register (int regno)
CORE_ADDR regaddr;
int i, size;
char *buf;
+ int pid;
if (regno >= the_low_target.num_regs)
return;
@@ -1694,6 +1934,8 @@ fetch_register (int regno)
regaddr = register_addr (regno);
if (regaddr == -1)
return;
+
+ pid = lwpid_of (get_thread_lwp (current_inferior));
size = ((register_size (regno) + sizeof (PTRACE_XFER_TYPE) - 1)
& - sizeof (PTRACE_XFER_TYPE));
buf = alloca (size);
@@ -1701,7 +1943,7 @@ fetch_register (int regno)
{
errno = 0;
*(PTRACE_XFER_TYPE *) (buf + i) =
- ptrace (PTRACE_PEEKUSER, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, 0);
+ ptrace (PTRACE_PEEKUSER, pid, (PTRACE_ARG3_TYPE) regaddr, 0);
regaddr += sizeof (PTRACE_XFER_TYPE);
if (errno != 0)
{
@@ -1766,10 +2008,11 @@ usr_store_inferior_registers (int regno)
else
collect_register (regno, buf);
+ pid = lwpid_of (get_thread_lwp (current_inferior));
for (i = 0; i < size; i += sizeof (PTRACE_XFER_TYPE))
{
errno = 0;
- ptrace (PTRACE_POKEUSER, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ ptrace (PTRACE_POKEUSER, pid, (PTRACE_ARG3_TYPE) regaddr,
*(PTRACE_XFER_TYPE *) (buf + i));
if (errno != 0)
{
@@ -1808,9 +2051,11 @@ regsets_fetch_inferior_registers ()
{
struct regset_info *regset;
int saw_general_regs = 0;
+ int pid;
regset = target_regsets;
+ pid = lwpid_of (get_thread_lwp (current_inferior));
while (regset->size >= 0)
{
void *buf;
@@ -1824,9 +2069,9 @@ regsets_fetch_inferior_registers ()
buf = xmalloc (regset->size);
#ifndef __sparc__
- res = ptrace (regset->get_request, inferior_pid, 0, buf);
+ res = ptrace (regset->get_request, pid, 0, buf);
#else
- res = ptrace (regset->get_request, inferior_pid, buf, 0);
+ res = ptrace (regset->get_request, pid, buf, 0);
#endif
if (res < 0)
{
@@ -1840,8 +2085,8 @@ regsets_fetch_inferior_registers ()
else
{
char s[256];
- sprintf (s, "ptrace(regsets_fetch_inferior_registers) PID=%ld",
- inferior_pid);
+ sprintf (s, "ptrace(regsets_fetch_inferior_registers) PID=%d",
+ pid);
perror (s);
}
}
@@ -1861,9 +2106,11 @@ regsets_store_inferior_registers ()
{
struct regset_info *regset;
int saw_general_regs = 0;
+ int pid;
regset = target_regsets;
+ pid = lwpid_of (get_thread_lwp (current_inferior));
while (regset->size >= 0)
{
void *buf;
@@ -1881,9 +2128,9 @@ regsets_store_inferior_registers ()
in case there are any items in the kernel's regset that are
not in gdbserver's regcache. */
#ifndef __sparc__
- res = ptrace (regset->get_request, inferior_pid, 0, buf);
+ res = ptrace (regset->get_request, pid, 0, buf);
#else
- res = ptrace (regset->get_request, inferior_pid, buf, 0);
+ res = ptrace (regset->get_request, pid, buf, 0);
#endif
if (res == 0)
@@ -1893,9 +2140,9 @@ regsets_store_inferior_registers ()
/* Only now do we write the register set. */
#ifndef __sparc__
- res = ptrace (regset->set_request, inferior_pid, 0, buf);
+ res = ptrace (regset->set_request, pid, 0, buf);
#else
- res = ptrace (regset->set_request, inferior_pid, buf, 0);
+ res = ptrace (regset->set_request, pid, buf, 0);
#endif
}
@@ -1979,13 +2226,14 @@ linux_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
= (PTRACE_XFER_TYPE *) alloca (count * sizeof (PTRACE_XFER_TYPE));
int fd;
char filename[64];
+ int pid = lwpid_of (get_thread_lwp (current_inferior));
/* Try using /proc. Don't bother for one word. */
if (len >= 3 * sizeof (long))
{
/* We could keep this file open and cache it - possibly one per
thread. That requires some juggling, but is even faster. */
- sprintf (filename, "/proc/%ld/mem", inferior_pid);
+ sprintf (filename, "/proc/%d/mem", pid);
fd = open (filename, O_RDONLY | O_LARGEFILE);
if (fd == -1)
goto no_proc;
@@ -2013,8 +2261,7 @@ linux_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
{
errno = 0;
- buffer[i] = ptrace (PTRACE_PEEKTEXT, inferior_pid,
- (PTRACE_ARG3_TYPE) addr, 0);
+ buffer[i] = ptrace (PTRACE_PEEKTEXT, pid, (PTRACE_ARG3_TYPE) addr, 0);
if (errno)
return errno;
}
@@ -2043,6 +2290,7 @@ linux_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
= (((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));
+ int pid = lwpid_of (get_thread_lwp (current_inferior));
if (debug_threads)
{
@@ -2051,13 +2299,12 @@ linux_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
/* Fill start and end extra bytes of buffer with existing memory data. */
- buffer[0] = ptrace (PTRACE_PEEKTEXT, inferior_pid,
- (PTRACE_ARG3_TYPE) addr, 0);
+ buffer[0] = ptrace (PTRACE_PEEKTEXT, pid, (PTRACE_ARG3_TYPE) addr, 0);
if (count > 1)
{
buffer[count - 1]
- = ptrace (PTRACE_PEEKTEXT, inferior_pid,
+ = ptrace (PTRACE_PEEKTEXT, pid,
(PTRACE_ARG3_TYPE) (addr + (count - 1)
* sizeof (PTRACE_XFER_TYPE)),
0);
@@ -2072,7 +2319,7 @@ linux_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
{
errno = 0;
- ptrace (PTRACE_POKETEXT, inferior_pid, (PTRACE_ARG3_TYPE) addr, buffer[i]);
+ ptrace (PTRACE_POKETEXT, pid, (PTRACE_ARG3_TYPE) addr, buffer[i]);
if (errno)
return errno;
}
@@ -2278,10 +2525,13 @@ static void
linux_look_up_symbols (void)
{
#ifdef USE_THREAD_DB
- if (thread_db_active)
+ struct process_info *proc = current_process ();
+
+ if (proc->private->thread_db_active)
return;
- thread_db_active = thread_db_init (!linux_supports_tracefork_flag);
+ proc->private->thread_db_active
+ = thread_db_init (!linux_supports_tracefork_flag);
#endif
}
@@ -2290,7 +2540,8 @@ linux_request_interrupt (void)
{
extern unsigned long signal_pid;
- if (cont_thread != 0 && cont_thread != -1)
+ if (!ptid_equal (cont_thread, null_ptid)
+ && !ptid_equal (cont_thread, minus_one_ptid))
{
struct lwp_info *lwp;
int lwpid;
@@ -2311,8 +2562,9 @@ linux_read_auxv (CORE_ADDR offset, unsigned char *myaddr, unsigned int len)
{
char filename[PATH_MAX];
int fd, n;
+ int pid = lwpid_of (get_thread_lwp (current_inferior));
- snprintf (filename, sizeof filename, "/proc/%ld/auxv", inferior_pid);
+ snprintf (filename, sizeof filename, "/proc/%d/auxv", pid);
fd = open (filename, O_RDONLY);
if (fd < 0)
@@ -2685,7 +2937,6 @@ initialize_low (void)
{
struct sigaction sigchld_action;
memset (&sigchld_action, 0, sizeof (sigchld_action));
- thread_db_active = 0;
set_target_ops (&linux_target_ops);
set_breakpoint_data (the_low_target.breakpoint,
the_low_target.breakpoint_len);