Patchwork [3/5] Avoid undefined behavior in Guile exception handling

login
register
mail settings
Submitter Tom Tromey
Date April 25, 2019, 4:52 p.m.
Message ID <20190425165256.31226-4-tromey@adacore.com>
Download mbox | patch
Permalink /patch/32414/
State New
Headers show

Comments

Tom Tromey - April 25, 2019, 4:52 p.m.
The Guile code will longjmp (via scm_throw) when an object requiring
destruction is on the stack.  This is undefined behavior.

This changes this code to run any destructors in inner scopes, and to
pass a POD to gdbscm_throw_gdb_exception.

gdb/ChangeLog
2019-04-25  Tom Tromey  <tromey@adacore.com>

	* guile/scm-exception.c (gdbscm_scm_from_gdb_exception)
	(gdbscm_throw_gdb_exception): Take a gdbscm_gdb_exception.
	* guile/scm-block.c, guile/scm-breakpoint.c, guile/scm-cmd.c,
	guile/scm-disasm.c, guile/scm-frame.c, guile/scm-lazy-string.c,
	guile/scm-math.c, guile/scm-param.c, guile/scm-ports.c,
	guile/scm-symbol.c, guile/scm-symtab.c, guile/scm-type.c,
	guile/scm-value.c: Use unpack.
	* guile/guile-internal.h (gdbscm_scm_from_gdb_exception): Take a
	gdbscm_gdb_exception.
	(gdbscm_throw_gdb_exception): Likewise.
	(struct gdbscm_gdb_exception): New.
	(unpack): New function.
	(gdbscm_wrap): Use unpack.
---
 gdb/ChangeLog               | 16 ++++++++
 gdb/guile/guile-internal.h  | 38 +++++++++++++++++--
 gdb/guile/scm-block.c       |  4 +-
 gdb/guile/scm-breakpoint.c  | 33 ++++++++++++-----
 gdb/guile/scm-cmd.c         |  4 +-
 gdb/guile/scm-disasm.c      |  4 +-
 gdb/guile/scm-exception.c   | 10 +++--
 gdb/guile/scm-frame.c       | 73 ++++++++++++++++++++++++++-----------
 gdb/guile/scm-lazy-string.c |  2 +-
 gdb/guile/scm-math.c        |  2 +-
 gdb/guile/scm-param.c       |  8 ++--
 gdb/guile/scm-ports.c       |  4 +-
 gdb/guile/scm-symbol.c      | 20 ++++++----
 gdb/guile/scm-symtab.c      |  4 +-
 gdb/guile/scm-type.c        | 42 +++++++++++++++------
 gdb/guile/scm-value.c       | 53 +++++++++++++++++++--------
 16 files changed, 235 insertions(+), 82 deletions(-)

Patch

