diff options
author | Pedro Alves <pedro@palves.net> | 2022-04-05 13:57:11 +0100 |
---|---|---|
committer | Pedro Alves <pedro@palves.net> | 2022-05-03 15:10:22 +0100 |
commit | 7f8acedeebe295fc8cc1d11ed971cbfc1942618c (patch) | |
tree | b07af08ce2cf645c90836a4bcf77c3a68c475780 /gdbserver/target.cc | |
parent | f4138e8f48948314d1049e713f4b793eec9757ca (diff) | |
download | gdb-7f8acedeebe295fc8cc1d11ed971cbfc1942618c.zip gdb-7f8acedeebe295fc8cc1d11ed971cbfc1942618c.tar.gz gdb-7f8acedeebe295fc8cc1d11ed971cbfc1942618c.tar.bz2 |
gdbserver: track current process as well as current thread
The recent commit 421490af33bf ("gdbserver/linux: Access memory even
if threads are running") caused a regression in
gdb.threads/access-mem-running-thread-exit.exp with gdbserver, which I
somehow missed. Like so:
(gdb) print global_var
Cannot access memory at address 0x555555558010
(gdb) FAIL: gdb.threads/access-mem-running-thread-exit.exp: non-stop: access mem (print global_var after writing, inf=2, iter=1)
The problem starts with GDB telling GDBserver to select a thread, via
the Hg packet, which GDBserver complies with, then that thread exits,
and GDB, without knowing the thread is gone, tries to write to memory,
through the context of the previously selected Hg thread.
GDBserver's GDB-facing memory access routines, gdb_read_memory and
gdb_write_memory, call set_desired_thread to make GDBserver re-select
the thread that GDB has selected with the Hg packet. Since the thread
is gone, set_desired_thread returns false, and the memory access
fails.
Now, to access memory, it doesn't really matter which thread is
selected. All we should need is the target process. Even if the
thread that GDB previously selected is gone, and GDB does not yet know
about that exit, it shouldn't matter, GDBserver should still know
which process that thread belonged to.
Fix this by making GDBserver track the current process separately,
like GDB also does. Add a new set_desired_process routine that is
similar to set_desired_thread, but just sets the current process,
leaving the current thread as NULL. Use it in the GDB-facing memory
read and write routines, to avoid failing if the selected thread is
gone, but the process is still around.
Change-Id: I4ff97cb6f42558efbed224b30d5c71f6112d44cd
Diffstat (limited to 'gdbserver/target.cc')
-rw-r--r-- | gdbserver/target.cc | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/gdbserver/target.cc b/gdbserver/target.cc index 8832423..adcfe6e 100644 --- a/gdbserver/target.cc +++ b/gdbserver/target.cc @@ -29,16 +29,56 @@ process_stratum_target *the_target; -int +/* See target.h. */ + +bool set_desired_thread () { client_state &cs = get_client_state (); thread_info *found = find_thread_ptid (cs.general_thread); - switch_to_thread (found); + if (found == nullptr) + { + process_info *proc = find_process_pid (cs.general_thread.pid ()); + if (proc == nullptr) + { + threads_debug_printf + ("did not find thread nor process for general_thread %s", + cs.general_thread.to_string ().c_str ()); + } + else + { + threads_debug_printf + ("did not find thread for general_thread %s, but found process", + cs.general_thread.to_string ().c_str ()); + } + switch_to_process (proc); + } + else + switch_to_thread (found); + return (current_thread != NULL); } +/* See target.h. */ + +bool +set_desired_process () +{ + client_state &cs = get_client_state (); + + process_info *proc = find_process_pid (cs.general_thread.pid ()); + if (proc == nullptr) + { + threads_debug_printf + ("did not find process for general_thread %s", + cs.general_thread.to_string ().c_str ()); + } + switch_to_process (proc); + + return proc != nullptr; +} + int read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len) { |