From ce05fcf529ba4d8eee9e20ad733a0e0348d0a176 Mon Sep 17 00:00:00 2001 From: Daniel Jacobowitz Date: Sun, 14 Dec 2003 20:28:56 +0000 Subject: Merge drow-cplus-branch to: cvs rtag -D 2003-12-14 00:00:00 UTC drow-cplus-merge-20031214 gdb+dejagnu --- gdb/infcmd.c | 517 +++++++++++++++++++++++++++++++---------------------------- 1 file changed, 274 insertions(+), 243 deletions(-) (limited to 'gdb/infcmd.c') diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 5359e290e7b..2c8631eb3ba 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -1,6 +1,6 @@ /* Memory-access and commands for "inferior" process, for GDB. Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1998, 1999, 2000, 2001, 2002 + 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. This file is part of GDB. @@ -41,6 +41,10 @@ #include "event-top.h" #include "parser-defs.h" #include "regcache.h" +#include "reggroups.h" +#include "block.h" +#include +#include "gdb_assert.h" /* Functions exported for general use, in inferior.h: */ @@ -78,6 +82,8 @@ static void float_info (char *, int); static void detach_command (char *, int); +static void disconnect_command (char *, int); + static void unset_environment_command (char *, int); static void set_environment_command (char *, int); @@ -112,8 +118,6 @@ void _initialize_infcmd (void); #define GO_USAGE "Usage: go \n" -static void breakpoint_auto_delete_contents (PTR); - #define ERROR_NO_INFERIOR \ if (!target_has_execution) error ("The program is not being run."); @@ -180,7 +184,7 @@ CORE_ADDR step_range_end; /* Exclusive */ This is how we know when we step into a subroutine call, and how to set the frame for the breakpoint used to step out. */ -CORE_ADDR step_frame_address; +struct frame_id step_frame_id; /* Our notion of the current stack pointer. */ @@ -258,7 +262,6 @@ notice_args_read (char *args, int from_tty, struct cmd_list_element *c) /* Compute command-line string given argument vector. This does the same shell processing as fork_inferior. */ -/* ARGSUSED */ char * construct_inferior_arguments (struct gdbarch *gdbarch, int argc, char **argv) { @@ -276,7 +279,7 @@ construct_inferior_arguments (struct gdbarch *gdbarch, int argc, char **argv) /* We over-compute the size. It shouldn't matter. */ for (i = 0; i < argc; ++i) - length += 2 * strlen (argv[i]) + 1; + length += 2 * strlen (argv[i]) + 1 + 2 * (argv[i][0] == '\0'); result = (char *) xmalloc (length); out = result; @@ -286,11 +289,20 @@ construct_inferior_arguments (struct gdbarch *gdbarch, int argc, char **argv) if (i > 0) *out++ = ' '; - for (cp = argv[i]; *cp; ++cp) + /* Need to handle empty arguments specially. */ + if (argv[i][0] == '\0') { - if (strchr (special, *cp) != NULL) - *out++ = '\\'; - *out++ = *cp; + *out++ = '\''; + *out++ = '\''; + } + else + { + for (cp = argv[i]; *cp; ++cp) + { + if (strchr (special, *cp) != NULL) + *out++ = '\\'; + *out++ = *cp; + } } } *out = '\0'; @@ -358,7 +370,6 @@ strip_bg_char (char **args) return 0; } -/* ARGSUSED */ void tty_command (char *file, int from_tty) { @@ -531,7 +542,6 @@ continue_command (char *proc_count_exp, int from_tty) /* Step until outside of current statement. */ -/* ARGSUSED */ static void step_command (char *count_string, int from_tty) { @@ -540,7 +550,6 @@ step_command (char *count_string, int from_tty) /* Likewise, but skip over subroutine calls as if single instructions. */ -/* ARGSUSED */ static void next_command (char *count_string, int from_tty) { @@ -549,14 +558,12 @@ next_command (char *count_string, int from_tty) /* Likewise, but step only one instruction. */ -/* ARGSUSED */ void stepi_command (char *count_string, int from_tty) { step_1 (0, 1, count_string); } -/* ARGSUSED */ void nexti_command (char *count_string, int from_tty) { @@ -572,7 +579,7 @@ disable_longjmp_breakpoint_cleanup (void *ignore) static void step_1 (int skip_subroutines, int single_inst, char *count_string) { - register int count = 1; + int count = 1; struct frame_info *frame; struct cleanup *cleanups = 0; int async_exec = 0; @@ -616,7 +623,7 @@ step_1 (int skip_subroutines, int single_inst, char *count_string) frame = get_current_frame (); if (!frame) /* Avoid coredump here. Why tho? */ error ("No current frame"); - step_frame_address = FRAME_FP (frame); + step_frame_id = get_frame_id (frame); step_sp = read_sp (); if (!single_inst) @@ -731,7 +738,7 @@ step_once (int skip_subroutines, int single_inst, int count) frame = get_current_frame (); if (!frame) /* Avoid coredump here. Why tho? */ error ("No current frame"); - step_frame_address = FRAME_FP (frame); + step_frame_id = get_frame_id (frame); step_sp = read_sp (); if (!single_inst) @@ -794,7 +801,7 @@ which has no line number information.\n", name); static void jump_command (char *arg, int from_tty) { - register CORE_ADDR addr; + CORE_ADDR addr; struct symtabs_and_lines sals; struct symtab_and_line sal; struct symbol *fn; @@ -843,7 +850,7 @@ jump_command (char *arg, int from_tty) if (fn != NULL && sfn != fn) { if (!query ("Line %d is not in `%s'. Jump anyway? ", sal.line, - SYMBOL_SOURCE_NAME (fn))) + SYMBOL_PRINT_NAME (fn))) { error ("Not confirmed."); /* NOTREACHED */ @@ -938,115 +945,6 @@ signal_command (char *signum_exp, int from_tty) proceed (oursig == TARGET_SIGNAL_0 ? (CORE_ADDR) -1 : stop_pc, oursig, 0); } -/* Call breakpoint_auto_delete on the current contents of the bpstat - pointed to by arg (which is really a bpstat *). */ - -static void -breakpoint_auto_delete_contents (PTR arg) -{ - breakpoint_auto_delete (*(bpstat *) arg); -} - - -/* Execute a "stack dummy", a piece of code stored in the stack - by the debugger to be executed in the inferior. - - To call: first, do PUSH_DUMMY_FRAME. - Then push the contents of the dummy. It should end with a breakpoint insn. - Then call here, passing address at which to start the dummy. - - The contents of all registers are saved before the dummy frame is popped - and copied into the buffer BUFFER. - - The dummy's frame is automatically popped whenever that break is hit. - If that is the first time the program stops, run_stack_dummy - returns to its caller with that frame already gone and returns 0. - - Otherwise, run_stack-dummy returns a non-zero value. - If the called function receives a random signal, we do not allow the user - to continue executing it as this may not work. The dummy frame is poped - and we return 1. - If we hit a breakpoint, we leave the frame in place and return 2 (the frame - will eventually be popped when we do hit the dummy end breakpoint). */ - -int -run_stack_dummy (CORE_ADDR addr, struct regcache *buffer) -{ - struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0); - int saved_async = 0; - - /* Now proceed, having reached the desired place. */ - clear_proceed_status (); - - if (CALL_DUMMY_BREAKPOINT_OFFSET_P) - { - struct breakpoint *bpt; - struct symtab_and_line sal; - - init_sal (&sal); /* initialize to zeroes */ - if (CALL_DUMMY_LOCATION == AT_ENTRY_POINT) - { - sal.pc = CALL_DUMMY_ADDRESS (); - } - else - { - sal.pc = addr - CALL_DUMMY_START_OFFSET + CALL_DUMMY_BREAKPOINT_OFFSET; - } - sal.section = find_pc_overlay (sal.pc); - - /* Set up a FRAME for the dummy frame so we can pass it to - set_momentary_breakpoint. We need to give the breakpoint a - frame in case there is only one copy of the dummy (e.g. - CALL_DUMMY_LOCATION == AFTER_TEXT_END). */ - flush_cached_frames (); - set_current_frame (create_new_frame (read_fp (), sal.pc)); - - /* If defined, CALL_DUMMY_BREAKPOINT_OFFSET is where we need to put - a breakpoint instruction. If not, the call dummy already has the - breakpoint instruction in it. - - addr is the address of the call dummy plus the CALL_DUMMY_START_OFFSET, - so we need to subtract the CALL_DUMMY_START_OFFSET. */ - bpt = set_momentary_breakpoint (sal, - get_current_frame (), - bp_call_dummy); - bpt->disposition = disp_del; - - /* If all error()s out of proceed ended up calling normal_stop (and - perhaps they should; it already does in the special case of error - out of resume()), then we wouldn't need this. */ - make_cleanup (breakpoint_auto_delete_contents, &stop_bpstat); - } - - disable_watchpoints_before_interactive_call_start (); - proceed_to_finish = 1; /* We want stop_registers, please... */ - - if (target_can_async_p ()) - saved_async = target_async_mask (0); - - proceed (addr, TARGET_SIGNAL_0, 0); - - if (saved_async) - target_async_mask (saved_async); - - enable_watchpoints_after_interactive_call_stop (); - - discard_cleanups (old_cleanups); - - /* We can stop during an inferior call because a signal is received. */ - if (stopped_by_random_signal) - return 1; - - /* We may also stop prematurely because we hit a breakpoint in the - called routine. */ - if (!stop_stack_dummy) - return 2; - - /* On normal return, the stack dummy has been popped already. */ - regcache_cpy_no_passthrough (buffer, stop_registers); - return 0; -} - /* Proceed until we reach a different source line with pc greater than our current one or exit the function. We skip calls in both cases. @@ -1055,7 +953,6 @@ run_stack_dummy (CORE_ADDR addr, struct regcache *buffer) we set. This may involve changes to wait_for_inferior and the proceed status code. */ -/* ARGSUSED */ static void until_next_command (int from_tty) { @@ -1094,7 +991,7 @@ until_next_command (int from_tty) } step_over_calls = STEP_OVER_ALL; - step_frame_address = FRAME_FP (frame); + step_frame_id = get_frame_id (frame); step_sp = read_sp (); step_multi = 0; /* Only one call to proceed */ @@ -1128,10 +1025,41 @@ until_command (char *arg, int from_tty) } if (arg) - until_break_command (arg, from_tty); + until_break_command (arg, from_tty, 0); else until_next_command (from_tty); } + +static void +advance_command (char *arg, int from_tty) +{ + int async_exec = 0; + + if (!target_has_execution) + error ("The program is not running."); + + if (arg == NULL) + error_no_arg ("a location"); + + /* 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 (event_loop_p && async_exec && !target_can_async_p ()) + 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 (event_loop_p && !async_exec && target_can_async_p ()) + { + /* Simulate synchronous execution. */ + async_disable_stdin (); + } + + until_break_command (arg, from_tty, 1); +} /* Print the result of a function at the end of a 'finish' command. */ @@ -1143,7 +1071,7 @@ print_return_value (int structure_return, struct type *value_type) if (!structure_return) { - value = value_being_returned (value_type, stop_registers, structure_return); + value = register_value_being_returned (value_type, stop_registers); stb = ui_out_stream_new (uiout); ui_out_text (uiout, "Value returned is "); ui_out_field_fmt (uiout, "gdb-result-var", "$%d", record_latest_value (value)); @@ -1152,19 +1080,56 @@ print_return_value (int structure_return, struct type *value_type) ui_out_field_stream (uiout, "return-value", stb); ui_out_text (uiout, "\n"); } - else + /* FIXME: 2003-09-27: When returning from a nested inferior function + call, it's possible (with no help from the architecture vector) + to locate and return/print a "struct return" value. This is just + a more complicated case of what is already being done in in the + inferior function call code. In fact, when inferior function + calls are made async, this will likely be made the norm. */ + else if (gdbarch_return_value_p (current_gdbarch)) + /* 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. */ { - /* 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 - value = 0; + gdb_assert (gdbarch_return_value (current_gdbarch, value_type, NULL, NULL, NULL) + == RETURN_VALUE_STRUCT_CONVENTION); ui_out_text (uiout, "Value returned has type: "); ui_out_field_string (uiout, "return-type", TYPE_NAME (value_type)); ui_out_text (uiout, "."); ui_out_text (uiout, " Cannot determine contents\n"); -#else - value = value_being_returned (value_type, stop_registers, structure_return); + return; + } + else + { + if (EXTRACT_STRUCT_VALUE_ADDRESS_P ()) + { + CORE_ADDR addr = EXTRACT_STRUCT_VALUE_ADDRESS (stop_registers); + if (!addr) + error ("Function return value unknown."); + value = value_at (value_type, addr, NULL); + } + else if (DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS_P ()) + { + char *buf = deprecated_grub_regcache_for_registers (stop_registers); + CORE_ADDR addr = DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS (buf); + if (!addr) + error ("Function return value unknown."); + value = value_at (value_type, addr, NULL); + } + else + { + /* It is "struct return" yet the value is being extracted, + presumably from registers, using EXTRACT_RETURN_VALUE. + This doesn't make sense. Unfortunately, the legacy + interfaces allowed this behavior. Sigh! */ + value = allocate_value (value_type); + CHECK_TYPEDEF (value_type); + /* If the function returns void, don't bother fetching the + return value. */ + EXTRACT_RETURN_VALUE (value_type, stop_registers, + VALUE_CONTENTS_RAW (value)); + } stb = ui_out_stream_new (uiout); ui_out_text (uiout, "Value returned is "); ui_out_field_fmt (uiout, "gdb-result-var", "$%d", record_latest_value (value)); @@ -1172,7 +1137,6 @@ print_return_value (int structure_return, struct type *value_type) value_print (value, stb->stream, 0, Val_no_prettyprint); ui_out_field_stream (uiout, "return-value", stb); ui_out_text (uiout, "\n"); -#endif } } @@ -1187,7 +1151,7 @@ print_return_value (int structure_return, struct type *value_type) void finish_command_continuation (struct continuation_arg *arg) { - register struct symbol *function; + struct symbol *function; struct breakpoint *breakpoint; struct cleanup *cleanups; @@ -1215,9 +1179,7 @@ finish_command_continuation (struct continuation_arg *arg) funcaddr = BLOCK_START (SYMBOL_BLOCK_VALUE (function)); - struct_return = using_struct_return (value_of_variable (function, NULL), - funcaddr, - check_typedef (value_type), + struct_return = using_struct_return (check_typedef (value_type), BLOCK_GCC_COMPILED (SYMBOL_BLOCK_VALUE (function))); print_return_value (struct_return, value_type); @@ -1232,8 +1194,8 @@ static void finish_command (char *arg, int from_tty) { struct symtab_and_line sal; - register struct frame_info *frame; - register struct symbol *function; + struct frame_info *frame; + struct symbol *function; struct breakpoint *breakpoint; struct cleanup *old_chain; struct continuation_arg *arg1, *arg2, *arg3; @@ -1261,19 +1223,19 @@ finish_command (char *arg, int from_tty) error ("The \"finish\" command does not take any arguments."); if (!target_has_execution) error ("The program is not running."); - if (selected_frame == NULL) + if (deprecated_selected_frame == NULL) error ("No selected frame."); - frame = get_prev_frame (selected_frame); + frame = get_prev_frame (deprecated_selected_frame); if (frame == 0) error ("\"finish\" not meaningful in the outermost frame."); clear_proceed_status (); - sal = find_pc_line (frame->pc, 0); - sal.pc = frame->pc; + sal = find_pc_line (get_frame_pc (frame), 0); + sal.pc = get_frame_pc (frame); - breakpoint = set_momentary_breakpoint (sal, frame, bp_finish); + breakpoint = set_momentary_breakpoint (sal, get_frame_id (frame), bp_finish); if (!event_loop_p || !target_can_async_p ()) old_chain = make_cleanup_delete_breakpoint (breakpoint); @@ -1282,15 +1244,15 @@ finish_command (char *arg, int from_tty) /* Find the function we will return from. */ - function = find_pc_function (selected_frame->pc); + function = find_pc_function (get_frame_pc (deprecated_selected_frame)); /* Print info on the selected frame, including level number but not source. */ if (from_tty) { printf_filtered ("Run till exit from "); - print_stack_frame (selected_frame, - frame_relative_level (selected_frame), 0); + print_stack_frame (deprecated_selected_frame, + frame_relative_level (deprecated_selected_frame), 0); } /* If running asynchronously and the target support asynchronous @@ -1343,9 +1305,7 @@ finish_command (char *arg, int from_tty) funcaddr = BLOCK_START (SYMBOL_BLOCK_VALUE (function)); struct_return = - using_struct_return (value_of_variable (function, NULL), - funcaddr, - check_typedef (value_type), + using_struct_return (check_typedef (value_type), BLOCK_GCC_COMPILED (SYMBOL_BLOCK_VALUE (function))); print_return_value (struct_return, value_type); @@ -1354,7 +1314,6 @@ finish_command (char *arg, int from_tty) } } -/* ARGSUSED */ static void program_info (char *args, int from_tty) { @@ -1407,7 +1366,7 @@ environment_info (char *var, int from_tty) { if (var) { - register char *val = get_in_environ (inferior_environ, var); + char *val = get_in_environ (inferior_environ, var); if (val) { puts_filtered (var); @@ -1424,7 +1383,7 @@ environment_info (char *var, int from_tty) } else { - register char **vector = environ_vector (inferior_environ); + char **vector = environ_vector (inferior_environ); while (*vector) { puts_filtered (*vector++); @@ -1436,7 +1395,7 @@ environment_info (char *var, int from_tty) static void set_environment_command (char *arg, int from_tty) { - register char *p, *val, *var; + char *p, *val, *var; int nullset = 0; if (arg == 0) @@ -1516,7 +1475,6 @@ unset_environment_command (char *var, int from_tty) static const char path_var_name[] = "PATH"; -/* ARGSUSED */ static void path_info (char *args, int from_tty) { @@ -1546,9 +1504,6 @@ path_command (char *dirname, int from_tty) } -#ifdef REGISTER_NAMES -char *gdb_register_names[] = REGISTER_NAMES; -#endif /* Print out the machine register regnum. If regnum is -1, print all registers (print_all == 1) or all non-float and non-vector registers (print_all == 0). @@ -1568,13 +1523,12 @@ default_print_registers_info (struct gdbarch *gdbarch, { int i; const int numregs = NUM_REGS + NUM_PSEUDO_REGS; - char *raw_buffer = alloca (MAX_REGISTER_RAW_SIZE); - char *virtual_buffer = alloca (MAX_REGISTER_VIRTUAL_SIZE); + char raw_buffer[MAX_REGISTER_SIZE]; + char virtual_buffer[MAX_REGISTER_SIZE]; - /* FIXME: cagney/2002-03-08: This should be deprecated. */ - if (DO_REGISTERS_INFO_P ()) + if (DEPRECATED_DO_REGISTERS_INFO_P ()) { - DO_REGISTERS_INFO (regnum, print_all); + DEPRECATED_DO_REGISTERS_INFO (regnum, print_all); return; } @@ -1584,11 +1538,14 @@ default_print_registers_info (struct gdbarch *gdbarch, specific reg. */ if (regnum == -1) { - if (!print_all) + if (print_all) { - if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT) + if (!gdbarch_register_reggroup_p (gdbarch, i, all_reggroup)) continue; - if (TYPE_VECTOR (REGISTER_VIRTUAL_TYPE (i))) + } + else + { + if (!gdbarch_register_reggroup_p (gdbarch, i, general_reggroup)) continue; } } @@ -1617,34 +1574,34 @@ default_print_registers_info (struct gdbarch *gdbarch, The function frame_register_read() should have returned the pre-cooked register so no conversion is necessary. */ /* Convert raw data to virtual format if necessary. */ - if (REGISTER_CONVERTIBLE (i)) + if (DEPRECATED_REGISTER_CONVERTIBLE (i)) { - REGISTER_CONVERT_TO_VIRTUAL (i, REGISTER_VIRTUAL_TYPE (i), + DEPRECATED_REGISTER_CONVERT_TO_VIRTUAL (i, register_type (current_gdbarch, i), raw_buffer, virtual_buffer); } else { memcpy (virtual_buffer, raw_buffer, - REGISTER_VIRTUAL_SIZE (i)); + DEPRECATED_REGISTER_VIRTUAL_SIZE (i)); } /* If virtual format is floating, print it that way, and in raw hex. */ - if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT) + if (TYPE_CODE (register_type (current_gdbarch, i)) == TYPE_CODE_FLT) { int j; - val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0, + val_print (register_type (current_gdbarch, i), virtual_buffer, 0, 0, file, 0, 1, 0, Val_pretty_default); fprintf_filtered (file, "\t(raw 0x"); - for (j = 0; j < REGISTER_RAW_SIZE (i); j++) + for (j = 0; j < DEPRECATED_REGISTER_RAW_SIZE (i); j++) { int idx; if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) idx = j; else - idx = REGISTER_RAW_SIZE (i) - 1 - j; + idx = DEPRECATED_REGISTER_RAW_SIZE (i) - 1 - j; fprintf_filtered (file, "%02x", (unsigned char) raw_buffer[idx]); } fprintf_filtered (file, ")"); @@ -1652,24 +1609,18 @@ default_print_registers_info (struct gdbarch *gdbarch, else { /* Print the register in hex. */ - val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0, + val_print (register_type (current_gdbarch, i), virtual_buffer, 0, 0, file, 'x', 1, 0, Val_pretty_default); /* If not a vector register, print it also according to its natural format. */ - if (TYPE_VECTOR (REGISTER_VIRTUAL_TYPE (i)) == 0) + if (TYPE_VECTOR (register_type (current_gdbarch, i)) == 0) { fprintf_filtered (file, "\t"); - val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0, + val_print (register_type (current_gdbarch, i), virtual_buffer, 0, 0, file, 0, 1, 0, Val_pretty_default); } } - /* The SPARC wants to print even-numbered float regs as doubles - in addition to printing them as floats. */ -#ifdef PRINT_REGISTER_HOOK - PRINT_REGISTER_HOOK (i); -#endif - fprintf_filtered (file, "\n"); } } @@ -1678,49 +1629,104 @@ void registers_info (char *addr_exp, int fpregs) { int regnum, numregs; - register char *end; + char *end; if (!target_has_registers) error ("The program has no registers now."); - if (selected_frame == NULL) + if (deprecated_selected_frame == NULL) error ("No selected frame."); if (!addr_exp) { gdbarch_print_registers_info (current_gdbarch, gdb_stdout, - selected_frame, -1, fpregs); + deprecated_selected_frame, -1, fpregs); return; } - do + while (*addr_exp != '\0') { - if (addr_exp[0] == '$') - addr_exp++; - end = addr_exp; - while (*end != '\0' && *end != ' ' && *end != '\t') - ++end; - numregs = NUM_REGS + NUM_PSEUDO_REGS; - - regnum = frame_map_name_to_regnum (addr_exp, end - addr_exp); - if (regnum >= 0) - goto found; + char *start; + const char *end; - regnum = numregs; + /* Keep skipping leading white space. */ + if (isspace ((*addr_exp))) + { + addr_exp++; + continue; + } - if (*addr_exp >= '0' && *addr_exp <= '9') - regnum = atoi (addr_exp); /* Take a number */ - if (regnum >= numregs) /* Bad name, or bad number */ - error ("%.*s: invalid register", (int) (end - addr_exp), addr_exp); + /* Discard any leading ``$''. Check that there is something + resembling a register following it. */ + if (addr_exp[0] == '$') + addr_exp++; + if (isspace ((*addr_exp)) || (*addr_exp) == '\0') + error ("Missing register name"); - found: - gdbarch_print_registers_info (current_gdbarch, gdb_stdout, - selected_frame, regnum, fpregs); + /* Find the start/end of this register name/num/group. */ + start = addr_exp; + while ((*addr_exp) != '\0' && !isspace ((*addr_exp))) + addr_exp++; + end = addr_exp; + + /* Figure out what we've found and display it. */ + + /* A register name? */ + { + int regnum = frame_map_name_to_regnum (deprecated_selected_frame, + start, end - start); + if (regnum >= 0) + { + gdbarch_print_registers_info (current_gdbarch, gdb_stdout, + deprecated_selected_frame, regnum, fpregs); + continue; + } + } + + /* A register number? (how portable is this one?). */ + { + char *endptr; + int regnum = strtol (start, &endptr, 0); + if (endptr == end + && regnum >= 0 + && regnum < NUM_REGS + NUM_PSEUDO_REGS) + { + gdbarch_print_registers_info (current_gdbarch, gdb_stdout, + deprecated_selected_frame, regnum, fpregs); + continue; + } + } + + /* A register group? */ + { + struct reggroup *group; + for (group = reggroup_next (current_gdbarch, NULL); + group != NULL; + group = reggroup_next (current_gdbarch, group)) + { + /* Don't bother with a length check. Should the user + enter a short register group name, go with the first + group that matches. */ + if (strncmp (start, reggroup_name (group), end - start) == 0) + break; + } + if (group != NULL) + { + int regnum; + for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++) + { + if (gdbarch_register_reggroup_p (current_gdbarch, regnum, + group)) + gdbarch_print_registers_info (current_gdbarch, + gdb_stdout, deprecated_selected_frame, + regnum, fpregs); + } + continue; + } + } - addr_exp = end; - while (*addr_exp == ' ' || *addr_exp == '\t') - ++addr_exp; + /* Nothing matched. */ + error ("Invalid register `%.*s'", (int) (end - start), start); } - while (*addr_exp != '\0'); } void @@ -1739,6 +1745,11 @@ static void print_vector_info (struct gdbarch *gdbarch, struct ui_file *file, struct frame_info *frame, const char *args) { + if (!target_has_registers) + error ("The program has no registers now."); + if (deprecated_selected_frame == NULL) + error ("No selected frame."); + if (gdbarch_print_vector_info_p (gdbarch)) gdbarch_print_vector_info (gdbarch, file, frame, args); else @@ -1746,14 +1757,9 @@ print_vector_info (struct gdbarch *gdbarch, struct ui_file *file, int regnum; int printed_something = 0; - if (!target_has_registers) - error ("The program has no registers now."); - if (selected_frame == NULL) - error ("No selected frame."); - for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++) { - if (TYPE_VECTOR (REGISTER_VIRTUAL_TYPE (regnum))) + if (gdbarch_register_reggroup_p (gdbarch, regnum, vector_reggroup)) { printed_something = 1; gdbarch_print_registers_info (gdbarch, file, frame, regnum, 1); @@ -1767,7 +1773,7 @@ print_vector_info (struct gdbarch *gdbarch, struct ui_file *file, static void vector_info (char *args, int from_tty) { - print_vector_info (current_gdbarch, gdb_stdout, selected_frame, args); + print_vector_info (current_gdbarch, gdb_stdout, deprecated_selected_frame, args); } @@ -1820,8 +1826,13 @@ attach_command (char *args, int from_tty) /* No traps are generated when attaching to inferior under Mach 3 or GNU hurd. */ #ifndef ATTACH_NO_WAIT - stop_soon_quietly = 1; + /* Careful here. See comments in inferior.h. Basically some OSes + don't ignore SIGSTOPs on continue requests anymore. We need a + way for handle_inferior_event to reset the stop_signal variable + after an attach, and this is what STOP_QUIETLY_NO_SIGSTOP is for. */ + stop_soon = STOP_QUIETLY_NO_SIGSTOP; wait_for_inferior (); + stop_soon = NO_STOP_QUIETLY; #endif /* @@ -1889,6 +1900,26 @@ detach_command (char *args, int from_tty) detach_hook (); } +/* Disconnect from the current target without resuming it (leaving it + waiting for a debugger). + + We'd better not have left any breakpoints in the program or the + next debugger will get confused. Currently only supported for some + remote targets, since the normal attach mechanisms don't work on + stopped processes on some native platforms (e.g. GNU/Linux). */ + +static void +disconnect_command (char *args, int from_tty) +{ + dont_repeat (); /* Not for the faint of heart */ + target_disconnect (args, from_tty); +#if defined(SOLIB_RESTART) + SOLIB_RESTART (); +#endif + if (detach_hook) + detach_hook (); +} + /* Stop the execution of the target while running in async mode, in the backgound. */ void @@ -1901,32 +1932,25 @@ interrupt_target_command (char *args, int from_tty) } } -/* ARGSUSED */ static void print_float_info (struct gdbarch *gdbarch, struct ui_file *file, struct frame_info *frame, const char *args) { + if (!target_has_registers) + error ("The program has no registers now."); + if (deprecated_selected_frame == NULL) + error ("No selected frame."); + if (gdbarch_print_float_info_p (gdbarch)) gdbarch_print_float_info (gdbarch, file, frame, args); else { -#ifdef FLOAT_INFO -#if GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL -#error "FLOAT_INFO defined in multi-arch" -#endif - FLOAT_INFO; -#else int regnum; int printed_something = 0; - if (!target_has_registers) - error ("The program has no registers now."); - if (selected_frame == NULL) - error ("No selected frame."); - for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++) { - if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT) + if (gdbarch_register_reggroup_p (gdbarch, regnum, float_reggroup)) { printed_something = 1; gdbarch_print_registers_info (gdbarch, file, frame, regnum, 1); @@ -1935,17 +1959,15 @@ print_float_info (struct gdbarch *gdbarch, struct ui_file *file, if (!printed_something) fprintf_filtered (file, "\ No floating-point info available for this processor.\n"); -#endif } } static void float_info (char *args, int from_tty) { - print_float_info (current_gdbarch, gdb_stdout, selected_frame, args); + print_float_info (current_gdbarch, gdb_stdout, deprecated_selected_frame, args); } -/* ARGSUSED */ static void unset_command (char *args, int from_tty) { @@ -2034,6 +2056,11 @@ to specify the program, and to load its symbol table."); If a process, it is no longer traced, and it continues its execution. If\n\ you were debugging a file, the file is closed and gdb no longer accesses it."); + add_com ("disconnect", class_run, disconnect_command, + "Disconnect from a target.\n\ +The target will wait for another debugger to connect. Not available for\n\ +all targets."); + add_com ("signal", class_run, signal_command, "Continue program giving it signal specified by the argument.\n\ An argument of \"0\" means continue program without giving it a signal."); @@ -2068,11 +2095,15 @@ Argument N means do this N times (or till program stops for another reason)."); c = add_com ("until", class_run, until_command, "Execute until the program reaches a source line greater than the current\n\ -or a specified line or address or function (same args as break command).\n\ -Execution will also stop upon exit from the current stack frame."); +or a specified location (same args as break command) within the current frame."); set_cmd_completer (c, location_completer); add_com_alias ("u", "until", class_run, 1); + c = add_com ("advance", class_run, advance_command, + "Continue the program up to the given location (same form as args for break command).\n\ +Execution will also stop upon exit from the current stack frame."); + set_cmd_completer (c, location_completer); + c = add_com ("jump", class_run, jump_command, "Continue program being debugged at specified line or address.\n\ Give as argument either LINENUM or *ADDR, where ADDR is an expression\n\ -- cgit v1.2.1