public inbox for gdb-cvs@sourceware.org
help / color / mirror / Atom feed
* [binutils-gdb] Support for DW_AT_loclists_base and DW_FORM_loclistx.
@ 2020-04-07 15:56 Tom Tromey
  0 siblings, 0 replies; only message in thread
From: Tom Tromey @ 2020-04-07 15:56 UTC (permalink / raw)
  To: gdb-cvs

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

commit 4114425321d5c380bc8fb5344db8bc8664c170c6
Author: nitachra <Nitika.Achra@amd.com>
Date:   Tue Apr 7 18:35:58 2020 +0530

    Support for DW_AT_loclists_base and DW_FORM_loclistx.
    
    Hi Tom,
    
    This is the updated series with ChangeLogs edits.
    
    Regards,
    Nitika

Diff:
---
 gdb/ChangeLog          |  15 ++++++
 gdb/dwarf2/attribute.c |   3 +-
 gdb/dwarf2/read.c      | 134 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 151 insertions(+), 1 deletion(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index af53206af46..a9e955304f6 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,18 @@
+2020-04-07  Nitika Achra  <Nitika.Achra@amd.com>
+
+	* dwarf2/read.c (cu_debug_loc_section): Added the declaration for the function.
+	(read_loclist_index): New function definition.
+	(lookup_loclist_base): New function definition.
+	(read_loclist_header): New function definition.
+	(dwarf2_cu): Add loclist_base and loclist_header field.
+	(dwarf2_locate_dwo_sections): Handle .debug_loclists.dwo section.
+	(read_full_die_1): Read the value of DW_AT_loclists_base.
+	(read_attribute_reprocess): Handle DW_FORM_loclistx.
+	(read_attribute_value): Handle DW_FORM_loclistx.
+	(skip_one_die): Handle DW_FORM_loclistx.
+	(loclist_header): New structure declaration.
+	* dwarf2/attribute.c (form_is_section_offset): Handle DW_FORM_loclistx.
+
 2020-04-07  Simon Marchi  <simon.marchi@polymtl.ca>
 
 	* dwarf2/read.h (struct dwarf2_psymtab): Remove two-parameters
diff --git a/gdb/dwarf2/attribute.c b/gdb/dwarf2/attribute.c
index 0e5a8c8f536..9ceacf0409e 100644
--- a/gdb/dwarf2/attribute.c
+++ b/gdb/dwarf2/attribute.c
@@ -78,7 +78,8 @@ attribute::form_is_section_offset () const
 {
   return (form == DW_FORM_data4
           || form == DW_FORM_data8
-	  || form == DW_FORM_sec_offset);
+	  || form == DW_FORM_sec_offset
+	  || form == DW_FORM_loclistx);
 }
 
 /* See attribute.h.  */
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 1e593b39065..f1ddadef8d5 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -114,6 +114,12 @@ static int dwarf2_loclist_index;
 static int dwarf2_locexpr_block_index;
 static int dwarf2_loclist_block_index;
 
+/* Size of .debug_loclists section header for 32-bit DWARF format.  */
+#define LOCLIST_HEADER_SIZE32 12
+
+/* Size of .debug_loclists section header for 64-bit DWARF format.  */
+#define LOCLIST_HEADER_SIZE64 20
+
 /* An index into a (C++) symbol name component in a symbol name as
    recorded in the mapped_index's symbol table.  For each C++ symbol
    in the symbol table, we record one entry for the start of each
@@ -346,6 +352,30 @@ dwop_section_names =
 
 /* local data types */
 
+/* The location list section (.debug_loclists) begins with a header,
+   which contains the following information.  */
+struct loclist_header
+{
+  /* A 4-byte or 12-byte length containing the length of the
+     set of entries for this compilation unit, not including the
+     length field itself.  */
+  unsigned int length;
+
+  /* A 2-byte version identifier.  */
+  short version;
+
+  /* A 1-byte unsigned integer containing the size in bytes of an address on
+     the target system.  */
+  unsigned char addr_size;
+
+  /* A 1-byte unsigned integer containing the size in bytes of a segment selector
+     on the target system.  */
+  unsigned char segment_collector_size;
+
+  /* A 4-byte count of the number of offsets that follow the header.  */
+  unsigned int offset_entry_count;
+};
+
 /* Type used for delaying computation of method physnames.
    See comments for compute_delayed_physnames.  */
 struct delayed_method_info
