LVU: dump loclists with locviews
authorAlexandre Oliva <aoliva@redhat.com>
Fri, 22 Sep 2017 20:05:51 +0000 (17:05 -0300)
committerAlexandre Oliva <aoliva@redhat.com>
Fri, 22 Sep 2017 20:05:51 +0000 (17:05 -0300)
When dumping location lists, also dump locview lists that may be
interspersed with them, and bring view pairs next to the corresponding
location list entries.

This patch supports DW_AT_GNU_locviews as a separate attribute for
DWARF4- loc_lists and split (dwo) loclists, as well as DWARF5
loclists.

It also supports, in DWARF5 loclists, the proposed
DW_LLE_GNU_view_pair loclist entry type proposed for DWARF6.

The tests use 32-bit DWARF, even on 64-bit targets, resolving offsets
to constants so as to reduce the risk that relocations be created for
them, or that the offsets be rejected as nonconstants.

The patch also adds an xfail to an unrelated test, namely dw5, so that
no unexpected fails remain on nds32*-elf, one of the tested targets.

Reviewed-by: Alan Modra <amodra@gmail.com>
for  include/ChangeLog

* dwarf2.def (DW_AT_GNU_locviews): New.
* dwarf2.h (enum dwarf_location_list_entry_type): Add
DW_LLE_GNU_view_pair.
(DW_LLE_view_pair): Define.

for  binutils/ChangeLog

* dwarf.h (debug_info): Add loc_views and num_loc_views.
* dwarf.c (vm1): New constant.
(print_dwarf_view): New function.
(read_and_display_attr_value): Support DW_AT_GNU_locviews.
(process_debug_info): Keep num_loc_offsets and num_loc_views
in sync.
(display_view_pair_list): New function.
(display_loc_list_dwo): Take vstart_ptr; update it.  Dump
location view pairs before the range they apply to, when a
viewlist augments the loc list.
(display_loc_list): Likewise.  Check view numbers in range
tests.
(display_loclists_list): Likewise.  Handle view pair entries,
and warn on trailing ones.
(loc_views): New variable.
(loc_offsets_compar): Compare loc_views if loc_offsets are the
same.
(display_debug_loc): Check and sort loc_views too.  Accept
loc_view as expected_start.  Skip if lists and views are the
same.  Dump locview list separately in order, and pass the
locview list base to each list dump function.  Warn and skip
overlap and hole checking if we find loclists and locviews to
not be adjacent.
* testsuite/binutils-all/locview-1.s: New.
* testsuite/binutils-all/readelf.locview-1: New.
* testsuite/binutils-all/locview-2.s: New.
* testsuite/binutils-all/readelf.locview-2: New.
* testsuite/binutils-all/readelf.exp: Run new tests.  Fix
option spelling in pr18374 fail message.  XFAIL dw5 test on
nds32*-elf.

binutils/ChangeLog
binutils/dwarf.c
binutils/dwarf.h
binutils/testsuite/binutils-all/locview-1.s [new file with mode: 0644]
binutils/testsuite/binutils-all/locview-2.s [new file with mode: 0644]
binutils/testsuite/binutils-all/readelf.exp
binutils/testsuite/binutils-all/readelf.locview-1 [new file with mode: 0644]
binutils/testsuite/binutils-all/readelf.locview-2 [new file with mode: 0644]
include/ChangeLog
include/dwarf2.def
include/dwarf2.h

index 87ee8a4..0374084 100644 (file)
@@ -1,3 +1,36 @@
+2017-09-22  Alexandre Oliva <aoliva@redhat.com>
+
+       * dwarf.h (debug_info): Add loc_views and num_loc_views.
+       * dwarf.c (vm1): New constant.
+       (print_dwarf_view): New function.
+       (read_and_display_attr_value): Support DW_AT_GNU_locviews.
+       (process_debug_info): Keep num_loc_offsets and num_loc_views
+       in sync.
+       (display_view_pair_list): New function.
+       (display_loc_list_dwo): Take vstart_ptr; update it.  Dump
+       location view pairs before the range they apply to, when a
+       viewlist augments the loc list.
+       (display_loc_list): Likewise.  Check view numbers in range
+       tests.
+       (display_loclists_list): Likewise.  Handle view pair entries,
+       and warn on trailing ones.
+       (loc_views): New variable.
+       (loc_offsets_compar): Compare loc_views if loc_offsets are the
+       same.
+       (display_debug_loc): Check and sort loc_views too.  Accept
+       loc_view as expected_start.  Skip if lists and views are the
+       same.  Dump locview list separately in order, and pass the
+       locview list base to each list dump function.  Warn and skip
+       overlap and hole checking if we find loclists and locviews to
+       not be adjacent.
+       * testsuite/binutils-all/locview-1.s: New.
+       * testsuite/binutils-all/readelf.locview-1: New.
+       * testsuite/binutils-all/locview-2.s: New.
+       * testsuite/binutils-all/readelf.locview-2: New.
+       * testsuite/binutils-all/readelf.exp: Run new tests.  Fix
+       option spelling in pr18374 fail message.  XFAIL dw5 test on
+       nds32*-elf.
+
 2017-09-22  Alan Modra  <amodra@gmail.com>
 
        * testsuite/binutils-all/readelf.exp: Don't perror and exit on
index d2fc799..af8732b 100644 (file)
@@ -74,6 +74,10 @@ unsigned long dwarf_start_die;
 
 int dwarf_check = 0;
 
+/* Convenient constant, to avoid having to cast -1 to dwarf_vma when
+   testing whether e.g. a locview list is present.  */
+static const dwarf_vma vm1 = -1;
+
 /* Collection of CU/TU section sets from .debug_cu_index and .debug_tu_index
    sections.  For version 1 package files, each set is stored in SHNDX_POOL
    as a zero-terminated list of section indexes comprising one set of debug
@@ -239,6 +243,26 @@ print_dwarf_vma (dwarf_vma value, unsigned num_bytes)
   printf ("%s ", dwarf_vmatoa_1 (NULL, value, num_bytes));
 }
 
+/* Print a view number in hexadecimal value, with the same width
+   print_dwarf_vma would have printed it with the same num_bytes.
+   Print blanks for zero view, unless force is nonzero.  */
+
+static void
+print_dwarf_view (dwarf_vma value, unsigned num_bytes, int force)
+{
+  int len;
+  if (!num_bytes)
+    len = 4;
+  else
+    len = num_bytes * 2;
+
+  assert (value == (unsigned long) value);
+  if (value || force)
+    printf ("v%0*lx ", len - 1, (unsigned long) value);
+  else
+    printf ("%*s", len + 1, "");
+}
+
 /* Format a 64-bit value, given as two 32-bit values, in hex.
    For reentrancy, this uses a buffer provided by the caller.  */
 
@@ -2012,6 +2036,7 @@ read_and_display_attr_value (unsigned long attribute,
          have_frame_base = 1;
          /* Fall through.  */
        case DW_AT_location:
+       case DW_AT_GNU_locviews:
        case DW_AT_string_length:
        case DW_AT_return_addr:
        case DW_AT_data_member_location:
@@ -2041,6 +2066,9 @@ read_and_display_attr_value (unsigned long attribute,
                  debug_info_p->loc_offsets = (dwarf_vma *)
                    xcrealloc (debug_info_p->loc_offsets,
                               lmax, sizeof (*debug_info_p->loc_offsets));
+                 debug_info_p->loc_views = (dwarf_vma *)
+                   xcrealloc (debug_info_p->loc_views,
+                              lmax, sizeof (*debug_info_p->loc_views));
                  debug_info_p->have_frame_base = (int *)
                    xcrealloc (debug_info_p->have_frame_base,
                               lmax, sizeof (*debug_info_p->have_frame_base));
@@ -2048,9 +2076,23 @@ read_and_display_attr_value (unsigned long attribute,
                }
              if (this_set != NULL)
                uvalue += this_set->section_offsets [DW_SECT_LOC];
-             debug_info_p->loc_offsets [num] = uvalue;
              debug_info_p->have_frame_base [num] = have_frame_base;
-             debug_info_p->num_loc_offsets++;
+             if (attribute != DW_AT_GNU_locviews)
+               {
+                 debug_info_p->loc_offsets [num] = uvalue;
+                 debug_info_p->num_loc_offsets++;
+                 assert (debug_info_p->num_loc_offsets
+                         - debug_info_p->num_loc_views <= 1);
+               }
+             else
+               {
+                 assert (debug_info_p->num_loc_views <= num);
+                 num = debug_info_p->num_loc_views;
+                 debug_info_p->loc_views [num] = uvalue;
+                 debug_info_p->num_loc_views++;
+                 assert (debug_info_p->num_loc_views
+                         - debug_info_p->num_loc_offsets <= 1);
+               }
            }
          break;
 
@@ -2858,21 +2900,22 @@ process_debug_info (struct dwarf_section *section,
              break;
            }
 
+         debug_info *debug_info_p =
+           (debug_information && unit < alloc_num_debug_info_entries)
+           ? debug_information + unit : NULL;
+
+         assert (!debug_info_p
+                 || (debug_info_p->num_loc_offsets
+                     == debug_info_p->num_loc_views));
+
          for (attr = entry->first_attr;
               attr && attr->attribute;
               attr = attr->next)
            {
-             debug_info *arg;
-
              if (! do_loc && do_printing)
                /* Show the offset from where the tag was extracted.  */
                printf ("    <%lx>", (unsigned long)(tags - section_begin));
 
-             if (debug_information && unit < alloc_num_debug_info_entries)
-               arg = debug_information + unit;
-             else
-               arg = NULL;
-
              tags = read_and_display_attr (attr->attribute,
                                            attr->form,
                                            attr->implicit_const,
@@ -2882,12 +2925,37 @@ process_debug_info (struct dwarf_section *section,
                                            compunit.cu_pointer_size,
                                            offset_size,
                                            compunit.cu_version,
-                                           arg,
+                                           debug_info_p,
                                            do_loc || ! do_printing,
                                            section,
                                            this_set);
            }
 
+         /* If a locview attribute appears before a location one,
+            make sure we don't associate it with an earlier
+            loclist. */
+         if (debug_info_p)
+           switch (debug_info_p->num_loc_offsets - debug_info_p->num_loc_views)
+             {
+             case 1:
+               debug_info_p->loc_views [debug_info_p->num_loc_views] = vm1;
+               debug_info_p->num_loc_views++;
+               assert (debug_info_p->num_loc_views
+                       == debug_info_p->num_loc_offsets);
+               break;
+
+             case 0:
+               break;
+
+             case -1:
+               warn(_("DIE has locviews without loclist\n"));
+               debug_info_p->num_loc_views--;
+               break;
+
+             default:
+               assert (0);
+           }
+
          if (entry->children)
            ++level;
        }
@@ -5023,6 +5091,52 @@ is_max_address (dwarf_vma addr, unsigned int pointer_size)
   return ((addr & mask) == mask);
 }
 
+/* Display a view pair list starting at *VSTART_PTR and ending at
+   VLISTEND within SECTION.  */
+
+static void
+display_view_pair_list (struct dwarf_section *section,
+                       unsigned char **vstart_ptr,
+                       unsigned int debug_info_entry,
+                       unsigned char *vlistend)
+{
+  unsigned char *vstart = *vstart_ptr;
+  unsigned char *section_end = section->start + section->size;
+  unsigned int pointer_size = debug_information [debug_info_entry].pointer_size;
+
+  if (vlistend < section_end)
+    section_end = vlistend;
+
+  putchar ('\n');
+
+  while (vstart < section_end)
+    {
+      dwarf_vma off = vstart - section->start;
+      dwarf_vma vbegin, vend;
+
+      unsigned int bytes_read;
+      vbegin = read_uleb128 (vstart, &bytes_read, section_end);
+      vstart += bytes_read;
+      if (vstart == section_end)
+       {
+         vstart -= bytes_read;
+         break;
+       }
+
+      vend = read_uleb128 (vstart, &bytes_read, section_end);
+      vstart += bytes_read;
+
+      printf ("    %8.8lx ", (unsigned long) off);
+
+      print_dwarf_view (vbegin, pointer_size, 1);
+      print_dwarf_view (vend, pointer_size, 1);
+      printf (_("location view pair\n"));
+    }
+
+  putchar ('\n');
+  *vstart_ptr = vstart;
+}
+
 /* Display a location list from a normal (ie, non-dwo) .debug_loc section.  */
 
 static void
