public inbox for gdb-cvs@sourceware.org
help / color / mirror / Atom feed
From: Tom Tromey <tromey@sourceware.org>
To: gdb-cvs@sourceware.org
Subject: [binutils-gdb] Handle multiple addresses in call_site_target
Date: Mon, 28 Mar 2022 19:56:28 +0000 (GMT)	[thread overview]
Message-ID: <20220328195628.BD99D3858C56@sourceware.org> (raw)

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=48ac197b0c209ccf1f2de9704eb6cdf7c5c73a8e

commit 48ac197b0c209ccf1f2de9704eb6cdf7c5c73a8e
Author: Tom Tromey <tromey@adacore.com>
Date:   Fri Nov 19 10:12:44 2021 -0700

    Handle multiple addresses in call_site_target
    
    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.

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;
 
+    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 = cust->block_line_section ();
+	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 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, 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<CORE_ADDR> &result);
+
 /* Read in DW_TAG_call_site and insert it to CU->call_site_htab.  */
 
 static void
@@ -13474,6 +13479,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;
@@ -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 != nullptr && ranges_attr->form_is_unsigned ())
+	{
+	  ULONGEST ranges_offset = (ranges_attr->as_unsigned ()
+				    + target_cu->gnu_ranges_base);
+	  std::vector<CORE_ADDR> 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;
@@ -14062,6 +14083,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<CORE_ADDR> &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,
   };
 
   void set_loc_physaddr (CORE_ADDR physaddr)
@@ -1854,6 +1856,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<void (CORE_ADDR)>;
@@ -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;
 
   /* * Discriminant for union field_location.  */


                 reply	other threads:[~2022-03-28 19:56 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220328195628.BD99D3858C56@sourceware.org \
    --to=tromey@sourceware.org \
    --cc=gdb-cvs@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).