* defs.h, infrun.c (wait_for_inferior), top.c: Call

target_wait_hook to allow GUI to handle blocking for inferior.  Call
	call_command_hook in execute_command to provide means for wrapping
	commands with GUI state change updates.
	* gdbtk.c (gdb_cmd):  Force GUI into idle mode when errors occur.
	* (gdb_stop):  New tcl command to stop the target process.
	* (x_event, gdbtk_wait):  Allow GUI to interrupt gdb out of target
	waits.
	* (gdbtk_call_command):  Wrapper around command processing to
	alert GUI of target state changes.
	* (gdbtk_init):  Get the fd of X server for doing async
	notification of X events (via x_event).  Setup new hooks.
	* gdbtk.tcl:  Add scrollbars to assembly and command windows.
	* Change window foreground & background colors.
	* Create margin tag for breakpoints in source and assembly windows.
	* Add new routines to be invoked when target state changes to/from
	idle.
	* Add start of expression window.
	* Change bindings of mouse button 1 in assembly and source window
	to just set or clear breakpoints when in the margin tag.
	* Change shape of register window to be more vertical to better
	reflect it's contents.
	* Add stop button.
	* Cleanup some code around command window bindings.

	* infrun.c (wait_for_inferior):  Make sure
	through_sigtramp_breakpoint is non-null before deleting.
This commit is contained in:
Stu Grossman 1994-10-21 00:59:20 +00:00
parent 1b79c34daa
commit 479f0f18d4
6 changed files with 366 additions and 54 deletions

View file

@ -1,3 +1,33 @@
Thu Oct 20 17:35:45 1994 Stu Grossman (grossman@cygnus.com)
* defs.h, infrun.c (wait_for_inferior), top.c: Call
target_wait_hook to allow GUI to handle blocking for inferior. Call
call_command_hook in execute_command to provide means for wrapping
commands with GUI state change updates.
* gdbtk.c (gdb_cmd): Force GUI into idle mode when errors occur.
* (gdb_stop): New tcl command to stop the target process.
* (x_event, gdbtk_wait): Allow GUI to interrupt gdb out of target
waits.
* (gdbtk_call_command): Wrapper around command processing to
alert GUI of target state changes.
* (gdbtk_init): Get the fd of X server for doing async
notification of X events (via x_event). Setup new hooks.
* gdbtk.tcl: Add scrollbars to assembly and command windows.
* Change window foreground & background colors.
* Create margin tag for breakpoints in source and assembly windows.
* Add new routines to be invoked when target state changes to/from
idle.
* Add start of expression window.
* Change bindings of mouse button 1 in assembly and source window
to just set or clear breakpoints when in the margin tag.
* Change shape of register window to be more vertical to better
reflect it's contents.
* Add stop button.
* Cleanup some code around command window bindings.
* infrun.c (wait_for_inferior): Make sure
through_sigtramp_breakpoint is non-null before deleting.
Thu Oct 20 10:26:43 1994 J.T. Conklin (jtc@phishhead.cygnus.com) Thu Oct 20 10:26:43 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
* config/powerpc/ppc-nw.mt (TDEPFILES): Removed exec.o. * config/powerpc/ppc-nw.mt (TDEPFILES): Removed exec.o.

View file

@ -689,7 +689,7 @@ extern char *strerror PARAMS ((int)); /* 4.11.6.2 */
# endif /* Not GNU C */ # endif /* Not GNU C */
#endif /* alloca not defined */ #endif /* alloca not defined */
/* TARGET_BYTE_ORDER and HOST_BYTE_ORDER must be defined to one of these. */ /* HOST_BYTE_ORDER must be defined to one of these. */
#if !defined (BIG_ENDIAN) #if !defined (BIG_ENDIAN)
#define BIG_ENDIAN 4321 #define BIG_ENDIAN 4321
@ -706,6 +706,17 @@ extern char *strerror PARAMS ((int)); /* 4.11.6.2 */
#include "tm.h" #include "tm.h"
#ifdef TARGET_BYTE_ORDER_SELECTABLE
/* The target endianness is selectable at runtime. Define
TARGET_BYTE_ORDER to be a variable. The user can use the `set
endian' command to change it. */
#undef TARGET_BYTE_ORDER
#define TARGET_BYTE_ORDER target_byte_order
extern int target_byte_order;
#endif
extern void set_endian_from_file PARAMS ((bfd *));
/* Number of bits in a char or unsigned char for the target machine. /* Number of bits in a char or unsigned char for the target machine.
Just like CHAR_BIT in <limits.h> but describes the target machine. */ Just like CHAR_BIT in <limits.h> but describes the target machine. */
#if !defined (TARGET_CHAR_BIT) #if !defined (TARGET_CHAR_BIT)
@ -778,6 +789,8 @@ extern char *strerror PARAMS ((int)); /* 4.11.6.2 */
from byte/word byte order. */ from byte/word byte order. */
#if !defined (BITS_BIG_ENDIAN) #if !defined (BITS_BIG_ENDIAN)
#ifndef TARGET_BYTE_ORDER_SELECTABLE
#if TARGET_BYTE_ORDER == BIG_ENDIAN #if TARGET_BYTE_ORDER == BIG_ENDIAN
#define BITS_BIG_ENDIAN 1 #define BITS_BIG_ENDIAN 1
#endif /* Big endian. */ #endif /* Big endian. */
@ -785,6 +798,12 @@ extern char *strerror PARAMS ((int)); /* 4.11.6.2 */
#if TARGET_BYTE_ORDER == LITTLE_ENDIAN #if TARGET_BYTE_ORDER == LITTLE_ENDIAN
#define BITS_BIG_ENDIAN 0 #define BITS_BIG_ENDIAN 0
#endif /* Little endian. */ #endif /* Little endian. */
#else /* defined (TARGET_BYTE_ORDER_SELECTABLE) */
#define BITS_BIG_ENDIAN (TARGET_BYTE_ORDER == BIG_ENDIAN)
#endif /* defined (TARGET_BYTE_ORDER_SELECTABLE) */
#endif /* BITS_BIG_ENDIAN not defined. */ #endif /* BITS_BIG_ENDIAN not defined. */
/* In findvar.c. */ /* In findvar.c. */
@ -854,6 +873,17 @@ extern void (*enable_breakpoint_hook) PARAMS ((struct breakpoint *bpt));
extern void (*disable_breakpoint_hook) PARAMS ((struct breakpoint *bpt)); extern void (*disable_breakpoint_hook) PARAMS ((struct breakpoint *bpt));
extern void (*interactive_hook) PARAMS ((void)); extern void (*interactive_hook) PARAMS ((void));
#ifdef __STDC__
struct target_waitstatus;
struct cmd_list_element;
#endif
extern int (*target_wait_hook) PARAMS ((int pid,
struct target_waitstatus *status));
extern void (*call_command_hook) PARAMS ((struct cmd_list_element *c,
char *cmd, int from_tty));
/* Inhibit window interface if non-zero. */ /* Inhibit window interface if non-zero. */
extern int no_windows; extern int no_windows;