diff --git a/gdb/guile/guile-internal.h b/gdb/guile/guile-internal.h
index a3e02abe41b..d316d1ce353 100644
--- a/gdb/guile/guile-internal.h
+++ b/gdb/guile/guile-internal.h
@@ -353,9 +353,11 @@  extern void gdbscm_misc_error (const char *subr, int arg_pos,
 
 extern void gdbscm_throw (SCM exception) ATTRIBUTE_NORETURN;
 
-extern SCM gdbscm_scm_from_gdb_exception (struct gdb_exception exception);
+struct gdbscm_gdb_exception;
+extern SCM gdbscm_scm_from_gdb_exception
+  (const struct gdbscm_gdb_exception &exception);
 
-extern void gdbscm_throw_gdb_exception (struct gdb_exception exception)
+extern void gdbscm_throw_gdb_exception (struct gdbscm_gdb_exception exception)
   ATTRIBUTE_NORETURN;
 
 extern void gdbscm_print_exception_with_stack (SCM port, SCM stack,
@@ -650,6 +652,33 @@  extern void gdbscm_initialize_values (void);
    with a TRY/CATCH, because the dtors won't otherwise be run when a
    Guile exceptions is thrown.  */
 
+/* This is a destructor-less clone of gdb_exception.  */
+
+struct gdbscm_gdb_exception
+{
+  enum return_reason reason;
+  enum errors error;
+  /* The message is xmalloc'd.  */
+  char *message;
+};
+
+/* Return a gdbscm_gdb_exception representing EXC.  */
+
+inline struct gdbscm_gdb_exception
+unpack (const gdb_exception &exc)
+{
+  struct gdbscm_gdb_exception result;
+  result.reason = exc.reason;
+  result.error = exc.error;
+  if (exc.message == nullptr)
+    result.message = nullptr;
+  else
+    result.message = xstrdup (exc.message->c_str ());
+  /* The message should be NULL iff the reason is zero.  */
+  gdb_assert ((result.reason == 0) == (result.message == nullptr));
+  return result;
+}
+
 /* Use this after a TRY/CATCH to throw the appropriate Scheme
    exception if a GDB error occurred.  */
 
@@ -676,6 +705,7 @@  SCM
 gdbscm_wrap (Function &&func, Args &&... args)
 {
   SCM result = SCM_BOOL_F;
+  struct gdbscm_gdb_exception exc {};
 
   try
     {
@@ -683,9 +713,11 @@  gdbscm_wrap (Function &&func, Args &&... args)
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
+
   if (gdbscm_is_exception (result))
     gdbscm_throw (result);
 
diff --git a/gdb/guile/scm-block.c b/gdb/guile/scm-block.c
index 2114ca1f199..3a78465f9e2 100644
--- a/gdb/guile/scm-block.c
+++ b/gdb/guile/scm-block.c
@@ -680,6 +680,7 @@  gdbscm_lookup_block (SCM pc_scm)
 
   gdbscm_parse_function_args (FUNC_NAME, SCM_ARG1, NULL, "U", pc_scm, &pc);
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       cust = find_pc_compunit_symtab (pc);
@@ -689,9 +690,10 @@  gdbscm_lookup_block (SCM pc_scm)
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   if (cust == NULL || COMPUNIT_OBJFILE (cust) == NULL)
     {
       gdbscm_out_of_range_error (FUNC_NAME, SCM_ARG1, pc_scm,
diff --git a/gdb/guile/scm-breakpoint.c b/gdb/guile/scm-breakpoint.c
index f86c26390c4..29ab859e07b 100644
--- a/gdb/guile/scm-breakpoint.c
+++ b/gdb/guile/scm-breakpoint.c
@@ -411,7 +411,7 @@  gdbscm_register_breakpoint_x (SCM self)
 {
   breakpoint_smob *bp_smob
     = bpscm_get_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
-  struct gdb_exception except;
+  struct gdbscm_gdb_exception except {};
   const char *location, *copy;
 
   /* We only support registering breakpoints created with make-breakpoint.  */
@@ -467,7 +467,7 @@  gdbscm_register_breakpoint_x (SCM self)
     }
   catch (const gdb_exception &ex)
     {
-      except = ex;
+      except = unpack (ex);
     }
 
   /* Ensure this gets reset, even if there's an error.  */
@@ -489,15 +489,17 @@  gdbscm_delete_breakpoint_x (SCM self)
   breakpoint_smob *bp_smob
     = bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       delete_breakpoint (bp_smob->bp);
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   return SCM_UNSPECIFIED;
 }
 
@@ -586,6 +588,7 @@  gdbscm_set_breakpoint_enabled_x (SCM self, SCM newvalue)
   SCM_ASSERT_TYPE (gdbscm_is_bool (newvalue), newvalue, SCM_ARG2, FUNC_NAME,
 		   _("boolean"));
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       if (gdbscm_is_true (newvalue))
@@ -595,9 +598,10 @@  gdbscm_set_breakpoint_enabled_x (SCM self, SCM newvalue)
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   return SCM_UNSPECIFIED;
 }
 
@@ -623,15 +627,17 @@  gdbscm_set_breakpoint_silent_x (SCM self, SCM newvalue)
   SCM_ASSERT_TYPE (gdbscm_is_bool (newvalue), newvalue, SCM_ARG2, FUNC_NAME,
 		   _("boolean"));
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       breakpoint_set_silent (bp_smob->bp, gdbscm_is_true (newvalue));
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   return SCM_UNSPECIFIED;
 }
 
@@ -663,15 +669,17 @@  gdbscm_set_breakpoint_ignore_count_x (SCM self, SCM newvalue)
   if (value < 0)
     value = 0;
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       set_ignore_count (bp_smob->number, (int) value, 0);
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   return SCM_UNSPECIFIED;
 }
 
@@ -783,15 +791,17 @@  gdbscm_set_breakpoint_task_x (SCM self, SCM newvalue)
     {
       id = scm_to_long (newvalue);
 
+      struct gdbscm_gdb_exception exc {};
       try
 	{
 	  valid_id = valid_task_id (id);
 	}
       catch (const gdb_exception &except)
 	{
-	  GDBSCM_HANDLE_GDB_EXCEPTION (except);
+	  exc = unpack (except);
 	}
 
+      GDBSCM_HANDLE_GDB_EXCEPTION (exc);
       if (! valid_id)
 	{
 	  gdbscm_out_of_range_error (FUNC_NAME, SCM_ARG2, newvalue,
@@ -803,15 +813,17 @@  gdbscm_set_breakpoint_task_x (SCM self, SCM newvalue)
   else
     SCM_ASSERT_TYPE (0, newvalue, SCM_ARG2, FUNC_NAME, _("integer or #f"));
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       breakpoint_set_task (bp_smob->bp, id);
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   return SCM_UNSPECIFIED;
 }
 
@@ -968,17 +980,18 @@  gdbscm_breakpoint_commands (SCM self)
   string_file buf;
 
   current_uiout->redirect (&buf);
+  struct gdbscm_gdb_exception exc {};
   try
     {
       print_command_lines (current_uiout, breakpoint_commands (bp), 0);
     }
   catch (const gdb_exception &except)
     {
-      current_uiout->redirect (NULL);
-      gdbscm_throw_gdb_exception (except);
+      exc = unpack (except);
     }
 
   current_uiout->redirect (NULL);
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   result = gdbscm_scm_from_c_string (buf.c_str ());
 
   return result;
diff --git a/gdb/guile/scm-cmd.c b/gdb/guile/scm-cmd.c
index 38db7f5c71f..0a9cd44a17a 100644
--- a/gdb/guile/scm-cmd.c
+++ b/gdb/guile/scm-cmd.c
@@ -758,6 +758,7 @@  gdbscm_register_command_x (SCM self)
   c_smob->cmd_name = gdbscm_gc_xstrdup (cmd_name);
   xfree (cmd_name);
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       if (c_smob->is_prefix)
@@ -778,8 +779,9 @@  gdbscm_register_command_x (SCM self)
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
 
   /* Note: At this point the command exists in gdb.
      So no more errors after this point.  */
diff --git a/gdb/guile/scm-disasm.c b/gdb/guile/scm-disasm.c
index d673a1eb90a..86129773931 100644
--- a/gdb/guile/scm-disasm.c
+++ b/gdb/guile/scm-disasm.c
@@ -247,6 +247,7 @@  gdbscm_arch_disassemble (SCM self, SCM start_scm, SCM rest)
       int insn_len = 0;
       string_file buf;
 
+      struct gdbscm_gdb_exception exc {};
       try
 	{
 	  if (using_port)
@@ -259,9 +260,10 @@  gdbscm_arch_disassemble (SCM self, SCM start_scm, SCM rest)
 	}
       catch (const gdb_exception &except)
 	{
-	  GDBSCM_HANDLE_GDB_EXCEPTION (except);
+	  exc = unpack (except);
 	}
 
+      GDBSCM_HANDLE_GDB_EXCEPTION (exc);
       result = scm_cons (dascm_make_insn (pc, buf.c_str (), insn_len),
 			 result);
 
diff --git a/gdb/guile/scm-exception.c b/gdb/guile/scm-exception.c
index 44cd7b35750..be24b8ac9d0 100644
--- a/gdb/guile/scm-exception.c
+++ b/gdb/guile/scm-exception.c
@@ -428,7 +428,7 @@  gdbscm_throw (SCM exception)
 /* Convert a GDB exception to a <gdb:exception> object.  */
 
 SCM
-gdbscm_scm_from_gdb_exception (struct gdb_exception exception)
+gdbscm_scm_from_gdb_exception (const struct gdbscm_gdb_exception &exception)
 {
   SCM key;
 
@@ -446,7 +446,7 @@  gdbscm_scm_from_gdb_exception (struct gdb_exception exception)
 
   return gdbscm_make_error (key, NULL, "~A",
 			    scm_list_1 (gdbscm_scm_from_c_string
-					(exception.what ())),
+					(exception.message)),
 			    SCM_BOOL_F);
 }
 
@@ -454,9 +454,11 @@  gdbscm_scm_from_gdb_exception (struct gdb_exception exception)
    This function does not return.  */
 
 void
-gdbscm_throw_gdb_exception (struct gdb_exception exception)
+gdbscm_throw_gdb_exception (struct gdbscm_gdb_exception exception)
 {
-  gdbscm_throw (gdbscm_scm_from_gdb_exception (exception));
+  SCM scm_exception = gdbscm_scm_from_gdb_exception (exception);
+  xfree (exception.message);
+  gdbscm_throw (scm_exception);
 }
 
 /* Print the error message portion of an exception.
diff --git a/gdb/guile/scm-frame.c b/gdb/guile/scm-frame.c
index f3795f83f72..fc7c7bff32a 100644
--- a/gdb/guile/scm-frame.c
+++ b/gdb/guile/scm-frame.c
@@ -250,7 +250,7 @@  frscm_scm_from_frame (struct frame_info *frame, struct inferior *inferior)
     }
   catch (const gdb_exception &except)
     {
-      return gdbscm_scm_from_gdb_exception (except);
+      return gdbscm_scm_from_gdb_exception (unpack (except));
     }
 
   f_scm = frscm_make_frame_smob ();
@@ -396,15 +396,17 @@  gdbscm_frame_valid_p (SCM self)
 
   f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       frame = frscm_frame_smob_to_frame (f_smob);
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   return scm_from_bool (frame != NULL);
 }
 
@@ -423,6 +425,7 @@  gdbscm_frame_name (SCM self)
 
   f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       frame = frscm_frame_smob_to_frame (f_smob);
@@ -431,9 +434,10 @@  gdbscm_frame_name (SCM self)
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   if (frame == NULL)
     {
       gdbscm_invalid_object_error (FUNC_NAME, SCM_ARG1, self,
@@ -460,6 +464,7 @@  gdbscm_frame_type (SCM self)
 
   f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       frame = frscm_frame_smob_to_frame (f_smob);
@@ -468,9 +473,10 @@  gdbscm_frame_type (SCM self)
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   if (frame == NULL)
     {
       gdbscm_invalid_object_error (FUNC_NAME, SCM_ARG1, self,
@@ -491,15 +497,17 @@  gdbscm_frame_arch (SCM self)
 
   f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       frame = frscm_frame_smob_to_frame (f_smob);
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   if (frame == NULL)
     {
       gdbscm_invalid_object_error (FUNC_NAME, SCM_ARG1, self,
@@ -521,15 +529,17 @@  gdbscm_frame_unwind_stop_reason (SCM self)
 
   f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       frame = frscm_frame_smob_to_frame (f_smob);
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   if (frame == NULL)
     {
       gdbscm_invalid_object_error (FUNC_NAME, SCM_ARG1, self,
@@ -553,6 +563,7 @@  gdbscm_frame_pc (SCM self)
 
   f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       frame = frscm_frame_smob_to_frame (f_smob);
@@ -561,9 +572,10 @@  gdbscm_frame_pc (SCM self)
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   if (frame == NULL)
     {
       gdbscm_invalid_object_error (FUNC_NAME, SCM_ARG1, self,
@@ -585,6 +597,7 @@  gdbscm_frame_block (SCM self)
 
   f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       frame = frscm_frame_smob_to_frame (f_smob);
@@ -593,9 +606,10 @@  gdbscm_frame_block (SCM self)
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   if (frame == NULL)
     {
       gdbscm_invalid_object_error (FUNC_NAME, SCM_ARG1, self,
@@ -635,6 +649,7 @@  gdbscm_frame_function (SCM self)
 
   f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       frame = frscm_frame_smob_to_frame (f_smob);
@@ -643,9 +658,10 @@  gdbscm_frame_function (SCM self)
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   if (frame == NULL)
     {
       gdbscm_invalid_object_error (FUNC_NAME, SCM_ARG1, self,
@@ -671,6 +687,7 @@  gdbscm_frame_older (SCM self)
 
   f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       frame = frscm_frame_smob_to_frame (f_smob);
@@ -679,9 +696,10 @@  gdbscm_frame_older (SCM self)
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   if (frame == NULL)
     {
       gdbscm_invalid_object_error (FUNC_NAME, SCM_ARG1, self,
@@ -707,6 +725,7 @@  gdbscm_frame_newer (SCM self)
 
   f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       frame = frscm_frame_smob_to_frame (f_smob);
@@ -715,9 +734,10 @@  gdbscm_frame_newer (SCM self)
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   if (frame == NULL)
     {
       gdbscm_invalid_object_error (FUNC_NAME, SCM_ARG1, self,
@@ -742,6 +762,7 @@  gdbscm_frame_sal (SCM self)
 
   f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       frame = frscm_frame_smob_to_frame (f_smob);
@@ -750,9 +771,10 @@  gdbscm_frame_sal (SCM self)
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   if (frame == NULL)
     {
       gdbscm_invalid_object_error (FUNC_NAME, SCM_ARG1, self,
@@ -777,7 +799,7 @@  gdbscm_frame_read_register (SCM self, SCM register_scm)
   gdbscm_parse_function_args (FUNC_NAME, SCM_ARG2, NULL, "s",
 			      register_scm, &register_str);
 
-  struct gdb_exception except;
+  struct gdbscm_gdb_exception except {};
 
   try
     {
@@ -795,7 +817,7 @@  gdbscm_frame_read_register (SCM self, SCM register_scm)
     }
   catch (const gdb_exception &ex)
     {
-      except = ex;
+      except = unpack (ex);
     }
 
   xfree (register_str);
@@ -838,15 +860,17 @@  gdbscm_frame_read_var (SCM self, SCM symbol_scm, SCM rest)
 
   f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       frame = frscm_frame_smob_to_frame (f_smob);
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   if (frame == NULL)
     {
       gdbscm_invalid_object_error (FUNC_NAME, SCM_ARG1, self,
@@ -864,7 +888,7 @@  gdbscm_frame_read_var (SCM self, SCM symbol_scm, SCM rest)
     }
   else if (scm_is_string (symbol_scm))
     {
-      struct gdb_exception except;
+      struct gdbscm_gdb_exception except {};
 
       if (! SCM_UNBNDP (block_scm))
 	{
@@ -896,7 +920,7 @@  gdbscm_frame_read_var (SCM self, SCM symbol_scm, SCM rest)
 	  }
 	catch (const gdb_exception &ex)
 	  {
-	    except = ex;
+	    except = unpack (ex);
 	  }
       }
 
@@ -919,9 +943,10 @@  gdbscm_frame_read_var (SCM self, SCM symbol_scm, SCM rest)
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   return vlscm_scm_from_value (value);
 }
 
@@ -936,6 +961,7 @@  gdbscm_frame_select (SCM self)
 
   f_smob = frscm_get_frame_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       frame = frscm_frame_smob_to_frame (f_smob);
@@ -944,9 +970,10 @@  gdbscm_frame_select (SCM self)
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   if (frame == NULL)
     {
       gdbscm_invalid_object_error (FUNC_NAME, SCM_ARG1, self,
@@ -964,15 +991,17 @@  gdbscm_newest_frame (void)
 {
   struct frame_info *frame = NULL;
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       frame = get_current_frame ();
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   return frscm_scm_from_frame_unsafe (frame, current_inferior ());
 }
 
@@ -984,15 +1013,17 @@  gdbscm_selected_frame (void)
 {
   struct frame_info *frame = NULL;
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       frame = get_selected_frame (_("No frame is currently selected"));
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   return frscm_scm_from_frame_unsafe (frame, current_inferior ());
 }
 
diff --git a/gdb/guile/scm-lazy-string.c b/gdb/guile/scm-lazy-string.c
index 4d69b234bb2..b0bbc827c8f 100644
--- a/gdb/guile/scm-lazy-string.c
+++ b/gdb/guile/scm-lazy-string.c
@@ -338,7 +338,7 @@  lsscm_safe_lazy_string_to_value (SCM string, int arg_pos,
     }
   catch (const gdb_exception &except)
     {
-      *except_scmp = gdbscm_scm_from_gdb_exception (except);
+      *except_scmp = gdbscm_scm_from_gdb_exception (unpack (except));
       return NULL;
     }
 
diff --git a/gdb/guile/scm-math.c b/gdb/guile/scm-math.c
index dc7245ba7b4..35ad4aa6035 100644
--- a/gdb/guile/scm-math.c
+++ b/gdb/guile/scm-math.c
@@ -826,7 +826,7 @@  vlscm_convert_typed_value_from_scheme (const char *func_name,
     }
   catch (const gdb_exception &except)
     {
-      except_scm = gdbscm_scm_from_gdb_exception (except);
+      except_scm = gdbscm_scm_from_gdb_exception (unpack (except));
     }
 
   if (gdbscm_is_true (except_scm))
diff --git a/gdb/guile/scm-param.c b/gdb/guile/scm-param.c
index cc10806d97e..eb5472db6bb 100644
--- a/gdb/guile/scm-param.c
+++ b/gdb/guile/scm-param.c
@@ -1006,6 +1006,7 @@  gdbscm_register_parameter_x (SCM self)
 		_("parameter exists, \"show\" command is already defined"));
     }
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       add_setshow_generic (p_smob->type, p_smob->cmd_class,
@@ -1020,9 +1021,10 @@  gdbscm_register_parameter_x (SCM self)
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   /* Note: At this point the parameter exists in gdb.
      So no more errors after this point.  */
 
@@ -1056,7 +1058,7 @@  gdbscm_parameter_value (SCM self)
       struct cmd_list_element *alias, *prefix, *cmd;
       char *newarg;
       int found = -1;
-      struct gdb_exception except;
+      struct gdbscm_gdb_exception except {};
 
       gdb::unique_xmalloc_ptr<char> name
 	= gdbscm_scm_to_host_string (self, NULL, &except_scm);
@@ -1069,7 +1071,7 @@  gdbscm_parameter_value (SCM self)
 	}
       catch (const gdb_exception &ex)
 	{
-	  except = ex;
+	  except = unpack (ex);
 	}
 
       xfree (newarg);
diff --git a/gdb/guile/scm-ports.c b/gdb/guile/scm-ports.c
index 57d3b18f962..c388a7769ec 100644
--- a/gdb/guile/scm-ports.c
+++ b/gdb/guile/scm-ports.c
@@ -272,6 +272,7 @@  ioscm_write (SCM port, const void *data, size_t size)
   if (scm_is_eq (port, input_port_scm))
     return;
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       if (scm_is_eq (port, error_port_scm))
@@ -281,8 +282,9 @@  ioscm_write (SCM port, const void *data, size_t size)
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
 }
 
 /* Flush gdb's stdout or stderr.  */
diff --git a/gdb/guile/scm-symbol.c b/gdb/guile/scm-symbol.c
index ab39123dff0..0cd6418b14b 100644
--- a/gdb/guile/scm-symbol.c
+++ b/gdb/guile/scm-symbol.c
@@ -486,15 +486,17 @@  gdbscm_symbol_needs_frame_p (SCM self)
   struct symbol *symbol = s_smob->symbol;
   int result = 0;
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       result = symbol_read_needs_frame (symbol);
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   return scm_from_bool (result);
 }
 
