diff options
Diffstat (limited to 'gdb/infcmd.c')
-rw-r--r-- | gdb/infcmd.c | 377 |
1 files changed, 324 insertions, 53 deletions
diff --git a/gdb/infcmd.c b/gdb/infcmd.c index eb11169..ba4e798 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -33,6 +33,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "language.h" #include "symfile.h" #include "objfiles.h" +#include "event-loop.h" /* Functions exported for general use: */ @@ -46,6 +47,8 @@ void registers_info PARAMS ((char *, int)); void continue_command PARAMS ((char *, int)); +static void finish_command_continuation PARAMS ((struct continuation_arg *)); + static void until_next_command PARAMS ((int)); static void until_command PARAMS ((char *, int)); @@ -94,6 +97,8 @@ static void run_no_args_command PARAMS ((char *args, int from_tty)); static void go_command PARAMS ((char *line_no, int from_tty)); +static int strip_bg_char PARAMS ((char **)); + void _initialize_infcmd PARAMS ((void)); #define GO_USAGE "Usage: go <location>\n" @@ -184,6 +189,35 @@ int step_multi; struct environ *inferior_environ; +/* This function detects whether or not a '&' character (indicating + background execution) has been added as *the last* of the arguments ARGS + of a command. If it has, it removes it and returns 1. Otherwise it + does nothing and returns 0. */ +static int +strip_bg_char (args) + char **args; +{ + char *p = NULL; + + if (p = strchr (*args, '&')) + { + if (p == (*args + strlen (*args) - 1)) + { + if (strlen (*args) >1) + { + do + p--; + while (*p == ' ' || *p == '\t'); + *(p + 1) = '\0'; + } + else + *args = 0; + return 1; + } + } + return 0; +} + /* ARGSUSED */ void tty_command (file, from_tty) @@ -239,12 +273,33 @@ Start it from the beginning? ")) the user has to manually nuke all symbols between runs if they want them to go away (PR 2207). This is probably reasonable. */ - if (args) + if (!args) + sync_execution = 1; + else { char *cmd; - cmd = concat ("set args ", args, NULL); - make_cleanup (free, cmd); - execute_command (cmd, from_tty); + int async_exec = strip_bg_char (&args); + + /* If we get a request for running in the bg but the target + doesn't support it, error out. */ + if (async_p && async_exec && !target_has_async) + error ("Asynchronous execution not supported on this target."); + + /* If we don't get a request of running in the bg, then we need + to simulate synchronous (fg) execution. */ + if (async_p && !async_exec && target_has_async) + { + /* Simulate synchronous execution */ + sync_execution = 1; + } + + /* If there were other args, beside '&', process them. */ + if (args) + { + cmd = concat ("set args ", args, NULL); + make_cleanup (free, cmd); + execute_command (cmd, from_tty); + } } if (from_tty) @@ -278,10 +333,28 @@ continue_command (proc_count_exp, from_tty) char *proc_count_exp; int from_tty; { + int async_exec = 0; ERROR_NO_INFERIOR; - /* If have argument, set proceed count of breakpoint we stopped at. */ + /* Find out whether we must run in the background. */ + if (proc_count_exp != NULL) + async_exec = strip_bg_char (&proc_count_exp); + + /* If we must run in the background, but the target can't do it, + error out. */ + if (async_p && async_exec && !target_has_async) + error ("Asynchronous execution not supported on this target."); + + /* If we are not asked to run in the bg, then prepare to run in the + foreground, synchronously. */ + if (async_p && !async_exec && target_has_async) + { + /* Simulate synchronous execution */ + sync_execution = 1; + } + /* If have argument (besides '&'), set proceed count of breakpoint + we stopped at. */ if (proc_count_exp != NULL) { bpstat bs = stop_bpstat; @@ -363,8 +436,26 @@ step_1 (skip_subroutines, single_inst, count_string) register int count = 1; struct frame_info *frame; struct cleanup *cleanups = 0; - + int async_exec = 0; + ERROR_NO_INFERIOR; + + if (count_string) + async_exec = strip_bg_char (&count_string); + + /* If we get a request for running in the bg but the target + doesn't support it, error out. */ + if (async_p && async_exec && !target_has_async) + error ("Asynchronous execution not supported on this target."); + + /* If we don't get a request of running in the bg, then we need + to simulate synchronous (fg) execution. */ + if (async_p && !async_exec && target_has_async) + { + /* Simulate synchronous execution */ + sync_execution = 1; + } + count = count_string ? parse_and_eval_address (count_string) : 1; if (!single_inst || skip_subroutines) /* leave si command alone */ @@ -443,9 +534,27 @@ jump_command (arg, from_tty) struct symtab_and_line sal; struct symbol *fn; struct symbol *sfn; - + int async_exec = 0; + ERROR_NO_INFERIOR; + /* Find out whether we must run in the background. */ + if (arg != NULL) + async_exec = strip_bg_char (&arg); + + /* If we must run in the background, but the target can't do it, + error out. */ + if (async_p && async_exec && !target_has_async) + error ("Asynchronous execution not supported on this target."); + + /* If we are not asked to run in the bg, then prepare to run in the + foreground, synchronously. */ + if (async_p && !async_exec && target_has_async) + { + /* Simulate synchronous execution */ + sync_execution = 1; + } + if (!arg) error_no_arg ("starting address"); @@ -490,7 +599,6 @@ jump_command (arg, from_tty) } } - addr = sal.pc; if (from_tty) @@ -731,14 +839,110 @@ until_command (arg, from_tty) char *arg; int from_tty; { + int async_exec = 0; + if (!target_has_execution) error ("The program is not running."); + + /* Find out whether we must run in the background. */ + if (arg != NULL) + async_exec = strip_bg_char (&arg); + + /* If we must run in the background, but the target can't do it, + error out. */ + if (async_p && async_exec && !target_has_async) + error ("Asynchronous execution not supported on this target."); + + /* If we are not asked to run in the bg, then prepare to run in the + foreground, synchronously. */ + if (async_p && !async_exec && target_has_async) + { + /* Simulate synchronous execution */ + sync_execution = 1; + } + if (arg) until_break_command (arg, from_tty); else until_next_command (from_tty); } + +/* Stuff that needs to be done by the finish command after the target + has stopped. In asynchronous mode, we wait for the target to stop in + the call to poll or select in the event loop, so it is impossible to + do all the stuff as part of the finish_command function itself. The + only chance we have to complete this command is in + fetch_inferior_event, which is called by the event loop as soon as it + detects that the target has stopped. This function is called via the + cmd_continaution pointer. */ +void +finish_command_continuation (arg) + struct continuation_arg *arg; +{ + register struct symbol *function; + struct breakpoint *breakpoint; + + breakpoint = (struct breakpoint *) arg->data; + function = (struct symbol *) (arg->next)->data; + + if (bpstat_find_breakpoint(stop_bpstat, breakpoint) != NULL + && function != 0) + { + struct type *value_type; + register value_ptr val; + CORE_ADDR funcaddr; + int struct_return; + + value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function)); + if (!value_type) + fatal ("internal: finish_command: function has no target type"); + + if (TYPE_CODE (value_type) == TYPE_CODE_VOID) + { + do_exec_cleanups (ALL_CLEANUPS); + return; + } + + funcaddr = BLOCK_START (SYMBOL_BLOCK_VALUE (function)); + + struct_return = using_struct_return (value_of_variable (function, NULL), + + funcaddr, + check_typedef (value_type), + BLOCK_GCC_COMPILED (SYMBOL_BLOCK_VALUE (function))); + + if (!struct_return) + { + val = value_being_returned (value_type, stop_registers, struct_return); + printf_filtered ("Value returned is $%d = ", record_latest_value (val)); + value_print (val, gdb_stdout, 0, Val_no_prettyprint); + printf_filtered ("\n"); + } + else + { + /* We cannot determine the contents of the structure because + it is on the stack, and we don't know where, since we did not + initiate the call, as opposed to the call_function_by_hand case */ +#ifdef VALUE_RETURNED_FROM_STACK + val = 0; + printf_filtered ("Value returned has type: %s.", + TYPE_NAME (value_type)); + printf_filtered (" Cannot determine contents\n"); +#else + val = value_being_returned (value_type, stop_registers, + struct_return); + printf_filtered ("Value returned is $%d = ", + record_latest_value (val)); + value_print (val, gdb_stdout, 0, Val_no_prettyprint); + printf_filtered ("\n"); +#endif + + } + } + do_exec_cleanups (ALL_CLEANUPS); +} + /* "finish": Set a temporary breakpoint at the place the selected frame will return to, then continue. */ @@ -752,6 +956,26 @@ finish_command (arg, from_tty) register struct symbol *function; struct breakpoint *breakpoint; struct cleanup *old_chain; + struct continuation_arg *arg1, *arg2; + + int async_exec = 0; + + /* Find out whether we must run in the background. */ + if (arg != NULL) + async_exec = strip_bg_char (&arg); + + /* If we must run in the background, but the target can't do it, + error out. */ + if (async_p && async_exec && !target_has_async) + error ("Asynchronous execution not supported on this target."); + + /* If we are not asked to run in the bg, then prepare to run in the + foreground, synchronously. */ + if (async_p && !async_exec && target_has_async) + { + /* Simulate synchronous execution */ + sync_execution = 1; + } if (arg) error ("The \"finish\" command does not take any arguments."); @@ -771,7 +995,10 @@ finish_command (arg, from_tty) breakpoint = set_momentary_breakpoint (sal, frame, bp_finish); - old_chain = make_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint); + if (!async_p || !target_has_async) + old_chain = make_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint); + else + make_exec_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint); /* Find the function we will return from. */ @@ -785,62 +1012,89 @@ finish_command (arg, from_tty) print_stack_frame (selected_frame, selected_frame_level, 0); } + /* If running asynchronously and the target support asynchronous + execution, set things up for the rest of the finish command to be + completed later on, when gdb has detected that the target has + stopped, in fetch_inferior_event. */ + if (async_p && target_has_async) + { + arg1 = + (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg)); + arg2 = + (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg)); + arg1->next = arg2; + arg2->next = NULL; + arg1->data = (PTR) breakpoint; + arg2->data = (PTR) function; + add_continuation (finish_command_continuation, arg1); + } + proceed_to_finish = 1; /* We want stop_registers, please... */ proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0); - /* Did we stop at our breakpoint? */ - if (bpstat_find_breakpoint(stop_bpstat, breakpoint) != NULL - && function != 0) - { - struct type *value_type; - register value_ptr val; - CORE_ADDR funcaddr; - int struct_return; + /* Do this only if not running asynchronously or if the target + cannot do async execution. Otherwise, complete this command when + the target actually stops, in fetch_inferior_event.*/ + if (!async_p || !target_has_async) + { - value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function)); - if (!value_type) - fatal ("internal: finish_command: function has no target type"); - - if (TYPE_CODE (value_type) == TYPE_CODE_VOID) - return; + /* Did we stop at our breakpoint? */ + if (bpstat_find_breakpoint(stop_bpstat, breakpoint) != NULL + && function != 0) + { + struct type *value_type; + register value_ptr val; + CORE_ADDR funcaddr; + int struct_return; - funcaddr = BLOCK_START (SYMBOL_BLOCK_VALUE (function)); + value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function)); + if (!value_type) + fatal ("internal: finish_command: function has no target type"); - struct_return = using_struct_return (value_of_variable (function, NULL), + /* FIXME: Shouldn't we do the cleanups before returning? */ + if (TYPE_CODE (value_type) == TYPE_CODE_VOID) + return; + + funcaddr = BLOCK_START (SYMBOL_BLOCK_VALUE (function)); + struct_return = + using_struct_return (value_of_variable (function, NULL), funcaddr, check_typedef (value_type), - BLOCK_GCC_COMPILED (SYMBOL_BLOCK_VALUE (function))); - - if (!struct_return) - { - val = value_being_returned (value_type, stop_registers, struct_return); - printf_filtered ("Value returned is $%d = ", record_latest_value (val)); - value_print (val, gdb_stdout, 0, Val_no_prettyprint); - printf_filtered ("\n"); - } - else - { - /* elz: we cannot determine the contents of the structure because - it is on the stack, and we don't know where, since we did not - initiate the call, as opposed to the call_function_by_hand case */ + BLOCK_GCC_COMPILED (SYMBOL_BLOCK_VALUE (function))); + + if (!struct_return) + { + val = + value_being_returned (value_type, stop_registers, struct_return); + printf_filtered ("Value returned is $%d = ", + record_latest_value (val)); + value_print (val, gdb_stdout, 0, Val_no_prettyprint); + printf_filtered ("\n"); + } + else + { + /* We cannot determine the contents of the structure + because it is on the stack, and we don't know + where, since we did not initiate the call, as + opposed to the call_function_by_hand case */ #ifdef VALUE_RETURNED_FROM_STACK - val = 0; - printf_filtered ("Value returned has type: %s.", - TYPE_NAME (value_type)); - printf_filtered (" Cannot determine contents\n"); + val = 0; + printf_filtered ("Value returned has type: %s.", + TYPE_NAME (value_type)); + printf_filtered (" Cannot determine contents\n"); #else - val = value_being_returned (value_type, stop_registers, - struct_return); - printf_filtered ("Value returned is $%d = ", - record_latest_value (val)); - value_print (val, gdb_stdout, 0, Val_no_prettyprint); - printf_filtered ("\n"); -#endif - + val = value_being_returned (value_type, stop_registers, + struct_return); + printf_filtered ("Value returned is $%d = ", + record_latest_value (val)); + value_print (val, gdb_stdout, 0, Val_no_prettyprint); + printf_filtered ("\n"); +#endif + } + } + do_cleanups(old_chain); } - } - do_cleanups(old_chain); } /* ARGSUSED */ @@ -1355,6 +1609,20 @@ detach_command (args, from_tty) #endif } +/* Stop the execution of the target while running in async mode, in + the backgound. */ +static void +interrupt_target_command (args, from_tty) + char *args; + int from_tty; +{ + if (async_p && target_has_async) + { + dont_repeat (); /* Not for the faint of heart */ + target_stop (); + } +} + /* ARGSUSED */ static void float_info (addr_exp, from_tty) @@ -1530,6 +1798,9 @@ use \"set args\" without arguments."); add_com ("R", class_run, run_no_args_command, "Start debugged program with no arguments."); + add_com ("interrupt", class_run, interrupt_target_command, + "Interrupt the execution of the debugged program."); + add_info ("registers", nofp_registers_info, "List of integer registers and their contents, for selected stack frame.\n\ Register name as argument means describe only that register."); |