2011-12-15 Shinichiro Hamaji <shinichiro.hamaji@gmail.com>
authorTristan Gingold <gingold@adacore.com>
Thu, 15 Dec 2011 11:01:14 +0000 (11:01 +0000)
committerTristan Gingold <gingold@adacore.com>
Thu, 15 Dec 2011 11:01:14 +0000 (11:01 +0000)
* mach-o.c (bfd_mach_o_canonicalize_reloc): Update relocation
table only when there isn't the cahce.
(bfd_mach_o_get_dynamic_reloc_upper_bound): Need one more space
for a pointer for the watchdog.
(bfd_mach_o_canonicalize_dynamic_reloc): Utilize cache like
bfd_mach_o_canonicalize_reloc.
(bfd_mach_o_close_and_cleanup): Call bfd_mach_o_free_cached_info.
(bfd_mach_o_free_cached_info): Free up cache data.
* mach-o.h (reloc_cache): A place to store cache of dynamic relocs.
(bfd_mach_o_free_cached_info): Add declaration.

bfd/ChangeLog
bfd/mach-o.c
bfd/mach-o.h

index e1cd2baa3dfd79c2575e4a5564bc3633e965dbb7..4c0c375310d2e57b7f76f69b9a21fd2588f9bdee 100644 (file)
@@ -1,3 +1,16 @@
+2011-12-15  Shinichiro Hamaji  <shinichiro.hamaji@gmail.com>
+
+       * mach-o.c (bfd_mach_o_canonicalize_reloc): Update relocation
+       table only when there isn't the cahce.
+       (bfd_mach_o_get_dynamic_reloc_upper_bound): Need one more space
+       for a pointer for the watchdog.
+       (bfd_mach_o_canonicalize_dynamic_reloc): Utilize cache like
+       bfd_mach_o_canonicalize_reloc.
+       (bfd_mach_o_close_and_cleanup): Call bfd_mach_o_free_cached_info.
+       (bfd_mach_o_free_cached_info): Free up cache data.
+       * mach-o.h (reloc_cache): A place to store cache of dynamic relocs.
+       (bfd_mach_o_free_cached_info): Add declaration.
+
 2011-12-15  Iain Sandoe  <iains@gcc.gnu.org>
 
        * mach-o-target.c (bfd_mach_o_bfd_set_private_flags): Use
index 0c2c2f77e66d341f56609bdf6309142eb4d81592..182f0efc2dfdd1f6eaca54d5bbe1c88f434e2edd 100644 (file)
@@ -1040,21 +1040,25 @@ bfd_mach_o_canonicalize_reloc (bfd *abfd, asection *asect,
   if (bed->_bfd_mach_o_swap_reloc_in == NULL)
     return 0;
 
-  res = bfd_malloc (asect->reloc_count * sizeof (arelent));
-  if (res == NULL)
-    return -1;
-
-  if (bfd_mach_o_canonicalize_relocs (abfd, asect->rel_filepos,
-                                      asect->reloc_count, res, syms) < 0)
+  if (asect->relocation == NULL)
     {
-      free (res);
-      return -1;
+      res = bfd_malloc (asect->reloc_count * sizeof (arelent));
+      if (res == NULL)
+        return -1;
+
+      if (bfd_mach_o_canonicalize_relocs (abfd, asect->rel_filepos,
+                                          asect->reloc_count, res, syms) < 0)
+        {
+          free (res);
+          return -1;
+        }
+      asect->relocation = res;
     }
 
+  res = asect->relocation;
   for (i = 0; i < asect->reloc_count; i++)
     rels[i] = &res[i];
   rels[i] = NULL;
-  asect->relocation = res;
 
   return i;
 }
@@ -1066,7 +1070,7 @@ bfd_mach_o_get_dynamic_reloc_upper_bound (bfd *abfd)
 
   if (mdata->dysymtab == NULL)
     return 1;
-  return (mdata->dysymtab->nextrel + mdata->dysymtab->nlocrel)
+  return (mdata->dysymtab->nextrel + mdata->dysymtab->nlocrel + 1)
     * sizeof (arelent *);
 }
 
