This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 2/2] x86_64-windows GDB crash due to fs_base/gs_base registers


GDB is currently crashing anytime we try to access the fs_base/gs_base
registers, either to read them, or to write them. This can be observed
under various scenarios:
  - Explicit reference to those registers (eg: print $fs_base) --
    probably relatively rare;
  - Calling a function in the inferior, with the crash happening
    because we are trying to read those registers in order to save
    their value ahead of making the function call;
  - Just a plain "info registers";

The crash was introduced by the following commit:

    | commit 48aeef91c248291dd03583798904612426b1f40a
    | Date:   Mon Jun 26 18:14:43 2017 -0700
    | Subject: Include the fs_base and gs_base registers in amd64 target descriptions.

The Windows-nat implementation was unfortunately not prepared to deal
with those new registers. In particular, the way it fetches registers
is done by using a table where the index is the register number, and
the value at that index is the offset in the area in the thread's CONTEXT
data where the corresponding register value is stored.

For instance, in amd64-windows-nat.c, we can find the mappings static
array containing the following 57 elements in it:

    #define context_offset(x) (offsetof (CONTEXT, x))
    static const int mappings[] =
    {
      context_offset (Rax),
      [...]
      context_offset (FloatSave.MxCsr)
    };

That array is then used by windows_fetch_one_register via:

    char *context_offset = ((char *) &th->context) + mappings[r];

The problem is that fs_base's register number is 172, which is
well past the end of the mappings array (57 elements in total).
We end up getting an undefined offset, which happens to be so large
that it then causes the address where we try to read the register
value (a little bit later) to be invalid, thus crashing GDB with
a SEGV.

This patch changes the approach taken for determining the offset
of a given register. Instead of the target-specific part of
window-nat (i.e. i386-windows-nat.c and amd64-windows-nat.c)
registering a table of offsets to windows-nat.c, they now
register functions that, given a register number, return an
offset. That way, we can more explicitly match register numbers
to specific offsets, which is a much less fragile, because
it doesn't depend on a register numbering which might change.
It is also resilient to the addition of new registers in the
fugure.

And regarding fs_base and gs_base themselves, it appears managing
those registers might not be supported; could not find a field
in CONTEXT that would correspond to those registers. So this patch
treats those two registers as not available. Eg:

    (gdb) info registers
    [...]
    fs_base        <unavailable>
    gs_base        <unavailable>

New AMD64_*_REGNUM and I386_*_REGNUM enumerates are being added
as well. We could have done without them, but they make the code
clearer to read.

