X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Finfcmd.c;h=6831d6be8f93504118d9c9d9a8b1bd4a444fe550;hb=c9263853b89401a8c592669ede96947711820b48;hp=a36258152c71385af0741cc99e1a39dc9634d643;hpb=a58dd3735c499b8e076e7e283b87361732119191;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/infcmd.c b/gdb/infcmd.c index a36258152c..6831d6be8f 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,9 @@ #include "event-top.h" #include "parser-defs.h" #include "regcache.h" +#include "reggroups.h" +#include "block.h" +#include /* Functions exported for general use, in inferior.h: */ @@ -78,6 +81,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 +117,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 +183,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. */ @@ -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') + { + *out++ = '\''; + *out++ = '\''; + } + else { - if (strchr (special, *cp) != NULL) - *out++ = '\\'; - *out++ = *cp; + for (cp = argv[i]; *cp; ++cp) + { + if (strchr (special, *cp) != NULL) + *out++ = '\\'; + *out++ = *cp; + } } } *out = '\0'; @@ -616,7 +628,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 +743,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) @@ -843,7 +855,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 +950,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. @@ -1094,7 +997,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 +1031,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. */ @@ -1261,19 +1195,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 +1216,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 @@ -1568,13 +1502,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 +1517,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,9 +1553,9 @@ 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 @@ -1630,11 +1566,11 @@ default_print_registers_info (struct gdbarch *gdbarch, /* 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"); @@ -1652,24 +1588,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"); } } @@ -1682,45 +1612,100 @@ registers_info (char *addr_exp, int fpregs) 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; + char *start; + const char *end; - regnum = frame_map_name_to_regnum (addr_exp, end - addr_exp); - if (regnum >= 0) - goto found; - - 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 +1724,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 +1736,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 +1752,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 +1805,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 +1879,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 @@ -1906,27 +1916,21 @@ 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,14 +1939,13 @@ 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 */ @@ -2034,6 +2037,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 +2076,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\