RFA: add debug hook to unwinder

Tom Tromey tromey@redhat.com
Thu Apr 9 23:26:00 GMT 2009


This patch adds a debugging hook to the dwarf unwinder.

The basic problem is that gdb can lose control of the inferior in the
presence of exceptions.  For example, if the user "next"s over a
function call, but that call throws an exception which passes over the
"next"ing frame, gdb will act as if the user typed "continue".  That
is because gdb has no way to intercept the exception as it unwinds the
stack.

I looked at a couple of approaches to fixing this.  The simplest was
to to add a hook to the unwinder, just for gdb.  So, that is what this
patch implements.

This patch does add a cost to all thrown exceptions.  However, I judge
this cost to be small, particularly given the existing cost of a
throw.

I've only updated the dwarf unwinder, but I think the same treatment
could be given to other unwinders.

I have a corresponding gdb patch to make this all work.  I will put
that in sometime after this patch.

I've bootstrapped and regtested this on x86-64 (compile farm).  (But
really this is pointless as the code does nothing until the debugger
sets the new _Unwind_DebugTrigger global.)

I did not document this because I did not see a good place for that.

Ok?

Tom

2009-04-09  Tom Tromey  <tromey@redhat.com>

	* unwind-dw2.c (_Unwind_DebugTrigger): New global.
	(_Unwind_DebugHook): New function.
	(uw_install_context): Call _Unwind_DebugHook.

Index: gcc/unwind-dw2.c
===================================================================
--- gcc/unwind-dw2.c	(revision 145853)
+++ gcc/unwind-dw2.c	(working copy)
@@ -1473,18 +1473,36 @@
   context->ra = __builtin_extract_return_addr (outer_ra);
 }
 
+/* This is used to trigger the debugger support in the unwinder.  When
+   non-zero, _Unwind_DebugHook is called during unwinding, just before
+   the unwinder returns to user code.  This is never set by the
+   unwinder; it must be set by the debugger.  */
+int _Unwind_DebugTrigger;
 
+void _Unwind_DebugHook (void *, void *) __attribute__ ((__noinline__));
+
+/* When _Unwind_DebugTrigger is non-zero, this function is called
+   during unwinding.  CFA is the CFA of the target frame.  HANDLER is
+   the PC to which control will be transferred.  */
+void
+_Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
+		   void *handler __attribute__ ((__unused__)))
+{
+}
+
 /* Install TARGET into CURRENT so that we can return to it.  This is a
    macro because __builtin_eh_return must be invoked in the context of
    our caller.  */
 
-#define uw_install_context(CURRENT, TARGET)				 \
-  do									 \
-    {									 \
-      long offset = uw_install_context_1 ((CURRENT), (TARGET));		 \
-      void *handler = __builtin_frob_return_addr ((TARGET)->ra);	 \
-      __builtin_eh_return (offset, handler);				 \
-    }									 \
+#define uw_install_context(CURRENT, TARGET)				\
+  do									\
+    {									\
+      long offset = uw_install_context_1 ((CURRENT), (TARGET));		\
+      void *handler = __builtin_frob_return_addr ((TARGET)->ra);	\
+      if (__builtin_expect (_Unwind_DebugTrigger, 0))			\
+	_Unwind_DebugHook ((TARGET)->cfa, handler);			\
+      __builtin_eh_return (offset, handler);				\
+    }									\
   while (0)
 
 static long



More information about the Gcc-patches mailing list