gdb/ChangeLog:

        * amd64-tdep.h (enum amd64_regnum): Add AMD64_ST2_REGNUM,
        AMD64_ST3_REGNUM, AMD64_ST4_REGNUM, AMD64_ST5_REGNUM,
        AMD64_ST6_REGNUM, AMD64_ST7_REGNUM, AMD64_FISEG_REGNUM,
        AMD64_FIOFF_REGNUM, AMD64_FOSEG_REGNUM, AMD64_FOOFF_REGNUM,
        AMD64_FOP_REGNUM, AMD64_XMM2_REGNUM, AMD64_XMM3_REGNUM,
        AMD64_XMM4_REGNUM, AMD64_XMM5_REGNUM, AMD64_XMM6_REGNUM,
        AMD64_XMM7_REGNUM, AMD64_XMM8_REGNUM, AMD64_XMM9_REGNUM,
        AMD64_XMM10_REGNUM, AMD64_XMM11_REGNUM, AMD64_XMM12_REGNUM,
        AMD64_XMM13_REGNUM, AMD64_XMM14_REGNUM, AMD64_XMM15_REGNUM.
        * amd64-windows-nat.c (mappings): Delete.
        (amd64_windows_context_register_offset): New function.
        (_initialize_amd64_windows_nat): Replace call to
        windows_set_context_register_offsets by call to
        windows_set_context_register_offset.
        * i386-tdep.h (enum i386_regnum): Add I386_ST1_REGNUM,
        I386_ST2_REGNUM, I386_ST3_REGNUM, I386_ST4_REGNUM, I386_ST5_REGNUM,
        I386_ST6_REGNUM, I386_ST7_REGNUM, I386_FCTRL_REGNUM,
        I386_FSTAT_REGNUM, I386_FTAG_REGNUM, I386_FISEG_REGNUM,
        I386_FIOFF_REGNUM, I386_FOSEG_REGNUM, I386_FOOFF_REGNUM,
        I386_FOP_REGNUM, I386_XMM0_REGNUM, I386_XMM1_REGNUM,
        I386_XMM2_REGNUM, I386_XMM3_REGNUM, I386_XMM4_REGNUM,
        I386_XMM5_REGNUM, I386_XMM6_REGNUM, I386_XMM7_REGNUM.
        * i386-windows-nat.c (mappings): Delete.
        (i386_windows_context_register_offset): New function.
        (_initialize_i386_windows_nat): Replace call to
        windows_set_context_register_offsets by call to
        windows_set_context_register_offset.
        * windows-nat.c (mappings): Delete.
        (context_register_offset): New static global.
        (windows_set_context_register_offsets): Renamed to
        windows_set_context_register_offset.  Update.
        (windows_fetch_one_register): Use context_register_offset
        instead of mappings to compute the register location.
        Add handling of the case where the register is not supported.
        Rename context_offset into reg_buf.
        (windows_store_one_register): Likewise.
        * windows-nat.h (context_register_offset_ftype): New typedef.
        (windows_set_context_register_offsets): Rename to
        windows_set_context_register_offset, and change paramter
        to "context_register_offset_ftype *" instead of "int".

No test added, as this issue is detected by gdb.base/reggroups.exp.
Any testcase that makes an inferior function call would also detect
this issue.

Tested on x86-windows and x86_64-windows using AdaCore's testsuite.
---
 gdb/amd64-tdep.h        |  25 +++++++++
 gdb/amd64-windows-nat.c | 142 +++++++++++++++++++++++++++---------------------
 gdb/i386-tdep.h         |  23 ++++++++
 gdb/i386-windows-nat.c  | 110 +++++++++++++++++++++----------------
 gdb/windows-nat.c       |  46 ++++++++++------
 gdb/windows-nat.h       |   9 ++-
 6 files changed, 226 insertions(+), 129 deletions(-)

diff --git a/gdb/amd64-tdep.h b/gdb/amd64-tdep.h
index 7d3791a..9c1b650 100644
--- a/gdb/amd64-tdep.h
+++ b/gdb/amd64-tdep.h
@@ -57,11 +57,36 @@ enum amd64_regnum
   AMD64_GS_REGNUM,		/* %gs */
   AMD64_ST0_REGNUM = 24,	/* %st0 */
   AMD64_ST1_REGNUM,		/* %st1 */
+  AMD64_ST2_REGNUM,		/* %st2 */
+  AMD64_ST3_REGNUM,		/* %st3 */
+  AMD64_ST4_REGNUM,		/* %st4 */
+  AMD64_ST5_REGNUM,		/* %st5 */
+  AMD64_ST6_REGNUM,		/* %st6 */
+  AMD64_ST7_REGNUM,		/* %st7 */
   AMD64_FCTRL_REGNUM = AMD64_ST0_REGNUM + 8,
   AMD64_FSTAT_REGNUM = AMD64_ST0_REGNUM + 9,
   AMD64_FTAG_REGNUM = AMD64_ST0_REGNUM + 10,
+  AMD64_FISEG_REGNUM,
+  AMD64_FIOFF_REGNUM,
+  AMD64_FOSEG_REGNUM,
+  AMD64_FOOFF_REGNUM,
+  AMD64_FOP_REGNUM,
   AMD64_XMM0_REGNUM = 40,	/* %xmm0 */
   AMD64_XMM1_REGNUM,		/* %xmm1 */
