public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] bfd: Add Support for DW_FORM_strx* and DW_FORM_addrx*.
@ 2022-04-22  6:36 Potharla, Rupesh
  2022-04-25 12:56 ` Jan Beulich
  0 siblings, 1 reply; 4+ messages in thread
From: Potharla, Rupesh @ 2022-04-22  6:36 UTC (permalink / raw)
  To: binutils; +Cc: George, Jini Susan, Parasuraman, Hariharan, Natarajan, Kavitha

[-- Attachment #1: Type: text/plain, Size: 176 bytes --]

[AMD Official Use Only]

Hi,

Requesting to review the attached patch. The patch provides support for strx* and addrx* forms to the bfd library.


Regards,
Rupesh P


[-- Attachment #2: 0001-bfd-dwarf2-Add-Support-for-DW_FORM_strx-and-DW_FORM_addrx.patch --]
[-- Type: application/octet-stream, Size: 15448 bytes --]

From c7ffb795ba446b21809e7e5bd503968a2c103555 Mon Sep 17 00:00:00 2001
From: rupothar <rupesh.potharla@amd.com>
Date: Wed, 30 Mar 2022 15:38:19 +0530
Subject: [PATCH]  bfd/dwarf2: Add Support for DW_FORM_strx* and
 DW_FORM_addrx*.

 Made code changes implementing strx* and addrx* forms to the BFD library.

Change-Id: I441dcd47d2b4a0fd152a0fb0df511cf994cee3c2
---
 bfd/dwarf2.c | 302 +++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 280 insertions(+), 22 deletions(-)

diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
index 9aa4e955a5e..f19df9c16c1 100644
--- a/bfd/dwarf2.c
+++ b/bfd/dwarf2.c
@@ -118,6 +118,18 @@ struct dwarf2_debug_file
   /* Length of the loaded .debug_str section.  */
   bfd_size_type dwarf_str_size;
 
+  /* Pointer to the .debug_str_offsets section loaded into memory.  */
+  bfd_byte *dwarf_str_offsets_buffer;
+
+  /* Length of the loaded .debug_str_offsets section.  */
+  bfd_size_type dwarf_str_offsets_size;
+
+  /* Pointer to the .debug_addr section loaded into memory.  */
+  bfd_byte *dwarf_addr_buffer;
+
+  /* Length of the loaded .debug_addr section.  */
+  bfd_size_type dwarf_addr_size;
+
   /* Pointer to the .debug_line_str section loaded into memory.  */
   bfd_byte *dwarf_line_str_buffer;
 
@@ -296,6 +308,12 @@ struct comp_unit
 
   /* TRUE if symbols are cached in hash table for faster lookup by name.  */
   bool cached;
+
+ /* Base address of debug_addr section.  */
+  unsigned long dwarf_addr_offset;
+
+  /* Base address of string offset table.  */
+  unsigned long dwarf_str_offset;
 };
 
 /* This data structure holds the information of an abbrev.  */
@@ -338,6 +356,8 @@ const struct dwarf_debug_section dwarf_debug_sections[] =
   { ".debug_static_vars",	".zdebug_static_vars" },
   { ".debug_str",		".zdebug_str", },
   { ".debug_str",		".zdebug_str", },
+  { ".debug_str_offsets",       ".zdebug_str_offsets", },
+  { ".debug_addr",              ".zdebug_addr", },
   { ".debug_line_str",		".zdebug_line_str", },
   { ".debug_types",		".zdebug_types" },
   /* GNU DWARF 1 extensions */
@@ -372,6 +392,8 @@ enum dwarf_debug_section_enum
   debug_static_vars,
   debug_str,
   debug_str_alt,
+  debug_str_offsets,
+  debug_addr,
   debug_line_str,
   debug_types,
   debug_sfnames,
@@ -1221,12 +1243,92 @@ is_int_form (const struct attribute *attr)
     }
 }
 
+/* Returns true if the form is strx[1-4].  */
+
+static inline bool
+is_strx_form(enum dwarf_form form)
+{
+  return (form == DW_FORM_strx
+          || form == DW_FORM_strx1
+          || form == DW_FORM_strx2
+          || form == DW_FORM_strx3
+          || form == DW_FORM_strx4);
+}
+
+/* Return true if the form is addrx[1-4].  */
+
+static inline bool
+is_addrx_form(enum dwarf_form form)
+{
+  return (form == DW_FORM_addrx
+          || form == DW_FORM_addrx1
+          || form == DW_FORM_addrx2
+          || form == DW_FORM_addrx3
+          || form == DW_FORM_addrx4);
+
+}
+
+/* Function to handle DW_FORM_addrx*.  */
+static int
+read_indexed_address (struct comp_unit *unit,
+                      unsigned long idx)
+{
+  struct dwarf2_debug *stash = unit->stash;
+  struct dwarf2_debug_file *file = unit->file;
+  unsigned long addr_base = unit->dwarf_addr_offset;
+  bfd_byte *info_ptr;
+
+  if (stash == NULL)
+      return 0;
+
+   if (! read_section (unit->abfd, &stash->debug_sections[debug_addr],
+                       file->syms, 0,
+                       &file->dwarf_addr_buffer, &file->dwarf_addr_size))
+      return 0;
+
+   info_ptr = (bfd_byte *)(file->dwarf_addr_buffer + addr_base
+              + idx * unit->offset_size);
+
+  if (unit->offset_size == 4)
+     return bfd_get_32 (unit->abfd, info_ptr);
+  else
+     return bfd_get_64 (unit->abfd, info_ptr);
+}
+
+/* Return the string for DW_FORM_strx*.  */
 static const char *
-read_indexed_string (bfd_uint64_t idx ATTRIBUTE_UNUSED,
-		     struct comp_unit * unit ATTRIBUTE_UNUSED)
+read_indexed_string (struct comp_unit * unit,
+                     unsigned long idx)
 {
-  /* FIXME: Add support for indexed strings.  */
-  return "<indexed strings not yet supported>";
+  struct dwarf2_debug *stash = unit->stash;
+  struct dwarf2_debug_file *file = unit->file;
+  bfd_byte *info_ptr;
+  unsigned long str_offset;
+
+   if (stash == NULL)
+       return NULL;
+
+  if (! read_section (unit->abfd, &stash->debug_sections[debug_str],
+                      file->syms, 0,
+                      &file->dwarf_str_buffer, &file->dwarf_str_size))
+  return NULL;
+
+  if (! read_section (unit->abfd, &stash->debug_sections[debug_str_offsets],
+                      file->syms, 0,
+                      &file->dwarf_str_offsets_buffer,
+                      &file->dwarf_str_offsets_size))
+  return NULL;
+
+  info_ptr = (bfd_byte *)(file->dwarf_str_offsets_buffer
+             +  unit->dwarf_str_offset
+             + idx * unit->offset_size);
+
+  if (unit->offset_size == 4)
+     str_offset = bfd_get_32 (unit->abfd, info_ptr);
+  else
+     str_offset = bfd_get_64 (unit->abfd, info_ptr);
+
+  return (const char*) (file->dwarf_str_buffer + str_offset);
 }
 
 /* Read and fill in the value of attribute ATTR as described by FORM.
@@ -1330,24 +1432,19 @@ read_attribute_value (struct attribute *  attr,
       break;
     case DW_FORM_strx1:
       attr->u.val = read_1_byte (abfd, &info_ptr, info_ptr_end);
-      attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
       break;
     case DW_FORM_strx2:
       attr->u.val = read_2_bytes (abfd, &info_ptr, info_ptr_end);
-      attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
       break;
     case DW_FORM_strx3:
       attr->u.val = read_3_bytes (abfd, &info_ptr, info_ptr_end);
-      attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
       break;
     case DW_FORM_strx4:
       attr->u.val = read_4_bytes (abfd, &info_ptr, info_ptr_end);
-      attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
       break;
     case DW_FORM_strx:
       attr->u.val = _bfd_safe_read_leb128 (abfd, &info_ptr,
 					   false, info_ptr_end);
-      attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
       break;
     case DW_FORM_exprloc:
     case DW_FORM_block:
@@ -1486,6 +1583,7 @@ struct line_info_table
   unsigned int		num_files;
   unsigned int		num_dirs;
   unsigned int		num_sequences;
+  unsigned int          version;
   char *		comp_dir;
   char **		dirs;
   struct fileinfo*	files;
@@ -2115,6 +2213,23 @@ read_formatted_entries (struct comp_unit *unit, bfd_byte **bufp,
 	    return false;
 	  switch (form)
 	    {
+	    case DW_FORM_strx:
+	    case DW_FORM_strx1:
+	    case DW_FORM_strx2:
+	    case DW_FORM_strx3:
+	    case DW_FORM_strx4:
+	      attr.u.str = (char*) read_indexed_string(unit, attr.u.val);
+	      *stringp = attr.u.str;
+	      break;
+
+	    case DW_FORM_addrx:
+	    case DW_FORM_addrx1:
+	    case DW_FORM_addrx2:
+	    case DW_FORM_addrx3:
+	    case DW_FORM_addrx4:
+	      attr.u.val = read_indexed_address(unit, attr.u.val);
+	      break;
+
 	    case DW_FORM_string:
 	    case DW_FORM_line_strp:
 	      *stringp = attr.u.str;
@@ -2134,10 +2249,8 @@ read_formatted_entries (struct comp_unit *unit, bfd_byte **bufp,
 	    }
 	}
 
-      /* Skip the first "zero entry", which is the compilation dir/file.  */
-      if (datai != 0)
-	if (!callback (table, fe.name, fe.dir, fe.time, fe.size))
-	  return false;
+      if (!callback (table, fe.name, fe.dir, fe.time, fe.size))
+	return false;
     }
 
   *bufp = buf;
@@ -2302,6 +2415,7 @@ decode_line_info (struct comp_unit *unit)
   table->sequences = NULL;
 
   table->lcl_head = NULL;
+  table->version = lh.version;
 
   if (lh.version >= 5)
     {
@@ -2484,6 +2598,8 @@ decode_line_info (struct comp_unit *unit)
 		filenum = _bfd_safe_read_leb128 (abfd, &line_ptr,
 						 false, line_end);
 		free (filename);
+		if (table->version >= 5)
+		  filenum = filenum + 1;
 		filename = concat_filename (table, filenum);
 		break;
 	      }
@@ -3081,6 +3197,11 @@ find_abstract_instance (struct comp_unit *unit,
 	    {
 	      info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit,
 					 info_ptr, info_ptr_end);
+	      if (is_strx_form(attr.form))
+		attr.u.str = (char*) read_indexed_string(unit, attr.u.val);
+	      if (is_addrx_form(attr.form))
+		attr.u.val = read_indexed_address(unit, attr.u.val);
+
 	      if (info_ptr == NULL)
 		break;
 	      switch (attr.name)
@@ -3116,8 +3237,12 @@ find_abstract_instance (struct comp_unit *unit,
 		  if (!comp_unit_maybe_decode_line_info (unit))
 		    return false;
 		  if (is_int_form (&attr))
-		    *filename_ptr = concat_filename (unit->line_table,
-						     attr.u.val);
+		    {
+		      if (unit->line_table->version >=5)
+			attr.u.val = attr.u.val + 1;
+		      *filename_ptr = concat_filename (unit->line_table,
+						       attr.u.val);
+		    }
 		  break;
 		case DW_AT_decl_line:
 		  if (is_int_form (&attr))
@@ -3453,6 +3578,10 @@ scan_unit_for_symbols (struct comp_unit *unit)
 				     unit, info_ptr, info_ptr_end);
 	  if (info_ptr == NULL)
 	    goto fail;
+	  if (is_strx_form(attr.form))
+	    attr.u.str = (char*) read_indexed_string(unit, attr.u.val);
+	  if (is_addrx_form(attr.form))
+	    attr.u.val = read_indexed_address(unit, attr.u.val);
 	}
 
       if (abbrev->has_children)
@@ -3554,6 +3683,10 @@ scan_unit_for_symbols (struct comp_unit *unit)
 				     unit, info_ptr, info_ptr_end);
 	  if (info_ptr == NULL)
 	    goto fail;
+	  if (is_strx_form(attr.form))
+	    attr.u.str = (char*) read_indexed_string(unit, attr.u.val);
+	  if (is_addrx_form(attr.form))
+	    attr.u.val = read_indexed_address(unit, attr.u.val);
 
 	  if (func)
 	    {
@@ -3561,8 +3694,12 @@ scan_unit_for_symbols (struct comp_unit *unit)
 		{
 		case DW_AT_call_file:
 		  if (is_int_form (&attr))
-		    func->caller_file = concat_filename (unit->line_table,
-							 attr.u.val);
+		  {
+		  if (unit->line_table->version >= 5)
+		    attr.u.val = attr.u.val + 1;
+		  func->caller_file = concat_filename (unit->line_table,
+						       attr.u.val);
+		  }
 		  break;
 
 		case DW_AT_call_line:
@@ -3624,8 +3761,12 @@ scan_unit_for_symbols (struct comp_unit *unit)
 
 		case DW_AT_decl_file:
 		  if (is_int_form (&attr))
-		    func->file = concat_filename (unit->line_table,
-						  attr.u.val);
+		    {
+		      if (unit->line_table->version >= 5)
+		        attr.u.val = attr.u.val + 1;
+		      func->file = concat_filename (unit->line_table,
+						    attr.u.val);
+		    }
 		  break;
 
 		case DW_AT_decl_line:
@@ -3675,8 +3816,12 @@ scan_unit_for_symbols (struct comp_unit *unit)
 
 		case DW_AT_decl_file:
 		  if (is_int_form (&attr))
-		    var->file = concat_filename (unit->line_table,
-						 attr.u.val);
+		    {
+		      if (unit->line_table->version >=5)
+		        attr.u.val = attr.u.val + 1;
+		      var->file = concat_filename (unit->line_table,
+					           attr.u.val);
+		    }
 		  break;
 
 		case DW_AT_decl_line:
@@ -3750,6 +3895,78 @@ scan_unit_for_symbols (struct comp_unit *unit)
   return false;
 }
 
+/* read the attributes of the form strx and addrx.  */
+static void reread_attribute (
+                struct comp_unit *    unit,
+                struct attribute attr,
+                bfd_vma *low_pc,
+                bfd_vma *high_pc,
+                bool *high_pc_relative,
+		bool compunit)
+{
+
+  if (is_strx_form(attr.form))
+    attr.u.str = (char*) read_indexed_string(unit, attr.u.val);
+  if (is_addrx_form(attr.form))
+    attr.u.val = read_indexed_address(unit, attr.u.val);
+
+  switch (attr.name)
+  {
+    case DW_AT_stmt_list:
+      unit->stmtlist = 1;
+      unit->line_offset = attr.u.val;
+      break;
+
+    case DW_AT_name:
+      if (is_str_form (&attr))
+        unit->name = attr.u.str;
+      break;
+
+    case DW_AT_low_pc:
+      *low_pc = attr.u.val;
+      if (compunit)
+        unit->base_address = *low_pc;
+      break;
+
+    case DW_AT_high_pc:
+      *high_pc = attr.u.val;
+      *high_pc_relative = attr.form != DW_FORM_addr;
+      break;
+
+    case DW_AT_ranges:
+      if (!read_rangelist (unit, &unit->arange, attr.u.val))
+        return;
+      break;
+
+    case DW_AT_comp_dir:
+    {
+      char *comp_dir = attr.u.str;
+
+      if (! is_str_form (&attr))
+      {
+         _bfd_error_handler
+          (_("DWARF error: DW_AT_comp_dir attribute encountered with a non-string form"));
+         comp_dir = NULL;
+      }
+
+      if (comp_dir)
+      {
+        char *cp = strchr (comp_dir, ':');
+
+        if (cp && cp != comp_dir && cp[-1] == '.' && cp[1] == '/')
+          comp_dir = cp + 1;
+      }
+        unit->comp_dir = comp_dir;
+        break;
+    }
+
+      case DW_AT_language:
+        unit->lang = attr.u.val;
+      default:
+        break;
+   }
+}
+
 /* Parse a DWARF2 compilation unit starting at INFO_PTR.  UNIT_LENGTH
    includes the compilation unit header that proceeds the DIE's, but
    does not include the length field that precedes each compilation
@@ -3783,6 +4000,9 @@ parse_comp_unit (struct dwarf2_debug *stash,
   bfd *abfd = file->bfd_ptr;
   bool high_pc_relative = false;
   enum dwarf_unit_type unit_type;
+  struct attribute *str_addrp = NULL;
+  unsigned int count = 0;
+  bool compunit_flag = false;
 
   version = read_2_bytes (abfd, &info_ptr, end_ptr);
   if (version < 2 || version > 5)
@@ -3887,12 +4107,29 @@ parse_comp_unit (struct dwarf2_debug *stash,
   unit->file = file;
   unit->info_ptr_unit = info_ptr_unit;
 
+  if (abbrev->tag == DW_TAG_compile_unit)
+    compunit_flag = true;
+
   for (i = 0; i < abbrev->num_attrs; ++i)
     {
       info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr, end_ptr);
       if (info_ptr == NULL)
 	return NULL;
 
+      /* Identify attributes of the form strx and addrx store them in
+	an array and process them again.  */
+      if (is_strx_form(attr.form) ||
+          is_addrx_form(attr.form))
+      {
+	str_addrp = (struct attribute *) bfd_realloc(str_addrp,
+			(count + 1) * sizeof(struct attribute));
+	str_addrp[count].name = attr.name;
+	str_addrp[count].form = (enum dwarf_form) attr.form;
+	str_addrp[count].u.val = attr.u.val;
+	count++;
+	continue;
+      }
+
       /* Store the data if it is of an attribute we want to keep in a
 	 partial symbol table.  */
       switch (attr.name)
@@ -3917,7 +4154,7 @@ parse_comp_unit (struct dwarf2_debug *stash,
 	      /* If the compilation unit DIE has a DW_AT_low_pc attribute,
 		 this is the base address to use when reading location
 		 lists or range lists.  */
-	      if (abbrev->tag == DW_TAG_compile_unit)
+	      if (compunit_flag)
 		unit->base_address = low_pc;
 	    }
 	  break;
@@ -3966,10 +4203,27 @@ parse_comp_unit (struct dwarf2_debug *stash,
 	    unit->lang = attr.u.val;
 	  break;
 
+	case DW_AT_addr_base:
+	  unit->dwarf_addr_offset = attr.u.val;
+	  break;
+
+	case DW_AT_str_offsets_base:
+	  unit->dwarf_str_offset = attr.u.val;
+	  break;
+
 	default:
 	  break;
 	}
     }
+
+  for (i = 0; i < count; ++i)
+    {
+	struct attribute attr1 = str_addrp[i];
+	reread_attribute( unit, attr1, &low_pc, &high_pc,
+			  &high_pc_relative, compunit_flag);
+
+    }
+
   if (high_pc_relative)
     high_pc += low_pc;
   if (high_pc != 0)
@@ -3979,6 +4233,10 @@ parse_comp_unit (struct dwarf2_debug *stash,
     }
 
   unit->first_child_die_ptr = info_ptr;
+
+  if (str_addrp != NULL)
+    free(str_addrp);
+
   return unit;
 }
 
-- 
2.17.1


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

* Re: [PATCH] bfd: Add Support for DW_FORM_strx* and DW_FORM_addrx*.
  2022-04-22  6:36 [PATCH] bfd: Add Support for DW_FORM_strx* and DW_FORM_addrx* Potharla, Rupesh
@ 2022-04-25 12:56 ` Jan Beulich
  2022-05-08 16:28   ` Potharla, Rupesh
  0 siblings, 1 reply; 4+ messages in thread
From: Jan Beulich @ 2022-04-25 12:56 UTC (permalink / raw)
  To: Potharla, Rupesh
  Cc: George, Jini Susan, Parasuraman, Hariharan, Natarajan, Kavitha, binutils

On 22.04.2022 08:36, Potharla, Rupesh via Binutils wrote:
> Requesting to review the attached patch. The patch provides support for strx* and addrx* forms to the bfd library.

There's a change to decode_line_info() which looks unrelated. If it's
related, you will want to explain this in the description. If it's
not related, you will want to split this into a separate patch with
its own justification. The same looks to repeat in
find_abstract_instance() and yet more places. 

There's a use of bfd_realloc() where you forgot to check for failure.

I consider it at least risky to open-code the conversion from index
to actual value into various callers of read_attribute(), instead of
keeping it in read_attribute_value(), as was clearly originally
intended.

In read_indexed_string(), besides swapping the parameter order for no
apparent reason, you go from a 64-bit type to "unsigned long". Are
you sure this is going to be sufficient on 32-bit architectures? I'd
rather see read_indexed_address() use bfd_uint64_t as well ...

Furthermore read_indexed_address() has a return type of "int", but
you mean to return addresses there. Quite likely this wants to at
least be bfd_vma, if not bfd_uint64_t.

There are also quite a few indentation and padding issues, which you
will want to take care of.

To aid reviewers, please try to supply patches inline rather than as
attachment.

Jan


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

* RE: [PATCH] bfd: Add Support for DW_FORM_strx* and DW_FORM_addrx*.
  2022-04-25 12:56 ` Jan Beulich