@@ -1089,25 +1093,32 @@ bfd_mach_o_canonicalize_dynamic_reloc (bfd *abfd, arelent **rels,
   if (bed->_bfd_mach_o_swap_reloc_in == NULL)
     return 0;
 
-  res = bfd_malloc ((dysymtab->nextrel + dysymtab->nlocrel) * sizeof (arelent));
-  if (res == NULL)
-    return -1;
-
-  if (bfd_mach_o_canonicalize_relocs (abfd, dysymtab->extreloff,
-                                      dysymtab->nextrel, res, syms) < 0)
+  if (mdata->dyn_reloc_cache == NULL)
     {
-      free (res);
-      return -1;
-    }
+      res = bfd_malloc ((dysymtab->nextrel + dysymtab->nlocrel)
+                        * sizeof (arelent));
+      if (res == NULL)
+        return -1;
 
-  if (bfd_mach_o_canonicalize_relocs (abfd, dysymtab->locreloff,
-                                      dysymtab->nlocrel,
-                                      res + dysymtab->nextrel, syms) < 0)
-    {
-      free (res);
-      return -1;
+      if (bfd_mach_o_canonicalize_relocs (abfd, dysymtab->extreloff,
+                                          dysymtab->nextrel, res, syms) < 0)
+        {
+          free (res);
+          return -1;
+        }
+
+      if (bfd_mach_o_canonicalize_relocs (abfd, dysymtab->locreloff,
+                                          dysymtab->nlocrel,
+                                          res + dysymtab->nextrel, syms) < 0)
+        {
+          free (res);
+          return -1;
+        }
+
+      mdata->dyn_reloc_cache = res;
     }
 
+  res = mdata->dyn_reloc_cache;
   for (i = 0; i < dysymtab->nextrel + dysymtab->nlocrel; i++)
     rels[i] = &res[i];
   rels[i] = NULL;
@@ -3756,9 +3767,26 @@ bfd_mach_o_close_and_cleanup (bfd *abfd)
   if (bfd_get_format (abfd) == bfd_object && mdata != NULL)
     _bfd_dwarf2_cleanup_debug_info (abfd, &mdata->dwarf2_find_line_info);
 
+  bfd_mach_o_free_cached_info (abfd);
+
   return _bfd_generic_close_and_cleanup (abfd);
 }
 
+bfd_boolean bfd_mach_o_free_cached_info (bfd *abfd)
+{
+  bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
+  asection *asect;
+  free (mdata->dyn_reloc_cache);
+  mdata->dyn_reloc_cache = NULL;
+  for (asect = abfd->sections; asect != NULL; asect = asect->next)
+    {
+      free (asect->relocation);
+      asect->relocation = NULL;
+    }
+
+  return TRUE;
+}
+
 #define bfd_mach_o_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup 
 #define bfd_mach_o_bfd_reloc_name_lookup _bfd_norelocs_bfd_reloc_name_lookup
 
index e22b41a6022e2cbefc9ac950254e5d65522fb4ea..23c3e1c079c622dda70ca2636eef89aacd6d481d 100644 (file)
@@ -519,6 +519,9 @@ typedef struct mach_o_data_struct
 
   /* A place to stash dwarf2 info for this bfd.  */
   void *dwarf2_find_line_info;
+
+  /* Cache of dynamic relocs. */
+  arelent *dyn_reloc_cache;
 }
 bfd_mach_o_data_struct;
 
@@ -590,6 +593,7 @@ bfd_boolean bfd_mach_o_find_nearest_line (bfd *, asection *, asymbol **,
                                           bfd_vma, const char **,
                                           const char **, unsigned int *);
 bfd_boolean bfd_mach_o_close_and_cleanup (bfd *);
+bfd_boolean bfd_mach_o_free_cached_info (bfd *);
 
 unsigned int bfd_mach_o_section_get_nbr_indirect (bfd *, bfd_mach_o_section *);
 unsigned int bfd_mach_o_section_get_entry_size (bfd *, bfd_mach_o_section *);