@@ -538,6 +540,7 @@  gdbscm_symbol_value (SCM self, SCM rest)
 				 _("cannot get the value of a typedef"));
     }
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       if (f_smob != NULL)
@@ -558,9 +561,10 @@  gdbscm_symbol_value (SCM self, SCM rest)
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   return vlscm_scm_from_value (value);
 }
 
@@ -602,6 +606,7 @@  gdbscm_lookup_symbol (SCM name_scm, SCM rest)
     {
       struct frame_info *selected_frame;
 
+      struct gdbscm_gdb_exception exc {};
       try
 	{
 	  selected_frame = get_selected_frame (_("no frame selected"));
@@ -610,11 +615,12 @@  gdbscm_lookup_symbol (SCM name_scm, SCM rest)
       catch (const gdb_exception &ex)
 	{
 	  xfree (name);
-	  GDBSCM_HANDLE_GDB_EXCEPTION (ex);
+	  exc = unpack (ex);
 	}
+      GDBSCM_HANDLE_GDB_EXCEPTION (exc);
     }
 
-  struct gdb_exception except;
+  struct gdbscm_gdb_exception except {};
   try
     {
       symbol = lookup_symbol (name, block, (domain_enum) domain,
@@ -622,7 +628,7 @@  gdbscm_lookup_symbol (SCM name_scm, SCM rest)
     }
   catch (const gdb_exception &ex)
     {
-      except = ex;
+      except = unpack (ex);
     }
 
   xfree (name);
@@ -646,7 +652,7 @@  gdbscm_lookup_global_symbol (SCM name_scm, SCM rest)
   int domain_arg_pos = -1;
   int domain = VAR_DOMAIN;
   struct symbol *symbol = NULL;
-  struct gdb_exception except;
+  struct gdbscm_gdb_exception except {};
 
   gdbscm_parse_function_args (FUNC_NAME, SCM_ARG1, keywords, "s#i",
 			      name_scm, &name, rest,
@@ -658,7 +664,7 @@  gdbscm_lookup_global_symbol (SCM name_scm, SCM rest)
     }
   catch (const gdb_exception &ex)
     {
-      except = ex;
+      except = unpack (ex);
     }
 
   xfree (name);
diff --git a/gdb/guile/scm-symtab.c b/gdb/guile/scm-symtab.c
index 60ed7072556..0be09ab66c2 100644
--- a/gdb/guile/scm-symtab.c
+++ b/gdb/guile/scm-symtab.c
@@ -591,6 +591,7 @@  gdbscm_find_pc_line (SCM pc_scm)
 
   gdbscm_parse_function_args (FUNC_NAME, SCM_ARG1, NULL, "U", pc_scm, &pc_ull);
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       CORE_ADDR pc = (CORE_ADDR) pc_ull;
@@ -599,9 +600,10 @@  gdbscm_find_pc_line (SCM pc_scm)
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   return stscm_scm_from_sal (sal);
 }
 
diff --git a/gdb/guile/scm-type.c b/gdb/guile/scm-type.c
index 8f47ef68cc1..d326044d1e9 100644
--- a/gdb/guile/scm-type.c
+++ b/gdb/guile/scm-type.c
@@ -105,6 +105,7 @@  tyscm_type_smob_type (type_smob *t_smob)
 static std::string
 tyscm_type_name (struct type *type)
 {
+  SCM excp;
   try
     {
       string_file stb;
@@ -114,11 +115,10 @@  tyscm_type_name (struct type *type)
     }
   catch (const gdb_exception &except)
     {
-      SCM excp = gdbscm_scm_from_gdb_exception (except);
-      gdbscm_throw (excp);
+      excp = gdbscm_scm_from_gdb_exception (unpack (except));
     }
 
-  gdb_assert_not_reached ("no way to get here");
+  gdbscm_throw (excp);
 }
 
 /* Administrivia for type smobs.  */
@@ -234,15 +234,17 @@  tyscm_equal_p_type_smob (SCM type1_scm, SCM type2_scm)
   type1 = type1_smob->type;
   type2 = type2_smob->type;
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       result = types_deeply_equal (type1, type2);
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   return scm_from_bool (result);
 }
 
