blob: dbe63322c660a02d35cd6d2d89843a0f04d19dd6 [file] [log] [blame]
# Copyright 2002 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 2 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, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# This file was written by Jason Molenda (jmolenda@apple.com)
# This file looks at $pc via different mechanisms as we go up and down the
# stack. If the pc is consistently wrong, this test won't flag any failures,
# but if the pc is reported differently, we can catch that.
if $tracelevel then {
strace $tracelevel
}
set prms_id 0
set bug_id 0
set testfile "pc-verify"
set srcfile ${testfile}.c
set binfile ${objdir}/${subdir}/${testfile}
global hex
if { [gdb_compile "${srcdir}/${subdir}/$srcfile" "${binfile}" executable {debug}] != "" } {
gdb_suppress_entire_file "Testcase compile failed, so all tests in this fil
e will automatically fail."
}
# Start with a fresh gdb
gdb_exit
gdb_start
gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${binfile}
if ![runto_main] then {
fail "pc-verify tests suppressed"
return -1
}
#####
##### Gather some information in main() before we call into a subroutine.
#####
gdb_test "next" ".*factorial.*" "next over boring line"
send_gdb "info line\n"
gdb_expect {
-re ".*Line.*starts at address ($hex) .*ends at ($hex) <main.$decimal>.\[\r\n\]*$gdb_prompt $" {
set main_info_line_start $expect_out(1,string)
set main_info_line_end $expect_out(2,string)
pass "info line in main()."
}
-re ".*$gdb_prompt $" {
fail "info line in main()."
}
timeout { fail "info line in main(). (timeout)" }
}
#warning "got pc value of $main_info_line_start\n"
send_gdb "p/x \$pc\n"
gdb_expect {
-re ".*$decimal = ($hex)\[\r\n\]*$gdb_prompt $" {
set main_cur_pc $expect_out(1,string)
pass "Get pc value in main() #1"
}
-re ".*$gdb_prompt $" {
fail "Get pc value in main() #1"
}
timeout { fail "Get pc value in main() #1 (timeout)" }
}
send_gdb "p/x \$fp\n"
gdb_expect {
-re ".*$decimal = ($hex)\[\r\n\]*$gdb_prompt $" {
set main_cur_fp $expect_out(1,string)
pass "Get fp value in main() #1"
}
-re ".*$gdb_prompt $" {
fail "Get fp value in main() #1"
}
timeout { fail "Get fp value in main() #1 (timeout)" }
}
send_gdb "info fr\n"
gdb_expect {
-re ".*Stack level 0, frame at ($hex):.*(pc|eip|rip) = ($hex) in main.*$gdb_prompt $" {
set main_current_fp_from_info_frame $expect_out(1,string)
set main_current_pc_from_info_frame $expect_out(3,string)
pass "info frame in main #1."
}
-re ".*$gdb_prompt $" {
fail "info frame in main #1."
}
timeout { fail "info frame in main #1. (timeout)" }
}
if {$main_current_pc_from_info_frame != $main_cur_pc} then {
fail "p/x \$pc returns the same as info frame's \$pc"
} else {
pass "p/x \$pc returns the same as info frame's \$pc"
}
# on x86, $fp (aka EBP) points two words into the stack frame.
# info frame will report the correct frame address, which starts
# with the saved EIP, then the saved ESP. EBP points to the
# space below that. So for the sake of this comparison add the
# offset to EBP so it matches info frame's output.
if [istarget "i\[3-6\]86-apple-darwin*"] {
set offset 8
} else {
set offset 0
}
if {$main_current_fp_from_info_frame != $main_cur_fp + $offset} then {
fail "p/x \$fp returns the same as info frame's \$fp"
} else {
pass "p/x \$fp returns the same as info frame's \$fp"
}
#####
##### Call into factorial(), see if the numbers make sense down there.
#####
gdb_test "step" ".*factorial.*" "step into factorial"
send_gdb "bt\n"
gdb_expect {
-re ".*#0 *factorial.*#1 *($hex) in main.*$gdb_prompt $" {
set main_calling_pc_from_backtrace $expect_out(1,string)
pass "backtrace in factorial level 1."
}
-re ".*$gdb_prompt $" {
fail "backtrace in factorial level 1."
}
timeout { fail "backtrace in factorial level 1. (timeout)" }
}
if { $main_calling_pc_from_backtrace < $main_info_line_start || \
$main_calling_pc_from_backtrace > $main_info_line_end } then {
fail "pc from backtrace is within info line range"
} else {
pass "pc from backtrace is within info line range"
}
send_gdb "info fr\n"
gdb_expect {
-re "Stack level 0, frame at ($hex).*(pc|eip|rip) = ($hex) in factorial.*saved (pc|eip|rip) ($hex).*$gdb_prompt $" {
set factorial_info_frame_fp $expect_out(1,string)
set factorial_info_frame_pc $expect_out(3,string)
set factorial_info_frame_saved_pc $expect_out(5,string)
pass "info frame in factorial"
}
-re ".*$gdb_prompt $" {
fail "info frame in factorial"
}
timeout { fail info frame in factorial. (timeout)" }
}
if { $factorial_info_frame_saved_pc < $main_info_line_start || \
$factorial_info_frame_saved_pc > $main_info_line_end } then {
fail "pc from info frame in factorial is within info line range"
} else {
pass "pc from info frame in factorial is within info line range"
}
gdb_test "up" ".*in main.*" "change frame back to main"
send_gdb "p/x \$pc\n"
gdb_expect {
-re ".*$decimal = ($hex)\[\r\n\]*$gdb_prompt $" {
set new_main_pc $expect_out(1,string)
pass "Get pc value in main() #2"
}
-re ".*$gdb_prompt $" {
fail "Get pc value in main() #2"
}
timeout { fail "Get pc value in main() #2 (timeout)" }
}
if {$new_main_pc == $factorial_info_frame_saved_pc} then {
pass "\$pc in main is the same as the saved pc from factorial"
} else {
fail "\$pc in main is the same as the saved pc from factorial"
}
if { $new_main_pc < $main_info_line_start || \
$new_main_pc > $main_info_line_end } then {
fail "p/x \$pc at stack level 1 reports pc within correct range"
} else {
pass "p/x \$pc at stack level 1 reports pc within correct range"
}
gdb_exit
return 0