@@ -5031,9 +5145,10 @@ display_loc_list (struct dwarf_section *section,
                  unsigned int debug_info_entry,
                  dwarf_vma offset,
                  dwarf_vma base_address,
+                 unsigned char **vstart_ptr,
                  int has_frame_base)
 {
-  unsigned char *start = *start_ptr;
+  unsigned char *start = *start_ptr, *vstart = *vstart_ptr;
   unsigned char *section_end = section->start + section->size;
   unsigned long cu_offset;
   unsigned int pointer_size;
@@ -5067,6 +5182,7 @@ display_loc_list (struct dwarf_section *section,
   while (1)
     {
       dwarf_vma off = offset + (start - *start_ptr);
+      dwarf_vma vbegin = vm1, vend = vm1;
 
       if (start + 2 * pointer_size > section_end)
        {
@@ -5107,6 +5223,24 @@ display_loc_list (struct dwarf_section *section,
          continue;
        }
 
+      if (vstart)
+       {
+         unsigned int bytes_read;
+
+         off = offset + (vstart - *start_ptr);
+
+         vbegin = read_uleb128 (vstart, &bytes_read, section_end);
+         vstart += bytes_read;
+         print_dwarf_view (vbegin, pointer_size, 1);
+
+         vend = read_uleb128 (vstart, &bytes_read, section_end);
+         vstart += bytes_read;
+         print_dwarf_view (vend, pointer_size, 1);
+
+         printf (_("views at %8.8lx for:\n    %*s "),
+                 (unsigned long) off, 8, "");
+       }
+
       if (start + 2 > section_end)
        {
          warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
@@ -5138,9 +5272,9 @@ display_loc_list (struct dwarf_section *section,
       if (need_frame_base && !has_frame_base)
        printf (_(" [without DW_AT_frame_base]"));
 
-      if (begin == end)
+      if (begin == end && vbegin == vend)
        fputs (_(" (start == end)"), stdout);
-      else if (begin > end)
+      else if (begin > end || (begin == end && vbegin > vend))
        fputs (_(" (start > end)"), stdout);
 
       putchar ('\n');
@@ -5149,6 +5283,7 @@ display_loc_list (struct dwarf_section *section,
     }
 
   *start_ptr = start;
+  *vstart_ptr = vstart;
 }
 
 /* Display a location list from a normal (ie, non-dwo) .debug_loclists section.  */
@@ -5159,9 +5294,10 @@ display_loclists_list (struct dwarf_section *section,
                       unsigned int debug_info_entry,
                       dwarf_vma offset,
                       dwarf_vma base_address,
+                      unsigned char **vstart_ptr,
                       int has_frame_base)
 {
-  unsigned char *start = *start_ptr;
+  unsigned char *start = *start_ptr, *vstart = *vstart_ptr;
   unsigned char *section_end = section->start + section->size;
   unsigned long cu_offset;
   unsigned int pointer_size;
@@ -5170,8 +5306,8 @@ display_loclists_list (struct dwarf_section *section,
   unsigned int bytes_read;
 
   /* Initialize it due to a false compiler warning.  */
-  dwarf_vma begin = -1;
-  dwarf_vma end = -1;
+  dwarf_vma begin = -1, vbegin = -1;
+  dwarf_vma end = -1, vend = -1;
   dwarf_vma length;
   int need_frame_base;
 
@@ -5211,6 +5347,22 @@ display_loclists_list (struct dwarf_section *section,
 
       SAFE_BYTE_GET_AND_INC (llet, start, 1, section_end);
 
+      if (vstart && llet == DW_LLE_offset_pair)
+       {
+         off = offset + (vstart - *start_ptr);
+
+         vbegin = read_uleb128 (vstart, &bytes_read, section_end);
+         vstart += bytes_read;
+         print_dwarf_view (vbegin, pointer_size, 1);
+
+         vend = read_uleb128 (vstart, &bytes_read, section_end);
+         vstart += bytes_read;
+         print_dwarf_view (vend, pointer_size, 1);
+
+         printf (_("views at %8.8lx for:\n    %*s "),
+                 (unsigned long) off, 8, "");
+       }
+
       switch (llet)
        {
        case DW_LLE_end_of_list:
@@ -5228,6 +5380,21 @@ display_loclists_list (struct dwarf_section *section,
          print_dwarf_vma (base_address, pointer_size);
          printf (_("(base address)\n"));
          break;
+#ifdef DW_LLE_view_pair
+       case DW_LLE_view_pair:
+         if (vstart)
+           printf (_("View pair entry in loclist with locviews attribute\n"));
+         vbegin = read_uleb128 (start, &bytes_read, section_end);
+         start += bytes_read;
+         print_dwarf_view (vbegin, pointer_size, 1);
+
+         vend = read_uleb128 (start, &bytes_read, section_end);
+         start += bytes_read;
+         print_dwarf_view (vend, pointer_size, 1);
+
+         printf (_("views for:\n"));
+         continue;
+#endif
        default:
          error (_("Invalid location list entry type %d\n"), llet);
          return;
@@ -5262,17 +5429,22 @@ display_loclists_list (struct dwarf_section *section,
       if (need_frame_base && !has_frame_base)
        printf (_(" [without DW_AT_frame_base]"));
 
-      if (begin == end)
+      if (begin == end && vbegin == vend)
        fputs (_(" (start == end)"), stdout);
-      else if (begin > end)
+      else if (begin > end || (begin == end && vbegin > vend))
        fputs (_(" (start > end)"), stdout);
 
       putchar ('\n');
 
       start += length;
+      vbegin = vend = -1;
     }
 
+  if (vbegin != vm1 || vend != vm1)
+    printf (_("Trailing view pair not used in a range"));
+
   *start_ptr = start;
+  *vstart_ptr = vstart;
 }
 
 /* Print a .debug_addr table index in decimal, surrounded by square brackets,
@@ -5295,9 +5467,10 @@ display_loc_list_dwo (struct dwarf_section *section,
                      unsigned char **start_ptr,
                      unsigned int debug_info_entry,
                      dwarf_vma offset,
+                     unsigned char **vstart_ptr,
                      int has_frame_base)
 {
-  unsigned char *start = *start_ptr;
+  unsigned char *start = *start_ptr, *vstart = *vstart_ptr;
   unsigned char *section_end = section->start + section->size;
   unsigned long cu_offset;
   unsigned int pointer_size;
@@ -5340,17 +5513,47 @@ display_loc_list_dwo (struct dwarf_section *section,
        }
 
       SAFE_BYTE_GET_AND_INC (entry_type, start, 1, section_end);
+
+      if (vstart)
+       switch (entry_type)
+         {
+         default:
+           break;
+
+         case 2:
+         case 3:
+         case 4:
+           {
+             dwarf_vma view;
+             dwarf_vma off = offset + (vstart - *start_ptr);
+
+             view = read_uleb128 (vstart, &bytes_read, section_end);
+             vstart += bytes_read;
+             print_dwarf_view (view, 8, 1);
+
+             view = read_uleb128 (vstart, &bytes_read, section_end);
+             vstart += bytes_read;
+             print_dwarf_view (view, 8, 1);
+
+             printf (_("views at %8.8lx for:\n    %*s "),
+                     (unsigned long) off, 8, "");
+
+           }
+           break;
+         }
+
       switch (entry_type)
        {
        case 0: /* A terminating entry.  */
          *start_ptr = start;
+         *vstart_ptr = vstart;
          printf (_("<End of list>\n"));
          return;
        case 1: /* A base-address entry.  */
          idx = read_uleb128 (start, &bytes_read, section_end);
          start += bytes_read;
          print_addr_index (idx, 8);
-         printf ("         ");
+         printf ("%*s", 9 + (vstart ? 2 * 6 : 0), "");
          printf (_("(base address selection entry)\n"));
          continue;
        case 2: /* A start/end entry.  */
@@ -5377,6 +5580,7 @@ display_loc_list_dwo (struct dwarf_section *section,
        default:
          warn (_("Unknown location list entry type 0x%x.\n"), entry_type);
          *start_ptr = start;
+         *vstart_ptr = vstart;
          return;
        }
 
@@ -5413,11 +5617,13 @@ display_loc_list_dwo (struct dwarf_section *section,
     }
 
   *start_ptr = start;
+  *vstart_ptr = vstart;
 }
 
-/* Sort array of indexes in ascending order of loc_offsets[idx].  */
+/* Sort array of indexes in ascending order of loc_offsets[idx] and
+   loc_views.  */
 
-static dwarf_vma *loc_offsets;
+static dwarf_vma *loc_offsets, *loc_views;
 
 static int
 loc_offsets_compar (const void *ap, const void *bp)
@@ -5425,23 +5631,33 @@ loc_offsets_compar (const void *ap, const void *bp)
   dwarf_vma a = loc_offsets[*(const unsigned int *) ap];
   dwarf_vma b = loc_offsets[*(const unsigned int *) bp];
 
-  return (a > b) - (b > a);
+  int ret = (a > b) - (b > a);
+  if (ret)
+    return ret;
+
+  a = loc_views[*(const unsigned int *) ap];
+  b = loc_views[*(const unsigned int *) bp];
+
+  ret = (a > b) - (b > a);
+
+  return ret;
 }
 
 static int
 display_debug_loc (struct dwarf_section *section, void *file)
 {
-  unsigned char *start = section->start;
+  unsigned char *start = section->start, *vstart = NULL;
   unsigned long bytes;
   unsigned char *section_begin = start;
   unsigned int num_loc_list = 0;
   unsigned long last_offset = 0;
+  unsigned long last_view = 0;
   unsigned int first = 0;
   unsigned int i;
   unsigned int j;
   int seen_first_offset = 0;
   int locs_sorted = 1;
-  unsigned char *next;
+  unsigned char *next = start, *vnext = vstart;
   unsigned int *array = NULL;
   const char *suffix = strrchr (section->name, '.');
   int is_dwo = 0;
@@ -5529,6 +5745,7 @@ display_debug_loc (struct dwarf_section *section, void *file)
            {
              /* This is the first location list.  */
              last_offset = debug_information [i].loc_offsets [0];
+             last_view = debug_information [i].loc_views [0];
              first = i;
              seen_first_offset = 1;
              j = 1;
@@ -5539,12 +5756,15 @@ display_debug_loc (struct dwarf_section *section, void *file)
          for (; j < num; j++)
            {
              if (last_offset >
-                 debug_information [i].loc_offsets [j])
+                 debug_information [i].loc_offsets [j]
+                 || (last_offset == debug_information [i].loc_offsets [j]
+                     && last_view > debug_information [i].loc_views [j]))
                {
                  locs_sorted = 0;
                  break;
                }
              last_offset = debug_information [i].loc_offsets [j];
+             last_view = debug_information [i].loc_views [j];
            }
        }
     }
@@ -5553,7 +5773,8 @@ display_debug_loc (struct dwarf_section *section, void *file)
     error (_("No location lists in .debug_info section!\n"));
 
   if (debug_information [first].num_loc_offsets > 0
-      && debug_information [first].loc_offsets [0] != expected_start)
+      && debug_information [first].loc_offsets [0] != expected_start
+      && debug_information [first].loc_views [0] != expected_start)
     warn (_("Location lists in %s section start at 0x%s\n"),
          section->name,
          dwarf_vmatoa ("x", debug_information [first].loc_offsets [0]));
@@ -5568,7 +5789,7 @@ display_debug_loc (struct dwarf_section *section, void *file)
   seen_first_offset = 0;
   for (i = first; i < num_debug_info_entries; i++)
     {
-      dwarf_vma offset;
+      dwarf_vma offset, voffset;
       dwarf_vma base_address;
       unsigned int k;
       int has_frame_base;
@@ -5578,24 +5799,42 @@ display_debug_loc (struct dwarf_section *section, void *file)
          for (k = 0; k < debug_information [i].num_loc_offsets; k++)
            array[k] = k;
          loc_offsets = debug_information [i].loc_offsets;
+         loc_views = debug_information [i].loc_views;
          qsort (array, debug_information [i].num_loc_offsets,
                 sizeof (*array), loc_offsets_compar);
        }
 
+      int adjacent_view_loclists = 1;
       for (k = 0; k < debug_information [i].num_loc_offsets; k++)
        {
          j = locs_sorted ? k : array[k];
          if (k
-             && debug_information [i].loc_offsets [locs_sorted
+             && (debug_information [i].loc_offsets [locs_sorted
                                                    ? k - 1 : array [k - 1]]
-                == debug_information [i].loc_offsets [j])
+                 == debug_information [i].loc_offsets [j])
+             && (debug_information [i].loc_views [locs_sorted
+                                                  ? k - 1 : array [k - 1]]
+                 == debug_information [i].loc_views [j]))
            continue;
          has_frame_base = debug_information [i].have_frame_base [j];
          offset = debug_information [i].loc_offsets [j];
          next = section_begin + offset;
+         voffset = debug_information [i].loc_views [j];
+         if (voffset != vm1)
+           vnext = section_begin + voffset;
+         else
+           vnext = NULL;
          base_address = debug_information [i].base_address;
 
-         if (!seen_first_offset)
+         if (vnext && vnext < next)
+           {
+             vstart = vnext;
+             display_view_pair_list (section, &vstart, i, next);
+             if (start == vnext)
+               start = vstart;
+           }
+
+         if (!seen_first_offset || !adjacent_view_loclists)
            seen_first_offset = 1;
          else
            {
@@ -5609,6 +5848,7 @@ display_debug_loc (struct dwarf_section *section, void *file)
                      (unsigned long) offset);
            }
          start = next;
+         vstart = vnext;
 
          if (offset >= bytes)
            {
@@ -5617,14 +5857,21 @@ display_debug_loc (struct dwarf_section *section, void *file)
              continue;
            }
 
+         if (vnext && voffset >= bytes)
+           {
+             warn (_("View Offset 0x%lx is bigger than .debug_loc section size.\n"),
+                   (unsigned long) voffset);
+             continue;
+           }
+
          if (!is_loclists)
            {
              if (is_dwo)
                display_loc_list_dwo (section, &start, i, offset,
-                                     has_frame_base);
+                                     &vstart, has_frame_base);
              else
                display_loc_list (section, &start, i, offset, base_address,
-                                 has_frame_base);
+                                 &vstart, has_frame_base);
            }
          else
            {
@@ -5632,8 +5879,25 @@ display_debug_loc (struct dwarf_section *section, void *file)
                warn (_("DWO is not yet supported.\n"));
              else
                display_loclists_list (section, &start, i, offset, base_address,
-                                      has_frame_base);
+                                      &vstart, has_frame_base);
+           }
+
+         /* FIXME: this arrangement is quite simplistic.  Nothing
+            requires locview lists to be adjacent to corresponding
+            loclists, and a single loclist could be augmented by
+            different locview lists, and vice-versa, unlikely as it
+            is that it would make sense to do so.  Hopefully we'll
+            have view pair support built into loclists before we ever
+            need to address all these possibilities.  */
+         if (adjacent_view_loclists && vnext
+             && vnext != start && vstart != next)
+           {
+             adjacent_view_loclists = 0;
+             warn (_("Hole and overlap detection requires adjacent view lists and loclists.\n"));
            }
+
+         if (vnext && vnext == start)
+           display_view_pair_list (section, &start, i, vstart);
        }
     }
 
