[v4,1/4] gdb, dwarf: add support for DW_AT_trampoline in DWARF reader

Message ID 20230801224744.24433-2-abdul.b.ijaz@intel.com
State New
Headers
Series GDB support for DW_AT_trampoline |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gdb_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gdb_check--master-arm success Testing passed

Commit Message

Abdul Basit Ijaz Aug. 1, 2023, 10:47 p.m. UTC
  From: Nils-Christian Kempke <nils-christian.kempke@intel.com>

DW_AT_trampoline can be used to describe compiler generated functions
that serve some intermediary purpose on making a call to another
function.  A compiler can emit this tag in order to help a debugger hide
the trampolines from a user.

The attribute is only applicable to DW_TAG_subroutine and
DW_TAG_inlined_subroutine tags.  It contains information about the
trampoline target either as a reference to its DIE, as its address or
its name.  DW_AT_trampoline can also be a flag indicating that the DIE
is a trampoline or not without specifying the target (e.g. if it is
unknown).

This patch adds support to GDB for reading the DW_AT_trampoline
attribute.  It stores the attribute and its value in the type_specific
part of a GDB type.  This patch is implemented in preparation of the
following patches, which will add a mechanism to hide DW_AT_trampoline
subroutines from the user.

2023-08-01 Nils-Christian Kempke <nils-christian.kempke@intel.com>
---
 gdb/dwarf2/read.c |  49 +++++++++++++++++++-
 gdb/gdbtypes.c    |  34 +++++++++++++-
 gdb/gdbtypes.h    | 113 ++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 189 insertions(+), 7 deletions(-)
  

Comments

Tom Tromey Aug. 2, 2023, 8:07 p.m. UTC | #1
>>>>> "Abdul" == Abdul Basit Ijaz via Gdb-patches <gdb-patches@sourceware.org> writes:

Abdul> This patch adds support to GDB for reading the DW_AT_trampoline
Abdul> attribute.  It stores the attribute and its value in the type_specific
Abdul> part of a GDB type.  This patch is implemented in preparation of the
Abdul> following patches, which will add a mechanism to hide DW_AT_trampoline
Abdul> subroutines from the user.

Thanks for the patch.

Abdul> +	  if (target_name == NULL)
Abdul> +	    target_name = dwarf2_physname (NULL, target_die, target_cu);

Probably your patch predates this but nowadays we're using nullptr
instead of NULL.

Abdul> +	  unrelocated_addr target_addr_reloc = attr->as_address ();
Abdul> +	  CORE_ADDR target_addr
Abdul> +	    = cu->per_objfile->relocate (target_addr_reloc);
Abdul> +	  target_addr = gdbarch_adjust_dwarf2_addr (objfile->arch (),
Abdul> +						    target_addr);

dwarf2_per_objfile::relocate already calls gdbarch_adjust_dwarf2_addr,
so that call isn't needed.

Abdul> +	gdb_printf ("%*sfunc_type_flags %u\n", spaces, "",
Abdul> +		    (unsigned int) TYPE_FUNC_FLAGS (type));

If we're just printing the flags as an int, how about using hex instead?

Abdul> -    unsigned int is_noreturn : 1;
Abdul> +    func_type_flags flags;

This should use ENUM_BITFIELD like the other spot in the patch.

Tom
  
Tom Tromey Aug. 2, 2023, 8:13 p.m. UTC | #2
>>>>> "Abdul" == Abdul Basit Ijaz via Gdb-patches <gdb-patches@sourceware.org> writes:

