From patchwork Sun Nov 24 22:03:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Ijaz, Abdul B" X-Patchwork-Id: 101804 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 C38EF3858019 for ; Sun, 24 Nov 2024 22:06:15 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C38EF3858019 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=GFyrCVav X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.11]) by sourceware.org (Postfix) with ESMTPS id 1C7653858CD9 for ; Sun, 24 Nov 2024 22:04:22 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 1C7653858CD9 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 1C7653858CD9 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=192.198.163.11 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1732485862; cv=none; b=P7fz9irag4b6sUXAStazXGb/wB9scn0NybyAsC3r0EfnFe7KwgvKUrdHbzBPh2V4X5P3APyOdGXBdx5m0ltyhvl0xUfveq2u3prN0vfQfpLG3EwUDRdT6G0odAkV4eCEHzGrzwox+FtV/Fgyqm0bjZjlIrGfq8TvaDZBDCNI6Mg= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1732485862; c=relaxed/simple; bh=/P9L6r6rMRbPk9FUUWQkfVDxGsSb/cEudoBhqC03K34=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=ErDhHEQR+VtmbdIU1UI1c4xauQp/iGJjtGrIx0KVTS1l1Xh/cgsX2+GR4CvnvzWfivPo9T3uusi26KJeJPNAW+5OplBgcYdzW8EW90R+qktAESNoot7ZH7PSRGNQGCHKCNBZBDDfYi6xiKFWh5NHSUsrlwodWJg/4pC4tWKSHNk= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 1C7653858CD9 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1732485862; x=1764021862; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=/P9L6r6rMRbPk9FUUWQkfVDxGsSb/cEudoBhqC03K34=; b=GFyrCVavPgV2d1AtidBSUwX0w/iD1J0oK4BwiTB7z2L/eF/GT7tjcj5V Hmhk49Dqij/CvZhgULb36weNvQUo20WSsdxlefx2MwH2PaCVTiO8DYiK8 uhcztGbEVhPcmnMCkzg69ymWvAGSXX30ruzbku6oxesN1kbBp9lQRpISx ebMMxWeGR3rA2IKeHEnfbJzAV3UzTXLTrmQOs6wlDiFI5gu2IlN/TLSX6 7NanZm9Y5YZM2/RZozzzuHVGcTFBAw51EGdFerT9XzAGU3nYW2mU5ZLR6 obJTIzyEvRDvgG+fMmahuvPwYVxrCWmvSk7BXjXhGbe3orNYfYAab7jol A==; X-CSE-ConnectionGUID: Uhmg4MYISlWmVYNlIm75oA== X-CSE-MsgGUID: 5ayJbcgLR3+xjyylNsu8LQ== X-IronPort-AV: E=McAfee;i="6700,10204,11266"; a="43187989" X-IronPort-AV: E=Sophos;i="6.12,181,1728975600"; d="scan'208";a="43187989" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 24 Nov 2024 14:04:21 -0800 X-CSE-ConnectionGUID: YVMdY5OjT7aEzWZqIMKPqQ== X-CSE-MsgGUID: T21eNGhcRHWOc+OWWJFLxg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,181,1728975600"; d="scan'208";a="95502157" Received: from abijaz-mobl2.ger.corp.intel.com (HELO localhost) ([10.245.166.144]) by fmviesa005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 24 Nov 2024 14:04:19 -0800 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 v9 01/10] gdb, dwarf: add support for DW_AT_trampoline in DWARF reader Date: Sun, 24 Nov 2024 23:03:44 +0100 Message-Id: <20241124220353.3465-2-abdul.b.ijaz@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241124220353.3465-1-abdul.b.ijaz@intel.com> References: <20241124220353.3465-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, 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-11-24 Nils-Christian Kempke --- gdb/dwarf2/read.c | 39 +++++++++++++++- gdb/gdbtypes.c | 34 +++++++++++++- gdb/gdbtypes.h | 113 ++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 179 insertions(+), 7 deletions(-) diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 2f421a4c266..ff002252ab7 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -14751,6 +14751,43 @@ 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 + 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 + TYPE_TRAMPOLINE_TARGET (ftype)->set_target_addr (attr->as_address ()); + } + /* 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. */ @@ -14768,7 +14805,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 1a04488d272..accd8143938 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -5104,6 +5104,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. */ @@ -5379,6 +5406,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: @@ -5593,8 +5624,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 7fdb377c263..b6340379c90 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -93,6 +93,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. */ @@ -1808,11 +1823,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 @@ -1827,6 +1840,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. */ @@ -1969,7 +2063,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