* event-loop.c (event_handle_func): Adjust to use gdb_fildes_t.
[deliverable/binutils-gdb.git] / gdb / gdbserver / win32-i386-low.c
index 7e058a58b564866122d4ea07845a257833e92b88..2d7721133378c71ebc7c512bd847626a0de3a879 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "win32-low.h"
 #include "i386-low.h"
 
+#ifndef CONTEXT_EXTENDED_REGISTERS
+#define CONTEXT_EXTENDED_REGISTERS 0
+#endif
+
 #define FCS_REGNUM 27
 #define FOP_REGNUM 31
 
 #define FLAG_TRACE_BIT 0x100
 
+#ifdef __x86_64__
+/* Defined in auto-generated file reg-amd64.c.  */
+void init_registers_amd64 (void);
+#else
 /* Defined in auto-generated file reg-i386.c.  */
 void init_registers_i386 (void);
+#endif
 
 static struct i386_debug_reg_state debug_reg_state;
+static unsigned dr_status_mirror;
+static unsigned dr_control_mirror;
 
 static int debug_registers_changed = 0;
 static int debug_registers_used = 0;
@@ -47,6 +58,14 @@ i386_dr_low_set_addr (const struct i386_debug_reg_state *state, int regnum)
   debug_registers_used = 1;
 }
 
+CORE_ADDR
+i386_dr_low_get_addr (int regnum)
+{
+  gdb_assert (DR_FIRSTADDR <= regnum && regnum < DR_LASTADDR);
+
+  return debug_reg_state.dr_mirror[regnum];
+}
+
 /* Update the inferior's DR7 debug control register from STATE.  */
 
 void
@@ -59,14 +78,21 @@ i386_dr_low_set_control (const struct i386_debug_reg_state *state)
   debug_registers_used = 1;
 }
 
+unsigned
+i386_dr_low_get_control (void)
+{
+  return dr_control_mirror;
+}
+
 /* Get the value of the DR6 debug status register from the inferior
    and record it in STATE.  */
 
-void
-i386_dr_low_get_status (struct i386_debug_reg_state *state)
+unsigned
+i386_dr_low_get_status (void)
 {
   /* We don't need to do anything here, the last call to thread_rec for
      current_event.dwThreadId id has already set it.  */
+  return dr_status_mirror;
 }
 
 /* Watchpoint support.  */
@@ -124,18 +150,35 @@ i386_initial_stuff (void)
   i386_low_init_dregs (&debug_reg_state);
   debug_registers_changed = 0;
   debug_registers_used = 0;
+  dr_status_mirror = 0;
+  dr_control_mirror = 0;
 }
 
 static void
 i386_get_thread_context (win32_thread_info *th, DEBUG_EVENT* current_event)
 {
-  th->context.ContextFlags = \
-    CONTEXT_FULL | \
-    CONTEXT_FLOATING_POINT | \
-    CONTEXT_EXTENDED_REGISTERS | \
-    CONTEXT_DEBUG_REGISTERS;
+  /* Requesting the CONTEXT_EXTENDED_REGISTERS register set fails if
+     the system doesn't support extended registers.  */
+  static DWORD extended_registers = CONTEXT_EXTENDED_REGISTERS;
 
-  GetThreadContext (th->h, &th->context);
+ again:
+  th->context.ContextFlags = (CONTEXT_FULL
+                             | CONTEXT_FLOATING_POINT
+                             | CONTEXT_DEBUG_REGISTERS
+                             | extended_registers);
+
+  if (!GetThreadContext (th->h, &th->context))
+    {
+      DWORD e = GetLastError ();
+
+      if (extended_registers && e == ERROR_INVALID_PARAMETER)
+       {
+         extended_registers = 0;
+         goto again;
+       }
+
+      error ("GetThreadContext failure %ld\n", (long) e);
+    }
 
   debug_registers_changed = 0;
 
@@ -147,8 +190,8 @@ i386_get_thread_context (win32_thread_info *th, DEBUG_EVENT* current_event)
       dr->dr_mirror[1] = th->context.Dr1;
       dr->dr_mirror[2] = th->context.Dr2;
       dr->dr_mirror[3] = th->context.Dr3;
-      dr->dr_status_mirror = th->context.Dr6;
-      dr->dr_control_mirror = th->context.Dr7;
+      dr_status_mirror = th->context.Dr6;
+      dr_control_mirror = th->context.Dr7;
     }
 }
 