View file

@ -54,6 +54,8 @@ static Tcl_Interp *interp = NULL;
/* Handle for TK main window */ /* Handle for TK main window */
static Tk_Window mainWindow = NULL; static Tk_Window mainWindow = NULL;
static int x_fd; /* X network socket */
static void static void
null_routine(arg) null_routine(arg)
int arg; int arg;
@ -336,6 +338,12 @@ gdb_cmd (clientData, interp, argc, argv)
val = catch_errors (gdb_cmd_stub, argv[1], "", RETURN_MASK_ERROR); val = catch_errors (gdb_cmd_stub, argv[1], "", RETURN_MASK_ERROR);
/* In case of an error, we may need to force the GUI into idle mode because
gdbtk_call_command may have bombed out while in the command routine. */
if (val == 0)
Tcl_VarEval (interp, "gdbtk_tcl_idle", NULL);
bpstat_do_actions (&stop_bpstat); bpstat_do_actions (&stop_bpstat);
do_cleanups (old_chain); do_cleanups (old_chain);
@ -367,6 +375,22 @@ gdb_listfiles (clientData, interp, argc, argv)
return TCL_OK; return TCL_OK;
} }
static int
gdb_stop (clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char *argv[];
{
extern pid_t inferior_process_group;
/* XXX - This is WRONG for remote targets. Probably need a target vector
entry to do this right. */
kill (-inferior_process_group, SIGINT);
}
static void static void
tk_command (cmd, from_tty) tk_command (cmd, from_tty)
@ -401,11 +425,59 @@ gdbtk_interactive ()
/* Tk_DoOneEvent (TK_DONT_WAIT|TK_IDLE_EVENTS); */ /* Tk_DoOneEvent (TK_DONT_WAIT|TK_IDLE_EVENTS); */
} }
/* Come here when there is activity on the X file descriptor. */
static void
x_event (signo)
int signo;
{
/* Process pending events */
while (Tk_DoOneEvent (TK_DONT_WAIT|TK_ALL_EVENTS) != 0);
}
static int
gdbtk_wait (pid, ourstatus)
int pid;
struct target_waitstatus *ourstatus;
{
signal (SIGIO, x_event);
pid = target_wait (pid, ourstatus);
signal (SIGIO, SIG_IGN);
return pid;
}
/* This is called from execute_command, and provides a wrapper around
various command routines in a place where both protocol messages and
user input both flow through. Mostly this is used for indicating whether
the target process is running or not.
*/
static void
gdbtk_call_command (cmdblk, arg, from_tty)
struct cmd_list_element *cmdblk;
char *arg;
int from_tty;
{
if (cmdblk->class == class_run)
{
Tcl_VarEval (interp, "gdbtk_tcl_busy", NULL);
(*cmdblk->function.cfunc)(arg, from_tty);
Tcl_VarEval (interp, "gdbtk_tcl_idle", NULL);
}
else
(*cmdblk->function.cfunc)(arg, from_tty);
}
static void static void
gdbtk_init () gdbtk_init ()
{ {
struct cleanup *old_chain; struct cleanup *old_chain;
char *gdbtk_filename; char *gdbtk_filename;
int i;
old_chain = make_cleanup (cleanup_init, 0); old_chain = make_cleanup (cleanup_init, 0);
@ -430,6 +502,7 @@ gdbtk_init ()
Tcl_CreateCommand (interp, "gdb_cmd", gdb_cmd, NULL, NULL); Tcl_CreateCommand (interp, "gdb_cmd", gdb_cmd, NULL, NULL);
Tcl_CreateCommand (interp, "gdb_loc", gdb_loc, NULL, NULL); Tcl_CreateCommand (interp, "gdb_loc", gdb_loc, NULL, NULL);
Tcl_CreateCommand (interp, "gdb_listfiles", gdb_listfiles, NULL, NULL); Tcl_CreateCommand (interp, "gdb_listfiles", gdb_listfiles, NULL, NULL);
Tcl_CreateCommand (interp, "gdb_stop", gdb_stop, NULL, NULL);
gdbtk_filename = getenv ("GDBTK_FILENAME"); gdbtk_filename = getenv ("GDBTK_FILENAME");
if (!gdbtk_filename) if (!gdbtk_filename)
@ -441,6 +514,19 @@ gdbtk_init ()
if (Tcl_EvalFile (interp, gdbtk_filename) != TCL_OK) if (Tcl_EvalFile (interp, gdbtk_filename) != TCL_OK)
error ("Failure reading %s: %s", gdbtk_filename, interp->result); error ("Failure reading %s: %s", gdbtk_filename, interp->result);
/* XXX - Get the file descriptor for the network socket. This is not Kosher
as it involves looking at data private to Xlib. */
x_fd = Tk_Display (mainWindow) -> fd;
/* Setup for I/O interrupts */
signal (SIGIO, SIG_IGN);
i = fcntl (x_fd, F_GETFL, 0);
fcntl (x_fd, F_SETFL, i|FASYNC);
fcntl (x_fd, F_SETOWN, getpid());
command_loop_hook = Tk_MainLoop; command_loop_hook = Tk_MainLoop;
fputs_unfiltered_hook = gdbtk_fputs; fputs_unfiltered_hook = gdbtk_fputs;
print_frame_info_listing_hook = null_routine; print_frame_info_listing_hook = null_routine;
@ -451,6 +537,8 @@ gdbtk_init ()
enable_breakpoint_hook = gdbtk_enable_breakpoint; enable_breakpoint_hook = gdbtk_enable_breakpoint;
disable_breakpoint_hook = gdbtk_disable_breakpoint; disable_breakpoint_hook = gdbtk_disable_breakpoint;
interactive_hook = gdbtk_interactive; interactive_hook = gdbtk_interactive;
target_wait_hook = gdbtk_wait;
call_command_hook = gdbtk_call_command;
discard_cleanups (old_chain); discard_cleanups (old_chain);

View file

@ -8,10 +8,8 @@ set screen_top 0
set screen_bot 0 set screen_bot 0
set current_output_win .command.text set current_output_win .command.text
set cfunc NIL set cfunc NIL
option add *Foreground White
proc test {} { option add *Background Blue
update_listing {termcap.c foo /etc/termcap 200}
}
proc echo string {puts stdout $string} proc echo string {puts stdout $string}
@ -322,6 +320,8 @@ proc insert_breakpoint_tag {win line} {
$win delete $line.0 $win delete $line.0
$win insert $line.0 "B" $win insert $line.0 "B"
$win tag add $line $line.0 $win tag add $line $line.0
$win tag add delete $line.0 "$line.0 lineend"
$win tag add margin $line.0 "$line.0 lineend"
$win configure -state disabled $win configure -state disabled
} }
@ -342,9 +342,57 @@ proc delete_breakpoint_tag {win line} {
$win delete $line.0 $win delete $line.0
$win insert $line.0 " " $win insert $line.0 " "
$win tag delete $line $win tag delete $line
$win tag add delete $line.0 "$line.0 lineend"
$win tag add margin $line.0 "$line.0 lineend"
$win configure -state disabled $win configure -state disabled
} }
proc gdbtk_tcl_busy {} {
.start configure -state disabled
.stop configure -state normal
.step configure -state disabled
.next configure -state disabled
.continue configure -state disabled
.finish configure -state disabled
.exit configure -state disabled
.up configure -state disabled
.down configure -state disabled
.bottom configure -state disabled
.asm_but configure -state disabled
.registers configure -state disabled
.asm.stepi configure -state disabled
.asm.nexti configure -state disabled
.asm.continue configure -state disabled
.asm.finish configure -state disabled
.asm.up configure -state disabled
.asm.down configure -state disabled
.asm.bottom configure -state disabled
.asm.close configure -state disabled
}
proc gdbtk_tcl_idle {} {
.start configure -state normal
.stop configure -state disabled
.step configure -state normal
.next configure -state normal
.continue configure -state normal
.finish configure -state normal
.exit configure -state normal
.up configure -state normal
.down configure -state normal
.bottom configure -state normal
.asm_but configure -state normal
.registers configure -state normal
.asm.stepi configure -state normal
.asm.nexti configure -state normal
.asm.continue configure -state normal
.asm.finish configure -state normal
.asm.up configure -state normal
.asm.down configure -state normal
.asm.bottom configure -state normal
.asm.close configure -state normal
}
# #
# Local procedure: # Local procedure:
# #
@ -620,6 +668,49 @@ proc asm_window_button_1 {win x y xrel yrel} {
proc do_nothing {} {} proc do_nothing {} {}
#
# Local procedure:
#
# create_expr_win - Creat expression display window
#
# Description:
#
# Create the expression display window.
#
proc create_expr_win {} {
toplevel .expr
wm minsize .expr 1 1
wm title .expr Expression
canvas .expr.c -yscrollcommand {.expr.scroll set} -cursor hand2 \
-borderwidth 2 -relief groove
scrollbar .expr.scroll -orient vertical -command {.expr.c yview}
entry .expr.entry -borderwidth 2 -relief groove
pack .expr.entry -side bottom -fill x
pack .expr.c -side left -fill both -expand yes
pack .expr.scroll -side right -fill y
.expr.c create text 100 0 -text "Text string"
.expr.c create rectangle 245 195 255 205 -outline black -fill white
}
#
# Local procedure:
#
# display_expression (expression) - Display EXPRESSION in display window
#
# Description:
#
# Display EXPRESSION and it's value in the expression display window.
#
proc display_expression {expression} {
if ![winfo exists .expr] {create_expr_win}
}
# #
# Local procedure: # Local procedure:
# #
@ -669,8 +760,10 @@ proc create_file_win {filename} {
# Setup all the bindings # Setup all the bindings
bind $win <Enter> {focus %W} bind $win <Enter> {focus %W}
bind $win <1> {listing_window_button_1 %W %X %Y %x %y} # bind $win <1> {listing_window_button_1 %W %X %Y %x %y}
bind $win <1> do_nothing
bind $win <B1-Motion> do_nothing bind $win <B1-Motion> do_nothing
bind $win n {gdb_cmd next ; update_ptr} bind $win n {gdb_cmd next ; update_ptr}
bind $win s {gdb_cmd step ; update_ptr} bind $win s {gdb_cmd step ; update_ptr}
bind $win c {gdb_cmd continue ; update_ptr} bind $win c {gdb_cmd continue ; update_ptr}
@ -688,8 +781,36 @@ proc create_file_win {filename} {
set numlines [lindex [split $numlines .] 0] set numlines [lindex [split $numlines .] 0]
for {set i 1} {$i <= $numlines} {incr i} { for {set i 1} {$i <= $numlines} {incr i} {
$win insert $i.0 [format " %4d " $i] $win insert $i.0 [format " %4d " $i]
$win tag add margin $i.0 $i.8
$win tag add source $i.8 "$i.0 lineend"
} }
$win tag bind margin <1> {listing_window_button_1 %W %X %Y %x %y}
$win tag bind source <1> {
%W mark set anchor "@%x,%y wordstart"
set last [%W index "@%x,%y wordend"]
%W tag remove sel 0.0 anchor
%W tag remove sel $last end
%W tag add sel anchor $last
}
# $win tag bind source <Double-Button-1> {
# %W mark set anchor "@%x,%y wordstart"
# set last [%W index "@%x,%y wordend"]
# %W tag remove sel 0.0 anchor
# %W tag remove sel $last end
# %W tag add sel anchor $last
# echo "Selected [selection get]"
# }
$win tag bind source <B1-Motion> {
%W tag remove sel 0.0 anchor
%W tag remove sel $last end
%W tag add sel anchor @%x,%y
}
$win tag bind sel <1> do_nothing
$win tag bind sel <Double-Button-1> {display_expression [selection get]}
$win tag raise sel
# Scan though the breakpoint data base and install any destined for this file # Scan though the breakpoint data base and install any destined for this file
foreach bpnum [array names breakpoint_file] { foreach bpnum [array names breakpoint_file] {
@ -963,7 +1084,8 @@ proc asm_command {} {
text $win -height 25 -width 80 -relief raised -borderwidth 2 \ text $win -height 25 -width 80 -relief raised -borderwidth 2 \
-setgrid true -cursor hand2 \ -setgrid true -cursor hand2 \
-yscrollcommand asmscrollproc -yscrollcommand asmscrollproc
scrollbar .asm.scroll -orient vertical -command {$win yview} scrollbar .asm.scroll -orient vertical \
-command {[asm_win_name $cfunc] yview}
frame .asm.buts frame .asm.buts
button .asm.stepi -text Stepi \ button .asm.stepi -text Stepi \
@ -1011,7 +1133,7 @@ proc registers_command {} {
wm title .reg Registers wm title .reg Registers
set win .reg.regs set win .reg.regs
text $win -height 25 -width 80 -relief raised \ text $win -height 41 -width 45 -relief raised \
-borderwidth 2 \ -borderwidth 2 \
-setgrid true -cursor hand2 -setgrid true -cursor hand2
@ -1044,7 +1166,7 @@ proc update_registers {} {
gdb_cmd "info registers" gdb_cmd "info registers"
set current_output_win .command.text set current_output_win .command.text
$win yview 1 $win yview 0
$win configure -state disabled $win configure -state disabled
} }
@ -1209,6 +1331,7 @@ button .start -text Start -command \
gdb_cmd {enable delete $bpnum} gdb_cmd {enable delete $bpnum}
gdb_cmd run gdb_cmd run
update_ptr } update_ptr }
button .stop -text Stop -fg red -activeforeground red -state disabled -command gdb_stop
button .step -text Step -command {gdb_cmd step ; update_ptr} button .step -text Step -command {gdb_cmd step ; update_ptr}
button .next -text Next -command {gdb_cmd next ; update_ptr} button .next -text Next -command {gdb_cmd next ; update_ptr}
button .continue -text Continue -command {gdb_cmd continue ; update_ptr} button .continue -text Continue -command {gdb_cmd continue ; update_ptr}
@ -1243,7 +1366,7 @@ button .files -text Files -command files_command
pack .listing -side bottom -fill both -expand yes pack .listing -side bottom -fill both -expand yes
#pack .test -side bottom -fill x #pack .test -side bottom -fill x
pack .start .step .next .continue .finish .up .down .bottom .asm_but \ pack .start .stop .step .next .continue .finish .up .down .bottom .asm_but \
.registers .files .exit -side left .registers .files .exit -side left
toplevel .command toplevel .command
wm title .command Command wm title .command Command
@ -1251,10 +1374,12 @@ wm title .command Command
# Setup command window # Setup command window
label .command.label -text "* Command Buffer *" -borderwidth 2 -relief raised label .command.label -text "* Command Buffer *" -borderwidth 2 -relief raised
text .command.text -height 25 -width 80 -relief raised -borderwidth 2 -setgrid true -cursor hand2 text .command.text -height 25 -width 80 -relief raised -borderwidth 2 -setgrid true -cursor hand2 -yscrollcommand {.command.scroll set}
scrollbar .command.scroll -orient vertical -command {.command.text yview}
pack .command.label -side top -fill x pack .command.label -side top -fill x
pack .command.text -side top -expand yes -fill both pack .command.text -side left -expand yes -fill both
pack .command.scroll -side right -fill y
set command_line {} set command_line {}
@ -1262,6 +1387,10 @@ gdb_cmd {set language c}
gdb_cmd {set height 0} gdb_cmd {set height 0}
gdb_cmd {set width 0} gdb_cmd {set width 0}
bind .command.text <Enter> {focus %W}
bind .command.text <Delete> {delete_char %W}
bind .command.text <BackSpace> {delete_char %W}
bind .command.text <Control-u> {delete_line %W}
bind .command.text <Any-Key> { bind .command.text <Any-Key> {
global command_line global command_line
@ -1280,10 +1409,7 @@ bind .command.text <Key-Return> {
%W insert end "(gdb) " %W insert end "(gdb) "
%W yview -pickplace end %W yview -pickplace end
} }
bind .command.text <Enter> {focus %W}
bind .command.text <Delete> {delete_char %W}
bind .command.text <BackSpace> {delete_char %W}
bind .command.text <Control-u> {delete_line %W}
proc delete_char {win} { proc delete_char {win} {
global command_line global command_line

View file

@ -308,7 +308,7 @@ proceed (addr, siggnal, step)
breakpoint to be hit again, but you can always continue, so it's not breakpoint to be hit again, but you can always continue, so it's not
a big deal.) */ a big deal.) */
if (! step && PREPARE_TO_PROCEED && breakpoint_here_p (read_pc ())) if (! step && PREPARE_TO_PROCEED (1) && breakpoint_here_p (read_pc ()))
oneproc = 1; oneproc = 1;
#endif /* PREPARE_TO_PROCEED */ #endif /* PREPARE_TO_PROCEED */
@ -362,10 +362,8 @@ The same program may be running in another process.");
to be preserved over calls to it and cleared when the inferior to be preserved over calls to it and cleared when the inferior
is started. */ is started. */
static CORE_ADDR prev_pc; static CORE_ADDR prev_pc;
static CORE_ADDR prev_sp;
static CORE_ADDR prev_func_start; static CORE_ADDR prev_func_start;
static char *prev_func_name; static char *prev_func_name;
static CORE_ADDR prev_frame_address;
/* Start remote-debugging of a machine over a serial link. */ /* Start remote-debugging of a machine over a serial link. */
@ -388,10 +386,8 @@ init_wait_for_inferior ()
{ {
/* These are meaningless until the first time through wait_for_inferior. */ /* These are meaningless until the first time through wait_for_inferior. */
prev_pc = 0; prev_pc = 0;
prev_sp = 0;
prev_func_start = 0; prev_func_start = 0;
prev_func_name = NULL; prev_func_name = NULL;
prev_frame_address = 0;
trap_expected_after_continue = 0; trap_expected_after_continue = 0;
breakpoints_inserted = 0; breakpoints_inserted = 0;
@ -423,7 +419,6 @@ wait_for_inferior ()
struct target_waitstatus w; struct target_waitstatus w;
int another_trap; int another_trap;
int random_signal; int random_signal;
CORE_ADDR stop_sp = 0;
CORE_ADDR stop_func_start; CORE_ADDR stop_func_start;
CORE_ADDR stop_func_end; CORE_ADDR stop_func_end;
char *stop_func_name; char *stop_func_name;
@ -436,6 +431,7 @@ wait_for_inferior ()
struct breakpoint *step_resume_breakpoint = NULL; struct breakpoint *step_resume_breakpoint = NULL;
struct breakpoint *through_sigtramp_breakpoint = NULL; struct breakpoint *through_sigtramp_breakpoint = NULL;
int pid; int pid;
int update_step_sp = 0;
old_cleanups = make_cleanup (delete_breakpoint_current_contents, old_cleanups = make_cleanup (delete_breakpoint_current_contents,
&step_resume_breakpoint); &step_resume_breakpoint);
@ -462,7 +458,10 @@ wait_for_inferior ()
registers_changed (); registers_changed ();
pid = target_wait (-1, &w); if (target_wait_hook)
pid = target_wait_hook (-1, &w);
else
pid = target_wait (-1, &w);
flush_cached_frames (); flush_cached_frames ();
@ -473,6 +472,17 @@ wait_for_inferior ()
{ {
fprintf_unfiltered (gdb_stderr, "[New %s]\n", target_pid_to_str (pid)); fprintf_unfiltered (gdb_stderr, "[New %s]\n", target_pid_to_str (pid));
add_thread (pid); add_thread (pid);
/* We may want to consider not doing a resume here in order to give
the user a chance to play with the new thread. It might be good
to make that a user-settable option. */
/* At this point, all threads are stopped (happens automatically in
either the OS or the native code). Therefore we need to continue
all threads in order to make progress. */
target_resume (-1, 0, TARGET_SIGNAL_0);
continue;
} }
switch (w.kind) switch (w.kind)
@ -498,8 +508,7 @@ wait_for_inferior ()
printf_filtered ("\nProgram exited with code 0%o.\n", printf_filtered ("\nProgram exited with code 0%o.\n",
(unsigned int)w.value.integer); (unsigned int)w.value.integer);
else else
if (!batch_mode()) printf_filtered ("\nProgram exited normally.\n");
printf_filtered ("\nProgram exited normally.\n");
gdb_flush (gdb_stdout); gdb_flush (gdb_stdout);
target_mourn_inferior (); target_mourn_inferior ();
#ifdef NO_SINGLE_STEP #ifdef NO_SINGLE_STEP
@ -559,7 +568,11 @@ wait_for_inferior ()
target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */ target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */
/* FIXME: What if a signal arrives instead of the single-step /* FIXME: What if a signal arrives instead of the single-step
happening? */ happening? */
target_wait (pid, &w);
if (target_wait_hook)
target_wait_hook (pid, &w);
else
target_wait (pid, &w);
insert_breakpoints (); insert_breakpoints ();
target_resume (pid, 0, TARGET_SIGNAL_0); target_resume (pid, 0, TARGET_SIGNAL_0);
continue; continue;
@ -630,7 +643,6 @@ wait_for_inferior ()
through_sigtramp_breakpoint = NULL; through_sigtramp_breakpoint = NULL;
} }
prev_pc = 0; prev_pc = 0;
prev_sp = 0;
prev_func_name = NULL; prev_func_name = NULL;
step_range_start = 0; step_range_start = 0;
step_range_end = 0; step_range_end = 0;
@ -654,9 +666,6 @@ wait_for_inferior ()
continue; continue;
} }
set_current_frame (create_new_frame (read_fp (), stop_pc));
select_frame (get_current_frame (), 0);
#ifdef HAVE_STEPPABLE_WATCHPOINT #ifdef HAVE_STEPPABLE_WATCHPOINT
/* It may not be necessary to disable the watchpoint to stop over /* It may not be necessary to disable the watchpoint to stop over
it. For example, the PA can (with some kernel cooperation) it. For example, the PA can (with some kernel cooperation)
@ -696,8 +705,6 @@ wait_for_inferior ()
STOPPED_BY_WATCHPOINT (w); STOPPED_BY_WATCHPOINT (w);
#endif #endif
stop_frame_address = FRAME_FP (get_current_frame ());
stop_sp = read_sp ();
stop_func_start = 0; stop_func_start = 0;
stop_func_name = 0; stop_func_name = 0;
/* Don't care about return value; stop_func_start and stop_func_name /* Don't care about return value; stop_func_start and stop_func_name
@ -758,7 +765,7 @@ wait_for_inferior ()
{ {
/* See if there is a breakpoint at the current PC. */ /* See if there is a breakpoint at the current PC. */
stop_bpstat = bpstat_stop_status stop_bpstat = bpstat_stop_status
(&stop_pc, stop_frame_address, (&stop_pc,
#if DECR_PC_AFTER_BREAK #if DECR_PC_AFTER_BREAK
/* Notice the case of stepping through a jump /* Notice the case of stepping through a jump
that lands just after a breakpoint. that lands just after a breakpoint.
@ -782,7 +789,8 @@ wait_for_inferior ()
= !(bpstat_explains_signal (stop_bpstat) = !(bpstat_explains_signal (stop_bpstat)
|| trap_expected || trap_expected
#ifndef CALL_DUMMY_BREAKPOINT_OFFSET #ifndef CALL_DUMMY_BREAKPOINT_OFFSET
|| PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address) || PC_IN_CALL_DUMMY (stop_pc, read_sp (),
FRAME_FP (get_current_frame ()))
#endif /* No CALL_DUMMY_BREAKPOINT_OFFSET. */ #endif /* No CALL_DUMMY_BREAKPOINT_OFFSET. */
|| (step_range_end && step_resume_breakpoint == NULL)); || (step_range_end && step_resume_breakpoint == NULL));
else else
@ -793,7 +801,8 @@ wait_for_inferior ()
news) give another signal besides SIGTRAP, news) give another signal besides SIGTRAP,
so check here as well as above. */ so check here as well as above. */
#ifndef CALL_DUMMY_BREAKPOINT_OFFSET #ifndef CALL_DUMMY_BREAKPOINT_OFFSET
|| PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address) || PC_IN_CALL_DUMMY (stop_pc, read_sp (),
FRAME_FP (get_current_frame ()))
#endif /* No CALL_DUMMY_BREAKPOINT_OFFSET. */ #endif /* No CALL_DUMMY_BREAKPOINT_OFFSET. */
); );
if (!random_signal) if (!random_signal)
@ -904,7 +913,7 @@ wait_for_inferior ()
#if 0 #if 0
/* FIXME - Need to implement nested temporary breakpoints */ /* FIXME - Need to implement nested temporary breakpoints */
if (step_over_calls if (step_over_calls
&& (stop_frame_address && (FRAME_FP (get_current_frame ())
INNER_THAN step_frame_address)) INNER_THAN step_frame_address))
{ {
another_trap = 1; another_trap = 1;
@ -950,7 +959,8 @@ wait_for_inferior ()
break; break;
case BPSTAT_WHAT_THROUGH_SIGTRAMP: case BPSTAT_WHAT_THROUGH_SIGTRAMP:
delete_breakpoint (through_sigtramp_breakpoint); if (through_sigtramp_breakpoint)
delete_breakpoint (through_sigtramp_breakpoint);
through_sigtramp_breakpoint = NULL; through_sigtramp_breakpoint = NULL;
/* If were waiting for a trap, hitting the step_resume_break /* If were waiting for a trap, hitting the step_resume_break
@ -983,7 +993,7 @@ wait_for_inferior ()
just stop silently, unless the user was doing an si/ni, in which just stop silently, unless the user was doing an si/ni, in which
case she'd better know what she's doing. */ case she'd better know what she's doing. */
if (PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address) if (PC_IN_CALL_DUMMY (stop_pc, read_sp (), FRAME_FP (get_current_frame ()))
&& !step_range_end) && !step_range_end)
{ {
stop_print_frame = 0; stop_print_frame = 0;
@ -1017,17 +1027,21 @@ wait_for_inferior ()
step range and either the stack or frame pointers step range and either the stack or frame pointers
just changed, we've stepped outside */ just changed, we've stepped outside */
&& !(stop_pc == step_range_start && !(stop_pc == step_range_start
&& stop_frame_address && FRAME_FP (get_current_frame ())
&& (stop_sp INNER_THAN prev_sp && (read_sp () INNER_THAN step_sp
|| stop_frame_address != step_frame_address))) || FRAME_FP (get_current_frame ()) != step_frame_address)))
{ {
/* We might be doing a BPSTAT_WHAT_SINGLE and getting a signal. /* We might be doing a BPSTAT_WHAT_SINGLE and getting a signal.
So definately need to check for sigtramp here. */ So definately need to check for sigtramp here. */
goto check_sigtramp2; goto check_sigtramp2;
} }
/* We stepped out of the stepping range. See if that was due /* We stepped out of the stepping range. */
to a subroutine call that we should proceed to the end of. */
/* We can't update step_sp every time through the loop, because
reading the stack pointer would slow down stepping too much.
But we can update it every time we leave the step range. */
update_step_sp = 1;
/* Did we just take a signal? */ /* Did we just take a signal? */
if (IN_SIGTRAMP (stop_pc, stop_func_name) if (IN_SIGTRAMP (stop_pc, stop_func_name)
@ -1052,8 +1066,7 @@ wait_for_inferior ()
sr_sal.symtab = NULL; sr_sal.symtab = NULL;
sr_sal.line = 0; sr_sal.line = 0;
/* We could probably be setting the frame to /* We could probably be setting the frame to
prev_frame_address; the reason we don't is that it didn't used step_frame_address; I don't think anyone thought to try it. */
to exist. */
step_resume_breakpoint = step_resume_breakpoint =
set_momentary_breakpoint (sr_sal, NULL, bp_step_resume); set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
if (breakpoints_inserted) if (breakpoints_inserted)
@ -1073,6 +1086,9 @@ wait_for_inferior ()
} }
#if 1 #if 1
/* See if we left the step range due to a subroutine call that
we should proceed to the end of. */
if (stop_func_start) if (stop_func_start)
{ {
struct symtab *s; struct symtab *s;
@ -1096,7 +1112,7 @@ wait_for_inferior ()
/* Might be a recursive call if either we have a prologue /* Might be a recursive call if either we have a prologue
or the call instruction itself saves the PC on the stack. */ or the call instruction itself saves the PC on the stack. */
|| prologue_pc != stop_func_start || prologue_pc != stop_func_start
|| stop_sp != prev_sp) || read_sp () != step_sp)
&& (/* PC is completely out of bounds of any known objfiles. Treat && (/* PC is completely out of bounds of any known objfiles. Treat
like a subroutine call. */ like a subroutine call. */
! stop_func_start ! stop_func_start
@ -1112,6 +1128,16 @@ wait_for_inferior ()
|| stop_pc < prologue_pc || stop_pc < prologue_pc
/* ...and if it is a leaf function, the prologue might
consist of gp loading only, so the call transfers to
the first instruction after the prologue. */
|| (stop_pc == prologue_pc
/* Distinguish this from the case where we jump back
to the first instruction after the prologue,
within a function. */
&& stop_func_start != prev_func_start)
/* If we end up in certain places, it means we did a subroutine /* If we end up in certain places, it means we did a subroutine
call. I'm not completely sure this is necessary now that we call. I'm not completely sure this is necessary now that we
have the above checks with stop_func_start (and now that have the above checks with stop_func_start (and now that
@ -1183,7 +1209,7 @@ step_over_function:
step_resume_breakpoint = step_resume_breakpoint =
set_momentary_breakpoint (sr_sal, get_current_frame (), set_momentary_breakpoint (sr_sal, get_current_frame (),
bp_step_resume); bp_step_resume);
step_resume_breakpoint->frame = prev_frame_address; step_resume_breakpoint->frame = step_frame_address;
if (breakpoints_inserted) if (breakpoints_inserted)
insert_breakpoints (); insert_breakpoints ();
} }
@ -1341,8 +1367,10 @@ step_into_function:
been at the start of a been at the start of a
function. */ function. */
prev_func_name = stop_func_name; prev_func_name = stop_func_name;
prev_sp = stop_sp;
prev_frame_address = stop_frame_address; if (update_step_sp)
step_sp = read_sp ();
update_step_sp = 0;
/* If we did not do break;, it means we should keep /* If we did not do break;, it means we should keep
running the inferior and not return to debugger. */ running the inferior and not return to debugger. */
@ -1417,8 +1445,6 @@ step_into_function:
prev_pc = read_pc (); prev_pc = read_pc ();
prev_func_start = stop_func_start; prev_func_start = stop_func_start;
prev_func_name = stop_func_name; prev_func_name = stop_func_name;
prev_sp = stop_sp;
prev_frame_address = stop_frame_address;
} }
do_cleanups (old_cleanups); do_cleanups (old_cleanups);
} }
@ -1492,6 +1518,8 @@ Further execution is probably impossible.\n");
if we have one. */ if we have one. */
if (!stop_stack_dummy) if (!stop_stack_dummy)
{ {
select_frame (get_current_frame (), 0);
if (stop_print_frame) if (stop_print_frame)
{ {
int source_only; int source_only;
@ -1499,7 +1527,7 @@ Further execution is probably impossible.\n");
source_only = bpstat_print (stop_bpstat); source_only = bpstat_print (stop_bpstat);
source_only = source_only || source_only = source_only ||
( stop_step ( stop_step
&& step_frame_address == stop_frame_address && step_frame_address == FRAME_FP (get_current_frame ())
&& step_start_function == find_pc_function (stop_pc)); && step_start_function == find_pc_function (stop_pc));
print_stack_frame (selected_frame, -1, source_only? -1: 1); print_stack_frame (selected_frame, -1, source_only? -1: 1);
@ -1828,7 +1856,6 @@ save_inferior_status (inf_status, restore_stack_info)
{ {
inf_status->stop_signal = stop_signal; inf_status->stop_signal = stop_signal;
inf_status->stop_pc = stop_pc; inf_status->stop_pc = stop_pc;
inf_status->stop_frame_address = stop_frame_address;
inf_status->stop_step = stop_step; inf_status->stop_step = stop_step;
inf_status->stop_stack_dummy = stop_stack_dummy; inf_status->stop_stack_dummy = stop_stack_dummy;
inf_status->stopped_by_random_signal = stopped_by_random_signal; inf_status->stopped_by_random_signal = stopped_by_random_signal;
@ -1898,7 +1925,6 @@ restore_inferior_status (inf_status)
{ {
stop_signal = inf_status->stop_signal; stop_signal = inf_status->stop_signal;
stop_pc = inf_status->stop_pc; stop_pc = inf_status->stop_pc;
stop_frame_address = inf_status->stop_frame_address;
stop_step = inf_status->stop_step; stop_step = inf_status->stop_step;
stop_stack_dummy = inf_status->stop_stack_dummy; stop_stack_dummy = inf_status->stop_stack_dummy;
stopped_by_random_signal = inf_status->stopped_by_random_signal; stopped_by_random_signal = inf_status->stopped_by_random_signal;

View file

@ -379,6 +379,16 @@ void (*disable_breakpoint_hook) PARAMS ((struct breakpoint *bpt));
void (*interactive_hook) PARAMS ((void)); void (*interactive_hook) PARAMS ((void));
/* Called when going to wait for the target. Usually allows the GUI to run
while waiting for target events. */
int (*target_wait_hook) PARAMS ((int pid, struct target_waitstatus *status));
/* Used by UI as a wrapper around command execution. May do various things
like enabling/disabling buttons, etc... */
void (*call_command_hook) PARAMS ((struct cmd_list_element *c, char *cmd,
int from_tty));
/* Where to go for return_to_top_level (RETURN_ERROR). */ /* Where to go for return_to_top_level (RETURN_ERROR). */
jmp_buf error_return; jmp_buf error_return;
@ -858,6 +868,8 @@ execute_command (p, from_tty)
do_setshow_command (arg, from_tty & caution, c); do_setshow_command (arg, from_tty & caution, c);
else if (c->function.cfunc == NO_FUNCTION) else if (c->function.cfunc == NO_FUNCTION)
error ("That is not a command, just a help topic."); error ("That is not a command, just a help topic.");
else if (call_command_hook)
call_command_hook (c, arg, from_tty & caution);
else else
(*c->function.cfunc) (arg, from_tty & caution); (*c->function.cfunc) (arg, from_tty & caution);
} }