From 0114ce5b4d8383abc6bbfa034c92ee9a29cb7e2c Mon Sep 17 00:00:00 2001
From: Jon Turney <jon.turney@dronecode.org.uk>
Date: Sun, 24 Jul 2016 18:18:10 +0100
Subject: [PATCH 4/5] 7.8-symtab-cygwin

See https://sourceware.org/ml/gdb-patches/2002-03/msg00557.html
---
 gdb/symtab.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/gdb/symtab.c b/gdb/symtab.c
index b519499f262..a051f4a7ea4 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -791,6 +791,10 @@ create_demangled_names_hash (struct objfile_per_bfd_storage *per_bfd)
      free_demangled_name_entry, xcalloc, xfree));
 }
 
+#ifdef __CYGWIN__
+#define LINKER_SYMBOLS_HAVE_WIN32_STDCALL_ARG_SIZES (1)
+#endif
+
 /* See symtab.h  */
 
 char *
@@ -800,6 +804,39 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol,
   char *demangled = NULL;
   int i;
 
+  /* On Windows, some functions use the `stdcall' calling convention,
+     in which the callee is expected to pop the arguments off the
+     stack.  Normally, the caller takes care of this, because only the
+     caller knows how many arguments it really passed.  To avoid
+     confusion, the linker symbols for `stdcall' functions have names
+     with a suffix "@N" attached to them, where "N" is the number of
+     bytes they'll pop.  That way, if a caller thinks some `stdcall'
+     function `foo' expects M argument bytes, but the definition of
+     `foo' expects N argument bytes, N != M, then the call will be a
+     reference to `foo@M', but the definition will have a linker
+     symbol `foo@N', and you'll get a link-time `symbol not found'
+     error, instead of a crash at run-time.
+
+     (Note how this fails to address calls through function pointers,
+     since the byte count isn't part of the function pointer's type.
+     Go, Microsoft!)
+
+     Whatever.  But our demangler doesn't like that '@N' suffix, so we
+     need to strip it off.  */
+  if (LINKER_SYMBOLS_HAVE_WIN32_STDCALL_ARG_SIZES)
+    {
+      char *arg_byte_suffix = strchr (mangled, '@');
+      if (arg_byte_suffix)
+        {
+          int prefix_len = arg_byte_suffix - mangled;
+          char *mangled_sans_suffix = (char *)(alloca (prefix_len + 1));
+          memcpy (mangled_sans_suffix, mangled, prefix_len);
+          mangled_sans_suffix[prefix_len] = '\0';
+
+          mangled = mangled_sans_suffix;
+        }
+    }
+
   if (gsymbol->language () == language_unknown)
     gsymbol->m_language = language_auto;
 
-- 
2.31.1.windows.1