@ 2022-05-08 16:28   ` Potharla, Rupesh
  2022-05-17 11:38     ` Jan Beulich
  0 siblings, 1 reply; 4+ messages in thread
From: Potharla, Rupesh @ 2022-05-08 16:28 UTC (permalink / raw)
  To: Jan Beulich
  Cc: George, Jini Susan, Parasuraman, Hariharan, Natarajan, Kavitha, binutils

[-- Attachment #1: Type: text/plain, Size: 16394 bytes --]

[Public]

 Jan, 

Apologies for the delayed reply did not get a chance to work on this due to personal reasons. Made the code changes suggested and removed code changes related to file index will send the patch separately for review.  Can you review my code changes and send in your comments/suggestions?

Regards,
Rupesh P

From 812ce279d73cfba5dea464d91536edc512d193b3 Mon Sep 17 00:00:00 2001
From: rupothar <rupesh.potharla@amd.com>
Date: Wed, 30 Mar 2022 15:38:19 +0530
Subject: [PATCH] bfd/dwarf2: Add Support for DW_FORM_strx* and DW_FORM_addrx*.

 Made code changes implementing strx* and addrx* forms to the BFD library.
---
 bfd/dwarf2.c | 275 ++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 264 insertions(+), 11 deletions(-)

diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
index 404f35df62b..fe6c0b907c4 100644
--- a/bfd/dwarf2.c
+++ b/bfd/dwarf2.c
@@ -118,6 +118,18 @@ struct dwarf2_debug_file
   /* Length of the loaded .debug_str section.  */
   bfd_size_type dwarf_str_size;
 
+  /* Pointer to the .debug_str_offsets section loaded into memory.  */
+  bfd_byte *dwarf_str_offsets_buffer;
+
+  /* Length of the loaded .debug_str_offsets section.  */
+  bfd_size_type dwarf_str_offsets_size;
+
+  /* Pointer to the .debug_addr section loaded into memory.  */
+  bfd_byte *dwarf_addr_buffer;
+
+  /* Length of the loaded .debug_addr section.  */
+  bfd_size_type dwarf_addr_size;
+
   /* Pointer to the .debug_line_str section loaded into memory.  */
   bfd_byte *dwarf_line_str_buffer;
 
@@ -296,6 +308,12 @@ struct comp_unit
 
   /* TRUE if symbols are cached in hash table for faster lookup by name.  */
   bool cached;
+
+ /* Base address of debug_addr section.  */
+  unsigned long dwarf_addr_offset;
+
+  /* Base address of string offset table.  */
+  unsigned long dwarf_str_offset;
 };
 
 /* This data structure holds the information of an abbrev.  */
