From 619a703ea3e1ef4463c168e96b17802b6aa480a0 Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
Date: Fri, 8 Feb 2013 07:04:50 +0000
Subject: [PATCH] 	PR binutils/15106 	* elf-bfd.h (struct
 elf_obj_tdata): Add elf_find_function_cache. 	* elf.c (elf_find_function):
 Revert last change.  Use new 	tdata field rather than static vars for cache.

---
 bfd/ChangeLog |  7 +++++++
 bfd/elf-bfd.h |  3 +++
 bfd/elf.c     | 54 +++++++++++++++++++++++++++++----------------------
 3 files changed, 41 insertions(+), 23 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 4c936117c16..eb723b3f044 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,10 @@
+2013-02-08  Alan Modra  <amodra@gmail.com>
+
+	PR binutils/15106
+	* elf-bfd.h (struct elf_obj_tdata): Add elf_find_function_cache.
+	* elf.c (elf_find_function): Revert last change.  Use new
+	tdata field rather than static vars for cache.
+
 2013-02-07  H.J. Lu  <hongjiu.lu@intel.com>
 
 	PR ld/15107
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 9b383175823..e3876257d9d 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -1598,6 +1598,9 @@ struct elf_obj_tdata
   /* A place to stash dwarf2 info for this bfd.  */
   void *dwarf2_find_line_info;
 
+  /* Stash away info for yet another find line/function variant.  */
+  void *elf_find_function_cache;
+
   /* An array of stub sections indexed by symbol number, used by the
      MIPS ELF linker.  FIXME: We should figure out some way to only
      include this field for a MIPS ELF target.  */
diff --git a/bfd/elf.c b/bfd/elf.c
index 9d6ff318924..380f6eff2a6 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -7504,20 +7504,29 @@ elf_find_function (bfd *abfd,
 		   const char **filename_ptr,
 		   const char **functionname_ptr)
 {
-  static asection *last_section;
-  static asymbol **last_symbols;
-  static asymbol *func;
-  static const char *filename;
-  static bfd_size_type func_size;
+  struct elf_find_function_cache
+  {
+    asection *last_section;
+    asymbol *func;
+    const char *filename;
+    bfd_size_type func_size;
+  } *cache;
 
   if (symbols == NULL)
     return FALSE;
 
-  if (last_section != section
-      || last_symbols != symbols
-      || func == NULL
-      || offset < func->value
-      || offset >= func->value + func_size)
+  cache = elf_tdata (abfd)->elf_find_function_cache;
+  if (cache == NULL)
+    {
+      cache = bfd_zalloc (abfd, sizeof (*cache));
+      elf_tdata (abfd)->elf_find_function_cache = cache;
+      if (cache == NULL)
+	return FALSE;
+    }
+  if (cache->last_section != section
+      || cache->func == NULL
+      || offset < cache->func->value
+      || offset >= cache->func->value + cache->func_size)
     {
       asymbol *file;
       bfd_vma low_func;
@@ -7533,14 +7542,13 @@ elf_find_function (bfd *abfd,
       enum { nothing_seen, symbol_seen, file_after_symbol_seen } state;
       const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
-      filename = NULL;
-      func = NULL;
       file = NULL;
       low_func = 0;
       state = nothing_seen;
-      func_size = 0;
-      last_section = section;
-      last_symbols = symbols;
+      cache->filename = NULL;
+      cache->func = NULL;
+      cache->func_size = 0;
+      cache->last_section = section;
 
       for (p = symbols; *p != NULL; p++)
 	{
@@ -7561,29 +7569,29 @@ elf_find_function (bfd *abfd,
 	      && code_off <= offset
 	      && (code_off > low_func
 		  || (code_off == low_func
-		      && size > func_size)))
+		      && size > cache->func_size)))
 	    {
-	      func = sym;
-	      func_size = size;
+	      cache->func = sym;
+	      cache->func_size = size;
+	      cache->filename = NULL;
 	      low_func = code_off;
-	      filename = NULL;
 	      if (file != NULL
 		  && ((sym->flags & BSF_LOCAL) != 0
 		      || state != file_after_symbol_seen))
-		filename = bfd_asymbol_name (file);
+		cache->filename = bfd_asymbol_name (file);
 	    }
 	  if (state == nothing_seen)
 	    state = symbol_seen;
 	}
     }
 
-  if (func == NULL)
+  if (cache->func == NULL)
     return FALSE;
 
   if (filename_ptr)
-    *filename_ptr = filename;
+    *filename_ptr = cache->filename;
   if (functionname_ptr)
-    *functionname_ptr = bfd_asymbol_name (func);
+    *functionname_ptr = bfd_asymbol_name (cache->func);
 
   return TRUE;
 }