summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYaakov Selkowitz <yselkowi@redhat.com>2016-09-12 16:11:45 -0500
committerYaakov Selkowitz <yselkowi@redhat.com>2016-09-12 16:11:45 -0500
commit0ddc85a82cb785cc9f6e8d9ed0ddbf2f6d14ab95 (patch)
tree3baf662a8588dbec8462cd198a5fa7ad20b4f46f
parent9563634446cc0a4fddbbafd2468dadff09cbe368 (diff)
downloadcygwin-gdb-0ddc85a82cb785cc9f6e8d9ed0ddbf2f6d14ab95.tar.gz
cygwin-gdb-0ddc85a82cb785cc9f6e8d9ed0ddbf2f6d14ab95.tar.xz
cygwin-gdb-0ddc85a82cb785cc9f6e8d9ed0ddbf2f6d14ab95.zip
cygwin-gdb 7.10.1HEADmaster
-rw-r--r--.gitignore1
-rw-r--r--0001-Teach-gdb-how-to-unwind-cygwin-_sigbe-and-sigdelayed.patch457
-rw-r--r--0002-7.8-windows-nat-cygwin.patch.patch139
-rw-r--r--0003-Better-handling-for-realpath-failures-in-windows_mak.patch52
-rw-r--r--7.8-symtab-cygwin.patch44
-rw-r--r--cygwin-gdb.spec14
-rw-r--r--sources2
7 files changed, 707 insertions, 2 deletions
diff --git a/.gitignore b/.gitignore
index d66b1e3..9491609 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
/gdb-7.9.1.tar.xz
+/gdb-7.10.1.tar.xz
diff --git a/0001-Teach-gdb-how-to-unwind-cygwin-_sigbe-and-sigdelayed.patch b/0001-Teach-gdb-how-to-unwind-cygwin-_sigbe-and-sigdelayed.patch
new file mode 100644
index 0000000..9cee767
--- /dev/null
+++ b/0001-Teach-gdb-how-to-unwind-cygwin-_sigbe-and-sigdelayed.patch
@@ -0,0 +1,457 @@
+From 3b165f5d903053172dfb2182eea98595b73fd8d1 Mon Sep 17 00:00:00 2001
+From: Jon Turney <jon.turney@dronecode.org.uk>
+Date: Tue, 12 Jan 2016 22:49:09 +0000
+Subject: [PATCH 1/3] Teach gdb how to unwind cygwin _sigbe and sigdelayed
+ frames
+
+The majority of functions in the cygwin DLL are wrapped by routines which use an
+an alternate stack to return via a signal handler if a signal occured while
+inside the function. (See [1],[2])
+
+At present, these frames cannot be correctly unwound by gdb. There doesn't seem
+to currently be a way to correctly describe these frames using DWARF CFI.
+
+So instead, write a custom unwinder for _sigbe and sigdelayed frames, which gets
+the return address from the alternate stack.
+
+The offset of tls::stackptr from TIB.stacktop is determined by analyzing the
+code in _sigbe or sigdelayed.
+
+This can backtrace from _sigbe and from a sighandler through sigdelayed.
+
+Implemented for amd64 and i386
+
+Issues:
+
+1. We should detect if we are in the wrapper after the return address has been
+popped off the alternate stack, and if so, fetch the return address from the
+register it's been popped into.
+
+2. If there are multiple _sigbe or sigdelayed stack frames to be unwound, this
+only unwinds the first one correctly, because we don't unwind the value of the
+alternate stack pointer itself.
+
+This is no worse than currently, when we can't even unwind one of these frame
+correctly, but isn't quite correct.
+
+I guess this could be handled by defining a pseduo-register to track it's value
+as we unwind the stack.
+
+[1] https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;a=blob;f=winsup/cygwin/gendef
+[2] https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;a=blob;f=winsup/cygwin/how-signals-work.txt
+---
+ gdb/amd64-windows-tdep.c | 57 ++++++++++++
+ gdb/i386-cygwin-tdep.c | 28 ++++++
+ gdb/windows-tdep.c | 237 +++++++++++++++++++++++++++++++++++++++++++++++
+ gdb/windows-tdep.h | 21 +++++
+ 4 files changed, 343 insertions(+)
+
+diff --git a/gdb/amd64-windows-tdep.c b/gdb/amd64-windows-tdep.c
+index a092298..c9b9d20 100644
+--- a/gdb/amd64-windows-tdep.c
++++ b/gdb/amd64-windows-tdep.c
+@@ -1218,11 +1218,68 @@ amd64_windows_auto_wide_charset (void)
+ return "UTF-16";
+ }
+
++static const struct insn_pattern amd64_sigbe_bytes[] = {
++ /* movq $-8,%r11 */
++ { 0x49, 0xff },
++ { 0xc7, 0xff },
++ { 0xc3, 0xff },
++ { 0xf8, 0xff },
++ { 0xff, 0xff },
++ { 0xff, 0xff },
++ { 0xff, 0xff },
++ /* xaddq %r11,$tls::stackptr(%r10) */
++ { 0x4d, 0xff },
++ { 0x0f, 0xff },
++ { 0xc1, 0xff },
++ { 0x9a, 0xff },
++ { 0x00, 0x00 }, /* 4 bytes for tls::stackptr */
++ { 0x00, 0x00 },
++ { 0x00, 0x00 },
++ { 0x00, 0x00 }
++};
++
++static const struct insn_pattern amd64_sigdelayed_bytes[] = {
++ /* movq $-8,%r11 */
++ { 0x49, 0xff },
++ { 0xc7, 0xff },
++ { 0xc3, 0xff },
++ { 0xf8, 0xff },
++ { 0xff, 0xff },
++ { 0xff, 0xff },
++ { 0xff, 0xff },
++ /* xaddq %r11,$tls::stackptr(%r12) */
++ { 0x4d, 0xff },
++ { 0x0f, 0xff },
++ { 0xc1, 0xff },
++ { 0x9c, 0xff },
++ { 0x24, 0xff },
++ { 0x00, 0x00 }, /* 4 bytes for tls::stackptr */
++ { 0x00, 0x00 },
++ { 0x00, 0x00 },
++ { 0x00, 0x00 }
++};
++
++#define COUNT(x) (sizeof(x)/sizeof(x[0]))
++
++static const struct insn_pattern_sequence amd64_sigbe =
++ {
++ amd64_sigbe_bytes, COUNT(amd64_sigbe_bytes)
++ };
++
++static const struct insn_pattern_sequence amd64_sigdelayed =
++ {
++ amd64_sigdelayed_bytes, COUNT(amd64_sigdelayed_bytes)
++ };
++
+ static void
+ amd64_windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+ {
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
++ cygwin_sigwrapper_frame_unwind_set_sigbe_pattern (&amd64_sigbe);
++ cygwin_sigwrapper_frame_unwind_set_sigdelayed_pattern (&amd64_sigdelayed);
++ frame_unwind_append_unwinder (gdbarch, &cygwin_sigwrapper_frame_unwind);
++
+ /* 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 correcly handled
+diff --git a/gdb/i386-cygwin-tdep.c b/gdb/i386-cygwin-tdep.c
+index 79ff478..4fc4686 100644
+--- a/gdb/i386-cygwin-tdep.c
++++ b/gdb/i386-cygwin-tdep.c
+@@ -26,6 +26,7 @@
+ #include "xml-support.h"
+ #include "gdbcore.h"
+ #include "inferior.h"
++#include "frame-unwind.h"
+
+ /* Core file support. */
+
+@@ -204,11 +205,38 @@ i386_cygwin_auto_wide_charset (void)
+ return "UTF-16";
+ }
+
++static const struct insn_pattern i386_sigbe_bytes[] = {
++ /* movl $-4,%eax */
++ { 0xb8, 0xff },
++ { 0xfc, 0xff },
++ { 0xff, 0xff },
++ { 0xff, 0xff },
++ { 0xff, 0xff },
++ /* xadd %eax,$tls::stackptr(%ebx) */
++ { 0x0f, 0xff },
++ { 0xc1, 0xff },
++ { 0x83, 0xff },
++ { 0x00, 0x00 }, /* 4 bytes for tls::stackptr */
++ { 0x00, 0x00 },
++ { 0x00, 0x00 },
++ { 0x00, 0x00 }
++};
++
++#define COUNT(x) (sizeof(x)/sizeof(x[0]))
++
++static const struct insn_pattern_sequence i386_sigbe =
++ {
++ i386_sigbe_bytes, COUNT(i386_sigbe_bytes)
++ };
++
+ static void
+ i386_cygwin_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+ {
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
++ cygwin_sigwrapper_frame_unwind_set_sigbe_pattern (&i386_sigbe);
++ frame_unwind_append_unwinder (gdbarch, &cygwin_sigwrapper_frame_unwind);
++
+ windows_init_abi (info, gdbarch);
+
+ set_gdbarch_skip_trampoline_code (gdbarch, i386_cygwin_skip_trampoline_code);
+diff --git a/gdb/windows-tdep.c b/gdb/windows-tdep.c
+index dc4e2e4..352df90 100644
+--- a/gdb/windows-tdep.c
++++ b/gdb/windows-tdep.c
+@@ -33,6 +33,7 @@
+ #include "complaints.h"
+ #include "solib.h"
+ #include "solib-target.h"
++#include "frame-unwind.h"
+ #include "gdbcore.h"
+
+ struct cmd_list_element *info_w32_cmdlist;
+@@ -540,3 +541,239 @@ even if their meaning is unknown."),
+ isn't another convenience variable of the same name. */
+ create_internalvar_type_lazy ("_tlb", &tlb_funcs, NULL);
+ }
++
++struct cygwin_sigwrapper_frame_cache
++{
++ CORE_ADDR sp;
++ CORE_ADDR pc;
++ CORE_ADDR prev_pc;
++ int tlsoffset;
++};
++
++/* Return non-zero if the instructions at PC match the series
++ described in PATTERN, or zero otherwise. PATTERN is an array of
++ 'struct insn_pattern' objects, terminated by an entry whose mask is
++ zero.
++
++ When the match is successful, fill INSN[i] with what PATTERN[i]
++ matched. */
++static int
++insns_match_pattern (struct gdbarch *gdbarch, CORE_ADDR pc,
++ const struct insn_pattern *pattern, int length,
++ gdb_byte *insn)
++{
++ int i;
++ CORE_ADDR npc = pc;
++
++ for (i = 0; i < length; i++)
++ {
++ gdb_byte buf;
++ target_read_memory (npc, &buf, 1);
++ insn[i] = buf;
++ if ((insn[i] & pattern[i].mask) == pattern[i].data)
++ npc += 1;
++ else
++ return 0;
++ }
++ return 1;
++}
++
++const struct insn_pattern_sequence *sigbe_pattern;
++const struct insn_pattern_sequence *sigdelayed_pattern;
++
++void cygwin_sigwrapper_frame_unwind_set_sigbe_pattern (
++ const struct insn_pattern_sequence *pattern)
++{
++ sigbe_pattern = pattern;
++}
++
++void cygwin_sigwrapper_frame_unwind_set_sigdelayed_pattern (
++ const struct insn_pattern_sequence *pattern)
++{
++ sigdelayed_pattern = pattern;
++}
++
++static void
++cygwin_sigwrapper_frame_analyze (struct gdbarch *gdbarch, CORE_ADDR start,
++ CORE_ADDR end, int *tlsoffset)
++{
++ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
++ CORE_ADDR addr;
++
++ *tlsoffset = 0;
++
++ for (addr = start; addr < end; addr++)
++ {
++ if (sigbe_pattern)
++ {
++ int len = sigbe_pattern->length;
++ gdb_byte insn[len];
++
++ if (insns_match_pattern (gdbarch, addr, sigbe_pattern->pattern,
++ len, insn))
++ {
++ *tlsoffset = extract_signed_integer (&(insn[len - 4]), 4,
++ byte_order);
++ break;
++ }
++ }
++
++ if (sigdelayed_pattern)
++ {
++ int len = sigdelayed_pattern->length;
++ gdb_byte insn[len];
++
++ if (insns_match_pattern (gdbarch, addr, sigdelayed_pattern->pattern,
++ len, insn))
++ {
++ *tlsoffset = extract_signed_integer (&(insn[len - 4]), 4,
++ byte_order);
++ break;
++ }
++ }
++ }
++
++ /*
++ XXX: Perhaps we should also note the address of the xaddq instruction which
++ pops the RA from the sigstack. If PC is after that, we should look in the
++ appropriate register to get the RA, not on the sigstack.
++ */
++}
++
++/* Fill THIS_CACHE using the cygwin sigwrapper unwinding data
++ for THIS_FRAME. */
++
++static struct cygwin_sigwrapper_frame_cache *
++cygwin_sigwrapper_frame_cache (struct frame_info *this_frame, void **this_cache)
++{
++ struct gdbarch *gdbarch = get_frame_arch (this_frame);
++ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
++ struct cygwin_sigwrapper_frame_cache *cache = *this_cache;
++ ptid_t ptid;
++ CORE_ADDR thread_local_base;
++ CORE_ADDR stacktop;
++ CORE_ADDR signalstackptr;
++ CORE_ADDR ra;
++ const int len = gdbarch_addr_bit (gdbarch)/8;
++ gdb_byte buf[len];
++
++ /* Get current PC and SP. */
++ cache->pc = get_frame_pc (this_frame);
++ get_frame_register (this_frame, gdbarch_sp_regnum(gdbarch), buf);
++ cache->sp = extract_unsigned_integer (buf, len, byte_order);
++
++ /* Get address of top of stack from thread information block */
++ ptid = inferior_ptid;
++ target_get_tib_address (ptid, &thread_local_base);
++
++ read_memory(thread_local_base + len, buf, len);
++ stacktop = extract_unsigned_integer(buf, len, byte_order);
++
++ if (frame_debug)
++ fprintf_unfiltered (gdb_stdlog,
++ "cygwin_sigwrapper_frame_prev_register TEB.stacktop=%s\n",
++ paddress (gdbarch, stacktop ));
++
++ /* Find cygtls, relative to stacktop, and read signalstackptr from cygtls */
++ read_memory(stacktop + cache->tlsoffset, buf, len);
++ signalstackptr = extract_unsigned_integer(buf, len, byte_order);
++
++ if (frame_debug)
++ fprintf_unfiltered (gdb_stdlog,
++ "cygwin_sigwrapper_frame_prev_register sigsp=%s\n",
++ paddress (gdbarch, signalstackptr));
++
++ /* Read return address from signal stack */
++ read_memory (signalstackptr - len, buf, len);
++ cache->prev_pc = extract_unsigned_integer (buf, len, byte_order);
++
++ if (frame_debug)
++ fprintf_unfiltered (gdb_stdlog,
++ "cygwin_sigwrapper_frame_prev_register ra=%s\n",
++ paddress (gdbarch, cache->prev_pc));
++
++ return cache;
++}
++
++static struct value *
++cygwin_sigwrapper_frame_prev_register (struct frame_info *this_frame, void **this_cache,
++ int regnum)
++{
++ struct gdbarch *gdbarch = get_frame_arch (this_frame);
++ struct cygwin_sigwrapper_frame_cache *cache =
++ cygwin_sigwrapper_frame_cache (this_frame, this_cache);
++
++ if (frame_debug)
++ fprintf_unfiltered (gdb_stdlog,
++ "cygwin_sigwrapper_frame_prev_register %s for pc=%s\n",
++ gdbarch_register_name (gdbarch, regnum),
++ paddress (gdbarch, cache->prev_pc));
++
++ if (regnum == gdbarch_pc_regnum (gdbarch))
++ return frame_unwind_got_address (this_frame, regnum, cache->prev_pc);
++
++ return frame_unwind_got_register (this_frame, regnum, regnum);
++}
++
++static void
++cygwin_sigwrapper_frame_this_id (struct frame_info *this_frame, void **this_cache,
++ struct frame_id *this_id)
++{
++ *this_id = frame_id_build_unavailable_stack (get_frame_func (this_frame));
++}
++
++static int
++cygwin_sigwrapper_frame_sniffer (const struct frame_unwind *self,
++ struct frame_info *this_frame,
++ void **this_cache)
++{
++ struct gdbarch *gdbarch = get_frame_arch (this_frame);
++ struct cygwin_sigwrapper_frame_cache* cache;
++ const char *name;
++ int tlsoffset;
++ CORE_ADDR start, end;
++
++ CORE_ADDR pc = get_frame_pc (this_frame);
++ find_pc_partial_function (pc, &name, &start, &end);
++
++ if (!name)
++ return 0;
++
++ if ((strcmp(name, "_sigbe") != 0) && (strcmp(name, "__sigbe") != 0) &&
++ (strcmp(name, "sigdelayed") != 0) && (strcmp(name, "_sigdelayed") != 0))
++ return 0;
++
++ if (frame_debug)
++ fprintf_unfiltered (gdb_stdlog,
++ "cygwin_sigwrapper_frame_sniffer name=%s, start=%s, end=%s\n",
++ name, paddress (gdbarch, start), paddress (gdbarch, end));
++
++ cygwin_sigwrapper_frame_analyze(gdbarch, start, end, &tlsoffset);
++ if (tlsoffset == 0)
++ return 0;
++
++ if (frame_debug)
++ fprintf_unfiltered (gdb_stdlog,
++ "cygwin_sigwrapper_frame_sniffer sigstackptroffset=%x\n",
++ tlsoffset);
++
++ cache = FRAME_OBSTACK_ZALLOC (struct cygwin_sigwrapper_frame_cache);
++ cache->tlsoffset = tlsoffset;
++
++ *this_cache = cache;
++ cygwin_sigwrapper_frame_cache (this_frame, this_cache);
++
++ return 1;
++}
++
++/* Cygwin sigwapper unwinder. */
++
++const struct frame_unwind cygwin_sigwrapper_frame_unwind =
++{
++ NORMAL_FRAME,
++ default_frame_unwind_stop_reason,
++ &cygwin_sigwrapper_frame_this_id,
++ &cygwin_sigwrapper_frame_prev_register,
++ NULL,
++ &cygwin_sigwrapper_frame_sniffer
++};
+diff --git a/gdb/windows-tdep.h b/gdb/windows-tdep.h
+index e1c34c2..b16a64a 100644
+--- a/gdb/windows-tdep.h
++++ b/gdb/windows-tdep.h
+@@ -32,4 +32,25 @@ extern void windows_xfer_shared_library (const char* so_name,
+
+ extern void windows_init_abi (struct gdbarch_info info,
+ struct gdbarch *gdbarch);
++
++extern const struct frame_unwind cygwin_sigwrapper_frame_unwind;
++
++/* An instruction to match. */
++struct insn_pattern
++{
++ gdb_byte data; /* See if it matches this.... */
++ gdb_byte mask; /* ... with this mask. */
++};
++
++struct insn_pattern_sequence
++{
++ const struct insn_pattern *pattern;
++ int length;
++};
++
++extern void cygwin_sigwrapper_frame_unwind_set_sigbe_pattern(
++ const struct insn_pattern_sequence *pattern);
++extern void cygwin_sigwrapper_frame_unwind_set_sigdelayed_pattern(
++ const struct insn_pattern_sequence *pattern);
++
+ #endif
+--
+2.6.2
+
diff --git a/0002-7.8-windows-nat-cygwin.patch.patch b/0002-7.8-windows-nat-cygwin.patch.patch
new file mode 100644
index 0000000..8f14555
--- /dev/null
+++ b/0002-7.8-windows-nat-cygwin.patch.patch
@@ -0,0 +1,139 @@
+From 6ff2426819cc3cfb9cf4a12ed733a580f25ee0e9 Mon Sep 17 00:00:00 2001
+From: Jon Turney <jon.turney@dronecode.org.uk>
+Date: Tue, 12 Jan 2016 22:26:26 +0000
+Subject: [PATCH 2/3] 7.8-windows-nat-cygwin.patch
+
+Remaining parts of 7.8-windows-nat-cygwin.patch not yet upstream.
+
+Signal changes:
+
+* Replace have_saved_context with signal_thread_id throughout, and store the
+thread id in it
+
+* In thread_rec(), only use the signal saved context if we are retrieving the
+context for the correct thread.
+
+* Clear ContextFlags in the signal saved context so we never attempt to restore
+it to the inferior
+
+Since the signal context is the context which will be restored after any signal
+handler has been run, to resume to it skips over the actual signal delivery.
+
+(Unfortunately, this isn't quite right. If GDB decides it needs to single-step
+after continuing by setting FLAG_TRACE_BIT, we must alter the inferior state. So
+we potentially need to have both the signal saved context, and the actual
+context for the thread. Which is not a straightforward change to make.)
+
+Unrelated changes:
+
+* An unclear change for detecting if it's an unexpected Cygwin message. Just
+checking for a leading 'cYg' should be enough?
+
+* Cast DWORD thread_id to int before returning it from get_windows_event.
+(I don't think this is needed. If DWORD->int is a narrowing conversion, we
+have other problems...)
+
+* In one place, clarify that thread_rec()'s second parameter is a bool flag.
+(This should be done everywhere, or not)
+---
+ gdb/windows-nat.c | 28 ++++++++++++++++++----------
+ 1 file changed, 18 insertions(+), 10 deletions(-)
+
+diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
+index 2f674b6..0d145ac 100644
+--- a/gdb/windows-nat.c
++++ b/gdb/windows-nat.c
+@@ -118,8 +118,7 @@ static COORD WINAPI (*GetConsoleFontSize) (HANDLE, DWORD);
+ # define bad_GetModuleFileNameEx bad_GetModuleFileNameExW
+ #endif
+
+-static int have_saved_context; /* True if we've saved context from a
+- cygwin signal. */
++static DWORD signal_thread_id; /* Non-zero if we saved context. */
+ static CONTEXT saved_context; /* Containes the saved context from a
+ cygwin signal. */
+
+@@ -301,7 +300,8 @@ thread_rec (DWORD id, int get_context)
+ {
+ if (!th->suspended && get_context)
+ {
+- if (get_context > 0 && id != current_event.dwThreadId)
++ if (get_context > 0 && id != current_event.dwThreadId
++ && id != signal_thread_id)
+ {
+ if (SuspendThread (th->h) == (DWORD) -1)
+ {
+@@ -436,7 +436,7 @@ do_windows_fetch_inferior_registers (struct regcache *regcache, int r)
+ if (current_thread->reload_context)
+ {
+ #ifdef __CYGWIN__
+- if (have_saved_context)
++ if (signal_thread_id)
+ {
+ /* Lie about where the program actually is stopped since
+ cygwin has informed us that we should consider the signal
+@@ -444,7 +444,7 @@ do_windows_fetch_inferior_registers (struct regcache *regcache, int r)
+ "saved_context. */
+ memcpy (&current_thread->context, &saved_context,
+ __COPY_CONTEXT_SIZE);
+- have_saved_context = 0;
++ signal_thread_id = 0;
+ }
+ else
+ #endif
+@@ -819,7 +819,11 @@ handle_output_debug_string (struct target_waitstatus *ourstatus)
+ else if (!startswith (s, _CYGWIN_SIGNAL_STRING))
+ {
+ #ifdef __CYGWIN__
+- if (!startswith (s, "cYg"))
++ /* This looks like this is supposed to ignore all other expected Cygwin
++ debug output (e.g. handle and strace output), but isn't quite right as
++ strace output might be indicated by any 8 digit hex address. */
++ if (!startswith (s, "cYg") || (strncmp (s + 3, "FFFFFFFF", 8) != 0
++ && strncmp (s + 3, "std", 3) != 0))
+ #endif
+ {
+ char *p = strchr (s, '\0');
+@@ -858,7 +862,12 @@ handle_output_debug_string (struct target_waitstatus *ourstatus)
+ &saved_context,
+ __COPY_CONTEXT_SIZE, &n)
+ && n == __COPY_CONTEXT_SIZE)
+- have_saved_context = 1;
++ {
++ signal_thread_id = retval;
++ saved_context.ContextFlags = 0; /* Don't attempt to call SetContext */
++ }
++ else
++ retval = 0;
+ }
+ }
+ #endif
+@@ -1343,7 +1352,6 @@ get_windows_debug_event (struct target_ops *ops,
+ event_code = current_event.dwDebugEventCode;
+ ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
+ th = NULL;
+- have_saved_context = 0;
+
+ switch (event_code)
+ {
+@@ -1521,7 +1529,7 @@ get_windows_debug_event (struct target_ops *ops,
+ }
+
+ out:
+- return thread_id;
++ return (int) thread_id;
+ }
+
+ /* Wait for interesting events to occur in the target process. */
+@@ -2467,7 +2475,7 @@ windows_get_tib_address (struct target_ops *self,
+ {
+ windows_thread_info *th;
+
+- th = thread_rec (ptid_get_tid (ptid), 0);
++ th = thread_rec (ptid_get_tid (ptid), FALSE);
+ if (th == NULL)
+ return 0;
+
+--
+2.6.2
+
diff --git a/0003-Better-handling-for-realpath-failures-in-windows_mak.patch b/0003-Better-handling-for-realpath-failures-in-windows_mak.patch
new file mode 100644
index 0000000..4a74ce1
--- /dev/null
+++ b/0003-Better-handling-for-realpath-failures-in-windows_mak.patch
@@ -0,0 +1,52 @@
+From cc58015ddf527b4344183c4c3e2dcc4333457011 Mon Sep 17 00:00:00 2001
+From: Jon Turney <jon.turney@dronecode.org.uk>
+Date: Wed, 13 Jan 2016 18:27:48 +0000
+Subject: [PATCH 3/3] Better handling for realpath() failures in
+ windows_make_so() on Cygwin
+
+Fix a memory leak which would occur in the case when the result of realpath() is
+greater than or equal to SO_NAME_MAX_PATH_SIZE.
+
+Distinguish between realpath() failing (returning NULL), and returning a path
+longer than SO_NAME_MAX_PATH_SIZE
+
+Warn rather than stopping with an error in those cases.
+
+Original patch from Tim Chick. Memory leak fix by Corinna Vinschen.
+---
+ gdb/windows-nat.c | 15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
+index 0d145ac..2e26286 100644
+--- a/gdb/windows-nat.c
++++ b/gdb/windows-nat.c
+@@ -619,13 +619,22 @@ windows_make_so (const char *name, LPVOID load_addr)
+ else
+ {
+ char *rname = realpath (name, NULL);
+- if (rname && strlen (rname) < SO_NAME_MAX_PATH_SIZE)
++ if (rname)
+ {
+- strcpy (so->so_name, rname);
++ if (strlen (rname) < SO_NAME_MAX_PATH_SIZE)
++ strcpy (so->so_name, rname);
++ else
++ {
++ warning (_("dll path \"%s\" too long"), rname);
++ strcpy (so->so_name, so->so_original_name);
++ }
+ free (rname);
+ }
+ else
+- error (_("dll path too long"));
++ {
++ warning (_("dll path for \"%s\" can not be evaluated"), name);
++ strcpy (so->so_name, so->so_original_name);
++ }
+ }
+ /* Record cygwin1.dll .text start/end. */
+ p = strchr (so->so_name, '\0') - (sizeof ("/cygwin1.dll") - 1);
+--
+2.6.2
+
diff --git a/7.8-symtab-cygwin.patch b/7.8-symtab-cygwin.patch
new file mode 100644
index 0000000..6af82ba
--- /dev/null
+++ b/7.8-symtab-cygwin.patch
@@ -0,0 +1,44 @@
+See https://sourceware.org/ml/gdb-patches/2002-03/msg00557.html
+
+--- origsrc/gdb-7.8/gdb/symtab.c 2014-07-29 14:37:42.000000000 +0200
++++ src/gdb-7.8/gdb/symtab.c 2014-08-04 12:04:47.173108524 +0200
+@@ -641,6 +641,39 @@ symbol_find_demangled_name (struct gener
+ {
+ char *demangled = NULL;
+
++ /* 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 (1)
++ {
++ char *arg_byte_suffix = strchr (mangled, '@');
++ if (arg_byte_suffix)
++ {
++ int prefix_len = arg_byte_suffix - mangled;
++ char *mangled_sans_suffix = 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->language = language_auto;
+
diff --git a/cygwin-gdb.spec b/cygwin-gdb.spec
index 9d1ba5f..407e3dd 100644
--- a/cygwin-gdb.spec
+++ b/cygwin-gdb.spec
@@ -1,12 +1,17 @@
Name: cygwin-gdb
-Version: 7.9.1
+Version: 7.10.1
Release: 1%{?dist}
Summary: Cygwin GNU debugger
License: GPLv3+
Group: Development/Utilities
URL: http://www.gnu.org/software/gdb/
+
Source0: ftp://sourceware.org/pub/gdb/releases/gdb-%{version}.tar.xz
+Patch0: 7.8-symtab-cygwin.patch
+Patch1: 0001-Teach-gdb-how-to-unwind-cygwin-_sigbe-and-sigdelayed.patch
+Patch2: 0002-7.8-windows-nat-cygwin.patch.patch
+Patch3: 0003-Better-handling-for-realpath-failures-in-windows_mak.patch
BuildRequires: expat-devel
BuildRequires: ncurses-devel
@@ -52,6 +57,10 @@ using a gdbserver(1) instance on a Cygwin machine to run the executable.
%prep
%setup -q -n gdb-%{version}
+%patch0 -p2
+%patch1 -p1
+%patch2 -p1
+%patch3 -p1
%build
@@ -127,6 +136,9 @@ rm -f $RPM_BUILD_ROOT%{_mandir}/man1/*gdbserver*
%changelog
+* Mon Sep 12 2016 Yaakov Selkowitz <yselkowi@redhat.com> - 7.10.1-1
+- new version
+
* Thu Aug 20 2015 Yaakov Selkowitz <yselkowi@redhat.com> - 7.9.1-1
- New version with split support for Cygwin 32- and 64-bit toolchains
diff --git a/sources b/sources
index c93b64d..9cba2ff 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-35374c77a70884eb430c97061053a36e gdb-7.9.1.tar.xz
+39e654460c9cdd80200a29ac020cfe11 gdb-7.10.1.tar.xz