--- gdb/gdbsupport/gdb_wait.h~0	2019-09-21 00:58:17.000000000 +0300
+++ gdb/gdbsupport/gdb_wait.h	2019-12-18 17:59:28.434097000 +0200
@@ -40,18 +40,84 @@
    NOTE exception for GNU/Linux below).  We also fail to declare
    wait() and waitpid().  */
 
+/* For MINGW, the underlying idea is that when a Windows program is
+   terminated by a fatal exception, its exit code is the value of that
+   exception, as defined by the various EXCEPTION_* symbols in the
+   Windows API headers.
+
+   The translation below is not perfect, because a program could
+   legitimately exit normally with a status whose value happens to
+   have the high bits set, but that's extremely rare, to say the
+   least, and it is deemed such a negligibly small probability of
+   false positives is justified by the utility of reporting the
+   terminating signal in the "normal" cases.  */
+
+#ifdef __MINGW32__
+
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>		/* for EXCEPTION_* constants */
+# include "gdb/signals.h"	/* for enum gdb_signal */
+
+struct xlate_status
+{
+  DWORD status;		/* exit status (actually, fatal exception code) */
+  enum gdb_signal sig;	/* corresponding GDB signal value */
+};
+
+static inline enum gdb_signal
+windows_status_to_termsig (DWORD status)
+{
+  static const xlate_status status_xlate_tbl[] =
+    {
+     {EXCEPTION_ACCESS_VIOLATION, 	  GDB_SIGNAL_SEGV},
+     {EXCEPTION_IN_PAGE_ERROR,		  GDB_SIGNAL_SEGV},
+     {EXCEPTION_INVALID_HANDLE, 	  GDB_SIGNAL_SEGV},
+     {EXCEPTION_ILLEGAL_INSTRUCTION, 	  GDB_SIGNAL_ILL},
+     {EXCEPTION_NONCONTINUABLE_EXCEPTION, GDB_SIGNAL_ILL},
+     {EXCEPTION_ARRAY_BOUNDS_EXCEEDED, 	  GDB_SIGNAL_SEGV},
+     {EXCEPTION_FLT_DENORMAL_OPERAND, 	  GDB_SIGNAL_FPE},
+     {EXCEPTION_FLT_DIVIDE_BY_ZERO, 	  GDB_SIGNAL_FPE},
+     {EXCEPTION_FLT_INEXACT_RESULT, 	  GDB_SIGNAL_FPE},
+     {EXCEPTION_FLT_INVALID_OPERATION, 	  GDB_SIGNAL_FPE},
+     {EXCEPTION_FLT_OVERFLOW, 		  GDB_SIGNAL_FPE},
+     {EXCEPTION_FLT_STACK_CHECK, 	  GDB_SIGNAL_FPE},
+     {EXCEPTION_FLT_UNDERFLOW, 		  GDB_SIGNAL_FPE},
+     {EXCEPTION_INT_DIVIDE_BY_ZERO, 	  GDB_SIGNAL_FPE},
+     {EXCEPTION_INT_OVERFLOW, 		  GDB_SIGNAL_FPE},
+     {EXCEPTION_PRIV_INSTRUCTION, 	  GDB_SIGNAL_ILL},
+     {EXCEPTION_STACK_OVERFLOW, 	  GDB_SIGNAL_SEGV},
+     {CONTROL_C_EXIT, 			  GDB_SIGNAL_TERM}
+    };
+
+  for (const xlate_status &x : status_xlate_tbl)
+    if (x.status == status)
+      return x.sig;
+
+  return GDB_SIGNAL_UNKNOWN;
+}
+
+#endif	/* __MINGW32__ */
+
 #ifndef	WIFEXITED
-#define WIFEXITED(w)	(((w)&0377) == 0)
+# ifdef __MINGW32__
+#  define WIFEXITED(w)	(((w) & 0xC0000000) == 0)
+# else
+#  define WIFEXITED(w)	(((w)&0377) == 0)
+# endif
 #endif
 
 #ifndef	WIFSIGNALED
-#define WIFSIGNALED(w)	(((w)&0377) != 0177 && ((w)&~0377) == 0)
+# ifdef __MINGW32__
+#  define WIFSIGNALED(w)	(((w) & 0xC0000000) == 0xC0000000)
+# else
+#  define WIFSIGNALED(w)	(((w)&0377) != 0177 && ((w)&~0377) == 0)
+# endif
 #endif
 
 #ifndef	WIFSTOPPED
 #ifdef IBM6000
 
-/* Unfortunately, the above comment (about being compatible in all Unix 
+/* Unfortunately, the above comment (about being compatible in all Unix
    systems) is not quite correct for AIX, sigh.  And AIX 3.2 can generate
    status words like 0x57c (sigtrap received after load), and gdb would
    choke on it.  */
@@ -64,11 +130,19 @@
 #endif
 
 #ifndef	WEXITSTATUS
-#define WEXITSTATUS(w)	(((w) >> 8) & 0377) /* same as WRETCODE */
+# ifdef __MINGW32__
+#  define WEXITSTATUS(w)	((w) & ~0xC0000000)
+# else
+#  define WEXITSTATUS(w)	(((w) >> 8) & 0377) /* same as WRETCODE */
+# endif
 #endif
 
 #ifndef	WTERMSIG
