Eliminate catch_errors

If you want to use catch_errors with a function with parameters, then
currently you have to manually write a "capture" struct wrapping the
arguments and marshall/unmarshall that.

https://sourceware.org/ml/gdb-patches/2017-09/msg00834.html proposed
adjusting catch_errors to use gdb::function_view, which would allow
passing lambdas with automatic captures.  However, it seems like using
TRY/CATCH directly instead ends up producing clearer and easier to
debug code.  This is what this commit does.

Note that removing catch_errors exposes further cleanup opportunities
around no longer having to follow catch_errors callback type, and also
removes a few cleanups.

I didn't do anything to save/restore current_uiout because I think
that should be the responsibility of the code that changes
current_uiout in the first place.

(Another approach could be to make catch_errors a variadic template
like:

  template<typename Function, typename... Args>
  int catch_errors (const char *errstring, return_mask mask,
		    Function &&func, Args... args);

and then with:

  extern void function_with_args (int, int);
  extern void function_with_no_args ();

calls to the above functions would be wrapped like this:

  catch_errors ("some error happened", RETURN_MASK_ERROR,
                function_with_args, arg1, arg2);

  catch_errors ("some error happened", RETURN_MASK_ERROR,
                function_with_no_args);

but I'm thinking that that doesn't improve much if at all either.)

gdb/ChangeLog
2017-10-10  Pedro Alves  <palves@redhat.com>
	    Tom Tromey  <tom@tromey.com>

	* breakpoint.c (breakpoint_cond_eval): Change return type to bool
	and reverse logic.
	(WP_DELETED, WP_VALUE_CHANGED, WP_VALUE_NOT_CHANGED, WP_IGNORE):
	No longer macros.  Instead ...
	(enum wp_check_result): They're now values of this new
	enumeration.
	(watchpoint_check): Change return type to wp_check_result and
	parameter type to bpstat.
	(bpstat_check_watchpoint): Use TRY/CATCH instead of catch_errors.
	(bpstat_check_breakpoint_conditions): Use TRY/CATCH instead of
	catch_errors.  Reverse logic of watchpoint_check call.
	(breakpoint_re_set_one): Now returns void and takes a breakpoint
	pointer as parameter.
	(breakpoint_re_set): Use TRY/CATCH instead of catch_errors.
	* common/common-exceptions.c (throw_exception_sjlj): Update
	comments to avoid mentioning catch_errors.
	* exceptions.c (catch_errors): Delete.
	* exceptions.h: Update comments to avoid mentioning catch_errors.
	(catch_errors_ftype, catch_errors): Delete.
	* infrun.c (normal_stop): Use TRY/CATCH instead of catch_errors.
	(hook_stop_stub): Delete.
	(restore_selected_frame): Change return type to void, and
	parameter type to const frame_id &.
	(restore_infcall_control_state): Use TRY/CATCH instead of
	catch_errors.
	* main.c (captured_command_loop): Return void and remove
	parameter.  Remove references to catch_errors.
	(captured_main): Use TRY/CATCH instead of catch_errors.
	* objc-lang.c (objc_submethod_helper_data)
	(find_objc_msgcall_submethod_helper): Delete.
	(find_objc_msgcall_submethod): Use TRY/CATCH instead of
	catch_errors.
	* record-full.c (record_full_message): Return void.
	(record_full_message_args, record_full_message_wrapper): Delete.
	(record_full_message_wrapper_safe): Return bool and use TRY/CATCH
	instead of catch_errors.
	* solib-aix.c (solib_aix_open_symbol_file_object): Change
	parameter type to int.
	* solib-darwin.c (open_symbol_file_object): Ditto.
	* solib-dsbt.c (open_symbol_file_object): Ditto.
	* solib-frv.c (open_symbol_file_object): Ditto.
	* solib-svr4.c (open_symbol_file_object): Ditto.
	* solib-target.c (solib_target_open_symbol_file_object): Ditto.
	* solib.c (update_solib_list): Use TRY/CATCH instead of
	catch_errors.
	* solist.h (struct target_so_ops) <open_symbol_file_object>:
	Change type.
	* symmisc.c (struct print_symbol_args): Remove.
	(dump_symtab_1): Use TRY/CATCH instead of catch_errors.
	(print_symbol): Change type.
	* windows-nat.c (handle_load_dll, handle_unload_dll): Return void
	and remove parameters.
	(catch_errors): New.
	(get_windows_debug_event): Adjust.

gdb/testsuite/ChangeLog:
2017-10-10  Pedro Alves  <palves@redhat.com>

	* lib/selftest-support.exp (selftest_setup): Update for
	captured_command_loop's prototype change.
This commit is contained in:
Pedro Alves 2017-10-10 16:45:50 +01:00
parent 6c699715f6
commit bf46927112
21 changed files with 284 additions and 306 deletions

View file

@ -1,3 +1,61 @@
2017-10-10 Pedro Alves <palves@redhat.com>
Tom Tromey <tom@tromey.com>
* breakpoint.c (breakpoint_cond_eval): Change return type to bool
and reverse logic.
(WP_DELETED, WP_VALUE_CHANGED, WP_VALUE_NOT_CHANGED, WP_IGNORE):
No longer macros. Instead ...
(enum wp_check_result): They're now values of this new
enumeration.
(watchpoint_check): Change return type to wp_check_result and
parameter type to bpstat.
(bpstat_check_watchpoint): Use TRY/CATCH instead of catch_errors.
(bpstat_check_breakpoint_conditions): Use TRY/CATCH instead of
catch_errors. Reverse logic of watchpoint_check call.
(breakpoint_re_set_one): Now returns void and takes a breakpoint
pointer as parameter.
(breakpoint_re_set): Use TRY/CATCH instead of catch_errors.
* common/common-exceptions.c (throw_exception_sjlj): Update
comments to avoid mentioning catch_errors.
* exceptions.c (catch_errors): Delete.
* exceptions.h: Update comments to avoid mentioning catch_errors.
(catch_errors_ftype, catch_errors): Delete.
* infrun.c (normal_stop): Use TRY/CATCH instead of catch_errors.
(hook_stop_stub): Delete.
(restore_selected_frame): Change return type to void, and
parameter type to const frame_id &.
(restore_infcall_control_state): Use TRY/CATCH instead of
catch_errors.
* main.c (captured_command_loop): Return void and remove
parameter. Remove references to catch_errors.
(captured_main): Use TRY/CATCH instead of catch_errors.
* objc-lang.c (objc_submethod_helper_data)
(find_objc_msgcall_submethod_helper): Delete.
(find_objc_msgcall_submethod): Use TRY/CATCH instead of
catch_errors.
* record-full.c (record_full_message): Return void.
(record_full_message_args, record_full_message_wrapper): Delete.
(record_full_message_wrapper_safe): Return bool and use TRY/CATCH
instead of catch_errors.
* solib-aix.c (solib_aix_open_symbol_file_object): Change
parameter type to int.
* solib-darwin.c (open_symbol_file_object): Ditto.
* solib-dsbt.c (open_symbol_file_object): Ditto.
* solib-frv.c (open_symbol_file_object): Ditto.
* solib-svr4.c (open_symbol_file_object): Ditto.
* solib-target.c (solib_target_open_symbol_file_object): Ditto.
* solib.c (update_solib_list): Use TRY/CATCH instead of
catch_errors.
* solist.h (struct target_so_ops) <open_symbol_file_object>:
Change type.
* symmisc.c (struct print_symbol_args): Remove.
(dump_symtab_1): Use TRY/CATCH instead of catch_errors.
(print_symbol): Change type.
* windows-nat.c (handle_load_dll, handle_unload_dll): Return void
and remove parameters.
(catch_errors): New.
(get_windows_debug_event): Adjust.
2017-10-09 Tom Tromey <tom@tromey.com> 2017-10-09 Tom Tromey <tom@tromey.com>
* mi/mi-main.c (free_splay_tree): Remove. * mi/mi-main.c (free_splay_tree): Remove.

View file

