This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: arm-elf-ld 2.16.1 crash at bfd/elf32-arm.c:5536


On 8/8/05, Nick Clifton <nickc@redhat.com> wrote:
...
> So with that one small change I have checked our combined patch in, and
> I'll close the PR again.

Any chance there's a release of binutils 2.16.2 planned that fixes
PR-1147 [1]? For posterity, I've attached the combined patch that
fixed this bug.

Thanks!
Shaun

[1] http://sourceware.org/bugzilla/show_bug.cgi?id=1147
Index: bfd/elf32-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.c,v
retrieving revision 1.49
retrieving revision 1.51
diff -u -r1.49 -r1.51
--- bfd/elf32-arm.c	8 Jul 2005 06:19:58 -0000	1.49
+++ bfd/elf32-arm.c	8 Aug 2005 11:06:16 -0000	1.51
@@ -1515,15 +1515,16 @@
 }
 elf32_arm_section_map;
 
-struct _arm_elf_section_data
+typedef struct _arm_elf_section_data
 {
   struct bfd_elf_section_data elf;
-  int mapcount;
+  unsigned int mapcount;
   elf32_arm_section_map *map;
-};
+}
+_arm_elf_section_data;
 
 #define elf32_arm_section_data(sec) \
-  ((struct _arm_elf_section_data *) elf_section_data (sec))
+  ((_arm_elf_section_data *) elf_section_data (sec))
 
 /* The size of the thread control block.  */
 #define TCB_SIZE	8
@@ -4400,7 +4401,7 @@
 
   /* 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
+     cannot actually cause any incompatiblity.  Do not short-circuit
      dynamic objects; their section list may be emptied by
     elf_link_add_object_symbols.
 
@@ -6511,6 +6512,71 @@
   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 _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
+unrecord_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.  */
 
@@ -6523,6 +6589,8 @@
 {
   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.  */
@@ -6538,25 +6606,35 @@
   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;
+  /* 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.  */
-  map = bfd_realloc (map, mapcount * sizeof (elf32_arm_section_map));
-  elf32_arm_section_data (input_sec)->map = map;
+  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];
+    }
 
-  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;
+  _arm_elf_section_data *sdata;
   bfd_size_type amt = sizeof (*sdata);
 
   sdata = bfd_zalloc (abfd, amt);
@@ -6564,6 +6642,8 @@
     return FALSE;
   sec->used_by_bfd = sdata;
 
+  record_section_with_arm_elf_section_data (sec);
+
   return _bfd_elf_new_section_hook (abfd, sec);
 }
 
@@ -6586,6 +6666,7 @@
 			 bfd_byte *contents)
 {
   int mapcount;
+  _arm_elf_section_data *arm_data;
   elf32_arm_section_map *map;
   bfd_vma ptr;
   bfd_vma end;
@@ -6593,14 +6674,19 @@
   bfd_byte tmp;
   int i;
 
-  mapcount = elf32_arm_section_data (sec)->mapcount;
-  map = elf32_arm_section_data (sec)->map;
+  /* 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 (elf32_arm_section_map),
-	 elf32_arm_compare_mapping);
+  qsort (map, mapcount, sizeof (* map), elf32_arm_compare_mapping);
 
   offset = sec->output_section->vma + sec->output_offset;
   ptr = map[0].vma - offset;
@@ -6644,10 +6730,31 @@
 	}
       ptr = end;
     }
+
   free (map);
+  arm_data->mapcount = 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)
+{
+  bfd_map_over_sections (abfd, unrecord_section_via_map_over_sections, NULL);
+
+  return _bfd_elf_close_and_cleanup (abfd);
+}
+
 /* Display STT_ARM_TFUNC symbols as functions.  */
 
 static void
@@ -6806,6 +6913,7 @@
 #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 elf_backend_get_symbol_type             elf32_arm_get_symbol_type
 #define elf_backend_gc_mark_hook                elf32_arm_gc_mark_hook
Index: bfd/elfxx-target.h
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-target.h,v
retrieving revision 1.88
retrieving revision 1.89
diff -u -r1.88 -r1.89
--- bfd/elfxx-target.h	29 Jul 2005 02:46:04 -0000	1.88
+++ bfd/elfxx-target.h	8 Aug 2005 11:06:16 -0000	1.89
@@ -26,7 +26,9 @@
    There are two such structures here:  one for big-endian machines and
    one for little-endian machines.   */
 
+#ifndef bfd_elfNN_close_and_cleanup
 #define	bfd_elfNN_close_and_cleanup _bfd_elf_close_and_cleanup
+#endif
 #define bfd_elfNN_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
 #ifndef bfd_elfNN_get_section_contents
 #define bfd_elfNN_get_section_contents _bfd_generic_get_section_contents

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]