From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id CUTSDlWVa2kYxwcAWB0awg (envelope-from ) for ; Sat, 17 Jan 2026 08:57:41 -0500 Authentication-Results: simark.ca; dkim=pass (2048-bit key; unprotected) header.d=yahoo.de header.i=@yahoo.de header.a=rsa-sha256 header.s=s2048 header.b=rRjicOEN; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 3221D1E0E7; Sat, 17 Jan 2026 08:57:41 -0500 (EST) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-2.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,RCVD_IN_VALIDITY_CERTIFIED_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED,RCVD_IN_VALIDITY_SAFE_BLOCKED autolearn=ham autolearn_force=no version=4.0.1 Received: from vm01.sourceware.org (vm01.sourceware.org [38.145.34.32]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 2CA0A1E070 for ; Sat, 17 Jan 2026 08:57:40 -0500 (EST) Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id A6F5D4BA23F8 for ; Sat, 17 Jan 2026 13:57:39 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A6F5D4BA23F8 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=yahoo.de header.i=@yahoo.de header.a=rsa-sha256 header.s=s2048 header.b=rRjicOEN Received: from sonic306-20.consmr.mail.ir2.yahoo.com (sonic306-20.consmr.mail.ir2.yahoo.com [77.238.176.206]) by sourceware.org (Postfix) with ESMTPS id 3396B4BA23C7 for ; Sat, 17 Jan 2026 13:55:20 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 3396B4BA23C7 Authentication-Results: sourceware.org; dmarc=pass (p=reject dis=none) header.from=yahoo.de Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=yahoo.de ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 3396B4BA23C7 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=77.238.176.206 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1768658120; cv=none; b=u1YSrLNirCiYSJEB7cdl4ALRnbCBHbWC008P3x755/vA6pYiGMMxC4GfvGitgecjjBOJxjr8G7Lm3gfGRzR5DT8neKCgARLf5ejsy3sZ0OsZ2JHFSlFls3lJrMDJKigy2hFRWBI6b1TVUm7aW/SJlwSQlIa/T93xG9txBaiwPmQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1768658120; c=relaxed/simple; bh=bSPYfCsnQ12yUTa/FvnDMCup5ebDOpvGswa0cs74B/8=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=XI7sAX0JghSmR2312dSyzrmcNfDPbgpZwhW/Sc3ju4ihWw0yWQLIV34wS+LKKM/xBGDqDk41jn9LatpCDX/SYmtg/KELT38+gEdqYNYatEFLCE5mWpu0hiC6SkqGB0KKL3u5MXevjJbB6Rtr1dSjzXBIcovd6W4y3dljTKv5atk= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3396B4BA23C7 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.de; s=s2048; t=1768658119; bh=55K1q90hph5MsejGVcVMQMTTZy4qtWoBa4J+5YlmXCQ=; h=From:To:Subject:Date:In-Reply-To:References:From:Subject:Reply-To; b=rRjicOENSN8DIdzh9mMRXAdF9fDkZpznN6NdNZHLf3D+ccw523w+OGh5FVoDbeygZcCq3s7gJ/xP6C8iIY4gOKd2p4dcvLvLss+TmQ+VZ3K1qrmtCtQW6tFZq3DBwsJnhTgrFMd+7ygoFuKY5Nfh1zf5sDhVVCqv9/+Okb+Kg1YVo3jKicVmWwFUKed9RIcPTx9vKClCqi7uxZ1zE8E6i0TkMQvmG/9FRKyfut7yq/pqNRnDxbGEF/HcD2M4qmTH/gZSzk7mn9HVajlaZdfUeeHmuT3I+fVMYZvxZ1mzcU6kNjTEEdzLsQ5jC+lvzca32r8PdKh99Iagf8DDzYKYxA== X-SONIC-DKIM-SIGN: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1768658119; bh=nbcurrfF55BdIbQzv2bFLlrfl6z7eVFXxrLKbDm9RzC=; h=X-Sonic-MF:From:To:Subject:Date:From:Subject; b=RpwIKCPnTsdHNnvFUnhoorUTPvDXYB5ej+VCIKVGyUyWYhd/WSwLm0rR7oCIspWMsKuGJhs8vrBfdNTpnaFDaBVpKmkgQjJrLwGPqn/wQXibsfNvg/ffIRl+wl4XHPnMmQgT1By47qd1X7PfcXsaiBGtYt2AXwhts4EVeJeoXnMvN/1ghen8Pvd7VSFLrMlrW39Q57hgN19wXirsZRopkQ9KhjhFgl4oiE2j9hORzF32b5MH9dNR8dpLPf91FP3J20snR+HSMARheBKYlqxP2ITjt4VAcWDHFbMRZhdC1Ql0V4nns2VFwNZ/X//dbjBruA61ciGJcd3gHOakJGEFiA== X-YMail-OSG: QsGoLy8VM1mhzaY.HYQbRGdXpCZiispA8lrdBQjiRnU10kxOnZjk5Cud98ozOGO DcOYviDVZXXVw.xzHA0RStOASXVhBx4Iqs0k1b3mR.WN2L0Pu3DEix96ThDmwKEKSJQgV3JSwp6m Z2y3uv2XznvluNQqMDGVt8P5ngs5sRm7DZBC07DkS.qD7LBOr0RaTAyybyKcYuyYRgw2EXQH.FKJ FYRaRwfF3eHxtWWSBNe8Bne6ekfY45GrMi45KkgXof_JCUqZjZOfjLeKvMyb.pyalZdbSLirNpbJ nELwt19275et6hjqacinUKL3ldDjS6dCMYcO2vuq9mAcdeW1nm2EzzAyQLLe51pZ294SFDTOfr.p IRZ6T3qkSxb708cI82hVNqKpCjVcC8o5Tusu_dE.b6ChzEd5CHJG81JG_hI844GMfHyARoSOblOX XANooABPqWDk10Vbrlkmekxk86EtwhKmOsHUGLRK6oGbVMt8kZr8hwVIQN19PpQ_hzz2ZXP_f.wY RQvaOhLHySgW6V6U2HTcgAjxc221alSzvJw3gGk2fgmP_0TtjLWQRBVKazo7P9UzFzqrgTDh5jwN XdH1tekCwl2s3fIlpD3ylz5nsDQe9zvO5lbJt7bAbz1cu9oaJBIzQEhHhnFFdZXOi4hS9vszOOwR _zsd29sgIDkrQMZDPpj33B_Z4XcsDiMMZW6rOK5h1tKH87KTuYn.lbXmHKrX7DEllXSwUZnUOrzZ SsE8lvrEDPX4cFmpGodxJj0s9MEYf3Evl8saEeTPR_Krpl0VzHGHRZTRkOrNNKEO_S64COzo2Qit C3._5DH6F6PhkapVxYyLyiMul9azrsvdrSNoi_vI.QTtWF2fG19K7Bg1OKrRWtlGuI6OgU.0zNzP QIykFKvUgCPKk70zRW3cqSx40.u.cUc6Hx.cw9GXSw1sbh31kljsdvElcxz0yKKKoBjQHoIgqoI8 BFW1.F3Ekk7LTtsiPWSdYKy4rgq.J_tDVkmzkN5UT_3fvbLHUnDYwei7OInOBjZaFW1AhoPkR9VW O_OT4ZdTJfGtBHCgKsnx_ON2MSzBxMuvptU1y3zrKBy46JUl2M_k9eKQU_2PleaYsfi9Gmrixb7t 7RhKsck2t30c0uuhcAfxZ8VCd_YL7cIYqYa__mo9fGQA1bb6bvOCHBfYYXx_SatuKBtLJewOiBWW PyRLGi6C7ozkd63PPbk_zYB57YLUqQr.BPg8svVFV8Zkua2201ULhkF9pGSi2NPzJpTIiehwz.LR hzXecrvB_pf9KK.JOiiTeb1wneDPbB7b6vV8OnbX8r9e0bGyIQKF_Vyp2ObpqfHgNg.JN_7kHoen VwDWwkGXa4Tz0ATpXpMr9KcYQrCTzJTfcKGWjKEkrmZ9lfhktqVWxhUeiVbajiykGo.RzZIO_dMG Nq004fFkgRym9x70RxZ6YiSiAJ2P2Jeh6am4xzSj.6iBV7FKkdDHiW5C1d.v6rrYgY4K7ykkNoMX HMfUyaStt6U6M23XfpdCsk2l1K7uFhFRMe.lHgBcqXSNdxdWdBw2nrVEsjjfs9AO1ypf4M5h4C2q rcAZZFcnV2mm.SezHfeeluc5eOjNjtKdO3hczrLSfhgIbBimsRQQ_KJ9T2Ngg1FJvb2HnymhNyeV 2cQRvqxwTNL0RDzaZuWu8eigD5BiNVz_FzywsJ5YjM6WO45BRJ06VO7..1W5Ig5iYDozL93UmFeF abvlTo0aDyecCP_12BVYPAEcVEuXb12rapAMMVjN3ZmdQCzZBnpJG2wng0fyYzabDs0H0YVtKf7J hddEREurBsngJnRNuDA0OQ4EhDkJ.HQJJy4pknTERF0KRV2yPfnwZUF8.zSkCdvuns.358mqjA0t e4PckpgWrpYsing6AjKlT__xviAMxVuzCLKQFfFaLejjGBda4qPxiAPGFzuxADT.9AaWrqoiQpDf Iia.rmdtgBsOoubw0mT_BUkYWfa4rd_E8ebDYYL0Pzv_EPdbrAlxUtB1eGdJoHSCkC1EpL.Ggwo3 T.LqUTaHmuRPblb1YtNuWVSoObi3ACTUQyBYmN9BqePBM20SxBNZRi5sqTarpeN69rBpnvJkfuYr 0_Z8vhs.uplx5QIciqnWsuhIMFoBGNZoqcx2shMFxVj1LLVMcpUEMK60qHxpaqeYPpnZI8F74PHJ Mo41Uos33ifrxqXJB4dKbk9wx7BL1bZULSbE1P_68gvxAdBYBRI3uoZIYAuM4smJrfIKYuqSeXHk 1yljcweUQDEkpORELcnz7RYHZlJoaH24b_6S6zZAwPg-- X-Sonic-MF: X-Sonic-ID: e5d73fee-de9c-4879-92e4-0c2550bdd9f3 Received: from sonic.gate.mail.ne1.yahoo.com by sonic306.consmr.mail.ir2.yahoo.com with HTTP; Sat, 17 Jan 2026 13:55:19 +0000 Received: by hermes--production-ir2-6fcf857f6f-68cr8 (Yahoo Inc. Hermes SMTP Server) with ESMTPA ID 1ab9324439058ba9e338fb11da35c341; Sat, 17 Jan 2026 13:55:15 +0000 (UTC) From: Hannes Domani To: gdb-patches@sourceware.org Subject: [PATCH v2 05/11] Move x86 debug registers and related code into x86-windows-nat.c Date: Sat, 17 Jan 2026 14:54:28 +0100 Message-ID: <20260117135448.2666604-5-ssbssa@yahoo.de> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260117134052.2660009-1-ssbssa@yahoo.de> References: <20260117134052.2660009-1-ssbssa@yahoo.de> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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~public-inbox=simark.ca@sourceware.org --- gdb/windows-nat.c | 148 ++------------------------------ gdb/windows-nat.h | 19 ++++- gdb/x86-windows-nat.c | 191 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 215 insertions(+), 143 deletions(-) diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c index 68eebe1eaf9..e1da956b125 100644 --- a/gdb/windows-nat.c +++ b/gdb/windows-nat.c @@ -62,7 +62,6 @@ #include "windows-tdep.h" #include "windows-nat.h" -#include "x86-nat.h" #include "complaints.h" #include "gdbsupport/gdb_tilde_expand.h" #include "gdbsupport/pathstuff.h" @@ -85,18 +84,6 @@ windows_per_inferior *windows_process; # define STARTUPINFO STARTUPINFOW #endif -/* If we're not using the old Cygwin header file set, define the - following which never should have been in the generic Win32 API - headers in the first place since they were our own invention... */ -#ifndef _GNU_H_WINDOWS_H -enum - { - FLAG_TRACE_BIT = 0x100, - }; -#endif - -#define DR6_CLEAR_VALUE 0xffff0ff0 - /* The string sent by cygwin when it processes a signal. FIXME: This should be in a cygwin include file. */ #ifndef _CYGWIN_SIGNAL_STRING @@ -116,12 +103,6 @@ enum debug_prefixed_printf_cond (debug_exceptions, "windows except", fmt, \ ## __VA_ARGS__) -static void cygwin_set_dr (int i, CORE_ADDR addr); -static void cygwin_set_dr7 (unsigned long val); -static CORE_ADDR cygwin_get_dr (int i); -static unsigned long cygwin_get_dr6 (void); -static unsigned long cygwin_get_dr7 (void); - /* User options. */ static bool new_console = false; #ifdef __CYGWIN__ @@ -494,23 +475,7 @@ windows_nat_target::fetch_registers (struct regcache *regcache, int r) if (th->reload_context) { - windows_process->with_context (th, [&] (auto *context) - { - context->ContextFlags = WindowsContext::all; - CHECK (get_thread_context (th->h, context)); - /* Copy dr values from that thread. - But only if there were not modified since last stop. - PR gdb/2388 */ - if (!th->debug_registers_changed) - { - windows_process->dr[0] = context->Dr0; - windows_process->dr[1] = context->Dr1; - windows_process->dr[2] = context->Dr2; - windows_process->dr[3] = context->Dr3; - windows_process->dr[6] = context->Dr6; - windows_process->dr[7] = context->Dr7; - } - }); + fill_thread_context (th); th->reload_context = false; } @@ -1009,35 +974,7 @@ windows_nat_target::windows_continue (DWORD continue_status, int id, for (auto &th : windows_process->thread_list) if (id == -1 || id == (int) th->tid) { - windows_process->with_context (th.get (), [&] (auto *context) - { - if (th->debug_registers_changed) - { - context->ContextFlags - |= WindowsContext::debug; - context->Dr0 = windows_process->dr[0]; - context->Dr1 = windows_process->dr[1]; - context->Dr2 = windows_process->dr[2]; - context->Dr3 = windows_process->dr[3]; - context->Dr6 = DR6_CLEAR_VALUE; - context->Dr7 = windows_process->dr[7]; - th->debug_registers_changed = false; - } - if (context->ContextFlags) - { - DWORD ec = 0; - - if (GetExitCodeThread (th->h, &ec) - && ec == STILL_ACTIVE) - { - BOOL status = set_thread_context (th->h, context); - - if (!killed) - CHECK (status); - } - context->ContextFlags = 0; - } - }); + thread_context_continue (th.get (), killed); th->resume (); } @@ -1153,10 +1090,7 @@ windows_nat_target::resume (ptid_t ptid, int step, enum gdb_signal sig) regcache *regcache = get_thread_regcache (inferior_thread ()); struct gdbarch *gdbarch = regcache->arch (); fetch_registers (regcache, gdbarch_ps_regnum (gdbarch)); - windows_process->with_context (th, [&] (auto *context) - { - context->EFlags |= FLAG_TRACE_BIT; - }); + thread_context_step (th); } /* Allow continuing with the same signal that interrupted us. @@ -1536,15 +1470,12 @@ windows_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus, void windows_nat_target::do_initial_windows_stuff (DWORD pid, bool attaching) { - int i; struct inferior *inf; + initialize_windows_arch (); + windows_process->last_sig = GDB_SIGNAL_0; windows_process->open_process_used = 0; - for (i = 0; - i < sizeof (windows_process->dr) / sizeof (windows_process->dr[0]); - i++) - windows_process->dr[i] = 0; #ifdef __CYGWIN__ windows_process->cygwin_load_start = 0; windows_process->cygwin_load_end = 0; @@ -1890,7 +1821,7 @@ windows_nat_target::detach (inferior *inf, int from_tty) target_announce_detach (from_tty); - x86_cleanup_dregs (); + cleanup_windows_arch (); switch_to_no_thread (); detach_inferior (inf); @@ -2622,7 +2553,7 @@ void windows_nat_target::mourn_inferior () { (void) windows_continue (DBG_CONTINUE, -1, 0, true); - x86_cleanup_dregs(); + cleanup_windows_arch (); if (windows_process->open_process_used) { CHECK (CloseHandle (windows_process->handle)); @@ -2857,16 +2788,6 @@ windows_nat_target::thread_name (struct thread_info *thr) INIT_GDB_FILE (windows_nat) { - x86_dr_low.set_control = cygwin_set_dr7; - x86_dr_low.set_addr = cygwin_set_dr; - x86_dr_low.get_addr = cygwin_get_dr; - x86_dr_low.get_status = cygwin_get_dr6; - x86_dr_low.get_control = cygwin_get_dr7; - - /* x86_dr_low.debug_register_length field is set by - calling x86_set_debug_register_length function - in processor windows specific native file. */ - #ifdef __CYGWIN__ cygwin_internal (CW_SET_DOS_FILE_WARNING, 0); #endif @@ -2956,61 +2877,6 @@ Use \"%ps\" or \"%ps\" command to load executable/libraries directly."), } } -/* Hardware watchpoint support, adapted from go32-nat.c code. */ - -/* Pass the address ADDR to the inferior in the I'th debug register. - Here we just store the address in dr array, the registers will be - actually set up when windows_continue is called. */ -static void -cygwin_set_dr (int i, CORE_ADDR addr) -{ - if (i < 0 || i > 3) - internal_error (_("Invalid register %d in cygwin_set_dr.\n"), i); - windows_process->dr[i] = addr; - - for (auto &th : windows_process->thread_list) - th->debug_registers_changed = true; -} - -/* Pass the value VAL to the inferior in the DR7 debug control - register. Here we just store the address in D_REGS, the watchpoint - will be actually set up in windows_wait. */ -static void -cygwin_set_dr7 (unsigned long val) -{ - windows_process->dr[7] = (CORE_ADDR) val; - - for (auto &th : windows_process->thread_list) - th->debug_registers_changed = true; -} - -/* Get the value of debug register I from the inferior. */ - -static CORE_ADDR -cygwin_get_dr (int i) -{ - return windows_process->dr[i]; -} - -/* Get the value of the DR6 debug status register from the inferior. - Here we just return the value stored in dr[6] - by the last call to thread_rec for current_event.dwThreadId id. */ -static unsigned long -cygwin_get_dr6 (void) -{ - return (unsigned long) windows_process->dr[6]; -} - -/* Get the value of the DR7 debug status register from the inferior. - Here we just return the value stored in dr[7] by the last call to - thread_rec for current_event.dwThreadId id. */ - -static unsigned long -cygwin_get_dr7 (void) -{ - return (unsigned long) windows_process->dr[7]; -} - /* Determine if the thread referenced by "ptid" is alive by "polling" it. If WaitForSingleObject returns WAIT_OBJECT_0 it means that the thread has died. Otherwise it is assumed to be alive. */ diff --git a/gdb/windows-nat.h b/gdb/windows-nat.h index 03c358fac54..6553052f420 100644 --- a/gdb/windows-nat.h +++ b/gdb/windows-nat.h @@ -54,8 +54,6 @@ struct windows_per_inferior : public windows_nat::windows_process_info void handle_unload_dll () override; bool handle_access_violation (const EXCEPTION_RECORD *rec) override; - uintptr_t dr[8] {}; - int windows_initialization_done = 0; std::vector> thread_list; @@ -183,6 +181,23 @@ struct windows_nat_target : public inf_child_target return serial_event_fd (m_wait_event); } +protected: + + /* Initialize arch-specific data for a new inferior (debug registers, + register mappings). */ + virtual void initialize_windows_arch () = 0; + /* Cleanup arch-specific data after inferior exit. */ + virtual void cleanup_windows_arch () = 0; + + /* Reload the thread context. */ + virtual void fill_thread_context (windows_thread_info *th) = 0; + + /* Prepare the thread context for continuing. */ + virtual void thread_context_continue (windows_thread_info *th, + int killed) = 0; + /* Set the stepping bit in the thread context. */ + virtual void thread_context_step (windows_thread_info *th) = 0; + private: windows_thread_info *add_thread (ptid_t ptid, HANDLE h, void *tlb, diff --git a/gdb/x86-windows-nat.c b/gdb/x86-windows-nat.c index d1f78a01255..88844e0675a 100644 --- a/gdb/x86-windows-nat.c +++ b/gdb/x86-windows-nat.c @@ -18,22 +18,213 @@ along with this program. If not, see . */ #include "windows-nat.h" +#include "regcache.h" +#include "gdbarch.h" #include "x86-nat.h" +using namespace windows_nat; + +/* If we're not using the old Cygwin header file set, define the + following which never should have been in the generic Win32 API + headers in the first place since they were our own invention... */ +#ifndef _GNU_H_WINDOWS_H +enum + { + FLAG_TRACE_BIT = 0x100, + }; +#endif + +#define DR6_CLEAR_VALUE 0xffff0ff0 + +#define CHECK(x) check (x, __FILE__,__LINE__) + +static void +check (BOOL ok, const char *file, int line) +{ + if (!ok) + { + unsigned err = (unsigned) GetLastError (); + gdb_printf ("error return %s:%d was %u: %s\n", file, line, + err, strwinerror (err)); + } +} + struct x86_windows_per_inferior : public windows_per_inferior { + uintptr_t dr[8] {}; }; struct x86_windows_nat_target final : public x86_nat_target { + void initialize_windows_arch () override; + void cleanup_windows_arch () override; + + void fill_thread_context (windows_thread_info *th) override; + + void thread_context_continue (windows_thread_info *th, int killed) override; + void thread_context_step (windows_thread_info *th) override; }; /* The current process. */ static x86_windows_per_inferior x86_windows_process; +/* See windows-nat.h. */ + +void +x86_windows_nat_target::initialize_windows_arch () +{ + memset (x86_windows_process.dr, 0, sizeof (x86_windows_process.dr)); +} + +/* See windows-nat.h. */ + +void +x86_windows_nat_target::cleanup_windows_arch () +{ + x86_cleanup_dregs (); +} + +/* See windows-nat.h. */ + +void +x86_windows_nat_target::fill_thread_context (windows_thread_info *th) +{ + x86_windows_process.with_context (th, [&] (auto *context) + { + context->ContextFlags = WindowsContext::all; + CHECK (get_thread_context (th->h, context)); + + /* Copy dr values from that thread. + But only if there were not modified since last stop. + PR gdb/2388 */ + if (!th->debug_registers_changed) + { + x86_windows_process.dr[0] = context->Dr0; + x86_windows_process.dr[1] = context->Dr1; + x86_windows_process.dr[2] = context->Dr2; + x86_windows_process.dr[3] = context->Dr3; + x86_windows_process.dr[6] = context->Dr6; + x86_windows_process.dr[7] = context->Dr7; + } + }); +} + +/* See windows-nat.h. */ + +void +x86_windows_nat_target::thread_context_continue (windows_thread_info *th, + int killed) +{ + x86_windows_process.with_context (th, [&] (auto *context) + { + if (th->debug_registers_changed) + { + context->ContextFlags |= WindowsContext::debug; + context->Dr0 = x86_windows_process.dr[0]; + context->Dr1 = x86_windows_process.dr[1]; + context->Dr2 = x86_windows_process.dr[2]; + context->Dr3 = x86_windows_process.dr[3]; + context->Dr6 = DR6_CLEAR_VALUE; + context->Dr7 = x86_windows_process.dr[7]; + th->debug_registers_changed = false; + } + + if (context->ContextFlags) + { + DWORD ec = 0; + + if (GetExitCodeThread (th->h, &ec) + && ec == STILL_ACTIVE) + { + BOOL status = set_thread_context (th->h, context); + + if (!killed) + CHECK (status); + } + context->ContextFlags = 0; + } + }); +} + +/* See windows-nat.h. */ + +void +x86_windows_nat_target::thread_context_step (windows_thread_info *th) +{ + x86_windows_process.with_context (th, [&] (auto *context) + { + context->EFlags |= FLAG_TRACE_BIT; + }); +} + +/* Hardware watchpoint support, adapted from go32-nat.c code. */ + +/* Pass the address ADDR to the inferior in the I'th debug register. + Here we just store the address in dr array, the registers will be + actually set up when windows_continue is called. */ +static void +cygwin_set_dr (int i, CORE_ADDR addr) +{ + if (i < 0 || i > 3) + internal_error (_("Invalid register %d in cygwin_set_dr.\n"), i); + x86_windows_process.dr[i] = addr; + + for (auto &th : x86_windows_process.thread_list) + th->debug_registers_changed = true; +} + +/* Pass the value VAL to the inferior in the DR7 debug control + register. Here we just store the address in D_REGS, the watchpoint + will be actually set up in windows_wait. */ +static void +cygwin_set_dr7 (unsigned long val) +{ + x86_windows_process.dr[7] = (CORE_ADDR) val; + + for (auto &th : x86_windows_process.thread_list) + th->debug_registers_changed = true; +} + +/* Get the value of debug register I from the inferior. */ + +static CORE_ADDR +cygwin_get_dr (int i) +{ + return x86_windows_process.dr[i]; +} + +/* Get the value of the DR6 debug status register from the inferior. + Here we just return the value stored in dr[6] + by the last call to thread_rec for current_event.dwThreadId id. */ +static unsigned long +cygwin_get_dr6 (void) +{ + return (unsigned long) x86_windows_process.dr[6]; +} + +/* Get the value of the DR7 debug status register from the inferior. + Here we just return the value stored in dr[7] by the last call to + thread_rec for current_event.dwThreadId id. */ + +static unsigned long +cygwin_get_dr7 (void) +{ + return (unsigned long) x86_windows_process.dr[7]; +} + INIT_GDB_FILE (x86_windows_nat) { + x86_dr_low.set_control = cygwin_set_dr7; + x86_dr_low.set_addr = cygwin_set_dr; + x86_dr_low.get_addr = cygwin_get_dr; + x86_dr_low.get_status = cygwin_get_dr6; + x86_dr_low.get_control = cygwin_get_dr7; + + /* x86_dr_low.debug_register_length field is set by + calling x86_set_debug_register_length function + in processor windows specific native file. */ + /* The target is not a global specifically to avoid a C++ "static initializer fiasco" situation. */ add_inf_child_target (new x86_windows_nat_target); -- 2.52.0