Add readelf support for dumping gold version note sections.
[deliverable/binutils-gdb.git] / gdb / gdbserver / win32-i386-low.c
index 655da86d7a856ad491c1cd76af847fc3755cd9bb..1cb0c5fb66c4a32335d0fdca53964a05fcbec511 100644 (file)
@@ -1,13 +1,10 @@
-/* Low level interface to Windows debugging, for gdbserver.
-   Copyright (C) 2006, 2007 Free Software Foundation, Inc.
-
-   Contributed by Leo Zayas.  Based on "win32-nat.c" from GDB.
+/* Copyright (C) 2007-2014 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "server.h"
-#include "regcache.h"
-#include "gdb/signals.h"
-
-#include <windows.h>
-#include <imagehlp.h>
-#include <psapi.h>
-#include <sys/param.h>
-#include <malloc.h>
-#include <process.h>
+#include "win32-low.h"
+#include "i386-low.h"
 
-#ifndef USE_WIN32API
-#include <sys/cygwin.h>
+#ifndef CONTEXT_EXTENDED_REGISTERS
+#define CONTEXT_EXTENDED_REGISTERS 0
 #endif
 
-#define LOG 0
+#define FCS_REGNUM 27
+#define FOP_REGNUM 31
+
+#define FLAG_TRACE_BIT 0x100
 
-#define OUTMSG(X) do { printf X; fflush (stdout); } while (0)
-#if LOG
-#define OUTMSG2(X) do { printf X; fflush (stdout); } while (0)
+#ifdef __x86_64__
+/* Defined in auto-generated file reg-amd64.c.  */
+void init_registers_amd64 (void);
+extern const struct target_desc *tdesc_amd64;
 #else
-#define OUTMSG2(X)
+/* Defined in auto-generated file reg-i386.c.  */
+void init_registers_i386 (void);
+extern const struct target_desc *tdesc_i386;
 #endif
 
-int using_threads = 1;
-
-/* Globals.  */
-static HANDLE current_process_handle = NULL;
-static DWORD current_process_id = 0;
-static enum target_signal last_sig = TARGET_SIGNAL_0;
-
-/* The current debug event from WaitForDebugEvent.  */
-static DEBUG_EVENT current_event;
+static struct i386_debug_reg_state debug_reg_state;
 
 static int debug_registers_changed = 0;
 static int debug_registers_used = 0;
-static unsigned dr[8];
 
-typedef BOOL winapi_DebugActiveProcessStop (DWORD dwProcessId);
-typedef BOOL winapi_DebugSetProcessKillOnExit (BOOL KillOnExit);
+/* Update the inferior's debug register REGNUM from STATE.  */
 
-#define FLAG_TRACE_BIT 0x100
-#define CONTEXT_DEBUGGER (CONTEXT_FULL | CONTEXT_FLOATING_POINT)
-#define CONTEXT_DEBUGGER_DR CONTEXT_DEBUGGER | CONTEXT_DEBUG_REGISTERS \
-  | CONTEXT_EXTENDED_REGISTERS
-
-/* Thread information structure used to track extra information about
-   each thread.  */
-typedef struct thread_info_struct
+void
+i386_dr_low_set_addr (const struct i386_debug_reg_state *state, int regnum)
 {
-  DWORD tid;
-  HANDLE h;
-  int suspend_count;
-  CONTEXT context;
-} thread_info;
-static DWORD main_thread_id = 0;
+  if (! (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR))
+    fatal ("Invalid debug register %d", regnum);
 
-/* Get the thread ID from the current selected inferior (the current
-   thread).  */
-static DWORD
-current_inferior_tid (void)
-{
-  thread_info *th = inferior_target_data (current_inferior);
-  return th->tid;
+  /* 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;
 }
 
-/* Find a thread record given a thread id.  If GET_CONTEXT is set then
-   also retrieve the context for this thread.  */
-static thread_info *
-thread_rec (DWORD id, int get_context)
+CORE_ADDR
+i386_dr_low_get_addr (int regnum)
 {
-  struct thread_info *thread;
-  thread_info *th;
-
-  thread = (struct thread_info *) find_inferior_id (&all_threads, id);
-  if (thread == NULL)
-    return NULL;
-
-  th = inferior_target_data (thread);
-  if (!th->suspend_count && get_context)
-    {
-      if (get_context > 0 && id != current_event.dwThreadId)
-       th->suspend_count = SuspendThread (th->h) + 1;
-      else if (get_context < 0)
-       th->suspend_count = -1;
-
-      th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
+  gdb_assert (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR);
 
-      GetThreadContext (th->h, &th->context);
+  return debug_reg_state.dr_mirror[regnum];
+}
 
-      if (id == current_event.dwThreadId)
-       {
-         /* Copy dr values from that 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;
-       }
-    }
+/* Update the inferior's DR7 debug control register from STATE.  */
 
-  return th;
+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;
 }
 
-/* Add a thread to the thread list.  */
-static thread_info *
-child_add_thread (DWORD tid, HANDLE h)
+unsigned
+i386_dr_low_get_control (void)
 {
-  thread_info *th;
+  return debug_reg_state.dr_control_mirror;
+}
 
-  if ((th = thread_rec (tid, FALSE)))
-    return th;
+/* Get the value of the DR6 debug status register from the inferior
+   and record it in STATE.  */
 
-  th = (thread_info *) malloc (sizeof (*th));
-  memset (th, 0, sizeof (*th));
-  th->tid = tid;
-  th->h = h;
+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 debug_reg_state.dr_status_mirror;
+}
 
-  add_thread (tid, th, (unsigned int) tid);
-  set_inferior_regcache_data ((struct thread_info *)
-                             find_inferior_id (&all_threads, tid),
-                             new_register_cache ());
+/* Watchpoint support.  */
 
-  /* Set the debug registers for the new thread if they are used.  */
-  if (debug_registers_used)
+static int
+i386_insert_point (char type, CORE_ADDR addr, int len)
+{
+  switch (type)
     {
-      /* Only change the value of the debug registers.  */
-      th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
-
-      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];
-         FIXME: should we set dr6 also ?? */
-      th->context.Dr7 = dr[7];
-      SetThreadContext (th->h, &th->context);
-      th->context.ContextFlags = 0;
+    case '2':
+    case '3':
+    case '4':
+      return i386_low_insert_watchpoint (&debug_reg_state,
+                                        type, addr, len);
+    default:
+      /* Unsupported.  */
+      return 1;
     }
+}
 
-  return th;
+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;
+    }
 }
 
-/* Delete a thread from the list of threads.  */
-static void
-delete_thread_info (struct inferior_list_entry *thread)
+static int
+i386_stopped_by_watchpoint (void)
 {
-  thread_info *th = inferior_target_data ((struct thread_info *) thread);
+  return i386_low_stopped_by_watchpoint (&debug_reg_state);
+}
 
-  remove_thread ((struct thread_info *) thread);
-  CloseHandle (th->h);
-  free (th);
+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;
 }
 
-/* Delete a thread from the list of threads.  */
 static void
-child_delete_thread (DWORD id)
+i386_initial_stuff (void)
 {
-  struct inferior_list_entry *thread;
-
-  /* If the last thread is exiting, just return.  */
-  if (all_threads.head == all_threads.tail)
-    return;
-
-  thread = find_inferior_id (&all_threads, id);
-  if (thread == NULL)
-    return;
-
-  delete_thread_info (thread);
+  i386_low_init_dregs (&debug_reg_state);
+  debug_registers_changed = 0;
+  debug_registers_used = 0;
 }
 
-/* Transfer memory from/to the debugged process.  */
-static int
-child_xfer_memory (CORE_ADDR memaddr, char *our, int len,
-                  int write, struct target_ops *target)
+static void
+i386_get_thread_context (win32_thread_info *th, DEBUG_EVENT* current_event)
 {
-  SIZE_T done;
-  long addr = (long) memaddr;
+  /* Requesting the CONTEXT_EXTENDED_REGISTERS register set fails if
+     the system doesn't support extended registers.  */
+  static DWORD extended_registers = CONTEXT_EXTENDED_REGISTERS;
+
+ again:
+  th->context.ContextFlags = (CONTEXT_FULL
+                             | CONTEXT_FLOATING_POINT
+                             | CONTEXT_DEBUG_REGISTERS
+                             | extended_registers);
 
-  if (write)
+  if (!GetThreadContext (th->h, &th->context))
     {
-      WriteProcessMemory (current_process_handle, (LPVOID) addr,
-                         (LPCVOID) our, len, &done);
-      FlushInstructionCache (current_process_handle, (LPCVOID) addr, len);
+      DWORD e = GetLastError ();
+
+      if (extended_registers && e == ERROR_INVALID_PARAMETER)
+       {
+         extended_registers = 0;
+         goto again;
+       }
+
+      error ("GetThreadContext failure %ld\n", (long) e);
     }
-  else
+
+  debug_registers_changed = 0;
+
+  if (th->tid == current_event->dwThreadId)
     {
-      ReadProcessMemory (current_process_handle, (LPCVOID) addr, (LPVOID) our,
-                        len, &done);
+      /* Copy dr values from the current thread.  */
+      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->dr_status_mirror = th->context.Dr6;
+      dr->dr_control_mirror = th->context.Dr7;
     }
-  return done;
 }
 
-/* Generally, what has the program done?  */
-enum target_waitkind
+static void
+i386_set_thread_context (win32_thread_info *th, DEBUG_EVENT* current_event)
 {
-  /* The program has exited.  The exit status is in value.integer.  */
-  TARGET_WAITKIND_EXITED,
-
-  /* The program has stopped with a signal.  Which signal is in
-     value.sig.  */
-  TARGET_WAITKIND_STOPPED,
+  if (debug_registers_changed)
+    {
+      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->dr_status_mirror;
+        FIXME: should we set dr6 also ?? */
+      th->context.Dr7 = dr->dr_control_mirror;
+    }
 
-  /* The program is letting us know that it dynamically loaded something
-     (e.g. it called load(2) on AIX).  */
-  TARGET_WAITKIND_LOADED,
+  SetThreadContext (th->h, &th->context);
+}
 
-  /* The program has exec'ed a new executable file.  The new file's
-     pathname is pointed to by value.execd_pathname.  */
+static void
+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);
 
