* [PATCH 2/5] Move cleanups.[ch] to common
2014-08-18 8:47 [PATCH 0/5] Make gdbserver use exceptions and cleanups Gary Benson
@ 2014-08-18 8:47 ` Gary Benson
2014-08-20 16:47 ` Pedro Alves
` (2 more replies)
2014-08-18 8:47 ` [PATCH 1/5] Move internal_{,v}warning to common/errors.[ch] Gary Benson
` (4 subsequent siblings)
5 siblings, 3 replies; 14+ messages in thread
From: Gary Benson @ 2014-08-18 8:47 UTC (permalink / raw)
To: gdb-patches
This commit moves cleanups.[ch] into gdb/common/. The only change to
the content of the files is that cleanups.c's include list was altered
to match its new location.
gdb/
2014-08-18 Gary Benson <gbenson@redhat.com>
* cleanups.h: Moved to...
* common/cleanups.h: New file.
* cleanups.c: Moved to...
* common/cleanups.c: New file.
* Makefile.in (SFILES): Replace cleanups.c with common/cleanups.c.
(HFILES_NO_SRCDIR): Replace cleanups.h with common/cleanups.h.
(cleanups.o): New rule.
gdb/gdbserver/
2014-08-18 Gary Benson <gbenson@redhat.com>
* Makefile.in (SFILES): Add common/cleanups.c.
(OBS): cleanups.o.
(cleanups.o): New rule.
---
gdb/ChangeLog | 10 ++
gdb/Makefile.in | 10 ++-
gdb/cleanups.c | 296 --------------------------------------------
gdb/cleanups.h | 69 -----------
gdb/common/cleanups.c | 297 +++++++++++++++++++++++++++++++++++++++++++++
gdb/common/cleanups.h | 69 +++++++++++
gdb/gdbserver/ChangeLog | 6 +
gdb/gdbserver/Makefile.in | 7 +-
8 files changed, 395 insertions(+), 369 deletions(-)
delete mode 100644 gdb/cleanups.c
delete mode 100644 gdb/cleanups.h
create mode 100644 gdb/common/cleanups.c
create mode 100644 gdb/common/cleanups.h
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index e68798d..1840ce7 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -794,7 +794,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
breakpoint.c break-catch-sig.c break-catch-throw.c \
build-id.c buildsym.c \
c-exp.y c-lang.c c-typeprint.c c-valprint.c c-varobj.c \
- charset.c cleanups.c cli-out.c coffread.c coff-pe-read.c \
+ charset.c common/cleanups.c cli-out.c coffread.c coff-pe-read.c \
complaints.c completer.c continuations.c corefile.c corelow.c \
cp-abi.c cp-support.c cp-namespace.c cp-valprint.c \
d-exp.y d-lang.c d-support.c d-valprint.c \
@@ -885,7 +885,7 @@ objfiles.h common/vec.h disasm.h mips-tdep.h ser-base.h \
gdb_curses.h bfd-target.h memattr.h inferior.h ax.h dummy-frame.h \
inflow.h fbsd-nat.h ia64-libunwind-tdep.h completer.h inf-ttrace.h \
solib-target.h gdb_vfork.h alpha-tdep.h dwarf2expr.h \
-m2-lang.h stack.h charset.h cleanups.h addrmap.h command.h solist.h source.h \
+m2-lang.h stack.h charset.h addrmap.h command.h solist.h source.h \
target.h target-dcache.h prologue-value.h cp-abi.h tui/tui-hooks.h tui/tui.h \
tui/tui-file.h tui/tui-command.h tui/tui-disasm.h tui/tui-wingeneral.h \
tui/tui-windata.h tui/tui-data.h tui/tui-win.h tui/tui-stack.h \
@@ -938,6 +938,8 @@ target/wait.h target/waitstatus.h nat/linux-nat.h nat/linux-waitpid.h \
common/print-utils.h common/rsp-low.h nat/i386-dregs.h x86-linux-nat.h \
i386-linux-nat.h common/common-defs.h common/errors.h common/common-types.h \
common/common-debug.h target/target.h target/symbol.h common/common-regcache.h
+common/common-debug.h target/target.h target/symbol.h common/common-regcache.h \
+common/cleanups.h
# Header files that already have srcdir in them, or which are in objdir.
@@ -2154,6 +2156,10 @@ common-debug.o: ${srcdir}/common/common-debug.c
$(COMPILE) $(srcdir)/common/common-debug.c
$(POSTCOMPILE)
+cleanups.o: ${srcdir}/common/cleanups.c
+ $(COMPILE) $(srcdir)/common/cleanups.c
+ $(POSTCOMPILE)
+
#
# gdb/target/ dependencies
#
diff --git a/gdb/cleanups.c b/gdb/cleanups.c
deleted file mode 100644
index ddf8e5b..0000000
--- a/gdb/cleanups.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/* Cleanup routines for GDB, the GNU debugger.
-
- Copyright (C) 1986-2014 Free Software Foundation, Inc.
-
- This file is part of GDB.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#include "defs.h"
-
-/* The cleanup list records things that have to be undone
- if an error happens (descriptors to be closed, memory to be freed, etc.)
- Each link in the chain records a function to call and an
- argument to give it.
-
- Use make_cleanup to add an element to the cleanup chain.
- Use do_cleanups to do all cleanup actions back to a given
- point in the chain. Use discard_cleanups to remove cleanups
- from the chain back to a given point, not doing them.
-
- If the argument is pointer to allocated memory, then you need
- to additionally set the 'free_arg' member to a function that will
- free that memory. This function will be called both when the cleanup
- is executed and when it's discarded. */
-
-struct cleanup
-{
- struct cleanup *next;
- void (*function) (void *);
- void (*free_arg) (void *);
- void *arg;
-};
-
-/* Used to mark the end of a cleanup chain.
- The value is chosen so that it:
- - is non-NULL so that make_cleanup never returns NULL,
- - causes a segv if dereferenced
- [though this won't catch errors that a value of, say,
- ((struct cleanup *) -1) will]
- - displays as something useful when printed in gdb.
- This is const for a bit of extra robustness.
- It is initialized to coax gcc into putting it into .rodata.
- All fields are initialized to survive -Wextra. */
-static const struct cleanup sentinel_cleanup = { 0, 0, 0, 0 };
-
-/* Handy macro to use when referring to sentinel_cleanup. */
-#define SENTINEL_CLEANUP ((struct cleanup *) &sentinel_cleanup)
-
-/* Chain of cleanup actions established with make_cleanup,
- to be executed if an error happens. */
-static struct cleanup *cleanup_chain = SENTINEL_CLEANUP;
-
-/* Chain of cleanup actions established with make_final_cleanup,
- to be executed when gdb exits. */
-static struct cleanup *final_cleanup_chain = SENTINEL_CLEANUP;
-
-/* Main worker routine to create a cleanup.
- PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
- FUNCTION is the function to call to perform the cleanup.
- ARG is passed to FUNCTION when called.
- FREE_ARG, if non-NULL, is called after the cleanup is performed.
-
- The result is a pointer to the previous chain pointer
- to be passed later to do_cleanups or discard_cleanups. */
-
-static struct cleanup *
-make_my_cleanup2 (struct cleanup **pmy_chain, make_cleanup_ftype *function,
- void *arg, void (*free_arg) (void *))
-{
- struct cleanup *new
- = (struct cleanup *) xmalloc (sizeof (struct cleanup));
- struct cleanup *old_chain = *pmy_chain;
-
- new->next = *pmy_chain;
- new->function = function;
- new->free_arg = free_arg;
- new->arg = arg;
- *pmy_chain = new;
-
- gdb_assert (old_chain != NULL);
- return old_chain;
-}
-
-/* Worker routine to create a cleanup without a destructor.
- PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
- FUNCTION is the function to call to perform the cleanup.
- ARG is passed to FUNCTION when called.
-
- The result is a pointer to the previous chain pointer
- to be passed later to do_cleanups or discard_cleanups. */
-
-static struct cleanup *
-make_my_cleanup (struct cleanup **pmy_chain, make_cleanup_ftype *function,
- void *arg)
-{
- return make_my_cleanup2 (pmy_chain, function, arg, NULL);
-}
-
-/* Add a new cleanup to the cleanup_chain,
- and return the previous chain pointer
- to be passed later to do_cleanups or discard_cleanups.
- Args are FUNCTION to clean up with, and ARG to pass to it. */
-
-struct cleanup *
-make_cleanup (make_cleanup_ftype *function, void *arg)
-{
- return make_my_cleanup (&cleanup_chain, function, arg);
-}
-
-/* Same as make_cleanup except also includes TDOR, a destructor to free ARG.
- DTOR is invoked when the cleanup is performed or when it is discarded. */
-
-struct cleanup *
-make_cleanup_dtor (make_cleanup_ftype *function, void *arg,
- void (*dtor) (void *))
-{
- return make_my_cleanup2 (&cleanup_chain,
- function, arg, dtor);
-}
-
-/* Same as make_cleanup except the cleanup is added to final_cleanup_chain. */
-
-struct cleanup *
-make_final_cleanup (make_cleanup_ftype *function, void *arg)
-{
- return make_my_cleanup (&final_cleanup_chain, function, arg);
-}
-
-/* Worker routine to perform cleanups.
- PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
- OLD_CHAIN is the result of a "make" cleanup routine.
- Cleanups are performed until we get back to the old end of the chain. */
-
-static void
-do_my_cleanups (struct cleanup **pmy_chain,
- struct cleanup *old_chain)
-{
- struct cleanup *ptr;
-
- while ((ptr = *pmy_chain) != old_chain)
- {
- *pmy_chain = ptr->next; /* Do this first in case of recursion. */
- (*ptr->function) (ptr->arg);
- if (ptr->free_arg)
- (*ptr->free_arg) (ptr->arg);
- xfree (ptr);
- }
-}
-
-/* Return a value that can be passed to do_cleanups, do_final_cleanups to
- indicate perform all cleanups. */
-
-struct cleanup *
-all_cleanups (void)
-{
- return SENTINEL_CLEANUP;
-}
-
-/* Discard cleanups and do the actions they describe
- until we get back to the point OLD_CHAIN in the cleanup_chain. */
-
-void
-do_cleanups (struct cleanup *old_chain)
-{
- do_my_cleanups (&cleanup_chain, old_chain);
-}
-
-/* Discard cleanups and do the actions they describe
- until we get back to the point OLD_CHAIN in the final_cleanup_chain. */
-
-void
-do_final_cleanups (struct cleanup *old_chain)
-{
- do_my_cleanups (&final_cleanup_chain, old_chain);
-}
-
-/* Main worker routine to discard cleanups.
- PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
- OLD_CHAIN is the result of a "make" cleanup routine.
- Cleanups are discarded until we get back to the old end of the chain. */
-
-static void
-discard_my_cleanups (struct cleanup **pmy_chain,
- struct cleanup *old_chain)
-{
- struct cleanup *ptr;
-
- while ((ptr = *pmy_chain) != old_chain)
- {
- *pmy_chain = ptr->next;
- if (ptr->free_arg)
- (*ptr->free_arg) (ptr->arg);
- xfree (ptr);
- }
-}
-
-/* Discard cleanups, not doing the actions they describe,
- until we get back to the point OLD_CHAIN in the cleanup chain. */
-
-void
-discard_cleanups (struct cleanup *old_chain)
-{
- discard_my_cleanups (&cleanup_chain, old_chain);
-}
-
-/* Discard final cleanups, not doing the actions they describe,
- until we get back to the point OLD_CHAIN in the final cleanup chain. */
-
-void
-discard_final_cleanups (struct cleanup *old_chain)
-{
- discard_my_cleanups (&final_cleanup_chain, old_chain);
-}
-
-/* Main worker routine to save cleanups.
- PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
- The chain is emptied and the result is a pointer to the old chain. */
-
-static struct cleanup *
-save_my_cleanups (struct cleanup **pmy_chain)
-{
- struct cleanup *old_chain = *pmy_chain;
-
- *pmy_chain = SENTINEL_CLEANUP;
- return old_chain;
-}
-
-/* Set the cleanup_chain to 0, and return the old cleanup_chain. */
-
-struct cleanup *
-save_cleanups (void)
-{
- return save_my_cleanups (&cleanup_chain);
-}
-
-/* Set the final_cleanup_chain to 0, and return the old
- final_cleanup_chain. */
-
-struct cleanup *
-save_final_cleanups (void)
-{
- return save_my_cleanups (&final_cleanup_chain);
-}
-
-/* Main worker routine to save cleanups.
- PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
- The chain is restored from CHAIN. */
-
-static void
-restore_my_cleanups (struct cleanup **pmy_chain, struct cleanup *chain)
-{
- if (*pmy_chain != SENTINEL_CLEANUP)
- internal_warning (__FILE__, __LINE__,
- _("restore_my_cleanups has found a stale cleanup"));
-
- *pmy_chain = chain;
-}
-
-/* Restore the cleanup chain from a previously saved chain. */
-
-void
-restore_cleanups (struct cleanup *chain)
-{
- restore_my_cleanups (&cleanup_chain, chain);
-}
-
-/* Restore the final cleanup chain from a previously saved chain. */
-
-void
-restore_final_cleanups (struct cleanup *chain)
-{
- restore_my_cleanups (&final_cleanup_chain, chain);
-}
-
-/* Provide a known function that does nothing, to use as a base for
- a possibly long chain of cleanups. This is useful where we
- use the cleanup chain for handling normal cleanups as well as dealing
- with cleanups that need to be done as a result of a call to error().
- In such cases, we may not be certain where the first cleanup is, unless
- we have a do-nothing one to always use as the base. */
-
-void
-null_cleanup (void *arg)
-{
-}
diff --git a/gdb/cleanups.h b/gdb/cleanups.h
deleted file mode 100644
index aad5add..0000000
--- a/gdb/cleanups.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* Cleanups.
- Copyright (C) 1986-2014 Free Software Foundation, Inc.
-
- This file is part of GDB.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#ifndef CLEANUPS_H
-#define CLEANUPS_H
-
-/* Outside of cleanups.c, this is an opaque type. */
-struct cleanup;
-
-/* NOTE: cagney/2000-03-04: This typedef is strictly for the
- make_cleanup function declarations below. Do not use this typedef
- as a cast when passing functions into the make_cleanup() code.
- Instead either use a bounce function or add a wrapper function.
- Calling a f(char*) function with f(void*) is non-portable. */
-typedef void (make_cleanup_ftype) (void *);
-
-/* Function type for the dtor in make_cleanup_dtor. */
-typedef void (make_cleanup_dtor_ftype) (void *);
-
-/* WARNING: The result of the "make cleanup" routines is not the intuitive
- choice of being a handle on the just-created cleanup. Instead it is an
- opaque handle of the cleanup mechanism and represents all cleanups created
- from that point onwards.
- The result is guaranteed to be non-NULL though. */
-
-extern struct cleanup *make_cleanup (make_cleanup_ftype *, void *);
-
-extern struct cleanup *make_cleanup_dtor (make_cleanup_ftype *, void *,
- make_cleanup_dtor_ftype *);
-
-extern struct cleanup *make_final_cleanup (make_cleanup_ftype *, void *);
-
-/* A special value to pass to do_cleanups and do_final_cleanups
- to tell them to do all cleanups. */
-extern struct cleanup *all_cleanups (void);
-
-extern void do_cleanups (struct cleanup *);
-extern void do_final_cleanups (struct cleanup *);
-
-extern void discard_cleanups (struct cleanup *);
-extern void discard_final_cleanups (struct cleanup *);
-
-extern struct cleanup *save_cleanups (void);
-extern struct cleanup *save_final_cleanups (void);
-
-extern void restore_cleanups (struct cleanup *);
-extern void restore_final_cleanups (struct cleanup *);
-
-/* A no-op cleanup.
- This is useful when you want to establish a known reference point
- to pass to do_cleanups. */
-extern void null_cleanup (void *);
-
-#endif /* CLEANUPS_H */
diff --git a/gdb/common/cleanups.c b/gdb/common/cleanups.c
new file mode 100644
index 0000000..49b643b
--- /dev/null
+++ b/gdb/common/cleanups.c
@@ -0,0 +1,297 @@
+/* Cleanup routines for GDB, the GNU debugger.
+
+ Copyright (C) 1986-2014 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "common-defs.h"
+#include "cleanups.h"
+
+/* The cleanup list records things that have to be undone
+ if an error happens (descriptors to be closed, memory to be freed, etc.)
+ Each link in the chain records a function to call and an
+ argument to give it.
+
+ Use make_cleanup to add an element to the cleanup chain.
+ Use do_cleanups to do all cleanup actions back to a given
+ point in the chain. Use discard_cleanups to remove cleanups
+ from the chain back to a given point, not doing them.
+
+ If the argument is pointer to allocated memory, then you need
+ to additionally set the 'free_arg' member to a function that will
+ free that memory. This function will be called both when the cleanup
+ is executed and when it's discarded. */
+
+struct cleanup
+{
+ struct cleanup *next;
+ void (*function) (void *);
+ void (*free_arg) (void *);
+ void *arg;
+};
+
+/* Used to mark the end of a cleanup chain.
+ The value is chosen so that it:
+ - is non-NULL so that make_cleanup never returns NULL,
+ - causes a segv if dereferenced
+ [though this won't catch errors that a value of, say,
+ ((struct cleanup *) -1) will]
+ - displays as something useful when printed in gdb.
+ This is const for a bit of extra robustness.
+ It is initialized to coax gcc into putting it into .rodata.
+ All fields are initialized to survive -Wextra. */
+static const struct cleanup sentinel_cleanup = { 0, 0, 0, 0 };
+
+/* Handy macro to use when referring to sentinel_cleanup. */
+#define SENTINEL_CLEANUP ((struct cleanup *) &sentinel_cleanup)
+
+/* Chain of cleanup actions established with make_cleanup,
+ to be executed if an error happens. */
+static struct cleanup *cleanup_chain = SENTINEL_CLEANUP;
+
+/* Chain of cleanup actions established with make_final_cleanup,
+ to be executed when gdb exits. */
+static struct cleanup *final_cleanup_chain = SENTINEL_CLEANUP;
+
+/* Main worker routine to create a cleanup.
+ PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
+ FUNCTION is the function to call to perform the cleanup.
+ ARG is passed to FUNCTION when called.
+ FREE_ARG, if non-NULL, is called after the cleanup is performed.
+
+ The result is a pointer to the previous chain pointer
+ to be passed later to do_cleanups or discard_cleanups. */
+
+static struct cleanup *
+make_my_cleanup2 (struct cleanup **pmy_chain, make_cleanup_ftype *function,
+ void *arg, void (*free_arg) (void *))
+{
+ struct cleanup *new
+ = (struct cleanup *) xmalloc (sizeof (struct cleanup));
+ struct cleanup *old_chain = *pmy_chain;
+
+ new->next = *pmy_chain;
+ new->function = function;
+ new->free_arg = free_arg;
+ new->arg = arg;
+ *pmy_chain = new;
+
+ gdb_assert (old_chain != NULL);
+ return old_chain;
+}
+
+/* Worker routine to create a cleanup without a destructor.
+ PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
+ FUNCTION is the function to call to perform the cleanup.
+ ARG is passed to FUNCTION when called.
+
+ The result is a pointer to the previous chain pointer
+ to be passed later to do_cleanups or discard_cleanups. */
+
+static struct cleanup *
+make_my_cleanup (struct cleanup **pmy_chain, make_cleanup_ftype *function,
+ void *arg)
+{
+ return make_my_cleanup2 (pmy_chain, function, arg, NULL);
+}
+
+/* Add a new cleanup to the cleanup_chain,
+ and return the previous chain pointer
+ to be passed later to do_cleanups or discard_cleanups.
+ Args are FUNCTION to clean up with, and ARG to pass to it. */
+
+struct cleanup *
+make_cleanup (make_cleanup_ftype *function, void *arg)
+{
+ return make_my_cleanup (&cleanup_chain, function, arg);
+}
+
+/* Same as make_cleanup except also includes TDOR, a destructor to free ARG.
+ DTOR is invoked when the cleanup is performed or when it is discarded. */
+
+struct cleanup *
+make_cleanup_dtor (make_cleanup_ftype *function, void *arg,
+ void (*dtor) (void *))
+{
+ return make_my_cleanup2 (&cleanup_chain,
+ function, arg, dtor);
+}
+
+/* Same as make_cleanup except the cleanup is added to final_cleanup_chain. */
+
+struct cleanup *
+make_final_cleanup (make_cleanup_ftype *function, void *arg)
+{
+ return make_my_cleanup (&final_cleanup_chain, function, arg);
+}
+
+/* Worker routine to perform cleanups.
+ PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
+ OLD_CHAIN is the result of a "make" cleanup routine.
+ Cleanups are performed until we get back to the old end of the chain. */
+
+static void
+do_my_cleanups (struct cleanup **pmy_chain,
+ struct cleanup *old_chain)
+{
+ struct cleanup *ptr;
+
+ while ((ptr = *pmy_chain) != old_chain)
+ {
+ *pmy_chain = ptr->next; /* Do this first in case of recursion. */
+ (*ptr->function) (ptr->arg);
+ if (ptr->free_arg)
+ (*ptr->free_arg) (ptr->arg);
+ xfree (ptr);
+ }
+}
+
+/* Return a value that can be passed to do_cleanups, do_final_cleanups to
+ indicate perform all cleanups. */
+
+struct cleanup *
+all_cleanups (void)
+{
+ return SENTINEL_CLEANUP;
+}
+
+/* Discard cleanups and do the actions they describe
+ until we get back to the point OLD_CHAIN in the cleanup_chain. */
+
+void
+do_cleanups (struct cleanup *old_chain)
+{
+ do_my_cleanups (&cleanup_chain, old_chain);
+}
+
+/* Discard cleanups and do the actions they describe
+ until we get back to the point OLD_CHAIN in the final_cleanup_chain. */
+
+void
+do_final_cleanups (struct cleanup *old_chain)
+{
+ do_my_cleanups (&final_cleanup_chain, old_chain);
+}
+
+/* Main worker routine to discard cleanups.
+ PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
+ OLD_CHAIN is the result of a "make" cleanup routine.
+ Cleanups are discarded until we get back to the old end of the chain. */
+
+static void
+discard_my_cleanups (struct cleanup **pmy_chain,
+ struct cleanup *old_chain)
+{
+ struct cleanup *ptr;
+
+ while ((ptr = *pmy_chain) != old_chain)
+ {
+ *pmy_chain = ptr->next;
+ if (ptr->free_arg)
+ (*ptr->free_arg) (ptr->arg);
+ xfree (ptr);
+ }
+}
+
+/* Discard cleanups, not doing the actions they describe,
+ until we get back to the point OLD_CHAIN in the cleanup chain. */
+
+void
+discard_cleanups (struct cleanup *old_chain)
+{
+ discard_my_cleanups (&cleanup_chain, old_chain);
+}
+
+/* Discard final cleanups, not doing the actions they describe,
+ until we get back to the point OLD_CHAIN in the final cleanup chain. */
+
+void
+discard_final_cleanups (struct cleanup *old_chain)
+{
+ discard_my_cleanups (&final_cleanup_chain, old_chain);
+}
+
+/* Main worker routine to save cleanups.
+ PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
+ The chain is emptied and the result is a pointer to the old chain. */
+
+static struct cleanup *
+save_my_cleanups (struct cleanup **pmy_chain)
+{
+ struct cleanup *old_chain = *pmy_chain;
+
+ *pmy_chain = SENTINEL_CLEANUP;
+ return old_chain;
+}
+
+/* Set the cleanup_chain to 0, and return the old cleanup_chain. */
+
+struct cleanup *
+save_cleanups (void)
+{
+ return save_my_cleanups (&cleanup_chain);
+}
+
+/* Set the final_cleanup_chain to 0, and return the old
+ final_cleanup_chain. */
+
+struct cleanup *
+save_final_cleanups (void)
+{
+ return save_my_cleanups (&final_cleanup_chain);
+}
+
+/* Main worker routine to save cleanups.
+ PMY_CHAIN is a pointer to either cleanup_chain or final_cleanup_chain.
+ The chain is restored from CHAIN. */
+
+static void
+restore_my_cleanups (struct cleanup **pmy_chain, struct cleanup *chain)
+{
+ if (*pmy_chain != SENTINEL_CLEANUP)
+ internal_warning (__FILE__, __LINE__,
+ _("restore_my_cleanups has found a stale cleanup"));
+
+ *pmy_chain = chain;
+}
+
+/* Restore the cleanup chain from a previously saved chain. */
+
+void
+restore_cleanups (struct cleanup *chain)
+{
+ restore_my_cleanups (&cleanup_chain, chain);
+}
+
+/* Restore the final cleanup chain from a previously saved chain. */
+
+void
+restore_final_cleanups (struct cleanup *chain)
+{
+ restore_my_cleanups (&final_cleanup_chain, chain);
+}
+
+/* Provide a known function that does nothing, to use as a base for
+ a possibly long chain of cleanups. This is useful where we
+ use the cleanup chain for handling normal cleanups as well as dealing
+ with cleanups that need to be done as a result of a call to error().
+ In such cases, we may not be certain where the first cleanup is, unless
+ we have a do-nothing one to always use as the base. */
+
+void
+null_cleanup (void *arg)
+{
+}
diff --git a/gdb/common/cleanups.h b/gdb/common/cleanups.h
new file mode 100644
index 0000000..aad5add
--- /dev/null
+++ b/gdb/common/cleanups.h
@@ -0,0 +1,69 @@
+/* Cleanups.
+ Copyright (C) 1986-2014 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef CLEANUPS_H
+#define CLEANUPS_H
+
+/* Outside of cleanups.c, this is an opaque type. */
+struct cleanup;
+
+/* NOTE: cagney/2000-03-04: This typedef is strictly for the
+ make_cleanup function declarations below. Do not use this typedef
+ as a cast when passing functions into the make_cleanup() code.
+ Instead either use a bounce function or add a wrapper function.
+ Calling a f(char*) function with f(void*) is non-portable. */
+typedef void (make_cleanup_ftype) (void *);
+
+/* Function type for the dtor in make_cleanup_dtor. */
+typedef void (make_cleanup_dtor_ftype) (void *);
+
+/* WARNING: The result of the "make cleanup" routines is not the intuitive
+ choice of being a handle on the just-created cleanup. Instead it is an
+ opaque handle of the cleanup mechanism and represents all cleanups created
+ from that point onwards.
+ The result is guaranteed to be non-NULL though. */
+
+extern struct cleanup *make_cleanup (make_cleanup_ftype *, void *);
+
+extern struct cleanup *make_cleanup_dtor (make_cleanup_ftype *, void *,
+ make_cleanup_dtor_ftype *);
+
+extern struct cleanup *make_final_cleanup (make_cleanup_ftype *, void *);
+
+/* A special value to pass to do_cleanups and do_final_cleanups
+ to tell them to do all cleanups. */
+extern struct cleanup *all_cleanups (void);
+
+extern void do_cleanups (struct cleanup *);
+extern void do_final_cleanups (struct cleanup *);
+
+extern void discard_cleanups (struct cleanup *);
+extern void discard_final_cleanups (struct cleanup *);
+
+extern struct cleanup *save_cleanups (void);
+extern struct cleanup *save_final_cleanups (void);
+
+extern void restore_cleanups (struct cleanup *);
+extern void restore_final_cleanups (struct cleanup *);
+
+/* A no-op cleanup.
+ This is useful when you want to establish a known reference point
+ to pass to do_cleanups. */
+extern void null_cleanup (void *);
+
+#endif /* CLEANUPS_H */
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 18486c6..f130082 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -170,7 +170,7 @@ SFILES= $(srcdir)/gdbreplay.c $(srcdir)/inferiors.c $(srcdir)/dll.c \
$(srcdir)/common/filestuff.c $(srcdir)/target/waitstatus.c \
$(srcdir)/nat/mips-linux-watch.c $(srcdir)/common/print-utils.c \
$(srcdir)/common/rsp-low.c $(srcdir)/common/errors.c \
- $(srcdir)/common/common-debug.c
+ $(srcdir)/common/common-debug.c $(srcdir)/common/cleanups.c
DEPFILES = @GDBSERVER_DEPFILES@
@@ -183,7 +183,7 @@ OBS = agent.o ax.o inferiors.o regcache.o remote-utils.o server.o signals.o \
target.o waitstatus.o utils.o debug.o version.o vec.o gdb_vecs.o \
mem-break.o hostio.o event-loop.o tracepoint.o xml-utils.o \
common-utils.o ptid.o buffer.o format.o filestuff.o dll.o notif.o \
- tdesc.o print-utils.o rsp-low.o errors.o common-debug.o \
+ tdesc.o print-utils.o rsp-low.o errors.o common-debug.o cleanups.o \
$(XML_BUILTIN) $(DEPFILES) $(LIBOBJS)
GDBREPLAY_OBS = gdbreplay.o version.o
GDBSERVER_LIBS = @GDBSERVER_LIBS@
@@ -544,6 +544,9 @@ errors.o: ../common/errors.c
common-debug.o: ../common/common-debug.c
$(COMPILE) $<
$(POSTCOMPILE)
+cleanups.o: ../common/cleanups.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
waitstatus.o: ../target/waitstatus.c
$(COMPILE) $<
$(POSTCOMPILE)
--
1.7.1
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [PATCH 2/5] Move cleanups.[ch] to common
2014-08-18 8:47 ` [PATCH 2/5] Move cleanups.[ch] to common Gary Benson
@ 2014-08-20 16:47 ` Pedro Alves
2014-08-20 19:05 ` Gary Benson
2014-08-28 15:35 ` Pedro Alves
2014-08-28 15:36 ` Pedro Alves
2 siblings, 1 reply; 14+ messages in thread
From: Pedro Alves @ 2014-08-20 16:47 UTC (permalink / raw)
To: Gary Benson, gdb-patches
On 08/18/2014 09:46 AM, Gary Benson wrote:
> This commit moves cleanups.[ch] into gdb/common/. The only change to
> the content of the files is that cleanups.c's include list was altered
> to match its new location.
Please send a 'git diff -M' version.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/5] Move cleanups.[ch] to common
2014-08-20 16:47 ` Pedro Alves
@ 2014-08-20 19:05 ` Gary Benson
0 siblings, 0 replies; 14+ messages in thread
From: Gary Benson @ 2014-08-20 19:05 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
Pedro Alves wrote:
> On 08/18/2014 09:46 AM, Gary Benson wrote:
> > This commit moves cleanups.[ch] into gdb/common/. The only change
> > to the content of the files is that cleanups.c's include list was
> > altered to match its new location.
>
> Please send a 'git diff -M' version.
Sure:
--
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index e68798d..1840ce7 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -794,7 +794,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
breakpoint.c break-catch-sig.c break-catch-throw.c \
build-id.c buildsym.c \
c-exp.y c-lang.c c-typeprint.c c-valprint.c c-varobj.c \
- charset.c cleanups.c cli-out.c coffread.c coff-pe-read.c \
+ charset.c common/cleanups.c cli-out.c coffread.c coff-pe-read.c \
complaints.c completer.c continuations.c corefile.c corelow.c \
cp-abi.c cp-support.c cp-namespace.c cp-valprint.c \
d-exp.y d-lang.c d-support.c d-valprint.c \
@@ -885,7 +885,7 @@ objfiles.h common/vec.h disasm.h mips-tdep.h ser-base.h \
gdb_curses.h bfd-target.h memattr.h inferior.h ax.h dummy-frame.h \
inflow.h fbsd-nat.h ia64-libunwind-tdep.h completer.h inf-ttrace.h \
solib-target.h gdb_vfork.h alpha-tdep.h dwarf2expr.h \
-m2-lang.h stack.h charset.h cleanups.h addrmap.h command.h solist.h source.h \
+m2-lang.h stack.h charset.h addrmap.h command.h solist.h source.h \
target.h target-dcache.h prologue-value.h cp-abi.h tui/tui-hooks.h tui/tui.h \
tui/tui-file.h tui/tui-command.h tui/tui-disasm.h tui/tui-wingeneral.h \
tui/tui-windata.h tui/tui-data.h tui/tui-win.h tui/tui-stack.h \
@@ -938,6 +938,8 @@ target/wait.h target/waitstatus.h nat/linux-nat.h nat/linux-waitpid.h \
common/print-utils.h common/rsp-low.h nat/i386-dregs.h x86-linux-nat.h \
i386-linux-nat.h common/common-defs.h common/errors.h common/common-types.h \
common/common-debug.h target/target.h target/symbol.h common/common-regcache.h
+common/common-debug.h target/target.h target/symbol.h common/common-regcache.h \
+common/cleanups.h
# Header files that already have srcdir in them, or which are in objdir.
@@ -2154,6 +2156,10 @@ common-debug.o: ${srcdir}/common/common-debug.c
$(COMPILE) $(srcdir)/common/common-debug.c
$(POSTCOMPILE)
+cleanups.o: ${srcdir}/common/cleanups.c
+ $(COMPILE) $(srcdir)/common/cleanups.c
+ $(POSTCOMPILE)
+
#
# gdb/target/ dependencies
#
diff --git a/gdb/cleanups.c b/gdb/common/cleanups.c
similarity index 99%
rename from gdb/cleanups.c
rename to gdb/common/cleanups.c
index ddf8e5b..49b643b 100644
--- a/gdb/cleanups.c
+++ b/gdb/common/cleanups.c
@@ -17,7 +17,8 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
-#include "defs.h"
+#include "common-defs.h"
+#include "cleanups.h"
/* The cleanup list records things that have to be undone
if an error happens (descriptors to be closed, memory to be freed, etc.)
diff --git a/gdb/cleanups.h b/gdb/common/cleanups.h
similarity index 100%
rename from gdb/cleanups.h
rename to gdb/common/cleanups.h
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 18486c6..f130082 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -170,7 +170,7 @@ SFILES= $(srcdir)/gdbreplay.c $(srcdir)/inferiors.c $(srcdir)/dll.c \
$(srcdir)/common/filestuff.c $(srcdir)/target/waitstatus.c \
$(srcdir)/nat/mips-linux-watch.c $(srcdir)/common/print-utils.c \
$(srcdir)/common/rsp-low.c $(srcdir)/common/errors.c \
- $(srcdir)/common/common-debug.c
+ $(srcdir)/common/common-debug.c $(srcdir)/common/cleanups.c
DEPFILES = @GDBSERVER_DEPFILES@
@@ -183,7 +183,7 @@ OBS = agent.o ax.o inferiors.o regcache.o remote-utils.o server.o signals.o \
target.o waitstatus.o utils.o debug.o version.o vec.o gdb_vecs.o \
mem-break.o hostio.o event-loop.o tracepoint.o xml-utils.o \
common-utils.o ptid.o buffer.o format.o filestuff.o dll.o notif.o \
- tdesc.o print-utils.o rsp-low.o errors.o common-debug.o \
+ tdesc.o print-utils.o rsp-low.o errors.o common-debug.o cleanups.o \
$(XML_BUILTIN) $(DEPFILES) $(LIBOBJS)
GDBREPLAY_OBS = gdbreplay.o version.o
GDBSERVER_LIBS = @GDBSERVER_LIBS@
@@ -544,6 +544,9 @@ errors.o: ../common/errors.c
common-debug.o: ../common/common-debug.c
$(COMPILE) $<
$(POSTCOMPILE)
+cleanups.o: ../common/cleanups.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
waitstatus.o: ../target/waitstatus.c
$(COMPILE) $<
$(POSTCOMPILE)
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/5] Move cleanups.[ch] to common
2014-08-18 8:47 ` [PATCH 2/5] Move cleanups.[ch] to common Gary Benson
2014-08-20 16:47 ` Pedro Alves
@ 2014-08-28 15:35 ` Pedro Alves
2014-08-28 15:36 ` Pedro Alves
2 siblings, 0 replies; 14+ messages in thread
From: Pedro Alves @ 2014-08-28 15:35 UTC (permalink / raw)
To: Gary Benson, gdb-patches
On 08/18/2014 09:46 AM, Gary Benson wrote:
> @@ -938,6 +938,8 @@ target/wait.h target/waitstatus.h nat/linux-nat.h nat/linux-waitpid.h \
> common/print-utils.h common/rsp-low.h nat/i386-dregs.h x86-linux-nat.h \
> i386-linux-nat.h common/common-defs.h common/errors.h common/common-types.h \
> common/common-debug.h target/target.h target/symbol.h common/common-regcache.h
> +common/common-debug.h target/target.h target/symbol.h common/common-regcache.h \
> +common/cleanups.h
Note, this breaks the build. The
common/common-debug.h target/target.h target/symbol.h common/common-regcache.h
line should have been removed.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/5] Move cleanups.[ch] to common
2014-08-18 8:47 ` [PATCH 2/5] Move cleanups.[ch] to common Gary Benson
2014-08-20 16:47 ` Pedro Alves
2014-08-28 15:35 ` Pedro Alves
@ 2014-08-28 15:36 ` Pedro Alves
2 siblings, 0 replies; 14+ messages in thread
From: Pedro Alves @ 2014-08-28 15:36 UTC (permalink / raw)
To: Gary Benson, gdb-patches
Hi Gary,
On 08/18/2014 09:46 AM, Gary Benson wrote:
> gdb/
> 2014-08-18 Gary Benson <gbenson@redhat.com>
>
> * cleanups.h: Moved to...
> * common/cleanups.h: New file.
> * cleanups.c: Moved to...
> * common/cleanups.c: New file.
> --- a/gdb/cleanups.c
> +++ b/gdb/common/cleanups.c
> @@ -17,7 +17,8 @@
> You should have received a copy of the GNU General Public License
> along with this program. If not, see <http://www.gnu.org/licenses/>. */
>
> -#include "defs.h"
> +#include "common-defs.h"
> +#include "cleanups.h"
The new cleanups.h inclusion should be mentioned in the ChangeLog as well.
> * Makefile.in (SFILES): Replace cleanups.c with common/cleanups.c.
> (HFILES_NO_SRCDIR): Replace cleanups.h with common/cleanups.h.
> (cleanups.o): New rule.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 1/5] Move internal_{,v}warning to common/errors.[ch]
2014-08-18 8:47 [PATCH 0/5] Make gdbserver use exceptions and cleanups Gary Benson
2014-08-18 8:47 ` [PATCH 2/5] Move cleanups.[ch] to common Gary Benson
@ 2014-08-18 8:47 ` Gary Benson
2014-08-18 8:47 ` [PATCH 3/5] Introduce common/gdb_setjmp.h Gary Benson
` (3 subsequent siblings)
5 siblings, 0 replies; 14+ messages in thread
From: Gary Benson @ 2014-08-18 8:47 UTC (permalink / raw)
To: gdb-patches
This commit moves internal_warning and internal_vwarning into
common/errors.[ch].
gdb/
2014-08-18 Gary Benson <gbenson@redhat.com>
* common/errors.h (internal_warning): New declaration.
(internal_vwarning): Likewise.
* common/errors.c (internal_warning): New function.
* utils.h (internal_warning): Don't declare.
(internal_vwarning): Likewise.
* utils.c (internal_warning): Removed.
gdb/gdbserver/
2014-08-18 Gary Benson <gbenson@redhat.com>
* utils.c (internal_vwarning): New function.
---
gdb/ChangeLog | 9 +++++++++
gdb/common/errors.c | 12 ++++++++++++
gdb/common/errors.h | 15 +++++++++++++++
gdb/gdbserver/ChangeLog | 4 ++++
gdb/gdbserver/utils.c | 11 +++++++++++
gdb/utils.c | 10 ----------
gdb/utils.h | 7 -------
7 files changed, 51 insertions(+), 17 deletions(-)
diff --git a/gdb/common/errors.c b/gdb/common/errors.c
index 6da2666..089c64b 100644
--- a/gdb/common/errors.c
+++ b/gdb/common/errors.c
@@ -55,3 +55,15 @@ internal_error (const char *file, int line, const char *fmt, ...)
internal_verror (file, line, fmt, ap);
va_end (ap);
}
+
+/* See common/errors.h. */
+
+void
+internal_warning (const char *file, int line, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start (ap, fmt);
+ internal_vwarning (file, line, fmt, ap);
+ va_end (ap);
+}
diff --git a/gdb/common/errors.h b/gdb/common/errors.h
index 4e6c2b3..88d77e5 100644
--- a/gdb/common/errors.h
+++ b/gdb/common/errors.h
@@ -58,6 +58,21 @@ extern void internal_error (const char *file, int line,
extern void internal_verror (const char *file, int line,
const char *fmt, va_list args)
ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (3, 0);
+
+/* An internal problem was detected, but the requested operation can
+ still proceed. Internal warnings indicate programming errors as
+ opposed to more general issues beyond the application's control.
+ A warning message is constructed using a printf- or vprintf-style
+ argument list. The function "internal_vwarning" must be provided
+ by the client. */
+
+extern void internal_warning (const char *file, int line,
+ const char *fmt, ...)
+ ATTRIBUTE_PRINTF (3, 4);
+
+extern void internal_vwarning (const char *file, int line,
+ const char *fmt, va_list args)
+ ATTRIBUTE_PRINTF (3, 0);
\f
/* Like "error", but the error message is constructed by combining
diff --git a/gdb/gdbserver/utils.c b/gdb/gdbserver/utils.c
index 3aac3cd..3ec4add 100644
--- a/gdb/gdbserver/utils.c
+++ b/gdb/gdbserver/utils.c
@@ -129,6 +129,17 @@ internal_verror (const char *file, int line, const char *fmt, va_list args)
exit (1);
}
+/* Report a problem internal to GDBserver. */
+
+void
+internal_vwarning (const char *file, int line, const char *fmt, va_list args)
+{
+ fprintf (stderr, "\
+%s:%d: A problem internal to " TOOLNAME " has been detected.\n", file, line);
+ vfprintf (stderr, fmt, args);
+ fprintf (stderr, "\n");
+}
+
/* Convert a CORE_ADDR into a HEX string, like %lx.
The result is stored in a circular static buffer, NUMCELLS deep. */
diff --git a/gdb/utils.c b/gdb/utils.c
index 2b64023..759ec84 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -797,16 +797,6 @@ internal_vwarning (const char *file, int line, const char *fmt, va_list ap)
internal_vproblem (&internal_warning_problem, file, line, fmt, ap);
}
-void
-internal_warning (const char *file, int line, const char *string, ...)
-{
- va_list ap;
-
- va_start (ap, string);
- internal_vwarning (file, line, string, ap);
- va_end (ap);
-}
-
static struct internal_problem demangler_warning_problem = {
"demangler-warning", 1, internal_problem_ask, 0, internal_problem_no
};
diff --git a/gdb/utils.h b/gdb/utils.h
index 57a1c0f..2ec3fda 100644
--- a/gdb/utils.h
+++ b/gdb/utils.h
@@ -283,13 +283,6 @@ extern char *warning_pre_print;
extern void error_stream (struct ui_file *) ATTRIBUTE_NORETURN;
-extern void internal_vwarning (const char *file, int line,
- const char *, va_list ap)
- ATTRIBUTE_PRINTF (3, 0);
-
-extern void internal_warning (const char *file, int line,
- const char *, ...) ATTRIBUTE_PRINTF (3, 4);
-
extern void demangler_vwarning (const char *file, int line,
const char *, va_list ap)
ATTRIBUTE_PRINTF (3, 0);
--
1.7.1
^ permalink raw reply [flat|nested] 14+ messages in thread* [PATCH 3/5] Introduce common/gdb_setjmp.h
2014-08-18 8:47 [PATCH 0/5] Make gdbserver use exceptions and cleanups Gary Benson
2014-08-18 8:47 ` [PATCH 2/5] Move cleanups.[ch] to common Gary Benson
2014-08-18 8:47 ` [PATCH 1/5] Move internal_{,v}warning to common/errors.[ch] Gary Benson
@ 2014-08-18 8:47 ` Gary Benson
2014-08-20 16:54 ` Pedro Alves
2014-08-18 8:52 ` [PATCH 4/5] Introduce common/common-exceptions.[ch] Gary Benson
` (2 subsequent siblings)
5 siblings, 1 reply; 14+ messages in thread
From: Gary Benson @ 2014-08-18 8:47 UTC (permalink / raw)
To: gdb-patches
This commit creates a new file, common/gdb_setjmp.h, to hold some
portability macros for setjmp/longjmp et al. that are used by the
exceptions subsystem and by the demangler crash catcher.
gdb/
2014-08-18 Gary Benson <gbenson@redhat.com>
* common/gdb_setjmp.h: New file.
* Makefile.in (HFILES_NO_SRCDIR): Add common/gdb_setjmp.h.
* configure.ac: Move sigsetjmp check...
* common/common.m4: ...here.
* configure: Regenerate.
* cp-support.c (SIGJMP_BUF): Undefine.
(SIGSETJMP): Likewise.
(SIGLONGJMP): Likewise.
* exceptions.h (gdb_setjmp.h): Include.
(setjmp.h): Do not include.
(EXCEPTIONS_SIGJMP_BUF): Undefine.
(EXCEPTIONS_SIGSETJMP): Likewise.
(EXCEPTIONS_SIGLONGJMP): Likewise.
Replace all uses of EXCEPTIONS_SIG* macros with SIG* macros
from gdb_setjmp.h.
* exceptions.c: Likewise.
gdb/gdbserver/
2014-08-18 Gary Benson <gbenson@redhat.com>
* config.in: Regenerate.
* configure: Likewise.
---
gdb/ChangeLog | 19 +++++++++++++
gdb/Makefile.in | 2 +-
gdb/common/common.m4 | 11 +++++++
gdb/common/gdb_setjmp.h | 34 +++++++++++++++++++++++
gdb/configure | 68 ++++++++++++++++++++++------------------------
gdb/configure.ac | 11 -------
gdb/cp-support.c | 12 --------
gdb/exceptions.c | 6 ++--
gdb/exceptions.h | 25 ++++-------------
gdb/gdbserver/ChangeLog | 5 +++
gdb/gdbserver/config.in | 3 ++
gdb/gdbserver/configure | 33 ++++++++++++++++++++++
12 files changed, 148 insertions(+), 81 deletions(-)
create mode 100644 gdb/common/gdb_setjmp.h
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 1840ce7..951a738 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -939,7 +939,7 @@ common/print-utils.h common/rsp-low.h nat/i386-dregs.h x86-linux-nat.h \
i386-linux-nat.h common/common-defs.h common/errors.h common/common-types.h \
common/common-debug.h target/target.h target/symbol.h common/common-regcache.h
common/common-debug.h target/target.h target/symbol.h common/common-regcache.h \
-common/cleanups.h
+common/cleanups.h common/gdb_setjmp.h
# Header files that already have srcdir in them, or which are in objdir.
diff --git a/gdb/common/common.m4 b/gdb/common/common.m4
index 426df79..7aabd07 100644
--- a/gdb/common/common.m4
+++ b/gdb/common/common.m4
@@ -33,4 +33,15 @@ AC_DEFUN([GDB_AC_COMMON], [
AC_CHECK_FUNCS([fdwalk getrlimit pipe pipe2 socketpair])
AC_CHECK_DECLS([strerror, strstr])
+
+ dnl Check if sigsetjmp is available. Using AC_CHECK_FUNCS won't
+ dnl do since sigsetjmp might only be defined as a macro.
+AC_CACHE_CHECK([for sigsetjmp], gdb_cv_func_sigsetjmp,
+[AC_TRY_COMPILE([
+#include <setjmp.h>
+], [sigjmp_buf env; while (! sigsetjmp (env, 1)) siglongjmp (env, 1);],
+gdb_cv_func_sigsetjmp=yes, gdb_cv_func_sigsetjmp=no)])
+if test $gdb_cv_func_sigsetjmp = yes; then
+ AC_DEFINE(HAVE_SIGSETJMP, 1, [Define if sigsetjmp is available. ])
+fi
])
diff --git a/gdb/common/gdb_setjmp.h b/gdb/common/gdb_setjmp.h
new file mode 100644
index 0000000..aba50a4
--- /dev/null
+++ b/gdb/common/gdb_setjmp.h
@@ -0,0 +1,34 @@
+/* Portability wrappers for setjmp and longjmp.
+ Copyright (C) 1986-2014 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDB_SETJMP_H
+#define GDB_SETJMP_H
+
+#include <setjmp.h>
+
+#ifdef HAVE_SIGSETJMP
+#define SIGJMP_BUF sigjmp_buf
+#define SIGSETJMP(buf) sigsetjmp((buf), 1)
+#define SIGLONGJMP(buf,val) siglongjmp((buf), (val))
+#else
+#define SIGJMP_BUF jmp_buf
+#define SIGSETJMP(buf) setjmp(buf)
+#define SIGLONGJMP(buf,val) longjmp((buf), (val))
+#endif
+
+#endif /* GDB_SETJMP_H */
diff --git a/gdb/configure b/gdb/configure
index 874922d..0551f95 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -11054,6 +11054,39 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sigsetjmp" >&5
+$as_echo_n "checking for sigsetjmp... " >&6; }
+if test "${gdb_cv_func_sigsetjmp+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <setjmp.h>
+
+int
+main ()
+{
+sigjmp_buf env; while (! sigsetjmp (env, 1)) siglongjmp (env, 1);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ gdb_cv_func_sigsetjmp=yes
+else
+ gdb_cv_func_sigsetjmp=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gdb_cv_func_sigsetjmp" >&5
+$as_echo "$gdb_cv_func_sigsetjmp" >&6; }
+if test $gdb_cv_func_sigsetjmp = yes; then
+
+$as_echo "#define HAVE_SIGSETJMP 1" >>confdefs.h
+
+fi
+
# Check the return and argument types of ptrace. No canned test for
# this, so roll our own.
@@ -11316,41 +11349,6 @@ if test $ac_cv_func_setpgrp_void = yes; then
fi
fi
-# Check if sigsetjmp is available. Using AC_CHECK_FUNCS won't do
-# since sigsetjmp might only be defined as a macro.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sigsetjmp" >&5
-$as_echo_n "checking for sigsetjmp... " >&6; }
-if test "${gdb_cv_func_sigsetjmp+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-#include <setjmp.h>
-
-int
-main ()
-{
-sigjmp_buf env; while (! sigsetjmp (env, 1)) siglongjmp (env, 1);
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- gdb_cv_func_sigsetjmp=yes
-else
- gdb_cv_func_sigsetjmp=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gdb_cv_func_sigsetjmp" >&5
-$as_echo "$gdb_cv_func_sigsetjmp" >&6; }
-if test $gdb_cv_func_sigsetjmp = yes; then
-
-$as_echo "#define HAVE_SIGSETJMP 1" >>confdefs.h
-
-fi
-
# Assume we'll default to using the included libiberty regex.
gdb_use_included_regex=yes
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 61919b4..26c8ecf 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -1441,17 +1441,6 @@ if test $ac_cv_func_setpgrp_void = yes; then
fi
fi
-# Check if sigsetjmp is available. Using AC_CHECK_FUNCS won't do
-# since sigsetjmp might only be defined as a macro.
-AC_CACHE_CHECK([for sigsetjmp], gdb_cv_func_sigsetjmp,
-[AC_TRY_COMPILE([
-#include <setjmp.h>
-], [sigjmp_buf env; while (! sigsetjmp (env, 1)) siglongjmp (env, 1);],
-gdb_cv_func_sigsetjmp=yes, gdb_cv_func_sigsetjmp=no)])
-if test $gdb_cv_func_sigsetjmp = yes; then
- AC_DEFINE(HAVE_SIGSETJMP, 1, [Define if sigsetjmp is available. ])
-fi
-
# Assume we'll default to using the included libiberty regex.
gdb_use_included_regex=yes
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index 20a4a07..14aaac8 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -1488,18 +1488,6 @@ cp_lookup_rtti_type (const char *name, struct block *block)
static int catch_demangler_crashes = 1;
-/* Wrap set/long jmp so that it's more portable. */
-
-#if defined(HAVE_SIGSETJMP)
-#define SIGJMP_BUF sigjmp_buf
-#define SIGSETJMP(buf) sigsetjmp((buf), 1)
-#define SIGLONGJMP(buf,val) siglongjmp((buf), (val))
-#else
-#define SIGJMP_BUF jmp_buf
-#define SIGSETJMP(buf) setjmp(buf)
-#define SIGLONGJMP(buf,val) longjmp((buf), (val))
-#endif
-
/* Stack context and environment for demangler crash recovery. */
static SIGJMP_BUF gdb_demangle_jmp_buf;
diff --git a/gdb/exceptions.c b/gdb/exceptions.c
index 38e966c..99a147c 100644
--- a/gdb/exceptions.c
+++ b/gdb/exceptions.c
@@ -51,7 +51,7 @@ struct catcher
{
enum catcher_state state;
/* Jump buffer pointing back at the exception handler. */
- EXCEPTIONS_SIGJMP_BUF buf;
+ SIGJMP_BUF buf;
/* Status buffer belonging to the exception handler. */
volatile struct gdb_exception *exception;
/* Saved/current state. */
@@ -80,7 +80,7 @@ catcher_list_size (void)
return size;
}
-EXCEPTIONS_SIGJMP_BUF *
+SIGJMP_BUF *
exceptions_state_mc_init (volatile struct gdb_exception *exception,
return_mask mask)
{
@@ -229,7 +229,7 @@ throw_exception (struct gdb_exception exception)
be zero, by definition in defs.h. */
exceptions_state_mc (CATCH_THROWING);
*current_catcher->exception = exception;
- EXCEPTIONS_SIGLONGJMP (current_catcher->buf, exception.reason);
+ SIGLONGJMP (current_catcher->buf, exception.reason);
}
static void
diff --git a/gdb/exceptions.h b/gdb/exceptions.h
index be74ad5..e3ff672 100644
--- a/gdb/exceptions.h
+++ b/gdb/exceptions.h
@@ -21,7 +21,7 @@
#define EXCEPTIONS_H
#include "ui-out.h"
-#include <setjmp.h>
+#include "gdb_setjmp.h"
/* Reasons for calling throw_exceptions(). NOTE: all reason values
must be less than zero. enum value 0 is reserved for internal use
@@ -114,24 +114,11 @@ struct gdb_exception
/* A pre-defined non-exception. */
extern const struct gdb_exception exception_none;
-/* Wrap set/long jmp so that it's more portable (internal to
- exceptions). */
-
-#if defined(HAVE_SIGSETJMP)
-#define EXCEPTIONS_SIGJMP_BUF sigjmp_buf
-#define EXCEPTIONS_SIGSETJMP(buf) sigsetjmp((buf), 1)
-#define EXCEPTIONS_SIGLONGJMP(buf,val) siglongjmp((buf), (val))
-#else
-#define EXCEPTIONS_SIGJMP_BUF jmp_buf
-#define EXCEPTIONS_SIGSETJMP(buf) setjmp(buf)
-#define EXCEPTIONS_SIGLONGJMP(buf,val) longjmp((buf), (val))
-#endif
-
/* Functions to drive the exceptions state m/c (internal to
exceptions). */
-EXCEPTIONS_SIGJMP_BUF *exceptions_state_mc_init (volatile struct
- gdb_exception *exception,
- return_mask mask);
+SIGJMP_BUF *exceptions_state_mc_init (volatile struct
+ gdb_exception *exception,
+ return_mask mask);
int exceptions_state_mc_action_iter (void);
int exceptions_state_mc_action_iter_1 (void);
@@ -159,9 +146,9 @@ int exceptions_state_mc_action_iter_1 (void);
#define TRY_CATCH(EXCEPTION,MASK) \
{ \
- EXCEPTIONS_SIGJMP_BUF *buf = \
+ SIGJMP_BUF *buf = \
exceptions_state_mc_init (&(EXCEPTION), (MASK)); \
- EXCEPTIONS_SIGSETJMP (*buf); \
+ SIGSETJMP (*buf); \
} \
while (exceptions_state_mc_action_iter ()) \
while (exceptions_state_mc_action_iter_1 ())
diff --git a/gdb/gdbserver/config.in b/gdb/gdbserver/config.in
index 216c01d..7828bf9 100644
--- a/gdb/gdbserver/config.in
+++ b/gdb/gdbserver/config.in
@@ -154,6 +154,9 @@
/* Define to 1 if you have the <signal.h> header file. */
#undef HAVE_SIGNAL_H
+/* Define if sigsetjmp is available. */
+#undef HAVE_SIGSETJMP
+
/* Define to 1 if you have the `socketpair' function. */
#undef HAVE_SOCKETPAIR
diff --git a/gdb/gdbserver/configure b/gdb/gdbserver/configure
index 9c1f9a8..9495905 100755
--- a/gdb/gdbserver/configure
+++ b/gdb/gdbserver/configure
@@ -5322,6 +5322,39 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sigsetjmp" >&5
+$as_echo_n "checking for sigsetjmp... " >&6; }
+if test "${gdb_cv_func_sigsetjmp+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <setjmp.h>
+
+int
+main ()
+{
+sigjmp_buf env; while (! sigsetjmp (env, 1)) siglongjmp (env, 1);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ gdb_cv_func_sigsetjmp=yes
+else
+ gdb_cv_func_sigsetjmp=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gdb_cv_func_sigsetjmp" >&5
+$as_echo "$gdb_cv_func_sigsetjmp" >&6; }
+if test $gdb_cv_func_sigsetjmp = yes; then
+
+$as_echo "#define HAVE_SIGSETJMP 1" >>confdefs.h
+
+fi
+
# Check for UST
ustlibs=""
--
1.7.1
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [PATCH 3/5] Introduce common/gdb_setjmp.h
2014-08-18 8:47 ` [PATCH 3/5] Introduce common/gdb_setjmp.h Gary Benson
@ 2014-08-20 16:54 ` Pedro Alves
0 siblings, 0 replies; 14+ messages in thread
From: Pedro Alves @ 2014-08-20 16:54 UTC (permalink / raw)
To: Gary Benson, gdb-patches
On 08/18/2014 09:46 AM, Gary Benson wrote:
> This commit creates a new file, common/gdb_setjmp.h, to hold some
> portability macros for setjmp/longjmp et al. that are used by the
> exceptions subsystem and by the demangler crash catcher.
Looks like this one stands on its own.
OK, with ...
>
> gdb/
> 2014-08-18 Gary Benson <gbenson@redhat.com>
>
> * common/gdb_setjmp.h: New file.
> * Makefile.in (HFILES_NO_SRCDIR): Add common/gdb_setjmp.h.
> * configure.ac: Move sigsetjmp check...
> * common/common.m4: ...here.
> * configure: Regenerate.
> * cp-support.c (SIGJMP_BUF): Undefine.
... please say "Delete.". "Undefine" makes the reader expect
an #undef.
> (SIGSETJMP): Likewise.
> (SIGLONGJMP): Likewise.
> * exceptions.h (gdb_setjmp.h): Include.
> (setjmp.h): Do not include.
> (EXCEPTIONS_SIGJMP_BUF): Undefine.
Likewise.
> (EXCEPTIONS_SIGSETJMP): Likewise.
> (EXCEPTIONS_SIGLONGJMP): Likewise.
> Replace all uses of EXCEPTIONS_SIG* macros with SIG* macros
> from gdb_setjmp.h.
> * exceptions.c: Likewise.
>
> gdb/gdbserver/
> 2014-08-18 Gary Benson <gbenson@redhat.com>
>
> * config.in: Regenerate.
> * configure: Likewise.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 4/5] Introduce common/common-exceptions.[ch]
2014-08-18 8:47 [PATCH 0/5] Make gdbserver use exceptions and cleanups Gary Benson
` (2 preceding siblings ...)
2014-08-18 8:47 ` [PATCH 3/5] Introduce common/gdb_setjmp.h Gary Benson
@ 2014-08-18 8:52 ` Gary Benson
2014-08-18 9:25 ` [PATCH 5/5] Use exceptions and cleanups in gdbserver Gary Benson
2014-08-28 15:39 ` [PATCH 0/5] Make gdbserver use exceptions and cleanups Pedro Alves
5 siblings, 0 replies; 14+ messages in thread
From: Gary Benson @ 2014-08-18 8:52 UTC (permalink / raw)
To: gdb-patches
This commit moves the exception throwing and catching code
into gdb/common/. All exception printing code remains in
gdb/exceptions.[ch].
gdb/
2014-08-18 Gary Benson <gbenson@redhat.com>
* common/common-exceptions.h: New file.
* common/common-exceptions.c: Likewise.
* Makefile.in (SFILES): Add common/common-exceptions.c.
(HFILES_NO_SRCDIR): Add common/common-exceptions.h.
(COMMON_OBS): Add common-exceptions.o.
(common-exceptions.o): New rule.
* exceptions.h (common-exceptions.h): Include.
(gdb_setjmp.h): Do not include.
(return_reason): Moved to common-exceptions.h.
(enum return_reason): Likewise.
(RETURN_MASK): Likewise.
(typedef return_mask): Likewise.
(enum errors): Likewise.
(struct gdb_exception): Likewise.
(exceptions_state_mc_init): Likewise.
(exceptions_state_mc_action_iter): Likewise.
(exceptions_state_mc_action_iter_1): Likewise.
(TRY_CATCH): Likewise.
(throw_exception): Likewise.
(throw_verror): Likewise.
(throw_vquit): Likewise.
(throw_error): Likewise.
(throw_quit): Likewise.
* exceptions.c (enum catcher_state): Moved to common-exceptions.c.
(enum catcher_action): Likewise.
(struct catcher): Likewise.
(current_catcher): Likewise.
(catcher_list_size): Likewise.
(exceptions_state_mc_init): Likewise.
(catcher_pop): Likewise.
(exceptions_state_mc): Likewise.
(exceptions_state_mc_action_iter): Likewise.
(exceptions_state_mc_action_iter_1): Likewise.
(throw_exception): Likewise.
(exception_messages): Likewise.
(exception_messages_size): Likewise.
(throw_it): Likewise.
(throw_verror): Likewise.
(throw_vquit): Likewise.
(throw_error): Likewise.
(throw_quit): Likewise.
(prepare_to_throw_exception): New function.
gdb/gdbserver/
2014-08-18 Gary Benson <gbenson@redhat.com>
* Makefile.in (SFILES): Add common/common-exceptions.c.
(OBS): Add common-exceptions.o.
(common-exceptions.o): New rule.
* utils.c (prepare_to_throw_exception): New function.
---
gdb/ChangeLog | 45 ++++++
gdb/Makefile.in | 11 +-
gdb/common/common-exceptions.c | 308 ++++++++++++++++++++++++++++++++++++++++
gdb/common/common-exceptions.h | 185 ++++++++++++++++++++++++
gdb/exceptions.c | 282 +------------------------------------
gdb/exceptions.h | 154 +--------------------
gdb/gdbserver/ChangeLog | 7 +
gdb/gdbserver/Makefile.in | 7 +-
gdb/gdbserver/utils.c | 8 +
9 files changed, 569 insertions(+), 438 deletions(-)
create mode 100644 gdb/common/common-exceptions.c
create mode 100644 gdb/common/common-exceptions.h
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 951a738..3298825 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -851,7 +851,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
common/ptid.c common/buffer.c gdb-dlfcn.c common/agent.c \
common/format.c common/filestuff.c btrace.c record-btrace.c ctf.c \
target/waitstatus.c common/print-utils.c common/rsp-low.c \
- common/errors.c common/common-debug.c
+ common/errors.c common/common-debug.c common/common-exceptions.c
LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
@@ -939,7 +939,7 @@ common/print-utils.h common/rsp-low.h nat/i386-dregs.h x86-linux-nat.h \
i386-linux-nat.h common/common-defs.h common/errors.h common/common-types.h \
common/common-debug.h target/target.h target/symbol.h common/common-regcache.h
common/common-debug.h target/target.h target/symbol.h common/common-regcache.h \
-common/cleanups.h common/gdb_setjmp.h
+common/cleanups.h common/gdb_setjmp.h common/common-exceptions.h
# Header files that already have srcdir in them, or which are in objdir.
@@ -1038,7 +1038,8 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
gdb_vecs.o jit.o progspace.o skip.o probe.o \
common-utils.o buffer.o ptid.o gdb-dlfcn.o common-agent.o \
format.o registry.o btrace.o record-btrace.o waitstatus.o \
- print-utils.o rsp-low.o errors.o common-debug.o debug.o
+ print-utils.o rsp-low.o errors.o common-debug.o debug.o \
+ common-exceptions.o
TSOBS = inflow.o
@@ -2160,6 +2161,10 @@ cleanups.o: ${srcdir}/common/cleanups.c
$(COMPILE) $(srcdir)/common/cleanups.c
$(POSTCOMPILE)
+common-exceptions.o: ${srcdir}/common/common-exceptions.c
+ $(COMPILE) $(srcdir)/common/common-exceptions.c
+ $(POSTCOMPILE)
+
#
# gdb/target/ dependencies
#
diff --git a/gdb/common/common-exceptions.c b/gdb/common/common-exceptions.c
new file mode 100644
index 0000000..c382d86
--- /dev/null
+++ b/gdb/common/common-exceptions.c
@@ -0,0 +1,308 @@
+/* Exception (throw catch) mechanism, for GDB, the GNU debugger.
+
+ Copyright (C) 1986-2014 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "common-defs.h"
+#include "common-exceptions.h"
+#include "cleanups.h"
+
+/* Possible catcher states. */
+enum catcher_state {
+ /* Initial state, a new catcher has just been created. */
+ CATCHER_CREATED,
+ /* The catch code is running. */
+ CATCHER_RUNNING,
+ CATCHER_RUNNING_1,
+ /* The catch code threw an exception. */
+ CATCHER_ABORTING
+};
+
+/* Possible catcher actions. */
+enum catcher_action {
+ CATCH_ITER,
+ CATCH_ITER_1,
+ CATCH_THROWING
+};
+
+struct catcher
+{
+ enum catcher_state state;
+ /* Jump buffer pointing back at the exception handler. */
+ SIGJMP_BUF buf;
+ /* Status buffer belonging to the exception handler. */
+ volatile struct gdb_exception *exception;
+ /* Saved/current state. */
+ int mask;
+ struct cleanup *saved_cleanup_chain;
+ /* Back link. */
+ struct catcher *prev;
+};
+
+/* Where to go for throw_exception(). */
+static struct catcher *current_catcher;
+
+/* Return length of current_catcher list. */
+
+static int
+catcher_list_size (void)
+{
+ int size;
+ struct catcher *catcher;
+
+ for (size = 0, catcher = current_catcher;
+ catcher != NULL;
+ catcher = catcher->prev)
+ ++size;
+
+ return size;
+}
+
+SIGJMP_BUF *
+exceptions_state_mc_init (volatile struct gdb_exception *exception,
+ return_mask mask)
+{
+ struct catcher *new_catcher = XCNEW (struct catcher);
+
+ /* Start with no exception, save it's address. */
+ exception->reason = 0;
+ exception->error = GDB_NO_ERROR;
+ exception->message = NULL;
+ new_catcher->exception = exception;
+
+ new_catcher->mask = mask;
+
+ /* Prevent error/quit during FUNC from calling cleanups established
+ prior to here. */
+ new_catcher->saved_cleanup_chain = save_cleanups ();
+
+ /* Push this new catcher on the top. */
+ new_catcher->prev = current_catcher;
+ current_catcher = new_catcher;
+ new_catcher->state = CATCHER_CREATED;
+
+ return &new_catcher->buf;
+}
+
+static void
+catcher_pop (void)
+{
+ struct catcher *old_catcher = current_catcher;
+
+ current_catcher = old_catcher->prev;
+
+ /* Restore the cleanup chain, the error/quit messages, and the uiout
+ builder, to their original states. */
+
+ restore_cleanups (old_catcher->saved_cleanup_chain);
+
+ xfree (old_catcher);
+}
+
+/* Catcher state machine. Returns non-zero if the m/c should be run
+ again, zero if it should abort. */
+
+static int
+exceptions_state_mc (enum catcher_action action)
+{
+ switch (current_catcher->state)
+ {
+ case CATCHER_CREATED:
+ switch (action)
+ {
+ case CATCH_ITER:
+ /* Allow the code to run the catcher. */
+ current_catcher->state = CATCHER_RUNNING;
+ return 1;
+ default:
+ internal_error (__FILE__, __LINE__, _("bad state"));
+ }
+ case CATCHER_RUNNING:
+ switch (action)
+ {
+ case CATCH_ITER:
+ /* No error/quit has occured. Just clean up. */
+ catcher_pop ();
+ return 0;
+ case CATCH_ITER_1:
+ current_catcher->state = CATCHER_RUNNING_1;
+ return 1;
+ case CATCH_THROWING:
+ current_catcher->state = CATCHER_ABORTING;
+ /* See also throw_exception. */
+ return 1;
+ default:
+ internal_error (__FILE__, __LINE__, _("bad switch"));
+ }
+ case CATCHER_RUNNING_1:
+ switch (action)
+ {
+ case CATCH_ITER:
+ /* The did a "break" from the inner while loop. */
+ catcher_pop ();
+ return 0;
+ case CATCH_ITER_1:
+ current_catcher->state = CATCHER_RUNNING;
+ return 0;
+ case CATCH_THROWING:
+ current_catcher->state = CATCHER_ABORTING;
+ /* See also throw_exception. */
+ return 1;
+ default:
+ internal_error (__FILE__, __LINE__, _("bad switch"));
+ }
+ case CATCHER_ABORTING:
+ switch (action)
+ {
+ case CATCH_ITER:
+ {
+ struct gdb_exception exception = *current_catcher->exception;
+
+ if (current_catcher->mask & RETURN_MASK (exception.reason))
+ {
+ /* Exit normally if this catcher can handle this
+ exception. The caller analyses the func return
+ values. */
+ catcher_pop ();
+ return 0;
+ }
+ /* The caller didn't request that the event be caught,
+ relay the event to the next containing
+ catch_errors(). */
+ catcher_pop ();
+ throw_exception (exception);
+ }
+ default:
+ internal_error (__FILE__, __LINE__, _("bad state"));
+ }
+ default:
+ internal_error (__FILE__, __LINE__, _("bad switch"));
+ }
+}
+
+int
+exceptions_state_mc_action_iter (void)
+{
+ return exceptions_state_mc (CATCH_ITER);
+}
+
+int
+exceptions_state_mc_action_iter_1 (void)
+{
+ return exceptions_state_mc (CATCH_ITER_1);
+}
+
+/* Return EXCEPTION to the nearest containing catch_errors(). */
+
+void
+throw_exception (struct gdb_exception exception)
+{
+ prepare_to_throw_exception ();
+
+ do_cleanups (all_cleanups ());
+
+ /* Jump to the containing catch_errors() call, communicating REASON
+ to that call via setjmp's return value. Note that REASON can't
+ be zero, by definition in defs.h. */
+ exceptions_state_mc (CATCH_THROWING);
+ *current_catcher->exception = exception;
+ SIGLONGJMP (current_catcher->buf, exception.reason);
+}
+
+/* A stack of exception messages.
+ This is needed to handle nested calls to throw_it: we don't want to
+ xfree space for a message before it's used.
+ This can happen if we throw an exception during a cleanup:
+ An outer TRY_CATCH may have an exception message it wants to print,
+ but while doing cleanups further calls to throw_it are made.
+
+ This is indexed by the size of the current_catcher list.
+ It is a dynamically allocated array so that we don't care how deeply
+ GDB nests its TRY_CATCHs. */
+static char **exception_messages;
+
+/* The number of currently allocated entries in exception_messages. */
+static int exception_messages_size;
+
+static void ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (3, 0)
+throw_it (enum return_reason reason, enum errors error, const char *fmt,
+ va_list ap)
+{
+ struct gdb_exception e;
+ char *new_message;
+ int depth = catcher_list_size ();
+
+ gdb_assert (depth > 0);
+
+ /* Note: The new message may use an old message's text. */
+ new_message = xstrvprintf (fmt, ap);
+
+ if (depth > exception_messages_size)
+ {
+ int old_size = exception_messages_size;
+
+ exception_messages_size = depth + 10;
+ exception_messages = (char **) xrealloc (exception_messages,
+ exception_messages_size
+ * sizeof (char *));
+ memset (exception_messages + old_size, 0,
+ (exception_messages_size - old_size) * sizeof (char *));
+ }
+
+ xfree (exception_messages[depth - 1]);
+ exception_messages[depth - 1] = new_message;
+
+ /* Create the exception. */
+ e.reason = reason;
+ e.error = error;
+ e.message = new_message;
+
+ /* Throw the exception. */
+ throw_exception (e);
+}
+
+void
+throw_verror (enum errors error, const char *fmt, va_list ap)
+{
+ throw_it (RETURN_ERROR, error, fmt, ap);
+}
+
+void
+throw_vquit (const char *fmt, va_list ap)
+{
+ throw_it (RETURN_QUIT, GDB_NO_ERROR, fmt, ap);
+}
+
+void
+throw_error (enum errors error, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start (args, fmt);
+ throw_verror (error, fmt, args);
+ va_end (args);
+}
+
+void
+throw_quit (const char *fmt, ...)
+{
+ va_list args;
+
+ va_start (args, fmt);
+ throw_vquit (fmt, args);
+ va_end (args);
+}
diff --git a/gdb/common/common-exceptions.h b/gdb/common/common-exceptions.h
new file mode 100644
index 0000000..5f750c3
--- /dev/null
+++ b/gdb/common/common-exceptions.h
@@ -0,0 +1,185 @@
+/* Exception (throw catch) mechanism, for GDB, the GNU debugger.
+
+ Copyright (C) 1986-2014 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef COMMON_EXCEPTIONS_H
+#define COMMON_EXCEPTIONS_H
+
+#include "gdb_setjmp.h"
+
+/* Reasons for calling throw_exceptions(). NOTE: all reason values
+ must be less than zero. enum value 0 is reserved for internal use
+ as the return value from an initial setjmp(). The function
+ catch_exceptions() reserves values >= 0 as legal results from its
+ wrapped function. */
+
+enum return_reason
+ {
+ /* User interrupt. */
+ RETURN_QUIT = -2,
+ /* Any other error. */
+ RETURN_ERROR
+ };
+
+#define RETURN_MASK(reason) (1 << (int)(-reason))
+
+typedef enum
+{
+ RETURN_MASK_QUIT = RETURN_MASK (RETURN_QUIT),
+ RETURN_MASK_ERROR = RETURN_MASK (RETURN_ERROR),
+ RETURN_MASK_ALL = (RETURN_MASK_QUIT | RETURN_MASK_ERROR)
+} return_mask;
+
+/* Describe all exceptions. */
+
+enum errors {
+ GDB_NO_ERROR,
+
+ /* Any generic error, the corresponding text is in
+ exception.message. */
+ GENERIC_ERROR,
+
+ /* Something requested was not found. */
+ NOT_FOUND_ERROR,
+
+ /* Thread library lacks support necessary for finding thread local
+ storage. */
+ TLS_NO_LIBRARY_SUPPORT_ERROR,
+
+ /* Load module not found while attempting to find thread local storage. */
+ TLS_LOAD_MODULE_NOT_FOUND_ERROR,
+
+ /* Thread local storage has not been allocated yet. */
+ TLS_NOT_ALLOCATED_YET_ERROR,
+
+ /* Something else went wrong while attempting to find thread local
+ storage. The ``struct gdb_exception'' message field provides
+ more detail. */
+ TLS_GENERIC_ERROR,
+
+ /* Problem parsing an XML document. */
+ XML_PARSE_ERROR,
+
+ /* Error accessing memory. */
+ MEMORY_ERROR,
+
+ /* Value not available. E.g., a register was not collected in a
+ traceframe. */
+ NOT_AVAILABLE_ERROR,
+
+ /* Value was optimized out. Note: if the value was a register, this
+ means the register was not saved in the frame. */
+ OPTIMIZED_OUT_ERROR,
+
+ /* DW_OP_GNU_entry_value resolving failed. */
+ NO_ENTRY_VALUE_ERROR,
+
+ /* Target throwing an error has been closed. Current command should be
+ aborted as the inferior state is no longer valid. */
+ TARGET_CLOSE_ERROR,
+
+ /* An undefined command was executed. */
+ UNDEFINED_COMMAND_ERROR,
+
+ /* Requested feature, method, mechanism, etc. is not supported. */
+ NOT_SUPPORTED_ERROR,
+
+ /* Add more errors here. */
+ NR_ERRORS
+};
+
+struct gdb_exception
+{
+ enum return_reason reason;
+ enum errors error;
+ const char *message;
+};
+
+/* Functions to drive the exceptions state machine. Though declared
+ here by necessity, these functions should be considered internal to
+ the exceptions subsystem and not used other than via the TRY_CATCH
+ macro defined below. */
+
+extern SIGJMP_BUF *exceptions_state_mc_init (volatile struct
+ gdb_exception *exception,
+ return_mask mask);
+extern int exceptions_state_mc_action_iter (void);
+extern int exceptions_state_mc_action_iter_1 (void);
+
+/* Macro to wrap up standard try/catch behavior.
+
+ The double loop lets us correctly handle code "break"ing out of the
+ try catch block. (It works as the "break" only exits the inner
+ "while" loop, the outer for loop detects this handling it
+ correctly.) Of course "return" and "goto" are not so lucky.
+
+ For instance:
+
+ *INDENT-OFF*
+
+ volatile struct gdb_exception e;
+ TRY_CATCH (e, RETURN_MASK_ERROR)
+ {
+ }
+ switch (e.reason)
+ {
+ case RETURN_ERROR: ...
+ }
+
+ */
+
+#define TRY_CATCH(EXCEPTION,MASK) \
+ { \
+ SIGJMP_BUF *buf = \
+ exceptions_state_mc_init (&(EXCEPTION), (MASK)); \
+ SIGSETJMP (*buf); \
+ } \
+ while (exceptions_state_mc_action_iter ()) \
+ while (exceptions_state_mc_action_iter_1 ())
+
+/* *INDENT-ON* */
+
+/* Hook to allow client-specific actions to be performed prior to
+ throwing an exception. This function must be provided by the
+ client, and will be called before any cleanups are run. */
+
+extern void prepare_to_throw_exception (void);
+
+/* Throw an exception (as described by "struct gdb_exception"). Will
+ execute a LONG JUMP to the inner most containing exception handler
+ established using catch_exceptions() (or similar).
+
+ Code normally throws an exception using error() et.al. For various
+ reaons, GDB also contains code that throws an exception directly.
+ For instance, the remote*.c targets contain CNTRL-C signal handlers
+ that propogate the QUIT event up the exception chain. ``This could
+ be a good thing or a dangerous thing.'' -- the Existential
+ Wombat. */
+
+extern void throw_exception (struct gdb_exception exception)
+ ATTRIBUTE_NORETURN;
+extern void throw_verror (enum errors, const char *fmt, va_list ap)
+ ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (2, 0);
+extern void throw_vquit (const char *fmt, va_list ap)
+ ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (1, 0);
+extern void throw_error (enum errors error, const char *fmt, ...)
+ ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (2, 3);
+extern void throw_quit (const char *fmt, ...)
+ ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (1, 2);
+
+#endif /* COMMON_EXCEPTIONS_H */
diff --git a/gdb/exceptions.c b/gdb/exceptions.c
index 99a147c..5533758 100644
--- a/gdb/exceptions.c
+++ b/gdb/exceptions.c
@@ -29,207 +29,11 @@
const struct gdb_exception exception_none = { 0, GDB_NO_ERROR, NULL };
-/* Possible catcher states. */
-enum catcher_state {
- /* Initial state, a new catcher has just been created. */
- CATCHER_CREATED,
- /* The catch code is running. */
- CATCHER_RUNNING,
- CATCHER_RUNNING_1,
- /* The catch code threw an exception. */
- CATCHER_ABORTING
-};
-
-/* Possible catcher actions. */
-enum catcher_action {
- CATCH_ITER,
- CATCH_ITER_1,
- CATCH_THROWING
-};
-
-struct catcher
-{
- enum catcher_state state;
- /* Jump buffer pointing back at the exception handler. */
- SIGJMP_BUF buf;
- /* Status buffer belonging to the exception handler. */
- volatile struct gdb_exception *exception;
- /* Saved/current state. */
- int mask;
- struct cleanup *saved_cleanup_chain;
- /* Back link. */
- struct catcher *prev;
-};
-
-/* Where to go for throw_exception(). */
-static struct catcher *current_catcher;
-
-/* Return length of current_catcher list. */
-
-static int
-catcher_list_size (void)
-{
- int size;
- struct catcher *catcher;
-
- for (size = 0, catcher = current_catcher;
- catcher != NULL;
- catcher = catcher->prev)
- ++size;
-
- return size;
-}
-
-SIGJMP_BUF *
-exceptions_state_mc_init (volatile struct gdb_exception *exception,
- return_mask mask)
-{
- struct catcher *new_catcher = XCNEW (struct catcher);
-
- /* Start with no exception, save it's address. */
- exception->reason = 0;
- exception->error = GDB_NO_ERROR;
- exception->message = NULL;
- new_catcher->exception = exception;
-
- new_catcher->mask = mask;
-
- /* Prevent error/quit during FUNC from calling cleanups established
- prior to here. */
- new_catcher->saved_cleanup_chain = save_cleanups ();
-
- /* Push this new catcher on the top. */
- new_catcher->prev = current_catcher;
- current_catcher = new_catcher;
- new_catcher->state = CATCHER_CREATED;
-
- return &new_catcher->buf;
-}
-
-static void
-catcher_pop (void)
-{
- struct catcher *old_catcher = current_catcher;
-
- current_catcher = old_catcher->prev;
-
- /* Restore the cleanup chain, the error/quit messages, and the uiout
- builder, to their original states. */
-
- restore_cleanups (old_catcher->saved_cleanup_chain);
-
- xfree (old_catcher);
-}
-
-/* Catcher state machine. Returns non-zero if the m/c should be run
- again, zero if it should abort. */
-
-static int
-exceptions_state_mc (enum catcher_action action)
-{
- switch (current_catcher->state)
- {
- case CATCHER_CREATED:
- switch (action)
- {
- case CATCH_ITER:
- /* Allow the code to run the catcher. */
- current_catcher->state = CATCHER_RUNNING;
- return 1;
- default:
- internal_error (__FILE__, __LINE__, _("bad state"));
- }
- case CATCHER_RUNNING:
- switch (action)
- {
- case CATCH_ITER:
- /* No error/quit has occured. Just clean up. */
- catcher_pop ();
- return 0;
- case CATCH_ITER_1:
- current_catcher->state = CATCHER_RUNNING_1;
- return 1;
- case CATCH_THROWING:
- current_catcher->state = CATCHER_ABORTING;
- /* See also throw_exception. */
- return 1;
- default:
- internal_error (__FILE__, __LINE__, _("bad switch"));
- }
- case CATCHER_RUNNING_1:
- switch (action)
- {
- case CATCH_ITER:
- /* The did a "break" from the inner while loop. */
- catcher_pop ();
- return 0;
- case CATCH_ITER_1:
- current_catcher->state = CATCHER_RUNNING;
- return 0;
- case CATCH_THROWING:
- current_catcher->state = CATCHER_ABORTING;
- /* See also throw_exception. */
- return 1;
- default:
- internal_error (__FILE__, __LINE__, _("bad switch"));
- }
- case CATCHER_ABORTING:
- switch (action)
- {
- case CATCH_ITER:
- {
- struct gdb_exception exception = *current_catcher->exception;
-
- if (current_catcher->mask & RETURN_MASK (exception.reason))
- {
- /* Exit normally if this catcher can handle this
- exception. The caller analyses the func return
- values. */
- catcher_pop ();
- return 0;
- }
- /* The caller didn't request that the event be caught,
- relay the event to the next containing
- catch_errors(). */
- catcher_pop ();
- throw_exception (exception);
- }
- default:
- internal_error (__FILE__, __LINE__, _("bad state"));
- }
- default:
- internal_error (__FILE__, __LINE__, _("bad switch"));
- }
-}
-
-int
-exceptions_state_mc_action_iter (void)
-{
- return exceptions_state_mc (CATCH_ITER);
-}
-
-int
-exceptions_state_mc_action_iter_1 (void)
-{
- return exceptions_state_mc (CATCH_ITER_1);
-}
-
-/* Return EXCEPTION to the nearest containing catch_errors(). */
-
void
-throw_exception (struct gdb_exception exception)
+prepare_to_throw_exception (void)
{
clear_quit_flag ();
immediate_quit = 0;
-
- do_cleanups (all_cleanups ());
-
- /* Jump to the containing catch_errors() call, communicating REASON
- to that call via setjmp's return value. Note that REASON can't
- be zero, by definition in defs.h. */
- exceptions_state_mc (CATCH_THROWING);
- *current_catcher->exception = exception;
- SIGLONGJMP (current_catcher->buf, exception.reason);
}
static void
@@ -329,90 +133,6 @@ exception_fprintf (struct ui_file *file, struct gdb_exception e,
}
}
-/* A stack of exception messages.
- This is needed to handle nested calls to throw_it: we don't want to
- xfree space for a message before it's used.
- This can happen if we throw an exception during a cleanup:
- An outer TRY_CATCH may have an exception message it wants to print,
- but while doing cleanups further calls to throw_it are made.
-
- This is indexed by the size of the current_catcher list.
- It is a dynamically allocated array so that we don't care how deeply
- GDB nests its TRY_CATCHs. */
-static char **exception_messages;
-
-/* The number of currently allocated entries in exception_messages. */
-static int exception_messages_size;
-
-static void ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (3, 0)
-throw_it (enum return_reason reason, enum errors error, const char *fmt,
- va_list ap)
-{
- struct gdb_exception e;
- char *new_message;
- int depth = catcher_list_size ();
-
- gdb_assert (depth > 0);
-
- /* Note: The new message may use an old message's text. */
- new_message = xstrvprintf (fmt, ap);
-
- if (depth > exception_messages_size)
- {
- int old_size = exception_messages_size;
-
- exception_messages_size = depth + 10;
- exception_messages = (char **) xrealloc (exception_messages,
- exception_messages_size
- * sizeof (char *));
- memset (exception_messages + old_size, 0,
- (exception_messages_size - old_size) * sizeof (char *));
- }
-
- xfree (exception_messages[depth - 1]);
- exception_messages[depth - 1] = new_message;
-
- /* Create the exception. */
- e.reason = reason;
- e.error = error;
- e.message = new_message;
-
- /* Throw the exception. */
- throw_exception (e);
-}
-
-void
-throw_verror (enum errors error, const char *fmt, va_list ap)
-{
- throw_it (RETURN_ERROR, error, fmt, ap);
-}
-
-void
-throw_vquit (const char *fmt, va_list ap)
-{
- throw_it (RETURN_QUIT, GDB_NO_ERROR, fmt, ap);
-}
-
-void
-throw_error (enum errors error, const char *fmt, ...)
-{
- va_list args;
-
- va_start (args, fmt);
- throw_verror (error, fmt, args);
- va_end (args);
-}
-
-void
-throw_quit (const char *fmt, ...)
-{
- va_list args;
-
- va_start (args, fmt);
- throw_vquit (fmt, args);
- va_end (args);
-}
-
/* Call FUNC(UIOUT, FUNC_ARGS) but wrapped within an exception
handler. If an exception (enum return_reason) is thrown using
throw_exception() than all cleanups installed since
diff --git a/gdb/exceptions.h b/gdb/exceptions.h
index e3ff672..00d2b61 100644
--- a/gdb/exceptions.h
+++ b/gdb/exceptions.h
@@ -20,142 +20,12 @@
#ifndef EXCEPTIONS_H
#define EXCEPTIONS_H
+#include "common-exceptions.h"
#include "ui-out.h"
-#include "gdb_setjmp.h"
-
-/* Reasons for calling throw_exceptions(). NOTE: all reason values
- must be less than zero. enum value 0 is reserved for internal use
- as the return value from an initial setjmp(). The function
- catch_exceptions() reserves values >= 0 as legal results from its
- wrapped function. */
-
-enum return_reason
- {
- /* User interrupt. */
- RETURN_QUIT = -2,
- /* Any other error. */
- RETURN_ERROR
- };
-
-#define RETURN_MASK(reason) (1 << (int)(-reason))
-
-typedef enum
-{
- RETURN_MASK_QUIT = RETURN_MASK (RETURN_QUIT),
- RETURN_MASK_ERROR = RETURN_MASK (RETURN_ERROR),
- RETURN_MASK_ALL = (RETURN_MASK_QUIT | RETURN_MASK_ERROR)
-} return_mask;
-
-/* Describe all exceptions. */
-
-enum errors {
- GDB_NO_ERROR,
-
- /* Any generic error, the corresponding text is in
- exception.message. */
- GENERIC_ERROR,
-
- /* Something requested was not found. */
- NOT_FOUND_ERROR,
-
- /* Thread library lacks support necessary for finding thread local
- storage. */
- TLS_NO_LIBRARY_SUPPORT_ERROR,
-
- /* Load module not found while attempting to find thread local storage. */
- TLS_LOAD_MODULE_NOT_FOUND_ERROR,
-
- /* Thread local storage has not been allocated yet. */
- TLS_NOT_ALLOCATED_YET_ERROR,
-
- /* Something else went wrong while attempting to find thread local
- storage. The ``struct gdb_exception'' message field provides
- more detail. */
- TLS_GENERIC_ERROR,
-
- /* Problem parsing an XML document. */
- XML_PARSE_ERROR,
-
- /* Error accessing memory. */
- MEMORY_ERROR,
-
- /* Value not available. E.g., a register was not collected in a
- traceframe. */
- NOT_AVAILABLE_ERROR,
-
- /* Value was optimized out. Note: if the value was a register, this
- means the register was not saved in the frame. */
- OPTIMIZED_OUT_ERROR,
-
- /* DW_OP_GNU_entry_value resolving failed. */
- NO_ENTRY_VALUE_ERROR,
-
- /* Target throwing an error has been closed. Current command should be
- aborted as the inferior state is no longer valid. */
- TARGET_CLOSE_ERROR,
-
- /* An undefined command was executed. */
- UNDEFINED_COMMAND_ERROR,
-
- /* Requested feature, method, mechanism, etc. is not supported. */
- NOT_SUPPORTED_ERROR,
-
- /* Add more errors here. */
- NR_ERRORS
-};
-
-struct gdb_exception
-{
- enum return_reason reason;
- enum errors error;
- const char *message;
-};
/* A pre-defined non-exception. */
extern const struct gdb_exception exception_none;
-/* Functions to drive the exceptions state m/c (internal to
- exceptions). */
-SIGJMP_BUF *exceptions_state_mc_init (volatile struct
- gdb_exception *exception,
- return_mask mask);
-int exceptions_state_mc_action_iter (void);
-int exceptions_state_mc_action_iter_1 (void);
-
-/* Macro to wrap up standard try/catch behavior.
-
- The double loop lets us correctly handle code "break"ing out of the
- try catch block. (It works as the "break" only exits the inner
- "while" loop, the outer for loop detects this handling it
- correctly.) Of course "return" and "goto" are not so lucky.
-
- For instance:
-
- *INDENT-OFF*
-
- volatile struct gdb_exception e;
- TRY_CATCH (e, RETURN_MASK_ERROR)
- {
- }
- switch (e.reason)
- {
- case RETURN_ERROR: ...
- }
-
- */
-
-#define TRY_CATCH(EXCEPTION,MASK) \
- { \
- SIGJMP_BUF *buf = \
- exceptions_state_mc_init (&(EXCEPTION), (MASK)); \
- SIGSETJMP (*buf); \
- } \
- while (exceptions_state_mc_action_iter ()) \
- while (exceptions_state_mc_action_iter_1 ())
-
-/* *INDENT-ON* */
-
-
/* If E is an exception, print it's error message on the specified
stream. For _fprintf, prefix the message with PREFIX... */
extern void exception_print (struct ui_file *file, struct gdb_exception e);
@@ -163,28 +33,6 @@ extern void exception_fprintf (struct ui_file *file, struct gdb_exception e,
const char *prefix,
...) ATTRIBUTE_PRINTF (3, 4);
-/* Throw an exception (as described by "struct gdb_exception"). Will
- execute a LONG JUMP to the inner most containing exception handler
- established using catch_exceptions() (or similar).
-
- Code normally throws an exception using error() et.al. For various
- reaons, GDB also contains code that throws an exception directly.
- For instance, the remote*.c targets contain CNTRL-C signal handlers
- that propogate the QUIT event up the exception chain. ``This could
- be a good thing or a dangerous thing.'' -- the Existential
- Wombat. */
-
-extern void throw_exception (struct gdb_exception exception)
- ATTRIBUTE_NORETURN;
-extern void throw_verror (enum errors, const char *fmt, va_list ap)
- ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (2, 0);
-extern void throw_vquit (const char *fmt, va_list ap)
- ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (1, 0);
-extern void throw_error (enum errors error, const char *fmt, ...)
- ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (2, 3);
-extern void throw_quit (const char *fmt, ...)
- ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (1, 2);
-
/* Call FUNC(UIOUT, FUNC_ARGS) but wrapped within an exception
handler. If an exception (enum return_reason) is thrown using
throw_exception() than all cleanups installed since
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index f130082..21ac6f2 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -170,7 +170,8 @@ SFILES= $(srcdir)/gdbreplay.c $(srcdir)/inferiors.c $(srcdir)/dll.c \
$(srcdir)/common/filestuff.c $(srcdir)/target/waitstatus.c \
$(srcdir)/nat/mips-linux-watch.c $(srcdir)/common/print-utils.c \
$(srcdir)/common/rsp-low.c $(srcdir)/common/errors.c \
- $(srcdir)/common/common-debug.c $(srcdir)/common/cleanups.c
+ $(srcdir)/common/common-debug.c $(srcdir)/common/cleanups.c \
+ $(srcdir)/common/common-exceptions.c
DEPFILES = @GDBSERVER_DEPFILES@
@@ -184,6 +185,7 @@ OBS = agent.o ax.o inferiors.o regcache.o remote-utils.o server.o signals.o \
mem-break.o hostio.o event-loop.o tracepoint.o xml-utils.o \
common-utils.o ptid.o buffer.o format.o filestuff.o dll.o notif.o \
tdesc.o print-utils.o rsp-low.o errors.o common-debug.o cleanups.o \
+ common-exceptions.o \
$(XML_BUILTIN) $(DEPFILES) $(LIBOBJS)
GDBREPLAY_OBS = gdbreplay.o version.o
GDBSERVER_LIBS = @GDBSERVER_LIBS@
@@ -547,6 +549,9 @@ common-debug.o: ../common/common-debug.c
cleanups.o: ../common/cleanups.c
$(COMPILE) $<
$(POSTCOMPILE)
+common-exceptions.o: ../common/common-exceptions.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
waitstatus.o: ../target/waitstatus.c
$(COMPILE) $<
$(POSTCOMPILE)
diff --git a/gdb/gdbserver/utils.c b/gdb/gdbserver/utils.c
index 3ec4add..6283877 100644
--- a/gdb/gdbserver/utils.c
+++ b/gdb/gdbserver/utils.c
@@ -160,3 +160,11 @@ pfildes (gdb_fildes_t fd)
return plongest (fd);
#endif
}
+
+/* See common/common-exceptions.h. */
+
+void
+prepare_to_throw_exception (void)
+{
+ /* No client-specific actions required. */
+}
--
1.7.1
^ permalink raw reply [flat|nested] 14+ messages in thread* [PATCH 5/5] Use exceptions and cleanups in gdbserver
2014-08-18 8:47 [PATCH 0/5] Make gdbserver use exceptions and cleanups Gary Benson
` (3 preceding siblings ...)
2014-08-18 8:52 ` [PATCH 4/5] Introduce common/common-exceptions.[ch] Gary Benson
@ 2014-08-18 9:25 ` Gary Benson
2014-08-28 15:35 ` Pedro Alves
2014-08-28 15:39 ` [PATCH 0/5] Make gdbserver use exceptions and cleanups Pedro Alves
5 siblings, 1 reply; 14+ messages in thread
From: Gary Benson @ 2014-08-18 9:25 UTC (permalink / raw)
To: gdb-patches
This commit replaces the hacky "exception" system in gdbserver with
the exceptions and cleanups subsystem from GDB.
Only the catch/cleanup code in what was "main" has been updated to
use the new system. Other parts of gdbserver could likely be
converted to TRY_CATCH and cleanups too, but that can be done on an
as-needed basis if this patch is accepted.
A side-effect of this patch is that some error messages will change
slightly, and in cases with multiple errors the error messages will
be printed in a different order.
gdb/gdbserver/
2014-08-18 Gary Benson <gbenson@redhat.com>
* server.h (setjmp.h): Do not include.
(toplevel): Do not declare.
* server.c (common-exceptions.h): Include.
(cleanups.h): Likewise.
(toplevel): Do not define.
(exit_code): New static global.
(detach_or_kill_for_exit_cleanup): New function.
(main): New function. Original main renamed to...
(captured_main): New function.
* utils.c (common-exceptions.h): Include.
(verror) [!IN_PROCESS_AGENT]: Use throw_verror.
---
gdb/gdbserver/ChangeLog | 14 ++++
gdb/gdbserver/server.c | 196 ++++++++++++++++++++++++++---------------------
gdb/gdbserver/server.h | 4 -
gdb/gdbserver/utils.c | 11 +--
4 files changed, 127 insertions(+), 98 deletions(-)
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 500260c..aec70f0 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -35,6 +35,8 @@
#include "tracepoint.h"
#include "dll.h"
#include "hostio.h"
+#include "common-exceptions.h"
+#include "cleanups.h"
/* The thread set with an `Hc' packet. `Hc' is deprecated in favor of
`vCont'. Note the multi-process extensions made `vCont' a
@@ -73,8 +75,6 @@ int pass_signals[GDB_SIGNAL_LAST];
int program_signals[GDB_SIGNAL_LAST];
int program_signals_p;
-jmp_buf toplevel;
-
/* The PID of the originally created or attached inferior. Used to
send signals to the process when GDB sends us an asynchronous interrupt
(user hitting Control-C in the client), and to wait for the child to exit
@@ -3010,8 +3010,34 @@ detach_or_kill_for_exit (void)
for_each_inferior (&all_processes, detach_or_kill_inferior_callback);
}
-int
-main (int argc, char *argv[])
+/* Value that will be passed to exit(3) when gdbserver exits. */
+static int exit_code;
+
+/* Cleanup version of detach_or_kill_for_exit. */
+
+static void
+detach_or_kill_for_exit_cleanup (void *ignore)
+{
+ volatile struct gdb_exception exception;
+
+ TRY_CATCH (exception, RETURN_MASK_ALL)
+ {
+ detach_or_kill_for_exit ();
+ }
+
+ if (exception.reason < 0)
+ {
+ fflush (stdout);
+ fprintf (stderr, "Detach or kill failed: %s\n", exception.message);
+ exit_code = 1;
+ }
+}
+
+/* Main function. This is called by the real "main" function,
+ wrapped in a TRY_CATCH that handles any uncaught exceptions. */
+
+static void ATTRIBUTE_NORETURN
+captured_main (int argc, char *argv[])
{
int bad_attach;
int pid;
@@ -3135,12 +3161,6 @@ main (int argc, char *argv[])
continue;
}
- if (setjmp (toplevel))
- {
- fprintf (stderr, "Exiting\n");
- exit (1);
- }
-
port = *next_arg;
next_arg++;
if (port == NULL || (!attach && !multi_mode && *next_arg == NULL))
@@ -3223,6 +3243,7 @@ main (int argc, char *argv[])
last_status.value.integer = 0;
last_ptid = minus_one_ptid;
}
+ make_cleanup (detach_or_kill_for_exit_cleanup, NULL);
initialize_notif ();
@@ -3231,19 +3252,6 @@ main (int argc, char *argv[])
shared library event" notice on gdb side. */
dlls_changed = 0;
- if (setjmp (toplevel))
- {
- /* If something fails and longjmps while detaching or killing
- inferiors, we'd end up here again, stuck in an infinite loop
- trap. Be sure that if that happens, we exit immediately
- instead. */
- if (setjmp (toplevel) == 0)
- detach_or_kill_for_exit ();
- else
- fprintf (stderr, "Detach or kill failed. Exiting\n");
- exit (1);
- }
-
if (last_status.kind == TARGET_WAITKIND_EXITED
|| last_status.kind == TARGET_WAITKIND_SIGNALLED)
was_running = 0;
@@ -3251,13 +3259,12 @@ main (int argc, char *argv[])
was_running = 1;
if (!was_running && !multi_mode)
- {
- fprintf (stderr, "No program to debug. GDBserver exiting.\n");
- exit (1);
- }
+ error ("No program to debug");
while (1)
{
+ volatile struct gdb_exception exception;
+
noack_mode = 0;
multi_process = 0;
/* Be sure we're out of tfind mode. */
@@ -3265,82 +3272,97 @@ main (int argc, char *argv[])
remote_open (port);
- if (setjmp (toplevel) != 0)
+ TRY_CATCH (exception, RETURN_MASK_ERROR)
{
- /* An error occurred. */
- if (response_needed)
- {
- write_enn (own_buf);
- putpkt (own_buf);
- }
- }
-
- /* Wait for events. This will return when all event sources are
- removed from the event loop. */
- start_event_loop ();
+ /* Wait for events. This will return when all event sources
+ are removed from the event loop. */
+ start_event_loop ();
- /* If an exit was requested (using the "monitor exit" command),
- terminate now. The only other way to get here is for
- getpkt to fail; close the connection and reopen it at the
- top of the loop. */
+ /* If an exit was requested (using the "monitor exit"
+ command), terminate now. The only other way to get
+ here is for getpkt to fail; close the connection
+ and reopen it at the top of the loop. */
- if (exit_requested || run_once)
- {
- /* If something fails and longjmps while detaching or
- killing inferiors, we'd end up here again, stuck in an
- infinite loop trap. Be sure that if that happens, we
- exit immediately instead. */
- if (setjmp (toplevel) == 0)
- {
- detach_or_kill_for_exit ();
- exit (0);
- }
- else
- {
- fprintf (stderr, "Detach or kill failed. Exiting\n");
- exit (1);
- }
- }
+ if (exit_requested || run_once)
+ throw_quit ("Quit");
- fprintf (stderr,
- "Remote side has terminated connection. "
- "GDBserver will reopen the connection.\n");
+ fprintf (stderr,
+ "Remote side has terminated connection. "
+ "GDBserver will reopen the connection.\n");
- /* Get rid of any pending statuses. An eventual reconnection
- (by the same GDB instance or another) will refresh all its
- state from scratch. */
- discard_queued_stop_replies (-1);
- for_each_inferior (&all_threads, clear_pending_status_callback);
+ /* Get rid of any pending statuses. An eventual reconnection
+ (by the same GDB instance or another) will refresh all its
+ state from scratch. */
+ discard_queued_stop_replies (-1);
+ for_each_inferior (&all_threads,
+ clear_pending_status_callback);
- if (tracing)
- {
- if (disconnected_tracing)
+ if (tracing)
{
- /* Try to enable non-stop/async mode, so we we can both
- wait for an async socket accept, and handle async
- target events simultaneously. There's also no point
- either in having the target always stop all threads,
- when we're going to pass signals down without
- informing GDB. */
- if (!non_stop)
+ if (disconnected_tracing)
{
- if (start_non_stop (1))
- non_stop = 1;
+ /* Try to enable non-stop/async mode, so we we can
+ both wait for an async socket accept, and handle
+ async target events simultaneously. There's also
+ no point either in having the target always stop
+ all threads, when we're going to pass signals
+ down without informing GDB. */
+ if (!non_stop)
+ {
+ if (start_non_stop (1))
+ non_stop = 1;
- /* Detaching implicitly resumes all threads; simply
- disconnecting does not. */
+ /* Detaching implicitly resumes all threads;
+ simply disconnecting does not. */
+ }
+ }
+ else
+ {
+ fprintf (stderr,
+ "Disconnected tracing disabled; "
+ "stopping trace run.\n");
+ stop_tracing ();
}
}
- else
+ }
+
+ if (exception.reason == RETURN_ERROR)
+ {
+ if (response_needed)
{
- fprintf (stderr,
- "Disconnected tracing disabled; stopping trace run.\n");
- stop_tracing ();
+ write_enn (own_buf);
+ putpkt (own_buf);
}
}
}
}
+/* Main function. */
+
+int
+main (int argc, char *argv[])
+{
+ volatile struct gdb_exception exception;
+
+ TRY_CATCH (exception, RETURN_MASK_ALL)
+ {
+ captured_main (argc, argv);
+ }
+
+ /* captured_main should never return. */
+ gdb_assert (exception.reason < 0);
+
+ if (exception.reason == RETURN_ERROR)
+ {
+ fflush (stdout);
+ fprintf (stderr, "%s\n", exception.message);
+ fprintf (stderr, "Exiting\n");
+ exit_code = 1;
+ }
+
+ exit (exit_code);
+}
+
/* Skip PACKET until the next semi-colon (or end of string). */
static void
diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h
index 97498a6..cac73e9 100644
--- a/gdb/gdbserver/server.h
+++ b/gdb/gdbserver/server.h
@@ -29,8 +29,6 @@ gdb_static_assert (sizeof (CORE_ADDR) >= sizeof (void *));
#include "version.h"
-#include <setjmp.h>
-
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#endif
@@ -88,8 +86,6 @@ extern int pass_signals[];
extern int program_signals[];
extern int program_signals_p;
-extern jmp_buf toplevel;
-
extern int disable_packet_vCont;
extern int disable_packet_Tthread;
extern int disable_packet_qC;
diff --git a/gdb/gdbserver/utils.c b/gdb/gdbserver/utils.c
index 6283877..e2eb4f4 100644
--- a/gdb/gdbserver/utils.c
+++ b/gdb/gdbserver/utils.c
@@ -17,6 +17,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "server.h"
+#include "common-exceptions.h"
#ifdef IN_PROCESS_AGENT
# define PREFIX "ipa: "
@@ -76,17 +77,13 @@ perror_with_name (const char *string)
void
verror (const char *string, va_list args)
{
-#ifndef IN_PROCESS_AGENT
- extern jmp_buf toplevel;
-#endif
-
+#ifdef IN_PROCESS_AGENT
fflush (stdout);
vfprintf (stderr, string, args);
fprintf (stderr, "\n");
-#ifndef IN_PROCESS_AGENT
- longjmp (toplevel, 1);
-#else
exit (1);
+#else
+ throw_verror (GENERIC_ERROR, string, args);
#endif
}
--
1.7.1
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [PATCH 5/5] Use exceptions and cleanups in gdbserver
2014-08-18 9:25 ` [PATCH 5/5] Use exceptions and cleanups in gdbserver Gary Benson
@ 2014-08-28 15:35 ` Pedro Alves
0 siblings, 0 replies; 14+ messages in thread
From: Pedro Alves @ 2014-08-28 15:35 UTC (permalink / raw)
To: Gary Benson, gdb-patches
On 08/18/2014 09:46 AM, Gary Benson wrote:
> diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h
> index 97498a6..cac73e9 100644
> diff --git a/gdb/gdbserver/utils.c b/gdb/gdbserver/utils.c
> index 6283877..e2eb4f4 100644
> --- a/gdb/gdbserver/utils.c
> +++ b/gdb/gdbserver/utils.c
> @@ -17,6 +17,7 @@
> along with this program. If not, see <http://www.gnu.org/licenses/>. */
>
> #include "server.h"
> +#include "common-exceptions.h"
>
...
> diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
> index 500260c..aec70f0 100644
> --- a/gdb/gdbserver/server.c
> +++ b/gdb/gdbserver/server.c
> @@ -35,6 +35,8 @@
> #include "tracepoint.h"
> #include "dll.h"
> #include "hostio.h"
> +#include "common-exceptions.h"
> +#include "cleanups.h"
We'll want to start using exceptions/cleanups everywhere.
We'll no doubt end up including them from a central place, either
server.h or somewhere in common/. I think we should just put
them in server.h already ...
> --- a/gdb/gdbserver/server.h
> +++ b/gdb/gdbserver/server.h
> @@ -29,8 +29,6 @@ gdb_static_assert (sizeof (CORE_ADDR) >= sizeof (void *));
>
> #include "version.h"
>
> -#include <setjmp.h>
> -
> #ifdef HAVE_ALLOCA_H
> #include <alloca.h>
> #endif
> @@ -88,8 +86,6 @@ extern int pass_signals[];
> extern int program_signals[];
> extern int program_signals_p;
>
> -extern jmp_buf toplevel;
> -
> extern int disable_packet_vCont;
> extern int disable_packet_Tthread;
> extern int disable_packet_qC;
... which is the same place we had the bare bones setjmp stuff,
avoiding the sprinkling-includes-around-only-to-inevitably-remove-them-later.
This way, even if we move them somewhere in common/ at some point, we'll
still have only a single place to touch.
Other than that, looks good.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 0/5] Make gdbserver use exceptions and cleanups
2014-08-18 8:47 [PATCH 0/5] Make gdbserver use exceptions and cleanups Gary Benson
` (4 preceding siblings ...)
2014-08-18 9:25 ` [PATCH 5/5] Use exceptions and cleanups in gdbserver Gary Benson
@ 2014-08-28 15:39 ` Pedro Alves
2014-08-29 10:07 ` Gary Benson
5 siblings, 1 reply; 14+ messages in thread
From: Pedro Alves @ 2014-08-28 15:39 UTC (permalink / raw)
To: Gary Benson, gdb-patches
On 08/18/2014 09:46 AM, Gary Benson wrote:
> gdbserver has the rudiments of an exception system, but it's kind of
> hacky. This series converts gdbserver to use the same exceptions and
> cleanups as GDB.
>
> This series is fairly minimal in that only the catch/cleanup code in
> what was "main" has been updated to use the new system. Other parts
> of gdbserver could likely be converted to TRY_CATCH and cleanups too,
> but that can be done on an as-needed basis if this patch is accepted.
>
> A side-effect of this patch is that some error messages will change
> slightly, and in cases with multiple errors the error messages will
> be printed in a different order.
>
> Built and regtested on RHEL 6.5 x86_64.
>
> Ok to commit?
Other than the minor nits I just picked in the responses to the
patches, this looks great to me.
Thanks a lot for doing this.
Pedro Alves
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [PATCH 0/5] Make gdbserver use exceptions and cleanups
2014-08-28 15:39 ` [PATCH 0/5] Make gdbserver use exceptions and cleanups Pedro Alves
@ 2014-08-29 10:07 ` Gary Benson
0 siblings, 0 replies; 14+ messages in thread
From: Gary Benson @ 2014-08-29 10:07 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
Pedro Alves wrote:
> On 08/18/2014 09:46 AM, Gary Benson wrote:
> > gdbserver has the rudiments of an exception system, but it's
> > kind of hacky. This series converts gdbserver to use the
> > same exceptions and cleanups as GDB.
> >
> > This series is fairly minimal in that only the catch/cleanup code
> > in what was "main" has been updated to use the new system. Other
> > parts of gdbserver could likely be converted to TRY_CATCH and
> > cleanups too, but that can be done on an as-needed basis if this
> > patch is accepted.
> >
> > A side-effect of this patch is that some error messages will
> > change slightly, and in cases with multiple errors the error
> > messages will be printed in a different order.
> >
> > Built and regtested on RHEL 6.5 x86_64.
> >
> > Ok to commit?
>
> Other than the minor nits I just picked in the responses to the
> patches, this looks great to me.
>
> Thanks a lot for doing this.
No problem, thanks for the review :)
I've pushed this with the changes you suggested.
common-exceptions.h and cleanups.h are now included in server.h.
They're not global includes in GDB, but I could put together a
patch making them so if you like? Let me know...
Thanks,
Gary
--
http://gbenson.net/
^ permalink raw reply [flat|nested] 14+ messages in thread