From patchwork Tue May 7 23:42:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 89698 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 92A2F386F818 for ; Tue, 7 May 2024 23:47:13 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-wr1-f53.google.com (mail-wr1-f53.google.com [209.85.221.53]) by sourceware.org (Postfix) with ESMTPS id 974C43849ADB for ; Tue, 7 May 2024 23:44:06 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 974C43849ADB Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=palves.net Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 974C43849ADB Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=209.85.221.53 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1715125453; cv=none; b=YRqIr/ZqEzrY/TdOJPlffDt82URbQC+UYDaOP1vdvDWx0feq8w5wXMVwJTA6DAoDumQkWODjwMwJGjBNkMNzMMF79AhZhBHO5AJVqa+D1h9x14fl7RwraJAWkf6VrOF/tLK8GmqvR3rDftU7OgsWARY/87HysHOw7Z/9CMnYJTY= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1715125453; c=relaxed/simple; bh=SXW/C4aIX/WDZ3OIPSOdzLA47f8sHg7ZWFCxslx6M70=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=DQ9Cq9sRk6csIaPFUxITJgN0rpve8nERrkNv3vkq2JtXtH3jVGo9otE9YRrk/rDv60u3nvTGkCfFCPSk+tu4li2PIbe3X6K8r0bHaKDnKkWgl63gezr7VacP1gyoIvXwT3Rfy82gv3Of4gXF4qlPyR1TIZLnABdX3IZJv60VudM= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-wr1-f53.google.com with SMTP id ffacd0b85a97d-346359c8785so2784815f8f.0 for ; Tue, 07 May 2024 16:44:05 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1715125445; x=1715730245; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=q8ucj+eJbxQRgvxDBcz8zEMwNCXOXJylzbAI4pvSOXI=; b=gBcnjecZLQKhFgBOCvHAeUmTxtGaFTSHBKZeXrarl4x4E85WsH9adOkCs950gROph5 B3vywK6CzHba9eOyMOKUuwT/OHbWxQQe+daQeyqQbJGpXFZbdCztbOlLa2fFbh2zEGRf XVLft/vz+GX/EsXf9rsLD4s1JWpMWFmGv3PNPOg1fsebT9IoOlPl1chMnjn+kjjNKk07 AAkHKv2/i6Ng8gq5hlhdMOGIA02awWhXrBdvlaNiMjypa2FSra2Ilrj10Zz5tn4Rm+bD cOagmLeItiisB2tnyoIxrd7QirWJxS545dV5OKSc+drKM3mesoIQqE6vMCRZBVFif1Gy 8Slw== X-Gm-Message-State: AOJu0YydWqf5ahNE/8Z+Y5zyn+yaFm+pun9xcREooZiUo0Yf57u6x5l7 lJw26eprKbk/KxHTiRVschDFEjPNaKauDYAwvbmNTEu2yKxuFa9G4WVhTzSx X-Google-Smtp-Source: AGHT+IGclbZ0LQP1uOHoYyjCNyqw83MTiEszgOkPUou0t2FBxVkDaSQwro4eiRH7r75SRiO3/b9EUQ== X-Received: by 2002:a5d:60c7:0:b0:343:efb7:8748 with SMTP id ffacd0b85a97d-34fcb3acc24mr790786f8f.66.1715125444293; Tue, 07 May 2024 16:44:04 -0700 (PDT) Received: from localhost ([2001:8a0:f908:4900:2dd1:1a0d:2b75:dc42]) by smtp.gmail.com with UTF8SMTPSA id m3-20020adffa03000000b0034db974d7a1sm13913017wrr.81.2024.05.07.16.44.03 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 07 May 2024 16:44:03 -0700 (PDT) From: Pedro Alves To: gdb-patches@sourceware.org Subject: [PATCH 21/34] Windows gdb+gdbserver: Make current_event per-thread state Date: Wed, 8 May 2024 00:42:20 +0100 Message-ID: <20240507234233.371123-22-pedro@palves.net> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240507234233.371123-1-pedro@palves.net> References: <20240507234233.371123-1-pedro@palves.net> MIME-Version: 1.0 X-Spam-Status: No, score=-10.8 required=5.0 tests=BAYES_00, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, KAM_DMARC_STATUS, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org 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 --- gdb/nat/windows-nat.c | 13 ++-- gdb/nat/windows-nat.h | 24 ++++---- gdb/windows-nat.c | 136 ++++++++++++++++++++++------------------- gdbserver/win32-low.cc | 70 ++++++++++----------- gdbserver/win32-low.h | 5 +- 5 files changed, 129 insertions(+), 119 deletions(-) diff --git a/gdb/nat/windows-nat.c b/gdb/nat/windows-nat.c index 7f8834facd4..cabc61fb2d2 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 ¤t_event) { + const EXCEPTION_RECORD *rec = ¤t_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 ¤t_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 ¤t_event) { gdb_assert (current_event.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT); - LOAD_DLL_DEBUG_INFO *event = ¤t_event.u.LoadDll; + const LOAD_DLL_DEBUG_INFO *event = ¤t_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 70912fd6210..73c828ec2c9 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 ¤t_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 ¤t_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 ¤t_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 ¤t_event); /* Iterate over all DLLs currently mapped by our inferior, and add them to our list of solibs. */ @@ -222,7 +220,7 @@ struct windows_process_info 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 ¤t_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 5ebf53e2816..1a01ae57e54 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 ¤t_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 ¤t_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 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 @@ struct windows_nat_target final : public x86_nat_target 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 ¤t_event); BOOL windows_continue (DWORD continue_status, int id, windows_continue_flags cont_flags = 0); @@ -979,7 +981,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 ¤t_event) { LPVOID lpBaseOfDll = current_event.u.UnloadDll.lpBaseOfDll; @@ -1042,7 +1044,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 ¤t_event, + struct target_waitstatus *ourstatus) { DWORD thread_id = 0; @@ -1387,11 +1390,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 ¤t_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 @@ -1400,12 +1403,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 @@ -1422,6 +1424,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 @@ -1434,8 +1443,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); @@ -1452,7 +1460,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; @@ -1469,36 +1477,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; } } @@ -1562,7 +1562,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; @@ -1580,7 +1581,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 ()); @@ -1589,7 +1590,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) { @@ -1597,11 +1597,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) @@ -1619,7 +1619,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++; } @@ -1716,7 +1716,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) { @@ -1736,7 +1736,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) { @@ -1753,7 +1753,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: @@ -1775,7 +1776,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: @@ -1800,6 +1802,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 @@ -1818,8 +1822,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 @@ -1845,7 +1849,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, + ¤t_event); if ((options & TARGET_WNOHANG) != 0 && ourstatus->kind () == TARGET_WAITKIND_IGNORE) @@ -1864,11 +1871,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) { @@ -1909,8 +1916,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); @@ -1957,7 +1962,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)); @@ -2233,7 +2241,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); @@ -2244,7 +2252,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); } @@ -3041,9 +3049,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 (¤t_event); + if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break; } diff --git a/gdbserver/win32-low.cc b/gdbserver/win32-low.cc index 99a6150599e..5608fb902b1 100644 --- a/gdbserver/win32-low.cc +++ b/gdbserver/win32-low.cc @@ -309,9 +309,6 @@ do_initial_child_stuff (HANDLE proch, DWORD pid, int attached) windows_process.open_process_used = true; - memset (&windows_process.current_event, 0, - sizeof (windows_process.current_event)); - #ifdef __x86_64__ BOOL wow64; if (!IsWow64Process (proch, &wow64)) @@ -622,7 +619,8 @@ win32_process_target::attach (unsigned long pid) DWORD gdbserver_windows_process::handle_output_debug_string - (struct target_waitstatus *ourstatus) + (const DEBUG_EVENT ¤t_event, + struct target_waitstatus *ourstatus) { #define READ_BUFFER_LEN 1024 CORE_ADDR addr; @@ -691,14 +689,13 @@ win32_process_target::kill (process_info *process) { if (!child_continue_for_kill (DBG_CONTINUE, -1)) break; - if (!wait_for_debug_event (&windows_process.current_event, INFINITE)) + DEBUG_EVENT current_event; + if (!wait_for_debug_event (¤t_event, INFINITE)) break; - if (windows_process.current_event.dwDebugEventCode - == EXIT_PROCESS_DEBUG_EVENT) + if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break; - else if (windows_process.current_event.dwDebugEventCode - == OUTPUT_DEBUG_STRING_EVENT) - windows_process.handle_output_debug_string (nullptr); + else if (current_event.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT) + windows_process.handle_output_debug_string (current_event, nullptr); } win32_clear_inferiors (); @@ -772,8 +769,7 @@ resume_one_thread (thread_info *thread, bool step, gdb_signal sig, OUTMSG (("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) { OUTMSG (("Cannot continue with signal %s here. " "Not stopped for EXCEPTION_DEBUG_EVENT.\n", @@ -918,7 +914,7 @@ gdbserver_windows_process::handle_load_dll (const char *name, LPVOID base) /* See nat/windows-nat.h. */ void -gdbserver_windows_process::handle_unload_dll () +gdbserver_windows_process::handle_unload_dll (const DEBUG_EVENT ¤t_event) { CORE_ADDR load_addr = (CORE_ADDR) (uintptr_t) current_event.u.UnloadDll.lpBaseOfDll; @@ -952,7 +948,7 @@ gdbserver_windows_process::handle_access_violation PC. */ static void -maybe_adjust_pc () +maybe_adjust_pc (const DEBUG_EVENT ¤t_event) { struct regcache *regcache = get_thread_regcache (current_thread, 1); child_fetch_inferior_registers (regcache, -1); @@ -961,10 +957,10 @@ maybe_adjust_pc () = windows_process.find_thread (current_thread_ptid ()); th->stopped_at_software_breakpoint = false; - if (windows_process.current_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT - && ((windows_process.current_event.u.Exception.ExceptionRecord.ExceptionCode + if (current_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT + && ((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.child_initialization_done) { @@ -979,7 +975,8 @@ maybe_adjust_pc () static int get_child_debug_event (DWORD *continue_status, - struct target_waitstatus *ourstatus) + struct target_waitstatus *ourstatus, + DEBUG_EVENT *current_event) { ptid_t ptid; @@ -990,8 +987,6 @@ get_child_debug_event (DWORD *continue_status, /* Check if GDB sent us an interrupt request. */ check_remote_input_interrupt_request (); - DEBUG_EVENT *current_event = &windows_process.current_event; - windows_process.attaching = 0; { for (thread_info *thread : all_threads) @@ -1003,8 +998,8 @@ get_child_debug_event (DWORD *continue_status, { *ourstatus = th->pending_stop.status; th->pending_stop.status.set_ignore (); - windows_process.current_event = th->pending_stop.event; - ptid = debug_event_ptid (&windows_process.current_event); + *current_event = th->last_event; + ptid = debug_event_ptid (current_event); switch_to_thread (find_thread_ptid (ptid)); return 1; } @@ -1013,7 +1008,7 @@ get_child_debug_event (DWORD *continue_status, /* Keep the wait time low enough for comfortable remote interruption, but high enough so gdbserver doesn't become a bottleneck. */ - if (!wait_for_debug_event (&windows_process.current_event, 250)) + if (!wait_for_debug_event (current_event, 250)) { DWORD e = GetLastError(); @@ -1108,7 +1103,7 @@ get_child_debug_event (DWORD *continue_status, CloseHandle (current_event->u.LoadDll.hFile); if (! windows_process.child_initialization_done) break; - windows_process.dll_loaded_event (); + windows_process.dll_loaded_event (*current_event); ourstatus->set_loaded (); break; @@ -1120,7 +1115,7 @@ get_child_debug_event (DWORD *continue_status, (unsigned) current_event->dwThreadId)); if (! windows_process.child_initialization_done) break; - windows_process.handle_unload_dll (); + windows_process.handle_unload_dll (*current_event); ourstatus->set_loaded (); break; @@ -1129,7 +1124,8 @@ get_child_debug_event (DWORD *continue_status, "for pid=%u tid=%x\n", (unsigned) current_event->dwProcessId, (unsigned) current_event->dwThreadId)); - if (windows_process.handle_exception (ourstatus, debug_threads) + if (windows_process.handle_exception (*current_event, + ourstatus, debug_threads) == HANDLE_EXCEPTION_UNHANDLED) *continue_status = DBG_EXCEPTION_NOT_HANDLED; break; @@ -1140,7 +1136,7 @@ get_child_debug_event (DWORD *continue_status, "for pid=%u tid=%x\n", (unsigned) current_event->dwProcessId, (unsigned) current_event->dwThreadId)); - windows_process.handle_output_debug_string (nullptr); + windows_process.handle_output_debug_string (*current_event, nullptr); break; default: @@ -1152,10 +1148,12 @@ get_child_debug_event (DWORD *continue_status, break; } - ptid = debug_event_ptid (&windows_process.current_event); + ptid = debug_event_ptid (current_event); windows_thread_info *th = windows_process.find_thread (ptid); + th->last_event = *current_event; + if (th != nullptr && th->suspended) { /* Pending stop. See the comment by the definition of @@ -1164,9 +1162,8 @@ get_child_debug_event (DWORD *continue_status, OUTMSG2 (("get_windows_debug_event - " "unexpected stop in suspended thread 0x%x\n", th->tid)); - maybe_adjust_pc (); + maybe_adjust_pc (*current_event); th->pending_stop.status = *ourstatus; - th->pending_stop.event = *current_event; ourstatus->set_spurious (); } else @@ -1190,13 +1187,16 @@ win32_process_target::wait (ptid_t ptid, target_waitstatus *ourstatus, fails). Report it now. */ *ourstatus = windows_process.cached_status; windows_process.cached_status.set_ignore (); - return debug_event_ptid (&windows_process.current_event); + return ptid_t (windows_process.process_id, + windows_process.main_thread_id, 0); } while (1) { DWORD continue_status; - if (!get_child_debug_event (&continue_status, ourstatus)) + DEBUG_EVENT current_event; + if (!get_child_debug_event (&continue_status, ourstatus, + ¤t_event)) continue; switch (ourstatus->kind ()) @@ -1205,20 +1205,20 @@ win32_process_target::wait (ptid_t ptid, target_waitstatus *ourstatus, OUTMSG2 (("Child exited with retcode = %x\n", ourstatus->exit_status ())); win32_clear_inferiors (); - return ptid_t (windows_process.current_event.dwProcessId); + return ptid_t (windows_process.process_id); case TARGET_WAITKIND_STOPPED: case TARGET_WAITKIND_SIGNALLED: case TARGET_WAITKIND_LOADED: { OUTMSG2 (("Child Stopped with signal = %d \n", ourstatus->sig ())); - maybe_adjust_pc (); + maybe_adjust_pc (current_event); /* All-stop, suspend all threads until they are explicitly resumed. */ for_each_thread (suspend_one_thread); - return debug_event_ptid (&windows_process.current_event); + return debug_event_ptid (¤t_event); } default: OUTMSG (("Ignoring unknown internal event, %d\n", diff --git a/gdbserver/win32-low.h b/gdbserver/win32-low.h index 4d26b87d73d..e99e47ea829 100644 --- a/gdbserver/win32-low.h +++ b/gdbserver/win32-low.h @@ -175,9 +175,10 @@ class win32_process_target : public process_stratum_target struct gdbserver_windows_process : public windows_nat::windows_process_info { windows_nat::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 ¤t_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 ¤t_event) override; bool handle_access_violation (const EXCEPTION_RECORD *rec) override; int attaching = 0;