-#define WTERMSIG(w)	((w) & 0177)
+# ifdef __MINGW32__
+#  define WTERMSIG(w)	windows_status_to_termsig (w)
+# else
+#  define WTERMSIG(w)	((w) & 0177)
+# endif
 #endif
 
 #ifndef	WSTOPSIG
--- gdb/windows-nat.c~0	2019-12-11 22:24:51.000000000 +0200
+++ gdb/windows-nat.c	2019-12-18 18:21:00.264558400 +0200
@@ -68,6 +68,7 @@
 #include "inf-child.h"
 #include "gdbsupport/gdb_tilde_expand.h"
 #include "gdbsupport/pathstuff.h"
+#include "gdbsupport/gdb_wait.h"
 
 #define AdjustTokenPrivileges		dyn_AdjustTokenPrivileges
 #define DebugActiveProcessStop		dyn_DebugActiveProcessStop
@@ -1620,8 +1621,17 @@ get_windows_debug_event (struct target_o
 	  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 (WIFEXITED (exit_status))
+	    {
+	      ourstatus->kind = TARGET_WAITKIND_EXITED;
+	      ourstatus->value.integer = WEXITSTATUS (exit_status);
+	    }
+	  else
+	    {
+	      ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
+	      ourstatus->value.sig = WTERMSIG (exit_status);
+	    }
 	  thread_id = current_event.dwThreadId;
 	}
       break;
--- gdb/windows-tdep.c~0	2019-09-21 00:58:17.000000000 +0300
+++ gdb/windows-tdep.c	2019-12-18 17:49:52.360580700 +0200
@@ -35,6 +35,8 @@
 #include "solib-target.h"
 #include "gdbcore.h"
 
+#include <signal.h>
+
 struct cmd_list_element *info_w32_cmdlist;
 
 typedef struct thread_information_block_32
@@ -461,6 +463,29 @@ init_w32_command_list (void)
     }
 }
 
+static int
+windows_gdb_signal_to_target (struct gdbarch *gdbarch, enum gdb_signal signal)
+{
+  switch (signal)
+    {
+    case GDB_SIGNAL_0:
+      return 0;
+    case GDB_SIGNAL_INT:
+      return SIGINT;
+    case GDB_SIGNAL_ILL:
+      return SIGILL;
+    case GDB_SIGNAL_ABRT:
+      return SIGABRT;
+    case GDB_SIGNAL_FPE:
+      return SIGFPE;
+    case GDB_SIGNAL_SEGV:
+      return SIGSEGV;
+    case GDB_SIGNAL_TERM:
+      return SIGTERM;
+    }
+  return -1;
+}
+
 /* To be called from the various GDB_OSABI_CYGWIN handlers for the
    various Windows architectures and machine types.  */
 
@@ -477,6 +502,8 @@ windows_init_abi (struct gdbarch_info in
   set_gdbarch_iterate_over_objfiles_in_search_order
     (gdbarch, windows_iterate_over_objfiles_in_search_order);
 
+  set_gdbarch_gdb_signal_to_target (gdbarch, windows_gdb_signal_to_target);
+
   set_solib_ops (gdbarch, &solib_target_so_ops);
 }
 
--- gdb/gdbserver/win32-low.c~0	2019-11-19 03:10:41.000000000 +0200
+++ gdb/gdbserver/win32-low.c	2019-12-18 17:51:32.098324200 +0200
@@ -34,6 +34,7 @@
 #include <process.h>
 #include "gdbsupport/gdb_tilde_expand.h"
 #include "gdbsupport/common-inferior.h"
+#include "gdbsupport/gdb_wait.h"
 
 #ifndef USE_WIN32API
 #include <sys/cygwin.h>
@@ -1511,8 +1512,19 @@ get_child_debug_event (struct target_wai
 		"for pid=%u tid=%x\n",
 		(unsigned) current_event.dwProcessId,
 		(unsigned) current_event.dwThreadId));
-      ourstatus->kind = TARGET_WAITKIND_EXITED;
-      ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
+      {
+	DWORD exit_status = current_event.u.ExitProcess.dwExitCode;
+	if (WIFEXITED (exit_status))
+	  {
+	    ourstatus->kind = TARGET_WAITKIND_EXITED;
+	    ourstatus->value.integer = WEXITSTATUS (exit_status);
+	  }
+	else
+	  {
+	    ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
+	    ourstatus->value.sig = WTERMSIG (exit_status);
+	  }
+      }
       child_continue (DBG_CONTINUE, -1);
       CloseHandle (current_process_handle);
       current_process_handle = NULL;
@@ -1607,6 +1619,7 @@ win32_wait (ptid_t ptid, struct target_w
 	  win32_clear_inferiors ();
 	  return ptid_t (current_event.dwProcessId);
 	case TARGET_WAITKIND_STOPPED:
+	case TARGET_WAITKIND_SIGNALLED:
 	case TARGET_WAITKIND_LOADED:
 	  OUTMSG2 (("Child Stopped with signal = %d \n",
 		    ourstatus->value.sig));