index 4d3330c..15719ee 100644 (file)
@@ -170,9 +170,12 @@ typedef struct
   dwarf_vma     ranges_base;
   /* This is an array of offsets to the location list table.  */
   dwarf_vma *    loc_offsets;
+  /* This is an array of offsets to the location view table.  */
+  dwarf_vma *    loc_views;
   int *          have_frame_base;
   unsigned int   num_loc_offsets;
   unsigned int   max_loc_offsets;
+  unsigned int   num_loc_views;
   /* List of .debug_ranges offsets seen in this .debug_info.  */
   dwarf_vma *    range_lists;
   unsigned int   num_range_lists;
diff --git a/binutils/testsuite/binutils-all/locview-1.s b/binutils/testsuite/binutils-all/locview-1.s
new file mode 100644 (file)
index 0000000..d9d9b5b
--- /dev/null
@@ -0,0 +1,270 @@
+       .text
+.Ltext0:
+.LFB0:
+       /* locview.c:1 */
+.LM1:
+       /* view -0 */
+       /* locview.c:2 */
+.LM2:
+       /* view 1 */
+.LVL0:
+       /* DEBUG i => 0 */
+       /* locview.c:3 */
+.LM3:
+       /* view 2 */
+       /* DEBUG j => 0x1 */
+       /* locview.c:4 */
+.LM4:
+       /* view 3 */
+       /* DEBUG i => 0x2 */
+       /* locview.c:5 */
+.LM5:
+       /* view 4 */
+       /* DEBUG j => 0x3 */
+       /* locview.c:6 */
+.LM6:
+       /* view 5 */
+       /* DEBUG k => 0x4 */
+       /* DEBUG l => 0x4 */
+       /* locview.c:7 */
+.LM7:
+       /* view 6 */
+       /* DEBUG k => 0x5 */
+       /* DEBUG l => 0x5 */
+       /* locview.c:8 */
+.LM8:
+       /* view 7 */
+       /* DEBUG k => 0x6 */
+       /* DEBUG l => 0x6 */
+       /* locview.c:9 */
+.LM9:
+       /* view 8 */
+       .byte   0
+.LFE0:
+.Letext0:
+
+       .section        .debug_info
+.Ldebug_info0:
+.LIbase:
+       .4byte  .LIend - .LIstart       /* Length of Compilation Unit Info */
+.LIstart:
+       .2byte  0x4     /* DWARF version number */
+       .4byte  .Ldebug_abbrev0 /* Offset Into Abbrev. Section */
+       .byte   0x4     /* Pointer Size (in bytes) */
+.LIcu:
+       .uleb128 0x1    /* (DIE (cu) DW_TAG_compile_unit) */
+       .ascii "hand-crafted based on GCC output\0"
+       .byte   0xc     /* DW_AT_language */
+       .ascii "locview.c\0"
+       .ascii "/tmp\0"
+       .4byte  0       /* DW_AT_low_pc */
+.LIsubf:
+       .uleb128 0x2    /* (DIE (subf) DW_TAG_subprogram) */
+       .ascii "f\0"    /* DW_AT_name */
+       .byte   0x1     /* DW_AT_decl_file (locview.c) */
+       .byte   0x1     /* DW_AT_decl_line */
+       .4byte  .LIint-.LIbase  /* DW_AT_type */
+       .4byte  .LFB0   /* DW_AT_low_pc */
+       .4byte  1 /* .LFE0-.LFB0 */     /* DW_AT_high_pc */
+       .uleb128 0x1    /* DW_AT_frame_base */
+       .byte   0x9c    /* DW_OP_call_frame_cfa */
+                       /* DW_AT_GNU_all_call_sites */
+       .4byte  .LIint - .LIbase        /* DW_AT_sibling */
+.LIvari:
+       .uleb128 0x3    /* (DIE (vari) DW_TAG_variable) */
+       .ascii "i\0"    /* DW_AT_name */
+       .byte   0x1     /* DW_AT_decl_file (locview.c) */
+       .byte   0x2     /* DW_AT_decl_line */
+       .4byte  .LIint-.LIbase  /* DW_AT_type */
+       .4byte  .LLST0  /* DW_AT_location */
+       .4byte  .LVUS0  /* DW_AT_GNU_locviews */
+.LIvarj:
+       .uleb128 0x3    /* (DIE (varf) DW_TAG_variable) */
+       .ascii "j\0"    /* DW_AT_name */
+       .byte   0x1     /* DW_AT_decl_file (locview.c) */
+       .byte   0x3     /* DW_AT_decl_line */
+       .4byte  .LIint - .LIbase        /* DW_AT_type */
+       .4byte  .LLST1  /* DW_AT_location */
+       .4byte  .LVUS1  /* DW_AT_GNU_locviews */
+.LIvark:
+       .uleb128 0x5    /* (DIE (vark) DW_TAG_variable) */
+       .ascii "k\0"    /* DW_AT_name */
+       .byte   0x1     /* DW_AT_decl_file (locview.c) */
+       .byte   0x6     /* DW_AT_decl_line */
+       .4byte  .LIint - .LIbase        /* DW_AT_type */
+       .4byte  .LVUS2  /* DW_AT_GNU_locviews */
+       .4byte  .LLST2  /* DW_AT_location */
+       .byte   0       /* end of children of subf */
+.LIvarl:
+       .uleb128 0x5    /* (DIE (varl) DW_TAG_variable) */
+       .ascii "l\0"    /* DW_AT_name */
+       .byte   0x1     /* DW_AT_decl_file (locview.c) */
+       .byte   0x6     /* DW_AT_decl_line */
+       .4byte  .LIint - .LIbase        /* DW_AT_type */
+       .4byte  .LVUS2  /* DW_AT_GNU_locviews */
+       .4byte  .LLST2  /* DW_AT_location */
+       .byte   0       /* end of children of subf */
+
+.LIint:
+       .uleb128 0x4    /* (DIE (int) DW_TAG_base_type) */
+       .byte   0x4     /* DW_AT_byte_size */
+       .byte   0x5     /* DW_AT_encoding */
+       .ascii "int\0"  /* DW_AT_name */
+       .byte   0       /* end of children of cu */
+.LIend:
+
+       .section        .debug_abbrev
+.Ldebug_abbrev0:
+.LAbrv1:
+       .uleb128 0x1    /* (abbrev code) */
+       .uleb128 0x11   /* (TAG: DW_TAG_compile_unit) */
+       .byte   0x1     /* DW_children_yes */
+       .uleb128 0x25   /* (DW_AT_producer) */
+       .uleb128 0x8    /* (DW_FORM_string) */
+       .uleb128 0x13   /* (DW_AT_language) */
+       .uleb128 0xb    /* (DW_FORM_data1) */
+       .uleb128 0x3    /* (DW_AT_name) */
+       .uleb128 0x8    /* (DW_FORM_string) */
+       .uleb128 0x1b   /* (DW_AT_comp_dir) */
+       .uleb128 0x8    /* (DW_FORM_string) */
+       .uleb128 0x11   /* (DW_AT_low_pc) */
+       .uleb128 0x1    /* (DW_FORM_addr) */
+       .byte   0
+       .byte   0
+.LAbrv2:
+       .uleb128 0x2    /* (abbrev code) */
+       .uleb128 0x2e   /* (TAG: DW_TAG_subprogram) */
+       .byte   0x1     /* DW_children_yes */
+       .uleb128 0x3    /* (DW_AT_name) */
+       .uleb128 0x8    /* (DW_FORM_string) */
+       .uleb128 0x3a   /* (DW_AT_decl_file) */
+       .uleb128 0xb    /* (DW_FORM_data1) */
+       .uleb128 0x3b   /* (DW_AT_decl_line) */
+       .uleb128 0xb    /* (DW_FORM_data1) */
+       .uleb128 0x49   /* (DW_AT_type) */
+       .uleb128 0x13   /* (DW_FORM_ref4) */
+       .uleb128 0x11   /* (DW_AT_low_pc) */
+       .uleb128 0x1    /* (DW_FORM_addr) */
+       .uleb128 0x12   /* (DW_AT_high_pc) */
+       .uleb128 0x6    /* (DW_FORM_data4) */
+       .uleb128 0x40   /* (DW_AT_frame_base) */
+       .uleb128 0x18   /* (DW_FORM_exprloc) */
+       .uleb128 0x2117 /* (DW_AT_GNU_all_call_sites) */
+       .uleb128 0x19   /* (DW_FORM_flag_present) */
+       .uleb128 0x1    /* (DW_AT_sibling) */
+       .uleb128 0x13   /* (DW_FORM_ref4) */
+       .byte   0
+       .byte   0
+.LAbrv3:
+       .uleb128 0x3    /* (abbrev code) */
+       .uleb128 0x34   /* (TAG: DW_TAG_variable) */
+       .byte   0       /* DW_children_no */
+       .uleb128 0x3    /* (DW_AT_name) */
+       .uleb128 0x8    /* (DW_FORM_string) */
+       .uleb128 0x3a   /* (DW_AT_decl_file) */
+       .uleb128 0xb    /* (DW_FORM_data1) */
+       .uleb128 0x3b   /* (DW_AT_decl_line) */
+       .uleb128 0xb    /* (DW_FORM_data1) */
+       .uleb128 0x49   /* (DW_AT_type) */
+       .uleb128 0x13   /* (DW_FORM_ref4) */
+       .uleb128 0x2    /* (DW_AT_location) */
+       .uleb128 0x17   /* (DW_FORM_sec_offset) */
+       .uleb128 0x2137 /* (DW_AT_GNU_locviews) */
+       .uleb128 0x17   /* (DW_FORM_sec_offset) */
+       .byte   0
+       .byte   0
+.LAbrv4:
+       .uleb128 0x4    /* (abbrev code) */
+       .uleb128 0x24   /* (TAG: DW_TAG_base_type) */
+       .byte   0       /* DW_children_no */
+       .uleb128 0xb    /* (DW_AT_byte_size) */
+       .uleb128 0xb    /* (DW_FORM_data1) */
+       .uleb128 0x3e   /* (DW_AT_encoding) */
+       .uleb128 0xb    /* (DW_FORM_data1) */
+       .uleb128 0x3    /* (DW_AT_name) */
+       .uleb128 0x8    /* (DW_FORM_string) */
+       .byte   0
+       .byte   0
+.LAbrv5:
+       .uleb128 0x5    /* (abbrev code) */
+       .uleb128 0x34   /* (TAG: DW_TAG_variable) */
+       .byte   0       /* DW_children_no */
+       .uleb128 0x3    /* (DW_AT_name) */
+       .uleb128 0x8    /* (DW_FORM_string) */
+       .uleb128 0x3a   /* (DW_AT_decl_file) */
+       .uleb128 0xb    /* (DW_FORM_data1) */
+       .uleb128 0x3b   /* (DW_AT_decl_line) */
+       .uleb128 0xb    /* (DW_FORM_data1) */
+       .uleb128 0x49   /* (DW_AT_type) */
+       .uleb128 0x13   /* (DW_FORM_ref4) */
+       .uleb128 0x2137 /* (DW_AT_GNU_locviews) */
+       .uleb128 0x17   /* (DW_FORM_sec_offset) */
+       .uleb128 0x2    /* (DW_AT_location) */
+       .uleb128 0x17   /* (DW_FORM_sec_offset) */
+       .byte   0
+       .byte   0
+       .byte   0
+
+       .section        .debug_loc
+.Ldebug_loc0:
+.LVUS0:
+       .uleb128 0x2    /* View list begin (*.LVUS0) */
+       .uleb128 0x4    /* View list end (*.LVUS0) */
+       .uleb128 0x4    /* View list begin (*.LVUS0) */
+       .uleb128 0      /* View list end (*.LVUS0) */
+.LLST0:
+       .4byte  .LVL0   /* Location list begin address (*.LLST0) */
+       .4byte  .LVL0   /* Location list end address (*.LLST0) */
+       .2byte  0x2     /* Location expression size */
+       .byte   0x30    /* DW_OP_lit0 */
+       .byte   0x9f    /* DW_OP_stack_value */
+       .4byte  .LVL0   /* Location list begin address (*.LLST0) */
+       .4byte  .LFE0   /* Location list end address (*.LLST0) */
+       .2byte  0x2     /* Location expression size */
+       .byte   0x32    /* DW_OP_lit2 */
+       .byte   0x9f    /* DW_OP_stack_value */
+       .4byte  0       /* Location list terminator begin (*.LLST0) */
+       .4byte  0       /* Location list terminator end (*.LLST0) */
+.LLST1:
+       .4byte  .LVL0   /* Location list begin address (*.LLST1) */
+       .4byte  .LVL0   /* Location list end address (*.LLST1) */
+       .2byte  0x2     /* Location expression size */
+       .byte   0x31    /* DW_OP_lit1 */
+       .byte   0x9f    /* DW_OP_stack_value */
+       .4byte  .LVL0   /* Location list begin address (*.LLST1) */
+       .4byte  .LFE0   /* Location list end address (*.LLST1) */
+       .2byte  0x2     /* Location expression size */
+       .byte   0x33    /* DW_OP_lit3 */
+       .byte   0x9f    /* DW_OP_stack_value */
+       .4byte  0       /* Location list terminator begin (*.LLST1) */
+       .4byte  0       /* Location list terminator end (*.LLST1) */
+.LVUS1:
+       .uleb128 0x3    /* View list begin (*.LVUS1) */
+       .uleb128 0x5    /* View list end (*.LVUS1) */
+       .uleb128 0x5    /* View list begin (*.LVUS1) */
+       .uleb128 0      /* View list end (*.LVUS1) */
+.LVUS2:
+       .uleb128 0x6    /* View list begin (*.LVUS2) */
+       .uleb128 0x7    /* View list end (*.LVUS2) */
+       .uleb128 0x7    /* View list begin (*.LVUS2) */
+       .uleb128 0x8    /* View list end (*.LVUS2) */
+       .uleb128 0x8    /* View list begin (*.LVUS2) */
+       .uleb128 0      /* View list end (*.LVUS2) */
+.LLST2:
+       .4byte  .LVL0   /* Location list begin address (*.LLST2) */
+       .4byte  .LVL0   /* Location list end address (*.LLST2) */
+       .2byte  0x2     /* Location expression size */
+       .byte   0x34    /* DW_OP_lit4 */
+       .byte   0x9f    /* DW_OP_stack_value */
+       .4byte  .LVL0   /* Location list begin address (*.LLST2) */
+       .4byte  .LVL0   /* Location list end address (*.LLST2) */
+       .2byte  0x2     /* Location expression size */
+       .byte   0x35    /* DW_OP_lit5 */
+       .byte   0x9f    /* DW_OP_stack_value */
+       .4byte  .LVL0   /* Location list begin address (*.LLST2) */
+       .4byte  .LFE0   /* Location list end address (*.LLST2) */
+       .2byte  0x2     /* Location expression size */
+       .byte   0x36    /* DW_OP_lit6 */
+       .byte   0x9f    /* DW_OP_stack_value */
+       .4byte  0       /* Location list terminator begin (*.LLST2) */
+       .4byte  0       /* Location list terminator end (*.LLST2) */
diff --git a/binutils/testsuite/binutils-all/locview-2.s b/binutils/testsuite/binutils-all/locview-2.s
new file mode 100644 (file)
index 0000000..d9b1d58
--- /dev/null
@@ -0,0 +1,335 @@
+       .text
+.Ltext0:
+.LFB0:
+       /* locview.c:1 */
+.LM1:
+       /* view -0 */
+       /* locview.c:2 */
+.LM2:
+       /* view 1 */
+.LVL0:
+       /* DEBUG i => 0 */
+       /* locview.c:3 */
+.LM3:
+       /* view 2 */
+       /* DEBUG j => 0x1 */
+       /* locview.c:4 */
+.LM4:
+       /* view 3 */
+       /* DEBUG i => 0x2 */
+       /* locview.c:5 */
+.LM5:
+       /* view 4 */
+       /* DEBUG j => 0x3 */
+       /* locview.c:6 */
+.LM6:
+       /* view 5 */
+       /* DEBUG k => 0x4 */
+       /* DEBUG l => 0x4 */
+       /* locview.c:7 */
+.LM7:
+       /* view 6 */
+       /* DEBUG k => 0x5 */
+       /* DEBUG l => 0x5 */
+       /* locview.c:8 */
+.LM8:
+       /* view 7 */
+       /* DEBUG k => 0x6 */
+       /* DEBUG l => 0x6 */
+       /* locview.c:9 */
+.LM9:
+       /* view 8 */
+       .byte   0
+.LFE0:
+.Letext0:
+
+       .section        .debug_info
+.Ldebug_info0:
+.LIbase:
+       .4byte  .LIend - .LIstart       /* Length of Compilation Unit Info */
+.LIstart:
+       .2byte  0x5     /* DWARF version number */
+       .byte   0x1     /* DW_UT_compile */
+       .byte   0x4     /* Pointer Size (in bytes) */
+       .4byte  .Ldebug_abbrev0 /* Offset Into Abbrev. Section */
+.LIcu:
+       .uleb128 0x2    /* (DIE (cu) DW_TAG_compile_unit) */
+       .ascii "hand-crafted based on GCC output\0"
+       .byte   0x1d    /* DW_AT_language */
+       .ascii "locview.c\0"
+       .ascii "/tmp\0"
+       .4byte  0       /* DW_AT_low_pc */
+.LIsubf:
+       .uleb128 0x3    /* (DIE (subf) DW_TAG_subprogram) */
+       .ascii "f\0"    /* DW_AT_name */
+       .byte   0x1     /* DW_AT_decl_file (locview.c) */
+       .byte   0x1     /* DW_AT_decl_line */
+       .4byte  .LIint-.LIbase  /* DW_AT_type */
+       .4byte  .LFB0   /* DW_AT_low_pc */
+       .4byte  1 /* .LFE0-.LFB0 */     /* DW_AT_high_pc */
+       .uleb128 0x1    /* DW_AT_frame_base */
+       .byte   0x9c    /* DW_OP_call_frame_cfa */
+                       /* DW_AT_call_all_calls */
+       .4byte  .LIint - .LIbase        /* DW_AT_sibling */
+.LIvari:
+       .uleb128 0x1    /* (DIE (vari) DW_TAG_variable) */
+       .ascii "i\0"    /* DW_AT_name */
+                       /* DW_AT_decl_file (1, locview.c) */
+       .byte   0x2     /* DW_AT_decl_line */
+       .4byte  .LIint - .LIbase        /* DW_AT_type */
+       .4byte  .LLST0  /* DW_AT_location */
+       .4byte  .LVUS0  /* DW_AT_GNU_locviews */
+.LIvarj:
+       .uleb128 0x1    /* (DIE (varj) DW_TAG_variable) */
+       .ascii "j\0"    /* DW_AT_name */
+                       /* DW_AT_decl_file (1, locview.c) */
+       .byte   0x3     /* DW_AT_decl_line */
+       .4byte  .LIint - .LIbase        /* DW_AT_type */
+       .4byte  .LLST1  /* DW_AT_location */
+       .4byte  .LVUS1  /* DW_AT_GNU_locviews */
+.LIvark:
+       .uleb128 0x5    /* (DIE (vark) DW_TAG_variable) */
+       .ascii "k\0"    /* DW_AT_name */
+                       /* DW_AT_decl_file (1, locview.c) */
+       .byte   0x6     /* DW_AT_decl_line */
+       .4byte  .LIint - .LIbase        /* DW_AT_type */
+       .4byte  .LVUS2  /* DW_AT_GNU_locviews */
+       .4byte  .LLST2  /* DW_AT_location */
+.LIvarl:
+       .uleb128 0x6    /* (DIE (varl) DW_TAG_variable) */
+       .ascii "l\0"    /* DW_AT_name */
+                       /* DW_AT_decl_file (1, locview.c) */
+       .byte   0x6     /* DW_AT_decl_line */
+       .4byte  .LIint - .LIbase        /* DW_AT_type */
+       .4byte  .LLST3  /* DW_AT_location */
+       .byte   0       /* end of children of DIE subf */
+
+.LIint:
+       .uleb128 0x4    /* (DIE (int) DW_TAG_base_type) */
+       .byte   0x4     /* DW_AT_byte_size */
+       .byte   0x5     /* DW_AT_encoding */
+       .ascii "int\0"  /* DW_AT_name */
+       .byte   0       /* end of children of DIE cu */
+.LIend:
+       .section        .debug_abbrev
+.Ldebug_abbrev0:
+.LAbrv1:
+       .uleb128 0x1    /* (abbrev code) */
+       .uleb128 0x34   /* (TAG: DW_TAG_variable) */
+       .byte   0       /* DW_children_no */
+       .uleb128 0x3    /* (DW_AT_name) */
+       .uleb128 0x8    /* (DW_FORM_string) */
+       .uleb128 0x3a   /* (DW_AT_decl_file) */
+       .uleb128 0x21   /* (DW_FORM_implicit_const) */
+       .sleb128 1      /* (locview.c) */
+       .uleb128 0x3b   /* (DW_AT_decl_line) */
+       .uleb128 0xb    /* (DW_FORM_data1) */
+       .uleb128 0x49   /* (DW_AT_type) */
+       .uleb128 0x13   /* (DW_FORM_ref4) */
+       .uleb128 0x2    /* (DW_AT_location) */
+       .uleb128 0x17   /* (DW_FORM_sec_offset) */
+       .uleb128 0x2137 /* (DW_AT_GNU_locviews) */
+       .uleb128 0x17   /* (DW_FORM_sec_offset) */
+       .byte   0
+       .byte   0
+.LAbrv2:
+       .uleb128 0x2    /* (abbrev code) */
+       .uleb128 0x11   /* (TAG: DW_TAG_compile_unit) */
+       .byte   0x1     /* DW_children_yes */
+       .uleb128 0x25   /* (DW_AT_producer) */
+       .uleb128 0x8    /* (DW_FORM_string) */
+       .uleb128 0x13   /* (DW_AT_language) */
+       .uleb128 0xb    /* (DW_FORM_data1) */
+       .uleb128 0x3    /* (DW_AT_name) */
+       .uleb128 0x8    /* (DW_FORM_string) */
+       .uleb128 0x1b   /* (DW_AT_comp_dir) */
+       .uleb128 0x8    /* (DW_FORM_string) */
+       .uleb128 0x11   /* (DW_AT_low_pc) */
+       .uleb128 0x1    /* (DW_FORM_addr) */
+       .byte   0
+       .byte   0
+.LAbrv3:
+       .uleb128 0x3    /* (abbrev code) */
+       .uleb128 0x2e   /* (TAG: DW_TAG_subprogram) */
+       .byte   0x1     /* DW_children_yes */
+       .uleb128 0x3    /* (DW_AT_name) */
+       .uleb128 0x8    /* (DW_FORM_string) */
+       .uleb128 0x3a   /* (DW_AT_decl_file) */
+       .uleb128 0xb    /* (DW_FORM_data1) */
+       .uleb128 0x3b   /* (DW_AT_decl_line) */
+       .uleb128 0xb    /* (DW_FORM_data1) */
+       .uleb128 0x49   /* (DW_AT_type) */
+       .uleb128 0x13   /* (DW_FORM_ref4) */
+       .uleb128 0x11   /* (DW_AT_low_pc) */
+       .uleb128 0x1    /* (DW_FORM_addr) */
+       .uleb128 0x12   /* (DW_AT_high_pc) */
+       .uleb128 0x6    /* (DW_FORM_data4) */
+       .uleb128 0x40   /* (DW_AT_frame_base) */
+       .uleb128 0x18   /* (DW_FORM_exprloc) */
+       .uleb128 0x7a   /* (DW_AT_call_all_calls) */
+       .uleb128 0x19   /* (DW_FORM_flag_present) */
+       .uleb128 0x1    /* (DW_AT_sibling) */
+       .uleb128 0x13   /* (DW_FORM_ref4) */
+       .byte   0
+       .byte   0
+.LAbrv4:
+       .uleb128 0x4    /* (abbrev code) */
+       .uleb128 0x24   /* (TAG: DW_TAG_base_type) */
+       .byte   0       /* DW_children_no */
+       .uleb128 0xb    /* (DW_AT_byte_size) */
+       .uleb128 0xb    /* (DW_FORM_data1) */
+       .uleb128 0x3e   /* (DW_AT_encoding) */
+       .uleb128 0xb    /* (DW_FORM_data1) */
+       .uleb128 0x3    /* (DW_AT_name) */
+       .uleb128 0x8    /* (DW_FORM_string) */
+       .byte   0
+       .byte   0
+.LAbrv5:
+       .uleb128 0x5    /* (abbrev code) */
+       .uleb128 0x34   /* (TAG: DW_TAG_variable) */
+       .byte   0       /* DW_children_no */
+       .uleb128 0x3    /* (DW_AT_name) */
+       .uleb128 0x8    /* (DW_FORM_string) */
+       .uleb128 0x3a   /* (DW_AT_decl_file) */
+       .uleb128 0x21   /* (DW_FORM_implicit_const) */
+       .sleb128 1      /* (locview.c) */
+       .uleb128 0x3b   /* (DW_AT_decl_line) */
+       .uleb128 0xb    /* (DW_FORM_data1) */
+       .uleb128 0x49   /* (DW_AT_type) */
+       .uleb128 0x13   /* (DW_FORM_ref4) */
+       .uleb128 0x2137 /* (DW_AT_GNU_locviews) */
+       .uleb128 0x17   /* (DW_FORM_sec_offset) */
+       .uleb128 0x2    /* (DW_AT_location) */
+       .uleb128 0x17   /* (DW_FORM_sec_offset) */
+       .byte   0
+       .byte   0
+.LAbrv6:
+       .uleb128 0x6    /* (abbrev code) */
+       .uleb128 0x34   /* (TAG: DW_TAG_variable) */
+       .byte   0       /* DW_children_no */
+       .uleb128 0x3    /* (DW_AT_name) */
+       .uleb128 0x8    /* (DW_FORM_string) */
+       .uleb128 0x3a   /* (DW_AT_decl_file) */
+       .uleb128 0x21   /* (DW_FORM_implicit_const) */
+       .sleb128 1      /* (locview.c) */
+       .uleb128 0x3b   /* (DW_AT_decl_line) */
+       .uleb128 0xb    /* (DW_FORM_data1) */
+       .uleb128 0x49   /* (DW_AT_type) */
+       .uleb128 0x13   /* (DW_FORM_ref4) */
+       .uleb128 0x2    /* (DW_AT_location) */
+       .uleb128 0x17   /* (DW_FORM_sec_offset) */
+       .byte   0
+       .byte   0
+       .byte   0
+
+       .section        .debug_loclists
+       .4byte  .Ldebug_loc2-.Ldebug_loc1       /* Length of Location Lists */
+.Ldebug_loc1:
+       .2byte  0x5     /* DWARF version number */
+       .byte   0x4     /* Address Size */
+       .byte   0       /* Segment Size */
+       .4byte  0       /* Offset Entry Count */
+.Ldebug_loc0:
+.LVUS0:
+       .uleb128 0x2    /* View list begin (*.LVUS0) */
+       .uleb128 0x4    /* View list end (*.LVUS0) */
+       .uleb128 0x4    /* View list begin (*.LVUS0) */
+       .uleb128 0      /* View list end (*.LVUS0) */
+.LLST0:
+       .byte   0x6     /* DW_LLE_base_address (*.LLST0) */
+       .4byte  .LVL0   /* Base address (*.LLST0) */
+       .byte   0x4     /* DW_LLE_offset_pair (*.LLST0) */
+       .uleb128 0 /* .LVL0-.LVL0 */    /* Location list begin address (*.LLST0) */
+       .uleb128 0 /* .LVL0-.LVL0 */    /* Location list end address (*.LLST0) */
+       .uleb128 0x2    /* Location expression size */
+       .byte   0x30    /* DW_OP_lit0 */
+       .byte   0x9f    /* DW_OP_stack_value */
+       .byte   0x4     /* DW_LLE_offset_pair (*.LLST0) */
+       .uleb128 0 /* .LVL0-.LVL0 */    /* Location list begin address (*.LLST0) */
+       .uleb128 1 /* .LFE0-.LVL0 */    /* Location list end address (*.LLST0) */
+       .uleb128 0x2    /* Location expression size */
+       .byte   0x32    /* DW_OP_lit2 */
+       .byte   0x9f    /* DW_OP_stack_value */
+       .byte   0       /* DW_LLE_end_of_list (*.LLST0) */
+.LLST1:
+       .byte   0x6     /* DW_LLE_base_address (*.LLST1) */
+       .4byte  .LVL0   /* Base address (*.LLST1) */
+       .byte   0x4     /* DW_LLE_offset_pair (*.LLST1) */
+       .uleb128 0 /* .LVL0-.LVL0 */    /* Location list begin address (*.LLST1) */
+       .uleb128 0 /* .LVL0-.LVL0 */    /* Location list end address (*.LLST1) */
+       .uleb128 0x2    /* Location expression size */
+       .byte   0x31    /* DW_OP_lit1 */
+       .byte   0x9f    /* DW_OP_stack_value */
+       .byte   0x4     /* DW_LLE_offset_pair (*.LLST1) */
+       .uleb128 0 /* .LVL0-.LVL0 */    /* Location list begin address (*.LLST1) */
+       .uleb128 1 /* .LFE0-.LVL0 */    /* Location list end address (*.LLST1) */
+       .uleb128 0x2    /* Location expression size */
+       .byte   0x33    /* DW_OP_lit3 */
+       .byte   0x9f    /* DW_OP_stack_value */
+       .byte   0       /* DW_LLE_end_of_list (*.LLST1) */
+.LVUS1:
+       .uleb128 0x3    /* View list begin (*.LVUS1) */
+       .uleb128 0x5    /* View list end (*.LVUS1) */
+       .uleb128 0x5    /* View list begin (*.LVUS1) */
+       .uleb128 0      /* View list end (*.LVUS1) */
+.LVUS2:
+       .uleb128 0x6    /* View list begin (*.LVUS2) */
+       .uleb128 0x7    /* View list end (*.LVUS2) */
+       .uleb128 0x7    /* View list begin (*.LVUS2) */
+       .uleb128 0x8    /* View list end (*.LVUS2) */
+       .uleb128 0x8    /* View list begin (*.LVUS2) */
+       .uleb128 0      /* View list end (*.LVUS2) */
+.LLST2:
+       .byte   0x6     /* DW_LLE_base_address (*.LLST2) */
+       .4byte  .LVL0   /* Base address (*.LLST2) */
+       .byte   0x4     /* DW_LLE_offset_pair (*.LLST2) */
+       .uleb128 0 /* .LVL0-.LVL0 */    /* Location list begin address (*.LLST2) */
+       .uleb128 0 /* .LVL0-.LVL0 */    /* Location list end address (*.LLST2) */
+       .uleb128 0x2    /* Location expression size */
+       .byte   0x34    /* DW_OP_lit4 */
+       .byte   0x9f    /* DW_OP_stack_value */
+       .byte   0x4     /* DW_LLE_offset_pair (*.LLST2) */
+       .uleb128 0 /* .LVL0-.LVL0 */    /* Location list begin address (*.LLST2) */
+       .uleb128 0 /* .LVL0-.LVL0 */    /* Location list end address (*.LLST2) */
+       .uleb128 0x2    /* Location expression size */
+       .byte   0x35    /* DW_OP_lit5 */
+       .byte   0x9f    /* DW_OP_stack_value */
+       .byte   0x4     /* DW_LLE_offset_pair (*.LLST2) */
+       .uleb128 0 /* .LVL0-.LVL0 */    /* Location list begin address (*.LLST2) */
+       .uleb128 1 /* .LFE0-.LVL0 */    /* Location list end address (*.LLST2) */
+       .uleb128 0x2    /* Location expression size */
+       .byte   0x36    /* DW_OP_lit6 */
+       .byte   0x9f    /* DW_OP_stack_value */
+       .byte   0       /* DW_LLE_end_of_list (*.LLST2) */
+.LLST3:
+       .byte   0x6     /* DW_LLE_base_address (*.LLST3) */
+       .4byte  .LVL0   /* Base address (*.LLST3) */
+       .byte   0x9     /* DW_LLE_view_pair (extension proposed for DWARF6) */
+       .uleb128 0x6    /* View list begin (*.LLST3) */
+       .uleb128 0x7    /* View list end (*.LVUS3) */
+       .byte   0x4     /* DW_LLE_offset_pair (*.LLST3) */
+       .uleb128 0 /* .LVL0-.LVL0 */    /* Location list begin address (*.LLST3) */
+       .uleb128 0 /* .LVL0-.LVL0 */    /* Location list end address (*.LLST3) */
+       .uleb128 0x2    /* Location expression size */
+       .byte   0x34    /* DW_OP_lit4 */
+       .byte   0x9f    /* DW_OP_stack_value */
+       .byte   0x9     /* DW_LLE_view_pair */
+       .uleb128 0x7    /* View list begin (*.LLST3) */
+       .uleb128 0x8    /* View list end (*.LVUS3) */
+       .byte   0x4     /* DW_LLE_offset_pair (*.LLST3) */
+       .uleb128 0 /* .LVL0-.LVL0 */    /* Location list begin address (*.LLST3) */
+       .uleb128 0 /* .LVL0-.LVL0 */    /* Location list end address (*.LLST3) */
+       .uleb128 0x2    /* Location expression size */
+       .byte   0x35    /* DW_OP_lit5 */
+       .byte   0x9f    /* DW_OP_stack_value */
+       .byte   0x9     /* DW_LLE_view_pair */
+       .uleb128 0x8    /* View list begin (*.LLST3) */
+       .uleb128 0x0    /* View list end (*.LVUS3) */
+       .byte   0x4     /* DW_LLE_offset_pair (*.LLST3) */
+       .uleb128 0 /* .LVL0-.LVL0 */    /* Location list begin address (*.LLST3) */
+       .uleb128 1 /* .LFE0-.LVL0 */    /* Location list end address (*.LLST3) */
+       .uleb128 0x2    /* Location expression size */
+       .byte   0x36    /* DW_OP_lit6 */
+       .byte   0x9f    /* DW_OP_stack_value */
+       .byte   0       /* DW_LLE_end_of_list (*.LLST3) */
+.Ldebug_loc2:
index 6a7b562..81d1809 100644 (file)
@@ -379,6 +379,33 @@ if {![binutils_assemble $srcdir/$subdir/pr18374.s tmpdir/pr18374.o]} then {
 }
 
 