@@ -338,6 +356,8 @@ const struct dwarf_debug_section dwarf_debug_sections[] =
   { ".debug_static_vars",	".zdebug_static_vars" },
   { ".debug_str",		".zdebug_str", },
   { ".debug_str",		".zdebug_str", },
+  { ".debug_str_offsets",       ".zdebug_str_offsets", },
+  { ".debug_addr",              ".zdebug_addr", },
   { ".debug_line_str",		".zdebug_line_str", },
   { ".debug_types",		".zdebug_types" },
   /* GNU DWARF 1 extensions */
@@ -372,6 +392,8 @@ enum dwarf_debug_section_enum
   debug_static_vars,
   debug_str,
   debug_str_alt,
+  debug_str_offsets,
+  debug_addr,
   debug_line_str,
   debug_types,
   debug_sfnames,
@@ -1221,12 +1243,93 @@ is_int_form (const struct attribute *attr)
     }
 }
 
+/* Returns true if the form is strx[1-4].  */
+
+static inline bool
+is_strx_form(enum dwarf_form form)
+{
+  return (form == DW_FORM_strx
+	  || form == DW_FORM_strx1
+	  || form == DW_FORM_strx2
+	  || form == DW_FORM_strx3
+	  || form == DW_FORM_strx4);
+}
+
+/* Return true if the form is addrx[1-4].  */
+
+static inline bool
+is_addrx_form(enum dwarf_form form)
+{
+  return (form == DW_FORM_addrx
+	  || form == DW_FORM_addrx1
+	  || form == DW_FORM_addrx2
+	  || form == DW_FORM_addrx3
+	  || form == DW_FORM_addrx4);
+}
+
+/* Returns the address in .debug_addr section using DW_AT_addr_base.
+   Used to implement DW_FORM_addrx*.  */
+static bfd_vma
+read_indexed_address (bfd_uint64_t idx,
+		      struct comp_unit *unit)
+{
+  struct dwarf2_debug *stash = unit->stash;
+  struct dwarf2_debug_file *file = unit->file;
+  unsigned long addr_base = unit->dwarf_addr_offset;
+  bfd_byte *info_ptr;
+
+  if (stash == NULL)
+    return 0;
+
+  if (!read_section (unit->abfd, &stash->debug_sections[debug_addr],
+		     file->syms, 0,
+		     &file->dwarf_addr_buffer, &file->dwarf_addr_size))
+    return 0;
+
+  info_ptr = (bfd_byte *)(file->dwarf_addr_buffer + addr_base
+	      + idx * unit->offset_size);
+
+  if (unit->offset_size == 4)
+     return bfd_get_32 (unit->abfd, info_ptr);
+  else
+     return bfd_get_64 (unit->abfd, info_ptr);
+}
+
+/* Returns the string using DW_AT_str_offsets_base.
+   Used to implement DW_FORM_strx*.  */
 static const char *
-read_indexed_string (bfd_uint64_t idx ATTRIBUTE_UNUSED,
-		     struct comp_unit * unit ATTRIBUTE_UNUSED)
+read_indexed_string (bfd_uint64_t idx,
+		     struct comp_unit * unit)
 {
-  /* FIXME: Add support for indexed strings.  */
-  return "<indexed strings not yet supported>";
+  struct dwarf2_debug *stash = unit->stash;
+  struct dwarf2_debug_file *file = unit->file;
+  bfd_byte *info_ptr;
+  unsigned long str_offset;
+
+  if (stash == NULL)
+    return NULL;
+
+  if (!read_section (unit->abfd, &stash->debug_sections[debug_str],
+		     file->syms, 0,
+		     &file->dwarf_str_buffer, &file->dwarf_str_size))
+    return NULL;
+
+  if (!read_section (unit->abfd, &stash->debug_sections[debug_str_offsets],
+		     file->syms, 0,
+		     &file->dwarf_str_offsets_buffer,
+		     &file->dwarf_str_offsets_size))
+  return NULL;
+
+  info_ptr = (bfd_byte *)(file->dwarf_str_offsets_buffer
+	      +  unit->dwarf_str_offset
+	      + idx * unit->offset_size);
+
+  if (unit->offset_size == 4)
+     str_offset = bfd_get_32 (unit->abfd, info_ptr);
+  else
+     str_offset = bfd_get_64 (unit->abfd, info_ptr);
+
+  return (const char*) (file->dwarf_str_buffer + str_offset);
 }
 
 /* Read and fill in the value of attribute ATTR as described by FORM.
@@ -1295,21 +1398,37 @@ read_attribute_value (struct attribute *  attr,
     case DW_FORM_ref1:
     case DW_FORM_flag:
     case DW_FORM_data1:
+      attr->u.val = read_1_byte (abfd, &info_ptr, info_ptr_end);
+      break;
     case DW_FORM_addrx1:
       attr->u.val = read_1_byte (abfd, &info_ptr, info_ptr_end);
+      /* dwarf_addr_offset value 0 indicates the attribute DW_AT_addr_base
+	 is not yet read.  */
+      if (unit->dwarf_addr_offset != 0)
+	attr->u.val = read_indexed_address(attr->u.val, unit);
       break;
     case DW_FORM_data2:
