* [PATCH v11 01/10] gdb, dwarf: add support for DW_AT_trampoline in DWARF reader
2026-08-03 19:34 [PATCH v11 00/10] GDB support for DW_AT_trampoline Abdul Basit Ijaz
@ 2026-08-03 19:34 ` Abdul Basit Ijaz
2026-10-21 20:33 ` Tom Tromey
2026-08-03 19:34 ` [PATCH v11 02/10] gdb/symtab: add lookup for trampoline functions Abdul Basit Ijaz
` (9 subsequent siblings)
10 siblings, 1 reply; 32+ messages in thread
From: Abdul Basit Ijaz @ 2026-08-03 19:34 UTC (permalink / raw)
To: gdb-patches
Cc: abdul.b.ijaz, JiniSusan.George, tom, eliz, Nils-Christian Kempke
From: Nils-Christian Kempke <nils-christian.kempke@intel.com>
DW_AT_trampoline can be used to describe compiler generated functions
that serve some intermediary purpose on making a call to another
function. A compiler can emit this tag in order to help a debugger hide
the trampolines from a user.
The attribute is only applicable to DW_TAG_subroutine and
DW_TAG_inlined_subroutine tags. It contains information about the
trampoline target either as a reference to its DIE, as its address or
its name. DW_AT_trampoline can also be a flag indicating that the DIE
is a trampoline or not without specifying the target (e.g. if it is
unknown).
This patch adds support to GDB for reading the DW_AT_trampoline
attribute. It stores the attribute and its value in the type_specific
part of a GDB type. This patch is implemented in preparation of the
following patches, which will add a mechanism to hide DW_AT_trampoline
subroutines from the user.
---
gdb/dwarf2/read.c | 39 +++++++++++++++-
gdb/gdbtypes.c | 34 +++++++++++++-
gdb/gdbtypes.h | 113 ++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 179 insertions(+), 7 deletions(-)
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index ca475f53745..71f4838a402 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -12430,6 +12430,43 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
if (prototyped_function_p (die, cu))
ftype->set_is_prototyped (true);
+ /* If this is a trampoline function store it and its target here. */
+ attr = dwarf2_attr (die, DW_AT_trampoline, cu);
+ if (attr != nullptr)
+ {
+ TYPE_FUNC_FLAGS (ftype) |= FUNC_TYPE_TRAMPOLINE;
+ TYPE_TRAMPOLINE_TARGET (ftype)
+ = (trampoline_target *) TYPE_ZALLOC (ftype,
+ sizeof (trampoline_target));
+
+ /* A DW_AT_trampoline can be either an address, a flag, a reference or a
+ string. */
+ if (attr->form_is_string ())
+ TYPE_TRAMPOLINE_TARGET (ftype)->set_target_name
+ (attr->as_string ());
+ else if (attr->form_is_ref ())
+ {
+ die_info *target_die;
+ dwarf2_cu *target_cu = cu;
+ unrelocated_addr lowpc;
+
+ target_die = follow_die_ref (die, attr, &target_cu);
+
+ if (dwarf2_get_pc_bounds (target_die, &lowpc, NULL, target_cu,
+ nullptr, nullptr) <= PC_BOUNDS_INVALID)
+ complaint (_("DW_AT_trampoline target DIE has invalid "
+ "low pc, for referencing DIE %s[in module %s]"),
+ sect_offset_str (die->sect_off),
+ objfile_name (objfile));
+ else
+ TYPE_TRAMPOLINE_TARGET (ftype)->set_target_addr (lowpc);
+ }
+ else if (attr->form_is_unsigned ())
+ TYPE_TRAMPOLINE_TARGET (ftype)->set_target_flag (attr->as_boolean ());
+ else
+ TYPE_TRAMPOLINE_TARGET (ftype)->set_target_addr (attr->as_address ());
+ }
+
/* Store the calling convention in the type if it's available in
the subroutine die. Otherwise set the calling convention to
the default value DW_CC_normal. */
@@ -12451,7 +12488,7 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
if the DWARF producer set that information. */
attr = dwarf2_attr (die, DW_AT_noreturn, cu);
if (attr && attr->as_boolean ())
- TYPE_NO_RETURN (ftype) = 1;
+ TYPE_FUNC_FLAGS (ftype) |= FUNC_TYPE_NO_RETURN;
/* We need to add the subroutine type to the die immediately so
we don't infinitely recurse when dealing with parameters
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 9098727959e..76af0a911e5 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -4919,6 +4919,33 @@ print_fixed_point_type_info (struct type *type, int spaces)
type->fixed_point_scaling_factor ().str ().c_str ());
}
+/* Print the contents of the TYPE's self_trampoline_target, assuming that its
+ type-specific kind is TYPE_SPECIFIC_FUNC and is_trampoline is not 0. */
+static void
+print_trampoline_target_info (struct type *type, int spaces)
+{
+ switch (TYPE_TRAMPOLINE_TARGET (type)->target_kind ())
+ {
+ case TRAMPOLINE_TARGET_ADDR:
+ gdb_printf ("%*starget addr: 0x%s\n", spaces + 2, "",
+ print_core_address (type->arch_owner (),
+ (CORE_ADDR) TYPE_TRAMPOLINE_TARGET (type)
+ ->target_addr ()));
+ break;
+ case TRAMPOLINE_TARGET_NAME:
+ gdb_printf ("%*starget name: %s\n", spaces + 2, "",
+ TYPE_TRAMPOLINE_TARGET (type)->target_name ());
+ break;
+ case TRAMPOLINE_TARGET_FLAG:
+ gdb_printf ("%*starget flag: %d\n", spaces + 2, "",
+ TYPE_TRAMPOLINE_TARGET (type)->target_flag ());
+ break;
+ default:
+ gdb_assert_not_reached ("unhandled trampoline target kind");
+ break;
+ }
+}
+
static struct obstack dont_print_type_obstack;
/* Print the dynamic_prop PROP. */
@@ -5149,6 +5176,10 @@ recursive_dump_type (struct type *type, int spaces)
gdb_printf ("%*scalling_convention %d\n", spaces, "",
TYPE_CALLING_CONVENTION (type));
/* tail_call_list is not printed. */
+ gdb_printf ("%*sfunc_type_flags 0x%x\n", spaces, "",
+ (unsigned int) TYPE_FUNC_FLAGS (type));
+ if (TYPE_IS_TRAMPOLINE (type))
+ print_trampoline_target_info (type, spaces);
break;
case TYPE_SPECIFIC_SELF_TYPE:
@@ -5320,8 +5351,9 @@ copy_type_recursive (struct type *type, copied_types_hash_t &copied_types)
case TYPE_SPECIFIC_FUNC:
INIT_FUNC_SPECIFIC (new_type);
TYPE_CALLING_CONVENTION (new_type) = TYPE_CALLING_CONVENTION (type);
- TYPE_NO_RETURN (new_type) = TYPE_NO_RETURN (type);
+ TYPE_FUNC_FLAGS (new_type) = TYPE_FUNC_FLAGS (type);
TYPE_TAIL_CALL_LIST (new_type) = NULL;
+ TYPE_TRAMPOLINE_TARGET (new_type) = TYPE_TRAMPOLINE_TARGET (type);
break;
case TYPE_SPECIFIC_FLOATFORMAT:
TYPE_FLOATFORMAT (new_type) = TYPE_FLOATFORMAT (type);
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index eda09641248..c65d71fc761 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -99,6 +99,21 @@ enum harvard_address_space
HARVARD_ASPACE_DATA = 2,
};
+/* * Define flags for function types. */
+enum func_type_flag_value : unsigned
+{
+ /* * Flag indicates, whether this function normally returns to its
+ caller. It is set from the DW_AT_noreturn attribute if set on
+ the DW_TAG_subprogram. */
+ FUNC_TYPE_NO_RETURN = (1 << 0),
+
+ /* * Flag is used for functions marked with DW_AT_trampoline. These
+ are compiler generated wrappers that should be hidden from the user. */
+ FUNC_TYPE_TRAMPOLINE = (1 << 1)
+};
+
+DEF_ENUM_FLAGS_TYPE (enum func_type_flag_value, func_type_flags);
+
/* A type's instance_flags. */
struct type_instance_flags
@@ -1891,11 +1906,9 @@ struct func_type
dwarf_calling_convention calling_convention : 8;
- /* Whether this function normally returns to its caller. It is
- set from the DW_AT_noreturn attribute if set on the
- DW_TAG_subprogram. */
+ /* * For storing function types defined in eunm func_type_flag_value. */
- unsigned int is_noreturn : 1;
+ func_type_flags flags;
/* Only those DW_TAG_call_site's in this function that have
DW_AT_call_tail_call set are linked in this list. Function
@@ -1910,6 +1923,87 @@ struct func_type
contains the method. */
struct type *self_type;
+
+ struct trampoline_target *self_trampoline_target;
+ };
+
+/* The kind of location held by this call site target. */
+enum trampoline_target_kind
+ {
+ /* An address. */
+ TRAMPOLINE_TARGET_ADDR,
+ /* A (mangled) name. */
+ TRAMPOLINE_TARGET_NAME,
+ /* A flag (target is unknown). */
+ TRAMPOLINE_TARGET_FLAG,
+ };
+
+/* Target information for trampoline functions. */
+
+struct trampoline_target
+ {
+ /* Returns what kind of target the trampoline points to. */
+ trampoline_target_kind target_kind () const
+ {
+ return m_target_kind;
+ }
+
+ /* Set the address for trampoline target. */
+ void set_target_addr (unrelocated_addr unreloc_addr)
+ {
+ m_target_kind = TRAMPOLINE_TARGET_ADDR;
+ m_trampoline_target.unreloc_addr = unreloc_addr;
+ }
+
+ /* Return the address of the trampoline target. */
+ unrelocated_addr target_addr () const
+ {
+ gdb_assert (m_target_kind == TRAMPOLINE_TARGET_ADDR);
+ return m_trampoline_target.unreloc_addr;
+ }
+
+ /* Set the name of the trampoline target. */
+ void set_target_name (const char *name)
+ {
+ m_target_kind = TRAMPOLINE_TARGET_NAME;
+ m_trampoline_target.name = name;
+ }
+
+ /* Return the name of the trampoline target. */
+ const char *target_name () const
+ {
+ gdb_assert (m_target_kind == TRAMPOLINE_TARGET_NAME);
+ return m_trampoline_target.name;
+ }
+
+ /* Set the flag for trampoline target subroutine. */
+ void set_target_flag (bool flag)
+ {
+ m_target_kind = TRAMPOLINE_TARGET_FLAG;
+ m_trampoline_target.flag = flag;
+ }
+
+ /* Return the flag for trampoline target. */
+ bool target_flag () const
+ {
+ gdb_assert (m_target_kind == TRAMPOLINE_TARGET_FLAG);
+ return m_trampoline_target.flag;
+ }
+
+ private:
+
+ union
+ {
+ /* Address. */
+ unrelocated_addr unreloc_addr;
+ /* Mangled name. */
+ const char *name;
+ /* Flag. */
+ bool flag;
+ } m_trampoline_target;
+
+ /* * Discriminant for union m_trampoline_target. */
+ ENUM_BITFIELD (trampoline_target_kind) m_target_kind : 2;
};
/* The type-specific info for TYPE_CODE_FIXED_POINT types. */
@@ -2022,7 +2116,16 @@ extern void set_type_vptr_basetype (struct type *, struct type *);
#define TYPE_GNAT_SPECIFIC(thistype) (thistype)->main_type->type_specific.gnat_stuff
#define TYPE_DESCRIPTIVE_TYPE(thistype) TYPE_GNAT_SPECIFIC(thistype)->descriptive_type
#define TYPE_CALLING_CONVENTION(thistype) (thistype)->main_type->type_specific.func_stuff->calling_convention
-#define TYPE_NO_RETURN(thistype) (thistype)->main_type->type_specific.func_stuff->is_noreturn
+#define TYPE_FUNC_FLAGS(thistype) \
+ (thistype)->main_type->type_specific.func_stuff->flags
+#define TYPE_NO_RETURN(thistype) \
+ ((thistype)->main_type->type_specific.func_stuff->flags \
+ & FUNC_TYPE_NO_RETURN)
+#define TYPE_IS_TRAMPOLINE(thistype) \
+ ((thistype)->main_type->type_specific.func_stuff->flags \
+ & FUNC_TYPE_TRAMPOLINE)
+#define TYPE_TRAMPOLINE_TARGET(thistype) \
+ (thistype)->main_type->type_specific.func_stuff->self_trampoline_target
#define TYPE_TAIL_CALL_LIST(thistype) (thistype)->main_type->type_specific.func_stuff->tail_call_list
#define TYPE_BASECLASS(thistype,index) ((thistype)->field (index).type ())
#define TYPE_N_BASECLASSES(thistype) TYPE_CPLUS_SPECIFIC(thistype)->n_baseclasses
--
2.34.1
________________________________________
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 (89) 99143-0
www.intel.de
Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman
Chairperson of the Supervisory Board: Sonja Pierer
Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: [PATCH v11 01/10] gdb, dwarf: add support for DW_AT_trampoline in DWARF reader
2026-08-03 19:34 ` [PATCH v11 01/10] gdb, dwarf: add support for DW_AT_trampoline in DWARF reader Abdul Basit Ijaz
@ 2026-10-21 20:33 ` Tom Tromey
2026-10-22 11:02 ` Ijaz, Abdul B
0 siblings, 1 reply; 32+ messages in thread
From: Tom Tromey @ 2026-10-21 20:33 UTC (permalink / raw)
To: Abdul Basit Ijaz
Cc: gdb-patches, JiniSusan.George, tom, eliz, Nils-Christian Kempke
>>>>> Abdul Basit Ijaz <abdul.b.ijaz@intel.com> writes:
> DW_AT_trampoline can be used to describe compiler generated functions
> that serve some intermediary purpose on making a call to another
> function. A compiler can emit this tag in order to help a debugger hide
> the trampolines from a user.
> This patch adds support to GDB for reading the DW_AT_trampoline
> attribute. It stores the attribute and its value in the type_specific
> part of a GDB type. This patch is implemented in preparation of the
> following patches, which will add a mechanism to hide DW_AT_trampoline
> subroutines from the user.
One thing I don't understand is why this data is attached to the type,
and not to the function's symbol (or perhaps the block structure).
> + TYPE_TRAMPOLINE_TARGET (ftype)
> + = (trampoline_target *) TYPE_ZALLOC (ftype,
> + sizeof (trampoline_target));
This zero-initializes so...
> + if (dwarf2_get_pc_bounds (target_die, &lowpc, NULL, target_cu,
> + nullptr, nullptr) <= PC_BOUNDS_INVALID)
> + complaint (_("DW_AT_trampoline target DIE has invalid "
> + "low pc, for referencing DIE %s[in module %s]"),
> + sect_offset_str (die->sect_off),
> + objfile_name (objfile));
> + else
> + TYPE_TRAMPOLINE_TARGET (ftype)->set_target_addr (lowpc);
... if the complaint triggers, this will end up with a kind of
TRAMPOLINE_TARGET_ADDR and an unrelocated address of 0.
Perhaps in such a case it's better to avoid marking the function as a
trampoline. That way, if there is a problem in the DWARF, gdb will fall
back to the function simply being ordinary.
> + else if (attr->form_is_unsigned ())
> + TYPE_TRAMPOLINE_TARGET (ftype)->set_target_flag (attr->as_boolean ());
> + else
> + TYPE_TRAMPOLINE_TARGET (ftype)->set_target_addr (attr->as_address ());
This else clause also seems perhaps weird.
I had some other nits for this patch but I figured I'd rather find out
about the type issue before writing them up.
Tom
^ permalink raw reply [flat|nested] 32+ messages in thread* RE: [PATCH v11 01/10] gdb, dwarf: add support for DW_AT_trampoline in DWARF reader
2026-10-21 20:33 ` Tom Tromey
@ 2026-10-22 11:02 ` Ijaz, Abdul B
0 siblings, 0 replies; 32+ messages in thread
From: Ijaz, Abdul B @ 2026-10-22 11:02 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches, JiniSusan.George, eliz, Ijaz, Abdul B
Thanks Tom, for the feedback.
Please see the inline reply below:
Tom> One thing I don't understand is why this data is attached to the type, and not to the function's symbol (or perhaps the block structure).
Abdul> The type was chosen because that is where GDB already keeps the other DW_TAG_subprogram attributes that describe how a function behaves: DW_AT_noreturn (TYPE_NO_RETURN) is read in read_subroutine_type and stored in the function type's func_type. read_subroutine_type is also called for every DW_TAG_subprogram and DW_TAG_inlined_subroutine DIE (read_func_scope creates the symbol with read_type_die), and dwarf2_attr follows DW_AT_abstract_origin, so reading the attribute there covers concrete and inlined instances in one place. And it kept struct symbol, which is space critical, unchanged, since func_type only exists for functions.
That said, I agree that it is a property of the function and not of its type: DW_AT_trampoline is only allowed on subprograms and inlined subroutines, never on subroutine types (https://dwarfstd.org/doc/DWARF5.pdf [3.3.9 Trampolines]), and all the use cases in the following patches start from the function symbol anyway. So, for v12 I can move it to the symbol, as a new symbol subclass like template_symbol add SYMBOL_TRAMPOLINE to symbol_subclass_kind. The read_func_scope would allocate it when the DIE has a valid DW_AT_trampoline, as it does for template functions. Does that sound right to you, or would you prefer the block?
>> + TYPE_TRAMPOLINE_TARGET (ftype)
>> + = (trampoline_target *) TYPE_ZALLOC (ftype,
>> + sizeof (trampoline_target));
Tom> This zero-initializes so...
>> + if (dwarf2_get_pc_bounds (target_die, &lowpc, NULL, target_cu,
>> + nullptr, nullptr) <= PC_BOUNDS_INVALID)
>> + complaint (_("DW_AT_trampoline target DIE has invalid "
>> + "low pc, for referencing DIE %s[in module %s]"),
>> + sect_offset_str (die->sect_off),
>> + objfile_name (objfile));
Tom>... if the complaint triggers, this will end up with a kind of TRAMPOLINE_TARGET_ADDR and an unrelocated address of 0.
Tom> Perhaps in such a case it's better to avoid marking the function as a trampoline. That way, if there is a problem in the DWARF, gdb will fall back to the function simply being ordinary.
Abdul> Agreed, I'll only mark the function once the target is known to be valid to allow GDB to fall back to the ordinary function handling.
> > + else
> > + TYPE_TRAMPOLINE_TARGET (ftype)->set_target_addr (attr->as_address
> > +());
Tom> This else clause also seems perhaps weird.
Abdul> DWARF only allows the address, flag, reference, and string classes for DW_AT_trampoline. In v12, I'll handle the forms explicitly (flag forms, address forms, string forms, reference forms) and complain about anything else without marking the function as a trampoline.
Tom> I had some other nits for this patch, but I figured I'd rather find out about the type issue before writing them up.
Abdul> Thanks, I'll wait for those before sending v12.
Best Regards
Abdul Basit
-----Original Message-----
From: Tom Tromey <tom@tromey.com>
Sent: Wednesday, October 21, 2026 10:34 PM
To: Ijaz, Abdul B <abdul.b.ijaz@intel.com>
Cc: gdb-patches@sourceware.org; JiniSusan.George@amd.com; tom@tromey.com; eliz@gnu.org; Nils-Christian Kempke <nils-christian.kempke@intel.com>
Subject: Re: [PATCH v11 01/10] gdb, dwarf: add support for DW_AT_trampoline in DWARF reader
>>>>> Abdul Basit Ijaz <abdul.b.ijaz@intel.com> writes:
> DW_AT_trampoline can be used to describe compiler generated functions
> that serve some intermediary purpose on making a call to another
> function. A compiler can emit this tag in order to help a debugger
> hide the trampolines from a user.
> This patch adds support to GDB for reading the DW_AT_trampoline
> attribute. It stores the attribute and its value in the type_specific
> part of a GDB type. This patch is implemented in preparation of the
> following patches, which will add a mechanism to hide DW_AT_trampoline
> subroutines from the user.
One thing I don't understand is why this data is attached to the type, and not to the function's symbol (or perhaps the block structure).
> + TYPE_TRAMPOLINE_TARGET (ftype)
> + = (trampoline_target *) TYPE_ZALLOC (ftype,
> + sizeof (trampoline_target));
This zero-initializes so...
> + if (dwarf2_get_pc_bounds (target_die, &lowpc, NULL, target_cu,
> + nullptr, nullptr) <= PC_BOUNDS_INVALID)
> + complaint (_("DW_AT_trampoline target DIE has invalid "
> + "low pc, for referencing DIE %s[in module %s]"),
> + sect_offset_str (die->sect_off),
> + objfile_name (objfile));
> + else
> + TYPE_TRAMPOLINE_TARGET (ftype)->set_target_addr (lowpc);
... if the complaint triggers, this will end up with a kind of TRAMPOLINE_TARGET_ADDR and an unrelocated address of 0.
Perhaps in such a case it's better to avoid marking the function as a trampoline. That way, if there is a problem in the DWARF, gdb will fall back to the function simply being ordinary.
> + else if (attr->form_is_unsigned ())
> + TYPE_TRAMPOLINE_TARGET (ftype)->set_target_flag (attr->as_boolean ());
> + else
> + TYPE_TRAMPOLINE_TARGET (ftype)->set_target_addr (attr->as_address
> +());
This else clause also seems perhaps weird.
I had some other nits for this patch but I figured I'd rather find out about the type issue before writing them up.
Tom
________________________________________
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 (89) 99143-0
www.intel.de
Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman
Chairperson of the Supervisory Board: Sonja Pierer
Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v11 02/10] gdb/symtab: add lookup for trampoline functions
2026-08-03 19:34 [PATCH v11 00/10] GDB support for DW_AT_trampoline Abdul Basit Ijaz
2026-08-03 19:34 ` [PATCH v11 01/10] gdb, dwarf: add support for DW_AT_trampoline in DWARF reader Abdul Basit Ijaz
@ 2026-08-03 19:34 ` Abdul Basit Ijaz
2026-08-03 19:34 ` [PATCH v11 03/10] gdb: handle stepping through functions with DW_AT_trampoline Abdul Basit Ijaz
` (8 subsequent siblings)
10 siblings, 0 replies; 32+ messages in thread
From: Abdul Basit Ijaz @ 2026-08-03 19:34 UTC (permalink / raw)
To: gdb-patches
Cc: abdul.b.ijaz, JiniSusan.George, tom, eliz, Nils-Christian Kempke
From: Nils-Christian Kempke <nils-christian.kempke@intel.com>
In order to query information about the DW_AT_trampoline tag for
subroutines and inlined subroutines, three functions were added to symtab.
First, in_trampoline_code() a routine for querying whether the given
pc belongs to a block that is associated with a function (maybe inlined)
marked DW_AT_trampoline. Used inside trampoline code (inline or concrete)
that was stepped into and continues stepping through it. This function
uses find_symbol_for_pc_sect_maybe_inline() which calls containing_function
to detect inline trampolines as well as concrete ones.
Second, in_trampoline_function() a routine to check concrete trampoline
(non-inline) functions and attempt target resolution upfront. Used in
forward stepping and for frame navigation commands. This function uses
find_symbol_for_pc_sect() which calls block->linkage_function to skip
inlined blocks and return only the concrete function at the PC.
Third, find_function_trampoline_target() a routine for querying a trampoline
function's target. Subroutines and inlined subroutines marked with
DW_AT_trampoline usually contain information about the target subroutine
they are 'wrapping'/ passing control to.
These lookup functions will be used in the follow up commits for the
trampoline handling in different GDB commands.
Co-Authored-By: Abdul Basit Ijaz <abdul.b.ijaz@intel.com>
---
gdb/symtab.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++
gdb/symtab.h | 24 ++++++++++++
2 files changed, 132 insertions(+)
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 5d5076f2e77..e5464551807 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -74,6 +74,7 @@
#include "gdbsupport/common-utils.h"
#include <optional>
#include "gdbsupport/unordered_set.h"
+#include "gdbsupport/symbol.h"
/* Forward declarations for local functions. */
@@ -4103,6 +4104,113 @@ find_function_alias_target (bound_minimal_symbol msymbol)
return NULL;
}
+/* See symtab.h. */
+
+bool
+in_trampoline_code (CORE_ADDR pc)
+{
+ /* Find the innermost function containing pc, which might be an inlined
+ function. This is used by stepping logic to detect when execution is
+ within ANY trampoline code (inline or concrete) and continue stepping
+ through it.
+
+ Unlike in_trampoline_function(), this uses containing_function() by
+ calling find_symbol_for_pc_sect_maybe_inline to detect inline trampolines as
+ well as concrete ones. */
+ symbol *sym = find_symbol_for_pc_sect_maybe_inline (pc,
+ find_pc_mapped_section (pc));
+ return sym != nullptr && TYPE_IS_TRAMPOLINE (sym->type ());
+}
+
+/* See symtab.h. */
+
+bool
+in_trampoline_function (CORE_ADDR pc)
+{
+ /* Find the concrete non-inlined function at pc, skipping inlined blocks.
+ The find_symbol_for_pc_sect calls block->linkage_function which skips
+ inlined blocks to return the concrete function at the PC. This ensures
+ we check the concrete function's trampoline flag, not the flag from an
+ abstract inline origin that might be marked as a trampoline.
+
+ This is used by forward stepping to determine if about to step into a
+ concrete trampoline function and by frame navigation commands to skip
+ trampoline frames.
+
+ For O2 optimization, the compiler may create trampoline wrappers with
+ both DW_AT_trampoline + DW_AT_inline. At a given PC, inlined code from
+ such abstract trampolines may exist, but the concrete function at that
+ PC is the user's real function (not a trampoline). Using linkage_function
+ by calling find_symbol_for_pc_sect avoids incorrectly checking the inline
+ trampoline's abstract origin. */
+ symbol *sym = find_symbol_for_pc_sect (pc, find_pc_mapped_section (pc));
+ return sym != nullptr && TYPE_IS_TRAMPOLINE (sym->type ());
+}
+
+/* See symtab.h. */
+
+CORE_ADDR
+find_function_trampoline_target (CORE_ADDR pc)
+{
+ /* Find the innermost function containing pc. This might be an inlined
+ function. */
+ symbol *sym
+ = find_symbol_for_pc_sect_maybe_inline (pc, find_pc_mapped_section (pc));
+ CORE_ADDR target_address = 0;
+
+ if (sym != nullptr && TYPE_IS_TRAMPOLINE (sym->type ()))
+ {
+ trampoline_target *trampoline = TYPE_TRAMPOLINE_TARGET (sym->type ());
+
+ /* DW_AT_trampoline can be given as an address, name, or flag here (die
+ references have been resolved as names at this point. In the case
+ where DW_AT_trampoline contains a flag we do not know the target
+ address and return 0. */
+ if (trampoline->target_kind () == TRAMPOLINE_TARGET_NAME)
+ {
+ /* Handle both the mangled and demangled PHYSNAME. */
+ const char *physname = trampoline->target_name ();
+
+ /* First, check whether there exists a symbol matching the
+ physname. If we cannot find one also check for minimal
+ symbols. */
+ const block *blk = block_for_pc (pc);
+ block_symbol bs
+ = lookup_symbol (physname, blk, SEARCH_VAR_DOMAIN, 0);
+ if (bs.symbol != nullptr)
+ {
+ const block *block = bs.symbol->value_block ();
+ gdb_assert (block != nullptr);
+ target_address = block->start ();
+ }
+ else
+ {
+ /* We normally expect the target symbol to be located in one
+ objfile only. However, a JIT compiler may have generated
+ a duplicated symbol that most likely resides in the same
+ objfile with the trampoline symbol. Give priority to that
+ objfile in the search. If not found, try all objfiles.
+ This is a heuristic. */
+ if ((find_minimal_symbol_address (physname, &target_address,
+ sym->objfile ()) != 0)
+ && (find_minimal_symbol_address (physname, &target_address,
+ nullptr) != 0))
+ target_address = 0;
+ }
+ }
+ else if (trampoline->target_kind () == TRAMPOLINE_TARGET_ADDR)
+ {
+ /* If the function symbol containing this trampoline target has
+ been relocated we assume the target_address also needs relocation.
+ If it has not been relocated the offset should be zero. */
+ target_address = \
+ ( (CORE_ADDR) trampoline->target_addr ()
+ + sym->objfile ()->section_offsets[sym->section_index ()]);
+ }
+ }
+
+ return target_address;
+}
\f
/* If P is of the form "operator[ \t]+..." where `...' is
some legitimate operator text, return a pointer to the
diff --git a/gdb/symtab.h b/gdb/symtab.h
index 6443216fd7f..10f64548f58 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -2362,6 +2362,30 @@ extern const struct gnu_ifunc_fns *gnu_ifunc_fns_p;
extern CORE_ADDR find_solib_trampoline_target (const frame_info_ptr &, CORE_ADDR);
+/* Return whether the current pc is within a block that belongs to a
+ function that is marked as a trampoline by the compiler. This checks
+ only the concrete (non-inline) function at the PC. Used by forward stepping
+ to check if about to step into a concrete trampoline function and attempt
+ to resolve its target. Also used for frame navigation commands. */
+
+extern bool in_trampoline_function (CORE_ADDR pc);
+
+/* Return whether the current pc is within any trampoline code
+ (inline or concrete). Used to detect when execution stepped into ANY
+ trampoline code (inline or concrete) and continue stepping through it.
+ Also used for reverse stepping logic. */
+
+extern bool in_trampoline_code (CORE_ADDR pc);
+
+/* Find the target of a trampoline function marked via the DW_AT_trampoline
+ attribute and return its address. Returns 0 if the pc is not contained
+ in a trampoline function (inlined or not). If DW_AT_trampoline
+ is given as a flag, the target is unknown and the function will still return
+ 0. One has to additionally query in_trampoline_function to cover this
+ case. */
+
+extern CORE_ADDR find_function_trampoline_target (CORE_ADDR pc);
+
struct symtab_and_line
{
/* The program space of this sal. */
--
2.34.1
________________________________________
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 (89) 99143-0
www.intel.de
Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman
Chairperson of the Supervisory Board: Sonja Pierer
Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 32+ messages in thread* [PATCH v11 03/10] gdb: handle stepping through functions with DW_AT_trampoline
2026-08-03 19:34 [PATCH v11 00/10] GDB support for DW_AT_trampoline Abdul Basit Ijaz
2026-08-03 19:34 ` [PATCH v11 01/10] gdb, dwarf: add support for DW_AT_trampoline in DWARF reader Abdul Basit Ijaz
2026-08-03 19:34 ` [PATCH v11 02/10] gdb/symtab: add lookup for trampoline functions Abdul Basit Ijaz
@ 2026-08-03 19:34 ` Abdul Basit Ijaz
2026-10-21 20:39 ` Tom Tromey
2026-10-21 20:43 ` Tom Tromey
2026-08-03 19:34 ` [PATCH v11 04/10] gdb: Skip trampoline frames for the backtrace command Abdul Basit Ijaz
` (7 subsequent siblings)
10 siblings, 2 replies; 32+ messages in thread
From: Abdul Basit Ijaz @ 2026-08-03 19:34 UTC (permalink / raw)
To: gdb-patches
Cc: abdul.b.ijaz, JiniSusan.George, tom, eliz, Nils-Christian Kempke
From: Nils-Christian Kempke <nils-christian.kempke@intel.com>
This patch makes infrun continue stepping into and through trampoline
functions marked via the DW_AT_trampoline in DWARF. The attribute can
be emitted by the compiler for certain subroutines/inlined subroutines
that are compiler generated and should be hidden from a user.
Mainly, infrun is modified in 3 ways.
First, GDB will now attempt to step through trampoline functions.
Whenever we issued a step command that would make GDB step into a
function that is marked trampoline, GDB will try to step directly towards
the trampoline's 'target' instead and, e.g., not stop at the first
instruction of the trampoline.
The target can be specified by the compiler by the value of
DW_AT_trampoline if its form is either an address, a name, or a DIE
reference. DW_AT_trampoline is also allowed to be specified as a flag
(containing true or false), in which case the target is assumed to be
unknown. If GDB successfully finds a target, so if the value of
DW_AT_trampoline was not a flag and could be resolved successfully, GDB
steps directly towards the target and through the trampoline, hiding
the trampoline from the user. If GDB cannot, however deduce a target,
most likely because the DW_AT_trampoline was given as a flag or because
of broken debug info, it will instead continue inside execution in the
trampoline function until it reaches an instruction that is not
associated with a trampoline function, which is usually the target
function. It will then stop and give control back to the user.
It should be noted, that there might be the cases, where trampolines
call functions other than the target before the actual target call. If,
in such a situation, GDB fails to resolve the target, it would resume
execution until stepping into this other function call, and hand back
control to the user, without actually having reached the target. A
second step would have to be issued by the user to arrive a the target
(by resuming in the trampoline and then until leaving it a second time).
As this is a rather pathological case and no real instance of this is
known, I think the current behavior here is good enough and seems to be
the best GDB can do in such a situation.
Secondly, as trampoline functions normally do not have any real source
code correlation, it is likely that they mostly appear without line
info.
Normally, GDB would skip completely over a function call to a function
that has no source line information, so we would never get to the
aforementioned stepping through a trampoline and target resolution. To
remedy this, for debug info trampolines, GDB now attempts to step through
them regardless of them having source line information or not. So
issuing a step at a function call wrapped by a trampoline without source
line information will no longer skip the whole function call, but now
step through the trampoline and attempt to resolve the trampoline target
as described above (so usually, a single step at the call site will step
through the trampoline and towards the target, even if the trampoline had
not source line info).
Last, in all other cases when GDB is about to stop at a location that is
included in a trampoline region (e.g. after a step from the target back
into the trampoline) GDB will instead continue until the trampoline
region is left again and only then give control back to the user. This
change serves the purpose of allowing stepping back from a target call
through the trampoline without the user noticing the artificial function
call inbetween call site and target.
Together, these changes attempt to hide the trampoline function from the
user while stepping. Additionally, the skip-trampoline-functions option
has been introduced in infrun. It is set by default, and, when turned
off, GDB will return to its 'normal' stepping behavior and ignore any
possible DW_AT_trampoline.
As currently only ifx emits the DW_AT_trampoline tag, a test has been
added to gdb.dwarf2 that artificially creates a set of trampoline
functions.
---
gdb/NEWS | 11 +
gdb/doc/gdb.texinfo | 35 +++
gdb/infrun.c | 94 ++++++-
gdb/infrun.h | 5 +
.../gdb.dwarf2/dw2-function-trampolines.c | 80 ++++++
.../gdb.dwarf2/dw2-function-trampolines.exp | 244 ++++++++++++++++++
6 files changed, 465 insertions(+), 4 deletions(-)
create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-function-trampolines.c
create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-function-trampolines.exp
diff --git a/gdb/NEWS b/gdb/NEWS
index 8f40ca5cb11..5c618c0d38d 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -1768,6 +1768,17 @@ platform.
* New commands
+set skip-trampoline-functions on|off
+show skip-trampoline-functions
+ This setting is 'on' by default. When 'on' it controls whether GDB will
+ recognize function calls that have been marked as trampolines in the debug
+ info. It improves stepping behavior in that it steps over the trampoline
+ code and hides it from the user. Currently, only DWARF trampolines are
+ supported.
+
+ If this is turned off, GDB will handle @dfn{trampoline functions} the same
+ as any other function.
+
maint set backtrace-on-fatal-signal on|off
maint show backtrace-on-fatal-signal
This setting is 'on' by default. When 'on' GDB will print a limited
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 0030698dcee..f8dd7d8ec4e 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -6742,6 +6742,41 @@ debug information. This is the default.
Show whether @value{GDBN} will stop in or step over functions without
source line debug information.
+@kindex set skip-trampoline-functions
+@item set skip-trampoline-functions
+@cindex trampoline functions
+@cindex stepping through trampoline functions
+@itemx set skip-trampoline-functions on
+When calling a function in any language, some compilers might generate
+so-called @dfn{trampoline functions}, which wrap the actual function call (the
+target of the trampoline). The compiler might mark such a trampoline in
+its debug information.
+
+The default is @code{on} and it will cause @value{GDBN} to treat these
+trampolines differently.
+
+When issuing a @code{step} at the call site of a trampoline function if
+@code{skip-trampoline-functions} is set @value{GDBN} will attempt to determine
+the target of the trampoline and then step through the trampoline stopping at
+the target. If the target could not be found or was not given in the debug
+info, @value{GDBN} will simply continue execution until it leaves the
+trampoline code, even if the trampoline has no line info associated with it.
+When returning from a target function call and stepping back into the
+trampoline, @value{GDBN} will step over the trampoline towards the call site.
+Additionally, even if stopped in a trampoline function with source
+line information, issuing a @code{step} will prompt @value{GDBN} to resume
+execution until leaving the trampoline region. The @code{stepi} command
+is not affected by the setting which is enabled by default. Currently, only
+DWARF trampolines marked via DW_AT_trampoline are supported by this.
+
+@item set skip-trampoline-functions off
+Causes @value{GDBN} to completely ignore any trampoline information a compiler
+might have emitted in its debug info. Trampolines will be treated like any
+other normal function.
+
+@item show skip-trampoline-functions
+Show whether @value{GDBN} tries to skip trampolines or not.
+
@kindex finish
@kindex fin @r{(@code{finish})}
@item finish
diff --git a/gdb/infrun.c b/gdb/infrun.c
index c0767e7f764..0b032ce94c0 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -190,6 +190,12 @@ get_previous_thread ()
static bool detach_fork = true;
+/* If set (default) GDB will step through functions/inlined subroutines marked
+ DW_AT_trampoline by the compiler. If false, GDB will ignore the
+ attribute. */
+
+static bool skip_trampoline_functions = true;
+
bool debug_infrun = false;
static void
show_debug_infrun (struct ui_file *file, int from_tty,
@@ -7979,7 +7985,6 @@ process_event_stop_test (struct execution_control_state *ecs)
|| !ecs->event_thread->control.in_step_start_function (frame))))
{
CORE_ADDR stop_pc = ecs->event_thread->stop_pc ();
- CORE_ADDR real_stop_pc;
infrun_debug_printf ("stepped into subroutine");
@@ -8051,8 +8056,47 @@ process_event_stop_test (struct execution_control_state *ecs)
calling routine and the real function), locate the real
function. That's what tells us (a) whether we want to step
into it at all, and (b) what prologue we want to run to the
- end of, if we do step into it. */
- real_stop_pc = skip_language_trampoline (frame, stop_pc);
+ end of, if we do step into it. For functions marked as
+ trampoline functions we try to find their target and step
+ towards it (if skip_trampoline_functions is not set to false by the
+ user). If no target can be determined we just step into the
+ trampoline and hand control back to the user. */
+ CORE_ADDR real_stop_pc = 0;
+ bool in_trampoline = skip_trampoline_functions
+ && in_trampoline_function (stop_pc);
+
+ if (in_trampoline)
+ {
+ if (execution_direction == EXEC_REVERSE)
+ {
+ keep_going (ecs);
+ return;
+ }
+
+ real_stop_pc = find_function_trampoline_target (stop_pc);
+
+ for (int i = 0; i < MAX_TRAMPOLINE_CHAIN_SIZE
+ && in_trampoline_function (real_stop_pc); ++i)
+ {
+ real_stop_pc = find_function_trampoline_target (real_stop_pc);
+ /* Exit if find_function_trampoline_target failed to find the
+ trampoline target. Do not try to resolve the trampolines
+ in this case. */
+ if (real_stop_pc == 0x0)
+ break;
+ }
+
+ /* If we failed to find a target we will just single step in the
+ hope of leaving the trampoline again soon. */
+ if (real_stop_pc == 0x0)
+ {
+ keep_going (ecs);
+ return;
+ }
+ }
+
+ if (real_stop_pc == 0)
+ real_stop_pc = skip_language_trampoline (frame, stop_pc);
if (real_stop_pc == 0)
real_stop_pc = gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc);
if (real_stop_pc != 0)
@@ -8073,6 +8117,8 @@ process_event_stop_test (struct execution_control_state *ecs)
/* If we have line number information for the function we are
thinking of stepping into and the function isn't on the skip
list, step into it.
+ If we are about to step into a function marked trampoline with no
+ line number information, we still want to enter it here.
If there are several symtabs at that PC (e.g. with include
files), just want to know whether *any* of them have line
@@ -8081,7 +8127,9 @@ process_event_stop_test (struct execution_control_state *ecs)
struct symtab_and_line tmp_sal;
tmp_sal = find_sal_for_pc (ecs->stop_func_start, 0);
- if (tmp_sal.line != 0
+ if ((tmp_sal.line != 0
+ || (skip_trampoline_functions
+ && in_trampoline_function (ecs->stop_func_start)))
&& !function_name_is_marked_for_skip (ecs->stop_func_name,
tmp_sal)
&& !inline_frame_is_marked_for_skip (true, ecs->event_thread))
@@ -8234,6 +8282,26 @@ process_event_stop_test (struct execution_control_state *ecs)
return;
}
+ /* If we ended up in a function trampoline without stepping into a new
+ function we are either in some inlined trampoline or returning through a
+ trampoline function. In either case we continue to single step until we
+ are out of the trampoline code again. This check has to be done before
+ stop_pc_sal.line == 0 below, as trampolines usually don't have source
+ line information associated with them.
+ The in_trampoline_code() is used here (which detects both inline and
+ concrete trampolines). Because this is already mid-step and need to
+ detect ANY trampoline code (inline or concrete) to properly step through
+ it. This handles cases where compilers emit DW_AT_trampoline
+ + DW_AT_inline (e.g., O2 optimizations), where inlined trampoline code
+ may exist at the current PC even though the concrete function is not a
+ trampoline. */
+ if (skip_trampoline_functions && in_trampoline_code (stop_pc_sal.pc))
+ {
+ infrun_debug_printf ("stepped into trampoline code");
+ keep_going (ecs);
+ return;
+ }
+
if (stop_pc_sal.line == 0)
{
/* We have no line number information. That means to stop
@@ -10608,6 +10676,14 @@ show_exec_direction_func (struct ui_file *out, int from_tty,
}
}
+static void
+show_skip_trampoline_functions (ui_file *file, int from_tty,
+ cmd_list_element *c,
+ const char *value)
+{
+ gdb_printf (file, _("Skipping trampoline functions is %s.\n"), value);
+}
+
static void
show_schedule_multiple (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
@@ -10951,6 +11027,16 @@ Options are 'forward' or 'reverse'."),
set_exec_direction_func, show_exec_direction_func,
&setlist, &showlist);
+ add_setshow_boolean_cmd ("skip-trampoline-functions", class_run,
+ &skip_trampoline_functions, _("\
+Set whether gdb attempts to hide trampolines marked in the debug info."), _("\
+Show whether gdb attempts to hide trampolines marked in the debug info."), _("\
+If on, while stepping gdb will skip through functions and inlined functions\n\
+marked as trampolines by the compiler. If off, gdb will treat trampolines as\n\
+normal functions."),
+ nullptr, show_skip_trampoline_functions, &setlist,
+ &showlist);
+
/* Set/show detach-on-fork: user-settable mode. */
add_setshow_boolean_cmd ("detach-on-fork", class_run, &detach_fork, _("\
diff --git a/gdb/infrun.h b/gdb/infrun.h
index cbc603b74ed..135d1fc350b 100644
--- a/gdb/infrun.h
+++ b/gdb/infrun.h
@@ -75,6 +75,11 @@ infrun_debug_show_threads (const char *title, ThreadRange threads)
}
+/* Maximum size of trampoline chain to process while resolving
+ trampolines. This avoids infinite loops for malformed debug
+ information. */
+#define MAX_TRAMPOLINE_CHAIN_SIZE 10
+
/* Nonzero if we want to give control to the user when we're notified
of shared library events by the dynamic linker. */
extern int stop_on_solib_events;
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-function-trampolines.c b/gdb/testsuite/gdb.dwarf2/dw2-function-trampolines.c
new file mode 100644
index 00000000000..9629b753e7d
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-function-trampolines.c
@@ -0,0 +1,80 @@
+/* Copyright 2026 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 test relies on inlined_trampoline being inlined into main and the other
+ functions not. All functions except target will be marked via
+ DW_AT_trampoline in the debug info and we'll check whether one can step
+ through the trampolines towards target. */
+volatile int global_var;
+
+int __attribute__ ((noinline))
+target () /* target decl line */
+{ /* target prologue */
+ asm ("target_label: .globl target_label");
+ ++global_var; /* target add */
+ asm ("target_label2: .globl target_label2");
+ return 9 + 10; /* target return */
+} /* target end */
+
+int __attribute__ ((noinline))
+trampoline ()
+{ /* trampoline prologue */
+ asm ("trampoline_label: .globl trampoline_label");
+ ++global_var;
+ return target (); /* trampoline target call */
+} /* trampoline end */
+
+static inline int __attribute__ ((always_inline))
+inlined_trampoline ()
+{ /* inlined_trampoline prologue */
+ asm ("inlined_trampoline_label: .globl inlined_trampoline_label");
+ ++global_var; /* inlined_trampoline add */
+ asm ("inlined_trampoline_label2: .globl inlined_trampoline_label2");
+ return target (); /* inlined_trampoline target call */
+} /* inlined_trampoline end */
+
+int __attribute__ ((noinline))
+chained_trampoline ()
+{ /* chained_trampoline prologue */
+ asm ("chained_trampoline_label: .globl chained_trampoline_label");
+ ++global_var;
+ return trampoline (); /* chained_trampoline trampoline call */
+} /* chained_trampoline end */
+
+int __attribute__ ((noinline))
+doubly_chained_trampoline ()
+{ /* doubly_chained_trampoline prologue */
+ asm ("doubly_chained_trampoline_label: .globl doubly_chained_trampoline_label");
+ ++global_var;
+ return chained_trampoline (); /* doubly_chained_trampoline chained_trampoline call */
+} /* doubly_chained_trampoline end */
+
+int
+main () /* main decl line */
+{ /* main prologue */
+ int ans;
+ asm ("main_label: .globl main_label");
+ global_var = 0; /* main set global_var */
+ asm ("main_label2: .globl main_label2");
+ ans = inlined_trampoline (); /* main call inlined_trampoline */
+ asm ("main_label3: .globl main_label3");
+ ans = trampoline (); /* main call trampoline */
+ asm ("main_label4: .globl main_label4");
+ ans = chained_trampoline (); /* main call chained_trampoline */
+ asm ("main_label5: .globl main_label5");
+ ans = doubly_chained_trampoline (); /* main call doubly_chained_trampoline */
+ asm ("main_label6: .globl main_label6");
+ return ans; /* main call return */
+} /* main end */
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-function-trampolines.exp b/gdb/testsuite/gdb.dwarf2/dw2-function-trampolines.exp
new file mode 100644
index 00000000000..f2aa43e27c9
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-function-trampolines.exp
@@ -0,0 +1,244 @@
+# Copyright 2026 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 test checks GDB's handling of functions/inlined functions marked
+# DW_AT_trampoline by the compiler. A function marked as trampoline should
+# generally be hidden from the user. We check whether we can step through
+# trampolines. Every trampoline is defined using a different type for its
+# target: a string, an address, a DIE reference or a flag.
+# Setting skip-trampoline-functions to false inside GDB should make it return
+# to its 'normal' behavior, ignore the DW_AT_trampoline, and skip all of the
+# non-inlined trampoline calls (as their DIEs don't have any source
+# information).
+
+load_lib dwarf.exp
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+if {![dwarf2_support]} {
+ return
+}
+
+standard_testfile .c .S
+
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+ declare_labels lines_label trampoline_label
+
+ get_func_info target
+ get_func_info trampoline
+ get_func_info chained_trampoline
+ get_func_info doubly_chained_trampoline
+ get_func_info main
+
+ set target_decl_line [gdb_get_line_number "target decl line"]
+ set main_decl_line [gdb_get_line_number "main decl line"]
+ set main_call_inlined_trampoline_line [gdb_get_line_number "main call inlined_trampoline"]
+
+ cu {} {
+ compile_unit {
+ DW_AT_language @DW_LANG_C
+ DW_AT_name dw2-function-trampolines.c
+ DW_AT_low_pc 0 addr
+ DW_AT_stmt_list ${lines_label} DW_FORM_sec_offset
+ } {
+ subprogram {
+ DW_AT_name target
+ DW_AT_low_pc $target_start addr
+ DW_AT_high_pc "$target_start + $target_len" addr
+ DW_AT_decl_file 1 data1
+ DW_AT_decl_line $target_decl_line data1
+ }
+ # The 'trampoline' subprogram declares its target by name.
+ trampoline_label: subprogram {
+ DW_AT_name trampoline
+ DW_AT_low_pc $trampoline_start addr
+ DW_AT_high_pc "$trampoline_start + $trampoline_len" addr
+ DW_AT_trampoline target string
+ }
+ # The 'chained_trampoline' subprogram declares its target as die
+ # reference.
+ subprogram {
+ DW_AT_name chained_trampoline
+ DW_AT_low_pc $chained_trampoline_start addr
+ DW_AT_high_pc "$chained_trampoline_start + $chained_trampoline_len" addr
+ DW_AT_trampoline %$trampoline_label
+ }
+ # The 'doubly_chained_trampoline' subprogram declares no target.
+ # Its DW_AT_trampoline is a flag set to true.
+ subprogram {
+ DW_AT_name doubly_chained_trampoline
+ DW_AT_low_pc $doubly_chained_trampoline_start addr
+ DW_AT_high_pc "$doubly_chained_trampoline_start + $doubly_chained_trampoline_len" addr
+ DW_AT_trampoline 1 flag
+ }
+ subprogram {
+ DW_AT_external 1 flag
+ DW_AT_name main
+ DW_AT_main_subprogram 1 flag
+ DW_AT_low_pc $main_start addr
+ DW_AT_high_pc "$main_start + $main_len" addr
+ DW_AT_decl_file 1 data1
+ DW_AT_decl_line $main_decl_line data1
+ } {
+ # The 'inlined_trampoline' subroutine declares its target as
+ # an address.
+ inlined_subroutine {
+ DW_AT_name inlined_trampoline
+ DW_AT_low_pc main_label2 addr
+ DW_AT_high_pc main_label3 addr
+ DW_AT_trampoline $target_start addr
+ DW_AT_call_file 1 data1
+ DW_AT_call_line $main_call_inlined_trampoline_line data1
+ }
+ }
+ }
+ }
+
+ lines {version 2} lines_label {
+ include_dir "$::srcdir/$::subdir"
+ file_name "$::srcfile" 1
+
+ program {
+ DW_LNE_set_address $main_start
+ line [gdb_get_line_number "main set global_var"]
+ DW_LNS_copy
+ DW_LNE_set_address main_label
+ line [gdb_get_line_number "main set global_var"]
+ DW_LNS_copy
+ DW_LNE_set_address main_label2
+ line [gdb_get_line_number "main call inlined_trampoline"]
+ DW_LNS_copy
+ DW_LNE_set_address inlined_trampoline_label
+ line [gdb_get_line_number "inlined_trampoline add"]
+ DW_LNS_copy
+ DW_LNE_set_address inlined_trampoline_label2
+ line [gdb_get_line_number "inlined_trampoline target call"]
+ DW_LNS_copy
+ DW_LNE_set_address main_label3
+ line [gdb_get_line_number "main call trampoline"]
+ DW_LNS_copy
+ DW_LNE_set_address main_label4
+ line [gdb_get_line_number "main call chained_trampoline"]
+ DW_LNS_copy
+ DW_LNE_set_address main_label5
+ line [gdb_get_line_number "main call doubly_chained_trampoline"]
+ DW_LNS_copy
+ DW_LNE_set_address main_label6
+ line [gdb_get_line_number "main call return"]
+ DW_LNS_copy
+ DW_LNE_set_address $main_end
+ DW_LNE_end_sequence
+
+ DW_LNE_set_address $target_start
+ line [gdb_get_line_number "target prologue"]
+ DW_LNS_negate_stmt
+ DW_LNS_copy
+ DW_LNE_set_address target_label
+ line [gdb_get_line_number "target add"]
+ DW_LNS_negate_stmt
+ DW_LNS_copy
+ DW_LNE_set_address target_label2
+ line [gdb_get_line_number "target return"]
+ DW_LNS_copy
+ DW_LNE_set_address $target_end
+ DW_LNE_end_sequence
+ }
+ }
+}
+
+if {[prepare_for_testing "failed to prepare" ${testfile} \
+ [list $srcfile $asm_file] {nodebug additional_flags=-O0}]} {
+ return
+}
+
+set target_first_line_pattern ".*target add.*"
+set target_second_line_pattern ".*target return.*"
+
+if {![runto_main]} {
+ return
+}
+
+gdb_test "show skip-trampoline-functions" \
+ "Skipping trampoline functions is on\." \
+ "check skip-trampoline-functions is enabled"
+
+with_test_prefix "with trampoline handling" {
+ foreach {trampoline return_line} { "inlined_trampoline" "trampoline" \
+ "trampoline" "chained_trampoline" \
+ "chained_trampoline" "doubly_chained_trampoline" } {
+
+ gdb_test "s" "$target_first_line_pattern" "step through $trampoline"
+ gdb_test "s" "$target_second_line_pattern" \
+ "step target second line from $trampoline"
+ gdb_test "s" ".*main call $return_line.*" \
+ "step back through $trampoline"
+ }
+
+ # The doubly_chained_trampoline has only been marked as trampoline but no
+ # target was given. In this case GDB steps into the trampoline and then
+ # continues until the trampoline section is left again.
+
+ # When compiled with gcc 7.5 (and possibly others) on a 32 bit system, the
+ # trampoline function contains a call to __x86.get_pc_thunk.ax before the
+ # actual target call. So, we end up in __x86.get_pc_thunk.ax. Issuing a
+ # second step command will return from the function call back into the
+ # trampoline and go on inside the trampoline towards the actual target call.
+ # On other targets we step directly towards the target call.
+ gdb_test_multiple "s" "step through double_chained_trampoline" {
+ -re -wrap "$target_first_line_pattern" {
+ pass $gdb_test_name
+ }
+ -re -wrap ".*__x86.get_pc_thunk.ax.*" {
+ gdb_test "s" "$target_first_line_pattern" \
+ "step through double_chained_trampoline 2nd try"
+ }
+ }
+ gdb_test "s" "$target_second_line_pattern" \
+ "step target second line fromdoubly_chained_trampoline"
+ gdb_test "s" ".*main call return.*" \
+ "step back through doubly_chained_trampoline"
+}
+
+clean_restart ${testfile}
+
+if {![runto_main]} {
+ return
+}
+
+gdb_test_no_output "set skip-trampoline-functions off" \
+ "disable trampoline handling"
+gdb_test "show skip-trampoline-functions" \
+ "Skipping trampoline functions is off." \
+ "check skip-trampoline-functions is disabled"
+
+with_test_prefix "without trampoline handling" {
+ gdb_test "s" ".*main call inlined_trampoline.*"
+ gdb_test "s" ".*inlined_trampoline add.*" \
+ "step into inlined_trampoline with skip-trampoline off"
+ gdb_test "s" ".*inlined_trampoline target call.*" \
+ "step in inlined_trampoline with skip-trampoline off"
+ gdb_test "s" "$target_first_line_pattern" \
+ "step into target with skip-trampoline off"
+ gdb_test "s" "$target_second_line_pattern" \
+ "step second line in target with skip-trampoline off"
+ gdb_test "s" ".*main call trampoline.*" \
+ "step brack from target with skip-trampoline off"
+ gdb_test "s" ".*main call chained_trampoline.*" \
+ "skip trampoline call with no line info"
+ gdb_test "s" ".*main call doubly_chained_trampoline.*" \
+ "skip chained_trampoline call with no line info"
+ gdb_test "s" ".*main call return.*" \
+ "skip doubly_chained_trampoline call with no line info"
+}
--
2.34.1
________________________________________
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 (89) 99143-0
www.intel.de
Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman
Chairperson of the Supervisory Board: Sonja Pierer
Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: [PATCH v11 03/10] gdb: handle stepping through functions with DW_AT_trampoline
2026-08-03 19:34 ` [PATCH v11 03/10] gdb: handle stepping through functions with DW_AT_trampoline Abdul Basit Ijaz
@ 2026-10-21 20:39 ` Tom Tromey
2026-10-22 11:15 ` Ijaz, Abdul B
2026-10-21 20:43 ` Tom Tromey
1 sibling, 1 reply; 32+ messages in thread
From: Tom Tromey @ 2026-10-21 20:39 UTC (permalink / raw)
To: Abdul Basit Ijaz
Cc: gdb-patches, JiniSusan.George, tom, eliz, Nils-Christian Kempke
>>>>> Abdul Basit Ijaz <abdul.b.ijaz@intel.com> writes:
> This patch makes infrun continue stepping into and through trampoline
> functions marked via the DW_AT_trampoline in DWARF.
I'm probably not the best person to review this but I did have one
question:
> diff --git a/gdb/infrun.h b/gdb/infrun.h
> index cbc603b74ed..135d1fc350b 100644
> --- a/gdb/infrun.h
> +++ b/gdb/infrun.h
> +/* Maximum size of trampoline chain to process while resolving
> + trampolines. This avoids infinite loops for malformed debug
> + information. */
> +#define MAX_TRAMPOLINE_CHAIN_SIZE 10
Are there cases where there may be multiple trampolines chained
together?
If it's unusual or pathological then I guess some hard-coded limit seems
fine.
If it's normal then why 10? Like, I'm wondering if perhaps some other
approach should be taken.
Tom
^ permalink raw reply [flat|nested] 32+ messages in thread
* RE: [PATCH v11 03/10] gdb: handle stepping through functions with DW_AT_trampoline
2026-10-21 20:39 ` Tom Tromey
@ 2026-10-22 11:15 ` Ijaz, Abdul B
0 siblings, 0 replies; 32+ messages in thread
From: Ijaz, Abdul B @ 2026-10-22 11:15 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches, JiniSusan.George, eliz, Ijaz, Abdul B
Thanks Tom, for the feedback.
Please see the inline reply below:
>> +/* Maximum size of trampoline chain to process while resolving
>> + trampolines. This avoids infinite loops for malformed debug
>> + information. */
>> +#define MAX_TRAMPOLINE_CHAIN_SIZE 10
Tom> Are there cases where there may be multiple trampolines chained together?
Tom> If it's unusual or pathological then I guess some hard-coded limit seems fine.
Tom> If it's normal then why 10? Like, I'm wondering if perhaps some other approach should be taken.
Abdul> It is unusual. A chain means a trampoline whose target is itself a trampoline; the test covers a chain of two (chained_trampoline -> trampoline -> target in gdb.dwarf2/dw2-function-trampolines.c), and I am not aware of compilers emitting longer ones. Normally a trampoline directly calls its target.
The limit is only a safeguard, so that malformed debug information, e.g. two trampolines naming each other as target, cannot make GDB loop forever. 10 is well above what is expected in practice, so I would like to keep it as it is.
Best Regards,
Abdul Basit
-----Original Message-----
From: Tom Tromey <tom@tromey.com>
Sent: Wednesday, October 21, 2026 10:39 PM
To: Ijaz, Abdul B <abdul.b.ijaz@intel.com>
Cc: gdb-patches@sourceware.org; JiniSusan.George@amd.com; tom@tromey.com; eliz@gnu.org; Nils-Christian Kempke <nils-christian.kempke@intel.com>
Subject: Re: [PATCH v11 03/10] gdb: handle stepping through functions with DW_AT_trampoline
>>>>> Abdul Basit Ijaz <abdul.b.ijaz@intel.com> writes:
> This patch makes infrun continue stepping into and through trampoline
> functions marked via the DW_AT_trampoline in DWARF.
I'm probably not the best person to review this but I did have one
question:
> diff --git a/gdb/infrun.h b/gdb/infrun.h index
> cbc603b74ed..135d1fc350b 100644
> --- a/gdb/infrun.h
> +++ b/gdb/infrun.h
> +/* Maximum size of trampoline chain to process while resolving
> + trampolines. This avoids infinite loops for malformed debug
> + information. */
> +#define MAX_TRAMPOLINE_CHAIN_SIZE 10
Are there cases where there may be multiple trampolines chained together?
If it's unusual or pathological then I guess some hard-coded limit seems fine.
If it's normal then why 10? Like, I'm wondering if perhaps some other approach should be taken.
Tom
________________________________________
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 (89) 99143-0
www.intel.de
Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman
Chairperson of the Supervisory Board: Sonja Pierer
Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v11 03/10] gdb: handle stepping through functions with DW_AT_trampoline
2026-08-03 19:34 ` [PATCH v11 03/10] gdb: handle stepping through functions with DW_AT_trampoline Abdul Basit Ijaz
2026-10-21 20:39 ` Tom Tromey
@ 2026-10-21 20:43 ` Tom Tromey
2026-10-22 11:37 ` Ijaz, Abdul B
1 sibling, 1 reply; 32+ messages in thread
From: Tom Tromey @ 2026-10-21 20:43 UTC (permalink / raw)
To: Abdul Basit Ijaz
Cc: gdb-patches, JiniSusan.George, tom, eliz, Nils-Christian Kempke
>>>>> Abdul Basit Ijaz <abdul.b.ijaz@intel.com> writes:
> As currently only ifx emits the DW_AT_trampoline tag, a test has been
> added to gdb.dwarf2 that artificially creates a set of trampoline
> functions.
I was also wondering if this affects the "finish" command.
That is, suppose you have a call chain like A -> Trampoline -> B.
If you "finish" from B, then it seems like it ought to return all the
way to A.
Similarly for "return"?
If that's intended then those cases need tests.
If it's not intended then I wonder whether you can end up in a situation
where gdb is confused.
Tom
^ permalink raw reply [flat|nested] 32+ messages in thread
* RE: [PATCH v11 03/10] gdb: handle stepping through functions with DW_AT_trampoline
2026-10-21 20:43 ` Tom Tromey
@ 2026-10-22 11:37 ` Ijaz, Abdul B
0 siblings, 0 replies; 32+ messages in thread
From: Ijaz, Abdul B @ 2026-10-22 11:37 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches, JiniSusan.George, eliz, Ijaz, Abdul B
Thanks Tom, for the feedback.
Please see the inline reply below:
Tom> I was also wondering if this affects the "finish" command.
Tom> That is, suppose you have a call chain like A -> Trampoline -> B.
Tom> If you "finish" from B, then it seems like it ought to return all the way to A.
Tom> Similarly for "return"?
Tom> If that's intended then those cases need tests.
Abdul> Yes, that is intended, and it is handled in the later patches of this series, one per command:
gdb: Skip trampoline functions for the finish and reverse-finish commands.
gdb: Skip trampoline functions for the up command.
gdb: Skip trampoline functions for the return command.
With skip-trampoline-functions on (the default), each of them skips the trampoline frames, so "finish", "reverse-finish", "up" and "return" from B end up in A. These patches add tests to gdb.fortran/func-trampoline.exp ("finish", "up" and "return" from second through its trampoline back to first) and gdb.reverse/finish-reverse-trampoline.exp ("reverse-finish"). Both of those tests need ifx, though.
Thanks & Best Regards,
Abdul Basit
-----Original Message-----
From: Tom Tromey <tom@tromey.com>
Sent: Wednesday, October 21, 2026 10:44 PM
To: Ijaz, Abdul B <abdul.b.ijaz@intel.com>
Cc: gdb-patches@sourceware.org; JiniSusan.George@amd.com; tom@tromey.com; eliz@gnu.org; Nils-Christian Kempke <nils-christian.kempke@intel.com>
Subject: Re: [PATCH v11 03/10] gdb: handle stepping through functions with DW_AT_trampoline
>>>>> Abdul Basit Ijaz <abdul.b.ijaz@intel.com> writes:
> As currently only ifx emits the DW_AT_trampoline tag, a test has been
> added to gdb.dwarf2 that artificially creates a set of trampoline
> functions.
I was also wondering if this affects the "finish" command.
That is, suppose you have a call chain like A -> Trampoline -> B.
If you "finish" from B, then it seems like it ought to return all the way to A.
Similarly for "return"?
If that's intended then those cases need tests.
If it's not intended then I wonder whether you can end up in a situation where gdb is confused.
Tom
________________________________________
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 (89) 99143-0
www.intel.de
Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman
Chairperson of the Supervisory Board: Sonja Pierer
Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v11 04/10] gdb: Skip trampoline frames for the backtrace command.
2026-08-03 19:34 [PATCH v11 00/10] GDB support for DW_AT_trampoline Abdul Basit Ijaz
` (2 preceding siblings ...)
2026-08-03 19:34 ` [PATCH v11 03/10] gdb: handle stepping through functions with DW_AT_trampoline Abdul Basit Ijaz
@ 2026-08-03 19:34 ` Abdul Basit Ijaz
2026-10-21 20:50 ` Tom Tromey
2026-08-03 19:34 ` [PATCH v11 05/10] gdb: Skip trampoline functions for the finish and reverse-finish commands Abdul Basit Ijaz
` (6 subsequent siblings)
10 siblings, 1 reply; 32+ messages in thread
From: Abdul Basit Ijaz @ 2026-08-03 19:34 UTC (permalink / raw)
To: gdb-patches; +Cc: abdul.b.ijaz, JiniSusan.George, tom, eliz
This change filters trampoline functions when the option
'skip-trampoline-functions' is set to 'on' for the backtrace command.
Before the change, GDB prints the frames indicated by the compiler with
DIE "DW_AT_trampoline" in the backtrace, but for better user experience,
all such frames can be hidden from the user.
For O2 optimized code where inlined trampoline wrappers are inlined into
regular functions. Check the frame's function directly for inline frames
instead of looking up by PC, which would incorrectly return the caller's
function.
The test 'gdb.fortran/mixed-lang-stack' test used to fail for the IFX
compiler because of extra trampoline frames in the backtrace. After the
commit, those trampoline frames are filtered and test is updated accordingly.
Extra trampoline frames:
bt -frame-arguments all
'''
\#8 0x0000000000405535 in mixed_func_1b_.t86p.t87p.t88p.t89p.t90p.t91p.t3v ()
\#10 0x0000000000405439 in mixed_func_1a_.void () at mixed-lang-stack.f90:33
'''
(gdb) FAIL: gdb.fortran/mixed-lang-stack.exp: lang=auto: bt -frame-arguments all
In this example the IFX compiler emits "DW_AT_trampoline" tag for the 'first'
and 'second' trampoline functions like following:
function second (x, y) result(z)
integer, intent(in) :: x, y
integer :: z
z = x * y ! breakpt-backtrace
end function second
function first (num1, num2) result(total)
integer, intent(in) :: num1, num2
integer :: total
total = second (num1 + 4, num2 * 3) ! first-breakpt
total = total + 30
end function first
Related Dwarf:
0x0000013f: DW_TAG_subprogram
DW_AT_low_pc (0x0000000000404350)
DW_AT_high_pc (0x000000000040435f)
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_linkage_name ("second_.t74p.t75p")
DW_AT_name ("second_.t74p.t75p")
DW_AT_trampoline ("second_")
0x0000015a: DW_TAG_subprogram
DW_AT_low_pc (0x00000000004044a0)
DW_AT_high_pc (0x00000000004044af)
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_linkage_name ("first_.t104p.t105p")
DW_AT_name ("first_.t104p.t105p")
DW_AT_trampoline ("first_")
Before this change, the backtrace command output looks like:
'''
(gdb) backtrace 3
\#0 second (x=20, y=9) at test.f90:4
\#1 0x0000000000405209 in second_.t74p.t75p () at test.f90:12
\#2 0x00000000004051e3 in first (num1=16, num2=3) at test.f90:10
(gdb) backtrace -3
\#2 0x00000000004051e3 in first (num1=16, num2=3) at test.f90:10
\#3 0x0000000000405309 in first_.t95p.t96p () at test.f90:21
\#4 0x0000000000405234 in func_trampoline () at test.f90:17
'''
After the change:
'''
(gdb) backtrace 3
\#0 second (x=20, y=9) at test.f90:4
\#2 0x00000000004051e3 in first (num1=16, num2=3) at test.f90:10
\#4 0x0000000000405234 in func_trampoline () at test.f90:17
(gdb) backtrace -3
\#2 0x00000000004051e3 in first (num1=16, num2=3) at test.f90:10
\#4 0x0000000000405234 in func_trampoline () at test.f90:17
'''
The test gdb.fortran/func-trampoline.exp is added for testing the change
using O0 and O2 optimization level.
---
gdb/NEWS | 5 +-
gdb/doc/gdb.texinfo | 6 ++
gdb/infrun.c | 6 +-
gdb/infrun.h | 6 ++
gdb/stack.c | 8 ++
gdb/symtab.c | 31 +++++++
gdb/symtab.h | 5 ++
gdb/testsuite/gdb.fortran/func-trampoline.exp | 87 +++++++++++++++++++
gdb/testsuite/gdb.fortran/func-trampoline.f90 | 40 +++++++++
.../gdb.fortran/mixed-lang-stack.exp | 8 +-
10 files changed, 195 insertions(+), 7 deletions(-)
create mode 100644 gdb/testsuite/gdb.fortran/func-trampoline.exp
create mode 100644 gdb/testsuite/gdb.fortran/func-trampoline.f90
diff --git a/gdb/NEWS b/gdb/NEWS
index 5c618c0d38d..8100f7cd7b4 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -1773,8 +1773,9 @@ show skip-trampoline-functions
This setting is 'on' by default. When 'on' it controls whether GDB will
recognize function calls that have been marked as trampolines in the debug
info. It improves stepping behavior in that it steps over the trampoline
- code and hides it from the user. Currently, only DWARF trampolines are
- supported.
+ code and hides it from the user. It improves the printing of the stack by
+ hiding trampoline functions from the backtrace. Currently, only DWARF
+ trampolines are supported.
If this is turned off, GDB will handle @dfn{trampoline functions} the same
as any other function.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index f8dd7d8ec4e..af57610ddc3 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -6769,6 +6769,12 @@ execution until leaving the trampoline region. The @code{stepi} command
is not affected by the setting which is enabled by default. Currently, only
DWARF trampolines marked via DW_AT_trampoline are supported by this.
+When issuing a @code{backtrace}, if @code{skip-trampoline-functions} is set,
+@value{GDBN} will skip trampoline frames while printing the stack.
+
+Currently, only DWARF trampolines marked via DW_AT_trampoline are supported by
+this.
+
@item set skip-trampoline-functions off
Causes @value{GDBN} to completely ignore any trampoline information a compiler
might have emitted in its debug info. Trampolines will be treated like any
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 0b032ce94c0..9d1b85e9d1f 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -194,7 +194,7 @@ static bool detach_fork = true;
DW_AT_trampoline by the compiler. If false, GDB will ignore the
attribute. */
-static bool skip_trampoline_functions = true;
+bool skip_trampoline_functions = true;
bool debug_infrun = false;
static void
@@ -11031,8 +11031,8 @@ Options are 'forward' or 'reverse'."),
&skip_trampoline_functions, _("\
Set whether gdb attempts to hide trampolines marked in the debug info."), _("\
Show whether gdb attempts to hide trampolines marked in the debug info."), _("\
-If on, while stepping gdb will skip through functions and inlined functions\n\
-marked as trampolines by the compiler. If off, gdb will treat trampolines as\n\
+If on, gdb will skip through functions and inlined functions marked as\n\
+trampolines by the compiler. If off, gdb will treat trampolines as\n\
normal functions."),
nullptr, show_skip_trampoline_functions, &setlist,
&showlist);
diff --git a/gdb/infrun.h b/gdb/infrun.h
index 135d1fc350b..a5c6f317193 100644
--- a/gdb/infrun.h
+++ b/gdb/infrun.h
@@ -106,6 +106,12 @@ extern bool non_stop;
starting an inferior. */
extern bool disable_randomization;
+/* If set (default) GDB will step through functions/inlined subroutines marked
+ DW_AT_trampoline by the compiler. If false, GDB will ignore the
+ attribute. */
+
+extern bool skip_trampoline_functions;
+
/* Returns a unique identifier for the current stop. This can be used
to tell whether a command has proceeded the inferior past the
current location. */
diff --git a/gdb/stack.c b/gdb/stack.c
index f41f818cebb..fa217ae9f6f 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -1978,6 +1978,14 @@ backtrace_command_1 (const frame_print_options &fp_opts,
{
QUIT;
+ if (skip_trampoline_functions && in_trampoline_frame (fi))
+ {
+ /* Trampoline frames are not printed so they are not counted in
+ the backtrace limit. */
+ count++;
+ continue;
+ }
+
/* Don't use print_stack_frame; if an error() occurs it probably
means further attempts to backtrace would fail (on the other
hand, perhaps the code does or could be fixed to make sure
diff --git a/gdb/symtab.c b/gdb/symtab.c
index e5464551807..8931f50775c 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -4149,6 +4149,37 @@ in_trampoline_function (CORE_ADDR pc)
/* See symtab.h. */
+bool
+in_trampoline_frame (frame_info_ptr fi)
+{
+ /* For inline frames, they share the PC of their caller. We need to check
+ the frame's function directly, not look up the function at the PC.
+ Looking up by PC would return the caller's function not the inline
+ function itself.
+
+ For O2 optimized code, the compiler may inline trampoline wrappers into
+ regular functions. In such cases, looking up by PC would point to the
+ concrete regular function and incorrectly return false (not a trampoline).
+ By checking the inline frame's function directly via get_frame_function(),
+ we correctly identify when the inline frame itself is a trampoline. */
+ if (get_frame_type (fi) == INLINE_FRAME)
+ {
+ symbol *func = get_frame_function (fi);
+ return func != nullptr && TYPE_IS_TRAMPOLINE (func->type ());
+ }
+
+ /* For non-inline frames, use in_trampoline_function() which looks up only
+ the concrete function at the PC, ensuring we check the actual frame's
+ function and not any inlined code within it. */
+ std::optional<CORE_ADDR> pc;
+ if ((pc = get_frame_pc_if_available (fi)))
+ return in_trampoline_function (pc.value ());
+
+ return false;
+}
+
+/* See symtab.h. */
+
CORE_ADDR
find_function_trampoline_target (CORE_ADDR pc)
{
diff --git a/gdb/symtab.h b/gdb/symtab.h
index 10f64548f58..8a8d9f3f85f 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -2377,6 +2377,11 @@ extern bool in_trampoline_function (CORE_ADDR pc);
extern bool in_trampoline_code (CORE_ADDR pc);
+/* Return whether or not the pc of the current frame is within a block that
+ belongs to a function that is marked as a trampoline by the compiler. */
+
+extern bool in_trampoline_frame (frame_info_ptr);
+
/* Find the target of a trampoline function marked via the DW_AT_trampoline
attribute and return its address. Returns 0 if the pc is not contained
in a trampoline function (inlined or not). If DW_AT_trampoline
diff --git a/gdb/testsuite/gdb.fortran/func-trampoline.exp b/gdb/testsuite/gdb.fortran/func-trampoline.exp
new file mode 100644
index 00000000000..5216de25a45
--- /dev/null
+++ b/gdb/testsuite/gdb.fortran/func-trampoline.exp
@@ -0,0 +1,87 @@
+# Copyright 2026 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/> .
+
+# Test "backtrace" and "backtrace -n" commands for functions with trampoline
+# calls.
+
+require allow_fortran_tests
+
+if {![test_compiler_info {ifx-*} f90]} {
+ untested "This test is only applicable for IFX, which emits the\
+ trampoline DIE in Dwarf."
+ return
+}
+
+standard_testfile ".f90"
+load_lib fortran.exp
+
+# Initialize the test by running the program to the innermost
+# function name "second".
+
+proc init_test {opt_level} {
+ clean_restart ${::testfile}_${opt_level}
+ if {![fortran_runto_main]} {
+ return
+ }
+
+ # Set breakpoint inside the innermost function 'second'.
+ gdb_breakpoint "$::srcfile:$::inner_loc"
+ gdb_continue_to_breakpoint "innermost-body" ".*$::srcfile:$::inner_loc.*"
+}
+
+set inner_loc [gdb_get_line_number "second-breakpt"]
+set middle_loc [gdb_get_line_number "first-breakpt"]
+set outer_loc [gdb_get_line_number "main-outer-loc"]
+set fill "\[^\r\n\]*"
+
+# Test both O0 and O2 to verify trampoline handling works correctly
+# with and without optimization.
+foreach_with_prefix opt_level {O0 O2} {
+ if {[build_executable "failed to prepare" ${testfile}_${opt_level} ${srcfile} \
+ [list debug f90 "optimize=-${opt_level}"]]} {
+ continue
+ }
+
+ set binfile "${testfile}_${opt_level}"
+
+ if {[string match -nocase "O2" $opt_level]} {
+ # At O2, parameters may be optimized out
+ set inner_desc "second \\(.*\\) at ${fill}$srcfile:$inner_loc"
+ set middle_desc "first \\(.*\\) at ${fill}$srcfile:$middle_loc"
+ } else {
+ set inner_desc "second \\(x=20, y=9\\) at ${fill}$srcfile:$inner_loc"
+ set middle_desc "first \\(num1=16, num2=3\\) at ${fill}$srcfile:$middle_loc"
+ }
+ set outer_desc ".* at .*$srcfile:$outer_loc"
+
+ with_test_prefix "backtrace" {
+ init_test $opt_level
+
+ # Limit the backtrace to 3 frames and ensure both frames for first
+ # and second function are shown only and trampoline frames are filtered.
+ gdb_test "backtrace 3" [multi_line \
+ "#$decimal.* $inner_desc" \
+ "#$decimal.* $middle_desc" \
+ "#$decimal.* $outer_desc.*"]
+ }
+
+ with_test_prefix "backtrace outerframes" {
+ init_test $opt_level
+
+ gdb_test "backtrace -3" [multi_line \
+ "#$decimal.* $middle_desc" \
+ "#$decimal.* $outer_desc.*"]
+ }
+}
diff --git a/gdb/testsuite/gdb.fortran/func-trampoline.f90 b/gdb/testsuite/gdb.fortran/func-trampoline.f90
new file mode 100644
index 00000000000..bb9ce7f3491
--- /dev/null
+++ b/gdb/testsuite/gdb.fortran/func-trampoline.f90
@@ -0,0 +1,40 @@
+! Copyright 2026 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/> .
+
+! Source code for func-trampoline.exp.
+
+!DIR$ ATTRIBUTES NOINLINE :: second
+integer(kind=4) function second(x, y)
+ integer(kind=4), intent(in) :: x
+ integer(kind=4), intent(in) :: y
+
+ second = x * y ! second-breakpt
+end function
+
+integer(kind=4) function first(num1, num2)
+ integer(kind=4), intent(in) :: num1
+ integer(kind=4), intent(in) :: num2
+
+ first = second (num1 + 4, num2 * 3) ! first-breakpt
+end function
+
+program func_trampoline
+ integer(kind=4) :: total
+
+ total = first(16, 3) ! main-outer-loc
+
+ write(*,*) "Result is ", total, "\n"
+ ! Expected: 180
+end program func_trampoline
diff --git a/gdb/testsuite/gdb.fortran/mixed-lang-stack.exp b/gdb/testsuite/gdb.fortran/mixed-lang-stack.exp
index 43f77d3eb66..b470554988e 100644
--- a/gdb/testsuite/gdb.fortran/mixed-lang-stack.exp
+++ b/gdb/testsuite/gdb.fortran/mixed-lang-stack.exp
@@ -63,6 +63,10 @@ proc run_tests { lang } {
set e_arg "\['\"\]abcdef\['\"\]"
set 1b_args "\[^\r\n\]+$e_arg\[^\r\n\]+"
set 1g_args "obj=\[^\r\n\]+"
+ # Generic decimal number is checked in regex for Frame #8 and #9 to
+ # handle filtered trampoline frames. Since Frame#8 and Frame#10 are
+ # set to trampoline in DWARF by Intel® Fortran Compiler (ifx), they
+ # are not shown by the backtrace command.
set bt_stack \
[multi_line \
"#0\\s+breakpt \\(\\) at \[^\r\n\]+" \
@@ -73,8 +77,8 @@ proc run_tests { lang } {
"#5\\s+$hex in mixed_func_1d \\(\[^\r\n\]+\\) at \[^\r\n\]+" \
"#6\\s+$hex in mixed_func_1c \\(\[^\r\n\]+\\) at \[^\r\n\]+" \
"#7\\s+$hex in mixed_func_1b \\($1b_args\\) at \[^\r\n\]+" \
- "#8\\s+$hex in mixed_func_1a \\(\\) at \[^\r\n\]+" \
- "#9\\s+$hex in mixed_stack_main \\(\\) at \[^\r\n\]+" ]
+ "#$::decimal\\s+$hex in mixed_func_1a \\(\\) at \[^\r\n\]+" \
+ "#$::decimal\\s+$hex in mixed_stack_main \\(\\) at \[^\r\n\]+" ]
set main_args "argc=1, argv=${hex}( \[^\r\n\]+)?"
set bt_stack_kfail \
[multi_line \
--
2.34.1
________________________________________
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 (89) 99143-0
www.intel.de
Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman
Chairperson of the Supervisory Board: Sonja Pierer
Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: [PATCH v11 04/10] gdb: Skip trampoline frames for the backtrace command.
2026-08-03 19:34 ` [PATCH v11 04/10] gdb: Skip trampoline frames for the backtrace command Abdul Basit Ijaz
@ 2026-10-21 20:50 ` Tom Tromey
2026-10-22 12:11 ` Ijaz, Abdul B
0 siblings, 1 reply; 32+ messages in thread
From: Tom Tromey @ 2026-10-21 20:50 UTC (permalink / raw)
To: Abdul Basit Ijaz; +Cc: gdb-patches, JiniSusan.George, tom, eliz
>>>>> Abdul Basit Ijaz <abdul.b.ijaz@intel.com> writes:
> This change filters trampoline functions when the option
> 'skip-trampoline-functions' is set to 'on' for the backtrace command.
> Before the change, GDB prints the frames indicated by the compiler with
> DIE "DW_AT_trampoline" in the backtrace, but for better user experience,
> all such frames can be hidden from the user.
> For O2 optimized code where inlined trampoline wrappers are inlined into
> regular functions. Check the frame's function directly for inline frames
> instead of looking up by PC, which would incorrectly return the caller's
> function.
> The test 'gdb.fortran/mixed-lang-stack' test used to fail for the IFX
> compiler because of extra trampoline frames in the backtrace. After the
> commit, those trampoline frames are filtered and test is updated accordingly.
It's maybe somewhat unfortunate that this doesn't follow the precedent
set by Python frame filters, where a frame can be marked "elided" and
then is either printed indented (the default) or hidden (with "bt
-hide").
> diff --git a/gdb/stack.c b/gdb/stack.c
> index f41f818cebb..fa217ae9f6f 100644
> --- a/gdb/stack.c
> +++ b/gdb/stack.c
> @@ -1978,6 +1978,14 @@ backtrace_command_1 (const frame_print_options &fp_opts,
> {
> QUIT;
> + if (skip_trampoline_functions && in_trampoline_frame (fi))
> + {
> + /* Trampoline frames are not printed so they are not counted in
> + the backtrace limit. */
> + count++;
> + continue;
> + }
What happens if I "break 0x..." using an address in a trampoline
function and then "bt" from there?
I think this means the frame won't be printed. But this could be
confusing because gdb will be lying about the PC.
In this scenario what would "disassemble" by itself show?
That is, I somewhat suspect that there should be a special case here for
the "live" frame.
Tom
^ permalink raw reply [flat|nested] 32+ messages in thread* RE: [PATCH v11 04/10] gdb: Skip trampoline frames for the backtrace command.
2026-10-21 20:50 ` Tom Tromey
@ 2026-10-22 12:11 ` Ijaz, Abdul B
0 siblings, 0 replies; 32+ messages in thread
From: Ijaz, Abdul B @ 2026-10-22 12:11 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches, JiniSusan.George, eliz, Ijaz, Abdul B
Thanks Tom, for the feedback.
Please see the inline reply below:
Tom> It's maybe somewhat unfortunate that this doesn't follow the precedent set by Python frame filters, where a frame can be marked "elided" and then is either printed indented (the default) or hidden (with "bt -hide").
Abdul> "bt -hide" is a backtrace option, but frames can currently only be marked as elided by a Python frame filter , and only the Python printing code in py-framefilter.c honors it; the built-in backtrace loop never elides frames.
Using elision for trampolines would be possible, but needs:
- the built-in backtrace (no filters, or "bt -no-filters") to attach a trampoline frame as elided to the frame it calls, print it indented, and drop it for "bt -hide";
- the same for the frames passed to Python frame filters, so that trampolines are elided and not printed as normal frames when a user filter is loaded;
- the MI -stack-list-* commands to report them as "children", like the Python frame filter code does for MI.
It would also change the default: trampolines would be shown, indented, unless "bt -hide" is used, while this series hides them by default because the compiler marks them with DW_AT_trampoline so that a debugger does not show them. On the positive side it would solve the "live" frame issue below for free, since a trampoline at frame #0 has no inner frame to be elided under and would be printed normally. Stepping, "up", "finish" and "return" are not affected either way.
Would you prefer that then I go with elision, or otherwise keep hiding trampoline frames by default, controlled by skip-trampoline-functions?
>> + if (skip_trampoline_functions && in_trampoline_frame (fi))
>> + {
>> + /* Trampoline frames are not printed so they are not counted in
>> + the backtrace limit. */
>> + count++;
>> + continue;
>> + }
Tom> What happens if I "break 0x..." using an address in a trampoline function and then "bt" from there?
Tom> I think this means the frame won't be printed. But this could be confusing because gdb will be lying about the PC.
Tom> In this scenario what would "disassemble" by itself show?
Tom> That is, I somewhat suspect that there should be a special case here for the "live" frame.
Abdul > You are right: with the default "skip-trampoline-functions on", frame #0 is not printed, while "frame", "info frame" and "disassemble" all show the trampoline, so the backtrace does not match the PC. Only with "set skip-trampoline-functions off" does "bt" show it. For example, with the gdb.dwarf2/dw2-function-trampolines.exp program:
'''
(gdb) info address trampoline_label
Symbol "trampoline_label" is at 0x55555555514f in a file compiled without debugging.
(gdb) info address trampoline_label
Symbol "trampoline_label" is at 0x55555555514f in a file compiled without debugging.
(gdb) break *0x55555555514f
Breakpoint 2 at 0x55555555514f
(gdb) continue
Continuing.
Breakpoint 2, 0x000055555555514f in trampoline ()
(gdb) bt
#1 0x00005555555551ec in main () at gdb.dwarf2/dw2-function-trampolines.c:73
(gdb) x/i $pc
=> 0x55555555514f <trampoline+8>: mov 0x2ebf(%rip),%eax # 0x555555558014 <global_var>
(gdb) set skip-trampoline-functions off
(gdb) bt
#0 0x000055555555514f in trampoline ()
#1 0x00005555555551ec in main () at gdb.dwarf2/dw2-function-trampolines.c:73
'''
If we keep hiding trampoline frames instead of eliding them, for v12 I will always print the innermost frame to fix it, even if it is a trampoline, and only hide the trampoline frames further out (with elision this happens anyway). Either way I will add a test that stops at a trampoline address with "break *ADDR" and checks that "bt" shows the trampoline as frame #0. So this special case will be handled.
Best Regards,
Abdul Basit
-----Original Message-----
From: Tom Tromey <tom@tromey.com>
Sent: Wednesday, October 21, 2026 10:51 PM
To: Ijaz, Abdul B <abdul.b.ijaz@intel.com>
Cc: gdb-patches@sourceware.org; JiniSusan.George@amd.com; tom@tromey.com; eliz@gnu.org
Subject: Re: [PATCH v11 04/10] gdb: Skip trampoline frames for the backtrace command.
>>>>> Abdul Basit Ijaz <abdul.b.ijaz@intel.com> writes:
> This change filters trampoline functions when the option
> 'skip-trampoline-functions' is set to 'on' for the backtrace command.
> Before the change, GDB prints the frames indicated by the compiler
> with DIE "DW_AT_trampoline" in the backtrace, but for better user
> experience, all such frames can be hidden from the user.
> For O2 optimized code where inlined trampoline wrappers are inlined
> into regular functions. Check the frame's function directly for
> inline frames instead of looking up by PC, which would incorrectly
> return the caller's function.
> The test 'gdb.fortran/mixed-lang-stack' test used to fail for the IFX
> compiler because of extra trampoline frames in the backtrace. After
> the commit, those trampoline frames are filtered and test is updated accordingly.
It's maybe somewhat unfortunate that this doesn't follow the precedent set by Python frame filters, where a frame can be marked "elided" and then is either printed indented (the default) or hidden (with "bt -hide").
> diff --git a/gdb/stack.c b/gdb/stack.c index f41f818cebb..fa217ae9f6f
> 100644
> --- a/gdb/stack.c
> +++ b/gdb/stack.c
> @@ -1978,6 +1978,14 @@ backtrace_command_1 (const frame_print_options &fp_opts,
> {
> QUIT;
> + if (skip_trampoline_functions && in_trampoline_frame (fi))
> + {
> + /* Trampoline frames are not printed so they are not counted in
> + the backtrace limit. */
> + count++;
> + continue;
> + }
What happens if I "break 0x..." using an address in a trampoline function and then "bt" from there?
I think this means the frame won't be printed. But this could be confusing because gdb will be lying about the PC.
In this scenario what would "disassemble" by itself show?
That is, I somewhat suspect that there should be a special case here for the "live" frame.
Tom
________________________________________
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 (89) 99143-0
www.intel.de
Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman
Chairperson of the Supervisory Board: Sonja Pierer
Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v11 05/10] gdb: Skip trampoline functions for the finish and reverse-finish commands.
2026-08-03 19:34 [PATCH v11 00/10] GDB support for DW_AT_trampoline Abdul Basit Ijaz
` (3 preceding siblings ...)
2026-08-03 19:34 ` [PATCH v11 04/10] gdb: Skip trampoline frames for the backtrace command Abdul Basit Ijaz
@ 2026-08-03 19:34 ` Abdul Basit Ijaz
2026-10-21 20:52 ` Tom Tromey
2026-08-03 19:34 ` [PATCH v11 06/10] gdb: Skip trampoline functions for the up command Abdul Basit Ijaz
` (5 subsequent siblings)
10 siblings, 1 reply; 32+ messages in thread
From: Abdul Basit Ijaz @ 2026-08-03 19:34 UTC (permalink / raw)
To: gdb-patches; +Cc: abdul.b.ijaz, JiniSusan.George, tom, eliz
This change skips trampoline functions when the option
'skip-trampoline-functions' is set to 'on' for the finish or reverse-finish
command. Before this change, for these commands GDB returns to the trampoline
function indicated by the compiler with DIE "DW_AT_trampoline". For better
user experience, all such frames can be hidden from the user.
In this example the IFX compiler emits "DW_AT_trampoline" tag for the 'first'
and 'second' trampoline functions like following:
function second (x, y) result(z)
integer, intent(in) :: x, y
integer :: z
z = x * y ! breakpt-finish
end function second
function first (num1, num2) result(total)
integer, intent(in) :: num1, num2
integer :: total
total = second (num1 + 4, num2 * 3) ! first-breakpt
total = total + 30
end function first
Related Dwarf:
0x0000013f: DW_TAG_subprogram
DW_AT_low_pc (0x0000000000404350)
DW_AT_high_pc (0x000000000040435f)
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_linkage_name ("second_.t74p.t75p")
DW_AT_name ("second_.t74p.t75p")
DW_AT_trampoline ("second_")
0x0000015a: DW_TAG_subprogram
DW_AT_low_pc (0x00000000004044a0)
DW_AT_high_pc (0x00000000004044af)
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_linkage_name ("first_.t104p.t105p")
DW_AT_name ("first_.t104p.t105p")
DW_AT_trampoline ("first_")
Before this change, the finish command output looks like:
'''
(gdb) finish
Run till exit from #0 second (x=20, y=9) at test.f90:4
0x0000000000405209 in second_.t74p.t75p () at test.f90:12
12 end function first
Value returned is $1 = 180
'''
The reverse-finish command output in this test before the change:
'''
(gdb) reverse-finish
Run back to call of #0 second (x=20, y=9) at test.f90:4
0x0000000000405204 in second_.t74p.t75p () at test.f90:12
12 end function first
'''
After this change:
'''
(gdb) finish
Run till exit from #0 second (x=20, y=9) at test.f90:4
0x00000000004051e3 in first (num1=16, num2=3) at test.f90:10
10 total = second (num1 + 4, num2 * 3) ! first-breakpt
Value returned is $1 = 180
(gdb) reverse-finish
Run back to call of #0 second (x=20, y=9) at test.f90:4
0x00000000004051de in first (num1=16, num2=3) at test.f90:10
10 total = second (num1 + 4, num2 * 3) ! first-breakpt
'''
The test gdb.fortran/func-trampoline.exp is updated for testing the finish
command. The test gdb.reverse/finish-reverse-trampoline.exp is
added for testing the reverse-finish command.
---
gdb/NEWS | 5 +-
gdb/doc/gdb.texinfo | 4 ++
gdb/infcmd.c | 12 ++++
gdb/infrun.c | 9 +++
gdb/infrun.h | 5 ++
gdb/testsuite/gdb.fortran/func-trampoline.exp | 17 +++++-
.../gdb.reverse/finish-reverse-trampoline.exp | 56 +++++++++++++++++++
7 files changed, 104 insertions(+), 4 deletions(-)
create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-trampoline.exp
diff --git a/gdb/NEWS b/gdb/NEWS
index 8100f7cd7b4..ed035f25303 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -1774,8 +1774,9 @@ show skip-trampoline-functions
recognize function calls that have been marked as trampolines in the debug
info. It improves stepping behavior in that it steps over the trampoline
code and hides it from the user. It improves the printing of the stack by
- hiding trampoline functions from the backtrace. Currently, only DWARF
- trampolines are supported.
+ hiding the trampoline frames from the backtrace and skips trampoline
+ functions while returning from the target function of a trampoline call.
+ Currently, only DWARF trampolines are supported.
If this is turned off, GDB will handle @dfn{trampoline functions} the same
as any other function.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index af57610ddc3..b9dd6c14809 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -6772,6 +6772,10 @@ DWARF trampolines marked via DW_AT_trampoline are supported by this.
When issuing a @code{backtrace}, if @code{skip-trampoline-functions} is set,
@value{GDBN} will skip trampoline frames while printing the stack.
+When issuing a @code{finish} or @code{reverse-finish}, if
+@code{skip-trampoline-functions} is set, @value{GDBN} will skip trampoline
+frames while returning from the target function.
+
Currently, only DWARF trampolines marked via DW_AT_trampoline are supported by
this.
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 3e943123519..451777e3087 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1952,6 +1952,18 @@ finish_command (const char *arg, int from_tty)
error (_("\"%ps\" not meaningful in the outermost frame."),
styled_string (command_style.style (), "finish"));
+ if (skip_trampoline_functions)
+ {
+ for (int i = 0; (SAFE_TRAMPOLINE_CHAIN (i, frame)
+ && in_trampoline_frame (frame)); ++i)
+ frame = get_prev_frame (frame);
+
+ if (frame == nullptr)
+ error (_("\"finish\" not meaningful in the outermost non-trampoline \
+frame. Consider running \"set skip-trampoline-functions off\", to stop in \
+trampoline frames for the \"finish\" command."));
+ }
+
clear_proceed_status (0);
tp = inferior_thread ();
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 9d1b85e9d1f..024bf30aced 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -8211,6 +8211,15 @@ process_event_stop_test (struct execution_control_state *ecs)
keep_going (ecs);
return;
}
+ else if (skip_trampoline_functions && in_trampoline_code (stop_pc))
+ {
+ /* While reverse stepping if we are in trampoline code
+ we will just continue single step in the hope of leaving the
+ trampoline again soon. Uses in_trampoline_code() to detect
+ both inline and concrete trampolines. */
+ keep_going (ecs);
+ return;
+ }
}
/* This always returns the sal for the inner-most frame when we are in a
diff --git a/gdb/infrun.h b/gdb/infrun.h
index a5c6f317193..019ea86c43f 100644
--- a/gdb/infrun.h
+++ b/gdb/infrun.h
@@ -80,6 +80,11 @@ infrun_debug_show_threads (const char *title, ThreadRange threads)
information. */
#define MAX_TRAMPOLINE_CHAIN_SIZE 10
+/* True if the trampoline index "i" is less then the maximum allowed size
+ of a trampoline chain. */
+#define SAFE_TRAMPOLINE_CHAIN(i, frame) \
+ (i < MAX_TRAMPOLINE_CHAIN_SIZE && (frame != nullptr))
+
/* Nonzero if we want to give control to the user when we're notified
of shared library events by the dynamic linker. */
extern int stop_on_solib_events;
diff --git a/gdb/testsuite/gdb.fortran/func-trampoline.exp b/gdb/testsuite/gdb.fortran/func-trampoline.exp
index 5216de25a45..f330ac54ef2 100644
--- a/gdb/testsuite/gdb.fortran/func-trampoline.exp
+++ b/gdb/testsuite/gdb.fortran/func-trampoline.exp
@@ -13,8 +13,8 @@
# 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 "backtrace" and "backtrace -n" commands for functions with trampoline
-# calls.
+# Test "backtrace", "backtrace -n" and "finish" commands for functions with
+# trampoline calls.
require allow_fortran_tests
@@ -84,4 +84,17 @@ foreach_with_prefix opt_level {O0 O2} {
"#$decimal.* $middle_desc" \
"#$decimal.* $outer_desc.*"]
}
+
+ if {[string match -nocase "O2" $opt_level]} {
+ continue
+ }
+
+ with_test_prefix "finish" {
+ init_test $opt_level
+
+ gdb_test "finish" [multi_line \
+ "Run till exit from #0 $fill second \\(x=20, y=9\\) $fill" \
+ "${fill}first \\(num1=16, num2=3\\)${fill}" \
+ "${fill}(\r\nValue returned is $valnum_re = 180)"]
+ }
}
diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-trampoline.exp b/gdb/testsuite/gdb.reverse/finish-reverse-trampoline.exp
new file mode 100644
index 00000000000..fb342eca030
--- /dev/null
+++ b/gdb/testsuite/gdb.reverse/finish-reverse-trampoline.exp
@@ -0,0 +1,56 @@
+# Copyright 2026 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/>.
+
+# Test "reverse-finish" command for functions with trampoline.
+
+require supports_reverse allow_fortran_tests
+
+if {![test_compiler_info {ifx-*} f90]} {
+ untested "This test is only applicable for IFX, which emits the\
+ trampoline DIE in Dwarf."
+ return
+}
+
+load_lib fortran.exp
+
+set testfile finish-reverse-trampoline
+set srcfile "${srcdir}/gdb.fortran/func-trampoline.f90"
+set binfile [standard_output_file $testfile]
+
+if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
+ {debug f90}]} {
+ return
+}
+
+if {![fortran_runto_main]} {
+ return
+}
+
+set inner_loc [gdb_get_line_number "second-breakpt"]
+
+if [supports_process_record] {
+ # Activate process record/replay
+ gdb_test_no_output "record" "turn on process record"
+}
+
+# Set breakpoint inside the innermost function 'second'.
+gdb_breakpoint "$srcfile:$inner_loc"
+gdb_continue_to_breakpoint "innermost-body" ".*$srcfile:$inner_loc.*"
+
+gdb_test "reverse-finish" [multi_line \
+ "Run back to call of #0 second \\(x=20, y=9\\).*" \
+ ".*in first \\(num1=16, num2=3\\).*"]
+
+gdb_test "frame" "#0.*first.*" "Frame 0 shows first function"
--
2.34.1
________________________________________
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 (89) 99143-0
www.intel.de
Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman
Chairperson of the Supervisory Board: Sonja Pierer
Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: [PATCH v11 05/10] gdb: Skip trampoline functions for the finish and reverse-finish commands.
2026-08-03 19:34 ` [PATCH v11 05/10] gdb: Skip trampoline functions for the finish and reverse-finish commands Abdul Basit Ijaz
@ 2026-10-21 20:52 ` Tom Tromey
2026-10-22 12:31 ` Ijaz, Abdul B
0 siblings, 1 reply; 32+ messages in thread
From: Tom Tromey @ 2026-10-21 20:52 UTC (permalink / raw)
To: Abdul Basit Ijaz; +Cc: gdb-patches, JiniSusan.George, tom, eliz
>>>>> Abdul Basit Ijaz <abdul.b.ijaz@intel.com> writes:
> This change skips trampoline functions when the option
> 'skip-trampoline-functions' is set to 'on' for the finish or reverse-finish
> command. Before this change, for these commands GDB returns to the trampoline
> function indicated by the compiler with DIE "DW_AT_trampoline". For better
> user experience, all such frames can be hidden from the user.
Ah, ok. I was looking at the patches mostly in order, so I missed that
there was a separate patch for "finish".
> + for (int i = 0; (SAFE_TRAMPOLINE_CHAIN (i, frame)
> + && in_trampoline_frame (frame)); ++i)
> + frame = get_prev_frame (frame);
This snippet appears in several places and I think it would be better as
a function.
Then maybe the SAFE_TRAMPOLINE_CHAIN macro could be dispensed with as
well.
Tom
^ permalink raw reply [flat|nested] 32+ messages in thread
* RE: [PATCH v11 05/10] gdb: Skip trampoline functions for the finish and reverse-finish commands.
2026-10-21 20:52 ` Tom Tromey
@ 2026-10-22 12:31 ` Ijaz, Abdul B
0 siblings, 0 replies; 32+ messages in thread
From: Ijaz, Abdul B @ 2026-10-22 12:31 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches, JiniSusan.George, eliz, Ijaz, Abdul B
Thanks Tom, for the feedback.
Please see the inline reply below:
>> + for (int i = 0; (SAFE_TRAMPOLINE_CHAIN (i, frame)
>> + && in_trampoline_frame (frame)); ++i)
>> + frame = get_prev_frame (frame);
Tom> This snippet appears in several places and I think it would be better as a function.
Tom> Then maybe the SAFE_TRAMPOLINE_CHAIN macro could be dispensed with as well.
Abdul> Agreed. For v12 I will add a function, next to in_trampoline_frame. It will be added in this patch, the first one that needs it, and used for "finish", "up", the MI -stack-list-frames and -stack-list-arguments commands and the Python frame filters. The chain limit moves into the function, so SAFE_TRAMPOLINE_CHAIN goes away.
The "return" command handling is different: it pops the trampoline frames one by one and looks at the new current frame each time, so it keeps its own loop, but without the macro.
Best Regards,
Abdul Basit
-----Original Message-----
From: Tom Tromey <tom@tromey.com>
Sent: Wednesday, October 21, 2026 10:53 PM
To: Ijaz, Abdul B <abdul.b.ijaz@intel.com>
Cc: gdb-patches@sourceware.org; JiniSusan.George@amd.com; tom@tromey.com; eliz@gnu.org
Subject: Re: [PATCH v11 05/10] gdb: Skip trampoline functions for the finish and reverse-finish commands.
>>>>> Abdul Basit Ijaz <abdul.b.ijaz@intel.com> writes:
> This change skips trampoline functions when the option
> 'skip-trampoline-functions' is set to 'on' for the finish or
> reverse-finish command. Before this change, for these commands GDB
> returns to the trampoline function indicated by the compiler with DIE
> "DW_AT_trampoline". For better user experience, all such frames can be hidden from the user.
Ah, ok. I was looking at the patches mostly in order, so I missed that there was a separate patch for "finish".
> + for (int i = 0; (SAFE_TRAMPOLINE_CHAIN (i, frame)
> + && in_trampoline_frame (frame)); ++i)
> + frame = get_prev_frame (frame);
This snippet appears in several places and I think it would be better as a function.
Then maybe the SAFE_TRAMPOLINE_CHAIN macro could be dispensed with as well.
Tom
________________________________________
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 (89) 99143-0
www.intel.de
Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman
Chairperson of the Supervisory Board: Sonja Pierer
Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v11 06/10] gdb: Skip trampoline functions for the up command.
2026-08-03 19:34 [PATCH v11 00/10] GDB support for DW_AT_trampoline Abdul Basit Ijaz
` (4 preceding siblings ...)
2026-08-03 19:34 ` [PATCH v11 05/10] gdb: Skip trampoline functions for the finish and reverse-finish commands Abdul Basit Ijaz
@ 2026-08-03 19:34 ` Abdul Basit Ijaz
2026-10-21 20:53 ` Tom Tromey
2026-08-03 19:34 ` [PATCH v11 07/10] gdb: Skip trampoline functions for the return command Abdul Basit Ijaz
` (4 subsequent siblings)
10 siblings, 1 reply; 32+ messages in thread
From: Abdul Basit Ijaz @ 2026-08-03 19:34 UTC (permalink / raw)
To: gdb-patches; +Cc: abdul.b.ijaz, JiniSusan.George, tom, eliz
This change skips trampoline functions when the option
'skip-trampoline-functions' is set to 'on' for the up command. Before this
change, GDB processes trampoline functions indicated by the compiler with
DIE "DW_AT_trampoline" and stops at the trampoline function for the 'up'
command. For better user experience, all such frames can be
skipped and hidden from the user.
In this example the IFX compiler emits "DW_AT_trampoline" tag for the 'first'
and 'second' trampoline functions like following:
function second (x, y) result(z)
integer, intent(in) :: x, y
integer :: z
z = x * y ! breakpt-up
end function second
function first (num1, num2) result(total)
integer, intent(in) :: num1, num2
integer :: total
total = second (num1 + 4, num2 * 3) ! first-breakpt
total = total + 30
end function first
Related Dwarf:
0x0000013f: DW_TAG_subprogram
DW_AT_low_pc (0x0000000000404350)
DW_AT_high_pc (0x000000000040435f)
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_linkage_name ("second_.t74p.t75p")
DW_AT_name ("second_.t74p.t75p")
DW_AT_trampoline ("second_")
0x0000015a: DW_TAG_subprogram
DW_AT_low_pc (0x00000000004044a0)
DW_AT_high_pc (0x00000000004044af)
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_linkage_name ("first_.t104p.t105p")
DW_AT_name ("first_.t104p.t105p")
DW_AT_trampoline ("first_")
Before this change, the 'up' command output looks like:
'''
(gdb) up
\#1 0x0000000000405209 in second_.t74p.t75p () at test.f90:12
12 end function first
'''
After this change:
'''
(gdb) up
\#2 0x00000000004051e3 in first (num1=16, num2=3) at test.f90:10
10 total = second (num1 + 4, num2 * 3) ! first-breakpt
'''
The test gdb.fortran/func-trampoline.exp is updated for testing this change.
---
gdb/doc/gdb.texinfo | 2 +-
gdb/stack.c | 7 +++++++
gdb/testsuite/gdb.fortran/func-trampoline.exp | 12 ++++++++++--
3 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index b9dd6c14809..ee94ad09fd9 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -6772,7 +6772,7 @@ DWARF trampolines marked via DW_AT_trampoline are supported by this.
When issuing a @code{backtrace}, if @code{skip-trampoline-functions} is set,
@value{GDBN} will skip trampoline frames while printing the stack.
-When issuing a @code{finish} or @code{reverse-finish}, if
+When issuing a @code{finish}, @code{reverse-finish} or @code{up}, if
@code{skip-trampoline-functions} is set, @value{GDBN} will skip trampoline
frames while returning from the target function.
diff --git a/gdb/stack.c b/gdb/stack.c
index fa217ae9f6f..8b1644ddb6e 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -2636,6 +2636,13 @@ up_silently_base (const char *count_exp)
frame = find_relative_frame (get_selected_frame ("No stack."), &count);
if (count != 0 && count_exp == NULL)
error (_("Initial frame selected; you cannot go up."));
+
+ if (skip_trampoline_functions)
+ {
+ for (int i = 0; (SAFE_TRAMPOLINE_CHAIN (i, frame)
+ && in_trampoline_frame (frame)); ++i)
+ frame = get_prev_frame (frame);
+ }
select_frame (frame);
}
diff --git a/gdb/testsuite/gdb.fortran/func-trampoline.exp b/gdb/testsuite/gdb.fortran/func-trampoline.exp
index f330ac54ef2..ce9f14160aa 100644
--- a/gdb/testsuite/gdb.fortran/func-trampoline.exp
+++ b/gdb/testsuite/gdb.fortran/func-trampoline.exp
@@ -13,8 +13,8 @@
# 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 "backtrace", "backtrace -n" and "finish" commands for functions with
-# trampoline calls.
+# Test "backtrace", "backtrace -n", "finish" and "up" commands for
+# functions with trampoline calls.
require allow_fortran_tests
@@ -97,4 +97,12 @@ foreach_with_prefix opt_level {O0 O2} {
"${fill}first \\(num1=16, num2=3\\)${fill}" \
"${fill}(\r\nValue returned is $valnum_re = 180)"]
}
+
+ with_test_prefix "up" {
+ init_test $opt_level
+
+ gdb_test "up" [multi_line \
+ "#$decimal.* $middle_desc" \
+ "${fill}first = second \\(num1 \\+ 4, num2 \\* 3\\).*${fill}"]
+ }
}
--
2.34.1
________________________________________
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 (89) 99143-0
www.intel.de
Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman
Chairperson of the Supervisory Board: Sonja Pierer
Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: [PATCH v11 06/10] gdb: Skip trampoline functions for the up command.
2026-08-03 19:34 ` [PATCH v11 06/10] gdb: Skip trampoline functions for the up command Abdul Basit Ijaz
@ 2026-10-21 20:53 ` Tom Tromey
2026-10-22 13:01 ` Tom Tromey
0 siblings, 1 reply; 32+ messages in thread
From: Tom Tromey @ 2026-10-21 20:53 UTC (permalink / raw)
To: Abdul Basit Ijaz; +Cc: gdb-patches, JiniSusan.George, tom, eliz
>>>>> Abdul Basit Ijaz <abdul.b.ijaz@intel.com> writes:
> This change skips trampoline functions when the option
> 'skip-trampoline-functions' is set to 'on' for the up command. Before this
> change, GDB processes trampoline functions indicated by the compiler with
> DIE "DW_AT_trampoline" and stops at the trampoline function for the 'up'
> command. For better user experience, all such frames can be
> skipped and hidden from the user.
Why "up" but not "down"?
Tom
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v11 06/10] gdb: Skip trampoline functions for the up command.
2026-10-21 20:53 ` Tom Tromey
@ 2026-10-22 13:01 ` Tom Tromey
2026-10-22 14:02 ` Ijaz, Abdul B
0 siblings, 1 reply; 32+ messages in thread
From: Tom Tromey @ 2026-10-22 13:01 UTC (permalink / raw)
To: Tom Tromey; +Cc: Abdul Basit Ijaz, gdb-patches, JiniSusan.George, eliz
>>>>> "Tom" == Tom Tromey <tom@tromey.com> writes:
>>>>> Abdul Basit Ijaz <abdul.b.ijaz@intel.com> writes:
>> This change skips trampoline functions when the option
>> 'skip-trampoline-functions' is set to 'on' for the up command. Before this
>> change, GDB processes trampoline functions indicated by the compiler with
>> DIE "DW_AT_trampoline" and stops at the trampoline function for the 'up'
>> command. For better user experience, all such frames can be
>> skipped and hidden from the user.
Tom> Why "up" but not "down"?
I was thinking about this last night and wondering how this change
interacts with the "frame" command as well.
Tom
^ permalink raw reply [flat|nested] 32+ messages in thread
* RE: [PATCH v11 06/10] gdb: Skip trampoline functions for the up command.
2026-10-22 13:01 ` Tom Tromey
@ 2026-10-22 14:02 ` Ijaz, Abdul B
0 siblings, 0 replies; 32+ messages in thread
From: Ijaz, Abdul B @ 2026-10-22 14:02 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches, JiniSusan.George, eliz, Ijaz, Abdul B
Thanks Tom, for the feedback.
>> This change skips trampoline functions when the option
>> 'skip-trampoline-functions' is set to 'on' for the up command. Before
>> this change, GDB processes trampoline functions indicated by the
>> compiler with DIE "DW_AT_trampoline" and stops at the trampoline function for the 'up'
>> command. For better user experience, all such frames can be skipped
>> and hidden from the user.
Tom> Why "up" but not "down"?
Abdul> No reason and just missed, but will be added in V12. The "down" command should skip trampoline frames as well;
Currently using v11 patch, "down" command from the frame outside a trampoline selects the trampoline, which "bt" does not show. With ifx and gdb.fortran/func-trampoline.f90 (func_trampoline -> first_.t95p.t96p -> first -> second_.t74p.t75p -> second), stopped in "second":
(gdb) bt
#0 second (x=20, y=9) at func-trampoline.f90:23
#2 0x00000000004052a3 in first (num1=16, num2=3) at func-trampoline.f90:30
#4 0x00000000004052f4 in func_trampoline () at func-trampoline.f90:36
(gdb) up
#2 0x00000000004052a3 in first (num1=16, num2=3) at func-trampoline.f90:30
(gdb) down
#1 0x00000000004052c9 in second_.t74p.t75p () at func-trampoline.f90:31
For v12 "down" will skip trampoline frames too, stopping at the innermost frame even if that is a trampoline.
Tom> I was thinking about this last night and wondering how this change interacts with the "frame" command as well.
The "frame" command works as expected. Trampoline frames always exist; they are only skipped by commands like "backtrace", "finish" or "up", where they do not add useful information. If the user wants to select a trampoline frame, "frame N" (and "frame level", "frame function", ...) still selects it, with its real level:
(gdb) frame 1
#1 0x00000000004052c9 in second_.t74p.t75p () at func-trampoline.f90:31
(gdb) frame 0
#0 second (x=20, y=9) at func-trampoline.f90:23
"frame apply all", "frame apply N" are different, though: they walk all frames, so they also run the command in the trampoline frames that "bt" does not show.
(gdb) frame apply all -c print num1
#0 second (x=20, y=9) at func-trampoline.f90:23
No symbol "num1" in current context.
#1 0x00000000004052c9 in second_.t74p.t75p () at func-trampoline.f90:31
No symbol "num1" in current context.
#2 0x00000000004052a3 in first (num1=16, num2=3) at func-trampoline.f90:30
$1 = 16
#3 0x00000000004053c9 in first_.t95p.t96p () at func-trampoline.f90:40
No symbol "num1" in current context.
#4 0x00000000004052f4 in func_trampoline () at func-trampoline.f90:36
No symbol "num1" in current context.
For v12 I will make them skip trampoline frames like "bt" (or follow whatever we decide for "bt" in 04/10), and add tests accordingly.
Thanks & Best Regards,
Abdul Basit
-----Original Message-----
From: Tom Tromey <tom@tromey.com>
Sent: Thursday, October 22, 2026 3:02 PM
To: Tom Tromey <tom@tromey.com>
Cc: Ijaz, Abdul B <abdul.b.ijaz@intel.com>; gdb-patches@sourceware.org; JiniSusan.George@amd.com; eliz@gnu.org
Subject: Re: [PATCH v11 06/10] gdb: Skip trampoline functions for the up command.
>>>>> "Tom" == Tom Tromey <tom@tromey.com> writes:
>>>>> Abdul Basit Ijaz <abdul.b.ijaz@intel.com> writes:
>> This change skips trampoline functions when the option
>> 'skip-trampoline-functions' is set to 'on' for the up command.
>> Before this change, GDB processes trampoline functions indicated by
>> the compiler with DIE "DW_AT_trampoline" and stops at the trampoline function for the 'up'
>> command. For better user experience, all such frames can be skipped
>> and hidden from the user.
Tom> Why "up" but not "down"?
I was thinking about this last night and wondering how this change interacts with the "frame" command as well.
Tom
________________________________________
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 (89) 99143-0
www.intel.de
Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman
Chairperson of the Supervisory Board: Sonja Pierer
Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v11 07/10] gdb: Skip trampoline functions for the return command.
2026-08-03 19:34 [PATCH v11 00/10] GDB support for DW_AT_trampoline Abdul Basit Ijaz
` (5 preceding siblings ...)
2026-08-03 19:34 ` [PATCH v11 06/10] gdb: Skip trampoline functions for the up command Abdul Basit Ijaz
@ 2026-08-03 19:34 ` Abdul Basit Ijaz
2026-08-03 19:34 ` [PATCH v11 08/10] gdb, mi: Skip trampoline functions for the -stack-list-frames command Abdul Basit Ijaz
` (3 subsequent siblings)
10 siblings, 0 replies; 32+ messages in thread
From: Abdul Basit Ijaz @ 2026-08-03 19:34 UTC (permalink / raw)
To: gdb-patches; +Cc: abdul.b.ijaz, JiniSusan.George, tom, eliz
This change skips trampoline functions for the return command
when the option 'skip-trampoline-functions' is set to 'on'. Before this
change, GDB processes trampoline functions indicated by the compiler with
DIE "DW_AT_trampoline" for the return command and stops at the trampoline
functions. For better user experience, all such frames can
be skipped and hidden from the user.
In this example the IFX compiler emits "DW_AT_trampoline" tag for the 'first'
and 'second' trampoline functions like following:
function second (x, y) result(z)
integer, intent(in) :: x, y
integer :: z
z = x * y ! breakpt-return
end function second
function first (num1, num2) result(total)
integer, intent(in) :: num1, num2
integer :: total
total = second (num1 + 4, num2 * 3) ! first-breakpt
total = total + 30
end function first
Related Dwarf:
0x0000013f: DW_TAG_subprogram
DW_AT_low_pc (0x0000000000404350)
DW_AT_high_pc (0x000000000040435f)
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_linkage_name ("second_.t74p.t75p")
DW_AT_name ("second_.t74p.t75p")
DW_AT_trampoline ("second_")
0x0000015a: DW_TAG_subprogram
DW_AT_low_pc (0x00000000004044a0)
DW_AT_high_pc (0x00000000004044af)
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_linkage_name ("first_.t104p.t105p")
DW_AT_name ("first_.t104p.t105p")
DW_AT_trampoline ("first_")
Before this change, the return command output looks like:
'''
(gdb) return
Make second return now? (y or n) y
\#0 0x0000000000405209 in second_.t74p.t75p () at test.f90:12
12 end function first
'''
After this change:
'''
(gdb) return
Make second return now? (y or n) y
\#0 0x00000000004051e3 in first (num1=16, num2=3) at test.f90:10
10 total = second (num1 + 4, num2 * 3) ! first-breakpt
'''
The test gdb.fortran/func-trampoline.exp is updated for testing this change.
---
gdb/doc/gdb.texinfo | 6 +++---
gdb/stack.c | 11 +++++++++++
gdb/testsuite/gdb.fortran/func-trampoline.exp | 10 +++++++++-
3 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index ee94ad09fd9..b73cdf8b430 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -6772,9 +6772,9 @@ DWARF trampolines marked via DW_AT_trampoline are supported by this.
When issuing a @code{backtrace}, if @code{skip-trampoline-functions} is set,
@value{GDBN} will skip trampoline frames while printing the stack.
-When issuing a @code{finish}, @code{reverse-finish} or @code{up}, if
-@code{skip-trampoline-functions} is set, @value{GDBN} will skip trampoline
-frames while returning from the target function.
+When issuing a @code{finish}, @code{reverse-finish}, @code{up} or
+@code{return}, if @code{skip-trampoline-functions} is set, @value{GDBN} will
+skip trampoline frames while returning from the target function.
Currently, only DWARF trampolines marked via DW_AT_trampoline are supported by
this.
diff --git a/gdb/stack.c b/gdb/stack.c
index 8b1644ddb6e..90d6fef6824 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -2839,6 +2839,17 @@ return_command (const char *retval_exp, int from_tty)
if (get_frame_type (get_current_frame ()) == DUMMY_FRAME)
frame_pop (get_current_frame ());
+ if (skip_trampoline_functions)
+ {
+ frame_info_ptr ret_frame = get_current_frame ();
+ for (int i = 0; (SAFE_TRAMPOLINE_CHAIN (i, ret_frame)
+ && in_trampoline_frame (ret_frame)); ++i)
+ {
+ frame_pop (ret_frame);
+ ret_frame = get_current_frame ();
+ }
+ }
+
select_frame (get_current_frame ());
/* If interactive, print the frame that is now current. */
if (from_tty)
diff --git a/gdb/testsuite/gdb.fortran/func-trampoline.exp b/gdb/testsuite/gdb.fortran/func-trampoline.exp
index ce9f14160aa..4f91aa17860 100644
--- a/gdb/testsuite/gdb.fortran/func-trampoline.exp
+++ b/gdb/testsuite/gdb.fortran/func-trampoline.exp
@@ -13,7 +13,7 @@
# 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 "backtrace", "backtrace -n", "finish" and "up" commands for
+# Test "backtrace", "backtrace -n", "finish", "up" and "return" commands for
# functions with trampoline calls.
require allow_fortran_tests
@@ -105,4 +105,12 @@ foreach_with_prefix opt_level {O0 O2} {
"#$decimal.* $middle_desc" \
"${fill}first = second \\(num1 \\+ 4, num2 \\* 3\\).*${fill}"]
}
+
+ with_test_prefix "return" {
+ init_test $opt_level
+
+ gdb_test "return" \
+ ".*first = second \\(num1 \\+ 4, num2 \\* 3\\) \\! first-breakpt" \
+ "" "Make second return now.*y or n. $" "y"
+ }
}
--
2.34.1
________________________________________
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 (89) 99143-0
www.intel.de
Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman
Chairperson of the Supervisory Board: Sonja Pierer
Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 32+ messages in thread* [PATCH v11 08/10] gdb, mi: Skip trampoline functions for the -stack-list-frames command.
2026-08-03 19:34 [PATCH v11 00/10] GDB support for DW_AT_trampoline Abdul Basit Ijaz
` (6 preceding siblings ...)
2026-08-03 19:34 ` [PATCH v11 07/10] gdb: Skip trampoline functions for the return command Abdul Basit Ijaz
@ 2026-08-03 19:34 ` Abdul Basit Ijaz
2026-10-21 20:58 ` Tom Tromey
2026-08-03 19:34 ` [PATCH v11 09/10] gdb, mi: Skip trampoline functions for the -stack-list-arguments command Abdul Basit Ijaz
` (2 subsequent siblings)
10 siblings, 1 reply; 32+ messages in thread
From: Abdul Basit Ijaz @ 2026-08-03 19:34 UTC (permalink / raw)
To: gdb-patches; +Cc: abdul.b.ijaz, JiniSusan.George, tom, eliz
This change skips trampoline functions for the '-stack-list-frames' command
when the option 'skip-trampoline-functions' is set to 'on'. Before this
change, GDB prints the frames indicated by the compiler with DIE
"DW_AT_trampoline" in the backtrace for mi command stack-list-frames, but
for better user experience, all such frames can be hidden from the user.
In this example the IFX compiler emits "DW_AT_trampoline" tag for the 'first'
and 'second' trampoline functions like following:
function second (x, y) result(z)
integer, intent(in) :: x, y
integer :: z
z = x * y ! breakpt-backtrace
end function second
function first (num1, num2) result(total)
integer, intent(in) :: num1, num2
integer :: total
total = second (num1 + 4, num2 * 3) ! first-breakpt
total = total + 30
end function first
Related Dwarf:
0x0000013f: DW_TAG_subprogram
DW_AT_low_pc (0x0000000000404350)
DW_AT_high_pc (0x000000000040435f)
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_linkage_name ("second_.t74p.t75p")
DW_AT_name ("second_.t74p.t75p")
DW_AT_trampoline ("second_")
0x0000015a: DW_TAG_subprogram
DW_AT_low_pc (0x00000000004044a0)
DW_AT_high_pc (0x00000000004044af)
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_linkage_name ("first_.t104p.t105p")
DW_AT_name ("first_.t104p.t105p")
DW_AT_trampoline ("first_")
Before this change, the '-stack-list-frames' command output looks like:
'''
(gdb) -stack-list-frames
-stack-list-frames
^done,
stack=[
frame={level="0",addr="0x0000000000405194",func="second",
file="test.f90",fullname="/home/test.f90",line="4",
arch="i386:x86-64"},
frame={level="1",addr="0x0000000000405209",
func="second_.t74p.t75p",
file="test.f90",fullname="/home/test.f90",line="12",
arch="i386:x86-64"},
frame={level="2",addr="0x00000000004051e3",func="first",
file="test.f90",fullname="/home/test.f90",line="10",
arch="i386:x86-64"},
frame={level="3",addr="0x0000000000405309",
func="first_.t95p.t96p",file="test.f90",
fullname="/home/test.f90",line="21",arch="i386:x86-64"},
frame={level="4",addr="0x0000000000405234",
func="func_trampoline",file="test.f90",
fullname="/home/test.f90",line="17",arch="i386:x86-64"}]
'''
After this change:
'''
(gdb) -stack-list-frames
-stack-list-frames
^done,
stack=[frame={level="0",addr="0x0000000000405194",func="second",
file="test.f90",fullname="/home/test.f90",line="4",
arch="i386:x86-64"},
frame={level="2",addr="0x00000000004051e3",func="first",
file="test.f90",fullname="/home/test.f90",line="10",
arch="i386:x86-64"},
frame={level="4",addr="0x0000000000405234",
func="func_trampoline",file="test.f90",fullname="/home/test.f90",
line="17",arch="i386:x86-64"}]
'''
New test gdb.mi/mi-func-trampoline.exp is added for testing the change.
---
gdb/doc/gdb.texinfo | 4 +-
gdb/mi/mi-cmd-stack.c | 7 +++
gdb/testsuite/gdb.mi/mi-func-trampoline.exp | 69 +++++++++++++++++++++
3 files changed, 79 insertions(+), 1 deletion(-)
create mode 100644 gdb/testsuite/gdb.mi/mi-func-trampoline.exp
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index b73cdf8b430..684716a869e 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -35476,7 +35476,9 @@ an error if @var{low-frame} is larger than the actual number of
frames. On the other hand, @var{high-frame} may be larger than the
actual number of frames, in which case only existing frames will be
returned. If the option @code{--no-frame-filters} is supplied, then
-Python frame filters will not be executed.
+Python frame filters will not be executed. If the option
+@code{skip-trampoline-functions} is set, @value{GDBN} will skip the trampoline
+frames while printing a backtrace.
@subsubheading @value{GDBN} Command
diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c
index 37a470701af..1f66c02f8b4 100644
--- a/gdb/mi/mi-cmd-stack.c
+++ b/gdb/mi/mi-cmd-stack.c
@@ -174,6 +174,13 @@ mi_cmd_stack_list_frames (const char *command, const char *const *argv,
i++, fi = get_prev_frame (fi))
{
QUIT;
+ if (skip_trampoline_functions)
+ {
+ for (int j = 0; (SAFE_TRAMPOLINE_CHAIN (j, fi)
+ && in_trampoline_frame (fi)); ++j)
+ fi = get_prev_frame (fi);
+ }
+
/* Print the location and the address always, even for level 0.
If args is 0, don't print the arguments. */
print_frame_info (user_frame_print_options,
diff --git a/gdb/testsuite/gdb.mi/mi-func-trampoline.exp b/gdb/testsuite/gdb.mi/mi-func-trampoline.exp
new file mode 100644
index 00000000000..f40a9722f91
--- /dev/null
+++ b/gdb/testsuite/gdb.mi/mi-func-trampoline.exp
@@ -0,0 +1,69 @@
+# Copyright 2026 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/> .
+
+# Test -stack-list-frames command for functions with trampoline
+# calls. Also checks if trampoline frames are filtered while printing
+# stack.
+
+require allow_fortran_tests
+
+if {![test_compiler_info {ifx-*} f90]} {
+ untested "This test is only applicable for IFX, which emits the\
+ trampoline DIE in Dwarf."
+ return
+}
+
+load_lib fortran.exp
+load_lib mi-support.exp
+
+set MIFLAGS "-i=mi"
+
+if {[mi_clean_restart]} {
+ return
+}
+
+set testfile mi-func-trampoline
+set srcfile "${srcdir}/gdb.fortran/func-trampoline.f90"
+set binfile [standard_output_file $testfile]
+
+if { [gdb_compile "${srcfile}" "${binfile}" executable \
+ {debug f90} ] != "" } {
+ untested "failed to compile"
+ return
+}
+
+mi_delete_breakpoints
+mi_gdb_reinitialize_dir $srcdir/$subdir
+mi_gdb_load ${binfile}
+
+set inner_loc [gdb_get_line_number "second-breakpt"]
+set fill "\[^\r\n\]*"
+
+set frame1_regx "\{level=\"0\",addr=\"$hex\",func=\"second\",file=\".*func-trampoline.f90\",fullname=\"${fullname_syntax}func-trampoline.f90\",line=\"$inner_loc\",arch=\".*\"\}"
+set frame2_regx "\{level=\"2\",addr=\"$hex\",func=\"first\",.*\}"
+set frame3_regx "\{level=\"4\",addr=\"$hex\",func=\"func_trampoline\",.*\}"
+
+# Set breakpoint inside the innermost function 'second'.
+mi_create_breakpoint "-t $srcfile:$inner_loc" \
+ "insert breakpoint at line $inner_loc " \
+ -number 1 -disp del -func second -file ".*trampoline.f90" \
+ -line $inner_loc -addr $hex
+mi_run_cmd
+mi_expect_stop \
+ "breakpoint-hit" "second" ".*" ".*trampoline.f90" "\[0-9\]+" { "" "disp=\"del\"" } \
+ "run to breakpoint at line $inner_loc"
+
+mi_gdb_test "100-stack-list-frames" \
+ "100\\^done,stack=\\\[frame=${frame1_regx},frame=${frame2_regx},frame=${frame3_regx}\\\]"
--
2.34.1
________________________________________
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 (89) 99143-0
www.intel.de
Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman
Chairperson of the Supervisory Board: Sonja Pierer
Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: [PATCH v11 08/10] gdb, mi: Skip trampoline functions for the -stack-list-frames command.
2026-08-03 19:34 ` [PATCH v11 08/10] gdb, mi: Skip trampoline functions for the -stack-list-frames command Abdul Basit Ijaz
@ 2026-10-21 20:58 ` Tom Tromey
2026-10-22 14:18 ` Ijaz, Abdul B
0 siblings, 1 reply; 32+ messages in thread
From: Tom Tromey @ 2026-10-21 20:58 UTC (permalink / raw)
To: Abdul Basit Ijaz; +Cc: gdb-patches, JiniSusan.George, tom, eliz
>>>>> Abdul Basit Ijaz <abdul.b.ijaz@intel.com> writes:
> This change skips trampoline functions for the '-stack-list-frames' command
> when the option 'skip-trampoline-functions' is set to 'on'. Before this
> change, GDB prints the frames indicated by the compiler with DIE
> "DW_AT_trampoline" in the backtrace for mi command stack-list-frames, but
> for better user experience, all such frames can be hidden from the user.
This is another spot where the Python layer seems to already have
related functionality.
It doesn't seem to be documented :-(
But from py-framefilter.c, it seems to put the elided frames into a
"children" element of the parent frame.
This way the UI can decide for itself what to do.
Anyway, I wonder whether the new work should perhaps just follow the
existing precedent here.
There's a similar issue in DAP, BTW. See gdb/python/lib/gdb/dap/frames.py
and in particular the work done in _frame_id_generator.
Tom
^ permalink raw reply [flat|nested] 32+ messages in thread
* RE: [PATCH v11 08/10] gdb, mi: Skip trampoline functions for the -stack-list-frames command.
2026-10-21 20:58 ` Tom Tromey
@ 2026-10-22 14:18 ` Ijaz, Abdul B
0 siblings, 0 replies; 32+ messages in thread
From: Ijaz, Abdul B @ 2026-10-22 14:18 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches, JiniSusan.George, eliz, Ijaz, Abdul B
Thanks Tom, for the feedback.
Please see the inline reply below:
>> This change skips trampoline functions for the '-stack-list-frames'
>> command when the option 'skip-trampoline-functions' is set to 'on'.
>> Before this change, GDB prints the frames indicated by the compiler
>> with DIE "DW_AT_trampoline" in the backtrace for mi command
>> stack-list-frames, but for better user experience, all such frames can be hidden from the user.
Tom> This is another spot where the Python layer seems to already have related functionality.
Tom> It doesn't seem to be documented :-(
Tom> But from py-framefilter.c, it seems to put the elided frames into a "children" element of the parent frame.
Tom> This way the UI can decide for itself what to do.
Tom> Anyway, I wonder whether the new work should perhaps just follow the existing precedent here.
Abdul> This is the same question as for the backtrace command, which we are discussing in the reply to 04/10 ("gdb: Skip trampoline frames for the backtrace command"). The MI -stack-list-* commands will follow whatever we decide there: if trampoline frames become elided frames, they will be reported as "children" of the frame they lead to, as the frame filter code already does for MI. I will update this patch and the -stack-list-arguments accordingly.
Best Regards,
Abdul Basit
-----Original Message-----
From: Tom Tromey <tom@tromey.com>
Sent: Wednesday, October 21, 2026 10:58 PM
To: Ijaz, Abdul B <abdul.b.ijaz@intel.com>
Cc: gdb-patches@sourceware.org; JiniSusan.George@amd.com; tom@tromey.com; eliz@gnu.org
Subject: Re: [PATCH v11 08/10] gdb, mi: Skip trampoline functions for the -stack-list-frames command.
>>>>> Abdul Basit Ijaz <abdul.b.ijaz@intel.com> writes:
> This change skips trampoline functions for the '-stack-list-frames'
> command when the option 'skip-trampoline-functions' is set to 'on'.
> Before this change, GDB prints the frames indicated by the compiler
> with DIE "DW_AT_trampoline" in the backtrace for mi command
> stack-list-frames, but for better user experience, all such frames can be hidden from the user.
This is another spot where the Python layer seems to already have related functionality.
It doesn't seem to be documented :-(
But from py-framefilter.c, it seems to put the elided frames into a "children" element of the parent frame.
This way the UI can decide for itself what to do.
Anyway, I wonder whether the new work should perhaps just follow the existing precedent here.
There's a similar issue in DAP, BTW. See gdb/python/lib/gdb/dap/frames.py and in particular the work done in _frame_id_generator.
Tom
________________________________________
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 (89) 99143-0
www.intel.de
Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman
Chairperson of the Supervisory Board: Sonja Pierer
Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v11 09/10] gdb, mi: Skip trampoline functions for the -stack-list-arguments command.
2026-08-03 19:34 [PATCH v11 00/10] GDB support for DW_AT_trampoline Abdul Basit Ijaz
` (7 preceding siblings ...)
2026-08-03 19:34 ` [PATCH v11 08/10] gdb, mi: Skip trampoline functions for the -stack-list-frames command Abdul Basit Ijaz
@ 2026-08-03 19:34 ` Abdul Basit Ijaz
2026-08-03 19:34 ` [PATCH v11 10/10] gdb: Filter trampoline frames in backtrace when using Python frame-filters Abdul Basit Ijaz
2026-09-09 7:40 ` [PING][PATCH v11 00/10] GDB support for DW_AT_trampoline Ijaz, Abdul B
10 siblings, 0 replies; 32+ messages in thread
From: Abdul Basit Ijaz @ 2026-08-03 19:34 UTC (permalink / raw)
To: gdb-patches; +Cc: abdul.b.ijaz, JiniSusan.George, tom, eliz
This change skips trampoline functions for the '-stack-list-arguments'
command when the option 'skip-trampoline-functions' is set to 'on'. Before
this change, GDB prints the arguments of frames indicated by the
compiler with DIE "DW_AT_trampoline" in the backtrace for the mi command
stack-list-arguments, but for better user experience, all such frames
can be hidden from the user.
In this example the IFX compiler emits "DW_AT_trampoline" tag for the
'first' and 'second' trampoline functions like following:
function second (x, y) result(z)
integer, intent(in) :: x, y
integer :: z
z = x * y ! breakpt-args
end function second
function first (num1, num2) result(total)
integer, intent(in) :: num1, num2
integer :: total
total = second (num1 + 4, num2 * 3) ! first-breakpt
total = total + 30
end function first
Related Dwarf:
0x0000013f: DW_TAG_subprogram
DW_AT_low_pc (0x0000000000404350)
DW_AT_high_pc (0x000000000040435f)
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_linkage_name ("second_.t74p.t75p")
DW_AT_name ("second_.t74p.t75p")
DW_AT_trampoline ("second_")
0x0000015a: DW_TAG_subprogram
DW_AT_low_pc (0x00000000004044a0)
DW_AT_high_pc (0x00000000004044af)
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_linkage_name ("first_.t104p.t105p")
DW_AT_name ("first_.t104p.t105p")
DW_AT_trampoline ("first_")
Before this change, the -stack-list-arguments' command output looks like:
'''
(gdb)
-stack-list-arguments 0
^done,
stack-args=[
frame={level="0",args=[name="x",name="y"]},
frame={level="1",args=[]},
frame={level="2",args=[name="num1",name="num2"]},
frame={level="3",args=[]},
frame={level="4",args=[]}]
'''
After change:
'''
(gdb)
-stack-list-arguments 0
^done,
stack-args=[
frame={level="0",args=[name="x",name="y"]},
frame={level="1",args=[name="num1",name="num2"]},
frame={level="2",args=[]}]
'''
The test gdb.mi/mi-func-treampoline is updated for testing the change.
---
gdb/doc/gdb.texinfo | 3 +++
gdb/mi/mi-cmd-stack.c | 7 +++++++
gdb/testsuite/gdb.mi/mi-func-trampoline.exp | 13 ++++++++++---
3 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 684716a869e..99909984241 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -35815,6 +35815,9 @@ variable object is updated, @value{GDBN} makes sure that the
thread/frame combination the variable object is bound to still exists,
and re-evaluates the variable object in context of that thread/frame.
+If the option @code{skip-trampoline-functions} is set, @value{GDBN} will
+not show trampoline functions in the stack.
+
The following is the complete set of @sc{gdb/mi} operations defined to
access this functionality:
diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c
index 1f66c02f8b4..66c758bd44e 100644
--- a/gdb/mi/mi-cmd-stack.c
+++ b/gdb/mi/mi-cmd-stack.c
@@ -401,6 +401,13 @@ mi_cmd_stack_list_args (const char *command, const char *const *argv, int argc)
i++, fi = get_prev_frame (fi))
{
QUIT;
+ if (skip_trampoline_functions)
+ {
+ for (int j = 0; (SAFE_TRAMPOLINE_CHAIN (j, fi)
+ && in_trampoline_frame (fi)); ++j)
+ fi = get_prev_frame (fi);
+ }
+
ui_out_emit_tuple tuple_emitter (uiout, "frame");
uiout->field_signed ("level", i);
list_args_or_locals (user_frame_print_options,
diff --git a/gdb/testsuite/gdb.mi/mi-func-trampoline.exp b/gdb/testsuite/gdb.mi/mi-func-trampoline.exp
index f40a9722f91..4e0c3922eb6 100644
--- a/gdb/testsuite/gdb.mi/mi-func-trampoline.exp
+++ b/gdb/testsuite/gdb.mi/mi-func-trampoline.exp
@@ -13,9 +13,9 @@
# 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 -stack-list-frames command for functions with trampoline
-# calls. Also checks if trampoline frames are filtered while printing
-# stack.
+# Test -stack-list-frames and -stack-list-arguments command for functions
+# with trampoline calls. Also checks if trampoline frames are filtered
+# while printing stack.
require allow_fortran_tests
@@ -55,6 +55,10 @@ set frame1_regx "\{level=\"0\",addr=\"$hex\",func=\"second\",file=\".*func-tramp
set frame2_regx "\{level=\"2\",addr=\"$hex\",func=\"first\",.*\}"
set frame3_regx "\{level=\"4\",addr=\"$hex\",func=\"func_trampoline\",.*\}"
+set arg1_regx "\{level=\"0\",args=\\\[name=\"x\",name=\"y\"\\\]\}"
+set arg2_regx "\{level=\"1\",args=\\\[name=\"num1\",name=\"num2\"\\\]\}"
+set arg3_regx "\{level=\"2\",args=\\\[\\\]\}"
+
# Set breakpoint inside the innermost function 'second'.
mi_create_breakpoint "-t $srcfile:$inner_loc" \
"insert breakpoint at line $inner_loc " \
@@ -67,3 +71,6 @@ mi_expect_stop \
mi_gdb_test "100-stack-list-frames" \
"100\\^done,stack=\\\[frame=${frame1_regx},frame=${frame2_regx},frame=${frame3_regx}\\\]"
+
+mi_gdb_test "200-stack-list-arguments 0" \
+ "200\\^done,stack-args=\\\[frame=${arg1_regx},frame=${arg2_regx},frame=${arg3_regx}\\\]"
--
2.34.1
________________________________________
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 (89) 99143-0
www.intel.de
Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman
Chairperson of the Supervisory Board: Sonja Pierer
Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 32+ messages in thread* [PATCH v11 10/10] gdb: Filter trampoline frames in backtrace when using Python frame-filters.
2026-08-03 19:34 [PATCH v11 00/10] GDB support for DW_AT_trampoline Abdul Basit Ijaz
` (8 preceding siblings ...)
2026-08-03 19:34 ` [PATCH v11 09/10] gdb, mi: Skip trampoline functions for the -stack-list-arguments command Abdul Basit Ijaz
@ 2026-08-03 19:34 ` Abdul Basit Ijaz
2026-10-21 21:03 ` Tom Tromey
2026-09-09 7:40 ` [PING][PATCH v11 00/10] GDB support for DW_AT_trampoline Ijaz, Abdul B
10 siblings, 1 reply; 32+ messages in thread
From: Abdul Basit Ijaz @ 2026-08-03 19:34 UTC (permalink / raw)
To: gdb-patches; +Cc: abdul.b.ijaz, JiniSusan.George, tom, eliz
In case of the Python frame-filters, this change filters trampoline functions
when the option 'skip-trampoline-functions' is set to 'on'. GDB recently
added the option to hide frames that are marked by the compiler with
"DW_AT_trampoline", see commit 'Skip trampoline frames for the backtrace
command'. This implements the same functionality when python frame filters
are in use.
In this example the IFX compiler emits "DW_AT_trampoline" tag for the 'first'
and 'second' trampoline functions like following:
function second (x, y) result(z)
integer, intent(in) :: x, y
integer :: z
z = x * y ! breakpt-framefilter
end function second
function first (num1, num2) result(total)
integer, intent(in) :: num1, num2
integer :: total
total = second (num1 + 4, num2 * 3) ! first-breakpt
total = total + 30
end function first
Related Dwarf:
0x0000013f: DW_TAG_subprogram
DW_AT_low_pc (0x0000000000404350)
DW_AT_high_pc (0x000000000040435f)
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_linkage_name ("second_.t74p.t75p")
DW_AT_name ("second_.t74p.t75p")
DW_AT_trampoline ("second_")
0x0000015a: DW_TAG_subprogram
DW_AT_low_pc (0x00000000004044a0)
DW_AT_high_pc (0x00000000004044af)
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_linkage_name ("first_.t104p.t105p")
DW_AT_name ("first_.t104p.t105p")
DW_AT_trampoline ("first_")
Once frame filters are enabled the backtrace command output before this
change looks like:
'''
(gdb) info frame-filter
global frame-filters:
Priority Enabled Name
100 Yes TestTrampolineFrameFilter
(gdb) backtrace 3
\#0 second (x=20, y=9) at test.f90:4
\#1 0x0000000000405209 in second_.t74p.t75p () at test.f90:12
\#2 0x00000000004051e3 in first (num1=16, num2=3) at test.f90:10
(gdb) backtrace -3
\#2 0x00000000004051e3 in first (num1=16, num2=3) at test.f90:10
\#3 0x0000000000405309 in first_.t95p.t96p () at test.f90:21
\#4 0x0000000000405234 in func_trampoline () at test.f90:17
'''
After this change:
'''
(gdb) info frame-filter
global frame-filters:
Priority Enabled Name
100 Yes TestTrampolineFrameFilter
(gdb) backtrace 3
\#0 second (x=20, y=9) at test.f90:4
\#2 0x00000000004051e3 in first (num1=16, num2=3) at test.f90:10
\#4 0x0000000000405234 in func_trampoline () at test.f90:17
(gdb) backtrace -3
\#2 0x00000000004051e3 in first (num1=16, num2=3) at test.f90:10
\#4 0x0000000000405234 in func_trampoline () at test.f90:17
'''
New test gdb.python/py-framefilter-trampoline.exp is added to test this
change.
---
gdb/python/py-frame.c | 11 +++
.../gdb.python/py-framefilter-trampoline.exp | 77 +++++++++++++++++++
.../gdb.python/py-framefilter-trampoline.py | 31 ++++++++
3 files changed, 119 insertions(+)
create mode 100644 gdb/testsuite/gdb.python/py-framefilter-trampoline.exp
create mode 100644 gdb/testsuite/gdb.python/py-framefilter-trampoline.py
diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c
index afa89f0d112..098b37230e1 100644
--- a/gdb/python/py-frame.c
+++ b/gdb/python/py-frame.c
@@ -59,6 +59,17 @@ frame_object_to_frame_info (PyObject *obj)
if (frame == NULL)
return NULL;
+ if (skip_trampoline_functions)
+ {
+ for (int i = 0; (SAFE_TRAMPOLINE_CHAIN (i, frame)
+ && in_trampoline_frame (frame)); ++i)
+ {
+ frame = get_prev_frame (frame);
+ if (frame == nullptr)
+ return nullptr;
+ }
+ }
+
return frame;
}
diff --git a/gdb/testsuite/gdb.python/py-framefilter-trampoline.exp b/gdb/testsuite/gdb.python/py-framefilter-trampoline.exp
new file mode 100644
index 00000000000..23fd22164ef
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-framefilter-trampoline.exp
@@ -0,0 +1,77 @@
+# Copyright (C) 2026 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 is part of the GDB testsuite. It tests skipping of trampolines
+# in the backtrace command in case Python-based frame-filters are enabled.
+
+load_lib gdb-python.exp
+
+require allow_python_tests allow_fortran_tests
+
+if {![test_compiler_info {ifx-*} f90]} {
+ untested "This test is only applicable for IFX, which emits the\
+ trampoline DIE in Dwarf."
+ return
+}
+
+load_lib fortran.exp
+
+set testfile py-framefilter-trampoline
+set srcfile "${srcdir}/gdb.fortran/func-trampoline.f90"
+set binfile [standard_output_file $testfile]
+
+if {[build_executable $testfile.exp $testfile $srcfile {debug f90}] == -1} {
+ return
+}
+
+# Start with a fresh gdb.
+gdb_exit
+gdb_start
+
+gdb_test "info frame-filter" \
+ "No frame filters\\." \
+ "info frame filter before loading filters"
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if {![runto_main]} {
+ return
+}
+gdb_test_no_output "set python print-stack full" \
+ "set python print-stack to full"
+
+# Load frame-filters
+set remote_python_file [gdb_remote_download host \
+ ${srcdir}/${subdir}/${testfile}.py]
+gdb_test_no_output "source ${remote_python_file}" "load python file"
+
+set inner_loc [gdb_get_line_number "second-breakpt"]
+set middle_loc [gdb_get_line_number "first-breakpt"]
+set outer_loc [gdb_get_line_number "main-outer-loc"]
+set fill "\[^\r\n\]*"
+
+set inner_desc "second \\(x=20, y=9\\) at ${fill}$srcfile:$inner_loc"
+set middle_desc "first \\(num1=16, num2=3\\) at ${fill}$srcfile:$middle_loc"
+set outer_desc ".* at .*$srcfile:$outer_loc"
+
+# Set breakpoint inside the innermost function 'second'.
+gdb_breakpoint "$srcfile:$inner_loc"
+gdb_continue_to_breakpoint "innermost-body" ".*$srcfile:$inner_loc.*"
+
+# Test with frame filter.
+gdb_test "bt" [multi_line \
+ "#$decimal.* $middle_desc" \
+ "#$decimal.* $outer_desc.*"]
diff --git a/gdb/testsuite/gdb.python/py-framefilter-trampoline.py b/gdb/testsuite/gdb.python/py-framefilter-trampoline.py
new file mode 100644
index 00000000000..0cdaf7bb4de
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-framefilter-trampoline.py
@@ -0,0 +1,31 @@
+# Copyright (C) 2026 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 is part of the GDB testsuite. It tests if trampolines are
+# skipped when Python-based frame-filters are enabled.
+
+import gdb
+
+class TestTrampolineFrameFilter():
+ def __init__(self):
+ self.name = "TestTrampolineFrameFilter"
+ self.priority = 100
+ self.enabled = True
+ gdb.frame_filters[self.name] = self
+
+ def filter(self, frame_iter):
+ return frame_iter
+
+TestTrampolineFrameFilter()
--
2.34.1
________________________________________
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 (89) 99143-0
www.intel.de
Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman
Chairperson of the Supervisory Board: Sonja Pierer
Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: [PATCH v11 10/10] gdb: Filter trampoline frames in backtrace when using Python frame-filters.
2026-08-03 19:34 ` [PATCH v11 10/10] gdb: Filter trampoline frames in backtrace when using Python frame-filters Abdul Basit Ijaz
@ 2026-10-21 21:03 ` Tom Tromey
2026-10-22 17:04 ` Ijaz, Abdul B
0 siblings, 1 reply; 32+ messages in thread
From: Tom Tromey @ 2026-10-21 21:03 UTC (permalink / raw)
To: Abdul Basit Ijaz; +Cc: gdb-patches, JiniSusan.George, tom, eliz
>>>>> Abdul Basit Ijaz <abdul.b.ijaz@intel.com> writes:
> In case of the Python frame-filters, this change filters trampoline functions
> when the option 'skip-trampoline-functions' is set to 'on'. GDB recently
> added the option to hide frames that are marked by the compiler with
> "DW_AT_trampoline", see commit 'Skip trampoline frames for the backtrace
> command'. This implements the same functionality when python frame filters
> are in use.
> diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c
> index afa89f0d112..098b37230e1 100644
> --- a/gdb/python/py-frame.c
> +++ b/gdb/python/py-frame.c
> @@ -59,6 +59,17 @@ frame_object_to_frame_info (PyObject *obj)
> if (frame == NULL)
> return NULL;
> + if (skip_trampoline_functions)
> + {
> + for (int i = 0; (SAFE_TRAMPOLINE_CHAIN (i, frame)
> + && in_trampoline_frame (frame)); ++i)
> + {
> + frame = get_prev_frame (frame);
> + if (frame == nullptr)
> + return nullptr;
> + }
> + }
This seems suspicious to me.
For one thing, suppose you have A -> Trampoline -> B. Then in Python
you fetch the frame B. What does B.newer() return?
I think with this code it will just return B again.
For DAP, and frame filters, I tend to think it would be better for
Python to simply see the frames as they are, but then add a new
attribute -- on the frame, but also maybe on the symbol -- indicating if
it's been marked as a trampoline.
Then maybe _FrameDecoratorBase.elided could return True if the frame is
a non-"live" trampoline frame.
Tom
^ permalink raw reply [flat|nested] 32+ messages in thread* RE: [PATCH v11 10/10] gdb: Filter trampoline frames in backtrace when using Python frame-filters.
2026-10-21 21:03 ` Tom Tromey
@ 2026-10-22 17:04 ` Ijaz, Abdul B
0 siblings, 0 replies; 32+ messages in thread
From: Ijaz, Abdul B @ 2026-10-22 17:04 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches, JiniSusan.George, eliz, Ijaz, Abdul B
Thanks Tom, for the feedback.
Please see the inline reply below:
>> + if (skip_trampoline_functions)
>> + {
>> + for (int i = 0; (SAFE_TRAMPOLINE_CHAIN (i, frame)
>> + && in_trampoline_frame (frame)); ++i)
>> + {
>> + frame = get_prev_frame (frame);
>> + if (frame == nullptr)
>> + return nullptr;
>> + }
>> + }
Tom> This seems suspicious to me.
Tom> For one thing, suppose you have A -> Trampoline -> B. Then in Python you fetch the frame B. What does B.newer() return?
Tom> I think with this code it will just return B again.
Abdul> You are right that newer () returns the same frame again, and it is a real problem, though for the caller: with A calling the trampoline and the trampoline calling B, it is A.newer () that returns A again, while B.newer () is not affected. Since every gdb.Frame of a trampoline is turned into the next outer frame, the frame object that A.newer () returns for the trampoline behaves as A, so walking newer () never gets back to B.
For example, with ifx and gdb.fortran/func-trampoline.f90, the call stack is:
func_trampoline -> first_.t95p.t96p -> first -> second_.t74p.t75p -> second
where first_.t95p.t96p and second_.t74p.t75p are the trampolines. Stopped in "second":
(gdb) python f2 = gdb.selected_frame().older()
(gdb) python print(f2.level(), f2.name())
2 first
(gdb) python print(f2.newer().level(), f2.newer().name())
2 first
Here f2.newer () should return "second" (level 0), or the trampoline second_.t74p.t75p at level 1, but not "first" again.
Tom> For DAP, and frame filters, I tend to think it would be better for Python to simply see the frames as they are, but then add a new attribute -- on the frame, but also maybe on the symbol -- indicating if it's been marked as a trampoline.
Tom> Then maybe _FrameDecoratorBase.elided could return True if the frame is a non-"live" trampoline frame.
Abdul> Agreed. For v12 I will drop the change to frame_object_to_frame_info, so that Python sees the frames as they are, and add new attributes:
- gdb.Symbol.is_trampoline, an attribute like Symbol.is_function;
- gdb.Frame.is_trampoline (), a method like the other gdb.Frame accessors, true if the frame's function is marked as a trampoline;
For the frame filters, elided () returns the frames elided under a frame, so I would do it the other way round: the frame that a trampoline leads to returns the trampoline frames as its elided frames, except for the live frame, which is never elided. Frame filters and DAP then handle them like other elided frames. This depends on what we decide for the backtrace command in 04/10, and I will keep the Python side consistent with that.
Thanks & Best Regards,
Abdul Basit
-----Original Message-----
From: Tom Tromey <tom@tromey.com>
Sent: Wednesday, October 21, 2026 11:03 PM
To: Ijaz, Abdul B <abdul.b.ijaz@intel.com>
Cc: gdb-patches@sourceware.org; JiniSusan.George@amd.com; tom@tromey.com; eliz@gnu.org
Subject: Re: [PATCH v11 10/10] gdb: Filter trampoline frames in backtrace when using Python frame-filters.
>>>>> Abdul Basit Ijaz <abdul.b.ijaz@intel.com> writes:
> In case of the Python frame-filters, this change filters trampoline
> functions when the option 'skip-trampoline-functions' is set to 'on'.
> GDB recently added the option to hide frames that are marked by the
> compiler with "DW_AT_trampoline", see commit 'Skip trampoline frames
> for the backtrace command'. This implements the same functionality
> when python frame filters are in use.
> diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c index
> afa89f0d112..098b37230e1 100644
> --- a/gdb/python/py-frame.c
> +++ b/gdb/python/py-frame.c
> @@ -59,6 +59,17 @@ frame_object_to_frame_info (PyObject *obj)
> if (frame == NULL)
> return NULL;
> + if (skip_trampoline_functions)
> + {
> + for (int i = 0; (SAFE_TRAMPOLINE_CHAIN (i, frame)
> + && in_trampoline_frame (frame)); ++i)
> + {
> + frame = get_prev_frame (frame);
> + if (frame == nullptr)
> + return nullptr;
> + }
> + }
This seems suspicious to me.
For one thing, suppose you have A -> Trampoline -> B. Then in Python you fetch the frame B. What does B.newer() return?
I think with this code it will just return B again.
For DAP, and frame filters, I tend to think it would be better for Python to simply see the frames as they are, but then add a new attribute -- on the frame, but also maybe on the symbol -- indicating if it's been marked as a trampoline.
Then maybe _FrameDecoratorBase.elided could return True if the frame is a non-"live" trampoline frame.
Tom
________________________________________
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 (89) 99143-0
www.intel.de
Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman
Chairperson of the Supervisory Board: Sonja Pierer
Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PING][PATCH v11 00/10] GDB support for DW_AT_trampoline
2026-08-03 19:34 [PATCH v11 00/10] GDB support for DW_AT_trampoline Abdul Basit Ijaz
` (9 preceding siblings ...)
2026-08-03 19:34 ` [PATCH v11 10/10] gdb: Filter trampoline frames in backtrace when using Python frame-filters Abdul Basit Ijaz
@ 2026-09-09 7:40 ` Ijaz, Abdul B
2026-09-18 9:33 ` Ijaz, Abdul B
10 siblings, 1 reply; 32+ messages in thread
From: Ijaz, Abdul B @ 2026-09-09 7:40 UTC (permalink / raw)
To: gdb-patches; +Cc: JiniSusan.George, tom, eliz, Ijaz, Abdul B
Ping.
V11 Patch series: https://sourceware.org/pipermail/gdb-patches/2026-August/229157.html
Thanks & Best Regards
Abdul Basit
-----Original Message-----
From: Ijaz, Abdul B <abdul.b.ijaz@intel.com>
Sent: Monday, August 3, 2026 9:35 PM
To: gdb-patches@sourceware.org
Cc: Ijaz, Abdul B <abdul.b.ijaz@intel.com>; JiniSusan.George@amd.com; tom@tromey.com; eliz@gnu.org
Subject: [PATCH v11 00/10] GDB support for DW_AT_trampoline
Hi All,
please find attached a series of patches that attempts to enable GDB to handle the DW_AT_trampoline attribute on functions and inlined functions.
DW_AT_trampoline can be emitted by the compiler for functions that are compiler generated trampolines (e.g. wrapping other function calls).
In doing so, the compiler can specify a target as the value of DW_AT_trampoline which the trampoline is wrapping.
This series enables GDB to recognize the DW_AT_trampoline and store the target for a given function. Patch 3 adapts GDB's stepping behavior when dealing with trampolines and attempts to - by default - hide these trampolines from the user. When about to step into a trampoline, instead, GDB will try and step through the trampoline and directly towards the target. For rest of the patches as the name of the patch indicates it implements skipping of trampolines for the command mentioned in the patch name.
A new setting has also been introduced in this change to turn off this modified stepping behavior or printing of stack for trampolines.
The motivation for these patches comes from ifx which emits the attribute for some of its compiler generated functions. As I do not know of any other compiler (especially gcc/gfortran) emitting DW_AT_trampoline, I added a gdb.dwarf2 test to this series in order to test the trampoline handling within GDB.
No changes in the reviewed documentation since V8 patch:
https://sourceware.org/pipermail/gdb-patches/2024-May/209395.html
https://sourceware.org/pipermail/gdb-patches/2024-May/209396.html
Changes since V10:
* Rebase and update copyright year to 2026 for newly added files in this patch.
* Fix issue related to O2 and update test to cover both O0 & O2.
No regression seen on testing x64/(-m32)/x32 configurations.
Thanks & Best Regards
Abdul Basit Ijaz
Abdul Basit Ijaz (7):
gdb: Skip trampoline frames for the backtrace command.
gdb: Skip trampoline functions for the finish and reverse-finish
commands.
gdb: Skip trampoline functions for the up command.
gdb: Skip trampoline functions for the return command.
gdb, mi: Skip trampoline functions for the -stack-list-frames command.
gdb, mi: Skip trampoline functions for the -stack-list-arguments
command.
gdb: Filter trampoline frames in backtrace when using Python
frame-filters.
Nils-Christian Kempke (3):
gdb, dwarf: add support for DW_AT_trampoline in DWARF reader
gdb/symtab: add lookup for trampoline functions
gdb: handle stepping through functions with DW_AT_trampoline
gdb/NEWS | 13 +
gdb/doc/gdb.texinfo | 52 +++-
gdb/dwarf2/read.c | 39 ++-
gdb/gdbtypes.c | 34 ++-
gdb/gdbtypes.h | 113 +++++++-
gdb/infcmd.c | 12 +
gdb/infrun.c | 103 +++++++-
gdb/infrun.h | 16 ++
gdb/mi/mi-cmd-stack.c | 14 +
gdb/python/py-frame.c | 11 +
gdb/stack.c | 26 ++
gdb/symtab.c | 139 ++++++++++
gdb/symtab.h | 29 +++
.../gdb.dwarf2/dw2-function-trampolines.c | 80 ++++++
.../gdb.dwarf2/dw2-function-trampolines.exp | 244 ++++++++++++++++++
gdb/testsuite/gdb.fortran/func-trampoline.exp | 116 +++++++++
gdb/testsuite/gdb.fortran/func-trampoline.f90 | 40 +++
.../gdb.fortran/mixed-lang-stack.exp | 8 +-
gdb/testsuite/gdb.mi/mi-func-trampoline.exp | 76 ++++++
.../gdb.python/py-framefilter-trampoline.exp | 77 ++++++
.../gdb.python/py-framefilter-trampoline.py | 31 +++
.../gdb.reverse/finish-reverse-trampoline.exp | 56 ++++
22 files changed, 1315 insertions(+), 14 deletions(-) create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-function-trampolines.c
create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-function-trampolines.exp
create mode 100644 gdb/testsuite/gdb.fortran/func-trampoline.exp
create mode 100644 gdb/testsuite/gdb.fortran/func-trampoline.f90
create mode 100644 gdb/testsuite/gdb.mi/mi-func-trampoline.exp
create mode 100644 gdb/testsuite/gdb.python/py-framefilter-trampoline.exp
create mode 100644 gdb/testsuite/gdb.python/py-framefilter-trampoline.py
create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-trampoline.exp
--
2.34.1
________________________________________
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 (89) 99143-0
www.intel.de
Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman
Chairperson of the Supervisory Board: Sonja Pierer
Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 32+ messages in thread* RE: [PING][PATCH v11 00/10] GDB support for DW_AT_trampoline
2026-09-09 7:40 ` [PING][PATCH v11 00/10] GDB support for DW_AT_trampoline Ijaz, Abdul B
@ 2026-09-18 9:33 ` Ijaz, Abdul B
2026-10-01 7:49 ` Ijaz, Abdul B
0 siblings, 1 reply; 32+ messages in thread
From: Ijaz, Abdul B @ 2026-09-18 9:33 UTC (permalink / raw)
To: gdb-patches; +Cc: JiniSusan.George, tom, eliz, Ijaz, Abdul B
Ping.
V11 Patch series: https://sourceware.org/pipermail/gdb-patches/2026-August/229157.html
Thanks & Best Regards
Abdul Basit
-----Original Message-----
From: Ijaz, Abdul B
Sent: Wednesday, September 9, 2026 9:40 AM
To: gdb-patches@sourceware.org
Cc: JiniSusan.George@amd.com; tom@tromey.com; eliz@gnu.org; Ijaz, Abdul B <abdul.b.ijaz@intel.com>
Subject: [PING][PATCH v11 00/10] GDB support for DW_AT_trampoline
Ping.
V11 Patch series: https://sourceware.org/pipermail/gdb-patches/2026-August/229157.html
Thanks & Best Regards
Abdul Basit
-----Original Message-----
From: Ijaz, Abdul B <abdul.b.ijaz@intel.com>
Sent: Monday, August 3, 2026 9:35 PM
To: gdb-patches@sourceware.org
Cc: Ijaz, Abdul B <abdul.b.ijaz@intel.com>; JiniSusan.George@amd.com; tom@tromey.com; eliz@gnu.org
Subject: [PATCH v11 00/10] GDB support for DW_AT_trampoline
Hi All,
please find attached a series of patches that attempts to enable GDB to handle the DW_AT_trampoline attribute on functions and inlined functions.
DW_AT_trampoline can be emitted by the compiler for functions that are compiler generated trampolines (e.g. wrapping other function calls).
In doing so, the compiler can specify a target as the value of DW_AT_trampoline which the trampoline is wrapping.
This series enables GDB to recognize the DW_AT_trampoline and store the target for a given function. Patch 3 adapts GDB's stepping behavior when dealing with trampolines and attempts to - by default - hide these trampolines from the user. When about to step into a trampoline, instead, GDB will try and step through the trampoline and directly towards the target. For rest of the patches as the name of the patch indicates it implements skipping of trampolines for the command mentioned in the patch name.
A new setting has also been introduced in this change to turn off this modified stepping behavior or printing of stack for trampolines.
The motivation for these patches comes from ifx which emits the attribute for some of its compiler generated functions. As I do not know of any other compiler (especially gcc/gfortran) emitting DW_AT_trampoline, I added a gdb.dwarf2 test to this series in order to test the trampoline handling within GDB.
No changes in the reviewed documentation since V8 patch:
https://sourceware.org/pipermail/gdb-patches/2024-May/209395.html
https://sourceware.org/pipermail/gdb-patches/2024-May/209396.html
Changes since V10:
* Rebase and update copyright year to 2026 for newly added files in this patch.
* Fix issue related to O2 and update test to cover both O0 & O2.
No regression seen on testing x64/(-m32)/x32 configurations.
Thanks & Best Regards
Abdul Basit Ijaz
Abdul Basit Ijaz (7):
gdb: Skip trampoline frames for the backtrace command.
gdb: Skip trampoline functions for the finish and reverse-finish
commands.
gdb: Skip trampoline functions for the up command.
gdb: Skip trampoline functions for the return command.
gdb, mi: Skip trampoline functions for the -stack-list-frames command.
gdb, mi: Skip trampoline functions for the -stack-list-arguments
command.
gdb: Filter trampoline frames in backtrace when using Python
frame-filters.
Nils-Christian Kempke (3):
gdb, dwarf: add support for DW_AT_trampoline in DWARF reader
gdb/symtab: add lookup for trampoline functions
gdb: handle stepping through functions with DW_AT_trampoline
gdb/NEWS | 13 +
gdb/doc/gdb.texinfo | 52 +++-
gdb/dwarf2/read.c | 39 ++-
gdb/gdbtypes.c | 34 ++-
gdb/gdbtypes.h | 113 +++++++-
gdb/infcmd.c | 12 +
gdb/infrun.c | 103 +++++++-
gdb/infrun.h | 16 ++
gdb/mi/mi-cmd-stack.c | 14 +
gdb/python/py-frame.c | 11 +
gdb/stack.c | 26 ++
gdb/symtab.c | 139 ++++++++++
gdb/symtab.h | 29 +++
.../gdb.dwarf2/dw2-function-trampolines.c | 80 ++++++
.../gdb.dwarf2/dw2-function-trampolines.exp | 244 ++++++++++++++++++
gdb/testsuite/gdb.fortran/func-trampoline.exp | 116 +++++++++
gdb/testsuite/gdb.fortran/func-trampoline.f90 | 40 +++
.../gdb.fortran/mixed-lang-stack.exp | 8 +-
gdb/testsuite/gdb.mi/mi-func-trampoline.exp | 76 ++++++
.../gdb.python/py-framefilter-trampoline.exp | 77 ++++++
.../gdb.python/py-framefilter-trampoline.py | 31 +++
.../gdb.reverse/finish-reverse-trampoline.exp | 56 ++++
22 files changed, 1315 insertions(+), 14 deletions(-) create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-function-trampolines.c
create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-function-trampolines.exp
create mode 100644 gdb/testsuite/gdb.fortran/func-trampoline.exp
create mode 100644 gdb/testsuite/gdb.fortran/func-trampoline.f90
create mode 100644 gdb/testsuite/gdb.mi/mi-func-trampoline.exp
create mode 100644 gdb/testsuite/gdb.python/py-framefilter-trampoline.exp
create mode 100644 gdb/testsuite/gdb.python/py-framefilter-trampoline.py
create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-trampoline.exp
--
2.34.1
________________________________________
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 (89) 99143-0
www.intel.de
Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman
Chairperson of the Supervisory Board: Sonja Pierer
Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 32+ messages in thread* RE: [PING][PATCH v11 00/10] GDB support for DW_AT_trampoline
2026-09-18 9:33 ` Ijaz, Abdul B
@ 2026-10-01 7:49 ` Ijaz, Abdul B
2026-10-12 13:52 ` Ijaz, Abdul B
0 siblings, 1 reply; 32+ messages in thread
From: Ijaz, Abdul B @ 2026-10-01 7:49 UTC (permalink / raw)
To: gdb-patches; +Cc: JiniSusan.George, tom, eliz, Ijaz, Abdul B
Ping.
V11 Patch series: https://sourceware.org/pipermail/gdb-patches/2026-August/229157.html
Thanks & Best Regards
Abdul Basit
-----Original Message-----
From: Ijaz, Abdul B <abdul.b.ijaz@intel.com>
Sent: Monday, August 3, 2026 9:35 PM
To: gdb-patches@sourceware.org
Cc: Ijaz, Abdul B <abdul.b.ijaz@intel.com>; JiniSusan.George@amd.com; tom@tromey.com; eliz@gnu.org
Subject: [PATCH v11 00/10] GDB support for DW_AT_trampoline
Hi All,
please find attached a series of patches that attempts to enable GDB to handle the DW_AT_trampoline attribute on functions and inlined functions.
DW_AT_trampoline can be emitted by the compiler for functions that are compiler generated trampolines (e.g. wrapping other function calls).
In doing so, the compiler can specify a target as the value of DW_AT_trampoline which the trampoline is wrapping.
This series enables GDB to recognize the DW_AT_trampoline and store the target for a given function. Patch 3 adapts GDB's stepping behavior when dealing with trampolines and attempts to - by default - hide these trampolines from the user. When about to step into a trampoline, instead, GDB will try and step through the trampoline and directly towards the target. For rest of the patches as the name of the patch indicates it implements skipping of trampolines for the command mentioned in the patch name.
A new setting has also been introduced in this change to turn off this modified stepping behavior or printing of stack for trampolines.
The motivation for these patches comes from ifx which emits the attribute for some of its compiler generated functions. As I do not know of any other compiler (especially gcc/gfortran) emitting DW_AT_trampoline, I added a gdb.dwarf2 test to this series in order to test the trampoline handling within GDB.
No changes in the reviewed documentation since V8 patch:
https://sourceware.org/pipermail/gdb-patches/2024-May/209395.html
https://sourceware.org/pipermail/gdb-patches/2024-May/209396.html
Changes since V10:
* Rebase and update copyright year to 2026 for newly added files in this patch.
* Fix issue related to O2 and update test to cover both O0 & O2.
No regression seen on testing x64/(-m32)/x32 configurations.
Thanks & Best Regards
Abdul Basit Ijaz
Abdul Basit Ijaz (7):
gdb: Skip trampoline frames for the backtrace command.
gdb: Skip trampoline functions for the finish and reverse-finish
commands.
gdb: Skip trampoline functions for the up command.
gdb: Skip trampoline functions for the return command.
gdb, mi: Skip trampoline functions for the -stack-list-frames command.
gdb, mi: Skip trampoline functions for the -stack-list-arguments
command.
gdb: Filter trampoline frames in backtrace when using Python
frame-filters.
Nils-Christian Kempke (3):
gdb, dwarf: add support for DW_AT_trampoline in DWARF reader
gdb/symtab: add lookup for trampoline functions
gdb: handle stepping through functions with DW_AT_trampoline
gdb/NEWS | 13 +
gdb/doc/gdb.texinfo | 52 +++-
gdb/dwarf2/read.c | 39 ++-
gdb/gdbtypes.c | 34 ++-
gdb/gdbtypes.h | 113 +++++++-
gdb/infcmd.c | 12 +
gdb/infrun.c | 103 +++++++-
gdb/infrun.h | 16 ++
gdb/mi/mi-cmd-stack.c | 14 +
gdb/python/py-frame.c | 11 +
gdb/stack.c | 26 ++
gdb/symtab.c | 139 ++++++++++
gdb/symtab.h | 29 +++
.../gdb.dwarf2/dw2-function-trampolines.c | 80 ++++++
.../gdb.dwarf2/dw2-function-trampolines.exp | 244 ++++++++++++++++++
gdb/testsuite/gdb.fortran/func-trampoline.exp | 116 +++++++++
gdb/testsuite/gdb.fortran/func-trampoline.f90 | 40 +++
.../gdb.fortran/mixed-lang-stack.exp | 8 +-
gdb/testsuite/gdb.mi/mi-func-trampoline.exp | 76 ++++++
.../gdb.python/py-framefilter-trampoline.exp | 77 ++++++
.../gdb.python/py-framefilter-trampoline.py | 31 +++
.../gdb.reverse/finish-reverse-trampoline.exp | 56 ++++
22 files changed, 1315 insertions(+), 14 deletions(-) create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-function-trampolines.c
create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-function-trampolines.exp
create mode 100644 gdb/testsuite/gdb.fortran/func-trampoline.exp
create mode 100644 gdb/testsuite/gdb.fortran/func-trampoline.f90
create mode 100644 gdb/testsuite/gdb.mi/mi-func-trampoline.exp
create mode 100644 gdb/testsuite/gdb.python/py-framefilter-trampoline.exp
create mode 100644 gdb/testsuite/gdb.python/py-framefilter-trampoline.py
create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-trampoline.exp
--
2.34.1
________________________________________
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 (89) 99143-0
www.intel.de
Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman
Chairperson of the Supervisory Board: Sonja Pierer
Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 32+ messages in thread* RE: [PING][PATCH v11 00/10] GDB support for DW_AT_trampoline
2026-10-01 7:49 ` Ijaz, Abdul B
@ 2026-10-12 13:52 ` Ijaz, Abdul B
0 siblings, 0 replies; 32+ messages in thread
From: Ijaz, Abdul B @ 2026-10-12 13:52 UTC (permalink / raw)
To: gdb-patches; +Cc: JiniSusan.George, tom, eliz
Ping.
V11 Patch series: https://sourceware.org/pipermail/gdb-patches/2026-August/229157.html
Thanks & Best Regards
Abdul Basit
-----Original Message-----
From: Ijaz, Abdul B <abdul.b.ijaz@intel.com>
Sent: Monday, August 3, 2026 9:35 PM
To: gdb-patches@sourceware.org
Cc: Ijaz, Abdul B <abdul.b.ijaz@intel.com>; JiniSusan.George@amd.com; tom@tromey.com; eliz@gnu.org
Subject: [PATCH v11 00/10] GDB support for DW_AT_trampoline
Hi All,
please find attached a series of patches that attempts to enable GDB to handle the DW_AT_trampoline attribute on functions and inlined functions.
DW_AT_trampoline can be emitted by the compiler for functions that are compiler generated trampolines (e.g. wrapping other function calls).
In doing so, the compiler can specify a target as the value of DW_AT_trampoline which the trampoline is wrapping.
This series enables GDB to recognize the DW_AT_trampoline and store the target for a given function. Patch 3 adapts GDB's stepping behavior when dealing with trampolines and attempts to - by default - hide these trampolines from the user. When about to step into a trampoline, instead, GDB will try and step through the trampoline and directly towards the target. For rest of the patches as the name of the patch indicates it implements skipping of trampolines for the command mentioned in the patch name.
A new setting has also been introduced in this change to turn off this modified stepping behavior or printing of stack for trampolines.
The motivation for these patches comes from ifx which emits the attribute for some of its compiler generated functions. As I do not know of any other compiler (especially gcc/gfortran) emitting DW_AT_trampoline, I added a gdb.dwarf2 test to this series in order to test the trampoline handling within GDB.
No changes in the reviewed documentation since V8 patch:
https://sourceware.org/pipermail/gdb-patches/2024-May/209395.html
https://sourceware.org/pipermail/gdb-patches/2024-May/209396.html
Changes since V10:
* Rebase and update copyright year to 2026 for newly added files in this patch.
* Fix issue related to O2 and update test to cover both O0 & O2.
No regression seen on testing x64/(-m32)/x32 configurations.
Thanks & Best Regards
Abdul Basit Ijaz
Abdul Basit Ijaz (7):
gdb: Skip trampoline frames for the backtrace command.
gdb: Skip trampoline functions for the finish and reverse-finish
commands.
gdb: Skip trampoline functions for the up command.
gdb: Skip trampoline functions for the return command.
gdb, mi: Skip trampoline functions for the -stack-list-frames command.
gdb, mi: Skip trampoline functions for the -stack-list-arguments
command.
gdb: Filter trampoline frames in backtrace when using Python
frame-filters.
Nils-Christian Kempke (3):
gdb, dwarf: add support for DW_AT_trampoline in DWARF reader
gdb/symtab: add lookup for trampoline functions
gdb: handle stepping through functions with DW_AT_trampoline
gdb/NEWS | 13 +
gdb/doc/gdb.texinfo | 52 +++-
gdb/dwarf2/read.c | 39 ++-
gdb/gdbtypes.c | 34 ++-
gdb/gdbtypes.h | 113 +++++++-
gdb/infcmd.c | 12 +
gdb/infrun.c | 103 +++++++-
gdb/infrun.h | 16 ++
gdb/mi/mi-cmd-stack.c | 14 +
gdb/python/py-frame.c | 11 +
gdb/stack.c | 26 ++
gdb/symtab.c | 139 ++++++++++
gdb/symtab.h | 29 +++
.../gdb.dwarf2/dw2-function-trampolines.c | 80 ++++++
.../gdb.dwarf2/dw2-function-trampolines.exp | 244 ++++++++++++++++++
gdb/testsuite/gdb.fortran/func-trampoline.exp | 116 +++++++++
gdb/testsuite/gdb.fortran/func-trampoline.f90 | 40 +++
.../gdb.fortran/mixed-lang-stack.exp | 8 +-
gdb/testsuite/gdb.mi/mi-func-trampoline.exp | 76 ++++++
.../gdb.python/py-framefilter-trampoline.exp | 77 ++++++
.../gdb.python/py-framefilter-trampoline.py | 31 +++
.../gdb.reverse/finish-reverse-trampoline.exp | 56 ++++
22 files changed, 1315 insertions(+), 14 deletions(-) create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-function-trampolines.c
create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-function-trampolines.exp
create mode 100644 gdb/testsuite/gdb.fortran/func-trampoline.exp
create mode 100644 gdb/testsuite/gdb.fortran/func-trampoline.f90
create mode 100644 gdb/testsuite/gdb.mi/mi-func-trampoline.exp
create mode 100644 gdb/testsuite/gdb.python/py-framefilter-trampoline.exp
create mode 100644 gdb/testsuite/gdb.python/py-framefilter-trampoline.py
create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-trampoline.exp
--
2.34.1
________________________________________
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 (89) 99143-0
www.intel.de
Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman
Chairperson of the Supervisory Board: Sonja Pierer
Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 32+ messages in thread