From 96ce32f762803a7d74ca30c3930f1679afc0100c 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 14:07:17 +0530
Subject: [PATCH] [PATCH 1/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 1/2.

Issues fixed in patch 1/2 are:
Issue 1: .debug_rnglists section dump for single CU.
Issue 2: location list offset address dump under DW_AT_location is corrected.
Issue 3: range list offset address dump under DW_AT_ranges is corrected.

	* dwarf.c (fetch_indexed_value): Add base_address as parameter and
	use it to access the section offset.
	(read_and_display_attr_value): Handle DW_FORM_loclistx and
	DW_FORM_rnglistx forms separately.
	(display_debug_rnglists_list): Fix support for DW_RLE_base_addressx,
	DW_RLE_startx_length.
	(display_debug_ranges): Correct the range list entries starting address.
---
 binutils/dwarf.c | 32 +++++++++++++++++++++-----------
 1 file changed, 21 insertions(+), 11 deletions(-)

diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index caa3ce48d00..566104762d1 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -118,6 +118,7 @@ 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.  */
@@ -826,7 +827,8 @@ fetch_indexed_addr (dwarf_vma offset, uint32_t num_bytes)
 
 static dwarf_vma
 fetch_indexed_value (dwarf_vma idx,
-		     enum dwarf_section_display_enum sec_enum)
+		     enum dwarf_section_display_enum sec_enum,
+		     dwarf_vma base_address)
 {
   struct dwarf_section *section = &debug_displays [sec_enum].section;
 
@@ -851,8 +853,12 @@ fetch_indexed_value (dwarf_vma idx,
  
   dwarf_vma offset = idx * pointer_size;
 
-  /* Offsets are biased by the size of the section header.  */
-  offset += bias;
+  /* Offsets are biased by the size of the section header
+     or base address.  */
+  if (sec_enum == loclists)
+    offset += base_address;
+  else
+    offset += bias;
 
   if (offset + pointer_size > section->size)
     {
@@ -2788,7 +2794,15 @@ read_and_display_attr_value (unsigned long           attribute,
 
 	  offset = base + uvalue * pointer_size;
 
-	  if (do_wide)
+	  if (form == DW_FORM_loclistx)
+	    printf (_("%c(index: 0x%s): %s"), delimiter,
+	            dwarf_vmatoa ("x", uvalue),
+	            dwarf_vmatoa ("x", debug_info_p->loc_offsets [uvalue]));
+	  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)));
+	  else if (do_wide)
 	    /* We have already displayed the form name.  */
 	    printf (_("%c(index: 0x%s): %s"), delimiter,
 		    dwarf_vmatoa ("x", uvalue),
@@ -2870,7 +2884,7 @@ read_and_display_attr_value (unsigned long           attribute,
 		}
 
 	      if (form == DW_FORM_loclistx)
-		uvalue = fetch_indexed_value (uvalue, loclists);
+		uvalue = fetch_indexed_value (num, loclists, debug_info_p->loclists_base);
 	      else if (this_set != NULL)
 		uvalue += this_set->section_offsets [DW_SECT_LOC];
 
@@ -2939,7 +2953,7 @@ read_and_display_attr_value (unsigned long           attribute,
 		}
 
 	      if (form == DW_FORM_rnglistx)
-		uvalue = fetch_indexed_value (uvalue, rnglists);
+		uvalue = fetch_indexed_value (uvalue, rnglists, 0);
 
 	      debug_info_p->range_lists [num] = uvalue;
 	      debug_info_p->num_range_lists++;
@@ -7976,9 +7990,6 @@ display_debug_rnglists_list (unsigned char * start,
 	case DW_RLE_base_addressx:
 	  READ_ULEB (base_address, start, finish);
 	  print_dwarf_vma (base_address, pointer_size);
-	  printf (_("(base address index) "));
-	  base_address = fetch_indexed_addr (base_address, pointer_size);
-	  print_dwarf_vma (base_address, pointer_size);
 	  printf (_("(base address)\n"));
 	  break;
 	case DW_RLE_startx_endx:
@@ -7990,7 +8001,6 @@ display_debug_rnglists_list (unsigned char * start,
 	case DW_RLE_startx_length:
 	  READ_ULEB (begin, start, finish);
 	  READ_ULEB (length, start, finish);
-	  begin = fetch_indexed_addr (begin, pointer_size);
 	  end = begin + length;
 	  break;
 	case DW_RLE_offset_pair:
@@ -8243,7 +8253,7 @@ display_debug_ranges (struct dwarf_section *section,
 		(unsigned long) offset, i);
 	  continue;
 	}
-      next = section_begin + offset;
+      next = section_begin + offset + DEBUG_LOCLISTS_RNGLISTS_SECTION_HEADER_LEN;
 
       /* If multiple DWARF entities reference the same range then we will
          have multiple entries in the `range_entries' list for the same
-- 
2.17.1

