diff -r 4863a5e8f8a3 libgo/go/reflect/makefunc_386.S
--- a/libgo/go/reflect/makefunc_386.S	Wed Dec 11 14:34:28 2013 -0800
+++ b/libgo/go/reflect/makefunc_386.S	Wed Dec 11 15:35:56 2013 -0800
@@ -48,6 +48,15 @@
 	leal	8(%ebp), %eax	/* Set esp field in struct.  */
 	movl	%eax, -24(%ebp)
 
+	/* For MakeFunc functions that call recover.  */
+	movl	4(%ebp), %eax
+	movl	%eax, (%esp)
+#ifdef __PIC__
+	call	__go_makefunc_can_recover@PLT
+#else
+	call	__go_makefunc_can_recover
+#endif
+
 #ifdef __PIC__
 	call	__go_get_closure@PLT
 #else
@@ -65,6 +74,13 @@
 	call	reflect.MakeFuncStubGo
 #endif
 
+	/* MakeFunc functions can no longer call recover.  */
+#ifdef __PIC__
+	call __go_makefunc_returning@PLT
+#else
+	call __go_makefunc_returning
+#endif
+
 	/* Set return registers.  */
 
 	movl	-20(%ebp), %eax
diff -r 4863a5e8f8a3 libgo/go/reflect/makefunc_amd64.S
--- a/libgo/go/reflect/makefunc_amd64.S	Wed Dec 11 14:34:28 2013 -0800
+++ b/libgo/go/reflect/makefunc_amd64.S	Wed Dec 11 15:35:56 2013 -0800
@@ -61,6 +61,14 @@
 	movdqa	%xmm6, 0xa0(%rsp)
 	movdqa	%xmm7, 0xb0(%rsp)
 
+	/* For MakeFunc functions that call recover.  */
+	movq	8(%rbp), %rdi
+#ifdef __PIC__
+	call	__go_makefunc_can_recover@PLT
+#else
+	call	__go_makefunc_can_recover
+#endif
+
 	# Get function type.
 #ifdef __PIC__
 	call	__go_get_closure@PLT
@@ -77,6 +85,13 @@
 	call	reflect.MakeFuncStubGo
 #endif
 
+	/* MakeFunc functions can no longer call recover.  */
+#ifdef __PIC__
+	call __go_makefunc_returning@PLT
+#else
+	call __go_makefunc_returning
+#endif
+
 	# The structure will be updated with any return values.  Load
 	# all possible return registers before returning to the caller.
 
diff -r 4863a5e8f8a3 libgo/runtime/go-defer.c
--- a/libgo/runtime/go-defer.c	Wed Dec 11 14:34:28 2013 -0800
+++ b/libgo/runtime/go-defer.c	Wed Dec 11 15:35:56 2013 -0800
@@ -27,6 +27,7 @@
   n->__pfn = pfn;
   n->__arg = arg;
   n->__retaddr = NULL;
+  n->__makefunc_can_recover = 0;
   g->defer = n;
 }
 
diff -r 4863a5e8f8a3 libgo/runtime/go-defer.h
--- a/libgo/runtime/go-defer.h	Wed Dec 11 14:34:28 2013 -0800
+++ b/libgo/runtime/go-defer.h	Wed Dec 11 15:35:56 2013 -0800
@@ -34,4 +34,10 @@
      set by __go_set_defer_retaddr which is called by the thunks
      created by defer statements.  */
   const void *__retaddr;
+
+  /* Set to true if a function created by reflect.MakeFunc is
+     permitted to recover.  The return address of such a function
+     function will be somewhere in libffi, so __retaddr is not
+     useful.  */
+  _Bool __makefunc_can_recover;
 };
diff -r 4863a5e8f8a3 libgo/runtime/go-recover.c
--- a/libgo/runtime/go-recover.c	Wed Dec 11 14:34:28 2013 -0800
+++ b/libgo/runtime/go-recover.c	Wed Dec 11 15:35:56 2013 -0800
@@ -16,12 +16,14 @@
    __go_can_recover--this is, the thunk.  */
 
 _Bool
-__go_can_recover (const void* retaddr)
+__go_can_recover (const void *retaddr)
 {
   G *g;
   struct __go_defer_stack *d;
   const char* ret;
   const char* dret;
+  Location loc;
+  const byte *name;
 
   g = runtime_g ();
 
@@ -52,7 +54,73 @@
 #endif
 
   dret = (const char *) d->__retaddr;
-  return ret <= dret && ret + 16 >= dret;
+  if (ret <= dret && ret + 16 >= dret)
+    return 1;
+
+  /* If the function calling recover was created by reflect.MakeFunc,
+     then RETADDR will be somewhere in libffi.  Our caller is
+     permitted to recover if it was called from libffi.  */
+  if (!d->__makefunc_can_recover)
+    return 0;
+
+  if (runtime_callers (2, &loc, 1) < 1)
+    return 0;
+
+  /* If we have no function name, then we weren't called by Go code.
+     Guess that we were called by libffi.  */
+  if (loc.function.len == 0)
+    return 1;
+
+  if (loc.function.len < 4)
+    return 0;
+  name = loc.function.str;
+  if (*name == '_')
+    {
+      if (loc.function.len < 5)
+	return 0;
+      ++name;
+    }
+
+  if (name[0] == 'f' && name[1] == 'f' && name[2] == 'i' && name[3] == '_')
+    return 1;
+
+  return 0;
+}
+
+/* This function is called when code is about to enter a function
+   created by reflect.MakeFunc.  It is called by the function stub
+   used by MakeFunc.  If the stub is permitted to call recover, then a
+   real MakeFunc function is permitted to call recover.  */
+
+void
+__go_makefunc_can_recover (const void *retaddr)
+{
+  struct __go_defer_stack *d;
+
+  d = runtime_g ()->defer;
+  if (d != NULL
+      && !d->__makefunc_can_recover
+      && __go_can_recover (retaddr))
+    d->__makefunc_can_recover = 1;
+}
+
+/* This function is called when code is about to exit a function
+   created by reflect.MakeFunc.  It is called by the function stub
+   used by MakeFunc.  It clears the __makefunc_can_recover field.
+   It's OK to always clear this field, because __go_can_recover will
+   only be called by a stub created for a function that calls recover.
+   That stub will not call a function created by reflect.MakeFunc, so
+   by the time we get here any caller higher up on the call stack no
+   longer needs the information.  */
+
+void
+__go_makefunc_returning (void)
+{
+  struct __go_defer_stack *d;
+
+  d = runtime_g ()->defer;
+  if (d != NULL)
+    d->__makefunc_can_recover = 0;
 }
 
 /* This is only called when it is valid for the caller to recover the
diff -r 4863a5e8f8a3 libgo/runtime/proc.c
--- a/libgo/runtime/proc.c	Wed Dec 11 14:34:28 2013 -0800
+++ b/libgo/runtime/proc.c	Wed Dec 11 15:35:56 2013 -0800
@@ -539,6 +539,7 @@
 	d.__arg = (void*)-1;
 	d.__panic = g->panic;
 	d.__retaddr = nil;
+	d.__makefunc_can_recover = 0;
 	d.__frame = &frame;
 	g->defer = &d;
 
