]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/amd64-windows-tdep.c
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / amd64-windows-tdep.c
index 2ca979513cd7c08b3febeeb858c01b829e27afee..14477e61fdd47ada989cfecab1fe8922f5816414 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009-2020 Free Software Foundation, Inc.
+/* Copyright (C) 2009-2023 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -42,13 +42,78 @@ static int amd64_windows_dummy_call_integer_regs[] =
   AMD64_R9_REGNUM            /* %r9 */
 };
 
+/* This vector maps GDB's idea of a register's number into an offset into
+   the Windows API CONTEXT structure.  */
+static int amd64_windows_gregset_reg_offset[] =
+{
+  120, /* Rax */
+  144, /* Rbx */
+  128, /* Rcx */
+  136, /* Rdx */
+  168, /* Rsi */
+  176, /* Rdi */
+  160, /* Rbp */
+  152, /* Rsp */
+  184, /* R8 */
+  192, /* R9 */
+  200, /* R10 */
+  208, /* R11 */
+  216, /* R12 */
+  224, /* R13 */
+  232, /* R14 */
+  240, /* R15 */
+  248, /* Rip */
+  68,  /* EFlags */
+  56,  /* SegCs */
+  66,  /* SegSs */
+  58,  /* SegDs */
+  60,  /* SegEs */
+  62,  /* SegFs */
+  64,  /* SegGs */
+  288, /* FloatSave.FloatRegisters[0] */
+  304, /* FloatSave.FloatRegisters[1] */
+  320, /* FloatSave.FloatRegisters[2] */
+  336, /* FloatSave.FloatRegisters[3] */
+  352, /* FloatSave.FloatRegisters[4] */
+  368, /* FloatSave.FloatRegisters[5] */
+  384, /* FloatSave.FloatRegisters[6] */
+  400, /* FloatSave.FloatRegisters[7] */
+  256, /* FloatSave.ControlWord */
+  258, /* FloatSave.StatusWord */
+  260, /* FloatSave.TagWord */
+  268, /* FloatSave.ErrorSelector */
+  264, /* FloatSave.ErrorOffset */
+  276, /* FloatSave.DataSelector */
+  272, /* FloatSave.DataOffset */
+  268, /* FloatSave.ErrorSelector */
+  416, /* Xmm0 */
+  432, /* Xmm1 */
+  448, /* Xmm2 */
+  464, /* Xmm3 */
+  480, /* Xmm4 */
+  496, /* Xmm5 */
+  512, /* Xmm6 */
+  528, /* Xmm7 */
+  544, /* Xmm8 */
+  560, /* Xmm9 */
+  576, /* Xmm10 */
+  592, /* Xmm11 */
+  608, /* Xmm12 */
+  624, /* Xmm13 */
+  640, /* Xmm14 */
+  656, /* Xmm15 */
+  280, /* FloatSave.MxCsr */
+};
+
+#define AMD64_WINDOWS_SIZEOF_GREGSET 1232
+
 /* Return nonzero if an argument of type TYPE should be passed
    via one of the integer registers.  */
 
 static int
 amd64_windows_passed_by_integer_register (struct type *type)
 {
-  switch (TYPE_CODE (type))
+  switch (type->code ())
     {
       case TYPE_CODE_INT:
       case TYPE_CODE_ENUM:
@@ -60,10 +125,11 @@ amd64_windows_passed_by_integer_register (struct type *type)
       case TYPE_CODE_RVALUE_REF:
       case TYPE_CODE_STRUCT:
       case TYPE_CODE_UNION:
-       return (TYPE_LENGTH (type) == 1
-               || TYPE_LENGTH (type) == 2
-               || TYPE_LENGTH (type) == 4
-               || TYPE_LENGTH (type) == 8);
+      case TYPE_CODE_COMPLEX:
+       return (type->length () == 1
+               || type->length () == 2
+               || type->length () == 4
+               || type->length () == 8);
 
       default:
        return 0;
@@ -76,9 +142,9 @@ amd64_windows_passed_by_integer_register (struct type *type)
 static int
 amd64_windows_passed_by_xmm_register (struct type *type)
 {
-  return ((TYPE_CODE (type) == TYPE_CODE_FLT
-          || TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
-          && (TYPE_LENGTH (type) == 4 || TYPE_LENGTH (type) == 8));
+  return ((type->code () == TYPE_CODE_FLT
+          || type->code () == TYPE_CODE_DECFLOAT)
+         && (type->length () == 4 || type->length () == 8));
 }
 
 /* Return non-zero iff an argument of the given TYPE should be passed
@@ -113,8 +179,8 @@ amd64_windows_adjust_args_passed_by_pointer (struct value **args,
     if (amd64_windows_passed_by_pointer (value_type (args[i])))
       {
        struct type *type = value_type (args[i]);
-       const gdb_byte *valbuf = value_contents (args[i]);
-       const int len = TYPE_LENGTH (type);
+       const gdb_byte *valbuf = value_contents (args[i]).data ();
+       const int len = type->length ();
 
        /* Store a copy of that argument on the stack, aligned to
           a 16 bytes boundary, and then use the copy's address as
@@ -139,12 +205,12 @@ amd64_windows_store_arg_in_reg (struct regcache *regcache,
                                struct value *arg, int regno)
 {
   struct type *type = value_type (arg);
-  const gdb_byte *valbuf = value_contents (arg);
+  const gdb_byte *valbuf = value_contents (arg).data ();
   gdb_byte buf[8];
 
-  gdb_assert (TYPE_LENGTH (type) <= 8);
+  gdb_assert (type->length () <= 8);
   memset (buf, 0, sizeof buf);
-  memcpy (buf, valbuf, std::min (TYPE_LENGTH (type), (ULONGEST) 8));
+  memcpy (buf, valbuf, std::min (type->length (), (ULONGEST) 8));
   regcache->cooked_write (regno, buf);
 }
 
@@ -186,7 +252,7 @@ amd64_windows_push_arguments (struct regcache *regcache, int nargs,
   for (i = 0; i < nargs; i++)
     {
       struct type *type = value_type (args[i]);
-      int len = TYPE_LENGTH (type);
+      int len = type->length ();
       int on_stack_p = 1;
 
       if (reg_idx < ARRAY_SIZE (amd64_windows_dummy_call_integer_regs))
@@ -202,7 +268,7 @@ amd64_windows_push_arguments (struct regcache *regcache, int nargs,
          else if (amd64_windows_passed_by_xmm_register (type))
            {
              amd64_windows_store_arg_in_reg
-               (regcache, args[i], AMD64_XMM0_REGNUM + reg_idx);
+               (regcache, args[i], AMD64_XMM0_REGNUM + reg_idx);
              /* In case of varargs, these parameters must also be
                 passed via the integer registers.  */
              amd64_windows_store_arg_in_reg
@@ -229,10 +295,10 @@ amd64_windows_push_arguments (struct regcache *regcache, int nargs,
   for (i = 0; i < num_stack_args; i++)
     {
       struct type *type = value_type (stack_args[i]);
-      const gdb_byte *valbuf = value_contents (stack_args[i]);
+      const gdb_byte *valbuf = value_contents (stack_args[i]).data ();
 
-      write_memory (sp + element * 8, valbuf, TYPE_LENGTH (type));
-      element += ((TYPE_LENGTH (type) + 7) / 8);
+      write_memory (sp + element * 8, valbuf, type->length ());
+      element += ((type->length () + 7) / 8);
     }
 
   return sp;
@@ -258,7 +324,7 @@ amd64_windows_push_dummy_call
   if (return_method == return_method_struct)
     {
       /* The "hidden" argument is passed throught the first argument
-         register.  */
+        register.  */
       const int arg_regnum = amd64_windows_dummy_call_integer_regs[0];
 
       store_unsigned_integer (buf, 8, byte_order, struct_addr);
@@ -291,37 +357,49 @@ amd64_windows_return_value (struct gdbarch *gdbarch, struct value *function,
                            struct type *type, struct regcache *regcache,
                            gdb_byte *readbuf, const gdb_byte *writebuf)
 {
-  int len = TYPE_LENGTH (type);
+  int len = type->length ();
   int regnum = -1;
 
   /* See if our value is returned through a register.  If it is, then
      store the associated register number in REGNUM.  */
-  switch (TYPE_CODE (type))
+  switch (type->code ())
     {
       case TYPE_CODE_FLT:
-      case TYPE_CODE_DECFLOAT:
-        /* __m128, __m128i, __m128d, floats, and doubles are returned
-           via XMM0.  */
-        if (len == 4 || len == 8 || len == 16)
-          regnum = AMD64_XMM0_REGNUM;
-        break;
+       /* floats, and doubles are returned via XMM0.  */
+       if (len == 4 || len == 8)
+         regnum = AMD64_XMM0_REGNUM;
+       break;
+      case TYPE_CODE_ARRAY:
+       /* __m128, __m128i and __m128d are returned via XMM0.  */
+       if (type->is_vector () && len == 16)
+         {
+           enum type_code code = type->target_type ()->code ();
+           if (code == TYPE_CODE_INT || code == TYPE_CODE_FLT)
+             {
+               regnum = AMD64_XMM0_REGNUM;
+               break;
+             }
+         }
+       /* fall through */
       default:
-        /* All other values that are 1, 2, 4 or 8 bytes long are returned
-           via RAX.  */
-        if (len == 1 || len == 2 || len == 4 || len == 8)
-          regnum = AMD64_RAX_REGNUM;
-        break;
+       /* All other values that are 1, 2, 4 or 8 bytes long are returned
+          via RAX.  */
+       if (len == 1 || len == 2 || len == 4 || len == 8)
+         regnum = AMD64_RAX_REGNUM;
+       else if (len == 16 && type->code () == TYPE_CODE_INT)
+         regnum = AMD64_XMM0_REGNUM;
+       break;
     }
 
   if (regnum < 0)
     {
       /* RAX contains the address where the return value has been stored.  */
       if (readbuf)
-        {
+       {
          ULONGEST addr;
 
          regcache_raw_read_unsigned (regcache, AMD64_RAX_REGNUM, &addr);
-         read_memory (addr, readbuf, TYPE_LENGTH (type));
+         read_memory (addr, readbuf, type->length ());
        }
       return RETURN_VALUE_ABI_RETURNS_ADDRESS;
     }
@@ -351,17 +429,17 @@ amd64_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
       gdb_byte buf[4];
 
       if (target_read_memory (pc + 1, buf, sizeof buf) == 0)
-       {
-         struct bound_minimal_symbol s;
-         CORE_ADDR call_dest;
+       {
+         struct bound_minimal_symbol s;
+         CORE_ADDR call_dest;
 
          call_dest = pc + 5 + extract_signed_integer (buf, 4, byte_order);
-         s = lookup_minimal_symbol_by_pc (call_dest);
-         if (s.minsym != NULL
-             && s.minsym->linkage_name () != NULL
-             && strcmp (s.minsym->linkage_name (), "__main") == 0)
-           pc += 5;
-       }
+         s = lookup_minimal_symbol_by_pc (call_dest);
+         if (s.minsym != NULL
+             && s.minsym->linkage_name () != NULL
+             && strcmp (s.minsym->linkage_name (), "__main") == 0)
+           pc += 5;
+       }
     }
 
   return pc;
@@ -435,7 +513,7 @@ pc_in_range (CORE_ADDR pc, const struct amd64_windows_frame_cache *cache)
    Return 1 if an epilogue sequence was recognized, 0 otherwise.  */
 
 static int
-amd64_windows_frame_decode_epilogue (struct frame_info *this_frame,
+amd64_windows_frame_decode_epilogue (frame_info_ptr this_frame,
                                     struct amd64_windows_frame_cache *cache)
 {
   /* According to MSDN an epilogue "must consist of either an add RSP,constant
@@ -615,7 +693,7 @@ amd64_windows_frame_decode_epilogue (struct frame_info *this_frame,
 /* Decode and execute unwind insns at UNWIND_INFO.  */
 
 static void
-amd64_windows_frame_decode_insns (struct frame_info *this_frame,
+amd64_windows_frame_decode_insns (frame_info_ptr this_frame,
                                  struct amd64_windows_frame_cache *cache,
                                  CORE_ADDR unwind_info)
 {
@@ -678,14 +756,10 @@ amd64_windows_frame_decode_insns (struct frame_info *this_frame,
                              (gdb_byte *) &ex_ui, sizeof (ex_ui)) != 0)
        return;
 
-      if (frame_debug)
-       fprintf_unfiltered
-         (gdb_stdlog,
-          "amd64_windows_frame_decodes_insn: "
-          "%s: ver: %02x, plgsz: %02x, cnt: %02x, frame: %02x\n",
-          paddress (gdbarch, unwind_info),
-          ex_ui.Version_Flags, ex_ui.SizeOfPrologue,
-          ex_ui.CountOfCodes, ex_ui.FrameRegisterOffset);
+      frame_debug_printf ("%s: ver: %02x, plgsz: %02x, cnt: %02x, frame: %02x",
+                         paddress (gdbarch, unwind_info),
+                         ex_ui.Version_Flags, ex_ui.SizeOfPrologue,
+                         ex_ui.CountOfCodes, ex_ui.FrameRegisterOffset);
 
       /* Check version.  */
       if (PEX64_UWI_VERSION (ex_ui.Version_Flags) != 1
@@ -723,10 +797,9 @@ amd64_windows_frame_decode_insns (struct frame_info *this_frame,
          get_frame_register (this_frame, frreg, buf);
          save_addr = extract_unsigned_integer (buf, 8, byte_order);
 
-         if (frame_debug)
-           fprintf_unfiltered (gdb_stdlog, "   frame_reg=%s, val=%s\n",
-                               gdbarch_register_name (gdbarch, frreg),
-                               paddress (gdbarch, save_addr));
+         frame_debug_printf ("   frame_reg=%s, val=%s",
+                             gdbarch_register_name (gdbarch, frreg),
+                             paddress (gdbarch, save_addr));
        }
 
       /* Read opcodes.  */
@@ -757,10 +830,8 @@ amd64_windows_frame_decode_insns (struct frame_info *this_frame,
             prologue has been fully executed.  */
          if (cache->pc >= start + p[0] || cache->pc < start)
            {
-             if (frame_debug)
-               fprintf_unfiltered
-                 (gdb_stdlog, "   op #%u: off=0x%02x, insn=0x%02x\n",
-                  (unsigned) (p - insns), p[0], p[1]);
+             frame_debug_printf ("   op #%u: off=0x%02x, insn=0x%02x",
+                                 (unsigned) (p - insns), p[0], p[1]);
 
              /* If there is no frame registers defined, the current value of
                 rsp is used instead.  */
@@ -834,11 +905,11 @@ amd64_windows_frame_decode_insns (struct frame_info *this_frame,
                }
 
              /* Display address where the register was saved.  */
-             if (frame_debug && reg >= 0)
-               fprintf_unfiltered
-                 (gdb_stdlog, "     [reg %s at %s]\n",
-                  gdbarch_register_name (gdbarch, reg),
-                  paddress (gdbarch, cache->prev_reg_addr[reg]));
+             if (reg >= 0)
+               frame_debug_printf ("     [reg %s at %s]",
+                                   gdbarch_register_name (gdbarch, reg),
+                                   paddress (gdbarch,
+                                             cache->prev_reg_addr[reg]));
            }
 
          /* Adjust with the length of the opcode.  */
@@ -900,14 +971,11 @@ amd64_windows_frame_decode_insns (struct frame_info *this_frame,
          unwind_info =
            extract_unsigned_integer (d.rva_UnwindData, 4, byte_order);
 
-         if (frame_debug)
-           fprintf_unfiltered
-             (gdb_stdlog,
-              "amd64_windows_frame_decodes_insn (next in chain):"
-              " unwind_data=%s, start_rva=%s, end_rva=%s\n",
-              paddress (gdbarch, unwind_info),
-              paddress (gdbarch, cache->start_rva),
-              paddress (gdbarch, cache->end_rva));
+         frame_debug_printf ("next in chain: unwind_data=%s, start_rva=%s, "
+                             "end_rva=%s",
+                             paddress (gdbarch, unwind_info),
+                             paddress (gdbarch, cache->start_rva),
+                             paddress (gdbarch, cache->end_rva));
        }
 
       /* Allow the user to break this loop.  */
@@ -918,10 +986,9 @@ amd64_windows_frame_decode_insns (struct frame_info *this_frame,
     cache->prev_rip_addr = cur_sp;
   cache->prev_sp = cur_sp + 8;
 
-  if (frame_debug)
-    fprintf_unfiltered (gdb_stdlog, "   prev_sp: %s, prev_pc @%s\n",
-                       paddress (gdbarch, cache->prev_sp),
-                       paddress (gdbarch, cache->prev_rip_addr));
+  frame_debug_printf ("   prev_sp: %s, prev_pc @%s",
+                     paddress (gdbarch, cache->prev_sp),
+                     paddress (gdbarch, cache->prev_rip_addr));
 }
 
 /* Find SEH unwind info for PC, returning 0 on success.
@@ -995,11 +1062,9 @@ amd64_windows_find_unwind_info (struct gdbarch *gdbarch, CORE_ADDR pc,
        break;
     }
 
-  if (frame_debug)
-    fprintf_unfiltered
-      (gdb_stdlog,
-       "amd64_windows_find_unwind_data:  image_base=%s, unwind_data=%s\n",
-       paddress (gdbarch, base), paddress (gdbarch, *unwind_info));
+  frame_debug_printf ("image_base=%s, unwind_data=%s",
+                     paddress (gdbarch, base),
+                     paddress (gdbarch, *unwind_info));
 
   return 0;
 }
@@ -1008,7 +1073,7 @@ amd64_windows_find_unwind_info (struct gdbarch *gdbarch, CORE_ADDR pc,
    for THIS_FRAME.  */
 
 static struct amd64_windows_frame_cache *
-amd64_windows_frame_cache (struct frame_info *this_frame, void **this_cache)
+amd64_windows_frame_cache (frame_info_ptr this_frame, void **this_cache)
 {
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
@@ -1053,7 +1118,7 @@ amd64_windows_frame_cache (struct frame_info *this_frame, void **this_cache)
    using the standard Windows x64 SEH info.  */
 
 static struct value *
-amd64_windows_frame_prev_register (struct frame_info *this_frame,
+amd64_windows_frame_prev_register (frame_info_ptr this_frame,
                                   void **this_cache, int regnum)
 {
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
@@ -1061,11 +1126,9 @@ amd64_windows_frame_prev_register (struct frame_info *this_frame,
     amd64_windows_frame_cache (this_frame, this_cache);
   CORE_ADDR prev;
 
-  if (frame_debug)
-    fprintf_unfiltered (gdb_stdlog,
-                       "amd64_windows_frame_prev_register %s for sp=%s\n",
-                       gdbarch_register_name (gdbarch, regnum),
-                       paddress (gdbarch, cache->prev_sp));
+  frame_debug_printf ("%s for sp=%s",
+                     gdbarch_register_name (gdbarch, regnum),
+                     paddress (gdbarch, cache->prev_sp));
 
   if (regnum >= AMD64_XMM0_REGNUM && regnum <= AMD64_XMM0_REGNUM + 15)
       prev = cache->prev_xmm_addr[regnum - AMD64_XMM0_REGNUM];
@@ -1082,8 +1145,8 @@ amd64_windows_frame_prev_register (struct frame_info *this_frame,
   else
     prev = 0;
 
-  if (prev && frame_debug)
-    fprintf_unfiltered (gdb_stdlog, "  -> at %s\n", paddress (gdbarch, prev));
+  if (prev != 0)
+    frame_debug_printf ("  -> at %s", paddress (gdbarch, prev));
 
   if (prev)
     {
@@ -1101,7 +1164,7 @@ amd64_windows_frame_prev_register (struct frame_info *this_frame,
    the standard Windows x64 SEH info.  */
 
 static void
-amd64_windows_frame_this_id (struct frame_info *this_frame, void **this_cache,
+amd64_windows_frame_this_id (frame_info_ptr this_frame, void **this_cache,
                   struct frame_id *this_id)
 {
   struct amd64_windows_frame_cache *cache =
@@ -1115,6 +1178,7 @@ amd64_windows_frame_this_id (struct frame_info *this_frame, void **this_cache,
 
 static const struct frame_unwind amd64_windows_frame_unwind =
 {
+  "amd64 windows",
   NORMAL_FRAME,
   default_frame_unwind_stop_reason,
   &amd64_windows_frame_this_id,
@@ -1166,7 +1230,7 @@ amd64_windows_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
 /* Check Win64 DLL jmp trampolines and find jump destination.  */
 
 static CORE_ADDR
-amd64_windows_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
+amd64_windows_skip_trampoline_code (frame_info_ptr frame, CORE_ADDR pc)
 {
   CORE_ADDR destination = 0;
   struct gdbarch *gdbarch = get_frame_arch (frame);
@@ -1208,9 +1272,13 @@ amd64_windows_auto_wide_charset (void)
   return "UTF-16";
 }
 
+/* Common parts for gdbarch initialization for Windows and Cygwin on AMD64.  */
+
 static void
-amd64_windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+amd64_windows_init_abi_common (gdbarch_info info, struct gdbarch *gdbarch)
 {
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
+
   /* The dwarf2 unwinder (appended very early by i386_gdbarch_init) is
      preferred over the SEH one.  The reasons are:
      - binaries without SEH but with dwarf2 debug info are correctly handled
@@ -1227,11 +1295,6 @@ amd64_windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   amd64_init_abi (info, gdbarch,
                  amd64_target_description (X86_XSTATE_SSE_MASK, false));
 
-  windows_init_abi (info, gdbarch);
-
-  /* On Windows, "long"s are only 32bit.  */
-  set_gdbarch_long_bit (gdbarch, 32);
-
   /* Function calls.  */
   set_gdbarch_push_dummy_call (gdbarch, amd64_windows_push_dummy_call);
   set_gdbarch_return_value (gdbarch, amd64_windows_return_value);
@@ -1241,17 +1304,69 @@ amd64_windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 
   set_gdbarch_skip_prologue (gdbarch, amd64_windows_skip_prologue);
 
+  tdep->gregset_reg_offset = amd64_windows_gregset_reg_offset;
+  tdep->gregset_num_regs = ARRAY_SIZE (amd64_windows_gregset_reg_offset);
+  tdep->sizeof_gregset = AMD64_WINDOWS_SIZEOF_GREGSET;
+  tdep->sizeof_fpregset = 0;
+
+  /* Core file support.  */
+  set_gdbarch_core_xfer_shared_libraries
+    (gdbarch, windows_core_xfer_shared_libraries);
+  set_gdbarch_core_pid_to_str (gdbarch, windows_core_pid_to_str);
+
   set_gdbarch_auto_wide_charset (gdbarch, amd64_windows_auto_wide_charset);
 }
 
+/* gdbarch initialization for Windows on AMD64.  */
+
+static void
+amd64_windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  amd64_windows_init_abi_common (info, gdbarch);
+  windows_init_abi (info, gdbarch);
+
+  /* On Windows, "long"s are only 32bit.  */
+  set_gdbarch_long_bit (gdbarch, 32);
+}
+
+/* gdbarch initialization for Cygwin on AMD64.  */
+
+static void
+amd64_cygwin_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  amd64_windows_init_abi_common (info, gdbarch);
+  cygwin_init_abi (info, gdbarch);
+}
+
 static gdb_osabi
 amd64_windows_osabi_sniffer (bfd *abfd)
 {
   const char *target_name = bfd_get_target (abfd);
 
-  if (strcmp (target_name, "pei-x86-64") == 0)
+  if (!streq (target_name, "pei-x86-64"))
+    return GDB_OSABI_UNKNOWN;
+
+  if (is_linked_with_cygwin_dll (abfd))
     return GDB_OSABI_CYGWIN;
 
+  return GDB_OSABI_WINDOWS;
+}
+
+static enum gdb_osabi
+amd64_cygwin_core_osabi_sniffer (bfd *abfd)
+{
+  const char *target_name = bfd_get_target (abfd);
+
+  /* Cygwin uses elf core dumps.  Do not claim all ELF executables,
+     check whether there is a .reg section of proper size.  */
+  if (strcmp (target_name, "elf64-x86-64") == 0)
+    {
+      asection *section = bfd_get_section_by_name (abfd, ".reg");
+      if (section != nullptr
+         && bfd_section_size (section) == AMD64_WINDOWS_SIZEOF_GREGSET)
+       return GDB_OSABI_CYGWIN;
+    }
+
   return GDB_OSABI_UNKNOWN;
 }
 
@@ -1259,9 +1374,16 @@ void _initialize_amd64_windows_tdep ();
 void
 _initialize_amd64_windows_tdep ()
 {
+  gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, GDB_OSABI_WINDOWS,
+                         amd64_windows_init_abi);
   gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, GDB_OSABI_CYGWIN,
-                          amd64_windows_init_abi);
+                         amd64_cygwin_init_abi);
 
   gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour,
                                  amd64_windows_osabi_sniffer);
+
+  /* Cygwin uses elf core dumps.  */
+  gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour,
+                                 amd64_cygwin_core_osabi_sniffer);
+
 }