mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-10-19 22:03:57 +08:00
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.
This commit is contained in:
@ -1,3 +1,17 @@
|
|||||||
|
2013-04-15 Tom Tromey <tromey@redhat.com>
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
2013-04-15 Tom Tromey <tromey@redhat.com>
|
2013-04-15 Tom Tromey <tromey@redhat.com>
|
||||||
|
|
||||||
* break-catch-throw.c (struct exception_names): New.
|
* break-catch-throw.c (struct exception_names): New.
|
||||||
|
3
gdb/NEWS
3
gdb/NEWS
@ -105,6 +105,9 @@ Tilera TILE-Gx GNU/Linux tilegx*-*-linux
|
|||||||
|
|
||||||
* 'info proc' now works on some core files.
|
* 'info proc' now works on some core files.
|
||||||
|
|
||||||
|
* The new convenience variable $_exception holds the exception being
|
||||||
|
thrown or caught at an exception-related catchpoint.
|
||||||
|
|
||||||
* Python scripting
|
* Python scripting
|
||||||
|
|
||||||
** Vectors can be created with gdb.Type.vector.
|
** Vectors can be created with gdb.Type.vector.
|
||||||
|
@ -32,6 +32,8 @@
|
|||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "linespec.h"
|
#include "linespec.h"
|
||||||
#include "probe.h"
|
#include "probe.h"
|
||||||
|
#include "objfiles.h"
|
||||||
|
#include "cp-abi.h"
|
||||||
|
|
||||||
/* Enums for exception-handling support. */
|
/* Enums for exception-handling support. */
|
||||||
enum exception_event_kind
|
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
|
static void
|
||||||
initialize_throw_catchpoint_ops (void)
|
initialize_throw_catchpoint_ops (void)
|
||||||
{
|
{
|
||||||
@ -370,4 +427,6 @@ Catch an exception, when rethrown."),
|
|||||||
NULL,
|
NULL,
|
||||||
CATCH_PERMANENT,
|
CATCH_PERMANENT,
|
||||||
CATCH_TEMPORARY);
|
CATCH_TEMPORARY);
|
||||||
|
|
||||||
|
create_internalvar_type_lazy ("_exception", &exception_funcs, NULL);
|
||||||
}
|
}
|
||||||
|
10
gdb/cp-abi.c
10
gdb/cp-abi.c
@ -199,6 +199,16 @@ cplus_typeid_type (struct gdbarch *gdbarch)
|
|||||||
return (*current_cp_abi.get_typeid_type) (gdbarch);
|
return (*current_cp_abi.get_typeid_type) (gdbarch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* See cp-abi.h. */
|
||||||
|
|
||||||
|
struct type *
|
||||||
|
cplus_type_from_type_info (struct value *value)
|
||||||
|
{
|
||||||
|
if (current_cp_abi.get_type_from_type_info == NULL)
|
||||||
|
error (_("GDB cannot find the type from a std::type_info on this target"));
|
||||||
|
return (*current_cp_abi.get_type_from_type_info) (value);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
cp_pass_by_reference (struct type *type)
|
cp_pass_by_reference (struct type *type)
|
||||||
{
|
{
|
||||||
|
@ -188,6 +188,12 @@ extern struct value *cplus_typeid (struct value *value);
|
|||||||
|
|
||||||
extern struct type *cplus_typeid_type (struct gdbarch *gdbarch);
|
extern struct type *cplus_typeid_type (struct gdbarch *gdbarch);
|
||||||
|
|
||||||
|
/* Given a value which holds a pointer to a std::type_info, return the
|
||||||
|
type which that type_info represents. Throw an exception if the
|
||||||
|
type cannot be found. */
|
||||||
|
|
||||||
|
extern struct type *cplus_type_from_type_info (struct value *value);
|
||||||
|
|
||||||
/* Determine if we are currently in a C++ thunk. If so, get the
|
/* Determine if we are currently in a C++ thunk. If so, get the
|
||||||
address of the routine we are thunking to and continue to there
|
address of the routine we are thunking to and continue to there
|
||||||
instead. */
|
instead. */
|
||||||
@ -231,6 +237,7 @@ struct cp_abi_ops
|
|||||||
void (*print_vtable) (struct value *);
|
void (*print_vtable) (struct value *);
|
||||||
struct value *(*get_typeid) (struct value *value);
|
struct value *(*get_typeid) (struct value *value);
|
||||||
struct type *(*get_typeid_type) (struct gdbarch *gdbarch);
|
struct type *(*get_typeid_type) (struct gdbarch *gdbarch);
|
||||||
|
struct type *(*get_type_from_type_info) (struct value *value);
|
||||||
CORE_ADDR (*skip_trampoline) (struct frame_info *, CORE_ADDR);
|
CORE_ADDR (*skip_trampoline) (struct frame_info *, CORE_ADDR);
|
||||||
int (*pass_by_reference) (struct type *type);
|
int (*pass_by_reference) (struct type *type);
|
||||||
};
|
};
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
2013-04-15 Tom Tromey <tromey@redhat.com>
|
||||||
|
|
||||||
|
* gdb.texinfo (Set Catchpoints): Document $_exception.
|
||||||
|
(Convenience Vars): Mention $_exception.
|
||||||
|
|
||||||
2013-04-15 Tom Tromey <tromey@redhat.com>
|
2013-04-15 Tom Tromey <tromey@redhat.com>
|
||||||
|
|
||||||
* gdb.texinfo (Set Catchpoints): Reorganize exception
|
* gdb.texinfo (Set Catchpoints): Reorganize exception
|
||||||
|
@ -4080,6 +4080,11 @@ Stop when @var{event} occurs. @var{event} can be any of the following:
|
|||||||
@cindex stop on C@t{++} exceptions
|
@cindex stop on C@t{++} exceptions
|
||||||
The throwing, re-throwing, or catching of a C@t{++} exception.
|
The throwing, re-throwing, or catching of a C@t{++} exception.
|
||||||
|
|
||||||
|
@vindex $_exception@r{, convenience variable}
|
||||||
|
The convenience variable @code{$_exception} is available at an
|
||||||
|
exception-related catchpoint, on some systems. This holds the
|
||||||
|
exception being thrown.
|
||||||
|
|
||||||
There are currently some limitations to C@t{++} exception handling in
|
There are currently some limitations to C@t{++} exception handling in
|
||||||
@value{GDBN}:
|
@value{GDBN}:
|
||||||
|
|
||||||
@ -4089,6 +4094,15 @@ The support for these commands is system-dependent. Currently, only
|
|||||||
systems using the @samp{gnu-v3} C@t{++} ABI (@pxref{ABI}) are
|
systems using the @samp{gnu-v3} C@t{++} ABI (@pxref{ABI}) are
|
||||||
supported.
|
supported.
|
||||||
|
|
||||||
|
@item
|
||||||
|
The @code{$_exception} convenience variable relies on the presence of
|
||||||
|
some SDT probes in @code{libstdc++}. If these probes are not present,
|
||||||
|
then this variable cannot be used.
|
||||||
|
|
||||||
|
@item
|
||||||
|
The @code{$_exception} convenience variable is only valid at the
|
||||||
|
instruction at which an exception-related catchpoint is set.
|
||||||
|
|
||||||
@item
|
@item
|
||||||
When an exception-related catchpoint is hit, @value{GDBN} stops at a
|
When an exception-related catchpoint is hit, @value{GDBN} stops at a
|
||||||
location in the system library which implements runtime exception
|
location in the system library which implements runtime exception
|
||||||
@ -9510,6 +9524,10 @@ to match the format in which the data was printed.
|
|||||||
The variable @code{$_exitcode} is automatically set to the exit code when
|
The variable @code{$_exitcode} is automatically set to the exit code when
|
||||||
the program being debugged terminates.
|
the program being debugged terminates.
|
||||||
|
|
||||||
|
@item $_exception
|
||||||
|
The variable @code{$_exception} is set to the exception object being
|
||||||
|
thrown at an exception-related catchpoint. @xref{Set Catchpoints}.
|
||||||
|
|
||||||
@item $_probe_argc
|
@item $_probe_argc
|
||||||
@itemx $_probe_arg0@dots{}$_probe_arg11
|
@itemx $_probe_arg0@dots{}$_probe_arg11
|
||||||
Arguments to a static probe. @xref{Static Probe Points}.
|
Arguments to a static probe. @xref{Static Probe Points}.
|
||||||
|
@ -1138,6 +1138,69 @@ gnuv3_get_typeid (struct value *value)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get the type name given a type_info object. */
|
||||||
|
|
||||||
|
static char *
|
||||||
|
gnuv3_get_typename_from_type_info (struct value *type_info_ptr)
|
||||||
|
{
|
||||||
|
struct gdbarch *gdbarch = get_type_arch (value_type (type_info_ptr));
|
||||||
|
struct bound_minimal_symbol typeinfo_sym;
|
||||||
|
CORE_ADDR addr;
|
||||||
|
const char *symname;
|
||||||
|
const char *class_name;
|
||||||
|
const char *atsign;
|
||||||
|
|
||||||
|
addr = value_as_address (type_info_ptr);
|
||||||
|
typeinfo_sym = lookup_minimal_symbol_by_pc (addr);
|
||||||
|
if (typeinfo_sym.minsym == NULL)
|
||||||
|
error (_("could not find minimal symbol for typeinfo address %s"),
|
||||||
|
paddress (gdbarch, addr));
|
||||||
|
|
||||||
|
#define TYPEINFO_PREFIX "typeinfo for "
|
||||||
|
#define TYPEINFO_PREFIX_LEN (sizeof (TYPEINFO_PREFIX) - 1)
|
||||||
|
symname = SYMBOL_DEMANGLED_NAME (typeinfo_sym.minsym);
|
||||||
|
if (symname == NULL || strncmp (symname, TYPEINFO_PREFIX,
|
||||||
|
TYPEINFO_PREFIX_LEN))
|
||||||
|
error (_("typeinfo symbol '%s' has unexpected name"),
|
||||||
|
SYMBOL_LINKAGE_NAME (typeinfo_sym.minsym));
|
||||||
|
class_name = symname + TYPEINFO_PREFIX_LEN;
|
||||||
|
|
||||||
|
/* Strip off @plt and version suffixes. */
|
||||||
|
atsign = strchr (class_name, '@');
|
||||||
|
if (atsign != NULL)
|
||||||
|
return savestring (class_name, atsign - class_name);
|
||||||
|
return xstrdup (class_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Implement the 'get_type_from_type_info' method. */
|
||||||
|
|
||||||
|
static struct type *
|
||||||
|
gnuv3_get_type_from_type_info (struct value *type_info_ptr)
|
||||||
|
{
|
||||||
|
char *typename;
|
||||||
|
struct cleanup *cleanup;
|
||||||
|
struct value *type_val;
|
||||||
|
struct expression *expr;
|
||||||
|
struct type *result;
|
||||||
|
|
||||||
|
typename = gnuv3_get_typename_from_type_info (type_info_ptr);
|
||||||
|
cleanup = make_cleanup (xfree, typename);
|
||||||
|
|
||||||
|
/* We have to parse the type name, since in general there is not a
|
||||||
|
symbol for a type. This is somewhat bogus since there may be a
|
||||||
|
mis-parse. Another approach might be to re-use the demangler's
|
||||||
|
internal form to reconstruct the type somehow. */
|
||||||
|
|
||||||
|
expr = parse_expression (typename);
|
||||||
|
make_cleanup (xfree, expr);
|
||||||
|
|
||||||
|
type_val = evaluate_type (expr);
|
||||||
|
result = value_type (type_val);
|
||||||
|
|
||||||
|
do_cleanups (cleanup);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* Determine if we are currently in a C++ thunk. If so, get the address
|
/* Determine if we are currently in a C++ thunk. If so, get the address
|
||||||
of the routine we are thunking to and continue to there instead. */
|
of the routine we are thunking to and continue to there instead. */
|
||||||
|
|
||||||
@ -1292,6 +1355,7 @@ init_gnuv3_ops (void)
|
|||||||
gnu_v3_abi_ops.print_vtable = gnuv3_print_vtable;
|
gnu_v3_abi_ops.print_vtable = gnuv3_print_vtable;
|
||||||
gnu_v3_abi_ops.get_typeid = gnuv3_get_typeid;
|
gnu_v3_abi_ops.get_typeid = gnuv3_get_typeid;
|
||||||
gnu_v3_abi_ops.get_typeid_type = gnuv3_get_typeid_type;
|
gnu_v3_abi_ops.get_typeid_type = gnuv3_get_typeid_type;
|
||||||
|
gnu_v3_abi_ops.get_type_from_type_info = gnuv3_get_type_from_type_info;
|
||||||
gnu_v3_abi_ops.skip_trampoline = gnuv3_skip_trampoline;
|
gnu_v3_abi_ops.skip_trampoline = gnuv3_skip_trampoline;
|
||||||
gnu_v3_abi_ops.pass_by_reference = gnuv3_pass_by_reference;
|
gnu_v3_abi_ops.pass_by_reference = gnuv3_pass_by_reference;
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
2013-04-15 Tom Tromey <tromey@redhat.com>
|
||||||
|
|
||||||
|
* 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.
|
||||||
|
|
||||||
2013-04-15 Tom Tromey <tromey@redhat.com>
|
2013-04-15 Tom Tromey <tromey@redhat.com>
|
||||||
|
|
||||||
* gdb.cp/typeid.cc: New file.
|
* gdb.cp/typeid.cc: New file.
|
||||||
|
@ -604,6 +604,7 @@ set show_conv_list \
|
|||||||
{$_sdata = void} \
|
{$_sdata = void} \
|
||||||
{$_siginfo = void} \
|
{$_siginfo = void} \
|
||||||
{$_thread = 0} \
|
{$_thread = 0} \
|
||||||
|
{$_exception = <error: No frame selected>} \
|
||||||
{$_probe_argc = <error: No frame selected>} \
|
{$_probe_argc = <error: No frame selected>} \
|
||||||
{$_probe_arg0 = <error: No frame selected>} \
|
{$_probe_arg0 = <error: No frame selected>} \
|
||||||
{$_probe_arg1 = <error: No frame selected>} \
|
{$_probe_arg1 = <error: No frame selected>} \
|
||||||
|
65
gdb/testsuite/gdb.cp/exceptprint.cc
Normal file
65
gdb/testsuite/gdb.cp/exceptprint.cc
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/* This testcase is part of GDB, the GNU debugger.
|
||||||
|
|
||||||
|
Copyright 2013 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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/>. */
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void
|
||||||
|
throwit (T val)
|
||||||
|
{
|
||||||
|
throw val;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void
|
||||||
|
rethrowit (T val)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
throwit (val);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
// Ignore.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct maude
|
||||||
|
{
|
||||||
|
int mv;
|
||||||
|
|
||||||
|
maude (int x) : mv (x) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
maude mm (77);
|
||||||
|
maude &mmm (mm);
|
||||||
|
|
||||||
|
rethrowit ("hi bob");
|
||||||
|
rethrowit (23);
|
||||||
|
rethrowit (mm);
|
||||||
|
rethrowit (mmm);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
73
gdb/testsuite/gdb.cp/exceptprint.exp
Normal file
73
gdb/testsuite/gdb.cp/exceptprint.exp
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
# Copyright 2013 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
standard_testfile .cc
|
||||||
|
|
||||||
|
if {[skip_cplus_tests]} {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[prepare_for_testing $testfile.exp $testfile $srcfile {debug c++}]} {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if {![runto_main]} {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if {![skip_libstdcxx_probe_tests]} {
|
||||||
|
untested "could not find libstdc++ stap probe"
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
proc do_continue_to_catchpoint {name} {
|
||||||
|
global gdb_prompt
|
||||||
|
|
||||||
|
gdb_test_multiple "continue" $name {
|
||||||
|
-re "Continuing.*Catchpoint \[0-9\].*\r\n$gdb_prompt $" {
|
||||||
|
pass $name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
proc do_exceptprint_tests {prefix output} {
|
||||||
|
with_test_prefix $prefix {
|
||||||
|
do_continue_to_catchpoint "continue to throw"
|
||||||
|
gdb_test "print \$_exception" " = $output" \
|
||||||
|
"print exception value at throw"
|
||||||
|
|
||||||
|
do_continue_to_catchpoint "continue to catch"
|
||||||
|
gdb_test "print \$_exception" " = $output" \
|
||||||
|
"print exception value at catch"
|
||||||
|
|
||||||
|
do_continue_to_catchpoint "continue to rethrow"
|
||||||
|
gdb_test "print \$_exception" " = $output" \
|
||||||
|
"print exception value at rethrow"
|
||||||
|
|
||||||
|
do_continue_to_catchpoint "continue to final catch"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_test "catch catch" "Catchpoint \[0-9\]+ \\(catch\\)" \
|
||||||
|
"catch catch"
|
||||||
|
gdb_test "catch throw" "Catchpoint \[0-9\]+ \\(throw\\)" \
|
||||||
|
"catch throw"
|
||||||
|
gdb_test "catch rethrow" "Catchpoint \[0-9\]+ \\(rethrow\\)" \
|
||||||
|
"catch rethrow"
|
||||||
|
|
||||||
|
do_exceptprint_tests string "$hex \"hi bob\""
|
||||||
|
do_exceptprint_tests int 23
|
||||||
|
do_exceptprint_tests struct "{mv = 77}"
|
||||||
|
do_exceptprint_tests "reference to struct" "{mv = 77}"
|
@ -2310,6 +2310,24 @@ proc skip_unwinder_tests {} {
|
|||||||
return $ok
|
return $ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Return 0 if we should skip tests that require the libstdc++ stap
|
||||||
|
# probes. This must be invoked while gdb is running, after shared
|
||||||
|
# libraries have been loaded.
|
||||||
|
|
||||||
|
proc skip_libstdcxx_probe_tests {} {
|
||||||
|
global gdb_prompt
|
||||||
|
|
||||||
|
set ok 0
|
||||||
|
gdb_test_multiple "info probe" "check for stap probe in libstdc++" {
|
||||||
|
-re ".*libstdcxx.*catch.*\r\n$gdb_prompt $" {
|
||||||
|
set ok 1
|
||||||
|
}
|
||||||
|
-re "\r\n$gdb_prompt $" {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $ok
|
||||||
|
}
|
||||||
|
|
||||||
set compiler_info "unknown"
|
set compiler_info "unknown"
|
||||||
set gcc_compiled 0
|
set gcc_compiled 0
|
||||||
set hp_cc_compiler 0
|
set hp_cc_compiler 0
|
||||||
|
Reference in New Issue
Block a user