From: Abdul Basit Ijaz <abdul.b.ijaz@intel.com>
To: gdb-patches@sourceware.org
Cc: abdul.b.ijaz@intel.com, JiniSusan.George@amd.com, tom@tromey.com,
eliz@gnu.org,
Nils-Christian Kempke <nils-christian.kempke@intel.com>
Subject: [PATCH v11 01/10] gdb, dwarf: add support for DW_AT_trampoline in DWARF reader
Date: Mon, 3 Aug 2026 21:34:40 +0200 [thread overview]
Message-ID: <20260803193449.33375-2-abdul.b.ijaz@intel.com> (raw)
In-Reply-To: <20260803193449.33375-1-abdul.b.ijaz@intel.com>
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.
next prev parent reply other threads:[~2026-08-03 19:36 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
2026-08-03 19:34 ` [PATCH v11 02/10] gdb/symtab: add lookup for trampoline functions Abdul Basit Ijaz
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 ` [PATCH v11 04/10] gdb: Skip trampoline frames for the backtrace command Abdul Basit Ijaz
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 ` [PATCH v11 06/10] gdb: Skip trampoline functions for the up command Abdul Basit Ijaz
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 ` [PATCH v11 08/10] gdb, mi: Skip trampoline functions for the -stack-list-frames command Abdul Basit Ijaz
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 ` [PATCH v11 10/10] gdb: Filter trampoline frames in backtrace when using Python frame-filters Abdul Basit Ijaz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260803193449.33375-2-abdul.b.ijaz@intel.com \
--to=abdul.b.ijaz@intel.com \
--cc=JiniSusan.George@amd.com \
--cc=eliz@gnu.org \
--cc=gdb-patches@sourceware.org \
--cc=nils-christian.kempke@intel.com \
--cc=tom@tromey.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox