Index: bfd/elf32-arm.c =================================================================== RCS file: /cvs/src/src/bfd/elf32-arm.c,v retrieving revision 1.49 diff -c -3 -p -r1.49 elf32-arm.c *** bfd/elf32-arm.c 8 Jul 2005 06:19:58 -0000 1.49 --- bfd/elf32-arm.c 31 Jul 2005 18:47:13 -0000 *************** typedef struct elf32_elf_section_map *** 1515,1529 **** } elf32_arm_section_map; ! struct _arm_elf_section_data { struct bfd_elf_section_data elf; ! int mapcount; elf32_arm_section_map *map; ! }; #define elf32_arm_section_data(sec) \ ! ((struct _arm_elf_section_data *) elf_section_data (sec)) /* The size of the thread control block. */ #define TCB_SIZE 8 --- 1515,1530 ---- } elf32_arm_section_map; ! typedef struct _arm_elf_section_data { struct bfd_elf_section_data elf; ! unsigned int mapcount; elf32_arm_section_map *map; ! } ! _arm_elf_section_data; #define elf32_arm_section_data(sec) \ ! ((_arm_elf_section_data *) elf_section_data (sec)) /* The size of the thread control block. */ #define TCB_SIZE 8 *************** elf32_arm_merge_private_bfd_data (bfd * *** 4400,4406 **** /* Check to see if the input BFD actually contains any sections. If not, its flags may not have been initialised either, but it ! cannot actually cause any incompatibility. Do not short-circuit dynamic objects; their section list may be emptied by elf_link_add_object_symbols. --- 4401,4407 ---- /* Check to see if the input BFD actually contains any sections. If not, its flags may not have been initialised either, but it ! cannot actually cause any incompatiblity. Do not short-circuit dynamic objects; their section list may be emptied by elf_link_add_object_symbols. *************** elf32_arm_section_from_shdr (bfd *abfd, *** 6511,6516 **** --- 6512,6582 ---- 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 (bfd * abfd, asection * sec) + { + struct section_list * entry; + + entry = bfd_alloc (abfd, 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 _arm_elf_section_data * + get_arm_elf_section_data (asection * sec) + { + struct section_list * entry; + + for (entry = sections_with_arm_elf_section_data; entry; entry = entry->next) + if (entry->sec == sec) + return elf32_arm_section_data (sec); + return NULL; + } + + static void + remove_section_with_arm_elf_section_data (asection * sec) + { + struct section_list * entry; + + for (entry = sections_with_arm_elf_section_data; entry; entry = entry->next) + if (entry->sec == sec) + { + 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); + break; + } + } + /* Called for each symbol. Builds a section map based on mapping symbols. Does not alter any of the symbols. */ *************** elf32_arm_output_symbol_hook (struct bfd *** 6523,6528 **** --- 6589,6596 ---- { int mapcount; elf32_arm_section_map *map; + elf32_arm_section_map *newmap; + _arm_elf_section_data *arm_data; struct elf32_arm_link_hash_table *globals; /* Only do this on final link. */ *************** elf32_arm_output_symbol_hook (struct bfd *** 6538,6562 **** if (! bfd_is_arm_mapping_symbol_name (name)) return TRUE; ! mapcount = ++(elf32_arm_section_data (input_sec)->mapcount); ! map = elf32_arm_section_data (input_sec)->map; /* TODO: This may be inefficient, but we probably don't usually have many mapping symbols per section. */ ! map = bfd_realloc (map, mapcount * sizeof (elf32_arm_section_map)); ! elf32_arm_section_data (input_sec)->map = map; - map[mapcount - 1].vma = elfsym->st_value; - map[mapcount - 1].type = name[1]; return TRUE; } - /* Allocate target specific section data. */ static bfd_boolean elf32_arm_new_section_hook (bfd *abfd, asection *sec) { ! struct _arm_elf_section_data *sdata; bfd_size_type amt = sizeof (*sdata); sdata = bfd_zalloc (abfd, amt); --- 6606,6640 ---- if (! bfd_is_arm_mapping_symbol_name (name)) return TRUE; ! /* If this section has not been allocated an _arm_elf_section_data ! structure then we cannot record anything. */ ! arm_data = get_arm_elf_section_data (input_sec); ! if (arm_data == NULL) ! return TRUE; ! ! mapcount = arm_data->mapcount + 1; ! map = arm_data->map; /* TODO: This may be inefficient, but we probably don't usually have many mapping symbols per section. */ ! newmap = bfd_realloc (map, mapcount * sizeof (* map)); ! if (newmap != NULL) ! { ! arm_data->map = newmap; ! arm_data->mapcount = mapcount; ! ! map[mapcount - 1].vma = elfsym->st_value; ! map[mapcount - 1].type = name[1]; ! } return TRUE; } /* Allocate target specific section data. */ static bfd_boolean elf32_arm_new_section_hook (bfd *abfd, asection *sec) { ! _arm_elf_section_data *sdata; bfd_size_type amt = sizeof (*sdata); sdata = bfd_zalloc (abfd, amt); *************** elf32_arm_new_section_hook (bfd *abfd, a *** 6564,6569 **** --- 6642,6649 ---- return FALSE; sec->used_by_bfd = sdata; + record_section_with_arm_elf_section_data (abfd, sec); + return _bfd_elf_new_section_hook (abfd, sec); } *************** elf32_arm_write_section (bfd *output_bfd *** 6586,6591 **** --- 6666,6672 ---- bfd_byte *contents) { int mapcount; + _arm_elf_section_data *arm_data; elf32_arm_section_map *map; bfd_vma ptr; bfd_vma end; *************** elf32_arm_write_section (bfd *output_bfd *** 6593,6606 **** bfd_byte tmp; int i; ! mapcount = elf32_arm_section_data (sec)->mapcount; ! map = elf32_arm_section_data (sec)->map; if (mapcount == 0) return FALSE; ! qsort (map, mapcount, sizeof (elf32_arm_section_map), ! elf32_arm_compare_mapping); offset = sec->output_section->vma + sec->output_offset; ptr = map[0].vma - offset; --- 6674,6692 ---- bfd_byte tmp; int i; ! /* If this section has not been allocated an _arm_elf_section_data ! structure then we cannot record anything. */ ! arm_data = get_arm_elf_section_data (sec); ! if (arm_data == NULL) ! return FALSE; ! ! mapcount = arm_data->mapcount; ! map = arm_data->map; if (mapcount == 0) return FALSE; ! qsort (map, mapcount, sizeof (* map), elf32_arm_compare_mapping); offset = sec->output_section->vma + sec->output_offset; ptr = map[0].vma - offset; *************** elf32_arm_write_section (bfd *output_bfd *** 6644,6650 **** --- 6730,6741 ---- } ptr = end; } + free (map); + arm_data->mapcount = 0; + arm_data->map = NULL; + remove_section_with_arm_elf_section_data (sec); + return FALSE; }