This is the mail archive of the binutils-cvs@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]

[binutils-gdb] Add support for files that contain multiple symbol index tables. Fixes PR 15835


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=6a40cf0c5c845683fdb82721813ebd5dd867cce5

commit 6a40cf0c5c845683fdb82721813ebd5dd867cce5
Author: Nick Clifton <nickc@redhat.com>
Date:   Wed Sep 23 17:23:58 2015 +0100

    Add support for files that contain multiple symbol index tables.  Fixes PR 15835
    
    binutils	PR binutils/15835
    	* readelf.c (struct elf_section_list): New structure.
    	(symtab_shndx_hdr): Replace with symtab_shndx_list.
    	(get_32bit_elf_symbols): Scan for a symbol index table matching
    	the symbol table in use.
    	(get_64bit_elf_symbols): Likewise.
    	(process_section_headers): Handle multiple symbol index sections.
    
    bfd	* elf-bfd.h (struct elf_section_list): New structure.
    	(struct elf_obj_tdata): Replace symtab_shndx_hdr with
    	symtab_shndx_list.  Delete symtab_shndx_section.
    	(elf_symtab_shndx): Replace macro with elf_symtab_shndx_list.
    	* elf.c (bfd_elf_get_syms): If symtab index sections are present,
    	scan them for the section that matches the provided symbol table.
    	(bfd_section_from_shdr): Record all SHT_SYMTAB_SHNDX sections.
    	(assign_section_numbers): Use the first symtab index table in the
    	list.
    	(_bfd_elf_compute_section_file_positions): Replace use of
    	symtab_shndx_hdr with use of symtab_shndx_list.
    	(find_section_in_list): New function.
    	(assign_file_postions_except_relocs): Use new function.
    	(_bfd_elf_copy_private_symbol_data): Likewise.
    	(swap_out_syms): Handle multiple symbol table index sections.
    	* elf32-m32c.c (m32c_elf_relax_section): Replace use of
    	symtab_shndx_hdr with use of symtab_shndx_list.
    	* elf32-rl78.c (rl78_elf_relax_section): Likewise.
    	* elf32-rx.c (rx_relax_section): Likewise.
    	* elf32-v850.c (v850_elf_relax_delete_bytes): Likewise.
    	* elflink.c (bfd_elf_final_link): Likewise.

Diff:
---
 bfd/ChangeLog      |  25 ++++++++
 bfd/elf-bfd.h      |  14 ++++-
 bfd/elf.c          | 173 +++++++++++++++++++++++++++++++++++++----------------
 bfd/elf32-m32c.c   |  21 +++++--
 bfd/elf32-rl78.c   |   9 ++-
 bfd/elf32-rx.c     |   9 ++-
 bfd/elf32-v850.c   |  14 ++++-
 bfd/elflink.c      |   6 +-
 binutils/ChangeLog |  10 ++++
 binutils/readelf.c | 104 ++++++++++++++++++--------------
 10 files changed, 266 insertions(+), 119 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index d63d55b..bdae109 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,28 @@
+2015-09-23  Nick Clifton  <nickc@redhat.com>
+
+	PR binutils/15835
+	* elf-bfd.h (struct elf_section_list): New structure.
+	(struct elf_obj_tdata): Replace symtab_shndx_hdr with
+	symtab_shndx_list.  Delete symtab_shndx_section.
+	(elf_symtab_shndx): Replace macro with elf_symtab_shndx_list.
+	* elf.c (bfd_elf_get_syms): If symtab index sections are present,
+	scan them for the section that matches the provided symbol table.
+	(bfd_section_from_shdr): Record all SHT_SYMTAB_SHNDX sections.
+	(assign_section_numbers): Use the first symtab index table in the
+	list.
+	(_bfd_elf_compute_section_file_positions): Replace use of
+	symtab_shndx_hdr with use of symtab_shndx_list.
+	(find_section_in_list): New function.
+	(assign_file_postions_except_relocs): Use new function.
+	(_bfd_elf_copy_private_symbol_data): Likewise.
+	(swap_out_syms): Handle multiple symbol table index sections.
+	* elf32-m32c.c (m32c_elf_relax_section): Replace use of
+	symtab_shndx_hdr with use of symtab_shndx_list.
+	* elf32-rl78.c (rl78_elf_relax_section): Likewise.
+	* elf32-rx.c (rx_relax_section): Likewise.
+	* elf32-v850.c (v850_elf_relax_delete_bytes): Likewise.
+	* elflink.c (bfd_elf_final_link): Likewise.
+
 2015-09-21  H.J. Lu  <hongjiu.lu@intel.com>
 
 	* bfd.c (bfd_update_compression_header): Use bfd_put_32 on
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index e0e372f..b7ca2d0 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -1654,6 +1654,14 @@ enum elf_gnu_symbols
     elf_gnu_symbol_all = (elf_gnu_symbol_ifunc | elf_gnu_symbol_unique)
   };
 
+typedef struct elf_section_list
+{
+  Elf_Internal_Shdr          hdr;
+  unsigned int               ndx;
+  struct elf_section_list *  next;
+} elf_section_list;
+  
+    
 /* Some private data is stashed away for future use using the tdata pointer
    in the bfd structure.  */
 
@@ -1670,7 +1678,7 @@ struct elf_obj_tdata
   Elf_Internal_Shdr dynversym_hdr;
   Elf_Internal_Shdr dynverref_hdr;
   Elf_Internal_Shdr dynverdef_hdr;
-  Elf_Internal_Shdr symtab_shndx_hdr;
+  elf_section_list * symtab_shndx_list;
   bfd_vma gp;				/* The gp value */
   unsigned int gp_size;			/* The gp size */
   unsigned int num_elf_sections;	/* elf_sect_ptr size */
@@ -1745,7 +1753,7 @@ struct elf_obj_tdata
   Elf_Internal_Shdr **group_sect_ptr;
   int num_group;
 
-  unsigned int symtab_section, symtab_shndx_section, dynsymtab_section;
+  unsigned int symtab_section, dynsymtab_section;
   unsigned int dynversym_section, dynverdef_section, dynverref_section;
 
   /* An identifier used to distinguish different target
@@ -1787,7 +1795,7 @@ struct elf_obj_tdata
 #define elf_stack_flags(bfd)	(elf_tdata(bfd) -> o->stack_flags)
 #define elf_shstrtab(bfd)	(elf_tdata(bfd) -> o->strtab_ptr)
 #define elf_onesymtab(bfd)	(elf_tdata(bfd) -> symtab_section)
-#define elf_symtab_shndx(bfd)	(elf_tdata(bfd) -> symtab_shndx_section)
+#define elf_symtab_shndx_list(bfd)	(elf_tdata(bfd) -> symtab_shndx_list)
 #define elf_strtab_sec(bfd)	(elf_tdata(bfd) -> o->strtab_section)
 #define elf_shstrtab_sec(bfd)	(elf_tdata(bfd) -> o->shstrtab_section)
 #define elf_symtab_hdr(bfd)	(elf_tdata(bfd) -> symtab_hdr)
diff --git a/bfd/elf.c b/bfd/elf.c
index 35c0f6c..6c878bd 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -400,8 +400,28 @@ bfd_elf_get_elf_syms (bfd *ibfd,
 
   /* Normal syms might have section extension entries.  */
   shndx_hdr = NULL;
-  if (symtab_hdr == &elf_tdata (ibfd)->symtab_hdr)
-    shndx_hdr = &elf_tdata (ibfd)->symtab_shndx_hdr;
+  if (elf_symtab_shndx_list (ibfd) != NULL)
+    {
+      elf_section_list * entry;
+      Elf_Internal_Shdr **sections = elf_elfsections (ibfd);
+
+      /* Find an index section that is linked to this symtab section.  */
+      for (entry = elf_symtab_shndx_list (ibfd); entry != NULL; entry = entry->next)
+	if (sections[entry->hdr.sh_link] == symtab_hdr)
+	  {
+	    shndx_hdr = & entry->hdr;
+	    break;
+	  };
+
+      if (shndx_hdr == NULL)
+	{
+	  if (symtab_hdr == & elf_symtab_hdr (ibfd))
+	    /* Not really accurate, but this was how the old code used to work.  */
+	    shndx_hdr = & elf_symtab_shndx_list (ibfd)->hdr;
+	  /* Otherwise we do nothing.  The assumption is that
+	     the index table will not be needed.  */
+	}
+    }
 
   /* Read the symbols.  */
   alloc_ext = NULL;
@@ -1843,8 +1863,8 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
 	  goto success;
 	}
       elf_onesymtab (abfd) = shindex;
-      elf_tdata (abfd)->symtab_hdr = *hdr;
-      elf_elfsections (abfd)[shindex] = hdr = &elf_tdata (abfd)->symtab_hdr;
+      elf_symtab_hdr (abfd) = *hdr;
+      elf_elfsections (abfd)[shindex] = hdr = & elf_symtab_hdr (abfd);
       abfd->flags |= HAS_SYMS;
 
       /* Sometimes a shared object will map in the symbol table.  If
@@ -1862,30 +1882,39 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
       /* Go looking for SHT_SYMTAB_SHNDX too, since if there is one we
 	 can't read symbols without that section loaded as well.  It
 	 is most likely specified by the next section header.  */
-      if (elf_elfsections (abfd)[elf_symtab_shndx (abfd)]->sh_link != shindex)
-	{
-	  unsigned int i, num_sec;
+      {
+	elf_section_list * entry;
+	unsigned int i, num_sec;
 
-	  num_sec = elf_numsections (abfd);
-	  for (i = shindex + 1; i < num_sec; i++)
+	for (entry = elf_symtab_shndx_list (abfd); entry != NULL; entry = entry->next)
+	  if (entry->hdr.sh_link == shindex)
+	    goto success;
+
+	num_sec = elf_numsections (abfd);
+	for (i = shindex + 1; i < num_sec; i++)
+	  {
+	    Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i];
+
+	    if (hdr2->sh_type == SHT_SYMTAB_SHNDX
+		&& hdr2->sh_link == shindex)
+	      break;
+	  }
+
+	if (i == num_sec)
+	  for (i = 1; i < shindex; i++)
 	    {
 	      Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i];
+
 	      if (hdr2->sh_type == SHT_SYMTAB_SHNDX
 		  && hdr2->sh_link == shindex)
 		break;
 	    }
-	  if (i == num_sec)
-	    for (i = 1; i < shindex; i++)
-	      {
-		Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i];
-		if (hdr2->sh_type == SHT_SYMTAB_SHNDX
-		    && hdr2->sh_link == shindex)
-		  break;
-	      }
-	  if (i != shindex)
-	    ret = bfd_section_from_shdr (abfd, i);
-	}
-      goto success;
+
+	if (i != shindex)
+	  ret = bfd_section_from_shdr (abfd, i);
+	/* else FIXME: we have failed to find the symbol table - should we issue an error ? */
+	goto success;
+      }
 
     case SHT_DYNSYM:		/* A dynamic symbol table.  */
       if (elf_dynsymtab (abfd) == shindex)
@@ -1926,14 +1955,23 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
       goto success;
 
     case SHT_SYMTAB_SHNDX:	/* Symbol section indices when >64k sections.  */
-      if (elf_symtab_shndx (abfd) == shindex)
-	goto success;
+      {
+	elf_section_list * entry;
 
-      BFD_ASSERT (elf_symtab_shndx (abfd) == 0);
-      elf_symtab_shndx (abfd) = shindex;
-      elf_tdata (abfd)->symtab_shndx_hdr = *hdr;
-      elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->symtab_shndx_hdr;
-      goto success;
+	for (entry = elf_symtab_shndx_list (abfd); entry != NULL; entry = entry->next)
+	  if (entry->ndx == shindex)
+	    goto success;
+	
+	entry = bfd_alloc (abfd, sizeof * entry);
+	if (entry == NULL)
+	  goto fail;
+	entry->ndx = shindex;
+	entry->hdr = * hdr;
+	entry->next = elf_symtab_shndx_list (abfd);
+	elf_symtab_shndx_list (abfd) = entry;
+	elf_elfsections (abfd)[shindex] = & entry->hdr;
+	goto success;
+      }
 
     case SHT_STRTAB:		/* A string table.  */
       if (hdr->bfd_section != NULL)
@@ -3377,11 +3415,17 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
       _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->symtab_hdr.sh_name);
       if (section_number > ((SHN_LORESERVE - 2) & 0xFFFF))
 	{
-	  elf_symtab_shndx (abfd) = section_number++;
-	  t->symtab_shndx_hdr.sh_name
+	  elf_section_list * entry;
+
+	  BFD_ASSERT (elf_symtab_shndx_list (abfd) == NULL);
+
+	  entry = bfd_zalloc (abfd, sizeof * entry);
+	  entry->ndx = section_number++;
+	  elf_symtab_shndx_list (abfd) = entry;
+	  entry->hdr.sh_name
 	    = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd),
 						  ".symtab_shndx", FALSE);
-	  if (t->symtab_shndx_hdr.sh_name == (unsigned int) -1)
+	  if (entry->hdr.sh_name == (unsigned int) -1)
 	    return FALSE;
 	}
       elf_strtab_sec (abfd) = section_number++;
@@ -3421,8 +3465,10 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
       i_shdrp[elf_onesymtab (abfd)] = &t->symtab_hdr;
       if (elf_numsections (abfd) > (SHN_LORESERVE & 0xFFFF))
 	{
-	  i_shdrp[elf_symtab_shndx (abfd)] = &t->symtab_shndx_hdr;
-	  t->symtab_shndx_hdr.sh_link = elf_onesymtab (abfd);
+	  elf_section_list * entry = elf_symtab_shndx_list (abfd);
+	  BFD_ASSERT (entry != NULL);
+	  i_shdrp[entry->ndx] = & entry->hdr;
+	  entry->hdr.sh_link = elf_onesymtab (abfd);
 	}
       i_shdrp[elf_strtab_sec (abfd)] = &t->strtab_hdr;
       t->symtab_hdr.sh_link = elf_strtab_sec (abfd);
@@ -3883,12 +3929,16 @@ _bfd_elf_compute_section_file_positions (bfd *abfd,
 
       off = elf_next_file_pos (abfd);
 
-      hdr = &elf_tdata (abfd)->symtab_hdr;
+      hdr = & elf_symtab_hdr (abfd);
       off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
 
-      hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
-      if (hdr->sh_size != 0)
-	off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
+      if (elf_symtab_shndx_list (abfd) != NULL)
+	{
+	  hdr = & elf_symtab_shndx_list (abfd)->hdr;
+	  if (hdr->sh_size != 0)
+	    off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
+	  /* FIXME: What about other symtab_shndx sections in the list ?  */
+	}
 
       hdr = &elf_tdata (abfd)->strtab_hdr;
       off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
@@ -5286,7 +5336,8 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
 		   && (hdr->bfd_section->flags & SEC_ELF_COMPRESS))
 		   /* Compress DWARF debug sections.  */
 	       || hdr == i_shdrpp[elf_onesymtab (abfd)]
-	       || hdr == i_shdrpp[elf_symtab_shndx (abfd)]
+	       || (elf_symtab_shndx_list (abfd) != NULL
+		   && hdr == i_shdrpp[elf_symtab_shndx_list (abfd)->ndx])
 	       || hdr == i_shdrpp[elf_strtab_sec (abfd)]
 	       || hdr == i_shdrpp[elf_shstrtab_sec (abfd)])
 	hdr->sh_offset = -1;
@@ -5492,6 +5543,15 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
   return TRUE;
 }
 
+static elf_section_list *
+find_section_in_list (unsigned int i, elf_section_list * list)
+{
+  for (;list != NULL; list = list->next)
+    if (list->ndx == i)
+      break;
+  return list;
+}
+
 /* Work out the file positions of all the sections.  This is called by
    _bfd_elf_compute_section_file_positions.  All the section sizes and
    VMAs must be known before this is called.
@@ -5540,7 +5600,8 @@ assign_file_positions_except_relocs (bfd *abfd,
 		  && (hdr->bfd_section->flags & SEC_ELF_COMPRESS))
 		  /* Compress DWARF debug sections.  */
 	      || i == elf_onesymtab (abfd)
-	      || i == elf_symtab_shndx (abfd)
+	      || (elf_symtab_shndx_list (abfd) != NULL
+		  && hdr == i_shdrpp[elf_symtab_shndx_list (abfd)->ndx])
 	      || i == elf_strtab_sec (abfd)
 	      || i == elf_shstrtab_sec (abfd))
 	    {
@@ -7130,7 +7191,7 @@ _bfd_elf_copy_private_symbol_data (bfd *ibfd,
 	shndx = MAP_STRTAB;
       else if (shndx == elf_shstrtab_sec (ibfd))
 	shndx = MAP_SHSTRTAB;
-      else if (shndx == elf_symtab_shndx (ibfd))
+      else if (find_section_in_list (shndx, elf_symtab_shndx_list (ibfd)))
 	shndx = MAP_SYM_SHNDX;
       osym->internal_elf_sym.st_shndx = shndx;
     }
@@ -7205,20 +7266,25 @@ error_return:
 
   outbound_shndx = NULL;
   outbound_shndx_index = 0;
-  symtab_shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
-  if (symtab_shndx_hdr->sh_name != 0)
+
+  if (elf_symtab_shndx_list (abfd))
     {
-      amt = (bfd_size_type) (1 + symcount) * sizeof (Elf_External_Sym_Shndx);
-      outbound_shndx =  (bfd_byte *)
-          bfd_zalloc2 (abfd, 1 + symcount, sizeof (Elf_External_Sym_Shndx));
-      if (outbound_shndx == NULL)
-	goto error_return;
+      symtab_shndx_hdr = & elf_symtab_shndx_list (abfd)->hdr;
+      if (symtab_shndx_hdr->sh_name != 0)
+	{
+	  amt = (bfd_size_type) (1 + symcount) * sizeof (Elf_External_Sym_Shndx);
+	  outbound_shndx =  (bfd_byte *)
+	    bfd_zalloc2 (abfd, 1 + symcount, sizeof (Elf_External_Sym_Shndx));
+	  if (outbound_shndx == NULL)
+	    goto error_return;
 
-      symtab_shndx_hdr->contents = outbound_shndx;
-      symtab_shndx_hdr->sh_type = SHT_SYMTAB_SHNDX;
-      symtab_shndx_hdr->sh_size = amt;
-      symtab_shndx_hdr->sh_addralign = sizeof (Elf_External_Sym_Shndx);
-      symtab_shndx_hdr->sh_entsize = sizeof (Elf_External_Sym_Shndx);
+	  symtab_shndx_hdr->contents = outbound_shndx;
+	  symtab_shndx_hdr->sh_type = SHT_SYMTAB_SHNDX;
+	  symtab_shndx_hdr->sh_size = amt;
+	  symtab_shndx_hdr->sh_addralign = sizeof (Elf_External_Sym_Shndx);
+	  symtab_shndx_hdr->sh_entsize = sizeof (Elf_External_Sym_Shndx);
+	}
+      /* FIXME: What about any other headers in the list ?  */
     }
 
   /* Now generate the data (for "contents").  */
@@ -7327,7 +7393,8 @@ error_return:
 		  shndx = elf_shstrtab_sec (abfd);
 		  break;
 		case MAP_SYM_SHNDX:
-		  shndx = elf_symtab_shndx (abfd);
+		  if (elf_symtab_shndx_list (abfd))
+		    shndx = elf_symtab_shndx_list (abfd)->ndx;
 		  break;
 		default:
 		  shndx = SHN_ABS;
diff --git a/bfd/elf32-m32c.c b/bfd/elf32-m32c.c
index 953f00e..b2db4f5 100644
--- a/bfd/elf32-m32c.c
+++ b/bfd/elf32-m32c.c
@@ -1473,8 +1473,11 @@ m32c_elf_relax_section
       || (sec->flags & SEC_CODE) == 0)
     return TRUE;
 
-  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
+  symtab_hdr = & elf_symtab_hdr (abfd);
+  if (elf_symtab_shndx_list (abfd))
+    shndx_hdr = & elf_symtab_shndx_list (abfd)->hdr;
+  else
+    shndx_hdr = NULL;
 
   /* Get the section contents.  */
   if (elf_section_data (sec)->this_hdr.contents != NULL)
@@ -1495,7 +1498,7 @@ m32c_elf_relax_section
       symtab_hdr->contents = (bfd_byte *) intsyms;
     }
 
-  if (shndx_hdr->sh_size != 0)
+  if (shndx_hdr && shndx_hdr->sh_size != 0)
     {
       bfd_size_type amt;
 
@@ -2043,8 +2046,16 @@ m32c_elf_relax_delete_bytes
   isymend = isym + symtab_hdr->sh_info;
 
   sec_shndx  = _bfd_elf_section_from_bfd_section (abfd, sec);
-  shndx_hdr  = & elf_tdata (abfd)->symtab_shndx_hdr;
-  shndx_buf  = (Elf_External_Sym_Shndx *) shndx_hdr->contents;
+  if (elf_symtab_shndx_list (abfd))
+    {
+      shndx_hdr = & elf_symtab_shndx_list (abfd)->hdr;
+      shndx_buf  = (Elf_External_Sym_Shndx *) shndx_hdr->contents;
+    }
+  else
+    {
+      shndx_hdr = NULL;
+      shndx_buf = NULL;
+    }
   shndx = shndx_buf;
 
   for (; isym < isymend; isym++, shndx = (shndx ? shndx + 1 : NULL))
diff --git a/bfd/elf32-rl78.c b/bfd/elf32-rl78.c
index 8cddb58..723cb4b 100644
--- a/bfd/elf32-rl78.c
+++ b/bfd/elf32-rl78.c
@@ -2094,8 +2094,11 @@ rl78_elf_relax_section
       || (sec->flags & SEC_CODE) == 0)
     return TRUE;
 
-  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
+  symtab_hdr = & elf_symtab_hdr (abfd);
+  if (elf_symtab_shndx_list (abfd))
+    shndx_hdr = & elf_symtab_shndx_list (abfd)->hdr;
+  else
+    shndx_hdr = NULL;
 
   /* Get the section contents.  */
   if (elf_section_data (sec)->this_hdr.contents != NULL)
@@ -2118,7 +2121,7 @@ rl78_elf_relax_section
       symtab_hdr->contents = (bfd_byte *) intsyms;
     }
 
-  if (shndx_hdr->sh_size != 0)
+  if (shndx_hdr && shndx_hdr->sh_size != 0)
     {
       bfd_size_type amt;
 
diff --git a/bfd/elf32-rx.c b/bfd/elf32-rx.c
index df765ae..c58c184 100644
--- a/bfd/elf32-rx.c
+++ b/bfd/elf32-rx.c
@@ -2009,8 +2009,11 @@ elf32_rx_relax_section (bfd *                  abfd,
       || (sec->flags & SEC_CODE) == 0)
     return TRUE;
 
-  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
+  symtab_hdr = & elf_symtab_hdr (abfd);
+  if (elf_symtab_shndx_list (abfd))
+    shndx_hdr = & elf_symtab_shndx_list (abfd)->hdr;
+  else
+    shndx_hdr = NULL;
 
   sec_start = sec->output_section->vma + sec->output_offset;
 
@@ -2035,7 +2038,7 @@ elf32_rx_relax_section (bfd *                  abfd,
       symtab_hdr->contents = (bfd_byte *) intsyms;
     }
 
-  if (shndx_hdr->sh_size != 0)
+  if (shndx_hdr && shndx_hdr->sh_size != 0)
     {
       bfd_size_type amt;
 
diff --git a/bfd/elf32-v850.c b/bfd/elf32-v850.c
index 859afd2..c6a6d2f 100644
--- a/bfd/elf32-v850.c
+++ b/bfd/elf32-v850.c
@@ -3205,7 +3205,6 @@ v850_elf_relax_delete_bytes (bfd *abfd,
   Elf_Internal_Rela *irel;
   Elf_Internal_Rela *irelend;
   struct elf_link_hash_entry *sym_hash;
-  Elf_Internal_Shdr *shndx_hdr;
   Elf_External_Sym_Shndx *shndx;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
@@ -3230,8 +3229,17 @@ v850_elf_relax_delete_bytes (bfd *abfd,
   /* Adjust all the relocs.  */
   irel = elf_section_data (sec)->relocs;
   irelend = irel + sec->reloc_count;
-  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
-  shndx = (Elf_External_Sym_Shndx *) shndx_hdr->contents;
+  if (elf_symtab_shndx_list (abfd))
+    {
+      Elf_Internal_Shdr *shndx_hdr;
+
+      shndx_hdr = & elf_symtab_shndx_list (abfd)->hdr;
+      shndx = (Elf_External_Sym_Shndx *) shndx_hdr->contents;
+    }
+  else
+    {
+      shndx = NULL;
+    }
 
   for (; irel < irelend; irel++)
     {
diff --git a/bfd/elflink.c b/bfd/elflink.c
index aec96e5..ff7ae73 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -11032,7 +11032,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 		    max_sym_count = sym_count;
 
 		  if (sym_count > max_sym_shndx_count
-		      && elf_symtab_shndx (sec->owner) != 0)
+		      && elf_symtab_shndx_list (sec->owner) != NULL)
 		    max_sym_shndx_count = sym_count;
 
 		  if ((sec->flags & SEC_RELOC) != 0)
@@ -11562,8 +11562,8 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
       Elf_Internal_Shdr *symstrtab_hdr;
       file_ptr off = symtab_hdr->sh_offset + symtab_hdr->sh_size;
 
-      symtab_shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
-      if (symtab_shndx_hdr->sh_name != 0)
+      symtab_shndx_hdr = & elf_symtab_shndx_list (abfd)->hdr;
+      if (symtab_shndx_hdr != NULL && symtab_shndx_hdr->sh_name != 0)
 	{
 	  symtab_shndx_hdr->sh_type = SHT_SYMTAB_SHNDX;
 	  symtab_shndx_hdr->sh_entsize = sizeof (Elf_External_Sym_Shndx);
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 13f2166..be987ec 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,13 @@
+2015-09-23  Nick Clifton  <nickc@redhat.com>
+
+	PR binutils/15835
+	* readelf.c (struct elf_section_list): New structure.
+	(symtab_shndx_hdr): Replace with symtab_shndx_list.
+	(get_32bit_elf_symbols): Scan for a symbol index table matching
+	the symbol table in use.
+	(get_64bit_elf_symbols): Likewise.
+	(process_section_headers): Handle multiple symbol index sections.
+
 2015-09-22  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
 	* readelf.c (process_dynamic_section): Handle DF_1_STUB, DF_1_PIE.
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 4d19e6f..bbf5b02 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -164,6 +164,12 @@
 #define offsetof(TYPE, MEMBER) ((size_t) &(((TYPE *) 0)->MEMBER))
 #endif
 
+typedef struct elf_section_list
+{
+  Elf_Internal_Shdr * hdr;
+  struct elf_section_list * next;
+} elf_section_list;
+
 char * program_name = "readelf";
 static unsigned long archive_file_offset;
 static unsigned long archive_file_size;
@@ -188,7 +194,7 @@ static Elf_Internal_Ehdr elf_header;
 static Elf_Internal_Shdr * section_headers;
 static Elf_Internal_Phdr * program_headers;
 static Elf_Internal_Dyn *  dynamic_section;
-static Elf_Internal_Shdr * symtab_shndx_hdr;
+static elf_section_list * symtab_shndx_list;
 static int show_name;
 static int do_dynamic;
 static int do_syms;
@@ -4984,27 +4990,30 @@ get_32bit_elf_symbols (FILE * file,
   if (esyms == NULL)
     goto exit_point;
 
-  shndx = NULL;
-  if (symtab_shndx_hdr != NULL
-      && (symtab_shndx_hdr->sh_link
-	  == (unsigned long) (section - section_headers)))
-    {
-      shndx = (Elf_External_Sym_Shndx *) get_data (NULL, file,
-                                                   symtab_shndx_hdr->sh_offset,
-                                                   1, symtab_shndx_hdr->sh_size,
-                                                   _("symbol table section indicies"));
-      if (shndx == NULL)
-	goto exit_point;
-      /* PR17531: file: heap-buffer-overflow */
-      else if (symtab_shndx_hdr->sh_size / sizeof (Elf_External_Sym_Shndx) < number)
-	{
-	  error (_("Index section %s has an sh_size of 0x%lx - expected 0x%lx\n"),
-		 printable_section_name (symtab_shndx_hdr),
-		 (unsigned long) symtab_shndx_hdr->sh_size,
-		 (unsigned long) section->sh_size);
-	  goto exit_point;
+  {
+    elf_section_list * entry;
+
+    shndx = NULL;
+    for (entry = symtab_shndx_list; entry != NULL; entry = entry->next)
+      if (entry->hdr->sh_link == (unsigned long) (section - section_headers))
+	{
+	  shndx = (Elf_External_Sym_Shndx *) get_data (NULL, file,
+						       entry->hdr->sh_offset,
+						       1, entry->hdr->sh_size,
+						       _("symbol table section indicies"));
+	  if (shndx == NULL)
+	    goto exit_point;
+	  /* PR17531: file: heap-buffer-overflow */
+	  else if (entry->hdr->sh_size / sizeof (Elf_External_Sym_Shndx) < number)
+	    {
+	      error (_("Index section %s has an sh_size of 0x%lx - expected 0x%lx\n"),
+		     printable_section_name (entry->hdr),
+		     (unsigned long) entry->hdr->sh_size,
+		     (unsigned long) section->sh_size);
+	      goto exit_point;
+	    }
 	}
-    }
+  }
 
   isyms = (Elf_Internal_Sym *) cmalloc (number, sizeof (Elf_Internal_Sym));
 
@@ -5094,25 +5103,30 @@ get_64bit_elf_symbols (FILE * file,
   if (!esyms)
     goto exit_point;
 
-  if (symtab_shndx_hdr != NULL
-      && (symtab_shndx_hdr->sh_link
-	  == (unsigned long) (section - section_headers)))
-    {
-      shndx = (Elf_External_Sym_Shndx *) get_data (NULL, file,
-                                                   symtab_shndx_hdr->sh_offset,
-                                                   1, symtab_shndx_hdr->sh_size,
-                                                   _("symbol table section indicies"));
-      if (shndx == NULL)
-	goto exit_point;
-      else if (symtab_shndx_hdr->sh_size / sizeof (Elf_External_Sym_Shndx) < number)
-	{
-	  error (_("Index section %s has an sh_size of 0x%lx - expected 0x%lx\n"),
-		 printable_section_name (symtab_shndx_hdr),
-		 (unsigned long) symtab_shndx_hdr->sh_size,
-		 (unsigned long) section->sh_size);
-	  goto exit_point;
+  {
+    elf_section_list * entry;
+
+    shndx = NULL;
+    for (entry = symtab_shndx_list; entry != NULL; entry = entry->next)
+      if (entry->hdr->sh_link == (unsigned long) (section - section_headers))
+	{
+	  shndx = (Elf_External_Sym_Shndx *) get_data (NULL, file,
+						       entry->hdr->sh_offset,
+						       1, entry->hdr->sh_size,
+						       _("symbol table section indicies"));
+	  if (shndx == NULL)
+	    goto exit_point;
+	  /* PR17531: file: heap-buffer-overflow */
+	  else if (entry->hdr->sh_size / sizeof (Elf_External_Sym_Shndx) < number)
+	    {
+	      error (_("Index section %s has an sh_size of 0x%lx - expected 0x%lx\n"),
+		     printable_section_name (entry->hdr),
+		     (unsigned long) entry->hdr->sh_size,
+		     (unsigned long) section->sh_size);
+	      goto exit_point;
+	    }
 	}
-    }
+  }
 
   isyms = (Elf_Internal_Sym *) cmalloc (number, sizeof (Elf_Internal_Sym));
 
@@ -5470,7 +5484,7 @@ process_section_headers (FILE * file)
   dynamic_symbols = NULL;
   dynamic_strings = NULL;
   dynamic_syminfo = NULL;
-  symtab_shndx_hdr = NULL;
+  symtab_shndx_list = NULL;
 
   eh_addr_size = is_32bit_elf ? 4 : 8;
   switch (elf_header.e_machine)
@@ -5575,12 +5589,10 @@ process_section_headers (FILE * file)
 	}
       else if (section->sh_type == SHT_SYMTAB_SHNDX)
 	{
-	  if (symtab_shndx_hdr != NULL)
-	    {
-	      error (_("File contains multiple symtab shndx tables\n"));
-	      continue;
-	    }
-	  symtab_shndx_hdr = section;
+	  elf_section_list * entry = xmalloc (sizeof * entry);
+	  entry->hdr = section;
+	  entry->next = symtab_shndx_list;
+	  symtab_shndx_list = entry;
 	}
       else if (section->sh_type == SHT_SYMTAB)
 	CHECK_ENTSIZE (section, i, Sym);


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