@ -103,8 +103,6 @@ static void map_breakpoint_numbers (const char *,
static void ignore_command (char *, int); static void ignore_command (char *, int);
static int breakpoint_re_set_one (void *);
static void breakpoint_re_set_default (struct breakpoint *); static void breakpoint_re_set_default (struct breakpoint *);
static void static void
@ -178,8 +176,6 @@ static void info_breakpoints_command (char *, int);
static void info_watchpoints_command (char *, int); static void info_watchpoints_command (char *, int);
static int breakpoint_cond_eval (void *);
static void cleanup_executing_breakpoints (void *); static void cleanup_executing_breakpoints (void *);
static void commands_command (char *, int); static void commands_command (char *, int);
@ -191,8 +187,6 @@ static int remove_breakpoint_1 (struct bp_location *, enum remove_bp_reason);
static enum print_stop_action print_bp_stop_message (bpstat bs); static enum print_stop_action print_bp_stop_message (bpstat bs);
static int watchpoint_check (void *);
static int hw_breakpoint_used_count (void); static int hw_breakpoint_used_count (void);
static int hw_watchpoint_use_count (struct breakpoint *); static int hw_watchpoint_use_count (struct breakpoint *);
@ -4842,21 +4836,16 @@ bpstat_print (bpstat bs, int kind)
return PRINT_UNKNOWN; return PRINT_UNKNOWN;
} }
/* Evaluate the expression EXP and return 1 if value is zero. /* Evaluate the boolean expression EXP and return the result. */
This returns the inverse of the condition because it is called
from catch_errors which returns 0 if an exception happened, and if an
exception happens we want execution to stop.
The argument is a "struct expression *" that has been cast to a
"void *" to make it pass through catch_errors. */
static int static bool
breakpoint_cond_eval (void *exp) breakpoint_cond_eval (expression *exp)
{ {
struct value *mark = value_mark (); struct value *mark = value_mark ();
int i = !value_true (evaluate_expression ((struct expression *) exp)); bool res = value_true (evaluate_expression (exp));
value_free_to_mark (mark); value_free_to_mark (mark);
return i; return res;
} }
/* Allocate a new bpstat. Link it to the FIFO list by BS_LINK_POINTER. */ /* Allocate a new bpstat. Link it to the FIFO list by BS_LINK_POINTER. */
@ -4966,30 +4955,31 @@ watchpoints_triggered (struct target_waitstatus *ws)
return 1; return 1;
} }
/* Possible return values for watchpoint_check (this can't be an enum /* Possible return values for watchpoint_check. */
because of check_errors). */ enum wp_check_result
/* The watchpoint has been deleted. */ {
#define WP_DELETED 1 /* The watchpoint has been deleted. */
/* The value has changed. */ WP_DELETED = 1,
#define WP_VALUE_CHANGED 2
/* The value has not changed. */ /* The value has changed. */
#define WP_VALUE_NOT_CHANGED 3 WP_VALUE_CHANGED = 2,
/* Ignore this watchpoint, no matter if the value changed or not. */
#define WP_IGNORE 4 /* The value has not changed. */
WP_VALUE_NOT_CHANGED = 3,
/* Ignore this watchpoint, no matter if the value changed or not. */
WP_IGNORE = 4,
};
#define BP_TEMPFLAG 1 #define BP_TEMPFLAG 1
#define BP_HARDWAREFLAG 2 #define BP_HARDWAREFLAG 2
/* Evaluate watchpoint condition expression and check if its value /* Evaluate watchpoint condition expression and check if its value
changed. changed. */
P should be a pointer to struct bpstat, but is defined as a void * static wp_check_result
in order for this function to be usable with catch_errors. */ watchpoint_check (bpstat bs)
static int
watchpoint_check (void *p)
{ {
bpstat bs = (bpstat) p;
struct watchpoint *b; struct watchpoint *b;
struct frame_info *fr; struct frame_info *fr;
int within_current_scope; int within_current_scope;
@ -5185,13 +5175,29 @@ bpstat_check_watchpoint (bpstat bs)
if (must_check_value) if (must_check_value)
{ {
char *message wp_check_result e;
= xstrprintf ("Error evaluating expression for watchpoint %d\n",
b->number); TRY
struct cleanup *cleanups = make_cleanup (xfree, message); {
int e = catch_errors (watchpoint_check, bs, message, e = watchpoint_check (bs);
RETURN_MASK_ALL); }
do_cleanups (cleanups); CATCH (ex, RETURN_MASK_ALL)
{
exception_fprintf (gdb_stderr, ex,
"Error evaluating expression "
"for watchpoint %d\n",
b->number);
SWITCH_THRU_ALL_UIS ()
{
printf_filtered (_("Watchpoint %d deleted.\n"),
b->number);
}
watchpoint_del_at_next_stop (b);
e = WP_DELETED;
}
END_CATCH
switch (e) switch (e)
{ {
case WP_DELETED: case WP_DELETED:
@ -5287,18 +5293,6 @@ bpstat_check_watchpoint (bpstat bs)
break; break;
default: default:
/* Can't happen. */ /* Can't happen. */
case 0:
/* Error from catch_errors. */
{
SWITCH_THRU_ALL_UIS ()
{
printf_filtered (_("Watchpoint %d deleted.\n"),
b->number);
}
watchpoint_del_at_next_stop (b);
/* We've already printed what needs to be printed. */
bs->print_it = print_it_done;
}
break; break;
} }
} }
@ -5324,7 +5318,8 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid)
{ {
const struct bp_location *bl; const struct bp_location *bl;
struct breakpoint *b; struct breakpoint *b;
int value_is_zero = 0; /* Assume stop. */
bool condition_result = true;
struct expression *cond; struct expression *cond;
gdb_assert (bs->stop); gdb_assert (bs->stop);
@ -5420,23 +5415,30 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid)
within_current_scope = 0; within_current_scope = 0;
} }
if (within_current_scope) if (within_current_scope)
value_is_zero {
= catch_errors (breakpoint_cond_eval, cond, TRY
"Error in testing breakpoint condition:\n", {
RETURN_MASK_ALL); condition_result = breakpoint_cond_eval (cond);
}
CATCH (ex, RETURN_MASK_ALL)
{
exception_fprintf (gdb_stderr, ex,
"Error in testing breakpoint condition:\n");
}
END_CATCH
}
else else
{ {
warning (_("Watchpoint condition cannot be tested " warning (_("Watchpoint condition cannot be tested "
"in the current scope")); "in the current scope"));
/* If we failed to set the right context for this /* If we failed to set the right context for this
watchpoint, unconditionally report it. */ watchpoint, unconditionally report it. */
value_is_zero = 0;
} }
/* FIXME-someday, should give breakpoint #. */ /* FIXME-someday, should give breakpoint #. */
value_free_to_mark (mark); value_free_to_mark (mark);
} }
if (cond && value_is_zero) if (cond && !condition_result)
{ {
bs->stop = 0; bs->stop = 0;
} }
@ -14148,21 +14150,16 @@ prepare_re_set_context (struct breakpoint *b)
return make_cleanup (null_cleanup, NULL); return make_cleanup (null_cleanup, NULL);
} }
/* Reset a breakpoint given it's struct breakpoint * BINT. /* Reset a breakpoint. */
The value we return ends up being the return value from catch_errors.
Unused in this case. */
static int static void
breakpoint_re_set_one (void *bint) breakpoint_re_set_one (breakpoint *b)
{ {
/* Get past catch_errs. */
struct breakpoint *b = (struct breakpoint *) bint;
struct cleanup *cleanups; struct cleanup *cleanups;
cleanups = prepare_re_set_context (b); cleanups = prepare_re_set_context (b);
b->ops->re_set (b); b->ops->re_set (b);
do_cleanups (cleanups); do_cleanups (cleanups);
return 0;
} }
/* Re-set breakpoint locations for the current program space. /* Re-set breakpoint locations for the current program space.
@ -14188,12 +14185,17 @@ breakpoint_re_set (void)
ALL_BREAKPOINTS_SAFE (b, b_tmp) ALL_BREAKPOINTS_SAFE (b, b_tmp)
{ {
/* Format possible error msg. */ TRY
char *message = xstrprintf ("Error in re-setting breakpoint %d: ", {
b->number); breakpoint_re_set_one (b);
struct cleanup *cleanups = make_cleanup (xfree, message); }
catch_errors (breakpoint_re_set_one, b, message, RETURN_MASK_ALL); CATCH (ex, RETURN_MASK_ALL)
do_cleanups (cleanups); {
exception_fprintf (gdb_stderr, ex,
"Error in re-setting breakpoint %d: ",
b->number);
}
END_CATCH
} }
set_language (save_language); set_language (save_language);
input_radix = save_input_radix; input_radix = save_input_radix;

