This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] LVU: dump loclists with locviews


On Sep 13, 2017, Alan Modra <amodra@gmail.com> wrote:

> Reposting, since I discovered all the emails I tried to send while at
> the cauldron disappeared..

Aah, that's why I couldn't find it before you reposted it ;-)  Thanks!

> mn10200-elf  +FAIL: readelf --debug-dump=loc
> nds32le-elf  +FAIL: readelf --debug-dump=loc
> riscv32-elf  +FAIL: readelf --debug-dump=loc (reason: unexpected output)
> riscv32-elf  +ERROR:
> /home/alan/src/binutils-gdb/binutils/testsuite/binutils-all/locview-2.s:
> assembly failed
> riscv32-elf  +ERROR: could not assemble locview-2 test file
> riscv32-elf  +FAIL: readelf --debug-dump=loc
> riscv64-elf  +FAIL: readelf --debug-dump=loc (reason: unexpected output)
> riscv64-elf  +ERROR:
> /home/alan/src/binutils-gdb/binutils/testsuite/binutils-all/locview-2.s:
> assembly failed
> riscv64-elf  +ERROR: could not assemble locview-2 test file
> riscv64-elf  +FAIL: readelf --debug-dump=loc
> xtensa-elf  +FAIL: readelf --debug-dump=loc

> A couple of those can be fixed, I think, by adding #... in the right
> place in your .d file, the others should be xfailed.

Instead of xfailing them, I found out that if I used constants instead
of label offsets in some places, I got past a number of assembler and
readelf errors.  I also XFAILed an unrelated failure of dw5 on
nds32*-elf (we fail to dump loclists because of relocations).

Since I made changes different from those you'd suggested, I'll wait for
explicit approval.  The incremental diff can be taken from commit
13b9f79a1904081d984a64037af6457c1e3ff7b6 in branch users/aoliva/SFN.

I've successfully tested this patch on x86_64-linux-gnu with the
following targets:

arm-eabi     mn10300-elf  riscv64-elf  x86_64-linux-gnu
mips64-elf   nds32le-elf  sh-elf       xtensa-elf
mn10200-elf  riscv32-elf  sh-pe




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.


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/dwarf.c                                  |  333 +++++++++++++++++++--
 binutils/dwarf.h                                  |    3 
 binutils/testsuite/binutils-all/locview-1.s       |  270 +++++++++++++++++
 binutils/testsuite/binutils-all/locview-2.s       |  335 +++++++++++++++++++++
 binutils/testsuite/binutils-all/readelf.exp       |   35 ++
 binutils/testsuite/binutils-all/readelf.locview-1 |   35 ++
 binutils/testsuite/binutils-all/readelf.locview-2 |   46 +++
 include/dwarf2.def                                |    2 
 include/dwarf2.h                                  |    8 +
 9 files changed, 1031 insertions(+), 36 deletions(-)
 create mode 100644 binutils/testsuite/binutils-all/locview-1.s
 create mode 100644 binutils/testsuite/binutils-all/locview-2.s
 create mode 100644 binutils/testsuite/binutils-all/readelf.locview-1
 create mode 100644 binutils/testsuite/binutils-all/readelf.locview-2

diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index d2fc799..1b5b27c 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -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,16 @@ 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 +5774,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 +5790,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 +5800,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 +5849,7 @@ display_debug_loc (struct dwarf_section *section, void *file)
 		      (unsigned long) offset);
 	    }
 	  start = next;
+	  vstart = vnext;
 
 	  if (offset >= bytes)
 	    {
@@ -5617,14 +5858,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 +5880,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);
 	}
     }
 
diff --git a/binutils/dwarf.h b/binutils/dwarf.h
index 4d3330c..15719ee 100644
--- a/binutils/dwarf.h
+++ b/binutils/dwarf.h
@@ -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
index 0000000..d9d9b5b
--- /dev/null
+++ b/binutils/testsuite/binutils-all/locview-1.s
@@ -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
index 0000000..d9b1d58
--- /dev/null
+++ b/binutils/testsuite/binutils-all/locview-2.s
@@ -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:
diff --git a/binutils/testsuite/binutils-all/readelf.exp b/binutils/testsuite/binutils-all/readelf.exp
index d9e437d..3cbc1d2 100644
--- a/binutils/testsuite/binutils-all/readelf.exp
+++ b/binutils/testsuite/binutils-all/readelf.exp
@@ -366,7 +366,7 @@ if {![binutils_assemble $srcdir/$subdir/version.s tmpdir/version.o]} then {
 if {![binutils_assemble $srcdir/$subdir/pr18374.s tmpdir/pr18374.o]} then {
     perror "could not assemble PR18374 test file"
     unresolved "readelf - failed to assemble"
-    fail "readelf --debug-loc"
+    fail "readelf --debug-dump=loc"
 } else {
 
     if ![is_remote host] {
@@ -379,6 +379,37 @@ 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 {
+    perror "could not assemble locview-1 test file"
+    unresolved "readelf - failed to assemble"
+    fail "readelf --debug-dump=loc"
+} 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 {
+    perror "could not assemble locview-2 test file"
+    unresolved "readelf - failed to assemble"
+    fail "readelf --debug-dump=loc"
+} 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 {
     perror "could not assemble decompress dump test file"
@@ -421,5 +452,5 @@ 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
index 0000000..6148520
--- /dev/null
+++ b/binutils/testsuite/binutils-all/readelf.locview-1
@@ -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
index 0000000..f064ad7
--- /dev/null
+++ b/binutils/testsuite/binutils-all/readelf.locview-2
@@ -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
diff --git a/include/dwarf2.def b/include/dwarf2.def
index 2a3b23f..8e731a3 100644
--- a/include/dwarf2.def
+++ b/include/dwarf2.def
@@ -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.  */
diff --git a/include/dwarf2.h b/include/dwarf2.h
index a2e022d..fd76d82 100644
--- a/include/dwarf2.h
+++ b/include/dwarf2.h
@@ -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,


-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]