GNU Binutils with patches for OS216
Revisión | 9c6595ab6873e15fe533b05bb7b98c11f17c5d57 (tree) |
---|---|
Tiempo | 2015-10-29 21:55:01 |
Autor | Pedro Alves <palves@redh...> |
Commiter | Pedro Alves |
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.
@@ -1,3 +1,20 @@ | ||
1 | +2015-10-29 Pedro Alves <palves@redhat.com> | |
2 | + | |
3 | + * dwarf2-frame-tailcall.c (dwarf2_tailcall_sniffer_first): Don't | |
4 | + assume that "break" breaks out of a TRY/CATCH. | |
5 | + * python/py-framefilter.c (py_print_single_arg): Don't assume | |
6 | + "continue" breaks out of a TRY/CATCH. | |
7 | + * python/py-value.c (valpy_binop_throw): New function, factored | |
8 | + out from ... | |
9 | + (valpy_binop): ... this. | |
10 | + (valpy_richcompare_throw): New function, factored | |
11 | + out from ... | |
12 | + (valpy_richcompare): ... this. | |
13 | + * solib.c (solib_read_symbols): Don't assume "break" breaks out | |
14 | + of a TRY/CATCH. | |
15 | + * common/common-exceptions.h [USE_RAW_CXX_TRY] | |
16 | + <TRY/CATCH/END_CATCH>: Define as 1-1 wrappers around try/catch. | |
17 | + | |
1 | 18 | 2015-10-28 Simon Dardis <Simon.Dardis@imgtec.com> |
2 | 19 | |
3 | 20 | * mips-linux-tdep.c (mips_linux_in_dynsym_stub): Recognise 'or' |
@@ -195,6 +195,14 @@ struct exception_try_scope | ||
195 | 195 | void *saved_state; |
196 | 196 | }; |
197 | 197 | |
198 | +/* Define this to build with TRY/CATCH mapped directly to raw | |
199 | + try/catch. GDB won't work correctly, but building that way catches | |
200 | + code tryin to break/continue out of the try block, along with | |
201 | + spurious code between the TRY and the CATCH block. */ | |
202 | +//#define USE_RAW_CXX_TRY | |
203 | + | |
204 | +#ifndef USE_RAW_CXX_TRY | |
205 | + | |
198 | 206 | /* We still need to wrap TRY/CATCH in C++ so that cleanups and C++ |
199 | 207 | exceptions can coexist. The TRY blocked is wrapped in a |
200 | 208 | do/while(0) so that break/continue within the block works the same |
@@ -216,6 +224,14 @@ struct exception_try_scope | ||
216 | 224 | { \ |
217 | 225 | exception_rethrow (); \ |
218 | 226 | } |
227 | +#else | |
228 | + | |
229 | +#define TRY try | |
230 | +#define CATCH(EXCEPTION, MASK) \ | |
231 | + catch (struct gdb_exception ## _ ## MASK &EXCEPTION) | |
232 | +#define END_CATCH | |
233 | + | |
234 | +#endif | |
219 | 235 | |
220 | 236 | /* The exception types client code may catch. They're just shims |
221 | 237 | around gdb_exception that add nothing but type info. Which is used |
@@ -386,13 +386,15 @@ dwarf2_tailcall_sniffer_first (struct frame_info *this_frame, | ||
386 | 386 | /* call_site_find_chain can throw an exception. */ |
387 | 387 | chain = call_site_find_chain (prev_gdbarch, prev_pc, this_pc); |
388 | 388 | |
389 | - if (entry_cfa_sp_offsetp == NULL) | |
390 | - break; | |
391 | - sp_regnum = gdbarch_sp_regnum (prev_gdbarch); | |
392 | - if (sp_regnum == -1) | |
393 | - break; | |
394 | - prev_sp = frame_unwind_register_unsigned (this_frame, sp_regnum); | |
395 | - prev_sp_p = 1; | |
389 | + if (entry_cfa_sp_offsetp != NULL) | |
390 | + { | |
391 | + sp_regnum = gdbarch_sp_regnum (prev_gdbarch); | |
392 | + if (sp_regnum != -1) | |
393 | + { | |
394 | + prev_sp = frame_unwind_register_unsigned (this_frame, sp_regnum); | |
395 | + prev_sp_p = 1; | |
396 | + } | |
397 | + } | |
396 | 398 | } |
397 | 399 | CATCH (except, RETURN_MASK_ERROR) |
398 | 400 | { |
@@ -448,37 +448,39 @@ py_print_single_arg (struct ui_out *out, | ||
448 | 448 | { |
449 | 449 | retval = EXT_LANG_BT_ERROR; |
450 | 450 | do_cleanups (cleanups); |
451 | - continue; | |
452 | 451 | } |
453 | 452 | } |
454 | 453 | |
455 | - if (val != NULL) | |
456 | - annotate_arg_value (value_type (val)); | |
457 | - | |
458 | - /* If the output is to the CLI, and the user option "set print | |
459 | - frame-arguments" is set to none, just output "...". */ | |
460 | - if (! ui_out_is_mi_like_p (out) && args_type == NO_VALUES) | |
461 | - ui_out_field_string (out, "value", "..."); | |
462 | - else | |
454 | + if (retval != EXT_LANG_BT_ERROR) | |
463 | 455 | { |
464 | - /* Otherwise, print the value for both MI and the CLI, except | |
465 | - for the case of MI_PRINT_NO_VALUES. */ | |
466 | - if (args_type != NO_VALUES) | |
456 | + if (val != NULL) | |
457 | + annotate_arg_value (value_type (val)); | |
458 | + | |
459 | + /* If the output is to the CLI, and the user option "set print | |
460 | + frame-arguments" is set to none, just output "...". */ | |
461 | + if (! ui_out_is_mi_like_p (out) && args_type == NO_VALUES) | |
462 | + ui_out_field_string (out, "value", "..."); | |
463 | + else | |
467 | 464 | { |
468 | - if (val == NULL) | |
465 | + /* Otherwise, print the value for both MI and the CLI, except | |
466 | + for the case of MI_PRINT_NO_VALUES. */ | |
467 | + if (args_type != NO_VALUES) | |
469 | 468 | { |
470 | - gdb_assert (fa != NULL && fa->error != NULL); | |
471 | - ui_out_field_fmt (out, "value", | |
472 | - _("<error reading variable: %s>"), | |
473 | - fa->error); | |
469 | + if (val == NULL) | |
470 | + { | |
471 | + gdb_assert (fa != NULL && fa->error != NULL); | |
472 | + ui_out_field_fmt (out, "value", | |
473 | + _("<error reading variable: %s>"), | |
474 | + fa->error); | |
475 | + } | |
476 | + else if (py_print_value (out, val, opts, 0, args_type, language) | |
477 | + == EXT_LANG_BT_ERROR) | |
478 | + retval = EXT_LANG_BT_ERROR; | |
474 | 479 | } |
475 | - else if (py_print_value (out, val, opts, 0, args_type, language) | |
476 | - == EXT_LANG_BT_ERROR) | |
477 | - retval = EXT_LANG_BT_ERROR; | |
478 | 480 | } |
479 | - } | |
480 | 481 | |
481 | - do_cleanups (cleanups); | |
482 | + do_cleanups (cleanups); | |
483 | + } | |
482 | 484 | } |
483 | 485 | CATCH (except, RETURN_MASK_ERROR) |
484 | 486 | { |
@@ -1018,133 +1018,147 @@ enum valpy_opcode | ||
1018 | 1018 | #define STRIP_REFERENCE(TYPE) \ |
1019 | 1019 | ((TYPE_CODE (TYPE) == TYPE_CODE_REF) ? (TYPE_TARGET_TYPE (TYPE)) : (TYPE)) |
1020 | 1020 | |
1021 | -/* Returns a value object which is the result of applying the operation | |
1022 | - specified by OPCODE to the given arguments. Returns NULL on error, with | |
1023 | - a python exception set. */ | |
1021 | +/* Helper for valpy_binop. Returns a value object which is the result | |
1022 | + of applying the operation specified by OPCODE to the given | |
1023 | + arguments. Throws a GDB exception on error. */ | |
1024 | + | |
1024 | 1025 | static PyObject * |
1025 | -valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other) | |
1026 | +valpy_binop_throw (enum valpy_opcode opcode, PyObject *self, PyObject *other) | |
1026 | 1027 | { |
1027 | 1028 | PyObject *result = NULL; |
1028 | 1029 | |
1029 | - TRY | |
1030 | + struct value *arg1, *arg2; | |
1031 | + struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ()); | |
1032 | + struct value *res_val = NULL; | |
1033 | + enum exp_opcode op = OP_NULL; | |
1034 | + int handled = 0; | |
1035 | + | |
1036 | + /* If the gdb.Value object is the second operand, then it will be | |
1037 | + passed to us as the OTHER argument, and SELF will be an entirely | |
1038 | + different kind of object, altogether. Because of this, we can't | |
1039 | + assume self is a gdb.Value object and need to convert it from | |
1040 | + python as well. */ | |
1041 | + arg1 = convert_value_from_python (self); | |
1042 | + if (arg1 == NULL) | |
1030 | 1043 | { |
1031 | - struct value *arg1, *arg2; | |
1032 | - struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ()); | |
1033 | - struct value *res_val = NULL; | |
1034 | - enum exp_opcode op = OP_NULL; | |
1035 | - int handled = 0; | |
1036 | - | |
1037 | - /* If the gdb.Value object is the second operand, then it will be passed | |
1038 | - to us as the OTHER argument, and SELF will be an entirely different | |
1039 | - kind of object, altogether. Because of this, we can't assume self is | |
1040 | - a gdb.Value object and need to convert it from python as well. */ | |
1041 | - arg1 = convert_value_from_python (self); | |
1042 | - if (arg1 == NULL) | |
1043 | - { | |
1044 | - do_cleanups (cleanup); | |
1045 | - break; | |
1046 | - } | |
1044 | + do_cleanups (cleanup); | |
1045 | + return NULL; | |
1046 | + } | |
1047 | 1047 | |
1048 | - arg2 = convert_value_from_python (other); | |
1049 | - if (arg2 == NULL) | |
1050 | - { | |
1051 | - do_cleanups (cleanup); | |
1052 | - break; | |
1053 | - } | |
1048 | + arg2 = convert_value_from_python (other); | |
1049 | + if (arg2 == NULL) | |
1050 | + { | |
1051 | + do_cleanups (cleanup); | |
1052 | + return NULL; | |
1053 | + } | |
1054 | 1054 | |
1055 | - switch (opcode) | |
1056 | - { | |
1057 | - case VALPY_ADD: | |
1055 | + switch (opcode) | |
1056 | + { | |
1057 | + case VALPY_ADD: | |
1058 | + { | |
1059 | + struct type *ltype = value_type (arg1); | |
1060 | + struct type *rtype = value_type (arg2); | |
1061 | + | |
1062 | + ltype = check_typedef (ltype); | |
1063 | + ltype = STRIP_REFERENCE (ltype); | |
1064 | + rtype = check_typedef (rtype); | |
1065 | + rtype = STRIP_REFERENCE (rtype); | |
1066 | + | |
1067 | + handled = 1; | |
1068 | + if (TYPE_CODE (ltype) == TYPE_CODE_PTR | |
1069 | + && is_integral_type (rtype)) | |
1070 | + res_val = value_ptradd (arg1, value_as_long (arg2)); | |
1071 | + else if (TYPE_CODE (rtype) == TYPE_CODE_PTR | |
1072 | + && is_integral_type (ltype)) | |
1073 | + res_val = value_ptradd (arg2, value_as_long (arg1)); | |
1074 | + else | |
1058 | 1075 | { |
1059 | - struct type *ltype = value_type (arg1); | |
1060 | - struct type *rtype = value_type (arg2); | |
1061 | - | |
1062 | - ltype = check_typedef (ltype); | |
1063 | - ltype = STRIP_REFERENCE (ltype); | |
1064 | - rtype = check_typedef (rtype); | |
1065 | - rtype = STRIP_REFERENCE (rtype); | |
1066 | - | |
1067 | - handled = 1; | |
1068 | - if (TYPE_CODE (ltype) == TYPE_CODE_PTR | |
1069 | - && is_integral_type (rtype)) | |
1070 | - res_val = value_ptradd (arg1, value_as_long (arg2)); | |
1071 | - else if (TYPE_CODE (rtype) == TYPE_CODE_PTR | |
1072 | - && is_integral_type (ltype)) | |
1073 | - res_val = value_ptradd (arg2, value_as_long (arg1)); | |
1074 | - else | |
1075 | - { | |
1076 | - handled = 0; | |
1077 | - op = BINOP_ADD; | |
1078 | - } | |
1076 | + handled = 0; | |
1077 | + op = BINOP_ADD; | |
1079 | 1078 | } |
1080 | - break; | |
1081 | - case VALPY_SUB: | |
1079 | + } | |
1080 | + break; | |
1081 | + case VALPY_SUB: | |
1082 | + { | |
1083 | + struct type *ltype = value_type (arg1); | |
1084 | + struct type *rtype = value_type (arg2); | |
1085 | + | |
1086 | + ltype = check_typedef (ltype); | |
1087 | + ltype = STRIP_REFERENCE (ltype); | |
1088 | + rtype = check_typedef (rtype); | |
1089 | + rtype = STRIP_REFERENCE (rtype); | |
1090 | + | |
1091 | + handled = 1; | |
1092 | + if (TYPE_CODE (ltype) == TYPE_CODE_PTR | |
1093 | + && TYPE_CODE (rtype) == TYPE_CODE_PTR) | |
1094 | + /* A ptrdiff_t for the target would be preferable here. */ | |
1095 | + res_val = value_from_longest (builtin_type_pyint, | |
1096 | + value_ptrdiff (arg1, arg2)); | |
1097 | + else if (TYPE_CODE (ltype) == TYPE_CODE_PTR | |
1098 | + && is_integral_type (rtype)) | |
1099 | + res_val = value_ptradd (arg1, - value_as_long (arg2)); | |
1100 | + else | |
1082 | 1101 | { |
1083 | - struct type *ltype = value_type (arg1); | |
1084 | - struct type *rtype = value_type (arg2); | |
1085 | - | |
1086 | - ltype = check_typedef (ltype); | |
1087 | - ltype = STRIP_REFERENCE (ltype); | |
1088 | - rtype = check_typedef (rtype); | |
1089 | - rtype = STRIP_REFERENCE (rtype); | |
1090 | - | |
1091 | - handled = 1; | |
1092 | - if (TYPE_CODE (ltype) == TYPE_CODE_PTR | |
1093 | - && TYPE_CODE (rtype) == TYPE_CODE_PTR) | |
1094 | - /* A ptrdiff_t for the target would be preferable here. */ | |
1095 | - res_val = value_from_longest (builtin_type_pyint, | |
1096 | - value_ptrdiff (arg1, arg2)); | |
1097 | - else if (TYPE_CODE (ltype) == TYPE_CODE_PTR | |
1098 | - && is_integral_type (rtype)) | |
1099 | - res_val = value_ptradd (arg1, - value_as_long (arg2)); | |
1100 | - else | |
1101 | - { | |
1102 | - handled = 0; | |
1103 | - op = BINOP_SUB; | |
1104 | - } | |
1102 | + handled = 0; | |
1103 | + op = BINOP_SUB; | |
1105 | 1104 | } |
1106 | - break; | |
1107 | - case VALPY_MUL: | |
1108 | - op = BINOP_MUL; | |
1109 | - break; | |
1110 | - case VALPY_DIV: | |
1111 | - op = BINOP_DIV; | |
1112 | - break; | |
1113 | - case VALPY_REM: | |
1114 | - op = BINOP_REM; | |
1115 | - break; | |
1116 | - case VALPY_POW: | |
1117 | - op = BINOP_EXP; | |
1118 | - break; | |
1119 | - case VALPY_LSH: | |
1120 | - op = BINOP_LSH; | |
1121 | - break; | |
1122 | - case VALPY_RSH: | |
1123 | - op = BINOP_RSH; | |
1124 | - break; | |
1125 | - case VALPY_BITAND: | |
1126 | - op = BINOP_BITWISE_AND; | |
1127 | - break; | |
1128 | - case VALPY_BITOR: | |
1129 | - op = BINOP_BITWISE_IOR; | |
1130 | - break; | |
1131 | - case VALPY_BITXOR: | |
1132 | - op = BINOP_BITWISE_XOR; | |
1133 | - break; | |
1134 | - } | |
1105 | + } | |
1106 | + break; | |
1107 | + case VALPY_MUL: | |
1108 | + op = BINOP_MUL; | |
1109 | + break; | |
1110 | + case VALPY_DIV: | |
1111 | + op = BINOP_DIV; | |
1112 | + break; | |
1113 | + case VALPY_REM: | |
1114 | + op = BINOP_REM; | |
1115 | + break; | |
1116 | + case VALPY_POW: | |
1117 | + op = BINOP_EXP; | |
1118 | + break; | |
1119 | + case VALPY_LSH: | |
1120 | + op = BINOP_LSH; | |
1121 | + break; | |
1122 | + case VALPY_RSH: | |
1123 | + op = BINOP_RSH; | |
1124 | + break; | |
1125 | + case VALPY_BITAND: | |
1126 | + op = BINOP_BITWISE_AND; | |
1127 | + break; | |
1128 | + case VALPY_BITOR: | |
1129 | + op = BINOP_BITWISE_IOR; | |
1130 | + break; | |
1131 | + case VALPY_BITXOR: | |
1132 | + op = BINOP_BITWISE_XOR; | |
1133 | + break; | |
1134 | + } | |
1135 | + | |
1136 | + if (!handled) | |
1137 | + { | |
1138 | + if (binop_user_defined_p (op, arg1, arg2)) | |
1139 | + res_val = value_x_binop (arg1, arg2, op, OP_NULL, EVAL_NORMAL); | |
1140 | + else | |
1141 | + res_val = value_binop (arg1, arg2, op); | |
1142 | + } | |
1135 | 1143 | |
1136 | - if (!handled) | |
1137 | - { | |
1138 | - if (binop_user_defined_p (op, arg1, arg2)) | |
1139 | - res_val = value_x_binop (arg1, arg2, op, OP_NULL, EVAL_NORMAL); | |
1140 | - else | |
1141 | - res_val = value_binop (arg1, arg2, op); | |
1142 | - } | |
1144 | + if (res_val) | |
1145 | + result = value_to_value_object (res_val); | |
1143 | 1146 | |
1144 | - if (res_val) | |
1145 | - result = value_to_value_object (res_val); | |
1147 | + do_cleanups (cleanup); | |
1148 | + return result; | |
1149 | +} | |
1146 | 1150 | |
1147 | - do_cleanups (cleanup); | |
1151 | +/* Returns a value object which is the result of applying the operation | |
1152 | + specified by OPCODE to the given arguments. Returns NULL on error, with | |
1153 | + a python exception set. */ | |
1154 | +static PyObject * | |
1155 | +valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other) | |
1156 | +{ | |
1157 | + PyObject *result = NULL; | |
1158 | + | |
1159 | + TRY | |
1160 | + { | |
1161 | + result = valpy_binop_throw (opcode, self, other); | |
1148 | 1162 | } |
1149 | 1163 | CATCH (except, RETURN_MASK_ALL) |
1150 | 1164 | { |
@@ -1351,6 +1365,63 @@ valpy_xor (PyObject *self, PyObject *other) | ||
1351 | 1365 | return valpy_binop (VALPY_BITXOR, self, other); |
1352 | 1366 | } |
1353 | 1367 | |
1368 | +/* Helper for valpy_richcompare. Implements comparison operations for | |
1369 | + value objects. Returns true/false on success. Returns -1 with a | |
1370 | + Python exception set if a Python error is detected. Throws a GDB | |
1371 | + exception on other errors (memory error, etc.). */ | |
1372 | + | |
1373 | +static int | |
1374 | +valpy_richcompare_throw (PyObject *self, PyObject *other, int op) | |
1375 | +{ | |
1376 | + int result; | |
1377 | + struct value *value_other; | |
1378 | + struct value *value_self; | |
1379 | + struct value *mark = value_mark (); | |
1380 | + struct cleanup *cleanup; | |
1381 | + | |
1382 | + value_other = convert_value_from_python (other); | |
1383 | + if (value_other == NULL) | |
1384 | + return -1; | |
1385 | + | |
1386 | + cleanup = make_cleanup_value_free_to_mark (mark); | |
1387 | + | |
1388 | + value_self = ((value_object *) self)->value; | |
1389 | + | |
1390 | + switch (op) | |
1391 | + { | |
1392 | + case Py_LT: | |
1393 | + result = value_less (value_self, value_other); | |
1394 | + break; | |
1395 | + case Py_LE: | |
1396 | + result = value_less (value_self, value_other) | |
1397 | + || value_equal (value_self, value_other); | |
1398 | + break; | |
1399 | + case Py_EQ: | |
1400 | + result = value_equal (value_self, value_other); | |
1401 | + break; | |
1402 | + case Py_NE: | |
1403 | + result = !value_equal (value_self, value_other); | |
1404 | + break; | |
1405 | + case Py_GT: | |
1406 | + result = value_less (value_other, value_self); | |
1407 | + break; | |
1408 | + case Py_GE: | |
1409 | + result = (value_less (value_other, value_self) | |
1410 | + || value_equal (value_self, value_other)); | |
1411 | + break; | |
1412 | + default: | |
1413 | + /* Can't happen. */ | |
1414 | + PyErr_SetString (PyExc_NotImplementedError, | |
1415 | + _("Invalid operation on gdb.Value.")); | |
1416 | + result = -1; | |
1417 | + break; | |
1418 | + } | |
1419 | + | |
1420 | + do_cleanups (cleanup); | |
1421 | + return result; | |
1422 | +} | |
1423 | + | |
1424 | + | |
1354 | 1425 | /* Implements comparison operations for value objects. Returns NULL on error, |
1355 | 1426 | with a python exception set. */ |
1356 | 1427 | static PyObject * |
@@ -1379,48 +1450,7 @@ valpy_richcompare (PyObject *self, PyObject *other, int op) | ||
1379 | 1450 | |
1380 | 1451 | TRY |
1381 | 1452 | { |
1382 | - struct value *value_other, *mark = value_mark (); | |
1383 | - struct cleanup *cleanup; | |
1384 | - | |
1385 | - value_other = convert_value_from_python (other); | |
1386 | - if (value_other == NULL) | |
1387 | - { | |
1388 | - result = -1; | |
1389 | - break; | |
1390 | - } | |
1391 | - | |
1392 | - cleanup = make_cleanup_value_free_to_mark (mark); | |
1393 | - | |
1394 | - switch (op) { | |
1395 | - case Py_LT: | |
1396 | - result = value_less (((value_object *) self)->value, value_other); | |
1397 | - break; | |
1398 | - case Py_LE: | |
1399 | - result = value_less (((value_object *) self)->value, value_other) | |
1400 | - || value_equal (((value_object *) self)->value, value_other); | |
1401 | - break; | |
1402 | - case Py_EQ: | |
1403 | - result = value_equal (((value_object *) self)->value, value_other); | |
1404 | - break; | |
1405 | - case Py_NE: | |
1406 | - result = !value_equal (((value_object *) self)->value, value_other); | |
1407 | - break; | |
1408 | - case Py_GT: | |
1409 | - result = value_less (value_other, ((value_object *) self)->value); | |
1410 | - break; | |
1411 | - case Py_GE: | |
1412 | - result = value_less (value_other, ((value_object *) self)->value) | |
1413 | - || value_equal (((value_object *) self)->value, value_other); | |
1414 | - break; | |
1415 | - default: | |
1416 | - /* Can't happen. */ | |
1417 | - PyErr_SetString (PyExc_NotImplementedError, | |
1418 | - _("Invalid operation on gdb.Value.")); | |
1419 | - result = -1; | |
1420 | - break; | |
1421 | - } | |
1422 | - | |
1423 | - do_cleanups (cleanup); | |
1453 | + result = valpy_richcompare_throw (self, other, op); | |
1424 | 1454 | } |
1425 | 1455 | CATCH (except, RETURN_MASK_ALL) |
1426 | 1456 | { |
@@ -696,16 +696,16 @@ solib_read_symbols (struct so_list *so, int flags) | ||
696 | 696 | && so->objfile->addr_low == so->addr_low) |
697 | 697 | break; |
698 | 698 | } |
699 | - if (so->objfile != NULL) | |
700 | - break; | |
701 | - | |
702 | - sap = build_section_addr_info_from_section_table (so->sections, | |
703 | - so->sections_end); | |
704 | - so->objfile = symbol_file_add_from_bfd (so->abfd, so->so_name, | |
705 | - flags, sap, OBJF_SHARED, | |
706 | - NULL); | |
707 | - so->objfile->addr_low = so->addr_low; | |
708 | - free_section_addr_info (sap); | |
699 | + if (so->objfile == NULL) | |
700 | + { | |
701 | + sap = build_section_addr_info_from_section_table (so->sections, | |
702 | + so->sections_end); | |
703 | + so->objfile = symbol_file_add_from_bfd (so->abfd, so->so_name, | |
704 | + flags, sap, OBJF_SHARED, | |
705 | + NULL); | |
706 | + so->objfile->addr_low = so->addr_low; | |
707 | + free_section_addr_info (sap); | |
708 | + } | |
709 | 709 | |
710 | 710 | so->symbols_loaded = 1; |
711 | 711 | } |