* 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:
parent
1b79c34daa
commit
479f0f18d4
@ -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)
|
||||
|
||||
* config/powerpc/ppc-nw.mt (TDEPFILES): Removed exec.o.
|
||||
|
32
gdb/defs.h
32
gdb/defs.h
@ -689,7 +689,7 @@ extern char *strerror PARAMS ((int)); /* 4.11.6.2 */
|
||||
# endif /* Not GNU C */
|
||||
#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)
|
||||
#define BIG_ENDIAN 4321
|
||||
@ -706,6 +706,17 @@ extern char *strerror PARAMS ((int)); /* 4.11.6.2 */
|
||||
|
||||
#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.
|
||||
Just like CHAR_BIT in <limits.h> but describes the target machine. */
|
||||
#if !defined (TARGET_CHAR_BIT)
|
||||
@ -778,6 +789,8 @@ extern char *strerror PARAMS ((int)); /* 4.11.6.2 */
|
||||
from byte/word byte order. */
|
||||
|
||||
#if !defined (BITS_BIG_ENDIAN)
|
||||
#ifndef TARGET_BYTE_ORDER_SELECTABLE
|
||||
|
||||
#if TARGET_BYTE_ORDER == BIG_ENDIAN
|
||||
#define BITS_BIG_ENDIAN 1
|
||||
#endif /* Big endian. */
|
||||
@ -785,6 +798,12 @@ extern char *strerror PARAMS ((int)); /* 4.11.6.2 */
|
||||
#if TARGET_BYTE_ORDER == LITTLE_ENDIAN
|
||||
#define BITS_BIG_ENDIAN 0
|
||||
#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. */
|
||||
|
||||
/* 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 (*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. */
|
||||
|
||||
extern int no_windows;
|
||||
|
88
gdb/gdbtk.c
88
gdb/gdbtk.c
@ -54,6 +54,8 @@ static Tcl_Interp *interp = NULL;
|
||||
/* Handle for TK main window */
|
||||
static Tk_Window mainWindow = NULL;
|
||||
|
||||
static int x_fd; /* X network socket */
|
||||
|
||||
static void
|
||||
null_routine(arg)
|
||||
int arg;
|
||||
@ -336,6 +338,12 @@ gdb_cmd (clientData, interp, argc, argv)
|
||||
|
||||
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);
|
||||
do_cleanups (old_chain);
|
||||
|
||||
@ -367,6 +375,22 @@ gdb_listfiles (clientData, interp, argc, argv)
|
||||
|
||||
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
|
||||
tk_command (cmd, from_tty)
|
||||
@ -401,11 +425,59 @@ gdbtk_interactive ()
|
||||
/* 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
|
||||
gdbtk_init ()
|
||||
{
|
||||
struct cleanup *old_chain;
|
||||
char *gdbtk_filename;
|
||||
int i;
|
||||
|
||||
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_loc", gdb_loc, 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");
|
||||
if (!gdbtk_filename)
|
||||
@ -441,6 +514,19 @@ gdbtk_init ()
|
||||
if (Tcl_EvalFile (interp, gdbtk_filename) != TCL_OK)
|
||||
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;
|
||||
fputs_unfiltered_hook = gdbtk_fputs;
|
||||
print_frame_info_listing_hook = null_routine;
|
||||
@ -451,6 +537,8 @@ gdbtk_init ()
|
||||
enable_breakpoint_hook = gdbtk_enable_breakpoint;
|
||||
disable_breakpoint_hook = gdbtk_disable_breakpoint;
|
||||
interactive_hook = gdbtk_interactive;
|
||||
target_wait_hook = gdbtk_wait;
|
||||
call_command_hook = gdbtk_call_command;
|
||||
|
||||
discard_cleanups (old_chain);
|
||||
|
||||
|
156
gdb/gdbtk.tcl
156
gdb/gdbtk.tcl
@ -8,10 +8,8 @@ set screen_top 0
|
||||
set screen_bot 0
|
||||
set current_output_win .command.text
|
||||
set cfunc NIL
|
||||
|
||||
proc test {} {
|
||||
update_listing {termcap.c foo /etc/termcap 200}
|
||||
}
|
||||
option add *Foreground White
|
||||
option add *Background Blue
|
||||
|
||||
proc echo string {puts stdout $string}
|
||||
|
||||
@ -322,6 +320,8 @@ proc insert_breakpoint_tag {win line} {
|
||||
$win delete $line.0
|
||||
$win insert $line.0 "B"
|
||||
$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
|
||||
}
|
||||
@ -342,9 +342,57 @@ proc delete_breakpoint_tag {win line} {
|
||||
$win delete $line.0
|
||||
$win insert $line.0 " "
|
||||
$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
|
||||
}
|
||||
|
||||
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:
|
||||
#
|
||||
@ -620,6 +668,49 @@ proc asm_window_button_1 {win x y xrel yrel} {
|
||||
|
||||
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:
|
||||
#
|
||||
@ -669,8 +760,10 @@ proc create_file_win {filename} {
|
||||
# Setup all the bindings
|
||||
|
||||
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 n {gdb_cmd next ; update_ptr}
|
||||
bind $win s {gdb_cmd step ; 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]
|
||||
for {set i 1} {$i <= $numlines} {incr 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
|
||||
|
||||
foreach bpnum [array names breakpoint_file] {
|
||||
@ -963,7 +1084,8 @@ proc asm_command {} {
|
||||
text $win -height 25 -width 80 -relief raised -borderwidth 2 \
|
||||
-setgrid true -cursor hand2 \
|
||||
-yscrollcommand asmscrollproc
|
||||
scrollbar .asm.scroll -orient vertical -command {$win yview}
|
||||
scrollbar .asm.scroll -orient vertical \
|
||||
-command {[asm_win_name $cfunc] yview}
|
||||
frame .asm.buts
|
||||
|
||||
button .asm.stepi -text Stepi \
|
||||
@ -1011,7 +1133,7 @@ proc registers_command {} {
|
||||
wm title .reg Registers
|
||||
set win .reg.regs
|
||||
|
||||
text $win -height 25 -width 80 -relief raised \
|
||||
text $win -height 41 -width 45 -relief raised \
|
||||
-borderwidth 2 \
|
||||
-setgrid true -cursor hand2
|
||||
|
||||
@ -1044,7 +1166,7 @@ proc update_registers {} {
|
||||
gdb_cmd "info registers"
|
||||
set current_output_win .command.text
|
||||
|
||||
$win yview 1
|
||||
$win yview 0
|
||||
$win configure -state disabled
|
||||
}
|
||||
|
||||
@ -1209,6 +1331,7 @@ button .start -text Start -command \
|
||||
gdb_cmd {enable delete $bpnum}
|
||||
gdb_cmd run
|
||||
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 .next -text Next -command {gdb_cmd next ; 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 .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
|
||||
toplevel .command
|
||||
wm title .command Command
|
||||
@ -1251,10 +1374,12 @@ wm title .command Command
|
||||
# Setup command window
|
||||
|
||||
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.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 {}
|
||||
|
||||
@ -1262,6 +1387,10 @@ gdb_cmd {set language c}
|
||||
gdb_cmd {set height 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> {
|
||||
global command_line
|
||||
|
||||
@ -1280,10 +1409,7 @@ bind .command.text <Key-Return> {
|
||||
%W insert end "(gdb) "
|
||||
%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} {
|
||||
global command_line
|
||||
|
||||
|
102
gdb/infrun.c
102
gdb/infrun.c
@ -308,7 +308,7 @@ proceed (addr, siggnal, step)
|
||||
breakpoint to be hit again, but you can always continue, so it's not
|
||||
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;
|
||||
#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
|
||||
is started. */
|
||||
static CORE_ADDR prev_pc;
|
||||
static CORE_ADDR prev_sp;
|
||||
static CORE_ADDR prev_func_start;
|
||||
static char *prev_func_name;
|
||||
static CORE_ADDR prev_frame_address;
|
||||
|
||||
|
||||
/* 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. */
|
||||
prev_pc = 0;
|
||||
prev_sp = 0;
|
||||
prev_func_start = 0;
|
||||
prev_func_name = NULL;
|
||||
prev_frame_address = 0;
|
||||
|
||||
trap_expected_after_continue = 0;
|
||||
breakpoints_inserted = 0;
|
||||
@ -423,7 +419,6 @@ wait_for_inferior ()
|
||||
struct target_waitstatus w;
|
||||
int another_trap;
|
||||
int random_signal;
|
||||
CORE_ADDR stop_sp = 0;
|
||||
CORE_ADDR stop_func_start;
|
||||
CORE_ADDR stop_func_end;
|
||||
char *stop_func_name;
|
||||
@ -436,6 +431,7 @@ wait_for_inferior ()
|
||||
struct breakpoint *step_resume_breakpoint = NULL;
|
||||
struct breakpoint *through_sigtramp_breakpoint = NULL;
|
||||
int pid;
|
||||
int update_step_sp = 0;
|
||||
|
||||
old_cleanups = make_cleanup (delete_breakpoint_current_contents,
|
||||
&step_resume_breakpoint);
|
||||
@ -462,7 +458,10 @@ wait_for_inferior ()
|
||||
|
||||
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 ();
|
||||
|
||||
@ -473,6 +472,17 @@ wait_for_inferior ()
|
||||
{
|
||||
fprintf_unfiltered (gdb_stderr, "[New %s]\n", target_pid_to_str (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)
|
||||
@ -498,8 +508,7 @@ wait_for_inferior ()
|
||||
printf_filtered ("\nProgram exited with code 0%o.\n",
|
||||
(unsigned int)w.value.integer);
|
||||
else
|
||||
if (!batch_mode())
|
||||
printf_filtered ("\nProgram exited normally.\n");
|
||||
printf_filtered ("\nProgram exited normally.\n");
|
||||
gdb_flush (gdb_stdout);
|
||||
target_mourn_inferior ();
|
||||
#ifdef NO_SINGLE_STEP
|
||||
@ -559,7 +568,11 @@ wait_for_inferior ()
|
||||
target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */
|
||||
/* FIXME: What if a signal arrives instead of the single-step
|
||||
happening? */
|
||||
target_wait (pid, &w);
|
||||
|
||||
if (target_wait_hook)
|
||||
target_wait_hook (pid, &w);
|
||||
else
|
||||
target_wait (pid, &w);
|
||||
insert_breakpoints ();
|
||||
target_resume (pid, 0, TARGET_SIGNAL_0);
|
||||
continue;
|
||||
@ -630,7 +643,6 @@ wait_for_inferior ()
|
||||
through_sigtramp_breakpoint = NULL;
|
||||
}
|
||||
prev_pc = 0;
|
||||
prev_sp = 0;
|
||||
prev_func_name = NULL;
|
||||
step_range_start = 0;
|
||||
step_range_end = 0;
|
||||
@ -654,9 +666,6 @@ wait_for_inferior ()
|
||||
continue;
|
||||
}
|
||||
|
||||
set_current_frame (create_new_frame (read_fp (), stop_pc));
|
||||
select_frame (get_current_frame (), 0);
|
||||
|
||||
#ifdef HAVE_STEPPABLE_WATCHPOINT
|
||||
/* It may not be necessary to disable the watchpoint to stop over
|
||||
it. For example, the PA can (with some kernel cooperation)
|
||||
@ -696,8 +705,6 @@ wait_for_inferior ()
|
||||
STOPPED_BY_WATCHPOINT (w);
|
||||
#endif
|
||||
|
||||
stop_frame_address = FRAME_FP (get_current_frame ());
|
||||
stop_sp = read_sp ();
|
||||
stop_func_start = 0;
|
||||
stop_func_name = 0;
|
||||
/* 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. */
|
||||
stop_bpstat = bpstat_stop_status
|
||||
(&stop_pc, stop_frame_address,
|
||||
(&stop_pc,
|
||||
#if DECR_PC_AFTER_BREAK
|
||||
/* Notice the case of stepping through a jump
|
||||
that lands just after a breakpoint.
|
||||
@ -782,7 +789,8 @@ wait_for_inferior ()
|
||||
= !(bpstat_explains_signal (stop_bpstat)
|
||||
|| trap_expected
|
||||
#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. */
|
||||
|| (step_range_end && step_resume_breakpoint == NULL));
|
||||
else
|
||||
@ -793,7 +801,8 @@ wait_for_inferior ()
|
||||
news) give another signal besides SIGTRAP,
|
||||
so check here as well as above. */
|
||||
#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. */
|
||||
);
|
||||
if (!random_signal)
|
||||
@ -904,7 +913,7 @@ wait_for_inferior ()
|
||||
#if 0
|
||||
/* FIXME - Need to implement nested temporary breakpoints */
|
||||
if (step_over_calls
|
||||
&& (stop_frame_address
|
||||
&& (FRAME_FP (get_current_frame ())
|
||||
INNER_THAN step_frame_address))
|
||||
{
|
||||
another_trap = 1;
|
||||
@ -950,7 +959,8 @@ wait_for_inferior ()
|
||||
break;
|
||||
|
||||
case BPSTAT_WHAT_THROUGH_SIGTRAMP:
|
||||
delete_breakpoint (through_sigtramp_breakpoint);
|
||||
if (through_sigtramp_breakpoint)
|
||||
delete_breakpoint (through_sigtramp_breakpoint);
|
||||
through_sigtramp_breakpoint = NULL;
|
||||
|
||||
/* 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
|
||||
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)
|
||||
{
|
||||
stop_print_frame = 0;
|
||||
@ -1017,17 +1027,21 @@ wait_for_inferior ()
|
||||
step range and either the stack or frame pointers
|
||||
just changed, we've stepped outside */
|
||||
&& !(stop_pc == step_range_start
|
||||
&& stop_frame_address
|
||||
&& (stop_sp INNER_THAN prev_sp
|
||||
|| stop_frame_address != step_frame_address)))
|
||||
&& FRAME_FP (get_current_frame ())
|
||||
&& (read_sp () INNER_THAN step_sp
|
||||
|| FRAME_FP (get_current_frame ()) != step_frame_address)))
|
||||
{
|
||||
/* We might be doing a BPSTAT_WHAT_SINGLE and getting a signal.
|
||||
So definately need to check for sigtramp here. */
|
||||
goto check_sigtramp2;
|
||||
}
|
||||
|
||||
/* We stepped out of the stepping range. See if that was due
|
||||
to a subroutine call that we should proceed to the end of. */
|
||||
/* We stepped out of the stepping range. */
|
||||
|
||||
/* 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? */
|
||||
if (IN_SIGTRAMP (stop_pc, stop_func_name)
|
||||
@ -1052,8 +1066,7 @@ wait_for_inferior ()
|
||||
sr_sal.symtab = NULL;
|
||||
sr_sal.line = 0;
|
||||
/* We could probably be setting the frame to
|
||||
prev_frame_address; the reason we don't is that it didn't used
|
||||
to exist. */
|
||||
step_frame_address; I don't think anyone thought to try it. */
|
||||
step_resume_breakpoint =
|
||||
set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
|
||||
if (breakpoints_inserted)
|
||||
@ -1073,6 +1086,9 @@ wait_for_inferior ()
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
struct symtab *s;
|
||||
@ -1096,7 +1112,7 @@ wait_for_inferior ()
|
||||
/* Might be a recursive call if either we have a prologue
|
||||
or the call instruction itself saves the PC on the stack. */
|
||||
|| prologue_pc != stop_func_start
|
||||
|| stop_sp != prev_sp)
|
||||
|| read_sp () != step_sp)
|
||||
&& (/* PC is completely out of bounds of any known objfiles. Treat
|
||||
like a subroutine call. */
|
||||
! stop_func_start
|
||||
@ -1112,6 +1128,16 @@ wait_for_inferior ()
|
||||
|
||||
|| 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
|
||||
call. I'm not completely sure this is necessary now that we
|
||||
have the above checks with stop_func_start (and now that
|
||||
@ -1183,7 +1209,7 @@ step_over_function:
|
||||
step_resume_breakpoint =
|
||||
set_momentary_breakpoint (sr_sal, get_current_frame (),
|
||||
bp_step_resume);
|
||||
step_resume_breakpoint->frame = prev_frame_address;
|
||||
step_resume_breakpoint->frame = step_frame_address;
|
||||
if (breakpoints_inserted)
|
||||
insert_breakpoints ();
|
||||
}
|
||||
@ -1341,8 +1367,10 @@ step_into_function:
|
||||
been at the start of a
|
||||
function. */
|
||||
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
|
||||
running the inferior and not return to debugger. */
|
||||
@ -1417,8 +1445,6 @@ step_into_function:
|
||||
prev_pc = read_pc ();
|
||||
prev_func_start = stop_func_start;
|
||||
prev_func_name = stop_func_name;
|
||||
prev_sp = stop_sp;
|
||||
prev_frame_address = stop_frame_address;
|
||||
}
|
||||
do_cleanups (old_cleanups);
|
||||
}
|
||||
@ -1492,6 +1518,8 @@ Further execution is probably impossible.\n");
|
||||
if we have one. */
|
||||
if (!stop_stack_dummy)
|
||||
{
|
||||
select_frame (get_current_frame (), 0);
|
||||
|
||||
if (stop_print_frame)
|
||||
{
|
||||
int source_only;
|
||||
@ -1499,7 +1527,7 @@ Further execution is probably impossible.\n");
|
||||
source_only = bpstat_print (stop_bpstat);
|
||||
source_only = source_only ||
|
||||
( stop_step
|
||||
&& step_frame_address == stop_frame_address
|
||||
&& step_frame_address == FRAME_FP (get_current_frame ())
|
||||
&& step_start_function == find_pc_function (stop_pc));
|
||||
|
||||
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_pc = stop_pc;
|
||||
inf_status->stop_frame_address = stop_frame_address;
|
||||
inf_status->stop_step = stop_step;
|
||||
inf_status->stop_stack_dummy = stop_stack_dummy;
|
||||
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_pc = inf_status->stop_pc;
|
||||
stop_frame_address = inf_status->stop_frame_address;
|
||||
stop_step = inf_status->stop_step;
|
||||
stop_stack_dummy = inf_status->stop_stack_dummy;
|
||||
stopped_by_random_signal = inf_status->stopped_by_random_signal;
|
||||
|
12
gdb/top.c
12
gdb/top.c
@ -379,6 +379,16 @@ void (*disable_breakpoint_hook) PARAMS ((struct breakpoint *bpt));
|
||||
|
||||
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). */
|
||||
jmp_buf error_return;
|
||||
@ -858,6 +868,8 @@ execute_command (p, from_tty)
|
||||
do_setshow_command (arg, from_tty & caution, c);
|
||||
else if (c->function.cfunc == NO_FUNCTION)
|
||||
error ("That is not a command, just a help topic.");
|
||||
else if (call_command_hook)
|
||||
call_command_hook (c, arg, from_tty & caution);
|
||||
else
|
||||
(*c->function.cfunc) (arg, from_tty & caution);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user