+  AMD64_XMM2_REGNUM,		/* %xmm2 */
+  AMD64_XMM3_REGNUM,		/* %xmm3 */
+  AMD64_XMM4_REGNUM,		/* %xmm4 */
+  AMD64_XMM5_REGNUM,		/* %xmm5 */
+  AMD64_XMM6_REGNUM,		/* %xmm6 */
+  AMD64_XMM7_REGNUM,		/* %xmm7 */
+  AMD64_XMM8_REGNUM,		/* %xmm8 */
+  AMD64_XMM9_REGNUM,		/* %xmm9 */
+  AMD64_XMM10_REGNUM,		/* %xmm10 */
+  AMD64_XMM11_REGNUM,		/* %xmm11 */
+  AMD64_XMM12_REGNUM,		/* %xmm12 */
+  AMD64_XMM13_REGNUM,		/* %xmm13 */
+  AMD64_XMM14_REGNUM,		/* %xmm14 */
+  AMD64_XMM15_REGNUM,		/* %xmm15 */
   AMD64_MXCSR_REGNUM = AMD64_XMM0_REGNUM + 16,
   AMD64_YMM0H_REGNUM,		/* %ymm0h */
   AMD64_YMM15H_REGNUM = AMD64_YMM0H_REGNUM + 15,
diff --git a/gdb/amd64-windows-nat.c b/gdb/amd64-windows-nat.c
index 0c7dbed..61aed8d 100644
--- a/gdb/amd64-windows-nat.c
+++ b/gdb/amd64-windows-nat.c
@@ -22,70 +22,86 @@
 
 #include <windows.h>
 
