From 882829b72716d43a7f4b3ce2c82e58d3fa6d4573 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E2=80=9Cbhkumarn=E2=80=9D?= <Bhuvanendra.KumarN@amd.com>
Date: Tue, 31 May 2022 15:03:16 +0530
Subject: [PATCH] [PATCH 2/2] Binutils support for dwarf-5.

For clang compiled with dwarf-5, multiple issues are fixed which are
related to .debug_rnglists and .debug_loclists sections and their offset
address dump comprising single and multiple CU. There are 2 patches
and this is patch 2/2 and it has dependency on patch 1/2 and its
continuation of patch 1/2.

Issues fixed in patch 2/2 are:
Issue 4: .debug_rnglists section dump for multiple CU.

	* dwarf.c (fetch_indexed_value): Use base_address parameter to
	access the section offset.
	(read_and_display_attr_value): Fix support for DW_FORM_rnglistx form.
	Add support for DW_AT_rnglists_base attribute.
	Read attribute DW_AT_rnglists_base which can come before or after
	DW_AT_ranges attribute.
	(display_offset_entry_loclists): Fix support for DW_LLE_base_addressx.
	(display_debug_rnglists_list): Add start_header as parameter and
	return the start of the range list header of next compilation unit.
	(display_debug_rnglists_header): New function to dump range lists header
	for each compilation unit.
	(display_debug_ranges): For each compilation unit call
	display_debug_rnglists_header accordingly.
	* dwarf.h (struct debug_info): Add rnglists_base field.
	* testsuite/binutils-all/dw5-loclist.S: New file, .debug_loclists section
	content is updated.
	* testsuite/binutils-all/dw5-loclist.W: New file, expected output.
	* testsuite/binutils-all/readelf.exp: Added new test point dw5-loclist.
---
 binutils/dwarf.c                              | 143 +++-
 binutils/dwarf.h                              |   1 +
 binutils/testsuite/binutils-all/dw5-loclist.S | 691 ++++++++++++++++++
 binutils/testsuite/binutils-all/dw5-loclist.W |  27 +
 binutils/testsuite/binutils-all/readelf.exp   |  19 +
 5 files changed, 865 insertions(+), 16 deletions(-)
 create mode 100644 binutils/testsuite/binutils-all/dw5-loclist.S
 create mode 100644 binutils/testsuite/binutils-all/dw5-loclist.W

diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index 566104762d1..58675b4088d 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -118,7 +118,6 @@ int dwarf_cutoff_level = -1;
 unsigned long dwarf_start_die;
 
 int dwarf_check = 0;
-#define DEBUG_LOCLISTS_RNGLISTS_SECTION_HEADER_LEN 12
 
 /* Convenient constant, to avoid having to cast -1 to dwarf_vma when
    testing whether e.g. a locview list is present.  */
@@ -855,7 +854,7 @@ fetch_indexed_value (dwarf_vma idx,
 
   /* Offsets are biased by the size of the section header
      or base address.  */
-  if (sec_enum == loclists)
+  if ((sec_enum == loclists) || (sec_enum == rnglists))
     offset += base_address;
   else
     offset += bias;
@@ -921,6 +920,7 @@ typedef struct abbrev_map
 static abbrev_map *   cu_abbrev_map = NULL;
 static unsigned long  num_abbrev_map_entries = 0;
 static unsigned long  next_free_abbrev_map_entry = 0;
+static abbrev_attr *ranges_attr = NULL;
 
 #define INITIAL_NUM_ABBREV_MAP_ENTRIES 8
 #define ABBREV_MAP_ENTRIES_INCREMENT   8
@@ -2451,6 +2451,7 @@ read_and_display_attr_value (unsigned long           attribute,
   dwarf_vma uvalue_hi = 0;
   unsigned char *block_start = NULL;
   unsigned char *orig_data = data;
+  dwarf_vma uvalue_rnglists_base;
 
   if (data > end || (data == end && form != DW_FORM_flag_present))
     {
@@ -2801,7 +2802,7 @@ read_and_display_attr_value (unsigned long           attribute,
 	  else if (form == DW_FORM_rnglistx)
 	    printf (_("%c(index: 0x%s): %s"), delimiter,
 	            dwarf_vmatoa ("x", uvalue),
-	            dwarf_vmatoa ("x", fetch_indexed_value (uvalue, rnglists, 0)));
+	            dwarf_vmatoa ("x", debug_info_p->range_lists [uvalue]));
 	  else if (do_wide)
 	    /* We have already displayed the form name.  */
 	    printf (_("%c(index: 0x%s): %s"), delimiter,
@@ -2839,6 +2840,13 @@ read_and_display_attr_value (unsigned long           attribute,
 	  debug_info_p->loclists_base = uvalue;
 	  break;
 
+	case DW_AT_rnglists_base:
+	  if (debug_info_p->rnglists_base)
+	    warn (_("CU @ 0x%s has multiple rnglists_base values"),
+	          dwarf_vmatoa ("x", debug_info_p->cu_offset));
+	  debug_info_p->rnglists_base = uvalue;
+	  break;
+
 	case DW_AT_frame_base:
 	  have_frame_base = 1;
 	  /* Fall through.  */
@@ -2934,6 +2942,24 @@ read_and_display_attr_value (unsigned long           attribute,
 	  break;
 
 	case DW_AT_ranges:
+	  uvalue_rnglists_base = 0;
+	  /* DW_AT_rnglists_base can appear before or after DW_AT_ranges attribute.
+	     If its found before, DW_AT_rnglists_base is used directly,
+	     otherwise its looked ahead from DW_AT_ranges and read.  */
+	  if (!debug_info_p->rnglists_base) {
+	    if (ranges_attr && ranges_attr->next && ranges_attr->next->next &&
+	        (ranges_attr->next->next->attribute == DW_AT_rnglists_base)) {
+	      unsigned char *data_dupl = data;
+	      dwarf_vma uvalue_skip;
+	      data_dupl = skip_attr_bytes (ranges_attr->next->form, data_dupl, end,
+	                                   pointer_size, offset_size,
+	                                   dwarf_version, &uvalue_skip);
+	      SAFE_BYTE_GET_AND_INC (uvalue_rnglists_base, data_dupl, offset_size, end);
+	    }
+	  }
+	  else
+	    uvalue_rnglists_base = debug_info_p->rnglists_base;
+
 	  if ((dwarf_version < 4
 	       && (form == DW_FORM_data4 || form == DW_FORM_data8))
 	      || form == DW_FORM_sec_offset
@@ -2942,6 +2968,7 @@ read_and_display_attr_value (unsigned long           attribute,
 	      /* Process range list.  */
 	      unsigned int lmax = debug_info_p->max_range_lists;
 	      unsigned int num = debug_info_p->num_range_lists;
+	      dwarf_vma uvalue_index;
 
 	      if (lmax == 0 || num >= lmax)
 		{
@@ -2952,10 +2979,15 @@ read_and_display_attr_value (unsigned long           attribute,
 		  debug_info_p->max_range_lists = lmax;
 		}
 
+	      uvalue_index = uvalue;
 	      if (form == DW_FORM_rnglistx)
-		uvalue = fetch_indexed_value (uvalue, rnglists, 0);
+		uvalue = fetch_indexed_value (uvalue, rnglists, uvalue_rnglists_base);
 
-	      debug_info_p->range_lists [num] = uvalue;
+	      uvalue += uvalue_rnglists_base;
+	      if (form == DW_FORM_rnglistx)
+	        debug_info_p->range_lists [uvalue_index] = uvalue;
+	      else
+	        debug_info_p->range_lists [num] = uvalue;
 	      debug_info_p->num_range_lists++;
 	    }
 	  break;
@@ -3329,6 +3361,7 @@ read_and_display_attr_value (unsigned long           attribute,
       /* Fall through.  */
     case DW_AT_location:
     case DW_AT_loclists_base:
+    case DW_AT_rnglists_base:
     case DW_AT_string_length:
     case DW_AT_return_addr:
     case DW_AT_data_member_location:
@@ -3347,8 +3380,12 @@ read_and_display_attr_value (unsigned long           attribute,
       if ((dwarf_version < 4
 	   && (form == DW_FORM_data4 || form == DW_FORM_data8))
 	  || form == DW_FORM_sec_offset
-	  || form == DW_FORM_loclistx)
-	printf (_(" (location list)"));
+	  || form == DW_FORM_loclistx) {
+	if (attribute == DW_AT_rnglists_base)
+	  printf (_(" (range list)"));
+	else
+	  printf (_(" (location list)"));
+      }
       /* Fall through.  */
     case DW_AT_allocated:
     case DW_AT_associated:
@@ -3835,6 +3872,7 @@ process_debug_info (struct dwarf_section * section,
 	  debug_information [unit].range_lists = NULL;
 	  debug_information [unit].max_range_lists= 0;
 	  debug_information [unit].num_range_lists = 0;
+	  debug_information [unit].rnglists_base = 0;
 	}
 
       if (!do_loc && dwarf_start_die == 0)
@@ -4056,6 +4094,8 @@ process_debug_info (struct dwarf_section * section,
 	      if (! do_loc && do_printing)
 		/* Show the offset from where the tag was extracted.  */
 		printf ("    <%lx>", (unsigned long)(tags - section_begin));
+	      if (attr->attribute == DW_AT_ranges)
+	        ranges_attr = attr;
 	      tags = read_and_display_attr (attr->attribute,
 					    attr->form,
 					    attr->implicit_const,
@@ -7086,9 +7126,6 @@ display_offset_entry_loclists (struct dwarf_section *section)
 	    case DW_LLE_base_addressx:
 	      READ_ULEB (base_address, start, end);
 	      print_dwarf_vma (base_address, address_size);
-	      printf (_("(index into .debug_addr) "));
-	      base_address = fetch_indexed_addr (base_address, address_size);
-	      print_dwarf_vma (base_address, address_size);
 	      printf (_("(base address)\n"));
 	      continue;
 
@@ -7959,7 +7996,8 @@ display_debug_rnglists_list (unsigned char * start,
 			     unsigned char * finish,
 			     unsigned int    pointer_size,
 			     dwarf_vma       offset,
-			     dwarf_vma       base_address)
+			     dwarf_vma       base_address,
+			     unsigned char ** start_header)
 {
   unsigned char *next = start;
 
@@ -8026,8 +8064,10 @@ display_debug_rnglists_list (unsigned char * start,
 	  rlet = DW_RLE_end_of_list;
 	  break;
 	}
-      if (rlet == DW_RLE_end_of_list)
-	break;
+      if (rlet == DW_RLE_end_of_list) {
+        *start_header = start;
+        break;
+      }
       if (rlet == DW_RLE_base_address || rlet == DW_RLE_base_addressx)
 	continue;
 
@@ -8050,6 +8090,69 @@ display_debug_rnglists_list (unsigned char * start,
     }
 }
 
+static void display_debug_rnglists_header (unsigned char * start,
+                                           unsigned char * finish)
+{
+      dwarf_vma initial_length;
+      unsigned char segment_selector_size;
+      unsigned int offset_size, offset_entry_count, i;
+      unsigned short version;
+      unsigned char  address_size = 0;
+
+      /* Get and check the length of the block.  */
+      SAFE_BYTE_GET_AND_INC (initial_length, start, 4, finish);
+
+      if (initial_length == 0xffffffff)
+        {
+          /* This section is 64-bit DWARF 3.  */
+          SAFE_BYTE_GET_AND_INC (initial_length, start, 8, finish);
+          offset_size = 8;
+        }
+      else
+        offset_size = 4;
+
+      /* Get the other fields in the header.  */
+      SAFE_BYTE_GET_AND_INC (version, start, 2, finish);
+      SAFE_BYTE_GET_AND_INC (address_size, start, 1, finish);
+      SAFE_BYTE_GET_AND_INC (segment_selector_size, start, 1, finish);
+      SAFE_BYTE_GET_AND_INC (offset_entry_count, start, 4, finish);
+
+      putchar ('\n');
+      printf (_("  Length:          0x%s\n"), dwarf_vmatoa ("x", initial_length));
+      printf (_("  DWARF version:   %u\n"), version);
+      printf (_("  Address size:    %u\n"), address_size);
+      printf (_("  Segment size:    %u\n"), segment_selector_size);
+      printf (_("  Offset entries:  %u\n"), offset_entry_count);
+
+      if (offset_entry_count != 0)
+        {
+          printf (_("\n   Offsets starting at 0x%lx:\n"),
+                  (long)(start - debug_displays [rnglists].section.start));
+          if (offset_size == 8)
+            {
+              for (i = 0; i < offset_entry_count; i++)
+                {
+                  dwarf_vma entry;
+
+                  SAFE_BYTE_GET_AND_INC (entry, start, 8, finish);
+                  printf (_("    [%6u] 0x%s\n"), i, dwarf_vmatoa ("x", entry));
+                }
+            }
+          else
+            {
+              for (i = 0; i < offset_entry_count; i++)
+                {
+                  uint32_t entry;
+
+                  SAFE_BYTE_GET_AND_INC (entry, start, 4, finish);
+                  printf (_("    [%6u] 0x%x\n"), i, entry);
+                }
+            }
+        }
+      putchar ('\n');
+      printf (_("    Offset   Begin    End\n"));
+}
+
 static int
 display_debug_ranges (struct dwarf_section *section,
 		      void *file ATTRIBUTE_UNUSED)
@@ -8066,6 +8169,7 @@ display_debug_ranges (struct dwarf_section *section,
   /* Initialize it due to a false compiler warning.  */
   unsigned char         address_size = 0;
   dwarf_vma             last_offset = 0;
+  unsigned char *       start_header = NULL;
 
   if (bytes == 0)
     {
@@ -8226,7 +8330,8 @@ display_debug_ranges (struct dwarf_section *section,
   putchar ('\n');
   printf (_("    Offset   Begin    End\n"));
 
-  for (i = 0; i < num_range_list; i++)
+  unsigned int range_lists_count = 0;
+  for (i = 0; i < num_range_list; i++, range_lists_count++)
     {
       struct range_entry *range_entry = &range_entries[i];
       debug_info *debug_info_p = range_entry->debug_info_p;
@@ -8239,6 +8344,12 @@ display_debug_ranges (struct dwarf_section *section,
       offset = range_entry->ranges_offset;
       base_address = debug_info_p->base_address;
 
+      if ((i > 0) &&
+          (start_header != NULL) &&
+          (range_lists_count == range_entries[i-1].debug_info_p->num_range_lists)) {
+        range_lists_count = 0;
+        display_debug_rnglists_header (start_header, finish);
+      }
       /* PR 17512: file: 001-101485-0.001:0.1.  */
       if (pointer_size < 2 || pointer_size > 8)
 	{
@@ -8253,7 +8364,7 @@ display_debug_ranges (struct dwarf_section *section,
 		(unsigned long) offset, i);
 	  continue;
 	}
-      next = section_begin + offset + DEBUG_LOCLISTS_RNGLISTS_SECTION_HEADER_LEN;
+      next = section_begin + offset;
 
       /* If multiple DWARF entities reference the same range then we will
          have multiple entries in the `range_entries' list for the same
@@ -8285,7 +8396,7 @@ display_debug_ranges (struct dwarf_section *section,
 
       if (is_rnglists)
 	display_debug_rnglists_list
-	  (start, finish, pointer_size, offset, base_address);
+	  (start, finish, pointer_size, offset, base_address, &start_header);
       else
 	display_debug_ranges_list
 	  (start, finish, pointer_size, offset, base_address);
diff --git a/binutils/dwarf.h b/binutils/dwarf.h
index 040e674c6ce..8a89c08e7c2 100644
--- a/binutils/dwarf.h
+++ b/binutils/dwarf.h
@@ -192,6 +192,7 @@ typedef struct
   dwarf_vma *    range_lists;
   unsigned int   num_range_lists;
   unsigned int   max_range_lists;
+  dwarf_vma      rnglists_base;
 }
 debug_info;
 
diff --git a/binutils/testsuite/binutils-all/dw5-loclist.S b/binutils/testsuite/binutils-all/dw5-loclist.S
new file mode 100644
index 00000000000..5adf66c66c0
--- /dev/null
+++ b/binutils/testsuite/binutils-all/dw5-loclist.S
@@ -0,0 +1,691 @@
+/* Copyright (C) 2017-2022 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+	.file	"main.c"
+	.text
+.Ltext0:
+	.p2align 4,,15
+	.globl	func
+	.type	func, %function
+func:
+.LFB0:
+	/* main.c:5 */
+.LM1:
+/* BLOCK 2 freq:10000 seq:0 */
+/* PRED: ENTRY [100.0%]  (FALLTHRU) */
+	/* main.c:5 */
+.LM2:
+	.dc.b 0
+/* SUCC: */
+	.dc.b 0
+.LFE0:
+	.size	func, .-func
+	.section	.text.startup,"ax",%progbits
+	.p2align 4,,15
+	.globl	main
+	.type	main, %function
+main:
+.LFB1:
+	/* main.c:6 */
+.LM3:
+.LVL0:
+/* BLOCK 2 freq:10000 seq:0 */
+/* PRED: ENTRY [100.0%]  (FALLTHRU) */
+	.dc.b 0
+	/* main.c:6 */
+.LM4:
+	.dc.b 0
+.LVL1:
+	.dc.b 0
+.LVL2:
+	.dc.b 0
+/* SUCC: EXIT [100.0%]  */
+	.dc.b 0
+.LFE1:
+	.size	main, .-main
+ .ifdef HPUX
+pvar	.comm	8
+yvar	.comm	4
+ .else
+	.comm	pvar,8,8
+	.comm	yvar,4,4
+ .endif
+	.globl	xvar
+	.data
+	.align 4
+	.type	xvar, %object
+	.size	xvar, 4
+xvar:
+	.4byte	42
+	.text
+.Letext0:
+	.section	.debug_info,"",%progbits
+.Ldebug_info0:
+	.4byte	0x160	/* Length of Compilation Unit Info */
+	.2byte	0x5	/* DWARF version number */
+	.byte	0x1	/* DW_UT_compile */
+	.byte	0x8	/* Pointer Size (in bytes) */
+	.4byte	.Ldebug_abbrev0	/* Offset Into Abbrev. Section */
+	.uleb128 0x6	/* (DIE (0xc) DW_TAG_compile_unit) */
+	.4byte	.LASF21	/* DW_AT_producer: "GNU C11 7.0.1 20170218 (experimental) -mtune=generic -march=x86-64 -gdwarf-5 -O2" */
+	.byte	0x1d	/* DW_AT_language */
+	.4byte	.LASF0	/* DW_AT_name: "main.c" */
+	.4byte	.LASF1	/* DW_AT_comp_dir: "" */
+	.4byte	.LLRL2	/* DW_AT_ranges */
+	.8byte	0	/* DW_AT_low_pc */
+	.4byte	.Ldebug_line0	/* DW_AT_stmt_list */
+	.uleb128 0x1	/* (DIE (0x2a) DW_TAG_base_type) */
+	.byte	0x1	/* DW_AT_byte_size */
+	.byte	0x8	/* DW_AT_encoding */
+	.4byte	.LASF2	/* DW_AT_name: "unsigned char" */
+	.uleb128 0x1	/* (DIE (0x31) DW_TAG_base_type) */
+	.byte	0x2	/* DW_AT_byte_size */
+	.byte	0x7	/* DW_AT_encoding */
+	.4byte	.LASF3	/* DW_AT_name: "short unsigned int" */
+	.uleb128 0x1	/* (DIE (0x38) DW_TAG_base_type) */
+	.byte	0x4	/* DW_AT_byte_size */
+	.byte	0x7	/* DW_AT_encoding */
+	.4byte	.LASF4	/* DW_AT_name: "unsigned int" */
+	.uleb128 0x1	/* (DIE (0x3f) DW_TAG_base_type) */
+	.byte	0x8	/* DW_AT_byte_size */
+	.byte	0x7	/* DW_AT_encoding */
+	.4byte	.LASF5	/* DW_AT_name: "long unsigned int" */
+	.uleb128 0x1	/* (DIE (0x46) DW_TAG_base_type) */
+	.byte	0x1	/* DW_AT_byte_size */
+	.byte	0x6	/* DW_AT_encoding */
+	.4byte	.LASF6	/* DW_AT_name: "signed char" */
+	.uleb128 0x1	/* (DIE (0x4d) DW_TAG_base_type) */
+	.byte	0x2	/* DW_AT_byte_size */
+	.byte	0x5	/* DW_AT_encoding */
+	.4byte	.LASF7	/* DW_AT_name: "short int" */
+	.uleb128 0x7	/* (DIE (0x54) DW_TAG_base_type) */
+	.byte	0x4	/* DW_AT_byte_size */
+	.byte	0x5	/* DW_AT_encoding */
+	.ascii "int\0"	/* DW_AT_name */
+	.uleb128 0x1	/* (DIE (0x5b) DW_TAG_base_type) */
+	.byte	0x8	/* DW_AT_byte_size */
+	.byte	0x5	/* DW_AT_encoding */
+	.4byte	.LASF8	/* DW_AT_name: "long int" */
+	.uleb128 0x1	/* (DIE (0x62) DW_TAG_base_type) */
+	.byte	0x8	/* DW_AT_byte_size */
+	.byte	0x7	/* DW_AT_encoding */
+	.4byte	.LASF9	/* DW_AT_name: "sizetype" */
+	.uleb128 0x3	/* (DIE (0x69) DW_TAG_pointer_type) */
+			/* DW_AT_byte_size (0x8) */
+	.4byte	0x6e	/* DW_AT_type */
+	.uleb128 0x1	/* (DIE (0x6e) DW_TAG_base_type) */
+	.byte	0x1	/* DW_AT_byte_size */
+	.byte	0x6	/* DW_AT_encoding */
+	.4byte	.LASF10	/* DW_AT_name: "char" */
+	.uleb128 0x8	/* (DIE (0x75) DW_TAG_variable) */
+	.4byte	.LASF11	/* DW_AT_name: "__environ" */
+	.byte	0x2	/* DW_AT_decl_file (/usr/include/unistd.h) */
+	.2byte	0x222	/* DW_AT_decl_line */
+	.4byte	0x81	/* DW_AT_type */
+			/* DW_AT_external */
+			/* DW_AT_declaration */
+	.uleb128 0x3	/* (DIE (0x81) DW_TAG_pointer_type) */
+			/* DW_AT_byte_size (0x8) */
+	.4byte	0x69	/* DW_AT_type */
+	.uleb128 0x2	/* (DIE (0x86) DW_TAG_variable) */
+	.4byte	.LASF12	/* DW_AT_name: "optarg" */
+			/* DW_AT_decl_file (3, /usr/include/getopt.h) */
+	.byte	0x39	/* DW_AT_decl_line */
+	.4byte	0x69	/* DW_AT_type */
+			/* DW_AT_external */
+			/* DW_AT_declaration */
+	.uleb128 0x2	/* (DIE (0x90) DW_TAG_variable) */
+	.4byte	.LASF13	/* DW_AT_name: "optind" */
+			/* DW_AT_decl_file (3, /usr/include/getopt.h) */
+	.byte	0x47	/* DW_AT_decl_line */
+	.4byte	0x54	/* DW_AT_type */
+			/* DW_AT_external */
+			/* DW_AT_declaration */
+	.uleb128 0x2	/* (DIE (0x9a) DW_TAG_variable) */
+	.4byte	.LASF14	/* DW_AT_name: "opterr" */
+			/* DW_AT_decl_file (3, /usr/include/getopt.h) */
+	.byte	0x4c	/* DW_AT_decl_line */
+	.4byte	0x54	/* DW_AT_type */
+			/* DW_AT_external */
+			/* DW_AT_declaration */
+	.uleb128 0x2	/* (DIE (0xa4) DW_TAG_variable) */
+	.4byte	.LASF15	/* DW_AT_name: "optopt" */
+			/* DW_AT_decl_file (3, /usr/include/getopt.h) */
+	.byte	0x50	/* DW_AT_decl_line */
+	.4byte	0x54	/* DW_AT_type */
+			/* DW_AT_external */
+			/* DW_AT_declaration */
+	.uleb128 0x4	/* (DIE (0xae) DW_TAG_variable) */
+	.4byte	.LASF16	/* DW_AT_name: "xvar" */
+			/* DW_AT_decl_file (1, main.c) */
+	.byte	0x2	/* DW_AT_decl_line */
+	.4byte	0x54	/* DW_AT_type */
+			/* DW_AT_external */
+	.uleb128 0x9	/* DW_AT_location */
+	.byte	0x3	/* DW_OP_addr */
+	.8byte	0x1234
+	.uleb128 0x4	/* (DIE (0xc2) DW_TAG_variable) */
+	.4byte	.LASF17	/* DW_AT_name: "yvar" */
+			/* DW_AT_decl_file (1, main.c) */
+	.byte	0x3	/* DW_AT_decl_line */
+	.4byte	0x54	/* DW_AT_type */
+			/* DW_AT_external */
+	.uleb128 0x9	/* DW_AT_location */
+	.byte	0x3	/* DW_OP_addr */
+	.8byte	0x1234
+	.uleb128 0x4	/* (DIE (0xd6) DW_TAG_variable) */
+	.4byte	.LASF18	/* DW_AT_name: "pvar" */
+			/* DW_AT_decl_file (1, main.c) */
+	.byte	0x4	/* DW_AT_decl_line */
+	.4byte	0xea	/* DW_AT_type */
+			/* DW_AT_external */
+	.uleb128 0x9	/* DW_AT_location */
+	.byte	0x3	/* DW_OP_addr */
+	.8byte	0x1234
+	.uleb128 0x3	/* (DIE (0xea) DW_TAG_pointer_type) */
+			/* DW_AT_byte_size (0x8) */
+	.4byte	0x54	/* DW_AT_type */
+	.uleb128 0x9	/* (DIE (0xef) DW_TAG_subprogram) */
+			/* DW_AT_external */
+	.4byte	.LASF22	/* DW_AT_name: "main" */
+	.byte	0x1	/* DW_AT_decl_file (main.c) */
+	.byte	0x6	/* DW_AT_decl_line */
+			/* DW_AT_prototyped */
+	.4byte	0x54	/* DW_AT_type */
+	.8byte	0x1234	/* DW_AT_low_pc */
+	.8byte	0x5678	/* DW_AT_high_pc */
+	.uleb128 0x1	/* DW_AT_frame_base */
+	.byte	0x9c	/* DW_OP_call_frame_cfa */
+			/* DW_AT_call_all_calls */
+	.4byte	0x13e	/* DW_AT_sibling */
+	.uleb128 0x5	/* (DIE (0x110) DW_TAG_formal_parameter) */
+	.4byte	.LASF19	/* DW_AT_name: "argc" */
+			/* DW_AT_decl_file (1, main.c) */
+			/* DW_AT_decl_line (0x6) */
+	.4byte	0x54	/* DW_AT_type */
+	.4byte	.LLST0	/* DW_AT_location */
+	.uleb128 0x5	/* (DIE (0x11d) DW_TAG_formal_parameter) */
+	.4byte	.LASF20	/* DW_AT_name: "argv" */
+			/* DW_AT_decl_file (1, main.c) */
+			/* DW_AT_decl_line (0x6) */
+	.4byte	0x81	/* DW_AT_type */
+	.4byte	.LLST1	/* DW_AT_location */
+	.uleb128 0xa	/* (DIE (0x12a) DW_TAG_call_site) */
+	.8byte	0x12345	/* DW_AT_call_return_pc */
+	.4byte	0x157	/* DW_AT_call_origin */
+	.uleb128 0xb	/* (DIE (0x137) DW_TAG_call_site_parameter) */
+	.uleb128 0x1	/* DW_AT_location */
+	.byte	0x55	/* DW_OP_reg5 */
+	.uleb128 0x1	/* DW_AT_call_value */
+	.byte	0x30	/* DW_OP_lit0 */
+	.byte	0	/* end of children of DIE 0x12a */
+	.byte	0	/* end of children of DIE 0xef */
+	.uleb128 0xc	/* (DIE (0x13e) DW_TAG_subprogram) */
+			/* DW_AT_external */
+	.4byte	.LASF23	/* DW_AT_name: "func" */
+	.byte	0x1	/* DW_AT_decl_file (main.c) */
+	.byte	0x5	/* DW_AT_decl_line */
+			/* DW_AT_prototyped */
+	.8byte	0x1234	/* DW_AT_low_pc */
+	.8byte	0x5678	/* DW_AT_high_pc */
+	.uleb128 0x1	/* DW_AT_frame_base */
+	.byte	0x9c	/* DW_OP_call_frame_cfa */
+			/* DW_AT_call_all_calls */
+	.uleb128 0xd	/* (DIE (0x157) DW_TAG_subprogram) */
+			/* DW_AT_external */
+			/* DW_AT_declaration */
+	.4byte	.LASF24	/* DW_AT_linkage_name: "alarm" */
+	.4byte	.LASF24	/* DW_AT_name: "alarm" */
+	.byte	0x2	/* DW_AT_decl_file (/usr/include/unistd.h) */
+	.2byte	0x1b3	/* DW_AT_decl_line */
+	.byte	0	/* end of children of DIE 0xc */
+	.section	.debug_abbrev,"",%progbits
+.Ldebug_abbrev0:
+.Lfunc_begin0:
+	.uleb128 0x1	/* (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) */
+.Lfunc_end0:
+	.uleb128 0x3	/* (DW_AT_name) */
+	.uleb128 0xe	/* (DW_FORM_strp) */
+	.byte	0
+	.byte	0
+	.uleb128 0x2	/* (abbrev code) */
+	.uleb128 0x34	/* (TAG: DW_TAG_variable) */
+	.byte	0	/* DW_children_no */
+	.uleb128 0x3	/* (DW_AT_name) */
+	.uleb128 0xe	/* (DW_FORM_strp) */
+	.uleb128 0x3a	/* (DW_AT_decl_file) */
+	.uleb128 0x21	/* (DW_FORM_implicit_const) */
+	.sleb128 3	/* (/usr/include/getopt.h) */
+	.uleb128 0x3b	/* (DW_AT_decl_line) */
+	.uleb128 0xb	/* (DW_FORM_data1) */
+	.uleb128 0x49	/* (DW_AT_type) */
+	.uleb128 0x13	/* (DW_FORM_ref4) */
+	.uleb128 0x3f	/* (DW_AT_external) */
+	.uleb128 0x19	/* (DW_FORM_flag_present) */
+	.uleb128 0x3c	/* (DW_AT_declaration) */
+	.uleb128 0x19	/* (DW_FORM_flag_present) */
+	.byte	0
+	.byte	0
+	.uleb128 0x3	/* (abbrev code) */
+	.uleb128 0xf	/* (TAG: DW_TAG_pointer_type) */
+	.byte	0	/* DW_children_no */
+	.uleb128 0xb	/* (DW_AT_byte_size) */
+	.uleb128 0x21	/* (DW_FORM_implicit_const) */
+	.sleb128 8
+	.uleb128 0x49	/* (DW_AT_type) */
+	.uleb128 0x13	/* (DW_FORM_ref4) */
+	.byte	0
+	.byte	0
+	.uleb128 0x4	/* (abbrev code) */
+	.uleb128 0x34	/* (TAG: DW_TAG_variable) */
+	.byte	0	/* DW_children_no */
+	.uleb128 0x3	/* (DW_AT_name) */
+	.uleb128 0xe	/* (DW_FORM_strp) */
+	.uleb128 0x3a	/* (DW_AT_decl_file) */
+	.uleb128 0x21	/* (DW_FORM_implicit_const) */
+	.sleb128 1	/* (main.c) */
+	.uleb128 0x3b	/* (DW_AT_decl_line) */
+	.uleb128 0xb	/* (DW_FORM_data1) */
+	.uleb128 0x49	/* (DW_AT_type) */
+	.uleb128 0x13	/* (DW_FORM_ref4) */
+	.uleb128 0x3f	/* (DW_AT_external) */
+	.uleb128 0x19	/* (DW_FORM_flag_present) */
+	.uleb128 0x2	/* (DW_AT_location) */
+	.uleb128 0x18	/* (DW_FORM_exprloc) */
+	.byte	0
+	.byte	0
+	.uleb128 0x5	/* (abbrev code) */
+	.uleb128 0x5	/* (TAG: DW_TAG_formal_parameter) */
+	.byte	0	/* DW_children_no */
+	.uleb128 0x3	/* (DW_AT_name) */
+	.uleb128 0xe	/* (DW_FORM_strp) */
+	.uleb128 0x3a	/* (DW_AT_decl_file) */
+	.uleb128 0x21	/* (DW_FORM_implicit_const) */
+	.sleb128 1	/* (main.c) */
+	.uleb128 0x3b	/* (DW_AT_decl_line) */
+	.uleb128 0x21	/* (DW_FORM_implicit_const) */
+	.sleb128 6
+	.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
+	.uleb128 0x6	/* (abbrev code) */
+	.uleb128 0x11	/* (TAG: DW_TAG_compile_unit) */
+	.byte	0x1	/* DW_children_yes */
+	.uleb128 0x25	/* (DW_AT_producer) */
+	.uleb128 0xe	/* (DW_FORM_strp) */
+	.uleb128 0x13	/* (DW_AT_language) */
+	.uleb128 0xb	/* (DW_FORM_data1) */
+	.uleb128 0x3	/* (DW_AT_name) */
+	.uleb128 0x1f	/* (DW_FORM_line_strp) */
+	.uleb128 0x1b	/* (DW_AT_comp_dir) */
+	.uleb128 0x1f	/* (DW_FORM_line_strp) */
+	.uleb128 0x55	/* (DW_AT_ranges) */
+	.uleb128 0x17	/* (DW_FORM_sec_offset) */
+	.uleb128 0x11	/* (DW_AT_low_pc) */
+	.uleb128 0x1	/* (DW_FORM_addr) */
+	.uleb128 0x10	/* (DW_AT_stmt_list) */
+	.uleb128 0x17	/* (DW_FORM_sec_offset) */
+	.byte	0
+	.byte	0
+	.uleb128 0x7	/* (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
+	.uleb128 0x8	/* (abbrev code) */
+	.uleb128 0x34	/* (TAG: DW_TAG_variable) */
+	.byte	0	/* DW_children_no */
+	.uleb128 0x3	/* (DW_AT_name) */
+	.uleb128 0xe	/* (DW_FORM_strp) */
+	.uleb128 0x3a	/* (DW_AT_decl_file) */
+	.uleb128 0xb	/* (DW_FORM_data1) */
+	.uleb128 0x3b	/* (DW_AT_decl_line) */
+	.uleb128 0x5	/* (DW_FORM_data2) */
+	.uleb128 0x49	/* (DW_AT_type) */
+	.uleb128 0x13	/* (DW_FORM_ref4) */
+	.uleb128 0x3f	/* (DW_AT_external) */
+	.uleb128 0x19	/* (DW_FORM_flag_present) */
+	.uleb128 0x3c	/* (DW_AT_declaration) */
+	.uleb128 0x19	/* (DW_FORM_flag_present) */
+	.byte	0
+	.byte	0
+	.uleb128 0x9	/* (abbrev code) */
+	.uleb128 0x2e	/* (TAG: DW_TAG_subprogram) */
+	.byte	0x1	/* DW_children_yes */
+	.uleb128 0x3f	/* (DW_AT_external) */
+	.uleb128 0x19	/* (DW_FORM_flag_present) */
+	.uleb128 0x3	/* (DW_AT_name) */
+	.uleb128 0xe	/* (DW_FORM_strp) */
+	.uleb128 0x3a	/* (DW_AT_decl_file) */
+	.uleb128 0xb	/* (DW_FORM_data1) */
+	.uleb128 0x3b	/* (DW_AT_decl_line) */
+	.uleb128 0xb	/* (DW_FORM_data1) */
+	.uleb128 0x27	/* (DW_AT_prototyped) */
+	.uleb128 0x19	/* (DW_FORM_flag_present) */
+	.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 0x7	/* (DW_FORM_data8) */
+	.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
+	.uleb128 0xa	/* (abbrev code) */
+	.uleb128 0x48	/* (TAG: DW_TAG_call_site) */
+	.byte	0x1	/* DW_children_yes */
+	.uleb128 0x7d	/* (DW_AT_call_return_pc) */
+	.uleb128 0x1	/* (DW_FORM_addr) */
+	.uleb128 0x7f	/* (DW_AT_call_origin) */
+	.uleb128 0x13	/* (DW_FORM_ref4) */
+	.byte	0
+	.byte	0
+	.uleb128 0xb	/* (abbrev code) */
+	.uleb128 0x49	/* (TAG: DW_TAG_call_site_parameter) */
+	.byte	0	/* DW_children_no */
+	.uleb128 0x2	/* (DW_AT_location) */
+	.uleb128 0x18	/* (DW_FORM_exprloc) */
+	.uleb128 0x7e	/* (DW_AT_call_value) */
+	.uleb128 0x18	/* (DW_FORM_exprloc) */
+	.byte	0
+	.byte	0
+	.uleb128 0xc	/* (abbrev code) */
+	.uleb128 0x2e	/* (TAG: DW_TAG_subprogram) */
+	.byte	0	/* DW_children_no */
+	.uleb128 0x3f	/* (DW_AT_external) */
+	.uleb128 0x19	/* (DW_FORM_flag_present) */
+	.uleb128 0x3	/* (DW_AT_name) */
+	.uleb128 0xe	/* (DW_FORM_strp) */
+	.uleb128 0x3a	/* (DW_AT_decl_file) */
+	.uleb128 0xb	/* (DW_FORM_data1) */
+	.uleb128 0x3b	/* (DW_AT_decl_line) */
+	.uleb128 0xb	/* (DW_FORM_data1) */
+	.uleb128 0x27	/* (DW_AT_prototyped) */
+	.uleb128 0x19	/* (DW_FORM_flag_present) */
+	.uleb128 0x11	/* (DW_AT_low_pc) */
+	.uleb128 0x1	/* (DW_FORM_addr) */
+	.uleb128 0x12	/* (DW_AT_high_pc) */
+	.uleb128 0x7	/* (DW_FORM_data8) */
+	.uleb128 0x40	/* (DW_AT_frame_base) */
+	.uleb128 0x18	/* (DW_FORM_exprloc) */
+	.uleb128 0x7a	/* (DW_AT_call_all_calls) */
+	.uleb128 0x19	/* (DW_FORM_flag_present) */
+	.byte	0
+	.byte	0
+	.uleb128 0xd	/* (abbrev code) */
+	.uleb128 0x2e	/* (TAG: DW_TAG_subprogram) */
+	.byte	0	/* DW_children_no */
+	.uleb128 0x3f	/* (DW_AT_external) */
+	.uleb128 0x19	/* (DW_FORM_flag_present) */
+	.uleb128 0x3c	/* (DW_AT_declaration) */
+	.uleb128 0x19	/* (DW_FORM_flag_present) */
+	.uleb128 0x6e	/* (DW_AT_linkage_name) */
+	.uleb128 0xe	/* (DW_FORM_strp) */
+	.uleb128 0x3	/* (DW_AT_name) */
+	.uleb128 0xe	/* (DW_FORM_strp) */
+	.uleb128 0x3a	/* (DW_AT_decl_file) */
+	.uleb128 0xb	/* (DW_FORM_data1) */
+	.uleb128 0x3b	/* (DW_AT_decl_line) */
+	.uleb128 0x5	/* (DW_FORM_data2) */
+	.byte	0
+	.byte	0
+	.byte	0
+	.section	.debug_loclists,"",%progbits
+        .long   .Ldebug_list_header_end0-.Ldebug_list_header_start0 # Length
+.Ldebug_list_header_start0:
+        .short  5                               # Version
+        .byte   8                               # Address size
+        .byte   0                               # Segment selector size
+        .long   3                               # Offset entry count
+.Lloclists_table_base0:
+        .long   .Ldebug_loc0-.Lloclists_table_base0
+        .long   .Ldebug_loc1-.Lloclists_table_base0
+        .long   .Ldebug_loc2-.Lloclists_table_base0
+.Ldebug_loc0:
+        .byte   4                               # DW_LLE_offset_pair
+        .uleb128 .Lfunc_begin0-.Lfunc_begin0    #   starting offset
+        .uleb128 .Lfunc_end0-.Lfunc_begin0      #   ending offset
+        .byte   6                               # Loc expr size
+        .byte   85                              # DW_OP_reg5
+        .byte   147                             # DW_OP_piece
+        .byte   8                               # 8
+        .byte   84                              # super-register DW_OP_reg4
+        .byte   147                             # DW_OP_piece
+        .byte   4                               # 4
+        .byte   0                               # DW_LLE_end_of_list
+.Ldebug_loc1:
+        .byte   4                               # DW_LLE_offset_pair
+        .uleb128 .Lfunc_begin0-.Lfunc_begin0    #   starting offset
+        .uleb128 .Lfunc_end0-.Lfunc_begin0      #   ending offset
+        .byte   6                               # Loc expr size
+        .byte   81                              # DW_OP_reg1
+        .byte   147                             # DW_OP_piece
+        .byte   8                               # 8
+        .byte   82                              # super-register DW_OP_reg2
+        .byte   147                             # DW_OP_piece
+        .byte   4                               # 4
+        .byte   0                               # DW_LLE_end_of_list
+.Ldebug_loc2:
+        .byte   4                               # DW_LLE_offset_pair
+        .uleb128 .Lfunc_begin0-.Lfunc_begin0    #   starting offset
+        .uleb128 .Lfunc_end0-.Lfunc_begin0      #   ending offset
+        .byte   6                               # Loc expr size
+        .byte   88                              # DW_OP_reg8
+        .byte   147                             # DW_OP_piece
+        .byte   8                               # 8
+        .byte   89                              # super-register DW_OP_reg9
+        .byte   147                             # DW_OP_piece
+        .byte   4                               # 4
+        .byte   0                               # DW_LLE_end_of_list
+.Ldebug_list_header_end0:
+	.section	.debug_aranges,"",%progbits
+	.4byte	0x3c	/* Length of Address Ranges Info */
+	.2byte	0x2	/* DWARF Version */
+	.4byte	.Ldebug_info0	/* Offset of Compilation Unit Info */
+	.byte	0x8	/* Size of Address */
+	.byte	0	/* Size of Segment Descriptor */
+	.2byte	0	/* Pad to 16 byte boundary */
+	.2byte	0
+	.8byte	0x1234	/* Address */
+	.8byte	0x4567	/* Length */
+	.8byte	0x1234	/* Address */
+	.8byte	0x5678	/* Length */
+	.8byte	0
+	.8byte	0
+	.section	.debug_rnglists,"",%progbits
+.Ldebug_ranges0:
+	.4byte	.Ldebug_ranges3-.Ldebug_ranges2	/* Length of Range Lists */
+.Ldebug_ranges2:
+	.2byte	0x5	/* DWARF Version */
+	.byte	0x8	/* Address Size */
+	.byte	0	/* Segment Size */
+	.4byte	0	/* Offset Entry Count */
+.LLRL2:
+	.byte	0x7	/* DW_RLE_start_length (*.LLRL2) */
+	.8byte	0x1234	/* Range begin address (*.LLRL2) */
+	.uleb128 .Letext0-.Ltext0	/* Range length (*.LLRL2) */
+	.byte	0x7	/* DW_RLE_start_length (*.LLRL2) */
+	.8byte	0x1234	/* Range begin address (*.LLRL2) */
+	.uleb128 .LFE1-.LFB1	/* Range length (*.LLRL2) */
+	.byte	0	/* DW_RLE_end_of_list (*.LLRL2) */
+.Ldebug_ranges3:
+	.section	.debug_line,"",%progbits
+.Ldebug_line0:
+	.4byte	.LELT0-.LSLT0	/* Length of Source Line Info */
+.LSLT0:
+	.2byte	0x5	/* DWARF Version */
+	.byte	0x8	/* Address Size */
+	.byte	0	/* Segment Size */
+	.4byte	.LELTP0-.LASLTP0	/* Prolog Length */
+.LASLTP0:
+	.byte	0x1	/* Minimum Instruction Length */
+	.byte	0x1	/* Maximum Operations Per Instruction */
+	.byte	0x1	/* Default is_stmt_start flag */
+	.byte	0xf6	/* Line Base Value (Special Opcodes) */
+	.byte	0xf2	/* Line Range Value (Special Opcodes) */
+	.byte	0xd	/* Special Opcode Base */
+	.byte	0	/* opcode: 0x1 has 0 args */
+	.byte	0x1	/* opcode: 0x2 has 1 arg */
+	.byte	0x1	/* opcode: 0x3 has 1 arg */
+	.byte	0x1	/* opcode: 0x4 has 1 arg */
+	.byte	0x1	/* opcode: 0x5 has 1 arg */
+	.byte	0	/* opcode: 0x6 has 0 args */
+	.byte	0	/* opcode: 0x7 has 0 args */
+	.byte	0	/* opcode: 0x8 has 0 args */
+	.byte	0x1	/* opcode: 0x9 has 1 arg */
+	.byte	0	/* opcode: 0xa has 0 args */
+	.byte	0	/* opcode: 0xb has 0 args */
+	.byte	0x1	/* opcode: 0xc has 1 arg */
+	.byte	0x1	/* Directory entry format count */
+	.uleb128 0x1	/* DW_LNCT_path */
+	.uleb128 0x1f	/* DW_FORM_line_strp */
+	.uleb128 0x3	/* Directories count */
+	.4byte	.LASF1	/* Directory Entry: 0: "" */
+	.4byte	.LASF25	/* Directory Entry: 0: "" */
+	.4byte	.LASF26	/* Directory Entry: 0: "/usr/include" */
+	.byte	0x2	/* File name entry format count */
+	.uleb128 0x1	/* DW_LNCT_path */
+	.uleb128 0x1f	/* DW_FORM_line_strp */
+	.uleb128 0x2	/* DW_LNCT_directory_index */
+	.uleb128 0xb	/* DW_FORM_data1 */
+	.uleb128 0x4	/* File names count */
+	.4byte	.LASF0	/* File Entry: 0: "main.c" */
+	.byte	0
+	.4byte	.LASF27	/* File Entry: 0: "main.c" */
+	.byte	0x1
+	.4byte	.LASF28	/* File Entry: 0: "unistd.h" */
+	.byte	0x2
+	.4byte	.LASF29	/* File Entry: 0: "getopt.h" */
+	.byte	0x2
+.LELTP0:
+	.byte	0	/* set address *.LM3 */
+	.uleb128 0x9
+	.byte	0x2
+	.8byte	0x1234
+	.byte	0x1c	/* line 6 */
+	.byte	0	/* set address *.LM4 */
+	.uleb128 0x9
+	.byte	0x2
+	.8byte	0x12346
+	.byte	0x1	/* copy line 6 */
+	.byte	0	/* set address *.LFE1 */
+	.uleb128 0x9
+	.byte	0x2
+	.8byte	0x1234
+	.byte	0	/* end sequence */
+	.uleb128 0x1
+	.byte	0x1
+	.byte	0	/* set address *.LM1 */
+	.uleb128 0x9
+	.byte	0x2
+	.8byte	0x1234
+	.byte	0x1b	/* line 5 */
+	.byte	0	/* set address *.LM2 */
+	.uleb128 0x9
+	.byte	0x2
+	.8byte	0x1234
+	.byte	0x1	/* copy line 5 */
+	.byte	0	/* set address *.Letext0 */
+	.uleb128 0x9
+	.byte	0x2
+	.8byte	0x1234
+	.byte	0	/* end sequence */
+	.uleb128 0x1
+	.byte	0x1
+.LELT0:
+	.section	.debug_str,"MS",%progbits,1
+.LASF4:
+	.asciz	"unsigned int"
+.LASF15:
+	.asciz	"optopt"
+.LASF22:
+	.asciz	"main"
+.LASF6:
+	.asciz	"signed char"
+.LASF16:
+	.asciz	"xvar"
+.LASF5:
+	.asciz	"long unsigned int"
+.LASF14:
+	.asciz	"opterr"
+.LASF21:
+	.asciz	"GNU C11 7.0.1 20170218 (experimental) -mtune=generic -march=x86-64 -gdwarf-5 -O2"
+.LASF2:
+	.asciz	"unsigned char"
+.LASF10:
+	.asciz	"char"
+.LASF13:
+	.asciz	"optind"
+.LASF8:
+	.asciz	"long int"
+.LASF19:
+	.asciz	"argc"
+.LASF3:
+	.asciz	"short unsigned int"
+.LASF17:
+	.asciz	"yvar"
+.LASF18:
+	.asciz	"pvar"
+.LASF11:
+	.asciz	"__environ"
+.LASF23:
+	.asciz	"func"
+.LASF12:
+	.asciz	"optarg"
+.LASF7:
+	.asciz	"short int"
+.LASF24:
+	.asciz	"alarm"
+.LASF9:
+	.asciz	"sizetype"
+.LASF20:
+	.asciz	"argv"
+	.section	.debug_line_str,"MS",%progbits,1
+.LASF1:
+	.asciz	""
+.LASF25:
+	.asciz	""
+.LASF29:
+	.asciz	"getopt.h"
+.LASF28:
+	.asciz	"unistd.h"
+.LASF0:
+	.asciz	"main.c"
+.LASF27:
+	.asciz	"main.c"
+.LASF26:
+	.asciz	"/usr/include"
+	.ident	"GCC: (GNU) 7.0.1 20170218 (experimental)"
+	.section	.note.GNU-stack,"",%progbits
diff --git a/binutils/testsuite/binutils-all/dw5-loclist.W b/binutils/testsuite/binutils-all/dw5-loclist.W
new file mode 100644
index 00000000000..79c220aa658
--- /dev/null
+++ b/binutils/testsuite/binutils-all/dw5-loclist.W
@@ -0,0 +1,27 @@
+Contents of the .debug_loclists section:
+
+Table at Offset 0x0
+  Length:          0x35
+  DWARF version:   5
+  Address size:    8
+  Segment size:    0
+  Offset entries:  3
+
+   Offset Entries starting at 0xc:
+    \[     0\] 0xc
+    \[     1\] 0x17
+    \[     2\] 0x22
+
+   Offset Entry 0
+    00000018 0000000000000000 0000000000000007  DW_OP_reg5 \(rdi\); DW_OP_piece: 8; DW_OP_reg4 \(rsi\); DW_OP_piece: 4
+    00000022 <End of list>
+
+   Offset Entry 1
+    00000023 0000000000000000 0000000000000007  DW_OP_reg1 \(rdx\); DW_OP_piece: 8; DW_OP_reg2 \(rcx\); DW_OP_piece: 4
+    0000002d <End of list>
+
+   Offset Entry 2
+    0000002e 0000000000000000 0000000000000007  DW_OP_reg8 \(r8\); DW_OP_piece: 8; DW_OP_reg9 \(r9\); DW_OP_piece: 4
+    00000038 <End of list>
+
+
diff --git a/binutils/testsuite/binutils-all/readelf.exp b/binutils/testsuite/binutils-all/readelf.exp
index 0f7a1f3b5a0..aaa50cf6c12 100644
--- a/binutils/testsuite/binutils-all/readelf.exp
+++ b/binutils/testsuite/binutils-all/readelf.exp
@@ -616,3 +616,22 @@ readelf_find_size $tempfile 2
 # Make sure that readelf can decode the contents.
 readelf_test -wi $tempfile dw5-op.W
 }
+
+# Check dwarf-5 support for .debug_loclists section dump.
+if {![binutils_assemble_flags $srcdir/$subdir/dw5-loclist.S tmpdir/dw5-loclist.o $hpux]} then {
+    unsupported "readelf -wo dw5-loclist (failed to assemble)"
+} else {
+
+# Download it.
+if ![is_remote host] {
+    set tempfile tmpdir/dw5-loclist.o
+} else {
+    set tempfile [remote_download host tmpdir/dw5-loclist.o]
+}
+
+# First, determine the size, so specific output matchers can be used.
+readelf_find_size $tempfile 2
+
+# Make sure that readelf can decode the contents.
+readelf_test -wo $tempfile dw5-loclist.W
+}
-- 
2.17.1