@@ -162,9 +205,9 @@ i386_set_thread_context (win32_thread_info *th, DEBUG_EVENT* current_event)
       th->context.Dr1 = dr->dr_mirror[1];
       th->context.Dr2 = dr->dr_mirror[2];
       th->context.Dr3 = dr->dr_mirror[3];
-      /* th->context.Dr6 = dr->dr_status_mirror;
+      /* th->context.Dr6 = dr_status_mirror;
         FIXME: should we set dr6 also ?? */
-      th->context.Dr7 = dr->dr_control_mirror;
+      th->context.Dr7 = dr_control_mirror;
     }
 
   SetThreadContext (th->h, &th->context);
@@ -184,9 +227,9 @@ i386_thread_added (win32_thread_info *th)
       th->context.Dr1 = dr->dr_mirror[1];
       th->context.Dr2 = dr->dr_mirror[2];
       th->context.Dr3 = dr->dr_mirror[3];
-      /* th->context.Dr6 = dr->dr_status_mirror;
+      /* th->context.Dr6 = dr_status_mirror;
         FIXME: should we set dr6 also ?? */
-      th->context.Dr7 = dr->dr_control_mirror;
+      th->context.Dr7 = dr_control_mirror;
 
       SetThreadContext (th->h, &th->context);
       th->context.ContextFlags = 0;
@@ -199,6 +242,8 @@ i386_single_step (win32_thread_info *th)
   th->context.EFlags |= FLAG_TRACE_BIT;
 }
 
+#ifndef __x86_64__
+
 /* An array of offset mappings into a Win32 Context structure.
    This is a one-to-one mapping which is indexed by gdb's register
    numbers.  It retrieves an offset into the context structure where
@@ -254,9 +299,79 @@ static const int mappings[] = {
 };
 #undef context_offset
 
+#else /* __x86_64__ */
+
+#define context_offset(x) (offsetof (CONTEXT, x))
+static const int mappings[] =
+{
+  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)
+};
+#undef context_offset
+
+#endif /* __x86_64__ */
+
 /* Fetch register from gdbserver regcache data.  */
 static void
-i386_fetch_inferior_register (win32_thread_info *th, int r)
+i386_fetch_inferior_register (struct regcache *regcache,
+                             win32_thread_info *th, int r)
 {
   char *context_offset = (char *) &th->context + mappings[r];
 
@@ -264,27 +379,41 @@ i386_fetch_inferior_register (win32_thread_info *th, int r)
   if (r == FCS_REGNUM)
     {
       l = *((long *) context_offset) & 0xffff;
-      supply_register (r, (char *) &l);
+      supply_register (regcache, r, (char *) &l);
     }
   else if (r == FOP_REGNUM)
     {
       l = (*((long *) context_offset) >> 16) & ((1 << 11) - 1);
-      supply_register (r, (char *) &l);
+      supply_register (regcache, r, (char *) &l);
     }
   else
-    supply_register (r, context_offset);
+    supply_register (regcache, r, context_offset);
 }
 
 /* Store a new register value into the thread context of TH.  */
 static void
-i386_store_inferior_register (win32_thread_info *th, int r)
+i386_store_inferior_register (struct regcache *regcache,
+                             win32_thread_info *th, int r)
 {
   char *context_offset = (char *) &th->context + mappings[r];
-  collect_register (r, context_offset);
+  collect_register (regcache, r, context_offset);
+}
+
+static const unsigned char i386_win32_breakpoint = 0xcc;
+#define i386_win32_breakpoint_len 1
+
+static void
+init_windows_x86 (void)
+{
+#ifdef __x86_64__
+  init_registers_amd64 ();
+#else
+  init_registers_i386 ();
+#endif
 }
 
 struct win32_target_ops the_low_target = {
-  init_registers_i386,
+  init_windows_x86,
   sizeof (mappings) / sizeof (mappings[0]),
   i386_initial_stuff,
   i386_get_thread_context,
@@ -293,8 +422,8 @@ struct win32_target_ops the_low_target = {
   i386_fetch_inferior_register,
   i386_store_inferior_register,
   i386_single_step,
-  NULL, /* breakpoint */
-  0, /* breakpoint_len */
+  &i386_win32_breakpoint,
+  i386_win32_breakpoint_len,
   i386_insert_point,
   i386_remove_point,
   i386_stopped_by_watchpoint,
This page took 0.027234 seconds and 4 git commands to generate.