From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by sourceware.org (Postfix) with ESMTPS id B96F13858D32 for ; Thu, 7 Jul 2022 12:15:45 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org B96F13858D32 X-IronPort-AV: E=McAfee;i="6400,9594,10400"; a="267038745" X-IronPort-AV: E=Sophos;i="5.92,252,1650956400"; d="scan'208";a="267038745" Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Jul 2022 05:15:44 -0700 X-IronPort-AV: E=Sophos;i="5.92,252,1650956400"; d="scan'208";a="661364819" Received: from labpcdell3650-003.iul.intel.com (HELO localhost) ([172.28.49.87]) by fmsmga004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Jul 2022 05:15:43 -0700 From: Nils-Christian Kempke To: gdb-patches@sourceware.org Subject: [PATCH 1/3] gdb: add support for DW_AT_trampoline in DWARF reader Date: Thu, 7 Jul 2022 14:15:36 +0200 Message-Id: <20220707121538.1317473-2-nils-christian.kempke@intel.com> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-10.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 07 Jul 2022 12:15:48 -0000 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 * 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 --- 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 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