View file

@ -264,16 +264,16 @@ gdb_exception_sliced_copy (struct gdb_exception *to, const struct gdb_exception
#endif /* !GDB_XCPT_SJMP */ #endif /* !GDB_XCPT_SJMP */
/* Return EXCEPTION to the nearest containing catch_errors(). */ /* Return EXCEPTION to the nearest containing CATCH_SJLJ block. */
void void
throw_exception_sjlj (struct gdb_exception exception) throw_exception_sjlj (struct gdb_exception exception)
{ {
do_cleanups (all_cleanups ()); do_cleanups (all_cleanups ());
/* Jump to the containing catch_errors() call, communicating REASON /* Jump to the nearest CATCH_SJLJ block, communicating REASON to
to that call via setjmp's return value. Note that REASON can't that call via setjmp's return value. Note that REASON can't be
be zero, by definition in defs.h. */ zero, by definition in common-exceptions.h. */
exceptions_state_mc (CATCH_THROWING); exceptions_state_mc (CATCH_THROWING);
current_catcher->exception = exception; current_catcher->exception = exception;
longjmp (current_catcher->buf, exception.reason); longjmp (current_catcher->buf, exception.reason);

View file

@ -217,45 +217,6 @@ catch_exceptions_with_msg (struct ui_out *func_uiout,
return val; return val;
} }
/* This function is superseded by catch_exceptions(). */
int
catch_errors (catch_errors_ftype *func, void *func_args,
const char *errstring, return_mask mask)
{
struct gdb_exception exception = exception_none;
volatile int val = 0;
struct ui_out *saved_uiout;
/* Save the global ``struct ui_out'' builder. */
saved_uiout = current_uiout;
TRY
{
val = func (func_args);
}
CATCH (ex, RETURN_MASK_ALL)
{
exception = ex;
}
END_CATCH
/* Restore the global builder. */
current_uiout = saved_uiout;
if (exception.reason < 0 && (mask & RETURN_MASK (exception.reason)) == 0)
{
/* The caller didn't request that the event be caught.
Rethrow. */
throw_exception (exception);
}
exception_fprintf (gdb_stderr, exception, "%s", errstring);
if (exception.reason != 0)
return 0;
return val;
}
/* See exceptions.h. */ /* See exceptions.h. */
int int

View file

@ -48,21 +48,16 @@ extern void exception_fprintf (struct ui_file *file, struct gdb_exception e,
copy of the gdb error message. This is used when a silent error is copy of the gdb error message. This is used when a silent error is
issued and the caller wants to manually issue the error message. issued and the caller wants to manually issue the error message.
MASK specifies what to catch; it is normally set to MASK specifies what to catch; it is normally set to RETURN_MASK_ALL
RETURN_MASK_ALL, if for no other reason than that the code which if the code which calls catch_exceptions is not set up to deal with
calls catch_errors might not be set up to deal with a quit which a quit which isn't caught. But if the code can deal with it, it
isn't caught. But if the code can deal with it, it generally generally should be RETURN_MASK_ERROR, unless for some reason it is
should be RETURN_MASK_ERROR, unless for some reason it is more more useful to abort only the portion of the operation inside the
useful to abort only the portion of the operation inside the catch_exceptions. Note that quit should return to the command line
catch_errors. Note that quit should return to the command line
fairly quickly, even if some further processing is being done. fairly quickly, even if some further processing is being done.
FIXME; cagney/2001-08-13: The need to override the global UIOUT FIXME; cagney/2001-08-13: The need to override the global UIOUT
builder variable should just go away. builder variable should just go away. */
This function supersedes catch_errors().
This function uses SETJMP() and LONGJUMP(). */
struct ui_out; struct ui_out;
typedef int (catch_exceptions_ftype) (struct ui_out *ui_out, void *args); typedef int (catch_exceptions_ftype) (struct ui_out *ui_out, void *args);
@ -76,19 +71,6 @@ extern int catch_exceptions_with_msg (struct ui_out *uiout,
char **gdberrmsg, char **gdberrmsg,
return_mask mask); return_mask mask);
/* If CATCH_ERRORS_FTYPE throws an error, catch_errors() returns zero
otherwize the result from CATCH_ERRORS_FTYPE is returned. It is
probably useful for CATCH_ERRORS_FTYPE to always return a non-zero
value. It's unfortunate that, catch_errors() does not return an
indication of the exact exception that it caught - quit_flag might
help.
This function is superseded by catch_exceptions(). */
typedef int (catch_errors_ftype) (void *);
extern int catch_errors (catch_errors_ftype *, void *,
const char *, return_mask);
/* Compare two exception objects for print equality. */ /* Compare two exception objects for print equality. */
extern int exception_print_same (struct gdb_exception e1, extern int exception_print_same (struct gdb_exception e1,
struct gdb_exception e2); struct gdb_exception e2);

View file

@ -80,10 +80,6 @@ static void sig_print_header (void);
static void resume_cleanups (void *); static void resume_cleanups (void *);
static int hook_stop_stub (void *);
static int restore_selected_frame (void *);
static int follow_fork (void); static int follow_fork (void);
static int follow_fork_inferior (int follow_child, int detach_fork); static int follow_fork_inferior (int follow_child, int detach_fork);
@ -8314,8 +8310,16 @@ normal_stop (void)
struct cleanup *old_chain struct cleanup *old_chain
= make_cleanup (release_stop_context_cleanup, saved_context); = make_cleanup (release_stop_context_cleanup, saved_context);
catch_errors (hook_stop_stub, stop_command, TRY
"Error while running hook_stop:\n", RETURN_MASK_ALL); {
execute_cmd_pre_hook (stop_command);
}
CATCH (ex, RETURN_MASK_ALL)
{
exception_fprintf (gdb_stderr, ex,
"Error while running hook_stop:\n");
}
END_CATCH
/* If the stop hook resumes the target, then there's no point in /* If the stop hook resumes the target, then there's no point in
trying to notify about the previous stop; its context is trying to notify about the previous stop; its context is
@ -8356,13 +8360,6 @@ normal_stop (void)
return 0; return 0;
} }
static int
hook_stop_stub (void *cmd)
{
execute_cmd_pre_hook ((struct cmd_list_element *) cmd);
return (0);
}
int int
signal_stop_state (int signo) signal_stop_state (int signo)
@ -8983,25 +8980,20 @@ save_infcall_control_state (void)
return inf_status; return inf_status;
} }
static int static void
restore_selected_frame (void *args) restore_selected_frame (const frame_id &fid)
{ {
struct frame_id *fid = (struct frame_id *) args; frame_info *frame = frame_find_by_id (fid);
struct frame_info *frame;
frame = frame_find_by_id (*fid);
/* If inf_status->selected_frame_id is NULL, there was no previously /* If inf_status->selected_frame_id is NULL, there was no previously
selected frame. */ selected frame. */
if (frame == NULL) if (frame == NULL)
{ {
warning (_("Unable to restore previously selected frame.")); warning (_("Unable to restore previously selected frame."));
return 0; return;
} }
select_frame (frame); select_frame (frame);
return (1);
} }
/* Restore inferior session state to INF_STATUS. */ /* Restore inferior session state to INF_STATUS. */
@ -9031,16 +9023,22 @@ restore_infcall_control_state (struct infcall_control_state *inf_status)
if (target_has_stack) if (target_has_stack)
{ {
/* The point of catch_errors is that if the stack is clobbered, /* The point of the try/catch is that if the stack is clobbered,
walking the stack might encounter a garbage pointer and walking the stack might encounter a garbage pointer and
error() trying to dereference it. */ error() trying to dereference it. */
if (catch_errors TRY
(restore_selected_frame, &inf_status->selected_frame_id, {
"Unable to restore previously selected frame:\n", restore_selected_frame (inf_status->selected_frame_id);
RETURN_MASK_ERROR) == 0) }
/* Error in restoring the selected frame. Select the innermost CATCH (ex, RETURN_MASK_ERROR)
frame. */ {
select_frame (get_current_frame ()); exception_fprintf (gdb_stderr, ex,
"Unable to restore previously selected frame:\n");
/* Error in restoring the selected frame. Select the
innermost frame. */
select_frame (get_current_frame ());
}
END_CATCH
} }
xfree (inf_status); xfree (inf_status);

View file

@ -305,11 +305,10 @@ setup_alternate_signal_stack (void)
#endif #endif
} }
/* Call command_loop. If it happens to return, pass that through as a /* Call command_loop. */
non-zero return status. */
static int static void
captured_command_loop (void *data) captured_command_loop ()
{ {
struct ui *ui = current_ui; struct ui *ui = current_ui;
@ -333,11 +332,9 @@ captured_command_loop (void *data)
check to detect bad FUNCs code. */ check to detect bad FUNCs code. */
do_cleanups (all_cleanups ()); do_cleanups (all_cleanups ());
/* If the command_loop returned, normally (rather than threw an /* If the command_loop returned, normally (rather than threw an
error) we try to quit. If the quit is aborted, catch_errors() error) we try to quit. If the quit is aborted, our caller
which called this catch the signal and restart the command catches the signal and restarts the command loop. */
loop. */
quit_command (NULL, ui->instream == ui->stdin_stream); quit_command (NULL, ui->instream == ui->stdin_stream);
return 1;
} }
/* Handle command errors thrown from within catch_command_errors. */ /* Handle command errors thrown from within catch_command_errors. */
@ -1145,7 +1142,15 @@ captured_main (void *data)
change - SET_TOP_LEVEL() - has been eliminated. */ change - SET_TOP_LEVEL() - has been eliminated. */
while (1) while (1)
{ {
catch_errors (captured_command_loop, 0, "", RETURN_MASK_ALL); TRY
{
captured_command_loop ();
}
CATCH (ex, RETURN_MASK_ALL)
{
exception_print (gdb_stderr, ex);
}
END_CATCH
} }
/* No exit -- exit is through quit_command. */ /* No exit -- exit is through quit_command. */
} }

View file

@ -1310,43 +1310,25 @@ find_objc_msgsend (void)
* dependent modules. * dependent modules.
*/ */
struct objc_submethod_helper_data {
int (*f) (CORE_ADDR, CORE_ADDR *);
CORE_ADDR pc;
CORE_ADDR *new_pc;
};
static int
find_objc_msgcall_submethod_helper (void * arg)
{
struct objc_submethod_helper_data *s =
(struct objc_submethod_helper_data *) arg;
if (s->f (s->pc, s->new_pc) == 0)
return 1;
else
return 0;
}
static int static int
find_objc_msgcall_submethod (int (*f) (CORE_ADDR, CORE_ADDR *), find_objc_msgcall_submethod (int (*f) (CORE_ADDR, CORE_ADDR *),
CORE_ADDR pc, CORE_ADDR pc,
CORE_ADDR *new_pc) CORE_ADDR *new_pc)
{ {
struct objc_submethod_helper_data s; TRY
{
if (f (pc, new_pc) == 0)
return 1;
}
CATCH (ex, RETURN_MASK_ALL)
{
exception_fprintf (gdb_stderr, ex,
"Unable to determine target of "
"Objective-C method call (ignoring):\n");
}
END_CATCH
s.f = f; return 0;
s.pc = pc;
s.new_pc = new_pc;
if (catch_errors (find_objc_msgcall_submethod_helper,
(void *) &s,
"Unable to determine target of "
"Objective-C method call (ignoring):\n",
RETURN_MASK_ALL) == 0)
return 1;
else
return 0;
} }
int int

