From f2b90e9a972c1f997c91d49e0f92b8f654564aef Mon Sep 17 00:00:00 2001
From: Hannes Domani <ssbssa@yahoo.de>
Date: Thu, 31 Jan 2019 01:31:05 +0100
Subject: [PATCH 3/6] Additional core file functions for minidump.

---
 bfd/coff-i386.c    |   2 +-
 bfd/coff-x86_64.c  |   2 +-
 bfd/coffgen.c      | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 bfd/libcoff-in.h   |   8 ++++
 bfd/libcoff.h      |   8 ++++
 gdb/windows-tdep.c |  47 +++++++++++++++++++++++
 6 files changed, 172 insertions(+), 2 deletions(-)

diff --git a/bfd/coff-i386.c b/bfd/coff-i386.c
index 705df2eb75..4bcfcb668c 100644
--- a/bfd/coff-i386.c
+++ b/bfd/coff-i386.c
@@ -695,7 +695,7 @@ const bfd_target
 
   BFD_JUMP_TABLE_GENERIC (coff),
   BFD_JUMP_TABLE_COPY (coff),
-  BFD_JUMP_TABLE_CORE (_bfd_nocore),
+  BFD_JUMP_TABLE_CORE (coff),
   BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
   BFD_JUMP_TABLE_SYMBOLS (coff),
   BFD_JUMP_TABLE_RELOCS (coff),
diff --git a/bfd/coff-x86_64.c b/bfd/coff-x86_64.c
index 0dc0136cd5..854434886f 100644
--- a/bfd/coff-x86_64.c
+++ b/bfd/coff-x86_64.c
@@ -812,7 +812,7 @@ const bfd_target
 
   BFD_JUMP_TABLE_GENERIC (coff),
   BFD_JUMP_TABLE_COPY (coff),
-  BFD_JUMP_TABLE_CORE (_bfd_nocore),
+  BFD_JUMP_TABLE_CORE (coff),
   BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
   BFD_JUMP_TABLE_SYMBOLS (coff),
   BFD_JUMP_TABLE_RELOCS (coff),
diff --git a/bfd/coffgen.c b/bfd/coffgen.c
index f9f2530952..2e1e03332a 100644
--- a/bfd/coffgen.c
+++ b/bfd/coffgen.c
@@ -42,6 +42,7 @@
 #include "libbfd.h"
 #include "coff/internal.h"
 #include "libcoff.h"
+#include "libiberty.h"
 
 /* Take a section header read from a coff file (in HOST byte order),
    and make a BFD "section" out of it.  This is used by ECOFF.  */
@@ -3186,6 +3187,14 @@ _bfd_coff_close_and_cleanup (bfd *abfd)
 
 /* Read minidump file.  */
 
+typedef struct
+{
+  int pid;
+  int signal;
+  char *exe_name;
+}
+pe_core_data;
+
 #pragma pack(push,4)
 
 typedef struct
@@ -3345,6 +3354,14 @@ typedef struct
 }
 dump_module;
 
+typedef struct
+{
+  uint32_t infoSize;
+  uint32_t flags;
+  uint32_t processId;
+}
+dump_misc;
+
 #pragma pack(pop)
 
 
@@ -3384,6 +3401,7 @@ coff_core_file_p (bfd *abfd)
   uint32_t exceptionRva = 0;
   uint32_t threadListRva = 0;
   uint32_t systemInfoRva = 0;
+  uint32_t miscInfoRva = 0;
 
   if (bfd_bread (&header, sizeof header, abfd) != sizeof header)
     goto fail;
@@ -3392,6 +3410,12 @@ coff_core_file_p (bfd *abfd)
       header.sig[2] != 'M' || header.sig[3] != 'P')
     goto fail;
 
+  pe_core_data *pcd = bfd_zalloc (abfd, sizeof (pe_core_data));
+  if (!pcd)
+    goto fail;
+
+  abfd->tdata.any = pcd;
+
   for (s = 0; s < header.streamCount; s++)
     {
       dump_directory dir;
@@ -3418,6 +3442,9 @@ coff_core_file_p (bfd *abfd)
 	case SystemInfoStream:
 	  systemInfoRva = dir.loc.rva;
 	  break;
+	case MiscInfoStream:
+	  miscInfoRva = dir.loc.rva;
+	  break;
 	}
     }
 
