diff options
-rw-r--r-- | bfd/ChangeLog | 13 | ||||
-rw-r--r-- | bfd/coffgen.c | 34 | ||||
-rw-r--r-- | bfd/cofflink.c | 88 | ||||
-rw-r--r-- | bfd/libcoff-in.h | 3 | ||||
-rw-r--r-- | bfd/libcoff.h | 3 |
5 files changed, 131 insertions, 10 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index f20d7cc..d4b33c5 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,16 @@ +2011-11-02 Jan Beulich <jbeulich@suse.com> + + * coffgen.c (coff_write_alien_symbol): Make public. Add 'struct + internal_syment *' parameter. Extend 'dummy' to an array with two + elements. Set n_numaux early. Handle BSF_FILE. + (coff_write_symbols): Pass NULL as new third argument to + coff_write_alien_symbol(). + * cofflink.c (_bfd_coff_final_link): Don't use COFF-specific + obj_raw_syment_count() on non-COFF input BFD. Insert local symbols + from non-COFF input BFDs. + * libcoff-in.h (coff_write_alien_symbol): Declare. + * libcoff.h (coff_write_alien_symbol): Re-generate. + 2011-11-01 DJ Delorie <dj@redhat.com> * Makefile.am (ALL_MACHINES): Add cpu-rl78.lo. diff --git a/bfd/coffgen.c b/bfd/coffgen.c index 87a3bfa..c0505c6 100644 --- a/bfd/coffgen.c +++ b/bfd/coffgen.c @@ -983,31 +983,36 @@ coff_write_symbol (bfd *abfd, file originally. This symbol may have been created by the linker, or we may be linking a non COFF file to a COFF file. */ -static bfd_boolean +bfd_boolean coff_write_alien_symbol (bfd *abfd, asymbol *symbol, + struct internal_syment *isym, bfd_vma *written, bfd_size_type *string_size_p, asection **debug_string_section_p, bfd_size_type *debug_string_size_p) { combined_entry_type *native; - combined_entry_type dummy; + combined_entry_type dummy[2]; asection *output_section = symbol->section->output_section ? symbol->section->output_section : symbol->section; struct bfd_link_info *link_info = coff_data (abfd)->link_info; + bfd_boolean ret; if ((!link_info || link_info->strip_discarded) && !bfd_is_abs_section (symbol->section) && symbol->section->output_section == bfd_abs_section_ptr) { symbol->name = ""; + if (isym != NULL) + memset (isym, 0, sizeof(*isym)); return TRUE; } - native = &dummy; + native = dummy; native->u.syment.n_type = T_NULL; native->u.syment.n_flags = 0; + native->u.syment.n_numaux = 0; if (bfd_is_und_section (symbol->section)) { native->u.syment.n_scnum = N_UNDEF; @@ -1018,6 +1023,11 @@ coff_write_alien_symbol (bfd *abfd, native->u.syment.n_scnum = N_UNDEF; native->u.syment.n_value = symbol->value; } + else if (symbol->flags & BSF_FILE) + { + native->u.syment.n_scnum = N_DEBUG; + native->u.syment.n_numaux = 1; + } else if (symbol->flags & BSF_DEBUGGING) { /* There isn't much point to writing out a debugging symbol @@ -1025,6 +1035,8 @@ coff_write_alien_symbol (bfd *abfd, format. So, we just ignore them. We must clobber the symbol name to keep it from being put in the string table. */ symbol->name = ""; + if (isym != NULL) + memset (isym, 0, sizeof(*isym)); return TRUE; } else @@ -1045,16 +1057,20 @@ coff_write_alien_symbol (bfd *abfd, } native->u.syment.n_type = 0; - if (symbol->flags & BSF_LOCAL) + if (symbol->flags & BSF_FILE) + native->u.syment.n_sclass = C_FILE; + else if (symbol->flags & BSF_LOCAL) native->u.syment.n_sclass = C_STAT; else if (symbol->flags & BSF_WEAK) native->u.syment.n_sclass = obj_pe (abfd) ? C_NT_WEAK : C_WEAKEXT; else native->u.syment.n_sclass = C_EXT; - native->u.syment.n_numaux = 0; - return coff_write_symbol (abfd, symbol, native, written, string_size_p, - debug_string_section_p, debug_string_size_p); + ret = coff_write_symbol (abfd, symbol, native, written, string_size_p, + debug_string_section_p, debug_string_size_p); + if (isym != NULL) + *isym = native->u.syment; + return ret; } /* Write a native symbol to a COFF file. */ @@ -1170,8 +1186,8 @@ 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, &written, &string_size, - &debug_string_section, + if (!coff_write_alien_symbol (abfd, symbol, NULL, &written, + &string_size, &debug_string_section, &debug_string_size)) return FALSE; } diff --git a/bfd/cofflink.c b/bfd/cofflink.c index bca1364..1ebdfdd 100644 --- a/bfd/cofflink.c +++ b/bfd/cofflink.c @@ -866,7 +866,7 @@ _bfd_coff_final_link (bfd *abfd, size_t sz; sub->output_has_begun = FALSE; - sz = obj_raw_syment_count (sub); + sz = bfd_family_coff (sub) ? obj_raw_syment_count (sub) : 2; if (sz > max_sym_count) max_sym_count = sz; } @@ -943,6 +943,92 @@ _bfd_coff_final_link (bfd *abfd, } } + if (finfo.info->strip != strip_all && finfo.info->discard != discard_all) + { + /* Add local symbols from foreign inputs. */ + for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) + { + unsigned int i; + + if (bfd_family_coff (sub) || ! bfd_get_outsymbols (sub)) + continue; + for (i = 0; i < bfd_get_symcount (sub); ++i) + { + asymbol *sym = bfd_get_outsymbols (sub) [i]; + file_ptr pos; + struct internal_syment isym; + bfd_size_type string_size = 0; + bfd_vma written = 0; + bfd_boolean rewrite = FALSE; + + if (! (sym->flags & BSF_LOCAL) + || (sym->flags & (BSF_SECTION_SYM | BSF_DEBUGGING_RELOC + | BSF_THREAD_LOCAL | BSF_RELC | BSF_SRELC + | BSF_SYNTHETIC)) + || ((sym->flags & BSF_DEBUGGING) + && ! (sym->flags & BSF_FILE))) + continue; + + /* See if we are discarding symbols with this name. */ + if ((finfo.info->strip == strip_some + && (bfd_hash_lookup (finfo.info->keep_hash, + bfd_asymbol_name(sym), FALSE, FALSE) + == NULL)) + || (((finfo.info->discard == discard_sec_merge + && (bfd_get_section (sym)->flags & SEC_MERGE) + && ! finfo.info->relocatable) + || finfo.info->discard == discard_l) + && bfd_is_local_label_name (sub, bfd_asymbol_name(sym)))) + continue; + + pos = obj_sym_filepos (abfd) + obj_raw_syment_count (abfd) + * symesz; + if (bfd_seek (abfd, pos, SEEK_SET) != 0) + goto error_return; + if (! coff_write_alien_symbol(abfd, sym, &isym, &written, + &string_size, NULL, NULL)) + goto error_return; + + if (string_size) + { + bfd_boolean hash = ! (abfd->flags & BFD_TRADITIONAL_FORMAT); + bfd_size_type indx; + + indx = _bfd_stringtab_add (finfo.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, finfo.outsyms); + rewrite = TRUE; + } + + if (isym.n_sclass == C_FILE) + { + if (finfo.last_file_index != -1) + { + finfo.last_file.n_value = obj_raw_syment_count (abfd); + bfd_coff_swap_sym_out (abfd, &finfo.last_file, + finfo.outsyms); + pos = obj_sym_filepos (abfd) + finfo.last_file_index + * symesz; + rewrite = TRUE; + } + finfo.last_file_index = obj_raw_syment_count (abfd); + finfo.last_file = isym; + } + + if (rewrite + && (bfd_seek (abfd, pos, SEEK_SET) != 0 + || bfd_bwrite (finfo.outsyms, symesz, abfd) != symesz)) + goto error_return; + + obj_raw_syment_count (abfd) += written; + } + } + } + if (! bfd_coff_final_link_postscript (abfd, & finfo)) goto error_return; diff --git a/bfd/libcoff-in.h b/bfd/libcoff-in.h index 8bfda72..0cd8de5 100644 --- a/bfd/libcoff-in.h +++ b/bfd/libcoff-in.h @@ -318,6 +318,9 @@ extern void coff_mangle_symbols (bfd *); 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 *); extern bfd_boolean coff_write_linenumbers (bfd *); extern alent *coff_get_lineno diff --git a/bfd/libcoff.h b/bfd/libcoff.h index 958650c..8aef552 100644 --- a/bfd/libcoff.h +++ b/bfd/libcoff.h @@ -322,6 +322,9 @@ extern void coff_mangle_symbols (bfd *); 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 *); extern bfd_boolean coff_write_linenumbers (bfd *); extern alent *coff_get_lineno |