diff options
author | Jan Beulich <jbeulich@novell.com> | 2015-12-15 14:31:25 +0100 |
---|---|---|
committer | Jan Beulich <jbeulich@suse.com> | 2015-12-15 14:31:25 +0100 |
commit | 270f824531ceef276616a5d2f3027fa9f537c10b (patch) | |
tree | 3f20d74a1748d2da2516da51fa9afc63430f35e0 | |
parent | 1d19cae752a7b032b8253feb4fa3b9f1dc162823 (diff) | |
download | binutils-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/ChangeLog | 14 | ||||
-rw-r--r-- | bfd/coffgen.c | 5 | ||||
-rw-r--r-- | bfd/cofflink.c | 48 | ||||
-rw-r--r-- | bfd/libcoff-in.h | 4 | ||||
-rw-r--r-- | 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 |