summaryrefslogtreecommitdiff
path: root/gdb/break-catch-throw.c
diff options
context:
space:
mode:
authorTom Tromey <tromey@redhat.com>2013-04-15 18:09:01 +0000
committerTom Tromey <tromey@redhat.com>2013-04-15 18:09:01 +0000
commit28af0d6627b6dd8059011ea5ba8ca81ce6530673 (patch)
tree885b531650d31efb00070e821e7d0a61b505fa35 /gdb/break-catch-throw.c
parent57e585c7379ae9b187ff75dca72e4bc4448cbac3 (diff)
downloadgdb-28af0d6627b6dd8059011ea5ba8ca81ce6530673.tar.gz
PR c++/15176:
* NEWS: Update. * break-catch-throw.c (compute_exception): New function. (exception_funcs): New global. (_initialize_break_catch_throw): Create $_exception. * cp-abi.c (cplus_type_from_type_info): New function. * cp-abi.h (cplus_type_from_type_info): Declare. (struct cp_abi_ops) <get_type_from_type_info>: New field. * gnu-v3-abi.c (gnuv3_get_typename_from_type_info) (gnuv3_get_type_from_type_info): New functions. (init_gnuv3_ops): Set get_type_from_type_info ABI field. gdb/doc * gdb.texinfo (Set Catchpoints): Document $_exception. (Convenience Vars): Mention $_exception. gdb/testsuite * gdb.base/default.exp: Update for $_exception. * gdb.cp/exceptprint.cc: New file. * gdb.cp/exceptprint.exp: New file. * lib/gdb.exp (skip_libstdcxx_probe_tests): New proc.
Diffstat (limited to 'gdb/break-catch-throw.c')
-rw-r--r--gdb/break-catch-throw.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/gdb/break-catch-throw.c b/gdb/break-catch-throw.c
index 8b9b837f9fd..ed236ef20bf 100644
--- a/gdb/break-catch-throw.c
+++ b/gdb/break-catch-throw.c
@@ -32,6 +32,8 @@
#include "exceptions.h"
#include "linespec.h"
#include "probe.h"
+#include "objfiles.h"
+#include "cp-abi.h"
/* Enums for exception-handling support. */
enum exception_event_kind
@@ -327,6 +329,61 @@ catch_rethrow_command (char *arg, int from_tty,
+/* Implement the 'make_value' method for the $_exception
+ internalvar. */
+
+static struct value *
+compute_exception (struct gdbarch *argc, struct internalvar *var, void *ignore)
+{
+ struct frame_info *frame = get_selected_frame (_("No frame selected"));
+ CORE_ADDR pc = get_frame_pc (frame);
+ struct probe *pc_probe;
+ const struct sym_probe_fns *pc_probe_fns;
+ unsigned n_args;
+ struct value *arg0, *arg1;
+ struct type *obj_type;
+
+ pc_probe = find_probe_by_pc (pc);
+ if (pc_probe == NULL
+ || strcmp (pc_probe->provider, "libstdcxx") != 0
+ || (strcmp (pc_probe->name, "catch") != 0
+ && strcmp (pc_probe->name, "throw") != 0
+ && strcmp (pc_probe->name, "rethrow") != 0))
+ error (_("not stopped at a C++ exception catchpoint"));
+
+ gdb_assert (pc_probe->objfile != NULL);
+ gdb_assert (pc_probe->objfile->sf != NULL);
+ gdb_assert (pc_probe->objfile->sf->sym_probe_fns != NULL);
+
+ pc_probe_fns = pc_probe->objfile->sf->sym_probe_fns;
+ n_args = pc_probe_fns->sym_get_probe_argument_count (pc_probe);
+ if (n_args < 2)
+ error (_("C++ exception catchpoint has too few arguments"));
+
+ arg0 = pc_probe_fns->sym_evaluate_probe_argument (pc_probe, 0);
+ arg1 = pc_probe_fns->sym_evaluate_probe_argument (pc_probe, 1);
+
+ if (arg0 == NULL || arg1 == NULL)
+ error (_("error computing probe argument at c++ exception catchpoint"));
+
+ /* ARG0 is a pointer to the exception object. ARG1 is a pointer to
+ the std::type_info for the exception. Now we find the type from
+ the type_info and cast the result. */
+ obj_type = cplus_type_from_type_info (arg1);
+ return value_ind (value_cast (make_pointer_type (obj_type, NULL), arg0));
+}
+
+/* Implementation of the '$_exception' variable. */
+
+static const struct internalvar_funcs exception_funcs =
+{
+ compute_exception,
+ NULL,
+ NULL
+};
+
+
+
static void
initialize_throw_catchpoint_ops (void)
{
@@ -370,4 +427,6 @@ Catch an exception, when rethrown."),
NULL,
CATCH_PERMANENT,
CATCH_TEMPORARY);
+
+ create_internalvar_type_lazy ("_exception", &exception_funcs, NULL);
}