From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2205) id 6DCDA385840F; Thu, 26 Jan 2023 16:21:07 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 6DCDA385840F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1674750067; bh=htOZH3c+J8ByDDCICBCSKjbCfVGB2691VvdLJqKxyag=; h=From:To:Subject:Date:From; b=tM7VkJBwT0k6fRJAR7pZypGdOtl9xuz9iKtzHwl6RVmhUT0mwOYzJQLl4O0kz65QU vvW2ULjKMzcL28IFcDPrZKsU7SSKoITXRPEBCxrZmjxj/C6s8X4EUq5n5t+ZYkCAlM GvJDNnW/1d5dxvdGiRqQubbcy1ZRjCuurS4uLfKI= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Tom de Vries To: gdb-cvs@sourceware.org Subject: [binutils-gdb] [gdb/testsuite] Add gdb.base/unwind-on-each-insn-{amd64,i386}.exp X-Act-Checkin: binutils-gdb X-Git-Author: Tom de Vries X-Git-Refname: refs/heads/master X-Git-Oldrev: 4fe960e8f105c1c3c672a56f768bb65b2b8cc04e X-Git-Newrev: 1d98e564c97f770bb39954b347c129aa8950dc3b Message-Id: <20230126162107.6DCDA385840F@sourceware.org> Date: Thu, 26 Jan 2023 16:21:07 +0000 (GMT) List-Id: https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3D1d98e564c97f= 770bb39954b347c129aa8950dc3b commit 1d98e564c97f770bb39954b347c129aa8950dc3b Author: Tom de Vries Date: Thu Jan 26 17:21:01 2023 +0100 [gdb/testsuite] Add gdb.base/unwind-on-each-insn-{amd64,i386}.exp =20 The gcc 4.4.x (and earlier) compilers had the problem that the unwind i= nfo in the epilogue was inaccurate. =20 In order to work around this in gdb, epilogue unwinders were added with= a higher priority than the dwarf unwinders in the amd64 and i386 targets: - amd64_epilogue_frame_unwind, and - i386_epilogue_frame_unwind. =20 Subsequently, the epilogue unwind info problem got fixed in gcc 4.5.0. =20 However, the epilogue unwinders prevented gdb from taking advantage of = the fixed epilogue unwind info, so the scope of the epilogue unwinders was limited, bailing out for gcc >=3D 4.5.0. =20 There was no regression test added for this preference scheme, so if we= now declare epilogue unwind info from all gcc versions as trusted, no test = will start failing. =20 Fix this by adding an amd64 and i386 regression test for this. =20 I have no gcc 4.4.x lying around, so I fabricated the assembly files by: - commenting out some .cfi directives to break the epilogue unwind info= , and - hand-editing the producer info to 4.4.7 to activate the fix. =20 Tested on x86_64-linux, target boards unix/{-m64,-m32}. Diff: --- .../gdb.base/unwind-on-each-insn-amd64.exp | 41 ++++ gdb/testsuite/gdb.base/unwind-on-each-insn-amd64.s | 263 +++++++++++++++++= ++++ .../gdb.base/unwind-on-each-insn-i386.exp | 41 ++++ gdb/testsuite/gdb.base/unwind-on-each-insn-i386.s | 262 +++++++++++++++++= +++ gdb/testsuite/gdb.base/unwind-on-each-insn.exp | 158 +------------ gdb/testsuite/gdb.base/unwind-on-each-insn.exp.tcl | 180 ++++++++++++++ 6 files changed, 792 insertions(+), 153 deletions(-) diff --git a/gdb/testsuite/gdb.base/unwind-on-each-insn-amd64.exp b/gdb/tes= tsuite/gdb.base/unwind-on-each-insn-amd64.exp new file mode 100644 index 00000000000..b005715aa56 --- /dev/null +++ b/gdb/testsuite/gdb.base/unwind-on-each-insn-amd64.exp @@ -0,0 +1,41 @@ +# Copyright 2023 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 . */ + +# Check that epilogue unwind info is not used for gcc < 4.5.0, amd64 case. + +require is_x86_64_m64_target + +set srcfile_flags {} +set srcfile2_flags {} +set srcfile_debug 1 +set srcfile2_debug 1 + +if [info exists COMPILE] { + standard_testfile unwind-on-each-insn.c unwind-on-each-insn-foo.c + # When updating the .s file, use these flags to generate the file: + #lappend srcfile2_flags additional_flags=3D-save-temps + #lappend srcfile2_flags additional_flags=3D-dA + # and do the following: + # - copy it in place, run the test-case and verify that all tests pass. + # - break the epilogue unwind info by commenting out the cfi directive + # before ret, and verify that some tests start failing. + # - change the producer strings to 4.4.7 (for completeness, do this al= so + # in the comments generated by -dA), and verify that all tests pass + # again. +} else { + standard_testfile unwind-on-each-insn.c .s +} + +source $srcdir/$subdir/unwind-on-each-insn.exp.tcl diff --git a/gdb/testsuite/gdb.base/unwind-on-each-insn-amd64.s b/gdb/tests= uite/gdb.base/unwind-on-each-insn-amd64.s new file mode 100644 index 00000000000..0def4f61457 --- /dev/null +++ b/gdb/testsuite/gdb.base/unwind-on-each-insn-amd64.s @@ -0,0 +1,263 @@ + .file "unwind-on-each-insn-foo.c" + .text +.Ltext0: + .globl foo + .type foo, @function +foo: +.LFB0: + .file 1 "/home/vries/gdb_versions/devel/src/gdb/testsuite/gdb.base/unwind= -on-each-insn-foo.c" + # /home/vries/gdb_versions/devel/src/gdb/testsuite/gdb.base/unwind-on-eac= h-insn-foo.c:20 + .loc 1 20 0 + .cfi_startproc +# BLOCK 2 seq:0 +# PRED: ENTRY (FALLTHRU) + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + movq %rdi, -8(%rbp) + # /home/vries/gdb_versions/devel/src/gdb/testsuite/gdb.base/unwind-on-eac= h-insn-foo.c:22 + .loc 1 22 0 + nop + popq %rbp + #.cfi_def_cfa 7, 8 +# SUCC: EXIT [100.0%]=20 + ret + .cfi_endproc +.LFE0: + .size foo, .-foo + .globl bar + .type bar, @function +bar: +.LFB1: + # /home/vries/gdb_versions/devel/src/gdb/testsuite/gdb.base/unwind-on-eac= h-insn-foo.c:26 + .loc 1 26 0 + .cfi_startproc +# BLOCK 2 seq:0 +# PRED: ENTRY (FALLTHRU) + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + subq $8, %rsp + movq %rdi, -8(%rbp) + # /home/vries/gdb_versions/devel/src/gdb/testsuite/gdb.base/unwind-on-eac= h-insn-foo.c:27 + .loc 1 27 0 + movq -8(%rbp), %rax + movq %rax, %rdi + call foo + # /home/vries/gdb_versions/devel/src/gdb/testsuite/gdb.base/unwind-on-eac= h-insn-foo.c:28 + .loc 1 28 0 + nop + leave + #.cfi_def_cfa 7, 8 +# SUCC: EXIT [100.0%]=20 + ret + .cfi_endproc +.LFE1: + .size bar, .-bar +.Letext0: + .section .debug_info,"",@progbits +.Ldebug_info0: + .long 0x8c # Length of Compilation Unit Info + .value 0x4 # DWARF version number + .long .Ldebug_abbrev0 # Offset Into Abbrev. Section + .byte 0x8 # Pointer Size (in bytes) + .uleb128 0x1 # (DIE (0xb) DW_TAG_compile_unit) + .long .LASF0 # DW_AT_producer: "GNU C11 4.4.7 -mtune=3Dgeneric -march=3Dx= 86-64 -g -fno-stack-protector" + .byte 0xc # DW_AT_language + .long .LASF1 # DW_AT_name: "/home/vries/gdb_versions/devel/src/gdb/testsu= ite/gdb.base/unwind-on-each-insn-foo.c" + .long .LASF2 # DW_AT_comp_dir: "/home/vries/gdb_versions/devel/build/gdb/= testsuite" + .quad .Ltext0 # DW_AT_low_pc + .quad .Letext0-.Ltext0 # DW_AT_high_pc + .long .Ldebug_line0 # DW_AT_stmt_list + .uleb128 0x2 # (DIE (0x2d) DW_TAG_subprogram) + # DW_AT_external + .ascii "bar\0" # DW_AT_name + .byte 0x1 # DW_AT_decl_file (/home/vries/gdb_versions/devel/src/gdb/tests= uite/gdb.base/unwind-on-each-insn-foo.c) + .byte 0x19 # DW_AT_decl_line + # DW_AT_prototyped + .quad .LFB1 # DW_AT_low_pc + .quad .LFE1-.LFB1 # DW_AT_high_pc + .uleb128 0x1 # DW_AT_frame_base + .byte 0x9c # DW_OP_call_frame_cfa + # DW_AT_GNU_all_tail_call_sites + .long 0x57 # DW_AT_sibling + .uleb128 0x3 # (DIE (0x4a) DW_TAG_formal_parameter) + .ascii "s\0" # DW_AT_name + .byte 0x1 # DW_AT_decl_file (/home/vries/gdb_versions/devel/src/gdb/tests= uite/gdb.base/unwind-on-each-insn-foo.c) + .byte 0x19 # DW_AT_decl_line + .long 0x57 # DW_AT_type + .uleb128 0x2 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 -24 + .byte 0 # end of children of DIE 0x2d + .uleb128 0x4 # (DIE (0x57) DW_TAG_pointer_type) + .byte 0x8 # DW_AT_byte_size + .long 0x64 # DW_AT_type + .uleb128 0x5 # (DIE (0x5d) DW_TAG_base_type) + .byte 0x1 # DW_AT_byte_size + .byte 0x6 # DW_AT_encoding + .long .LASF3 # DW_AT_name: "char" + .uleb128 0x6 # (DIE (0x64) DW_TAG_const_type) + .long 0x5d # DW_AT_type + .uleb128 0x7 # (DIE (0x69) DW_TAG_subprogram) + # DW_AT_external + .ascii "foo\0" # DW_AT_name + .byte 0x1 # DW_AT_decl_file (/home/vries/gdb_versions/devel/src/gdb/tests= uite/gdb.base/unwind-on-each-insn-foo.c) + .byte 0x13 # DW_AT_decl_line + # DW_AT_prototyped + .quad .LFB0 # DW_AT_low_pc + .quad .LFE0-.LFB0 # DW_AT_high_pc + .uleb128 0x1 # DW_AT_frame_base + .byte 0x9c # DW_OP_call_frame_cfa + # DW_AT_GNU_all_call_sites + .uleb128 0x3 # (DIE (0x82) DW_TAG_formal_parameter) + .ascii "s\0" # DW_AT_name + .byte 0x1 # DW_AT_decl_file (/home/vries/gdb_versions/devel/src/gdb/tests= uite/gdb.base/unwind-on-each-insn-foo.c) + .byte 0x13 # DW_AT_decl_line + .long 0x57 # DW_AT_type + .uleb128 0x2 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 -24 + .byte 0 # end of children of DIE 0x69 + .byte 0 # end of children of DIE 0xb + .section .debug_abbrev,"",@progbits +.Ldebug_abbrev0: + .uleb128 0x1 # (abbrev code) + .uleb128 0x11 # (TAG: DW_TAG_compile_unit) + .byte 0x1 # DW_children_yes + .uleb128 0x25 # (DW_AT_producer) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x13 # (DW_AT_language) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x1b # (DW_AT_comp_dir) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x11 # (DW_AT_low_pc) + .uleb128 0x1 # (DW_FORM_addr) + .uleb128 0x12 # (DW_AT_high_pc) + .uleb128 0x7 # (DW_FORM_data8) + .uleb128 0x10 # (DW_AT_stmt_list) + .uleb128 0x17 # (DW_FORM_sec_offset) + .byte 0 + .byte 0 + .uleb128 0x2 # (abbrev code) + .uleb128 0x2e # (TAG: DW_TAG_subprogram) + .byte 0x1 # DW_children_yes + .uleb128 0x3f # (DW_AT_external) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0x8 # (DW_FORM_string) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x27 # (DW_AT_prototyped) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x11 # (DW_AT_low_pc) + .uleb128 0x1 # (DW_FORM_addr) + .uleb128 0x12 # (DW_AT_high_pc) + .uleb128 0x7 # (DW_FORM_data8) + .uleb128 0x40 # (DW_AT_frame_base) + .uleb128 0x18 # (DW_FORM_exprloc) + .uleb128 0x2116 # (DW_AT_GNU_all_tail_call_sites) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x1 # (DW_AT_sibling) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0 + .byte 0 + .uleb128 0x3 # (abbrev code) + .uleb128 0x5 # (TAG: DW_TAG_formal_parameter) + .byte 0 # DW_children_no + .uleb128 0x3 # (DW_AT_name) + .uleb128 0x8 # (DW_FORM_string) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .uleb128 0x2 # (DW_AT_location) + .uleb128 0x18 # (DW_FORM_exprloc) + .byte 0 + .byte 0 + .uleb128 0x4 # (abbrev code) + .uleb128 0xf # (TAG: DW_TAG_pointer_type) + .byte 0 # DW_children_no + .uleb128 0xb # (DW_AT_byte_size) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0 + .byte 0 + .uleb128 0x5 # (abbrev code) + .uleb128 0x24 # (TAG: DW_TAG_base_type) + .byte 0 # DW_children_no + .uleb128 0xb # (DW_AT_byte_size) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3e # (DW_AT_encoding) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .byte 0 + .byte 0 + .uleb128 0x6 # (abbrev code) + .uleb128 0x26 # (TAG: DW_TAG_const_type) + .byte 0 # DW_children_no + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0 + .byte 0 + .uleb128 0x7 # (abbrev code) + .uleb128 0x2e # (TAG: DW_TAG_subprogram) + .byte 0x1 # DW_children_yes + .uleb128 0x3f # (DW_AT_external) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0x8 # (DW_FORM_string) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x27 # (DW_AT_prototyped) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x11 # (DW_AT_low_pc) + .uleb128 0x1 # (DW_FORM_addr) + .uleb128 0x12 # (DW_AT_high_pc) + .uleb128 0x7 # (DW_FORM_data8) + .uleb128 0x40 # (DW_AT_frame_base) + .uleb128 0x18 # (DW_FORM_exprloc) + .uleb128 0x2117 # (DW_AT_GNU_all_call_sites) + .uleb128 0x19 # (DW_FORM_flag_present) + .byte 0 + .byte 0 + .byte 0 + .section .debug_aranges,"",@progbits + .long 0x2c # Length of Address Ranges Info + .value 0x2 # DWARF Version + .long .Ldebug_info0 # Offset of Compilation Unit Info + .byte 0x8 # Size of Address + .byte 0 # Size of Segment Descriptor + .value 0 # Pad to 16 byte boundary + .value 0 + .quad .Ltext0 # Address + .quad .Letext0-.Ltext0 # Length + .quad 0 + .quad 0 + .section .debug_line,"",@progbits +.Ldebug_line0: + .section .debug_str,"MS",@progbits,1 +.LASF0: + .string "GNU C11 4.4.7 -mtune=3Dgeneric -march=3Dx86-64 -g -fno-stack-pro= tector" +.LASF1: + .string "/home/vries/gdb_versions/devel/src/gdb/testsuite/gdb.base/unwind= -on-each-insn-foo.c" +.LASF2: + .string "/home/vries/gdb_versions/devel/build/gdb/testsuite" +.LASF3: + .string "char" + .ident "GCC: (SUSE Linux) 7.5.0" + .section .note.GNU-stack,"",@progbits diff --git a/gdb/testsuite/gdb.base/unwind-on-each-insn-i386.exp b/gdb/test= suite/gdb.base/unwind-on-each-insn-i386.exp new file mode 100644 index 00000000000..d4d57eb57a9 --- /dev/null +++ b/gdb/testsuite/gdb.base/unwind-on-each-insn-i386.exp @@ -0,0 +1,41 @@ +# Copyright 2023 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 . */ + +# Check that epilogue unwind info is not used for gcc < 4.5.0, i386 case. + +require is_x86_like_target + +set srcfile_flags {} +set srcfile2_flags {} +set srcfile_debug 1 +set srcfile2_debug 1 + +if [info exists COMPILE] { + standard_testfile unwind-on-each-insn.c unwind-on-each-insn-foo.c + # When updating the .s file, use these flags to generate the file: + #lappend srcfile2_flags additional_flags=3D-save-temps + #lappend srcfile2_flags additional_flags=3D-dA + # and do the following: + # - copy it in place, run the test-case and verify that all tests pass. + # - break the epilogue unwind info by commenting out the cfi directive + # before ret, and verify that some tests start failing. + # - change the producer strings to 4.4.7 (for completeness, do this al= so + # in the comments generated by -dA), and verify that all tests pass + # again. +} else { + standard_testfile unwind-on-each-insn.c .s +} + +source $srcdir/$subdir/unwind-on-each-insn.exp.tcl diff --git a/gdb/testsuite/gdb.base/unwind-on-each-insn-i386.s b/gdb/testsu= ite/gdb.base/unwind-on-each-insn-i386.s new file mode 100644 index 00000000000..d0f96bef252 --- /dev/null +++ b/gdb/testsuite/gdb.base/unwind-on-each-insn-i386.s @@ -0,0 +1,262 @@ + .file "unwind-on-each-insn-foo.c" + .text +.Ltext0: + .globl foo + .type foo, @function +foo: +.LFB0: + .file 1 "/home/vries/gdb_versions/devel/src/gdb/testsuite/gdb.base/unwind= -on-each-insn-foo.c" + # /home/vries/gdb_versions/devel/src/gdb/testsuite/gdb.base/unwind-on-eac= h-insn-foo.c:20 + .loc 1 20 0 + .cfi_startproc +# BLOCK 2 seq:0 +# PRED: ENTRY (FALLTHRU) + pushl %ebp + .cfi_def_cfa_offset 8 + .cfi_offset 5, -8 + movl %esp, %ebp + .cfi_def_cfa_register 5 + # /home/vries/gdb_versions/devel/src/gdb/testsuite/gdb.base/unwind-on-eac= h-insn-foo.c:22 + .loc 1 22 0 + nop + popl %ebp + .cfi_restore 5 +# .cfi_def_cfa 4, 4 +# SUCC: EXIT [100.0%]=20 + ret + .cfi_endproc +.LFE0: + .size foo, .-foo + .globl bar + .type bar, @function +bar: +.LFB1: + # /home/vries/gdb_versions/devel/src/gdb/testsuite/gdb.base/unwind-on-eac= h-insn-foo.c:26 + .loc 1 26 0 + .cfi_startproc +# BLOCK 2 seq:0 +# PRED: ENTRY (FALLTHRU) + pushl %ebp + .cfi_def_cfa_offset 8 + .cfi_offset 5, -8 + movl %esp, %ebp + .cfi_def_cfa_register 5 + # /home/vries/gdb_versions/devel/src/gdb/testsuite/gdb.base/unwind-on-eac= h-insn-foo.c:27 + .loc 1 27 0 + pushl 8(%ebp) + call foo + addl $4, %esp + # /home/vries/gdb_versions/devel/src/gdb/testsuite/gdb.base/unwind-on-eac= h-insn-foo.c:28 + .loc 1 28 0 + nop + leave + .cfi_restore 5 +# .cfi_def_cfa 4, 4 +# SUCC: EXIT [100.0%]=20 + ret + .cfi_endproc +.LFE1: + .size bar, .-bar +.Letext0: + .section .debug_info,"",@progbits +.Ldebug_info0: + .long 0x74 # Length of Compilation Unit Info + .value 0x4 # DWARF version number + .long .Ldebug_abbrev0 # Offset Into Abbrev. Section + .byte 0x4 # Pointer Size (in bytes) + .uleb128 0x1 # (DIE (0xb) DW_TAG_compile_unit) + .long .LASF0 # DW_AT_producer: "GNU C11 4.4.7 -m32 -mtune=3Dgeneric -marc= h=3Dx86-64 -g -fno-stack-protector" + .byte 0xc # DW_AT_language + .long .LASF1 # DW_AT_name: "/home/vries/gdb_versions/devel/src/gdb/testsu= ite/gdb.base/unwind-on-each-insn-foo.c" + .long .LASF2 # DW_AT_comp_dir: "/home/vries/gdb_versions/devel/build/gdb/= testsuite" + .long .Ltext0 # DW_AT_low_pc + .long .Letext0-.Ltext0 # DW_AT_high_pc + .long .Ldebug_line0 # DW_AT_stmt_list + .uleb128 0x2 # (DIE (0x25) DW_TAG_subprogram) + # DW_AT_external + .ascii "bar\0" # DW_AT_name + .byte 0x1 # DW_AT_decl_file (/home/vries/gdb_versions/devel/src/gdb/tests= uite/gdb.base/unwind-on-each-insn-foo.c) + .byte 0x19 # DW_AT_decl_line + # DW_AT_prototyped + .long .LFB1 # DW_AT_low_pc + .long .LFE1-.LFB1 # DW_AT_high_pc + .uleb128 0x1 # DW_AT_frame_base + .byte 0x9c # DW_OP_call_frame_cfa + # DW_AT_GNU_all_tail_call_sites + .long 0x47 # DW_AT_sibling + .uleb128 0x3 # (DIE (0x3a) DW_TAG_formal_parameter) + .ascii "s\0" # DW_AT_name + .byte 0x1 # DW_AT_decl_file (/home/vries/gdb_versions/devel/src/gdb/tests= uite/gdb.base/unwind-on-each-insn-foo.c) + .byte 0x19 # DW_AT_decl_line + .long 0x47 # DW_AT_type + .uleb128 0x2 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 0 + .byte 0 # end of children of DIE 0x25 + .uleb128 0x4 # (DIE (0x47) DW_TAG_pointer_type) + .byte 0x4 # DW_AT_byte_size + .long 0x54 # DW_AT_type + .uleb128 0x5 # (DIE (0x4d) DW_TAG_base_type) + .byte 0x1 # DW_AT_byte_size + .byte 0x6 # DW_AT_encoding + .long .LASF3 # DW_AT_name: "char" + .uleb128 0x6 # (DIE (0x54) DW_TAG_const_type) + .long 0x4d # DW_AT_type + .uleb128 0x7 # (DIE (0x59) DW_TAG_subprogram) + # DW_AT_external + .ascii "foo\0" # DW_AT_name + .byte 0x1 # DW_AT_decl_file (/home/vries/gdb_versions/devel/src/gdb/tests= uite/gdb.base/unwind-on-each-insn-foo.c) + .byte 0x13 # DW_AT_decl_line + # DW_AT_prototyped + .long .LFB0 # DW_AT_low_pc + .long .LFE0-.LFB0 # DW_AT_high_pc + .uleb128 0x1 # DW_AT_frame_base + .byte 0x9c # DW_OP_call_frame_cfa + # DW_AT_GNU_all_call_sites + .uleb128 0x3 # (DIE (0x6a) DW_TAG_formal_parameter) + .ascii "s\0" # DW_AT_name + .byte 0x1 # DW_AT_decl_file (/home/vries/gdb_versions/devel/src/gdb/tests= uite/gdb.base/unwind-on-each-insn-foo.c) + .byte 0x13 # DW_AT_decl_line + .long 0x47 # DW_AT_type + .uleb128 0x2 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 0 + .byte 0 # end of children of DIE 0x59 + .byte 0 # end of children of DIE 0xb + .section .debug_abbrev,"",@progbits +.Ldebug_abbrev0: + .uleb128 0x1 # (abbrev code) + .uleb128 0x11 # (TAG: DW_TAG_compile_unit) + .byte 0x1 # DW_children_yes + .uleb128 0x25 # (DW_AT_producer) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x13 # (DW_AT_language) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x1b # (DW_AT_comp_dir) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x11 # (DW_AT_low_pc) + .uleb128 0x1 # (DW_FORM_addr) + .uleb128 0x12 # (DW_AT_high_pc) + .uleb128 0x6 # (DW_FORM_data4) + .uleb128 0x10 # (DW_AT_stmt_list) + .uleb128 0x17 # (DW_FORM_sec_offset) + .byte 0 + .byte 0 + .uleb128 0x2 # (abbrev code) + .uleb128 0x2e # (TAG: DW_TAG_subprogram) + .byte 0x1 # DW_children_yes + .uleb128 0x3f # (DW_AT_external) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0x8 # (DW_FORM_string) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x27 # (DW_AT_prototyped) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x11 # (DW_AT_low_pc) + .uleb128 0x1 # (DW_FORM_addr) + .uleb128 0x12 # (DW_AT_high_pc) + .uleb128 0x6 # (DW_FORM_data4) + .uleb128 0x40 # (DW_AT_frame_base) + .uleb128 0x18 # (DW_FORM_exprloc) + .uleb128 0x2116 # (DW_AT_GNU_all_tail_call_sites) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x1 # (DW_AT_sibling) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0 + .byte 0 + .uleb128 0x3 # (abbrev code) + .uleb128 0x5 # (TAG: DW_TAG_formal_parameter) + .byte 0 # DW_children_no + .uleb128 0x3 # (DW_AT_name) + .uleb128 0x8 # (DW_FORM_string) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .uleb128 0x2 # (DW_AT_location) + .uleb128 0x18 # (DW_FORM_exprloc) + .byte 0 + .byte 0 + .uleb128 0x4 # (abbrev code) + .uleb128 0xf # (TAG: DW_TAG_pointer_type) + .byte 0 # DW_children_no + .uleb128 0xb # (DW_AT_byte_size) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0 + .byte 0 + .uleb128 0x5 # (abbrev code) + .uleb128 0x24 # (TAG: DW_TAG_base_type) + .byte 0 # DW_children_no + .uleb128 0xb # (DW_AT_byte_size) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3e # (DW_AT_encoding) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .byte 0 + .byte 0 + .uleb128 0x6 # (abbrev code) + .uleb128 0x26 # (TAG: DW_TAG_const_type) + .byte 0 # DW_children_no + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0 + .byte 0 + .uleb128 0x7 # (abbrev code) + .uleb128 0x2e # (TAG: DW_TAG_subprogram) + .byte 0x1 # DW_children_yes + .uleb128 0x3f # (DW_AT_external) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0x8 # (DW_FORM_string) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x27 # (DW_AT_prototyped) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x11 # (DW_AT_low_pc) + .uleb128 0x1 # (DW_FORM_addr) + .uleb128 0x12 # (DW_AT_high_pc) + .uleb128 0x6 # (DW_FORM_data4) + .uleb128 0x40 # (DW_AT_frame_base) + .uleb128 0x18 # (DW_FORM_exprloc) + .uleb128 0x2117 # (DW_AT_GNU_all_call_sites) + .uleb128 0x19 # (DW_FORM_flag_present) + .byte 0 + .byte 0 + .byte 0 + .section .debug_aranges,"",@progbits + .long 0x1c # Length of Address Ranges Info + .value 0x2 # DWARF Version + .long .Ldebug_info0 # Offset of Compilation Unit Info + .byte 0x4 # Size of Address + .byte 0 # Size of Segment Descriptor + .value 0 # Pad to 8 byte boundary + .value 0 + .long .Ltext0 # Address + .long .Letext0-.Ltext0 # Length + .long 0 + .long 0 + .section .debug_line,"",@progbits +.Ldebug_line0: + .section .debug_str,"MS",@progbits,1 +.LASF0: + .string "GNU C11 4.4.7 -m32 -mtune=3Dgeneric -march=3Dx86-64 -g -fno-stac= k-protector" +.LASF2: + .string "/home/vries/gdb_versions/devel/build/gdb/testsuite" +.LASF1: + .string "/home/vries/gdb_versions/devel/src/gdb/testsuite/gdb.base/unwind= -on-each-insn-foo.c" +.LASF3: + .string "char" + .ident "GCC: (SUSE Linux) 7.5.0" + .section .note.GNU-stack,"",@progbits diff --git a/gdb/testsuite/gdb.base/unwind-on-each-insn.exp b/gdb/testsuite= /gdb.base/unwind-on-each-insn.exp index 0d0683659c3..e86565a03f6 100644 --- a/gdb/testsuite/gdb.base/unwind-on-each-insn.exp +++ b/gdb/testsuite/gdb.base/unwind-on-each-insn.exp @@ -13,159 +13,11 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . */ =20 -# Single step through a simple (empty) function that was compiled -# without DWARF debug information. -# -# At each instruction check that the frame-id, and frame base address, -# are calculated correctly. -# -# Additionally, check we can correctly unwind to the previous frame, -# and that the previous stack-pointer value, and frame base address -# value, can be calculated correctly. - standard_testfile .c -foo.c =20 -set debug_flags {debug} -set nodebug_flags {nodebug} - -# Make sure that we don't use .eh_frame info, by not generating it, -# using -fno-asynchronous-unwind-tables, if supported. -if { [gdb_can_simple_compile fno-asynchronous-unwind-tables \ - { void foo () { } } object -fno-asynchronous-unwind-tables] } { - lappend nodebug_flags additional_flags=3D-fno-asynchronous-unwind-tabl= es -} - -if {[prepare_for_testing_full "failed to prepare" \ - [list ${testfile} $debug_flags \ - $srcfile $debug_flags $srcfile2 $nodebug_flags]]} { - return -1 -} - -if {![runto_main]} { - return 0 -} - -# Return a two element list, the first element is the stack-pointer -# value (from the $sp register), and the second element is the frame -# base address (from the 'info frame' output). -proc get_sp_and_fba { testname } { - with_test_prefix "get \$sp and frame base $testname" { - set sp [get_hexadecimal_valueof "\$sp" "*UNKNOWN*"] - - set fba "" - gdb_test_multiple "info frame" "" { - -re -wrap ".*Stack level ${::decimal}, frame at ($::hex):.*" { - set fba $expect_out(1,string) - } - } - - return [list $sp $fba] - } -} - -# Return the frame-id of the current frame, collected using the 'maint -# print frame-id' command. -proc get_fid { } { - set fid "" - gdb_test_multiple "maint print frame-id" "" { - -re -wrap ".*frame-id for frame #${::decimal}: (.*)" { - set fid $expect_out(1,string) - } - } - return $fid -} - -# Record the current stack-pointer, and the frame base address. -lassign [get_sp_and_fba "in main"] main_sp main_fba -set main_fid [get_fid] - -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 tri= gger - # 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 =3D=3D $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 =3D=3D 1 } { - # The stack-pointer may have changed while running to *$function. - set ::main_sp $sp_value - } else { - gdb_assert { $sp_value =3D=3D $::main_sp } - } - gdb_assert { $fba_value =3D=3D $::main_fba } - - # 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" ".*" - - 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 - } - - gdb_test $step_cmd - - set in_fn 0 - gdb_test_multiple "info frame" "" { - -re -wrap " =3D $::hex in ${function}( \\(.*\\))?;.*" { - set in_fn 1 - } - -re -wrap "" {} - } - - if { ! $in_fn } { - break - } - } - } -} +set srcfile_flags {} +set srcfile2_flags {} +set srcfile_debug 1 +set srcfile2_debug 0 =20 -foreach { - function step_cmd -} { - foo stepi - bar nexti -} { - with_test_prefix $function { - do_test $function $step_cmd - } -} +source $srcdir/$subdir/unwind-on-each-insn.exp.tcl diff --git a/gdb/testsuite/gdb.base/unwind-on-each-insn.exp.tcl b/gdb/tests= uite/gdb.base/unwind-on-each-insn.exp.tcl new file mode 100644 index 00000000000..45ed91a3986 --- /dev/null +++ b/gdb/testsuite/gdb.base/unwind-on-each-insn.exp.tcl @@ -0,0 +1,180 @@ +# Copyright 2022-2023 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 . */ + +# Single step through a simple (empty) function that was compiled +# without DWARF debug information. +# +# At each instruction check that the frame-id, and frame base address, +# are calculated correctly. +# +# Additionally, check we can correctly unwind to the previous frame, +# and that the previous stack-pointer value, and frame base address +# value, can be calculated correctly. + +set debug_flags {debug} +set nodebug_flags {nodebug} + +# Make sure that we don't use .eh_frame info, by not generating it, +# using -fno-asynchronous-unwind-tables, if supported. +if { [gdb_can_simple_compile fno-asynchronous-unwind-tables \ + { void foo () { } } object -fno-asynchronous-unwind-tables] } { + lappend nodebug_flags additional_flags=3D-fno-asynchronous-unwind-tabl= es +} + +if { $srcfile_debug } { + lappend srcfile_flags $debug_flags +} else { + lappend srcfile_flags $nodebug_flags +} +if { $srcfile2_debug } { + lappend srcfile2_flags $debug_flags +} else { + lappend srcfile2_flags $nodebug_flags +} + +if {[prepare_for_testing_full "failed to prepare" \ + [list ${testfile} $debug_flags \ + $srcfile $srcfile_flags $srcfile2 $srcfile2_flags]]} { + return -1 +} + +if {![runto_main]} { + return 0 +} + +# Return a two element list, the first element is the stack-pointer +# value (from the $sp register), and the second element is the frame +# base address (from the 'info frame' output). +proc get_sp_and_fba { testname } { + with_test_prefix "get \$sp and frame base $testname" { + set sp [get_hexadecimal_valueof "\$sp" "*UNKNOWN*"] + + set fba "" + gdb_test_multiple "info frame" "" { + -re -wrap ".*Stack level ${::decimal}, frame at ($::hex):.*" { + set fba $expect_out(1,string) + } + } + + return [list $sp $fba] + } +} + +# Return the frame-id of the current frame, collected using the 'maint +# print frame-id' command. +proc get_fid { } { + set fid "" + gdb_test_multiple "maint print frame-id" "" { + -re -wrap ".*frame-id for frame #${::decimal}: (.*)" { + set fid $expect_out(1,string) + } + } + return $fid +} + +# Record the current stack-pointer, and the frame base address. +lassign [get_sp_and_fba "in main"] main_sp main_fba +set main_fid [get_fid] + +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 tri= gger + # 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 =3D=3D $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 =3D=3D 1 } { + # The stack-pointer may have changed while running to *$function. + set ::main_sp $sp_value + } else { + gdb_assert { $sp_value =3D=3D $::main_sp } + } + gdb_assert { $fba_value =3D=3D $::main_fba } + + # 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" ".*" + + 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 + } + + gdb_test $step_cmd + + set in_fn 0 + gdb_test_multiple "info frame" "" { + -re -wrap " =3D $::hex in ${function}( \\(.*\\))?;.*" { + set in_fn 1 + } + -re -wrap "" {} + } + + if { ! $in_fn } { + break + } + } + } +} + +foreach { + function step_cmd +} { + foo stepi + bar nexti +} { + with_test_prefix $function { + do_test $function $step_cmd + } +}