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 /bfd/cofflink.c
parentFix invalid left shift of negative value (diff)
downloadbinutils-gdb-270f824531ceef276616a5d2f3027fa9f537c10b.tar.gz
binutils-gdb-270f824531ceef276616a5d2f3027fa9f537c10b.tar.bz2
binutils-gdb-270f824531ceef276616a5d2f3027fa9f537c10b.zip
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).
Diffstat (limited to 'bfd/cofflink.c')
-rw-r--r--bfd/cofflink.c48
1 files changed, 39 insertions, 9 deletions
diff --git a/bfd/cofflink.c b/bfd/cofflink.c
index 13d773aca5b..16ba0acb103 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)