gdb: bool-ify follow_fork
[deliverable/binutils-gdb.git] / gdb / windows-nat.c
index df44994c95a8fcf5d94bc6e3be531becca431496..614b235edeac8c2bae374df3e4427cf4d64d0ff6 100644 (file)
@@ -1,6 +1,6 @@
 /* Target-vector operations for controlling windows child processes, for GDB.
 
 /* Target-vector operations for controlling windows child processes, for GDB.
 
-   Copyright (C) 1995-2019 Free Software Foundation, Inc.
+   Copyright (C) 1995-2020 Free Software Foundation, Inc.
 
    Contributed by Cygnus Solutions, A Red Hat Company.
 
 
    Contributed by Cygnus Solutions, A Red Hat Company.
 
 #include "inf-child.h"
 #include "gdbsupport/gdb_tilde_expand.h"
 #include "gdbsupport/pathstuff.h"
 #include "inf-child.h"
 #include "gdbsupport/gdb_tilde_expand.h"
 #include "gdbsupport/pathstuff.h"
+#include "gdbsupport/gdb_wait.h"
+
+#define STATUS_WX86_BREAKPOINT 0x4000001F
+#define STATUS_WX86_SINGLE_STEP 0x4000001E
 
 #define AdjustTokenPrivileges          dyn_AdjustTokenPrivileges
 #define DebugActiveProcessStop         dyn_DebugActiveProcessStop
 #define DebugBreakProcess              dyn_DebugBreakProcess
 #define DebugSetProcessKillOnExit      dyn_DebugSetProcessKillOnExit
 #define EnumProcessModules             dyn_EnumProcessModules
 
 #define AdjustTokenPrivileges          dyn_AdjustTokenPrivileges
 #define DebugActiveProcessStop         dyn_DebugActiveProcessStop
 #define DebugBreakProcess              dyn_DebugBreakProcess
 #define DebugSetProcessKillOnExit      dyn_DebugSetProcessKillOnExit
 #define EnumProcessModules             dyn_EnumProcessModules
+#define EnumProcessModulesEx           dyn_EnumProcessModulesEx
 #define GetModuleInformation           dyn_GetModuleInformation
 #define LookupPrivilegeValueA          dyn_LookupPrivilegeValueA
 #define OpenProcessToken               dyn_OpenProcessToken
 #define GetConsoleFontSize             dyn_GetConsoleFontSize
 #define GetCurrentConsoleFont          dyn_GetCurrentConsoleFont
 #define GetModuleInformation           dyn_GetModuleInformation
 #define LookupPrivilegeValueA          dyn_LookupPrivilegeValueA
 #define OpenProcessToken               dyn_OpenProcessToken
 #define GetConsoleFontSize             dyn_GetConsoleFontSize
 #define GetCurrentConsoleFont          dyn_GetCurrentConsoleFont
+#define Wow64SuspendThread             dyn_Wow64SuspendThread
+#define Wow64GetThreadContext          dyn_Wow64GetThreadContext
+#define Wow64SetThreadContext          dyn_Wow64SetThreadContext
+#define Wow64GetThreadSelectorEntry    dyn_Wow64GetThreadSelectorEntry
 
 typedef BOOL WINAPI (AdjustTokenPrivileges_ftype) (HANDLE, BOOL,
                                                   PTOKEN_PRIVILEGES,
 
 typedef BOOL WINAPI (AdjustTokenPrivileges_ftype) (HANDLE, BOOL,
                                                   PTOKEN_PRIVILEGES,
@@ -99,6 +108,12 @@ typedef BOOL WINAPI (EnumProcessModules_ftype) (HANDLE, HMODULE *, DWORD,
                                                LPDWORD);
 static EnumProcessModules_ftype *EnumProcessModules;
 
                                                LPDWORD);
 static EnumProcessModules_ftype *EnumProcessModules;
 
+#ifdef __x86_64__
+typedef BOOL WINAPI (EnumProcessModulesEx_ftype) (HANDLE, HMODULE *, DWORD,
+                                                 LPDWORD, DWORD);
+static EnumProcessModulesEx_ftype *EnumProcessModulesEx;
+#endif
+
 typedef BOOL WINAPI (GetModuleInformation_ftype) (HANDLE, HMODULE,
                                                  LPMODULEINFO, DWORD);
 static GetModuleInformation_ftype *GetModuleInformation;
 typedef BOOL WINAPI (GetModuleInformation_ftype) (HANDLE, HMODULE,
                                                  LPMODULEINFO, DWORD);
 static GetModuleInformation_ftype *GetModuleInformation;
@@ -116,6 +131,22 @@ static GetCurrentConsoleFont_ftype *GetCurrentConsoleFont;
 typedef COORD WINAPI (GetConsoleFontSize_ftype) (HANDLE, DWORD);
 static GetConsoleFontSize_ftype *GetConsoleFontSize;
 
 typedef COORD WINAPI (GetConsoleFontSize_ftype) (HANDLE, DWORD);
 static GetConsoleFontSize_ftype *GetConsoleFontSize;
 
+#ifdef __x86_64__
+typedef DWORD WINAPI (Wow64SuspendThread_ftype) (HANDLE);
+static Wow64SuspendThread_ftype *Wow64SuspendThread;
+
+typedef BOOL WINAPI (Wow64GetThreadContext_ftype) (HANDLE, PWOW64_CONTEXT);
+static Wow64GetThreadContext_ftype *Wow64GetThreadContext;
+
+typedef BOOL WINAPI (Wow64SetThreadContext_ftype) (HANDLE,
+                                                  const WOW64_CONTEXT *);
+static Wow64SetThreadContext_ftype *Wow64SetThreadContext;
+
+typedef BOOL WINAPI (Wow64GetThreadSelectorEntry_ftype) (HANDLE, DWORD,
+                                                        PLDT_ENTRY);
+static Wow64GetThreadSelectorEntry_ftype *Wow64GetThreadSelectorEntry;
+#endif
+
 #undef STARTUPINFO
 #undef CreateProcess
 #undef GetModuleFileNameEx
 #undef STARTUPINFO
 #undef CreateProcess
 #undef GetModuleFileNameEx
@@ -147,7 +178,7 @@ static GetConsoleFontSize_ftype *GetConsoleFontSize;
 static int have_saved_context; /* True if we've saved context from a
                                   cygwin signal.  */
 #ifdef __CYGWIN__
 static int have_saved_context; /* True if we've saved context from a
                                   cygwin signal.  */
 #ifdef __CYGWIN__
