From mboxrd@z Thu Jan 1 00:00:00 1970 From: Richard Henderson To: binutils@sourceware.cygnus.com Subject: Re: .dynsym pain Date: Tue, 13 Jul 1999 18:20:00 -0000 Message-id: <19990713182017.A4034@cygnus.com> References: <19990712180512.A24797@cygnus.com> <19990713033625.1347.qmail@daffy.airs.com> X-SW-Source: 1999-q3/msg00189.html On Mon, Jul 12, 1999 at 11:36:25PM -0400, Ian Lance Taylor wrote: > I assume you mean by this that dynamic relocations can refer to them. Yep. > I gather there is some reason that you can't convert the dynamic > relocations to refer to section symbols instead; presumably there is > extra information attached to the STB_LOCAL dynamic symbols somehow. Not quite -- just a bit of ABI silliness that requires r_addend to be zero for the relocations in question. > Which gets in the way of the fact that I need it to have an index, but > to be pushed out with STB_LOCAL rather than whatever it had had before. > > I'm not sure why this matters, but I agree with it. Explained in a comment I added in elf-bfd.h. > What type are you going to be put on the linked list? The pair is the unique token. I'm also keeping around the entire Elf_Internal_Sym, just because it's painful to acquire, and I didn't want to have to do it twice. > You'll then need to run through the list specially at some point; Yep. In final_link, just before we call elf_link_output_extsym. For reference, here's the patch I checked in. I've tested it against my new target and on Alpha. It also fixes a bug on x86, since we were failing to output the section symbols in shared libraries there. r~ * elf-bfd.h (struct elf_link_local_dynamic_entry): New. (struct elf_link_hash_table): Add dynlocal. (_bfd_elf_link_lookup_local_dynindx): Prototype. (_bfd_elf_link_adjust_dynindx): Delete. (_bfd_elf_link_renumber_dynsyms): Prototype. (_bfd_elf,link_record_local_dynamic_symbol): Prototype. * elfcode.h (elf_link_record_local_dynamic_symbol): New alias. * elflink.c (_bfd_elf_link_adjust_dynindx): Delete. (_bfd_elf_link_lookup_local_dynindx): New function. (elf_link_renumber_hash_table_dynsyms): New function. (_bfd_elf_link_renumber_dynsyms): New function. * elflink.h (elf_link_record_local_dynamic_symbol): New function. (struct elf_assign_sym_version_info): Delete removed_dynamic. (bfd_elf,size_dynamic_sections): Use _bfd_strip_section_from_output instead of elf_link_remove_section_and_adjust_dynindices. Remove removed_dynamic code. Use _bfd_elf_link_renumber_dynsyms. (elf_link_assign_sym_version): Remove removed_dynamic code. (elf_link_renumber_dynsyms): Delete. (elf_bfd_final_link): Install section and local symbols into .dynsym. * elf32-m68k.c (elf_m68k_adjust_dynindx): Delete. (elf_m68k_size_dynamic_sections): Don't set section dynindicies. (elf_m68k_finish_dynamic_sections): Don't write section dynsyms. * elf32-mips.c: Similarly. * elf32-ppc.c: Similarly. * elf32-sparc.c: Similarly. * elf64-alpha.c: Similarly. * elf64-sparc.c: Similarly. Index: elf-bfd.h =================================================================== RCS file: /cvs/binutils/binutils/bfd/elf-bfd.h,v retrieving revision 1.10 diff -c -p -d -r1.10 elf-bfd.h *** elf-bfd.h 1999/07/11 17:13:34 1.10 --- elf-bfd.h 1999/07/14 01:04:15 *************** struct elf_link_hash_entry *** 86,91 **** --- 86,101 ---- /* Symbol index as a dynamic symbol. Initialized to -1, and remains -1 if this is not a dynamic symbol. */ + /* ??? Note that this is consistently used as a synonym for tests + against whether we can perform various simplifying transformations + to the code. (E.g. changing a pc-relative jump to a PLT entry + into a pc-relative jump to the target function.) That test, which + is often relatively complex, and someplaces wrong or incomplete, + should really be replaced by a predicate in elflink.c. + + End result: this field -1 does not indicate that the symbol is + not in the dynamic symbol table, but rather that the symbol is + not visible outside this DSO. */ long dynindx; /* String table index in .dynstr if this is a dynamic symbol. */ *************** struct elf_link_hash_entry *** 181,186 **** --- 191,215 ---- #define ELF_LINK_HASH_MARK 04000 }; + /* Records local symbols to be emitted in the dynamic symbol table. */ + + struct elf_link_local_dynamic_entry + { + struct elf_link_local_dynamic_entry *next; + + /* The input bfd this symbol came from. */ + bfd *input_bfd; + + /* The index of the local symbol being copied. */ + long input_indx; + + /* The index in the outgoing dynamic symbol table. */ + long dynindx; + + /* A copy of the input symbol. */ + Elf_Internal_Sym isym; + }; + /* ELF linker hash table. */ struct elf_link_hash_table *************** struct elf_link_hash_table *** 209,214 **** --- 238,245 ---- struct elf_link_hash_entry *hgot; /* A pointer to information used to link stabs in sections. */ PTR stab_info; + /* A linked list of local symbols to be added to .dynsym. */ + struct elf_link_local_dynamic_entry *dynlocal; }; /* Look up an entry in an ELF linker hash table. */ *************** struct bfd_strtab_hash *_bfd_elf_stringt *** 956,961 **** --- 987,995 ---- boolean _bfd_elf_link_record_dynamic_symbol PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *)); + long + _bfd_elf_link_lookup_local_dynindx PARAMS ((struct bfd_link_info *, + bfd *, long)); boolean _bfd_elf_compute_section_file_positions PARAMS ((bfd *, struct bfd_link_info *)); *************** boolean _bfd_elf_create_dynamic_sections *** 970,977 **** struct bfd_link_info *)); boolean _bfd_elf_create_got_section PARAMS ((bfd *, struct bfd_link_info *)); ! boolean _bfd_elf_link_adjust_dynindx PARAMS ((struct elf_link_hash_entry *, ! PTR)); elf_linker_section_t *_bfd_elf_create_linker_section PARAMS ((bfd *abfd, --- 1004,1011 ---- struct bfd_link_info *)); boolean _bfd_elf_create_got_section PARAMS ((bfd *, struct bfd_link_info *)); ! unsigned long _bfd_elf_link_renumber_dynsyms PARAMS ((bfd *, ! struct bfd_link_info *)); elf_linker_section_t *_bfd_elf_create_linker_section PARAMS ((bfd *abfd, *************** extern boolean bfd_elf64_link_create_dyn *** 1113,1120 **** extern Elf_Internal_Rela *_bfd_elf64_link_read_relocs PARAMS ((bfd *, asection *, PTR, Elf_Internal_Rela *, boolean)); ! #define bfd_elf32_link_record_dynamic_symbol _bfd_elf_link_record_dynamic_symbol ! #define bfd_elf64_link_record_dynamic_symbol _bfd_elf_link_record_dynamic_symbol extern boolean _bfd_elf_close_and_cleanup PARAMS ((bfd *)); extern bfd_reloc_status_type _bfd_elf_rel_vtable_reloc_fn --- 1147,1161 ---- extern Elf_Internal_Rela *_bfd_elf64_link_read_relocs PARAMS ((bfd *, asection *, PTR, Elf_Internal_Rela *, boolean)); ! #define bfd_elf32_link_record_dynamic_symbol \ ! _bfd_elf_link_record_dynamic_symbol ! #define bfd_elf64_link_record_dynamic_symbol \ ! _bfd_elf_link_record_dynamic_symbol ! ! boolean _bfd_elf32_link_record_local_dynamic_symbol ! PARAMS ((struct bfd_link_info *, bfd *, long)); ! boolean _bfd_elf64_link_record_local_dynamic_symbol ! PARAMS ((struct bfd_link_info *, bfd *, long)); extern boolean _bfd_elf_close_and_cleanup PARAMS ((bfd *)); extern bfd_reloc_status_type _bfd_elf_rel_vtable_reloc_fn Index: elf32-m68k.c =================================================================== RCS file: /cvs/binutils/binutils/bfd/elf32-m68k.c,v retrieving revision 1.6 diff -c -p -d -r1.6 elf32-m68k.c *** elf32-m68k.c 1999/07/12 08:15:16 1.6 --- elf32-m68k.c 1999/07/14 01:04:15 *************** static boolean elf_m68k_gc_sweep_hook *** 43,50 **** const Elf_Internal_Rela *)); static boolean elf_m68k_adjust_dynamic_symbol PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *)); - static boolean elf_m68k_adjust_dynindx - PARAMS ((struct elf_link_hash_entry *, PTR)); static boolean elf_m68k_size_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); static boolean elf_m68k_relocate_section --- 43,48 ---- *************** elf_m68k_size_dynamic_sections (output_b *** 1312,1365 **** } } - /* If we are generating a shared library, we generate a section - symbol for each output section for which we might need to copy - relocs. These are local symbols, which means that they must come - first in the dynamic symbol table. That means we must increment - the dynamic symbol index of every other dynamic symbol. */ - if (info->shared) - { - int c; - - c = 0; - for (s = output_bfd->sections; s != NULL; s = s->next) - { - if ((s->flags & SEC_LINKER_CREATED) != 0 - || (s->flags & SEC_ALLOC) == 0) - continue; - - elf_section_data (s)->dynindx = c + 1; - - /* These symbols will have no names, so we don't need to - fiddle with dynstr_index. */ - - ++c; - } - - elf_link_hash_traverse (elf_hash_table (info), - elf_m68k_adjust_dynindx, - (PTR) &c); - elf_hash_table (info)->dynsymcount += c; - } - return true; } - /* Increment the index of a dynamic symbol by a given amount. Called - via elf_link_hash_traverse. */ - - static boolean - elf_m68k_adjust_dynindx (h, cparg) - struct elf_link_hash_entry *h; - PTR cparg; - { - int *cp = (int *) cparg; - - if (h->dynindx != -1) - h->dynindx += *cp; - return true; - } - /* This function is called via elf_m68k_link_hash_traverse if we are creating a shared object with -Bsymbolic. It discards the space allocated to copy PC relative relocs against symbols which are defined --- 1310,1318 ---- *************** elf_m68k_finish_dynamic_sections (output *** 2212,2261 **** } elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; - - if (info->shared) - { - asection *sdynsym; - asection *s; - Elf_Internal_Sym sym; - int c; - - /* Set up the section symbols for the output sections. */ - - sdynsym = bfd_get_section_by_name (dynobj, ".dynsym"); - BFD_ASSERT (sdynsym != NULL); - - sym.st_size = 0; - sym.st_name = 0; - sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION); - sym.st_other = 0; - - c = 0; - for (s = output_bfd->sections; s != NULL; s = s->next) - { - int indx; - - if (elf_section_data (s)->dynindx == 0) - continue; - - sym.st_value = s->vma; - - indx = elf_section_data (s)->this_idx; - BFD_ASSERT (indx > 0); - sym.st_shndx = indx; - - bfd_elf32_swap_symbol_out (output_bfd, &sym, - (PTR) (((Elf32_External_Sym *) - sdynsym->contents) - + elf_section_data (s)->dynindx)); - - ++c; - } - - /* Set the sh_info field of the output .dynsym section to the - index of the first global symbol. */ - elf_section_data (sdynsym->output_section)->this_hdr.sh_info = c + 1; - } return true; } --- 2165,2170 ---- Index: elf32-mips.c =================================================================== RCS file: /cvs/binutils/binutils/bfd/elf32-mips.c,v retrieving revision 1.20 diff -c -p -d -r1.20 elf32-mips.c *** elf32-mips.c 1999/07/13 15:23:22 1.20 --- elf32-mips.c 1999/07/14 01:04:15 *************** _bfd_mips_elf_size_dynamic_sections (out *** 7693,7724 **** return false; } - /* If we use dynamic linking, we generate a section symbol for each - output section. These are local symbols, which means that they - must come first in the dynamic symbol table. - That means we must increment the dynamic symbol index of every - other dynamic symbol. */ - { - unsigned int c, i; - - c = 0; - if (elf_hash_table (info)->dynamic_sections_created) - { - c = bfd_count_sections (output_bfd); - elf_link_hash_traverse (elf_hash_table (info), - _bfd_elf_link_adjust_dynindx, - (PTR) &c); - elf_hash_table (info)->dynsymcount += c; - - for (i = 1, s = output_bfd->sections; s != NULL; s = s->next, i++) - { - elf_section_data (s)->dynindx = i; - /* These symbols will have no names, so we don't need to - fiddle with dynstr_index. */ - } - } - } - return true; } --- 7693,7698 ---- *************** _bfd_mips_elf_finish_dynamic_sections (o *** 8163,8221 **** = MIPS_ELF_GOT_SIZE (output_bfd); { - asection *sdynsym; asection *smsym; asection *s; - Elf_Internal_Sym sym; Elf32_compact_rel cpt; ! /* Set up the section symbols for the output sections. SGI sets ! the STT_NOTYPE attribute for these symbols. Should we do so? */ - sdynsym = bfd_get_section_by_name (dynobj, ".dynsym"); smsym = bfd_get_section_by_name (dynobj, MIPS_ELF_MSYM_SECTION_NAME (dynobj)); ! if (sdynsym != NULL) { Elf32_Internal_Msym msym; - sym.st_size = 0; - sym.st_name = 0; - sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION); - sym.st_other = 0; - msym.ms_hash_value = 0; msym.ms_info = ELF32_MS_INFO (0, 1); for (s = output_bfd->sections; s != NULL; s = s->next) { ! int indx; ! long dynindx; ! ! sym.st_value = s->vma; ! ! indx = elf_section_data (s)->this_idx; ! BFD_ASSERT (indx > 0); ! sym.st_shndx = indx; ! ! dynindx = elf_section_data (s)->dynindx; ! (*get_elf_backend_data (output_bfd)->s->swap_symbol_out) ! (output_bfd, &sym, ! sdynsym->contents ! + (dynindx * MIPS_ELF_SYM_SIZE (output_bfd))); ! ! if (smsym) ! bfd_mips_elf_swap_msym_out ! (output_bfd, &msym, ! (((Elf32_External_Msym *) smsym->contents) ! + dynindx)); } - - /* Set the sh_info field of the output .dynsym section to - the index of the first global symbol. */ - elf_section_data (sdynsym->output_section)->this_hdr.sh_info = - bfd_count_sections (output_bfd) + 1; } if (SGI_COMPAT (output_bfd)) --- 8137,8168 ---- = MIPS_ELF_GOT_SIZE (output_bfd); { asection *smsym; asection *s; Elf32_compact_rel cpt; ! /* ??? The section symbols for the output sections were set up in ! _bfd_elf_final_link. SGI sets the STT_NOTYPE attribute for these ! symbols. Should we do so? */ smsym = bfd_get_section_by_name (dynobj, MIPS_ELF_MSYM_SECTION_NAME (dynobj)); ! if (smsym != NULL) { Elf32_Internal_Msym msym; msym.ms_hash_value = 0; msym.ms_info = ELF32_MS_INFO (0, 1); for (s = output_bfd->sections; s != NULL; s = s->next) { ! long dynindx = elf_section_data (s)->dynindx; ! bfd_mips_elf_swap_msym_out ! (output_bfd, &msym, ! (((Elf32_External_Msym *) smsym->contents) ! + dynindx)); } } if (SGI_COMPAT (output_bfd)) Index: elf32-ppc.c =================================================================== RCS file: /cvs/binutils/binutils/bfd/elf32-ppc.c,v retrieving revision 1.5 diff -c -p -d -r1.5 elf32-ppc.c *** elf32-ppc.c 1999/07/12 10:29:28 1.5 --- elf32-ppc.c 1999/07/14 01:04:15 *************** static boolean ppc_elf_gc_sweep_hook PAR *** 80,87 **** static boolean ppc_elf_adjust_dynamic_symbol PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *)); - static boolean ppc_elf_adjust_dynindx PARAMS ((struct elf_link_hash_entry *, PTR)); - static boolean ppc_elf_size_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); static boolean ppc_elf_relocate_section PARAMS ((bfd *, --- 80,85 ---- *************** ppc_elf_adjust_dynamic_symbol (info, h) *** 1881,1907 **** } - /* Increment the index of a dynamic symbol by a given amount. Called - via elf_link_hash_traverse. */ - - static boolean - ppc_elf_adjust_dynindx (h, cparg) - struct elf_link_hash_entry *h; - PTR cparg; - { - int *cp = (int *) cparg; - - #ifdef DEBUG - fprintf (stderr, "ppc_elf_adjust_dynindx called, h->dynindx = %d, *cp = %d\n", h->dynindx, *cp); - #endif - - if (h->dynindx != -1) - h->dynindx += *cp; - - return true; - } - - /* Set the sizes of the dynamic sections. */ static boolean --- 1879,1884 ---- *************** ppc_elf_size_dynamic_sections (output_bf *** 2083,2125 **** } } - /* If we are generating a shared library, we generate a section - symbol for each output section. These are local symbols, which - means that they must come first in the dynamic symbol table. - That means we must increment the dynamic symbol index of every - other dynamic symbol. - - FIXME: We assume that there will never be relocations to - locations in linker-created sections that do not have - externally-visible names. Instead, we should work out precisely - which sections relocations are targetted at. */ - if (info->shared) - { - int c; - - for (c = 0, s = output_bfd->sections; s != NULL; s = s->next) - { - if ((s->flags & SEC_LINKER_CREATED) != 0 - || (s->flags & SEC_ALLOC) == 0) - { - elf_section_data (s)->dynindx = 0; - continue; - } - - /* These symbols will have no names, so we don't need to - fiddle with dynstr_index. */ - - elf_section_data (s)->dynindx = c + 1; - - c++; - } - - elf_link_hash_traverse (elf_hash_table (info), - ppc_elf_adjust_dynindx, - (PTR) &c); - elf_hash_table (info)->dynsymcount += c; - } - return true; } --- 2060,2065 ---- *************** ppc_elf_finish_dynamic_sections (output_ *** 2922,2975 **** contents+4); elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; - } - - if (info->shared) - { - asection *sdynsym; - asection *s; - Elf_Internal_Sym sym; - int maxdindx = 0; - - /* Set up the section symbols for the output sections. */ - - sdynsym = bfd_get_section_by_name (dynobj, ".dynsym"); - BFD_ASSERT (sdynsym != NULL); - - sym.st_size = 0; - sym.st_name = 0; - sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION); - sym.st_other = 0; - - for (s = output_bfd->sections; s != NULL; s = s->next) - { - int indx, dindx; - - sym.st_value = s->vma; - - indx = elf_section_data (s)->this_idx; - dindx = elf_section_data (s)->dynindx; - if (dindx > 0) - { - BFD_ASSERT(indx > 0); - BFD_ASSERT(dindx > 0); - - if (dindx > maxdindx) - maxdindx = dindx; - - sym.st_shndx = indx; - - bfd_elf32_swap_symbol_out (output_bfd, &sym, - (PTR) (((Elf32_External_Sym *) - sdynsym->contents) - + dindx)); - } - } - - /* Set the sh_info field of the output .dynsym section to the - index of the first global symbol. */ - elf_section_data (sdynsym->output_section)->this_hdr.sh_info = - maxdindx + 1; } return true; --- 2862,2867 ---- Index: elf32-sparc.c =================================================================== RCS file: /cvs/binutils/binutils/bfd/elf32-sparc.c,v retrieving revision 1.4 diff -c -p -d -r1.4 elf32-sparc.c *** elf32-sparc.c 1999/07/12 10:29:33 1.4 --- elf32-sparc.c 1999/07/14 01:04:16 *************** static boolean elf32_sparc_check_relocs *** 33,40 **** const Elf_Internal_Rela *)); static boolean elf32_sparc_adjust_dynamic_symbol PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *)); - static boolean elf32_sparc_adjust_dynindx - PARAMS ((struct elf_link_hash_entry *, PTR)); static boolean elf32_sparc_size_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); static boolean elf32_sparc_relocate_section --- 33,38 ---- *************** elf32_sparc_size_dynamic_sections (outpu *** 1043,1096 **** } } - /* If we are generating a shared library, we generate a section - symbol for each output section for which we might need to copy - relocs. These are local symbols, which means that they must come - first in the dynamic symbol table. That means we must increment - the dynamic symbol index of every other dynamic symbol. */ - if (info->shared) - { - int c; - - c = 0; - for (s = output_bfd->sections; s != NULL; s = s->next) - { - if ((s->flags & SEC_LINKER_CREATED) != 0 - || (s->flags & SEC_ALLOC) == 0) - continue; - - elf_section_data (s)->dynindx = c + 1; - - /* These symbols will have no names, so we don't need to - fiddle with dynstr_index. */ - - ++c; - } - - elf_link_hash_traverse (elf_hash_table (info), - elf32_sparc_adjust_dynindx, - (PTR) &c); - elf_hash_table (info)->dynsymcount += c; - } - return true; } - /* Increment the index of a dynamic symbol by a given amount. Called - via elf_link_hash_traverse. */ - - static boolean - elf32_sparc_adjust_dynindx (h, cparg) - struct elf_link_hash_entry *h; - PTR cparg; - { - int *cp = (int *) cparg; - - if (h->dynindx != -1) - h->dynindx += *cp; - return true; - } - /* Relocate a SPARC ELF section. */ static boolean --- 1041,1049 ---- *************** elf32_sparc_finish_dynamic_sections (out *** 1849,1898 **** } elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; - - if (info->shared) - { - asection *sdynsym; - asection *s; - Elf_Internal_Sym sym; - int c; - - /* Set up the section symbols for the output sections. */ - - sdynsym = bfd_get_section_by_name (dynobj, ".dynsym"); - BFD_ASSERT (sdynsym != NULL); - - sym.st_size = 0; - sym.st_name = 0; - sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION); - sym.st_other = 0; - - c = 0; - for (s = output_bfd->sections; s != NULL; s = s->next) - { - int indx; - - if (elf_section_data (s)->dynindx == 0) - continue; - - sym.st_value = s->vma; - - indx = elf_section_data (s)->this_idx; - BFD_ASSERT (indx > 0); - sym.st_shndx = indx; - - bfd_elf32_swap_symbol_out (output_bfd, &sym, - (PTR) (((Elf32_External_Sym *) - sdynsym->contents) - + elf_section_data (s)->dynindx)); - - ++c; - } - - /* Set the sh_info field of the output .dynsym section to the - index of the first global symbol. */ - elf_section_data (sdynsym->output_section)->this_hdr.sh_info = c + 1; - } return true; } --- 1802,1807 ---- Index: elf64-alpha.c =================================================================== RCS file: /cvs/binutils/binutils/bfd/elf64-alpha.c,v retrieving revision 1.2 diff -c -p -d -r1.2 elf64-alpha.c *** elf64-alpha.c 1999/06/18 04:25:56 1.2 --- elf64-alpha.c 1999/07/14 01:04:16 *************** static boolean elf64_alpha_adjust_dynami *** 115,122 **** PARAMS((struct bfd_link_info *, struct elf_link_hash_entry *)); static boolean elf64_alpha_size_dynamic_sections PARAMS((bfd *, struct bfd_link_info *)); - static boolean elf64_alpha_adjust_dynindx - PARAMS((struct elf_link_hash_entry *, PTR)); static boolean elf64_alpha_relocate_section PARAMS((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); --- 115,120 ---- *************** elf64_alpha_size_dynamic_sections (outpu *** 3264,3297 **** } } - /* If we are generating a shared library, we generate a section - symbol for each output section. These are local symbols, which - means that they must come first in the dynamic symbol table. - That means we must increment the dynamic symbol index of every - other dynamic symbol. */ - if (info->shared) - { - long c[2], i; - asection *p; - - c[0] = 0; - c[1] = bfd_count_sections (output_bfd); - - elf_hash_table (info)->dynsymcount += c[1]; - elf_link_hash_traverse (elf_hash_table(info), - elf64_alpha_adjust_dynindx, - (PTR) c); - - for (i = 1, p = output_bfd->sections; - p != NULL; - p = p->next, i++) - { - elf_section_data (p)->dynindx = i; - /* These symbols will have no names, so we don't need to - fiddle with dynstr_index. */ - } - } - if (elf_hash_table (info)->dynamic_sections_created) { /* Add some entries to the .dynamic section. We fill in the --- 3262,3267 ---- *************** elf64_alpha_size_dynamic_sections (outpu *** 3332,3353 **** return true; } - /* Increment the index of a dynamic symbol by a given amount. Called - via elf_link_hash_traverse. */ - - static boolean - elf64_alpha_adjust_dynindx (h, cparg) - struct elf_link_hash_entry *h; - PTR cparg; - { - long *cp = (long *)cparg; - - if (h->dynindx >= cp[0]) - h->dynindx += cp[1]; - - return true; - } - /* Relocate an Alpha ELF section. */ static boolean --- 3302,3307 ---- *************** elf64_alpha_finish_dynamic_sections (out *** 3989,4032 **** elf_section_data (splt->output_section)->this_hdr.sh_entsize = PLT_HEADER_SIZE; } - } - - if (info->shared) - { - asection *sdynsym; - asection *s; - Elf_Internal_Sym sym; - - /* Set up the section symbols for the output sections. */ - - sdynsym = bfd_get_section_by_name (dynobj, ".dynsym"); - BFD_ASSERT (sdynsym != NULL); - - sym.st_size = 0; - sym.st_name = 0; - sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION); - sym.st_other = 0; - - for (s = output_bfd->sections; s != NULL; s = s->next) - { - int indx; - - sym.st_value = s->vma; - - indx = elf_section_data (s)->this_idx; - BFD_ASSERT (indx > 0); - sym.st_shndx = indx; - - bfd_elf64_swap_symbol_out (output_bfd, &sym, - (PTR) (((Elf64_External_Sym *) - sdynsym->contents) - + elf_section_data (s)->dynindx)); - } - - /* Set the sh_info field of the output .dynsym section to the - index of the first global symbol. */ - elf_section_data (sdynsym->output_section)->this_hdr.sh_info = - bfd_count_sections (output_bfd) + 1; } return true; --- 3943,3948 ---- Index: elf64-sparc.c =================================================================== RCS file: /cvs/binutils/binutils/bfd/elf64-sparc.c,v retrieving revision 1.2 diff -c -p -d -r1.2 elf64-sparc.c *** elf64-sparc.c 1999/06/10 20:59:54 1.2 --- elf64-sparc.c 1999/07/14 01:04:16 *************** static boolean sparc64_elf_adjust_dynami *** 51,58 **** PARAMS((struct bfd_link_info *, struct elf_link_hash_entry *)); static boolean sparc64_elf_size_dynamic_sections PARAMS((bfd *, struct bfd_link_info *)); - static boolean sparc64_elf_adjust_dynindx - PARAMS((struct elf_link_hash_entry *, PTR)); static boolean sparc64_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *)); --- 51,56 ---- *************** sparc64_elf_size_dynamic_sections (outpu *** 1146,1199 **** } } - /* If we are generating a shared library, we generate a section - symbol for each output section for which we might need to copy - relocs. These are local symbols, which means that they must come - first in the dynamic symbol table. That means we must increment - the dynamic symbol index of every other dynamic symbol. */ - if (info->shared) - { - int c; - - c = 0; - for (s = output_bfd->sections; s != NULL; s = s->next) - { - if ((s->flags & SEC_LINKER_CREATED) != 0 - || (s->flags & SEC_ALLOC) == 0) - continue; - - elf_section_data (s)->dynindx = c + 1; - - /* These symbols will have no names, so we don't need to - fiddle with dynstr_index. */ - - ++c; - } - - elf_link_hash_traverse (elf_hash_table (info), - sparc64_elf_adjust_dynindx, - (PTR) &c); - elf_hash_table (info)->dynsymcount += c; - } - - return true; - } - - /* Increment the index of a dynamic symbol by a given amount. Called - via elf_link_hash_traverse. */ - - static boolean - sparc64_elf_adjust_dynindx (h, cparg) - struct elf_link_hash_entry *h; - PTR cparg; - { - int *cp = (int *) cparg; - - if (h->dynindx != -1) - h->dynindx += *cp; return true; } - /* Relocate a SPARC64 ELF section. */ --- 1144,1151 ---- *************** sparc64_elf_finish_dynamic_sections (out *** 2089,2138 **** } elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 8; - - if (info->shared) - { - asection *sdynsym; - asection *s; - Elf_Internal_Sym sym; - int c; - - /* Set up the section symbols for the output sections. */ - - sdynsym = bfd_get_section_by_name (dynobj, ".dynsym"); - BFD_ASSERT (sdynsym != NULL); - - sym.st_size = 0; - sym.st_name = 0; - sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION); - sym.st_other = 0; - - c = 0; - for (s = output_bfd->sections; s != NULL; s = s->next) - { - int indx; - - if (elf_section_data (s)->dynindx == 0) - continue; - - sym.st_value = s->vma; - - indx = elf_section_data (s)->this_idx; - BFD_ASSERT (indx > 0); - sym.st_shndx = indx; - - bfd_elf64_swap_symbol_out (output_bfd, &sym, - (PTR) (((Elf64_External_Sym *) - sdynsym->contents) - + elf_section_data (s)->dynindx)); - - ++c; - } - - /* Set the sh_info field of the output .dynsym section to the - index of the first global symbol. */ - elf_section_data (sdynsym->output_section)->this_hdr.sh_info = c + 1; - } return true; } --- 2041,2046 ---- Index: elfcode.h =================================================================== RCS file: /cvs/binutils/binutils/bfd/elfcode.h,v retrieving revision 1.5 diff -c -p -d -r1.5 elfcode.h *** elfcode.h 1999/07/07 17:50:55 1.5 --- elfcode.h 1999/07/14 01:04:16 *************** Foundation, Inc., 59 Temple Place - Suit *** 130,135 **** --- 130,137 ---- #define elf_gc_common_final_link NAME(_bfd_elf,gc_common_final_link) #define elf_gc_record_vtinherit NAME(_bfd_elf,gc_record_vtinherit) #define elf_gc_record_vtentry NAME(_bfd_elf,gc_record_vtentry) + #define elf_link_record_local_dynamic_symbol \ + NAME(_bfd_elf,link_record_local_dynamic_symbol) #if ARCH_SIZE == 64 #define ELF_R_INFO(X,Y) ELF64_R_INFO(X,Y) Index: elflink.c =================================================================== RCS file: /cvs/binutils/binutils/bfd/elflink.c,v retrieving revision 1.5 diff -c -p -d -r1.5 elflink.c *** elflink.c 1999/07/11 19:49:34 1.5 --- elflink.c 1999/07/14 01:04:16 *************** _bfd_elf_link_record_dynamic_symbol (inf *** 260,281 **** return true; } ! /* Increase the index at which H will appear in the dynamic symbol ! table by INCREMENT (which is really an `int *'). Called via ! elf_link_hash_traverse. */ ! boolean ! _bfd_elf_link_adjust_dynindx (h, increment) struct elf_link_hash_entry *h; ! PTR increment; { if (h->dynindx != -1) ! h->dynindx += *((int *) increment); ! return true; } ! /* Create a special linker section, or return a pointer to a linker section already created */ elf_linker_section_t * _bfd_elf_create_linker_section (abfd, info, which, defaults) --- 260,342 ---- return true; } ! /* Return the dynindex of a local dynamic symbol. */ ! long ! _bfd_elf_link_lookup_local_dynindx (info, input_bfd, input_indx) ! struct bfd_link_info *info; ! bfd *input_bfd; ! long input_indx; ! { ! struct elf_link_local_dynamic_entry *e; ! ! for (e = elf_hash_table (info)->dynlocal; e ; e = e->next) ! if (e->input_bfd == input_bfd && e->input_indx == input_indx) ! return e->dynindx; ! return -1; ! } ! ! /* This function is used to renumber the dynamic symbols, if some of ! them are removed because they are marked as local. This is called ! via elf_link_hash_traverse. */ ! ! static boolean elf_link_renumber_hash_table_dynsyms ! PARAMS ((struct elf_link_hash_entry *, PTR)); ! ! static boolean ! elf_link_renumber_hash_table_dynsyms (h, data) struct elf_link_hash_entry *h; ! PTR data; { + size_t *count = (size_t *) data; + if (h->dynindx != -1) ! h->dynindx = ++(*count); ! return true; } + + /* Assign dynsym indicies. In a shared library we generate a section + symbol for each output section, which come first. Next come all of + the back-end allocated local dynamic syms, followed by the rest of + the global symbols. */ + + unsigned long + _bfd_elf_link_renumber_dynsyms (output_bfd, info) + bfd *output_bfd; + struct bfd_link_info *info; + { + unsigned long dynsymcount = 0; + + if (info->shared) + { + asection *p; + for (p = output_bfd->sections; p ; p = p->next) + elf_section_data (p)->dynindx = ++dynsymcount; + } + + if (elf_hash_table (info)->dynlocal) + { + struct elf_link_local_dynamic_entry *p; + for (p = elf_hash_table (info)->dynlocal; p ; p = p->next) + p->dynindx = ++dynsymcount; + } + + elf_link_hash_traverse (elf_hash_table (info), + elf_link_renumber_hash_table_dynsyms, + &dynsymcount); + + /* There is an unused NULL entry at the head of the table which + we must account for in our count. Unless there weren't any + symbols, which means we'll have no table at all. */ + if (dynsymcount != 0) + ++dynsymcount; + + return elf_hash_table (info)->dynsymcount = dynsymcount; + } ! /* Create a special linker section, or return a pointer to a linker ! section already created */ elf_linker_section_t * _bfd_elf_create_linker_section (abfd, info, which, defaults) Index: elflink.h =================================================================== RCS file: /cvs/binutils/binutils/bfd/elflink.h,v retrieving revision 1.15 diff -c -p -d -r1.15 elflink.h *** elflink.h 1999/07/11 19:49:35 1.15 --- elflink.h 1999/07/14 01:04:16 *************** static boolean elf_link_find_version_dep *** 48,61 **** PARAMS ((struct elf_link_hash_entry *, PTR)); static boolean elf_link_assign_sym_version PARAMS ((struct elf_link_hash_entry *, PTR)); - static boolean elf_link_renumber_dynsyms - PARAMS ((struct elf_link_hash_entry *, PTR)); static boolean elf_collect_hash_codes PARAMS ((struct elf_link_hash_entry *, PTR)); static boolean elf_link_read_relocs_from_section PARAMS ((bfd *, Elf_Internal_Shdr *, PTR, Elf_Internal_Rela *)); - static void elf_link_remove_section_and_adjust_dynindices - PARAMS ((struct bfd_link_info *, asection *)); static void elf_link_output_relocs PARAMS ((bfd *, asection *, Elf_Internal_Shdr *, Elf_Internal_Rela *)); static boolean elf_link_size_reloc_section --- 48,57 ---- *************** elf_add_dynamic_entry (info, tag, val) *** 2051,2056 **** --- 2047,2119 ---- return true; } + + /* Record a new local dynamic symbol. */ + + boolean + elf_link_record_local_dynamic_symbol (info, input_bfd, input_indx) + struct bfd_link_info *info; + bfd *input_bfd; + long input_indx; + { + struct elf_link_local_dynamic_entry *entry; + struct elf_link_hash_table *eht; + struct bfd_strtab_hash *dynstr; + Elf_External_Sym esym; + unsigned long dynstr_index; + char *name; + int elfsec, link; + + /* See if the entry exists already. */ + for (entry = elf_hash_table (info)->dynlocal; entry ; entry = entry->next) + if (entry->input_bfd == input_bfd && entry->input_indx == input_indx) + return true; + + entry = (struct elf_link_local_dynamic_entry *) + bfd_alloc (input_bfd, sizeof (*entry)); + if (entry == NULL) + return false; + + /* Go find the symbol, so that we can find it's name. */ + if (bfd_seek (input_bfd, + (elf_tdata (input_bfd)->symtab_hdr.sh_offset + + input_indx * sizeof (Elf_External_Sym)), + SEEK_SET) != 0 + || (bfd_read (&esym, sizeof (Elf_External_Sym), 1, input_bfd) + != sizeof (Elf_External_Sym))) + return false; + elf_swap_symbol_in (input_bfd, &esym, &entry->isym); + + name = (bfd_elf_string_from_elf_section + (input_bfd, elf_tdata (input_bfd)->symtab_hdr.sh_link, + entry->isym.st_name)); + + dynstr = elf_hash_table (info)->dynstr; + if (dynstr == NULL) + { + /* Create a strtab to hold the dynamic symbol names. */ + elf_hash_table (info)->dynstr = dynstr = _bfd_elf_stringtab_init (); + if (dynstr == NULL) + return false; + } + + dynstr_index = _bfd_stringtab_add (dynstr, name, true, false); + if (dynstr_index == (unsigned long) -1) + return false; + entry->isym.st_name = dynstr_index; + + eht = elf_hash_table (info); + + entry->next = eht->dynlocal; + eht->dynlocal = entry; + entry->input_bfd = input_bfd; + entry->input_indx = input_indx; + eht->dynsymcount++; + + /* The dynindx will be set at the end of size_dynamic_sections. */ + + return true; + } /* Read and swap the relocs from the section indicated by SHDR. This *************** struct elf_assign_sym_version_info *** 2310,2317 **** struct bfd_elf_version_tree *verdefs; /* Whether we are exporting all dynamic symbols. */ boolean export_dynamic; - /* Whether we removed any symbols from the dynamic symbol table. */ - boolean removed_dynamic; /* Whether we had a failure. */ boolean failed; }; --- 2373,2378 ---- *************** compute_bucket_count (info) *** 2486,2527 **** return best_size; } - /* Remove SECTION from the BFD. If a symbol for SECTION was going to - be put into the dynamic symbol table, remove it, and renumber - subsequent entries. */ - - static void - elf_link_remove_section_and_adjust_dynindices (info, section) - struct bfd_link_info *info; - asection *section; - { - /* Remove the section from the output list. */ - _bfd_strip_section_from_output (section); - - if (elf_section_data (section->output_section)->dynindx) - { - asection *s; - int increment = -1; - - /* We were going to output an entry in the dynamic symbol table - for the symbol corresponding to this section. Now, the - section is gone. So, we must renumber the dynamic indices of - all subsequent sections and all other entries in the dynamic - symbol table. */ - elf_section_data (section->output_section)->dynindx = 0; - for (s = section->output_section->next; s; s = s->next) - if (elf_section_data (s)->dynindx) - --elf_section_data (s)->dynindx; - - elf_link_hash_traverse (elf_hash_table (info), - _bfd_elf_link_adjust_dynindx, - &increment); - - /* There is one less dynamic symbol than there was before. */ - --elf_hash_table (info)->dynsymcount; - } - } - /* Set up the sizes and contents of the ELF dynamic sections. This is called by the ELF linker emulation before_allocation routine. We must set the sizes of the sections before the linker sets the --- 2547,2552 ---- *************** NAME(bfd_elf,size_dynamic_sections) (out *** 2545,2551 **** bfd_size_type soname_indx; bfd *dynobj; struct elf_backend_data *bed; - bfd_size_type old_dynsymcount; struct elf_assign_sym_version_info asvinfo; *sinterpptr = NULL; --- 2570,2575 ---- *************** NAME(bfd_elf,size_dynamic_sections) (out *** 2650,2656 **** asvinfo.info = info; asvinfo.verdefs = verdefs; asvinfo.export_dynamic = export_dynamic; - asvinfo.removed_dynamic = false; asvinfo.failed = false; elf_link_hash_traverse (elf_hash_table (info), --- 2674,2679 ---- *************** NAME(bfd_elf,size_dynamic_sections) (out *** 2712,2718 **** /* 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 && ! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info)) return false; --- 2735,2740 ---- *************** NAME(bfd_elf,size_dynamic_sections) (out *** 2734,2740 **** verdefs = asvinfo.verdefs; if (verdefs == NULL) ! elf_link_remove_section_and_adjust_dynindices (info, s); else { unsigned int cdefs; --- 2756,2762 ---- verdefs = asvinfo.verdefs; if (verdefs == NULL) ! _bfd_strip_section_from_output (s); else { unsigned int cdefs; *************** NAME(bfd_elf,size_dynamic_sections) (out *** 2744,2766 **** Elf_Internal_Verdef def; Elf_Internal_Verdaux defaux; - if (asvinfo.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. 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); - } - cdefs = 0; size = 0; --- 2766,2771 ---- *************** NAME(bfd_elf,size_dynamic_sections) (out *** 2927,2933 **** (PTR) &sinfo); if (elf_tdata (output_bfd)->verref == NULL) ! elf_link_remove_section_and_adjust_dynindices (info, s); else { Elf_Internal_Verneed *t; --- 2932,2938 ---- (PTR) &sinfo); if (elf_tdata (output_bfd)->verref == NULL) ! _bfd_strip_section_from_output (s); else { Elf_Internal_Verneed *t; *************** NAME(bfd_elf,size_dynamic_sections) (out *** 3018,3024 **** } } ! dynsymcount = elf_hash_table (info)->dynsymcount; /* Work out the size of the symbol version section. */ s = bfd_get_section_by_name (dynobj, ".gnu.version"); --- 3023,3034 ---- } } ! /* Assign dynsym indicies. In a shared library we generate a ! section symbol for each output section, which come first. ! Next come all of the back-end allocated local dynamic syms, ! followed by the rest of the global symbols. */ ! ! dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info); /* Work out the size of the symbol version section. */ s = bfd_get_section_by_name (dynobj, ".gnu.version"); *************** NAME(bfd_elf,size_dynamic_sections) (out *** 3026,3035 **** if (dynsymcount == 0 || (verdefs == NULL && elf_tdata (output_bfd)->verref == NULL)) { ! elf_link_remove_section_and_adjust_dynindices (info, s); /* The DYNSYMCOUNT might have changed if we were going to output a dynamic symbol table entry for S. */ ! dynsymcount = elf_hash_table (info)->dynsymcount; } else { --- 3036,3045 ---- if (dynsymcount == 0 || (verdefs == NULL && elf_tdata (output_bfd)->verref == NULL)) { ! _bfd_strip_section_from_output (s); /* The DYNSYMCOUNT might have changed if we were going to output a dynamic symbol table entry for S. */ ! dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info); } else { *************** elf_link_assign_sym_version (h, data) *** 3513,3519 **** && info->shared && ! sinfo->export_dynamic) { - sinfo->removed_dynamic = true; h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL; h->elf_link_hash_flags &=~ ELF_LINK_HASH_NEEDS_PLT; --- 3523,3528 ---- *************** elf_link_assign_sym_version (h, data) *** 3629,3635 **** && info->shared && ! sinfo->export_dynamic) { - sinfo->removed_dynamic = true; h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL; h->elf_link_hash_flags &=~ ELF_LINK_HASH_NEEDS_PLT; h->dynindx = -1; --- 3638,3643 ---- *************** elf_link_assign_sym_version (h, data) *** 3654,3660 **** && info->shared && ! sinfo->export_dynamic) { - sinfo->removed_dynamic = true; h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL; h->elf_link_hash_flags &=~ ELF_LINK_HASH_NEEDS_PLT; h->dynindx = -1; --- 3662,3667 ---- *************** elf_link_assign_sym_version (h, data) *** 3667,3692 **** return true; } - - /* This function is used to renumber the dynamic symbols, if some of - them are removed because they are marked as local. This is called - via elf_link_hash_traverse. */ - - static boolean - elf_link_renumber_dynsyms (h, data) - struct elf_link_hash_entry *h; - PTR data; - { - struct bfd_link_info *info = (struct bfd_link_info *) data; - - if (h->dynindx != -1) - { - h->dynindx = elf_hash_table (info)->dynsymcount; - ++elf_hash_table (info)->dynsymcount; - } - - return true; - } /* Final phase of ELF linker. */ --- 3674,3679 ---- *************** elf_bfd_final_link (abfd, info) *** 4161,4171 **** return false; } ! /* The sh_info field records the index of the first non local ! symbol. */ symtab_hdr->sh_info = bfd_get_symcount (abfd); if (dynamic) ! elf_section_data (finfo.dynsym_sec->output_section)->this_hdr.sh_info = 1; /* We get the global symbols from the hash table. */ eoinfo.failed = false; --- 4148,4224 ---- return false; } ! /* The sh_info field records the index of the first non local symbol. */ symtab_hdr->sh_info = bfd_get_symcount (abfd); + if (dynamic) ! { ! Elf_Internal_Sym sym; ! Elf_External_Sym *dynsym = ! (Elf_External_Sym *)finfo.dynsym_sec->contents; ! unsigned long last_local = 0; ! ! /* Write out the section symbols for the output sections. */ ! if (info->shared) ! { ! asection *s; ! ! sym.st_size = 0; ! sym.st_name = 0; ! sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION); ! sym.st_other = 0; ! ! for (s = abfd->sections; s != NULL; s = s->next) ! { ! int indx; ! indx = elf_section_data (s)->this_idx; ! BFD_ASSERT (indx > 0); ! sym.st_shndx = indx; ! sym.st_value = s->vma; ! ! elf_swap_symbol_out (abfd, &sym, ! dynsym + elf_section_data (s)->dynindx); ! } ! ! last_local = bfd_count_sections (abfd); ! } ! ! /* Write out the local dynsyms. */ ! if (elf_hash_table (info)->dynlocal) ! { ! struct elf_link_local_dynamic_entry *e; ! for (e = elf_hash_table (info)->dynlocal; e ; e = e->next) ! { ! asection *s, *os; ! ! sym.st_size = e->isym.st_size; ! sym.st_other = e->isym.st_other; ! ! /* Note that we saved a word of storage and overwrote ! the original st_name with the dynstr_index. */ ! sym.st_name = e->isym.st_name; ! ! /* Whatever binding the symbol had before, it's now local. */ ! sym.st_info = ELF_ST_INFO (STB_LOCAL, ! ELF_ST_TYPE (e->isym.st_info)); ! ! s = bfd_section_from_elf_index (e->input_bfd, e->isym.st_shndx); ! ! sym.st_shndx = elf_section_data (s->output_section)->this_idx; ! sym.st_value = (s->output_section->vma ! + s->output_offset ! + e->isym.st_value); ! ! if (last_local < e->dynindx) ! last_local = e->dynindx; ! ! elf_swap_symbol_out (abfd, &sym, dynsym + e->dynindx); ! } ! } ! ! elf_section_data (finfo.dynsym_sec->output_section) ! ->this_hdr.sh_info = last_local; ! } /* We get the global symbols from the hash table. */ eoinfo.failed = false;