From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id 0J+XL19dBWbUdhkAWB0awg (envelope-from ) for ; Thu, 28 Mar 2024 08:06:55 -0400 Authentication-Results: simark.ca; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=oBq9Gro0; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id BD3DD1E0C0; Thu, 28 Mar 2024 08:06:55 -0400 (EDT) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id A69A81E030 for ; Thu, 28 Mar 2024 08:06:53 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 3B016385840D for ; Thu, 28 Mar 2024 12:06:53 +0000 (GMT) Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) by sourceware.org (Postfix) with ESMTPS id 6DDCE3858CDB for ; Thu, 28 Mar 2024 12:05:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 6DDCE3858CDB Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=intel.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 6DDCE3858CDB Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1711627565; cv=none; b=g9jjp5n+OfCxg+KNNckgK+Suwb2nPFS2eOkDF0MhBnzbzD8IL9mMnewxBVsUoyKd8nIl7EWTqu42Z8Ruz+YwPrRSmt0PiUzqC1R2wrc7lOaDOfPkKL9k3N2yMttRPmBEVBdOySaZl9HAXIdOaCRsjQ2RLw3bVnIS4JLXPenpyKk= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1711627565; c=relaxed/simple; bh=3iDe+dFPoCkexHCr0n1kEhs3N9Sy79FePalvUiQff9g=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=vhGASc1blfhyxUH4ZMXK/we5nLDIhAS5HAjy5p1RLyIOJ4+/V3mPimvnmOnDSIfLssfoxvV6A7VSoCRmxMleo4/NpzdoyEmI3vwqaqnPVWVDK3A+cG5NVjPoBcBH/gdCrDSl/sKwTrLQCg5D/gNrlceAkij4TGriBXINgNKfb4Y= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1711627554; x=1743163554; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=3iDe+dFPoCkexHCr0n1kEhs3N9Sy79FePalvUiQff9g=; b=oBq9Gro0KGzekSxdeI95RRD6YLeura80qThVknlOqIAHojMF1hZTGLeA 4ENjKk7hi4VBdCNFiSFzxEY7YGX/06vjOCLZh3T0hUQSqA5FDxmCOpkBq QXFrwbQ9V9OgxarptAlIHUQuOuYoJe7rfE9VcP/5jXtSxAKm8N7pru7jV fgi6lZo4fBExL4JPNG9ui2Tc8SOfjYvyIGMaU3uztobQkXxFVo4T6m59W 2HmLo2mowswQFE2BILsDQvzVMF/QL3Tw3ewX/8rpojiQB9CmMliB2KPOQ rRVEBXev+j5IX4ThfJhrdqYsUqTNWxOGX3aPi+UevIVGKGkSx0I8ncs2n w==; X-CSE-ConnectionGUID: 1twip7otQ1eyyMoJtp7/HA== X-CSE-MsgGUID: KbZGFGLjT4+53O5V9jTSBw== X-IronPort-AV: E=McAfee;i="6600,9927,11026"; a="10582603" X-IronPort-AV: E=Sophos;i="6.07,161,1708416000"; d="scan'208";a="10582603" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Mar 2024 05:05:53 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.07,161,1708416000"; d="scan'208";a="17035459" Received: from abijaz-mobl2.ger.corp.intel.com (HELO localhost) ([10.246.42.1]) by orviesa007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Mar 2024 05:05:51 -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, Nils-Christian Kempke Subject: [PATCH v6 01/10] gdb, dwarf: add support for DW_AT_trampoline in DWARF reader Date: Thu, 28 Mar 2024 13:05:19 +0100 Message-Id: <20240328120528.30382-2-abdul.b.ijaz@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240328120528.30382-1-abdul.b.ijaz@intel.com> References: <20240328120528.30382-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.8 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, 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 X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+public-inbox=simark.ca@sourceware.org From: Nils-Christian Kempke 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. 2024-03-28 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 31313bc88b3..6ab8a675018 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -14581,6 +14581,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. */ @@ -14598,7 +14642,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 1e1a7e9ce61..cce45795d5a 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -5069,6 +5069,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. */ @@ -5344,6 +5371,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: @@ -5558,8 +5589,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 f80bd7e071a..0cd4941e85b 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -97,6 +97,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. */ @@ -1812,11 +1827,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 @@ -1831,6 +1844,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. */ @@ -1973,7 +2067,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