View file

@ -565,7 +565,7 @@ record_full_arch_list_cleanups (void *ignore)
record the running message of inferior and set them to record the running message of inferior and set them to
record_full_arch_list, and add it to record_full_list. */ record_full_arch_list, and add it to record_full_list. */
static int static void
record_full_message (struct regcache *regcache, enum gdb_signal signal) record_full_message (struct regcache *regcache, enum gdb_signal signal)
{ {
int ret; int ret;
@ -633,36 +633,24 @@ record_full_message (struct regcache *regcache, enum gdb_signal signal)
record_full_list_release_first (); record_full_list_release_first ();
else else
record_full_insn_num++; record_full_insn_num++;
return 1;
} }
struct record_full_message_args { static bool
struct regcache *regcache;
enum gdb_signal signal;
};
static int
record_full_message_wrapper (void *args)
{
struct record_full_message_args *record_full_args
= (struct record_full_message_args *) args;
return record_full_message (record_full_args->regcache,
record_full_args->signal);
}
static int
record_full_message_wrapper_safe (struct regcache *regcache, record_full_message_wrapper_safe (struct regcache *regcache,
enum gdb_signal signal) enum gdb_signal signal)
{ {
struct record_full_message_args args; TRY
{
record_full_message (regcache, signal);
}
CATCH (ex, RETURN_MASK_ALL)
{
exception_print (gdb_stderr, ex);
return false;
}
END_CATCH
args.regcache = regcache; return true;
args.signal = signal;
return catch_errors (record_full_message_wrapper, &args, "",
RETURN_MASK_ALL);
} }
/* Set to 1 if record_full_store_registers and record_full_xfer_partial /* Set to 1 if record_full_store_registers and record_full_xfer_partial

View file

@ -589,7 +589,7 @@ solib_aix_current_sos (void)
/* Implement the "open_symbol_file_object" target_so_ops method. */ /* Implement the "open_symbol_file_object" target_so_ops method. */
static int static int
solib_aix_open_symbol_file_object (void *from_ttyp) solib_aix_open_symbol_file_object (int from_tty)
{ {
return 0; return 0;
} }

View file

@ -222,7 +222,7 @@ find_program_interpreter (void)
Note that darwin-nat.c implements pid_to_exec_file. */ Note that darwin-nat.c implements pid_to_exec_file. */
static int static int
open_symbol_file_object (void *from_ttyp) open_symbol_file_object (int from_tty)
{ {
return 0; return 0;
} }

View file

@ -507,16 +507,10 @@ scan_dyntag (int dyntag, bfd *abfd, CORE_ADDR *ptr)
return 0; return 0;
} }
/* If no open symbol file, attempt to locate and open the main symbol /* See solist.h. */
file.
If FROM_TTYP dereferences to a non-zero integer, allow messages to
be printed. This parameter is a pointer rather than an int because
open_symbol_file_object is called via catch_errors and
catch_errors requires a pointer argument. */
static int static int
open_symbol_file_object (void *from_ttyp) open_symbol_file_object (int from_tty)
{ {
/* Unimplemented. */ /* Unimplemented. */
return 0; return 0;

View file

@ -246,7 +246,7 @@ static int enable_break2 (void);
/* Implement the "open_symbol_file_object" target_so_ops method. */ /* Implement the "open_symbol_file_object" target_so_ops method. */
static int static int
open_symbol_file_object (void *from_ttyp) open_symbol_file_object (int from_tty)
{ {
/* Unimplemented. */ /* Unimplemented. */
return 0; return 0;

View file

@ -984,20 +984,14 @@ svr4_keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
return (name_lm >= vaddr && name_lm < vaddr + size); return (name_lm >= vaddr && name_lm < vaddr + size);
} }
/* Implement the "open_symbol_file_object" target_so_ops method. /* See solist.h. */
If no open symbol file, attempt to locate and open the main symbol
file. On SVR4 systems, this is the first link map entry. If its
name is here, we can open it. Useful when attaching to a process
without first loading its symbol file. */
static int static int
open_symbol_file_object (void *from_ttyp) open_symbol_file_object (int from_tty)
{ {
CORE_ADDR lm, l_name; CORE_ADDR lm, l_name;
char *filename; char *filename;
int errcode; int errcode;
int from_tty = *(int *)from_ttyp;
struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr; struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
int l_name_size = TYPE_LENGTH (ptr_type); int l_name_size = TYPE_LENGTH (ptr_type);

View file

@ -452,7 +452,7 @@ Could not relocate shared library \"%s\": bad offsets"), so->so_name);
} }
static int static int
solib_target_open_symbol_file_object (void *from_ttyp) solib_target_open_symbol_file_object (int from_tty)
{ {
/* We can't locate the main symbol file based on the target's /* We can't locate the main symbol file based on the target's
knowledge; the user has to specify it. */ knowledge; the user has to specify it. */

View file

@ -760,9 +760,19 @@ update_solib_list (int from_tty)
have not opened a symbol file, we may be able to get its have not opened a symbol file, we may be able to get its
symbols now! */ symbols now! */
if (inf->attach_flag && symfile_objfile == NULL) if (inf->attach_flag && symfile_objfile == NULL)
catch_errors (ops->open_symbol_file_object, &from_tty, {
"Error reading attached process's symbol file.\n", TRY
RETURN_MASK_ALL); {
ops->open_symbol_file_object (from_tty);
}
CATCH (ex, RETURN_MASK_ALL)
{
exception_fprintf (gdb_stderr, ex,
"Error reading attached "
"process's symbol file.\n");
}
END_CATCH
}
} }
/* GDB and the inferior's dynamic linker each maintain their own /* GDB and the inferior's dynamic linker each maintain their own

View file

@ -121,11 +121,8 @@ struct target_so_ops
struct so_list *(*current_sos) (void); struct so_list *(*current_sos) (void);
/* Find, open, and read the symbols for the main executable. If /* Find, open, and read the symbols for the main executable. If
FROM_TTYP dereferences to a non-zero integer, allow messages to FROM_TTY is non-zero, allow messages to be printed. */
be printed. This parameter is a pointer rather than an int int (*open_symbol_file_object) (int from_ttyp);
because open_symbol_file_object is called via catch_errors and
catch_errors requires a pointer argument. */
int (*open_symbol_file_object) (void *from_ttyp);
/* Determine if PC lies in the dynamic symbol resolution code of /* Determine if PC lies in the dynamic symbol resolution code of
the run time loader. */ the run time loader. */

View file

@ -54,15 +54,8 @@ FILE *std_err;
static int block_depth (struct block *); static int block_depth (struct block *);
struct print_symbol_args static void print_symbol (struct gdbarch *gdbarch, struct symbol *symbol,
{ int depth, ui_file *outfile);
struct gdbarch *gdbarch;
struct symbol *symbol;
int depth;
struct ui_file *outfile;
};
static int print_symbol (void *);
void void
@ -357,14 +350,16 @@ dump_symtab_1 (struct symtab *symtab, struct ui_file *outfile)
block, not any blocks from included symtabs. */ block, not any blocks from included symtabs. */
ALL_DICT_SYMBOLS (BLOCK_DICT (b), iter, sym) ALL_DICT_SYMBOLS (BLOCK_DICT (b), iter, sym)
{ {
struct print_symbol_args s; TRY
{
s.gdbarch = gdbarch; print_symbol (gdbarch, sym, depth + 1, outfile);
s.symbol = sym; }
s.depth = depth + 1; CATCH (ex, RETURN_MASK_ERROR)
s.outfile = outfile; {
catch_errors (print_symbol, &s, "Error printing symbol:\n", exception_fprintf (gdb_stderr, ex,
RETURN_MASK_ERROR); "Error printing symbol:\n");
}
END_CATCH
} }
} }
fprintf_filtered (outfile, "\n"); fprintf_filtered (outfile, "\n");
@ -515,18 +510,12 @@ maintenance_print_symbols (const char *args, int from_tty)
} }
} }
/* Print symbol ARGS->SYMBOL on ARGS->OUTFILE. ARGS->DEPTH says how /* Print symbol SYMBOL on OUTFILE. DEPTH says how far to indent. */
far to indent. ARGS is really a struct print_symbol_args *, but is
declared as char * to get it past catch_errors. Returns 0 for error,
1 for success. */
static int static void
print_symbol (void *args) print_symbol (struct gdbarch *gdbarch, struct symbol *symbol,
int depth, ui_file *outfile)
{ {
struct gdbarch *gdbarch = ((struct print_symbol_args *) args)->gdbarch;
struct symbol *symbol = ((struct print_symbol_args *) args)->symbol;
int depth = ((struct print_symbol_args *) args)->depth;
struct ui_file *outfile = ((struct print_symbol_args *) args)->outfile;
struct obj_section *section; struct obj_section *section;
if (SYMBOL_OBJFILE_OWNED (symbol)) if (SYMBOL_OBJFILE_OWNED (symbol))
@ -546,8 +535,9 @@ print_symbol (void *args)
section->the_bfd_section)); section->the_bfd_section));
else else
fprintf_filtered (outfile, "\n"); fprintf_filtered (outfile, "\n");
return 1; return;
} }
if (SYMBOL_DOMAIN (symbol) == STRUCT_DOMAIN) if (SYMBOL_DOMAIN (symbol) == STRUCT_DOMAIN)
{ {
if (TYPE_TAG_NAME (SYMBOL_TYPE (symbol))) if (TYPE_TAG_NAME (SYMBOL_TYPE (symbol)))
@ -694,7 +684,6 @@ print_symbol (void *args)
} }
} }
fprintf_filtered (outfile, "\n"); fprintf_filtered (outfile, "\n");
return 1;
} }
static void static void

View file

@ -1,3 +1,8 @@
2017-10-10 Pedro Alves <palves@redhat.com>
* lib/selftest-support.exp (selftest_setup): Update for
captured_command_loop's prototype change.
2017-10-09 Pedro Alves <palves@redhat.com> 2017-10-09 Pedro Alves <palves@redhat.com>
Test both arch1=>arch2 and arch2=>arch1. Test both arch1=>arch2 and arch2=>arch1.

View file