-    case DW_FORM_addrx2:
     case DW_FORM_ref2:
       attr->u.val = read_2_bytes (abfd, &info_ptr, info_ptr_end);
       break;
+    case DW_FORM_addrx2:
+      attr->u.val = read_2_bytes (abfd, &info_ptr, info_ptr_end);
+      if (unit->dwarf_addr_offset != 0)
+	attr->u.val = read_indexed_address(attr->u.val, unit);
+      break;
     case DW_FORM_addrx3:
       attr->u.val = read_3_bytes (abfd, &info_ptr, info_ptr_end);
+      if (unit->dwarf_addr_offset != 0)
+	attr->u.val = read_indexed_address(attr->u.val, unit);
       break;
     case DW_FORM_ref4:
     case DW_FORM_data4:
+      attr->u.val = read_4_bytes (abfd, &info_ptr, info_ptr_end);
+      break;
     case DW_FORM_addrx4:
       attr->u.val = read_4_bytes (abfd, &info_ptr, info_ptr_end);
+      if (unit->dwarf_addr_offset != 0)
+	attr->u.val = read_indexed_address(attr->u.val, unit);
       break;
     case DW_FORM_data8:
     case DW_FORM_ref8:
@@ -1330,24 +1449,31 @@ read_attribute_value (struct attribute *  attr,
       break;
     case DW_FORM_strx1:
       attr->u.val = read_1_byte (abfd, &info_ptr, info_ptr_end);
-      attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+      /* dwarf_str_offset value 0 indicates the attribute DW_AT_str_offsets_base
+	 is not yet read.  */
+      if (unit->dwarf_str_offset != 0)
+	attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
       break;
     case DW_FORM_strx2:
       attr->u.val = read_2_bytes (abfd, &info_ptr, info_ptr_end);
-      attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+      if (unit->dwarf_str_offset != 0)
+	attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
       break;
     case DW_FORM_strx3:
       attr->u.val = read_3_bytes (abfd, &info_ptr, info_ptr_end);
-      attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+      if (unit->dwarf_str_offset != 0)
+	attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
       break;
     case DW_FORM_strx4:
       attr->u.val = read_4_bytes (abfd, &info_ptr, info_ptr_end);
-      attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+      if (unit->dwarf_str_offset != 0)
+	attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
       break;
     case DW_FORM_strx:
       attr->u.val = _bfd_safe_read_leb128 (abfd, &info_ptr,
 					   false, info_ptr_end);
-      attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+      if (unit->dwarf_str_offset != 0)
+	attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
       break;
     case DW_FORM_exprloc:
     case DW_FORM_block:
@@ -1369,9 +1495,14 @@ read_attribute_value (struct attribute *  attr,
       break;
     case DW_FORM_ref_udata:
     case DW_FORM_udata:
+      attr->u.val = _bfd_safe_read_leb128 (abfd, &info_ptr,
+					   false, info_ptr_end);
+      break;
     case DW_FORM_addrx:
       attr->u.val = _bfd_safe_read_leb128 (abfd, &info_ptr,
 					   false, info_ptr_end);
+      if (unit->dwarf_addr_offset != 0)
+	attr->u.val = read_indexed_address(attr->u.val, unit);
       break;
     case DW_FORM_indirect:
       form = _bfd_safe_read_leb128 (abfd, &info_ptr,
@@ -2117,6 +2248,11 @@ read_formatted_entries (struct comp_unit *unit, bfd_byte **bufp,
 	    {
 	    case DW_FORM_string:
 	    case DW_FORM_line_strp:
+	    case DW_FORM_strx:
+	    case DW_FORM_strx1:
+	    case DW_FORM_strx2:
+	    case DW_FORM_strx3:
+	    case DW_FORM_strx4:
 	      *stringp = attr.u.str;
 	      break;
 
@@ -3749,6 +3885,77 @@ scan_unit_for_symbols (struct comp_unit *unit)
   return false;
 }
 
+/* read the attributes of the form strx and addrx.  */
+static void reread_attribute (struct comp_unit *    unit,
+			      struct attribute attr,
+			      bfd_vma *low_pc,
+			      bfd_vma *high_pc,
+			      bool *high_pc_relative,
+			      bool compunit)
+{
+
+  if (is_strx_form(attr.form))
+    attr.u.str = (char*) read_indexed_string (attr.u.val, unit);
+  if (is_addrx_form(attr.form))
+    attr.u.val = read_indexed_address (attr.u.val, unit);
+
+  switch (attr.name)
+  {
+    case DW_AT_stmt_list:
+      unit->stmtlist = 1;
+      unit->line_offset = attr.u.val;
+      break;
+
+    case DW_AT_name:
+      if (is_str_form (&attr))
+        unit->name = attr.u.str;
+      break;
+
+    case DW_AT_low_pc:
+      *low_pc = attr.u.val;
+      if (compunit)
+        unit->base_address = *low_pc;
+      break;
+
+    case DW_AT_high_pc:
+      *high_pc = attr.u.val;
+      *high_pc_relative = attr.form != DW_FORM_addr;
+      break;
+
+    case DW_AT_ranges:
+      if (!read_rangelist (unit, &unit->arange, attr.u.val))
+        return;
+      break;
+
+    case DW_AT_comp_dir:
+    {
+      char *comp_dir = attr.u.str;
+
+      if (! is_str_form (&attr))
+      {
+         _bfd_error_handler
+          (_("DWARF error: DW_AT_comp_dir attribute encountered with a non-string form"));
+         comp_dir = NULL;
+      }
+
+      if (comp_dir)
+      {
+        char *cp = strchr (comp_dir, ':');
+
+        if (cp && cp != comp_dir && cp[-1] == '.' && cp[1] == '/')
+          comp_dir = cp + 1;
+      }
+        unit->comp_dir = comp_dir;
+        break;
+    }
+
+      case DW_AT_language:
+        unit->lang = attr.u.val;
+      default:
+        break;
+   }
+}
+
 /* Parse a DWARF2 compilation unit starting at INFO_PTR.  UNIT_LENGTH
    includes the compilation unit header that proceeds the DIE's, but
    does not include the length field that precedes each compilation
@@ -3782,6 +3989,9 @@ parse_comp_unit (struct dwarf2_debug *stash,
   bfd *abfd = file->bfd_ptr;
   bool high_pc_relative = false;
   enum dwarf_unit_type unit_type;
+  struct attribute *str_addrp = NULL;
+  unsigned int count = 0;
+  bool compunit_flag = false;
 
   version = read_2_bytes (abfd, &info_ptr, end_ptr);
   if (version < 2 || version > 5)
@@ -3886,12 +4096,34 @@ parse_comp_unit (struct dwarf2_debug *stash,
   unit->file = file;
   unit->info_ptr_unit = info_ptr_unit;
 
+  if (abbrev->tag == DW_TAG_compile_unit)
+    compunit_flag = true;
+
   for (i = 0; i < abbrev->num_attrs; ++i)
     {
       info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr, end_ptr);
       if (info_ptr == NULL)
 	return NULL;
 
+      /* Identify attributes of the form strx* and addrx* which come before
+	 DW_AT_str_offsets_base and DW_AT_addr_base respectively in the CU.
+	 Store the attributes in an array and process them later.  */
+      if ((is_strx_form(attr.form) &&
+	  unit->dwarf_str_offset == 0) ||
+          (is_addrx_form(attr.form)  &&
+	  unit->dwarf_addr_offset == 0))
+      {
+	str_addrp = (struct attribute *)
+	  bfd_realloc(str_addrp, (count + 1) * sizeof(struct attribute));
+	if (str_addrp == NULL)
+	  return NULL;
+	str_addrp[count].name = attr.name;
+	str_addrp[count].form = (enum dwarf_form) attr.form;
+	str_addrp[count].u.val = attr.u.val;
+	count++;
+	continue;
+      }
+
       /* Store the data if it is of an attribute we want to keep in a
 	 partial symbol table.  */
       switch (attr.name)
@@ -3916,7 +4148,7 @@ parse_comp_unit (struct dwarf2_debug *stash,
 	      /* If the compilation unit DIE has a DW_AT_low_pc attribute,
 		 this is the base address to use when reading location
 		 lists or range lists.  */
-	      if (abbrev->tag == DW_TAG_compile_unit)
+	      if (compunit_flag)
 		unit->base_address = low_pc;
 	    }
 	  break;
@@ -3965,10 +4197,27 @@ parse_comp_unit (struct dwarf2_debug *stash,
 	    unit->lang = attr.u.val;
 	  break;
 
+	case DW_AT_addr_base:
+	  unit->dwarf_addr_offset = attr.u.val;
+	  break;
+
+	case DW_AT_str_offsets_base:
+	  unit->dwarf_str_offset = attr.u.val;
+	  break;
+
 	default:
 	  break;
 	}
     }
+
+  for (i = 0; i < count; ++i)
+    {
+	struct attribute attr1 = str_addrp[i];
+	reread_attribute(unit, attr1, &low_pc, &high_pc,
+			 &high_pc_relative, compunit_flag);
+
+    }
+
   if (high_pc_relative)
     high_pc += low_pc;
   if (high_pc != 0)
@@ -3978,6 +4227,10 @@ parse_comp_unit (struct dwarf2_debug *stash,
     }
 
   unit->first_child_die_ptr = info_ptr;
+
+  if (str_addrp != NULL)
+    free(str_addrp);
+
   return unit;
 }
 
-- 
2.17.1


>-----Original Message-----
>From: Jan Beulich <jbeulich@suse.com>
>Sent: Monday, April 25, 2022 6:27 PM
>To: Potharla, Rupesh <Rupesh.Potharla@amd.com>
>Cc: George, Jini Susan <JiniSusan.George@amd.com>; Parasuraman,
>Hariharan <Hariharan.Parasuraman@amd.com>; Natarajan, Kavitha
><Kavitha.Natarajan@amd.com>; binutils@sourceware.org
>Subject: Re: [PATCH] bfd: Add Support for DW_FORM_strx* and
>DW_FORM_addrx*.
>
>[CAUTION: External Email]
>
>On 22.04.2022 08:36, Potharla, Rupesh via Binutils wrote:
>> Requesting to review the attached patch. The patch provides support for
>strx* and addrx* forms to the bfd library.
>
>There's a change to decode_line_info() which looks unrelated. If it's related,
>you will want to explain this in the description. If it's not related, you will want
>to split this into a separate patch with its own justification. The same looks to
>repeat in
>find_abstract_instance() and yet more places.
>
>There's a use of bfd_realloc() where you forgot to check for failure.
>
>I consider it at least risky to open-code the conversion from index to actual
>value into various callers of read_attribute(), instead of keeping it in
>read_attribute_value(), as was clearly originally intended.
>
>In read_indexed_string(), besides swapping the parameter order for no
>apparent reason, you go from a 64-bit type to "unsigned long". Are you sure
>this is going to be sufficient on 32-bit architectures? I'd rather see
>read_indexed_address() use bfd_uint64_t as well ...
>
>Furthermore read_indexed_address() has a return type of "int", but you mean
>to return addresses there. Quite likely this wants to at least be bfd_vma, if not
>bfd_uint64_t.
>
>There are also quite a few indentation and padding issues, which you will
>want to take care of.
>
>To aid reviewers, please try to supply patches inline rather than as
>attachment.
>
>Jan

[-- Attachment #2: 0001-bfd-dwarf2-Add-Support-for-DW_FORM_strx-and-DW_FORM_.patch --]
[-- Type: application/octet-stream, Size: 13711 bytes --]

From 812ce279d73cfba5dea464d91536edc512d193b3 Mon Sep 17 00:00:00 2001
From: rupothar <rupesh.potharla@amd.com>
Date: Wed, 30 Mar 2022 15:38:19 +0530
Subject: [PATCH] bfd/dwarf2: Add Support for DW_FORM_strx* and DW_FORM_addrx*.

 Made code changes implementing strx* and addrx* forms to the BFD library.
---
 bfd/dwarf2.c | 275 ++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 264 insertions(+), 11 deletions(-)

diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
index 404f35df62b..fe6c0b907c4 100644
--- a/bfd/dwarf2.c
+++ b/bfd/dwarf2.c
@@ -118,6 +118,18 @@ struct dwarf2_debug_file
   /* Length of the loaded .debug_str section.  */
   bfd_size_type dwarf_str_size;
 
+  /* Pointer to the .debug_str_offsets section loaded into memory.  */
+  bfd_byte *dwarf_str_offsets_buffer;
+
+  /* Length of the loaded .debug_str_offsets section.  */
+  bfd_size_type dwarf_str_offsets_size;
+
+  /* Pointer to the .debug_addr section loaded into memory.  */
+  bfd_byte *dwarf_addr_buffer;
+
+  /* Length of the loaded .debug_addr section.  */
+  bfd_size_type dwarf_addr_size;
+
   /* Pointer to the .debug_line_str section loaded into memory.  */
   bfd_byte *dwarf_line_str_buffer;
 
@@ -296,6 +308,12 @@ struct comp_unit
 
   /* TRUE if symbols are cached in hash table for faster lookup by name.  */
   bool cached;
+
+ /* Base address of debug_addr section.  */
+  unsigned long dwarf_addr_offset;
+
+  /* Base address of string offset table.  */
+  unsigned long dwarf_str_offset;
 };
 
 /* This data structure holds the information of an abbrev.  */
@@ -338,6 +356,8 @@ const struct dwarf_debug_section dwarf_debug_sections[] =
   { ".debug_static_vars",	".zdebug_static_vars" },
   { ".debug_str",		".zdebug_str", },
   { ".debug_str",		".zdebug_str", },
+  { ".debug_str_offsets",       ".zdebug_str_offsets", },
+  { ".debug_addr",              ".zdebug_addr", },
   { ".debug_line_str",		".zdebug_line_str", },
   { ".debug_types",		".zdebug_types" },
   /* GNU DWARF 1 extensions */
@@ -372,6 +392,8 @@ enum dwarf_debug_section_enum
   debug_static_vars,
   debug_str,
   debug_str_alt,
+  debug_str_offsets,
+  debug_addr,
   debug_line_str,
   debug_types,
   debug_sfnames,
@@ -1221,12 +1243,93 @@ is_int_form (const struct attribute *attr)
     }
 }
 
+/* Returns true if the form is strx[1-4].  */
+
+static inline bool
+is_strx_form(enum dwarf_form form)
+{
+  return (form == DW_FORM_strx
+	  || form == DW_FORM_strx1
+	  || form == DW_FORM_strx2
+	  || form == DW_FORM_strx3
+	  || form == DW_FORM_strx4);
+}
+
+/* Return true if the form is addrx[1-4].  */
+
+static inline bool
+is_addrx_form(enum dwarf_form form)
+{
+  return (form == DW_FORM_addrx
+	  || form == DW_FORM_addrx1
+	  || form == DW_FORM_addrx2
+	  || form == DW_FORM_addrx3
+	  || form == DW_FORM_addrx4);
+}
+
+/* Returns the address in .debug_addr section using DW_AT_addr_base.
+   Used to implement DW_FORM_addrx*.  */
+static bfd_vma
+read_indexed_address (bfd_uint64_t idx,
+		      struct comp_unit *unit)
+{
+  struct dwarf2_debug *stash = unit->stash;
+  struct dwarf2_debug_file *file = unit->file;
+  unsigned long addr_base = unit->dwarf_addr_offset;
+  bfd_byte *info_ptr;
+
+  if (stash == NULL)
+    return 0;
+
+  if (!read_section (unit->abfd, &stash->debug_sections[debug_addr],
+		     file->syms, 0,
+		     &file->dwarf_addr_buffer, &file->dwarf_addr_size))
+    return 0;
+
+  info_ptr = (bfd_byte *)(file->dwarf_addr_buffer + addr_base
+	      + idx * unit->offset_size);
+
+  if (unit->offset_size == 4)
+     return bfd_get_32 (unit->abfd, info_ptr);
+  else
+     return bfd_get_64 (unit->abfd, info_ptr);
+}
+
+/* Returns the string using DW_AT_str_offsets_base.
+   Used to implement DW_FORM_strx*.  */
 static const char *
-read_indexed_string (bfd_uint64_t idx ATTRIBUTE_UNUSED,
-		     struct comp_unit * unit ATTRIBUTE_UNUSED)
+read_indexed_string (bfd_uint64_t idx,
+		     struct comp_unit * unit)
 {
-  /* FIXME: Add support for indexed strings.  */
-  return "<indexed strings not yet supported>";
+  struct dwarf2_debug *stash = unit->stash;
+  struct dwarf2_debug_file *file = unit->file;
+  bfd_byte *info_ptr;
+  unsigned long str_offset;
+
+  if (stash == NULL)
+    return NULL;
+
+  if (!read_section (unit->abfd, &stash->debug_sections[debug_str],
+		     file->syms, 0,
+		     &file->dwarf_str_buffer, &file->dwarf_str_size))
+    return NULL;
+
+  if (!read_section (unit->abfd, &stash->debug_sections[debug_str_offsets],
+		     file->syms, 0,
+		     &file->dwarf_str_offsets_buffer,
+		     &file->dwarf_str_offsets_size))
+  return NULL;
+
+  info_ptr = (bfd_byte *)(file->dwarf_str_offsets_buffer
+	      +  unit->dwarf_str_offset
+	      + idx * unit->offset_size);
+
+  if (unit->offset_size == 4)
+     str_offset = bfd_get_32 (unit->abfd, info_ptr);
+  else
+     str_offset = bfd_get_64 (unit->abfd, info_ptr);
+
+  return (const char*) (file->dwarf_str_buffer + str_offset);
 }
 
 /* Read and fill in the value of attribute ATTR as described by FORM.
@@ -1295,21 +1398,37 @@ read_attribute_value (struct attribute *  attr,
     case DW_FORM_ref1:
     case DW_FORM_flag:
     case DW_FORM_data1:
+      attr->u.val = read_1_byte (abfd, &info_ptr, info_ptr_end);
+      break;
     case DW_FORM_addrx1:
       attr->u.val = read_1_byte (abfd, &info_ptr, info_ptr_end);
+      /* dwarf_addr_offset value 0 indicates the attribute DW_AT_addr_base
+	 is not yet read.  */
+      if (unit->dwarf_addr_offset != 0)
+	attr->u.val = read_indexed_address(attr->u.val, unit);
       break;
     case DW_FORM_data2:
-    case DW_FORM_addrx2:
     case DW_FORM_ref2:
       attr->u.val = read_2_bytes (abfd, &info_ptr, info_ptr_end);
       break;
+    case DW_FORM_addrx2:
+      attr->u.val = read_2_bytes (abfd, &info_ptr, info_ptr_end);
+      if (unit->dwarf_addr_offset != 0)
+	attr->u.val = read_indexed_address(attr->u.val, unit);
+      break;
     case DW_FORM_addrx3:
       attr->u.val = read_3_bytes (abfd, &info_ptr, info_ptr_end);
+      if (unit->dwarf_addr_offset != 0)
+	attr->u.val = read_indexed_address(attr->u.val, unit);
       break;
     case DW_FORM_ref4:
     case DW_FORM_data4:
+      attr->u.val = read_4_bytes (abfd, &info_ptr, info_ptr_end);
+      break;
     case DW_FORM_addrx4:
       attr->u.val = read_4_bytes (abfd, &info_ptr, info_ptr_end);
+      if (unit->dwarf_addr_offset != 0)
+	attr->u.val = read_indexed_address(attr->u.val, unit);
       break;
     case DW_FORM_data8:
     case DW_FORM_ref8:
@@ -1330,24 +1449,31 @@ read_attribute_value (struct attribute *  attr,
       break;
     case DW_FORM_strx1:
       attr->u.val = read_1_byte (abfd, &info_ptr, info_ptr_end);
-      attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+      /* dwarf_str_offset value 0 indicates the attribute DW_AT_str_offsets_base
+	 is not yet read.  */
+      if (unit->dwarf_str_offset != 0)
+	attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
       break;
     case DW_FORM_strx2:
       attr->u.val = read_2_bytes (abfd, &info_ptr, info_ptr_end);
-      attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+      if (unit->dwarf_str_offset != 0)
+	attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
       break;
     case DW_FORM_strx3:
       attr->u.val = read_3_bytes (abfd, &info_ptr, info_ptr_end);
-      attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+      if (unit->dwarf_str_offset != 0)
+	attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
       break;
     case DW_FORM_strx4:
       attr->u.val = read_4_bytes (abfd, &info_ptr, info_ptr_end);
-      attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+      if (unit->dwarf_str_offset != 0)
+	attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
       break;
     case DW_FORM_strx:
       attr->u.val = _bfd_safe_read_leb128 (abfd, &info_ptr,
 					   false, info_ptr_end);
-      attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+      if (unit->dwarf_str_offset != 0)
+	attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
       break;
     case DW_FORM_exprloc:
     case DW_FORM_block:
@@ -1369,9 +1495,14 @@ read_attribute_value (struct attribute *  attr,
       break;
     case DW_FORM_ref_udata:
     case DW_FORM_udata:
+      attr->u.val = _bfd_safe_read_leb128 (abfd, &info_ptr,
+					   false, info_ptr_end);
+      break;
     case DW_FORM_addrx:
       attr->u.val = _bfd_safe_read_leb128 (abfd, &info_ptr,
 					   false, info_ptr_end);
+      if (unit->dwarf_addr_offset != 0)
+	attr->u.val = read_indexed_address(attr->u.val, unit);
       break;
     case DW_FORM_indirect:
       form = _bfd_safe_read_leb128 (abfd, &info_ptr,
@@ -2117,6 +2248,11 @@ read_formatted_entries (struct comp_unit *unit, bfd_byte **bufp,
 	    {
 	    case DW_FORM_string:
 	    case DW_FORM_line_strp:
+	    case DW_FORM_strx:
+	    case DW_FORM_strx1:
+	    case DW_FORM_strx2:
+	    case DW_FORM_strx3:
+	    case DW_FORM_strx4:
 	      *stringp = attr.u.str;
 	      break;
 
@@ -3749,6 +3885,77 @@ scan_unit_for_symbols (struct comp_unit *unit)
   return false;
 }
 
+/* read the attributes of the form strx and addrx.  */
+static void reread_attribute (struct comp_unit *    unit,
+			      struct attribute attr,
+			      bfd_vma *low_pc,
+			      bfd_vma *high_pc,
+			      bool *high_pc_relative,
+			      bool compunit)
+{
+
+  if (is_strx_form(attr.form))
+    attr.u.str = (char*) read_indexed_string (attr.u.val, unit);
+  if (is_addrx_form(attr.form))
+    attr.u.val = read_indexed_address (attr.u.val, unit);
+
+  switch (attr.name)
+  {
+    case DW_AT_stmt_list:
+      unit->stmtlist = 1;
+      unit->line_offset = attr.u.val;
+      break;
+
+    case DW_AT_name:
+      if (is_str_form (&attr))
+        unit->name = attr.u.str;
+      break;
+
+    case DW_AT_low_pc:
+      *low_pc = attr.u.val;
+      if (compunit)
+        unit->base_address = *low_pc;
+      break;
+
+    case DW_AT_high_pc:
+      *high_pc = attr.u.val;
+      *high_pc_relative = attr.form != DW_FORM_addr;
+      break;
+
+    case DW_AT_ranges:
+      if (!read_rangelist (unit, &unit->arange, attr.u.val))
+        return;
+      break;
+
+    case DW_AT_comp_dir:
+    {
+      char *comp_dir = attr.u.str;
+
+      if (! is_str_form (&attr))
+      {
+         _bfd_error_handler
+          (_("DWARF error: DW_AT_comp_dir attribute encountered with a non-string form"));
+         comp_dir = NULL;
+      }
+
+      if (comp_dir)
+      {
+        char *cp = strchr (comp_dir, ':');
+
+        if (cp && cp != comp_dir && cp[-1] == '.' && cp[1] == '/')
+          comp_dir = cp + 1;
+      }
+        unit->comp_dir = comp_dir;
+        break;
+    }
+
+      case DW_AT_language:
+        unit->lang = attr.u.val;
+      default:
+        break;
+   }
+}
+
 /* Parse a DWARF2 compilation unit starting at INFO_PTR.  UNIT_LENGTH
    includes the compilation unit header that proceeds the DIE's, but
    does not include the length field that precedes each compilation
@@ -3782,6 +3989,9 @@ parse_comp_unit (struct dwarf2_debug *stash,
   bfd *abfd = file->bfd_ptr;
   bool high_pc_relative = false;
   enum dwarf_unit_type unit_type;
+  struct attribute *str_addrp = NULL;
+  unsigned int count = 0;
+  bool compunit_flag = false;
 
   version = read_2_bytes (abfd, &info_ptr, end_ptr);
   if (version < 2 || version > 5)
@@ -3886,12 +4096,34 @@ parse_comp_unit (struct dwarf2_debug *stash,
   unit->file = file;
   unit->info_ptr_unit = info_ptr_unit;
 
+  if (abbrev->tag == DW_TAG_compile_unit)
+    compunit_flag = true;
+
   for (i = 0; i < abbrev->num_attrs; ++i)
     {
       info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr, end_ptr);
       if (info_ptr == NULL)
 	return NULL;
 
+      /* Identify attributes of the form strx* and addrx* which come before
+	 DW_AT_str_offsets_base and DW_AT_addr_base respectively in the CU.
+	 Store the attributes in an array and process them later.  */
+      if ((is_strx_form(attr.form) &&
+	  unit->dwarf_str_offset == 0) ||
+          (is_addrx_form(attr.form)  &&
+	  unit->dwarf_addr_offset == 0))
+      {
+	str_addrp = (struct attribute *)
+	  bfd_realloc(str_addrp, (count + 1) * sizeof(struct attribute));
+	if (str_addrp == NULL)
+	  return NULL;
+	str_addrp[count].name = attr.name;
+	str_addrp[count].form = (enum dwarf_form) attr.form;
+	str_addrp[count].u.val = attr.u.val;
+	count++;
+	continue;
+      }
+
       /* Store the data if it is of an attribute we want to keep in a
 	 partial symbol table.  */
       switch (attr.name)
@@ -3916,7 +4148,7 @@ parse_comp_unit (struct dwarf2_debug *stash,
 	      /* If the compilation unit DIE has a DW_AT_low_pc attribute,
 		 this is the base address to use when reading location
 		 lists or range lists.  */
-	      if (abbrev->tag == DW_TAG_compile_unit)
+	      if (compunit_flag)
 		unit->base_address = low_pc;
 	    }
 	  break;
@@ -3965,10 +4197,27 @@ parse_comp_unit (struct dwarf2_debug *stash,
 	    unit->lang = attr.u.val;
 	  break;
 
+	case DW_AT_addr_base:
+	  unit->dwarf_addr_offset = attr.u.val;
+	  break;
+
+	case DW_AT_str_offsets_base:
+	  unit->dwarf_str_offset = attr.u.val;
+	  break;
+
 	default:
 	  break;
 	}
     }
+
+  for (i = 0; i < count; ++i)
+    {
+	struct attribute attr1 = str_addrp[i];
+	reread_attribute(unit, attr1, &low_pc, &high_pc,
+			 &high_pc_relative, compunit_flag);
+
+    }
+
   if (high_pc_relative)
     high_pc += low_pc;
   if (high_pc != 0)
@@ -3978,6 +4227,10 @@ parse_comp_unit (struct dwarf2_debug *stash,
     }
 
   unit->first_child_die_ptr = info_ptr;
+
+  if (str_addrp != NULL)
+    free(str_addrp);
+
   return unit;
 }
 
-- 
2.17.1


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

* Re: [PATCH] bfd: Add Support for DW_FORM_strx* and DW_FORM_addrx*.
  2022-05-08 16:28   ` Potharla, Rupesh
@ 2022-05-17 11:38     ` Jan Beulich
  0 siblings, 0 replies; 4+ messages in thread
From: Jan Beulich @ 2022-05-17 11:38 UTC (permalink / raw)
  To: Potharla, Rupesh
  Cc: George, Jini Susan, Parasuraman, Hariharan, Natarajan, Kavitha, binutils

On 08.05.2022 18:28, Potharla, Rupesh wrote:
> [Public]
> 
>  Jan, 
> 
> Apologies for the delayed reply did not get a chance to work on this due to personal reasons. Made the code changes suggested and removed code changes related to file index will send the patch separately for review.  Can you review my code changes and send in your comments/suggestions?
> 
> Regards,
> Rupesh P

Can you please submit a proper v2 patch?

Thanks, Jan

> From 812ce279d73cfba5dea464d91536edc512d193b3 Mon Sep 17 00:00:00 2001
> From: rupothar <rupesh.potharla@amd.com>
> Date: Wed, 30 Mar 2022 15:38:19 +0530
> Subject: [PATCH] bfd/dwarf2: Add Support for DW_FORM_strx* and DW_FORM_addrx*.
> 
>  Made code changes implementing strx* and addrx* forms to the BFD library.
> ---
>  bfd/dwarf2.c | 275 ++++++++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 264 insertions(+), 11 deletions(-)
> 
> diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
> index 404f35df62b..fe6c0b907c4 100644
> --- a/bfd/dwarf2.c
> +++ b/bfd/dwarf2.c
> @@ -118,6 +118,18 @@ struct dwarf2_debug_file
>    /* Length of the loaded .debug_str section.  */
>    bfd_size_type dwarf_str_size;
>  
> +  /* Pointer to the .debug_str_offsets section loaded into memory.  */
> +  bfd_byte *dwarf_str_offsets_buffer;
> +
> +  /* Length of the loaded .debug_str_offsets section.  */
> +  bfd_size_type dwarf_str_offsets_size;
> +
> +  /* Pointer to the .debug_addr section loaded into memory.  */
> +  bfd_byte *dwarf_addr_buffer;
> +
> +  /* Length of the loaded .debug_addr section.  */
> +  bfd_size_type dwarf_addr_size;
> +
>    /* Pointer to the .debug_line_str section loaded into memory.  */
>    bfd_byte *dwarf_line_str_buffer;
>  
> @@ -296,6 +308,12 @@ struct comp_unit
>  
>    /* TRUE if symbols are cached in hash table for faster lookup by name.  */
>    bool cached;
> +
> + /* Base address of debug_addr section.  */
> +  unsigned long dwarf_addr_offset;
> +
> +  /* Base address of string offset table.  */
> +  unsigned long dwarf_str_offset;
>  };
>  
>  /* This data structure holds the information of an abbrev.  */
> @@ -338,6 +356,8 @@ const struct dwarf_debug_section dwarf_debug_sections[] =
>    { ".debug_static_vars",	".zdebug_static_vars" },
>    { ".debug_str",		".zdebug_str", },
>    { ".debug_str",		".zdebug_str", },
> +  { ".debug_str_offsets",       ".zdebug_str_offsets", },
> +  { ".debug_addr",              ".zdebug_addr", },
>    { ".debug_line_str",		".zdebug_line_str", },
>    { ".debug_types",		".zdebug_types" },
>    /* GNU DWARF 1 extensions */
> @@ -372,6 +392,8 @@ enum dwarf_debug_section_enum
>    debug_static_vars,
>    debug_str,
>    debug_str_alt,
> +  debug_str_offsets,
> +  debug_addr,
>    debug_line_str,
>    debug_types,
>    debug_sfnames,
> @@ -1221,12 +1243,93 @@ is_int_form (const struct attribute *attr)
>      }
>  }
>  
> +/* Returns true if the form is strx[1-4].  */
> +
> +static inline bool
> +is_strx_form(enum dwarf_form form)
> +{
> +  return (form == DW_FORM_strx
> +	  || form == DW_FORM_strx1
> +	  || form == DW_FORM_strx2
> +	  || form == DW_FORM_strx3
> +	  || form == DW_FORM_strx4);
> +}
> +
> +/* Return true if the form is addrx[1-4].  */
> +
> +static inline bool
> +is_addrx_form(enum dwarf_form form)
> +{
> +  return (form == DW_FORM_addrx
> +	  || form == DW_FORM_addrx1
> +	  || form == DW_FORM_addrx2
> +	  || form == DW_FORM_addrx3
> +	  || form == DW_FORM_addrx4);
> +}
> +
> +/* Returns the address in .debug_addr section using DW_AT_addr_base.
> +   Used to implement DW_FORM_addrx*.  */
> +static bfd_vma
> +read_indexed_address (bfd_uint64_t idx,
> +		      struct comp_unit *unit)
> +{
> +  struct dwarf2_debug *stash = unit->stash;
> +  struct dwarf2_debug_file *file = unit->file;
> +  unsigned long addr_base = unit->dwarf_addr_offset;
> +  bfd_byte *info_ptr;
> +
> +  if (stash == NULL)
> +    return 0;
> +
> +  if (!read_section (unit->abfd, &stash->debug_sections[debug_addr],
> +		     file->syms, 0,
> +		     &file->dwarf_addr_buffer, &file->dwarf_addr_size))
> +    return 0;
> +
> +  info_ptr = (bfd_byte *)(file->dwarf_addr_buffer + addr_base
> +	      + idx * unit->offset_size);
> +
> +  if (unit->offset_size == 4)
> +     return bfd_get_32 (unit->abfd, info_ptr);
> +  else
> +     return bfd_get_64 (unit->abfd, info_ptr);
> +}
> +
> +/* Returns the string using DW_AT_str_offsets_base.
> +   Used to implement DW_FORM_strx*.  */
>  static const char *
> -read_indexed_string (bfd_uint64_t idx ATTRIBUTE_UNUSED,
> -		     struct comp_unit * unit ATTRIBUTE_UNUSED)
> +read_indexed_string (bfd_uint64_t idx,
> +		     struct comp_unit * unit)
>  {
> -  /* FIXME: Add support for indexed strings.  */
> -  return "<indexed strings not yet supported>";
> +  struct dwarf2_debug *stash = unit->stash;
> +  struct dwarf2_debug_file *file = unit->file;
> +  bfd_byte *info_ptr;
> +  unsigned long str_offset;
> +
> +  if (stash == NULL)
> +    return NULL;
> +
> +  if (!read_section (unit->abfd, &stash->debug_sections[debug_str],
> +		     file->syms, 0,
> +		     &file->dwarf_str_buffer, &file->dwarf_str_size))
> +    return NULL;
> +
> +  if (!read_section (unit->abfd, &stash->debug_sections[debug_str_offsets],
> +		     file->syms, 0,
> +		     &file->dwarf_str_offsets_buffer,
> +		     &file->dwarf_str_offsets_size))
> +  return NULL;
> +
> +  info_ptr = (bfd_byte *)(file->dwarf_str_offsets_buffer
> +	      +  unit->dwarf_str_offset
> +	      + idx * unit->offset_size);
> +
> +  if (unit->offset_size == 4)
> +     str_offset = bfd_get_32 (unit->abfd, info_ptr);
> +  else
> +     str_offset = bfd_get_64 (unit->abfd, info_ptr);
> +
> +  return (const char*) (file->dwarf_str_buffer + str_offset);
>  }
>  
>  /* Read and fill in the value of attribute ATTR as described by FORM.
> @@ -1295,21 +1398,37 @@ read_attribute_value (struct attribute *  attr,
>      case DW_FORM_ref1:
>      case DW_FORM_flag:
>      case DW_FORM_data1:
> +      attr->u.val = read_1_byte (abfd, &info_ptr, info_ptr_end);
> +      break;
>      case DW_FORM_addrx1:
>        attr->u.val = read_1_byte (abfd, &info_ptr, info_ptr_end);
> +      /* dwarf_addr_offset value 0 indicates the attribute DW_AT_addr_base
> +	 is not yet read.  */
> +      if (unit->dwarf_addr_offset != 0)
> +	attr->u.val = read_indexed_address(attr->u.val, unit);
>        break;
>      case DW_FORM_data2:
> -    case DW_FORM_addrx2:
>      case DW_FORM_ref2:
>        attr->u.val = read_2_bytes (abfd, &info_ptr, info_ptr_end);
>        break;
> +    case DW_FORM_addrx2:
> +      attr->u.val = read_2_bytes (abfd, &info_ptr, info_ptr_end);
> +      if (unit->dwarf_addr_offset != 0)
> +	attr->u.val = read_indexed_address(attr->u.val, unit);
> +      break;
>      case DW_FORM_addrx3:
>        attr->u.val = read_3_bytes (abfd, &info_ptr, info_ptr_end);
> +      if (unit->dwarf_addr_offset != 0)
> +	attr->u.val = read_indexed_address(attr->u.val, unit);
>        break;
>      case DW_FORM_ref4:
>      case DW_FORM_data4:
> +      attr->u.val = read_4_bytes (abfd, &info_ptr, info_ptr_end);
> +      break;
>      case DW_FORM_addrx4:
>        attr->u.val = read_4_bytes (abfd, &info_ptr, info_ptr_end);
> +      if (unit->dwarf_addr_offset != 0)
> +	attr->u.val = read_indexed_address(attr->u.val, unit);
>        break;
>      case DW_FORM_data8:
>      case DW_FORM_ref8:
> @@ -1330,24 +1449,31 @@ read_attribute_value (struct attribute *  attr,
>        break;
>      case DW_FORM_strx1:
>        attr->u.val = read_1_byte (abfd, &info_ptr, info_ptr_end);
> -      attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
> +      /* dwarf_str_offset value 0 indicates the attribute DW_AT_str_offsets_base
> +	 is not yet read.  */
> +      if (unit->dwarf_str_offset != 0)
> +	attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
>        break;
>      case DW_FORM_strx2:
>        attr->u.val = read_2_bytes (abfd, &info_ptr, info_ptr_end);
> -      attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
> +      if (unit->dwarf_str_offset != 0)
> +	attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
>        break;
>      case DW_FORM_strx3:
>        attr->u.val = read_3_bytes (abfd, &info_ptr, info_ptr_end);
> -      attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
> +      if (unit->dwarf_str_offset != 0)
> +	attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
>        break;
>      case DW_FORM_strx4:
>        attr->u.val = read_4_bytes (abfd, &info_ptr, info_ptr_end);
> -      attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
> +      if (unit->dwarf_str_offset != 0)
> +	attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
>        break;
>      case DW_FORM_strx:
>        attr->u.val = _bfd_safe_read_leb128 (abfd, &info_ptr,
>  					   false, info_ptr_end);
> -      attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
> +      if (unit->dwarf_str_offset != 0)
> +	attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
>        break;
>      case DW_FORM_exprloc:
>      case DW_FORM_block:
> @@ -1369,9 +1495,14 @@ read_attribute_value (struct attribute *  attr,
>        break;
>      case DW_FORM_ref_udata:
>      case DW_FORM_udata:
> +      attr->u.val = _bfd_safe_read_leb128 (abfd, &info_ptr,
> +					   false, info_ptr_end);
> +      break;
>      case DW_FORM_addrx:
>        attr->u.val = _bfd_safe_read_leb128 (abfd, &info_ptr,
>  					   false, info_ptr_end);
> +      if (unit->dwarf_addr_offset != 0)
> +	attr->u.val = read_indexed_address(attr->u.val, unit);
>        break;
>      case DW_FORM_indirect:
>        form = _bfd_safe_read_leb128 (abfd, &info_ptr,
> @@ -2117,6 +2248,11 @@ read_formatted_entries (struct comp_unit *unit, bfd_byte **bufp,
>  	    {
>  	    case DW_FORM_string:
>  	    case DW_FORM_line_strp:
> +	    case DW_FORM_strx:
> +	    case DW_FORM_strx1:
> +	    case DW_FORM_strx2:
> +	    case DW_FORM_strx3:
> +	    case DW_FORM_strx4:
>  	      *stringp = attr.u.str;
>  	      break;
>  
> @@ -3749,6 +3885,77 @@ scan_unit_for_symbols (struct comp_unit *unit)
>    return false;
>  }
>  
> +/* read the attributes of the form strx and addrx.  */
> +static void reread_attribute (struct comp_unit *    unit,
> +			      struct attribute attr,
> +			      bfd_vma *low_pc,
> +			      bfd_vma *high_pc,
> +			      bool *high_pc_relative,
> +			      bool compunit)
> +{
> +
> +  if (is_strx_form(attr.form))
> +    attr.u.str = (char*) read_indexed_string (attr.u.val, unit);
> +  if (is_addrx_form(attr.form))
> +    attr.u.val = read_indexed_address (attr.u.val, unit);
> +
> +  switch (attr.name)
> +  {
> +    case DW_AT_stmt_list:
> +      unit->stmtlist = 1;
> +      unit->line_offset = attr.u.val;
> +      break;
> +
> +    case DW_AT_name:
> +      if (is_str_form (&attr))
> +        unit->name = attr.u.str;
> +      break;
> +
> +    case DW_AT_low_pc:
> +      *low_pc = attr.u.val;
> +      if (compunit)
> +        unit->base_address = *low_pc;
> +      break;
> +
> +    case DW_AT_high_pc:
> +      *high_pc = attr.u.val;
> +      *high_pc_relative = attr.form != DW_FORM_addr;
> +      break;
> +
> +    case DW_AT_ranges:
> +      if (!read_rangelist (unit, &unit->arange, attr.u.val))
> +        return;
> +      break;
> +
> +    case DW_AT_comp_dir:
> +    {
> +      char *comp_dir = attr.u.str;
> +
> +      if (! is_str_form (&attr))
> +      {
> +         _bfd_error_handler
> +          (_("DWARF error: DW_AT_comp_dir attribute encountered with a non-string form"));
> +         comp_dir = NULL;
> +      }
> +
> +      if (comp_dir)
> +      {
> +        char *cp = strchr (comp_dir, ':');
> +
> +        if (cp && cp != comp_dir && cp[-1] == '.' && cp[1] == '/')
> +          comp_dir = cp + 1;
> +      }
> +        unit->comp_dir = comp_dir;
> +        break;
> +    }
> +
> +      case DW_AT_language:
> +        unit->lang = attr.u.val;
> +      default:
> +        break;
> +   }
> +}
> +
>  /* Parse a DWARF2 compilation unit starting at INFO_PTR.  UNIT_LENGTH
>     includes the compilation unit header that proceeds the DIE's, but
>     does not include the length field that precedes each compilation
> @@ -3782,6 +3989,9 @@ parse_comp_unit (struct dwarf2_debug *stash,
>    bfd *abfd = file->bfd_ptr;
>    bool high_pc_relative = false;
>    enum dwarf_unit_type unit_type;
> +  struct attribute *str_addrp = NULL;
> +  unsigned int count = 0;
> +  bool compunit_flag = false;
>  
>    version = read_2_bytes (abfd, &info_ptr, end_ptr);
>    if (version < 2 || version > 5)
> @@ -3886,12 +4096,34 @@ parse_comp_unit (struct dwarf2_debug *stash,
>    unit->file = file;
>    unit->info_ptr_unit = info_ptr_unit;
>  
> +  if (abbrev->tag == DW_TAG_compile_unit)
> +    compunit_flag = true;
> +
>    for (i = 0; i < abbrev->num_attrs; ++i)
>      {
>        info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr, end_ptr);
>        if (info_ptr == NULL)
>  	return NULL;
>  
> +      /* Identify attributes of the form strx* and addrx* which come before
> +	 DW_AT_str_offsets_base and DW_AT_addr_base respectively in the CU.
> +	 Store the attributes in an array and process them later.  */
> +      if ((is_strx_form(attr.form) &&
> +	  unit->dwarf_str_offset == 0) ||
> +          (is_addrx_form(attr.form)  &&
> +	  unit->dwarf_addr_offset == 0))
> +      {
> +	str_addrp = (struct attribute *)
> +	  bfd_realloc(str_addrp, (count + 1) * sizeof(struct attribute));
> +	if (str_addrp == NULL)
> +	  return NULL;
> +	str_addrp[count].name = attr.name;
> +	str_addrp[count].form = (enum dwarf_form) attr.form;
> +	str_addrp[count].u.val = attr.u.val;
> +	count++;
> +	continue;
> +      }
> +
>        /* Store the data if it is of an attribute we want to keep in a
>  	 partial symbol table.  */
>        switch (attr.name)
> @@ -3916,7 +4148,7 @@ parse_comp_unit (struct dwarf2_debug *stash,
>  	      /* If the compilation unit DIE has a DW_AT_low_pc attribute,
>  		 this is the base address to use when reading location
>  		 lists or range lists.  */
> -	      if (abbrev->tag == DW_TAG_compile_unit)
> +	      if (compunit_flag)
>  		unit->base_address = low_pc;
>  	    }
>  	  break;
> @@ -3965,10 +4197,27 @@ parse_comp_unit (struct dwarf2_debug *stash,
>  	    unit->lang = attr.u.val;
>  	  break;
>  
> +	case DW_AT_addr_base:
> +	  unit->dwarf_addr_offset = attr.u.val;
> +	  break;
> +
> +	case DW_AT_str_offsets_base:
> +	  unit->dwarf_str_offset = attr.u.val;
> +	  break;
> +
>  	default:
>  	  break;
>  	}
>      }
> +
> +  for (i = 0; i < count; ++i)
> +    {
> +	struct attribute attr1 = str_addrp[i];
> +	reread_attribute(unit, attr1, &low_pc, &high_pc,
> +			 &high_pc_relative, compunit_flag);
> +
> +    }
> +
>    if (high_pc_relative)
>      high_pc += low_pc;
>    if (high_pc != 0)
> @@ -3978,6 +4227,10 @@ parse_comp_unit (struct dwarf2_debug *stash,
>      }
>  
>    unit->first_child_die_ptr = info_ptr;
> +
> +  if (str_addrp != NULL)
> +    free(str_addrp);
> +
>    return unit;
>  }
>  


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

end of thread, other threads:[~2022-05-17 11:38 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-22  6:36 [PATCH] bfd: Add Support for DW_FORM_strx* and DW_FORM_addrx* Potharla, Rupesh
2022-04-25 12:56 ` Jan Beulich
2022-05-08 16:28   ` Potharla, Rupesh
2022-05-17 11:38     ` Jan Beulich

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).