public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 1/3] gdb: add support for DW_AT_trampoline in DWARF reader
@ 2022-07-07 12:15 Nils-Christian Kempke
  2022-07-07 12:15 ` [PATCH 2/3] gdb/symtab: add lookup for trampoline functions Nils-Christian Kempke
                   ` (3 more replies)
  0 siblings, 4 replies; 11+ messages in thread
From: Nils-Christian Kempke @ 2022-07-07 12:15 UTC (permalink / raw)
  To: gdb-patches

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_subroutines 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 but not specifying the target 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 done in preparation of the following
patches which will add a mechanism to hide DW_AT_trampoline subroutines
from the user.

gdb/ChangeLog:
2022-05-22  Nils-Christian Kempke  <nils-christian.kempke@intel.com>

	* dwarf2/read.c (read_subroutine_type): Read in DW_AT_trampoline.
	* gdbtypes.c (print_trampoline_target_info): New helper method.
	(recursive_dump_type): Add trampoline info.
	(copy_type_recursive): Copy trampoline info.
	* gdbtypes.h (func_type): Add trampoline specific fields.
	(trampoline_target_kind): New enum.
	(trampoline_target): New struct for storing DW_AT_trampoline's
	value.
	(TYPE_IS_TRAMPOLINE): New define.
	(TYPE_TRAMPOLINE_TARGET): New define.

Signed-off-by: Nils-Christian Kempke <nils-christian.kempke@intel.com>
---
 gdb/dwarf2/read.c | 43 ++++++++++++++++++++++++++
 gdb/gdbtypes.c    | 31 +++++++++++++++++++
 gdb/gdbtypes.h    | 79 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 153 insertions(+)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 23fe5679cbd..7f80c31d051 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -16491,6 +16491,49 @@ 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)
+    {
+      CORE_ADDR baseaddr = objfile->text_section_offset ();
+
+      TYPE_IS_TRAMPOLINE (ftype) = true;
+      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_physname
+	  (attr->as_string ());
+      else if (attr->form_is_ref ())
+	{
+	  die_info *target_die;
+	  dwarf2_cu *target_cu = cu;
+
+	  target_die = follow_die_ref (die, attr, &target_cu);
+	  const char* target_name = dwarf2_name (target_die, target_cu);
+	  if (target_name == nullptr)
+	    {
+	      complaint (_("DW_AT_trampoline target DIE has no name for"
+			 "referencing DIE %s [in module %s]"),
+			 sect_offset_str (die->sect_off),
+			 objfile_name (objfile));
+	    }
+	  TYPE_TRAMPOLINE_TARGET (ftype)->set_target_physname (target_name);
+	}
+      else if (attr->form_is_unsigned ())
+	TYPE_TRAMPOLINE_TARGET (ftype)->set_target_flag (attr->as_boolean ());
+      else
+	{
+	  CORE_ADDR target_addr = attr->as_address ();
+	  target_addr = gdbarch_adjust_dwarf2_addr (objfile->arch (),
+						    target_addr + baseaddr);
+	  TYPE_TRAMPOLINE_TARGET (ftype)->set_target_physaddr (target_addr);
+	}
+    }
+
   /* 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.  */
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index c8f98554859..66e04882d48 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -5205,6 +5205,31 @@ 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_PHYSADDR:
+      gdb_printf ("%*starget physaddr: 0x%lx\n", spaces + 2, "",
+		  TYPE_TRAMPOLINE_TARGET (type)->target_physaddr ());
+      break;
+    case TRAMPOLINE_TARGET_PHYSNAME:
+      gdb_printf ("%*starget physname: %s\n", spaces + 2, "",
+		  TYPE_TRAMPOLINE_TARGET (type)->target_physname ());
+      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.  */
@@ -5531,6 +5556,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 ("%*sis_trampoline %d\n", spaces, "",
+		    TYPE_IS_TRAMPOLINE (type));
+	if (TYPE_IS_TRAMPOLINE (type))
+	  print_trampoline_target_info (type, spaces);
 	break;
 
       case TYPE_SPECIFIC_SELF_TYPE:
@@ -5762,6 +5791,8 @@ copy_type_recursive (struct objfile *objfile,
       TYPE_CALLING_CONVENTION (new_type) = TYPE_CALLING_CONVENTION (type);
       TYPE_NO_RETURN (new_type) = TYPE_NO_RETURN (type);
       TYPE_TAIL_CALL_LIST (new_type) = NULL;
+      TYPE_IS_TRAMPOLINE (new_type) = TYPE_IS_TRAMPOLINE (type);
+      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 7437e1db8ab..846de1289ad 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -1811,6 +1811,83 @@ struct func_type
        contains the method.  */
 
     struct type *self_type;
+
+    /* * For functions marked with the DW_AT_trampoline.  These are
+       compiler generated wrappers that should be hidden from the user.  */
+
+    unsigned int is_trampoline : 1;
+
+    struct trampoline_target *self_trampoline_target;
+  };
+
+/* The kind of location held by this call site target.  */
+enum trampoline_target_kind
+  {
+    /* An address.  */
+    TRAMPOLINE_TARGET_PHYSADDR,
+    /* A (mangled) name.  */
+    TRAMPOLINE_TARGET_PHYSNAME,
+    /* An flag (target is unknown).  */
+    TRAMPOLINE_TARGET_FLAG,
+  };
+
+struct trampoline_target
+  {
+    trampoline_target_kind target_kind () const
+    {
+      return m_target_kind;
+    }
+
+    void set_target_physaddr (CORE_ADDR physaddr)
+    {
+      m_target_kind = TRAMPOLINE_TARGET_PHYSADDR;
+      m_trampoline_target.physaddr = physaddr;
+    }
+
+    CORE_ADDR target_physaddr () const
+    {
+      gdb_assert (m_target_kind == TRAMPOLINE_TARGET_PHYSADDR);
+      return m_trampoline_target.physaddr;
+    }
+
+    void set_target_physname (const char *physname)
+    {
+      m_target_kind = TRAMPOLINE_TARGET_PHYSNAME;
+      m_trampoline_target.physname = physname;
+    }
+
+    const char *target_physname () const
+    {
+      gdb_assert (m_target_kind == TRAMPOLINE_TARGET_PHYSNAME);
+      return m_trampoline_target.physname;
+    }
+
+    void set_target_flag (bool flag)
+    {
+      m_target_kind = TRAMPOLINE_TARGET_FLAG;
+      m_trampoline_target.flag = flag;
+    }
+
+    bool target_flag () const
+    {
+      gdb_assert (m_target_kind == TRAMPOLINE_TARGET_FLAG);
+      return m_trampoline_target.flag;
+    }
+
+  private:
+
+    union
+    {
+      /* Address.  */
+      CORE_ADDR physaddr;
+      /* Mangled name.  */
+      const char *physname;
+      /* Flag.  */
+      bool flag;
+    } m_trampoline_target;
+
+    /* * Discriminant for union m_trampoline_target.  */
+    ENUM_BITFIELD (trampoline_target_kind) m_target_kind : 2;
   };
 
 /* struct call_site_parameter can be referenced in callees by several ways.  */
@@ -2172,6 +2249,8 @@ extern void set_type_vptr_basetype (struct type *, struct type *);
 #define TYPE_CALLING_CONVENTION(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->calling_convention
 #define TYPE_NO_RETURN(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->is_noreturn
 #define TYPE_TAIL_CALL_LIST(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->tail_call_list
+#define TYPE_IS_TRAMPOLINE(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->is_trampoline
+#define TYPE_TRAMPOLINE_TARGET(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->self_trampoline_target
 #define TYPE_BASECLASS(thistype,index) ((thistype)->field (index).type ())
 #define TYPE_N_BASECLASSES(thistype) TYPE_CPLUS_SPECIFIC(thistype)->n_baseclasses
 #define TYPE_BASECLASS_NAME(thistype,index) (thistype->field (index).name ())
-- 
2.25.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 2/3] gdb/symtab: add lookup for trampoline functions
  2022-07-07 12:15 [PATCH 1/3] gdb: add support for DW_AT_trampoline in DWARF reader Nils-Christian Kempke
@ 2022-07-07 12:15 ` Nils-Christian Kempke
  2022-07-15 20:13   ` Tom Tromey
  2022-07-07 12:15 ` [PATCH 3/3] gdb/infrun: handle stepping through functions with DW_AT_trampoline Nils-Christian Kempke
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 11+ messages in thread
From: Nils-Christian Kempke @ 2022-07-07 12:15 UTC (permalink / raw)
  To: gdb-patches

In order to queriy information about the DW_AT_trampoline tag for
subroutines and inlined subroutines two function were added to symtab.

First, a routine for querying whether the given pc belongs to a block
that is associated with a function (maybe inlined) marked
DW_AT_trampoline.

Second, 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.

gdb/ChangeLog:
2022-05-30  Nils-Christian Kempke  <nils-christian.kempke@intel.com>

	* symtab.h (in_trampoline_function): New function
	(find_function_trampoline_target): New function.
	* symtab.c (in_trampoline_function): New function implementation.
	(find_function_trampoline_target): New implementation of
	trampoline target lookup.

Signed-off-by: Nils-Christian Kempke <nils-christian.kempke@intel.com>
---
 gdb/symtab.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/symtab.h | 14 ++++++++++++++
 2 files changed, 67 insertions(+)

diff --git a/gdb/symtab.c b/gdb/symtab.c
index 03aa2a96b87..a7ea928623b 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -72,6 +72,7 @@
 #include "gdbsupport/gdb_string_view.h"
 #include "gdbsupport/pathstuff.h"
 #include "gdbsupport/common-utils.h"
+#include "gdbsupport/symbol.h"
 
 /* Forward declarations for local functions.  */
 
@@ -4144,6 +4145,58 @@ find_function_alias_target (bound_minimal_symbol msymbol)
   return NULL;
 }
 
+/* See symtab.h.  */
+
+bool
+in_trampoline_function (CORE_ADDR pc)
+{
+  /* Find the innermost function containing pc.  This might be an inlined
+     function.  */
+  symbol *sym = find_pc_sect_containing_function (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_pc_sect_containing_function (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_PHYSNAME)
+	{
+	  /* Handle both the mangled and demangled PHYSNAME.  */
+	  const char *physname = trampoline->target_physname ();
+
+	  if (find_minimal_symbol_address (physname, &target_address, nullptr)
+	      != 0)
+	    target_address = 0;
+	}
+      else if (trampoline->target_kind () == TRAMPOLINE_TARGET_PHYSADDR)
+	{
+	  /* 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 = trampoline->target_physaddr ()
+	    + 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 ac902a4cbbe..7dad0ddba9f 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -2244,6 +2244,20 @@ extern const struct gnu_ifunc_fns *gnu_ifunc_fns_p;
 
 extern CORE_ADDR find_solib_trampoline_target (struct frame_info *, CORE_ADDR);
 
+/* Return wether or not the current pc is within a block that belongs to a
+   function that is marked as a trampoline by the compiler.  */
+
+extern bool in_trampoline_function (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.25.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 3/3] gdb/infrun: handle stepping through functions with DW_AT_trampoline
  2022-07-07 12:15 [PATCH 1/3] gdb: add support for DW_AT_trampoline in DWARF reader Nils-Christian Kempke
  2022-07-07 12:15 ` [PATCH 2/3] gdb/symtab: add lookup for trampoline functions Nils-Christian Kempke
@ 2022-07-07 12:15 ` Nils-Christian Kempke
  2022-07-15 20:20   ` Tom Tromey
  2022-07-13  7:39 ` [PATCH 1/3] gdb: add support for DW_AT_trampoline in DWARF reader George, Jini Susan
  2022-07-15 20:05 ` Tom Tromey
  3 siblings, 1 reply; 11+ messages in thread
From: Nils-Christian Kempke @ 2022-07-07 12:15 UTC (permalink / raw)
  To: gdb-patches

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/ChangeLog:
2022-05-31  Nils-Christian Kempke  <nils-christian.kempke@intel.com>

	* NEWS: Add skip-trampoline-functions to 'New commands' section.
	* infrun.c (skip_trampoline-functions): New static variable.
	(process_event_stop_test): Step into/through trampolines.
	(show_skip_trampoline_functions): New helper for the
	skip-trampoline-functions setting.
	(_initialize_infrun): Add skip-trampoline-functions setting.

gdb/doc/ChangeLog:
2022-05-31  Nils-Christian Kempke  <nils-christian.kempke@intel.com>

	* gdb.texinfo: Add section on skip-trampoline-functions setting.

gdb/testsuite/ChangeLog:
2022-05-31  Nils-Christian Kempke  <nils-christian.kempke@intel.com>

	* gdb.dwarf2/dw2-function-trampolines.c: New test source.
	* gdb.dwarf2/dw2-function-trampolines.exp: New test case.

Signed-off-by: Nils-Christian Kempke <nils-christian.kempke@intel.com>
---
 gdb/NEWS                                      |  14 +
 gdb/doc/gdb.texinfo                           |  36 +++
 gdb/infrun.c                                  |  82 +++++-
 .../gdb.dwarf2/dw2-function-trampolines.c     |  80 ++++++
 .../gdb.dwarf2/dw2-function-trampolines.exp   | 245 ++++++++++++++++++
 5 files changed, 453 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 1178a37017e..868e6a7f69f 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -164,6 +164,20 @@ GNU/Linux/LoongArch (gdbserver)	loongarch*-*-linux*
 
 * New commands
 
+set skip-trampoline-functions on|off
+show skip-trampoline-functions
+  This controls whether GDB's stepping behavior will recognize function calls
+  that have been marked as trampolines in the debug info.  It improves
+  stepping behavior in that it steps through trampoline code and hides it from
+  the user.  GDB can now step through trampolines that are correctly marked as
+  such in the compiler's debug info.  If the target of a trampoline is unknown,
+  GDB will continue until the trampoline section is left again and only then
+  hand control back to the user.  GDB does this even if the trampoline has no
+  associated line info.  If this is turned off, GDB will step into trampolines
+  if there is line table information for them or step over the trampoline calls
+  if there is no line table information.  Currently, only DWARF trampolines
+  are supported.
+
 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 7a4e337d15b..b9b69744260 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -6271,6 +6271,42 @@ 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 trampoline functions, which wrap the actual function call (the
+target of the trampoline).  The compiler might mark such a trampoline in its
+debug information.  Often, such trampolines do not have any source line
+information associated with them which will lead the @code{step} command to
+behave like a @code{next} and skip the function call completely.
+
+The @code{set skip-trampoline-functions on} command will cause the @code{step}
+command 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 again, 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 again
+step through 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 again.  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 the @code{step} command to completely ignore any trampoline information
+a compiler might have emitted in its debug info.  Trampolines will be treated
+like any other function when stepping.
+
+@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 02c98b50c8c..b7aeb102907 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -161,6 +161,12 @@ static ptid_t previous_inferior_ptid;
 
 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,
@@ -7061,7 +7067,6 @@ process_event_stop_test (struct execution_control_state *ecs)
 		  != find_pc_function (ecs->event_thread->stop_pc ())))))
     {
       CORE_ADDR stop_pc = ecs->event_thread->stop_pc ();
-      CORE_ADDR real_stop_pc;
 
       infrun_debug_printf ("stepped into subroutine");
 
@@ -7133,8 +7138,42 @@ 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)
+	{
+	  real_stop_pc = find_function_trampoline_target (stop_pc);
+
+	  /* Resolve a certian number of trampoline chains - 10 seems big
+	     enough here, but is arbitrary.  */
+	  for (int i = 0; i < 10 && 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)
@@ -7155,6 +7194,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
@@ -7163,7 +7204,9 @@ process_event_stop_test (struct execution_control_state *ecs)
 	struct symtab_and_line tmp_sal;
 
 	tmp_sal = find_pc_line (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))
@@ -7298,6 +7341,19 @@ 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.  */
+  if (skip_trampoline_functions && in_trampoline_function (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
@@ -9522,6 +9578,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)
@@ -9867,6 +9931,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 function trampolines and inlined\n\
+fucntion trampolines that have been marked trampolines in the compiler's\n\
+debug info.  If off, gdb will ignore the DW_TAG_trampoline while stepping."),
+			  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/testsuite/gdb.dwarf2/dw2-function-trampolines.c b/gdb/testsuite/gdb.dwarf2/dw2-function-trampolines.c
new file mode 100644
index 00000000000..0336710e130
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-function-trampolines.c
@@ -0,0 +1,80 @@
+/* Copyright 2022 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..0d1126c226c
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-function-trampolines.exp
@@ -0,0 +1,245 @@
+# Copyright 2019-2022 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 0
+}
+
+standard_testfile .c .S
+
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+    global srcdir subdir srcfile
+    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 {
+	    {language @DW_LANG_C}
+	    {name dw2-function-trampolines.c}
+	    {low_pc 0 addr}
+	    {stmt_list ${lines_label} DW_FORM_sec_offset}
+	} {
+	    subprogram {
+		{name target}
+		{low_pc $target_start addr}
+		{high_pc "$target_start + $target_len" addr}
+		{decl_file 1 data1}
+		{decl_line $target_decl_line data1}
+	    }
+	    # The 'trampoline' subprogram declares its target by name.
+	    trampoline_label: subprogram {
+		    {name trampoline}
+		    {low_pc $trampoline_start addr}
+		    {high_pc "$trampoline_start + $trampoline_len" addr}
+		    {trampoline target string}
+		}
+	    # The 'chained_trampoline' subprogram declares its target as die
+	    # reference.
+	    subprogram {
+		{name chained_trampoline}
+		{low_pc $chained_trampoline_start addr}
+		{high_pc "$chained_trampoline_start + $chained_trampoline_len" addr}
+		{trampoline %$trampoline_label}
+	    }
+	    # The 'doubly_chained_trampoline' subprogram declares no target.
+	    # Its DW_AT_trampoline is a flag set to true.
+	    subprogram {
+		{name doubly_chained_trampoline}
+		{low_pc $doubly_chained_trampoline_start addr}
+		{high_pc "$doubly_chained_trampoline_start + $doubly_chained_trampoline_len" addr}
+		{trampoline 1 flag}
+	    }
+	    subprogram {
+		{external 1 flag}
+		{name main}
+		{main_subprogram 1 flag}
+		{low_pc $main_start addr}
+		{high_pc "$main_start + $main_len" addr}
+		{decl_file 1 data1}
+		{decl_line $main_decl_line data1}
+	    } {
+		# The 'inlined_trampoline' subroutine declares its target as
+		# an address.
+		inlined_subroutine {
+		    {name inlined_trampoline}
+		    {low_pc main_label2 addr}
+		    {high_pc main_label3 addr}
+		    {trampoline $target_start addr}
+		    {call_file 1 data1}
+		    {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 -1
+}
+
+set target_first_line_pattern ".*target add.*"
+set target_second_line_pattern ".*target return.*"
+
+if ![runto_main] {
+    return -1
+}
+
+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 -1
+}
+
+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.25.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [PATCH 1/3] gdb: add support for DW_AT_trampoline in DWARF reader
  2022-07-07 12:15 [PATCH 1/3] gdb: add support for DW_AT_trampoline in DWARF reader Nils-Christian Kempke
  2022-07-07 12:15 ` [PATCH 2/3] gdb/symtab: add lookup for trampoline functions Nils-Christian Kempke
  2022-07-07 12:15 ` [PATCH 3/3] gdb/infrun: handle stepping through functions with DW_AT_trampoline Nils-Christian Kempke
@ 2022-07-13  7:39 ` George, Jini Susan
  2022-07-13 11:59   ` Kempke, Nils-Christian
  2022-07-15 20:05 ` Tom Tromey
  3 siblings, 1 reply; 11+ messages in thread
From: George, Jini Susan @ 2022-07-13  7:39 UTC (permalink / raw)
  To: Nils-Christian Kempke, gdb-patches

[Public]

Hi Nils,

Thanks for this. A few questions/ comments.

* Is there any common ground we can find with the way solib (linker PLT) trampolines are handled ? I am OK if we can't, but I think it might be better to check and rule it out.

* Also, do we want to resolve and display the target of the trampoline code (if possible) in the disassembled code also ?

* Also, do we want to refer to these trampolines differently so that these can be distinguished from the linker PLT trampolines and the signal trampolines ?

* In read.c, in read_subroutine_type(), where the DW_AT_trampoline attribute is of form reference, we seem to be storing the value corresponding to the  DW_AT_name attribute, whereas in many cases (C++ and other languages), it might make sense to store the mangled name typically obtained from the DW_AT_linkage_name attribute. Given this it might be good to have a C++ test case for this with trampoline target functions inside namespaces also. Maybe with the same target function name under multiple namespaces. Also, the comment in gdbtypes.h (Line 1883) mentions mangled name, which does not seem to match ?

* In gdbtypes.h:

1817
1818     unsigned int is_trampoline : 1;

Might be better to position this field as the 3rd field for better structure packing ?

* infrun.c: Line 7156: It might be better to have the '10' representing the number of chained trampoline traversals allowed as a macro.

A few nits below:
* infrun.c : Nits:
               Line 7154: spelling: certian
         Line 9941: spelling : fucntion

*symtab.h: Nit: line 2247: spelling: wether

Thanks,
Jini.

>>-----Original Message-----
>>From: Gdb-patches <gdb-patches-
>>bounces+jigeorge=amd.com@sourceware.org> On Behalf Of Nils-Christian
>>Kempke via Gdb-patches
>>Sent: Thursday, July 7, 2022 5:46 PM
>>To: gdb-patches@sourceware.org
>>Subject: [PATCH 1/3] gdb: add support for DW_AT_trampoline in DWARF reader
>>
>>[CAUTION: External Email]
>>
>>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_subroutines 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 but not specifying the target 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 done in preparation of the following patches which will add a
>>mechanism to hide DW_AT_trampoline subroutines from the user.
>>
>>gdb/ChangeLog:
>>2022-05-22  Nils-Christian Kempke  <nils-christian.kempke@intel.com>
>>
>>        * dwarf2/read.c (read_subroutine_type): Read in DW_AT_trampoline.
>>        * gdbtypes.c (print_trampoline_target_info): New helper method.
>>        (recursive_dump_type): Add trampoline info.
>>        (copy_type_recursive): Copy trampoline info.
>>        * gdbtypes.h (func_type): Add trampoline specific fields.
>>        (trampoline_target_kind): New enum.
>>        (trampoline_target): New struct for storing DW_AT_trampoline's
>>        value.
>>        (TYPE_IS_TRAMPOLINE): New define.
>>        (TYPE_TRAMPOLINE_TARGET): New define.
>>
>>Signed-off-by: Nils-Christian Kempke <nils-christian.kempke@intel.com>
>>---
>> gdb/dwarf2/read.c | 43 ++++++++++++++++++++++++++
>> gdb/gdbtypes.c    | 31 +++++++++++++++++++
>> gdb/gdbtypes.h    | 79
>>+++++++++++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 153 insertions(+)
>>
>>diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index
>>23fe5679cbd..7f80c31d051 100644
>>--- a/gdb/dwarf2/read.c
>>+++ b/gdb/dwarf2/read.c
>>@@ -16491,6 +16491,49 @@ 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)
>>+    {
>>+      CORE_ADDR baseaddr = objfile->text_section_offset ();
>>+
>>+      TYPE_IS_TRAMPOLINE (ftype) = true;
>>+      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_physname
>>+         (attr->as_string ());
>>+      else if (attr->form_is_ref ())
>>+       {
>>+         die_info *target_die;
>>+         dwarf2_cu *target_cu = cu;
>>+
>>+         target_die = follow_die_ref (die, attr, &target_cu);
>>+         const char* target_name = dwarf2_name (target_die, target_cu);
>>+         if (target_name == nullptr)
>>+           {
>>+             complaint (_("DW_AT_trampoline target DIE has no name for"
>>+                        "referencing DIE %s [in module %s]"),
>>+                        sect_offset_str (die->sect_off),
>>+                        objfile_name (objfile));
>>+           }
>>+         TYPE_TRAMPOLINE_TARGET (ftype)->set_target_physname
>>(target_name);
>>+       }
>>+      else if (attr->form_is_unsigned ())
>>+       TYPE_TRAMPOLINE_TARGET (ftype)->set_target_flag (attr->as_boolean ());
>>+      else
>>+       {
>>+         CORE_ADDR target_addr = attr->as_address ();
>>+         target_addr = gdbarch_adjust_dwarf2_addr (objfile->arch (),
>>+                                                   target_addr + baseaddr);
>>+         TYPE_TRAMPOLINE_TARGET (ftype)->set_target_physaddr (target_addr);
>>+       }
>>+    }
>>+
>>   /* 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.  */ diff --git a/gdb/gdbtypes.c
>>b/gdb/gdbtypes.c index c8f98554859..66e04882d48 100644
>>--- a/gdb/gdbtypes.c
>>+++ b/gdb/gdbtypes.c
>>@@ -5205,6 +5205,31 @@ 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_PHYSADDR:
>>+      gdb_printf ("%*starget physaddr: 0x%lx\n", spaces + 2, "",
>>+                 TYPE_TRAMPOLINE_TARGET (type)->target_physaddr ());
>>+      break;
>>+    case TRAMPOLINE_TARGET_PHYSNAME:
>>+      gdb_printf ("%*starget physname: %s\n", spaces + 2, "",
>>+                 TYPE_TRAMPOLINE_TARGET (type)->target_physname ());
>>+      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.  */
>>@@ -5531,6 +5556,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 ("%*sis_trampoline %d\n", spaces, "",
>>+                   TYPE_IS_TRAMPOLINE (type));
>>+       if (TYPE_IS_TRAMPOLINE (type))
>>+         print_trampoline_target_info (type, spaces);
>>        break;
>>
>>       case TYPE_SPECIFIC_SELF_TYPE:
>>@@ -5762,6 +5791,8 @@ copy_type_recursive (struct objfile *objfile,
>>       TYPE_CALLING_CONVENTION (new_type) = TYPE_CALLING_CONVENTION
>>(type);
>>       TYPE_NO_RETURN (new_type) = TYPE_NO_RETURN (type);
>>       TYPE_TAIL_CALL_LIST (new_type) = NULL;
>>+      TYPE_IS_TRAMPOLINE (new_type) = TYPE_IS_TRAMPOLINE (type);
>>+      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 7437e1db8ab..846de1289ad 100644
>>--- a/gdb/gdbtypes.h
>>+++ b/gdb/gdbtypes.h
>>@@ -1811,6 +1811,83 @@ struct func_type
>>        contains the method.  */
>>
>>     struct type *self_type;
>>+
>>+    /* * For functions marked with the DW_AT_trampoline.  These are
>>+       compiler generated wrappers that should be hidden from the user.
>>+ */
>>+
>>+    unsigned int is_trampoline : 1;
>>+
>>+    struct trampoline_target *self_trampoline_target;  };
>>+
>>+/* The kind of location held by this call site target.  */ enum
>>+trampoline_target_kind
>>+  {
>>+    /* An address.  */
>>+    TRAMPOLINE_TARGET_PHYSADDR,
>>+    /* A (mangled) name.  */
>>+    TRAMPOLINE_TARGET_PHYSNAME,
>>+    /* An flag (target is unknown).  */
>>+    TRAMPOLINE_TARGET_FLAG,
>>+  };
>>+
>>+struct trampoline_target
>>+  {
>>+    trampoline_target_kind target_kind () const
>>+    {
>>+      return m_target_kind;
>>+    }
>>+
>>+    void set_target_physaddr (CORE_ADDR physaddr)
>>+    {
>>+      m_target_kind = TRAMPOLINE_TARGET_PHYSADDR;
>>+      m_trampoline_target.physaddr = physaddr;
>>+    }
>>+
>>+    CORE_ADDR target_physaddr () const
>>+    {
>>+      gdb_assert (m_target_kind == TRAMPOLINE_TARGET_PHYSADDR);
>>+      return m_trampoline_target.physaddr;
>>+    }
>>+
>>+    void set_target_physname (const char *physname)
>>+    {
>>+      m_target_kind = TRAMPOLINE_TARGET_PHYSNAME;
>>+      m_trampoline_target.physname = physname;
>>+    }
>>+
>>+    const char *target_physname () const
>>+    {
>>+      gdb_assert (m_target_kind == TRAMPOLINE_TARGET_PHYSNAME);
>>+      return m_trampoline_target.physname;
>>+    }
>>+
>>+    void set_target_flag (bool flag)
>>+    {
>>+      m_target_kind = TRAMPOLINE_TARGET_FLAG;
>>+      m_trampoline_target.flag = flag;
>>+    }
>>+
>>+    bool target_flag () const
>>+    {
>>+      gdb_assert (m_target_kind == TRAMPOLINE_TARGET_FLAG);
>>+      return m_trampoline_target.flag;
>>+    }
>>+
>>+  private:
>>+
>>+    union
>>+    {
>>+      /* Address.  */
>>+      CORE_ADDR physaddr;
>>+      /* Mangled name.  */
>>+      const char *physname;
>>+      /* Flag.  */
>>+      bool flag;
>>+    } m_trampoline_target;
>>+
>>+    /* * Discriminant for union m_trampoline_target.  */
>>+    ENUM_BITFIELD (trampoline_target_kind) m_target_kind : 2;
>>   };
>>
>> /* struct call_site_parameter can be referenced in callees by several ways.  */
>>@@ -2172,6 +2249,8 @@ extern void set_type_vptr_basetype (struct type *,
>>struct type *);  #define TYPE_CALLING_CONVENTION(thistype)
>>TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->calling_convention
>> #define TYPE_NO_RETURN(thistype) TYPE_MAIN_TYPE(thistype)-
>>>type_specific.func_stuff->is_noreturn
>> #define TYPE_TAIL_CALL_LIST(thistype) TYPE_MAIN_TYPE(thistype)-
>>>type_specific.func_stuff->tail_call_list
>>+#define TYPE_IS_TRAMPOLINE(thistype)
>>+TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->is_trampoline
>>+#define TYPE_TRAMPOLINE_TARGET(thistype)
>>+TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->self_trampoline_tar
>>+get
>> #define TYPE_BASECLASS(thistype,index) ((thistype)->field (index).type ())
>>#define TYPE_N_BASECLASSES(thistype) TYPE_CPLUS_SPECIFIC(thistype)-
>>>n_baseclasses
>> #define TYPE_BASECLASS_NAME(thistype,index) (thistype->field (index).name ())
>>--
>>2.25.1
>>
>>Intel Deutschland GmbH
>>Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
>>Tel: +49 89 99 8853-0,
>>https://nam11.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.int
>>el.de%2F&amp;data=05%7C01%7CJiniSusan.George%40amd.com%7C9c3f28b5
>>98cf49f888f908da601272a0%7C3dd8961fe4884e608e11a82d994e183d%7C0%7
>>C0%7C637927929632561872%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLj
>>AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C
>>%7C&amp;sdata=MBaQ7XpSZ4XFO963dnxF%2Fy1PD0gcx6k%2FjdaifxoSUaY%3D
>>&amp;reserved=0
>><https://nam11.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.in
>>tel.de%2F&amp;data=05%7C01%7CJiniSusan.George%40amd.com%7C9c3f28b5
>>98cf49f888f908da601272a0%7C3dd8961fe4884e608e11a82d994e183d%7C0%7
>>C0%7C637927929632561872%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLj
>>AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C
>>%7C&amp;sdata=MBaQ7XpSZ4XFO963dnxF%2Fy1PD0gcx6k%2FjdaifxoSUaY%3D
>>&amp;reserved=0>
>>Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva
>>Chairperson of the Supervisory Board: Nicole Lau Registered Office: Munich
>>Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [PATCH 1/3] gdb: add support for DW_AT_trampoline in DWARF reader
  2022-07-13  7:39 ` [PATCH 1/3] gdb: add support for DW_AT_trampoline in DWARF reader George, Jini Susan
@ 2022-07-13 11:59   ` Kempke, Nils-Christian
  2022-07-17 12:57     ` George, Jini Susan
  0 siblings, 1 reply; 11+ messages in thread
From: Kempke, Nils-Christian @ 2022-07-13 11:59 UTC (permalink / raw)
  To: George, Jini Susan, gdb-patches

Hi Jini,

Thanks for the feedback!

I have a few questions regarding your comments as I inlined below.

Cheers,
Nils

> -----Original Message-----
> From: George, Jini Susan <JiniSusan.George@amd.com>
> Sent: Wednesday, July 13, 2022 9:40 AM
> To: Kempke, Nils-Christian <nils-christian.kempke@intel.com>; gdb-
> patches@sourceware.org
> Subject: RE: [PATCH 1/3] gdb: add support for DW_AT_trampoline in DWARF
> reader
> 
> [Public]
> 
> Hi Nils,
> 
> Thanks for this. A few questions/ comments.
> 
> * Is there any common ground we can find with the way solib (linker PLT)
> trampolines are handled ? I am OK if we can't, but I think it might be better to
> check and rule it out.

I don't quite understand what you mean here but am also not super familiar
with the solib handling part of GDB.  The attached patches treat any function
that was marked as DW_AT_Trampoline in DWARF by the compiler.  As far as I
know not a single compiler (except ifx) emits this attribute up until now.  If a
compiler were to generate DWARF for the solib trampolines and if it were to
add the attribute, we could also treat solib trampolines with this approach.
But generally, the DW_AT_trampoline is independent of any other GDB
trampoline handling.
Not sure whether this answers your question.  Maybe you can elaborate a bit
more?

> 
> * Also, do we want to resolve and display the target of the trampoline code
> (if possible) in the disassembled code also ?
> 

So you mean, when I am about to step into a wrapper/step through a wrapper
I would display the target at the respective call statement with some note like

(gdb) disassemble
...
0x080483fa <+0>: push %ebp
0x080483fb <+1>: mov %esp,%ebp
0x080483fd <+3>: sub $0x8,%esp
=> 0x08048400 <+6>: movl $0x2,0x4(%esp)
0x08048408 <+14>: movl $0x1,(%esp)
0x0804840f <+21>: call 0x80483ed <func> (trampoline to: 0x12345 <other>)

?
So a change in the pretty_printer for assembly I assume (or somewhere deeper).

This would mean, GDB would have to check every time a call appears
somewhere in the disassembly whether or not the target is a trampoline, and,
if so, GDB would need to resolve this.

Generally, I think this might be a nice feature.  I'll have a look whether it can be
done without too much effort, but if it turns out to be considerably difficult I'd
rather like to leave this for a different patch.
If this is already done in the other trampoline cases (solibs and signals) it might
be needed for the completion of this patch though.

> * Also, do we want to refer to these trampolines differently so that these
> can be distinguished from the linker PLT trampolines and the signal
> trampolines ?
> 

I hoped that the patches made the difference clear enough.  Or can you
pinpoint something that seems unclear?  How would you instead refer to
them, I am a bit lost here, to be honest.  They are, after all, according to
their DWARF/debug info trampolines.  Referring to them differently would
in my opinion maybe obscure things?  But maybe you had something in mind.

> * In read.c, in read_subroutine_type(), where the DW_AT_trampoline
> attribute is of form reference, we seem to be storing the value
> corresponding to the  DW_AT_name attribute, whereas in many cases (C++
> and other languages), it might make sense to store the mangled name
> typically obtained from the DW_AT_linkage_name attribute. Given this it
> might be good to have a C++ test case for this with trampoline target
> functions inside namespaces also. Maybe with the same target function
> name under multiple namespaces. Also, the comment in gdbtypes.h (Line
> 1883) mentions mangled name, which does not seem to match ?

Yes, I think initially the comment was intended to only describe the
DW_AT_trampoline when its FORM is string.  That string could have been
both, mangled and demangled.  But I get your point.  I am not sure whether
storing the linkage name or the 'normal' name is correct here.  I think these are
two different issues: which name should be stored and should it be
demangled or not.  But I'll check this again.  I guess I'll have to check symbol
lookup again for this and see what makes most sense.

> 
> * In gdbtypes.h:
> 
> 1817
> 1818     unsigned int is_trampoline : 1;
> 
> Might be better to position this field as the 3rd field for better structure
> packing ?

The structure was poorly packed in the first place I think.  We have the
ENUM_BITFIELD in the beginning which can be either an enum or an unsigned
int.  I am not sure whether the size of an enum is defined somewhere but I'd
assume it is compiler dependent and usually the size of an int?
This is followed by another unsigned int and then by two pointers.

If we aimed at proper structure packing I'd assume the pointers (which would
usually be 8 bytes to all come first, then the (unsigned) int's with their (usually)
4 bytes, followed finally by the enum?

I considered this when implementing it but it seemed like an unrelated change
to me.  Assuming int is 4 bytes and we align to 8 bytes moving is_trampoline to
the 3rd position would also not do anything, would it?  We'd be at

4 byte
4 byte
4 byte
8 byte
8 byte
8 byte

Instead of 

4 byte
4 byte
8 byte
8 byte
4 byte
8 byte

I think switching is_trampoline and self_trampoline_target would make the
most sense here? (without touching the other members).

> * infrun.c: Line 7156: It might be better to have the '10' representing the
> number of chained trampoline traversals allowed as a macro.
> 

I also thought about this when implementing it.  I back then decided against it
but sure, I'll add that.

> A few nits below:
> * infrun.c : Nits:
>                Line 7154: spelling: certian
>          Line 9941: spelling : fucntion
> 
> *symtab.h: Nit: line 2247: spelling: wether

Thanks!
I'll change this in v2!

> 
> Thanks,
> Jini.
> 
> >>-----Original Message-----
> >>From: Gdb-patches <gdb-patches-
> >>bounces+jigeorge=amd.com@sourceware.org> On Behalf Of Nils-
> Christian
> >>Kempke via Gdb-patches
> >>Sent: Thursday, July 7, 2022 5:46 PM
> >>To: gdb-patches@sourceware.org
> >>Subject: [PATCH 1/3] gdb: add support for DW_AT_trampoline in DWARF
> reader
> >>
> >>[CAUTION: External Email]
> >>
> >>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_subroutines 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 but not specifying the target 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 done in preparation of the following patches which will add a
> >>mechanism to hide DW_AT_trampoline subroutines from the user.
> >>
> >>gdb/ChangeLog:
> >>2022-05-22  Nils-Christian Kempke  <nils-christian.kempke@intel.com>
> >>
> >>        * dwarf2/read.c (read_subroutine_type): Read in DW_AT_trampoline.
> >>        * gdbtypes.c (print_trampoline_target_info): New helper method.
> >>        (recursive_dump_type): Add trampoline info.
> >>        (copy_type_recursive): Copy trampoline info.
> >>        * gdbtypes.h (func_type): Add trampoline specific fields.
> >>        (trampoline_target_kind): New enum.
> >>        (trampoline_target): New struct for storing DW_AT_trampoline's
> >>        value.
> >>        (TYPE_IS_TRAMPOLINE): New define.
> >>        (TYPE_TRAMPOLINE_TARGET): New define.
> >>
> >>Signed-off-by: Nils-Christian Kempke <nils-christian.kempke@intel.com>
> >>---
> >> gdb/dwarf2/read.c | 43 ++++++++++++++++++++++++++
> >> gdb/gdbtypes.c    | 31 +++++++++++++++++++
> >> gdb/gdbtypes.h    | 79
> >>+++++++++++++++++++++++++++++++++++++++++++++++
> >> 3 files changed, 153 insertions(+)
> >>
> >>diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index
> >>23fe5679cbd..7f80c31d051 100644
> >>--- a/gdb/dwarf2/read.c
> >>+++ b/gdb/dwarf2/read.c
> >>@@ -16491,6 +16491,49 @@ 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)
> >>+    {
> >>+      CORE_ADDR baseaddr = objfile->text_section_offset ();
> >>+
> >>+      TYPE_IS_TRAMPOLINE (ftype) = true;
> >>+      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_physname
> >>+         (attr->as_string ());
> >>+      else if (attr->form_is_ref ())
> >>+       {
> >>+         die_info *target_die;
> >>+         dwarf2_cu *target_cu = cu;
> >>+
> >>+         target_die = follow_die_ref (die, attr, &target_cu);
> >>+         const char* target_name = dwarf2_name (target_die, target_cu);
> >>+         if (target_name == nullptr)
> >>+           {
> >>+             complaint (_("DW_AT_trampoline target DIE has no name for"
> >>+                        "referencing DIE %s [in module %s]"),
> >>+                        sect_offset_str (die->sect_off),
> >>+                        objfile_name (objfile));
> >>+           }
> >>+         TYPE_TRAMPOLINE_TARGET (ftype)->set_target_physname
> >>(target_name);
> >>+       }
> >>+      else if (attr->form_is_unsigned ())
> >>+       TYPE_TRAMPOLINE_TARGET (ftype)->set_target_flag (attr-
> >as_boolean ());
> >>+      else
> >>+       {
> >>+         CORE_ADDR target_addr = attr->as_address ();
> >>+         target_addr = gdbarch_adjust_dwarf2_addr (objfile->arch (),
> >>+                                                   target_addr + baseaddr);
> >>+         TYPE_TRAMPOLINE_TARGET (ftype)->set_target_physaddr
> (target_addr);
> >>+       }
> >>+    }
> >>+
> >>   /* 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.  */ diff --git a/gdb/gdbtypes.c
> >>b/gdb/gdbtypes.c index c8f98554859..66e04882d48 100644
> >>--- a/gdb/gdbtypes.c
> >>+++ b/gdb/gdbtypes.c
> >>@@ -5205,6 +5205,31 @@ 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_PHYSADDR:
> >>+      gdb_printf ("%*starget physaddr: 0x%lx\n", spaces + 2, "",
> >>+                 TYPE_TRAMPOLINE_TARGET (type)->target_physaddr ());
> >>+      break;
> >>+    case TRAMPOLINE_TARGET_PHYSNAME:
> >>+      gdb_printf ("%*starget physname: %s\n", spaces + 2, "",
> >>+                 TYPE_TRAMPOLINE_TARGET (type)->target_physname ());
> >>+      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.  */
> >>@@ -5531,6 +5556,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 ("%*sis_trampoline %d\n", spaces, "",
> >>+                   TYPE_IS_TRAMPOLINE (type));
> >>+       if (TYPE_IS_TRAMPOLINE (type))
> >>+         print_trampoline_target_info (type, spaces);
> >>        break;
> >>
> >>       case TYPE_SPECIFIC_SELF_TYPE:
> >>@@ -5762,6 +5791,8 @@ copy_type_recursive (struct objfile *objfile,
> >>       TYPE_CALLING_CONVENTION (new_type) =
> TYPE_CALLING_CONVENTION
> >>(type);
> >>       TYPE_NO_RETURN (new_type) = TYPE_NO_RETURN (type);
> >>       TYPE_TAIL_CALL_LIST (new_type) = NULL;
> >>+      TYPE_IS_TRAMPOLINE (new_type) = TYPE_IS_TRAMPOLINE (type);
> >>+      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 7437e1db8ab..846de1289ad
> 100644
> >>--- a/gdb/gdbtypes.h
> >>+++ b/gdb/gdbtypes.h
> >>@@ -1811,6 +1811,83 @@ struct func_type
> >>        contains the method.  */
> >>
> >>     struct type *self_type;
> >>+
> >>+    /* * For functions marked with the DW_AT_trampoline.  These are
> >>+       compiler generated wrappers that should be hidden from the user.
> >>+ */
> >>+
> >>+    unsigned int is_trampoline : 1;
> >>+
> >>+    struct trampoline_target *self_trampoline_target;  };
> >>+
> >>+/* The kind of location held by this call site target.  */ enum
> >>+trampoline_target_kind
> >>+  {
> >>+    /* An address.  */
> >>+    TRAMPOLINE_TARGET_PHYSADDR,
> >>+    /* A (mangled) name.  */
> >>+    TRAMPOLINE_TARGET_PHYSNAME,
> >>+    /* An flag (target is unknown).  */
> >>+    TRAMPOLINE_TARGET_FLAG,
> >>+  };
> >>+
> >>+struct trampoline_target
> >>+  {
> >>+    trampoline_target_kind target_kind () const
> >>+    {
> >>+      return m_target_kind;
> >>+    }
> >>+
> >>+    void set_target_physaddr (CORE_ADDR physaddr)
> >>+    {
> >>+      m_target_kind = TRAMPOLINE_TARGET_PHYSADDR;
> >>+      m_trampoline_target.physaddr = physaddr;
> >>+    }
> >>+
> >>+    CORE_ADDR target_physaddr () const
> >>+    {
> >>+      gdb_assert (m_target_kind == TRAMPOLINE_TARGET_PHYSADDR);
> >>+      return m_trampoline_target.physaddr;
> >>+    }
> >>+
> >>+    void set_target_physname (const char *physname)
> >>+    {
> >>+      m_target_kind = TRAMPOLINE_TARGET_PHYSNAME;
> >>+      m_trampoline_target.physname = physname;
> >>+    }
> >>+
> >>+    const char *target_physname () const
> >>+    {
> >>+      gdb_assert (m_target_kind == TRAMPOLINE_TARGET_PHYSNAME);
> >>+      return m_trampoline_target.physname;
> >>+    }
> >>+
> >>+    void set_target_flag (bool flag)
> >>+    {
> >>+      m_target_kind = TRAMPOLINE_TARGET_FLAG;
> >>+      m_trampoline_target.flag = flag;
> >>+    }
> >>+
> >>+    bool target_flag () const
> >>+    {
> >>+      gdb_assert (m_target_kind == TRAMPOLINE_TARGET_FLAG);
> >>+      return m_trampoline_target.flag;
> >>+    }
> >>+
> >>+  private:
> >>+
> >>+    union
> >>+    {
> >>+      /* Address.  */
> >>+      CORE_ADDR physaddr;
> >>+      /* Mangled name.  */
> >>+      const char *physname;
> >>+      /* Flag.  */
> >>+      bool flag;
> >>+    } m_trampoline_target;
> >>+
> >>+    /* * Discriminant for union m_trampoline_target.  */
> >>+    ENUM_BITFIELD (trampoline_target_kind) m_target_kind : 2;
> >>   };
> >>
> >> /* struct call_site_parameter can be referenced in callees by several
> ways.  */
> >>@@ -2172,6 +2249,8 @@ extern void set_type_vptr_basetype (struct
> type *,
> >>struct type *);  #define TYPE_CALLING_CONVENTION(thistype)
> >>TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff-
> >calling_convention
> >> #define TYPE_NO_RETURN(thistype) TYPE_MAIN_TYPE(thistype)-
> >>>type_specific.func_stuff->is_noreturn
> >> #define TYPE_TAIL_CALL_LIST(thistype) TYPE_MAIN_TYPE(thistype)-
> >>>type_specific.func_stuff->tail_call_list
> >>+#define TYPE_IS_TRAMPOLINE(thistype)
> >>+TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->is_trampoline
> >>+#define TYPE_TRAMPOLINE_TARGET(thistype)
> >>+TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff-
> >self_trampoline_tar
> >>+get
> >> #define TYPE_BASECLASS(thistype,index) ((thistype)->field (index).type
> ())
> >>#define TYPE_N_BASECLASSES(thistype) TYPE_CPLUS_SPECIFIC(thistype)-
> >>>n_baseclasses
> >> #define TYPE_BASECLASS_NAME(thistype,index) (thistype->field
> (index).name ())
> >>--
> >>2.25.1
> >>
> >>Intel Deutschland GmbH
> >>Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
> >>Tel: +49 89 99 8853-0,
> >>https://nam11.safelinks.protection.outlook.com/?url=http%3A%2F%2Fw
> ww.int
> >>el.de%2F&amp;data=05%7C01%7CJiniSusan.George%40amd.com%7C9c3f
> 28b5
> >>98cf49f888f908da601272a0%7C3dd8961fe4884e608e11a82d994e183d%7C0
> %7
> >>C0%7C637927929632561872%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC
> 4wLj
> >>AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C
> %7C
> >>%7C&amp;sdata=MBaQ7XpSZ4XFO963dnxF%2Fy1PD0gcx6k%2FjdaifxoSUa
> Y%3D
> >>&amp;reserved=0
> >><https://nam11.safelinks.protection.outlook.com/?url=http%3A%2F%2Fw
> ww.in
> >>tel.de%2F&amp;data=05%7C01%7CJiniSusan.George%40amd.com%7C9c3
> f28b5
> >>98cf49f888f908da601272a0%7C3dd8961fe4884e608e11a82d994e183d%7C0
> %7
> >>C0%7C637927929632561872%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC
> 4wLj
> >>AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C
> %7C
> >>%7C&amp;sdata=MBaQ7XpSZ4XFO963dnxF%2Fy1PD0gcx6k%2FjdaifxoSUa
> Y%3D
> >>&amp;reserved=0>
> >>Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva
> >>Chairperson of the Supervisory Board: Nicole Lau Registered Office:
> Munich
> >>Commercial Register: Amtsgericht Muenchen HRB 186928

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/3] gdb: add support for DW_AT_trampoline in DWARF reader
  2022-07-07 12:15 [PATCH 1/3] gdb: add support for DW_AT_trampoline in DWARF reader Nils-Christian Kempke
                   ` (2 preceding siblings ...)
  2022-07-13  7:39 ` [PATCH 1/3] gdb: add support for DW_AT_trampoline in DWARF reader George, Jini Susan
@ 2022-07-15 20:05 ` Tom Tromey
  3 siblings, 0 replies; 11+ messages in thread
From: Tom Tromey @ 2022-07-15 20:05 UTC (permalink / raw)
  To: Nils-Christian Kempke via Gdb-patches

>>>>> Nils-Christian Kempke via Gdb-patches <gdb-patches@sourceware.org> 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.

Thank you for the patch.

> +	  const char* target_name = dwarf2_name (target_die, target_cu);

"*" comes after the space.

> +	{
> +	  CORE_ADDR target_addr = attr->as_address ();
> +	  target_addr = gdbarch_adjust_dwarf2_addr (objfile->arch (),
> +						    target_addr + baseaddr);
> +	  TYPE_TRAMPOLINE_TARGET (ftype)->set_target_physaddr (target_addr);

If a data structure holds an address that already has the section offset
applied, then objfile_relocate1 must be updated to relocate the value.

However, if you can possibly avoid adding the section offset, in favor
of handling this when the address is used, then that is better IMO.

thanks,
Tom

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 2/3] gdb/symtab: add lookup for trampoline functions
  2022-07-07 12:15 ` [PATCH 2/3] gdb/symtab: add lookup for trampoline functions Nils-Christian Kempke
@ 2022-07-15 20:13   ` Tom Tromey
  0 siblings, 0 replies; 11+ messages in thread
From: Tom Tromey @ 2022-07-15 20:13 UTC (permalink / raw)
  To: Nils-Christian Kempke via Gdb-patches

>>>>> Nils-Christian Kempke via Gdb-patches <gdb-patches@sourceware.org> writes:

> In order to queriy information about the DW_AT_trampoline tag for
> subroutines and inlined subroutines two function were added to symtab.

> First, a routine for querying whether the given pc belongs to a block
> that is associated with a function (maybe inlined) marked
> DW_AT_trampoline.

> Second, 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.

Thank you for the patch.

> gdb/ChangeLog:
> 2022-05-30  Nils-Christian Kempke  <nils-christian.kempke@intel.com>

> 	* symtab.h (in_trampoline_function): New function
> 	(find_function_trampoline_target): New function.
> 	* symtab.c (in_trampoline_function): New function implementation.
> 	(find_function_trampoline_target): New implementation of
> 	trampoline target lookup.

These aren't needed any more.

> +      if (trampoline->target_kind () == TRAMPOLINE_TARGET_PHYSNAME)
> +	{
> +	  /* Handle both the mangled and demangled PHYSNAME.  */
> +	  const char *physname = trampoline->target_physname ();
> +
> +	  if (find_minimal_symbol_address (physname, &target_address, nullptr)
> +	      != 0)
> +	    target_address = 0;

Will there always be a minimal symbol?  It seems like maybe this isn't a
requirement.

> +	  /* 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 = trampoline->target_physaddr ()
> +	    + sym->objfile ()->section_offsets[sym->section_index ()];

It seems to me that this adds an additional section offset, even though
one was already added when reading.

However as mentioned there, it's better to do this work here and undo
the offset in the reader.

Also this isn't formatted properly, you need parens around the right
hand side of the assignment.

Tom

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 3/3] gdb/infrun: handle stepping through functions with DW_AT_trampoline
  2022-07-07 12:15 ` [PATCH 3/3] gdb/infrun: handle stepping through functions with DW_AT_trampoline Nils-Christian Kempke
@ 2022-07-15 20:20   ` Tom Tromey
  0 siblings, 0 replies; 11+ messages in thread
From: Tom Tromey @ 2022-07-15 20:20 UTC (permalink / raw)
  To: Nils-Christian Kempke via Gdb-patches

>>>>> Nils-Christian Kempke via Gdb-patches <gdb-patches@sourceware.org> writes:

> 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.

Thank you for the patch.

I don't really know enough about infrun to comment on most of this patch.
It seems like a good idea to me.  It's close to a feature users have
wanted for a while -- an addition to the "skip" command to skip through
library-provided wrappers.

> +  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 function trampolines and inlined\n\
> +fucntion trampolines that have been marked trampolines in the compiler's\n\

Typo, "function".  Also maybe "marked as trampolines by the compiler" instead.

> +debug info.  If off, gdb will ignore the DW_TAG_trampoline while stepping."),

I think this should probably not refer to DW_TAG_trampoline.
Few users will understand this.

thanks,
Tom

^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [PATCH 1/3] gdb: add support for DW_AT_trampoline in DWARF reader
  2022-07-13 11:59   ` Kempke, Nils-Christian
@ 2022-07-17 12:57     ` George, Jini Susan
  2022-07-18 16:11       ` Tom Tromey
  0 siblings, 1 reply; 11+ messages in thread
From: George, Jini Susan @ 2022-07-17 12:57 UTC (permalink / raw)
  To: Kempke, Nils-Christian, gdb-patches

[Public]

Hi Nils,

My answers are inlined below.

>>-----Original Message-----
>>> -----Original Message-----
>>> From: George, Jini Susan <JiniSusan.George@amd.com>
>>> * Is there any common ground we can find with the way solib (linker
>>> PLT) trampolines are handled ? I am OK if we can't, but I think it
>>> might be better to check and rule it out.
>>
>>I don't quite understand what you mean here but am also not super familiar with
>>the solib handling part of GDB.  The attached patches treat any function that
>>was marked as DW_AT_Trampoline in DWARF by the compiler.  As far as I know
>>not a single compiler (except ifx) emits this attribute up until now.  If a compiler
>>were to generate DWARF for the solib trampolines and if it were to add the
>>attribute, we could also treat solib trampolines with this approach.
>>But generally, the DW_AT_trampoline is independent of any other GDB
>>trampoline handling.
>>Not sure whether this answers your question.  Maybe you can elaborate a bit
>>more?

From what I can make out, the solib trampolines (marked in the minimal symbol table as ms_type = mst_solib_trampoline) are identified in gdb from the elf symbol table based on their type. (The identification of these trampolines are different, and I would not think there would be any common ground here wrt the identification). But there could be some common ground wrt the handling. For example, while stepping through the code, we don't step into the solib trampolines, which typically are named as <target_func_name@plt>, but we end up stepping into the resolved target function. It would be great if that could be checked out. If it looks like there is nothing in common, that's fine, but it would be great if we make that decision after checking it out.


>>> * Also, do we want to resolve and display the target of the trampoline
>>> code (if possible) in the disassembled code also ?
>>>
>>
>>So you mean, when I am about to step into a wrapper/step through a wrapper I
>>would display the target at the respective call statement with some note like
>>
>>(gdb) disassemble
>>...
>>0x080483fa <+0>: push %ebp
>>0x080483fb <+1>: mov %esp,%ebp
>>0x080483fd <+3>: sub $0x8,%esp
>>=> 0x08048400 <+6>: movl $0x2,0x4(%esp)
>>0x08048408 <+14>: movl $0x1,(%esp)
>>0x0804840f <+21>: call 0x80483ed <func> (trampoline to: 0x12345 <other>)
>>
>>?
>>So a change in the pretty_printer for assembly I assume (or somewhere deeper).
>>
>>This would mean, GDB would have to check every time a call appears
>>somewhere in the disassembly whether or not the target is a trampoline, and, if
>>so, GDB would need to resolve this.
>>
>>Generally, I think this might be a nice feature.  I'll have a look whether it can be
>>done without too much effort, but if it turns out to be considerably difficult I'd
>>rather like to leave this for a different patch.
>>If this is already done in the other trampoline cases (solibs and signals) it might
>>be needed for the completion of this patch though.

I think you can disregard this comment of mine unless the effort involved is trivial. Wrt the solib trampolines, the target function names are embedded in the names of the trampolines (as <target_function_name>@plt, and the gdb disassembler would not have to do anything special to get that displayed.

>>> * Also, do we want to refer to these trampolines differently so that
>>> these can be distinguished from the linker PLT trampolines and the
>>> signal trampolines ?
>>>
>>
>>I hoped that the patches made the difference clear enough.  Or can you pinpoint
>>something that seems unclear?  How would you instead refer to them, I am a bit
>>lost here, to be honest.  They are, after all, according to their DWARF/debug
>>info trampolines.  Referring to them differently would in my opinion maybe
>>obscure things?  But maybe you had something in mind.

I was only referring to some term which could be used to refer to these trampolines (like how we already have 'solib trampolines' and 'signal trampolines'). But if none of the terms (compiler trampolines, debug info trampolines) seem to fit right, you can disregard this comment.

>>> * In read.c, in read_subroutine_type(), where the DW_AT_trampoline
>>> attribute is of form reference, we seem to be storing the value
>>> corresponding to the  DW_AT_name attribute, whereas in many cases (C++
>>> and other languages), it might make sense to store the mangled name
>>> typically obtained from the DW_AT_linkage_name attribute. Given this
>>> it might be good to have a C++ test case for this with trampoline
>>> target functions inside namespaces also. Maybe with the same target
>>> function name under multiple namespaces. Also, the comment in
>>> gdbtypes.h (Line
>>> 1883) mentions mangled name, which does not seem to match ?
>>
>>Yes, I think initially the comment was intended to only describe the
>>DW_AT_trampoline when its FORM is string.  That string could have been both,
>>mangled and demangled.  But I get your point.  I am not sure whether storing
>>the linkage name or the 'normal' name is correct here.  I think these are two
>>different issues: which name should be stored and should it be demangled or
>>not.  But I'll check this again.  I guess I'll have to check symbol lookup again for
>>this and see what makes most sense.

lookup_minimal_symbol() does a 2 pass search over both the mangled and the demangled names. If we end up comparing the demangled names, the name lookup might be incorrect since we will not be comparing fully qualified names.

>>> * In gdbtypes.h:
>>>
>>> 1817
>>> 1818     unsigned int is_trampoline : 1;
>>>
>>> Might be better to position this field as the 3rd field for better
>>> structure packing ?
>>
>>The structure was poorly packed in the first place I think.  We have the
>>ENUM_BITFIELD in the beginning which can be either an enum or an unsigned
>>int.  I am not sure whether the size of an enum is defined somewhere but I'd
>>assume it is compiler dependent and usually the size of an int?
>>This is followed by another unsigned int and then by two pointers.
>>
>>If we aimed at proper structure packing I'd assume the pointers (which would
>>usually be 8 bytes to all come first, then the (unsigned) int's with their (usually)
>>4 bytes, followed finally by the enum?
>>
>>I considered this when implementing it but it seemed like an unrelated change to
>>me.  Assuming int is 4 bytes and we align to 8 bytes moving is_trampoline to the
>>3rd position would also not do anything, would it?  We'd be at
>>
>>4 byte
>>4 byte
>>4 byte
>>8 byte
>>8 byte
>>8 byte
>>
>>Instead of
>>
>>4 byte
>>4 byte
>>8 byte
>>8 byte
>>4 byte
>>8 byte

I think you missed taking the bitfields (is_noreturn and is_trampoline) into consideration. If these get placed together, they would be fitted into one int since both these are just 1 bit each.


>>
>>I think switching is_trampoline and self_trampoline_target would make the most
>>sense here? (without touching the other members).
>>
>>> * infrun.c: Line 7156: It might be better to have the '10'
>>> representing the number of chained trampoline traversals allowed as a macro.
>>>
>>
>>I also thought about this when implementing it.  I back then decided against it
>>but sure, I'll add that.

Thanks,
Jini.

>>
>>> A few nits below:
>>> * infrun.c : Nits:
>>>                Line 7154: spelling: certian
>>>          Line 9941: spelling : fucntion
>>>
>>> *symtab.h: Nit: line 2247: spelling: wether
>>
>>Thanks!
>>I'll change this in v2!
>>
>>>
>>> Thanks,
>>> Jini.
>>>
>>> >>-----Original Message-----
>>> >>From: Gdb-patches <gdb-patches-
>>> >>bounces+jigeorge=amd.com@sourceware.org> On Behalf Of Nils-
>>> Christian
>>> >>Kempke via Gdb-patches
>>> >>Sent: Thursday, July 7, 2022 5:46 PM
>>> >>To: gdb-patches@sourceware.org
>>> >>Subject: [PATCH 1/3] gdb: add support for DW_AT_trampoline in DWARF
>>> reader
>>> >>
>>> >>[CAUTION: External Email]
>>> >>
>>> >>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_subroutines 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 but not specifying the target 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 done in preparation of the following patches which will add
>>> >>a mechanism to hide DW_AT_trampoline subroutines from the user.
>>> >>
>>> >>gdb/ChangeLog:
>>> >>2022-05-22  Nils-Christian Kempke  <nils-christian.kempke@intel.com>
>>> >>
>>> >>        * dwarf2/read.c (read_subroutine_type): Read in DW_AT_trampoline.
>>> >>        * gdbtypes.c (print_trampoline_target_info): New helper method.
>>> >>        (recursive_dump_type): Add trampoline info.
>>> >>        (copy_type_recursive): Copy trampoline info.
>>> >>        * gdbtypes.h (func_type): Add trampoline specific fields.
>>> >>        (trampoline_target_kind): New enum.
>>> >>        (trampoline_target): New struct for storing DW_AT_trampoline's
>>> >>        value.
>>> >>        (TYPE_IS_TRAMPOLINE): New define.
>>> >>        (TYPE_TRAMPOLINE_TARGET): New define.
>>> >>
>>> >>Signed-off-by: Nils-Christian Kempke
>>> >><nils-christian.kempke@intel.com>
>>> >>---
>>> >> gdb/dwarf2/read.c | 43 ++++++++++++++++++++++++++
>>> >> gdb/gdbtypes.c    | 31 +++++++++++++++++++
>>> >> gdb/gdbtypes.h    | 79
>>> >>+++++++++++++++++++++++++++++++++++++++++++++++
>>> >> 3 files changed, 153 insertions(+)
>>> >>
>>> >>diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index
>>> >>23fe5679cbd..7f80c31d051 100644
>>> >>--- a/gdb/dwarf2/read.c
>>> >>+++ b/gdb/dwarf2/read.c
>>> >>@@ -16491,6 +16491,49 @@ 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)
>>> >>+    {
>>> >>+      CORE_ADDR baseaddr = objfile->text_section_offset ();
>>> >>+
>>> >>+      TYPE_IS_TRAMPOLINE (ftype) = true;
>>> >>+      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_physname
>>> >>+         (attr->as_string ());
>>> >>+      else if (attr->form_is_ref ())
>>> >>+       {
>>> >>+         die_info *target_die;
>>> >>+         dwarf2_cu *target_cu = cu;
>>> >>+
>>> >>+         target_die = follow_die_ref (die, attr, &target_cu);
>>> >>+         const char* target_name = dwarf2_name (target_die, target_cu);
>>> >>+         if (target_name == nullptr)
>>> >>+           {
>>> >>+             complaint (_("DW_AT_trampoline target DIE has no name for"
>>> >>+                        "referencing DIE %s [in module %s]"),
>>> >>+                        sect_offset_str (die->sect_off),
>>> >>+                        objfile_name (objfile));
>>> >>+           }
>>> >>+         TYPE_TRAMPOLINE_TARGET (ftype)->set_target_physname
>>> >>(target_name);
>>> >>+       }
>>> >>+      else if (attr->form_is_unsigned ())
>>> >>+       TYPE_TRAMPOLINE_TARGET (ftype)->set_target_flag (attr-
>>> >as_boolean ());
>>> >>+      else
>>> >>+       {
>>> >>+         CORE_ADDR target_addr = attr->as_address ();
>>> >>+         target_addr = gdbarch_adjust_dwarf2_addr (objfile->arch (),
>>> >>+                                                   target_addr + baseaddr);
>>> >>+         TYPE_TRAMPOLINE_TARGET (ftype)->set_target_physaddr
>>> (target_addr);
>>> >>+       }
>>> >>+    }
>>> >>+
>>> >>   /* 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.  */ diff --git
>>> >>a/gdb/gdbtypes.c b/gdb/gdbtypes.c index c8f98554859..66e04882d48
>>> >>100644
>>> >>--- a/gdb/gdbtypes.c
>>> >>+++ b/gdb/gdbtypes.c
>>> >>@@ -5205,6 +5205,31 @@ 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_PHYSADDR:
>>> >>+      gdb_printf ("%*starget physaddr: 0x%lx\n", spaces + 2, "",
>>> >>+                 TYPE_TRAMPOLINE_TARGET (type)->target_physaddr ());
>>> >>+      break;
>>> >>+    case TRAMPOLINE_TARGET_PHYSNAME:
>>> >>+      gdb_printf ("%*starget physname: %s\n", spaces + 2, "",
>>> >>+                 TYPE_TRAMPOLINE_TARGET (type)->target_physname ());
>>> >>+      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.  */ @@ -5531,6 +5556,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 ("%*sis_trampoline %d\n", spaces, "",
>>> >>+                   TYPE_IS_TRAMPOLINE (type));
>>> >>+       if (TYPE_IS_TRAMPOLINE (type))
>>> >>+         print_trampoline_target_info (type, spaces);
>>> >>        break;
>>> >>
>>> >>       case TYPE_SPECIFIC_SELF_TYPE:
>>> >>@@ -5762,6 +5791,8 @@ copy_type_recursive (struct objfile *objfile,
>>> >>       TYPE_CALLING_CONVENTION (new_type) =
>>> TYPE_CALLING_CONVENTION
>>> >>(type);
>>> >>       TYPE_NO_RETURN (new_type) = TYPE_NO_RETURN (type);
>>> >>       TYPE_TAIL_CALL_LIST (new_type) = NULL;
>>> >>+      TYPE_IS_TRAMPOLINE (new_type) = TYPE_IS_TRAMPOLINE (type);
>>> >>+      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 7437e1db8ab..846de1289ad
>>> 100644
>>> >>--- a/gdb/gdbtypes.h
>>> >>+++ b/gdb/gdbtypes.h
>>> >>@@ -1811,6 +1811,83 @@ struct func_type
>>> >>        contains the method.  */
>>> >>
>>> >>     struct type *self_type;
>>> >>+
>>> >>+    /* * For functions marked with the DW_AT_trampoline.  These are
>>> >>+       compiler generated wrappers that should be hidden from the user.
>>> >>+ */
>>> >>+
>>> >>+    unsigned int is_trampoline : 1;
>>> >>+
>>> >>+    struct trampoline_target *self_trampoline_target;  };
>>> >>+
>>> >>+/* The kind of location held by this call site target.  */ enum
>>> >>+trampoline_target_kind
>>> >>+  {
>>> >>+    /* An address.  */
>>> >>+    TRAMPOLINE_TARGET_PHYSADDR,
>>> >>+    /* A (mangled) name.  */
>>> >>+    TRAMPOLINE_TARGET_PHYSNAME,
>>> >>+    /* An flag (target is unknown).  */
>>> >>+    TRAMPOLINE_TARGET_FLAG,
>>> >>+  };
>>> >>+
>>> >>+struct trampoline_target
>>> >>+  {
>>> >>+    trampoline_target_kind target_kind () const
>>> >>+    {
>>> >>+      return m_target_kind;
>>> >>+    }
>>> >>+
>>> >>+    void set_target_physaddr (CORE_ADDR physaddr)
>>> >>+    {
>>> >>+      m_target_kind = TRAMPOLINE_TARGET_PHYSADDR;
>>> >>+      m_trampoline_target.physaddr = physaddr;
>>> >>+    }
>>> >>+
>>> >>+    CORE_ADDR target_physaddr () const
>>> >>+    {
>>> >>+      gdb_assert (m_target_kind == TRAMPOLINE_TARGET_PHYSADDR);
>>> >>+      return m_trampoline_target.physaddr;
>>> >>+    }
>>> >>+
>>> >>+    void set_target_physname (const char *physname)
>>> >>+    {
>>> >>+      m_target_kind = TRAMPOLINE_TARGET_PHYSNAME;
>>> >>+      m_trampoline_target.physname = physname;
>>> >>+    }
>>> >>+
>>> >>+    const char *target_physname () const
>>> >>+    {
>>> >>+      gdb_assert (m_target_kind == TRAMPOLINE_TARGET_PHYSNAME);
>>> >>+      return m_trampoline_target.physname;
>>> >>+    }
>>> >>+
>>> >>+    void set_target_flag (bool flag)
>>> >>+    {
>>> >>+      m_target_kind = TRAMPOLINE_TARGET_FLAG;
>>> >>+      m_trampoline_target.flag = flag;
>>> >>+    }
>>> >>+
>>> >>+    bool target_flag () const
>>> >>+    {
>>> >>+      gdb_assert (m_target_kind == TRAMPOLINE_TARGET_FLAG);
>>> >>+      return m_trampoline_target.flag;
>>> >>+    }
>>> >>+
>>> >>+  private:
>>> >>+
>>> >>+    union
>>> >>+    {
>>> >>+      /* Address.  */
>>> >>+      CORE_ADDR physaddr;
>>> >>+      /* Mangled name.  */
>>> >>+      const char *physname;
>>> >>+      /* Flag.  */
>>> >>+      bool flag;
>>> >>+    } m_trampoline_target;
>>> >>+
>>> >>+    /* * Discriminant for union m_trampoline_target.  */
>>> >>+    ENUM_BITFIELD (trampoline_target_kind) m_target_kind : 2;
>>> >>   };
>>> >>
>>> >> /* struct call_site_parameter can be referenced in callees by
>>> >> several
>>> ways.  */
>>> >>@@ -2172,6 +2249,8 @@ extern void set_type_vptr_basetype (struct
>>> type *,
>>> >>struct type *);  #define TYPE_CALLING_CONVENTION(thistype)
>>> >>TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff-
>>> >calling_convention
>>> >> #define TYPE_NO_RETURN(thistype) TYPE_MAIN_TYPE(thistype)-
>>> >>>type_specific.func_stuff->is_noreturn
>>> >> #define TYPE_TAIL_CALL_LIST(thistype) TYPE_MAIN_TYPE(thistype)-
>>> >>>type_specific.func_stuff->tail_call_list
>>> >>+#define TYPE_IS_TRAMPOLINE(thistype)
>>> >>+TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->is_trampoline
>>> >>+#define TYPE_TRAMPOLINE_TARGET(thistype)
>>> >>+TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff-
>>> >self_trampoline_tar
>>> >>+get
>>> >> #define TYPE_BASECLASS(thistype,index) ((thistype)->field
>>> >> (index).type
>>> ())
>>> >>#define TYPE_N_BASECLASSES(thistype) TYPE_CPLUS_SPECIFIC(thistype)-
>>> >>>n_baseclasses
>>> >> #define TYPE_BASECLASS_NAME(thistype,index) (thistype->field
>>> (index).name ())
>>> >>--
>>> >>2.25.1
>>> >>
>>> >>Intel Deutschland GmbH
>>> >>Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
>>> >>Tel: +49 89 99 8853-0,
>>> >>https://nam11.safelinks.protection.outlook.com/?url=http%3A%2F%2Fw
>>> ww.int
>>> >>el.de%2F&amp;data=05%7C01%7CJiniSusan.George%40amd.com%7C9c3f
>>> 28b5
>>>
>>>>98cf49f888f908da601272a0%7C3dd8961fe4884e608e11a82d994e183d%7C0
>>> %7
>>> >>C0%7C637927929632561872%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC
>>> 4wLj
>>> >>AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C
>>> %7C
>>> >>%7C&amp;sdata=MBaQ7XpSZ4XFO963dnxF%2Fy1PD0gcx6k%2FjdaifxoSUa
>>> Y%3D
>>> >>&amp;reserved=0
>>> >><https://nam11.safelinks.protection.outlook.com/?url=http%3A%2F%2Fw
>>> ww.in
>>> >>tel.de%2F&amp;data=05%7C01%7CJiniSusan.George%40amd.com%7C9c3
>>> f28b5
>>>
>>>>98cf49f888f908da601272a0%7C3dd8961fe4884e608e11a82d994e183d%7C0
>>> %7
>>> >>C0%7C637927929632561872%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC
>>> 4wLj
>>> >>AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C
>>> %7C
>>> >>%7C&amp;sdata=MBaQ7XpSZ4XFO963dnxF%2Fy1PD0gcx6k%2FjdaifxoSUa
>>> Y%3D
>>> >>&amp;reserved=0>
>>> >>Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon
>>> >>Silva Chairperson of the Supervisory Board: Nicole Lau Registered Office:
>>> Munich
>>> >>Commercial Register: Amtsgericht Muenchen HRB 186928
>>
>>Intel Deutschland GmbH
>>Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
>>Tel: +49 89 99 8853-0,
>>https://nam11.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.int
>>el.de%2F&amp;data=05%7C01%7CJiniSusan.George%40amd.com%7Cd62c3e20
>>92aa47098d9908da64c720a7%7C3dd8961fe4884e608e11a82d994e183d%7C0%
>>7C0%7C637933103654397897%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wL
>>jAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C
>>%7C&amp;sdata=SqOet8GRTDgMHyLH9TKkvnaiK1N0AO1NQG09Pln8iJQ%3D&a
>>mp;reserved=0
>><https://nam11.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.in
>>tel.de%2F&amp;data=05%7C01%7CJiniSusan.George%40amd.com%7Cd62c3e2
>>092aa47098d9908da64c720a7%7C3dd8961fe4884e608e11a82d994e183d%7C0
>>%7C0%7C637933103654397897%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4
>>wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C
>>%7C%7C&amp;sdata=SqOet8GRTDgMHyLH9TKkvnaiK1N0AO1NQG09Pln8iJQ%3
>>D&amp;reserved=0>
>>Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva
>>Chairperson of the Supervisory Board: Nicole Lau Registered Office: Munich
>>Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/3] gdb: add support for DW_AT_trampoline in DWARF reader
  2022-07-17 12:57     ` George, Jini Susan
@ 2022-07-18 16:11       ` Tom Tromey
  0 siblings, 0 replies; 11+ messages in thread
From: Tom Tromey @ 2022-07-18 16:11 UTC (permalink / raw)
  To: George, Jini Susan via Gdb-patches
  Cc: Kempke, Nils-Christian, George, Jini Susan

>>> I considered this when implementing it but it seemed like an unrelated change to
>>> me.  Assuming int is 4 bytes and we align to 8 bytes moving is_trampoline to the
>>> 3rd position would also not do anything, would it?  We'd be at
[...]

> I think you missed taking the bitfields (is_noreturn and
> is_trampoline) into consideration. If these get placed together, they
> would be fitted into one int since both these are just 1 bit each.

FWIW you can check the packing using 'ptype/o'.
I'm also inclined to say the bitfields should be adjacent.

thanks,
Tom

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/3] gdb: add support for DW_AT_trampoline in DWARF reader
@ 2023-01-03  1:07 Ijaz, Abdul B
  0 siblings, 0 replies; 11+ messages in thread
From: Ijaz, Abdul B @ 2023-01-03  1:07 UTC (permalink / raw)
  To: JiniSusan.George, gdb-patches; +Cc: Ijaz, Abdul B

[-- Attachment #1: Type: text/plain, Size: 25945 bytes --]

Hi Jini,



Thanks for your feedback on the patch.



1)  Regarding solib and signal trampolines, Symbol trampoline or solib trampoline not just identification but handling also is completely different as far as I can understand as compare to DW_AT_trampoline DIE. Since for the signal case it is handled differently for each target, for solib it trampoline symbol is initialized  when symbol table is created for undefined symbols that are defined in some shared lib info so later then it is used for handling trampolines whereas DW_AT_trampoline handling is common for each target and each trampoline has a different frame for caller and callee functions.



2)  Regarding the mangled/demangled name it will be updated in V2 to look first mangled and then demangled name.

3)  Regarding bitfield alignment in struct func_type both is_noreturn & is_trampoline will be put together to single unsigned int type value in V2 patch.

4)  In addition, regarding this patch I think so far important missing part  regarding this change would be if we should filter the trampoline frames for commands like backtrace or finish commands. Since in case we filter trampoline frame while printing then frame levels need some special handling which seems to be tricky so would be nice to have others opinion regarding the expected behavior for these trampoline frames if we should handle frame->level for trampoline frames in get_prev_frame_raw() or just skipping such frames in stack print would be ok:



As an example where first and second functions having trampoline calls in the DWARF:

Backtrace without filtering so far shows trampoline calls in backtrace:

(gdb) backtrace 3

#0  second (x=20, y=9) at call-stack.f90:20

#1  0x00000000004049f9 in second_.t74p.t75p () at call-stack.f90:29

#2  0x00000000004049d3 in first (num1=16, num2=3) at call-stack.f90:27



If we filter the trampoline frames while printing and handle them for commands like finish then Backtrace with filtering where frame #1 and #3 are trampoline frames so they are not shown in backtrace:

(gdb) backtrace 3

#0  second (x=20, y=9) at call-stack.f90:20