-  TARGET_WAITKIND_EXECD,
+      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->dr_status_mirror;
+        FIXME: should we set dr6 also ?? */
+      th->context.Dr7 = dr->dr_control_mirror;
 
-  /* Nothing happened, but we stopped anyway.  This perhaps should be handled
-     within target_wait, but I'm not sure target_wait should be resuming the
-     inferior.  */
-  TARGET_WAITKIND_SPURIOUS,
-};
+      SetThreadContext (th->h, &th->context);
+      th->context.ContextFlags = 0;
+    }
+}
 
-struct target_waitstatus
+static void
+i386_single_step (win32_thread_info *th)
 {
-  enum target_waitkind kind;
+  th->context.EFlags |= FLAG_TRACE_BIT;
+}
 
-  /* Forked child pid, execd pathname, exit status or signal number.  */
-  union
-  {
-    int integer;
-    enum target_signal sig;
-    int related_pid;
-    char *execd_pathname;
-    int syscall_id;
-  }
-  value;
-};
-
-#define NUM_REGS 41
-#define FCS_REGNUM 27
-#define FOP_REGNUM 31
+#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
+   the 4 byte register is located.
+   An offset value of -1 indicates that Win32 does not provide this
+   register in it's CONTEXT structure.  In this case regptr will return
+   a pointer into a dummy register.  */
 #define context_offset(x) ((int)&(((CONTEXT *)NULL)->x))
 static const int mappings[] = {
   context_offset (Eax),
@@ -307,830 +295,137 @@ static const int mappings[] = {
   /* MXCSR */
   context_offset (ExtendedRegisters[24])
 };
+#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
 
-/* Clear out any old thread list and reintialize it to a pristine
-   state. */
-static void
-child_init_thread_list (void)
-{
-  for_each_inferior (&all_threads, delete_thread_info);
-}
+#endif /* __x86_64__ */
 
+/* Fetch register from gdbserver regcache data.  */
 static void
-do_initial_child_stuff (DWORD pid)
+i386_fetch_inferior_register (struct regcache *regcache,
+                             win32_thread_info *th, int r)
 {
-  int i;
-
-  last_sig = TARGET_SIGNAL_0;
-
-  debug_registers_changed = 0;
-  debug_registers_used = 0;
-  for (i = 0; i < sizeof (dr) / sizeof (dr[0]); i++)
-    dr[i] = 0;
-  memset (&current_event, 0, sizeof (current_event));
-
-  child_init_thread_list ();
-}
-
-/* Resume all artificially suspended threads if we are continuing
-   execution.  */
-static int
-continue_one_thread (struct inferior_list_entry *this_thread, void *id_ptr)
-{
-  struct thread_info *thread = (struct thread_info *) this_thread;
-  int thread_id = * (int *) id_ptr;
-  thread_info *th = inferior_target_data (thread);
-  int i;
-
-  if ((thread_id == -1 || thread_id == th->tid)
-      && th->suspend_count)
-    {
-      for (i = 0; i < th->suspend_count; i++)
-       (void) ResumeThread (th->h);
-      th->suspend_count = 0;
-      if (debug_registers_changed)
-       {
-         /* Only change the value of the debug registers.  */
-         th->context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
-         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];
-            FIXME: should we set dr6 also ?? */
-         th->context.Dr7 = dr[7];
-         SetThreadContext (th->h, &th->context);
-         th->context.ContextFlags = 0;
-       }
-    }
-
-  return 0;
-}
-
-static BOOL
-child_continue (DWORD continue_status, int thread_id)
-{
-  BOOL res;
-
-  res = ContinueDebugEvent (current_event.dwProcessId,
-                           current_event.dwThreadId, continue_status);
-  continue_status = 0;
-  if (res)
-    find_inferior (&all_threads, continue_one_thread, &thread_id);
+  char *context_offset = (char *) &th->context + mappings[r];
 
-  debug_registers_changed = 0;
-  return res;
-}
-
-/* Fetch register(s) from gdbserver regcache data.  */
-static void
-do_child_fetch_inferior_registers (thread_info *th, int r)
-{
-  char *context_offset = ((char *) &th->context) + mappings[r];
   long l;
   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);
 }
 
-/* Fetch register(s) from the current thread context.  */
+/* Store a new register value into the thread context of TH.  */
 static void
-child_fetch_inferior_registers (int r)
+i386_store_inferior_register (struct regcache *regcache,
+                             win32_thread_info *th, int r)
 {
-  int regno;
-  thread_info *th = thread_rec (current_inferior_tid (), TRUE);
-  if (r == -1 || r == 0 || r > NUM_REGS)
-    child_fetch_inferior_registers (NUM_REGS);
-  else
-    for (regno = 0; regno < r; regno++)
-      do_child_fetch_inferior_registers (th, regno);
+  char *context_offset = (char *) &th->context + mappings[r];
+  collect_register (regcache, r, context_offset);
 }
 
-/* Get register from gdbserver regcache data.  */
-static void
-do_child_store_inferior_registers (thread_info *th, int r)
-{
-  collect_register (r, ((char *) &th->context) + mappings[r]);
-}
+static const unsigned char i386_win32_breakpoint = 0xcc;
+#define i386_win32_breakpoint_len 1
 
-/* Store a new register value into the current thread context.  We don't
-   change the program's context until later, when we resume it.  */
 static void
