bac2d67
--- binutils-2.27.orig/bfd/dwarf2.c	2016-11-22 17:26:23.634699582 +0000
bac2d67
+++ binutils-2.27/bfd/dwarf2.c	2016-11-22 17:26:49.849841652 +0000
bac2d67
@@ -256,6 +256,12 @@ struct comp_unit
bac2d67
   /* A list of the functions found in this comp. unit.  */
bac2d67
   struct funcinfo *function_table;
bac2d67
 
bac2d67
+  /* A table of function information references searchable by address.  */
bac2d67
+  struct lookup_funcinfo *lookup_funcinfo_table;
bac2d67
+
bac2d67
+  /* Number of functions in the function_table and sorted_function_table.  */
bac2d67
+  bfd_size_type number_of_functions;
bac2d67
+
bac2d67
   /* A list of the variables found in this comp. unit.  */
bac2d67
   struct varinfo *variable_table;
bac2d67
 
bac2d67
@@ -1236,6 +1242,8 @@ struct line_sequence
bac2d67
   bfd_vma               low_pc;
bac2d67
   struct line_sequence* prev_sequence;
bac2d67
   struct line_info*     last_line;  /* Largest VMA.  */
bac2d67
+  struct line_info**    line_info_lookup;
bac2d67
+  bfd_size_type		num_lines;
bac2d67
 };
bac2d67
 
bac2d67
 struct line_info_table
bac2d67
@@ -1278,6 +1286,20 @@ struct funcinfo
bac2d67
   asection *sec;
bac2d67
 };
bac2d67
 
bac2d67
+struct lookup_funcinfo
bac2d67
+{
bac2d67
+  /* Function information corresponding to this lookup table entry.  */
bac2d67
+  struct funcinfo *funcinfo;
bac2d67
+
bac2d67
+  /* The lowest address for this specific function.  */
bac2d67
+  bfd_vma low_addr;
bac2d67
+
bac2d67
+  /* The highest address of this function before the lookup table is sorted.
bac2d67
+  The highest address of all prior functions after the lookup table is sorted,
bac2d67
+  which is used for binary search.  */
bac2d67
+  bfd_vma high_addr;
bac2d67
+};
bac2d67
+
bac2d67
 struct varinfo
bac2d67
 {
bac2d67
   /* Pointer to previous variable in list of all variables */
bac2d67
@@ -1578,6 +1600,49 @@ compare_sequences (const void* a, const
bac2d67
   return 0;
bac2d67
 }
bac2d67
 
bac2d67
+/* Construct the line information table for quick lookup.  */
bac2d67
+
bac2d67
+static bfd_boolean
bac2d67
+build_line_info_table (struct line_info_table* table, struct line_sequence *seq)
bac2d67
+{
bac2d67
+  bfd_size_type amt;
bac2d67
+  struct line_info** line_info_lookup;
bac2d67
+  struct line_info* each_line;
bac2d67
+  unsigned int num_lines;
bac2d67
+  unsigned int index;
bac2d67
+
bac2d67
+  if (seq->line_info_lookup != NULL)
bac2d67
+    return TRUE;
bac2d67
+
bac2d67
+  /* Count the number of line information entries.  We could do this while
bac2d67
+     scanning the debug information, but some entries may be added via lcl_head
bac2d67
+     without having a sequence handy to increment the number of lines.  */
bac2d67
+  num_lines = 0;
bac2d67
+  for (each_line = seq->last_line; each_line; each_line = each_line->prev_line)
bac2d67
+    num_lines++;
bac2d67
+
bac2d67
+  if (num_lines == 0)
bac2d67
+    return TRUE;
bac2d67
+
bac2d67
+  /* Allocate space for the line information lookup table.  */
bac2d67
+  amt = sizeof (struct line_info*) * num_lines;
bac2d67
+  line_info_lookup = (struct line_info**) bfd_alloc (table->abfd, amt);
bac2d67
+  if (line_info_lookup == NULL)
bac2d67
+    return FALSE;
bac2d67
+
bac2d67
+  /* Create the line information lookup table.  */
bac2d67
+  index = num_lines;
bac2d67
+  for (each_line = seq->last_line; each_line; each_line = each_line->prev_line)
bac2d67
+    line_info_lookup[--index] = each_line;
bac2d67
+
bac2d67
+  BFD_ASSERT (index == 0);
bac2d67
+
bac2d67
+  seq->num_lines = num_lines;
bac2d67
+  seq->line_info_lookup = line_info_lookup;
bac2d67
+
bac2d67
+  return TRUE;
bac2d67
+}
bac2d67
+
bac2d67
 /* Sort the line sequences for quick lookup.  */
bac2d67
 
bac2d67
 static bfd_boolean
bac2d67
@@ -1609,6 +1674,8 @@ sort_line_sequences (struct line_info_ta
bac2d67
       sequences[n].low_pc = seq->low_pc;
bac2d67
       sequences[n].prev_sequence = NULL;
bac2d67
       sequences[n].last_line = seq->last_line;
bac2d67
+      sequences[n].line_info_lookup = NULL;
bac2d67
+      sequences[n].num_lines = 0;
bac2d67
       seq = seq->prev_sequence;
bac2d67
       free (last_seq);
bac2d67
     }
bac2d67
@@ -2089,7 +2156,7 @@ lookup_address_in_line_info_table (struc
bac2d67
 				   unsigned int *discriminator_ptr)
bac2d67
 {
bac2d67
   struct line_sequence *seq = NULL;
bac2d67
-  struct line_info *each_line;
bac2d67
+  struct line_info *info;
bac2d67
   int low, high, mid;
bac2d67
 
bac2d67
   /* Binary search the array of sequences.  */
bac2d67
@@ -2107,26 +2174,43 @@ lookup_address_in_line_info_table (struc
bac2d67
 	break;
bac2d67
     }
bac2d67
 
bac2d67
-  if (seq && addr >= seq->low_pc && addr < seq->last_line->address)
bac2d67
+  /* Check for a valid sequence.  */
bac2d67
+  if (!seq || addr < seq->low_pc || addr >= seq->last_line->address)
bac2d67
+    goto fail;
bac2d67
+
bac2d67
+  if (!build_line_info_table (table, seq))
bac2d67
+    goto fail;
bac2d67
+
bac2d67
+  /* Binary search the array of line information.  */
bac2d67
+  low = 0;
bac2d67
+  high = seq->num_lines;
bac2d67
+  info = NULL;
bac2d67
+  while (low < high)
bac2d67
     {
bac2d67
-      /* Note: seq->last_line should be a descendingly sorted list.  */
bac2d67
-      for (each_line = seq->last_line;
bac2d67
-	   each_line;
bac2d67
-	   each_line = each_line->prev_line)
bac2d67
-	if (addr >= each_line->address)
bac2d67
-	  break;
bac2d67
+      mid = (low + high) / 2;
bac2d67
+      info = seq->line_info_lookup[mid];
bac2d67
+      if (addr < info->address)
bac2d67
+	high = mid;
bac2d67
+      else if (addr >= seq->line_info_lookup[mid + 1]->address)
bac2d67
+	low = mid + 1;
bac2d67
+      else
bac2d67
+	break;
bac2d67
+    }
bac2d67
 
bac2d67
-      if (each_line
bac2d67
-	  && !(each_line->end_sequence || each_line == seq->last_line))
bac2d67
-	{
bac2d67
-	  *filename_ptr = each_line->filename;
bac2d67
-	  *linenumber_ptr = each_line->line;
bac2d67
-	  if (discriminator_ptr)
bac2d67
-	    *discriminator_ptr = each_line->discriminator;
bac2d67
-	  return seq->last_line->address - seq->low_pc;
bac2d67
-	}
bac2d67
+  /* Check for a valid line information entry.  */
bac2d67
+  if (info
bac2d67
+      && addr >= info->address
bac2d67
+      && addr < seq->line_info_lookup[mid + 1]->address
bac2d67
+      && !(info->end_sequence || info == seq->last_line))
bac2d67
+    {
bac2d67
+      *filename_ptr = info->filename;
bac2d67
+      *linenumber_ptr = info->line;
bac2d67
+      if (discriminator_ptr)
bac2d67
+	*discriminator_ptr = info->discriminator;
bac2d67
+      return seq->last_line->address - seq->low_pc;
bac2d67
     }
bac2d67
 
bac2d67
+fail:
bac2d67
   *filename_ptr = NULL;
bac2d67
   return 0;
bac2d67
 }
bac2d67
@@ -2144,6 +2228,93 @@ read_debug_ranges (struct comp_unit *uni
bac2d67
 
bac2d67
 /* Function table functions.  */
bac2d67
 
bac2d67
+static int
bac2d67
+compare_lookup_funcinfos (const void* a, const void* b)
bac2d67
+{
bac2d67
+  const struct lookup_funcinfo *lookup1 = a;
bac2d67
+  const struct lookup_funcinfo *lookup2 = b;
bac2d67
+  int result;
bac2d67
+
bac2d67
+  if (lookup1->low_addr < lookup2->low_addr)
bac2d67
+    result = -1;
bac2d67
+  else if (lookup1->low_addr > lookup2->low_addr)
bac2d67
+    result = 1;
bac2d67
+  else if (lookup1->high_addr < lookup2->high_addr)
bac2d67
+    result = -1;
bac2d67
+  else if (lookup1->high_addr > lookup1->high_addr)
bac2d67
+    result = 1;
bac2d67
+  else
bac2d67
+    result = 0;
bac2d67
+
bac2d67
+  return result;
bac2d67
+}
bac2d67
+
bac2d67
+static bfd_boolean
bac2d67
+build_lookup_funcinfo_table (struct comp_unit *unit)
bac2d67
+{
bac2d67
+  struct lookup_funcinfo *lookup_funcinfo_table = unit->lookup_funcinfo_table;
bac2d67
+  unsigned int number_of_functions = unit->number_of_functions;
bac2d67
+  struct funcinfo *each;
bac2d67
+  struct lookup_funcinfo *entry;
bac2d67
+  size_t index;
bac2d67
+  struct arange *range;
bac2d67
+  bfd_vma low_addr, high_addr;
bac2d67
+
bac2d67
+  if (lookup_funcinfo_table || number_of_functions == 0)
bac2d67
+    return TRUE;
bac2d67
+
bac2d67
+  /* Create the function info lookup table.  */
bac2d67
+  lookup_funcinfo_table = (struct lookup_funcinfo *)
bac2d67
+    bfd_malloc (number_of_functions * sizeof (struct lookup_funcinfo));
bac2d67
+  if (lookup_funcinfo_table == NULL)
bac2d67
+    return FALSE;
bac2d67
+
bac2d67
+  /* Populate the function info lookup table.  */
bac2d67
+  index = number_of_functions;
bac2d67
+  for (each = unit->function_table; each; each = each->prev_func)
bac2d67
+    {
bac2d67
+      entry = &lookup_funcinfo_table[--index];
bac2d67
+      entry->funcinfo = each;
bac2d67
+
bac2d67
+      /* Calculate the lowest and highest address for this function entry.  */
bac2d67
+      low_addr  = entry->funcinfo->arange.low;
bac2d67
+      high_addr = entry->funcinfo->arange.high;
bac2d67
+
bac2d67
+      for (range = entry->funcinfo->arange.next; range; range = range->next)
bac2d67
+      {
bac2d67
+	if (range->low < low_addr)
bac2d67
+	  low_addr = range->low;
bac2d67
+	if (range->high > high_addr)
bac2d67
+	  high_addr = range->high;
bac2d67
+      }
bac2d67
+
bac2d67
+      entry->low_addr = low_addr;
bac2d67
+      entry->high_addr = high_addr;
bac2d67
+    }
bac2d67
+
bac2d67
+  BFD_ASSERT (index == 0);
bac2d67
+
bac2d67
+  /* Sort the function by address.  */
bac2d67
+  qsort (lookup_funcinfo_table,
bac2d67
+	number_of_functions,
bac2d67
+	sizeof (struct lookup_funcinfo),
bac2d67
+	compare_lookup_funcinfos);
bac2d67
+
bac2d67
+  /* Calculate the high watermark for each function in the lookup table.  */
bac2d67
+  high_addr = lookup_funcinfo_table[0].high_addr;
bac2d67
+  for (index = 1; index < number_of_functions; index++)
bac2d67
+    {
bac2d67
+      entry = &lookup_funcinfo_table[index];
bac2d67
+      if (entry->high_addr > high_addr)
bac2d67
+	high_addr = entry->high_addr;
bac2d67
+      else
bac2d67
+	entry->high_addr = high_addr;
bac2d67
+    }
bac2d67
+
bac2d67
+  unit->lookup_funcinfo_table = lookup_funcinfo_table;
bac2d67
+  return TRUE;
bac2d67
+}
bac2d67
+
bac2d67
 /* If ADDR is within UNIT's function tables, set FUNCTION_PTR, and return
bac2d67
    TRUE.  Note that we need to find the function that has the smallest range
bac2d67
    that contains ADDR, to handle inlined functions without depending upon
bac2d67
@@ -2154,37 +2325,71 @@ lookup_address_in_function_table (struct
bac2d67
 				  bfd_vma addr,
bac2d67
 				  struct funcinfo **function_ptr)
bac2d67
 {
bac2d67
-  struct funcinfo* each_func;
bac2d67
+  unsigned int number_of_functions = unit->number_of_functions;
bac2d67
+  struct lookup_funcinfo* lookup_funcinfo = NULL;
bac2d67
+  struct funcinfo* funcinfo = NULL;
bac2d67
   struct funcinfo* best_fit = NULL;
bac2d67
   bfd_vma best_fit_len = 0;
bac2d67
+  bfd_size_type low, high, mid, first;
bac2d67
   struct arange *arange;
bac2d67
 
bac2d67
-  for (each_func = unit->function_table;
bac2d67
-       each_func;
bac2d67
-       each_func = each_func->prev_func)
bac2d67
+  if (!build_lookup_funcinfo_table (unit))
bac2d67
+    return FALSE;
bac2d67
+
bac2d67
+  /* Find the first function in the lookup table which may contain the
bac2d67
+     specified address.  */
bac2d67
+  low = 0;
bac2d67
+  high = number_of_functions;
bac2d67
+  first = high;
bac2d67
+  while (low < high)
bac2d67
     {
bac2d67
-      for (arange = &each_func->arange;
bac2d67
-	   arange;
bac2d67
-	   arange = arange->next)
bac2d67
+      mid = (low + high) / 2;
bac2d67
+      lookup_funcinfo = &unit->lookup_funcinfo_table[mid];
bac2d67
+      if (addr < lookup_funcinfo->low_addr)
bac2d67
+	high = mid;
bac2d67
+      else if (addr >= lookup_funcinfo->high_addr)
bac2d67
+	low = mid + 1;
bac2d67
+      else
bac2d67
+	high = first = mid;
bac2d67
+    }
bac2d67
+
bac2d67
+  /* Find the 'best' match for the address.  The prior algorithm defined the
bac2d67
+     best match as the function with the smallest address range containing
bac2d67
+     the specified address.  This definition should probably be changed to the
bac2d67
+     innermost inline routine containing the address, but right now we want
bac2d67
+     to get the same results we did before.  */
bac2d67
+  while (first < number_of_functions)
bac2d67
+    {
bac2d67
+      if (addr < unit->lookup_funcinfo_table[first].low_addr)
bac2d67
+	break;
bac2d67
+      funcinfo = unit->lookup_funcinfo_table[first].funcinfo;
bac2d67
+
bac2d67
+      for (arange = &funcinfo->arange; arange; arange = arange->next)
bac2d67
 	{
bac2d67
-	  if (addr >= arange->low && addr < arange->high)
bac2d67
+	  if (addr < arange->low || addr >= arange->high)
bac2d67
+	    continue;
bac2d67
+
bac2d67
+	  if (!best_fit
bac2d67
+	      || arange->high - arange->low < best_fit_len
bac2d67
+	      /* The following comparison is designed to return the same
bac2d67
+		 match as the previous algorithm for routines which have the
bac2d67
+		 same best fit length.  */
bac2d67
+	      || (arange->high - arange->low == best_fit_len
bac2d67
+		  && funcinfo > best_fit))
bac2d67
 	    {
bac2d67
-	      if (!best_fit
bac2d67
-		  || arange->high - arange->low < best_fit_len)
bac2d67
-		{
bac2d67
-		  best_fit = each_func;
bac2d67
-		  best_fit_len = arange->high - arange->low;
bac2d67
-		}
bac2d67
+	      best_fit = funcinfo;
bac2d67
+	      best_fit_len = arange->high - arange->low;
bac2d67
 	    }
bac2d67
 	}
bac2d67
-    }
bac2d67
 
bac2d67
-  if (best_fit)
bac2d67
-    {
bac2d67
-      *function_ptr = best_fit;
bac2d67
-      return TRUE;
bac2d67
+      first++;
bac2d67
     }
bac2d67
-  return FALSE;
bac2d67
+
bac2d67
+  if (!best_fit)
bac2d67
+    return FALSE;
bac2d67
+
bac2d67
+  *function_ptr = best_fit;
bac2d67
+  return TRUE;
bac2d67
 }
bac2d67
 
bac2d67
 /* If SYM at ADDR is within function table of UNIT, set FILENAME_PTR
bac2d67
@@ -2513,6 +2718,7 @@ scan_unit_for_symbols (struct comp_unit
bac2d67
 	  func->tag = abbrev->tag;
bac2d67
 	  func->prev_func = unit->function_table;
bac2d67
 	  unit->function_table = func;
bac2d67
+      unit->number_of_functions++;
bac2d67
 	  BFD_ASSERT (!unit->cached);
bac2d67
 
bac2d67
 	  if (func->tag == DW_TAG_inlined_subroutine)
bac2d67
@@ -4241,6 +4447,12 @@ _bfd_dwarf2_cleanup_debug_info (bfd *abf
bac2d67
 	  function_table = function_table->prev_func;
bac2d67
 	}
bac2d67
 
bac2d67
+      if (each->lookup_funcinfo_table)
bac2d67
+	{
bac2d67
+	  free (each->lookup_funcinfo_table);
bac2d67
+	  each->lookup_funcinfo_table = NULL;
bac2d67
+	}
bac2d67
+
bac2d67
       while (variable_table)
bac2d67
 	{
bac2d67
 	  if (variable_table->file)