-static CONTEXT saved_context;  /* Containes the saved context from a
+static CONTEXT saved_context;  /* Contains the saved context from a
                                   cygwin signal.  */
 #endif
 
                                   cygwin signal.  */
 #endif
 
@@ -223,7 +254,13 @@ typedef struct windows_thread_info_struct
     char *name;
     int suspended;
     int reload_context;
     char *name;
     int suspended;
     int reload_context;
-    CONTEXT context;
+    union
+      {
+       CONTEXT context;
+#ifdef __x86_64__
+       WOW64_CONTEXT wow64_context;
+#endif
+      };
   }
 windows_thread_info;
 
   }
 windows_thread_info;
 
@@ -235,12 +272,17 @@ static DEBUG_EVENT current_event; /* The current debug event from
                                           WaitForDebugEvent */
 static HANDLE current_process_handle;  /* Currently executing process */
 static windows_thread_info *current_thread;    /* Info on currently selected thread */
                                           WaitForDebugEvent */
 static HANDLE current_process_handle;  /* Currently executing process */
 static windows_thread_info *current_thread;    /* Info on currently selected thread */
+static EXCEPTION_RECORD siginfo_er;    /* Contents of $_siginfo */
 
 /* Counts of things.  */
 static int exception_count = 0;
 static int event_count = 0;
 static int saw_create;
 static int open_process_used = 0;
 
 /* Counts of things.  */
 static int exception_count = 0;
 static int event_count = 0;
 static int saw_create;
 static int open_process_used = 0;
+#ifdef __x86_64__
+static bool wow64_process = false;
+static bool ignore_first_breakpoint = false;
+#endif
 
 /* User options.  */
 static bool new_console = false;
 
 /* User options.  */
 static bool new_console = false;
@@ -349,6 +391,8 @@ struct windows_nat_target final : public x86_nat_target<inf_child_target>
   bool get_tib_address (ptid_t ptid, CORE_ADDR *addr) override;
 
   const char *thread_name (struct thread_info *) override;
   bool get_tib_address (ptid_t ptid, CORE_ADDR *addr) override;
 
   const char *thread_name (struct thread_info *) override;
+
+  int get_windows_debug_event (int pid, struct target_waitstatus *ourstatus);
 };
 
 static windows_nat_target the_windows_nat_target;
 };
 
 static windows_nat_target the_windows_nat_target;
@@ -356,15 +400,16 @@ static windows_nat_target the_windows_nat_target;
 /* Set the MAPPINGS static global to OFFSETS.
    See the description of MAPPINGS for more details.  */
 
 /* Set the MAPPINGS static global to OFFSETS.
    See the description of MAPPINGS for more details.  */
 
-void
+static void
 windows_set_context_register_offsets (const int *offsets)
 {
   mappings = offsets;
 }
 
 windows_set_context_register_offsets (const int *offsets)
 {
   mappings = offsets;
 }
 
-/* See windows-nat.h.  */
+/* Set the function that should be used by this module to determine
+   whether a given register is a segment register or not.  */
 
 
-void
+static void
 windows_set_segment_register_p (segment_register_p_ftype *fun)
 {
   segment_register_p = fun;
 windows_set_segment_register_p (segment_register_p_ftype *fun)
 {
   segment_register_p = fun;
@@ -448,6 +493,12 @@ windows_add_thread (ptid_t ptid, HANDLE h, void *tlb, bool main_thread_p)
   th->id = id;
   th->h = h;
   th->thread_local_base = (CORE_ADDR) (uintptr_t) tlb;
   th->id = id;
   th->h = h;
   th->thread_local_base = (CORE_ADDR) (uintptr_t) tlb;
+#ifdef __x86_64__
+  /* For WOW64 processes, this is actually the pointer to the 64bit TIB,
+     and the 32bit TIB is exactly 2 pages after it.  */
+  if (wow64_process)
+    th->thread_local_base += 0x2000;
+#endif
   th->next = thread_head.next;
   thread_head.next = th;
 
   th->next = thread_head.next;
   thread_head.next = th;
 
@@ -457,24 +508,43 @@ windows_add_thread (ptid_t ptid, HANDLE h, void *tlb, bool main_thread_p)
      the main thread silently (in reality, this thread is really
      more of a process to the user than a thread).  */
   if (main_thread_p)
      the main thread silently (in reality, this thread is really
      more of a process to the user than a thread).  */
   if (main_thread_p)
-    add_thread_silent (ptid);
+    add_thread_silent (&the_windows_nat_target, ptid);
   else
   else
-    add_thread (ptid);
+    add_thread (&the_windows_nat_target, ptid);
 
   /* Set the debug registers for the new thread if they are used.  */
   if (debug_registers_used)
     {
 
   /* Set the debug registers for the new thread if they are used.  */
   if (debug_registers_used)
     {
-      /* Only change the value of the debug registers.  */
-      th->context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
-      CHECK (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 = DR6_CLEAR_VALUE;
-      th->context.Dr7 = dr[7];
-      CHECK (SetThreadContext (th->h, &th->context));
-      th->context.ContextFlags = 0;
+#ifdef __x86_64__
+      if (wow64_process)
+       {
+         /* Only change the value of the debug registers.  */
+         th->wow64_context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+         CHECK (Wow64GetThreadContext (th->h, &th->wow64_context));
+         th->wow64_context.Dr0 = dr[0];
+         th->wow64_context.Dr1 = dr[1];
+         th->wow64_context.Dr2 = dr[2];
+         th->wow64_context.Dr3 = dr[3];
+         th->wow64_context.Dr6 = DR6_CLEAR_VALUE;
+         th->wow64_context.Dr7 = dr[7];
+         CHECK (Wow64SetThreadContext (th->h, &th->wow64_context));
+         th->wow64_context.ContextFlags = 0;
+       }
+      else
+#endif
+       {
+         /* Only change the value of the debug registers.  */
+         th->context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+         CHECK (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 = DR6_CLEAR_VALUE;
+         th->context.Dr7 = dr[7];
+         CHECK (SetThreadContext (th->h, &th->context));
+         th->context.ContextFlags = 0;
+       }
     }
   return th;
 }
     }
   return th;
 }
@@ -518,7 +588,7 @@ windows_delete_thread (ptid_t ptid, DWORD exit_code, bool main_thread_p)
 
      Note that no notification was printed when the main thread
      was created, and thus, unless in verbose mode, we should be
 
      Note that no notification was printed when the main thread
      was created, and thus, unless in verbose mode, we should be
-     symetrical, and avoid that notification for the main thread
+     symmetrical, and avoid that notification for the main thread
      here as well.  */
 
   if (info_verbose)
      here as well.  */
 
   if (info_verbose)
@@ -528,7 +598,7 @@ windows_delete_thread (ptid_t ptid, DWORD exit_code, bool main_thread_p)
                       target_pid_to_str (ptid).c_str (),
                       (unsigned) exit_code);
 
                       target_pid_to_str (ptid).c_str (),
                       (unsigned) exit_code);
 
-  delete_thread (find_thread_ptid (ptid));
+  delete_thread (find_thread_ptid (&the_windows_nat_target, ptid));
 
   for (th = &thread_head;
        th->next != NULL && th->next->id != id;
 
   for (th = &thread_head;
        th->next != NULL && th->next->id != id;
@@ -561,7 +631,13 @@ windows_fetch_one_register (struct regcache *regcache,
   gdb_assert (r >= 0);
   gdb_assert (!th->reload_context);
 
   gdb_assert (r >= 0);
   gdb_assert (!th->reload_context);
 
-  char *context_offset = ((char *) &th->context) + mappings[r];
+  char *context_ptr = (char *) &th->context;
+#ifdef __x86_64__
+  if (wow64_process)
+    context_ptr = (char *) &th->wow64_context;
+#endif
+
+  char *context_offset = context_ptr + mappings[r];
   struct gdbarch *gdbarch = regcache->arch ();
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   struct gdbarch *gdbarch = regcache->arch ();
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
@@ -612,6 +688,26 @@ windows_nat_target::fetch_registers (struct regcache *regcache, int r)
          have_saved_context = 0;
        }
       else
          have_saved_context = 0;
        }
       else
+#endif
+#ifdef __x86_64__
+      if (wow64_process)
+       {
+         th->wow64_context.ContextFlags = CONTEXT_DEBUGGER_DR;
+         CHECK (Wow64GetThreadContext (th->h, &th->wow64_context));
+         /* Copy dr values from that thread.
+            But only if there were not modified since last stop.
+            PR gdb/2388 */
+         if (!debug_registers_changed)
+           {
+             dr[0] = th->wow64_context.Dr0;
+             dr[1] = th->wow64_context.Dr1;
+             dr[2] = th->wow64_context.Dr2;
+             dr[3] = th->wow64_context.Dr3;
+             dr[6] = th->wow64_context.Dr6;
+             dr[7] = th->wow64_context.Dr7;
+           }
+       }
+      else
 #endif
        {
          th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
 #endif
        {
          th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
@@ -651,7 +747,13 @@ windows_store_one_register (const struct regcache *regcache,
 {
   gdb_assert (r >= 0);
 
 {
   gdb_assert (r >= 0);
 
-  regcache->raw_collect (r, ((char *) &th->context) + mappings[r]);
+  char *context_ptr = (char *) &th->context;
+#ifdef __x86_64__
+  if (wow64_process)
+    context_ptr = (char *) &th->wow64_context;
+#endif
+
+  regcache->raw_collect (r, context_ptr + mappings[r]);
 }
 
 /* Store a new register value into the context of the thread tied to
 }
 
 /* Store a new register value into the context of the thread tied to
@@ -679,6 +781,7 @@ windows_nat_target::store_registers (struct regcache *regcache, int r)
 struct lm_info_windows : public lm_info_base
 {
   LPVOID load_addr = 0;
 struct lm_info_windows : public lm_info_base
 {
   LPVOID load_addr = 0;
+  CORE_ADDR text_offset = 0;
 };
 
 static struct so_list solib_start, *solib_end;
 };
 
 static struct so_list solib_start, *solib_end;
@@ -940,7 +1043,14 @@ catch_errors (void (*func) ())
 static void
 windows_clear_solib (void)
 {
 static void
 windows_clear_solib (void)
 {
-  solib_start.next = NULL;
+  struct so_list *so;
+
+  for (so = solib_start.next; so; so = solib_start.next)
+    {
+      solib_start.next = so->next;
+      windows_free_so (so);
+    }
+
   solib_end = &solib_start;
 }
 
   solib_end = &solib_start;
 }
 
@@ -1031,7 +1141,14 @@ static int
 display_selector (HANDLE thread, DWORD sel)
 {
   LDT_ENTRY info;
 display_selector (HANDLE thread, DWORD sel)
 {
   LDT_ENTRY info;
-  if (GetThreadSelectorEntry (thread, sel, &info))
+  BOOL ret;
+#ifdef __x86_64__
+  if (wow64_process)
+    ret = Wow64GetThreadSelectorEntry (thread, sel, &info);
+  else
+#endif
+    ret = GetThreadSelectorEntry (thread, sel, &info);
+  if (ret)
     {
       int base, limit;
       printf_filtered ("0x%03x: ", (unsigned) sel);
     {
       int base, limit;
       printf_filtered ("0x%03x: ", (unsigned) sel);
@@ -1115,25 +1232,50 @@ display_selectors (const char * args, int from_tty)
     }
   if (!args)
     {
     }
   if (!args)
     {
-
-      puts_filtered ("Selector $cs\n");
-      display_selector (current_thread->h,
-       current_thread->context.SegCs);
-      puts_filtered ("Selector $ds\n");
-      display_selector (current_thread->h,
-       current_thread->context.SegDs);
-      puts_filtered ("Selector $es\n");
-      display_selector (current_thread->h,
-       current_thread->context.SegEs);
-      puts_filtered ("Selector $ss\n");
-      display_selector (current_thread->h,
-       current_thread->context.SegSs);
-      puts_filtered ("Selector $fs\n");
-      display_selector (current_thread->h,
-       current_thread->context.SegFs);
-      puts_filtered ("Selector $gs\n");
-      display_selector (current_thread->h,
-       current_thread->context.SegGs);
+#ifdef __x86_64__
+      if (wow64_process)
+       {
+         puts_filtered ("Selector $cs\n");
+         display_selector (current_thread->h,
+                           current_thread->wow64_context.SegCs);
+         puts_filtered ("Selector $ds\n");
+         display_selector (current_thread->h,
+                           current_thread->wow64_context.SegDs);
+         puts_filtered ("Selector $es\n");
+         display_selector (current_thread->h,
+                           current_thread->wow64_context.SegEs);
+         puts_filtered ("Selector $ss\n");
+         display_selector (current_thread->h,
+                           current_thread->wow64_context.SegSs);
+         puts_filtered ("Selector $fs\n");
+         display_selector (current_thread->h,
+                           current_thread->wow64_context.SegFs);
+         puts_filtered ("Selector $gs\n");
+         display_selector (current_thread->h,
+                           current_thread->wow64_context.SegGs);
+       }
+      else
+#endif
+       {
+         puts_filtered ("Selector $cs\n");
+         display_selector (current_thread->h,
+                           current_thread->context.SegCs);
+         puts_filtered ("Selector $ds\n");
+         display_selector (current_thread->h,
+                           current_thread->context.SegDs);
+         puts_filtered ("Selector $es\n");
+         display_selector (current_thread->h,
+                           current_thread->context.SegEs);
+         puts_filtered ("Selector $ss\n");
+         display_selector (current_thread->h,
+                           current_thread->context.SegSs);
+         puts_filtered ("Selector $fs\n");
+         display_selector (current_thread->h,
+                           current_thread->context.SegFs);
+         puts_filtered ("Selector $gs\n");
+         display_selector (current_thread->h,
+                           current_thread->context.SegGs);
+       }
     }
   else
     {
     }
   else
     {
@@ -1156,6 +1298,8 @@ handle_exception (struct target_waitstatus *ourstatus)
   DWORD code = rec->ExceptionCode;
   handle_exception_result result = HANDLE_EXCEPTION_HANDLED;
 
   DWORD code = rec->ExceptionCode;
   handle_exception_result result = HANDLE_EXCEPTION_HANDLED;
 
+  memcpy (&siginfo_er, rec, sizeof siginfo_er);
+
   ourstatus->kind = TARGET_WAITKIND_STOPPED;
 
   /* Record the context of the current thread.  */
   ourstatus->kind = TARGET_WAITKIND_STOPPED;
 
   /* Record the context of the current thread.  */
@@ -1232,6 +1376,19 @@ handle_exception (struct target_waitstatus *ourstatus)
       ourstatus->value.sig = GDB_SIGNAL_FPE;
       break;
     case EXCEPTION_BREAKPOINT:
       ourstatus->value.sig = GDB_SIGNAL_FPE;
       break;
     case EXCEPTION_BREAKPOINT:
+#ifdef __x86_64__
+      if (ignore_first_breakpoint)
+       {
+         /* For WOW64 processes, there are always 2 breakpoint exceptions
+            on startup, first a BREAKPOINT for the 64bit ntdll.dll,
+            then a WX86_BREAKPOINT for the 32bit ntdll.dll.
+            Here we only care about the WX86_BREAKPOINT's.  */
+         ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
+         ignore_first_breakpoint = false;
+       }
+#endif
+      /* FALLTHROUGH */
+    case STATUS_WX86_BREAKPOINT:
       DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
       ourstatus->value.sig = GDB_SIGNAL_TRAP;
       break;
       DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
       ourstatus->value.sig = GDB_SIGNAL_TRAP;
       break;
@@ -1244,6 +1401,7 @@ handle_exception (struct target_waitstatus *ourstatus)
       ourstatus->value.sig = GDB_SIGNAL_INT;
       break;
     case EXCEPTION_SINGLE_STEP:
       ourstatus->value.sig = GDB_SIGNAL_INT;
       break;
     case EXCEPTION_SINGLE_STEP:
+    case STATUS_WX86_SINGLE_STEP:
       DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_SINGLE_STEP");
       ourstatus->value.sig = GDB_SIGNAL_TRAP;
       break;
       DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_SINGLE_STEP");
       ourstatus->value.sig = GDB_SIGNAL_TRAP;
       break;
@@ -1332,29 +1490,62 @@ windows_continue (DWORD continue_status, int id, int killed)
     if ((id == -1 || id == (int) th->id)
        && th->suspended)
       {
     if ((id == -1 || id == (int) th->id)
        && th->suspended)
       {
-       if (debug_registers_changed)
+#ifdef __x86_64__
+       if (wow64_process)
          {
          {
-           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 = DR6_CLEAR_VALUE;
-           th->context.Dr7 = dr[7];
+           if (debug_registers_changed)
+             {
+               th->wow64_context.ContextFlags |= CONTEXT_DEBUG_REGISTERS;
+               th->wow64_context.Dr0 = dr[0];
+               th->wow64_context.Dr1 = dr[1];
+               th->wow64_context.Dr2 = dr[2];
+               th->wow64_context.Dr3 = dr[3];
+               th->wow64_context.Dr6 = DR6_CLEAR_VALUE;
+               th->wow64_context.Dr7 = dr[7];
+             }
+           if (th->wow64_context.ContextFlags)
+             {
+               DWORD ec = 0;
+
+               if (GetExitCodeThread (th->h, &ec)
+                   && ec == STILL_ACTIVE)
+                 {
+                   BOOL status = Wow64SetThreadContext (th->h,
+                                                        &th->wow64_context);
+
+                   if (!killed)
+                     CHECK (status);
+                 }
+               th->wow64_context.ContextFlags = 0;
+             }
          }
          }
-       if (th->context.ContextFlags)
+       else
+#endif
          {
          {
-           DWORD ec = 0;
-
-           if (GetExitCodeThread (th->h, &ec)
-               && ec == STILL_ACTIVE)
+           if (debug_registers_changed)
+             {
+               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 = DR6_CLEAR_VALUE;
+               th->context.Dr7 = dr[7];
+             }
+           if (th->context.ContextFlags)
              {
              {
-               BOOL status = SetThreadContext (th->h, &th->context);
+               DWORD ec = 0;
+
+               if (GetExitCodeThread (th->h, &ec)
+                   && ec == STILL_ACTIVE)
+                 {
+                   BOOL status = SetThreadContext (th->h, &th->context);
 
 
-               if (!killed)
-                 CHECK (status);
+                   if (!killed)
+                     CHECK (status);
+                 }
+               th->context.ContextFlags = 0;
              }
              }
-           th->context.ContextFlags = 0;
          }
        if (th->suspended > 0)
          (void) ResumeThread (th->h);
          }
        if (th->suspended > 0)
          (void) ResumeThread (th->h);
@@ -1447,35 +1638,66 @@ windows_nat_target::resume (ptid_t ptid, int step, enum gdb_signal sig)
 
   last_sig = GDB_SIGNAL_0;
 
 
   last_sig = GDB_SIGNAL_0;
 
-  DEBUG_EXEC (("gdb: windows_resume (pid=%d, tid=%ld, step=%d, sig=%d);\n",
-              ptid.pid (), ptid.tid (), step, sig));
+  DEBUG_EXEC (("gdb: windows_resume (pid=%d, tid=0x%x, step=%d, sig=%d);\n",
+              ptid.pid (), (unsigned) ptid.tid (), step, sig));
 
   /* Get context for currently selected thread.  */
   th = thread_rec (inferior_ptid.tid (), FALSE);
   if (th)
     {
 
   /* Get context for currently selected thread.  */
   th = thread_rec (inferior_ptid.tid (), FALSE);
   if (th)
     {
-      if (step)
+#ifdef __x86_64__
+      if (wow64_process)
        {
        {
-         /* Single step by setting t bit.  */
-         struct regcache *regcache = get_current_regcache ();
-         struct gdbarch *gdbarch = regcache->arch ();
-         fetch_registers (regcache, gdbarch_ps_regnum (gdbarch));
-         th->context.EFlags |= FLAG_TRACE_BIT;
-       }
+         if (step)
+           {
+             /* Single step by setting t bit.  */
+             struct regcache *regcache = get_current_regcache ();
+             struct gdbarch *gdbarch = regcache->arch ();
+             fetch_registers (regcache, gdbarch_ps_regnum (gdbarch));
+             th->wow64_context.EFlags |= FLAG_TRACE_BIT;
+           }
 
 
-      if (th->context.ContextFlags)
+         if (th->wow64_context.ContextFlags)
+           {
+             if (debug_registers_changed)
+               {
+                 th->wow64_context.Dr0 = dr[0];
+                 th->wow64_context.Dr1 = dr[1];
+                 th->wow64_context.Dr2 = dr[2];
+                 th->wow64_context.Dr3 = dr[3];
+                 th->wow64_context.Dr6 = DR6_CLEAR_VALUE;
+                 th->wow64_context.Dr7 = dr[7];
+               }
+             CHECK (Wow64SetThreadContext (th->h, &th->wow64_context));
+             th->wow64_context.ContextFlags = 0;
+           }
+       }
+      else
+#endif
        {
        {
-         if (debug_registers_changed)
+         if (step)
            {
            {
-             th->context.Dr0 = dr[0];
-             th->context.Dr1 = dr[1];
-             th->context.Dr2 = dr[2];
-             th->context.Dr3 = dr[3];
-             th->context.Dr6 = DR6_CLEAR_VALUE;
-             th->context.Dr7 = dr[7];
+             /* Single step by setting t bit.  */
+             struct regcache *regcache = get_current_regcache ();
+             struct gdbarch *gdbarch = regcache->arch ();
+             fetch_registers (regcache, gdbarch_ps_regnum (gdbarch));
+             th->context.EFlags |= FLAG_TRACE_BIT;
+           }
+
+         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 = DR6_CLEAR_VALUE;
+                 th->context.Dr7 = dr[7];
+               }
+             CHECK (SetThreadContext (th->h, &th->context));
+             th->context.ContextFlags = 0;
            }
            }
-         CHECK (SetThreadContext (th->h, &th->context));
-         th->context.ContextFlags = 0;
        }
     }
 
        }
     }
 
@@ -1516,9 +1738,10 @@ ctrl_c_handler (DWORD event_type)
 
 /* Get the next event from the child.  Returns a non-zero thread id if the event
    requires handling by WFI (or whatever).  */
 
 /* Get the next event from the child.  Returns a non-zero thread id if the event
    requires handling by WFI (or whatever).  */
-static int
-get_windows_debug_event (struct target_ops *ops,
-                        int pid, struct target_waitstatus *ourstatus)
+
+int
+windows_nat_target::get_windows_debug_event (int pid,
+                                            struct target_waitstatus *ourstatus)
 {
   BOOL debug_event;
   DWORD continue_status, event_code;
 {
   BOOL debug_event;
   DWORD continue_status, event_code;
@@ -1548,8 +1771,7 @@ get_windows_debug_event (struct target_ops *ops,
                     "CREATE_THREAD_DEBUG_EVENT"));
       if (saw_create != 1)
        {
                     "CREATE_THREAD_DEBUG_EVENT"));
       if (saw_create != 1)
        {
-         struct inferior *inf;
-         inf = find_inferior_pid (current_event.dwProcessId);
+         inferior *inf = find_inferior_pid (this, current_event.dwProcessId);
          if (!saw_create && inf->attach_flag)
            {
              /* Kludge around a Windows bug where first event is a create
          if (!saw_create && inf->attach_flag)
            {
              /* Kludge around a Windows bug where first event is a create
@@ -1620,8 +1842,23 @@ get_windows_debug_event (struct target_ops *ops,
          windows_delete_thread (ptid_t (current_event.dwProcessId, 0,
                                         current_event.dwThreadId),
                                 0, true /* main_thread_p */);
          windows_delete_thread (ptid_t (current_event.dwProcessId, 0,
                                         current_event.dwThreadId),
                                 0, true /* main_thread_p */);
-         ourstatus->kind = TARGET_WAITKIND_EXITED;
-         ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
+         DWORD exit_status = current_event.u.ExitProcess.dwExitCode;
+         /* If the exit status looks like a fatal exception, but we
+            don't recognize the exception's code, make the original
+            exit status value available, to avoid losing
+            information.  */
+         int exit_signal
+           = WIFSIGNALED (exit_status) ? WTERMSIG (exit_status) : -1;
+         if (exit_signal == -1)
+           {
+             ourstatus->kind = TARGET_WAITKIND_EXITED;
+             ourstatus->value.integer = exit_status;
+           }
+         else
+           {
+             ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
+             ourstatus->value.sig = gdb_signal_from_host (exit_signal);
+           }
          thread_id = current_event.dwThreadId;
        }
       break;
          thread_id = current_event.dwThreadId;
        }
       break;
@@ -1756,7 +1993,7 @@ windows_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
             the user tries to resume the execution in the inferior.
             This is a classic race that we should try to fix one day.  */
       SetConsoleCtrlHandler (&ctrl_c_handler, TRUE);
             the user tries to resume the execution in the inferior.
             This is a classic race that we should try to fix one day.  */
       SetConsoleCtrlHandler (&ctrl_c_handler, TRUE);
-      retval = get_windows_debug_event (this, pid, ourstatus);
+      retval = get_windows_debug_event (pid, ourstatus);
       SetConsoleCtrlHandler (&ctrl_c_handler, FALSE);
 
       if (retval)
       SetConsoleCtrlHandler (&ctrl_c_handler, FALSE);
 
       if (retval)
@@ -1785,17 +2022,41 @@ windows_add_all_dlls (void)
   HMODULE *hmodules;
   int i;
 
   HMODULE *hmodules;
   int i;
 
-  if (EnumProcessModules (current_process_handle, &dummy_hmodule,
-                         sizeof (HMODULE), &cb_needed) == 0)
-    return;
+#ifdef __x86_64__
+  if (wow64_process)
+    {
+      if (EnumProcessModulesEx (current_process_handle, &dummy_hmodule,
+                               sizeof (HMODULE), &cb_needed,
+                               LIST_MODULES_32BIT) == 0)
+       return;
+    }
+  else
+#endif
+    {
+      if (EnumProcessModules (current_process_handle, &dummy_hmodule,
+                             sizeof (HMODULE), &cb_needed) == 0)
+       return;
+    }
 
   if (cb_needed < 1)
     return;
 
   hmodules = (HMODULE *) alloca (cb_needed);
 
   if (cb_needed < 1)
     return;
 
   hmodules = (HMODULE *) alloca (cb_needed);
-  if (EnumProcessModules (current_process_handle, hmodules,
-                         cb_needed, &cb_needed) == 0)
-    return;
+#ifdef __x86_64__
+  if (wow64_process)
+    {
+      if (EnumProcessModulesEx (current_process_handle, hmodules,
+                               cb_needed, &cb_needed,
+                               LIST_MODULES_32BIT) == 0)
+       return;
+    }
+  else
+#endif
+    {
+      if (EnumProcessModules (current_process_handle, hmodules,
+                             cb_needed, &cb_needed) == 0)
+       return;
+    }
 
   for (i = 1; i < (int) (cb_needed / sizeof (HMODULE)); i++)
     {
 
   for (i = 1; i < (int) (cb_needed / sizeof (HMODULE)); i++)
     {
@@ -1850,6 +2111,21 @@ do_initial_windows_stuff (struct target_ops *ops, DWORD pid, int attaching)
   clear_proceed_status (0);
   init_wait_for_inferior ();
 
   clear_proceed_status (0);
   init_wait_for_inferior ();
 
+#ifdef __x86_64__
+  ignore_first_breakpoint = !attaching && wow64_process;
+
+  if (!wow64_process)
+    {
+      windows_set_context_register_offsets (amd64_mappings);
+      windows_set_segment_register_p (amd64_windows_segment_register_p);
+    }
+  else
+#endif
+    {
+      windows_set_context_register_offsets (i386_mappings);
+      windows_set_segment_register_p (i386_windows_segment_register_p);
+    }
+
   inf = current_inferior ();
   inferior_appeared (inf, pid);
   inf->attach_flag = attaching;
   inf = current_inferior ();
   inferior_appeared (inf, pid);
   inf->attach_flag = attaching;
@@ -1983,13 +2259,14 @@ windows_nat_target::attach (const char *args, int from_tty)
 #endif
 
   if (!ok)
 #endif
 
   if (!ok)
-    error (_("Can't attach to process."));
+    error (_("Can't attach to process %u (error %u)"),
+          (unsigned) pid, (unsigned) GetLastError ());
 
   DebugSetProcessKillOnExit (FALSE);
 
   if (from_tty)
     {
 
   DebugSetProcessKillOnExit (FALSE);
 
   if (from_tty)
     {
-      char *exec_file = (char *) get_exec_file (0);
+      const char *exec_file = get_exec_file (0);
 
       if (exec_file)
        printf_unfiltered ("Attaching to program `%s', %s\n", exec_file,
 
       if (exec_file)
        printf_unfiltered ("Attaching to program `%s', %s\n", exec_file,
@@ -1999,6 +2276,17 @@ windows_nat_target::attach (const char *args, int from_tty)
                           target_pid_to_str (ptid_t (pid)).c_str ());
     }
 
                           target_pid_to_str (ptid_t (pid)).c_str ());
     }
 
+#ifdef __x86_64__
+  HANDLE h = OpenProcess (PROCESS_QUERY_INFORMATION, FALSE, pid);
+  if (h != NULL)
+    {
+      BOOL wow64;
+      if (IsWow64Process (h, &wow64))
+       wow64_process = wow64;
+      CloseHandle (h);
+    }
+#endif
+
   do_initial_windows_stuff (this, pid, 1);
   target_terminal::ours ();
 }
   do_initial_windows_stuff (this, pid, 1);
   target_terminal::ours ();
 }
@@ -2053,9 +2341,21 @@ windows_get_exec_module_filename (char *exe_name_ret, size_t exe_name_max_len)
   DWORD cbNeeded;
 
   cbNeeded = 0;
   DWORD cbNeeded;
 
   cbNeeded = 0;
-  if (!EnumProcessModules (current_process_handle, &dh_buf,
-                          sizeof (HMODULE), &cbNeeded) || !cbNeeded)
-    return 0;
+#ifdef __x86_64__
+  if (wow64_process)
+    {
+      if (!EnumProcessModulesEx (current_process_handle, &dh_buf,
+                                sizeof (HMODULE), &cbNeeded,
+                                LIST_MODULES_32BIT) || !cbNeeded)
+       return 0;
+    }
+  else
+#endif
+    {
+      if (!EnumProcessModules (current_process_handle, &dh_buf,
+                              sizeof (HMODULE), &cbNeeded) || !cbNeeded)
+       return 0;
+    }
 
   /* We know the executable is always first in the list of modules,
      which we just fetched.  So no need to fetch more.  */
 
   /* We know the executable is always first in the list of modules,
      which we just fetched.  So no need to fetch more.  */
@@ -2709,7 +3009,7 @@ windows_nat_target::create_inferior (const char *exec_file,
        redirect_inferior_handles (allargs, allargs_copy,
                                   &fd_inp, &fd_out, &fd_err);
       if (errno)
        redirect_inferior_handles (allargs, allargs_copy,
                                   &fd_inp, &fd_out, &fd_err);
       if (errno)
-       warning (_("Error in redirection: %s."), strerror (errno));
+       warning (_("Error in redirection: %s."), safe_strerror (errno));
       else
        errno = e;
       allargs_len = strlen (allargs_copy);
       else
        errno = e;
       allargs_len = strlen (allargs_copy);
@@ -2813,6 +3113,12 @@ windows_nat_target::create_inferior (const char *exec_file,
     error (_("Error creating process %s, (error %u)."),
           exec_file, (unsigned) GetLastError ());
 
     error (_("Error creating process %s, (error %u)."),
           exec_file, (unsigned) GetLastError ());
 
+#ifdef __x86_64__
+  BOOL wow64;
+  if (IsWow64Process (pi.hProcess, &wow64))
+    wow64_process = wow64;
+#endif
+
   CloseHandle (pi.hThread);
   CloseHandle (pi.hProcess);
 
   CloseHandle (pi.hThread);
   CloseHandle (pi.hProcess);
 
@@ -2836,6 +3142,7 @@ windows_nat_target::mourn_inferior ()
       CHECK (CloseHandle (current_process_handle));
       open_process_used = 0;
     }
       CHECK (CloseHandle (current_process_handle));
       open_process_used = 0;
     }
+  siginfo_er.ExceptionCode = 0;
   inf_child_target::mourn_inferior ();
 }
 
   inf_child_target::mourn_inferior ();
 }
 
@@ -2948,6 +3255,7 @@ windows_xfer_shared_libraries (struct target_ops *ops,
 
       windows_xfer_shared_library (so->so_name, (CORE_ADDR)
                                   (uintptr_t) li->load_addr,
 
       windows_xfer_shared_library (so->so_name, (CORE_ADDR)
                                   (uintptr_t) li->load_addr,
+                                  &li->text_offset,
                                   target_gdbarch (), &obstack);
     }
   obstack_grow_str0 (&obstack, "</library-list>\n");
                                   target_gdbarch (), &obstack);
     }
   obstack_grow_str0 (&obstack, "</library-list>\n");
@@ -2968,6 +3276,51 @@ windows_xfer_shared_libraries (struct target_ops *ops,
   return len != 0 ? TARGET_XFER_OK : TARGET_XFER_EOF;
 }
 
   return len != 0 ? TARGET_XFER_OK : TARGET_XFER_EOF;
 }
 
