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