From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mgamail.intel.com (mgamail.intel.com [192.55.52.43]) by sourceware.org (Postfix) with ESMTPS id 63D5F385800C for ; Wed, 16 Aug 2023 21:54:20 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 63D5F385800C Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1692222860; x=1723758860; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=bBVMT0XVCDZBqkKHn7foqY/nCSDu0B5uxib6lbvCtWk=; b=F9E0XjGmxy+4gyY94nCoretbNmWqNtUdoWf/eMJdEUZq4UXOGHCVilGZ tL6cry8m2eE1al0AY8YvAPcOmMVQh0CZOflTA1snSnYDvYWa2Fv1VE9ph nXCNFWi6jmGmspnQ0qr33IhTx1HJVbFkAi9Qqe/HITvs0h1EtuXNMQLpn Few4D9AjM8Se7f8fjOByGvy60zZGWphr91rUuxlYZCYm72t2mcjT/aP7L OlzV4sPjGLOMO4s2T9Dr4MJESH5v8Aeec85BlEdoXojF5sOKUJ60BcVDW ye8pwwy6SNKHE5T1BvJcusxXWesow4va/V8m5Cj0dB5SmX3h8bCVTYDCJ g==; X-IronPort-AV: E=McAfee;i="6600,9927,10803"; a="459003149" X-IronPort-AV: E=Sophos;i="6.01,178,1684825200"; d="scan'208";a="459003149" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Aug 2023 14:54:19 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10803"; a="857966313" X-IronPort-AV: E=Sophos;i="6.01,178,1684825200"; d="scan'208";a="857966313" Received: from abijaz-mobl2.ger.corp.intel.com (HELO localhost) ([10.249.40.204]) by orsmga004-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Aug 2023 14:54:18 -0700 From: Abdul Basit Ijaz To: gdb-patches@sourceware.org Cc: abdul.b.ijaz@intel.com, JiniSusan.George@amd.com, tom@tromey.com, eliz@gnu.org, blarsen@redhat.com Subject: [PATCH v5 1/4] gdb, dwarf: add support for DW_AT_trampoline in DWARF reader Date: Wed, 16 Aug 2023 23:53:46 +0200 Message-Id: <20230816215349.6198-2-abdul.b.ijaz@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230816215349.6198-1-abdul.b.ijaz@intel.com> References: <20230816215349.6198-1-abdul.b.ijaz@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-10.1 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 autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: 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-16 Nils-Christian Kempke --- gdb/dwarf2/read.c | 46 ++++++++++++++++++- gdb/gdbtypes.c | 34 +++++++++++++- gdb/gdbtypes.h | 113 ++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 186 insertions(+), 7 deletions(-) diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index a64f82bd24a..748cdbc4eb2 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -14656,6 +14656,50 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu) if (prototyped_function_p (die, cu)) ftype->set_is_prototyped (true); + /* If this is a trampoline function store it and its target here. */ + attr = dwarf2_attr (die, DW_AT_trampoline, cu); + if (attr != nullptr) + { + TYPE_FUNC_FLAGS (ftype) |= FUNC_TYPE_TRAMPOLINE; + TYPE_TRAMPOLINE_TARGET (ftype) + = (trampoline_target *) TYPE_ZALLOC (ftype, + sizeof (trampoline_target)); + + /* A DW_AT_trampoline can be either an address, a flag, a reference or a + string. */ + if (attr->form_is_string ()) + TYPE_TRAMPOLINE_TARGET (ftype)->set_target_name + (attr->as_string ()); + else if (attr->form_is_ref ()) + { + die_info *target_die; + dwarf2_cu *target_cu = cu; + unrelocated_addr lowpc; + + target_die = follow_die_ref (die, attr, &target_cu); + + if (dwarf2_get_pc_bounds (target_die, &lowpc, NULL, target_cu, + nullptr, nullptr) <= PC_BOUNDS_INVALID) + complaint (_("DW_AT_trampoline target DIE has invalid " + "low pc, for referencing DIE %s[in module %s]"), + sect_offset_str (die->sect_off), + objfile_name (objfile)); + else + { + lowpc = cu->per_objfile->adjust (lowpc); + TYPE_TRAMPOLINE_TARGET (ftype)->set_target_addr (lowpc); + } + } + else if (attr->form_is_unsigned ()) + TYPE_TRAMPOLINE_TARGET (ftype)->set_target_flag (attr->as_boolean ()); + else + { + unrelocated_addr target_addr = attr->as_address (); + target_addr = cu->per_objfile->adjust (target_addr); + TYPE_TRAMPOLINE_TARGET (ftype)->set_target_addr (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. */ @@ -14673,7 +14717,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 d7db7beb554..096c5c85a75 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_ADDR: + gdb_printf ("%*starget addr: 0x%s\n", spaces + 2, "", + print_core_address (type->arch_owner (), + (CORE_ADDR) TYPE_TRAMPOLINE_TARGET (type) + ->target_addr ())); + break; + case TRAMPOLINE_TARGET_NAME: + gdb_printf ("%*starget name: %s\n", spaces + 2, "", + TYPE_TRAMPOLINE_TARGET (type)->target_name ()); + break; + case TRAMPOLINE_TARGET_FLAG: + gdb_printf ("%*starget flag: %d\n", spaces + 2, "", + TYPE_TRAMPOLINE_TARGET (type)->target_flag ()); + break; + default: + gdb_assert_not_reached ("unhandled trampoline target kind"); + break; + } +} + static struct obstack dont_print_type_obstack; /* Print the dynamic_prop PROP. */ @@ -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 0x%x\n", spaces, "", + (unsigned int) TYPE_FUNC_FLAGS (type)); + if (TYPE_IS_TRAMPOLINE (type)) + print_trampoline_target_info (type, spaces); break; case TYPE_SPECIFIC_SELF_TYPE: @@ -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..e43cd4e4d3b 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_ADDR, + /* A (mangled) name. */ + TRAMPOLINE_TARGET_NAME, + /* A flag (target is unknown). */ + TRAMPOLINE_TARGET_FLAG, + }; + +/* Target information for trampoline functions. */ + +struct trampoline_target + { + /* Returns what kind of target the trampoline points to. */ + trampoline_target_kind target_kind () const + { + return m_target_kind; + } + + /* Set the address for trampoline target. */ + void set_target_addr (unrelocated_addr unreloc_addr) + { + m_target_kind = TRAMPOLINE_TARGET_ADDR; + m_trampoline_target.unreloc_addr = unreloc_addr; + } + + /* Return the address of the trampoline target. */ + unrelocated_addr target_addr () const + { + gdb_assert (m_target_kind == TRAMPOLINE_TARGET_ADDR); + return m_trampoline_target.unreloc_addr; + } + + /* Set the name of the trampoline target. */ + void set_target_name (const char *name) + { + m_target_kind = TRAMPOLINE_TARGET_NAME; + m_trampoline_target.name = name; + } + + /* Return the name of the trampoline target. */ + const char *target_name () const + { + gdb_assert (m_target_kind == TRAMPOLINE_TARGET_NAME); + return m_trampoline_target.name; + } + + /* Set the flag for trampoline target subroutine. */ + void set_target_flag (bool flag) + { + m_target_kind = TRAMPOLINE_TARGET_FLAG; + m_trampoline_target.flag = flag; + } + + /* Return the flag for trampoline target. */ + bool target_flag () const + { + gdb_assert (m_target_kind == TRAMPOLINE_TARGET_FLAG); + return m_trampoline_target.flag; + } + + private: + + union + { + /* Address. */ + unrelocated_addr unreloc_addr; + /* Mangled name. */ + const char *name; + /* Flag. */ + bool flag; + } m_trampoline_target; + + /* * Discriminant for union m_trampoline_target. */ + ENUM_BITFIELD (trampoline_target_kind) m_target_kind : 2; }; /* The type-specific info for TYPE_CODE_FIXED_POINT types. */ @@ -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 -- 2.34.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