+/* Helper for windows_nat_target::xfer_partial that handles signal info.  */
+
+static enum target_xfer_status
+windows_xfer_siginfo (gdb_byte *readbuf, ULONGEST offset, ULONGEST len,
+                     ULONGEST *xfered_len)
+{
+  char *buf = (char *) &siginfo_er;
+  size_t bufsize = sizeof (siginfo_er);
+
+#ifdef __x86_64__
+  EXCEPTION_RECORD32 er32;
+  if (wow64_process)
+    {
+      buf = (char *) &er32;
+      bufsize = sizeof (er32);
+
+      er32.ExceptionCode = siginfo_er.ExceptionCode;
+      er32.ExceptionFlags = siginfo_er.ExceptionFlags;
+      er32.ExceptionRecord = (uintptr_t) siginfo_er.ExceptionRecord;
+      er32.ExceptionAddress = (uintptr_t) siginfo_er.ExceptionAddress;
+      er32.NumberParameters = siginfo_er.NumberParameters;
+      int i;
+      for (i = 0; i < EXCEPTION_MAXIMUM_PARAMETERS; i++)
+       er32.ExceptionInformation[i] = siginfo_er.ExceptionInformation[i];
+    }
+#endif
+
+  if (siginfo_er.ExceptionCode == 0)
+    return TARGET_XFER_E_IO;
+
+  if (readbuf == nullptr)
+    return TARGET_XFER_E_IO;
+
+  if (offset > bufsize)
+    return TARGET_XFER_E_IO;
+
+  if (offset + len > bufsize)
+    len = bufsize - offset;
+
+  memcpy (readbuf, buf + offset, len);
+  *xfered_len = len;
+
+  return TARGET_XFER_OK;
+}
+
 enum target_xfer_status
 windows_nat_target::xfer_partial (enum target_object object,
                                  const char *annex, gdb_byte *readbuf,
 enum target_xfer_status
 windows_nat_target::xfer_partial (enum target_object object,
                                  const char *annex, gdb_byte *readbuf,
@@ -2983,6 +3336,9 @@ windows_nat_target::xfer_partial (enum target_object object,
       return windows_xfer_shared_libraries (this, object, annex, readbuf,
                                            writebuf, offset, len, xfered_len);
 
       return windows_xfer_shared_libraries (this, object, annex, readbuf,
                                            writebuf, offset, len, xfered_len);
 
+    case TARGET_OBJECT_SIGNAL_INFO:
+      return windows_xfer_siginfo (readbuf, offset, len, xfered_len);
+
     default:
       if (beneath () == NULL)
        {
     default:
       if (beneath () == NULL)
        {
@@ -3030,8 +3386,9 @@ windows_nat_target::thread_name (struct thread_info *thr)
 }
 
 
 }
 
 
+void _initialize_windows_nat ();
 void
 void
-_initialize_windows_nat (void)
+_initialize_windows_nat ()
 {
   x86_dr_low.set_control = cygwin_set_dr7;
   x86_dr_low.set_addr = cygwin_set_dr;
 {
   x86_dr_low.set_control = cygwin_set_dr7;
   x86_dr_low.set_addr = cygwin_set_dr;
@@ -3192,8 +3549,9 @@ windows_nat_target::thread_alive (ptid_t ptid)
   return WaitForSingleObject (thread_rec (tid, FALSE)->h, 0) != WAIT_OBJECT_0;
 }
 
   return WaitForSingleObject (thread_rec (tid, FALSE)->h, 0) != WAIT_OBJECT_0;
 }
 
+void _initialize_check_for_gdb_ini ();
 void
 void
-_initialize_check_for_gdb_ini (void)
+_initialize_check_for_gdb_ini ()
 {
   char *homedir;
   if (inhibit_gdbinit)
 {
   char *homedir;
   if (inhibit_gdbinit)
@@ -3289,8 +3647,9 @@ bad_GetConsoleFontSize (HANDLE w, DWORD nFont)
 /* Load any functions which may not be available in ancient versions
    of Windows.  */
 
 /* Load any functions which may not be available in ancient versions
    of Windows.  */
 
+void _initialize_loadable ();
 void
 void
-_initialize_loadable (void)
+_initialize_loadable ()
 {
   HMODULE hm = NULL;
 
 {
   HMODULE hm = NULL;
 
@@ -3306,6 +3665,12 @@ _initialize_loadable (void)
       GPA (hm, GetConsoleFontSize);
       GPA (hm, DebugActiveProcessStop);
       GPA (hm, GetCurrentConsoleFont);
       GPA (hm, GetConsoleFontSize);
       GPA (hm, DebugActiveProcessStop);
       GPA (hm, GetCurrentConsoleFont);
+#ifdef __x86_64__
+      GPA (hm, Wow64SuspendThread);
+      GPA (hm, Wow64GetThreadContext);
+      GPA (hm, Wow64SetThreadContext);
+      GPA (hm, Wow64GetThreadSelectorEntry);
+#endif
     }
 
   /* Set variables to dummy versions of these processes if the function
     }
 
   /* Set variables to dummy versions of these processes if the function
@@ -3328,6 +3693,9 @@ _initialize_loadable (void)
   if (hm)
     {
       GPA (hm, EnumProcessModules);
   if (hm)
     {
       GPA (hm, EnumProcessModules);
+#ifdef __x86_64__
+      GPA (hm, EnumProcessModulesEx);
+#endif
       GPA (hm, GetModuleInformation);
       GetModuleFileNameEx = (GetModuleFileNameEx_ftype *)
         GetProcAddress (hm, GetModuleFileNameEx_name);
       GPA (hm, GetModuleInformation);
       GetModuleFileNameEx = (GetModuleFileNameEx_ftype *)
         GetProcAddress (hm, GetModuleFileNameEx_name);
This page took 0.033644 seconds and 4 git commands to generate.