+# locview - Check dumping of location lists with location views.
+if {![binutils_assemble $srcdir/$subdir/locview-1.s tmpdir/locview-1.o]} then {
+    unresolved "readelf --debug-dump=loc locview-1 (failed to assemble)"
+} else {
+
+    if ![is_remote host] {
+       set tempfile tmpdir/locview-1.o
+    } else {
+       set tempfile [remote_download host tmpdir/locview-1.o]
+    }
+
+    readelf_test --debug-dump=loc $tempfile readelf.locview-1  {}
+}
+if {![binutils_assemble $srcdir/$subdir/locview-2.s tmpdir/locview-2.o]} then {
+    unresolved "readelf --debug-dump=loc locview-2 (failed to assemble)"
+} else {
+
+    if ![is_remote host] {
+       set tempfile tmpdir/locview-2.o
+    } else {
+       set tempfile [remote_download host tmpdir/locview-2.o]
+    }
+
+    readelf_test --debug-dump=loc $tempfile readelf.locview-2  {}
+}
+
+
 # Check that decompressed dumps work.
 if {![binutils_assemble $srcdir/$subdir/z.s tmpdir/z.o]} then {
     unresolved "readelf --decompress --hex-dump .debug_loc z (failed to assemble)"
@@ -417,6 +444,6 @@ if ![istarget "riscv*-*-*"] then {
        readelf_find_size $tempfile
 
        # Make sure that readelf can decode the contents.
-       readelf_test -wiaoRlL $tempfile dw5.W {}
+       readelf_test -wiaoRlL $tempfile dw5.W { nds32*-elf }
     }
 }
diff --git a/binutils/testsuite/binutils-all/readelf.locview-1 b/binutils/testsuite/binutils-all/readelf.locview-1
new file mode 100644 (file)
index 0000000..6148520
--- /dev/null
@@ -0,0 +1,35 @@
+Contents of the .*ebug_loc section:
+
+    Offset   Begin            End              Expression
+
+    00000000 v0000002 v0000004 location view pair
+    00000002 v0000004 v0000000 location view pair
+
+    00000004 v0000002 v0000004 views at 00000000 for:
+             00000000 00000000 \(DW_OP_lit0; DW_OP_stack_value\)
+    00000010 v0000004 v0000000 views at 00000002 for:
+             00000000 00000001 \(DW_OP_lit2; DW_OP_stack_value\)
+    0000001c <End of list>
+    00000024 v0000003 v0000005 views at 00000044 for:
+             00000000 00000000 \(DW_OP_lit1; DW_OP_stack_value\)
+    00000030 v0000005 v0000000 views at 00000046 for:
+             00000000 00000001 \(DW_OP_lit3; DW_OP_stack_value\)
+    0000003c <End of list>
+
+    00000044 v0000003 v0000005 location view pair
+    00000046 v0000005 v0000000 location view pair
+
+
+    00000048 v0000006 v0000007 location view pair
+    0000004a v0000007 v0000008 location view pair
+    0000004c v0000008 v0000000 location view pair
+
+    0000004e v0000006 v0000007 views at 00000048 for:
+             00000000 00000000 \(DW_OP_lit4; DW_OP_stack_value\)
+    0000005a v0000007 v0000008 views at 0000004a for:
+             00000000 00000000 \(DW_OP_lit5; DW_OP_stack_value\)
+    00000066 v0000008 v0000000 views at 0000004c for:
+             00000000 00000001 \(DW_OP_lit6; DW_OP_stack_value\)
+    00000072 <End of list>
+
+#pass
diff --git a/binutils/testsuite/binutils-all/readelf.locview-2 b/binutils/testsuite/binutils-all/readelf.locview-2
new file mode 100644 (file)
index 0000000..f064ad7
--- /dev/null
@@ -0,0 +1,46 @@
+Contents of the .*ebug_loclists section:
+#...
+    Offset   Begin            End              Expression
+
+    0000000c v0000002 v0000004 location view pair
+    0000000e v0000004 v0000000 location view pair
+
+    00000010 00000000 \(base address\)
+    00000015 v0000002 v0000004 views at 0000000c for:
+             00000000 00000000 \(DW_OP_lit0; DW_OP_stack_value\)
+    0000001b v0000004 v0000000 views at 0000000e for:
+             00000000 00000001 \(DW_OP_lit2; DW_OP_stack_value\)
+    00000021 <End of list>
+    00000022 00000000 \(base address\)
+    00000027 v0000003 v0000005 views at 00000034 for:
+             00000000 00000000 \(DW_OP_lit1; DW_OP_stack_value\)
+    0000002d v0000005 v0000000 views at 00000036 for:
+             00000000 00000001 \(DW_OP_lit3; DW_OP_stack_value\)
+    00000033 <End of list>
+
+    00000034 v0000003 v0000005 location view pair
+    00000036 v0000005 v0000000 location view pair
+
+
+    00000038 v0000006 v0000007 location view pair
+    0000003a v0000007 v0000008 location view pair
+    0000003c v0000008 v0000000 location view pair
+
+    0000003e 00000000 \(base address\)
+    00000043 v0000006 v0000007 views at 00000038 for:
+             00000000 00000000 \(DW_OP_lit4; DW_OP_stack_value\)
+    00000049 v0000007 v0000008 views at 0000003a for:
+             00000000 00000000 \(DW_OP_lit5; DW_OP_stack_value\)
+    0000004f v0000008 v0000000 views at 0000003c for:
+             00000000 00000001 \(DW_OP_lit6; DW_OP_stack_value\)
+    00000055 <End of list>
+    00000056 00000000 \(base address\)
+    0000005b v0000006 v0000007 views for:
+    0000005e 00000000 00000000 \(DW_OP_lit4; DW_OP_stack_value\)
+    00000064 v0000007 v0000008 views for:
+    00000067 00000000 00000000 \(DW_OP_lit5; DW_OP_stack_value\)
+    0000006d v0000008 v0000000 views for:
+    00000070 00000000 00000001 \(DW_OP_lit6; DW_OP_stack_value\)
+    00000076 <End of list>
+
+#pass
index 1ba7de3..0ece8de 100644 (file)
@@ -1,3 +1,10 @@
+2017-09-22  Alexandre Oliva <aoliva@redhat.com>
+
+       * dwarf2.def (DW_AT_GNU_locviews): New.
+       * dwarf2.h (enum dwarf_location_list_entry_type): Add
+       DW_LLE_GNU_view_pair.
+       (DW_LLE_view_pair): Define.
+
 2017-09-15  Pedro Alves  <palves@redhat.com>
 
        Sync with mainline gcc sources (r252823)
