aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2015-12-15 14:31:25 +0100
committerJan Beulich <jbeulich@suse.com>2015-12-15 14:31:25 +0100
commit270f824531ceef276616a5d2f3027fa9f537c10b (patch)
tree3f20d74a1748d2da2516da51fa9afc63430f35e0
parent1d19cae752a7b032b8253feb4fa3b9f1dc162823 (diff)
downloadbinutils-270f824531ceef276616a5d2f3027fa9f537c10b.zip
binutils-270f824531ceef276616a5d2f3027fa9f537c10b.tar.gz
binutils-270f824531ceef276616a5d2f3027fa9f537c10b.tar.bz2
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).
-rw-r--r--bfd/ChangeLog14
-rw-r--r--bfd/coffgen.c5
-rw-r--r--bfd/cofflink.c48
-rw-r--r--bfd/libcoff-in.h4
-rw-r--r--bfd/libcoff.h4
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