aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorPedro Alves <pedro@palves.net>2021-10-21 18:16:58 +0100
committerPedro Alves <pedro@palves.net>2024-05-10 11:26:00 +0100
commitf428cac6151a5fb66812be52fd05b8eae8a164cd (patch)
tree42d6d3f7ea196ea9ef9ba8ed864e52b595f5f9c2 /gdb
parent11adfeba325cf8d28aa89f8652935a9e2d9e37ee (diff)
downloadbinutils-f428cac6151a5fb66812be52fd05b8eae8a164cd.zip
binutils-f428cac6151a5fb66812be52fd05b8eae8a164cd.tar.gz
binutils-f428cac6151a5fb66812be52fd05b8eae8a164cd.tar.bz2
Windows gdb+gdbserver: Make current_event per-thread state
With non-stop mode, each thread is controlled independently of the others, and each thread has its own independent reason for its last stop. Thus, any thread-specific state that is currently per-process must be converted to per-thread state. This patch converts windows_process_info::current_event, moving it to windows_thread_info instead, renamed to last_event. Since each thread will have its own copy of its last Windows debug event, we no longer need the same information stored in struct pending_stop. Since windows_process.current_event no longer exists, we need to pass the current event as parameter to a number of methods. This adjusts both native gdb and gdbserver. Change-Id: Ice09a5d932c912210608d5af25e1898f823e3c99
Diffstat (limited to 'gdb')
-rw-r--r--gdb/nat/windows-nat.c13
-rw-r--r--gdb/nat/windows-nat.h24
-rw-r--r--gdb/windows-nat.c136
3 files changed, 91 insertions, 82 deletions
diff --git a/gdb/nat/windows-nat.c b/gdb/nat/windows-nat.c
index 7f8834f..cabc61f 100644
--- a/gdb/nat/windows-nat.c
+++ b/gdb/nat/windows-nat.c
@@ -310,8 +310,10 @@ get_image_name (HANDLE h, void *address, int unicode)
/* See nat/windows-nat.h. */
bool
-windows_process_info::handle_ms_vc_exception (const EXCEPTION_RECORD *rec)
+windows_process_info::handle_ms_vc_exception (const DEBUG_EVENT &current_event)
{
+ const EXCEPTION_RECORD *rec = &current_event.u.Exception.ExceptionRecord;
+
if (rec->NumberParameters >= 3
&& (rec->ExceptionInformation[0] & 0xffffffff) == 0x1000)
{
@@ -352,7 +354,8 @@ windows_process_info::handle_ms_vc_exception (const EXCEPTION_RECORD *rec)
#define MS_VC_EXCEPTION 0x406d1388
handle_exception_result
-windows_process_info::handle_exception (struct target_waitstatus *ourstatus,
+windows_process_info::handle_exception (DEBUG_EVENT &current_event,
+ struct target_waitstatus *ourstatus,
bool debug_exceptions)
{
#define DEBUG_EXCEPTION_SIMPLE(x) if (debug_exceptions) \
@@ -480,7 +483,7 @@ windows_process_info::handle_exception (struct target_waitstatus *ourstatus,
break;
case MS_VC_EXCEPTION:
DEBUG_EXCEPTION_SIMPLE ("MS_VC_EXCEPTION");
- if (handle_ms_vc_exception (rec))
+ if (handle_ms_vc_exception (current_event))
{
ourstatus->set_stopped (GDB_SIGNAL_TRAP);
result = HANDLE_EXCEPTION_IGNORED;
@@ -634,11 +637,11 @@ windows_process_info::add_dll (LPVOID load_addr)
/* See nat/windows-nat.h. */
void
-windows_process_info::dll_loaded_event ()
+windows_process_info::dll_loaded_event (const DEBUG_EVENT &current_event)
{
gdb_assert (current_event.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT);
- LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
+ const LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
const char *dll_name;
/* Try getting the DLL name via the lpImageName field of the event.
diff --git a/gdb/nat/windows-nat.h b/gdb/nat/windows-nat.h
index 70912fd..73c828e 100644
--- a/gdb/nat/windows-nat.h
+++ b/gdb/nat/windows-nat.h
@@ -40,10 +40,6 @@ struct pending_stop
/* The target waitstatus we computed. TARGET_WAITKIND_IGNORE if the
thread does not have a pending stop. */
target_waitstatus status;
-
- /* The event. A few fields of this can be referenced after a stop,
- and it seemed simplest to store the entire event. */
- DEBUG_EVENT event;
};
@@ -98,6 +94,10 @@ struct windows_thread_info
process them once the step has completed. See PR gdb/22992. */
struct pending_stop pending_stop {};
+ /* The last Windows event returned by WaitForDebugEvent for this
+ thread. */
+ DEBUG_EVENT last_event {};
+
/* The context of the thread, including any manipulations. */
union
{
@@ -143,10 +143,6 @@ struct windows_process_info
DWORD main_thread_id = 0;
enum gdb_signal last_sig = GDB_SIGNAL_0;
- /* The current debug event from WaitForDebugEvent or from a pending
- stop. */
- DEBUG_EVENT current_event {};
-
/* Contents of $_siginfo */
EXCEPTION_RECORD siginfo_er {};
@@ -170,7 +166,8 @@ struct windows_process_info
a Cygwin signal. Otherwise just print the string as a warning.
This function must be supplied by the embedding application. */
- virtual DWORD handle_output_debug_string (struct target_waitstatus *ourstatus) = 0;
+ virtual DWORD handle_output_debug_string (const DEBUG_EVENT &current_event,
+ struct target_waitstatus *ourstatus) = 0;
/* Handle a DLL load event.
@@ -191,7 +188,7 @@ struct windows_process_info
This function must be supplied by the embedding application. */
- virtual void handle_unload_dll () = 0;
+ virtual void handle_unload_dll (const DEBUG_EVENT &current_event) = 0;
/* When EXCEPTION_ACCESS_VIOLATION is processed, we give the embedding
application a chance to change it to be considered "unhandled".
@@ -201,11 +198,12 @@ struct windows_process_info
virtual bool handle_access_violation (const EXCEPTION_RECORD *rec) = 0;
handle_exception_result handle_exception
- (struct target_waitstatus *ourstatus, bool debug_exceptions);
+ (DEBUG_EVENT &current_event,
+ struct target_waitstatus *ourstatus, bool debug_exceptions);
/* Call to indicate that a DLL was loaded. */
- void dll_loaded_event ();
+ void dll_loaded_event (const DEBUG_EVENT &current_event);
/* Iterate over all DLLs currently mapped by our inferior, and
add them to our list of solibs. */
@@ -222,7 +220,7 @@ private:
Return true if the exception was handled; return false otherwise. */
- bool handle_ms_vc_exception (const EXCEPTION_RECORD *rec);
+ bool handle_ms_vc_exception (const DEBUG_EVENT &current_event);
/* Iterate over all DLLs currently mapped by our inferior, looking for
a DLL which is loaded at LOAD_ADDR. If found, add the DLL to our
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 2913da6..bba8468 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -107,9 +107,10 @@ DEF_ENUM_FLAGS_TYPE (windows_continue_flag, windows_continue_flags);
struct windows_per_inferior : public windows_process_info
{
windows_thread_info *find_thread (ptid_t ptid) override;
- DWORD handle_output_debug_string (struct target_waitstatus *ourstatus) override;
+ DWORD handle_output_debug_string (const DEBUG_EVENT &current_event,
+ struct target_waitstatus *ourstatus) override;
void handle_load_dll (const char *dll_name, LPVOID base) override;
- void handle_unload_dll () override;
+ void handle_unload_dll (const DEBUG_EVENT &current_event) override;
bool handle_access_violation (const EXCEPTION_RECORD *rec) override;
void invalidate_context (windows_thread_info *th);
@@ -321,7 +322,8 @@ struct windows_nat_target final : public x86_nat_target<inf_child_target>
const char *thread_name (struct thread_info *) override;
ptid_t get_windows_debug_event (int pid, struct target_waitstatus *ourstatus,
- target_wait_flags options);
+ target_wait_flags options,
+ DEBUG_EVENT *current_event);
void do_initial_windows_stuff (DWORD pid, bool attaching);
@@ -352,7 +354,7 @@ private:
windows_thread_info *add_thread (ptid_t ptid, HANDLE h, void *tlb,
bool main_thread_p);
void delete_thread (ptid_t ptid, DWORD exit_code, bool main_thread_p);
- DWORD fake_create_process ();
+ DWORD fake_create_process (const DEBUG_EVENT &current_event);
BOOL windows_continue (DWORD continue_status, int id,
windows_continue_flags cont_flags = 0);
@@ -980,7 +982,7 @@ windows_per_inferior::handle_load_dll (const char *dll_name, LPVOID base)
/* See nat/windows-nat.h. */
void
-windows_per_inferior::handle_unload_dll ()
+windows_per_inferior::handle_unload_dll (const DEBUG_EVENT &current_event)
{
LPVOID lpBaseOfDll = current_event.u.UnloadDll.lpBaseOfDll;
@@ -1043,7 +1045,8 @@ signal_event_command (const char *args, int from_tty)
DWORD
windows_per_inferior::handle_output_debug_string
- (struct target_waitstatus *ourstatus)
+ (const DEBUG_EVENT &current_event,
+ struct target_waitstatus *ourstatus)
{
DWORD thread_id = 0;
@@ -1388,11 +1391,11 @@ windows_nat_target::windows_continue (DWORD continue_status, int id,
/* Called in pathological case where Windows fails to send a
CREATE_PROCESS_DEBUG_EVENT after an attach. */
DWORD
-windows_nat_target::fake_create_process ()
+windows_nat_target::fake_create_process (const DEBUG_EVENT &current_event)
{
windows_process.handle
= OpenProcess (PROCESS_ALL_ACCESS, FALSE,
- windows_process.current_event.dwProcessId);
+ current_event.dwProcessId);
if (windows_process.handle != NULL)
windows_process.open_process_used = 1;
else
@@ -1401,12 +1404,11 @@ windows_nat_target::fake_create_process ()
throw_winerror_with_name (_("OpenProcess call failed"), err);
/* We can not debug anything in that case. */
}
- add_thread (ptid_t (windows_process.current_event.dwProcessId,
- windows_process.current_event.dwThreadId, 0),
- windows_process.current_event.u.CreateThread.hThread,
- windows_process.current_event.u.CreateThread.lpThreadLocalBase,
+ add_thread (ptid_t (current_event.dwProcessId, current_event.dwThreadId, 0),
+ current_event.u.CreateThread.hThread,
+ current_event.u.CreateThread.lpThreadLocalBase,
true /* main_thread_p */);
- return windows_process.current_event.dwThreadId;
+ return current_event.dwThreadId;
}
void
@@ -1423,6 +1425,13 @@ windows_nat_target::resume (ptid_t ptid, int step, enum gdb_signal sig)
if (resume_all)
ptid = inferior_ptid;
+ DEBUG_EXEC ("pid=%d, tid=0x%x, step=%d, sig=%d",
+ ptid.pid (), (unsigned) ptid.lwp (), step, sig);
+
+ /* Get currently selected thread. */
+ th = windows_process.find_thread (inferior_ptid);
+ gdb_assert (th != nullptr);
+
if (sig != GDB_SIGNAL_0)
{
/* Note it is OK to call get_last_debug_event_ptid() from the
@@ -1435,8 +1444,7 @@ windows_nat_target::resume (ptid_t ptid, int step, enum gdb_signal sig)
DEBUG_EXCEPT ("Cannot continue with signal %d here. "
"Not last-event thread", sig);
}
- else if (windows_process.current_event.dwDebugEventCode
- != EXCEPTION_DEBUG_EVENT)
+ else if (th->last_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT)
{
DEBUG_EXCEPT ("Cannot continue with signal %d here. "
"Not stopped for EXCEPTION_DEBUG_EVENT", sig);
@@ -1453,7 +1461,7 @@ windows_nat_target::resume (ptid_t ptid, int step, enum gdb_signal sig)
for (const xlate_exception &x : xlate)
if (x.us == sig)
{
- current_event.u.Exception.ExceptionRecord.ExceptionCode
+ th->last_event.u.Exception.ExceptionRecord.ExceptionCode
= x.them;
continue_status = DBG_EXCEPTION_NOT_HANDLED;
break;
@@ -1470,36 +1478,28 @@ windows_nat_target::resume (ptid_t ptid, int step, enum gdb_signal sig)
windows_process.last_sig = GDB_SIGNAL_0;
- DEBUG_EXEC ("pid=%d, tid=0x%x, step=%d, sig=%d",
- ptid.pid (), (unsigned) ptid.lwp (), step, sig);
-
- /* Get context for currently selected thread. */
- th = windows_process.find_thread (inferior_ptid);
- if (th)
- {
#ifdef __x86_64__
- if (windows_process.wow64_process)
+ if (windows_process.wow64_process)
+ {
+ if (step)
{
- if (step)
- {
- /* Single step by setting t bit. */
- regcache *regcache = get_thread_regcache (inferior_thread ());
- struct gdbarch *gdbarch = regcache->arch ();
- fetch_registers (regcache, gdbarch_ps_regnum (gdbarch));
- th->wow64_context.EFlags |= FLAG_TRACE_BIT;
- }
+ /* Single step by setting t bit. */
+ regcache *regcache = get_thread_regcache (inferior_thread ());
+ struct gdbarch *gdbarch = regcache->arch ();
+ fetch_registers (regcache, gdbarch_ps_regnum (gdbarch));
+ th->wow64_context.EFlags |= FLAG_TRACE_BIT;
}
- else
+ }
+ else
#endif
+ {
+ if (step)
{
- if (step)
- {
- /* Single step by setting t bit. */
- regcache *regcache = get_thread_regcache (inferior_thread ());
- struct gdbarch *gdbarch = regcache->arch ();
- fetch_registers (regcache, gdbarch_ps_regnum (gdbarch));
- th->context.EFlags |= FLAG_TRACE_BIT;
- }
+ /* Single step by setting t bit. */
+ regcache *regcache = get_thread_regcache (inferior_thread ());
+ struct gdbarch *gdbarch = regcache->arch ();
+ fetch_registers (regcache, gdbarch_ps_regnum (gdbarch));
+ th->context.EFlags |= FLAG_TRACE_BIT;
}
}
@@ -1563,7 +1563,8 @@ windows_nat_target::pass_ctrlc ()
ptid_t
windows_nat_target::get_windows_debug_event
- (int pid, struct target_waitstatus *ourstatus, target_wait_flags options)
+ (int pid, struct target_waitstatus *ourstatus, target_wait_flags options,
+ DEBUG_EVENT *current_event)
{
DWORD continue_status, event_code;
DWORD thread_id = 0;
@@ -1581,7 +1582,7 @@ windows_nat_target::get_windows_debug_event
thread_id = th->tid;
*ourstatus = th->pending_stop.status;
th->pending_stop.status.set_ignore ();
- windows_process.current_event = th->pending_stop.event;
+ *current_event = th->last_event;
ptid_t ptid (windows_process.process_id, thread_id);
windows_process.invalidate_context (th.get ());
@@ -1590,7 +1591,6 @@ windows_nat_target::get_windows_debug_event
}
windows_process.last_sig = GDB_SIGNAL_0;
- DEBUG_EVENT *current_event = &windows_process.current_event;
if ((options & TARGET_WNOHANG) != 0 && !m_debug_event_pending)
{
@@ -1598,11 +1598,11 @@ windows_nat_target::get_windows_debug_event
return minus_one_ptid;
}
- wait_for_debug_event_main_thread (&windows_process.current_event);
+ wait_for_debug_event_main_thread (current_event);
continue_status = DBG_CONTINUE;
- event_code = windows_process.current_event.dwDebugEventCode;
+ event_code = current_event->dwDebugEventCode;
ourstatus->set_spurious ();
switch (event_code)
@@ -1620,7 +1620,7 @@ windows_nat_target::get_windows_debug_event
/* Kludge around a Windows bug where first event is a create
thread event. Caused when attached process does not have
a main thread. */
- thread_id = fake_create_process ();
+ thread_id = fake_create_process (*current_event);
if (thread_id)
windows_process.saw_create++;
}
@@ -1717,7 +1717,7 @@ windows_nat_target::get_windows_debug_event
break;
try
{
- windows_process.dll_loaded_event ();
+ windows_process.dll_loaded_event (*current_event);
}
catch (const gdb_exception &ex)
{
@@ -1737,7 +1737,7 @@ windows_nat_target::get_windows_debug_event
break;
try
{
- windows_process.handle_unload_dll ();
+ windows_process.handle_unload_dll (*current_event);
}
catch (const gdb_exception &ex)
{
@@ -1754,7 +1754,8 @@ windows_nat_target::get_windows_debug_event
"EXCEPTION_DEBUG_EVENT");
if (windows_process.saw_create != 1)
break;
- switch (windows_process.handle_exception (ourstatus, debug_exceptions))
+ switch (windows_process.handle_exception (*current_event,
+ ourstatus, debug_exceptions))
{
case HANDLE_EXCEPTION_UNHANDLED:
default:
@@ -1776,7 +1777,8 @@ windows_nat_target::get_windows_debug_event
"OUTPUT_DEBUG_STRING_EVENT");
if (windows_process.saw_create != 1)
break;
- thread_id = windows_process.handle_output_debug_string (ourstatus);
+ thread_id = windows_process.handle_output_debug_string (*current_event,
+ ourstatus);
break;
default:
@@ -1801,6 +1803,8 @@ windows_nat_target::get_windows_debug_event
const ptid_t ptid = ptid_t (current_event->dwProcessId, thread_id, 0);
windows_thread_info *th = windows_process.find_thread (ptid);
+ th->last_event = *current_event;
+
if (th->suspended)
{
/* Pending stop. See the comment by the definition of
@@ -1819,8 +1823,8 @@ windows_nat_target::get_windows_debug_event
th->stopped_at_software_breakpoint = true;
th->pc_adjusted = false;
}
+
th->pending_stop.status = *ourstatus;
- th->pending_stop.event = *current_event;
ourstatus->set_ignore ();
continue_last_debug_event_main_thread
@@ -1846,7 +1850,10 @@ windows_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
while (1)
{
- ptid_t result = get_windows_debug_event (pid, ourstatus, options);
+ DEBUG_EVENT current_event;
+
+ ptid_t result = get_windows_debug_event (pid, ourstatus, options,
+ &current_event);
if ((options & TARGET_WNOHANG) != 0
&& ourstatus->kind () == TARGET_WAITKIND_IGNORE)
@@ -1865,11 +1872,11 @@ windows_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
windows_thread_info *th = windows_process.find_thread (result);
th->stopped_at_software_breakpoint = false;
- if (windows_process.current_event.dwDebugEventCode
+ if (current_event.dwDebugEventCode
== EXCEPTION_DEBUG_EVENT
- && ((windows_process.current_event.u.Exception.ExceptionRecord.ExceptionCode
+ && ((current_event.u.Exception.ExceptionRecord.ExceptionCode
== EXCEPTION_BREAKPOINT)
- || (windows_process.current_event.u.Exception.ExceptionRecord.ExceptionCode
+ || (current_event.u.Exception.ExceptionRecord.ExceptionCode
== STATUS_WX86_BREAKPOINT))
&& windows_process.windows_initialization_done)
{
@@ -1910,8 +1917,6 @@ windows_nat_target::do_initial_windows_stuff (DWORD pid, bool attaching)
windows_process.cygwin_load_end = 0;
#endif
windows_process.process_id = pid;
- memset (&windows_process.current_event, 0,
- sizeof (windows_process.current_event));
inf = current_inferior ();
if (!inf->target_is_pushed (this))
inf->push_target (this);
@@ -1958,7 +1963,10 @@ windows_nat_target::do_initial_windows_stuff (DWORD pid, bool attaching)
&& status.kind () != TARGET_WAITKIND_SPURIOUS)
break;
- this->resume (minus_one_ptid, 0, GDB_SIGNAL_0);
+ /* Don't use windows_nat_target::resume here because that
+ assumes that inferior_ptid points at a valid thread, and we
+ haven't switched to any thread yet. */
+ windows_continue (DBG_CONTINUE, -1);
}
switch_to_thread (this->find_thread (last_ptid));
@@ -2234,7 +2242,7 @@ windows_nat_target::detach (inferior *inf, int from_tty)
if (process_alive)
do_synchronously ([&] ()
{
- if (!DebugActiveProcessStop (windows_process.current_event.dwProcessId))
+ if (!DebugActiveProcessStop (windows_process.process_id))
err = (unsigned) GetLastError ();
else
DebugSetProcessKillOnExit (FALSE);
@@ -2245,7 +2253,7 @@ windows_nat_target::detach (inferior *inf, int from_tty)
{
std::string msg
= string_printf (_("Can't detach process %u"),
- (unsigned) windows_process.current_event.dwProcessId);
+ windows_process.process_id);
throw_winerror_with_name (msg.c_str (), *err);
}
@@ -3042,9 +3050,9 @@ windows_nat_target::kill ()
{
if (!windows_continue (DBG_CONTINUE, -1, WCONT_KILLED))
break;
- wait_for_debug_event_main_thread (&windows_process.current_event);
- if (windows_process.current_event.dwDebugEventCode
- == EXIT_PROCESS_DEBUG_EVENT)
+ DEBUG_EVENT current_event;
+ wait_for_debug_event_main_thread (&current_event);
+ if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
break;
}