From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id MeqDG6B1c2lRYxEAWB0awg (envelope-from ) for ; Fri, 23 Jan 2026 08:20:32 -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=Mfeu/yL7; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 6BE181E0AD; Fri, 23 Jan 2026 08:20:32 -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 0C6FF1E08D for ; Fri, 23 Jan 2026 08:20:30 -0500 (EST) Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id 553394BCA2E3 for ; Fri, 23 Jan 2026 13:20:29 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 553394BCA2E3 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=Mfeu/yL7 Received: from sonic314-19.consmr.mail.ir2.yahoo.com (sonic314-19.consmr.mail.ir2.yahoo.com [77.238.177.145]) by sourceware.org (Postfix) with ESMTPS id C5A264BA23D2 for ; Fri, 23 Jan 2026 13:19:57 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C5A264BA23D2 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 C5A264BA23D2 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=77.238.177.145 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1769174398; cv=none; b=SERZPGwud3TfEU2I63WYW0ARBwTTTY+DdT/KOxtCDh3S9ffKgI/vZzWuA3kLIaLMEsnzLcyWMQWCiA3G95utTzwIOr/uR/HAkliMN2GHGeN81KMKGAJQzOrCsZHg/vCclizGAfoBPOY8kox9iq+Dzp1//SnhKFRHhbC1Bgmp7yE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1769174398; c=relaxed/simple; bh=hx/yuzTw4FaOHHykPNzbXAJ0tLM9ig8TmtqDjwxCCIA=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=v6q2YVr2WOU40IkMPhA6tCkZFG9m8Rrj33lTnweIm+rXvnS+tMdwOsb3D19f4KEXRcJMdQaJ7COFs5tMX7JVvV0QeADMjTGS8WB9IH9yOhxoSEHePnMiSfukEUCYwRnLavwT139/PBmUD8QDNM5ofaxVbGQWPRQxZAikGuRGwJU= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C5A264BA23D2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.de; s=s2048; t=1769174396; bh=Ry2KrSZ2orxDd4Xn4YU5QUBjQnouqFRpiz0bbD1bVQ0=; h=From:To:Subject:Date:In-Reply-To:References:From:Subject:Reply-To; b=Mfeu/yL7id3FsCINmsCbmuwg9+RPHetozOt8jeQN690EeEd6NPmeBNPNWJf3VQ9Q5EOoCZ5otVnGNes5S6NiwcLwwNoDdRf4rnlFKATXVMmcJShPAJ3cJmGitjLQh/fbmA09v1ntf4tuzqXoGrMqYKNTW4T1sZI/Gyb87mwjmQfuAF2T8jtBVIb7ll//sXAKDKiTfTTHaEBg/Y+Bj6XqvUG+5GWaIeF/tQk4MrcRFcwrNHcH0twh3j68KL17vAWj5UvV3SXnA5l/VRA0WIryYPnGl/cJVTWmnIi1EEQ2aFIOniqlONIBNpG7lBnph2HvvVHcvrQUsIkrt12fhnxHDg== X-SONIC-DKIM-SIGN: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1769174396; bh=N8icAmGlbsn9WUD0RvgZyXhLoF3nVIJuO0U7HLrPA6s=; h=X-Sonic-MF:From:To:Subject:Date:From:Subject; b=VtAptCj44R5C+Bp/2JFm8sdW+WJNUPvKco0KVAsHz8Rj8+1ua4F3Md0q+TpsJPFtrKEHwIDpEWt910kTYbC25Jw1b0zYgZ8oevK48pRMYM3FpOaNpIZ9wXkn620EzRpbKr6nSFuXRiIqolSAWz9HQeil01uTVYGKjXgUUGnkjo+9Q9yQBtIrcoTOkdhHvL9iq4MIZZN9IGcw2TgBq/TwKKQCdJqFa5bM44lao9yiBbsH1loxWicGm3QkDpVM/vtne9TORCoE6beOFo3C13hSW1dOBj3Y9n8buL04x12ydILkVYwU4V/YDlR0N+rLI+LYlcldES6FnNiKPGEdyNr/bg== X-YMail-OSG: Ihw5nwIVM1k4CmFB3GNylSKIw9BMPmveJZIynxEeJ8M7yhW2G5OJZxC4ky0V_kL 38OCAP4mQ_oXwXS.2hgDZQlMqtV8Q2eLVYuF2_1iiN9xfeCLo7ZcPQZlIBb9GwRxry0KtqoO8Y6o .J8Fmix3hP1kY2sdhePBTfjRfDUXew8eoOibR.q9TdI7IgbTsX8PIp4tyz157JFApz7wZSZukkB4 DTdhuUdEnmMV8gp6zuG0ytEVF94z_5GCnRKumGqekJpgdOHsV5u0b2apD.1N3orelo57gtiIbnbw 1nZqWiw0ytT_QeGL7ZOhKB3TcvxzYC0UMnKNotEuSk730YbbPXiAyKP3NFp18bWCqjan79guN0a8 MlfMi_.shLh5jfkvqTzWB.iPaLzPWQvqdX6r1fib3GK7TLmtZFI7QVM1ExMhRbXi4ytAxWywg4Df 9osNe9rObkFhIgciCNBG3InK2Kc7_UvIPplQo_DbRwSRndvFBsfAnorYjVAhYJdWjDIGMC11Lge3 M2M3cwOedtgkvUMAFxNgzrygYRO2By01HuYKFGkZkOfJs0fjSZlm.QfiF7LW0koHr.CSusRTjEvy 3t_6T.AYubsTwBkgAyFpqER83eLhjjY82El8IFZWR7zCmPBglggCguxBJE.fZk1rCwcVNQX7frmv c8lVt4djuw6rT3kAm.BDKFRhF7lR2j9TpwYcEzZ2nhDMY9apUmCBcfhm9b8REaaYYJCvWBcKtVK0 jaYWQ.fhFdDkMfZnJXL8blyzbMKyfnjp8puGSYnQHJfqD9GzDsQL9yK0YIpWrX01QQTFdO1RhB6J WMZ127IlE4wx_ZMTPdIhVwVRDKmPuz2Rs.CIDO1HG1A7ty6fYS70ro8wtgPxcNqFrimqAQ8LnrTy 3FXRKpTLmOarlurHPVxDnQNpivSKmUu_x9dpu3A2puXvQHKAMohnAYpotw8S90MWiR9eQIwXElhL 1IIbuHvicjxE9ZOFbwzT6I59U.8XsJ4PGD.QKonR.CRMm.PUVwhjfhjRfaIomnAOWjPu7UMoRZnB Btlk8rHAsGaxWuy9xSgK5a_FWRuMZGddBcDwwq6c6i2SHh_EM7almh9uXvHobKM3bAd4fCsdQqtN U7JpeK03ZQIDq6ro8z9v8d02J.6QSG4_9VJDLSczocwQVQo4WBPEZF81ug18EKrIY3JQi314P0JB 2d9SA9NadHbM8Ssesh0U1Icoe.R_GV_6pdV7f_MEwMg214PxLWlSx0.gJ0E3KWslMFjjKxYONUZN NHU1nct03plJVIYBvTfULr.s0yy2YHmeCadZQMoP5icGhocAZyILidpZwCOeF3X89zJoRghYcZZL ZtT4vewWyUrYf_q6JUkjoSxqTRXK7wR4UmeoXOU2ZPZs1MWfiIHkal5lM6QGTknW4k6C8Qf2l1YR jvIM6eZwiZL27Ivor1sTY_qDa.Go4.tP_bXRO5Kv3aZKiQ7ofryXe5A_5vTYXLedhciqpR6._t4f XCeH4X9CjOpwWQx6KGhVy7Tqf59fOb3Ua3yYa6AGoWyq0dPOMioEbmDbIvhnebXv1qgKQc1dsDtB H7B1XkcfbjmTa5gRL7ez4HtQcHe78OTb7BQL7Nk2BApzRxfA0UdWlCXCLEH9GAeTAeA_BODVk2q8 1DgklprS9bELJweirBco6anzWWg1afrmm8k0EWiLxlTqwv2tB6vWTkDaj8GdLKZYb_GSzp5wrTXd P3hIZaTv5JdO8.pfahkx1PKpc6UQZKuFWr4suglA942jzVRE9WLcg9MqzSnvIQysK9bzr8LsXKpZ Qei0pMG8jItBpHPft9nhGIAQWicatOcpiqTtcLLhC40ueLexZedgpvqSj7guzu7pZHpSwU6f9qLo PikXO9FB02tAsT_NRm1.8G9fE2ojIhVpR7KMdrcC7yTCk6LrgKDEu37.pkJdgX2_vhjUZMrPAEN7 IDDlrr.5vPglnE3FgbWGJ_2.5hbO6NNoAL_WOifwmqOvh5ly1xcKTLeGAbbDG1Xi3sukwss52RXX 3gc29bxCK.TiiVSvb0eLHIDklK3YP0CdVhQ8LFMhYfieuEbZyCee1iCBSbU473CVsfpMizVqRp26 _cFkz8d05hPbSY6NvsI2zOFYvjNb4GNfO3SucIrQ_LBpRt497_n83BQ7Q6uqcacv_jAnc72wQcqs HG2yy145Wtg.JzhZeRX7.yt1k3G7Jk86UccApXn43NerC_z35NuNdqXm7zNs5nl8dUXXz9gfUrZW gnckGDMWH6y8zoBvR7VkGL3OS X-Sonic-MF: X-Sonic-ID: c0e980a7-dce5-41a0-a957-cab11f391d0e Received: from sonic.gate.mail.ne1.yahoo.com by sonic314.consmr.mail.ir2.yahoo.com with HTTP; Fri, 23 Jan 2026 13:19:56 +0000 Received: by hermes--production-ir2-6fcf857f6f-fskn5 (Yahoo Inc. Hermes SMTP Server) with ESMTPA ID 4564e20569c7c44edd7457f7edcd270d; Fri, 23 Jan 2026 13:19:56 +0000 (UTC) From: Hannes Domani To: gdb-patches@sourceware.org Subject: [PATCH v3] Move x86 debug registers and related code into x86-windows-nat.c Date: Fri, 23 Jan 2026 14:17:37 +0100 Message-ID: <20260123131944.3317177-1-ssbssa@yahoo.de> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260117134052.2660009-5-ssbssa@yahoo.de> References: <20260117134052.2660009-5-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 --- Changes in v2: - changed new windows_nat_target functions from public to protected - better comments for these functions Changes in v3: - made check() function non-static, removed duplicate in x86-windows-nat.c --- gdb/windows-nat.c | 151 ++--------------------------------- gdb/windows-nat.h | 24 +++++- gdb/x86-windows-nat.c | 178 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 208 insertions(+), 145 deletions(-) diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c index 9bcbc740f86..88c821d885d 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,25 +84,12 @@ 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 #define _CYGWIN_SIGNAL_STRING "cYgSiGw00f" #endif -#define CHECK(x) check (x, __FILE__,__LINE__) #define DEBUG_EXEC(fmt, ...) \ debug_prefixed_printf_cond (debug_exec, "windows exec", fmt, ## __VA_ARGS__) #define DEBUG_EVENTS(fmt, ...) \ @@ -116,12 +102,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__ @@ -158,7 +138,7 @@ static const struct xlate_exception xlate[] = #endif /* 0 */ -static void +void check (BOOL ok, const char *file, int line) { if (!ok) @@ -494,23 +474,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 +973,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 +1089,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 +1469,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 +1820,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 +2552,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 +2787,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 +2876,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..f67ca3ad193 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, @@ -249,6 +264,11 @@ struct windows_nat_target : public inf_child_target bool m_continued = false; }; +/* Check if Windows API call succeeds, and otherwise print error code + and description. */ +void check (BOOL ok, const char *file, int line); +#define CHECK(x) check (x, __FILE__,__LINE__) + /* The current process. */ extern windows_per_inferior *windows_process; diff --git a/gdb/x86-windows-nat.c b/gdb/x86-windows-nat.c index d1f78a01255..58a9d3d8866 100644 --- a/gdb/x86-windows-nat.c +++ b/gdb/x86-windows-nat.c @@ -18,22 +18,200 @@ 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 + 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