From e549b1d2a3c79f49a487a26aa806b4241f329ee2 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 13 Mar 1997 02:41:44 +0000 Subject: [PATCH] * elflink.h (elf_link_add_object_symbols): Use extsymoff when setting ever. Sanity check the version number. Sort out copying flags and other information when adding an indirect symbol. (NAME(bfd_elf,size_dynamic_sections)): Preserve any dynamic symbols added by the backend. Clear the entire contents of the versym section. (elf_export_symbol): Ignore indirect symbols. (elf_link_output_extsym): Accept a section without an owner in an assert. * elfcode.h (elf_slurp_symbol_table): Add a sanity check on the version count. Correct the allocation of x_versymp. --- bfd/ChangeLog | 42 ++++++++++++++ bfd/elfcode.h | 90 +++++++++++++++++++++++++++-- bfd/elflink.h | 180 +++++++++++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 274 insertions(+), 38 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 295938b..7b21291 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,45 @@ +Wed Mar 12 21:36:05 1997 Ian Lance Taylor + + * elflink.h (elf_link_add_object_symbols): Use extsymoff when + setting ever. Sanity check the version number. Sort out copying + flags and other information when adding an indirect symbol. + (NAME(bfd_elf,size_dynamic_sections)): Preserve any dynamic + symbols added by the backend. Clear the entire contents of the + versym section. + (elf_export_symbol): Ignore indirect symbols. + (elf_link_output_extsym): Accept a section without an owner in an + assert. + * elfcode.h (elf_slurp_symbol_table): Add a sanity check on the + version count. Correct the allocation of x_versymp. + + * elf32-mips.c (mips_elf_add_symbol_hook): Don't set the owner of + the magic sections used for SHN_MIPS_TEXT and SHN_MIPS_DATA. + Don't return bfd_und_section_ptr when info->shared. + (mips_elf_final_link): Set the alignment of .rtproc to 4, not 12. + (mips_elf_create_dynamic_sections): Correct type: ^= for &=. + (mips_elf_check_relocs): Resolve an indirect symbol in + sym_hashes. + (mips_elf_finish_dynamic_symbol): Don't change SHN_ABS into + SHN_MIPS_TEXT or SHN_MIPS_DATA. + + * elf.c (bfd_elf_print_symbol): Tweak version output slightly. + +Tue Mar 11 01:38:36 1997 Ian Lance Taylor + + From Eric Youngdale : + * elf-bfd.h (ELF_LINK_FORCED_LOCAL): Define. + * elf.c (bfd_elf_print_symbol): Correct errors in last change. + * elflink.h (elf_link_add_object_symbols): Handle cases in which a + versioned symbol appears in both a regular and a shared object. + (elf_link_assign_sym_version): Set ELF_LINK_FORCED_LOCAL when + appropriate. Improve error message. + (struct elf_outext_info): Rename from elf_finfo_failed. Change + all uses. Add localsyms field. + (elf_bfd_final_link): When generating a shared library, call + elf_link_output_extsym to output all local symbols. + (elf_link_output_extsym): Handle symbols which were forced to + become local. + Sun Mar 9 23:08:49 1997 Ian Lance Taylor From Eric Youngdale : diff --git a/bfd/elfcode.h b/bfd/elfcode.h index 87e02f2..1320601 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -1,5 +1,5 @@ /* ELF executable support for BFD. - Copyright 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + Copyright 1991, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. Written by Fred Fish @ Cygnus Support, from information published in "UNIX System V Release 4, Programmers Guide: ANSI C and @@ -68,6 +68,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "bfdlink.h" #include "libbfd.h" #include "elf-bfd.h" +#include "fnmatch.h" /* Renaming structures, typedefs, macros and functions to be size-specific. */ #define Elf_External_Ehdr NAME(Elf,External_Ehdr) @@ -455,6 +456,7 @@ elf_object_p (abfd) struct elf_backend_data *ebd; struct elf_obj_tdata *preserved_tdata = elf_tdata (abfd); struct elf_obj_tdata *new_tdata = NULL; + asection *s; /* Read in the ELF header in external format. */ @@ -658,6 +660,25 @@ elf_object_p (abfd) goto got_wrong_format_error; } + /* If we have created any reloc sections that are associated with + debugging sections, mark the reloc sections as debugging as well. */ + for (s = abfd->sections; s != NULL; s = s->next) + { + if ((elf_section_data (s)->this_hdr.sh_type == SHT_REL + || elf_section_data (s)->this_hdr.sh_type == SHT_RELA) + && elf_section_data (s)->this_hdr.sh_info > 0) + { + unsigned long targ_index; + asection *targ_sec; + + targ_index = elf_section_data (s)->this_hdr.sh_info; + targ_sec = bfd_section_from_elf_index (abfd, targ_index); + if (targ_sec != NULL + && (targ_sec->flags & SEC_DEBUGGING) != 0) + s->flags |= SEC_DEBUGGING; + } + } + return (abfd->xvec); got_wrong_format_error: @@ -902,11 +923,13 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) boolean dynamic; { Elf_Internal_Shdr *hdr; + Elf_Internal_Shdr *verhdr; long symcount; /* Number of external ELF symbols */ elf_symbol_type *sym; /* Pointer to current bfd symbol */ elf_symbol_type *symbase; /* Buffer for generated bfd symbols */ Elf_Internal_Sym i_sym; Elf_External_Sym *x_symp = NULL; + Elf_External_Versym *x_versymp = NULL; /* Read each raw ELF symbol, converting from external ELF form to internal ELF form, and then using the information to create a @@ -918,10 +941,25 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) space left over at the end. When we have all the symbols, we build the caller's pointer vector. */ - if (dynamic) - hdr = &elf_tdata (abfd)->dynsymtab_hdr; + if (! dynamic) + { + hdr = &elf_tdata (abfd)->symtab_hdr; + verhdr = NULL; + } else - hdr = &elf_tdata (abfd)->symtab_hdr; + { + hdr = &elf_tdata (abfd)->dynsymtab_hdr; + verhdr = &elf_tdata (abfd)->dynversym_hdr; + if ((elf_tdata (abfd)->dynverdef_section != 0 + && elf_tdata (abfd)->verdef == NULL) + || (elf_tdata (abfd)->dynverref_section != 0 + && elf_tdata (abfd)->verref == NULL)) + { + if (! _bfd_elf_slurp_version_tables (abfd)) + return -1; + } + } + if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) == -1) return -1; @@ -951,6 +989,38 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) if (bfd_read ((PTR) x_symp, sizeof (Elf_External_Sym), symcount, abfd) != symcount * sizeof (Elf_External_Sym)) goto error_return; + + /* Read the raw ELF version symbol information. */ + + if (elf_dynversym (abfd) != 0 + && verhdr != NULL + && verhdr->sh_size / sizeof (Elf_External_Versym) != symcount) + { + (*_bfd_error_handler) + ("%s: version count (%ld) does not match symbol count (%ld)", + abfd->filename, + (long) (verhdr->sh_size / sizeof (Elf_External_Versym)), + symcount); + + /* Slurp in the symbols without the version information, + since that is more helpful than just quitting. */ + verhdr = NULL; + } + + if (verhdr != NULL) + { + if (bfd_seek (abfd, verhdr->sh_offset, SEEK_SET) != 0) + goto error_return; + + x_versymp = (Elf_External_Versym *) bfd_malloc (verhdr->sh_size); + if (x_versymp == NULL && symcount != 0) + goto error_return; + + if (bfd_read ((PTR) x_versymp, 1, verhdr->sh_size, abfd) + != verhdr->sh_size) + goto error_return; + } + /* Skip first symbol, which is a null dummy. */ for (i = 1; i < symcount; i++) { @@ -1035,6 +1105,14 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) if (dynamic) sym->symbol.flags |= BSF_DYNAMIC; + if (x_versymp != NULL) + { + Elf_Internal_Versym iversym; + + _bfd_elf_swap_versym_in (abfd, x_versymp + i, &iversym); + sym->version = iversym.vs_vers; + } + /* Do some backend-specific processing on this symbol. */ { struct elf_backend_data *ebd = get_elf_backend_data (abfd); @@ -1071,10 +1149,14 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic) *symptrs = 0; /* Final null pointer */ } + if (x_versymp != NULL) + free (x_versymp); if (x_symp != NULL) free (x_symp); return symcount; error_return: + if (x_versymp != NULL) + free (x_versymp); if (x_symp != NULL) free (x_symp); return -1; diff --git a/bfd/elflink.h b/bfd/elflink.h index 28df37e..b6a5d58 100644 --- a/bfd/elflink.h +++ b/bfd/elflink.h @@ -679,7 +679,7 @@ elf_link_add_object_symbols (abfd, info) weaks = NULL; - ever = extversym != NULL ? extversym + hdr->sh_info : NULL; + ever = extversym != NULL ? extversym + extsymoff : NULL; esymend = buf + extsymcount; for (esym = buf; esym < esymend; @@ -805,7 +805,16 @@ elf_link_add_object_symbols (abfd, info) int namelen, newlen; char *newname, *p; - if (vernum > 1) + if (vernum > elf_tdata (abfd)->dynverdef_hdr.sh_info) + { + (*_bfd_error_handler) + ("%s: %s: invalid version %d (max %d)", + abfd->filename, name, vernum, + elf_tdata (abfd)->dynverdef_hdr.sh_info); + bfd_set_error (bfd_error_bad_value); + goto error_return; + } + else if (vernum > 1) verstr = elf_tdata (abfd)->verdef[vernum - 1].vd_nodename; else verstr = ""; @@ -1128,15 +1137,64 @@ elf_link_add_object_symbols (abfd, info) if (hi->root.type == bfd_link_hash_indirect) { hi->elf_link_hash_flags &= ~ ELF_LINK_NON_ELF; - if (dynamic) - hi->elf_link_hash_flags |= - ELF_LINK_HASH_DEF_DYNAMIC; - /* We don't set DEF_REGULAR because we don't - the symbol to get exported even if we are - exporting all defined symbols. FIXME: - What a hack. */ - /* FIXME: Do we need to copy any flags from - H to HI? */ + + /* If the symbol became indirect, then we + assume that we have not seen a definition + before. */ + BFD_ASSERT ((hi->elf_link_hash_flags + & (ELF_LINK_HASH_DEF_DYNAMIC + | ELF_LINK_HASH_DEF_REGULAR)) + == 0); + + /* Copy down any references that we may have + already seen to the symbol which just + became indirect. */ + h->elf_link_hash_flags |= + (hi->elf_link_hash_flags + & (ELF_LINK_HASH_REF_DYNAMIC + | ELF_LINK_HASH_REF_REGULAR)); + + /* Copy over the global table offset entry. + This may have been already set up by a + check_relocs routine. */ + if (h->got_offset == (bfd_vma) -1) + { + h->got_offset = hi->got_offset; + hi->got_offset = (bfd_vma) -1; + } + BFD_ASSERT (hi->got_offset == (bfd_vma) -1); + + if (h->dynindx == -1) + { + h->dynindx = hi->dynindx; + h->dynstr_index = hi->dynstr_index; + hi->dynindx = -1; + hi->dynstr_index = 0; + } + BFD_ASSERT (hi->dynindx == -1); + + /* FIXME: There may be other information to + copy over for particular targets. */ + + /* See if the new flags lead us to realize + that the symbol must be dynamic. */ + if (! dynsym) + { + if (! dynamic) + { + if (info->shared + || ((hi->elf_link_hash_flags + & ELF_LINK_HASH_REF_DYNAMIC) + != 0)) + dynsym = true; + } + else + { + if ((hi->elf_link_hash_flags + & ELF_LINK_HASH_REF_REGULAR) != 0) + dynsym = true; + } + } } } @@ -1211,15 +1269,64 @@ elf_link_add_object_symbols (abfd, info) if (hi->root.type == bfd_link_hash_indirect) { hi->elf_link_hash_flags &= ~ ELF_LINK_NON_ELF; - if (dynamic) - hi->elf_link_hash_flags |= - ELF_LINK_HASH_DEF_DYNAMIC; - /* We don't set DEF_REGULAR because we don't - the symbol to get exported even if we are - exporting all defined symbols. FIXME: - What a hack. */ - /* FIXME: Do we need to copy any flags from - H to HI? */ + + /* If the symbol became indirect, then we + assume that we have not seen a definition + before. */ + BFD_ASSERT ((hi->elf_link_hash_flags + & (ELF_LINK_HASH_DEF_DYNAMIC + | ELF_LINK_HASH_DEF_REGULAR)) + == 0); + + /* Copy down any references that we may have + already seen to the symbol which just + became indirect. */ + h->elf_link_hash_flags |= + (hi->elf_link_hash_flags + & (ELF_LINK_HASH_REF_DYNAMIC + | ELF_LINK_HASH_REF_REGULAR)); + + /* Copy over the global table offset entry. + This may have been already set up by a + check_relocs routine. */ + if (h->got_offset == (bfd_vma) -1) + { + h->got_offset = hi->got_offset; + hi->got_offset = (bfd_vma) -1; + } + BFD_ASSERT (hi->got_offset == (bfd_vma) -1); + + if (h->dynindx == -1) + { + h->dynindx = hi->dynindx; + h->dynstr_index = hi->dynstr_index; + hi->dynindx = -1; + hi->dynstr_index = 0; + } + BFD_ASSERT (hi->dynindx == -1); + + /* FIXME: There may be other information to + copy over for particular targets. */ + + /* See if the new flags lead us to realize + that the symbol must be dynamic. */ + if (! dynsym) + { + if (! dynamic) + { + if (info->shared + || ((hi->elf_link_hash_flags + & ELF_LINK_HASH_REF_DYNAMIC) + != 0)) + dynsym = true; + } + else + { + if ((hi->elf_link_hash_flags + & ELF_LINK_HASH_REF_REGULAR) != 0) + dynsym = true; + } + } } } } @@ -1818,6 +1925,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, bfd_size_type soname_indx; bfd *dynobj; struct elf_backend_data *bed; + bfd_size_type old_dynsymcount; *sinterpptr = NULL; @@ -1959,6 +2067,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, /* The backend must work out the sizes of all the other dynamic sections. */ + old_dynsymcount = elf_hash_table (info)->dynsymcount; if (! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info)) return false; @@ -2018,11 +2127,15 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, if (sinfo.removed_dynamic) { /* Some dynamic symbols were changed to be local - symbols. In this case, we renumber all of the - dynamic symbols, so that we don't have a hole. - FIXME: The names of the removed symbols will still be - in the dynamic string table, wasting space. */ - elf_hash_table (info)->dynsymcount = 1; + symbols. In this case, we renumber all of the + dynamic symbols, so that we don't have a hole. If + the backend changed dynsymcount, then assume that the + new symbols are at the start. This is the case on + the MIPS. FIXME: The names of the removed symbols + will still be in the dynamic string table, wasting + space. */ + elf_hash_table (info)->dynsymcount = + 1 + (elf_hash_table (info)->dynsymcount - old_dynsymcount); elf_link_hash_traverse (elf_hash_table (info), elf_link_renumber_dynsyms, (PTR) info); @@ -2307,17 +2420,11 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, } else { - Elf_Internal_Versym intversym; - s->_raw_size = dynsymcount * sizeof (Elf_External_Versym); - s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size); + s->contents = (bfd_byte *) bfd_zalloc (output_bfd, s->_raw_size); if (s->contents == NULL) return false; - intversym.vs_vers = 0; - _bfd_elf_swap_versym_out (output_bfd, &intversym, - (Elf_External_Versym *) s->contents); - if (! elf_add_dynamic_entry (info, DT_VERSYM, 0)) return false; } @@ -2389,7 +2496,7 @@ elf_adjust_dynamic_symbol (h, data) bfd *dynobj; struct elf_backend_data *bed; - /* Ignore indirect symbols. There are added by the versioning code. */ + /* Ignore indirect symbols. These are added by the versioning code. */ if (h->root.type == bfd_link_hash_indirect) return true; @@ -2546,6 +2653,10 @@ elf_export_symbol (h, data) { struct elf_info_failed *eif = (struct elf_info_failed *) data; + /* Ignore indirect symbols. These are added by the versioning code. */ + if (h->root.type == bfd_link_hash_indirect) + return true; + if (h->dynindx == -1 && (h->elf_link_hash_flags & (ELF_LINK_HASH_DEF_REGULAR | ELF_LINK_HASH_REF_REGULAR)) != 0) @@ -3853,7 +3964,8 @@ elf_link_output_extsym (h, data) } else { - BFD_ASSERT ((input_sec->owner->flags & DYNAMIC) != 0); + BFD_ASSERT (input_sec->owner == NULL + || (input_sec->owner->flags & DYNAMIC) != 0); sym.st_shndx = SHN_UNDEF; input_sec = bfd_und_section_ptr; } -- 2.7.4