@@ -650,15 +652,17 @@  gdbscm_type_strip_typedefs (SCM self)
     = tyscm_get_type_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
   struct type *type = t_smob->type;
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       type = check_typedef (type);
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   return tyscm_scm_from_type (type);
 }
 
@@ -671,15 +675,17 @@  tyscm_get_composite (struct type *type)
 
   for (;;)
     {
+      struct gdbscm_gdb_exception exc {};
       try
 	{
 	  type = check_typedef (type);
 	}
       catch (const gdb_exception &except)
 	{
-	  GDBSCM_HANDLE_GDB_EXCEPTION (except);
+	  exc = unpack (except);
 	}
 
+      GDBSCM_HANDLE_GDB_EXCEPTION (exc);
       if (TYPE_CODE (type) != TYPE_CODE_PTR
 	  && TYPE_CODE (type) != TYPE_CODE_REF)
 	break;
@@ -725,6 +731,7 @@  tyscm_array_1 (SCM self, SCM n1_scm, SCM n2_scm, int is_vector,
 				 _("Array length must not be negative"));
     }
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       array = lookup_array_range_type (type, n1, n2);
@@ -733,9 +740,10 @@  tyscm_array_1 (SCM self, SCM n1_scm, SCM n2_scm, int is_vector,
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   return tyscm_scm_from_type (array);
 }
 