-#define context_offset(x) (offsetof (CONTEXT, x))
-static const int mappings[] =
+/* See context_register_offset_ftype.  */
+
+static int
+amd64_windows_context_register_offset (int regnum)
 {
-  context_offset (Rax),
-  context_offset (Rbx),
-  context_offset (Rcx),
-  context_offset (Rdx),
-  context_offset (Rsi),
-  context_offset (Rdi),
-  context_offset (Rbp),
-  context_offset (Rsp),
-  context_offset (R8),
-  context_offset (R9),
-  context_offset (R10),
-  context_offset (R11),
-  context_offset (R12),
-  context_offset (R13),
-  context_offset (R14),
-  context_offset (R15),
-  context_offset (Rip),
-  context_offset (EFlags),
-  context_offset (SegCs),
-  context_offset (SegSs),
-  context_offset (SegDs),
-  context_offset (SegEs),
-  context_offset (SegFs),
-  context_offset (SegGs),
-  context_offset (FloatSave.FloatRegisters[0]),
-  context_offset (FloatSave.FloatRegisters[1]),
-  context_offset (FloatSave.FloatRegisters[2]),
-  context_offset (FloatSave.FloatRegisters[3]),
-  context_offset (FloatSave.FloatRegisters[4]),
-  context_offset (FloatSave.FloatRegisters[5]),
-  context_offset (FloatSave.FloatRegisters[6]),
-  context_offset (FloatSave.FloatRegisters[7]),
-  context_offset (FloatSave.ControlWord),
-  context_offset (FloatSave.StatusWord),
-  context_offset (FloatSave.TagWord),
-  context_offset (FloatSave.ErrorSelector),
-  context_offset (FloatSave.ErrorOffset),
-  context_offset (FloatSave.DataSelector),
-  context_offset (FloatSave.DataOffset),
-  context_offset (FloatSave.ErrorSelector)
-  /* XMM0-7 */ ,
-  context_offset (Xmm0),
-  context_offset (Xmm1),
-  context_offset (Xmm2),
-  context_offset (Xmm3),
-  context_offset (Xmm4),
-  context_offset (Xmm5),
-  context_offset (Xmm6),
-  context_offset (Xmm7),
-  context_offset (Xmm8),
-  context_offset (Xmm9),
-  context_offset (Xmm10),
-  context_offset (Xmm11),
-  context_offset (Xmm12),
-  context_offset (Xmm13),
-  context_offset (Xmm14),
-  context_offset (Xmm15),
-  /* MXCSR */
-  context_offset (FloatSave.MxCsr)
-};
+#define context_offset(x) (offsetof (CONTEXT, x))
+  switch (regnum)
+    {
+      case AMD64_RAX_REGNUM: return context_offset (Rax);
+      case AMD64_RBX_REGNUM: return context_offset (Rbx);
+      case AMD64_RCX_REGNUM: return context_offset (Rcx);
+      case AMD64_RDX_REGNUM: return context_offset (Rdx);
+      case AMD64_RSI_REGNUM: return context_offset (Rsi);
+      case AMD64_RDI_REGNUM: return context_offset (Rdi);
+      case AMD64_RBP_REGNUM: return context_offset (Rbp);
+      case AMD64_RSP_REGNUM: return context_offset (Rsp);
+      case AMD64_R8_REGNUM: return context_offset (R8);
+      case AMD64_R9_REGNUM: return context_offset (R9);
+      case AMD64_R10_REGNUM: return context_offset (R10);
+      case AMD64_R11_REGNUM: return context_offset (R11);
+      case AMD64_R12_REGNUM: return context_offset (R12);
+      case AMD64_R13_REGNUM: return context_offset (R13);
+      case AMD64_R14_REGNUM: return context_offset (R14);
+      case AMD64_R15_REGNUM: return context_offset (R15);
+      case AMD64_RIP_REGNUM: return context_offset (Rip);
+      case AMD64_EFLAGS_REGNUM: return context_offset (EFlags);
+      case AMD64_CS_REGNUM: return context_offset (SegCs);
+      case AMD64_SS_REGNUM: return context_offset (SegSs);
+      case AMD64_DS_REGNUM: return context_offset (SegDs);
+      case AMD64_ES_REGNUM: return context_offset (SegEs);
+      case AMD64_FS_REGNUM: return context_offset (SegFs);
+      case AMD64_GS_REGNUM: return context_offset (SegGs);
+      case AMD64_ST0_REGNUM:
+	return context_offset (FloatSave.FloatRegisters[0]);
+      case AMD64_ST1_REGNUM:
+	return context_offset (FloatSave.FloatRegisters[1]);
+      case AMD64_ST2_REGNUM:
+	return context_offset (FloatSave.FloatRegisters[2]);
+      case AMD64_ST3_REGNUM:
+	return context_offset (FloatSave.FloatRegisters[3]);
+      case AMD64_ST4_REGNUM:
+	return context_offset (FloatSave.FloatRegisters[4]);
+      case AMD64_ST5_REGNUM:
+	return context_offset (FloatSave.FloatRegisters[5]);
+      case AMD64_ST6_REGNUM:
+	return context_offset (FloatSave.FloatRegisters[6]);
+      case AMD64_ST7_REGNUM:
+	return context_offset (FloatSave.FloatRegisters[7]);
+      case AMD64_FCTRL_REGNUM: return context_offset (FloatSave.ControlWord);
+      case AMD64_FSTAT_REGNUM: return context_offset (FloatSave.StatusWord);
+      case AMD64_FTAG_REGNUM: return context_offset (FloatSave.TagWord);
+      case AMD64_FISEG_REGNUM: return context_offset (FloatSave.ErrorSelector);
+      case AMD64_FIOFF_REGNUM: return context_offset (FloatSave.ErrorOffset);
+      case AMD64_FOSEG_REGNUM: return context_offset (FloatSave.DataSelector);
+      case AMD64_FOOFF_REGNUM: return context_offset (FloatSave.DataOffset);
+      case AMD64_FOP_REGNUM: return context_offset (FloatSave.ErrorSelector);
+      case AMD64_XMM0_REGNUM: return context_offset (Xmm0);
+      case AMD64_XMM1_REGNUM: return context_offset (Xmm1);
+      case AMD64_XMM2_REGNUM: return context_offset (Xmm2);
+      case AMD64_XMM3_REGNUM: return context_offset (Xmm3);
+      case AMD64_XMM4_REGNUM: return context_offset (Xmm4);
+      case AMD64_XMM5_REGNUM: return context_offset (Xmm5);
+      case AMD64_XMM6_REGNUM: return context_offset (Xmm6);
+      case AMD64_XMM7_REGNUM: return context_offset (Xmm7);
+      case AMD64_XMM8_REGNUM: return context_offset (Xmm8);
+      case AMD64_XMM9_REGNUM: return context_offset (Xmm9);
+      case AMD64_XMM10_REGNUM: return context_offset (Xmm10);
+      case AMD64_XMM11_REGNUM: return context_offset (Xmm11);
+      case AMD64_XMM12_REGNUM: return context_offset (Xmm12);
+      case AMD64_XMM13_REGNUM: return context_offset (Xmm13);
+      case AMD64_XMM14_REGNUM: return context_offset (Xmm14);
+      case AMD64_XMM15_REGNUM: return context_offset (Xmm15);
+      case AMD64_MXCSR_REGNUM: return context_offset (FloatSave.MxCsr);
+      case AMD64_FSBASE_REGNUM: return -1 /* Not in CONTEXT struct.  */;
+      case AMD64_GSBASE_REGNUM: return -1 /* Not in CONTEXT struct.  */;
+   }
 #undef context_offset
