aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdbserver/ChangeLog11
-rw-r--r--gdbserver/inferiors.cc10
-rw-r--r--gdbserver/inferiors.h3
-rw-r--r--gdbserver/server.cc49
-rw-r--r--gdbserver/thread-db.cc8
5 files changed, 68 insertions, 13 deletions
diff --git a/gdbserver/ChangeLog b/gdbserver/ChangeLog
index d924e72..f42b5c7 100644
--- a/gdbserver/ChangeLog
+++ b/gdbserver/ChangeLog
@@ -1,3 +1,14 @@
+2020-07-22 Pedro Alves <pedro@palves.net>
+
+ * inferiors.cc (switch_to_process): New, moved here from
+ thread-db.cc, and made extern.
+ * inferiors.h (switch_to_process): Declare.
+ * server.cc: Include "gdbsupport/scoped_restore.h".
+ (handle_qxfer_threads_proper): Now returns bool. Prepare to
+ access memory around target calls.
+ (handle_qxfer_threads): Handle errors.
+ * thread-db.cc (switch_to_process): Moved to inferiors.cc.
+
2020-07-21 Simon Marchi <simon.marchi@efficios.com>
* linux-low.cc (stopped_pids): Make static.
diff --git a/gdbserver/inferiors.cc b/gdbserver/inferiors.cc
index 88adb16..861c9f3 100644
--- a/gdbserver/inferiors.cc
+++ b/gdbserver/inferiors.cc
@@ -223,6 +223,16 @@ switch_to_thread (process_stratum_target *ops, ptid_t ptid)
current_thread = find_thread_ptid (ptid);
}
+/* See inferiors.h. */
+
+void
+switch_to_process (process_info *proc)
+{
+ int pid = pid_of (proc);
+
+ current_thread = find_any_thread_of_pid (pid);
+}
+
/* See gdbsupport/common-inferior.h. */
const char *
diff --git a/gdbserver/inferiors.h b/gdbserver/inferiors.h
index 4e24b2c..bf2a16f 100644
--- a/gdbserver/inferiors.h
+++ b/gdbserver/inferiors.h
@@ -138,6 +138,9 @@ struct process_info *find_process_pid (int pid);
int have_started_inferiors_p (void);
int have_attached_inferiors_p (void);
+/* Switch to a thread of PROC. */
+void switch_to_process (process_info *proc);
+
void clear_inferiors (void);
void *thread_target_data (struct thread_info *);
diff --git a/gdbserver/server.cc b/gdbserver/server.cc
index ab5363e..aadcb9b 100644
--- a/gdbserver/server.cc
+++ b/gdbserver/server.cc
@@ -48,6 +48,7 @@
#include "gdbsupport/selftest.h"
#include "gdbsupport/scope-exit.h"
#include "gdbsupport/gdb_select.h"
+#include "gdbsupport/scoped_restore.h"
#define require_running_or_return(BUF) \
if (!target_running ()) \
@@ -1678,19 +1679,54 @@ handle_qxfer_threads_worker (thread_info *thread, struct buffer *buffer)
buffer_xml_printf (buffer, "/>\n");
}
-/* Helper for handle_qxfer_threads. */
+/* Helper for handle_qxfer_threads. Return true on success, false
+ otherwise. */
-static void
+static bool
handle_qxfer_threads_proper (struct buffer *buffer)
{
+ client_state &cs = get_client_state ();
+
+ scoped_restore save_current_thread
+ = make_scoped_restore (&current_thread);
+ scoped_restore save_current_general_thread
+ = make_scoped_restore (&cs.general_thread);
+
buffer_grow_str (buffer, "<threads>\n");
- for_each_thread ([&] (thread_info *thread)
+ process_info *error_proc = find_process ([&] (process_info *process)
{
- handle_qxfer_threads_worker (thread, buffer);
+ /* The target may need to access memory and registers (e.g. via
+ libthread_db) to fetch thread properties. Prepare for memory
+ access here, so that we potentially pause threads just once
+ for all accesses. Note that even if someday we stop needing
+ to pause threads to access memory, we will need to be able to
+ access registers, or other ptrace accesses like
+ PTRACE_GET_THREAD_AREA. */
+
+ /* Need to switch to each process in turn, because
+ prepare_to_access_memory prepares for an access in the
+ current process pointed to by general_thread. */
+ switch_to_process (process);
+ cs.general_thread = current_thread->id;
+
+ int res = prepare_to_access_memory ();
+ if (res == 0)
+ {
+ for_each_thread (process->pid, [&] (thread_info *thread)
+ {
+ handle_qxfer_threads_worker (thread, buffer);
+ });
+
+ done_accessing_memory ();
+ return false;
+ }
+ else
+ return true;
});
buffer_grow_str0 (buffer, "</threads>\n");
+ return error_proc == nullptr;
}
/* Handle qXfer:threads:read. */
@@ -1719,11 +1755,14 @@ handle_qxfer_threads (const char *annex,
buffer_init (&buffer);
- handle_qxfer_threads_proper (&buffer);
+ bool res = handle_qxfer_threads_proper (&buffer);
result = buffer_finish (&buffer);
result_length = strlen (result);
buffer_free (&buffer);
+
+ if (!res)
+ return -1;
}
if (offset >= result_length)
diff --git a/gdbserver/thread-db.cc b/gdbserver/thread-db.cc
index 89c45cd..32dc376 100644
--- a/gdbserver/thread-db.cc
+++ b/gdbserver/thread-db.cc
@@ -767,14 +767,6 @@ thread_db_init (void)
return 0;
}
-static void
-switch_to_process (struct process_info *proc)
-{
- int pid = pid_of (proc);
-
- current_thread = find_any_thread_of_pid (pid);
-}
-
/* Disconnect from libthread_db and free resources. */
static void