#2  0x00000000004049d3 in first (num1=16, num2=3) at call-stack.f90:27

#4  0x0000000000405183 in MAIN__ at call-stack.f90:57





Thanks & Best Regards

Abdul Basit Ijaz



>>-----Original Message-----

>>> -----Original Message-----

>>> From: George, Jini Susan <JiniSusan.George@amd.com<mailto:JiniSusan.George@amd.com>>

>>> * Is there any common ground we can find with the way solib (linker

>>> PLT) trampolines are handled ? I am OK if we can't, but I think it

>>> might be better to check and rule it out.

>>

>>I don't quite understand what you mean here but am also not super familiar with

>>the solib handling part of GDB.  The attached patches treat any function that

>>was marked as DW_AT_Trampoline in DWARF by the compiler.  As far as I know

>>not a single compiler (except ifx) emits this attribute up until now.  If a compiler

>>were to generate DWARF for the solib trampolines and if it were to add the

>>attribute, we could also treat solib trampolines with this approach.

>>But generally, the DW_AT_trampoline is independent of any other GDB

>>trampoline handling.

>>Not sure whether this answers your question.  Maybe you can elaborate a bit

>>more?



>From what I can make out, the solib trampolines (marked in the minimal symbol table as ms_type = mst_solib_trampoline) are identified in gdb from the elf symbol table based on their type. (The identification of these trampolines are different, and I would not think there would be any common ground here wrt the identification). But there could be some common ground wrt the handling. For example, while stepping through the code, we don't step into the solib trampolines, which typically are named as <target_func_name@plt<mailto:target_func_name@plt>>, but we end up stepping into the resolved target function. It would be great if that could be checked out. If it looks like there is nothing in common, that's fine, but it would be great if we make that decision after checking it out.





