diff options
-rw-r--r-- | bfd/ChangeLog | 13 | ||||
-rw-r--r-- | bfd/mach-o.c | 78 | ||||
-rw-r--r-- | bfd/mach-o.h | 4 |
3 files changed, 70 insertions, 25 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index e1cd2ba..4c0c375 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -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 diff --git a/bfd/mach-o.c b/bfd/mach-o.c index 0c2c2f7..182f0ef 100644 --- a/bfd/mach-o.c +++ b/bfd/mach-o.c @@ -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 diff --git a/bfd/mach-o.h b/bfd/mach-o.h index e22b41a..23c3e1c 100644 --- a/bfd/mach-o.h +++ b/bfd/mach-o.h @@ -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 *); |