From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id CwFcO7WRa2lAwwcAWB0awg (envelope-from ) for ; Sat, 17 Jan 2026 08:42:13 -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=fpulPkF0; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id E4AD21E070; Sat, 17 Jan 2026 08:42:13 -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 DE6F61E070 for ; Sat, 17 Jan 2026 08:42:11 -0500 (EST) Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id 52D054BA23F4 for ; Sat, 17 Jan 2026 13:42:11 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 52D054BA23F4 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=fpulPkF0 Received: from sonic307-53.consmr.mail.ir2.yahoo.com (sonic307-53.consmr.mail.ir2.yahoo.com [87.248.110.30]) by sourceware.org (Postfix) with ESMTPS id C8DB54BA2E31 for ; Sat, 17 Jan 2026 13:41:23 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C8DB54BA2E31 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 C8DB54BA2E31 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=87.248.110.30 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1768657284; cv=none; b=qaD0OqBtgKYVo+XPgVmWx2GmJwKnSrtYOtn4uKXrKwzv4S6lOBzm05SON0NrQc1ZBsNw8xkq2pxICqEriqJUC2Ol4HTkBJROhIp3eMtYx5aogaskwo0OPufA3me4+6ZFNgOqUJdoIBvWQMm9mDUqQ8tJLLJc577TFYkCtPL1yzA= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1768657284; c=relaxed/simple; bh=LCeqNXkfYI3LFfQVIKvYvzCV8HsoI2KpGAY5FLoiqVM=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=KETnzlHH+SJ9i/4zqJ8mcoa1sNwKvvg46yZU1ASa71/r4WrBo1CQDg6ZbOyQgjUgEdDNqWwIgBbkIO5mwa5jxaRXVt5CL9hru9LR7aLzIqf/5q+RuGZityCIdkcK8YcOYgckdVw6Jxi6Bc0nMr180Rd9+0nYJyYXJl4ZFg5A7i8= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C8DB54BA2E31 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.de; s=s2048; t=1768657282; bh=oSOGTgmjOpnKzIPesbEw4bOBYpSN8bgFc1BiNkWae6s=; h=From:To:Subject:Date:In-Reply-To:References:From:Subject:Reply-To; b=fpulPkF0bjoCKXnhqNQyaKTPk6p5GDoHw9pB9lF+8RJ36nu2BWudD93MLGPr+8n42e49ahbp9WCXzjXPjnXg49t8Sd7c4kKzHnsL1+Zi3cBAMZkPGuE+LINSCyrRW33S2q8yagDLOEN6XQRtpYpPlaA5dtK0kKWjErrdqILl++jHqBOi7DDxrBQ3/eSqR/sEYIJvkEq03/zo9n4QgJKlmDEeUv/zCbEhWkca+u++LuSLXySSuoQBR+76GC9IdNlLB7tCpEVWO8eQTeb9aejarBTPqqW1D83OXtPIwfJxA29oTv49es/RzLAXe7Ff2uqlrx3DVG3Lc0J+jb4e8+tXmQ== X-SONIC-DKIM-SIGN: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1768657282; bh=Yk6O+YsztMO9KyFXYmGmZwOJJBHPoxgLcvBX66q8XkW=; h=X-Sonic-MF:From:To:Subject:Date:From:Subject; b=Ez/BEOAYoHz8k9cKTfJFzSxnmoX0ZpnbVG4rquGL9AaSQx1GNLNkBkXa4miUR86FjLO1GgRS5GL0Ycsw8DNjqFQwf7UR0r8lxagvx4tRA/hkEYIT+IbORDbrxrQBD1XgpxRc9RnqGMN4TgbblLL77dHx4EKDfnxiXmZX2xHdGGRtSbnGyDaWHXk/XmIjFdBP+qmq8i9+6iCe1MJYEQ2cvIaXLk6X3xWdJ1CZfdva3cVToXSI3bonQzm58ipEUskWEetB4KqMk7jj5Htd3wz+5hji6kz6X42oYL/MgQzYyBCeifSrnIcSoEqeIrkGWxQ/f0d65uEzIb3BpvTNYLQP5Q== X-YMail-OSG: 0pFfZfQVM1m9KGNkb6.jVRA2OT3Szo6ZeAXV0WvRIFQZM31boRyhSUXIuj9hyUD 5CiiRYBKztQr9sswmCUZkPSjTF5r7RMZQr03HqeL1xv3HjWj78LJ5l.UTQJjQY3ZebXvm5wYnEfC pzN4PtIMlCohsYQIHyEVYtBuNIboRDEslrdACO3hPjsmIjferzVPc_TRDuqNfFwiGWrm78.N6BMg SZq5ItGSlgZpulSyl1oecqYrN5zrha3kknGbxdOglJ5fcG06IrTjeDcVC21gtrWEqFXDwhmWjHIb kK5o03IOq_DgXnkvn39ulK_roAXZey0hhEJL3TVMhRY7r8i.mArnbGttPgHbL0JpNBGeB5mURgJJ Pe1nAN.GUc.i9FgCZMmfaFglfpxt8OVuxGLOsYz6rkMZkthrZHrUg_mTUb0XXfgxKTKR13y31QrM 6.cNN.49dnRULJLeLRMnsk6PG2LChDRuplgQVHG2W2PsGi3HTh4LVdvnag.5Yj5H8cFAEr57nfRa p66sxIZ2pvgX1bMUvFp3r66QI8HuT4NitEXYpKrC9kZYCeVqydu1lw8xRWjf4Dvm7VocBITAjXc2 y_xDdNLIYDiFHFZGUoSkIY3x_.TscuxHUanRJQ87O6XOwUbCUZtrOmuaKY1QD5ZQzsfy6Xq1O2rs VLR2LqZOXPD4oQ2tZqgDSUI0YI86pL4hDlgA5KEGoK_Ssj48lgGqsGbVFtLnL.R_dgEyIatz7UI7 6o9oqOVTMDxEAlvl5UYCbGbAjMR_OWYItoP9IkX5jH4JjosKdH2S58C3S_kCfV63TCP8jk4e9RWl dTK2WTi7h3aDUROCgORR4x7RdXHEah3V4tWNejUZcXIVWV3yKy3mr94wNY6LbZELMte_nhadqIWk WaeFsM_DnT5pkNHIw.1sinlAHhyCRaD2_nwk7x8zwrSlC66NrDcACfDfWWvmPFUDG.eI6P.wFsbd jrTx1Z5DZum98V8cmNC_D3BWQckK1bUnDWECmI6WJjs.F7148qASF_pkJOoGbfNOCRgT0s3o1QF6 C5grtFNVhZ5RJPe4bVLkJLbEJ29LM4EyrR2NRska4B444mOyvXsE3DowCATyFHA4WsF7DEarXBZ9 cLyCFkqyITcNuVTwY34NGkFy8MnmJ_TlXDfMa3uGse9Vb8QyP2EHKcpTY1FgBuHZDZGAMVYmLX0t DBpiKuSU71QnPgbt7drmyXh6dQU6oTs3GPPgsS9jh9_y41.m1cNNlwwZUGqbvcBn7nv_OweGlr78 EmG4K0hXA9N4WApkH56i.W4K7KVOSC0cXwas3PWHlatvIfeGqPG4axZbfi5WrGsMOfolQgWI_Gah 9pcuWevUlbdJVBPfDLwSBBpJd_yOPFfzvOnT7fei32GqHndGW1gedq5fUtOEGDpTIowniHYeYRhD MbupiGNNvlFWcrbdKL_SLTE13Zd3T2Ka1iztYyL_pkuzIHI5rZ8TwKCGPx_7ofvXSy1FDnw3aSHv iUxEnVsGfElW1Phda4DjpNrZaee_ZXLUoHvgu0CENMmuB1oNnJS4X9pie7iO8sCHIHNL_998DvUS 6iLcNNuZMuVl0L3Fnz0JP_.algsrDXgqZMIEyw2oqsXg_5OcempRGl05_ugsjm.FFxmcYCuBErd4 b0wsY2ek0X7lKcFuzFRmDID__WyK_e.CC1mCXtB058LD2P9LvIRvLHJ_QtQwI9AiubNsjfk1Co7u _8xjpuatadxv0c4dJ2JtyL_gHylVElxF_XS4v_peRy9kzDH033eyTYjDgw0b4aGFmY3_lnOZsieW 6OlDSUEBv2yL0SgnRurU6IF3yr_u18x72NEDWLyWEe7cDCbA63JKaezvWJQIe.ys7XnSRt.rYxrY rj0zvjWKVjNgwjltXWQ62nQLj1iovoSGOjO78sQMDzAKnEmRvbddmMPgYbk63TLGdk5z3fTVMDN3 _hRujU4j2_oa_ofrqY4YsUfXp0wCNV1HysQf0isSMg5U5uLjyTViZD1zYgLihJu1TT6NbUHdgGN5 RXZ9G7Sn4_X7tn2ogj6dSpiQB44OfZfconAOC0HjTH1okJP3k8iNdiIEex_oOhrKXe0OMnfH_cB. HxYKa1MFFqEL5FBhOWVov6CXz_cTdyoX2cFr2vmfGqiHlkYvtM1lzhVVqrge.B7E2ZZxDdSBanHK DLRD8qG1ZjzqUO2sz6fw_cRa3apxRVXi5c1gk5QVQwc53YgvYldgP7atSvWHtHKboxR0Kikqe7Tq PAbvmx93JSvpQLADeddaNtcQ1i0vICL1P X-Sonic-MF: X-Sonic-ID: 67bac08c-2161-4f12-a403-f257915ac28f Received: from sonic.gate.mail.ne1.yahoo.com by sonic307.consmr.mail.ir2.yahoo.com with HTTP; Sat, 17 Jan 2026 13:41:22 +0000 Received: by hermes--production-ir2-6fcf857f6f-fskn5 (Yahoo Inc. Hermes SMTP Server) with ESMTPA ID 8b536636b504c3e6f51c508e4731c748; Sat, 17 Jan 2026 13:41:21 +0000 (UTC) From: Hannes Domani To: gdb-patches@sourceware.org Subject: [PATCH v2 06/11] Move x86 register code into x86-windows-nat.c Date: Sat, 17 Jan 2026 14:36:17 +0100 Message-ID: <20260117134052.2660009-6-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 --- Changes in v2: - updated comment for initialize_windows_arch() describing the ATTACHING argument --- gdb/windows-nat.c | 144 ++---------------------------------------- gdb/windows-nat.h | 29 +++++++-- gdb/x86-windows-nat.c | 137 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 163 insertions(+), 147 deletions(-) diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c index e1da956b125..926b85d479b 100644 --- a/gdb/windows-nat.c +++ b/gdb/windows-nat.c @@ -57,9 +57,6 @@ #include "xml-support.h" #include "inttypes.h" -#include "i386-tdep.h" -#include "i387-tdep.h" - #include "windows-tdep.h" #include "windows-nat.h" #include "complaints.h" @@ -389,79 +386,6 @@ windows_nat_target::delete_thread (ptid_t ptid, DWORD exit_code, windows_process->thread_list.erase (iter); } -/* Fetches register number R from the given windows_thread_info, - and supplies its value to the given regcache. - - This function assumes that R is non-negative. A failed assertion - is raised if that is not true. - - This function assumes that TH->RELOAD_CONTEXT is not set, meaning - that the windows_thread_info has an up-to-date context. A failed - assertion is raised if that assumption is violated. */ - -static void -windows_fetch_one_register (struct regcache *regcache, - windows_thread_info *th, int r) -{ - gdb_assert (r >= 0); - gdb_assert (!th->reload_context); - - char *context_ptr = windows_process->with_context (th, [] (auto *context) - { - return (char *) context; - }); - - char *context_offset = context_ptr + windows_process->mappings[r]; - struct gdbarch *gdbarch = regcache->arch (); - i386_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - gdb_assert (!gdbarch_read_pc_p (gdbarch)); - gdb_assert (gdbarch_pc_regnum (gdbarch) >= 0); - gdb_assert (!gdbarch_write_pc_p (gdbarch)); - - /* GDB treats some registers as 32-bit, where they are in fact only - 16 bits long. These cases must be handled specially to avoid - reading extraneous bits from the context. */ - if (r == I387_FISEG_REGNUM (tdep) || windows_process->segment_register_p (r)) - { - gdb_byte bytes[4] = {}; - memcpy (bytes, context_offset, 2); - regcache->raw_supply (r, bytes); - } - else if (r == I387_FOP_REGNUM (tdep)) - { - long l = (*((long *) context_offset) >> 16) & ((1 << 11) - 1); - regcache->raw_supply (r, &l); - } - else - { - if (th->stopped_at_software_breakpoint - && !th->pc_adjusted - && r == gdbarch_pc_regnum (gdbarch)) - { - int size = register_size (gdbarch, r); - if (size == 4) - { - uint32_t value; - memcpy (&value, context_offset, size); - value -= gdbarch_decr_pc_after_break (gdbarch); - memcpy (context_offset, &value, size); - } - else - { - gdb_assert (size == 8); - uint64_t value; - memcpy (&value, context_offset, size); - value -= gdbarch_decr_pc_after_break (gdbarch); - memcpy (context_offset, &value, size); - } - /* Make sure we only rewrite the PC a single time. */ - th->pc_adjusted = true; - } - regcache->raw_supply (r, context_offset); - } -} - void windows_nat_target::fetch_registers (struct regcache *regcache, int r) { @@ -482,51 +406,9 @@ windows_nat_target::fetch_registers (struct regcache *regcache, int r) if (r < 0) for (r = 0; r < gdbarch_num_regs (regcache->arch()); r++) - windows_fetch_one_register (regcache, th, r); - else - windows_fetch_one_register (regcache, th, r); -} - -/* Collect the register number R from the given regcache, and store - its value into the corresponding area of the given thread's context. - - This function assumes that R is non-negative. A failed assertion - assertion is raised if that is not true. */ - -static void -windows_store_one_register (const struct regcache *regcache, - windows_thread_info *th, int r) -{ - gdb_assert (r >= 0); - - char *context_ptr = windows_process->with_context (th, [] (auto *context) - { - return (char *) context; - }); - - struct gdbarch *gdbarch = regcache->arch (); - i386_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - /* GDB treats some registers as 32-bit, where they are in fact only - 16 bits long. These cases must be handled specially to avoid - overwriting other registers in the context. */ - if (r == I387_FISEG_REGNUM (tdep) || windows_process->segment_register_p (r)) - { - gdb_byte bytes[4]; - regcache->raw_collect (r, bytes); - memcpy (context_ptr + windows_process->mappings[r], bytes, 2); - } - else if (r == I387_FOP_REGNUM (tdep)) - { - gdb_byte bytes[4]; - regcache->raw_collect (r, bytes); - /* The value of FOP occupies the top two bytes in the context, - so write the two low-order bytes from the cache into the - appropriate spot. */ - memcpy (context_ptr + windows_process->mappings[r] + 2, bytes, 2); - } + fetch_one_register (regcache, th, r); else - regcache->raw_collect (r, context_ptr + windows_process->mappings[r]); + fetch_one_register (regcache, th, r); } /* Store a new register value into the context of the thread tied to @@ -545,9 +427,9 @@ windows_nat_target::store_registers (struct regcache *regcache, int r) if (r < 0) for (r = 0; r < gdbarch_num_regs (regcache->arch ()); r++) - windows_store_one_register (regcache, th, r); + store_one_register (regcache, th, r); else - windows_store_one_register (regcache, th, r); + store_one_register (regcache, th, r); } bool @@ -1472,7 +1354,7 @@ windows_nat_target::do_initial_windows_stuff (DWORD pid, bool attaching) { struct inferior *inf; - initialize_windows_arch (); + initialize_windows_arch (attaching); windows_process->last_sig = GDB_SIGNAL_0; windows_process->open_process_used = 0; @@ -1490,22 +1372,6 @@ windows_nat_target::do_initial_windows_stuff (DWORD pid, bool attaching) clear_proceed_status (0); init_wait_for_inferior (); -#ifdef __x86_64__ - windows_process->ignore_first_breakpoint - = !attaching && windows_process->wow64_process; - - if (!windows_process->wow64_process) - { - windows_process->mappings = amd64_mappings; - windows_process->segment_register_p = amd64_windows_segment_register_p; - } - else -#endif - { - windows_process->mappings = i386_mappings; - windows_process->segment_register_p = i386_windows_segment_register_p; - } - inferior_appeared (inf, pid); inf->attach_flag = attaching; diff --git a/gdb/windows-nat.h b/gdb/windows-nat.h index 6553052f420..df872907535 100644 --- a/gdb/windows-nat.h +++ b/gdb/windows-nat.h @@ -83,10 +83,6 @@ struct windows_per_inferior : public windows_nat::windows_process_info const int *mappings = nullptr; - /* The function to use in order to determine whether a register is - a segment register or not. */ - segment_register_p_ftype *segment_register_p = nullptr; - std::vector solibs; #ifdef __CYGWIN__ @@ -184,8 +180,9 @@ struct windows_nat_target : public inf_child_target protected: /* Initialize arch-specific data for a new inferior (debug registers, - register mappings). */ - virtual void initialize_windows_arch () = 0; + register mappings). If ATTACHING is true, we're attaching to an + already-running process. */ + virtual void initialize_windows_arch (bool attaching) = 0; /* Cleanup arch-specific data after inferior exit. */ virtual void cleanup_windows_arch () = 0; @@ -198,6 +195,26 @@ struct windows_nat_target : public inf_child_target /* Set the stepping bit in the thread context. */ virtual void thread_context_step (windows_thread_info *th) = 0; + /* Fetches register number R from the given windows_thread_info, + and supplies its value to the given regcache. + + This function assumes that R is non-negative. A failed assertion + is raised if that is not true. + + This function assumes that TH->RELOAD_CONTEXT is not set, meaning + that the windows_thread_info has an up-to-date context. A failed + assertion is raised if that assumption is violated. */ + virtual void fetch_one_register (struct regcache *regcache, + windows_thread_info *th, int r) = 0; + + /* Collect the register number R from the given regcache, and store + its value into the corresponding area of the given thread's context. + + This function assumes that R is non-negative. A failed assertion + assertion is raised if that is not true. */ + virtual void store_one_register (const struct regcache *regcache, + windows_thread_info *th, int r) = 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 88844e0675a..96dd61b39fb 100644 --- a/gdb/x86-windows-nat.c +++ b/gdb/x86-windows-nat.c @@ -23,6 +23,9 @@ #include "x86-nat.h" +#include "i386-tdep.h" +#include "i387-tdep.h" + using namespace windows_nat; /* If we're not using the old Cygwin header file set, define the @@ -53,17 +56,26 @@ check (BOOL ok, const char *file, int line) struct x86_windows_per_inferior : public windows_per_inferior { uintptr_t dr[8] {}; + + /* The function to use in order to determine whether a register is + a segment register or not. */ + segment_register_p_ftype *segment_register_p = nullptr; }; struct x86_windows_nat_target final : public x86_nat_target { - void initialize_windows_arch () override; + void initialize_windows_arch (bool attaching) 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; + + void fetch_one_register (struct regcache *regcache, + windows_thread_info *th, int r) override; + void store_one_register (const struct regcache *regcache, + windows_thread_info *th, int r) override; }; /* The current process. */ @@ -72,9 +84,25 @@ static x86_windows_per_inferior x86_windows_process; /* See windows-nat.h. */ void -x86_windows_nat_target::initialize_windows_arch () +x86_windows_nat_target::initialize_windows_arch (bool attaching) { memset (x86_windows_process.dr, 0, sizeof (x86_windows_process.dr)); + +#ifdef __x86_64__ + x86_windows_process.ignore_first_breakpoint + = !attaching && x86_windows_process.wow64_process; + + if (!x86_windows_process.wow64_process) + { + x86_windows_process.mappings = amd64_mappings; + x86_windows_process.segment_register_p = amd64_windows_segment_register_p; + } + else +#endif + { + x86_windows_process.mappings = i386_mappings; + x86_windows_process.segment_register_p = i386_windows_segment_register_p; + } } /* See windows-nat.h. */ @@ -158,6 +186,111 @@ x86_windows_nat_target::thread_context_step (windows_thread_info *th) }); } +/* See windows-nat.h. */ + +void +x86_windows_nat_target::fetch_one_register (struct regcache *regcache, + windows_thread_info *th, int r) +{ + gdb_assert (r >= 0); + gdb_assert (!th->reload_context); + + char *context_ptr = x86_windows_process.with_context (th, [] (auto *context) + { + return (char *) context; + }); + + char *context_offset = context_ptr + x86_windows_process.mappings[r]; + struct gdbarch *gdbarch = regcache->arch (); + i386_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + gdb_assert (!gdbarch_read_pc_p (gdbarch)); + gdb_assert (gdbarch_pc_regnum (gdbarch) >= 0); + gdb_assert (!gdbarch_write_pc_p (gdbarch)); + + /* GDB treats some registers as 32-bit, where they are in fact only + 16 bits long. These cases must be handled specially to avoid + reading extraneous bits from the context. */ + if (r == I387_FISEG_REGNUM (tdep) + || x86_windows_process.segment_register_p (r)) + { + gdb_byte bytes[4] = {}; + memcpy (bytes, context_offset, 2); + regcache->raw_supply (r, bytes); + } + else if (r == I387_FOP_REGNUM (tdep)) + { + long l = (*((long *) context_offset) >> 16) & ((1 << 11) - 1); + regcache->raw_supply (r, &l); + } + else + { + if (th->stopped_at_software_breakpoint + && !th->pc_adjusted + && r == gdbarch_pc_regnum (gdbarch)) + { + int size = register_size (gdbarch, r); + if (size == 4) + { + uint32_t value; + memcpy (&value, context_offset, size); + value -= gdbarch_decr_pc_after_break (gdbarch); + memcpy (context_offset, &value, size); + } + else + { + gdb_assert (size == 8); + uint64_t value; + memcpy (&value, context_offset, size); + value -= gdbarch_decr_pc_after_break (gdbarch); + memcpy (context_offset, &value, size); + } + /* Make sure we only rewrite the PC a single time. */ + th->pc_adjusted = true; + } + regcache->raw_supply (r, context_offset); + } +} + +/* See windows-nat.h. */ + +void +x86_windows_nat_target::store_one_register (const struct regcache *regcache, + windows_thread_info *th, int r) +{ + gdb_assert (r >= 0); + + char *context_ptr = x86_windows_process.with_context (th, [] (auto *context) + { + return (char *) context; + }); + + struct gdbarch *gdbarch = regcache->arch (); + i386_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* GDB treats some registers as 32-bit, where they are in fact only + 16 bits long. These cases must be handled specially to avoid + overwriting other registers in the context. */ + if (r == I387_FISEG_REGNUM (tdep) + || x86_windows_process.segment_register_p (r)) + { + gdb_byte bytes[4]; + regcache->raw_collect (r, bytes); + memcpy (context_ptr + x86_windows_process.mappings[r], bytes, 2); + } + else if (r == I387_FOP_REGNUM (tdep)) + { + gdb_byte bytes[4]; + regcache->raw_collect (r, bytes); + /* The value of FOP occupies the top two bytes in the context, + so write the two low-order bytes from the cache into the + appropriate spot. */ + memcpy (context_ptr + x86_windows_process.mappings[r] + 2, bytes, 2); + } + else + regcache->raw_collect (r, context_ptr + x86_windows_process.mappings[r]); +} + /* Hardware watchpoint support, adapted from go32-nat.c code. */ /* Pass the address ADDR to the inferior in the I'th debug register. -- 2.52.0