diff options
author | Tom de Vries <tdevries@suse.de> | 2023-01-25 13:27:03 +0100 |
---|---|---|
committer | Tom de Vries <tdevries@suse.de> | 2023-01-25 13:27:03 +0100 |
commit | ebef88edb6474fa9568123645b6762bcd6872702 (patch) | |
tree | 3c01c6e80e0c492a509eac36c72d6a32f3b86a40 /gdb/testsuite | |
parent | 5f6ec13ffe8ae4db04419bf66868e082df73634d (diff) | |
download | gdb-ebef88edb6474fa9568123645b6762bcd6872702.zip gdb-ebef88edb6474fa9568123645b6762bcd6872702.tar.gz gdb-ebef88edb6474fa9568123645b6762bcd6872702.tar.bz2 |
[gdb/testsuite] Analyze non-leaf fn in gdb.base/unwind-on-each-insn.exp
In test-case gdb.base/unwind-on-each-insn.exp, we stepi through function foo
to check various invariants at each insn, in particular hoping to excercise
insns that modify stack and frame pointers.
Function foo is a leaf function, so add a non-leaf function bar, and step
through it as well (using nexti instead of stepi).
With the updated test-case, on powerpc64le-linux, I run into PR tdep/30049:
...
FAIL: bar: instruction 5: bt 2
FAIL: bar: instruction 5: up
FAIL: bar: instruction 5: [string equal $fid $::main_fid]
FAIL: bar: instruction 6: bt 2
FAIL: bar: instruction 6: up
FAIL: bar: instruction 6: [string equal $fid $::main_fid]
...
Tested on:
- x86_64-linux (-m64 and -m32)
- s390x-linux (-m64 and -m31)
- aarch64-linux
- powerpc64le-linux
Diffstat (limited to 'gdb/testsuite')
-rw-r--r-- | gdb/testsuite/gdb.base/unwind-on-each-insn-foo.c | 6 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/unwind-on-each-insn.c | 2 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/unwind-on-each-insn.exp | 137 |
3 files changed, 86 insertions, 59 deletions
diff --git a/gdb/testsuite/gdb.base/unwind-on-each-insn-foo.c b/gdb/testsuite/gdb.base/unwind-on-each-insn-foo.c index 635aa44..4a3b294 100644 --- a/gdb/testsuite/gdb.base/unwind-on-each-insn-foo.c +++ b/gdb/testsuite/gdb.base/unwind-on-each-insn-foo.c @@ -20,3 +20,9 @@ foo (const char *s) { /* Nothing. */ } + +void +bar (const char *s) +{ + foo (s); +} diff --git a/gdb/testsuite/gdb.base/unwind-on-each-insn.c b/gdb/testsuite/gdb.base/unwind-on-each-insn.c index 821df37..4aabc65 100644 --- a/gdb/testsuite/gdb.base/unwind-on-each-insn.c +++ b/gdb/testsuite/gdb.base/unwind-on-each-insn.c @@ -16,10 +16,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ extern void foo (const char *); +extern void bar (const char *); int main () { foo ("foo"); + bar ("bar"); return 0; } diff --git a/gdb/testsuite/gdb.base/unwind-on-each-insn.exp b/gdb/testsuite/gdb.base/unwind-on-each-insn.exp index 6e68b24..a5e43c6 100644 --- a/gdb/testsuite/gdb.base/unwind-on-each-insn.exp +++ b/gdb/testsuite/gdb.base/unwind-on-each-insn.exp @@ -79,72 +79,91 @@ proc get_fid { } { lassign [get_sp_and_fba "in main"] main_sp main_fba set main_fid [get_fid] -# Now enter the foo function. -gdb_breakpoint "*foo" -gdb_continue_to_breakpoint "enter foo" +proc do_test { function step_cmd } { + # Now enter the function. Ideally, stop at the first insn, so set a + # breakpoint at "*$function". The "*$function" breakpoint may not trigger + # for archs with gdbarch_skip_entrypoint_p, so set a backup breakpoint at + # "$function". + gdb_breakpoint "*$function" + gdb_breakpoint "$function" + gdb_continue_to_breakpoint "enter $function" + # Cleanup breakpoints. + delete_breakpoints + + # Record the current stack-pointer, and the frame base address. + lassign [get_sp_and_fba "in $function"] fn_sp fn_fba + set fn_fid [get_fid] + + for { set i_count 1 } { true } { incr i_count } { + with_test_prefix "instruction ${i_count}" { + + # The current stack-pointer value can legitimately change + # throughout the lifetime of a function, so we don't check the + # current stack-pointer value. But the frame base address + # should not change, so we do check for that. + lassign [get_sp_and_fba "for fn"] sp_value fba_value + gdb_assert { $fba_value == $fn_fba } + + # The frame-id should never change within a function, so check + # that now. + set fid [get_fid] + gdb_assert { [string equal $fid $fn_fid] } \ + "check frame-id matches" + + # Check that the previous frame is 'main'. + gdb_test "bt 2" "\r\n#1\\s+\[^\r\n\]+ in main \\(\\) .*" + + # Move up the stack (to main). + gdb_test "up" \ + "\r\n#1\\s+\[^\r\n\]+ in main \\(\\) .*" + + # Check we can unwind the stack-pointer and the frame base + # address correctly. + lassign [get_sp_and_fba "for main"] sp_value fba_value + if { $i_count == 1 } { + # The stack-pointer may have changed while running to *$function. + set ::main_sp $sp_value + } else { + gdb_assert { $sp_value == $::main_sp } + } + gdb_assert { $fba_value == $::main_fba } -# Record the current stack-pointer, and the frame base address. -lassign [get_sp_and_fba "in foo"] foo_sp foo_fba -set foo_fid [get_fid] - -for { set i_count 1 } { true } { incr i_count } { - with_test_prefix "instruction ${i_count}" { - - # The current stack-pointer value can legitimately change - # throughout the lifetime of a function, so we don't check the - # current stack-pointer value. But the frame base address - # should not change, so we do check for that. - lassign [get_sp_and_fba "for foo"] sp_value fba_value - gdb_assert { $fba_value == $foo_fba } - - # The frame-id should never change within a function, so check - # that now. - set fid [get_fid] - gdb_assert { [string equal $fid $foo_fid] } \ - "check frame-id matches" - - # Check that the previous frame is 'main'. - gdb_test "bt 2" "\r\n#1\\s+\[^\r\n\]+ in main \\(\\) .*" - - # Move up the stack (to main). - gdb_test "up" \ - "\r\n#1\\s+\[^\r\n\]+ in main \\(\\) .*" - - # Check we can unwind the stack-pointer and the frame base - # address correctly. - lassign [get_sp_and_fba "for main"] sp_value fba_value - if { $i_count == 1 } { - # The stack-pointer may have changed while running to *foo. - set main_sp $sp_value - } else { - gdb_assert { $sp_value == $main_sp } - } - gdb_assert { $fba_value == $main_fba } + # Check we have a consistent value for main's frame-id. + set fid [get_fid] + gdb_assert { [string equal $fid $::main_fid] } - # Check we have a consistent value for main's frame-id. - set fid [get_fid] - gdb_assert { [string equal $fid $main_fid] } + # Move back to the inner most frame. + gdb_test "frame 0" ".*" - # Move back to the inner most frame. - gdb_test "frame 0" ".*" + if { $i_count > 100 } { + # We expect a handful of instructions, if we reach 100, + # something is going wrong. Avoid an infinite loop. + fail "exceeded max number of instructions" + break + } - if { $i_count > 100 } { - # We expect a handful of instructions, if we reach 100, - # something is going wrong. Avoid an infinite loop. - fail "exceeded max number of instructions" - break - } + set in_fn 0 + gdb_test_multiple $step_cmd "" { + -re -wrap "$::hex in $function \\(\\)" { + set in_fn 1 + } + -re -wrap "" {} + } - set in_foo 0 - gdb_test_multiple "stepi" "" { - -re -wrap "$hex in foo \\(\\)" { - set in_foo 1 + if { ! $in_fn } { + break } - -re -wrap "" {} } + } +} - if { ! $in_foo } { - break - } +foreach { + function step_cmd +} { + foo stepi + bar nexti +} { + with_test_prefix $function { + do_test $function $step_cmd } } |