+  
+  return -1;
+}
 
 /* segment_register_p_ftype implementation for amd64.  */
 
@@ -98,7 +114,7 @@ amd64_windows_segment_register_p (int regnum)
 void
 _initialize_amd64_windows_nat (void)
 {
-  windows_set_context_register_offsets (mappings);
+  windows_set_context_register_offset (amd64_windows_context_register_offset);
   windows_set_segment_register_p (amd64_windows_segment_register_p);
   x86_set_debug_register_length (8);
 }
diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h
index 81a93f1..8cfa935 100644
--- a/gdb/i386-tdep.h
+++ b/gdb/i386-tdep.h
@@ -285,6 +285,29 @@ enum i386_regnum
   I386_FS_REGNUM,		/* %fs */
   I386_GS_REGNUM,		/* %gs */
   I386_ST0_REGNUM,		/* %st(0) */
+  I386_ST1_REGNUM,		/* %st(1) */
+  I386_ST2_REGNUM,		/* %st(2) */
+  I386_ST3_REGNUM,		/* %st(3) */
+  I386_ST4_REGNUM,		/* %st(4) */
+  I386_ST5_REGNUM,		/* %st(5) */
+  I386_ST6_REGNUM,		/* %st(6) */
+  I386_ST7_REGNUM,		/* %st(7) */
+  I386_FCTRL_REGNUM,
+  I386_FSTAT_REGNUM,
+  I386_FTAG_REGNUM,
+  I386_FISEG_REGNUM,
+  I386_FIOFF_REGNUM,
+  I386_FOSEG_REGNUM,
+  I386_FOOFF_REGNUM,
+  I386_FOP_REGNUM,
+  I386_XMM0_REGNUM,		/* %xmm0 */
+  I386_XMM1_REGNUM,		/* %xmm1 */
+  I386_XMM2_REGNUM,		/* %xmm2 */
+  I386_XMM3_REGNUM,		/* %xmm3 */
+  I386_XMM4_REGNUM,		/* %xmm4 */
+  I386_XMM5_REGNUM,		/* %xmm5 */
+  I386_XMM6_REGNUM,		/* %xmm6 */
+  I386_XMM7_REGNUM,		/* %xmm7 */
   I386_MXCSR_REGNUM = 40,	/* %mxcsr */ 
   I386_YMM0H_REGNUM,		/* %ymm0h */
   I386_YMM7H_REGNUM = I386_YMM0H_REGNUM + 7,
diff --git a/gdb/i386-windows-nat.c b/gdb/i386-windows-nat.c
index 9efe184..1f65774 100644
--- a/gdb/i386-windows-nat.c
+++ b/gdb/i386-windows-nat.c
@@ -22,55 +22,71 @@
 
 #include <windows.h>
 
-#define context_offset(x) ((int)&(((CONTEXT *)NULL)->x))
-static const int mappings[] =
+/* See context_register_offset_ftype.  */
+
+static int
+i386_windows_context_register_offset (int regnum)
 {
-  context_offset (Eax),
-  context_offset (Ecx),
-  context_offset (Edx),
-  context_offset (Ebx),
-  context_offset (Esp),
-  context_offset (Ebp),
-  context_offset (Esi),
-  context_offset (Edi),
-  context_offset (Eip),
-  context_offset (EFlags),
-  context_offset (SegCs),
-  context_offset (SegSs),
-  context_offset (SegDs),
-  context_offset (SegEs),
-  context_offset (SegFs),
-  context_offset (SegGs),
-  context_offset (FloatSave.RegisterArea[0 * 10]),
-  context_offset (FloatSave.RegisterArea[1 * 10]),
-  context_offset (FloatSave.RegisterArea[2 * 10]),
-  context_offset (FloatSave.RegisterArea[3 * 10]),
-  context_offset (FloatSave.RegisterArea[4 * 10]),
-  context_offset (FloatSave.RegisterArea[5 * 10]),
-  context_offset (FloatSave.RegisterArea[6 * 10]),
-  context_offset (FloatSave.RegisterArea[7 * 10]),
-  context_offset (FloatSave.ControlWord),
-  context_offset (FloatSave.StatusWord),
-  context_offset (FloatSave.TagWord),
-  context_offset (FloatSave.ErrorSelector),
-  context_offset (FloatSave.ErrorOffset),
-  context_offset (FloatSave.DataSelector),
-  context_offset (FloatSave.DataOffset),
-  context_offset (FloatSave.ErrorSelector)
-  /* XMM0-7 */ ,
-  context_offset (ExtendedRegisters[10*16]),
-  context_offset (ExtendedRegisters[11*16]),
-  context_offset (ExtendedRegisters[12*16]),
-  context_offset (ExtendedRegisters[13*16]),
-  context_offset (ExtendedRegisters[14*16]),
-  context_offset (ExtendedRegisters[15*16]),
-  context_offset (ExtendedRegisters[16*16]),
-  context_offset (ExtendedRegisters[17*16]),
-  /* MXCSR */
-  context_offset (ExtendedRegisters[24])
-};
+#define context_offset(x) ((int)&(((CONTEXT *)NULL)->x))
+  switch (regnum)
+    {
+      case I386_EAX_REGNUM: return context_offset (Eax);
+      case I386_ECX_REGNUM: return context_offset (Ecx);
+      case I386_EDX_REGNUM: return context_offset (Edx);
+      case I386_EBX_REGNUM: return context_offset (Ebx);
+      case I386_ESP_REGNUM: return context_offset (Esp);
+      case I386_EBP_REGNUM: return context_offset (Ebp);
+      case I386_ESI_REGNUM: return context_offset (Esi);
+      case I386_EDI_REGNUM: return context_offset (Edi);
+      case I386_EIP_REGNUM: return context_offset (Eip);
+      case I386_EFLAGS_REGNUM: return context_offset (EFlags);
+      case I386_CS_REGNUM: return context_offset (SegCs);
+      case I386_SS_REGNUM: return context_offset (SegSs);
+      case I386_DS_REGNUM: return context_offset (SegDs);
+      case I386_ES_REGNUM: return context_offset (SegEs);
+      case I386_FS_REGNUM: return context_offset (SegFs);
+      case I386_GS_REGNUM: return context_offset (SegGs);
+      case I386_ST0_REGNUM:
+	return context_offset (FloatSave.RegisterArea[0 * 10]);
+      case I386_ST1_REGNUM:
+	return context_offset (FloatSave.RegisterArea[1 * 10]);
+      case I386_ST2_REGNUM:
+	return context_offset (FloatSave.RegisterArea[2 * 10]);
+      case I386_ST3_REGNUM:
+	return context_offset (FloatSave.RegisterArea[3 * 10]);
+      case I386_ST4_REGNUM:
+	return context_offset (FloatSave.RegisterArea[4 * 10]);
+      case I386_ST5_REGNUM:
+	return context_offset (FloatSave.RegisterArea[5 * 10]);
+      case I386_ST6_REGNUM:
+	return context_offset (FloatSave.RegisterArea[6 * 10]);
+      case I386_ST7_REGNUM:
+	return context_offset (FloatSave.RegisterArea[7 * 10]);
+      case I386_FCTRL_REGNUM: return context_offset (FloatSave.ControlWord);
+      case I386_FSTAT_REGNUM: return context_offset (FloatSave.StatusWord);
+      case I386_FTAG_REGNUM: return context_offset (FloatSave.TagWord);
+      case I386_FISEG_REGNUM: return context_offset (FloatSave.ErrorSelector);
+      case I386_FIOFF_REGNUM: return context_offset (FloatSave.ErrorOffset);
+      case I386_FOSEG_REGNUM: return context_offset (FloatSave.DataSelector);
+      case I386_FOOFF_REGNUM: return context_offset (FloatSave.DataOffset);
+      case I386_FOP_REGNUM: return context_offset (FloatSave.ErrorSelector);
+      /* XMM0-7 */
+      case I386_XMM0_REGNUM: return context_offset (ExtendedRegisters[10*16]);
+      case I386_XMM1_REGNUM: return context_offset (ExtendedRegisters[11*16]);
+      case I386_XMM2_REGNUM: return context_offset (ExtendedRegisters[12*16]);
+      case I386_XMM3_REGNUM: return context_offset (ExtendedRegisters[13*16]);
+      case I386_XMM4_REGNUM: return context_offset (ExtendedRegisters[14*16]);
+      case I386_XMM5_REGNUM: return context_offset (ExtendedRegisters[15*16]);
+      case I386_XMM6_REGNUM: return context_offset (ExtendedRegisters[16*16]);
+      case I386_XMM7_REGNUM: return context_offset (ExtendedRegisters[17*16]);
+      /* MXCSR */
+      case I386_MXCSR_REGNUM: return context_offset (ExtendedRegisters[24]);
+    }
 #undef context_offset
 
