From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-io1-xd34.google.com (mail-io1-xd34.google.com [IPv6:2607:f8b0:4864:20::d34]) by sourceware.org (Postfix) with ESMTPS id 37F5E3858029 for ; Wed, 1 Dec 2021 22:04:41 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 37F5E3858029 Received: by mail-io1-xd34.google.com with SMTP id b187so21768716iof.11 for ; Wed, 01 Dec 2021 14:04:41 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=EPLQAcfUfk9hn0+JeqSZKCKiDf/DW0nXx+DGvGGpxbE=; b=3Uv7OtQk1BjyQUezskszl50upjhyoudOfisFjzYCSfvzML7EgtOpi3ybwpSm/crQiv BL/zlJ8KKTVC+Hrqs40suwFqWqGS1pS7Wgg26GNAg/ihHyKacYwwsdEIFC1snjG7o/bC BfO/Ta+S4yCbdoVOazygE12wxRAANRF8menf53LApXnOg0lWaEqSo4oXW2MRH12OcdV2 6NgpVfVS9ht4bYzoDwucOvKtGL0sfJENjxd8c4KXj0Osm8nDUfQm0SYp0S6AOhL8moob zNkZ3U3KupTNJeYjC260nREAZp8DBjawnwDHpdpSaCnu1zPHceJys86uNBznJlLhxMC8 UE9A== X-Gm-Message-State: AOAM531hdTqbgVmNRJ5rL1omPyz+MXlthYvUV7juXv54f/KXsxEF0FXK alCT/Q5NsmrWxr1tlKGY36Y9Ue7TXGELVw== X-Google-Smtp-Source: ABdhPJx9trh2BJWaSh8LintZ9NpfzrZX8LDZwLE2hfmUTBr9ppARsV1ZBktOHkKFn0gtjfYr0i/DNg== X-Received: by 2002:a05:6638:2103:: with SMTP id n3mr15256390jaj.25.1638396280568; Wed, 01 Dec 2021 14:04:40 -0800 (PST) Received: from murgatroyd.Home (97-122-84-67.hlrn.qwest.net. [97.122.84.67]) by smtp.gmail.com with ESMTPSA id l18sm622298iob.17.2021.12.01.14.04.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Dec 2021 14:04:40 -0800 (PST) From: Tom Tromey To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [PATCH 6/6] Handle multiple addresses in call_site_target Date: Wed, 1 Dec 2021 15:04:32 -0700 Message-Id: <20211201220432.4105152-7-tromey@adacore.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211201220432.4105152-1-tromey@adacore.com> References: <20211201220432.4105152-1-tromey@adacore.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-11.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 01 Dec 2021 22:04:42 -0000 A large customer program has a function that is partitioned into hot and cold parts. A variable in a callee of this function is described using DW_OP_GNU_entry_value, but gdb gets confused when trying to find the caller. I tracked this down to dwarf2_get_pc_bounds interpreting the function's changes so that the returned low PC is the "wrong" function. Intead, when processing DW_TAG_call_site, the low PC of each range in DW_AT_ranges should be preserved in the call_site_target. This fixes the variable lookup in the test case I have. I didn't write a standalone test for this as it seemed excessively complicated. --- gdb/dwarf2/loc.c | 12 ++++++++++++ gdb/dwarf2/read.c | 35 +++++++++++++++++++++++++++++++++++ gdb/gdbtypes.h | 15 +++++++++++++++ 3 files changed, 62 insertions(+) diff --git a/gdb/dwarf2/loc.c b/gdb/dwarf2/loc.c index e1001eb7adb..82508c78cc7 100644 --- a/gdb/dwarf2/loc.c +++ b/gdb/dwarf2/loc.c @@ -726,6 +726,18 @@ call_site_target::iterate_over_addresses } break; + case call_site_target::ADDRESSES: + { + dwarf2_per_objfile *per_objfile = call_site->per_objfile; + compunit_symtab *cust = per_objfile->get_symtab (call_site->per_cu); + int sect_idx = COMPUNIT_BLOCK_LINE_SECTION (cust); + CORE_ADDR delta = per_objfile->objfile->section_offsets[sect_idx]; + + for (unsigned i = 0; i < m_loc.addresses.length; ++i) + callback (m_loc.addresses.values[i] + delta); + } + break; + default: internal_error (__FILE__, __LINE__, _("invalid call site target kind")); } diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 57538fc0adf..f40606216d1 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -13335,6 +13335,11 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu) cu->get_builder ()->set_local_using_directives (cstk.local_using_directives); } +static void dwarf2_ranges_read_low_addrs (unsigned offset, + struct dwarf2_cu *cu, + dwarf_tag tag, + std::vector &result); + /* Read in DW_TAG_call_site and insert it to CU->call_site_htab. */ static void @@ -13498,6 +13503,10 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) target_die = follow_die_ref (die, attr, &target_cu); gdb_assert (target_cu->per_objfile->objfile == objfile); + + struct attribute *ranges_attr + = dwarf2_attr (target_die, DW_AT_ranges, target_cu); + if (die_is_declaration (target_die, target_cu)) { const char *target_physname; @@ -13513,6 +13522,18 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) else call_site->target.set_loc_physname (target_physname); } + else if (ranges_attr != nullptr && ranges_attr->form_is_unsigned ()) + { + ULONGEST ranges_offset = (ranges_attr->as_unsigned () + + target_cu->gnu_ranges_base); + std::vector addresses; + dwarf2_ranges_read_low_addrs (ranges_offset, target_cu, + target_die->tag, addresses); + CORE_ADDR *saved = XOBNEWVAR (&objfile->objfile_obstack, CORE_ADDR, + addresses.size ()); + std::copy (addresses.begin (), addresses.end (), saved); + call_site->target.set_loc_array (addresses.size (), saved); + } else { CORE_ADDR lowpc; @@ -14086,6 +14107,20 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return, return 1; } +/* Process ranges and fill in a vector of the low PC values only. */ + +static void +dwarf2_ranges_read_low_addrs (unsigned offset, struct dwarf2_cu *cu, + dwarf_tag tag, + std::vector &result) +{ + dwarf2_ranges_process (offset, cu, tag, + [&] (CORE_ADDR start, CORE_ADDR end) + { + result.push_back (start); + }); +} + /* Get low and high pc attributes from a die. See enum pc_bounds_kind definition for the return value. *LOWPC and *HIGHPC are set iff neither PC_BOUNDS_NOT_PRESENT nor PC_BOUNDS_INVALID are returned. */ diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index eaa3cd0dcb7..c89521c4318 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -1820,6 +1820,8 @@ struct call_site_target PHYSNAME, /* A DWARF block. */ DWARF_BLOCK, + /* An array of addresses. */ + ADDRESSES, }; void set_loc_physaddr (CORE_ADDR physaddr) @@ -1840,6 +1842,13 @@ struct call_site_target m_loc.dwarf_block = dwarf_block; } + void set_loc_array (unsigned length, const CORE_ADDR *data) + { + m_loc_kind = ADDRESSES; + m_loc.addresses.length = length; + m_loc.addresses.values = data; + } + /* Callback type for iterate_over_addresses. */ using iterate_ftype = gdb::function_view; @@ -1863,6 +1872,12 @@ struct call_site_target const char *physname; /* DWARF block. */ struct dwarf2_locexpr_baton *dwarf_block; + /* Array of addresses. */ + struct + { + unsigned length; + const CORE_ADDR *values; + } addresses; } m_loc; /* * Discriminant for union field_location. */ -- 2.31.1