From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2126) id BD99D3858C56; Mon, 28 Mar 2022 19:56:28 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org BD99D3858C56 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Tom Tromey To: gdb-cvs@sourceware.org Subject: [binutils-gdb] Handle multiple addresses in call_site_target X-Act-Checkin: binutils-gdb X-Git-Author: Tom Tromey X-Git-Refname: refs/heads/master X-Git-Oldrev: a0e0ca7044f240c0b56a829ed762f5efd0854fc6 X-Git-Newrev: 48ac197b0c209ccf1f2de9704eb6cdf7c5c73a8e Message-Id: <20220328195628.BD99D3858C56@sourceware.org> Date: Mon, 28 Mar 2022 19:56:28 +0000 (GMT) X-BeenThere: gdb-cvs@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 28 Mar 2022 19:56:28 -0000 https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3D48ac197b0c20= 9ccf1f2de9704eb6cdf7c5c73a8e commit 48ac197b0c209ccf1f2de9704eb6cdf7c5c73a8e Author: Tom Tromey Date: Fri Nov 19 10:12:44 2021 -0700 Handle multiple addresses in call_site_target =20 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. =20 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. =20 I didn't write a standalone test for this as it seemed excessively complicated. Diff: --- 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 37e5a16f3c0..5cfd5a2807c 100644 --- a/gdb/dwarf2/loc.c +++ b/gdb/dwarf2/loc.c @@ -726,6 +726,18 @@ call_site_target::iterate_over_addresses } break; =20 + case call_site_target::ADDRESSES: + { + dwarf2_per_objfile *per_objfile =3D call_site->per_objfile; + compunit_symtab *cust =3D per_objfile->get_symtab (call_site->per_cu); + int sect_idx =3D cust->block_line_section (); + CORE_ADDR delta =3D per_objfile->objfile->section_offsets[sect_idx]; + + for (unsigned i =3D 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 f9c942d91d3..6c41ede48b5 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -13311,6 +13311,11 @@ read_lexical_block_scope (struct die_info *die, st= ruct dwarf2_cu *cu) cu->get_builder ()->set_local_using_directives (cstk.local_using_directi= ves); } =20 +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. */ =20 static void @@ -13474,6 +13479,10 @@ read_call_site_scope (struct die_info *die, struct= dwarf2_cu *cu) =20 target_die =3D follow_die_ref (die, attr, &target_cu); gdb_assert (target_cu->per_objfile->objfile =3D=3D objfile); + + struct attribute *ranges_attr + =3D dwarf2_attr (target_die, DW_AT_ranges, target_cu); + if (die_is_declaration (target_die, target_cu)) { const char *target_physname; @@ -13489,6 +13498,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 !=3D nullptr && ranges_attr->form_is_unsigned (= )) + { + ULONGEST ranges_offset =3D (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 =3D 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; @@ -14062,6 +14083,20 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *lo= w_return, return 1; } =20 +/* 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 3b05adb2297..92a2b7cf207 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -1834,6 +1834,8 @@ struct call_site_target PHYSNAME, /* A DWARF block. */ DWARF_BLOCK, + /* An array of addresses. */ + ADDRESSES, }; =20 void set_loc_physaddr (CORE_ADDR physaddr) @@ -1854,6 +1856,13 @@ struct call_site_target m_loc.dwarf_block =3D dwarf_block; } =20 + void set_loc_array (unsigned length, const CORE_ADDR *data) + { + m_loc_kind =3D ADDRESSES; + m_loc.addresses.length =3D length; + m_loc.addresses.values =3D data; + } + /* Callback type for iterate_over_addresses. */ =20 using iterate_ftype =3D gdb::function_view; @@ -1877,6 +1886,12 @@ private: const char *physname; /* DWARF block. */ struct dwarf2_locexpr_baton *dwarf_block; + /* Array of addresses. */ + struct + { + unsigned length; + const CORE_ADDR *values; + } addresses; } m_loc; =20 /* * Discriminant for union field_location. */