@ -88,10 +88,10 @@ proc selftest_setup { executable function } {
set description "run until breakpoint at $function" set description "run until breakpoint at $function"
gdb_test_multiple "run $INTERNAL_GDBFLAGS" "$description" { gdb_test_multiple "run $INTERNAL_GDBFLAGS" "$description" {
-re "Starting program.*Breakpoint \[0-9\]+,.*$function .data.* at .*main.c:.*$gdb_prompt $" { -re "Starting program.*Breakpoint \[0-9\]+,.*$function \\(\\).* at .*main.c:.*$gdb_prompt $" {
pass "$description" pass "$description"
} }
-re "Starting program.*Breakpoint \[0-9\]+,.*$function .data.*$gdb_prompt $" { -re "Starting program.*Breakpoint \[0-9\]+,.*$function \\(\\).*$gdb_prompt $" {
xfail "$description (line numbers scrambled?)" xfail "$description (line numbers scrambled?)"
} }
-re "Starting program.*Breakpoint \[0-9\]+,.* at .*main.c:.*$function.*$gdb_prompt $" { -re "Starting program.*Breakpoint \[0-9\]+,.* at .*main.c:.*$function.*$gdb_prompt $" {

View file

@ -756,8 +756,8 @@ get_image_name (HANDLE h, void *address, int unicode)
do_initial_windows_stuff and windows_add_all_dlls for more info do_initial_windows_stuff and windows_add_all_dlls for more info
on how we handle DLL loading during that phase). */ on how we handle DLL loading during that phase). */
static int static void
handle_load_dll (void *dummy) handle_load_dll ()
{ {
LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll; LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
char *dll_name; char *dll_name;
@ -770,7 +770,7 @@ handle_load_dll (void *dummy)
dll_name = get_image_name (current_process_handle, dll_name = get_image_name (current_process_handle,
event->lpImageName, event->fUnicode); event->lpImageName, event->fUnicode);
if (!dll_name) if (!dll_name)
return 1; return;
solib_end->next = windows_make_so (dll_name, event->lpBaseOfDll); solib_end->next = windows_make_so (dll_name, event->lpBaseOfDll);
solib_end = solib_end->next; solib_end = solib_end->next;
@ -779,8 +779,6 @@ handle_load_dll (void *dummy)
DEBUG_EVENTS (("gdb: Loading dll \"%s\" at %s.\n", solib_end->so_name, DEBUG_EVENTS (("gdb: Loading dll \"%s\" at %s.\n", solib_end->so_name,
host_address_to_string (li->load_addr))); host_address_to_string (li->load_addr)));
return 1;
} }
static void static void
@ -800,8 +798,8 @@ windows_free_so (struct so_list *so)
do_initial_windows_stuff and windows_add_all_dlls for more info do_initial_windows_stuff and windows_add_all_dlls for more info
on how we handle DLL loading during that phase). */ on how we handle DLL loading during that phase). */
static int static void
handle_unload_dll (void *dummy) handle_unload_dll ()
{ {
LPVOID lpBaseOfDll = current_event.u.UnloadDll.lpBaseOfDll; LPVOID lpBaseOfDll = current_event.u.UnloadDll.lpBaseOfDll;
struct so_list *so; struct so_list *so;
@ -820,7 +818,7 @@ handle_unload_dll (void *dummy)
DEBUG_EVENTS (("gdb: Unloading dll \"%s\".\n", sodel->so_name)); DEBUG_EVENTS (("gdb: Unloading dll \"%s\".\n", sodel->so_name));
windows_free_so (sodel); windows_free_so (sodel);
return 1; return;
} }
} }
@ -833,8 +831,23 @@ handle_unload_dll (void *dummy)
32bit and 64bit worlds). */ 32bit and 64bit worlds). */
complaint (&symfile_complaints, _("dll starting at %s not found."), complaint (&symfile_complaints, _("dll starting at %s not found."),
host_address_to_string (lpBaseOfDll)); host_address_to_string (lpBaseOfDll));
}
return 0; /* Call FUNC wrapped in a TRY/CATCH that swallows all GDB
exceptions. */
static void
catch_errors (void (*func) ())
{
TRY
{
func ();
}
CATCH (ex, RETURN_MASK_ALL)
{
exception_print (gdb_stderr, ex);
}
END_CATCH
} }
/* Clear list of loaded DLLs. */ /* Clear list of loaded DLLs. */
@ -1542,7 +1555,7 @@ get_windows_debug_event (struct target_ops *ops,
CloseHandle (current_event.u.LoadDll.hFile); CloseHandle (current_event.u.LoadDll.hFile);
if (saw_create != 1 || ! windows_initialization_done) if (saw_create != 1 || ! windows_initialization_done)
break; break;
catch_errors (handle_load_dll, NULL, (char *) "", RETURN_MASK_ALL); catch_errors (handle_load_dll);
ourstatus->kind = TARGET_WAITKIND_LOADED; ourstatus->kind = TARGET_WAITKIND_LOADED;
ourstatus->value.integer = 0; ourstatus->value.integer = 0;
thread_id = main_thread_id; thread_id = main_thread_id;
@ -1555,7 +1568,7 @@ get_windows_debug_event (struct target_ops *ops,
"UNLOAD_DLL_DEBUG_EVENT")); "UNLOAD_DLL_DEBUG_EVENT"));
if (saw_create != 1 || ! windows_initialization_done) if (saw_create != 1 || ! windows_initialization_done)
break; break;
catch_errors (handle_unload_dll, NULL, (char *) "", RETURN_MASK_ALL); catch_errors (handle_unload_dll);
ourstatus->kind = TARGET_WAITKIND_LOADED; ourstatus->kind = TARGET_WAITKIND_LOADED;
ourstatus->value.integer = 0; ourstatus->value.integer = 0;
thread_id = main_thread_id; thread_id = main_thread_id;