@@ -781,15 +789,17 @@  gdbscm_type_pointer (SCM self)
     = tyscm_get_type_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
   struct type *type = t_smob->type;
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       type = lookup_pointer_type (type);
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   return tyscm_scm_from_type (type);
 }
 
@@ -842,15 +852,17 @@  gdbscm_type_reference (SCM self)
     = tyscm_get_type_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
   struct type *type = t_smob->type;
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       type = lookup_lvalue_reference_type (type);
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   return tyscm_scm_from_type (type);
 }
 
@@ -879,15 +891,17 @@  gdbscm_type_const (SCM self)
     = tyscm_get_type_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
   struct type *type = t_smob->type;
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       type = make_cv_type (1, 0, type, NULL);
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   return tyscm_scm_from_type (type);
 }
 
@@ -901,15 +915,17 @@  gdbscm_type_volatile (SCM self)
     = tyscm_get_type_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
   struct type *type = t_smob->type;
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       type = make_cv_type (0, 1, type, NULL);
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   return tyscm_scm_from_type (type);
 }
 
@@ -923,15 +939,17 @@  gdbscm_type_unqualified (SCM self)
     = tyscm_get_type_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
   struct type *type = t_smob->type;
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       type = make_cv_type (0, 0, type, NULL);
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   return tyscm_scm_from_type (type);
 }
 
