From patchwork Thu Mar 28 12:05:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abdul Basit Ijaz X-Patchwork-Id: 87762 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 29AEE385841C for ; Thu, 28 Mar 2024 12:06:57 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org 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 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+patchwork=sourceware.org@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 From patchwork Thu Mar 28 12:05:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abdul Basit Ijaz X-Patchwork-Id: 87761 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E5A1C385842D for ; Thu, 28 Mar 2024 12:06:35 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) by sourceware.org (Postfix) with ESMTPS id 1E8DD3858D32 for ; Thu, 28 Mar 2024 12:06:04 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 1E8DD3858D32 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 1E8DD3858D32 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=1711627567; cv=none; b=hglzuNqUIihK23lt8QIdL5MSEwmIYvbohTCphhcOlBDQKXooSVPH3INAgn/Y87Dsa00u0wpPjv3HGn4ulm2DTpDc6hkDpRbzUws97WKaz1tWHal+KOEb5Hv4lzOz6t1DmAhQSdZgLMPTdmQo/1ZMtG5FeIa26Vigm29JXktRsYg= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1711627567; c=relaxed/simple; bh=KkLJVACZB9pkgfsSF4CqywNjCsx+OIO3fqTxq6gQHCM=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=rfmYJ/rLUpzXSq+mR9UnMULlhYQ5NxUDMUaUZJLB9U5z+IIRHa6zgm0eZ0q7AXsjg7juUs23L/drFGZ68SNE2IzonP+DXSkIvoEni8c2e733pgqKxAeDRgPlgVNQ3M1nY/1apgUG92fmGiTKC/G0iQKqPBSp15qoyNjhw/Vh47k= 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=1711627565; x=1743163565; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=KkLJVACZB9pkgfsSF4CqywNjCsx+OIO3fqTxq6gQHCM=; b=Gv/p9XLzU7VDB3L+GE4GkPBip5DmVtMLyNYqLui96FOd/YHuy29pU5Il V4zQTChkbPIzl7lIggzzaja2KbcCWTUblKjxH3XpcJc+cWVoT28ZimhpA rhha1tDimFR4+PhVmTJeE+aOTbD8FzosOGXLcHbT1QLzRdCwctOnG35H4 nsVbabAB2z8F0+s47bay/QPaP3wY5bRXY8IO+bQFEHCrURz6zBD6C87jl Nm4KK4kz2cVP1GPfQGrJpulwm3181X5RsBwzhIqFqW8Nil5E5d+YoVXwT 0lYrXLR2x2i8jHRFpmLHEcZ2d+VbEuxfItQVKtRsNZxBUMpZ2YjrMziL+ A==; X-CSE-ConnectionGUID: 4SKDY1YxTqqPNjKFr95aPA== X-CSE-MsgGUID: w2lFwHxvRp2gSlr6yEfmYg== X-IronPort-AV: E=McAfee;i="6600,9927,11026"; a="10582622" X-IronPort-AV: E=Sophos;i="6.07,161,1708416000"; d="scan'208";a="10582622" 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:06:04 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.07,161,1708416000"; d="scan'208";a="17035501" 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:06:02 -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 02/10] gdb/symtab: add lookup for trampoline functions Date: Thu, 28 Mar 2024 13:05:20 +0100 Message-Id: <20240328120528.30382-3-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 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+patchwork=sourceware.org@sourceware.org From: Nils-Christian Kempke In order to query 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. 2024-03-28 Nils-Christian Kempke --- gdb/symtab.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/symtab.h | 14 +++++++++++ 2 files changed, 83 insertions(+) diff --git a/gdb/symtab.c b/gdb/symtab.c index 86603dfebc3..831a58a9aff 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -73,6 +73,7 @@ #include "gdbsupport/pathstuff.h" #include "gdbsupport/common-utils.h" #include +#include "gdbsupport/symbol.h" /* Forward declarations for local functions. */ @@ -4205,6 +4206,74 @@ 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_NAME) + { + /* Handle both the mangled and demangled PHYSNAME. */ + const char *physname = trampoline->target_name (); + + /* First, check whether there exists a symbol matching the + physname. If we cannot find one also check for minimal + symbols. */ + const block *blk = block_for_pc (pc); + struct block_symbol bs = lookup_symbol (physname, blk, + SEARCH_VAR_DOMAIN, 0); + if (bs.symbol != nullptr) + { + const struct block *block = bs.symbol->value_block (); + gdb_assert (block != nullptr); + target_address = block->start (); + } + else + { + if (find_minimal_symbol_address (physname, &target_address, + nullptr) != 0) + target_address = 0; + } + } + else if (trampoline->target_kind () == TRAMPOLINE_TARGET_ADDR) + { + /* 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 = \ + ( (CORE_ADDR) trampoline->target_addr () + + sym->objfile ()->section_offsets[sym->section_index ()]); + } + } + + return target_address; +} /* 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 bf9a3cfb79f..c60485dc6d3 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -2354,6 +2354,20 @@ extern const struct gnu_ifunc_fns *gnu_ifunc_fns_p; extern CORE_ADDR find_solib_trampoline_target (const frame_info_ptr &, CORE_ADDR); +/* Return whether 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. */ From patchwork Thu Mar 28 12:05:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abdul Basit Ijaz X-Patchwork-Id: 87763 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6C9DC3858410 for ; Thu, 28 Mar 2024 12:07:17 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) by sourceware.org (Postfix) with ESMTPS id E28303858410 for ; Thu, 28 Mar 2024 12:06:13 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E28303858410 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 E28303858410 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=1711627581; cv=none; b=Ei3ussXl7GiLGNnu1RYxjIGaIcu7RNbgcMSkWjzO/IutzNe0Z3hojNl95Hg7sc03iQtnf+IHPBSmc9zVgurqSN36cb7/aHSwqLnqmY6p3vwtLKRzsOFIOIbsCT9v8SnZ5IKRFOakIAG+C/eCT/8+OSMGgkLfhApeFQ1s3LQs5aY= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1711627581; c=relaxed/simple; bh=eICrVvOGhgpMIXZB8EpgR0mIHBXITJsbecv3Au1tiaU=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=sgfId9dF545i4Bc20ndDZRiUnzonWou/d4DvUM3EErFR+02KewRhysjcD6jzxY+jah+SQSsfpCtvIT4KzPq07KS+pY7LORyVPOtOePqU4vNCA++c0bDiqkM1ae8LxaEAD9gqMaUQ7T/GCWY2T64vanjABVNiuAGuZ8YM56SHTNQ= 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=1711627574; x=1743163574; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=eICrVvOGhgpMIXZB8EpgR0mIHBXITJsbecv3Au1tiaU=; b=i3LY041k7GCKjFzs3TL+2KG1hq3/GYCNZ31iI0gNkJgtJuL2yqbgMw4r NEY8GBDrhkDvFDT0uivEZVnWUZUTLfHXjLOqvW7qELrf0sgDLUxwqWlXs 9Hv3j6yPrzUePN8q4JGMxE0eSHobIwnXc3layyCZcdhgiWGPLI1oz7WkO 7fu99mKFa+Nu/EfnuLNScmvbwNgdKDaN6OBBIthqSgU4UZ03QNuDyqpDO GA/3COu1XWy6NE9pZFhZm0A7dr5lk73YIhv5VE4+565AnaJ3gdVNzmZgw a8YYJfHk48lww1PsyUb1/P0AYZERNlwAwmxtJpoHZpTdiL8PUon73AW88 A==; X-CSE-ConnectionGUID: BVDG1icZQW6NmxNTEed+0Q== X-CSE-MsgGUID: 96XYoQj5TTuVRTOHJtMMWg== X-IronPort-AV: E=McAfee;i="6600,9927,11026"; a="10582644" X-IronPort-AV: E=Sophos;i="6.07,161,1708416000"; d="scan'208";a="10582644" 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:06:12 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.07,161,1708416000"; d="scan'208";a="17035545" 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:06:10 -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 03/10] gdb: handle stepping through functions with DW_AT_trampoline Date: Thu, 28 Mar 2024 13:05:21 +0100 Message-Id: <20240328120528.30382-4-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 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, KAM_SHORT, 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+patchwork=sourceware.org@sourceware.org From: Nils-Christian Kempke 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-08-09 Nils-Christian Kempke * 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-08-09 Nils-Christian Kempke * gdb.texinfo: Add section on skip-trampoline-functions setting. gdb/testsuite/ChangeLog: 2022-08-09 Nils-Christian Kempke * gdb.dwarf2/dw2-function-trampolines.c: New test source. * gdb.dwarf2/dw2-function-trampolines.exp: New test case. 2024-03-28 Nils-Christian Kempke Reviewed-By: Eli Zaretskii Reviewed-By: Eli Zaretskii --- gdb/NEWS | 11 + gdb/doc/gdb.texinfo | 35 +++ gdb/infrun.c | 87 ++++++- gdb/infrun.h | 5 + .../gdb.dwarf2/dw2-function-trampolines.c | 80 ++++++ .../gdb.dwarf2/dw2-function-trampolines.exp | 245 ++++++++++++++++++ 6 files changed, 459 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 feb3a37393a..da0d936ff70 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -892,6 +892,17 @@ platform. * New commands +set skip-trampoline-functions on|off +show skip-trampoline-functions + This setting is 'on' by default. When 'on' it controls whether GDB will + recognize function calls that have been marked as trampolines in the debug + info. It improves stepping behavior in that it steps over the trampoline + code and hides it from the user. Currently, only DWARF trampolines are + supported. + + If this is turned off, GDB gdb will handle trampoline functions the same + as any other function. + 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 727f9275bfb..19fecd00480 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -6445,6 +6445,41 @@ 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. + +The default is @code{on} and it will cause @value{GDBN} 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, 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 step over 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. 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 @value{GDBN} to completely ignore any trampoline information a compiler +might have emitted in its debug info. Trampolines will be treated like any +other normal function. + +@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 a5030b16376..a669798f5b8 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -187,6 +187,12 @@ get_previous_thread () 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, @@ -7863,7 +7869,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"); @@ -7935,8 +7940,47 @@ 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) + { + if (execution_direction == EXEC_REVERSE) + { + keep_going (ecs); + return; + } + + real_stop_pc = find_function_trampoline_target (stop_pc); + + for (int i = 0; i < MAX_TRAMPOLINE_CHAIN_SIZE + && 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) @@ -7957,6 +8001,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 @@ -7965,7 +8011,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)) @@ -8118,6 +8166,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 @@ -10391,6 +10452,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) @@ -10736,6 +10805,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 functions and inlined functions\n\ +marked as trampolines by the compiler. If off, gdb will ignore such function\n\ +trampolines."), + 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/infrun.h b/gdb/infrun.h index 5f83ca2b4c3..ea1ec134c7c 100644 --- a/gdb/infrun.h +++ b/gdb/infrun.h @@ -76,6 +76,11 @@ infrun_debug_show_threads (const char *title, ThreadRange threads) } +/* Maximum size of trampoline chain to process while resolving + trampolines. This avoids infinite loops for malformed debug + information. */ +#define MAX_TRAMPOLINE_CHAIN_SIZE 10 + /* Nonzero if we want to give control to the user when we're notified of shared library events by the dynamic linker. */ extern int stop_on_solib_events; 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 . */ + +/* 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 . + +# 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" +} From patchwork Thu Mar 28 12:05:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Abdul Basit Ijaz X-Patchwork-Id: 87764 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 332683858424 for ; Thu, 28 Mar 2024 12:07:41 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) by sourceware.org (Postfix) with ESMTPS id 752D33858435 for ; Thu, 28 Mar 2024 12:06:21 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 752D33858435 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 752D33858435 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=1711627585; cv=none; b=qjOXvsyWTbNMj4kJhCtJNq7o83+cmqUJwuBDkDxi7YjRthNy5mZjZ4IlXISM0PeFJ/15VQUdGjsXEjxCXX1V2YHY8mqUcHaYA7lta5XPSnu42E7uvbjezAejOyT15bb1ExhA3jUS5J3BZaQFTv0xbC6NYZjygWjEqU3aS6v6wtM= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1711627585; c=relaxed/simple; bh=a+t5F2XpqgoZqnIy7Agtf0x0hw28TZlXEw8uALJpTvw=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=FF2eJGT4Z6k8osJLCiNqme0pE7pmpTC7HA6Ougo8n47i4bR3POu4O/y1CCYVhO1P3QyRvyN9JY2z0lyqmhXSjh3305GmGwrlv0ovjkzyTge1nNLZiufIrK+iBELjfmaqosReDTKaZSTIOUj7l5wZlm8zU54FGO654zJKKczSJRw= 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=1711627581; x=1743163581; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=a+t5F2XpqgoZqnIy7Agtf0x0hw28TZlXEw8uALJpTvw=; b=HMi4/yf9atICZxayBMKHzlaDF5Q9tsfugvYfgW7Ozd3f5P7FlOr52ofx Y+KsSO6WnGDrHCVoVTe/FVbTfpHeM/s2zd0ic4AXMGmwPAjXkyZElk6a6 2OdpytP5/HCKDN+/9iGqHNaoIQEcBbYUshlMjhwOOjjo3ZulEwe8Cwzdj C70LSkjhCs5V2JrCZuZ1CWrCA0iGGjIwe7BUQElft44SoFHYuPLcLEd7/ k+leW5RwVNlsOfPc/TRoCoxxG6Fum8+8JzuX9eaiVNBw8z6We9qkNNmWN y+TDyBj0g6ueBUEUqszVBHzLXaGgU7IKI52Il7d1ZzZE1UrFqs4wY1Az7 A==; X-CSE-ConnectionGUID: l/fvv2eNRfCasc3uTvQBUQ== X-CSE-MsgGUID: T8bwAsTrQESMilEEZjyi+A== X-IronPort-AV: E=McAfee;i="6600,9927,11026"; a="10582671" X-IronPort-AV: E=Sophos;i="6.07,161,1708416000"; d="scan'208";a="10582671" 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:06:20 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.07,161,1708416000"; d="scan'208";a="17035576" 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:06:19 -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 Subject: [PATCH v6 04/10] gdb: Skip trampoline frames for the backtrace command. Date: Thu, 28 Mar 2024 13:05:22 +0100 Message-Id: <20240328120528.30382-5-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 X-Spam-Status: No, score=-10.9 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, 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+patchwork=sourceware.org@sourceware.org From: "Ijaz, Abdul B" This change filters trampoline functions when the option 'skip-trampoline-functions' is set to 'on' for the backtrace command. Before the change, GDB prints the frames indicated by the compiler with DIE "DW_AT_trampoline" in the backtrace, but for better user experience, all such frames can be hidden from the user. The test 'gdb.fortran/mixed-lang-stack' test used to fail for the IFX compiler because of extra trampoline frames in the backtrace. After the commit, those trampoline frames are filtered and test is updated accordingly. Extra trampoline frames: bt -frame-arguments all ''' \#8 0x0000000000405535 in mixed_func_1b_.t86p.t87p.t88p.t89p.t90p.t91p.t3v () \#10 0x0000000000405439 in mixed_func_1a_.void () at mixed-lang-stack.f90:33 ''' (gdb) FAIL: gdb.fortran/mixed-lang-stack.exp: lang=auto: bt -frame-arguments all In this example the IFX compiler emits "DW_AT_trampoline" tag for the 'first' and 'second' trampoline functions like following: function second (x, y) result(z) integer, intent(in) :: x, y integer :: z z = x * y ! breakpt-backtrace end function second function first (num1, num2) result(total) integer, intent(in) :: num1, num2 integer :: total total = second (num1 + 4, num2 * 3) ! first-breakpt total = total + 30 end function first Related Dwarf: 0x0000013f: DW_TAG_subprogram DW_AT_low_pc (0x0000000000404350) DW_AT_high_pc (0x000000000040435f) DW_AT_frame_base (DW_OP_reg6 RBP) DW_AT_linkage_name ("second_.t74p.t75p") DW_AT_name ("second_.t74p.t75p") DW_AT_trampoline ("second_") 0x0000015a: DW_TAG_subprogram DW_AT_low_pc (0x00000000004044a0) DW_AT_high_pc (0x00000000004044af) DW_AT_frame_base (DW_OP_reg6 RBP) DW_AT_linkage_name ("first_.t104p.t105p") DW_AT_name ("first_.t104p.t105p") DW_AT_trampoline ("first_") Before this change, the backtrace command output looks like: ''' (gdb) backtrace 3 \#0 second (x=20, y=9) at test.f90:4 \#1 0x0000000000405209 in second_.t74p.t75p () at test.f90:12 \#2 0x00000000004051e3 in first (num1=16, num2=3) at test.f90:10 (gdb) backtrace -3 \#2 0x00000000004051e3 in first (num1=16, num2=3) at test.f90:10 \#3 0x0000000000405309 in first_.t95p.t96p () at test.f90:21 \#4 0x0000000000405234 in func_trampoline () at test.f90:17 ''' After the change: ''' (gdb) backtrace 3 \#0 second (x=20, y=9) at test.f90:4 \#2 0x00000000004051e3 in first (num1=16, num2=3) at test.f90:10 \#4 0x0000000000405234 in func_trampoline () at test.f90:17 (gdb) backtrace -3 \#2 0x00000000004051e3 in first (num1=16, num2=3) at test.f90:10 \#4 0x0000000000405234 in func_trampoline () at test.f90:17 ''' The test gdb.fortran/func-trampoline.exp is added for testing the change. 2024-03-28 Abdul Basit Ijaz --- gdb/NEWS | 5 +- gdb/doc/gdb.texinfo | 6 ++ gdb/infrun.c | 8 +- gdb/infrun.h | 6 ++ gdb/stack.c | 8 ++ gdb/symtab.c | 12 +++ gdb/symtab.h | 5 ++ gdb/testsuite/gdb.fortran/func-trampoline.exp | 77 +++++++++++++++++++ gdb/testsuite/gdb.fortran/func-trampoline.f90 | 39 ++++++++++ .../gdb.fortran/mixed-lang-stack.exp | 10 ++- 10 files changed, 167 insertions(+), 9 deletions(-) create mode 100644 gdb/testsuite/gdb.fortran/func-trampoline.exp create mode 100644 gdb/testsuite/gdb.fortran/func-trampoline.f90 diff --git a/gdb/NEWS b/gdb/NEWS index da0d936ff70..025f2e1a17e 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -897,8 +897,9 @@ show skip-trampoline-functions This setting is 'on' by default. When 'on' it controls whether GDB will recognize function calls that have been marked as trampolines in the debug info. It improves stepping behavior in that it steps over the trampoline - code and hides it from the user. Currently, only DWARF trampolines are - supported. + code and hides it from the user. It improves the printing of the stack by + hiding trampoline functions from the backtrace. Currently, only DWARF + trampolines are supported. If this is turned off, GDB gdb will handle trampoline functions the same as any other function. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 19fecd00480..6117f6e889f 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -6472,6 +6472,12 @@ execution until leaving the trampoline region. 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. +When issuing a @code{backtrace}, if @code{skip-trampoline-functions} is set, +@value{GDBN} will skip trampoline frames while printing the stack. + +Currently, only DWARF trampolines marked via DW_AT_trampoline are supported by +this. + @item set skip-trampoline-functions off Causes @value{GDBN} to completely ignore any trampoline information a compiler might have emitted in its debug info. Trampolines will be treated like any diff --git a/gdb/infrun.c b/gdb/infrun.c index a669798f5b8..1c5711b8c41 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -191,7 +191,7 @@ static bool detach_fork = true; DW_AT_trampoline by the compiler. If false, GDB will ignore the attribute. */ -static bool skip_trampoline_functions = true; +bool skip_trampoline_functions = true; bool debug_infrun = false; static void @@ -10809,9 +10809,9 @@ Options are 'forward' or 'reverse'."), &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 functions and inlined functions\n\ -marked as trampolines by the compiler. If off, gdb will ignore such function\n\ -trampolines."), +If on, gdb will skip through functions and inlined functions marked as\n\ +trampolines by the compiler. If off, gdb will handle trampoline functions\n\ +the same way as any other function."), nullptr, show_skip_trampoline_functions, &setlist, &showlist); diff --git a/gdb/infrun.h b/gdb/infrun.h index ea1ec134c7c..fbe88ad4595 100644 --- a/gdb/infrun.h +++ b/gdb/infrun.h @@ -107,6 +107,12 @@ extern bool non_stop; starting an inferior. */ extern bool disable_randomization; +/* If set (default) GDB will step through functions/inlined subroutines marked + DW_AT_trampoline by the compiler. If false, GDB will ignore the + attribute. */ + +extern bool skip_trampoline_functions; + /* Returns a unique identifier for the current stop. This can be used to tell whether a command has proceeded the inferior past the current location. */ diff --git a/gdb/stack.c b/gdb/stack.c index 9c679222708..6a25054673f 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -2065,6 +2065,14 @@ backtrace_command_1 (const frame_print_options &fp_opts, { QUIT; + if (skip_trampoline_functions && in_trampoline_frame (fi)) + { + /* Trampoline frames are not printed so they are not counted in + the backtrace limit. */ + count++; + continue; + } + /* Don't use print_stack_frame; if an error() occurs it probably means further attempts to backtrace would fail (on the other hand, perhaps the code does or could be fixed to make sure diff --git a/gdb/symtab.c b/gdb/symtab.c index 831a58a9aff..8f509663d9f 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -4220,6 +4220,18 @@ in_trampoline_function (CORE_ADDR pc) /* See symtab.h. */ +bool +in_trampoline_frame (frame_info_ptr fi) +{ + CORE_ADDR pc; + if (get_frame_pc_if_available (fi, &pc)) + return in_trampoline_function (pc); + + return false; +} + +/* See symtab.h. */ + CORE_ADDR find_function_trampoline_target (CORE_ADDR pc) { diff --git a/gdb/symtab.h b/gdb/symtab.h index c60485dc6d3..234171ed404 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -2359,6 +2359,11 @@ extern CORE_ADDR find_solib_trampoline_target (const frame_info_ptr &, CORE_ADDR extern bool in_trampoline_function (CORE_ADDR pc); +/* Return whether or not the pc of the current frame is within a block that + belongs to a function that is marked as a trampoline by the compiler. */ + +extern bool in_trampoline_frame (frame_info_ptr); + /* 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 diff --git a/gdb/testsuite/gdb.fortran/func-trampoline.exp b/gdb/testsuite/gdb.fortran/func-trampoline.exp new file mode 100644 index 00000000000..bfa0002cf0e --- /dev/null +++ b/gdb/testsuite/gdb.fortran/func-trampoline.exp @@ -0,0 +1,77 @@ +# Copyright 2024 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 . + +# Test "backtrace" and "backtrace -n" commands for functions with trampoline +# calls. + +require allow_fortran_tests + +if {![test_compiler_info {ifx-*} f90]} { + untested "This test is only applicable for IFX, which emits the\ + trampoline DIE in Dwarf." + return -1 +} + +standard_testfile ".f90" +load_lib fortran.exp + +# Initialize the test by running the program to the innermost +# function name "second". + +proc init_test {} { + global binfile srcfile inner_loc + + clean_restart ${binfile} + if {![fortran_runto_main]} { + return -1 + } + + # Set breakpoint inside the innermost function 'second'. + gdb_breakpoint "$srcfile:$inner_loc" + gdb_continue_to_breakpoint "innermost-body" ".*$srcfile:$inner_loc.*" +} + +if {[build_executable "failed to prepare" ${testfile} ${srcfile} \ + {debug f90}]} { + return -1 +} + +set inner_loc [gdb_get_line_number "second-breakpt"] +set middle_loc [gdb_get_line_number "first-breakpt"] +set outer_loc [gdb_get_line_number "main-outer-loc"] +set fill "\[^\r\n\]*" + +set inner_desc "second \\(x=20, y=9\\) at ${fill}$srcfile:$inner_loc" +set middle_desc "first \\(num1=16, num2=3\\) at ${fill}$srcfile:$middle_loc" +set outer_desc ".* at .*$srcfile:$outer_loc" + +with_test_prefix "backtrace" { + init_test + + # Limit the backtrace to 3 frames and ensure both frames for first + # and second function are shown only and trampoline frames are filtered. + gdb_test "backtrace 3" [multi_line \ + "#$decimal.* $inner_desc" \ + "#$decimal.* $middle_desc" \ + "#$decimal.* $outer_desc.*"] +} + +with_test_prefix "backtrace outerframes" { + init_test + + gdb_test "backtrace -3" [multi_line \ + "#$decimal.* $middle_desc" \ + "#$decimal.* $outer_desc.*"] +} diff --git a/gdb/testsuite/gdb.fortran/func-trampoline.f90 b/gdb/testsuite/gdb.fortran/func-trampoline.f90 new file mode 100644 index 00000000000..10eb3f5188f --- /dev/null +++ b/gdb/testsuite/gdb.fortran/func-trampoline.f90 @@ -0,0 +1,39 @@ +! Copyright 2024 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 . + +! Source code for func-trampoline.exp. + +integer(kind=4) function second(x, y) + integer(kind=4), intent(in) :: x + integer(kind=4), intent(in) :: y + + second = x * y ! second-breakpt +end function + +integer(kind=4) function first(num1, num2) + integer(kind=4), intent(in) :: num1 + integer(kind=4), intent(in) :: num2 + + first = second (num1 + 4, num2 * 3) ! first-breakpt +end function + +program func_trampoline + integer(kind=4) :: total + + total = first(16, 3) ! main-outer-loc + + write(*,*) "Result is ", total, "\n" + ! Expected: 180 +end program func_trampoline diff --git a/gdb/testsuite/gdb.fortran/mixed-lang-stack.exp b/gdb/testsuite/gdb.fortran/mixed-lang-stack.exp index eef84da0e44..4591880ca7b 100644 --- a/gdb/testsuite/gdb.fortran/mixed-lang-stack.exp +++ b/gdb/testsuite/gdb.fortran/mixed-lang-stack.exp @@ -41,7 +41,7 @@ set have_index [exec_has_index_section $binfile] # value to pass to GDB's 'set language ...' command. proc run_tests { lang } { with_test_prefix "lang=${lang}" { - global binfile hex have_index + global binfile hex have_index decimal clean_restart ${binfile} @@ -63,6 +63,10 @@ proc run_tests { lang } { set e_arg "\['\"\]abcdef\['\"\]" set 1b_args "\[^\r\n\]+$e_arg\[^\r\n\]+" set 1g_args "obj=\[^\r\n\]+" + # Generic decimal number is checked in regex for Frame #8 and #9 to + # handle filtered trampoline frames. Since Frame#8 and Frame#10 are + # set to trampoline in DWARF by Intel® Fortran Compiler (ifx), they + # are not shown by the backtrace command. set bt_stack \ [multi_line \ "#0\\s+breakpt \\(\\) at \[^\r\n\]+" \ @@ -73,8 +77,8 @@ proc run_tests { lang } { "#5\\s+$hex in mixed_func_1d \\(\[^\r\n\]+\\) at \[^\r\n\]+" \ "#6\\s+$hex in mixed_func_1c \\(\[^\r\n\]+\\) at \[^\r\n\]+" \ "#7\\s+$hex in mixed_func_1b \\($1b_args\\) at \[^\r\n\]+" \ - "#8\\s+$hex in mixed_func_1a \\(\\) at \[^\r\n\]+" \ - "#9\\s+$hex in mixed_stack_main \\(\\) at \[^\r\n\]+" ] + "#$decimal\\s+$hex in mixed_func_1a \\(\\) at \[^\r\n\]+" \ + "#$decimal\\s+$hex in mixed_stack_main \\(\\) at \[^\r\n\]+" ] set main_args "argc=1, argv=${hex}( \[^\r\n\]+)?" set bt_stack_kfail \ [multi_line \ From patchwork Thu Mar 28 12:05:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abdul Basit Ijaz X-Patchwork-Id: 87765 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D81D1385840B for ; Thu, 28 Mar 2024 12:07:49 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.10]) by sourceware.org (Postfix) with ESMTPS id DC5AF3858D38 for ; Thu, 28 Mar 2024 12:06:30 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org DC5AF3858D38 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 DC5AF3858D38 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=192.198.163.10 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1711627602; cv=none; b=qu2cLvyicnbhrboJCFoRojSVY+a0d9TnUx0GaFVlNmoaRztLXcSzpnnqDh2A4eY63IkM5aWy9vlaXbJf8L0zsGUDjrxDd1XIlKUp2ST+Q9Ywl8n9xKBMoZZI2c3U5o3d/YOaz6Ys9KJrUwBnmMdPNKWq97yUDhTMkIejl+oskec= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1711627602; c=relaxed/simple; bh=rka6ZPDwEqtHJ6Cj6AuNqjlf7Zlr8heRaL7QTmdcT/4=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=fFRO7DOiMKvKgfnpwEdItnQMKR8ptZAI3ZaRENBj4eX9y2KOdShA/u8AirsiTynp9RZyq6vm5SBrsSCLI7t/Puwel4VWV7uLjuldKAmQe9fjPokwYmFk5qRJ6iBJ2wQBu7A0FsXD9+HymB9UnQzp5YB0mErJ7kV6KuOP8Le3erI= 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=1711627591; x=1743163591; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=rka6ZPDwEqtHJ6Cj6AuNqjlf7Zlr8heRaL7QTmdcT/4=; b=CaLA8nhPL6azqMHE7rbPiJwqnfmrAi1QUhoLKY06k8XwHdQZQ8Lh59Xv oiaVXTwZs2aOk3Kl1IhsBB1ugSqHBog90U0BF5o1NiTBOO/oDtTsi72tJ nC1N9N+Cil4zuNrUq2gwKldwTEBn9VIx/3WWM0Vc0xor+0H/7KdUirgaA NJvpnYPkvGcXfALbBOX2VRsVONgg+7QC/OSc8D6kJ1Me55RV7Q4RM/LBZ KwEWdjI9XZzeov2MdXN3RBdB5OKdm48ILiKfDmTpN1HmS2aYMHdxUP0zZ VgEx3HJfllvTEjQsXj9HNAZ6f0vQ2c0aQkJDx/bQfCtdvU58cX/oMHcfb g==; X-CSE-ConnectionGUID: BxXOJYI+QbmOcV7MKhJ8ig== X-CSE-MsgGUID: LlqCbFUDQoWg+GTgRcKEIA== X-IronPort-AV: E=McAfee;i="6600,9927,11026"; a="18158620" X-IronPort-AV: E=Sophos;i="6.07,161,1708416000"; d="scan'208";a="18158620" Received: from fmviesa001.fm.intel.com ([10.60.135.141]) by fmvoesa104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Mar 2024 05:06:30 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.07,161,1708416000"; d="scan'208";a="47816090" Received: from abijaz-mobl2.ger.corp.intel.com (HELO localhost) ([10.246.42.1]) by smtpauth.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Mar 2024 05:06:28 -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 Subject: [PATCH v6 05/10] gdb: Skip trampoline functions for the finish and reverse-finish commands. Date: Thu, 28 Mar 2024 13:05:23 +0100 Message-Id: <20240328120528.30382-6-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 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, KAM_SHORT, 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+patchwork=sourceware.org@sourceware.org From: "Ijaz, Abdul B" This change skips trampoline functions when the option 'skip-trampoline-functions' is set to 'on' for the finish or reverse-finish command. Before this change, for these commands GDB returns to the trampoline function indicated by the compiler with DIE "DW_AT_trampoline". For better user experience, all such frames can be hidden from the user. In this example the IFX compiler emits "DW_AT_trampoline" tag for the 'first' and 'second' trampoline functions like following: function second (x, y) result(z) integer, intent(in) :: x, y integer :: z z = x * y ! breakpt-finish end function second function first (num1, num2) result(total) integer, intent(in) :: num1, num2 integer :: total total = second (num1 + 4, num2 * 3) ! first-breakpt total = total + 30 end function first Related Dwarf: 0x0000013f: DW_TAG_subprogram DW_AT_low_pc (0x0000000000404350) DW_AT_high_pc (0x000000000040435f) DW_AT_frame_base (DW_OP_reg6 RBP) DW_AT_linkage_name ("second_.t74p.t75p") DW_AT_name ("second_.t74p.t75p") DW_AT_trampoline ("second_") 0x0000015a: DW_TAG_subprogram DW_AT_low_pc (0x00000000004044a0) DW_AT_high_pc (0x00000000004044af) DW_AT_frame_base (DW_OP_reg6 RBP) DW_AT_linkage_name ("first_.t104p.t105p") DW_AT_name ("first_.t104p.t105p") DW_AT_trampoline ("first_") Before this change, the finish command output looks like: ''' (gdb) finish Run till exit from #0 second (x=20, y=9) at test.f90:4 0x0000000000405209 in second_.t74p.t75p () at test.f90:12 12 end function first Value returned is $1 = 180 ''' The reverse-finish command output in this test before the change: ''' (gdb) reverse-finish Run back to call of #0 second (x=20, y=9) at test.f90:4 0x0000000000405204 in second_.t74p.t75p () at test.f90:12 12 end function first ''' After this change: ''' (gdb) finish Run till exit from #0 second (x=20, y=9) at test.f90:4 0x00000000004051e3 in first (num1=16, num2=3) at test.f90:10 10 total = second (num1 + 4, num2 * 3) ! first-breakpt Value returned is $1 = 180 (gdb) reverse-finish Run back to call of #0 second (x=20, y=9) at test.f90:4 0x00000000004051de in first (num1=16, num2=3) at test.f90:10 10 total = second (num1 + 4, num2 * 3) ! first-breakpt ''' The test gdb.fortran/func-trampoline.exp is updated for testing the finish command. The test gdb.reverse/finish-reverse-trampoline.exp is added for testing the reverse-finish command. 2024-03-28 Ijaz, Abdul B Reviewed-By: Eli Zaretskii --- gdb/NEWS | 5 +- gdb/doc/gdb.texinfo | 4 ++ gdb/infcmd.c | 12 ++++ gdb/infrun.c | 8 +++ gdb/infrun.h | 5 ++ gdb/testsuite/gdb.fortran/func-trampoline.exp | 13 ++++- .../gdb.reverse/finish-reverse-trampoline.exp | 56 +++++++++++++++++++ 7 files changed, 99 insertions(+), 4 deletions(-) create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-trampoline.exp diff --git a/gdb/NEWS b/gdb/NEWS index 025f2e1a17e..b8577c58af7 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -898,8 +898,9 @@ show skip-trampoline-functions recognize function calls that have been marked as trampolines in the debug info. It improves stepping behavior in that it steps over the trampoline code and hides it from the user. It improves the printing of the stack by - hiding trampoline functions from the backtrace. Currently, only DWARF - trampolines are supported. + hiding the trampoline frames from the backtrace and skips trampoline + functions while returning from the target function of a trampoline call. + Currently, only DWARF trampolines are supported. If this is turned off, GDB gdb will handle trampoline functions the same as any other function. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 6117f6e889f..5782e06b91d 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -6475,6 +6475,10 @@ DWARF trampolines marked via DW_AT_trampoline are supported by this. When issuing a @code{backtrace}, if @code{skip-trampoline-functions} is set, @value{GDBN} will skip trampoline frames while printing the stack. +When issuing a @code{finish} or @code{reverse-finish}, if +@code{skip-trampoline-functions} is set, @value{GDBN} will skip trampoline +frames while returning from the target function. + Currently, only DWARF trampolines marked via DW_AT_trampoline are supported by this. diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 600c90c055a..cd9baa03ecd 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -1801,6 +1801,18 @@ finish_command (const char *arg, int from_tty) if (frame == 0) error (_("\"finish\" not meaningful in the outermost frame.")); + if (skip_trampoline_functions) + { + for (int i = 0; (SAFE_TRAMPOLINE_CHAIN (i, frame) + && in_trampoline_frame (frame)); ++i) + frame = get_prev_frame (frame); + + if (frame == nullptr) + error (_("\"finish\" not meaningful in the outermost non-trampoline \ +frame. Consider running \"set skip-trampoline-functions off\", to stop in \ +trampoline frames for the \"finish\" command.")); + } + clear_proceed_status (0); tp = inferior_thread (); diff --git a/gdb/infrun.c b/gdb/infrun.c index 1c5711b8c41..5419d58bf3b 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -8095,6 +8095,14 @@ process_event_stop_test (struct execution_control_state *ecs) keep_going (ecs); return; } + else if (skip_trampoline_functions && in_trampoline_function (stop_pc)) + { + /* While reverse stepping if we are in a trampoline function call + we will just continue single step in the hope of leaving the + trampoline again soon. */ + keep_going (ecs); + return; + } } /* This always returns the sal for the inner-most frame when we are in a diff --git a/gdb/infrun.h b/gdb/infrun.h index fbe88ad4595..3873cca7619 100644 --- a/gdb/infrun.h +++ b/gdb/infrun.h @@ -81,6 +81,11 @@ infrun_debug_show_threads (const char *title, ThreadRange threads) information. */ #define MAX_TRAMPOLINE_CHAIN_SIZE 10 +/* True if the trampoline index "i" is less then the maximum allowed size + of a trampoline chain. */ +#define SAFE_TRAMPOLINE_CHAIN(i, frame) \ + (i < MAX_TRAMPOLINE_CHAIN_SIZE && (frame != nullptr)) + /* Nonzero if we want to give control to the user when we're notified of shared library events by the dynamic linker. */ extern int stop_on_solib_events; diff --git a/gdb/testsuite/gdb.fortran/func-trampoline.exp b/gdb/testsuite/gdb.fortran/func-trampoline.exp index bfa0002cf0e..4cb9e4f4919 100644 --- a/gdb/testsuite/gdb.fortran/func-trampoline.exp +++ b/gdb/testsuite/gdb.fortran/func-trampoline.exp @@ -13,8 +13,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -# Test "backtrace" and "backtrace -n" commands for functions with trampoline -# calls. +# Test "backtrace", "backtrace -n" and "finish" commands for functions with +# trampoline calls. require allow_fortran_tests @@ -75,3 +75,12 @@ with_test_prefix "backtrace outerframes" { "#$decimal.* $middle_desc" \ "#$decimal.* $outer_desc.*"] } + +with_test_prefix "finish" { + init_test + + gdb_test "finish" [multi_line \ + "Run till exit from #0 $fill second \\(x=20, y=9\\) $fill" \ + "${fill}first \\(num1=16, num2=3\\)${fill}" \ + "${fill}(\r\nValue returned is $valnum_re = 180)"] +} diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-trampoline.exp b/gdb/testsuite/gdb.reverse/finish-reverse-trampoline.exp new file mode 100644 index 00000000000..3a23a30ad0d --- /dev/null +++ b/gdb/testsuite/gdb.reverse/finish-reverse-trampoline.exp @@ -0,0 +1,56 @@ +# Copyright 2024 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 . + +# Test "reverse-finish" command for functions with trampoline. + +require supports_reverse allow_fortran_tests + +if {![test_compiler_info {ifx-*} f90]} { + untested "This test is only applicable for IFX, which emits the\ + trampoline DIE in Dwarf." + return -1 +} + +load_lib fortran.exp + +set testfile finish-reverse-trampoline +set srcfile "${srcdir}/gdb.fortran/func-trampoline.f90" +set binfile [standard_output_file $testfile] + +if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \ + {debug f90}]} { + return -1 +} + +if {![fortran_runto_main]} { + return -1 +} + +set inner_loc [gdb_get_line_number "second-breakpt"] + +if [supports_process_record] { + # Activate process record/replay + gdb_test_no_output "record" "turn on process record" +} + +# Set breakpoint inside the innermost function 'second'. +gdb_breakpoint "$srcfile:$inner_loc" +gdb_continue_to_breakpoint "innermost-body" ".*$srcfile:$inner_loc.*" + +gdb_test "reverse-finish" [multi_line \ + "Run back to call of #0 second \\(x=20, y=9\\).*" \ + ".*in first \\(num1=16, num2=3\\).*"] + +gdb_test "frame" "#0.*first.*" "Frame 0 shows first function" From patchwork Thu Mar 28 12:05:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abdul Basit Ijaz X-Patchwork-Id: 87766 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 116433858418 for ; Thu, 28 Mar 2024 12:08:33 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.10]) by sourceware.org (Postfix) with ESMTPS id 50E1B3858420 for ; Thu, 28 Mar 2024 12:06:38 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 50E1B3858420 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 50E1B3858420 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=192.198.163.10 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1711627602; cv=none; b=dxVcMOQ8n8QCMJwlQgeQI5QCROoPF5jbptMvM1BuuKxDYT/qfniYuhJc3MJNUb/WIDjZJewLre+Dt226RFAxcXRrpibHii7xJLWNgTu+TNDOsSN8AzgAuqgrwPvPsvhvvxBsAJa6waW70YvER7CJlxy+4+nNs9FnL4lkQELgYXY= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1711627602; c=relaxed/simple; bh=haA3YbJ/N6pgTzLf7pQFcsfddNVeUQ4mmlluiSHpTxE=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=fIesW60bQVTjFdGlwkrxGYVNAOHA/z8dGQqAe2/kauk9C7Sdook9TPK9FdA4kc0csZeGF9qQoBH/jeZCBybc2XMTobUfTquO5fwr225lIz9w5YgdCTtlC6zKt/DuPEmAdRcjxjI4d0m/lb7WGuNTslwUz6VbvjtJtjkpXvJU8xM= 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=1711627598; x=1743163598; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=haA3YbJ/N6pgTzLf7pQFcsfddNVeUQ4mmlluiSHpTxE=; b=RQZfX9AdQ742eQ6zm3DRgVcPa2+64tr+Id64ueIijCWEAFZw/raRR0qQ UChLfCWHoa2vVhMH6CFY2pF3Lau2Ge6nLRJN6pqON17D1v6TsVZ6wYZ5f ixWczLkWsK2ipqUBDd20AErJMA0phvUVUI8yFhhBU28cvOwEL5U41mDI1 kem+igWNQiSbWDvKIU9Tl7km0+wrXC78a/6qzG74u0CDI2yfY+Gz6uwLE 5iQlb9tGpadayc17QaLkc/b4CKFIuC0FiYN4fIHImy2KdYtPi//gkPpxw seNmLq6hnaAkrE1CaA36y14HPxK2qS85imfTLwAFbM/hX6sWIUA7i897O A==; X-CSE-ConnectionGUID: mSAgyG2rT96uPiMBrN6Xbg== X-CSE-MsgGUID: EG2L61B5SyW17N3UAUBk6A== X-IronPort-AV: E=McAfee;i="6600,9927,11026"; a="18158639" X-IronPort-AV: E=Sophos;i="6.07,161,1708416000"; d="scan'208";a="18158639" Received: from fmviesa001.fm.intel.com ([10.60.135.141]) by fmvoesa104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Mar 2024 05:06:37 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.07,161,1708416000"; d="scan'208";a="47816113" Received: from abijaz-mobl2.ger.corp.intel.com (HELO localhost) ([10.246.42.1]) by smtpauth.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Mar 2024 05:06:35 -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 Subject: [PATCH v6 06/10] gdb: Skip trampoline functions for the up command. Date: Thu, 28 Mar 2024 13:05:24 +0100 Message-Id: <20240328120528.30382-7-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 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, KAM_SHORT, 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+patchwork=sourceware.org@sourceware.org From: "Ijaz, Abdul B" This change skips trampoline functions when the option 'skip-trampoline-functions' is set to 'on' for the up command. Before this change, GDB processes trampoline functions indicated by the compiler with DIE "DW_AT_trampoline" and stops at the trampoline function for the 'up' command. For better user experience, all such frames can be skipped and hidden from the user. In this example the IFX compiler emits "DW_AT_trampoline" tag for the 'first' and 'second' trampoline functions like following: function second (x, y) result(z) integer, intent(in) :: x, y integer :: z z = x * y ! breakpt-up end function second function first (num1, num2) result(total) integer, intent(in) :: num1, num2 integer :: total total = second (num1 + 4, num2 * 3) ! first-breakpt total = total + 30 end function first Related Dwarf: 0x0000013f: DW_TAG_subprogram DW_AT_low_pc (0x0000000000404350) DW_AT_high_pc (0x000000000040435f) DW_AT_frame_base (DW_OP_reg6 RBP) DW_AT_linkage_name ("second_.t74p.t75p") DW_AT_name ("second_.t74p.t75p") DW_AT_trampoline ("second_") 0x0000015a: DW_TAG_subprogram DW_AT_low_pc (0x00000000004044a0) DW_AT_high_pc (0x00000000004044af) DW_AT_frame_base (DW_OP_reg6 RBP) DW_AT_linkage_name ("first_.t104p.t105p") DW_AT_name ("first_.t104p.t105p") DW_AT_trampoline ("first_") Before this change, the 'up' command output looks like: ''' (gdb) up \#1 0x0000000000405209 in second_.t74p.t75p () at test.f90:12 12 end function first ''' After this change: ''' (gdb) up \#2 0x00000000004051e3 in first (num1=16, num2=3) at test.f90:10 10 total = second (num1 + 4, num2 * 3) ! first-breakpt ''' The test gdb.fortran/func-trampoline.exp is updated for testing this change. 2024-03-28 Ijaz, Abdul B Reviewed-By: Eli Zaretskii --- gdb/doc/gdb.texinfo | 2 +- gdb/stack.c | 7 +++++++ gdb/testsuite/gdb.fortran/func-trampoline.exp | 12 ++++++++++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 5782e06b91d..222faba5da3 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -6475,7 +6475,7 @@ DWARF trampolines marked via DW_AT_trampoline are supported by this. When issuing a @code{backtrace}, if @code{skip-trampoline-functions} is set, @value{GDBN} will skip trampoline frames while printing the stack. -When issuing a @code{finish} or @code{reverse-finish}, if +When issuing a @code{finish}, @code{reverse-finish} or @code{up}, if @code{skip-trampoline-functions} is set, @value{GDBN} will skip trampoline frames while returning from the target function. diff --git a/gdb/stack.c b/gdb/stack.c index 6a25054673f..2071d98ffe6 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -2605,6 +2605,13 @@ find_relative_frame (frame_info_ptr frame, int *level_offset_ptr) { frame_info_ptr prev = get_prev_frame (frame); + if (skip_trampoline_functions) + { + for (int i = 0; (SAFE_TRAMPOLINE_CHAIN (i, prev) + && in_trampoline_frame (prev)); ++i) + prev = get_prev_frame (prev); + } + if (!prev) break; (*level_offset_ptr)--; diff --git a/gdb/testsuite/gdb.fortran/func-trampoline.exp b/gdb/testsuite/gdb.fortran/func-trampoline.exp index 4cb9e4f4919..e7e4c8ae7b0 100644 --- a/gdb/testsuite/gdb.fortran/func-trampoline.exp +++ b/gdb/testsuite/gdb.fortran/func-trampoline.exp @@ -13,8 +13,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -# Test "backtrace", "backtrace -n" and "finish" commands for functions with -# trampoline calls. +# Test "backtrace", "backtrace -n", "finish" and "up" commands for +# functions with trampoline calls. require allow_fortran_tests @@ -84,3 +84,11 @@ with_test_prefix "finish" { "${fill}first \\(num1=16, num2=3\\)${fill}" \ "${fill}(\r\nValue returned is $valnum_re = 180)"] } + +with_test_prefix "up" { + init_test + + gdb_test "up" [multi_line \ + "#$decimal.* $middle_desc" \ + "${fill}first = second \\(num1 \\+ 4, num2 \\* 3\\).*${fill}"] +} From patchwork Thu Mar 28 12:05:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abdul Basit Ijaz X-Patchwork-Id: 87767 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 5F3863858D1E for ; Thu, 28 Mar 2024 12:08:39 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.10]) by sourceware.org (Postfix) with ESMTPS id 0E9913858407 for ; Thu, 28 Mar 2024 12:06:45 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 0E9913858407 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 0E9913858407 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=192.198.163.10 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1711627616; cv=none; b=UmRG6Cee9a46POX+ovJzbH/cZ8rTi0gMQiJaXK8gdtLYcwzwh9zUNTCNnWog85iXHgT/qeEgjsi2Ol3g22NUfs1BkyjwPo3NFEyll8hNrsLgTrHinP43WP0oFXAI4e/QWvPP9gX8mQWTCup9Trkj0c8/zCnJx6aRfG6pFhxG0Is= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1711627616; c=relaxed/simple; bh=Dw7/VV+RSjxu21xvhjDINrNVnd6jO/63NuQqrNRaMnQ=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=o4Jvl1wp9B0+Afxtr5RDF+hGVoyknHp7xoOpG8yyLd6vDQXagNwdRwhAfK459V0yzwSv6gmZnRvpACw/bHhooj56aE/nyuM5hOlrVzfnDAeK6s4e8j6g2DMYIvM0+G+24z4IhVrb01d0DC2BUzvIBEScWFf/9gEX2SyB4bPHJnE= 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=1711627606; x=1743163606; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Dw7/VV+RSjxu21xvhjDINrNVnd6jO/63NuQqrNRaMnQ=; b=kmMBa8FGRANwLGSWHGTjNfpNBYKVGVlG2864xKrynETEg5aSjsYJqYoH Ma0gcVZHztkK9usbUDgNoeyfhPPUaSyyrr8GnMIp98tVeZjAMV1CpmoZD lR3cFyqd/+r9K1W67ZNe2TY8b5YeNDmfcyuzukSt5j3uTlqDnUOlTIXJO nu33iyrAILKfelrHwEwCwNkTv1jxcTJYgobHkb+QBr8yzE6A0M55Qv6u5 7j4gSf8Rz1Sdi6vRUIjHOYG2AalImeJZJi7fBTewVAsgaZ8qer5SbLLaL PiOiyD2WTEmLK5d5ooFBR5BXBYaVRc6/GTcIR2Gbe7iFStR45l15OEhmd A==; X-CSE-ConnectionGUID: wZWtlvrWRySx7i2hHM7vpg== X-CSE-MsgGUID: /RQpr/kIScCC1RRxI8yCSQ== X-IronPort-AV: E=McAfee;i="6600,9927,11026"; a="18158660" X-IronPort-AV: E=Sophos;i="6.07,161,1708416000"; d="scan'208";a="18158660" Received: from fmviesa001.fm.intel.com ([10.60.135.141]) by fmvoesa104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Mar 2024 05:06:45 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.07,161,1708416000"; d="scan'208";a="47816222" Received: from abijaz-mobl2.ger.corp.intel.com (HELO localhost) ([10.246.42.1]) by smtpauth.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Mar 2024 05:06:43 -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 Subject: [PATCH v6 07/10] gdb: Skip trampoline functions for the return command. Date: Thu, 28 Mar 2024 13:05:25 +0100 Message-Id: <20240328120528.30382-8-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 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, KAM_SHORT, 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+patchwork=sourceware.org@sourceware.org From: "Ijaz, Abdul B" This change skips trampoline functions for the return command when the option 'skip-trampoline-functions' is set to 'on'. Before this change, GDB processes trampoline functions indicated by the compiler with DIE "DW_AT_trampoline" for the return command and stops at the trampoline functions. For better user experience, all such frames can be skipped and hidden from the user. In this example the IFX compiler emits "DW_AT_trampoline" tag for the 'first' and 'second' trampoline functions like following: function second (x, y) result(z) integer, intent(in) :: x, y integer :: z z = x * y ! breakpt-return end function second function first (num1, num2) result(total) integer, intent(in) :: num1, num2 integer :: total total = second (num1 + 4, num2 * 3) ! first-breakpt total = total + 30 end function first Related Dwarf: 0x0000013f: DW_TAG_subprogram DW_AT_low_pc (0x0000000000404350) DW_AT_high_pc (0x000000000040435f) DW_AT_frame_base (DW_OP_reg6 RBP) DW_AT_linkage_name ("second_.t74p.t75p") DW_AT_name ("second_.t74p.t75p") DW_AT_trampoline ("second_") 0x0000015a: DW_TAG_subprogram DW_AT_low_pc (0x00000000004044a0) DW_AT_high_pc (0x00000000004044af) DW_AT_frame_base (DW_OP_reg6 RBP) DW_AT_linkage_name ("first_.t104p.t105p") DW_AT_name ("first_.t104p.t105p") DW_AT_trampoline ("first_") Before this change, the return command output looks like: ''' (gdb) return Make second return now? (y or n) y \#0 0x0000000000405209 in second_.t74p.t75p () at test.f90:12 12 end function first ''' After this change: ''' (gdb) return Make second return now? (y or n) y \#0 0x00000000004051e3 in first (num1=16, num2=3) at test.f90:10 10 total = second (num1 + 4, num2 * 3) ! first-breakpt ''' The test gdb.fortran/func-trampoline.exp is updated for testing this change. 2024-03-28 Ijaz, Abdul B Reviewed-By: Eli Zaretskii --- gdb/doc/gdb.texinfo | 6 +++--- gdb/stack.c | 11 +++++++++++ gdb/testsuite/gdb.fortran/func-trampoline.exp | 10 +++++++++- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 222faba5da3..a6f74373dfe 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -6475,9 +6475,9 @@ DWARF trampolines marked via DW_AT_trampoline are supported by this. When issuing a @code{backtrace}, if @code{skip-trampoline-functions} is set, @value{GDBN} will skip trampoline frames while printing the stack. -When issuing a @code{finish}, @code{reverse-finish} or @code{up}, if -@code{skip-trampoline-functions} is set, @value{GDBN} will skip trampoline -frames while returning from the target function. +When issuing a @code{finish}, @code{reverse-finish}, @code{up} or +@code{return}, if @code{skip-trampoline-functions} is set, @value{GDBN} will +skip trampoline frames while returning from the target function. Currently, only DWARF trampolines marked via DW_AT_trampoline are supported by this. diff --git a/gdb/stack.c b/gdb/stack.c index 2071d98ffe6..85deedce682 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -2836,6 +2836,17 @@ return_command (const char *retval_exp, int from_tty) if (get_frame_type (get_current_frame ()) == DUMMY_FRAME) frame_pop (get_current_frame ()); + if (skip_trampoline_functions) + { + frame_info_ptr ret_frame = get_current_frame (); + for (int i = 0; (SAFE_TRAMPOLINE_CHAIN (i, ret_frame) + && in_trampoline_frame (ret_frame)); ++i) + { + frame_pop (ret_frame); + ret_frame = get_current_frame (); + } + } + select_frame (get_current_frame ()); /* If interactive, print the frame that is now current. */ if (from_tty) diff --git a/gdb/testsuite/gdb.fortran/func-trampoline.exp b/gdb/testsuite/gdb.fortran/func-trampoline.exp index e7e4c8ae7b0..dd26e5ab035 100644 --- a/gdb/testsuite/gdb.fortran/func-trampoline.exp +++ b/gdb/testsuite/gdb.fortran/func-trampoline.exp @@ -13,7 +13,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -# Test "backtrace", "backtrace -n", "finish" and "up" commands for +# Test "backtrace", "backtrace -n", "finish", "up" and "return" commands for # functions with trampoline calls. require allow_fortran_tests @@ -92,3 +92,11 @@ with_test_prefix "up" { "#$decimal.* $middle_desc" \ "${fill}first = second \\(num1 \\+ 4, num2 \\* 3\\).*${fill}"] } + +with_test_prefix "return" { + init_test + + gdb_test "return" \ + ".*first = second \\(num1 \\+ 4, num2 \\* 3\\) \\! first-breakpt" \ + "" "Make second return now.*y or n. $" "y" +} From patchwork Thu Mar 28 12:05:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abdul Basit Ijaz X-Patchwork-Id: 87768 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id DF3483858433 for ; Thu, 28 Mar 2024 12:08:43 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) by sourceware.org (Postfix) with ESMTPS id 3155B3858CDB for ; Thu, 28 Mar 2024 12:06:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 3155B3858CDB 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 3155B3858CDB Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1711627630; cv=none; b=r+nDxA4fRKgsdOxqgI0Qno+E1QrWjcqMfnGDDQcec00wfUXA3hR+W0JBK/1S3iGJODSkIGqhEBDkoc3s/Jd5zlX9zjjH/Aup5I/I4Yo70R60bWKpOwwb0zIiC/wP/l9QRcQpUXNyqje9G37rjSxf1tKYFWWw5S9935JIK2sntpo= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1711627630; c=relaxed/simple; bh=eRen82/tbgxApaSjQFena0M4eMtmguc8BShwdQl+kCc=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=En5oTgNx5hYlJGWlAznGft02/dEFMVZFhsq2RRbR0m12F/K/nc5/j6CnQoOycF9mbb8IofQjOnEDI9QyNOBn3YUVBsDiYzA4vB3XB0EsQUBMAUfQke5j/B4AXOE21OCg3fW67DRbW+abytDx5JMBRXRYhr7wkeo5Xkr7SMBRfVU= 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=1711627614; x=1743163614; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=eRen82/tbgxApaSjQFena0M4eMtmguc8BShwdQl+kCc=; b=NrHTVFYRiTgFG1wiLJJWgUTfFL/OeK32BG7rK/A3sx2ZhMrYUCPq2S2X Gw14himfzVPz6kUeU1Ta0ggQpDEpV7FubzWU/Zoc5FhGWDwD4qzV58Woq vAK74UWQB0fDj1CPxkmVITWjIxSH4w40ZW/cykpAW6GCUm/3nuCBoGnR+ CoqIRZbCERwmEFlp+EBMrX24XTV1XgqrRyAo5CwQtWPAC1mH5ILKzLV1m UwkTCkBJTLTziQwT1mONhm/r4SilxgaINxFue0BOuPdr3ZdvYmXRulE8A AgOKn3ahKvjWx4qyEcCqY1mKj1s0NQwl8MlptKpn2RR/W7k6ZG457xauS A==; X-CSE-ConnectionGUID: 6tEXn6EiRxSCR3H0znHa+A== X-CSE-MsgGUID: 0LqlQSdlQIeUd9dTTv9i1Q== X-IronPort-AV: E=McAfee;i="6600,9927,11026"; a="7374670" X-IronPort-AV: E=Sophos;i="6.07,161,1708416000"; d="scan'208";a="7374670" Received: from orviesa003.jf.intel.com ([10.64.159.143]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Mar 2024 05:06:52 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.07,161,1708416000"; d="scan'208";a="21277767" Received: from abijaz-mobl2.ger.corp.intel.com (HELO localhost) ([10.246.42.1]) by ORVIESA003-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Mar 2024 05:06: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 Subject: [PATCH v6 08/10] gdb, mi: Skip trampoline functions for the -stack-list-frames command. Date: Thu, 28 Mar 2024 13:05:26 +0100 Message-Id: <20240328120528.30382-9-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 X-Spam-Status: No, score=-10.9 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, 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+patchwork=sourceware.org@sourceware.org From: "Ijaz, Abdul B" This change skips trampoline functions for the '-stack-list-frames' command when the option 'skip-trampoline-functions' is set to 'on'. Before this change, GDB prints the frames indicated by the compiler with DIE "DW_AT_trampoline" in the backtrace for mi command stack-list-frames, but for better user experience, all such frames can be hidden from the user. In this example the IFX compiler emits "DW_AT_trampoline" tag for the 'first' and 'second' trampoline functions like following: function second (x, y) result(z) integer, intent(in) :: x, y integer :: z z = x * y ! breakpt-backtrace end function second function first (num1, num2) result(total) integer, intent(in) :: num1, num2 integer :: total total = second (num1 + 4, num2 * 3) ! first-breakpt total = total + 30 end function first Related Dwarf: 0x0000013f: DW_TAG_subprogram DW_AT_low_pc (0x0000000000404350) DW_AT_high_pc (0x000000000040435f) DW_AT_frame_base (DW_OP_reg6 RBP) DW_AT_linkage_name ("second_.t74p.t75p") DW_AT_name ("second_.t74p.t75p") DW_AT_trampoline ("second_") 0x0000015a: DW_TAG_subprogram DW_AT_low_pc (0x00000000004044a0) DW_AT_high_pc (0x00000000004044af) DW_AT_frame_base (DW_OP_reg6 RBP) DW_AT_linkage_name ("first_.t104p.t105p") DW_AT_name ("first_.t104p.t105p") DW_AT_trampoline ("first_") Before this change, the '-stack-list-frames' command output looks like: ''' (gdb) -stack-list-frames -stack-list-frames ^done, stack=[ frame={level="0",addr="0x0000000000405194",func="second", file="test.f90",fullname="/home/test.f90",line="4", arch="i386:x86-64"}, frame={level="1",addr="0x0000000000405209", func="second_.t74p.t75p", file="test.f90",fullname="/home/test.f90",line="12", arch="i386:x86-64"}, frame={level="2",addr="0x00000000004051e3",func="first", file="test.f90",fullname="/home/test.f90",line="10", arch="i386:x86-64"}, frame={level="3",addr="0x0000000000405309", func="first_.t95p.t96p",file="test.f90", fullname="/home/test.f90",line="21",arch="i386:x86-64"}, frame={level="4",addr="0x0000000000405234", func="func_trampoline",file="test.f90", fullname="/home/test.f90",line="17",arch="i386:x86-64"}] ''' After this change: ''' (gdb) -stack-list-frames -stack-list-frames ^done, stack=[frame={level="0",addr="0x0000000000405194",func="second", file="test.f90",fullname="/home/test.f90",line="4", arch="i386:x86-64"}, frame={level="2",addr="0x00000000004051e3",func="first", file="test.f90",fullname="/home/test.f90",line="10", arch="i386:x86-64"}, frame={level="4",addr="0x0000000000405234", func="func_trampoline",file="test.f90",fullname="/home/test.f90", line="17",arch="i386:x86-64"}] ''' New test gdb.mi/mi-func-trampoline.exp is added for testing the change. 2024-03-28 Ijaz, Abdul B Reviewed-By: Eli Zaretskii --- gdb/doc/gdb.texinfo | 4 +- gdb/mi/mi-cmd-stack.c | 7 +++ gdb/testsuite/gdb.mi/mi-func-trampoline.exp | 68 +++++++++++++++++++++ 3 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 gdb/testsuite/gdb.mi/mi-func-trampoline.exp diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index a6f74373dfe..90221e9b9c1 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -34866,7 +34866,9 @@ an error if @var{low-frame} is larger than the actual number of frames. On the other hand, @var{high-frame} may be larger than the actual number of frames, in which case only existing frames will be returned. If the option @code{--no-frame-filters} is supplied, then -Python frame filters will not be executed. +Python frame filters will not be executed. If the option +@code{skip-trampoline-functions} is set, @value{GDBN} will skip the trampoline +frames while printing a backtrace. @subsubheading @value{GDBN} Command diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c index b78c169e70b..830edcb816e 100644 --- a/gdb/mi/mi-cmd-stack.c +++ b/gdb/mi/mi-cmd-stack.c @@ -177,6 +177,13 @@ mi_cmd_stack_list_frames (const char *command, const char *const *argv, i++, fi = get_prev_frame (fi)) { QUIT; + if (skip_trampoline_functions) + { + for (int j = 0; (SAFE_TRAMPOLINE_CHAIN (j, fi) + && in_trampoline_frame (fi)); ++j) + fi = get_prev_frame (fi); + } + /* Print the location and the address always, even for level 0. If args is 0, don't print the arguments. */ print_frame_info (user_frame_print_options, diff --git a/gdb/testsuite/gdb.mi/mi-func-trampoline.exp b/gdb/testsuite/gdb.mi/mi-func-trampoline.exp new file mode 100644 index 00000000000..34a2c464f21 --- /dev/null +++ b/gdb/testsuite/gdb.mi/mi-func-trampoline.exp @@ -0,0 +1,68 @@ +# Copyright 2024 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 . + +# Test -stack-list-frames command for functions with trampoline +# calls. Also checks if trampoline frames are filtered while printing +# stack. + +require allow_fortran_tests + +if {![test_compiler_info {ifx-*} f90]} { + untested "This test is only applicable for IFX, which emits the\ + trampoline DIE in Dwarf." + return -1 +} + +load_lib fortran.exp +load_lib mi-support.exp + +set MIFLAGS "-i=mi" + +if {[mi_clean_restart]} { + return +} + +set testfile mi-func-trampoline +set srcfile "${srcdir}/gdb.fortran/func-trampoline.f90" +set binfile [standard_output_file $testfile] + +if { [gdb_compile "${srcfile}" "${binfile}" executable \ + {debug f90} ] != "" } { + untested "failed to compile" + return -1 +} + +mi_delete_breakpoints +mi_gdb_reinitialize_dir $srcdir/$subdir +mi_gdb_load ${binfile} + +set inner_loc [gdb_get_line_number "second-breakpt"] +set fill "\[^\r\n\]*" + +set frame1_regx "\{level=\"0\",addr=\"$hex\",func=\"second\",file=\".*func-trampoline.f90\",fullname=\"${fullname_syntax}func-trampoline.f90\",line=\"$inner_loc\",arch=\".*\"\}" +set frame2_regx "\{level=\"2\",addr=\"$hex\",func=\"first\",.*\}" +set frame3_regx "\{level=\"4\",addr=\"$hex\",func=\"func_trampoline\",.*\}" + +# Set breakpoint inside the innermost function 'second'. +mi_create_breakpoint "-t $srcfile:$inner_loc" \ + "insert breakpoint at line $inner_loc " \ + -number 1 -disp del -func second ".*trampoline.f90" $inner_loc $hex +mi_run_cmd +mi_expect_stop \ + "breakpoint-hit" "second" ".*" ".*trampoline.f90" "\[0-9\]+" { "" "disp=\"del\"" } \ + "run to breakpoint at line $inner_loc" + +mi_gdb_test "100-stack-list-frames" \ + "100\\^done,stack=\\\[frame=${frame1_regx},frame=${frame2_regx},frame=${frame3_regx}\\\]" From patchwork Thu Mar 28 12:05:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abdul Basit Ijaz X-Patchwork-Id: 87769 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 3E3E83858D34 for ; Thu, 28 Mar 2024 12:09:14 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) by sourceware.org (Postfix) with ESMTPS id DDB4E3858D34 for ; Thu, 28 Mar 2024 12:07:04 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org DDB4E3858D34 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 DDB4E3858D34 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1711627631; cv=none; b=YVCzARsI6PI4wnUc2d/ifcMdasnT71ko2YBCrnGujNaJ/nmpmCgA5qATpcPbpC0/W1jUqY4D8jupBaIGJ80PPIqOan0WNdSU47EnuOczllUn/S6yT63BWQovnki7mG9bW4cp4VmG8KbBu9SN9h9IxUYEkvdYKd4GSgnKjrv49tI= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1711627631; c=relaxed/simple; bh=0INohvx21xGKPM5IvyDrC9MuBv9NvwSgnA85Rp0rCek=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=ur9RZ5HNrtcgjN922bgSCBdF2BJQ6jkxQGp8q2VMqEjm/25MPFp6O3Ca0fmGYH1xb9rl7MHWNE/xkhR5qrFQpWButBWLW1jG35pEOxW4PWgGFBWxaP4qc+j1e+jFNsPqn0475UqCOz3CKMGR7i5MRp9ZHXv+f8nPsjzODar18i0= 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=1711627625; x=1743163625; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=0INohvx21xGKPM5IvyDrC9MuBv9NvwSgnA85Rp0rCek=; b=NfIJHP/gU0CEX4CdtsjgKhfuPYSJGVMMGuQThjQS/ZB131mWIYqqKjg+ QE8wHHWJ/x/F/pubH1+l0dRaSx8L6zA1XpM29fEOZMkajVoTlRUMTWZvL 0Q+OvmS4RaGnAXM43hXnJVak+UtouZ1Y2gDR41zQydY3CDLytAaa0QQWz 8MfD/1mp2siSYPtJZER6TqqNW55KfQ1sVha9oVVHjRAcXDKjN+LZ1sGVO W+9k81eO7dDdrerOqBUxeZwv79PNqefWrOqHM7eZ1jbtiw+hVHYNoTuhH ZoqBuA8ZE0GwRHuHrd7pG7lvaM27FzMF0tXznwpKWZYZPX/95a7i966W6 g==; X-CSE-ConnectionGUID: /XpeTwkhSHeaJRsouquf+w== X-CSE-MsgGUID: e5MqZ1joQQezJWjRXBcLIA== X-IronPort-AV: E=McAfee;i="6600,9927,11026"; a="7374686" X-IronPort-AV: E=Sophos;i="6.07,161,1708416000"; d="scan'208";a="7374686" Received: from orviesa003.jf.intel.com ([10.64.159.143]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Mar 2024 05:07:03 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.07,161,1708416000"; d="scan'208";a="21277844" Received: from abijaz-mobl2.ger.corp.intel.com (HELO localhost) ([10.246.42.1]) by ORVIESA003-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Mar 2024 05:07:02 -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 Subject: [PATCH v6 09/10] gdb, mi: Skip trampoline functions for the -stack-list-arguments command. Date: Thu, 28 Mar 2024 13:05:27 +0100 Message-Id: <20240328120528.30382-10-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 X-Spam-Status: No, score=-10.9 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, 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+patchwork=sourceware.org@sourceware.org From: "Ijaz, Abdul B" This change skips trampoline functions for the '-stack-list-arguments' command when the option 'skip-trampoline-functions' is set to 'on'. Before this change, GDB prints the arguments of frames indicated by the compiler with DIE "DW_AT_trampoline" in the backtrace for the mi command stack-list-arguments, but for better user experience, all such frames can be hidden from the user. In this example the IFX compiler emits "DW_AT_trampoline" tag for the 'first' and 'second' trampoline functions like following: function second (x, y) result(z) integer, intent(in) :: x, y integer :: z z = x * y ! breakpt-args end function second function first (num1, num2) result(total) integer, intent(in) :: num1, num2 integer :: total total = second (num1 + 4, num2 * 3) ! first-breakpt total = total + 30 end function first Related Dwarf: 0x0000013f: DW_TAG_subprogram DW_AT_low_pc (0x0000000000404350) DW_AT_high_pc (0x000000000040435f) DW_AT_frame_base (DW_OP_reg6 RBP) DW_AT_linkage_name ("second_.t74p.t75p") DW_AT_name ("second_.t74p.t75p") DW_AT_trampoline ("second_") 0x0000015a: DW_TAG_subprogram DW_AT_low_pc (0x00000000004044a0) DW_AT_high_pc (0x00000000004044af) DW_AT_frame_base (DW_OP_reg6 RBP) DW_AT_linkage_name ("first_.t104p.t105p") DW_AT_name ("first_.t104p.t105p") DW_AT_trampoline ("first_") Before this change, the -stack-list-arguments' command output looks like: ''' (gdb) -stack-list-arguments 0 ^done, stack-args=[ frame={level="0",args=[name="x",name="y"]}, frame={level="1",args=[]}, frame={level="2",args=[name="num1",name="num2"]}, frame={level="3",args=[]}, frame={level="4",args=[]}] ''' After change: ''' (gdb) -stack-list-arguments 0 ^done, stack-args=[ frame={level="0",args=[name="x",name="y"]}, frame={level="1",args=[name="num1",name="num2"]}, frame={level="2",args=[]}] ''' The test gdb.mi/mi-func-treampoline is updated for testing the change. 2024-03-28 Ijaz, Abdul B Reviewed-By: Eli Zaretskii --- gdb/doc/gdb.texinfo | 4 ++++ gdb/mi/mi-cmd-stack.c | 7 +++++++ gdb/testsuite/gdb.mi/mi-func-trampoline.exp | 13 ++++++++++--- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 90221e9b9c1..6b2f40c906c 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -35183,6 +35183,10 @@ variable object is updated, @value{GDBN} makes sure that the thread/frame combination the variable object is bound to still exists, and re-evaluates the variable object in context of that thread/frame. +If the option @code{skip-trampoline-functions} is set for the +@code{-stack-list-arguments}, @value{GDBN} will not show trampoline +functions in the stack. + The following is the complete set of @sc{gdb/mi} operations defined to access this functionality: diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c index 830edcb816e..9b288c3fe03 100644 --- a/gdb/mi/mi-cmd-stack.c +++ b/gdb/mi/mi-cmd-stack.c @@ -404,6 +404,13 @@ mi_cmd_stack_list_args (const char *command, const char *const *argv, int argc) i++, fi = get_prev_frame (fi)) { QUIT; + if (skip_trampoline_functions) + { + for (int j = 0; (SAFE_TRAMPOLINE_CHAIN (j, fi) + && in_trampoline_frame (fi)); ++j) + fi = get_prev_frame (fi); + } + ui_out_emit_tuple tuple_emitter (uiout, "frame"); uiout->field_signed ("level", i); list_args_or_locals (user_frame_print_options, diff --git a/gdb/testsuite/gdb.mi/mi-func-trampoline.exp b/gdb/testsuite/gdb.mi/mi-func-trampoline.exp index 34a2c464f21..44daba74cde 100644 --- a/gdb/testsuite/gdb.mi/mi-func-trampoline.exp +++ b/gdb/testsuite/gdb.mi/mi-func-trampoline.exp @@ -13,9 +13,9 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -# Test -stack-list-frames command for functions with trampoline -# calls. Also checks if trampoline frames are filtered while printing -# stack. +# Test -stack-list-frames and -stack-list-arguments command for functions +# with trampoline calls. Also checks if trampoline frames are filtered +# while printing stack. require allow_fortran_tests @@ -55,6 +55,10 @@ set frame1_regx "\{level=\"0\",addr=\"$hex\",func=\"second\",file=\".*func-tramp set frame2_regx "\{level=\"2\",addr=\"$hex\",func=\"first\",.*\}" set frame3_regx "\{level=\"4\",addr=\"$hex\",func=\"func_trampoline\",.*\}" +set arg1_regx "\{level=\"0\",args=\\\[name=\"x\",name=\"y\"\\\]\}" +set arg2_regx "\{level=\"1\",args=\\\[name=\"num1\",name=\"num2\"\\\]\}" +set arg3_regx "\{level=\"2\",args=\\\[\\\]\}" + # Set breakpoint inside the innermost function 'second'. mi_create_breakpoint "-t $srcfile:$inner_loc" \ "insert breakpoint at line $inner_loc " \ @@ -66,3 +70,6 @@ mi_expect_stop \ mi_gdb_test "100-stack-list-frames" \ "100\\^done,stack=\\\[frame=${frame1_regx},frame=${frame2_regx},frame=${frame3_regx}\\\]" + +mi_gdb_test "200-stack-list-arguments 0" \ + "200\\^done,stack-args=\\\[frame=${arg1_regx},frame=${arg2_regx},frame=${arg3_regx}\\\]" From patchwork Thu Mar 28 12:05:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abdul Basit Ijaz X-Patchwork-Id: 87770 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C04FE3858C3A for ; Thu, 28 Mar 2024 12:09:43 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) by sourceware.org (Postfix) with ESMTPS id B75373858401 for ; Thu, 28 Mar 2024 12:07:12 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org B75373858401 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 B75373858401 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1711627644; cv=none; b=DokNDGx15pFnRIbpAm+rfnvHqED5aSJCBqRoqmWTVPPT15TsCvOkLRcNJR1wv3lsD5wb/LZQNUCz3vGAyIXYpMHPFoQ3vkuiUrI4ajx/gffRh02VXHUt6dUyYw1e89eJeb4ZiDEge6/4LbDebA5LDHTXMfOKb7VdXDZoEfc9vH4= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1711627644; c=relaxed/simple; bh=ODQItpvsoyKdq62Vj24ItRaJdGtS0OSYvRnyBdn65gk=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=lNfib+yaxQu3ow5RKwLbFmHLhSk+mWaa+bjpVMwESEoJ7BvHMsc8/R7JrejPjA1KDb0Lub6tTFLSy1UMJQFtBSQXrSGr3ymQKeSB+vtHb+Dw0CMoM1zew2Ecl0hxvNJ9NdqaYHGFyTWgOfiftQrvFaPv8xZQ6qwHFr9fzaa81BQ= 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=1711627632; x=1743163632; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ODQItpvsoyKdq62Vj24ItRaJdGtS0OSYvRnyBdn65gk=; b=Nutpdsc3xSfsFIR83DLZv/gLhm64NjBw2aNHHDY4dexoof5d8oG60wnS yaPPPzd8PoHc+LqR5ryqdiG+OIVXHq3OOStti2QFSyUDIrfyWp2y5gNMd x7V4tcyQGInsVHpneY+AwvecTLjQhtKLltXoN8T6yacjA76oTo+kDlkha /SfDm4YGytYij3lxzvOrHCf0wieIdRs+Aq32OHZdCcjziwaOZ2GGDOK9B 1Shi5xUnSZLibsrFIs3ebur2SE/7zr+2ck55C3ixneCxWrMWLeRa2ajkv kWYt6iLX7wuyRrzBKyhG28wXi8TUpyP0hsQBxH7Svza2zFCH0JVmNuaDz Q==; X-CSE-ConnectionGUID: 49vCbOGmTFaDrpLm8UjhzA== X-CSE-MsgGUID: OLuJmZmzQGGex+6jeZlgPA== X-IronPort-AV: E=McAfee;i="6600,9927,11026"; a="7374706" X-IronPort-AV: E=Sophos;i="6.07,161,1708416000"; d="scan'208";a="7374706" Received: from orviesa003.jf.intel.com ([10.64.159.143]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Mar 2024 05:07:11 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.07,161,1708416000"; d="scan'208";a="21277872" Received: from abijaz-mobl2.ger.corp.intel.com (HELO localhost) ([10.246.42.1]) by ORVIESA003-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Mar 2024 05:07:10 -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 Subject: [PATCH v6 10/10] gdb: Filter trampoline frames in backtrace when using Python frame-filters. Date: Thu, 28 Mar 2024 13:05:28 +0100 Message-Id: <20240328120528.30382-11-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 X-Spam-Status: No, score=-11.0 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, 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+patchwork=sourceware.org@sourceware.org From: "Ijaz, Abdul B" In case of the Python frame-filters, this change filters trampoline functions when the option 'skip-trampoline-functions' is set to 'on'. GDB recently added the option to hide frames that are marked by the compiler with "DW_AT_trampoline", see commit 'Skip trampoline frames for the backtrace command'. This implements the same functionality when python frame filters are in use. In this example the IFX compiler emits "DW_AT_trampoline" tag for the 'first' and 'second' trampoline functions like following: function second (x, y) result(z) integer, intent(in) :: x, y integer :: z z = x * y ! breakpt-framefilter end function second function first (num1, num2) result(total) integer, intent(in) :: num1, num2 integer :: total total = second (num1 + 4, num2 * 3) ! first-breakpt total = total + 30 end function first Related Dwarf: 0x0000013f: DW_TAG_subprogram DW_AT_low_pc (0x0000000000404350) DW_AT_high_pc (0x000000000040435f) DW_AT_frame_base (DW_OP_reg6 RBP) DW_AT_linkage_name ("second_.t74p.t75p") DW_AT_name ("second_.t74p.t75p") DW_AT_trampoline ("second_") 0x0000015a: DW_TAG_subprogram DW_AT_low_pc (0x00000000004044a0) DW_AT_high_pc (0x00000000004044af) DW_AT_frame_base (DW_OP_reg6 RBP) DW_AT_linkage_name ("first_.t104p.t105p") DW_AT_name ("first_.t104p.t105p") DW_AT_trampoline ("first_") Once frame filters are enabled the backtrace command output before this change looks like: ''' (gdb) info frame-filter global frame-filters: Priority Enabled Name 100 Yes TestTrampolineFrameFilter (gdb) backtrace 3 \#0 second (x=20, y=9) at test.f90:4 \#1 0x0000000000405209 in second_.t74p.t75p () at test.f90:12 \#2 0x00000000004051e3 in first (num1=16, num2=3) at test.f90:10 (gdb) backtrace -3 \#2 0x00000000004051e3 in first (num1=16, num2=3) at test.f90:10 \#3 0x0000000000405309 in first_.t95p.t96p () at test.f90:21 \#4 0x0000000000405234 in func_trampoline () at test.f90:17 ''' After this change: ''' (gdb) info frame-filter global frame-filters: Priority Enabled Name 100 Yes TestTrampolineFrameFilter (gdb) backtrace 3 \#0 second (x=20, y=9) at test.f90:4 \#2 0x00000000004051e3 in first (num1=16, num2=3) at test.f90:10 \#4 0x0000000000405234 in func_trampoline () at test.f90:17 (gdb) backtrace -3 \#2 0x00000000004051e3 in first (num1=16, num2=3) at test.f90:10 \#4 0x0000000000405234 in func_trampoline () at test.f90:17 ''' New test gdb.python/py-framefilter-trampoline.exp is added to test this change. 2024-03-28 Ijaz, Abdul B --- gdb/python/py-frame.c | 11 +++ .../gdb.python/py-framefilter-trampoline.exp | 77 +++++++++++++++++++ .../gdb.python/py-framefilter-trampoline.py | 31 ++++++++ 3 files changed, 119 insertions(+) create mode 100644 gdb/testsuite/gdb.python/py-framefilter-trampoline.exp create mode 100644 gdb/testsuite/gdb.python/py-framefilter-trampoline.py diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c index bbb42afb2ed..5c07ba58b23 100644 --- a/gdb/python/py-frame.c +++ b/gdb/python/py-frame.c @@ -70,6 +70,17 @@ frame_object_to_frame_info (PyObject *obj) if (frame_obj->frame_id_is_next) frame = get_prev_frame (frame); + if (skip_trampoline_functions) + { + for (int i = 0; (SAFE_TRAMPOLINE_CHAIN (i, frame) + && in_trampoline_frame (frame)); ++i) + { + frame = get_prev_frame (frame); + if (frame == nullptr) + return nullptr; + } + } + return frame; } diff --git a/gdb/testsuite/gdb.python/py-framefilter-trampoline.exp b/gdb/testsuite/gdb.python/py-framefilter-trampoline.exp new file mode 100644 index 00000000000..76dbdaa970a --- /dev/null +++ b/gdb/testsuite/gdb.python/py-framefilter-trampoline.exp @@ -0,0 +1,77 @@ +# Copyright (C) 2024 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 . + +# This file is part of the GDB testsuite. It tests skipping of trampolines +# in the backtrace command in case Python-based frame-filters are enabled. + +load_lib gdb-python.exp + +require allow_python_tests allow_fortran_tests + +if {![test_compiler_info {ifx-*} f90]} { + untested "This test is only applicable for IFX, which emits the\ + trampoline DIE in Dwarf." + return -1 +} + +load_lib fortran.exp + +set testfile py-framefilter-trampoline +set srcfile "${srcdir}/gdb.fortran/func-trampoline.f90" +set binfile [standard_output_file $testfile] + +if {[build_executable $testfile.exp $testfile $srcfile {debug f90}] == -1} { + return -1 +} + +# Start with a fresh gdb. +gdb_exit +gdb_start + +gdb_test "info frame-filter" \ + "No frame filters\\." \ + "info frame filter before loading filters" + +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if {![runto_main]} { + return +} +gdb_test_no_output "set python print-stack full" \ + "set python print-stack to full" + +# Load frame-filters +set remote_python_file [gdb_remote_download host \ + ${srcdir}/${subdir}/${testfile}.py] +gdb_test_no_output "source ${remote_python_file}" "load python file" + +set inner_loc [gdb_get_line_number "second-breakpt"] +set middle_loc [gdb_get_line_number "first-breakpt"] +set outer_loc [gdb_get_line_number "main-outer-loc"] +set fill "\[^\r\n\]*" + +set inner_desc "second \\(x=20, y=9\\) at ${fill}$srcfile:$inner_loc" +set middle_desc "first \\(num1=16, num2=3\\) at ${fill}$srcfile:$middle_loc" +set outer_desc ".* at .*$srcfile:$outer_loc" + +# Set breakpoint inside the innermost function 'second'. +gdb_breakpoint "$srcfile:$inner_loc" +gdb_continue_to_breakpoint "innermost-body" ".*$srcfile:$inner_loc.*" + +# Test with frame filter. +gdb_test "bt" [multi_line \ + "#$decimal.* $middle_desc" \ + "#$decimal.* $outer_desc.*"] diff --git a/gdb/testsuite/gdb.python/py-framefilter-trampoline.py b/gdb/testsuite/gdb.python/py-framefilter-trampoline.py new file mode 100644 index 00000000000..0e9dfd7af2a --- /dev/null +++ b/gdb/testsuite/gdb.python/py-framefilter-trampoline.py @@ -0,0 +1,31 @@ +# Copyright (C) 2024 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 . + +# This file is part of the GDB testsuite. It tests if trampolines are +# skipped when Python-based frame-filters are enabled. + +import gdb + +class TestTrampolineFrameFilter(): + def __init__(self): + self.name = "TestTrampolineFrameFilter" + self.priority = 100 + self.enabled = True + gdb.frame_filters[self.name] = self + + def filter(self, frame_iter): + return frame_iter + +TestTrampolineFrameFilter()