index 2a3b23f..8e731a3 100644 (file)
@@ -443,6 +443,8 @@ DW_AT (DW_AT_GNU_pubtypes, 0x2135)
 /* Attribute for discriminator.
    See http://gcc.gnu.org/wiki/Discriminator  */
 DW_AT (DW_AT_GNU_discriminator, 0x2136)
+DW_AT (DW_AT_GNU_locviews, 0x2137)
+DW_AT (DW_AT_GNU_entry_view, 0x2138)
 /* VMS extensions.  */
 DW_AT (DW_AT_VMS_rtnbeg_pd_address, 0x2201)
 /* GNAT extensions.  */
index a2e022d..fd76d82 100644 (file)
@@ -298,6 +298,14 @@ enum dwarf_location_list_entry_type
     DW_LLE_start_end = 0x07,
     DW_LLE_start_length = 0x08,
 
+    /* <http://lists.dwarfstd.org/private.cgi/dwarf-discuss-dwarfstd.org/2017-April/004347.html>
+       has the proposal for now; only available to list members.
+
+       A (possibly updated) copy of the proposal is available at
+       <http://people.redhat.com/aoliva/papers/sfn/dwarf6-sfn-lvu.txt>.  */
+    DW_LLE_GNU_view_pair = 0x09,
+#define DW_LLE_view_pair DW_LLE_GNU_view_pair
+
     /* Former extension for Fission.
        See http://gcc.gnu.org/wiki/DebugFission.  */
     DW_LLE_GNU_end_of_list_entry = 0x00,