⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gdb.exp

📁 gdb-6.8 Linux下的调试程序 最新版本
💻 EXP
📖 第 1 页 / 共 5 页
字号:
# Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,# 2003, 2004, 2005, 2007, 2008 Free Software Foundation, Inc.# This program is free software; you can redistribute it and/or modify# it under the terms of the GNU General Public License as published by# the Free Software Foundation; either version 3 of the License, or# (at your option) any later version.## This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the# GNU General Public License for more details.## You should have received a copy of the GNU General Public License# along with this program.  If not, see <http://www.gnu.org/licenses/>.# This file was written by Fred Fish. (fnf@cygnus.com)# Generic gdb subroutines that should work for any target.  If these# need to be modified for any target, it can be done with a variable# or by passing arguments.if {$tool == ""} {    # Tests would fail, logs on get_compiler_info() would be missing.    send_error "`site.exp' not found, run `make site.exp'!\n"    exit 2}load_lib libgloss.expglobal GDBif [info exists TOOL_EXECUTABLE] {    set GDB $TOOL_EXECUTABLE;}if ![info exists GDB] {    if ![is_remote host] {	set GDB [findfile $base_dir/../../gdb/gdb "$base_dir/../../gdb/gdb" [transform gdb]]    } else {	set GDB [transform gdb];    }}verbose "using GDB = $GDB" 2global GDBFLAGSif ![info exists GDBFLAGS] {    set GDBFLAGS "-nx"}verbose "using GDBFLAGS = $GDBFLAGS" 2# The variable gdb_prompt is a regexp which matches the gdb prompt.# Set it if it is not already set.global gdb_promptif ![info exists gdb_prompt] then {    set gdb_prompt "\[(\]gdb\[)\]"}# The variable fullname_syntax_POSIX is a regexp which matches a POSIX # absolute path ie. /foo/ set fullname_syntax_POSIX "/.*/"# The variable fullname_syntax_UNC is a regexp which matches a Windows # UNC path ie. \\D\foo\ set fullname_syntax_UNC {\\\\[^\\]+\\.+\\}# The variable fullname_syntax_DOS_CASE is a regexp which matches a # particular DOS case that GDB most likely will output# ie. \foo\, but don't match \\.*\ set fullname_syntax_DOS_CASE {\\[^\\].*\\}# The variable fullname_syntax_DOS is a regexp which matches a DOS path# ie. a:\foo\ && a:foo\ set fullname_syntax_DOS {[a-zA-Z]:.*\\}# The variable fullname_syntax is a regexp which matches what GDB considers# an absolute path. It is currently debatable if the Windows style paths # d:foo and \abc should be considered valid as an absolute path.# Also, the purpse of this regexp is not to recognize a well formed # absolute path, but to say with certainty that a path is absolute.set fullname_syntax "($fullname_syntax_POSIX|$fullname_syntax_UNC|$fullname_syntax_DOS_CASE|$fullname_syntax_DOS)"# Needed for some tests under Cygwin.global EXEEXTglobal envif ![info exists env(EXEEXT)] {    set EXEEXT ""} else {    set EXEEXT $env(EXEEXT)}set octal "\[0-7\]+"### Only procedures should come after this point.## gdb_version -- extract and print the version number of GDB#proc default_gdb_version {} {    global GDB    global GDBFLAGS    global gdb_prompt    set fileid [open "gdb_cmd" w];    puts $fileid "q";    close $fileid;    set cmdfile [remote_download host "gdb_cmd"];    set output [remote_exec host "$GDB -nw --command $cmdfile"]    remote_file build delete "gdb_cmd";    remote_file host delete "$cmdfile";    set tmp [lindex $output 1];    set version ""    regexp " \[0-9\]\[^ \t\n\r\]+" "$tmp" version    if ![is_remote host] {	clone_output "[which $GDB] version $version $GDBFLAGS\n"    } else {	clone_output "$GDB on remote host version $version $GDBFLAGS\n"    }}proc gdb_version { } {    return [default_gdb_version];}## gdb_unload -- unload a file if one is loaded#proc gdb_unload {} {    global verbose    global GDB    global gdb_prompt    send_gdb "file\n"    gdb_expect 60 {	-re "No executable file now\[^\r\n\]*\[\r\n\]" { exp_continue }	-re "No symbol file now\[^\r\n\]*\[\r\n\]" { exp_continue }	-re "A program is being debugged already..*Kill it.*y or n. $"\	    { send_gdb "y\n"		verbose "\t\tKilling previous program being debugged"	    exp_continue	}	-re "Discard symbol table from .*y or n.*$" {	    send_gdb "y\n"	    exp_continue	}	-re "$gdb_prompt $" {}	timeout {	    perror "couldn't unload file in $GDB (timed out)."	    return -1	}    }}# Many of the tests depend on setting breakpoints at various places and# running until that breakpoint is reached.  At times, we want to start# with a clean-slate with respect to breakpoints, so this utility proc # lets us do this without duplicating this code everywhere.#proc delete_breakpoints {} {    global gdb_prompt    # we need a larger timeout value here or this thing just confuses    # itself.  May need a better implementation if possible. - guo    #    send_gdb "delete breakpoints\n"    gdb_expect 100 {	 -re "Delete all breakpoints.*y or n.*$" {	    send_gdb "y\n";	    exp_continue	}	 -re "$gdb_prompt $" { # This happens if there were no breakpoints	    }	 timeout { perror "Delete all breakpoints in delete_breakpoints (timeout)" ; return }    }    send_gdb "info breakpoints\n"    gdb_expect 100 {	 -re "No breakpoints or watchpoints..*$gdb_prompt $" {}	 -re "$gdb_prompt $" { perror "breakpoints not deleted" ; return }	 -re "Delete all breakpoints.*or n.*$" {	    send_gdb "y\n";	    exp_continue	}	 timeout { perror "info breakpoints (timeout)" ; return }    }}## Generic run command.## The second pattern below matches up to the first newline *only*.# Using ``.*$'' could swallow up output that we attempt to match# elsewhere.#proc gdb_run_cmd {args} {    global gdb_prompt    if [target_info exists gdb_init_command] {	send_gdb "[target_info gdb_init_command]\n";	gdb_expect 30 {	    -re "$gdb_prompt $" { }	    default {		perror "gdb_init_command for target failed";		return;	    }	}    }    if [target_info exists use_gdb_stub] {	if [target_info exists gdb,do_reload_on_run] {	    if { [gdb_reload] != 0 } {		return;	    }	    send_gdb "continue\n";	    gdb_expect 60 {		-re "Continu\[^\r\n\]*\[\r\n\]" {}		default {}	    }	    return;	}	if [target_info exists gdb,start_symbol] {	    set start [target_info gdb,start_symbol];	} else {	    set start "start";	}	send_gdb  "jump *$start\n"	set start_attempt 1;	while { $start_attempt } {	    # Cap (re)start attempts at three to ensure that this loop	    # always eventually fails.  Don't worry about trying to be	    # clever and not send a command when it has failed.	    if [expr $start_attempt > 3] {		perror "Jump to start() failed (retry count exceeded)";		return;	    }	    set start_attempt [expr $start_attempt + 1];	    gdb_expect 30 {		-re "Continuing at \[^\r\n\]*\[\r\n\]" {		    set start_attempt 0;		}		-re "No symbol \"_start\" in current.*$gdb_prompt $" {		    perror "Can't find start symbol to run in gdb_run";		    return;		}		-re "No symbol \"start\" in current.*$gdb_prompt $" {		    send_gdb "jump *_start\n";		}		-re "No symbol.*context.*$gdb_prompt $" {		    set start_attempt 0;		}		-re "Line.* Jump anyway.*y or n. $" {		    send_gdb "y\n"		}		-re "The program is not being run.*$gdb_prompt $" {		    if { [gdb_reload] != 0 } {			return;		    }		    send_gdb "jump *$start\n";		}		timeout {		    perror "Jump to start() failed (timeout)"; 		    return		}	    }	}	if [target_info exists gdb_stub] {	    gdb_expect 60 {		-re "$gdb_prompt $" {		    send_gdb "continue\n"		}	    }	}	return    }    if [target_info exists gdb,do_reload_on_run] {	if { [gdb_reload] != 0 } {	    return;	}    }    send_gdb "run $args\n"# This doesn't work quite right yet.# Use -notransfer here so that test cases (like chng-sym.exp)# may test for additional start-up messages.   gdb_expect 60 {	-re "The program .* has been started already.*y or n. $" {	    send_gdb "y\n"	    exp_continue	}	-notransfer -re "Starting program: \[^\r\n\]*" {}    }}# Generic start command.  Return 0 if we could start the program, -1# if we could not.proc gdb_start_cmd {args} {    global gdb_prompt    if [target_info exists gdb_init_command] {	send_gdb "[target_info gdb_init_command]\n";	gdb_expect 30 {	    -re "$gdb_prompt $" { }	    default {		perror "gdb_init_command for target failed";		return;	    }	}    }    if [target_info exists use_gdb_stub] {	return -1    }    send_gdb "start $args\n"    gdb_expect 60 {	-re "The program .* has been started already.*y or n. $" {	    send_gdb "y\n"	    exp_continue	}	# Use -notransfer here so that test cases (like chng-sym.exp)	# may test for additional start-up messages.	-notransfer -re "Starting program: \[^\r\n\]*" {	    return 0	}    }    return -1}# Set a breakpoint at FUNCTION.  If there is an additional argument it is# a list of options; the supported options are allow-pending and temporary.proc gdb_breakpoint { function args } {    global gdb_prompt    global decimal    set pending_response n    if {[lsearch -exact [lindex $args 0] allow-pending] != -1} {	set pending_response y    }    set break_command "break"    if {[lsearch -exact [lindex $args 0] temporary] != -1} {	set break_command "tbreak"    }    send_gdb "$break_command $function\n"    # The first two regexps are what we get with -g, the third is without -g.    gdb_expect 30 {	-re "Breakpoint \[0-9\]* at .*: file .*, line $decimal.\r\n$gdb_prompt $" {}	-re "Breakpoint \[0-9\]*: file .*, line $decimal.\r\n$gdb_prompt $" {}	-re "Breakpoint \[0-9\]* at .*$gdb_prompt $" {}	-re "Breakpoint \[0-9\]* \\(.*\\) pending.*$gdb_prompt $" {		if {$pending_response == "n"} {			fail "setting breakpoint at $function"			return 0		}	}	-re "Make breakpoint pending.*y or \\\[n\\\]. $" { 		send_gdb "$pending_response\n"		exp_continue	}	-re "$gdb_prompt $" { fail "setting breakpoint at $function" ; return 0 }	timeout { fail "setting breakpoint at $function (timeout)" ; return 0 }    }    return 1;}    # Set breakpoint at function and run gdb until it breaks there.# Since this is the only breakpoint that will be set, if it stops# at a breakpoint, we will assume it is the one we want.  We can't# just compare to "function" because it might be a fully qualified,# single quoted C++ function specifier.  If there's an additional argument,# pass it to gdb_breakpoint.proc runto { function args } {    global gdb_prompt    global decimal    delete_breakpoints    if ![gdb_breakpoint $function [lindex $args 0]] {	return 0;    }    gdb_run_cmd        # the "at foo.c:36" output we get with -g.    # the "in func" output we get without -g.    gdb_expect 30 {	-re "Break.* at .*:$decimal.*$gdb_prompt $" {	    return 1	}	-re "Breakpoint \[0-9\]*, \[0-9xa-f\]* in .*$gdb_prompt $" { 	    return 1	}	-re "$gdb_prompt $" { 	    fail "running to $function in runto"	    return 0	}	timeout { 	    fail "running to $function in runto (timeout)"	    return 0	}    }    return 1}## runto_main -- ask gdb to run until we hit a breakpoint at main.#		The case where the target uses stubs has to be handled#		specially--if it uses stubs, assuming we hit#		breakpoint() and just step out of the function.#proc runto_main { } {    global gdb_prompt    global decimal    if ![target_info exists gdb_stub] {	return [runto main]    }			    delete_breakpoints    gdb_step_for_stub;    return 1}### Continue, and expect to hit a breakpoint.### Report a pass or fail, depending on whether it seems to have### worked.  Use NAME as part of the test name; each call to### continue_to_breakpoint should use a NAME which is unique within### that test file.proc gdb_continue_to_breakpoint {name} {    global gdb_prompt    set full_name "continue to breakpoint: $name"    send_gdb "continue\n"    gdb_expect {	-re "Breakpoint .* at .*\r\n$gdb_prompt $" {	    pass $full_name	}	-re ".*$gdb_prompt $" {	    fail $full_name	}	timeout { 	    fail "$full_name (timeout)"	}    }}# gdb_internal_error_resync:## Answer the questions GDB asks after it reports an internal error# until we get back to a GDB prompt.  Decline to quit the debugging# session, and decline to create a core file.  Return non-zero if the# resync succeeds.## This procedure just answers whatever questions come up until it sees# a GDB prompt; it doesn't require you to have matched the input up to# any specific point.  However, it only answers questions it sees in# the output itself, so if you've matched a question, you had better# answer it yourself before calling this.## You can use this function thus:## gdb_expect {#     ...#     -re ".*A problem internal to GDB has been detected" {#         gdb_internal_error_resync#     }#     ...# }#proc gdb_internal_error_resync {} {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -