* event-loop.c (event_handle_func): Adjust to use gdb_fildes_t.
[deliverable/binutils-gdb.git] / gdb / gdbserver / win32-i386-low.c
index 18c60eab993a90d82e0cd05d93c3477fcd97f4b5..2d7721133378c71ebc7c512bd847626a0de3a879 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+/* Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 
 #include "server.h"
 #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 unsigned dr[8];
+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;
 
+/* Update the inferior's debug register REGNUM from STATE.  */
+
+void
+i386_dr_low_set_addr (const struct i386_debug_reg_state *state, int regnum)
+{
+  if (! (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR))
+    fatal ("Invalid debug register %d", regnum);
+
+  /* debug_reg_state.dr_mirror is already set.
+     Just notify i386_set_thread_context, i386_thread_added
+     that the registers need to be updated.  */
+  debug_registers_changed = 1;
+  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
+i386_dr_low_set_control (const struct i386_debug_reg_state *state)
+{
+  /* debug_reg_state.dr_control_mirror is already set.
+     Just notify i386_set_thread_context, i386_thread_added
+     that the registers need to be updated.  */
+  debug_registers_changed = 1;
+  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.  */
+
+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.  */
+
+static int
+i386_insert_point (char type, CORE_ADDR addr, int len)
+{
+  switch (type)
+    {
+    case '2':
+    case '3':
+    case '4':
+      return i386_low_insert_watchpoint (&debug_reg_state,
+                                        type, addr, len);
+    default:
+      /* Unsupported.  */
+      return 1;
+    }
+}
+
+static int
+i386_remove_point (char type, CORE_ADDR addr, int len)
+{
+  switch (type)
+    {
+    case '2':
+    case '3':
+    case '4':
+      return i386_low_remove_watchpoint (&debug_reg_state,
+                                        type, addr, len);
+    default:
+      /* Unsupported.  */
+      return 1;
+    }
+}
+
+static int
+i386_stopped_by_watchpoint (void)
+{
+  return i386_low_stopped_by_watchpoint (&debug_reg_state);
+}
+
+static CORE_ADDR
+i386_stopped_data_address (void)
+{
+  CORE_ADDR addr;
+  if (i386_low_stopped_data_address (&debug_reg_state, &addr))
+    return addr;
+  return 0;
+}
+
 static void
 i386_initial_stuff (void)
 {
-  memset (&dr, 0, sizeof (dr));
+  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;
 
   if (th->tid == current_event->dwThreadId)
     {
       /* Copy dr values from the current thread.  */
-      dr[0] = th->context.Dr0;
-      dr[1] = th->context.Dr1;
-      dr[2] = th->context.Dr2;
-      dr[3] = th->context.Dr3;
-      dr[6] = th->context.Dr6;
-      dr[7] = th->context.Dr7;
+      struct i386_debug_reg_state *dr = &debug_reg_state;
+      dr->dr_mirror[0] = th->context.Dr0;
+      dr->dr_mirror[1] = th->context.Dr1;
+      dr->dr_mirror[2] = th->context.Dr2;
+      dr->dr_mirror[3] = th->context.Dr3;
+      dr_status_mirror = th->context.Dr6;
+      dr_control_mirror = th->context.Dr7;
     }
 }
 
@@ -69,13 +200,14 @@ i386_set_thread_context (win32_thread_info *th, DEBUG_EVENT* current_event)
 {
   if (debug_registers_changed)
     {
-      th->context.Dr0 = dr[0];
-      th->context.Dr1 = dr[1];
-      th->context.Dr2 = dr[2];
-      th->context.Dr3 = dr[3];
-      /* th->context.Dr6 = dr[6];
+      struct i386_debug_reg_state *dr = &debug_reg_state;
+      th->context.Dr0 = dr->dr_mirror[0];
+      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_status_mirror;
         FIXME: should we set dr6 also ?? */
-      th->context.Dr7 = dr[7];
+      th->context.Dr7 = dr_control_mirror;
     }
 
   SetThreadContext (th->h, &th->context);
@@ -87,16 +219,17 @@ i386_thread_added (win32_thread_info *th)
   /* Set the debug registers for the new thread if they are used.  */
   if (debug_registers_used)
     {
+      struct i386_debug_reg_state *dr = &debug_reg_state;
       th->context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
       GetThreadContext (th->h, &th->context);
 
-      th->context.Dr0 = dr[0];
-      th->context.Dr1 = dr[1];
-      th->context.Dr2 = dr[2];
-      th->context.Dr3 = dr[3];
-      /* th->context.Dr6 = dr[6];
+      th->context.Dr0 = dr->dr_mirror[0];
+      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_status_mirror;
         FIXME: should we set dr6 also ?? */
-      th->context.Dr7 = dr[7];
+      th->context.Dr7 = dr_control_mirror;
 
       SetThreadContext (th->h, &th->context);
       th->context.ContextFlags = 0;
@@ -109,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
@@ -164,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];
 
@@ -174,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,
@@ -203,6 +422,10 @@ 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,
+  i386_stopped_data_address
 };
This page took 0.027575 seconds and 4 git commands to generate.