| From Binutils CVS: |
| |
| http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/elf32-arm.c?rev=1.230&content-type=text/x-cvsweb-markup&cvsroot=src |
| |
| Improves linking time from large projects on ARM. |
| diff -dupr binutils-2.20.orig/bfd/elf32-arm.c binutils-2.20/bfd/elf32-arm.c |
| --- binutils-2.20.orig/bfd/elf32-arm.c 2010-04-19 10:08:50.000000000 -0700 |
| +++ binutils-2.20/bfd/elf32-arm.c 2010-04-19 10:12:45.000000000 -0700 |
| @@ -12736,108 +12736,15 @@ elf32_arm_section_from_shdr (bfd *abfd, |
| return TRUE; |
| } |
| |
| -/* A structure used to record a list of sections, independently |
| - of the next and prev fields in the asection structure. */ |
| -typedef struct section_list |
| -{ |
| - asection * sec; |
| - struct section_list * next; |
| - struct section_list * prev; |
| -} |
| -section_list; |
| - |
| -/* Unfortunately we need to keep a list of sections for which |
| - an _arm_elf_section_data structure has been allocated. This |
| - is because it is possible for functions like elf32_arm_write_section |
| - to be called on a section which has had an elf_data_structure |
| - allocated for it (and so the used_by_bfd field is valid) but |
| - for which the ARM extended version of this structure - the |
| - _arm_elf_section_data structure - has not been allocated. */ |
| -static section_list * sections_with_arm_elf_section_data = NULL; |
| - |
| -static void |
| -record_section_with_arm_elf_section_data (asection * sec) |
| -{ |
| - struct section_list * entry; |
| - |
| - entry = bfd_malloc (sizeof (* entry)); |
| - if (entry == NULL) |
| - return; |
| - entry->sec = sec; |
| - entry->next = sections_with_arm_elf_section_data; |
| - entry->prev = NULL; |
| - if (entry->next != NULL) |
| - entry->next->prev = entry; |
| - sections_with_arm_elf_section_data = entry; |
| -} |
| - |
| -static struct section_list * |
| -find_arm_elf_section_entry (asection * sec) |
| -{ |
| - struct section_list * entry; |
| - static struct section_list * last_entry = NULL; |
| - |
| - /* This is a short cut for the typical case where the sections are added |
| - to the sections_with_arm_elf_section_data list in forward order and |
| - then looked up here in backwards order. This makes a real difference |
| - to the ld-srec/sec64k.exp linker test. */ |
| - entry = sections_with_arm_elf_section_data; |
| - if (last_entry != NULL) |
| - { |
| - if (last_entry->sec == sec) |
| - entry = last_entry; |
| - else if (last_entry->next != NULL |
| - && last_entry->next->sec == sec) |
| - entry = last_entry->next; |
| - } |
| - |
| - for (; entry; entry = entry->next) |
| - if (entry->sec == sec) |
| - break; |
| - |
| - if (entry) |
| - /* Record the entry prior to this one - it is the entry we are most |
| - likely to want to locate next time. Also this way if we have been |
| - called from unrecord_section_with_arm_elf_section_data() we will not |
| - be caching a pointer that is about to be freed. */ |
| - last_entry = entry->prev; |
| - |
| - return entry; |
| -} |
| - |
| static _arm_elf_section_data * |
| get_arm_elf_section_data (asection * sec) |
| { |
| - struct section_list * entry; |
| - |
| - entry = find_arm_elf_section_entry (sec); |
| - |
| - if (entry) |
| - return elf32_arm_section_data (entry->sec); |
| + if (sec && sec->owner && is_arm_elf (sec->owner)) |
| + return elf32_arm_section_data (sec); |
| else |
| return NULL; |
| } |
| |
| -static void |
| -unrecord_section_with_arm_elf_section_data (asection * sec) |
| -{ |
| - struct section_list * entry; |
| - |
| - entry = find_arm_elf_section_entry (sec); |
| - |
| - if (entry) |
| - { |
| - if (entry->prev != NULL) |
| - entry->prev->next = entry->next; |
| - if (entry->next != NULL) |
| - entry->next->prev = entry->prev; |
| - if (entry == sections_with_arm_elf_section_data) |
| - sections_with_arm_elf_section_data = entry->next; |
| - free (entry); |
| - } |
| -} |
| - |
| - |
| typedef struct |
| { |
| void *finfo; |
| @@ -13230,8 +13137,6 @@ elf32_arm_new_section_hook (bfd *abfd, a |
| sec->used_by_bfd = sdata; |
| } |
| |
| - record_section_with_arm_elf_section_data (sec); |
| - |
| return _bfd_elf_new_section_hook (abfd, sec); |
| } |
| |
| @@ -13659,44 +13564,13 @@ elf32_arm_write_section (bfd *output_bfd |
| } |
| |
| free (map); |
| - arm_data->mapcount = 0; |
| + arm_data->mapcount = -1; |
| arm_data->mapsize = 0; |
| arm_data->map = NULL; |
| - unrecord_section_with_arm_elf_section_data (sec); |
| |
| return FALSE; |
| } |
| |
| -static void |
| -unrecord_section_via_map_over_sections (bfd * abfd ATTRIBUTE_UNUSED, |
| - asection * sec, |
| - void * ignore ATTRIBUTE_UNUSED) |
| -{ |
| - unrecord_section_with_arm_elf_section_data (sec); |
| -} |
| - |
| -static bfd_boolean |
| -elf32_arm_close_and_cleanup (bfd * abfd) |
| -{ |
| - if (abfd->sections) |
| - bfd_map_over_sections (abfd, |
| - unrecord_section_via_map_over_sections, |
| - NULL); |
| - |
| - return _bfd_elf_close_and_cleanup (abfd); |
| -} |
| - |
| -static bfd_boolean |
| -elf32_arm_bfd_free_cached_info (bfd * abfd) |
| -{ |
| - if (abfd->sections) |
| - bfd_map_over_sections (abfd, |
| - unrecord_section_via_map_over_sections, |
| - NULL); |
| - |
| - return _bfd_free_cached_info (abfd); |
| -} |
| - |
| /* Display STT_ARM_TFUNC symbols as functions. */ |
| |
| static void |
| @@ -13882,8 +13756,6 @@ const struct elf_size_info elf32_arm_siz |
| #define bfd_elf32_find_inliner_info elf32_arm_find_inliner_info |
| #define bfd_elf32_new_section_hook elf32_arm_new_section_hook |
| #define bfd_elf32_bfd_is_target_special_symbol elf32_arm_is_target_special_symbol |
| -#define bfd_elf32_close_and_cleanup elf32_arm_close_and_cleanup |
| -#define bfd_elf32_bfd_free_cached_info elf32_arm_bfd_free_cached_info |
| #define bfd_elf32_bfd_final_link elf32_arm_final_link |
| |
| #define elf_backend_get_symbol_type elf32_arm_get_symbol_type |