diff --git a/gdb/guile/scm-value.c b/gdb/guile/scm-value.c
index 00d1c182e72..70e13a8ec52 100644
--- a/gdb/guile/scm-value.c
+++ b/gdb/guile/scm-value.c
@@ -156,6 +156,7 @@  vlscm_print_value_smob (SCM self, SCM port, scm_print_state *pstate)
      instead of writingp.  */
   opts.raw = !!pstate->writingp;
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       string_file stb;
@@ -165,9 +166,10 @@  vlscm_print_value_smob (SCM self, SCM port, scm_print_state *pstate)
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   if (pstate->writingp)
     scm_puts (">", port);
 
@@ -186,15 +188,17 @@  vlscm_equal_p_value_smob (SCM v1, SCM v2)
   const value_smob *v2_smob = (value_smob *) SCM_SMOB_DATA (v2);
   int result = 0;
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       result = value_equal (v1_smob->value, v2_smob->value);
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   return scm_from_bool (result);
 }
 
@@ -493,6 +497,7 @@  gdbscm_value_dynamic_type (SCM self)
   if (! SCM_UNBNDP (v_smob->dynamic_type))
     return v_smob->dynamic_type;
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       scoped_value_mark free_values;
@@ -531,9 +536,10 @@  gdbscm_value_dynamic_type (SCM self)
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   if (type == NULL)
     v_smob->dynamic_type = gdbscm_value_type (self);
   else
@@ -680,15 +686,17 @@  gdbscm_value_call (SCM self, SCM args)
   long args_count;
   struct value **vargs = NULL;
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       ftype = check_typedef (value_type (function));
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   SCM_ASSERT_TYPE (TYPE_CODE (ftype) == TYPE_CODE_FUNC, self,
 		   SCM_ARG1, FUNC_NAME,
 		   _("function (value of TYPE_CODE_FUNC)"));
@@ -746,6 +754,7 @@  gdbscm_value_to_bytevector (SCM self)
 
   type = value_type (value);
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       type = check_typedef (type);
@@ -754,9 +763,10 @@  gdbscm_value_to_bytevector (SCM self)
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   bv = scm_c_make_bytevector (length);
   memcpy (SCM_BYTEVECTOR_CONTENTS (bv), contents, length);
 
@@ -789,15 +799,17 @@  gdbscm_value_to_bool (SCM self)
 
   type = value_type (value);
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       type = check_typedef (type);
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   SCM_ASSERT_TYPE (is_intlike (type, 1), self, SCM_ARG1, FUNC_NAME,
 		   _("integer-like gdb value"));
 
@@ -810,9 +822,10 @@  gdbscm_value_to_bool (SCM self)
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   return scm_from_bool (l != 0);
 }
 
