Don't assume break/continue inside a TRY block works
In C++, this: try { break; } catch (..) {} is invalid. However, because our TRY/CATCH macros support it in C, the C++ version of those macros support it too. To catch such assumptions, this adds a (disabled) hack that maps TRY/CATCH to raw C++ try/catch. Then it goes through all instances that building on x86_64 GNU/Linux trips on, fixing them. This isn't strictly necessary yet, but I think it's nicer to try to keep the tree in a state where it's easier to eliminate the TRY/CATCH macros. gdb/ChangeLog: 2015-10-29 Pedro Alves <palves@redhat.com> * dwarf2-frame-tailcall.c (dwarf2_tailcall_sniffer_first): Don't assume that "break" breaks out of a TRY/CATCH. * python/py-framefilter.c (py_print_single_arg): Don't assume "continue" breaks out of a TRY/CATCH. * python/py-value.c (valpy_binop_throw): New function, factored out from ... (valpy_binop): ... this. (valpy_richcompare_throw): New function, factored out from ... (valpy_richcompare): ... this. * solib.c (solib_read_symbols): Don't assume "break" breaks out of a TRY/CATCH. * common/common-exceptions.h [USE_RAW_CXX_TRY] <TRY/CATCH/END_CATCH>: Define as 1-1 wrappers around try/catch.
This commit is contained in:
parent
f82aa1657b
commit
9c6595ab68
6 changed files with 269 additions and 202 deletions
|
@ -1,3 +1,20 @@
|
||||||
|
2015-10-29 Pedro Alves <palves@redhat.com>
|
||||||
|
|
||||||
|
* dwarf2-frame-tailcall.c (dwarf2_tailcall_sniffer_first): Don't
|
||||||
|
assume that "break" breaks out of a TRY/CATCH.
|
||||||
|
* python/py-framefilter.c (py_print_single_arg): Don't assume
|
||||||
|
"continue" breaks out of a TRY/CATCH.
|
||||||
|
* python/py-value.c (valpy_binop_throw): New function, factored
|
||||||
|
out from ...
|
||||||
|
(valpy_binop): ... this.
|
||||||
|
(valpy_richcompare_throw): New function, factored
|
||||||
|
out from ...
|
||||||
|
(valpy_richcompare): ... this.
|
||||||
|
* solib.c (solib_read_symbols): Don't assume "break" breaks out
|
||||||
|
of a TRY/CATCH.
|
||||||
|
* common/common-exceptions.h [USE_RAW_CXX_TRY]
|
||||||
|
<TRY/CATCH/END_CATCH>: Define as 1-1 wrappers around try/catch.
|
||||||
|
|
||||||
2015-10-28 Simon Dardis <Simon.Dardis@imgtec.com>
|
2015-10-28 Simon Dardis <Simon.Dardis@imgtec.com>
|
||||||
|
|
||||||
* mips-linux-tdep.c (mips_linux_in_dynsym_stub): Recognise 'or'
|
* mips-linux-tdep.c (mips_linux_in_dynsym_stub): Recognise 'or'
|
||||||
|
|
|
@ -195,6 +195,14 @@ struct exception_try_scope
|
||||||
void *saved_state;
|
void *saved_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Define this to build with TRY/CATCH mapped directly to raw
|
||||||
|
try/catch. GDB won't work correctly, but building that way catches
|
||||||
|
code tryin to break/continue out of the try block, along with
|
||||||
|
spurious code between the TRY and the CATCH block. */
|
||||||
|
//#define USE_RAW_CXX_TRY
|
||||||
|
|
||||||
|
#ifndef USE_RAW_CXX_TRY
|
||||||
|
|
||||||
/* We still need to wrap TRY/CATCH in C++ so that cleanups and C++
|
/* We still need to wrap TRY/CATCH in C++ so that cleanups and C++
|
||||||
exceptions can coexist. The TRY blocked is wrapped in a
|
exceptions can coexist. The TRY blocked is wrapped in a
|
||||||
do/while(0) so that break/continue within the block works the same
|
do/while(0) so that break/continue within the block works the same
|
||||||
|
@ -216,6 +224,14 @@ struct exception_try_scope
|
||||||
{ \
|
{ \
|
||||||
exception_rethrow (); \
|
exception_rethrow (); \
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define TRY try
|
||||||
|
#define CATCH(EXCEPTION, MASK) \
|
||||||
|
catch (struct gdb_exception ## _ ## MASK &EXCEPTION)
|
||||||
|
#define END_CATCH
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/* The exception types client code may catch. They're just shims
|
/* The exception types client code may catch. They're just shims
|
||||||
around gdb_exception that add nothing but type info. Which is used
|
around gdb_exception that add nothing but type info. Which is used
|
||||||
|
|
|
@ -386,14 +386,16 @@ dwarf2_tailcall_sniffer_first (struct frame_info *this_frame,
|
||||||
/* call_site_find_chain can throw an exception. */
|
/* call_site_find_chain can throw an exception. */
|
||||||
chain = call_site_find_chain (prev_gdbarch, prev_pc, this_pc);
|
chain = call_site_find_chain (prev_gdbarch, prev_pc, this_pc);
|
||||||
|
|
||||||
if (entry_cfa_sp_offsetp == NULL)
|
if (entry_cfa_sp_offsetp != NULL)
|
||||||
break;
|
{
|
||||||
sp_regnum = gdbarch_sp_regnum (prev_gdbarch);
|
sp_regnum = gdbarch_sp_regnum (prev_gdbarch);
|
||||||
if (sp_regnum == -1)
|
if (sp_regnum != -1)
|
||||||
break;
|
{
|
||||||
prev_sp = frame_unwind_register_unsigned (this_frame, sp_regnum);
|
prev_sp = frame_unwind_register_unsigned (this_frame, sp_regnum);
|
||||||
prev_sp_p = 1;
|
prev_sp_p = 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
CATCH (except, RETURN_MASK_ERROR)
|
CATCH (except, RETURN_MASK_ERROR)
|
||||||
{
|
{
|
||||||
if (entry_values_debug)
|
if (entry_values_debug)
|
||||||
|
|
|
@ -448,10 +448,11 @@ py_print_single_arg (struct ui_out *out,
|
||||||
{
|
{
|
||||||
retval = EXT_LANG_BT_ERROR;
|
retval = EXT_LANG_BT_ERROR;
|
||||||
do_cleanups (cleanups);
|
do_cleanups (cleanups);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (retval != EXT_LANG_BT_ERROR)
|
||||||
|
{
|
||||||
if (val != NULL)
|
if (val != NULL)
|
||||||
annotate_arg_value (value_type (val));
|
annotate_arg_value (value_type (val));
|
||||||
|
|
||||||
|
@ -480,6 +481,7 @@ py_print_single_arg (struct ui_out *out,
|
||||||
|
|
||||||
do_cleanups (cleanups);
|
do_cleanups (cleanups);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
CATCH (except, RETURN_MASK_ERROR)
|
CATCH (except, RETURN_MASK_ERROR)
|
||||||
{
|
{
|
||||||
gdbpy_convert_exception (except);
|
gdbpy_convert_exception (except);
|
||||||
|
|
|
@ -1018,38 +1018,38 @@ enum valpy_opcode
|
||||||
#define STRIP_REFERENCE(TYPE) \
|
#define STRIP_REFERENCE(TYPE) \
|
||||||
((TYPE_CODE (TYPE) == TYPE_CODE_REF) ? (TYPE_TARGET_TYPE (TYPE)) : (TYPE))
|
((TYPE_CODE (TYPE) == TYPE_CODE_REF) ? (TYPE_TARGET_TYPE (TYPE)) : (TYPE))
|
||||||
|
|
||||||
/* Returns a value object which is the result of applying the operation
|
/* Helper for valpy_binop. Returns a value object which is the result
|
||||||
specified by OPCODE to the given arguments. Returns NULL on error, with
|
of applying the operation specified by OPCODE to the given
|
||||||
a python exception set. */
|
arguments. Throws a GDB exception on error. */
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other)
|
valpy_binop_throw (enum valpy_opcode opcode, PyObject *self, PyObject *other)
|
||||||
{
|
{
|
||||||
PyObject *result = NULL;
|
PyObject *result = NULL;
|
||||||
|
|
||||||
TRY
|
|
||||||
{
|
|
||||||
struct value *arg1, *arg2;
|
struct value *arg1, *arg2;
|
||||||
struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
|
struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
|
||||||
struct value *res_val = NULL;
|
struct value *res_val = NULL;
|
||||||
enum exp_opcode op = OP_NULL;
|
enum exp_opcode op = OP_NULL;
|
||||||
int handled = 0;
|
int handled = 0;
|
||||||
|
|
||||||
/* If the gdb.Value object is the second operand, then it will be passed
|
/* If the gdb.Value object is the second operand, then it will be
|
||||||
to us as the OTHER argument, and SELF will be an entirely different
|
passed to us as the OTHER argument, and SELF will be an entirely
|
||||||
kind of object, altogether. Because of this, we can't assume self is
|
different kind of object, altogether. Because of this, we can't
|
||||||
a gdb.Value object and need to convert it from python as well. */
|
assume self is a gdb.Value object and need to convert it from
|
||||||
|
python as well. */
|
||||||
arg1 = convert_value_from_python (self);
|
arg1 = convert_value_from_python (self);
|
||||||
if (arg1 == NULL)
|
if (arg1 == NULL)
|
||||||
{
|
{
|
||||||
do_cleanups (cleanup);
|
do_cleanups (cleanup);
|
||||||
break;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
arg2 = convert_value_from_python (other);
|
arg2 = convert_value_from_python (other);
|
||||||
if (arg2 == NULL)
|
if (arg2 == NULL)
|
||||||
{
|
{
|
||||||
do_cleanups (cleanup);
|
do_cleanups (cleanup);
|
||||||
break;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (opcode)
|
switch (opcode)
|
||||||
|
@ -1145,6 +1145,20 @@ valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other)
|
||||||
result = value_to_value_object (res_val);
|
result = value_to_value_object (res_val);
|
||||||
|
|
||||||
do_cleanups (cleanup);
|
do_cleanups (cleanup);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns a value object which is the result of applying the operation
|
||||||
|
specified by OPCODE to the given arguments. Returns NULL on error, with
|
||||||
|
a python exception set. */
|
||||||
|
static PyObject *
|
||||||
|
valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other)
|
||||||
|
{
|
||||||
|
PyObject *result = NULL;
|
||||||
|
|
||||||
|
TRY
|
||||||
|
{
|
||||||
|
result = valpy_binop_throw (opcode, self, other);
|
||||||
}
|
}
|
||||||
CATCH (except, RETURN_MASK_ALL)
|
CATCH (except, RETURN_MASK_ALL)
|
||||||
{
|
{
|
||||||
|
@ -1351,6 +1365,63 @@ valpy_xor (PyObject *self, PyObject *other)
|
||||||
return valpy_binop (VALPY_BITXOR, self, other);
|
return valpy_binop (VALPY_BITXOR, self, other);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Helper for valpy_richcompare. Implements comparison operations for
|
||||||
|
value objects. Returns true/false on success. Returns -1 with a
|
||||||
|
Python exception set if a Python error is detected. Throws a GDB
|
||||||
|
exception on other errors (memory error, etc.). */
|
||||||
|
|
||||||
|
static int
|
||||||
|
valpy_richcompare_throw (PyObject *self, PyObject *other, int op)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
struct value *value_other;
|
||||||
|
struct value *value_self;
|
||||||
|
struct value *mark = value_mark ();
|
||||||
|
struct cleanup *cleanup;
|
||||||
|
|
||||||
|
value_other = convert_value_from_python (other);
|
||||||
|
if (value_other == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
cleanup = make_cleanup_value_free_to_mark (mark);
|
||||||
|
|
||||||
|
value_self = ((value_object *) self)->value;
|
||||||
|
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case Py_LT:
|
||||||
|
result = value_less (value_self, value_other);
|
||||||
|
break;
|
||||||
|
case Py_LE:
|
||||||
|
result = value_less (value_self, value_other)
|
||||||
|
|| value_equal (value_self, value_other);
|
||||||
|
break;
|
||||||
|
case Py_EQ:
|
||||||
|
result = value_equal (value_self, value_other);
|
||||||
|
break;
|
||||||
|
case Py_NE:
|
||||||
|
result = !value_equal (value_self, value_other);
|
||||||
|
break;
|
||||||
|
case Py_GT:
|
||||||
|
result = value_less (value_other, value_self);
|
||||||
|
break;
|
||||||
|
case Py_GE:
|
||||||
|
result = (value_less (value_other, value_self)
|
||||||
|
|| value_equal (value_self, value_other));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Can't happen. */
|
||||||
|
PyErr_SetString (PyExc_NotImplementedError,
|
||||||
|
_("Invalid operation on gdb.Value."));
|
||||||
|
result = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
do_cleanups (cleanup);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Implements comparison operations for value objects. Returns NULL on error,
|
/* Implements comparison operations for value objects. Returns NULL on error,
|
||||||
with a python exception set. */
|
with a python exception set. */
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -1379,48 +1450,7 @@ valpy_richcompare (PyObject *self, PyObject *other, int op)
|
||||||
|
|
||||||
TRY
|
TRY
|
||||||
{
|
{
|
||||||
struct value *value_other, *mark = value_mark ();
|
result = valpy_richcompare_throw (self, other, op);
|
||||||
struct cleanup *cleanup;
|
|
||||||
|
|
||||||
value_other = convert_value_from_python (other);
|
|
||||||
if (value_other == NULL)
|
|
||||||
{
|
|
||||||
result = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup = make_cleanup_value_free_to_mark (mark);
|
|
||||||
|
|
||||||
switch (op) {
|
|
||||||
case Py_LT:
|
|
||||||
result = value_less (((value_object *) self)->value, value_other);
|
|
||||||
break;
|
|
||||||
case Py_LE:
|
|
||||||
result = value_less (((value_object *) self)->value, value_other)
|
|
||||||
|| value_equal (((value_object *) self)->value, value_other);
|
|
||||||
break;
|
|
||||||
case Py_EQ:
|
|
||||||
result = value_equal (((value_object *) self)->value, value_other);
|
|
||||||
break;
|
|
||||||
case Py_NE:
|
|
||||||
result = !value_equal (((value_object *) self)->value, value_other);
|
|
||||||
break;
|
|
||||||
case Py_GT:
|
|
||||||
result = value_less (value_other, ((value_object *) self)->value);
|
|
||||||
break;
|
|
||||||
case Py_GE:
|
|
||||||
result = value_less (value_other, ((value_object *) self)->value)
|
|
||||||
|| value_equal (((value_object *) self)->value, value_other);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* Can't happen. */
|
|
||||||
PyErr_SetString (PyExc_NotImplementedError,
|
|
||||||
_("Invalid operation on gdb.Value."));
|
|
||||||
result = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
do_cleanups (cleanup);
|
|
||||||
}
|
}
|
||||||
CATCH (except, RETURN_MASK_ALL)
|
CATCH (except, RETURN_MASK_ALL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -696,9 +696,8 @@ solib_read_symbols (struct so_list *so, int flags)
|
||||||
&& so->objfile->addr_low == so->addr_low)
|
&& so->objfile->addr_low == so->addr_low)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (so->objfile != NULL)
|
if (so->objfile == NULL)
|
||||||
break;
|
{
|
||||||
|
|
||||||
sap = build_section_addr_info_from_section_table (so->sections,
|
sap = build_section_addr_info_from_section_table (so->sections,
|
||||||
so->sections_end);
|
so->sections_end);
|
||||||
so->objfile = symbol_file_add_from_bfd (so->abfd, so->so_name,
|
so->objfile = symbol_file_add_from_bfd (so->abfd, so->so_name,
|
||||||
|
@ -706,6 +705,7 @@ solib_read_symbols (struct so_list *so, int flags)
|
||||||
NULL);
|
NULL);
|
||||||
so->objfile->addr_low = so->addr_low;
|
so->objfile->addr_low = so->addr_low;
|
||||||
free_section_addr_info (sap);
|
free_section_addr_info (sap);
|
||||||
|
}
|
||||||
|
|
||||||
so->symbols_loaded = 1;
|
so->symbols_loaded = 1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue