This is the mail archive of the binutils@sources.redhat.com 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


Hi Shaun,

Good news! I found the test case that reproduces my bug. It involves objcopy:

And ignoring a rather important warning message from the linker:


unknown architecture of input file `empty.o' is incompatible with arm
output

But nevertheless the linker should not seg fault, so I have created a patch to fix the problem.


Could you do me a couple of favours please ?

1. Could you try out the attached patch and make sure that it works for you with your original test case.

2. Please could you create a bugzilla entry for this so that we have somewhere to record this bug, how to reproduce it and how it was fixed.

Cheers
  Nick


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;
  }
  

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