diff options
-rw-r--r-- | gdbserver/ChangeLog | 11 | ||||
-rw-r--r-- | gdbserver/inferiors.cc | 10 | ||||
-rw-r--r-- | gdbserver/inferiors.h | 3 | ||||
-rw-r--r-- | gdbserver/server.cc | 49 | ||||
-rw-r--r-- | gdbserver/thread-db.cc | 8 |
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 (¤t_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 |