>>> * Also, do we want to resolve and display the target of the trampoline

>>> code (if possible) in the disassembled code also ?

>>>

>>

>>So you mean, when I am about to step into a wrapper/step through a wrapper I

>>would display the target at the respective call statement with some note like

>>

>>(gdb) disassemble

>>...

>>0x080483fa <+0>: push %ebp

>>0x080483fb <+1>: mov %esp,%ebp

>>0x080483fd <+3>: sub $0x8,%esp

>>=> 0x08048400 <+6>: movl $0x2,0x4(%esp)

>>0x08048408 <+14>: movl $0x1,(%esp)

>>0x0804840f <+21>: call 0x80483ed <func> (trampoline to: 0x12345 <other>)

>>

>>?

>>So a change in the pretty_printer for assembly I assume (or somewhere deeper).

>>

>>This would mean, GDB would have to check every time a call appears

>>somewhere in the disassembly whether or not the target is a trampoline, and, if

>>so, GDB would need to resolve this.

>>

>>Generally, I think this might be a nice feature.  I'll have a look whether it can be

>>done without too much effort, but if it turns out to be considerably difficult I'd

>>rather like to leave this for a different patch.

>>If this is already done in the other trampoline cases (solibs and signals) it might

>>be needed for the completion of this patch though.



I think you can disregard this comment of mine unless the effort involved is trivial. Wrt the solib trampolines, the target function names are embedded in the names of the trampolines (as <target_function_name>@plt, and the gdb disassembler would not have to do anything special to get that displayed.



>>> * Also, do we want to refer to these trampolines differently so that

>>> these can be distinguished from the linker PLT trampolines and the

>>> signal trampolines ?

>>>

>>

>>I hoped that the patches made the difference clear enough.  Or can you pinpoint

>>something that seems unclear?  How would you instead refer to them, I am a bit

>>lost here, to be honest.  They are, after all, according to their DWARF/debug

>>info trampolines.  Referring to them differently would in my opinion maybe

>>obscure things?  But maybe you had something in mind.



I was only referring to some term which could be used to refer to these trampolines (like how we already have 'solib trampolines' and 'signal trampolines'). But if none of the terms (compiler trampolines, debug info trampolines) seem to fit right, you can disregard this comment.



>>> * In read.c, in read_subroutine_type(), where the DW_AT_trampoline

>>> attribute is of form reference, we seem to be storing the value

>>> corresponding to the  DW_AT_name attribute, whereas in many cases (C++

>>> and other languages), it might make sense to store the mangled name

>>> typically obtained from the DW_AT_linkage_name attribute. Given this

>>> it might be good to have a C++ test case for this with trampoline

>>> target functions inside namespaces also. Maybe with the same target

>>> function name under multiple namespaces. Also, the comment in

>>> gdbtypes.h (Line

>>> 1883) mentions mangled name, which does not seem to match ?

>>

>>Yes, I think initially the comment was intended to only describe the

>>DW_AT_trampoline when its FORM is string.  That string could have been both,

>>mangled and demangled.  But I get your point.  I am not sure whether storing

>>the linkage name or the 'normal' name is correct here.  I think these are two

>>different issues: which name should be stored and should it be demangled or

>>not.  But I'll check this again.  I guess I'll have to check symbol lookup again for

>>this and see what makes most sense.



lookup_minimal_symbol() does a 2 pass search over both the mangled and the demangled names. If we end up comparing the demangled names, the name lookup might be incorrect since we will not be comparing fully qualified names.



>>> * In gdbtypes.h:

>>>

>>> 1817

>>> 1818     unsigned int is_trampoline : 1;

>>>

>>> Might be better to position this field as the 3rd field for better

>>> structure packing ?

>>

>>The structure was poorly packed in the first place I think.  We have the

>>ENUM_BITFIELD in the beginning which can be either an enum or an unsigned

>>int.  I am not sure whether the size of an enum is defined somewhere but I'd

>>assume it is compiler dependent and usually the size of an int?

>>This is followed by another unsigned int and then by two pointers.

>>

>>If we aimed at proper structure packing I'd assume the pointers (which would

>>usually be 8 bytes to all come first, then the (unsigned) int's with their (usually)

>>4 bytes, followed finally by the enum?

>>

>>I considered this when implementing it but it seemed like an unrelated change to

>>me.  Assuming int is 4 bytes and we align to 8 bytes moving is_trampoline to the

>>3rd position would also not do anything, would it?  We'd be at

>>

>>4 byte

>>4 byte

>>4 byte

>>8 byte

>>8 byte

>>8 byte

>>

>>Instead of

>>

>>4 byte

>>4 byte

>>8 byte

>>8 byte

>>4 byte

>>8 byte



I think you missed taking the bitfields (is_noreturn and is_trampoline) into consideration. If these get placed together, they would be fitted into one int since both these are just 1 bit each.





>>

>>I think switching is_trampoline and self_trampoline_target would make the most

>>sense here? (without touching the other members).

>>

>>> * infrun.c: Line 7156: It might be better to have the '10'

>>> representing the number of chained trampoline traversals allowed as a macro.

>>>

>>

>>I also thought about this when implementing it.  I back then decided against it

>>but sure, I'll add that.



Thanks,

Jini.



>>

>>> A few nits below:

>>> * infrun.c : Nits:

>>>                Line 7154: spelling: certian

>>>          Line 9941: spelling : fucntion

>>>

>>> *symtab.h: Nit: line 2247: spelling: wether

>>

>>Thanks!

>>I'll change this in v2!

>>

>>>

>>> Thanks,

>>> Jini.

>>>

>>> >>-----Original Message-----

>>> >>From: Gdb-patches <gdb-patches-

>>> >>bounces+jigeorge=amd.com@sourceware.org<mailto:amd.com@sourceware.org>> On Behalf Of Nils-

>>> Christian

>>> >>Kempke via Gdb-patches

>>> >>Sent: Thursday, July 7, 2022 5:46 PM

>>> >>To: gdb-patches@sourceware.org<mailto:gdb-patches@sourceware.org>

>>> >>Subject: [PATCH 1/3] gdb: add support for DW_AT_trampoline in DWARF

>>> reader

>>> >>

>>> >>[CAUTION: External Email]

>>> >>

>>> >>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_subroutines 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 but not specifying the target 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 done in preparation of the following patches which will add

>>> >>a mechanism to hide DW_AT_trampoline subroutines from the user.

>>> >>

>>> >>gdb/ChangeLog:

>>> >>2022-05-22  Nils-Christian Kempke  <nils-christian.kempke@intel.com<mailto:nils-christian.kempke@intel.com>>

>>> >>

>>> >>        * dwarf2/read.c (read_subroutine_type): Read in DW_AT_trampoline.

>>> >>        * gdbtypes.c (print_trampoline_target_info): New helper method.

>>> >>        (recursive_dump_type): Add trampoline info.

>>> >>        (copy_type_recursive): Copy trampoline info.

>>> >>        * gdbtypes.h (func_type): Add trampoline specific fields.

>>> >>        (trampoline_target_kind): New enum.

>>> >>        (trampoline_target): New struct for storing DW_AT_trampoline's

>>> >>        value.

>>> >>        (TYPE_IS_TRAMPOLINE): New define.

>>> >>        (TYPE_TRAMPOLINE_TARGET): New define.

>>> >>

>>> >>Signed-off-by: Nils-Christian Kempke

>>> >><nils-christian.kempke@intel.com<mailto:nils-christian.kempke@intel.com>>

>>> >>---

>>> >> gdb/dwarf2/read.c | 43 ++++++++++++++++++++++++++

>>> >> gdb/gdbtypes.c    | 31 +++++++++++++++++++

>>> >> gdb/gdbtypes.h    | 79

>>> >>+++++++++++++++++++++++++++++++++++++++++++++++

>>> >> 3 files changed, 153 insertions(+)

>>> >>

>>> >>diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index

>>> >>23fe5679cbd..7f80c31d051 100644

>>> >>--- a/gdb/dwarf2/read.c

>>> >>+++ b/gdb/dwarf2/read.c

>>> >>@@ -16491,6 +16491,49 @@ 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)

