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] bfd: don't produce corrupt COFF symbol table due to long ELF file name symbols


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

commit 270f824531ceef276616a5d2f3027fa9f537c10b
Author: Jan Beulich <jbeulich@novell.com>
Date:   Tue Dec 15 14:31:25 2015 +0100

    bfd: don't produce corrupt COFF symbol table due to long ELF file name symbols
    
    The re-writing logic in _bfd_coff_final_link() overwrote the ".file"
    part of the symbol table entry, due to not coping with the auxiliary
    entry generated in all cases.
    
    Note that while I would have wanted to add a test case,
    (a) I didn't spot any one testing the base functionality here, and
    (b) I wasn't able to figure out proper conditionals to use in e.g.
        ld-elf/elf.exp to check for the necessary PE/PE+ support (which
        varies by target).

Diff:
---
 bfd/ChangeLog    | 14 ++++++++++++++
 bfd/coffgen.c    |  5 ++++-
 bfd/cofflink.c   | 48 +++++++++++++++++++++++++++++++++++++++---------
 bfd/libcoff-in.h |  4 ++--
 bfd/libcoff.h    |  4 ++--
 5 files changed, 61 insertions(+), 14 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 97e9bb6..0332563 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,17 @@
+2015-12-15  Jan Beulich  <jbeulich@suse.com>
+
+	* coffgen.c (coff_write_alien_symbol): New parameter "iaux".
+	(coff_write_symbols): Pass NULL for new argument.
+	* cofflink.c (_bfd_coff_final_link): New local variables
+	"iaux".
+	Extend scope of local variables "indx" and "hash". Pass address
+	of "iaux" to coff_write_alien_symbol(). Handle ".file" and the
+	file name ending up in the string table separately. Avoid
+	setting "rewrite" on more than one path.
+	* libcoff-in.h (coff_write_alien_symbol): New parameter of type
+	"union internal_auxent *".
+	* libcoff.h: Re-generate.
+
 2015-12-15  Nick Clifton  <nickc@redhat.com>
 
 	PR 19339
diff --git a/bfd/coffgen.c b/bfd/coffgen.c
index 9257f73..f8e82f1 100644
--- a/bfd/coffgen.c
+++ b/bfd/coffgen.c
@@ -1066,6 +1066,7 @@ bfd_boolean
 coff_write_alien_symbol (bfd *abfd,
 			 asymbol *symbol,
 			 struct internal_syment *isym,
+			 union internal_auxent *iaux,
 			 bfd_vma *written,
 			 bfd_size_type *string_size_p,
 			 asection **debug_string_section_p,
@@ -1151,6 +1152,8 @@ coff_write_alien_symbol (bfd *abfd,
 			   debug_string_section_p, debug_string_size_p);
   if (isym != NULL)
     *isym = native->u.syment;
+  if (iaux != NULL && native->u.syment.n_numaux)
+    *iaux = native[1].u.auxent;
   return ret;
 }
 
@@ -1268,7 +1271,7 @@ coff_write_symbols (bfd *abfd)
       if (c_symbol == (coff_symbol_type *) NULL
 	  || c_symbol->native == (combined_entry_type *) NULL)
 	{
-	  if (!coff_write_alien_symbol (abfd, symbol, NULL, &written,
+	  if (!coff_write_alien_symbol (abfd, symbol, NULL, NULL, &written,
 					&string_size, &debug_string_section,
 					&debug_string_size))
 	    return FALSE;
diff --git a/bfd/cofflink.c b/bfd/cofflink.c
index 13d773a..16ba0ac 100644
--- a/bfd/cofflink.c
+++ b/bfd/cofflink.c
@@ -872,9 +872,10 @@ _bfd_coff_final_link (bfd *abfd,
 	      asymbol *sym = bfd_get_outsymbols (sub) [i];
 	      file_ptr pos;
 	      struct internal_syment isym;
-	      bfd_size_type string_size = 0;
+	      union internal_auxent iaux;
+	      bfd_size_type string_size = 0, indx;
 	      bfd_vma written = 0;
-	      bfd_boolean rewrite = FALSE;
+	      bfd_boolean rewrite = FALSE, hash;
 
 	      if (! (sym->flags & BSF_LOCAL)
 		  || (sym->flags & (BSF_SECTION_SYM | BSF_DEBUGGING_RELOC
@@ -900,23 +901,52 @@ _bfd_coff_final_link (bfd *abfd,
 					     * symesz;
 	      if (bfd_seek (abfd, pos, SEEK_SET) != 0)
 		goto error_return;
-	      if (! coff_write_alien_symbol(abfd, sym, &isym, &written,
+	      if (! coff_write_alien_symbol(abfd, sym, &isym, &iaux, &written,
 					    &string_size, NULL, NULL))
 		goto error_return;
 
-	      if (string_size)
+	      hash = !flaginfo.info->traditional_format;
+
+	      if (string_size >= 6 && isym.n_sclass == C_FILE
+		  && ! isym._n._n_n._n_zeroes && isym.n_numaux)
 		{
-		  bfd_boolean hash = !flaginfo.info->traditional_format;
-		  bfd_size_type indx;
+		  indx = _bfd_stringtab_add (flaginfo.strtab, ".file", hash,
+					     FALSE);
+		  if (indx == (bfd_size_type) -1)
+		    goto error_return;
+		  isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
+		  bfd_coff_swap_sym_out (abfd, &isym, flaginfo.outsyms);
+		  if (bfd_seek (abfd, pos, SEEK_SET) != 0
+		      || bfd_bwrite (flaginfo.outsyms, symesz,
+				     abfd) != symesz)
+		    goto error_return;
+		  string_size -= 6;
+		}
 
+	      if (string_size)
+		{
 		  indx = _bfd_stringtab_add (flaginfo.strtab,
 					     bfd_asymbol_name (sym), hash,
 					     FALSE);
 		  if (indx == (bfd_size_type) -1)
 		    goto error_return;
-		  isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
-		  bfd_coff_swap_sym_out (abfd, &isym, flaginfo.outsyms);
-		  rewrite = TRUE;
+		  if (isym.n_sclass != C_FILE)
+		    {
+		      isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
+		      bfd_coff_swap_sym_out (abfd, &isym, flaginfo.outsyms);
+		      rewrite = TRUE;
+		    }
+		  else
+		    {
+		      BFD_ASSERT (isym.n_numaux == 1);
+		      iaux.x_file.x_n.x_offset = STRING_SIZE_SIZE + indx;
+		      bfd_coff_swap_aux_out (abfd, &iaux, isym.n_type, C_FILE,
+					     0, 1, flaginfo.outsyms + symesz);
+		      if (bfd_seek (abfd, pos + symesz, SEEK_SET) != 0
+			  || bfd_bwrite (flaginfo.outsyms + symesz, symesz,
+					 abfd) != symesz)
+			goto error_return;
+		    }
 		}
 
 	      if (isym.n_sclass == C_FILE)
diff --git a/bfd/libcoff-in.h b/bfd/libcoff-in.h
index 83775c6..7e7eeef 100644
--- a/bfd/libcoff-in.h
+++ b/bfd/libcoff-in.h
@@ -312,8 +312,8 @@ extern void coff_mangle_symbols
 extern bfd_boolean coff_write_symbols
   (bfd *);
 extern bfd_boolean coff_write_alien_symbol
-  (bfd *, asymbol *, struct internal_syment *, bfd_vma *,
-   bfd_size_type *, asection **, bfd_size_type *);
+  (bfd *, asymbol *, struct internal_syment *, union internal_auxent *,
+   bfd_vma *, bfd_size_type *, asection **, bfd_size_type *);
 extern bfd_boolean coff_write_linenumbers
   (bfd *);
 extern alent *coff_get_lineno
diff --git a/bfd/libcoff.h b/bfd/libcoff.h
index 124e603..178559f 100644
--- a/bfd/libcoff.h
+++ b/bfd/libcoff.h
@@ -316,8 +316,8 @@ extern void coff_mangle_symbols
 extern bfd_boolean coff_write_symbols
   (bfd *);
 extern bfd_boolean coff_write_alien_symbol
-  (bfd *, asymbol *, struct internal_syment *, bfd_vma *,
-   bfd_size_type *, asection **, bfd_size_type *);
+  (bfd *, asymbol *, struct internal_syment *, union internal_auxent *,
+   bfd_vma *, bfd_size_type *, asection **, bfd_size_type *);
 extern bfd_boolean coff_write_linenumbers
   (bfd *);
 extern alent *coff_get_lineno


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