public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v2 1/3] Support for DW_AT_loclists_base and DW_FORM_loclistx.
@ 2020-03-30 15:21 nitachra
  2020-03-30 15:21 ` [PATCH v2 2/3] DWARFv5: Handle location list for split dwarf nitachra
                   ` (3 more replies)
  0 siblings, 4 replies; 11+ messages in thread
From: nitachra @ 2020-03-30 15:21 UTC (permalink / raw)
  To: gdb-patches, simark; +Cc: JiniSusan.George, tom, nitachra

Thanks for the review. I have made all the style changes.

Regards,
Nitika
---

This patch handles DW_AT_loclists_base and DW_FORM_loclistx.
DW_AT_loclists_base is a new attribute added in DWARFv5 which
points to the beginning of the offset table of .debug_loclists
section. Reference to the location list (DW_FORM_loclistx) is
interpreted relative to this base. DW_FORM_loclistx is a new
form added in DWARFv5 which is used to access location list.

Tested by running the testsuite before and after the patch and there
is no increase in the number of test cases that fails. Tested with both
-gdwarf-4 and -gdwarf-5 flags. Also tested -gsplit-dwarf along with
-gdwarf-4 as well as -gdwarf5 flags. Used clang 10.0.0 for testing.

gdb/dwarf2/ChangeLog:

   *read.c (cu_debug_loc_section): Added the declaration for the function.
   (read_loclist_index): New function declaration.
   (lookup_loclist_base): New function declaration.
   (read_loclist_header): New function declaration
   (dwarf2_cu): Added 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.
   *attribute.c (form_is_section_offset): Handle DW_FORM_loclistx.

gdb/testsuite/ChangeLog:

   *gdb.dwarf2/dw5-form-loclistx.exp: New file.
   *gdb.dwarf2/dw5-form-loclistx.c: New file.

Signed-off-by: nitachra <Nitika.Achra@amd.com>
---
 gdb/dwarf2/attribute.c |   3 +-
 gdb/dwarf2/read.c      | 131 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 133 insertions(+), 1 deletion(-)

diff --git a/gdb/dwarf2/attribute.c b/gdb/dwarf2/attribute.c
index 0e5a8c8f53..9ceacf0409 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 8c5046ef41..556c3ab873 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 @@ struct dwarf2_cu
      whether the DW_AT_ranges attribute came from the skeleton or DWO.  */
   ULONGEST ranges_base = 0;
 
+  /* The DW_AT_loclists_base attribute if present.  */
+  gdb::optional<ULONGEST> loclist_base;
+
   /* 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
@@ -8564,6 +8600,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:
@@ -12029,6 +12066,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;
@@ -17496,6 +17538,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;
@@ -18298,6 +18344,81 @@ 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
@@ -18313,6 +18434,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:
@@ -18417,6 +18541,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;
-- 
2.17.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 2/3] DWARFv5: Handle location list for split dwarf.
  2020-03-30 15:21 [PATCH v2 1/3] Support for DW_AT_loclists_base and DW_FORM_loclistx nitachra
@ 2020-03-30 15:21 ` nitachra
  2020-03-30 15:21 ` [PATCH v2 3/3] DWARFv5: Info address command error in gdb with DWARFfv5 nitachra
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 11+ messages in thread
From: nitachra @ 2020-03-30 15:21 UTC (permalink / raw)
  To: gdb-patches, simark; +Cc: JiniSusan.George, tom, nitachra

>I tried to use this exact code and compilation command, but I don't see
>any .debug_loclists section in the output, nor any attributes using
>DW_FORM_loclistx,is that normal?

>The clang version I have is this one (from apt.llvm.org):

>clang version
>10.0.0-++20200323044127+d32170dbd5b-1~exp1~20200323154723.129

Please try it without any optimization.

clang -gdwarf-5 -gsplit-dwarf test.c -o test.out

I can see the following .debug_loclists.dwo section with the above
example-

.debug_loclists.dwo contents:
locations list header: length = 0x00000036, version = 0x0005, addr_size
= 0x08, seg_size = 0x00, offset_entry_count = 0x00000002
offsets: [
0x00000008
0x0000001a
]
0x00000014:
            DW_LLE_base_addressx   (0x0000000000000000)
            DW_LLE_offset_pair     (0x000000000000004c,
0x000000000000007c): DW_OP_breg9 R9+0
            DW_LLE_offset_pair     (0x000000000000007c,
0x0000000000000100): DW_OP_breg6 RBP-72, DW_OP_deref

0x00000026:
            DW_LLE_base_addressx   (0x0000000000000000)
            DW_LLE_offset_pair     (0x0000000000000071,
0x0000000000000080): DW_OP_breg10 R10+0
            DW_LLE_offset_pair     (0x0000000000000080,
0x0000000000000100): DW_OP_breg6 RBP-80, DW_OP_deref

Regards,
Nitika
---

GDB throws the error '<error reading variable: dwarf2_find_location_
expression: Corrupted DWARF expression.>' while printing the variable
value with executable file compiled with -gdwarf-5 and -gdwarf-split
flags. This is because DW_LLE_start* or DW_LLE_offset_pair with
DW_LLE_base_addressx are being emitted in DWARFv5 location list instead of
DW_LLE_GNU*. This patch fixes this error.

Tested by running the testsuite before and after the patch and there is no
increase in the number of test cases that fails. Tested with both -gdwarf-4
and -gdwarf-5 flags. Also tested -gslit-dwarf along with -gdwarf-4 as well as
-gdwarf-5 flags. Used clang version 10.0.0. This is the test case used-

void bar(int arr[], int l, int m, int r) {
    int i, j, k, n1= m - l + 1, n2= r - m, L[n1], R[n2];
    for (i = 0; i < n1; i++)
        L[i] = arr[l + i];
    for (j = 0; j < n2; j++)
        R[j] = arr[m + 1+ j];
}

int main()
{
    int arr[] = {12, 11};
    bar(arr,0,1,2);
    return 0;
}

clang -gdwarf-5 -gsplit-dwarf test.c -o test.out

gdb test.out
gdb> start
gdb> step
gdb> step
gdb> step
gdb> step
gdb> p L[0]
dwarf2_find_location_expression: Corrupted DWARF expression.

gdb/dwarf2/ChangeLog:

   *loc.c (enum debug_loc_kind): Added a new kind DEBUG_LOC_OFFSET_PAIR.
    (dwarf2_find_location_expression): Call the function decode_debug_loclists_
    addresses if DWARF version is 5 or more. DW_LLE_start* or DW_LLE_offset_pair
    with DW_LLE_base_addressx are being emitted in DWARFv5 instead of DW_LLE_GNU*.
    Add applicable base address if the entry is DW_LLE_offset_pair from DWO.
    (decode_debug_loclists_addresses): Return DEBUG_LOC_OFFSET_PAIR instead of
    DEBUG_LOC_START_END in case of DW_LLE_offset_pair.

Signed-off-by: nitachra <Nitika.Achra@amd.com>
---
 gdb/dwarf2/loc.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/gdb/dwarf2/loc.c b/gdb/dwarf2/loc.c
index 6440335ccb..62bec79035 100644
--- a/gdb/dwarf2/loc.c
+++ b/gdb/dwarf2/loc.c
@@ -92,6 +92,11 @@ enum debug_loc_kind
      as in .debug_loc.  */
   DEBUG_LOC_START_LENGTH = 3,
 
+   /* This is followed by two unsigned LEB128 operands. The values of these
+      operands are the starting and ending offsets, respectively, relative to
+      the applicable base address. */
+  DEBUG_LOC_OFFSET_PAIR = 4,
+
   /* An internal value indicating there is insufficient data.  */
   DEBUG_LOC_BUFFER_OVERFLOW = -1,
 
@@ -232,7 +237,7 @@ decode_debug_loclists_addresses (struct dwarf2_per_cu_data *per_cu,
 	return DEBUG_LOC_BUFFER_OVERFLOW;
       *high = u64;
       *new_ptr = loc_ptr;
-      return DEBUG_LOC_START_END;
+      return DEBUG_LOC_OFFSET_PAIR;
     /* Following cases are not supported yet.  */
     case DW_LLE_startx_endx:
     case DW_LLE_start_end:
@@ -332,7 +337,7 @@ dwarf2_find_location_expression (struct dwarf2_loclist_baton *baton,
       enum debug_loc_kind kind;
       const gdb_byte *new_ptr = NULL; /* init for gcc -Wall */
 
-      if (baton->from_dwo)
+      if (baton->per_cu->version () < 5 && baton->from_dwo)
 	kind = decode_debug_loc_dwo_addresses (baton->per_cu,
 					       loc_ptr, buf_end, &new_ptr,
 					       &low, &high, byte_order);
@@ -358,6 +363,7 @@ dwarf2_find_location_expression (struct dwarf2_loclist_baton *baton,
 	  continue;
 	case DEBUG_LOC_START_END:
 	case DEBUG_LOC_START_LENGTH:
+	case DEBUG_LOC_OFFSET_PAIR:
 	  break;
 	case DEBUG_LOC_BUFFER_OVERFLOW:
 	case DEBUG_LOC_INVALID_ENTRY:
@@ -369,9 +375,11 @@ dwarf2_find_location_expression (struct dwarf2_loclist_baton *baton,
 
       /* Otherwise, a location expression entry.
 	 If the entry is from a DWO, don't add base address: the entry is from
-	 .debug_addr which already has the DWARF "base address".  We still add
-	 base_offset in case we're debugging a PIE executable.  */
-      if (baton->from_dwo)
+	 .debug_addr which already has the DWARF "base address". We still add
+	 base_offset in case we're debugging a PIE executable. However, if the
+	 entry is DW_LLE_offset_pair from a DWO, add the base address as the
+	 operands are offsets relative to the applicable base address. */
+      if (baton->from_dwo && kind != DEBUG_LOC_OFFSET_PAIR)
 	{
 	  low += base_offset;
 	  high += base_offset;
-- 
2.17.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 3/3] DWARFv5: Info address command error in gdb with DWARFfv5.
  2020-03-30 15:21 [PATCH v2 1/3] Support for DW_AT_loclists_base and DW_FORM_loclistx nitachra
  2020-03-30 15:21 ` [PATCH v2 2/3] DWARFv5: Handle location list for split dwarf nitachra
@ 2020-03-30 15:21 ` nitachra
  2020-04-01 19:24   ` Tom Tromey
  2020-03-30 16:07 ` [PATCH v2 1/3] Support for DW_AT_loclists_base and DW_FORM_loclistx Simon Marchi
  2020-04-01 19:16 ` Tom Tromey
  3 siblings, 1 reply; 11+ messages in thread
From: nitachra @ 2020-03-30 15:21 UTC (permalink / raw)
  To: gdb-patches, simark; +Cc: JiniSusan.George, tom, nitachra

GDB throws the error 'Unrecognized DWARF opcode 0x02 at 2' when running
Info address command with the executable file compiled with -gdwarf-5 flag.
This patch fixes this error.

Tested by running the testsuite before and after the patch and there is
no increase in the number of test cases that fails. Tested with both
-gdwarf-4 and -gdwarf-5 flags. Also tested -gslit-dwarf along with
-gdwarf-4 as well as -gdwarf-5 flags. Used clang version 10.0.0.
This is the test case used-

void bar(int arr[], int l, int m, int r) {
    int i, j, k, n1= m - l + 1, n2= r - m, L[n1], R[n2];
    for (i = 0; i < n1; i++)
        L[i] = arr[l + i];
    for (j = 0; j < n2; j++)
        R[j] = arr[m + 1+ j];
}

int main()
{
    int arr[] = {12, 11};
    bar(arr,0,1,2);
    return 0;
}

clang -gdwarf-5 test.c -o test.out

gdb test.out
gdb> start
gdb> step
gdb> step
gdb> step
gdb> step
gdb> info address L
Symbol "L" is multi-location:
  Range 0x7c04007902bc5084-0x67fb876440700: a complex DWARF expression:
     0: DW_OP_breg16 1 [$rip]
Unrecognized DWARF opcode 0x02 at 2

gdb/dwarf2/ChangeLog:

*loc.c (loclist_describe_location): Call the function decode_debug_loclists_
 addresses if DWARF version is 5 or more because DW_LLE_start* or DW_LLE_offset_pair
 with DW_LLE_base_addressx are being emitted in DWARFv5.
 Add the newly added kind DW_LOC_OFFSET_PAIR also.
 The length of location description is an unsigned ULEB integer in DWARFv5 instead of
 unsigned integer.

Signed-off-by: nitachra <Nitika.Achra@amd.com>
---
 gdb/dwarf2/loc.c | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/gdb/dwarf2/loc.c b/gdb/dwarf2/loc.c
index 62bec79035..94be09a293 100644
--- a/gdb/dwarf2/loc.c
+++ b/gdb/dwarf2/loc.c
@@ -4453,15 +4453,20 @@ loclist_describe_location (struct symbol *symbol, CORE_ADDR addr,
       enum debug_loc_kind kind;
       const gdb_byte *new_ptr = NULL; /* init for gcc -Wall */
 
-      if (dlbaton->from_dwo)
+      if (dlbaton->per_cu->version () < 5 && dlbaton->from_dwo)
 	kind = decode_debug_loc_dwo_addresses (dlbaton->per_cu,
 					       loc_ptr, buf_end, &new_ptr,
 					       &low, &high, byte_order);
-      else
+      else if (dlbaton->per_cu->version () < 5)
 	kind = decode_debug_loc_addresses (loc_ptr, buf_end, &new_ptr,
 					   &low, &high,
 					   byte_order, addr_size,
 					   signed_addr_p);
+      else
+	kind = decode_debug_loclists_addresses (dlbaton->per_cu,
+						loc_ptr, buf_end, &new_ptr,
+						&low, &high, byte_order,
+						addr_size, signed_addr_p);
       loc_ptr = new_ptr;
       switch (kind)
 	{
@@ -4475,6 +4480,7 @@ loclist_describe_location (struct symbol *symbol, CORE_ADDR addr,
 	  continue;
 	case DEBUG_LOC_START_END:
 	case DEBUG_LOC_START_LENGTH:
+	case DEBUG_LOC_OFFSET_PAIR:
 	  break;
 	case DEBUG_LOC_BUFFER_OVERFLOW:
 	case DEBUG_LOC_INVALID_ENTRY:
@@ -4491,8 +4497,17 @@ loclist_describe_location (struct symbol *symbol, CORE_ADDR addr,
       low = gdbarch_adjust_dwarf2_addr (gdbarch, low);
       high = gdbarch_adjust_dwarf2_addr (gdbarch, high);
 
-      length = extract_unsigned_integer (loc_ptr, 2, byte_order);
-      loc_ptr += 2;
+      if (dlbaton->per_cu->version () < 5)
+	{
+	length = extract_unsigned_integer (loc_ptr, 2, byte_order);
+	loc_ptr += 2;
+	}
+      else
+	{
+	unsigned int bytes_read;
+	length = read_unsigned_leb128 (NULL, loc_ptr, &bytes_read);
+	loc_ptr += bytes_read;
+	}
 
       /* (It would improve readability to print only the minimum
 	 necessary digits of the second number of the range.)  */
-- 
2.17.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 1/3] Support for DW_AT_loclists_base and DW_FORM_loclistx.
  2020-03-30 15:21 [PATCH v2 1/3] Support for DW_AT_loclists_base and DW_FORM_loclistx nitachra
  2020-03-30 15:21 ` [PATCH v2 2/3] DWARFv5: Handle location list for split dwarf nitachra
  2020-03-30 15:21 ` [PATCH v2 3/3] DWARFv5: Info address command error in gdb with DWARFfv5 nitachra
@ 2020-03-30 16:07 ` Simon Marchi
  2020-04-01 19:16 ` Tom Tromey
  3 siblings, 0 replies; 11+ messages in thread
From: Simon Marchi @ 2020-03-30 16:07 UTC (permalink / raw)
  To: nitachra, gdb-patches; +Cc: JiniSusan.George, tom

On 2020-03-30 11:21 a.m., nitachra wrote:
> Thanks for the review. I have made all the style changes.
> 
> Regards,
> Nitika

Hmm, shouldn't this be v3?

Simon

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 1/3] Support for DW_AT_loclists_base and DW_FORM_loclistx.
  2020-03-30 15:21 [PATCH v2 1/3] Support for DW_AT_loclists_base and DW_FORM_loclistx nitachra
                   ` (2 preceding siblings ...)
  2020-03-30 16:07 ` [PATCH v2 1/3] Support for DW_AT_loclists_base and DW_FORM_loclistx Simon Marchi
@ 2020-04-01 19:16 ` Tom Tromey
  3 siblings, 0 replies; 11+ messages in thread
From: Tom Tromey @ 2020-04-01 19:16 UTC (permalink / raw)
  To: nitachra; +Cc: gdb-patches, simark, JiniSusan.George, tom

>>>>> ">" == nitachra  <Nitika.Achra@amd.com> writes:

Still some style nits here.  I listed them below.

What I primarily don't understand is:

+  gdb::optional<ULONGEST> loclist_base;

This uses an optional but it's never checked for validity.
It seems like it should be checked somewhere.

>> +read_loclist_header (struct loclist_header *header, struct dwarf2_section_info *section)

Over-long line.

>> +/* 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)

Here too.

>> +/* Given a DW_FORM_loclistx value LOCLIST_INDEX, fetch the offset from the array

Here too.

>> +    complaint(_("DW_FORM_loclistx used without .debug_loclists section [in module %s]"),
>> +	objfile_name (objfile));

Space before the paren after "complaint"; second line should line up
just after the "(".

>> +    complaint(_("DW_FORM_loclistx pointing outside of "
>> +	".debug_loclists offset array [in module %s]"),
>> +	objfile_name (objfile));

Formatting here too, and another complaint in this function.

>>        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;

This doesn't look like it's indented properly.  See if it lines up with
the other cases.

Tom

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 3/3] DWARFv5: Info address command error in gdb with DWARFfv5.
  2020-03-30 15:21 ` [PATCH v2 3/3] DWARFv5: Info address command error in gdb with DWARFfv5 nitachra
@ 2020-04-01 19:24   ` Tom Tromey
  0 siblings, 0 replies; 11+ messages in thread
From: Tom Tromey @ 2020-04-01 19:24 UTC (permalink / raw)
  To: nitachra; +Cc: gdb-patches, simark, JiniSusan.George, tom

>>>>> ">" == nitachra  <Nitika.Achra@amd.com> writes:

>>  The length of location description is an unsigned ULEB integer in DWARFv5 instead of
>>  unsigned integer.

I'd appreciate a reference to the section here.
Is it 2.6.2?

>> +      if (dlbaton->per_cu->version () < 5)
>> +	{
>> +	length = extract_unsigned_integer (loc_ptr, 2, byte_order);
>> +	loc_ptr += 2;
>> +	}
>> +      else
>> +	{
>> +	unsigned int bytes_read;
>> +	length = read_unsigned_leb128 (NULL, loc_ptr, &bytes_read);
>> +	loc_ptr += bytes_read;
>> +	}
 
The formatting looks off here.  See the GNU standards, or the examples
elsewhere in this file, to see how it should be done.

Tom

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 1/3] Support for DW_AT_loclists_base and DW_FORM_loclistx.
@ 2020-04-06  9:59 nitachra
  0 siblings, 0 replies; 11+ messages in thread
From: nitachra @ 2020-04-06  9:59 UTC (permalink / raw)
  To: gdb-patches, tom; +Cc: JiniSusan.George, nitachra

>Thank you.

>This still has one formatting nit, I think:

>>> +  if (cu->dwo_unit != nullptr)
>>> +  {
>>> +    if (cu->header.initial_length_size == 4)
>>> +      return LOCLIST_HEADER_SIZE32;
>>> +    return LOCLIST_HEADER_SIZE64;
>>> +  }

>The braces and their contents should be shifted right by 2 spaces.

>This is ok with that change.

Hi Tom,

Thank you. Done the formatting change. Can you please push this for me as I don't
have the required permission?

Regards,
Nitika


---

This patch handles DW_AT_loclists_base and DW_FORM_loclistx.
DW_AT_loclists_base is a new attribute added in DWARFv5 which
points to the beginning of the offset table of .debug_loclists
section. Reference to the location list (DW_FORM_loclistx) is
interpreted relative to this base. DW_FORM_loclistx is a new
form added in DWARFv5 which is used to access location list.

Tested by running the testsuite before and after the patch and there
is no increase in the number of test cases that fails. Tested with both
-gdwarf-4 and -gdwarf-5 flags. Also tested -gsplit-dwarf along with
-gdwarf-4 as well as -gdwarf5 flags. Used clang 10.0.0 for testing.

gdb/dwarf2/ChangeLog:

   *read.c (cu_debug_loc_section): Added the declaration for the function.
   (read_loclist_index): New function declaration.
   (lookup_loclist_base): New function declaration.
   (read_loclist_header): New function declaration
   (dwarf2_cu): Added 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.
   *attribute.c (form_is_section_offset): Handle DW_FORM_loclistx.

Signed-off-by: nitachra <Nitika.Achra@amd.com>
---
 gdb/dwarf2/attribute.c |   3 +-
 gdb/dwarf2/read.c      | 134 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 136 insertions(+), 1 deletion(-)

diff --git a/gdb/dwarf2/attribute.c b/gdb/dwarf2/attribute.c
index 0e5a8c8f53..9ceacf0409 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 8c5046ef41..0724a0d799 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 @@ struct dwarf2_cu
      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
@@ -8564,6 +8600,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:
@@ -12029,6 +12066,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;
@@ -17496,6 +17538,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;
@@ -18298,6 +18344,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
@@ -18313,6 +18437,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:
@@ -18417,6 +18544,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;
-- 
2.17.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 1/3] Support for DW_AT_loclists_base and DW_FORM_loclistx.
  2020-04-03 16:15 nitachra
@ 2020-04-03 18:07 ` Tom Tromey
  0 siblings, 0 replies; 11+ messages in thread
From: Tom Tromey @ 2020-04-03 18:07 UTC (permalink / raw)
  To: nitachra; +Cc: gdb-patches, tom, JiniSusan.George

>>>>> ">" == nitachra  <Nitika.Achra@amd.com> writes:

>> gdb/dwarf2/ChangeLog:

>>    *read.c (cu_debug_loc_section): Added the declaration for the function.
>>    (read_loclist_index): New function declaration.
>>    (lookup_loclist_base): New function declaration.
>>    (read_loclist_header): New function declaration
>>    (dwarf2_cu): Added 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.
>>    *attribute.c (form_is_section_offset): Handle DW_FORM_loclistx.

Thank you.

This still has one formatting nit, I think:

>> +  if (cu->dwo_unit != nullptr)
>> +  {
>> +    if (cu->header.initial_length_size == 4)
>> +      return LOCLIST_HEADER_SIZE32;
>> +    return LOCLIST_HEADER_SIZE64;
>> +  }

The braces and their contents should be shifted right by 2 spaces.

This is ok with that change.

Tom

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 1/3] Support for DW_AT_loclists_base and DW_FORM_loclistx.
@ 2020-04-03 16:15 nitachra
  2020-04-03 18:07 ` Tom Tromey
  0 siblings, 1 reply; 11+ messages in thread
From: nitachra @ 2020-04-03 16:15 UTC (permalink / raw)
  To: gdb-patches, tom; +Cc: JiniSusan.George, nitachra

Tom>Still some style nits here.  I listed them below.

Tom>What I primarily don't understand is:

Tom>+  gdb::optional<ULONGEST> loclist_base;

Tom>This uses an optional but it's never checked for validity.
Tom>It seems like it should be checked somewhere.

I changed it to ULONGEST as there is no need to check.

Tom>> +read_loclist_header (struct loclist_header *header, struct
Tom>> dwarf2_section_info *section)

Tom>Over-long line.

Done

Tom>> +/* Return the DW_AT_loclists_base value for the CU.  */
Tom>> +static ULONGEST
Tom>> +lookup_loclist_base (struct dwarf2_cu *cu)
Tom>> +{
Tom>> +  /* For the .dwo unit, the loclist_base points to the first
offset
Tom>> following
Tom>> +     the header. The header consists of the following entities-
Tom>> +     1. Unit Length (4 bytes for 32 bit DWARF format, and 12
bytes
Tom>> for the 64 bit format)

Tom>Here too.

Done

Tom>> +/* Given a DW_FORM_loclistx value LOCLIST_INDEX, fetch the offset
Tom>> from the array

Tom>Here too.

Done

Tom>> +    complaint(_("DW_FORM_loclistx used without .debug_loclists
Tom>> section [in module %s]"),
Tom>> +    objfile_name (objfile));

Tom>Space before the paren after "complaint"; second line should line up
Tom>just after the "(".

Done
Tom>> +    complaint(_("DW_FORM_loclistx pointing outside of "
Tom>> +    ".debug_loclists offset array [in module %s]"),
Tom>> +    objfile_name (objfile));

Tom>Formatting here too, and another complaint in this function.

Done

Tom>>        info_ptr += bytes_read;
Tom>>        break;
Tom>> +    case DW_FORM_loclistx:
Tom>> +    {
Tom>> +      *need_reprocess = true;
Tom>> +      DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr,
Tom>> &bytes_read);
Tom>> +      info_ptr += bytes_read;
Tom>> +    }
Tom>> +      break;

Tom>This doesn't look like it's indented properly.  See if it lines up
Tom>with the other cases

Done

Regards,
Nitika
---

This patch handles DW_AT_loclists_base and DW_FORM_loclistx.
DW_AT_loclists_base is a new attribute added in DWARFv5 which
points to the beginning of the offset table of .debug_loclists
section. Reference to the location list (DW_FORM_loclistx) is
interpreted relative to this base. DW_FORM_loclistx is a new
form added in DWARFv5 which is used to access location list.

Tested by running the testsuite before and after the patch and there
is no increase in the number of test cases that fails. Tested with both
-gdwarf-4 and -gdwarf-5 flags. Also tested -gsplit-dwarf along with
-gdwarf-4 as well as -gdwarf5 flags. Used clang 10.0.0 for testing.

gdb/dwarf2/ChangeLog:

   *read.c (cu_debug_loc_section): Added the declaration for the function.
   (read_loclist_index): New function declaration.
   (lookup_loclist_base): New function declaration.
   (read_loclist_header): New function declaration
   (dwarf2_cu): Added 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.
   *attribute.c (form_is_section_offset): Handle DW_FORM_loclistx.

gdb/testsuite/ChangeLog:

   *gdb.dwarf2/dw5-form-loclistx.exp: New file.
   *gdb.dwarf2/dw5-form-loclistx.c: New file.

Signed-off-by: nitachra <Nitika.Achra@amd.com>
---
 gdb/dwarf2/attribute.c |   3 +-
 gdb/dwarf2/read.c      | 134 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 136 insertions(+), 1 deletion(-)

diff --git a/gdb/dwarf2/attribute.c b/gdb/dwarf2/attribute.c
index 0e5a8c8f53..9ceacf0409 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 8c5046ef41..d2fb77847f 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 @@ struct dwarf2_cu
      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
@@ -8564,6 +8600,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:
@@ -12029,6 +12066,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;
@@ -17496,6 +17538,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;
@@ -18298,6 +18344,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
@@ -18313,6 +18437,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:
@@ -18417,6 +18544,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;
-- 
2.17.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 1/3] Support for DW_AT_loclists_base and DW_FORM_loclistx.
  2020-03-29 16:07 nitachra
@ 2020-03-29 23:58 ` Simon Marchi
  0 siblings, 0 replies; 11+ messages in thread
From: Simon Marchi @ 2020-03-29 23:58 UTC (permalink / raw)
  To: nitachra, gdb-patches; +Cc: JiniSusan.George, tom

Hi,

A quick pass for style.

On 2020-03-29 12:07 p.m., nitachra wrote:
> This patch handles DW_AT_loclists_base and DW_FORM_loclistx.
> DW_AT_loclists_base is a new attribute added in DWARFv5 which
> points to the beginning of the offset table of .debug_loclist
> section. Reference to the location list (DW_FORM_loclistx) is
> interpreted relative to this base. DW_FORM_loclistx is a new
> form added in DWARFv5 which is used to access location list.
> 
> Tested by running the testsuite before and after the patch and there
> is no increase in the number of test cases that fails. Tested with both
> -gdwarf-4 and -gdwarf-5 flags. Also tested -gsplit-dwarf along with
> -gdwarf-4 as well as -gdwarf5 flags. Used clang 10.0.0 for testing.
> 
> gdb/dwarf2/ChangeLog:
> 
>    *read.c (cu_debug_loc_section): Added the declaration for the function.
>    (read_loclist_index): New function declaration.
>    (lookup_loclist_base): New function declaration.
>    (read_loclist_header): New function declaration
>    (dwarf2_cu): Added loclist_base and loclist_header field.
>    (dwarf2_locate_dwo_sections): Handle .debug_loclist.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.
>    *attribute.c (form_is_section_offset): Handle DW_FORM_loclistx.
> 
> gdb/testsuite/ChangeLog:
> 
>    *gdb.dwarf2/dw5-form-loclistx.exp: New file.
>    *gdb.dwarf2/dw5-form-loclistx.c: New file.
> 
> Signed-off-by: nitachra <Nitika.Achra@amd.com>
> ---
>  gdb/dwarf2/attribute.c |   3 +-
>  gdb/dwarf2/read.c      | 127 +++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 129 insertions(+), 1 deletion(-)
> 
> diff --git a/gdb/dwarf2/attribute.c b/gdb/dwarf2/attribute.c
> index 0e5a8c8f53..9ceacf0409 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 8c5046ef41..ab3bc2ac5d 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_loclist section header for 32-bit DWARF format. */
> +#define LOCLIST_HEADER_SIZE32 12
> +
> +/* Size of .debug_loclist 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_loclist) 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. */

Align the wrapped lines with the first line (like you did for comments below).

Use two spaces after the last period (happens in multiple comments in this patch).

> +  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 @@ struct dwarf2_cu
>       whether the DW_AT_ranges attribute came from the skeleton or DWO.  */
>    ULONGEST ranges_base = 0;
>  
> +  /* The DW_AT_loclists_base attribute if present. */
> +  gdb::optional<ULONGEST> loclist_base;
> +
>    /* 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_loclist 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
> @@ -8564,6 +8600,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:
> @@ -12029,6 +12066,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;
> @@ -17495,6 +17537,9 @@ read_full_die_1 (const struct die_reader_specs *reader,
>    struct attribute *attr = die->attr (DW_AT_str_offsets_base);
>    if (attr != nullptr)
>      cu->str_offsets_base = DW_UNSND (attr);
> +  attr = die->attr (DW_AT_loclists_base);

Add an empty line before this, to make it clear it's not related to the lines above.

> +  if (attr != nullptr)
> +    cu->loclist_base = DW_UNSND (attr);
>  
>    auto maybe_addr_base = die->addr_base ();
>    if (maybe_addr_base.has_value ())
> @@ -18298,6 +18343,78 @@ partial_die_info::fixup (struct dwarf2_cu *cu)
>    fixup_called = 1;
>  }
>  
> +static void
> +read_loclist_header (struct loclist_header *header, struct dwarf2_section_info *section)
> +{

Please add an intro comment for all new functions.  It doesn't have to be long, but
it should at least describe the general intent of the function, and ideally its
parameters.

> +  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);
> +}
> +
> +

Remove one empty line here.

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

When comparing pointers, do an explicit comparison with nullptr:

  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. */

When referring to a variable/parameter name, put it in capital letters:

/* Given a DW_FORM_loclistx value LOCLIST_INDEX, ...

> +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;

Last line should be indented with 4 spaces (i.e. one mode indent than the previous line).

> +  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_loclist section [in module %s]"),

The section name is ".debug_loclists", with an s at the end.  This error happens at a few other spots.

> +	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_loclist 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_loclist section [in module %s]"),
> +	objfile_name (objfile));
> +  const gdb_byte *info_ptr = (section->buffer + loclist_base +
> +	loclist_index * cu->header.offset_size);

Align the wrapped line with the opening parenthesis, like this:

  const gdb_byte *info_ptr = (section->buffer + loclist_base +
			      loclist_index * cu->header.offset_size);

Or put the right-hand-side expression completely on the new line:

  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;
> +}

Please use some empty liens strategically, to separate the different logical steps
in the function.

Simon

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 1/3] Support for DW_AT_loclists_base and DW_FORM_loclistx.
@ 2020-03-29 16:07 nitachra
  2020-03-29 23:58 ` Simon Marchi
  0 siblings, 1 reply; 11+ messages in thread
From: nitachra @ 2020-03-29 16:07 UTC (permalink / raw)
  To: gdb-patches; +Cc: JiniSusan.George, tamur, tom, simark, nitachra

This patch handles DW_AT_loclists_base and DW_FORM_loclistx.
DW_AT_loclists_base is a new attribute added in DWARFv5 which
points to the beginning of the offset table of .debug_loclist
section. Reference to the location list (DW_FORM_loclistx) is
interpreted relative to this base. DW_FORM_loclistx is a new
form added in DWARFv5 which is used to access location list.

Tested by running the testsuite before and after the patch and there
is no increase in the number of test cases that fails. Tested with both
-gdwarf-4 and -gdwarf-5 flags. Also tested -gsplit-dwarf along with
-gdwarf-4 as well as -gdwarf5 flags. Used clang 10.0.0 for testing.

gdb/dwarf2/ChangeLog:

   *read.c (cu_debug_loc_section): Added the declaration for the function.
   (read_loclist_index): New function declaration.
   (lookup_loclist_base): New function declaration.
   (read_loclist_header): New function declaration
   (dwarf2_cu): Added loclist_base and loclist_header field.
   (dwarf2_locate_dwo_sections): Handle .debug_loclist.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.
   *attribute.c (form_is_section_offset): Handle DW_FORM_loclistx.

gdb/testsuite/ChangeLog:

   *gdb.dwarf2/dw5-form-loclistx.exp: New file.
   *gdb.dwarf2/dw5-form-loclistx.c: New file.

Signed-off-by: nitachra <Nitika.Achra@amd.com>
---
 gdb/dwarf2/attribute.c |   3 +-
 gdb/dwarf2/read.c      | 127 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 129 insertions(+), 1 deletion(-)

diff --git a/gdb/dwarf2/attribute.c b/gdb/dwarf2/attribute.c
index 0e5a8c8f53..9ceacf0409 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 8c5046ef41..ab3bc2ac5d 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_loclist section header for 32-bit DWARF format. */
+#define LOCLIST_HEADER_SIZE32 12
+
+/* Size of .debug_loclist 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_loclist) 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 @@ struct dwarf2_cu
      whether the DW_AT_ranges attribute came from the skeleton or DWO.  */
   ULONGEST ranges_base = 0;
 
+  /* The DW_AT_loclists_base attribute if present. */
+  gdb::optional<ULONGEST> loclist_base;
+
   /* 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_loclist 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
@@ -8564,6 +8600,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:
@@ -12029,6 +12066,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;
@@ -17495,6 +17537,9 @@ read_full_die_1 (const struct die_reader_specs *reader,
   struct attribute *attr = die->attr (DW_AT_str_offsets_base);
   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 ())
@@ -18298,6 +18343,78 @@ partial_die_info::fixup (struct dwarf2_cu *cu)
   fixup_called = 1;
 }
 
+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);
+}
+
+
+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)
+  {
+    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_loclist 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_loclist 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_loclist 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
@@ -18313,6 +18430,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:
@@ -18417,6 +18537,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;
-- 
2.17.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2020-04-06  9:59 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-30 15:21 [PATCH v2 1/3] Support for DW_AT_loclists_base and DW_FORM_loclistx nitachra
2020-03-30 15:21 ` [PATCH v2 2/3] DWARFv5: Handle location list for split dwarf nitachra
2020-03-30 15:21 ` [PATCH v2 3/3] DWARFv5: Info address command error in gdb with DWARFfv5 nitachra
2020-04-01 19:24   ` Tom Tromey
2020-03-30 16:07 ` [PATCH v2 1/3] Support for DW_AT_loclists_base and DW_FORM_loclistx Simon Marchi
2020-04-01 19:16 ` Tom Tromey
  -- strict thread matches above, loose matches on Subject: below --
2020-04-06  9:59 nitachra
2020-04-03 16:15 nitachra
2020-04-03 18:07 ` Tom Tromey
2020-03-29 16:07 nitachra
2020-03-29 23:58 ` Simon Marchi

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