Blame SOURCES/binutils-bfd-DWARF-improvements.patch

5be97c
diff -rup binutils.orig/bfd/dwarf2.c binutils-2.36.1/bfd/dwarf2.c
5be97c
--- binutils.orig/bfd/dwarf2.c	2022-04-11 12:06:47.745972052 +0100
5be97c
+++ binutils-2.36.1/bfd/dwarf2.c	2022-04-11 12:58:03.964445150 +0100
5be97c
@@ -1484,6 +1484,8 @@ struct funcinfo
5be97c
   struct arange		arange;
5be97c
   /* Where the symbol is defined.  */
5be97c
   asection *		sec;
5be97c
+  /* The offset of the funcinfo from the start of the unit.  */
5be97c
+  bfd_uint64_t          unit_offset;
5be97c
 };
5be97c
 
5be97c
 struct lookup_funcinfo
5be97c
@@ -3304,6 +3306,15 @@ read_rangelist (struct comp_unit *unit,
5be97c
     return read_rnglists (unit, arange, offset);
5be97c
 }
5be97c
 
5be97c
+static struct funcinfo *
5be97c
+lookup_func_by_offset (bfd_uint64_t offset, struct funcinfo * table)
5be97c
+{
5be97c
+  for (; table != NULL; table = table->prev_func)
5be97c
+    if (table->unit_offset == offset)
5be97c
+      return table;
5be97c
+  return NULL;
5be97c
+}
5be97c
+
5be97c
 static struct varinfo *
5be97c
 lookup_var_by_offset (bfd_uint64_t offset, struct varinfo * table)