>>> >>+    {

>>> >>+      CORE_ADDR baseaddr = objfile->text_section_offset ();

>>> >>+

>>> >>+      TYPE_IS_TRAMPOLINE (ftype) = true;

>>> >>+      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_physname

>>> >>+         (attr->as_string ());

>>> >>+      else if (attr->form_is_ref ())

>>> >>+       {

>>> >>+         die_info *target_die;

>>> >>+         dwarf2_cu *target_cu = cu;

>>> >>+

>>> >>+         target_die = follow_die_ref (die, attr, &target_cu);

>>> >>+         const char* target_name = dwarf2_name (target_die, target_cu);

>>> >>+         if (target_name == nullptr)

>>> >>+           {

>>> >>+             complaint (_("DW_AT_trampoline target DIE has no name for"

>>> >>+                        "referencing DIE %s [in module %s]"),

>>> >>+                        sect_offset_str (die->sect_off),

>>> >>+                        objfile_name (objfile));

>>> >>+           }

>>> >>+         TYPE_TRAMPOLINE_TARGET (ftype)->set_target_physname

>>> >>(target_name);

>>> >>+       }

>>> >>+      else if (attr->form_is_unsigned ())

>>> >>+       TYPE_TRAMPOLINE_TARGET (ftype)->set_target_flag (attr-

>>> >as_boolean ());

>>> >>+      else

>>> >>+       {

>>> >>+         CORE_ADDR target_addr = attr->as_address ();

>>> >>+         target_addr = gdbarch_adjust_dwarf2_addr (objfile->arch (),

>>> >>+                                                   target_addr + baseaddr);

>>> >>+         TYPE_TRAMPOLINE_TARGET (ftype)->set_target_physaddr

>>> (target_addr);

>>> >>+       }

>>> >>+    }

>>> >>+

>>> >>   /* 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.  */ diff --git

>>> >>a/gdb/gdbtypes.c b/gdb/gdbtypes.c index c8f98554859..66e04882d48

>>> >>100644

>>> >>--- a/gdb/gdbtypes.c

>>> >>+++ b/gdb/gdbtypes.c

>>> >>@@ -5205,6 +5205,31 @@ 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_PHYSADDR:

>>> >>+      gdb_printf ("%*starget physaddr: 0x%lx\n", spaces + 2, "",

>>> >>+                 TYPE_TRAMPOLINE_TARGET (type)->target_physaddr ());

>>> >>+      break;

>>> >>+    case TRAMPOLINE_TARGET_PHYSNAME:

>>> >>+      gdb_printf ("%*starget physname: %s\n", spaces + 2, "",

>>> >>+                 TYPE_TRAMPOLINE_TARGET (type)->target_physname ());

>>> >>+      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.  */ @@ -5531,6 +5556,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 ("%*sis_trampoline %d\n", spaces, "",

>>> >>+                   TYPE_IS_TRAMPOLINE (type));

>>> >>+       if (TYPE_IS_TRAMPOLINE (type))

>>> >>+         print_trampoline_target_info (type, spaces);

>>> >>        break;

>>> >>

>>> >>       case TYPE_SPECIFIC_SELF_TYPE:

>>> >>@@ -5762,6 +5791,8 @@ copy_type_recursive (struct objfile *objfile,

>>> >>       TYPE_CALLING_CONVENTION (new_type) =

>>> TYPE_CALLING_CONVENTION

>>> >>(type);

>>> >>       TYPE_NO_RETURN (new_type) = TYPE_NO_RETURN (type);

>>> >>       TYPE_TAIL_CALL_LIST (new_type) = NULL;

>>> >>+      TYPE_IS_TRAMPOLINE (new_type) = TYPE_IS_TRAMPOLINE (type);

>>> >>+      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 7437e1db8ab..846de1289ad

>>> 100644

>>> >>--- a/gdb/gdbtypes.h

>>> >>+++ b/gdb/gdbtypes.h

>>> >>@@ -1811,6 +1811,83 @@ struct func_type

>>> >>        contains the method.  */

>>> >>

>>> >>     struct type *self_type;

>>> >>+

>>> >>+    /* * For functions marked with the DW_AT_trampoline.  These are

>>> >>+       compiler generated wrappers that should be hidden from the user.

>>> >>+ */

>>> >>+

>>> >>+    unsigned int is_trampoline : 1;

>>> >>+

>>> >>+    struct trampoline_target *self_trampoline_target;  };

>>> >>+

>>> >>+/* The kind of location held by this call site target.  */ enum

>>> >>+trampoline_target_kind

>>> >>+  {

>>> >>+    /* An address.  */

>>> >>+    TRAMPOLINE_TARGET_PHYSADDR,

>>> >>+    /* A (mangled) name.  */

>>> >>+    TRAMPOLINE_TARGET_PHYSNAME,

>>> >>+    /* An flag (target is unknown).  */

>>> >>+    TRAMPOLINE_TARGET_FLAG,

>>> >>+  };

>>> >>+

>>> >>+struct trampoline_target

>>> >>+  {

>>> >>+    trampoline_target_kind target_kind () const

>>> >>+    {

>>> >>+      return m_target_kind;

>>> >>+    }

>>> >>+

>>> >>+    void set_target_physaddr (CORE_ADDR physaddr)

>>> >>+    {

>>> >>+      m_target_kind = TRAMPOLINE_TARGET_PHYSADDR;

>>> >>+      m_trampoline_target.physaddr = physaddr;

>>> >>+    }

>>> >>+

>>> >>+    CORE_ADDR target_physaddr () const

>>> >>+    {

>>> >>+      gdb_assert (m_target_kind == TRAMPOLINE_TARGET_PHYSADDR);

>>> >>+      return m_trampoline_target.physaddr;

>>> >>+    }

>>> >>+

>>> >>+    void set_target_physname (const char *physname)

>>> >>+    {

>>> >>+      m_target_kind = TRAMPOLINE_TARGET_PHYSNAME;

>>> >>+      m_trampoline_target.physname = physname;

>>> >>+    }

>>> >>+

>>> >>+    const char *target_physname () const

>>> >>+    {

>>> >>+      gdb_assert (m_target_kind == TRAMPOLINE_TARGET_PHYSNAME);

>>> >>+      return m_trampoline_target.physname;

>>> >>+    }

>>> >>+

>>> >>+    void set_target_flag (bool flag)

>>> >>+    {

>>> >>+      m_target_kind = TRAMPOLINE_TARGET_FLAG;

>>> >>+      m_trampoline_target.flag = flag;

>>> >>+    }

>>> >>+

>>> >>+    bool target_flag () const

>>> >>+    {

>>> >>+      gdb_assert (m_target_kind == TRAMPOLINE_TARGET_FLAG);

>>> >>+      return m_trampoline_target.flag;

>>> >>+    }

>>> >>+

>>> >>+  private:

>>> >>+

>>> >>+    union

>>> >>+    {

>>> >>+      /* Address.  */

>>> >>+      CORE_ADDR physaddr;

>>> >>+      /* Mangled name.  */

>>> >>+      const char *physname;

>>> >>+      /* Flag.  */

>>> >>+      bool flag;

>>> >>+    } m_trampoline_target;

>>> >>+

>>> >>+    /* * Discriminant for union m_trampoline_target.  */

>>> >>+    ENUM_BITFIELD (trampoline_target_kind) m_target_kind : 2;

>>> >>   };

>>> >>

>>> >> /* struct call_site_parameter can be referenced in callees by

>>> >> several

>>> ways.  */

>>> >>@@ -2172,6 +2249,8 @@ extern void set_type_vptr_basetype (struct

>>> type *,

>>> >>struct type *);  #define TYPE_CALLING_CONVENTION(thistype)

>>> >>TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff-

>>> >calling_convention

>>> >> #define TYPE_NO_RETURN(thistype) TYPE_MAIN_TYPE(thistype)-

>>> >>>type_specific.func_stuff->is_noreturn

>>> >> #define TYPE_TAIL_CALL_LIST(thistype) TYPE_MAIN_TYPE(thistype)-

>>> >>>type_specific.func_stuff->tail_call_list

>>> >>+#define TYPE_IS_TRAMPOLINE(thistype)

>>> >>+TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->is_trampoline

>>> >>+#define TYPE_TRAMPOLINE_TARGET(thistype)

>>> >>+TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff-

>>> >self_trampoline_tar

>>> >>+get

>>> >> #define TYPE_BASECLASS(thistype,index) ((thistype)->field

>>> >> (index).type

>>> ())

>>> >>#define TYPE_N_BASECLASSES(thistype) TYPE_CPLUS_SPECIFIC(thistype)-

>>> >>>n_baseclasses

>>> >> #define TYPE_BASECLASS_NAME(thistype,index) (thistype->field

>>> (index).name ())

>>> >>--

>>> >>2.25.1

>>> >>

>>> >>Intel Deutschland GmbH

>>> >>Registered Address: Am Campeon 10, 85579 Neubiberg, Germany

>>> >>Tel: +49 89 99 8853-0,

>>> >>https://nam11.safelinks.protection.outlook.com/?url=http%3A%2F%2Fw

>>> ww.int

>>> >>el.de%2F&data=05%7C01%7CJiniSusan.George%40amd.com%7C9c3f

>>> 28b5

>>>

>>>>98cf49f888f908da601272a0%7C3dd8961fe4884e608e11a82d994e183d%7C0

>>> %7

>>> >>C0%7C637927929632561872%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC

>>> 4wLj

>>> >>AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C

>>> %7C

>>> >>%7C&sdata=MBaQ7XpSZ4XFO963dnxF%2Fy1PD0gcx6k%2FjdaifxoSUa

>>> Y%3D

>>> >>&reserved=0

>>> >><https://nam11.safelinks.protection.outlook.com/?url=http%3A%2F%2Fw

>>> ww.in

>>> >>tel.de%2F&data=05%7C01%7CJiniSusan.George%40amd.com%7C9c3

>>> f28b5

>>>

>>>>98cf49f888f908da601272a0%7C3dd8961fe4884e608e11a82d994e183d%7C0

>>> %7

>>> >>C0%7C637927929632561872%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC

>>> 4wLj

>>> >>AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C

>>> %7C

>>> >>%7C&sdata=MBaQ7XpSZ4XFO963dnxF%2Fy1PD0gcx6k%2FjdaifxoSUa

>>> Y%3D

>>> >>&reserved=0>

>>> >>Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon

>>> >>Silva Chairperson of the Supervisory Board: Nicole Lau Registered Office:

>>> Munich

>>> >>Commercial Register: Amtsgericht Muenchen HRB 186928

>>

>>Intel Deutschland GmbH

>>Registered Address: Am Campeon 10, 85579 Neubiberg, Germany

>>Tel: +49 89 99 8853-0,

>>https://nam11.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.int

>>el.de%2F&data=05%7C01%7CJiniSusan.George%40amd.com%7Cd62c3e20

>>92aa47098d9908da64c720a7%7C3dd8961fe4884e608e11a82d994e183d%7C0%

>>7C0%7C637933103654397897%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wL

>>jAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C

>>%7C&sdata=SqOet8GRTDgMHyLH9TKkvnaiK1N0AO1NQG09Pln8iJQ%3D&a

>>mp;reserved=0

>><https://nam11.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.in

>>tel.de%2F&data=05%7C01%7CJiniSusan.George%40amd.com%7Cd62c3e2

>>092aa47098d9908da64c720a7%7C3dd8961fe4884e608e11a82d994e183d%7C0

>>%7C0%7C637933103654397897%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4

>>wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C

>>%7C%7C&sdata=SqOet8GRTDgMHyLH9TKkvnaiK1N0AO1NQG09Pln8iJQ%3

>>D&reserved=0>

>>Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva

>>Chairperson of the Supervisory Board: Nicole Lau Registered Office: Munich

>>Commercial Register: Amtsgericht Muenchen HRB 186928



Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2023-01-03  1:07 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-07 12:15 [PATCH 1/3] gdb: add support for DW_AT_trampoline in DWARF reader Nils-Christian Kempke
2022-07-07 12:15 ` [PATCH 2/3] gdb/symtab: add lookup for trampoline functions Nils-Christian Kempke
2022-07-15 20:13   ` Tom Tromey
2022-07-07 12:15 ` [PATCH 3/3] gdb/infrun: handle stepping through functions with DW_AT_trampoline Nils-Christian Kempke
2022-07-15 20:20   ` Tom Tromey
2022-07-13  7:39 ` [PATCH 1/3] gdb: add support for DW_AT_trampoline in DWARF reader George, Jini Susan
2022-07-13 11:59   ` Kempke, Nils-Christian
2022-07-17 12:57     ` George, Jini Susan
2022-07-18 16:11       ` Tom Tromey
2022-07-15 20:05 ` Tom Tromey
2023-01-03  1:07 Ijaz, Abdul B

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).