@@ -830,15 +843,17 @@  gdbscm_value_to_integer (SCM self)
 
   type = value_type (value);
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       type = check_typedef (type);
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   SCM_ASSERT_TYPE (is_intlike (type, 1), self, SCM_ARG1, FUNC_NAME,
 		   _("integer-like gdb value"));
 
@@ -851,9 +866,10 @@  gdbscm_value_to_integer (SCM self)
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   if (TYPE_UNSIGNED (type))
     return gdbscm_scm_from_ulongest (l);
   else
@@ -875,15 +891,17 @@  gdbscm_value_to_real (SCM self)
 
   type = value_type (value);
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       type = check_typedef (type);
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   SCM_ASSERT_TYPE (is_intlike (type, 0) || TYPE_CODE (type) == TYPE_CODE_FLT,
 		   self, SCM_ARG1, FUNC_NAME, _("number"));
 
@@ -907,9 +925,10 @@  gdbscm_value_to_real (SCM self)
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   /* TODO: Is there a better way to check if the value fits?  */
   if (!value_equal (value, check))
     gdbscm_out_of_range_error (FUNC_NAME, SCM_ARG1, self,
@@ -992,6 +1011,7 @@  gdbscm_value_to_string (SCM self, SCM rest)
   /* We don't assume anything about the result of scm_port_conversion_strategy.
      From this point on, if errors is not 'errors, use 'substitute.  */
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       gdb::unique_xmalloc_ptr<gdb_byte> buffer;
@@ -1001,8 +1021,9 @@  gdbscm_value_to_string (SCM self, SCM rest)
   catch (const gdb_exception &except)
     {
       xfree (encoding);
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
 
   /* If errors is "error", scm_from_stringn may throw a Scheme exception.
      Make sure we don't leak.  This is done via scm_dynwind_begin, et.al.  */
@@ -1048,7 +1069,7 @@  gdbscm_value_to_lazy_string (SCM self, SCM rest)
   char *encoding = NULL;
   int length = -1;
   SCM result = SCM_BOOL_F; /* -Wall */
-  struct gdb_exception except;
+  struct gdbscm_gdb_exception except {};
 
   /* The sequencing here, as everywhere else, is important.
      We can't have existing cleanups when a Scheme exception is thrown.  */
@@ -1121,7 +1142,7 @@  gdbscm_value_to_lazy_string (SCM self, SCM rest)
     }
   catch (const gdb_exception &ex)
     {
-      except = ex;
+      except = unpack (ex);
     }
 
   xfree (encoding);
@@ -1177,15 +1198,17 @@  gdbscm_value_print (SCM self)
 
   string_file stb;
 
+  struct gdbscm_gdb_exception exc {};
   try
     {
       common_val_print (value, &stb, 0, &opts, current_language);
     }
   catch (const gdb_exception &except)
     {
-      GDBSCM_HANDLE_GDB_EXCEPTION (except);
+      exc = unpack (except);
     }
 
+  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
   /* Use SCM_FAILED_CONVERSION_QUESTION_MARK to ensure this doesn't
      throw an error if the encoding fails.
      IWBN to use scm_take_locale_string here, but we'd have to temporarily