5be97c
 {
5be97c
@@ -3317,6 +3328,35 @@ lookup_var_by_offset (bfd_uint64_t offse
5be97c
   return NULL;
5be97c
 }
5be97c
 
5be97c
+static struct funcinfo *
5be97c
+reverse_funcinfo_list (struct funcinfo * head)
5be97c
+{
5be97c
+  struct funcinfo * rhead;
5be97c
+  struct funcinfo * temp;
5be97c
+
5be97c
+  for (rhead = NULL; head; head = temp)
5be97c
+    {
5be97c
+      temp = head->prev_func;
5be97c
+      head->prev_func = rhead;
5be97c
+      rhead = head;
5be97c
+    }
5be97c
+  return rhead;
5be97c
+}
5be97c
+
5be97c
+static struct varinfo *
5be97c
+reverse_varinfo_list (struct varinfo * head)
5be97c
+{
5be97c
+  struct varinfo * rhead;
5be97c
+  struct varinfo * temp;
5be97c
+
5be97c
+  for (rhead = NULL; head; head = temp)
5be97c
+    {
5be97c
+      temp = head->prev_var;
5be97c
+      head->prev_var = rhead;
5be97c
+      rhead = head;
5be97c
+    }
5be97c
+  return rhead;
5be97c
+}
5be97c
 
5be97c
 /* DWARF2 Compilation unit functions.  */
5be97c
 
5be97c
@@ -3334,6 +3374,8 @@ scan_unit_for_symbols (struct comp_unit
5be97c
     struct funcinfo *func;
5be97c
   } *nested_funcs;
5be97c
   int nested_funcs_size;
5be97c
+  struct funcinfo *last_func;
5be97c
+  struct varinfo *last_var;
5be97c
 
5be97c
   /* Maintain a stack of in-scope functions and inlined functions, which we
5be97c
      can use to set the caller_func field.  */
5be97c
@@ -3344,16 +3386,16 @@ scan_unit_for_symbols (struct comp_unit
5be97c
     return FALSE;
5be97c
   nested_funcs[nesting_level].func = 0;
5be97c
 
5be97c
+  /* PR 27484: We must scan the DIEs twice.  The first time we look for
5be97c
+     function and variable tags and accumulate them into their respective
5be97c
+     tables.  The second time through we process the attributes of the
5be97c
+     functions/variables and augment the table entries.  */
5be97c
   while (nesting_level >= 0)
5be97c
     {
5be97c
       unsigned int abbrev_number, bytes_read, i;
5be97c
       struct abbrev_info *abbrev;
5be97c
-      struct attribute attr;
5be97c
       struct funcinfo *func;
5be97c
       struct varinfo *var;
5be97c
-      bfd_vma low_pc = 0;
5be97c
-      bfd_vma high_pc = 0;
5be97c
-      bfd_boolean high_pc_relative = FALSE;
5be97c
       bfd_uint64_t current_offset;
5be97c
 
5be97c
       /* PR 17512: file: 9f405d9d.  */
5be97c
@@ -3400,6 +3442,7 @@ scan_unit_for_symbols (struct comp_unit
5be97c
 	    goto fail;
5be97c
 	  func->tag = abbrev->tag;
5be97c
 	  func->prev_func = unit->function_table;
5be97c
+	  func->unit_offset = current_offset;
5be97c
 	  unit->function_table = func;
5be97c
 	  unit->number_of_functions++;
5be97c
 	  BFD_ASSERT (!unit->cached);
5be97c
@@ -3440,6 +3483,111 @@ scan_unit_for_symbols (struct comp_unit
5be97c
 
5be97c
       for (i = 0; i < abbrev->num_attrs; ++i)
5be97c
 	{
5be97c
+	  struct attribute attr;
5be97c
+
5be97c
+	  info_ptr = read_attribute (&attr, &abbrev->attrs[i],
5be97c
+				     unit, info_ptr, info_ptr_end);
5be97c
+	  if (info_ptr == NULL)
5be97c
+	    goto fail;
5be97c
+	}
5be97c
+
5be97c
+      if (abbrev->has_children)
5be97c
+	{
5be97c
+	  nesting_level++;
5be97c
+
5be97c
+	  if (nesting_level >= nested_funcs_size)
5be97c
+	    {
5be97c
+	      struct nest_funcinfo *tmp;
5be97c
+
5be97c
+	      nested_funcs_size *= 2;
5be97c
+	      tmp = (struct nest_funcinfo *)
5be97c
+		bfd_realloc (nested_funcs,
5be97c
+			     nested_funcs_size * sizeof (*nested_funcs));
5be97c
+	      if (tmp == NULL)
5be97c
+		goto fail;
5be97c
+	      nested_funcs = tmp;
5be97c
+	    }
5be97c
+	  nested_funcs[nesting_level].func = 0;
5be97c
+	}
5be97c
+    }
5be97c
+
5be97c
+  unit->function_table = reverse_funcinfo_list (unit->function_table);
5be97c
+  unit->variable_table = reverse_varinfo_list (unit->variable_table);
5be97c
+
5be97c
+  /* This is the second pass over the abbrevs.  */      
5be97c
+  info_ptr = unit->first_child_die_ptr;
5be97c
+  nesting_level = 0;
5be97c
+  
5be97c
+  last_func = NULL;
5be97c
+  last_var = NULL;
5be97c
+
5be97c
+  while (nesting_level >= 0)
5be97c
+    {
5be97c
+      unsigned int abbrev_number, bytes_read, i;
5be97c
+      struct abbrev_info *abbrev;
5be97c
+      struct attribute attr;
5be97c
+      struct funcinfo *func;
5be97c
+      struct varinfo *var;
5be97c
+      bfd_vma low_pc = 0;
5be97c
+      bfd_vma high_pc = 0;
5be97c
+      bfd_boolean high_pc_relative = FALSE;
5be97c
+      bfd_uint64_t current_offset;
5be97c
+
5be97c
+      /* PR 17512: file: 9f405d9d.  */
5be97c
+      if (info_ptr >= info_ptr_end)
5be97c
+	goto fail;
5be97c
+
5be97c
+      current_offset = info_ptr - unit->info_ptr_unit;
5be97c
+      abbrev_number = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read,
5be97c
+					     FALSE, info_ptr_end);
5be97c
+      info_ptr += bytes_read;
5be97c
+
5be97c
+      if (! abbrev_number)
5be97c
+	{
5be97c
+	  nesting_level--;
5be97c
+	  continue;
5be97c
+	}
5be97c
+
5be97c
+      abbrev = lookup_abbrev (abbrev_number, unit->abbrevs);
5be97c
+      /* This should have been handled above.  */
5be97c
+      BFD_ASSERT (abbrev != NULL);
5be97c
+
5be97c
+      func = NULL;
5be97c
+      var = NULL;
5be97c
+      if (abbrev->tag == DW_TAG_subprogram
5be97c
+	  || abbrev->tag == DW_TAG_entry_point
5be97c
+	  || abbrev->tag == DW_TAG_inlined_subroutine)
5be97c
+	{
5be97c
+	  if (last_func
5be97c
+	      && last_func->prev_func
5be97c
+	      && last_func->prev_func->unit_offset == current_offset)
5be97c
+	    func = last_func->prev_func;
5be97c
+	  else
5be97c
+	    func = lookup_func_by_offset (current_offset, unit->function_table);
5be97c
+
5be97c
+	  if (func == NULL)
5be97c
+	    goto fail;
5be97c
+
5be97c
+	  last_func = func;
5be97c
+	}
5be97c
+      else if (abbrev->tag == DW_TAG_variable
5be97c
+	       || abbrev->tag == DW_TAG_member)
5be97c
+	{
5be97c
+	  if (last_var
5be97c
+	      && last_var->prev_var
5be97c
+	      && last_var->prev_var->unit_offset == current_offset)
5be97c
+	    var = last_var->prev_var;
5be97c
+	  else
5be97c
+	    var = lookup_var_by_offset (current_offset, unit->variable_table);
5be97c
+
5be97c
+	  if (var == NULL)
5be97c
+	    goto fail;
5be97c
+
5be97c
+	  last_var = var;
5be97c
+	}
5be97c
+
5be97c
+      for (i = 0; i < abbrev->num_attrs; ++i)
5be97c
+	{
5be97c
 	  info_ptr = read_attribute (&attr, &abbrev->attrs[i],
5be97c
 				     unit, info_ptr, info_ptr_end);
5be97c
 	  if (info_ptr == NULL)
5be97c
@@ -3604,6 +3752,9 @@ scan_unit_for_symbols (struct comp_unit
5be97c
 	    }
5be97c
 	}
5be97c
 
5be97c
+      if (abbrev->has_children)
5be97c
+	nesting_level++;
5be97c
+
5be97c
       if (high_pc_relative)
5be97c
 	high_pc += low_pc;
5be97c
 
5be97c
@@ -3612,27 +3763,11 @@ scan_unit_for_symbols (struct comp_unit
5be97c
 	  if (!arange_add (unit, &func->arange, low_pc, high_pc))
5be97c
 	    goto fail;
5be97c
 	}
5be97c
-
5be97c
-      if (abbrev->has_children)
5be97c
-	{
5be97c
-	  nesting_level++;
5be97c
-
5be97c
-	  if (nesting_level >= nested_funcs_size)
5be97c
-	    {
5be97c
-	      struct nest_funcinfo *tmp;
5be97c
-
5be97c
-	      nested_funcs_size *= 2;
5be97c
-	      tmp = (struct nest_funcinfo *)
5be97c
-		bfd_realloc (nested_funcs,
5be97c
-			     nested_funcs_size * sizeof (*nested_funcs));
5be97c
-	      if (tmp == NULL)
5be97c
-		goto fail;
5be97c
-	      nested_funcs = tmp;
5be97c
-	    }
5be97c
-	  nested_funcs[nesting_level].func = 0;
5be97c
-	}
5be97c
     }
5be97c
 
5be97c
+  unit->function_table = reverse_funcinfo_list (unit->function_table);
5be97c
+  unit->variable_table = reverse_varinfo_list (unit->variable_table);
5be97c
+
5be97c
   free (nested_funcs);
5be97c
   return TRUE;
5be97c
 
5be97c
@@ -3994,36 +4129,6 @@ comp_unit_find_line (struct comp_unit *u
5be97c
 					  linenumber_ptr);
5be97c
 }
5be97c
 
5be97c
-static struct funcinfo *
5be97c
-reverse_funcinfo_list (struct funcinfo *head)
5be97c
-{
5be97c
-  struct funcinfo *rhead;
5be97c
-  struct funcinfo *temp;
5be97c
-
5be97c
-  for (rhead = NULL; head; head = temp)
5be97c
-    {
5be97c
-      temp = head->prev_func;
5be97c
-      head->prev_func = rhead;
5be97c
-      rhead = head;
5be97c
-    }
5be97c
-  return rhead;
5be97c
-}
5be97c
-
5be97c
-static struct varinfo *
5be97c
-reverse_varinfo_list (struct varinfo *head)
5be97c
-{
5be97c
-  struct varinfo *rhead;
5be97c
-  struct varinfo *temp;
5be97c
-
5be97c
-  for (rhead = NULL; head; head = temp)
5be97c
-    {
5be97c
-      temp = head->prev_var;
5be97c
-      head->prev_var = rhead;
5be97c
-      rhead = head;
5be97c
-    }
5be97c
-  return rhead;
5be97c
-}
5be97c
-
5be97c
 /* Extract all interesting funcinfos and varinfos of a compilation
5be97c
    unit into hash tables for faster lookup.  Returns TRUE if no
5be97c
    errors were enountered; FALSE otherwise.  */