Abdul> +      else if (attr->form_is_ref ())
Abdul> +	{
Abdul> +	  die_info *target_die;
Abdul> +	  dwarf2_cu *target_cu = cu;
Abdul> +
Abdul> +	  target_die = follow_die_ref (die, attr, &target_cu);
Abdul> +	  const char *target_name;
Abdul> +	  /* Prefer the mangled name; otherwise compute the demangled one.  */
Abdul> +	  target_name = dw2_linkage_name (target_die, target_cu);
Abdul> +	  if (target_name == NULL)
Abdul> +	    target_name = dwarf2_physname (NULL, target_die, target_cu);
Abdul> +	  if (target_name == nullptr)
Abdul> +	    {
Abdul> +	      complaint (_("DW_AT_trampoline target DIE has no name for"
Abdul> +			 "referencing DIE %s [in module %s]"),
Abdul> +			 sect_offset_str (die->sect_off),
Abdul> +			 objfile_name (objfile));
Abdul> +	    }
Abdul> +	  TYPE_TRAMPOLINE_TARGET (ftype)->set_target_name (target_name);

I didn't realize this until starting to read patch 2, but it seems
strange to use the name here.  It seems to me it would be better to use
the address attached to the referenced subroutine DIE.  The "bad"
scenario would be where there are multiple functions with the same name
here, and gdb's symbol lookup returns the wrong one.  You can normally
trigger these bugs by carefully ordering shared libraries.

Tom
  
Terekhov, Mikhail via Gdb-patches Aug. 7, 2023, 1:36 p.m. UTC | #3
Hi Tom,

Thanks for the feedback.

Tom> I didn't realize this until starting to read patch 2, but it seems strange to use the name here.  It seems to me it would be better to use the address attached to the referenced subroutine DIE The "bad"
scenario would be where there are multiple functions with the same name here, and gdb's symbol lookup returns the wrong one

For this case of  value of attributes for this DIE may contain mangled name of the target. So for such cases we are preferring the linkage name to store. Shouldn't it cover such issues. Otherwise let me know then I may update accordingly.
As per dwarf spec: "
If the value is of class string, then the value is the (possibly mangled) name  of the target subprogram.
"

Thanks & Best Regards
Abdul Basit

-----Original Message-----
From: Tom Tromey <tom@tromey.com> 
Sent: Wednesday, August 2, 2023 10:13 PM
To: Abdul Basit Ijaz via Gdb-patches <gdb-patches@sourceware.org>
Cc: Ijaz, Abdul B <abdul.b.ijaz@intel.com>; JiniSusan.George@amd.com; tom@tromey.com; eliz@gnu.org; blarsen@redhat.com; Nils-Christian Kempke <nils-christian.kempke@intel.com>
Subject: Re: [PATCH v4 1/4] gdb, dwarf: add support for DW_AT_trampoline in DWARF reader

>>>>> "Abdul" == Abdul Basit Ijaz via Gdb-patches <gdb-patches@sourceware.org> writes:

Abdul> +      else if (attr->form_is_ref ())
Abdul> +	{
Abdul> +	  die_info *target_die;
Abdul> +	  dwarf2_cu *target_cu = cu;
Abdul> +
Abdul> +	  target_die = follow_die_ref (die, attr, &target_cu);
Abdul> +	  const char *target_name;
Abdul> +	  /* Prefer the mangled name; otherwise compute the demangled one.  */
Abdul> +	  target_name = dw2_linkage_name (target_die, target_cu);
Abdul> +	  if (target_name == NULL)
Abdul> +	    target_name = dwarf2_physname (NULL, target_die, target_cu);
Abdul> +	  if (target_name == nullptr)
Abdul> +	    {
Abdul> +	      complaint (_("DW_AT_trampoline target DIE has no name for"
Abdul> +			 "referencing DIE %s [in module %s]"),
Abdul> +			 sect_offset_str (die->sect_off),
Abdul> +			 objfile_name (objfile));
Abdul> +	    }
Abdul> +	  TYPE_TRAMPOLINE_TARGET (ftype)->set_target_name 
Abdul> +(target_name);

I didn't realize this until starting to read patch 2, but it seems strange to use the name here.  It seems to me it would be better to use the address attached to the referenced subroutine DIE.  The "bad"
scenario would be where there are multiple functions with the same name here, and gdb's symbol lookup returns the wrong one.  You can normally trigger these bugs by carefully ordering shared libraries.

Tom
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
  
Terekhov, Mikhail via Gdb-patches Aug. 7, 2023, 2:43 p.m. UTC | #4
Hi Tom,

Thanks for the feedback.

Abdul> +	  if (target_name == NULL)
Tom> Probably your patch predates this but nowadays we're using nullptr instead of NULL.
Will fix in V5 patch.

Abdul> +		    (unsigned int) TYPE_FUNC_FLAGS (type));
Tom> If we're just printing the flags as an int, how about using hex instead?
Will update print format to hex in V5 patch.

Abdul> +    func_type_flags flags;
Tom>This should use ENUM_BITFIELD like the other spot in the patch.
This flag may store multiple values together with no return and trampoline types for a function. That is the reason why it is used like this here. So value is already bitfield like:
enum func_type_flag_value : unsigned
{
  FUNC_TYPE_NO_RETURN = (1 << 0),
  FUNC_TYPE_TRAMPOLINE = (1 << 1)
};

Thanks & Best Regards
Abdul Basit

-----Original Message-----
From: Tom Tromey <tom@tromey.com> 
Sent: Wednesday, August 2, 2023 10:08 PM
To: Abdul Basit Ijaz via Gdb-patches <gdb-patches@sourceware.org>
Cc: Ijaz, Abdul B <abdul.b.ijaz@intel.com>; JiniSusan.George@amd.com; tom@tromey.com; eliz@gnu.org; blarsen@redhat.com; Nils-Christian Kempke <nils-christian.kempke@intel.com>
Subject: Re: [PATCH v4 1/4] gdb, dwarf: add support for DW_AT_trampoline in DWARF reader

>>>>> "Abdul" == Abdul Basit Ijaz via Gdb-patches <gdb-patches@sourceware.org> writes:

Abdul> This patch adds support to GDB for reading the DW_AT_trampoline 
Abdul> attribute.  It stores the attribute and its value in the 
Abdul> type_specific part of a GDB type.  This patch is implemented in 
Abdul> preparation of the following patches, which will add a mechanism 
Abdul> to hide DW_AT_trampoline subroutines from the user.

Thanks for the patch.

Abdul> +	  if (target_name == NULL)
Abdul> +	    target_name = dwarf2_physname (NULL, target_die, 
Abdul> +target_cu);

Probably your patch predates this but nowadays we're using nullptr instead of NULL.

Abdul> +	  unrelocated_addr target_addr_reloc = attr->as_address ();
Abdul> +	  CORE_ADDR target_addr
Abdul> +	    = cu->per_objfile->relocate (target_addr_reloc);
Abdul> +	  target_addr = gdbarch_adjust_dwarf2_addr (objfile->arch (),
Abdul> +						    target_addr);

dwarf2_per_objfile::relocate already calls gdbarch_adjust_dwarf2_addr, so that call isn't needed.

Abdul> +	gdb_printf ("%*sfunc_type_flags %u\n", spaces, "",
Abdul> +		    (unsigned int) TYPE_FUNC_FLAGS (type));

If we're just printing the flags as an int, how about using hex instead?

Abdul> -    unsigned int is_noreturn : 1;
Abdul> +    func_type_flags flags;

This should use ENUM_BITFIELD like the other spot in the patch.

Tom
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
  
Tom Tromey Aug. 10, 2023, 4:18 p.m. UTC | #5
Tom> I didn't realize this until starting to read patch 2, but it seems
Tom> strange to use the name here.  It seems to me it would be better to
Tom> use the address attached to the referenced subroutine DIE

> For this case of value of attributes for this DIE may contain mangled
> name of the target. So for such cases we are preferring the linkage
> name to store. Shouldn't it cover such issues. Otherwise let me know
> then I may update accordingly.

> As per dwarf spec: "
> If the value is of class string, then the value is the (possibly mangled) name  of the target subprogram.
> "

The case I was referring to is the one where the attribute is a
reference to another DIE:

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

And here, DWARF 5 says:

    If the value is of class reference, then the value specifies the
    debugging information entry of the target subprogram.

That is, the attribute references the subprogram DIE directly, so it
seems like using the name should not be needed.

Tom
  
Tom Tromey Aug. 10, 2023, 4:20 p.m. UTC | #6
>>>>> Ijaz, Abdul B via Gdb-patches <gdb-patches@sourceware.org> writes:

Abdul> +    func_type_flags flags;

Tom> This should use ENUM_BITFIELD like the other spot in the patch.

> This flag may store multiple values together with no return and
> trampoline types for a function. That is the reason why it is used
> like this here. So value is already bitfield like:

Actually I think I misread and thought this was still using a bitfield,
which it is not.  So I think that bit is fine.

Tom
  
Terekhov, Mikhail via Gdb-patches Aug. 14, 2023, 9:53 p.m. UTC | #7
Tom>That is, the attribute references the subprogram DIE directly, so it seems like using the name should not be needed.
Yes right, will use  the address of target subroutine instead of name. Will be updated it in v5.

Thanks & Best Regards
Abdul Basit

-----Original Message-----
From: Tom Tromey <tom@tromey.com> 
Sent: Thursday, August 10, 2023 6:19 PM
To: Ijaz, Abdul B via Gdb-patches <gdb-patches@sourceware.org>
Cc: Tom Tromey <tom@tromey.com>; Ijaz, Abdul B <abdul.b.ijaz@intel.com>; JiniSusan.George@amd.com; eliz@gnu.org; blarsen@redhat.com
Subject: Re: [PATCH v4 1/4] gdb, dwarf: add support for DW_AT_trampoline in DWARF reader

Tom> I didn't realize this until starting to read patch 2, but it seems 
Tom> strange to use the name here.  It seems to me it would be better to 
Tom> use the address attached to the referenced subroutine DIE

> For this case of value of attributes for this DIE may contain mangled 
> name of the target. So for such cases we are preferring the linkage 
> name to store. Shouldn't it cover such issues. Otherwise let me know 
> then I may update accordingly.

> As per dwarf spec: "
> If the value is of class string, then the value is the (possibly mangled) name  of the target subprogram.
> "

The case I was referring to is the one where the attribute is a reference to another DIE:

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

And here, DWARF 5 says:

    If the value is of class reference, then the value specifies the
    debugging information entry of the target subprogram.

That is, the attribute references the subprogram DIE directly, so it seems like using the name should not be needed.

Tom
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
  

Patch

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index b1f1c1d7257..56407c618d2 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -14657,6 +14657,53 @@  read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
   if (prototyped_function_p (die, cu))
     ftype->set_is_prototyped (true);
 
+  /* If this is a trampoline function store it and its target here.  */
+  attr = dwarf2_attr (die, DW_AT_trampoline, cu);
+  if (attr != nullptr)
+    {
+      TYPE_FUNC_FLAGS (ftype) |= FUNC_TYPE_TRAMPOLINE;
+      TYPE_TRAMPOLINE_TARGET (ftype)
+	= (trampoline_target *) TYPE_ZALLOC (ftype,
+					     sizeof (trampoline_target));
+
+      /* A DW_AT_trampoline can be either an address, a flag, a reference or a
+	 string.  */
+      if (attr->form_is_string ())
+	TYPE_TRAMPOLINE_TARGET (ftype)->set_target_name
+	  (attr->as_string ());
+      else if (attr->form_is_ref ())
+	{
+	  die_info *target_die;
+	  dwarf2_cu *target_cu = cu;
+
+	  target_die = follow_die_ref (die, attr, &target_cu);
+	  const char *target_name;
+	  /* Prefer the mangled name; otherwise compute the demangled one.  */
+	  target_name = dw2_linkage_name (target_die, target_cu);
+	  if (target_name == NULL)
+	    target_name = dwarf2_physname (NULL, 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_name (target_name);
+	}
+      else if (attr->form_is_unsigned ())
+	TYPE_TRAMPOLINE_TARGET (ftype)->set_target_flag (attr->as_boolean ());
+      else
+	{
+	  unrelocated_addr target_addr_reloc = attr->as_address ();
+	  CORE_ADDR target_addr
+	    = cu->per_objfile->relocate (target_addr_reloc);
+	  target_addr = gdbarch_adjust_dwarf2_addr (objfile->arch (),
+						    target_addr);
+	  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.  */
@@ -14674,7 +14721,7 @@  read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
      if the DWARF producer set that information.  */
   attr = dwarf2_attr (die, DW_AT_noreturn, cu);
   if (attr && attr->as_boolean ())
-    TYPE_NO_RETURN (ftype) = 1;
+    TYPE_FUNC_FLAGS (ftype) |= FUNC_TYPE_NO_RETURN;
 
   /* We need to add the subroutine type to the die immediately so
      we don't infinitely recurse when dealing with parameters
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index c5272979cb9..6d25cdc944e 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -5091,6 +5091,33 @@  print_fixed_point_type_info (struct type *type, int spaces)
 	      type->fixed_point_scaling_factor ().str ().c_str ());
 }
 
+/* Print the contents of the TYPE's self_trampoline_target, assuming that its
+   type-specific kind is TYPE_SPECIFIC_FUNC and is_trampoline is not 0.  */
+static void
+print_trampoline_target_info (struct type *type, int spaces)
+{
+  switch (TYPE_TRAMPOLINE_TARGET (type)->target_kind ())
+    {
+    case TRAMPOLINE_TARGET_PHYSADDR:
+      gdb_printf ("%*starget physaddr: 0x%s\n", spaces + 2, "",
+		  print_core_address (type->arch_owner (),
+				      TYPE_TRAMPOLINE_TARGET (type)
+				      ->target_physaddr ()));
+      break;
+    case TRAMPOLINE_TARGET_NAME:
+      gdb_printf ("%*starget name: %s\n", spaces + 2, "",
+		  TYPE_TRAMPOLINE_TARGET (type)->target_name ());
+      break;
+    case TRAMPOLINE_TARGET_FLAG:
+      gdb_printf ("%*starget flag: %d\n", spaces + 2, "",
+		  TYPE_TRAMPOLINE_TARGET (type)->target_flag ());
+      break;
+    default:
+      gdb_assert_not_reached ("unhandled trampoline target kind");
+      break;
+    }
+}
+
 static struct obstack dont_print_type_obstack;
 
 /* Print the dynamic_prop PROP.  */
@@ -5417,6 +5444,10 @@  recursive_dump_type (struct type *type, int spaces)
 	gdb_printf ("%*scalling_convention %d\n", spaces, "",
 		    TYPE_CALLING_CONVENTION (type));
 	/* tail_call_list is not printed.  */
+	gdb_printf ("%*sfunc_type_flags %u\n", spaces, "",
+		    (unsigned int) TYPE_FUNC_FLAGS (type));
+	if (TYPE_IS_TRAMPOLINE (type))
+	  print_trampoline_target_info (type, spaces);
 	break;
 
       case TYPE_SPECIFIC_SELF_TYPE:
@@ -5633,8 +5664,9 @@  copy_type_recursive (struct type *type, htab_t copied_types)
     case TYPE_SPECIFIC_FUNC:
       INIT_FUNC_SPECIFIC (new_type);
       TYPE_CALLING_CONVENTION (new_type) = TYPE_CALLING_CONVENTION (type);
-      TYPE_NO_RETURN (new_type) = TYPE_NO_RETURN (type);
+      TYPE_FUNC_FLAGS (new_type) = TYPE_FUNC_FLAGS (type);
       TYPE_TAIL_CALL_LIST (new_type) = NULL;
+      TYPE_TRAMPOLINE_TARGET (new_type) = TYPE_TRAMPOLINE_TARGET (type);
       break;
     case TYPE_SPECIFIC_FLOATFORMAT:
       TYPE_FLOATFORMAT (new_type) = TYPE_FLOATFORMAT (type);
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index aedaf53cd5d..310d00d0230 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -106,6 +106,21 @@  enum type_instance_flag_value : unsigned
 
 DEF_ENUM_FLAGS_TYPE (enum type_instance_flag_value, type_instance_flags);
 
+/* * Define flags for function types.  */
+enum func_type_flag_value : unsigned
+{
+  /* * Flag indicates, whether this function normally returns to its
+     caller.  It is set from the DW_AT_noreturn attribute if set on
+     the DW_TAG_subprogram.  */
+  FUNC_TYPE_NO_RETURN = (1 << 0),
+
+  /* * Flag is used for functions marked with DW_AT_trampoline.  These
+     are compiler generated wrappers that should be hidden from the user.  */
+  FUNC_TYPE_TRAMPOLINE = (1 << 1)
+};
+
+DEF_ENUM_FLAGS_TYPE (enum func_type_flag_value, func_type_flags);
+
 /* * Not textual.  By default, GDB treats all single byte integers as
    characters (or elements of strings) unless this flag is set.  */
 
@@ -1730,11 +1745,9 @@  struct func_type
 
     ENUM_BITFIELD (dwarf_calling_convention) calling_convention : 8;
 
-    /* * Whether this function normally returns to its caller.  It is
-       set from the DW_AT_noreturn attribute if set on the
-       DW_TAG_subprogram.  */
+    /* * For storing function types defined in eunm func_type_flag_value.  */
 
-    unsigned int is_noreturn : 1;
+    func_type_flags flags;
 
     /* * Only those DW_TAG_call_site's in this function that have
        DW_AT_call_tail_call set are linked in this list.  Function
@@ -1749,6 +1762,87 @@  struct func_type
        contains the method.  */
 
     struct type *self_type;
+
+    struct trampoline_target *self_trampoline_target;
+  };
+
+/* The kind of location held by this call site target.  */
+enum trampoline_target_kind
+  {
+    /* An address.  */
+    TRAMPOLINE_TARGET_PHYSADDR,
+    /* A (mangled) name.  */
+    TRAMPOLINE_TARGET_NAME,
+    /* An flag (target is unknown).  */
+    TRAMPOLINE_TARGET_FLAG,
+  };
+
+/* Target information for trampoline functions.  */
+
+struct trampoline_target
+  {
+    /* Returns what kind of target the trampoline points to.  */
+    trampoline_target_kind target_kind () const
+    {
+      return m_target_kind;
+    }
+
+    /* Set the address for trampoline target.  */
+    void set_target_physaddr (CORE_ADDR physaddr)
+    {
+      m_target_kind = TRAMPOLINE_TARGET_PHYSADDR;
+      m_trampoline_target.physaddr = physaddr;
+    }
+
+    /* Return the address of the trampoline target.  */
+    CORE_ADDR target_physaddr () const
+    {
+      gdb_assert (m_target_kind == TRAMPOLINE_TARGET_PHYSADDR);
+      return m_trampoline_target.physaddr;
+    }
+
+    /* Set the name of the trampoline target.  */
+    void set_target_name (const char *name)
+    {
+      m_target_kind = TRAMPOLINE_TARGET_NAME;
+      m_trampoline_target.name = name;
+    }
+
+    /* Return the name of the trampoline target.  */
+    const char *target_name () const
+    {
+      gdb_assert (m_target_kind == TRAMPOLINE_TARGET_NAME);
+      return m_trampoline_target.name;
+    }
+
+    /* Set the flag for trampoline target subroutine.  */
+    void set_target_flag (bool flag)
+    {
+      m_target_kind = TRAMPOLINE_TARGET_FLAG;
+      m_trampoline_target.flag = flag;
+    }
+
+    /* Return the flag for trampoline target.  */
+    bool target_flag () const
+    {
+      gdb_assert (m_target_kind == TRAMPOLINE_TARGET_FLAG);
+      return m_trampoline_target.flag;
+    }
+
+  private:
+
+    union
+    {
+      /* Address.  */
+      CORE_ADDR physaddr;
+      /* Mangled name.  */
+      const char *name;
+      /* Flag.  */
+      bool flag;
+    } m_trampoline_target;
+
+    /* * Discriminant for union m_trampoline_target.  */
+    ENUM_BITFIELD (trampoline_target_kind) m_target_kind : 2;
   };
 
 /* The type-specific info for TYPE_CODE_FIXED_POINT types.  */
@@ -1891,7 +1985,16 @@  extern void set_type_vptr_basetype (struct type *, struct type *);
 #define TYPE_GNAT_SPECIFIC(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.gnat_stuff
 #define TYPE_DESCRIPTIVE_TYPE(thistype) TYPE_GNAT_SPECIFIC(thistype)->descriptive_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_FUNC_FLAGS(thistype) \
+  TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->flags
+#define TYPE_NO_RETURN(thistype) \
+  (TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->flags \
+   & FUNC_TYPE_NO_RETURN)
+#define TYPE_IS_TRAMPOLINE(thistype) \
+  (TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->flags \
+   & FUNC_TYPE_TRAMPOLINE)
+#define TYPE_TRAMPOLINE_TARGET(thistype) \
+  TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->self_trampoline_target
 #define TYPE_TAIL_CALL_LIST(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->tail_call_list
 #define TYPE_BASECLASS(thistype,index) ((thistype)->field (index).type ())
 #define TYPE_N_BASECLASSES(thistype) TYPE_CPLUS_SPECIFIC(thistype)->n_baseclasses