@@ -493,6 +523,9 @@ public:
      whether the DW_AT_ranges attribute came from the skeleton or DWO.  */
   ULONGEST ranges_base = 0;
 
+  /* The DW_AT_loclists_base attribute if present.  */
+  ULONGEST loclist_base = 0;
+
   /* When reading debug info generated by older versions of rustc, we
      have to rewrite some union types to be struct types with a
      variant part.  This rewriting must be done after the CU is fully
@@ -1303,6 +1336,9 @@ static void read_variable (struct die_info *die, struct dwarf2_cu *cu);
 static int dwarf2_ranges_read (unsigned, CORE_ADDR *, CORE_ADDR *,
 			       struct dwarf2_cu *, dwarf2_psymtab *);
 
+/* Return the .debug_loclists section to use for cu.  */
+static struct dwarf2_section_info *cu_debug_loc_section (struct dwarf2_cu *cu);
+
 /* How dwarf2_get_pc_bounds constructed its *LOWPC and *HIGHPC return
    values.  Keep the items ordered with increasing constraints compliance.  */
 enum pc_bounds_kind
@@ -8591,6 +8627,7 @@ skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
 	case DW_FORM_GNU_addr_index:
 	case DW_FORM_GNU_str_index:
 	case DW_FORM_rnglistx:
+	case DW_FORM_loclistx:
 	  info_ptr = safe_skip_leb128 (info_ptr, buffer_end);
 	  break;
 	case DW_FORM_indirect:
@@ -12056,6 +12093,11 @@ dwarf2_locate_dwo_sections (bfd *abfd, asection *sectp, void *dwo_sections_ptr)
       dwo_sections->loc.s.section = sectp;
       dwo_sections->loc.size = bfd_section_size (sectp);
     }
+  else if (section_is_p (sectp->name, &names->loclists_dwo))
+    {
+      dwo_sections->loclists.s.section = sectp;
+      dwo_sections->loclists.size = bfd_section_size (sectp);
+    }
   else if (section_is_p (sectp->name, &names->macinfo_dwo))
     {
       dwo_sections->macinfo.s.section = sectp;
@@ -17537,6 +17579,10 @@ read_full_die_1 (const struct die_reader_specs *reader,
   if (attr != nullptr)
     cu->str_offsets_base = DW_UNSND (attr);
 
+  attr = die->attr (DW_AT_loclists_base);
+  if (attr != nullptr)
+    cu->loclist_base = DW_UNSND (attr);
+
   auto maybe_addr_base = die->addr_base ();
   if (maybe_addr_base.has_value ())
     cu->addr_base = *maybe_addr_base;
@@ -18375,6 +18421,84 @@ partial_die_info::fixup (struct dwarf2_cu *cu)
   fixup_called = 1;
 }
 
+/* Read the .debug_loclists header contents from the given SECTION in the
+   HEADER.  */
+static void
+read_loclist_header (struct loclist_header *header,
+		      struct dwarf2_section_info *section)
+{
+  unsigned int bytes_read;
+  bfd *abfd = section->get_bfd_owner ();
+  const gdb_byte *info_ptr = section->buffer;
+  header->length = read_initial_length (abfd, info_ptr, &bytes_read);
+  info_ptr += bytes_read;
+  header->version = read_2_bytes (abfd, info_ptr);
+  info_ptr += 2;
+  header->addr_size = read_1_byte (abfd, info_ptr);
+  info_ptr += 1;
+  header->segment_collector_size = read_1_byte (abfd, info_ptr);
+  info_ptr += 1;
+  header->offset_entry_count = read_4_bytes (abfd, info_ptr);
+}
+
+/* Return the DW_AT_loclists_base value for the CU.  */
+static ULONGEST
+lookup_loclist_base (struct dwarf2_cu *cu)
+{
+  /* For the .dwo unit, the loclist_base points to the first offset following
+     the header. The header consists of the following entities-
+     1. Unit Length (4 bytes for 32 bit DWARF format, and 12 bytes for the 64
+	 bit format)
+     2. version (2 bytes)
+     3. address size (1 byte)
+     4. segment selector size (1 byte)
+     5. offset entry count (4 bytes)
+     These sizes are derived as per the DWARFv5 standard.  */
+  if (cu->dwo_unit != nullptr)
+    {
+      if (cu->header.initial_length_size == 4)
+	 return LOCLIST_HEADER_SIZE32;
+      return LOCLIST_HEADER_SIZE64;
+    }
+  return cu->loclist_base;
+}
+
+/* Given a DW_FORM_loclistx value LOCLIST_INDEX, fetch the offset from the
+   array of offsets in the .debug_loclists section.  */
+static CORE_ADDR
+read_loclist_index (struct dwarf2_cu *cu, ULONGEST loclist_index)
+{
+  struct dwarf2_per_objfile *dwarf2_per_objfile
+    = cu->per_cu->dwarf2_per_objfile;
+  struct objfile *objfile = dwarf2_per_objfile->objfile;
+  bfd *abfd = objfile->obfd;
+  ULONGEST loclist_base = lookup_loclist_base (cu);
+  struct dwarf2_section_info *section = cu_debug_loc_section (cu);
+
+  section->read (objfile);
+  if (section->buffer == NULL)
+    complaint (_("DW_FORM_loclistx used without .debug_loclists "
+	        "section [in module %s]"), objfile_name (objfile));
+  struct loclist_header header;
+  read_loclist_header (&header, section);
+  if (loclist_index >= header.offset_entry_count)
+    complaint (_("DW_FORM_loclistx pointing outside of "
+	        ".debug_loclists offset array [in module %s]"),
+	        objfile_name (objfile));
+  if (loclist_base + loclist_index * cu->header.offset_size
+	>= section->size)
+    complaint (_("DW_FORM_loclistx pointing outside of "
+	        ".debug_loclists section [in module %s]"),
+	        objfile_name (objfile));
+  const gdb_byte *info_ptr
+    = section->buffer + loclist_base + loclist_index * cu->header.offset_size;
+
+  if (cu->header.offset_size == 4)
+    return bfd_get_32 (abfd, info_ptr) + loclist_base;
+  else
+    return bfd_get_64 (abfd, info_ptr) + loclist_base;
+}
+
 /* Process the attributes that had to be skipped in the first round. These
    attributes are the ones that need str_offsets_base or addr_base attributes.
    They could not have been processed in the first round, because at the time
@@ -18390,6 +18514,9 @@ read_attribute_reprocess (const struct die_reader_specs *reader,
       case DW_FORM_GNU_addr_index:
         DW_ADDR (attr) = read_addr_index (cu, DW_UNSND (attr));
         break;
+      case DW_FORM_loclistx:
+	 DW_UNSND (attr) = read_loclist_index (cu, DW_UNSND (attr));
+	 break;
       case DW_FORM_strx:
       case DW_FORM_strx1:
       case DW_FORM_strx2:
@@ -18494,6 +18621,13 @@ read_attribute_value (const struct die_reader_specs *reader,
       DW_UNSND (attr) = cu->header.read_offset (abfd, info_ptr, &bytes_read);
       info_ptr += bytes_read;
       break;
+    case DW_FORM_loclistx:
+      {
+	 *need_reprocess = true;
+	 DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+	 info_ptr += bytes_read;
+      }
+      break;
     case DW_FORM_string:
       DW_STRING (attr) = read_direct_string (abfd, info_ptr, &bytes_read);
       DW_STRING_IS_CANONICAL (attr) = 0;


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2020-04-07 15:56 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-07 15:56 [binutils-gdb] Support for DW_AT_loclists_base and DW_FORM_loclistx Tom Tromey

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).