gdb/aarch64: Step through GNU ld's erratum 843419 veneers
Checks
| Context |
Check |
Description |
| linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_gdb_build--master-arm |
success
|
Build passed
|
Commit Message
GNU ld's Cortex-A53 erratum 843419 workaround can move an instruction
into an e843419@ veneer. A plain branch replaces the original
instruction; the veneer executes it and branches back to the next
instruction in the same function. Neither branch updates the link
register.
When next or finish from an inline frame enters the veneer, GDB can
mistake it for a function call. With no veneer unwind information, GDB
can use an earlier call's return address from the link register for a
step-resume breakpoint, running the inferior to completion instead of
stopping after the inline function.
Recognize GNU ld's named e843419@ veneers through the existing
in_indirect_branch_thunk hook, before subroutine-entry handling.
Recognize both veneer instructions; minimal-symbol lookup already
checks the bounds of GNU ld's sized symbols. Stripped veneer symbols
remain unsupported.
skip_trampoline_code is too late on the forward STEP_OVER_ALL path:
GDB has already set the caller-return breakpoint and returned. The
existing hook needs no generic stepping changes or instruction decoding.
The assembly and DWARF regression test exercises next and inline finish
using explicitly defined veneer instructions and symbols. It reproduces the
GDB stepping bug without a Cortex-A53 CPU or the hardware erratum,
independent of compiler optimization and linker sequence detection.
A call to helper leaves a stale link register before entering the
veneer, which has no debug or unwind information. The assertions check
the initial inline backtrace, returned source line, and exact stop
address.
To reproduce on a native AArch64 ELF target:
1. Build GDB at the base commit below and retain its executable and
data-directory. Apply this patch and build the patched GDB.
2. From the patched build's gdb/testsuite directory, run the same test
with each GDB. Use absolute executable and data-directory paths:
make check \
RUNTESTFLAGS="GDB=/path/to/gdb \
GDBFLAGS=--data-directory=/path/to/data-directory \
gdb.arch/aarch64-erratum-843419-veneer.exp"
Save gdb.sum and gdb.log after each run; the next run overwrites them.
Recorded next sessions (patched source path shortened):
Before:
(gdb) next
[Inferior 1 (process 46367) exited normally]
(gdb) p $pc == (void *) &inline_high
No registers.
After:
(gdb) next
outer () at .../aarch64-erratum-843419-veneer.S:58
58 /* Outer after inline. */
(gdb) p $pc == (void *) &inline_high
$1 = 1
finish likewise changes from normal inferior exit to stopping at
inline_high in outer. The new test changes from 4 PASS and 4 FAIL to
8 PASS and no FAIL.
Tested on native aarch64-unknown-linux-gnu in an Ubuntu 26.04 container,
with GCC 15.2.0, GNU ld 2.46, and GDB 19.0.50.20260929-git.
Base commit: 4ba6bd8393418b63dc3efa0ec6f934903a10f140.
These eight existing test files stayed at 241 PASS and no FAIL in both
runs:
gdb.arch/aarch64-prologue.exp
gdb.arch/aarch64-unwind-pc.exp
gdb.opt/inline-cmds.exp
gdb.opt/inline-bt.exp
gdb.dwarf2/dw2-inline-stepping.exp
gdb.base/finish.exp
gdb.base/step-over-no-symbols.exp
gdb.base/step-line.exp
A rerun after comment-only cleanup also gave 8 PASS and no FAIL.
The full GDB testsuite and other targets were not tested.
CPython issue #157965 reports layout-sensitive failures in
test_bt_unwinds_from_inside_jit_executor on AArch64 release builds.
Later main builds did not consistently reproduce them, so the standalone
fixture is the regression test.
A separate check used a preserved CPython binary with a GNU ld-generated
e843419@ veneer and PYTHON_JIT=0. Before the fix, finish ran the inferior
to exit and bt reported "No stack." With the fix, it stopped in
mro_invoke with a valid backtrace. This used an existing binary; current
CPython main was not rebuilt and the issue's JIT test was not rerun.
Related report: https://github.com/python/cpython/issues/157965
---
This is my first contribution to GDB. I have not completed an FSF
copyright assignment. Could you please point me to the appropriate form?
gdb/aarch64-tdep.c | 16 +++
.../gdb.arch/aarch64-erratum-843419-veneer.S | 84 +++++++++++++
.../aarch64-erratum-843419-veneer.exp | 111 ++++++++++++++++++
3 files changed, 211 insertions(+)
create mode 100644 gdb/testsuite/gdb.arch/aarch64-erratum-843419-veneer.S
create mode 100644 gdb/testsuite/gdb.arch/aarch64-erratum-843419-veneer.exp
base-commit: 4ba6bd8393418b63dc3efa0ec6f934903a10f140
Comments
Hi,
Thanks for the patch. Before I review it, do you have a copyright
assignment on file to be able to contribute this change?
Otherwise we might not be able to accept it, as we currently don´t
accept DCO-style contributions.
On 30/09/2026 06:49, cocolato wrote:
> GNU ld's Cortex-A53 erratum 843419 workaround can move an instruction
> into an e843419@ veneer. A plain branch replaces the original
> instruction; the veneer executes it and branches back to the next
> instruction in the same function. Neither branch updates the link
> register.
>
> When next or finish from an inline frame enters the veneer, GDB can
> mistake it for a function call. With no veneer unwind information, GDB
> can use an earlier call's return address from the link register for a
> step-resume breakpoint, running the inferior to completion instead of
> stopping after the inline function.
>
> Recognize GNU ld's named e843419@ veneers through the existing
> in_indirect_branch_thunk hook, before subroutine-entry handling.
> Recognize both veneer instructions; minimal-symbol lookup already
> checks the bounds of GNU ld's sized symbols. Stripped veneer symbols
> remain unsupported.
>
> skip_trampoline_code is too late on the forward STEP_OVER_ALL path:
> GDB has already set the caller-return breakpoint and returned. The
> existing hook needs no generic stepping changes or instruction decoding.
>
> The assembly and DWARF regression test exercises next and inline finish
> using explicitly defined veneer instructions and symbols. It reproduces the
> GDB stepping bug without a Cortex-A53 CPU or the hardware erratum,
> independent of compiler optimization and linker sequence detection.
> A call to helper leaves a stale link register before entering the
> veneer, which has no debug or unwind information. The assertions check
> the initial inline backtrace, returned source line, and exact stop
> address.
>
> To reproduce on a native AArch64 ELF target:
>
> 1. Build GDB at the base commit below and retain its executable and
> data-directory. Apply this patch and build the patched GDB.
> 2. From the patched build's gdb/testsuite directory, run the same test
> with each GDB. Use absolute executable and data-directory paths:
>
> make check \
> RUNTESTFLAGS="GDB=/path/to/gdb \
> GDBFLAGS=--data-directory=/path/to/data-directory \
> gdb.arch/aarch64-erratum-843419-veneer.exp"
>
> Save gdb.sum and gdb.log after each run; the next run overwrites them.
>
> Recorded next sessions (patched source path shortened):
>
> Before:
> (gdb) next
> [Inferior 1 (process 46367) exited normally]
> (gdb) p $pc == (void *) &inline_high
> No registers.
>
> After:
> (gdb) next
> outer () at .../aarch64-erratum-843419-veneer.S:58
> 58 /* Outer after inline. */
> (gdb) p $pc == (void *) &inline_high
> $1 = 1
>
> finish likewise changes from normal inferior exit to stopping at
> inline_high in outer. The new test changes from 4 PASS and 4 FAIL to
> 8 PASS and no FAIL.
>
> Tested on native aarch64-unknown-linux-gnu in an Ubuntu 26.04 container,
> with GCC 15.2.0, GNU ld 2.46, and GDB 19.0.50.20260929-git.
> Base commit: 4ba6bd8393418b63dc3efa0ec6f934903a10f140.
> These eight existing test files stayed at 241 PASS and no FAIL in both
> runs:
>
> gdb.arch/aarch64-prologue.exp
> gdb.arch/aarch64-unwind-pc.exp
> gdb.opt/inline-cmds.exp
> gdb.opt/inline-bt.exp
> gdb.dwarf2/dw2-inline-stepping.exp
> gdb.base/finish.exp
> gdb.base/step-over-no-symbols.exp
> gdb.base/step-line.exp
>
> A rerun after comment-only cleanup also gave 8 PASS and no FAIL.
> The full GDB testsuite and other targets were not tested.
>
> CPython issue #157965 reports layout-sensitive failures in
> test_bt_unwinds_from_inside_jit_executor on AArch64 release builds.
> Later main builds did not consistently reproduce them, so the standalone
> fixture is the regression test.
>
> A separate check used a preserved CPython binary with a GNU ld-generated
> e843419@ veneer and PYTHON_JIT=0. Before the fix, finish ran the inferior
> to exit and bt reported "No stack." With the fix, it stopped in
> mro_invoke with a valid backtrace. This used an existing binary; current
> CPython main was not rebuilt and the issue's JIT test was not rerun.
>
> Related report: https://github.com/python/cpython/issues/157965
> ---
> This is my first contribution to GDB. I have not completed an FSF
> copyright assignment. Could you please point me to the appropriate form?
>
> gdb/aarch64-tdep.c | 16 +++
> .../gdb.arch/aarch64-erratum-843419-veneer.S | 84 +++++++++++++
> .../aarch64-erratum-843419-veneer.exp | 111 ++++++++++++++++++
> 3 files changed, 211 insertions(+)
> create mode 100644 gdb/testsuite/gdb.arch/aarch64-erratum-843419-veneer.S
> create mode 100644 gdb/testsuite/gdb.arch/aarch64-erratum-843419-veneer.exp
>
> diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
> index 950ad4f6..9e1b5612 100644
> --- a/gdb/aarch64-tdep.c
> +++ b/gdb/aarch64-tdep.c
> @@ -34,6 +34,7 @@
> #include "frame-base.h"
> #include "trad-frame.h"
> #include "objfiles.h"
> +#include "symtab.h"
> #include "dwarf2.h"
> #include "dwarf2/frame.h"
> #include "gdbtypes.h"
> @@ -4158,6 +4159,19 @@ aarch64_cannot_store_register (struct gdbarch *gdbarch, int regnum)
> && regnum < tdep->pauth_reg_base + tdep->pauth_reg_count);
> }
>
> +/* Implement the in_indirect_branch_thunk gdbarch method. GNU ld's
> + Cortex-A53 erratum 843419 veneers branch back into the same function,
> + so step through them rather than treating them as function calls. */
> +
> +static bool
> +aarch64_in_indirect_branch_thunk (gdbarch *, CORE_ADDR pc)
> +{
> + bound_minimal_symbol minsym = lookup_minimal_symbol_by_pc (pc);
> +
> + return (minsym.minsym != nullptr
> + && startswith (minsym.minsym->linkage_name (), "e843419@"));
> +}
> +
> /* Implement the stack_frame_destroyed_p gdbarch method. */
>
> static bool
> @@ -4788,6 +4802,8 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
> aarch64_breakpoint::bp_from_kind);
> set_gdbarch_have_nonsteppable_watchpoint (gdbarch, true);
> set_gdbarch_get_next_pcs (gdbarch, aarch64_software_single_step);
> + set_gdbarch_in_indirect_branch_thunk (gdbarch,
> + aarch64_in_indirect_branch_thunk);
>
> /* Information about registers, etc. */
> set_gdbarch_sp_regnum (gdbarch, AARCH64_SP_REGNUM);
> diff --git a/gdb/testsuite/gdb.arch/aarch64-erratum-843419-veneer.S b/gdb/testsuite/gdb.arch/aarch64-erratum-843419-veneer.S
> new file mode 100644
> index 00000000..e14a0d14
> --- /dev/null
> +++ b/gdb/testsuite/gdb.arch/aarch64-erratum-843419-veneer.S
> @@ -0,0 +1,84 @@
> +/* Copyright 2026 Free Software Foundation, Inc.
> +
> + This file is part of GDB.
> +
> + 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/>. */
> +
> +/* Calling helper leaves a stale link register. The veneer has no debug
> + or unwind information. */
> + .text
> + .global main
> + .type main, %function
> +main:
> + .cfi_startproc
> + stp x29, x30, [sp, -16]!
> + .cfi_def_cfa_offset 16
> + .cfi_offset x29, -16
> + .cfi_offset x30, -8
> + mov x29, sp
> + bl outer
> + mov w0, 0
> + ldp x29, x30, [sp], 16
> + .cfi_def_cfa_offset 0
> + .cfi_restore x29
> + .cfi_restore x30
> + ret
> + .cfi_endproc
> + .size main, .-main
> +
> + .global outer
> + .type outer, %function
> +outer:
> + .cfi_startproc
> + stp x29, x30, [sp, -16]!
> + .cfi_def_cfa_offset 16
> + .cfi_offset x29, -16
> + .cfi_offset x30, -8
> + mov x29, sp
> + mov x0, sp
> +
> + /* Outer call line. */
> + /* Inline body line. */
> + .global inline_low
> +inline_low:
> + bl helper
> + b .Lveneer
> +
> + /* Outer after inline. */
> + .global inline_high
> +inline_high:
> + ldp x29, x30, [sp], 16
> + .cfi_def_cfa_offset 0
> + .cfi_restore x29
> + .cfi_restore x30
> + ret
> + .cfi_endproc
> + .global outer_end
> +outer_end:
> + .size outer, .-outer
> +
> +helper:
> + ret
> +
> + .type "e843419@0000_00000000_0000", %function
> +"e843419@0000_00000000_0000":
> +.Lveneer:
> + ldr x2, [x0]
> + b inline_high
> + .size "e843419@0000_00000000_0000", .-.Lveneer
> +
> + .global program_end
> +program_end:
> +
> + .section .note.GNU-stack,"",%progbits
> diff --git a/gdb/testsuite/gdb.arch/aarch64-erratum-843419-veneer.exp b/gdb/testsuite/gdb.arch/aarch64-erratum-843419-veneer.exp
> new file mode 100644
> index 00000000..67a76052
> --- /dev/null
> +++ b/gdb/testsuite/gdb.arch/aarch64-erratum-843419-veneer.exp
> @@ -0,0 +1,111 @@
> +# Copyright 2026 Free Software Foundation, Inc.
> +
> +# This file is part of GDB.
> +
> +# 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/>.
> +
> +# Test stepping over a Cortex-A53 erratum 843419 veneer in an inline function.
> +# Fixed instructions and debug information avoid dependence on compiler
> +# optimizations or linker layout.
> +
> +load_lib dwarf.exp
> +
> +require is_aarch64_target
> +require is_elf_target
> +require dwarf2_support
> +
> +standard_testfile .S -dw.S
> +
> +set outer_call_line [gdb_get_line_number "Outer call line"]
> +set inline_line [gdb_get_line_number "Inline body line"]
> +set outer_after_line [gdb_get_line_number "Outer after inline"]
> +
> +set dwarf_asm [standard_output_file $srcfile2]
> +Dwarf::assemble $dwarf_asm {
> + global srcdir subdir srcfile
> + global outer_call_line inline_line outer_after_line
> +
> + declare_labels lines_label inline_subprogram
> +
> + cu {} {
> + compile_unit {
> + DW_AT_language @DW_LANG_C
> + DW_AT_name $srcfile
> + DW_AT_stmt_list $lines_label DW_FORM_sec_offset
> + DW_AT_low_pc main addr
> + DW_AT_high_pc program_end addr
> + } {
> + inline_subprogram: subprogram {
> + DW_AT_name inline_func
> + DW_AT_inline 3 data1
> + }
> + subprogram {
> + DW_AT_name outer
> + DW_AT_low_pc outer addr
> + DW_AT_high_pc outer_end addr
> + } {
> + inlined_subroutine {
> + DW_AT_abstract_origin %$inline_subprogram
> + DW_AT_low_pc inline_low addr
> + DW_AT_high_pc inline_high addr
> + DW_AT_call_file 1 data1
> + DW_AT_call_line $outer_call_line data1
> + }
> + }
> + }
> + }
> +
> + lines {version 2} lines_label {
> + include_dir "$srcdir/$subdir"
> + file_name "$srcfile" 1
> +
> + program {
> + DW_LNE_set_address outer
> + line $outer_call_line
> + DW_LNS_copy
> + # Describe the inline call site before the inline function's body.
> + DW_LNE_set_address inline_low
> + line $outer_call_line
> + DW_LNS_copy
> + DW_LNE_set_address inline_low
> + line $inline_line
> + DW_LNS_copy
> + DW_LNE_set_address inline_high
> + line $outer_after_line
> + DW_LNS_copy
> + DW_LNE_set_address outer_end
> + DW_LNE_end_sequence
> + }
> + }
> +}
> +
> +if { [prepare_for_testing "failed to prepare" $testfile \
> + [list $srcfile $dwarf_asm] {nodebug nopie}] } {
> + return
> +}
> +
> +foreach_with_prefix command {next finish} {
> + if { ![runto_main] } {
> + return
> + }
> +
> + gdb_breakpoint "*inline_low"
> + gdb_continue_to_breakpoint "inline function"
> +
> + gdb_test "bt" "#0 inline_func.*#1 outer.*#2 .*main.*" \
> + "backtrace in inline function"
> + gdb_test $command "Outer after inline.*" "step through erratum veneer"
> + gdb_test {p $pc == (void *) &inline_high} " = 1" \
> + "stopped after inline function"
> +}
>
> base-commit: 4ba6bd8393418b63dc3efa0ec6f934903a10f140
Hi,
I don't have an FSF copyright assignment on file yet. This is my first contribution to GNU/GDB. Could you please point me to the appropriate form to start the process?
Thanks,
Hai Zhu
@@ -34,6 +34,7 @@
#include "frame-base.h"
#include "trad-frame.h"
#include "objfiles.h"
+#include "symtab.h"
#include "dwarf2.h"
#include "dwarf2/frame.h"
#include "gdbtypes.h"
@@ -4158,6 +4159,19 @@ aarch64_cannot_store_register (struct gdbarch *gdbarch, int regnum)
&& regnum < tdep->pauth_reg_base + tdep->pauth_reg_count);
}
+/* Implement the in_indirect_branch_thunk gdbarch method. GNU ld's
+ Cortex-A53 erratum 843419 veneers branch back into the same function,
+ so step through them rather than treating them as function calls. */
+
+static bool
+aarch64_in_indirect_branch_thunk (gdbarch *, CORE_ADDR pc)
+{
+ bound_minimal_symbol minsym = lookup_minimal_symbol_by_pc (pc);
+
+ return (minsym.minsym != nullptr
+ && startswith (minsym.minsym->linkage_name (), "e843419@"));
+}
+
/* Implement the stack_frame_destroyed_p gdbarch method. */
static bool
@@ -4788,6 +4802,8 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
aarch64_breakpoint::bp_from_kind);
set_gdbarch_have_nonsteppable_watchpoint (gdbarch, true);
set_gdbarch_get_next_pcs (gdbarch, aarch64_software_single_step);
+ set_gdbarch_in_indirect_branch_thunk (gdbarch,
+ aarch64_in_indirect_branch_thunk);
/* Information about registers, etc. */
set_gdbarch_sp_regnum (gdbarch, AARCH64_SP_REGNUM);
new file mode 100644
@@ -0,0 +1,84 @@
+/* Copyright 2026 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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/>. */
+
+/* Calling helper leaves a stale link register. The veneer has no debug
+ or unwind information. */
+ .text
+ .global main
+ .type main, %function
+main:
+ .cfi_startproc
+ stp x29, x30, [sp, -16]!
+ .cfi_def_cfa_offset 16
+ .cfi_offset x29, -16
+ .cfi_offset x30, -8
+ mov x29, sp
+ bl outer
+ mov w0, 0
+ ldp x29, x30, [sp], 16
+ .cfi_def_cfa_offset 0
+ .cfi_restore x29
+ .cfi_restore x30
+ ret
+ .cfi_endproc
+ .size main, .-main
+
+ .global outer
+ .type outer, %function
+outer:
+ .cfi_startproc
+ stp x29, x30, [sp, -16]!
+ .cfi_def_cfa_offset 16
+ .cfi_offset x29, -16
+ .cfi_offset x30, -8
+ mov x29, sp
+ mov x0, sp
+
+ /* Outer call line. */
+ /* Inline body line. */
+ .global inline_low
+inline_low:
+ bl helper
+ b .Lveneer
+
+ /* Outer after inline. */
+ .global inline_high
+inline_high:
+ ldp x29, x30, [sp], 16
+ .cfi_def_cfa_offset 0
+ .cfi_restore x29
+ .cfi_restore x30
+ ret
+ .cfi_endproc
+ .global outer_end
+outer_end:
+ .size outer, .-outer
+
+helper:
+ ret
+
+ .type "e843419@0000_00000000_0000", %function
+"e843419@0000_00000000_0000":
+.Lveneer:
+ ldr x2, [x0]
+ b inline_high
+ .size "e843419@0000_00000000_0000", .-.Lveneer
+
+ .global program_end
+program_end:
+
+ .section .note.GNU-stack,"",%progbits
new file mode 100644
@@ -0,0 +1,111 @@
+# Copyright 2026 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# 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/>.
+
+# Test stepping over a Cortex-A53 erratum 843419 veneer in an inline function.
+# Fixed instructions and debug information avoid dependence on compiler
+# optimizations or linker layout.
+
+load_lib dwarf.exp
+
+require is_aarch64_target
+require is_elf_target
+require dwarf2_support
+
+standard_testfile .S -dw.S
+
+set outer_call_line [gdb_get_line_number "Outer call line"]
+set inline_line [gdb_get_line_number "Inline body line"]
+set outer_after_line [gdb_get_line_number "Outer after inline"]
+
+set dwarf_asm [standard_output_file $srcfile2]
+Dwarf::assemble $dwarf_asm {
+ global srcdir subdir srcfile
+ global outer_call_line inline_line outer_after_line
+
+ declare_labels lines_label inline_subprogram
+
+ cu {} {
+ compile_unit {
+ DW_AT_language @DW_LANG_C
+ DW_AT_name $srcfile
+ DW_AT_stmt_list $lines_label DW_FORM_sec_offset
+ DW_AT_low_pc main addr
+ DW_AT_high_pc program_end addr
+ } {
+ inline_subprogram: subprogram {
+ DW_AT_name inline_func
+ DW_AT_inline 3 data1
+ }
+ subprogram {
+ DW_AT_name outer
+ DW_AT_low_pc outer addr
+ DW_AT_high_pc outer_end addr
+ } {
+ inlined_subroutine {
+ DW_AT_abstract_origin %$inline_subprogram
+ DW_AT_low_pc inline_low addr
+ DW_AT_high_pc inline_high addr
+ DW_AT_call_file 1 data1
+ DW_AT_call_line $outer_call_line data1
+ }
+ }
+ }
+ }
+
+ lines {version 2} lines_label {
+ include_dir "$srcdir/$subdir"
+ file_name "$srcfile" 1
+
+ program {
+ DW_LNE_set_address outer
+ line $outer_call_line
+ DW_LNS_copy
+ # Describe the inline call site before the inline function's body.
+ DW_LNE_set_address inline_low
+ line $outer_call_line
+ DW_LNS_copy
+ DW_LNE_set_address inline_low
+ line $inline_line
+ DW_LNS_copy
+ DW_LNE_set_address inline_high
+ line $outer_after_line
+ DW_LNS_copy
+ DW_LNE_set_address outer_end
+ DW_LNE_end_sequence
+ }
+ }
+}
+
+if { [prepare_for_testing "failed to prepare" $testfile \
+ [list $srcfile $dwarf_asm] {nodebug nopie}] } {
+ return
+}
+
+foreach_with_prefix command {next finish} {
+ if { ![runto_main] } {
+ return
+ }
+
+ gdb_breakpoint "*inline_low"
+ gdb_continue_to_breakpoint "inline function"
+
+ gdb_test "bt" "#0 inline_func.*#1 outer.*#2 .*main.*" \
+ "backtrace in inline function"
+ gdb_test $command "Outer after inline.*" "step through erratum veneer"
+ gdb_test {p $pc == (void *) &inline_high} " = 1" \
+ "stopped after inline function"
+}