+  return -1;
+}
+
 /* segment_register_p_ftype implementation for x86.  */
 
 static int
@@ -82,7 +98,7 @@ i386_windows_segment_register_p (int regnum)
 void
 _initialize_i386_windows_nat (void)
 {
-  windows_set_context_register_offsets (mappings);
+  windows_set_context_register_offset (i386_windows_context_register_offset);
   windows_set_segment_register_p (i386_windows_segment_register_p);
   x86_set_debug_register_length (4);
 }
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index c51ef8f..3d4da60 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -254,15 +254,9 @@ static int debug_memory = 0;		/* show target memory accesses */
 static int debug_exceptions = 0;	/* show target exceptions */
 static int useshell = 0;		/* use shell for subprocesses */
 
-/* This vector maps GDB's idea of a register's number into an offset
-   in the windows exception context vector.
-
-   It also contains the bit mask needed to load the register in question.
-
-   The contents of this table can only be computed by the units
-   that provide CPU-specific support for Windows native debugging.
-   These units should set the table by calling
-   windows_set_context_register_offsets.
+/* A function that returns the offset of a given register inside
+   a thread's CONTEXT structure.  Should be set via a call to
+   windows_set_context_register_offset.
 
    One day we could read a reg, we could inspect the context we
    already have loaded, if it doesn't have the bit set that we need,
@@ -272,7 +266,7 @@ static int useshell = 0;		/* use shell for subprocesses */
    the other regs of the group, and then we copy the info in and set
    out bit.  */
 
-static const int *mappings;
+static context_register_offset_ftype *context_register_offset;
 
 /* The function to use in order to determine whether a register is
    a segment register or not.  */
@@ -354,9 +348,9 @@ static windows_nat_target the_windows_nat_target;
    See the description of MAPPINGS for more details.  */
 
 void
-windows_set_context_register_offsets (const int *offsets)
+windows_set_context_register_offset (context_register_offset_ftype *fun)
 {
-  mappings = offsets;
+  context_register_offset = fun;
 }
 
 /* See windows-nat.h.  */
@@ -545,18 +539,27 @@ windows_fetch_one_register (struct regcache *regcache,
   gdb_assert (r >= 0);
   gdb_assert (!th->reload_context);
 
-  char *context_offset = ((char *) &th->context) + mappings[r];
   struct gdbarch *gdbarch = regcache->arch ();
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int reg_offset = context_register_offset (r);
+
+  if (reg_offset < 0)
+    {
+      /* Unsupported register, nothing we can do, so just return.
+         GDB will show it as unavailable.  */
+      return;
+    }
+
+  char *reg_buf = ((char *) &th->context) + reg_offset;
 
   if (r == I387_FISEG_REGNUM (tdep))
     {
-      long l = *((long *) context_offset) & 0xffff;
+      long l = *((long *) reg_buf) & 0xffff;
       regcache->raw_supply (r, (char *) &l);
     }
   else if (r == I387_FOP_REGNUM (tdep))
     {
-      long l = (*((long *) context_offset) >> 16) & ((1 << 11) - 1);
+      long l = (*((long *) reg_buf) >> 16) & ((1 << 11) - 1);
       regcache->raw_supply (r, (char *) &l);
     }
   else if (segment_register_p (r))
@@ -564,11 +567,11 @@ windows_fetch_one_register (struct regcache *regcache,
       /* GDB treats segment registers as 32bit registers, but they are
 	 in fact only 16 bits long.  Make sure we do not read extra
 	 bits from our source buffer.  */
-      long l = *((long *) context_offset) & 0xffff;
+      long l = *((long *) reg_buf) & 0xffff;
       regcache->raw_supply (r, (char *) &l);
     }
   else
-    regcache->raw_supply (r, context_offset);
+    regcache->raw_supply (r, reg_buf);
 }
 
 void
@@ -629,7 +632,14 @@ windows_store_one_register (const struct regcache *regcache,
 {
   gdb_assert (r >= 0);
 
-  regcache->raw_collect (r, ((char *) &th->context) + mappings[r]);
+  int reg_offset = context_register_offset (r);
+  if (reg_offset < 0)
+    {
+      /* Unsupported register, nothing we can do, so just return.  */
+      return;
+    }
+
+  regcache->raw_collect (r, ((char *) &th->context) + reg_offset);
 }
 
 /* Store a new register value into the context of the thread tied to
diff --git a/gdb/windows-nat.h b/gdb/windows-nat.h
index a6a7f18..f4c9716 100644
--- a/gdb/windows-nat.h
+++ b/gdb/windows-nat.h
@@ -18,7 +18,14 @@
 #ifndef WINDOWS_NAT_H
 #define WINDOWS_NAT_H
 
-extern void windows_set_context_register_offsets (const int *offsets);
+/* A pointer to a function which, given a register number, returns
+   its offset into a thread's CONTEXT structure.
+
+   Returns a negative value if the register is not supported.  */
+typedef int (context_register_offset_ftype) (int regnum);
+
+extern void windows_set_context_register_offset
+  (context_register_offset_ftype *fun);
 
 /* A pointer to a function that should return non-zero iff REGNUM
    corresponds to one of the segment registers.  */
-- 
2.1.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]