-child_store_inferior_registers (int r)
+i386_arch_setup (void)
 {
-  int regno;
-  thread_info *th = thread_rec (current_inferior_tid (), TRUE);
-  if (r == -1 || r == 0 || r > NUM_REGS)
-    child_store_inferior_registers (NUM_REGS);
-  else
-    for (regno = 0; regno < r; regno++)
-      do_child_store_inferior_registers (th, regno);
-}
-
-/* Start a new process.
-   PROGRAM is a path to the program to execute.
-   ARGS is a standard NULL-terminated array of arguments,
-   to be passed to the inferior as ``argv''.
-   Returns the new PID on success, -1 on failure.  Registers the new
-   process with the process list.  */
-static int
-win32_create_inferior (char *program, char **program_args)
-{
-#ifndef USE_WIN32API
-  char real_path[MAXPATHLEN];
-  char *orig_path, *new_path, *path_ptr;
-#endif
-  char *winenv = NULL;
-  STARTUPINFO si;
-  PROCESS_INFORMATION pi;
-  BOOL ret;
-  DWORD flags;
-  char *args;
-  int argslen;
-  int argc;
-
-  if (!program)
-    error ("No executable specified, specify executable to debug.\n");
-
-  memset (&si, 0, sizeof (si));
-  si.cb = sizeof (si);
-
-  flags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS;
-
-#ifndef USE_WIN32API
-  orig_path = NULL;
-  path_ptr = getenv ("PATH");
-  if (path_ptr)
-    {
-      orig_path = alloca (strlen (path_ptr) + 1);
-      new_path = alloca (cygwin_posix_to_win32_path_list_buf_size (path_ptr));
-      strcpy (orig_path, path_ptr);
-      cygwin_posix_to_win32_path_list (path_ptr, new_path);
-      setenv ("PATH", new_path, 1);
-    }
-  cygwin_conv_to_win32_path (program, real_path);
-  program = real_path;
-#endif
-
-  argslen = strlen (program) + 1;
-  for (argc = 1; program_args[argc]; argc++)
-    argslen += strlen (program_args[argc]) + 1;
-  args = alloca (argslen);
-  strcpy (args, program);
-  for (argc = 1; program_args[argc]; argc++)
-    {
-      /* FIXME: Can we do better about quoting?  How does Cygwin
-         handle this?  */
-      strcat (args, " ");
-      strcat (args, program_args[argc]);
-    }
-  OUTMSG2 (("Command line is %s\n", args));
-
-  flags |= CREATE_NEW_PROCESS_GROUP;
-
-  ret = CreateProcess (0, args,        /* command line */
-                      NULL,    /* Security */
-                      NULL,    /* thread */
-                      TRUE,    /* inherit handles */
-                      flags,   /* start flags */
-                      winenv, NULL,    /* current directory */
-                      &si, &pi);
-
-#ifndef USE_WIN32API
-  if (orig_path)
-    setenv ("PATH", orig_path, 1);
+#ifdef __x86_64__
+  init_registers_amd64 ();
+  win32_tdesc = tdesc_amd64;
+#else
+  init_registers_i386 ();
+  win32_tdesc = tdesc_i386;
 #endif
-
-  if (!ret)
-    {
-      error ("Error creating process %s, (error %d): %s\n", args,
-            (int) GetLastError (), strerror (GetLastError ()));
-    }
-  else
-    {
-      OUTMSG2 (("Process created: %s\n", (char *) args));
-    }
-
-  CloseHandle (pi.hThread);
-
-  current_process_handle = pi.hProcess;
-  current_process_id = pi.dwProcessId;
-
-  do_initial_child_stuff (current_process_id);
-
-  return current_process_id;
-}
-
-/* Attach to a running process.
-   PID is the process ID to attach to, specified by the user
-   or a higher layer.  */
-static int
-win32_attach (unsigned long pid)
-{
-  int res = 0;
-  HMODULE kernel32 = LoadLibrary ("KERNEL32.DLL");
-  winapi_DebugActiveProcessStop *DebugActiveProcessStop = NULL;
-  winapi_DebugSetProcessKillOnExit *DebugSetProcessKillOnExit = NULL;
-
-  DebugActiveProcessStop =
-    (winapi_DebugActiveProcessStop *) GetProcAddress (kernel32,
-                                                     "DebugActiveProcessStop");
-  DebugSetProcessKillOnExit =
-    (winapi_DebugSetProcessKillOnExit *) GetProcAddress (kernel32,
-                                                        "DebugSetProcessKillOnExit");
-
-  res = DebugActiveProcess (pid) ? 1 : 0;
-
-  if (!res)
-    error ("Attach to process failed.");
-
-  if (DebugSetProcessKillOnExit != NULL)
-    DebugSetProcessKillOnExit (FALSE);
-
-  current_process_id = pid;
-  current_process_handle = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
-
-  if (current_process_handle == NULL)
-    {
-      res = 0;
-      if (DebugActiveProcessStop != NULL)
-       DebugActiveProcessStop (current_process_id);
-    }
-
-  if (res)
-    do_initial_child_stuff (pid);
-
-  FreeLibrary (kernel32);
-
-  return res;
-}
-
-/* Handle OUTPUT_DEBUG_STRING_EVENT from child process.  */
-static void
-handle_output_debug_string (struct target_waitstatus *ourstatus)
-{
-#define READ_BUFFER_LEN 1024
-  CORE_ADDR addr;
-  char s[READ_BUFFER_LEN + 1] = { 0 };
-  DWORD nbytes = current_event.u.DebugString.nDebugStringLength;
-
-  if (nbytes == 0)
-    return;
-
-  if (nbytes > READ_BUFFER_LEN)
-    nbytes = READ_BUFFER_LEN;
-
-  addr = (CORE_ADDR) (size_t) current_event.u.DebugString.lpDebugStringData;
-
-  if (current_event.u.DebugString.fUnicode)
-    {
-      /* The event tells us how many bytes, not chars, even
-         in Unicode.  */
-      WCHAR buffer[(READ_BUFFER_LEN + 1) / sizeof (WCHAR)] = { 0 };
-      if (read_inferior_memory (addr, (unsigned char *) buffer, nbytes) != 0)
-       return;
-      wcstombs (s, buffer, (nbytes + 1) / sizeof (WCHAR));
-    }
-  else
-    {
-      if (read_inferior_memory (addr, (unsigned char *) s, nbytes) != 0)
-       return;
-    }
-
-  if (strncmp (s, "cYg", 3) != 0)
-    monitor_output (s);
-#undef READ_BUFFER_LEN
-}
-
-/* Kill all inferiors.  */
-static void
-win32_kill (void)
-{
-  if (current_process_handle == NULL)
-    return;
-
-  TerminateProcess (current_process_handle, 0);
-  for (;;)
-    {
-      if (!child_continue (DBG_CONTINUE, -1))
-       break;
-      if (!WaitForDebugEvent (&current_event, INFINITE))
-       break;
-      if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
-       break;
-      else if (current_event.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT)
-       {
-         struct target_waitstatus our_status = { 0 };
-         handle_output_debug_string (&our_status);
-       }
-    }
-}
-
-/* Detach from all inferiors.  */
-static void
-win32_detach (void)
-{
-  HMODULE kernel32 = LoadLibrary ("KERNEL32.DLL");
-  winapi_DebugActiveProcessStop *DebugActiveProcessStop = NULL;
-  winapi_DebugSetProcessKillOnExit *DebugSetProcessKillOnExit = NULL;
-
-  DebugActiveProcessStop =
-    (winapi_DebugActiveProcessStop *) GetProcAddress (kernel32,
-                                                     "DebugActiveProcessStop");
-  DebugSetProcessKillOnExit =
-    (winapi_DebugSetProcessKillOnExit *) GetProcAddress (kernel32,
-                                                        "DebugSetProcessKillOnExit");
-
-  if (DebugSetProcessKillOnExit != NULL)
-    DebugSetProcessKillOnExit (FALSE);
-
-  if (DebugActiveProcessStop != NULL)
-    DebugActiveProcessStop (current_process_id);
-  else
-    win32_kill ();
-
-  FreeLibrary (kernel32);
-}
-
-/* Return 1 iff the thread with thread ID TID is alive.  */
-static int
-win32_thread_alive (unsigned long tid)
-{
-  int res;
-
-  /* Our thread list is reliable; don't bother to poll target
-     threads.  */
-  if (find_inferior_id (&all_threads, tid) != NULL)
-    res = 1;
-  else
-    res = 0;
-  return res;
-}
-
-/* Resume the inferior process.  RESUME_INFO describes how we want
-   to resume.  */
-static void
-win32_resume (struct thread_resume *resume_info)
-{
-  DWORD tid;
-  enum target_signal sig;
-  int step;
-  thread_info *th;
-  DWORD continue_status = DBG_CONTINUE;
-
-  /* This handles the very limited set of resume packets that GDB can
-     currently produce.  */
-
-  if (resume_info[0].thread == -1)
-    tid = -1;
-  else if (resume_info[1].thread == -1 && !resume_info[1].leave_stopped)
-    tid = -1;
-  else
-    /* Yes, we're ignoring resume_info[0].thread.  It'd be tricky to make
-       the Windows resume code do the right thing for thread switching.  */
-    tid = current_event.dwThreadId;
-
-  if (resume_info[0].thread != -1)
-    {
-      sig = resume_info[0].sig;
-      step = resume_info[0].step;
-    }
-  else
-    {
-      sig = 0;
-      step = 0;
-    }
-
-  if (sig != TARGET_SIGNAL_0)
-    {
-      if (current_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT)
-       {
-         OUTMSG (("Cannot continue with signal %d here.\n", sig));
-       }
-      else if (sig == last_sig)
-       continue_status = DBG_EXCEPTION_NOT_HANDLED;
-      else
-       OUTMSG (("Can only continue with recieved signal %d.\n", last_sig));
-    }
-
-  last_sig = TARGET_SIGNAL_0;
-
-  /* Get context for the currently selected thread.  */
-  th = thread_rec (current_event.dwThreadId, FALSE);
-  if (th)
-    {
-      if (th->context.ContextFlags)
-       {
-         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];
-                FIXME: should we set dr6 also ?? */
-             th->context.Dr7 = dr[7];
-           }
-
-         /* Move register values from the inferior into the thread
-            context structure.  */
-         regcache_invalidate ();
-
-         if (step)
-           th->context.EFlags |= FLAG_TRACE_BIT;
-
-         SetThreadContext (th->h, &th->context);
-         th->context.ContextFlags = 0;
-       }
-    }
-
-  /* Allow continuing with the same signal that interrupted us.
-     Otherwise complain.  */
-
-  child_continue (continue_status, tid);
 }
 
-static int
-handle_exception (struct target_waitstatus *ourstatus)
-{
-  thread_info *th;
-  DWORD code = current_event.u.Exception.ExceptionRecord.ExceptionCode;
-
-  ourstatus->kind = TARGET_WAITKIND_STOPPED;
-
-  /* Record the context of the current thread.  */
-  th = thread_rec (current_event.dwThreadId, -1);
-
-  switch (code)
-    {
-    case EXCEPTION_ACCESS_VIOLATION:
-      OUTMSG2 (("EXCEPTION_ACCESS_VIOLATION"));
-      ourstatus->value.sig = TARGET_SIGNAL_SEGV;
-      break;
-    case STATUS_STACK_OVERFLOW:
-      OUTMSG2 (("STATUS_STACK_OVERFLOW"));
-      ourstatus->value.sig = TARGET_SIGNAL_SEGV;
-      break;
-    case STATUS_FLOAT_DENORMAL_OPERAND:
-      OUTMSG2 (("STATUS_FLOAT_DENORMAL_OPERAND"));
-      ourstatus->value.sig = TARGET_SIGNAL_FPE;
-      break;
-    case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
-      OUTMSG2 (("EXCEPTION_ARRAY_BOUNDS_EXCEEDED"));
-      ourstatus->value.sig = TARGET_SIGNAL_FPE;
-      break;
-    case STATUS_FLOAT_INEXACT_RESULT:
-      OUTMSG2 (("STATUS_FLOAT_INEXACT_RESULT"));
-      ourstatus->value.sig = TARGET_SIGNAL_FPE;
-      break;
-    case STATUS_FLOAT_INVALID_OPERATION:
-      OUTMSG2 (("STATUS_FLOAT_INVALID_OPERATION"));
-      ourstatus->value.sig = TARGET_SIGNAL_FPE;
-      break;
-    case STATUS_FLOAT_OVERFLOW:
-      OUTMSG2 (("STATUS_FLOAT_OVERFLOW"));
-      ourstatus->value.sig = TARGET_SIGNAL_FPE;
-      break;
-    case STATUS_FLOAT_STACK_CHECK:
-      OUTMSG2 (("STATUS_FLOAT_STACK_CHECK"));
-      ourstatus->value.sig = TARGET_SIGNAL_FPE;
-      break;
-    case STATUS_FLOAT_UNDERFLOW:
-      OUTMSG2 (("STATUS_FLOAT_UNDERFLOW"));
-      ourstatus->value.sig = TARGET_SIGNAL_FPE;
-      break;
-    case STATUS_FLOAT_DIVIDE_BY_ZERO:
-      OUTMSG2 (("STATUS_FLOAT_DIVIDE_BY_ZERO"));
-      ourstatus->value.sig = TARGET_SIGNAL_FPE;
-      break;
-    case STATUS_INTEGER_DIVIDE_BY_ZERO:
-      OUTMSG2 (("STATUS_INTEGER_DIVIDE_BY_ZERO"));
-      ourstatus->value.sig = TARGET_SIGNAL_FPE;
-      break;
-    case STATUS_INTEGER_OVERFLOW:
-      OUTMSG2 (("STATUS_INTEGER_OVERFLOW"));
-      ourstatus->value.sig = TARGET_SIGNAL_FPE;
-      break;
-    case EXCEPTION_BREAKPOINT:
-      OUTMSG2 (("EXCEPTION_BREAKPOINT"));
-      ourstatus->value.sig = TARGET_SIGNAL_TRAP;
-      break;
-    case DBG_CONTROL_C:
-      OUTMSG2 (("DBG_CONTROL_C"));
-      ourstatus->value.sig = TARGET_SIGNAL_INT;
-      break;
-    case DBG_CONTROL_BREAK:
-      OUTMSG2 (("DBG_CONTROL_BREAK"));
-      ourstatus->value.sig = TARGET_SIGNAL_INT;
-      break;
-    case EXCEPTION_SINGLE_STEP:
-      OUTMSG2 (("EXCEPTION_SINGLE_STEP"));
-      ourstatus->value.sig = TARGET_SIGNAL_TRAP;
-      break;
-    case EXCEPTION_ILLEGAL_INSTRUCTION:
-      OUTMSG2 (("EXCEPTION_ILLEGAL_INSTRUCTION"));
-      ourstatus->value.sig = TARGET_SIGNAL_ILL;
-      break;
-    case EXCEPTION_PRIV_INSTRUCTION:
-      OUTMSG2 (("EXCEPTION_PRIV_INSTRUCTION"));
-      ourstatus->value.sig = TARGET_SIGNAL_ILL;
-      break;
-    case EXCEPTION_NONCONTINUABLE_EXCEPTION:
-      OUTMSG2 (("EXCEPTION_NONCONTINUABLE_EXCEPTION"));
-      ourstatus->value.sig = TARGET_SIGNAL_ILL;
-      break;
-    default:
-      if (current_event.u.Exception.dwFirstChance)
-       return 0;
-      OUTMSG2 (("gdbserver: unknown target exception 0x%08lx at 0x%08lx",
-               current_event.u.Exception.ExceptionRecord.ExceptionCode,
-               (DWORD) current_event.u.Exception.ExceptionRecord.
-               ExceptionAddress));
-      ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
-      break;
-    }
-  OUTMSG2 (("\n"));
-  last_sig = ourstatus->value.sig;
-  return 1;
-}
-
-/* Get the next event from the child.  Return 1 if the event requires
-   handling.  */
-static int
-get_child_debug_event (struct target_waitstatus *ourstatus)
-{
-  BOOL debug_event;
-  DWORD continue_status, event_code;
-  thread_info *th = NULL;
-  static thread_info dummy_thread_info;
-  int retval = 0;
-
-in:
-
-  last_sig = TARGET_SIGNAL_0;
-  ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
-
-  if (!(debug_event = WaitForDebugEvent (&current_event, 1000)))
-    goto out;
-
-  current_inferior =
-    (struct thread_info *) find_inferior_id (&all_threads,
-                                            current_event.dwThreadId);
-
-  continue_status = DBG_CONTINUE;
-  event_code = current_event.dwDebugEventCode;
-
-  switch (event_code)
-    {
-    case CREATE_THREAD_DEBUG_EVENT:
-      OUTMSG2 (("gdbserver: kernel event CREATE_THREAD_DEBUG_EVENT "
-               "for pid=%d tid=%x)\n",
-               (unsigned) current_event.dwProcessId,
-               (unsigned) current_event.dwThreadId));
-
-      /* Record the existence of this thread.  */
-      th = child_add_thread (current_event.dwThreadId,
-                            current_event.u.CreateThread.hThread);
-
-      retval = current_event.dwThreadId;
-      break;
-
-    case EXIT_THREAD_DEBUG_EVENT:
-      OUTMSG2 (("gdbserver: kernel event EXIT_THREAD_DEBUG_EVENT "
-               "for pid=%d tid=%x\n",
-               (unsigned) current_event.dwProcessId,
-               (unsigned) current_event.dwThreadId));
-      child_delete_thread (current_event.dwThreadId);
-      th = &dummy_thread_info;
-      break;
-
-    case CREATE_PROCESS_DEBUG_EVENT:
-      OUTMSG2 (("gdbserver: kernel event CREATE_PROCESS_DEBUG_EVENT "
-               "for pid=%d tid=%x\n",
-               (unsigned) current_event.dwProcessId,
-               (unsigned) current_event.dwThreadId));
-      CloseHandle (current_event.u.CreateProcessInfo.hFile);
-
-      current_process_handle = current_event.u.CreateProcessInfo.hProcess;
-      main_thread_id = current_event.dwThreadId;
-
-      ourstatus->kind = TARGET_WAITKIND_EXECD;
-      ourstatus->value.execd_pathname = "Main executable";
-
-      /* Add the main thread.  */
-      th =
-       child_add_thread (main_thread_id,
-                         current_event.u.CreateProcessInfo.hThread);
-
-      retval = ourstatus->value.related_pid = current_event.dwThreadId;
-      break;
-
-    case EXIT_PROCESS_DEBUG_EVENT:
-      OUTMSG2 (("gdbserver: kernel event EXIT_PROCESS_DEBUG_EVENT "
-               "for pid=%d tid=%x\n",
-               (unsigned) current_event.dwProcessId,
-               (unsigned) current_event.dwThreadId));
-      ourstatus->kind = TARGET_WAITKIND_EXITED;
-      ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
-      CloseHandle (current_process_handle);
-      current_process_handle = NULL;
-      retval = main_thread_id;
-      break;
-
-    case LOAD_DLL_DEBUG_EVENT:
-      OUTMSG2 (("gdbserver: kernel event LOAD_DLL_DEBUG_EVENT "
-               "for pid=%d tid=%x\n",
-               (unsigned) current_event.dwProcessId,
-               (unsigned) current_event.dwThreadId));
-      CloseHandle (current_event.u.LoadDll.hFile);
-
-      ourstatus->kind = TARGET_WAITKIND_LOADED;
-      ourstatus->value.integer = 0;
-      retval = main_thread_id;
-      break;
-
-    case UNLOAD_DLL_DEBUG_EVENT:
-      OUTMSG2 (("gdbserver: kernel event UNLOAD_DLL_DEBUG_EVENT "
-               "for pid=%d tid=%x\n",
-               (unsigned) current_event.dwProcessId,
-               (unsigned) current_event.dwThreadId));
-      break;
-
-    case EXCEPTION_DEBUG_EVENT:
-      OUTMSG2 (("gdbserver: kernel event EXCEPTION_DEBUG_EVENT "
-               "for pid=%d tid=%x\n",
-               (unsigned) current_event.dwProcessId,
-               (unsigned) current_event.dwThreadId));
-      retval = handle_exception (ourstatus);
-      break;
-
-    case OUTPUT_DEBUG_STRING_EVENT:
-      /* A message from the kernel (or Cygwin).  */
-      OUTMSG2 (("gdbserver: kernel event OUTPUT_DEBUG_STRING_EVENT "
-               "for pid=%d tid=%x\n",
-               (unsigned) current_event.dwProcessId,
-               (unsigned) current_event.dwThreadId));
-      handle_output_debug_string (ourstatus);
-      break;
-
-    default:
-      OUTMSG2 (("gdbserver: kernel event unknown "
-               "for pid=%d tid=%x code=%ld\n",
-               (unsigned) current_event.dwProcessId,
-               (unsigned) current_event.dwThreadId,
-               current_event.dwDebugEventCode));
-      break;
-    }
-
-  current_inferior =
-    (struct thread_info *) find_inferior_id (&all_threads,
-                                            current_event.dwThreadId);
-
-  if (!retval || (event_code != EXCEPTION_DEBUG_EVENT && event_code != EXIT_PROCESS_DEBUG_EVENT))
-    {
-      child_continue (continue_status, -1);
-      goto in;
-    }
-
-  if (th == NULL)
-    thread_rec (current_event.dwThreadId, TRUE);
-
-out:
-  return retval;
-}
-
-/* Wait for the inferior process to change state.
-   STATUS will be filled in with a response code to send to GDB.
-   Returns the signal which caused the process to stop. */
-static unsigned char
-win32_wait (char *status)
-{
-  struct target_waitstatus our_status;
-
-  *status = 'T';
-
-  while (1)
-    {
-      get_child_debug_event (&our_status);
-
-      if (our_status.kind == TARGET_WAITKIND_EXITED)
-       {
-         OUTMSG2 (("Child exited with retcode = %x\n",
-                   our_status.value.integer));
-
-         *status = 'W';
-
-         child_fetch_inferior_registers (-1);
-
-         return our_status.value.integer;
-       }
-      else if (our_status.kind == TARGET_WAITKIND_STOPPED)
-       {
-         OUTMSG2 (("Child Stopped with signal = %x \n",
-                   WSTOPSIG (our_status.value.sig)));
-
-         *status = 'T';
-
-         child_fetch_inferior_registers (-1);
-
-         return our_status.value.sig;
-       }
-      else
-       OUTMSG (("Ignoring unknown internal event, %d\n", our_status.kind));
-
-      {
-       struct thread_resume resume;
-       resume.thread = -1;
-       resume.step = 0;
-       resume.sig = 0;
-       resume.leave_stopped = 0;
-       win32_resume (&resume);
-      }
-    }
-}
-
-/* Fetch registers from the inferior process.
-   If REGNO is -1, fetch all registers; otherwise, fetch at least REGNO.  */
-static void
-win32_fetch_inferior_registers (int regno)
-{
-  child_fetch_inferior_registers (regno);
-}
-
-/* Store registers to the inferior process.
-   If REGNO is -1, store all registers; otherwise, store at least REGNO.  */
-static void
-win32_store_inferior_registers (int regno)
-{
-  child_store_inferior_registers (regno);
-}
-
-/* Read memory from the inferior process.  This should generally be
-   called through read_inferior_memory, which handles breakpoint shadowing.
-   Read LEN bytes at MEMADDR into a buffer at MYADDR.  */
-static int
-win32_read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
-{
-  return child_xfer_memory (memaddr, myaddr, len, 0, 0) != len;
-}
-
-/* Write memory to the inferior process.  This should generally be
-   called through write_inferior_memory, which handles breakpoint shadowing.
-   Write LEN bytes from the buffer at MYADDR to MEMADDR.
-   Returns 0 on success and errno on failure.  */
-static int
-win32_write_inferior_memory (CORE_ADDR memaddr, const unsigned char *myaddr,
-                            int len)
-{
-  return child_xfer_memory (memaddr, (char *) myaddr, len, 1, 0) != len;
-}
-
-static const char *
-win32_arch_string (void)
-{
-  return "i386";
-}
-
-static struct target_ops win32_target_ops = {
-  win32_create_inferior,
-  win32_attach,
-  win32_kill,
-  win32_detach,
-  win32_thread_alive,
-  win32_resume,
-  win32_wait,
-  win32_fetch_inferior_registers,
-  win32_store_inferior_registers,
-  win32_read_inferior_memory,
-  win32_write_inferior_memory,
-  NULL,
-  NULL,
-  NULL,
-  NULL,
-  NULL,
-  NULL,
-  NULL,
-  NULL,
-  NULL,
-  win32_arch_string
+struct win32_target_ops the_low_target = {
+  i386_arch_setup,
+  sizeof (mappings) / sizeof (mappings[0]),
+  i386_initial_stuff,
+  i386_get_thread_context,
+  i386_set_thread_context,
+  i386_thread_added,
+  i386_fetch_inferior_register,
+  i386_store_inferior_register,
+  i386_single_step,
+  &i386_win32_breakpoint,
+  i386_win32_breakpoint_len,
+  i386_insert_point,
+  i386_remove_point,
+  i386_stopped_by_watchpoint,
+  i386_stopped_data_address
 };
-
-/* Initialize the Win32 backend.  */
-void
-initialize_low (void)
-{
-  set_target_ops (&win32_target_ops);
-
-  init_registers ();
-}
This page took 0.047791 seconds and 4 git commands to generate.