@@ -3443,6 +3470,33 @@ coff_core_file_p (bfd *abfd)
 	      || bfd_bread (&size, sizeof size, abfd) != sizeof size)
 	    goto fail;
 
+	  if (!m && size > 1)
+	    {
+	      uint16_t *wide_name = bfd_malloc (size + 2);
+	      if (wide_name == NULL)
+		goto fail;
+
+	      if (bfd_bread (wide_name, size, abfd) == size)
+		{
+		  uint32_t len = size / 2;
+		  wide_name[len] = 0;
+		  pcd->exe_name = bfd_zalloc (abfd, len + 1);
+		  if (pcd->exe_name)
+		    {
+#ifdef __MINGW32__
+		      wcstombs (pcd->exe_name, wide_name, len);
+#else
+		      uint32_t n;
+		      for (n = 0; n < size; n++)
+			pcd->exe_name[n] =
+			  wide_name[n] < 0x80 ? wide_name[n] : '?';
+#endif
+		    }
+		}
+
+	      free (wide_name);
+	    }
+
 	  sprintf (secname, ".coremodule/%llx", module.base);
 
 	  sec = make_bfd_asection (abfd, secname,
@@ -3540,6 +3594,13 @@ coff_core_file_p (bfd *abfd)
 	goto fail;
 
       exceptionThreadId = exception.threadId;
+
+      /* some exception codes are bigger than INT_MAX, so this makes sure
+	 bits 24 - 27 are 0, and move the highest 4 bits down.
+	 windows_gdb_signal_from_target() uses these changed values. */
+      if (!(exception.record.code & 0x0F000000))
+	pcd->signal = ((exception.record.code & 0xF0000000) >> 4)
+	  | (exception.record.code & 0x00FFFFFF);
     }
 
   if (threadListRva)
@@ -3593,8 +3654,54 @@ coff_core_file_p (bfd *abfd)
 				 arch == 9 ? bfd_mach_x86_64 : 0);
     }
 
+  if (miscInfoRva)
+    {
+      dump_misc misc;
+      if (bfd_seek (abfd, miscInfoRva, SEEK_SET) != 0
+	  || bfd_bread (&misc, sizeof misc, abfd) != sizeof misc
+	  || misc.infoSize < sizeof misc
+	  || !(misc.flags & 1))
+	goto fail;
+
+      pcd->pid = misc.processId;
+    }
+
   return abfd->xvec;
 
 fail:
   return NULL;
 }
+
+
+char *
+coff_core_file_failing_command (bfd *abfd)
+{
+  return ((pe_core_data *) abfd->tdata.any)->exe_name;
+}
+
+int
+coff_core_file_failing_signal (bfd *abfd)
+{
+  return ((pe_core_data *) abfd->tdata.any)->signal;
+}
+
+int
+coff_core_file_pid (bfd *abfd)
+{
+  return ((pe_core_data *) abfd->tdata.any)->pid;
+}
+
+bfd_boolean
+coff_core_file_matches_executable_p (bfd *core_bfd,
+				     bfd *exec_bfd)
+{
+  const char *core_exe = ((pe_core_data *) core_bfd->tdata.any)->exe_name;
+  const char *exec_exe = bfd_get_filename (exec_bfd);
+  if (!core_exe)
+    return TRUE;
+
+  core_exe = dos_lbasename (core_exe);
+  exec_exe = lbasename (exec_exe);
+
+  return strcasecmp (core_exe, exec_exe) == 0;
+}
diff --git a/bfd/libcoff-in.h b/bfd/libcoff-in.h
index 7c50313961..6a86f17f4c 100644
--- a/bfd/libcoff-in.h
+++ b/bfd/libcoff-in.h
@@ -585,6 +585,14 @@ extern const char *bfd_coff_group_name
 
 extern const bfd_target *coff_core_file_p
   (bfd *);
+extern char *coff_core_file_failing_command
+  (bfd *);
+extern int coff_core_file_failing_signal
+  (bfd *);
+extern int coff_core_file_pid
+  (bfd *);
+extern bfd_boolean coff_core_file_matches_executable_p
+  (bfd *, bfd *);
 
 #define coff_get_section_contents_in_window \
   _bfd_generic_get_section_contents_in_window
diff --git a/bfd/libcoff.h b/bfd/libcoff.h
index ee73e9f982..1e8fd29c41 100644
--- a/bfd/libcoff.h
+++ b/bfd/libcoff.h
@@ -589,6 +589,14 @@ extern const char *bfd_coff_group_name
 
 extern const bfd_target *coff_core_file_p
   (bfd *);
+extern char *coff_core_file_failing_command
+  (bfd *);
+extern int coff_core_file_failing_signal
+  (bfd *);
+extern int coff_core_file_pid
+  (bfd *);
+extern bfd_boolean coff_core_file_matches_executable_p
+  (bfd *, bfd *);
 
 #define coff_get_section_contents_in_window \
   _bfd_generic_get_section_contents_in_window
diff --git a/gdb/windows-tdep.c b/gdb/windows-tdep.c
index 6bbee97910..03755a1244 100644
--- a/gdb/windows-tdep.c
+++ b/gdb/windows-tdep.c
@@ -938,6 +938,51 @@ i386_windows_core_pid_to_str (struct gdbarch *gdbarch, ptid_t ptid)
   return normal_pid_to_str (ptid);
 }
 
+static enum gdb_signal
+windows_gdb_signal_from_target (struct gdbarch *gdbarch,
+				int signal)
+{
+  unsigned int usignal = signal;
+  switch (usignal)
+    {
+    case 0:
+      return GDB_SIGNAL_0;
+
+    case 0xC000005: /* EXCEPTION_ACCESS_VIOLATION */
+    case 0xC0000FD: /* STATUS_STACK_OVERFLOW */
+      return GDB_SIGNAL_SEGV;
+
+    case 0xC00008C: /* EXCEPTION_ARRAY_BOUNDS_EXCEEDED */
+    case 0xC00008D: /* STATUS_FLOAT_DENORMAL_OPERAND */
+    case 0xC00008E: /* STATUS_FLOAT_DIVIDE_BY_ZERO */
+    case 0xC00008F: /* STATUS_FLOAT_INEXACT_RESULT */
+    case 0xC000090: /* STATUS_FLOAT_INVALID_OPERATION */
+    case 0xC000091: /* STATUS_FLOAT_OVERFLOW */
+    case 0xC000092: /* STATUS_FLOAT_STACK_CHECK */
+    case 0xC000093: /* STATUS_FLOAT_UNDERFLOW */
+    case 0xC000094: /* STATUS_INTEGER_DIVIDE_BY_ZERO */
+    case 0xC000095: /* STATUS_INTEGER_OVERFLOW */
+      return GDB_SIGNAL_FPE;
+
+    case 0x8000003: /* EXCEPTION_BREAKPOINT */
+    case 0x8000004: /* EXCEPTION_SINGLE_STEP */
+      return GDB_SIGNAL_TRAP;
+
+    case 0x4010005: /* DBG_CONTROL_C */
+    case 0x4010008: /* DBG_CONTROL_BREAK */
+      return GDB_SIGNAL_INT;
+
+    case 0xC00001D: /* EXCEPTION_ILLEGAL_INSTRUCTION */
+    case 0xC000096: /* EXCEPTION_PRIV_INSTRUCTION */
+    case 0xC000025: /* EXCEPTION_NONCONTINUABLE_EXCEPTION */
+      return GDB_SIGNAL_ILL;
+
+    case 0x4000015: /* FATAL_APP_EXIT */
+      return GDB_SIGNAL_ABRT;
+    }
+  return GDB_SIGNAL_UNKNOWN;
+}
+
 /* To be called from the various GDB_OSABI_CYGWIN handlers for the
    various Windows architectures and machine types.  */
 
@@ -964,6 +1009,8 @@ windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_gdbarch_core_xfer_shared_libraries
     (gdbarch, windows_core_xfer_shared_libraries);
   set_gdbarch_core_pid_to_str (gdbarch, i386_windows_core_pid_to_str);
+  set_gdbarch_gdb_signal_from_target (gdbarch,
+				      windows_gdb_signal_from_target);
 }
 
 /* Implementation of `tlb' variable.  */
-- 
2.15.1.windows.2

