From: Richard Sandiford Date: Wed, 22 Mar 2006 09:28:15 +0000 (+0000) Subject: Richard Sandiford X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0a44bf6950b3b1a1a79e46c36be2487c2499fd58;p=binutils-gdb.git Richard Sandiford Daniel Jacobowitz Phil Edwards Zack Weinberg Mark Mitchell Nathan Sidwell bfd/ * bfd-in2.h: Regenerate. * config.bfd (mips*-*-vxworks*, mips*el-*-vxworks*): New stanzas. * configure.in (bfd_elf32_bigmips_vxworks_vec): New stanza. (bfd_elf32_littlemips_vxworks_vec): Likewise. (bfd_elf32_bigmips_vec): Add elf-vxworks.lo. (bfd_elf32_littlemips_vec): Likewise. (bfd_elf32_nbigmips_vec): Likewise. (bfd_elf32_nlittlemips_vec): Likewise. (bfd_elf32_ntradbigmips_vec): Likewise. (bfd_elf32_ntradlittlemips_vec): Likewise. (bfd_elf32_tradbigmips_vec): Likewise. (bfd_elf32_tradlittlemips_vec): Likewise. (bfd_elf64_bigmips_vec): Likewise. (bfd_elf64_littlemips_vec): Likewise. (bfd_elf64_tradbigmips_vec): Likewise. (bfd_elf64_tradlittlemips_vec): Likewise. * elf32-mips.c: Include elf-vxworks.h. (mips_info_to_howto_rel): Use elf_backend_mips_rtype_to_howto instead of calling mips_elf32_rtype_to_howto directly. (mips_vxworks_copy_howto_rela): New reloc howto. (mips_vxworks_jump_slot_howto_rela): Likewise. (mips_vxworks_bfd_reloc_type_lookup): New function. (mips_vxworks_rtype_to_howto): Likewise. (mips_vxworks_final_write_processing): Likewise. (TARGET_LITTLE_SYM, TARGET_LITTLE_NAME): Override for VxWorks. (TARGET_BIG_SYM, TARGET_BIG_NAME, elf_bed, ELF_MAXPAGESIZE): Likewise. (elf_backend_want_got_plt): Likewise. (elf_backend_want_plt_sym): Likewise. (elf_backend_got_symbol_offset): Likewise. (elf_backend_want_dynbss): Likewise. (elf_backend_may_use_rel_p): Likewise. (elf_backend_may_use_rela_p): Likewise. (elf_backend_default_use_rela_p): Likewise. (elf_backend_got_header_size: Likewise. (elf_backend_plt_readonly): Likewise. (bfd_elf32_bfd_reloc_type_lookup): Likewise. (elf_backend_mips_rtype_to_howto): Likewise. (elf_backend_adjust_dynamic_symbol): Likewise. (elf_backend_finish_dynamic_symbol): Likewise. (bfd_elf32_bfd_link_hash_table_create): Likewise. (elf_backend_add_symbol_hook): Likewise. (elf_backend_link_output_symbol_hook): Likewise. (elf_backend_emit_relocs): Likewise. (elf_backend_final_write_processing: Likewise. (elf_backend_additional_program_headers): Likewise. (elf_backend_modify_segment_map): Likewise. (elf_backend_symbol_processing): Likewise. * elfxx-mips.c: Include elf-vxworks.h. (mips_elf_link_hash_entry): Add is_relocation_target and is_branch_target fields. (mips_elf_link_hash_table): Add is_vxworks, srelbss, sdynbss, srelplt, srelplt2, sgotplt, splt, plt_header_size and plt_entry_size fields. (MIPS_ELF_RELA_SIZE, MIPS_ELF_REL_DYN_NAME): New macros. (MIPS_RESERVED_GOTNO): Take a mips_elf_link_hash_table argument. Return 3 for VxWorks. (ELF_MIPS_GP_OFFSET): Change the argument from a bfd to a mips_elf_link_hash_table. Return 0 for VxWorks. (MIPS_ELF_GOT_MAX_SIZE): Change the argument from a bfd to a mips_elf_link_hash_table. Update the call to ELF_MIPS_GP_OFFSET. (mips_vxworks_exec_plt0_entry): New variable. (mips_vxworks_exec_plt_entry): Likewise. (mips_vxworks_shared_plt0_entry): Likewise. (mips_vxworks_shared_plt_entry): Likewise. (mips_elf_link_hash_newfunc): Initialize the new hash_entry fields. (mips_elf_rel_dyn_section): Change the bfd argument to a mips_elf_link_hash_table. Use MIPS_ELF_REL_DYN_NAME to get the name of the section. (mips_elf_initialize_tls_slots): Update the call to mips_elf_rel_dyn_section. (mips_elf_gotplt_index): New function. (mips_elf_local_got_index): Add an input_section argument. Update the call to mips_elf_create_local_got_entry. (mips_elf_got_page): Likewise. (mips_elf_got16_entry): Likewise. (mips_elf_create_local_got_entry): Add bfd_link_info and input_section arguments. Create dynamic relocations for each entry on VxWorks. (mips_elf_merge_gots): Update the use of MIPS_ELF_GOT_MAX_SIZE. (mips_elf_multi_got): Update the uses of MIPS_ELF_GOT_MAX_SIZE and MIPS_RESERVED_GOTNO. (mips_elf_create_got_section): Update the uses of MIPS_ELF_GOT_MAX_SIZE. Create .got.plt on VxWorks. (is_gott_symbol): New function. (mips_elf_calculate_relocation): Use a dynobj local variable. Update the calls to mips_elf_local_got_index, mips_elf_got16_entry and mips_elf_got_page_entry. Set G to the .got.plt entry when calculating VxWorks R_MIPS_CALL* relocations. Calculate and use G for all GOT relocations on VxWorks. Add dynamic relocations for references to the VxWorks __GOTT_BASE__ and __GOTT_INDEX__ symbols. Don't create dynamic relocations for R_MIPS_32, R_MIPS_REL32 or R_MIPS_64 in VxWorks executables. (mips_elf_allocate_dynamic_relocations): Add a bfd_link_info argument. Use MIPS_ELF_RELA_SIZE to calculate the size of a VxWorks entry. Don't allocate a null entry on VxWorks. (mips_elf_create_dynamic_relocation): Update the call to mips_elf_rel_dyn_section. Use absolute rather than relative relocations for VxWorks, and make them RELA rather than REL. (_bfd_mips_elf_create_dynamic_sections): Don't make .dynamic read-only on VxWorks. Update the call to mips_elf_rel_dyn_section. Create the .plt, .rela.plt, .dynbss and .rela.bss sections on VxWorks. Likewise create the _PROCEDURE_LINKAGE_TABLE symbol. Call elf_vxworks_create_dynamic_sections for VxWorks and initialize the plt_header_size and plt_entry_size fields. (_bfd_mips_elf_check_relocs): Don't allow GOT relocations to be used in VxWorks executables. Don't allocate dynamic relocations for R_MIPS_32, R_MIPS_REL32 or R_MIPS_64 in VxWorks executables. Set is_relocation_target for each symbol referenced by a relocation. Allocate .rela.dyn entries for relocations against the special VxWorks __GOTT_BASE__ and __GOTT_INDEX__ symbols. Create GOT entries for all VxWorks R_MIPS_GOT16 relocations. Don't allocate a global GOT entry for symbols mentioned in VxWorks R_MIPS_CALL*, R_MIPS_32, R_MIPS_REL32 or R_MIPS_64 relocations. Update the calls to mips_elf_rel_dyn_section and mips_elf_allocate_dynamic_relocations. Set is_branch_target for symbols mentioned in R_MIPS_PC16 or R_MIPS_26 relocations. Don't set no_fn_stub on VxWorks. (_bfd_mips_elf_adjust_dynamic_symbol): Update the call to mips_elf_allocate_dynamic_relocations. (_bfd_mips_vxworks_adjust_dynamic_symbol): New function. (_bfd_mips_elf_always_size_sections): Do not allocate GOT page entries for VxWorks, and do not create multiple GOTs. (_bfd_mips_elf_size_dynamic_sections): Use MIPS_ELF_REL_DYN_NAME. Handle .got specially for VxWorks. Update the uses of MIPS_RESERVED_GOTNO and mips_elf_allocate_dynamic_relocations. Check for sgotplt and splt. Allocate the .rel(a).dyn contents last, once its final size is known. Set DF_TEXTREL for VxWorks. Add DT_RELA, DT_RELASZ, DT_RELAENT, DT_PLTREL, DT_PLTRELSZ and DT_JMPREL tags on VxWorks. Do not add the MIPS-specific tags for VxWorks. (_bfd_mips_vxworks_finish_dynamic_symbol): New function. (mips_vxworks_finish_exec_plt): Likewise. (mips_vxworks_finish_shared_plt): Likewise. (_bfd_mips_elf_finish_dynamic_sections): Remove an unncessary call to mips_elf_rel_dyn_section. Use a VxWorks-specific value of DT_PLTGOT. Handle DT_RELA, DT_RELASZ, DT_RELAENT, DT_PLTREL, DT_PLTRELSZ and DT_JMPREL. Update the uses of MIPS_RESERVED_GOTNO and mips_elf_rel_dyn_section. Use a different GOT header for VxWorks. Don't sort .rela.dyn on VxWorks. Finish the PLT on VxWorks. (_bfd_mips_elf_link_hash_table_create): Initialize the new mips_elf_link_hash_table fields. (_bfd_mips_vxworks_link_hash_table_create): New function. (_bfd_mips_elf_final_link): Set the GP value to _GLOBAL_OFFSET_TABLE_ on VxWorks. Update the call to ELF_MIPS_GP_OFFSET. * elfxx-mips.h (_bfd_mips_vxworks_adjust_dynamic_symbol): Declare. (_bfd_mips_vxworks_finish_dynamic_symbol): Likewise. (_bfd_mips_vxworks_link_hash_table_create): Likewise. * libbfd.h: Regenerate. * Makefile.am (elfxx-mips.lo): Depend on elf-vxworks.h. (elf32-mips.lo): Likewise. * Makefile.in: Regenerate. * reloc.c (BFD_RELOC_MIPS_COPY, BFD_RELOC_MIPS_JUMP_SLOT): Declare. * targets.c (bfd_elf32_bigmips_vxworks_vec): Declare. (bfd_elf32_littlemips_vxworks_vec): Likewise. (_bfd_target_vector): Add entries for them. gas/ * config/tc-mips.c (mips_target_format): Handle vxworks targets. (md_begin): Complain about -G being used for PIC. Don't change the text, data and bss alignments on VxWorks. (reloc_needs_lo_p): Don't return true for R_MIPS_GOT16 when generating VxWorks PIC. (load_address): Extend SVR4_PIC handling to VXWORKS_PIC. (macro): Likewise, but do not treat la $25 specially for VxWorks PIC, and do not handle jal. (OPTION_MVXWORKS_PIC): New macro. (md_longopts): Add -mvxworks-pic. (md_parse_option): Don't complain about using PIC and -G together here. Handle OPTION_MVXWORKS_PIC. (md_estimate_size_before_relax): Always use the first relaxation sequence on VxWorks. * config/tc-mips.h (VXWORKS_PIC): New. gas/testsuite/ * gas/mips/vxworks1.s, gas/mips/vxworks1.d, * gas/mips/vxworks1-xgot.d: New tests. * gas/mips/mips.exp: Run them. Do not run other tests on VxWorks. include/elf/ * mips.h (R_MIPS_COPY, R_MIPS_JUMP_SLOT): New relocs. ld/ * configure.tgt (mips*el-*-vxworks*, mips*-*-vxworks*): Use separate VxWorks emulations. * emulparams/elf32ebmipvxworks.sh: New file. * emulparams/elf32elmipvxworks.sh: New file. * Makefile.am (ALL_EMULATIONS): Add eelf32ebmipvxworks.o and eelf32elmipvxworks.o. (eelf32ebmipvxworks.c, eelf32elmipvxworks.c): New rules. * Makefile.in: Regenerate. ld/testsuite/ * ld-mips/vxworks1.dd, ld-mips/vxworks1.ld, ld-mips/vxworks1-lib.dd, * ld-mips/vxworks1-lib.nd, ld-mips/vxworks1-lib.rd, * ld-mips/vxworks1-lib.s, ld-mips/vxworks1.rd, ld-mips/vxworks1.s, * ld-mips/vxworks1-static.d, ld-mips/vxworks2.s, ld-mips/vxworks2.sd, * ld-mips/vxworks2-static.sd: New tests. * ld-mips/mips-elf.exp: Run them. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 521fcb9c05b..0506cc7839c 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,162 @@ +2006-03-22 Richard Sandiford + Daniel Jacobowitz + Phil Edwards + Zack Weinberg + Mark Mitchell + Nathan Sidwell + + * bfd-in2.h: Regenerate. + * config.bfd (mips*-*-vxworks*, mips*el-*-vxworks*): New stanzas. + * configure.in (bfd_elf32_bigmips_vxworks_vec): New stanza. + (bfd_elf32_littlemips_vxworks_vec): Likewise. + (bfd_elf32_bigmips_vec): Add elf-vxworks.lo. + (bfd_elf32_littlemips_vec): Likewise. + (bfd_elf32_nbigmips_vec): Likewise. + (bfd_elf32_nlittlemips_vec): Likewise. + (bfd_elf32_ntradbigmips_vec): Likewise. + (bfd_elf32_ntradlittlemips_vec): Likewise. + (bfd_elf32_tradbigmips_vec): Likewise. + (bfd_elf32_tradlittlemips_vec): Likewise. + (bfd_elf64_bigmips_vec): Likewise. + (bfd_elf64_littlemips_vec): Likewise. + (bfd_elf64_tradbigmips_vec): Likewise. + (bfd_elf64_tradlittlemips_vec): Likewise. + * elf32-mips.c: Include elf-vxworks.h. + (mips_info_to_howto_rel): Use elf_backend_mips_rtype_to_howto + instead of calling mips_elf32_rtype_to_howto directly. + (mips_vxworks_copy_howto_rela): New reloc howto. + (mips_vxworks_jump_slot_howto_rela): Likewise. + (mips_vxworks_bfd_reloc_type_lookup): New function. + (mips_vxworks_rtype_to_howto): Likewise. + (mips_vxworks_final_write_processing): Likewise. + (TARGET_LITTLE_SYM, TARGET_LITTLE_NAME): Override for VxWorks. + (TARGET_BIG_SYM, TARGET_BIG_NAME, elf_bed, ELF_MAXPAGESIZE): Likewise. + (elf_backend_want_got_plt): Likewise. + (elf_backend_want_plt_sym): Likewise. + (elf_backend_got_symbol_offset): Likewise. + (elf_backend_want_dynbss): Likewise. + (elf_backend_may_use_rel_p): Likewise. + (elf_backend_may_use_rela_p): Likewise. + (elf_backend_default_use_rela_p): Likewise. + (elf_backend_got_header_size: Likewise. + (elf_backend_plt_readonly): Likewise. + (bfd_elf32_bfd_reloc_type_lookup): Likewise. + (elf_backend_mips_rtype_to_howto): Likewise. + (elf_backend_adjust_dynamic_symbol): Likewise. + (elf_backend_finish_dynamic_symbol): Likewise. + (bfd_elf32_bfd_link_hash_table_create): Likewise. + (elf_backend_add_symbol_hook): Likewise. + (elf_backend_link_output_symbol_hook): Likewise. + (elf_backend_emit_relocs): Likewise. + (elf_backend_final_write_processing: Likewise. + (elf_backend_additional_program_headers): Likewise. + (elf_backend_modify_segment_map): Likewise. + (elf_backend_symbol_processing): Likewise. + * elfxx-mips.c: Include elf-vxworks.h. + (mips_elf_link_hash_entry): Add is_relocation_target and + is_branch_target fields. + (mips_elf_link_hash_table): Add is_vxworks, srelbss, sdynbss, srelplt, + srelplt2, sgotplt, splt, plt_header_size and plt_entry_size fields. + (MIPS_ELF_RELA_SIZE, MIPS_ELF_REL_DYN_NAME): New macros. + (MIPS_RESERVED_GOTNO): Take a mips_elf_link_hash_table argument. + Return 3 for VxWorks. + (ELF_MIPS_GP_OFFSET): Change the argument from a bfd to a + mips_elf_link_hash_table. Return 0 for VxWorks. + (MIPS_ELF_GOT_MAX_SIZE): Change the argument from a bfd to a + mips_elf_link_hash_table. Update the call to ELF_MIPS_GP_OFFSET. + (mips_vxworks_exec_plt0_entry): New variable. + (mips_vxworks_exec_plt_entry): Likewise. + (mips_vxworks_shared_plt0_entry): Likewise. + (mips_vxworks_shared_plt_entry): Likewise. + (mips_elf_link_hash_newfunc): Initialize the new hash_entry fields. + (mips_elf_rel_dyn_section): Change the bfd argument to a + mips_elf_link_hash_table. Use MIPS_ELF_REL_DYN_NAME to get + the name of the section. + (mips_elf_initialize_tls_slots): Update the call to + mips_elf_rel_dyn_section. + (mips_elf_gotplt_index): New function. + (mips_elf_local_got_index): Add an input_section argument. + Update the call to mips_elf_create_local_got_entry. + (mips_elf_got_page): Likewise. + (mips_elf_got16_entry): Likewise. + (mips_elf_create_local_got_entry): Add bfd_link_info and input_section + arguments. Create dynamic relocations for each entry on VxWorks. + (mips_elf_merge_gots): Update the use of MIPS_ELF_GOT_MAX_SIZE. + (mips_elf_multi_got): Update the uses of MIPS_ELF_GOT_MAX_SIZE + and MIPS_RESERVED_GOTNO. + (mips_elf_create_got_section): Update the uses of + MIPS_ELF_GOT_MAX_SIZE. Create .got.plt on VxWorks. + (is_gott_symbol): New function. + (mips_elf_calculate_relocation): Use a dynobj local variable. + Update the calls to mips_elf_local_got_index, mips_elf_got16_entry and + mips_elf_got_page_entry. Set G to the .got.plt entry when calculating + VxWorks R_MIPS_CALL* relocations. Calculate and use G for all GOT + relocations on VxWorks. Add dynamic relocations for references + to the VxWorks __GOTT_BASE__ and __GOTT_INDEX__ symbols. Don't + create dynamic relocations for R_MIPS_32, R_MIPS_REL32 or R_MIPS_64 + in VxWorks executables. + (mips_elf_allocate_dynamic_relocations): Add a bfd_link_info argument. + Use MIPS_ELF_RELA_SIZE to calculate the size of a VxWorks entry. + Don't allocate a null entry on VxWorks. + (mips_elf_create_dynamic_relocation): Update the call to + mips_elf_rel_dyn_section. Use absolute rather than relative + relocations for VxWorks, and make them RELA rather than REL. + (_bfd_mips_elf_create_dynamic_sections): Don't make .dynamic + read-only on VxWorks. Update the call to mips_elf_rel_dyn_section. + Create the .plt, .rela.plt, .dynbss and .rela.bss sections on + VxWorks. Likewise create the _PROCEDURE_LINKAGE_TABLE symbol. + Call elf_vxworks_create_dynamic_sections for VxWorks and + initialize the plt_header_size and plt_entry_size fields. + (_bfd_mips_elf_check_relocs): Don't allow GOT relocations to be + used in VxWorks executables. Don't allocate dynamic relocations + for R_MIPS_32, R_MIPS_REL32 or R_MIPS_64 in VxWorks executables. + Set is_relocation_target for each symbol referenced by a relocation. + Allocate .rela.dyn entries for relocations against the special + VxWorks __GOTT_BASE__ and __GOTT_INDEX__ symbols. Create GOT + entries for all VxWorks R_MIPS_GOT16 relocations. Don't allocate + a global GOT entry for symbols mentioned in VxWorks R_MIPS_CALL*, + R_MIPS_32, R_MIPS_REL32 or R_MIPS_64 relocations. Update the calls + to mips_elf_rel_dyn_section and mips_elf_allocate_dynamic_relocations. + Set is_branch_target for symbols mentioned in R_MIPS_PC16 or R_MIPS_26 + relocations. Don't set no_fn_stub on VxWorks. + (_bfd_mips_elf_adjust_dynamic_symbol): Update the call to + mips_elf_allocate_dynamic_relocations. + (_bfd_mips_vxworks_adjust_dynamic_symbol): New function. + (_bfd_mips_elf_always_size_sections): Do not allocate GOT page + entries for VxWorks, and do not create multiple GOTs. + (_bfd_mips_elf_size_dynamic_sections): Use MIPS_ELF_REL_DYN_NAME. + Handle .got specially for VxWorks. Update the uses of + MIPS_RESERVED_GOTNO and mips_elf_allocate_dynamic_relocations. + Check for sgotplt and splt. Allocate the .rel(a).dyn contents last, + once its final size is known. Set DF_TEXTREL for VxWorks. Add + DT_RELA, DT_RELASZ, DT_RELAENT, DT_PLTREL, DT_PLTRELSZ and DT_JMPREL + tags on VxWorks. Do not add the MIPS-specific tags for VxWorks. + (_bfd_mips_vxworks_finish_dynamic_symbol): New function. + (mips_vxworks_finish_exec_plt): Likewise. + (mips_vxworks_finish_shared_plt): Likewise. + (_bfd_mips_elf_finish_dynamic_sections): Remove an unncessary call + to mips_elf_rel_dyn_section. Use a VxWorks-specific value of + DT_PLTGOT. Handle DT_RELA, DT_RELASZ, DT_RELAENT, DT_PLTREL, + DT_PLTRELSZ and DT_JMPREL. Update the uses of MIPS_RESERVED_GOTNO + and mips_elf_rel_dyn_section. Use a different GOT header for + VxWorks. Don't sort .rela.dyn on VxWorks. Finish the PLT on VxWorks. + (_bfd_mips_elf_link_hash_table_create): Initialize the new + mips_elf_link_hash_table fields. + (_bfd_mips_vxworks_link_hash_table_create): New function. + (_bfd_mips_elf_final_link): Set the GP value to _GLOBAL_OFFSET_TABLE_ + on VxWorks. Update the call to ELF_MIPS_GP_OFFSET. + * elfxx-mips.h (_bfd_mips_vxworks_adjust_dynamic_symbol): Declare. + (_bfd_mips_vxworks_finish_dynamic_symbol): Likewise. + (_bfd_mips_vxworks_link_hash_table_create): Likewise. + * libbfd.h: Regenerate. + * Makefile.am (elfxx-mips.lo): Depend on elf-vxworks.h. + (elf32-mips.lo): Likewise. + * Makefile.in: Regenerate. + * reloc.c (BFD_RELOC_MIPS_COPY, BFD_RELOC_MIPS_JUMP_SLOT): Declare. + * targets.c (bfd_elf32_bigmips_vxworks_vec): Declare. + (bfd_elf32_littlemips_vxworks_vec): Likewise. + (_bfd_target_vector): Add entries for them. + 2006-03-19 John David Anglin * elf64-hppa.c (elf64_hppa_special_sections): Change flags for .tbss diff --git a/bfd/Makefile.am b/bfd/Makefile.am index 4300ca9ed36..a0d5edf67d9 100644 --- a/bfd/Makefile.am +++ b/bfd/Makefile.am @@ -1350,14 +1350,14 @@ elfxx-mips.lo: elfxx-mips.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \ $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h \ elfxx-mips.h $(INCDIR)/elf/mips.h $(INCDIR)/elf/reloc-macros.h \ $(INCDIR)/coff/sym.h $(INCDIR)/coff/symconst.h $(INCDIR)/coff/ecoff.h \ - $(INCDIR)/coff/mips.h $(INCDIR)/coff/external.h + $(INCDIR)/coff/mips.h $(INCDIR)/coff/external.h elf-vxworks.h elf32-mips.lo: elf32-mips.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \ $(INCDIR)/bfdlink.h genlink.h elf-bfd.h $(INCDIR)/elf/common.h \ $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h elfxx-mips.h \ $(INCDIR)/elf/mips.h $(INCDIR)/elf/reloc-macros.h $(INCDIR)/coff/sym.h \ $(INCDIR)/coff/symconst.h $(INCDIR)/coff/internal.h \ $(INCDIR)/coff/ecoff.h $(INCDIR)/coff/mips.h $(INCDIR)/coff/external.h \ - ecoffswap.h elf32-target.h + ecoffswap.h elf32-target.h elf-vxworks.h elf32-mt.lo: elf32-mt.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \ elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \ $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(INCDIR)/elf/mt.h \ diff --git a/bfd/Makefile.in b/bfd/Makefile.in index ef96cc7a0ea..6b783333246 100644 --- a/bfd/Makefile.in +++ b/bfd/Makefile.in @@ -1917,14 +1917,14 @@ elfxx-mips.lo: elfxx-mips.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \ $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h \ elfxx-mips.h $(INCDIR)/elf/mips.h $(INCDIR)/elf/reloc-macros.h \ $(INCDIR)/coff/sym.h $(INCDIR)/coff/symconst.h $(INCDIR)/coff/ecoff.h \ - $(INCDIR)/coff/mips.h $(INCDIR)/coff/external.h + $(INCDIR)/coff/mips.h $(INCDIR)/coff/external.h elf-vxworks.h elf32-mips.lo: elf32-mips.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \ $(INCDIR)/bfdlink.h genlink.h elf-bfd.h $(INCDIR)/elf/common.h \ $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h elfxx-mips.h \ $(INCDIR)/elf/mips.h $(INCDIR)/elf/reloc-macros.h $(INCDIR)/coff/sym.h \ $(INCDIR)/coff/symconst.h $(INCDIR)/coff/internal.h \ $(INCDIR)/coff/ecoff.h $(INCDIR)/coff/mips.h $(INCDIR)/coff/external.h \ - ecoffswap.h elf32-target.h + ecoffswap.h elf32-target.h elf-vxworks.h elf32-mt.lo: elf32-mt.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \ elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \ $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(INCDIR)/elf/mt.h \ diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 4a777ed825c..62886c92849 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -2588,6 +2588,11 @@ to compensate for the borrow when the low bits are added. */ BFD_RELOC_MIPS_TLS_TPREL_LO16, +/* MIPS ELF relocations (VxWorks extensions). */ + BFD_RELOC_MIPS_COPY, + BFD_RELOC_MIPS_JUMP_SLOT, + + /* Fujitsu Frv Relocations. */ BFD_RELOC_FRV_LABEL16, BFD_RELOC_FRV_LABEL24, diff --git a/bfd/config.bfd b/bfd/config.bfd index 37dd03cee69..97648d9f0a1 100644 --- a/bfd/config.bfd +++ b/bfd/config.bfd @@ -868,6 +868,16 @@ case "${targ}" in targ_defvec=ecoff_big_vec targ_selvecs=ecoff_little_vec ;; +#ifdef BFD64 + mips*el-*-vxworks*) + targ_defvec=bfd_elf32_littlemips_vxworks_vec + targ_selvecs="bfd_elf32_littlemips_vec bfd_elf32_bigmips_vxworks_vec bfd_elf32_bigmips_vec bfd_elf64_bigmips_vec bfd_elf64_littlemips_vec" + ;; + mips*-*-vxworks*) + targ_defvec=bfd_elf32_bigmips_vxworks_vec + targ_selvecs="bfd_elf32_bigmips_vec bfd_elf32_littlemips_vxworks_vec bfd_elf32_bigmips_vec bfd_elf64_bigmips_vec bfd_elf64_littlemips_vec" + ;; +#endif mips*el-*-elf* | mips*el-*-vxworks* | mips*-*-chorus*) targ_defvec=bfd_elf32_littlemips_vec targ_selvecs="bfd_elf32_bigmips_vec bfd_elf64_bigmips_vec bfd_elf64_littlemips_vec" diff --git a/bfd/configure b/bfd/configure index ef1d5b50a26..4164bee08a6 100755 --- a/bfd/configure +++ b/bfd/configure @@ -13078,7 +13078,9 @@ do tb="$tb elf32-arm.lo elf32.lo elf-vxworks.lo $elf" ;; bfd_elf32_bigarm_vxworks_vec) tb="$tb elf32-arm.lo elf32.lo elf-vxworks.lo $elf" ;; - bfd_elf32_bigmips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo" ;; + bfd_elf32_bigmips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;; + bfd_elf32_bigmips_vxworks_vec) + tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;; bfd_elf32_cr16c_vec) tb="$tb elf32-cr16c.lo elf32.lo $elf" ;; bfd_elf32_cris_vec) tb="$tb elf32-cris.lo elf32.lo $elf" ;; bfd_elf32_crx_vec) tb="$tb elf32-crx.lo elf32.lo $elf" ;; @@ -13110,7 +13112,9 @@ do bfd_elf32_littlearm_vxworks_vec) tb="$tb elf32-arm.lo elf32.lo elf-vxworks.lo $elf" ;; bfd_elf32_littlearm_vec) tb="$tb elf32-arm.lo elf32.lo elf-vxworks.lo $elf" ;; - bfd_elf32_littlemips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo" ;; + bfd_elf32_littlemips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;; + bfd_elf32_littlemips_vxworks_vec) + tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;; bfd_elf32_m32c_vec) tb="$tb elf32-m32c.lo elf32.lo $elf" ;; bfd_elf32_m32r_vec) tb="$tb elf32-m32r.lo elf32.lo $elf" ;; bfd_elf32_m32rle_vec) tb="$tb elf32-m32r.lo elf32.lo $elf" ;; @@ -13126,10 +13130,10 @@ do bfd_elf32_mn10300_vec) tb="$tb elf-m10300.lo elf32.lo $elf" ;; bfd_elf32_mt_vec) tb="$tb elf32-mt.lo elf32.lo $elf" ;; bfd_elf32_msp430_vec) tb="$tb elf32-msp430.lo elf32.lo $elf" ;; - bfd_elf32_nbigmips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; - bfd_elf32_nlittlemips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; - bfd_elf32_ntradbigmips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; - bfd_elf32_ntradlittlemips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; + bfd_elf32_nbigmips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; + bfd_elf32_nlittlemips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; + bfd_elf32_ntradbigmips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; + bfd_elf32_ntradlittlemips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; bfd_elf32_openrisc_vec) tb="$tb elf32-openrisc.lo elf32.lo $elf" ;; bfd_elf32_or32_big_vec) tb="$tb elf32-or32.lo elf32.lo $elf" ;; bfd_elf32_pj_vec) tb="$tb elf32-pj.lo elf32.lo $elf";; @@ -13155,8 +13159,8 @@ do bfd_elf32_shlnbsd_vec) tb="$tb elf32-sh.lo elf32.lo $elf coff-sh.lo cofflink.lo" ;; bfd_elf32_shnbsd_vec) tb="$tb elf32-sh.lo elf32.lo $elf coff-sh.lo cofflink.lo" ;; bfd_elf32_sparc_vec) tb="$tb elf32-sparc.lo elfxx-sparc.lo elf32.lo $elf" ;; - bfd_elf32_tradbigmips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo" ;; - bfd_elf32_tradlittlemips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo" ;; + bfd_elf32_tradbigmips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;; + bfd_elf32_tradlittlemips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;; bfd_elf32_us_cris_vec) tb="$tb elf32-cris.lo elf32.lo $elf" ;; bfd_elf32_v850_vec) tb="$tb elf32-v850.lo elf32.lo $elf" ;; bfd_elf32_vax_vec) tb="$tb elf32-vax.lo elf32.lo $elf" ;; @@ -13167,14 +13171,14 @@ do bfd_elf64_alpha_freebsd_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;; bfd_elf64_alpha_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;; bfd_elf64_big_generic_vec) tb="$tb elf64-gen.lo elf64.lo $elf"; target_size=64 ;; - bfd_elf64_bigmips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; + bfd_elf64_bigmips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; bfd_elf64_hppa_linux_vec) tb="$tb elf64-hppa.lo elf64.lo $elf"; target_size=64 ;; bfd_elf64_hppa_vec) tb="$tb elf64-hppa.lo elf64.lo $elf"; target_size=64 ;; bfd_elf64_ia64_big_vec) tb="$tb elf64-ia64.lo elf64.lo $elf"; target_size=64 ;; bfd_elf64_ia64_hpux_big_vec) tb="$tb elf64-ia64.lo elf64.lo $elf"; target_size=64 ;; bfd_elf64_ia64_little_vec) tb="$tb elf64-ia64.lo elf64.lo $elf"; target_size=64 ;; bfd_elf64_little_generic_vec) tb="$tb elf64-gen.lo elf64.lo $elf"; target_size=64 ;; - bfd_elf64_littlemips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; + bfd_elf64_littlemips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; bfd_elf64_mmix_vec) tb="$tb elf64-mmix.lo elf64.lo $elf" target_size=64 ;; bfd_elf64_powerpc_vec) tb="$tb elf64-ppc.lo elf64-gen.lo elf64.lo $elf"; target_size=64 ;; bfd_elf64_powerpcle_vec) tb="$tb elf64-ppc.lo elf64-gen.lo elf64.lo $elf" target_size=64 ;; @@ -13186,8 +13190,8 @@ do bfd_elf64_sh64lnbsd_vec) tb="$tb elf64-sh64.lo elf64.lo $elf" target_size=64 ;; bfd_elf64_sh64nbsd_vec) tb="$tb elf64-sh64.lo elf64.lo $elf" target_size=64 ;; bfd_elf64_sparc_vec) tb="$tb elf64-sparc.lo elfxx-sparc.lo elf64.lo $elf"; target_size=64 ;; - bfd_elf64_tradbigmips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; - bfd_elf64_tradlittlemips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; + bfd_elf64_tradbigmips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; + bfd_elf64_tradlittlemips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; bfd_elf64_x86_64_vec) tb="$tb elf64-x86-64.lo elf64.lo $elf"; target_size=64 ;; bfd_mmo_vec) tb="$tb mmo.lo" target_size=64 ;; bfd_powerpc_pe_vec) tb="$tb pe-ppc.lo peigen.lo cofflink.lo" ;; diff --git a/bfd/configure.in b/bfd/configure.in index 5aaf17db8fe..bd950e32f19 100644 --- a/bfd/configure.in +++ b/bfd/configure.in @@ -591,7 +591,9 @@ do tb="$tb elf32-arm.lo elf32.lo elf-vxworks.lo $elf" ;; bfd_elf32_bigarm_vxworks_vec) tb="$tb elf32-arm.lo elf32.lo elf-vxworks.lo $elf" ;; - bfd_elf32_bigmips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo" ;; + bfd_elf32_bigmips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;; + bfd_elf32_bigmips_vxworks_vec) + tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;; bfd_elf32_cr16c_vec) tb="$tb elf32-cr16c.lo elf32.lo $elf" ;; bfd_elf32_cris_vec) tb="$tb elf32-cris.lo elf32.lo $elf" ;; bfd_elf32_crx_vec) tb="$tb elf32-crx.lo elf32.lo $elf" ;; @@ -623,7 +625,9 @@ do bfd_elf32_littlearm_vxworks_vec) tb="$tb elf32-arm.lo elf32.lo elf-vxworks.lo $elf" ;; bfd_elf32_littlearm_vec) tb="$tb elf32-arm.lo elf32.lo elf-vxworks.lo $elf" ;; - bfd_elf32_littlemips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo" ;; + bfd_elf32_littlemips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;; + bfd_elf32_littlemips_vxworks_vec) + tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;; bfd_elf32_m32c_vec) tb="$tb elf32-m32c.lo elf32.lo $elf" ;; bfd_elf32_m32r_vec) tb="$tb elf32-m32r.lo elf32.lo $elf" ;; bfd_elf32_m32rle_vec) tb="$tb elf32-m32r.lo elf32.lo $elf" ;; @@ -639,10 +643,10 @@ do bfd_elf32_mn10300_vec) tb="$tb elf-m10300.lo elf32.lo $elf" ;; bfd_elf32_mt_vec) tb="$tb elf32-mt.lo elf32.lo $elf" ;; bfd_elf32_msp430_vec) tb="$tb elf32-msp430.lo elf32.lo $elf" ;; - bfd_elf32_nbigmips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; - bfd_elf32_nlittlemips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; - bfd_elf32_ntradbigmips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; - bfd_elf32_ntradlittlemips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; + bfd_elf32_nbigmips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; + bfd_elf32_nlittlemips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; + bfd_elf32_ntradbigmips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; + bfd_elf32_ntradlittlemips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; bfd_elf32_openrisc_vec) tb="$tb elf32-openrisc.lo elf32.lo $elf" ;; bfd_elf32_or32_big_vec) tb="$tb elf32-or32.lo elf32.lo $elf" ;; bfd_elf32_pj_vec) tb="$tb elf32-pj.lo elf32.lo $elf";; @@ -668,8 +672,8 @@ do bfd_elf32_shlnbsd_vec) tb="$tb elf32-sh.lo elf32.lo $elf coff-sh.lo cofflink.lo" ;; bfd_elf32_shnbsd_vec) tb="$tb elf32-sh.lo elf32.lo $elf coff-sh.lo cofflink.lo" ;; bfd_elf32_sparc_vec) tb="$tb elf32-sparc.lo elfxx-sparc.lo elf32.lo $elf" ;; - bfd_elf32_tradbigmips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo" ;; - bfd_elf32_tradlittlemips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo" ;; + bfd_elf32_tradbigmips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;; + bfd_elf32_tradlittlemips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;; bfd_elf32_us_cris_vec) tb="$tb elf32-cris.lo elf32.lo $elf" ;; bfd_elf32_v850_vec) tb="$tb elf32-v850.lo elf32.lo $elf" ;; bfd_elf32_vax_vec) tb="$tb elf32-vax.lo elf32.lo $elf" ;; @@ -680,14 +684,14 @@ do bfd_elf64_alpha_freebsd_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;; bfd_elf64_alpha_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;; bfd_elf64_big_generic_vec) tb="$tb elf64-gen.lo elf64.lo $elf"; target_size=64 ;; - bfd_elf64_bigmips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; + bfd_elf64_bigmips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; bfd_elf64_hppa_linux_vec) tb="$tb elf64-hppa.lo elf64.lo $elf"; target_size=64 ;; bfd_elf64_hppa_vec) tb="$tb elf64-hppa.lo elf64.lo $elf"; target_size=64 ;; bfd_elf64_ia64_big_vec) tb="$tb elf64-ia64.lo elf64.lo $elf"; target_size=64 ;; bfd_elf64_ia64_hpux_big_vec) tb="$tb elf64-ia64.lo elf64.lo $elf"; target_size=64 ;; bfd_elf64_ia64_little_vec) tb="$tb elf64-ia64.lo elf64.lo $elf"; target_size=64 ;; bfd_elf64_little_generic_vec) tb="$tb elf64-gen.lo elf64.lo $elf"; target_size=64 ;; - bfd_elf64_littlemips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; + bfd_elf64_littlemips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; bfd_elf64_mmix_vec) tb="$tb elf64-mmix.lo elf64.lo $elf" target_size=64 ;; bfd_elf64_powerpc_vec) tb="$tb elf64-ppc.lo elf64-gen.lo elf64.lo $elf"; target_size=64 ;; bfd_elf64_powerpcle_vec) tb="$tb elf64-ppc.lo elf64-gen.lo elf64.lo $elf" target_size=64 ;; @@ -699,8 +703,8 @@ do bfd_elf64_sh64lnbsd_vec) tb="$tb elf64-sh64.lo elf64.lo $elf" target_size=64 ;; bfd_elf64_sh64nbsd_vec) tb="$tb elf64-sh64.lo elf64.lo $elf" target_size=64 ;; bfd_elf64_sparc_vec) tb="$tb elf64-sparc.lo elfxx-sparc.lo elf64.lo $elf"; target_size=64 ;; - bfd_elf64_tradbigmips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; - bfd_elf64_tradlittlemips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; + bfd_elf64_tradbigmips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; + bfd_elf64_tradlittlemips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; bfd_elf64_x86_64_vec) tb="$tb elf64-x86-64.lo elf64.lo $elf"; target_size=64 ;; bfd_mmo_vec) tb="$tb mmo.lo" target_size=64 ;; bfd_powerpc_pe_vec) tb="$tb pe-ppc.lo peigen.lo cofflink.lo" ;; diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c index 3cdaeeec6d6..6ed4ad35f62 100644 --- a/bfd/elf32-mips.c +++ b/bfd/elf32-mips.c @@ -37,6 +37,7 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. #include "elf-bfd.h" #include "elfxx-mips.h" #include "elf/mips.h" +#include "elf-vxworks.h" /* Get the ECOFF swapping routines. */ #include "coff/sym.h" @@ -1319,10 +1320,12 @@ mips_elf32_rtype_to_howto (unsigned int r_type, static void mips_info_to_howto_rel (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst) { + const struct elf_backend_data *bed; unsigned int r_type; r_type = ELF32_R_TYPE (dst->r_info); - cache_ptr->howto = mips_elf32_rtype_to_howto (r_type, FALSE); + bed = get_elf_backend_data (abfd); + cache_ptr->howto = bed->elf_backend_mips_rtype_to_howto (r_type, FALSE); /* The addend for a GPREL16 or LITERAL relocation comes from the GP value for the object file. We get the addend now, rather than @@ -1619,3 +1622,147 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = { /* Include the target file again for this target. */ #include "elf32-target.h" + + +/* Specific to VxWorks. */ +static reloc_howto_type mips_vxworks_copy_howto_rela = + HOWTO (R_MIPS_COPY, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_MIPS_COPY", /* name */ + FALSE, /* partial_inplace */ + 0x0, /* src_mask */ + 0x0, /* dst_mask */ + FALSE); /* pcrel_offset */ + +/* Specific to VxWorks. */ +static reloc_howto_type mips_vxworks_jump_slot_howto_rela = + HOWTO (R_MIPS_JUMP_SLOT, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_MIPS_JUMP_SLOT", /* name */ + FALSE, /* partial_inplace */ + 0x0, /* src_mask */ + 0x0, /* dst_mask */ + FALSE); /* pcrel_offset */ + +/* Implement elf_backend_bfd_reloc_type_lookup for VxWorks. */ + +static reloc_howto_type * +mips_vxworks_bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code) +{ + switch (code) + { + case BFD_RELOC_MIPS_COPY: + return &mips_vxworks_copy_howto_rela; + case BFD_RELOC_MIPS_JUMP_SLOT: + return &mips_vxworks_jump_slot_howto_rela; + default: + return bfd_elf32_bfd_reloc_type_lookup (abfd, code); + } +} + +/* Implement elf_backend_mips_rtype_to_lookup for VxWorks. */ + +static reloc_howto_type * +mips_vxworks_rtype_to_howto (unsigned int r_type, bfd_boolean rela_p) +{ + switch (r_type) + { + case R_MIPS_COPY: + return &mips_vxworks_copy_howto_rela; + case R_MIPS_JUMP_SLOT: + return &mips_vxworks_jump_slot_howto_rela; + default: + return mips_elf32_rtype_to_howto (r_type, rela_p); + } +} + +/* Implement elf_backend_final_write_processing for VxWorks. */ + +static void +mips_vxworks_final_write_processing (bfd *abfd, bfd_boolean linker) +{ + _bfd_mips_elf_final_write_processing (abfd, linker); + elf_vxworks_final_write_processing (abfd, linker); +} + +#undef TARGET_LITTLE_SYM +#undef TARGET_LITTLE_NAME +#undef TARGET_BIG_SYM +#undef TARGET_BIG_NAME + +#define TARGET_LITTLE_SYM bfd_elf32_littlemips_vxworks_vec +#define TARGET_LITTLE_NAME "elf32-littlemips-vxworks" +#define TARGET_BIG_SYM bfd_elf32_bigmips_vxworks_vec +#define TARGET_BIG_NAME "elf32-bigmips-vxworks" + +#undef elf32_bed +#define elf32_bed elf32_mips_vxworks_bed + +#undef ELF_MAXPAGESIZE +#define ELF_MAXPAGESIZE 0x1000 + +#undef elf_backend_want_got_plt +#define elf_backend_want_got_plt 1 +#undef elf_backend_want_plt_sym +#define elf_backend_want_plt_sym 1 +#undef elf_backend_got_symbol_offset +#define elf_backend_got_symbol_offset 0 +#undef elf_backend_want_dynbss +#define elf_backend_want_dynbss 1 +#undef elf_backend_may_use_rel_p +#define elf_backend_may_use_rel_p 0 +#undef elf_backend_may_use_rela_p +#define elf_backend_may_use_rela_p 1 +#undef elf_backend_default_use_rela_p +#define elf_backend_default_use_rela_p 1 +#undef elf_backend_got_header_size +#define elf_backend_got_header_size (4 * 3) +#undef elf_backend_plt_readonly +#define elf_backend_plt_readonly 1 + +#undef bfd_elf32_bfd_reloc_type_lookup +#define bfd_elf32_bfd_reloc_type_lookup \ + mips_vxworks_bfd_reloc_type_lookup +#undef elf_backend_mips_rtype_to_howto +#define elf_backend_mips_rtype_to_howto \ + mips_vxworks_rtype_to_howto +#undef elf_backend_adjust_dynamic_symbol +#define elf_backend_adjust_dynamic_symbol \ + _bfd_mips_vxworks_adjust_dynamic_symbol +#undef elf_backend_finish_dynamic_symbol +#define elf_backend_finish_dynamic_symbol \ + _bfd_mips_vxworks_finish_dynamic_symbol +#undef bfd_elf32_bfd_link_hash_table_create +#define bfd_elf32_bfd_link_hash_table_create \ + _bfd_mips_vxworks_link_hash_table_create +#undef elf_backend_add_symbol_hook +#define elf_backend_add_symbol_hook \ + elf_vxworks_add_symbol_hook +#undef elf_backend_link_output_symbol_hook +#define elf_backend_link_output_symbol_hook \ + elf_vxworks_link_output_symbol_hook +#undef elf_backend_emit_relocs +#define elf_backend_emit_relocs \ + elf_vxworks_emit_relocs +#undef elf_backend_final_write_processing +#define elf_backend_final_write_processing \ + mips_vxworks_final_write_processing + +#undef elf_backend_additional_program_headers +#undef elf_backend_modify_segment_map +#undef elf_backend_symbol_processing +/* NOTE: elf_backend_rela_normal is not defined for MIPS. */ + +#include "elf32-target.h" diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index 6f6b4a2e6c7..b5af3b1526e 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -34,6 +34,7 @@ #include "elf-bfd.h" #include "elfxx-mips.h" #include "elf/mips.h" +#include "elf-vxworks.h" /* Get the ECOFF swapping routines. */ #include "coff/sym.h" @@ -246,6 +247,12 @@ struct mips_elf_link_hash_entry the initial global GOT entry to a local GOT entry. */ bfd_boolean forced_local; + /* Are we referenced by some kind of relocation? */ + bfd_boolean is_relocation_target; + + /* Are we referenced by branch relocations? */ + bfd_boolean is_branch_target; + #define GOT_NORMAL 0 #define GOT_TLS_GD 1 #define GOT_TLS_LDM 2 @@ -283,6 +290,20 @@ struct mips_elf_link_hash_table bfd_vma rld_value; /* This is set if we see any mips16 stub sections. */ bfd_boolean mips16_stubs_seen; + /* True if we're generating code for VxWorks. */ + bfd_boolean is_vxworks; + /* Shortcuts to some dynamic sections, or NULL if they are not + being used. */ + asection *srelbss; + asection *sdynbss; + asection *srelplt; + asection *srelplt2; + asection *sgotplt; + asection *splt; + /* The size of the PLT header in bytes (VxWorks only). */ + bfd_vma plt_header_size; + /* The size of a PLT entry in bytes (VxWorks only). */ + bfd_vma plt_entry_size; }; #define TLS_RELOC_P(r_type) \ @@ -433,8 +454,8 @@ typedef struct runtime_pdr { #define rpdNil ((pRPDR) 0) static struct mips_got_entry *mips_elf_create_local_got_entry - (bfd *, bfd *, struct mips_got_info *, asection *, bfd_vma, unsigned long, - struct mips_elf_link_hash_entry *, int); + (bfd *, struct bfd_link_info *, bfd *, struct mips_got_info *, asection *, + asection *, bfd_vma, unsigned long, struct mips_elf_link_hash_entry *, int); static bfd_boolean mips_elf_sort_hash_table_f (struct mips_elf_link_hash_entry *, void *); static bfd_vma mips_elf_high @@ -490,6 +511,10 @@ static bfd *reldyn_sorting_bfd; #define MIPS_ELF_REL_SIZE(abfd) \ (get_elf_backend_data (abfd)->s->sizeof_rel) +/* The size of an external RELA relocation. */ +#define MIPS_ELF_RELA_SIZE(abfd) \ + (get_elf_backend_data (abfd)->s->sizeof_rela) + /* The size of an external dynamic table entry. */ #define MIPS_ELF_DYN_SIZE(abfd) \ (get_elf_backend_data (abfd)->s->sizeof_dyn) @@ -540,20 +565,26 @@ static bfd *reldyn_sorting_bfd; == (ABI_64_P (abfd) ? sizeof (Elf64_External_Rela) \ : sizeof (Elf32_External_Rela)))) +/* The name of the dynamic relocation section. */ +#define MIPS_ELF_REL_DYN_NAME(INFO) \ + (mips_elf_hash_table (INFO)->is_vxworks ? ".rela.dyn" : ".rel.dyn") + /* In case we're on a 32-bit machine, construct a 64-bit "-1" value from smaller values. Start with zero, widen, *then* decrement. */ #define MINUS_ONE (((bfd_vma)0) - 1) #define MINUS_TWO (((bfd_vma)0) - 2) /* The number of local .got entries we reserve. */ -#define MIPS_RESERVED_GOTNO (2) +#define MIPS_RESERVED_GOTNO(INFO) \ + (mips_elf_hash_table (INFO)->is_vxworks ? 3 : 2) /* The offset of $gp from the beginning of the .got section. */ -#define ELF_MIPS_GP_OFFSET(abfd) (0x7ff0) +#define ELF_MIPS_GP_OFFSET(INFO) \ + (mips_elf_hash_table (INFO)->is_vxworks ? 0x0 : 0x7ff0) /* The maximum size of the GOT for it to be addressable using 16-bit offsets from $gp. */ -#define MIPS_ELF_GOT_MAX_SIZE(abfd) (ELF_MIPS_GP_OFFSET(abfd) + 0x7fff) +#define MIPS_ELF_GOT_MAX_SIZE(INFO) (ELF_MIPS_GP_OFFSET (INFO) + 0x7fff) /* Instructions which appear in a stub. */ #define STUB_LW(abfd) \ @@ -636,6 +667,44 @@ static bfd *reldyn_sorting_bfd; #define CALL_STUB ".mips16.call." #define CALL_FP_STUB ".mips16.call.fp." +/* The format of the first PLT entry in a VxWorks executable. */ +static const bfd_vma mips_vxworks_exec_plt0_entry[] = { + 0x3c190000, /* lui t9, %hi(_GLOBAL_OFFSET_TABLE_) */ + 0x27390000, /* addiu t9, t9, %lo(_GLOBAL_OFFSET_TABLE_) */ + 0x8f390008, /* lw t9, 8(t9) */ + 0x00000000, /* nop */ + 0x03200008, /* jr t9 */ + 0x00000000 /* nop */ +}; + +/* The format of subsequent PLT entries. */ +static const bfd_vma mips_vxworks_exec_plt_entry[] = { + 0x10000000, /* b .PLT_resolver */ + 0x24180000, /* li t8, */ + 0x3c190000, /* lui t9, %hi(<.got.plt slot>) */ + 0x27390000, /* addiu t9, t9, %lo(<.got.plt slot>) */ + 0x8f390000, /* lw t9, 0(t9) */ + 0x00000000, /* nop */ + 0x03200008, /* jr t9 */ + 0x00000000 /* nop */ +}; + +/* The format of the first PLT entry in a VxWorks shared object. */ +static const bfd_vma mips_vxworks_shared_plt0_entry[] = { + 0x8f990008, /* lw t9, 8(gp) */ + 0x00000000, /* nop */ + 0x03200008, /* jr t9 */ + 0x00000000, /* nop */ + 0x00000000, /* nop */ + 0x00000000 /* nop */ +}; + +/* The format of subsequent PLT entries. */ +static const bfd_vma mips_vxworks_shared_plt_entry[] = { + 0x10000000, /* b .PLT_resolver */ + 0x24180000 /* li t8, */ +}; + /* Look up an entry in a MIPS ELF linker hash table. */ #define mips_elf_link_hash_lookup(table, string, create, copy, follow) \ @@ -715,6 +784,8 @@ mips_elf_link_hash_newfunc (struct bfd_hash_entry *entry, ret->call_stub = NULL; ret->call_fp_stub = NULL; ret->forced_local = FALSE; + ret->is_branch_target = FALSE; + ret->is_relocation_target = FALSE; ret->tls_type = GOT_NORMAL; } @@ -1896,14 +1967,19 @@ mips_elf_multi_got_entry_eq (const void *entry1, const void *entry2) : e1->d.h == e2->d.h); } -/* Returns the dynamic relocation section for DYNOBJ. */ +/* Return the dynamic relocation section. If it doesn't exist, try to + create a new it if CREATE_P, otherwise return NULL. Also return NULL + if creation fails. */ static asection * -mips_elf_rel_dyn_section (bfd *dynobj, bfd_boolean create_p) +mips_elf_rel_dyn_section (struct bfd_link_info *info, bfd_boolean create_p) { - static const char dname[] = ".rel.dyn"; + const char *dname; asection *sreloc; + bfd *dynobj; + dname = MIPS_ELF_REL_DYN_NAME (info); + dynobj = elf_hash_table (info)->dynobj; sreloc = bfd_get_section_by_name (dynobj, dname); if (sreloc == NULL && create_p) { @@ -2121,7 +2197,7 @@ mips_elf_initialize_tls_slots (bfd *abfd, bfd_vma got_offset, || h->root.root.type == bfd_link_hash_undefweak); /* Emit necessary relocations. */ - sreloc = mips_elf_rel_dyn_section (dynobj, FALSE); + sreloc = mips_elf_rel_dyn_section (info, FALSE); /* General Dynamic. */ if (*tls_type_p & GOT_TLS_GD) @@ -2240,14 +2316,46 @@ mips_tls_got_index (bfd *abfd, bfd_vma got_index, unsigned char *tls_type, return got_index; } -/* Returns the GOT offset at which the indicated address can be found. - If there is not yet a GOT entry for this value, create one. If - R_SYMNDX refers to a TLS symbol, create a TLS GOT entry instead. - Returns -1 if no satisfactory GOT offset can be found. */ +/* Return the offset from _GLOBAL_OFFSET_TABLE_ of the .got.plt entry + for global symbol H. .got.plt comes before the GOT, so the offset + will be negative. */ + +static bfd_vma +mips_elf_gotplt_index (struct bfd_link_info *info, + struct elf_link_hash_entry *h) +{ + bfd_vma plt_index, got_address, got_value; + struct mips_elf_link_hash_table *htab; + + htab = mips_elf_hash_table (info); + BFD_ASSERT (h->plt.offset != (bfd_vma) -1); + + /* Calculate the index of the symbol's PLT entry. */ + plt_index = (h->plt.offset - htab->plt_header_size) / htab->plt_entry_size; + + /* Calculate the address of the associated .got.plt entry. */ + got_address = (htab->sgotplt->output_section->vma + + htab->sgotplt->output_offset + + plt_index * 4); + + /* Calculate the value of _GLOBAL_OFFSET_TABLE_. */ + got_value = (htab->root.hgot->root.u.def.section->output_section->vma + + htab->root.hgot->root.u.def.section->output_offset + + htab->root.hgot->root.u.def.value); + + return got_address - got_value; +} + +/* Return the GOT offset for address VALUE, which was derived from + a symbol belonging to INPUT_SECTION. If there is not yet a GOT + entry for this value, create one. If R_SYMNDX refers to a TLS symbol, + create a TLS GOT entry instead. Return -1 if no satisfactory GOT + offset can be found. */ static bfd_vma mips_elf_local_got_index (bfd *abfd, bfd *ibfd, struct bfd_link_info *info, - bfd_vma value, unsigned long r_symndx, + asection *input_section, bfd_vma value, + unsigned long r_symndx, struct mips_elf_link_hash_entry *h, int r_type) { asection *sgot; @@ -2256,7 +2364,8 @@ mips_elf_local_got_index (bfd *abfd, bfd *ibfd, struct bfd_link_info *info, g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot); - entry = mips_elf_create_local_got_entry (abfd, ibfd, g, sgot, value, + entry = mips_elf_create_local_got_entry (abfd, info, ibfd, g, sgot, + input_section, value, r_symndx, h, r_type); if (!entry) return MINUS_ONE; @@ -2350,26 +2459,27 @@ mips_elf_global_got_index (bfd *abfd, bfd *ibfd, struct elf_link_hash_entry *h, return index; } -/* Find a GOT entry that is within 32KB of the VALUE. These entries - are supposed to be placed at small offsets in the GOT, i.e., - within 32KB of GP. Return the index into the GOT for this page, - and store the offset from this entry to the desired address in - OFFSETP, if it is non-NULL. */ +/* Find a GOT page entry that points to within 32KB of VALUE, which was + calculated from a symbol belonging to INPUT_SECTION. These entries + are supposed to be placed at small offsets in the GOT, i.e., within + 32KB of GP. Return the index of the GOT entry, or -1 if no entry + could be created. If OFFSETP is nonnull, use it to return the + offset of the GOT entry from VALUE. */ static bfd_vma mips_elf_got_page (bfd *abfd, bfd *ibfd, struct bfd_link_info *info, - bfd_vma value, bfd_vma *offsetp) + asection *input_section, bfd_vma value, bfd_vma *offsetp) { asection *sgot; struct mips_got_info *g; - bfd_vma index; + bfd_vma page, index; struct mips_got_entry *entry; g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot); - entry = mips_elf_create_local_got_entry (abfd, ibfd, g, sgot, - (value + 0x8000) - & (~(bfd_vma)0xffff), 0, + page = (value + 0x8000) & ~(bfd_vma) 0xffff; + entry = mips_elf_create_local_got_entry (abfd, info, ibfd, g, sgot, + input_section, page, 0, NULL, R_MIPS_GOT_PAGE); if (!entry) @@ -2383,30 +2493,32 @@ mips_elf_got_page (bfd *abfd, bfd *ibfd, struct bfd_link_info *info, return index; } -/* Find a GOT entry whose higher-order 16 bits are the same as those - for value. Return the index into the GOT for this entry. */ +/* Find a local GOT entry for an R_MIPS_GOT16 relocation against VALUE, + which was calculated from a symbol belonging to INPUT_SECTION. + EXTERNAL is true if the relocation was against a global symbol + that has been forced local. */ static bfd_vma mips_elf_got16_entry (bfd *abfd, bfd *ibfd, struct bfd_link_info *info, - bfd_vma value, bfd_boolean external) + asection *input_section, bfd_vma value, + bfd_boolean external) { asection *sgot; struct mips_got_info *g; struct mips_got_entry *entry; + /* GOT16 relocations against local symbols are followed by a LO16 + relocation; those against global symbols are not. Thus if the + symbol was originally local, the GOT16 relocation should load the + equivalent of %hi(VALUE), otherwise it should load VALUE itself. */ if (! external) - { - /* Although the ABI says that it is "the high-order 16 bits" that we - want, it is really the %high value. The complete value is - calculated with a `addiu' of a LO16 relocation, just as with a - HI16/LO16 pair. */ - value = mips_elf_high (value) << 16; - } + value = mips_elf_high (value) << 16; g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot); - entry = mips_elf_create_local_got_entry (abfd, ibfd, g, sgot, value, 0, NULL, - R_MIPS_GOT16); + entry = mips_elf_create_local_got_entry (abfd, info, ibfd, g, sgot, + input_section, value, 0, + NULL, R_MIPS_GOT16); if (entry) return entry->gotidx; else @@ -2431,20 +2543,24 @@ mips_elf_got_offset_from_index (bfd *dynobj, bfd *output_bfd, return sgot->output_section->vma + sgot->output_offset + index - gp; } -/* Create a local GOT entry for VALUE. Return the index of the entry, - or -1 if it could not be created. If R_SYMNDX refers to a TLS symbol, - create a TLS entry instead. */ +/* Create and return a local GOT entry for VALUE, which was calculated + from a symbol belonging to INPUT_SECTON. Return NULL if it could not + be created. If R_SYMNDX refers to a TLS symbol, create a TLS entry + instead. */ static struct mips_got_entry * -mips_elf_create_local_got_entry (bfd *abfd, bfd *ibfd, - struct mips_got_info *gg, - asection *sgot, bfd_vma value, - unsigned long r_symndx, +mips_elf_create_local_got_entry (bfd *abfd, struct bfd_link_info *info, + bfd *ibfd, struct mips_got_info *gg, + asection *sgot, asection *input_section, + bfd_vma value, unsigned long r_symndx, struct mips_elf_link_hash_entry *h, int r_type) { struct mips_got_entry entry, **loc; struct mips_got_info *g; + struct mips_elf_link_hash_table *htab; + + htab = mips_elf_hash_table (info); entry.abfd = NULL; entry.symndx = -1; @@ -2517,6 +2633,33 @@ mips_elf_create_local_got_entry (bfd *abfd, bfd *ibfd, MIPS_ELF_PUT_WORD (abfd, value, (sgot->contents + entry.gotidx)); + /* These GOT entries need a dynamic relocation on VxWorks. Because + the offset between segments is not fixed, the relocation must be + against a symbol in the same segment as the original symbol. + The easiest way to do this is to take INPUT_SECTION's output + section and emit a relocation against its section symbol. */ + if (htab->is_vxworks) + { + Elf_Internal_Rela outrel; + asection *s, *output_section; + bfd_byte *loc; + bfd_vma got_address; + int dynindx; + + s = mips_elf_rel_dyn_section (info, FALSE); + output_section = input_section->output_section; + dynindx = elf_section_data (output_section)->dynindx; + got_address = (sgot->output_section->vma + + sgot->output_offset + + entry.gotidx); + + loc = s->contents + (s->reloc_count++ * sizeof (Elf32_External_Rela)); + outrel.r_offset = got_address; + outrel.r_info = ELF32_R_INFO (dynindx, R_MIPS_32); + outrel.r_addend = value - output_section->vma; + bfd_elf32_swap_reloca_out (abfd, &outrel, loc); + } + return *loc; } @@ -2892,7 +3035,7 @@ mips_elf_merge_gots (void **bfd2got_, void *p) { unsigned int primary_total = lcount + tcount + arg->global_count; if (primary_total * MIPS_ELF_GOT_SIZE (bfd2got->bfd) - >= MIPS_ELF_GOT_MAX_SIZE (bfd2got->bfd)) + >= MIPS_ELF_GOT_MAX_SIZE (arg->info)) too_many_for_tls = TRUE; } @@ -3207,9 +3350,9 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info, /* Taking out PAGES entries is a worst-case estimate. We could compute the maximum number of pages that each separate input bfd uses, but it's probably not worth it. */ - got_per_bfd_arg.max_count = ((MIPS_ELF_GOT_MAX_SIZE (abfd) + got_per_bfd_arg.max_count = ((MIPS_ELF_GOT_MAX_SIZE (info) / MIPS_ELF_GOT_SIZE (abfd)) - - MIPS_RESERVED_GOTNO - pages); + - MIPS_RESERVED_GOTNO (info) - pages); /* The number of globals that will be included in the primary GOT. See the calls to mips_elf_set_global_got_offset below for more information. */ @@ -3344,7 +3487,7 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info, { struct mips_got_info *gn; - assign += MIPS_RESERVED_GOTNO; + assign += MIPS_RESERVED_GOTNO (info); g->assigned_gotno = assign; g->local_gotno += assign + pages; assign = g->local_gotno + g->global_gotno + g->tls_gotno; @@ -3540,6 +3683,9 @@ mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info, struct bfd_link_hash_entry *bh; struct mips_got_info *g; bfd_size_type amt; + struct mips_elf_link_hash_table *htab; + + htab = mips_elf_hash_table (info); /* This function may be called more than once. */ s = mips_elf_got_section (abfd, TRUE); @@ -3589,8 +3735,8 @@ mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info, g->global_gotsym = NULL; g->global_gotno = 0; g->tls_gotno = 0; - g->local_gotno = MIPS_RESERVED_GOTNO; - g->assigned_gotno = MIPS_RESERVED_GOTNO; + g->local_gotno = MIPS_RESERVED_GOTNO (info); + g->assigned_gotno = MIPS_RESERVED_GOTNO (info); g->bfd2got = NULL; g->next = NULL; g->tls_ldm_offset = MINUS_ONE; @@ -3602,9 +3748,33 @@ mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info, mips_elf_section_data (s)->elf.this_hdr.sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL; + /* VxWorks also needs a .got.plt section. */ + if (htab->is_vxworks) + { + s = bfd_make_section_with_flags (abfd, ".got.plt", + SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS + | SEC_IN_MEMORY | SEC_LINKER_CREATED); + if (s == NULL || !bfd_set_section_alignment (abfd, s, 4)) + return FALSE; + + htab->sgotplt = s; + } return TRUE; } +/* Return true if H refers to the special VxWorks __GOTT_BASE__ or + __GOTT_INDEX__ symbols. These symbols are only special for + shared objects; they are not used in executables. */ + +static bfd_boolean +is_gott_symbol (struct bfd_link_info *info, struct elf_link_hash_entry *h) +{ + return (mips_elf_hash_table (info)->is_vxworks + && info->shared + && (strcmp (h->root.root.string, "__GOTT_BASE__") == 0 + || strcmp (h->root.root.string, "__GOTT_INDEX__") == 0)); +} + /* Calculate the value produced by the RELOCATION (which comes from the INPUT_BFD). The ADDEND is the addend to use for this RELOCATION; RELOCATION->R_ADDEND is ignored. @@ -3667,6 +3837,11 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, bfd_boolean overflowed_p; /* TRUE if this relocation refers to a MIPS16 function. */ bfd_boolean target_is_16_bit_code_p = FALSE; + struct mips_elf_link_hash_table *htab; + bfd *dynobj; + + dynobj = elf_hash_table (info)->dynobj; + htab = mips_elf_hash_table (info); /* Parse the relocation. */ r_symndx = ELF_R_SYM (input_bfd, relocation->r_info); @@ -3916,52 +4091,61 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, /* Find the index into the GOT where this value is located. */ if (r_type == R_MIPS_TLS_LDM) { - g = mips_elf_local_got_index (abfd, input_bfd, info, 0, 0, NULL, - r_type); + g = mips_elf_local_got_index (abfd, input_bfd, info, + sec, 0, 0, NULL, r_type); if (g == MINUS_ONE) return bfd_reloc_outofrange; } else if (!local_p) { - /* GOT_PAGE may take a non-zero addend, that is ignored in a - GOT_PAGE relocation that decays to GOT_DISP because the - symbol turns out to be global. The addend is then added - as GOT_OFST. */ - BFD_ASSERT (addend == 0 || r_type == R_MIPS_GOT_PAGE); - g = mips_elf_global_got_index (elf_hash_table (info)->dynobj, - input_bfd, - (struct elf_link_hash_entry *) h, - r_type, info); - if (h->tls_type == GOT_NORMAL - && (! elf_hash_table(info)->dynamic_sections_created - || (info->shared - && (info->symbolic || h->root.forced_local) - && h->root.def_regular))) + /* On VxWorks, CALL relocations should refer to the .got.plt + entry, which is initialized to point at the PLT stub. */ + if (htab->is_vxworks + && (r_type == R_MIPS_CALL_HI16 + || r_type == R_MIPS_CALL_LO16 + || r_type == R_MIPS_CALL16)) + { + BFD_ASSERT (addend == 0); + BFD_ASSERT (h->root.needs_plt); + g = mips_elf_gotplt_index (info, &h->root); + } + else { - /* This is a static link or a -Bsymbolic link. The - symbol is defined locally, or was forced to be local. - We must initialize this entry in the GOT. */ - bfd *tmpbfd = elf_hash_table (info)->dynobj; - asection *sgot = mips_elf_got_section (tmpbfd, FALSE); - MIPS_ELF_PUT_WORD (tmpbfd, symbol, sgot->contents + g); + /* GOT_PAGE may take a non-zero addend, that is ignored in a + GOT_PAGE relocation that decays to GOT_DISP because the + symbol turns out to be global. The addend is then added + as GOT_OFST. */ + BFD_ASSERT (addend == 0 || r_type == R_MIPS_GOT_PAGE); + g = mips_elf_global_got_index (dynobj, input_bfd, + &h->root, r_type, info); + if (h->tls_type == GOT_NORMAL + && (! elf_hash_table(info)->dynamic_sections_created + || (info->shared + && (info->symbolic || h->root.forced_local) + && h->root.def_regular))) + { + /* This is a static link or a -Bsymbolic link. The + symbol is defined locally, or was forced to be local. + We must initialize this entry in the GOT. */ + asection *sgot = mips_elf_got_section (dynobj, FALSE); + MIPS_ELF_PUT_WORD (dynobj, symbol, sgot->contents + g); + } } } - else if (r_type == R_MIPS_GOT16 || r_type == R_MIPS_CALL16) - /* There's no need to create a local GOT entry here; the - calculation for a local GOT16 entry does not involve G. */ + else if (!htab->is_vxworks + && (r_type == R_MIPS_CALL16 || (r_type == R_MIPS_GOT16))) + /* The calculation below does not involve "g". */ break; else { - g = mips_elf_local_got_index (abfd, input_bfd, - info, symbol + addend, r_symndx, h, - r_type); + g = mips_elf_local_got_index (abfd, input_bfd, info, sec, + symbol + addend, r_symndx, h, r_type); if (g == MINUS_ONE) return bfd_reloc_outofrange; } /* Convert GOT indices to actual offsets. */ - g = mips_elf_got_offset_from_index (elf_hash_table (info)->dynobj, - abfd, input_bfd, g); + g = mips_elf_got_offset_from_index (dynobj, abfd, input_bfd, g); break; case R_MIPS_HI16: @@ -3974,10 +4158,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, case R_MIPS16_GPREL: gp0 = _bfd_get_gp_value (input_bfd); gp = _bfd_get_gp_value (abfd); - if (elf_hash_table (info)->dynobj) - gp += mips_elf_adjust_gp (abfd, - mips_elf_got_info - (elf_hash_table (info)->dynobj, NULL), + if (dynobj) + gp += mips_elf_adjust_gp (abfd, mips_elf_got_info (dynobj, NULL), input_bfd); break; @@ -3988,6 +4170,27 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, if (gnu_local_gp_p) symbol = gp; + /* Relocations against the VxWorks __GOTT_BASE__ and __GOTT_INDEX__ + symbols are resolved by the loader. Add them to .rela.dyn. */ + if (h != NULL && is_gott_symbol (info, &h->root)) + { + Elf_Internal_Rela outrel; + bfd_byte *loc; + asection *s; + + s = mips_elf_rel_dyn_section (info, FALSE); + loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela); + + outrel.r_offset = (input_section->output_section->vma + + input_section->output_offset + + relocation->r_offset); + outrel.r_info = ELF32_R_INFO (h->root.dynindx, r_type); + outrel.r_addend = addend; + bfd_elf32_swap_reloca_out (abfd, &outrel, loc); + *valuep = 0; + return bfd_reloc_ok; + } + /* Figure out what kind of relocation is being performed. */ switch (r_type) { @@ -4003,7 +4206,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, case R_MIPS_REL32: case R_MIPS_64: if ((info->shared - || (elf_hash_table (info)->dynamic_sections_created + || (!htab->is_vxworks + && htab->root.dynamic_sections_created && h != NULL && h->root.def_dynamic && !h->root.def_regular)) @@ -4014,7 +4218,11 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, against a symbol in a shared library, then we can't know where the symbol will end up. So, we create a relocation record in the output, and leave the job up to the dynamic - linker. */ + linker. + + In VxWorks executables, references to external symbols + are handled using copy relocs or PLT stubs, so there's + no need to add a dynamic relocation here. */ value = addend; if (!mips_elf_create_dynamic_relocation (abfd, info, @@ -4166,22 +4374,20 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, case R_MIPS_GOT16: case R_MIPS_CALL16: - if (local_p) + /* VxWorks does not have separate local and global semantics for + R_MIPS_GOT16; every relocation evaluates to "G". */ + if (!htab->is_vxworks && local_p) { bfd_boolean forced; - /* The special case is when the symbol is forced to be local. We - need the full address in the GOT since no R_MIPS_LO16 relocation - follows. */ forced = ! mips_elf_local_relocation_p (input_bfd, relocation, local_sections, FALSE); - value = mips_elf_got16_entry (abfd, input_bfd, info, + value = mips_elf_got16_entry (abfd, input_bfd, info, sec, symbol + addend, forced); if (value == MINUS_ONE) return bfd_reloc_outofrange; value - = mips_elf_got_offset_from_index (elf_hash_table (info)->dynobj, - abfd, input_bfd, value); + = mips_elf_got_offset_from_index (dynobj, abfd, input_bfd, value); overflowed_p = mips_elf_overflow_p (value, 16); break; } @@ -4231,17 +4437,18 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, 0. */ if (! local_p) goto got_disp; - value = mips_elf_got_page (abfd, input_bfd, info, symbol + addend, NULL); + value = mips_elf_got_page (abfd, input_bfd, info, sec, + symbol + addend, NULL); if (value == MINUS_ONE) return bfd_reloc_outofrange; - value = mips_elf_got_offset_from_index (elf_hash_table (info)->dynobj, - abfd, input_bfd, value); + value = mips_elf_got_offset_from_index (dynobj, abfd, input_bfd, value); overflowed_p = mips_elf_overflow_p (value, 16); break; case R_MIPS_GOT_OFST: if (local_p) - mips_elf_got_page (abfd, input_bfd, info, symbol + addend, &value); + mips_elf_got_page (abfd, input_bfd, info, sec, + symbol + addend, &value); else value = addend; overflowed_p = mips_elf_overflow_p (value, 16); @@ -4426,23 +4633,31 @@ mips_elf_stub_section_p (bfd *abfd ATTRIBUTE_UNUSED, asection *section) || strncmp (name, CALL_FP_STUB, sizeof CALL_FP_STUB - 1) == 0); } -/* Add room for N relocations to the .rel.dyn section in ABFD. */ +/* Add room for N relocations to the .rel(a).dyn section in ABFD. */ static void -mips_elf_allocate_dynamic_relocations (bfd *abfd, unsigned int n) +mips_elf_allocate_dynamic_relocations (bfd *abfd, struct bfd_link_info *info, + unsigned int n) { asection *s; + struct mips_elf_link_hash_table *htab; - s = mips_elf_rel_dyn_section (abfd, FALSE); + htab = mips_elf_hash_table (info); + s = mips_elf_rel_dyn_section (info, FALSE); BFD_ASSERT (s != NULL); - if (s->size == 0) + if (htab->is_vxworks) + s->size += n * MIPS_ELF_RELA_SIZE (abfd); + else { - /* Make room for a null element. */ - s->size += MIPS_ELF_REL_SIZE (abfd); - ++s->reloc_count; + if (s->size == 0) + { + /* Make room for a null element. */ + s->size += MIPS_ELF_REL_SIZE (abfd); + ++s->reloc_count; + } + s->size += n * MIPS_ELF_REL_SIZE (abfd); } - s->size += n * MIPS_ELF_REL_SIZE (abfd); } /* Create a rel.dyn relocation for the dynamic linker to resolve. REL @@ -4464,10 +4679,12 @@ mips_elf_create_dynamic_relocation (bfd *output_bfd, int r_type; long indx; bfd_boolean defined_p; + struct mips_elf_link_hash_table *htab; + htab = mips_elf_hash_table (info); r_type = ELF_R_TYPE (output_bfd, rel->r_info); dynobj = elf_hash_table (info)->dynobj; - sreloc = mips_elf_rel_dyn_section (dynobj, FALSE); + sreloc = mips_elf_rel_dyn_section (info, FALSE); BFD_ASSERT (sreloc != NULL); BFD_ASSERT (sreloc->contents != NULL); BFD_ASSERT (sreloc->reloc_count * MIPS_ELF_REL_SIZE (output_bfd) @@ -4552,10 +4769,15 @@ mips_elf_create_dynamic_relocation (bfd *output_bfd, if (defined_p && r_type != R_MIPS_REL32) *addendp += symbol; - /* The relocation is always an REL32 relocation because we don't - know where the shared library will wind up at load-time. */ - outrel[0].r_info = ELF_R_INFO (output_bfd, (unsigned long) indx, - R_MIPS_REL32); + if (htab->is_vxworks) + /* VxWorks uses non-relative relocations for this. */ + outrel[0].r_info = ELF32_R_INFO (indx, R_MIPS_32); + else + /* The relocation is always an REL32 relocation because we don't + know where the shared library will wind up at load-time. */ + outrel[0].r_info = ELF_R_INFO (output_bfd, (unsigned long) indx, + R_MIPS_REL32); + /* For strict adherence to the ABI specification, we should generate a R_MIPS_64 relocation record by itself before the _REL32/_64 record as well, such that the addend is read in as @@ -4593,6 +4815,15 @@ mips_elf_create_dynamic_relocation (bfd *output_bfd, (sreloc->contents + sreloc->reloc_count * sizeof (Elf64_Mips_External_Rel))); } + else if (htab->is_vxworks) + { + /* VxWorks uses RELA rather than REL dynamic relocations. */ + outrel[0].r_addend = *addendp; + bfd_elf32_swap_reloca_out + (output_bfd, &outrel[0], + (sreloc->contents + + sreloc->reloc_count * sizeof (Elf32_External_Rela))); + } else bfd_elf32_swap_reloc_out (output_bfd, &outrel[0], @@ -5609,23 +5840,29 @@ _bfd_mips_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) flagword flags; register asection *s; const char * const *namep; + struct mips_elf_link_hash_table *htab; + htab = mips_elf_hash_table (info); flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED | SEC_READONLY); - /* Mips ABI requests the .dynamic section to be read only. */ - s = bfd_get_section_by_name (abfd, ".dynamic"); - if (s != NULL) + /* The psABI requires a read-only .dynamic section, but the VxWorks + EABI doesn't. */ + if (!htab->is_vxworks) { - if (! bfd_set_section_flags (abfd, s, flags)) - return FALSE; + s = bfd_get_section_by_name (abfd, ".dynamic"); + if (s != NULL) + { + if (! bfd_set_section_flags (abfd, s, flags)) + return FALSE; + } } /* We need to create .got section. */ if (! mips_elf_create_got_section (abfd, info, FALSE)) return FALSE; - if (! mips_elf_rel_dyn_section (elf_hash_table (info)->dynobj, TRUE)) + if (! mips_elf_rel_dyn_section (info, TRUE)) return FALSE; /* Create .stub section. */ @@ -5746,6 +5983,45 @@ _bfd_mips_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) } } + if (htab->is_vxworks) + { + /* Create the .plt, .rela.plt, .dynbss and .rela.bss sections. + Also create the _PROCEDURE_LINKAGE_TABLE symbol. */ + if (!_bfd_elf_create_dynamic_sections (abfd, info)) + return FALSE; + + /* Cache the sections created above. */ + htab->sdynbss = bfd_get_section_by_name (abfd, ".dynbss"); + htab->srelbss = bfd_get_section_by_name (abfd, ".rela.bss"); + htab->srelplt = bfd_get_section_by_name (abfd, ".rela.plt"); + htab->splt = bfd_get_section_by_name (abfd, ".plt"); + if (!htab->sdynbss + || (!htab->srelbss && !info->shared) + || !htab->srelplt + || !htab->splt) + abort (); + + /* Do the usual VxWorks handling. */ + if (!elf_vxworks_create_dynamic_sections (abfd, info, &htab->srelplt2)) + return FALSE; + + /* Work out the PLT sizes. */ + if (info->shared) + { + htab->plt_header_size + = 4 * ARRAY_SIZE (mips_vxworks_shared_plt0_entry); + htab->plt_entry_size + = 4 * ARRAY_SIZE (mips_vxworks_shared_plt_entry); + } + else + { + htab->plt_header_size + = 4 * ARRAY_SIZE (mips_vxworks_exec_plt0_entry); + htab->plt_entry_size + = 4 * ARRAY_SIZE (mips_vxworks_exec_plt_entry); + } + } + return TRUE; } @@ -5767,10 +6043,12 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sgot; asection *sreloc; const struct elf_backend_data *bed; + struct mips_elf_link_hash_table *htab; if (info->relocatable) return TRUE; + htab = mips_elf_hash_table (info); dynobj = elf_hash_table (info)->dynobj; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); @@ -6012,13 +6290,24 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, if (! mips_elf_create_got_section (dynobj, info, FALSE)) return FALSE; g = mips_elf_got_info (dynobj, &sgot); + if (htab->is_vxworks && !info->shared) + { + (*_bfd_error_handler) + (_("%B: GOT reloc at 0x%lx not expected in executables"), + abfd, (unsigned long) rel->r_offset); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } break; case R_MIPS_32: case R_MIPS_REL32: case R_MIPS_64: + /* In VxWorks executables, references to external symbols + are handled using copy relocs or PLT stubs, so there's + no need to add a dynamic relocation here. */ if (dynobj == NULL - && (info->shared || h != NULL) + && (info->shared || (h != NULL && !htab->is_vxworks)) && (sec->flags & SEC_ALLOC) != 0) elf_hash_table (info)->dynobj = dynobj = abfd; break; @@ -6028,15 +6317,35 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, } } - if (!h && (r_type == R_MIPS_CALL_LO16 - || r_type == R_MIPS_GOT_LO16 - || r_type == R_MIPS_GOT_DISP)) + if (h) + { + ((struct mips_elf_link_hash_entry *) h)->is_relocation_target = TRUE; + + /* Relocations against the special VxWorks __GOTT_BASE__ and + __GOTT_INDEX__ symbols must be left to the loader. Allocate + room for them in .rela.dyn. */ + if (is_gott_symbol (info, h)) + { + if (sreloc == NULL) + { + sreloc = mips_elf_rel_dyn_section (info, TRUE); + if (sreloc == NULL) + return FALSE; + } + mips_elf_allocate_dynamic_relocations (dynobj, info, 1); + } + } + else if (r_type == R_MIPS_CALL_LO16 + || r_type == R_MIPS_GOT_LO16 + || r_type == R_MIPS_GOT_DISP + || (r_type == R_MIPS_GOT16 && htab->is_vxworks)) { /* We may need a local GOT entry for this relocation. We don't count R_MIPS_GOT_PAGE because we can estimate the maximum number of pages needed by looking at the size of the segment. Similar comments apply to R_MIPS_GOT16 and - R_MIPS_CALL16. We don't count R_MIPS_GOT_HI16, or + R_MIPS_CALL16, except on VxWorks, where GOT relocations + always evaluate to "G". We don't count R_MIPS_GOT_HI16, or R_MIPS_CALL_HI16 because these are always followed by an R_MIPS_GOT_LO16 or R_MIPS_CALL_LO16. */ if (! mips_elf_record_local_got_symbol (abfd, r_symndx, @@ -6061,8 +6370,11 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_MIPS_CALL_LO16: if (h != NULL) { - /* This symbol requires a global offset table entry. */ - if (! mips_elf_record_global_got_symbol (h, abfd, info, g, 0)) + /* VxWorks call relocations point the function's .got.plt + entry, which will be allocated by adjust_dynamic_symbol. + Otherwise, this symbol requires a global GOT entry. */ + if (!htab->is_vxworks + && !mips_elf_record_global_got_symbol (h, abfd, info, g, 0)) return FALSE; /* We need a stub, not a plt entry for the undefined @@ -6148,12 +6460,15 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_MIPS_32: case R_MIPS_REL32: case R_MIPS_64: - if ((info->shared || h != NULL) + /* In VxWorks executables, references to external symbols + are handled using copy relocs or PLT stubs, so there's + no need to add a .rela.dyn entry for this relocation. */ + if ((info->shared || (h != NULL && !htab->is_vxworks)) && (sec->flags & SEC_ALLOC) != 0) { if (sreloc == NULL) { - sreloc = mips_elf_rel_dyn_section (dynobj, TRUE); + sreloc = mips_elf_rel_dyn_section (info, TRUE); if (sreloc == NULL) return FALSE; } @@ -6162,9 +6477,8 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, { /* When creating a shared object, we must copy these reloc types into the output file as R_MIPS_REL32 - relocs. We make room for this reloc in the - .rel.dyn reloc section. */ - mips_elf_allocate_dynamic_relocations (dynobj, 1); + relocs. Make room for this reloc in .rel(a).dyn. */ + mips_elf_allocate_dynamic_relocations (dynobj, info, 1); if ((sec->flags & MIPS_READONLY_SECTION) == MIPS_READONLY_SECTION) /* We tell the dynamic linker that there are @@ -6189,8 +6503,10 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, /* Even though we don't directly need a GOT entry for this symbol, a symbol must have a dynamic symbol table index greater that DT_MIPS_GOTSYM if there are - dynamic relocations against it. */ - if (h != NULL) + dynamic relocations against it. This does not apply + to VxWorks, which does not have the usual coupling + between global GOT entries and .dynsym entries. */ + if (h != NULL && !htab->is_vxworks) { if (dynobj == NULL) elf_hash_table (info)->dynobj = dynobj = abfd; @@ -6207,7 +6523,16 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, sizeof (Elf32_External_crinfo); break; + case R_MIPS_PC16: + if (h) + ((struct mips_elf_link_hash_entry *) h)->is_branch_target = TRUE; + break; + case R_MIPS_26: + if (h) + ((struct mips_elf_link_hash_entry *) h)->is_branch_target = TRUE; + /* Fall through. */ + case R_MIPS_GPREL16: case R_MIPS_LITERAL: case R_MIPS_GPREL32: @@ -6235,24 +6560,21 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, } /* We must not create a stub for a symbol that has relocations - related to taking the function's address. */ - switch (r_type) - { - default: - if (h != NULL) - { - struct mips_elf_link_hash_entry *mh; - - mh = (struct mips_elf_link_hash_entry *) h; - mh->no_fn_stub = TRUE; - } - break; - case R_MIPS_CALL16: - case R_MIPS_CALL_HI16: - case R_MIPS_CALL_LO16: - case R_MIPS_JALR: - break; - } + related to taking the function's address. This doesn't apply to + VxWorks, where CALL relocs refer to a .got.plt entry instead of + a normal .got entry. */ + if (!htab->is_vxworks && h != NULL) + switch (r_type) + { + default: + ((struct mips_elf_link_hash_entry *) h)->no_fn_stub = TRUE; + break; + case R_MIPS_CALL16: + case R_MIPS_CALL_HI16: + case R_MIPS_CALL_LO16: + case R_MIPS_JALR: + break; + } /* If this reloc is not a 16 bit call, and it has a global symbol, then we will need the fn_stub if there is one. @@ -6479,8 +6801,8 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info, && (h->root.type == bfd_link_hash_defweak || !h->def_regular)) { - mips_elf_allocate_dynamic_relocations (dynobj, - hmips->possibly_dynamic_relocs); + mips_elf_allocate_dynamic_relocations + (dynobj, info, hmips->possibly_dynamic_relocs); if (hmips->readonly_reloc) /* We tell the dynamic linker that there are relocations against the text segment. */ @@ -6545,6 +6867,160 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info, return TRUE; } + +/* Likewise, for VxWorks. */ + +bfd_boolean +_bfd_mips_vxworks_adjust_dynamic_symbol (struct bfd_link_info *info, + struct elf_link_hash_entry *h) +{ + bfd *dynobj; + struct mips_elf_link_hash_entry *hmips; + struct mips_elf_link_hash_table *htab; + unsigned int power_of_two; + + htab = mips_elf_hash_table (info); + dynobj = elf_hash_table (info)->dynobj; + hmips = (struct mips_elf_link_hash_entry *) h; + + /* Make sure we know what is going on here. */ + BFD_ASSERT (dynobj != NULL + && (h->needs_plt + || h->needs_copy + || h->u.weakdef != NULL + || (h->def_dynamic + && h->ref_regular + && !h->def_regular))); + + /* If the symbol is defined by a dynamic object, we need a PLT stub if + either (a) we want to branch to the symbol or (b) we're linking an + executable that needs a canonical function address. In the latter + case, the canonical address will be the address of the executable's + load stub. */ + if ((hmips->is_branch_target + || (!info->shared + && h->type == STT_FUNC + && hmips->is_relocation_target)) + && h->def_dynamic + && h->ref_regular + && !h->def_regular + && !h->forced_local) + h->needs_plt = 1; + + /* Locally-binding symbols do not need a PLT stub; we can refer to + the functions directly. */ + else if (h->needs_plt + && (SYMBOL_CALLS_LOCAL (info, h) + || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT + && h->root.type == bfd_link_hash_undefweak))) + { + h->needs_plt = 0; + return TRUE; + } + + if (h->needs_plt) + { + /* If this is the first symbol to need a PLT entry, allocate room + for the header, and for the header's .rela.plt.unloaded entries. */ + if (htab->splt->size == 0) + { + htab->splt->size += htab->plt_header_size; + if (!info->shared) + htab->srelplt2->size += 2 * sizeof (Elf32_External_Rela); + } + + /* Assign the next .plt entry to this symbol. */ + h->plt.offset = htab->splt->size; + htab->splt->size += htab->plt_entry_size; + + /* If the output file has no definition of the symbol, set the + symbol's value to the address of the stub. For executables, + point at the PLT load stub rather than the lazy resolution stub; + this stub will become the canonical function address. */ + if (!h->def_regular) + { + h->root.u.def.section = htab->splt; + h->root.u.def.value = h->plt.offset; + if (!info->shared) + h->root.u.def.value += 8; + } + + /* Make room for the .got.plt entry and the R_JUMP_SLOT relocation. */ + htab->sgotplt->size += 4; + htab->srelplt->size += sizeof (Elf32_External_Rela); + + /* Make room for the .rela.plt.unloaded relocations. */ + if (!info->shared) + htab->srelplt2->size += 3 * sizeof (Elf32_External_Rela); + + return TRUE; + } + + /* If a function symbol is defined by a dynamic object, and we do not + need a PLT stub for it, the symbol's value should be zero. */ + if (h->type == STT_FUNC + && h->def_dynamic + && h->ref_regular + && !h->def_regular) + { + h->root.u.def.value = 0; + return TRUE; + } + + /* If this is a weak symbol, and there is a real definition, the + processor independent code will have arranged for us to see the + real definition first, and we can just use the same value. */ + if (h->u.weakdef != NULL) + { + BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined + || h->u.weakdef->root.type == bfd_link_hash_defweak); + h->root.u.def.section = h->u.weakdef->root.u.def.section; + h->root.u.def.value = h->u.weakdef->root.u.def.value; + return TRUE; + } + + /* This is a reference to a symbol defined by a dynamic object which + is not a function. */ + if (info->shared) + return TRUE; + + /* We must allocate the symbol in our .dynbss section, which will + become part of the .bss section of the executable. There will be + an entry for this symbol in the .dynsym section. The dynamic + object will contain position independent code, so all references + from the dynamic object to this symbol will go through the global + offset table. The dynamic linker will use the .dynsym entry to + determine the address it must put in the global offset table, so + both the dynamic object and the regular object will refer to the + same memory location for the variable. */ + + if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) + { + htab->srelbss->size += sizeof (Elf32_External_Rela); + h->needs_copy = 1; + } + + /* We need to figure out the alignment required for this symbol. */ + power_of_two = bfd_log2 (h->size); + if (power_of_two > 4) + power_of_two = 4; + + /* Apply the required alignment. */ + htab->sdynbss->size = BFD_ALIGN (htab->sdynbss->size, + (bfd_size_type) 1 << power_of_two); + if (power_of_two > bfd_get_section_alignment (dynobj, htab->sdynbss) + && !bfd_set_section_alignment (dynobj, htab->sdynbss, power_of_two)) + return FALSE; + + /* Define the symbol as being at this point in the section. */ + h->root.u.def.section = htab->sdynbss; + h->root.u.def.value = htab->sdynbss->size; + + /* Increment the section size to make room for the symbol. */ + htab->sdynbss->size += h->size; + + return TRUE; +} /* This function is called after all the input files have been read, and the input sections have been assigned to output sections. We @@ -6564,6 +7040,9 @@ _bfd_mips_elf_always_size_sections (bfd *output_bfd, bfd_size_type local_gotno; bfd *sub; struct mips_elf_count_tls_arg count_tls_arg; + struct mips_elf_link_hash_table *htab; + + htab = mips_elf_hash_table (info); /* The .reginfo section has a fixed size. */ ri = bfd_get_section_by_name (output_bfd, ".reginfo"); @@ -6622,9 +7101,15 @@ _bfd_mips_elf_always_size_sections (bfd *output_bfd, rld. */ loadable_size += MIPS_FUNCTION_STUB_SIZE * (i + 1); - /* Assume there are two loadable segments consisting of - contiguous sections. Is 5 enough? */ - local_gotno = (loadable_size >> 16) + 5; + if (htab->is_vxworks) + /* There's no need to allocate page entries for VxWorks; R_MIPS_GOT16 + relocations against local symbols evaluate to "G", and the EABI does + not include R_MIPS_GOT_PAGE. */ + local_gotno = 0; + else + /* Assume there are two loadable segments consisting of contiguous + sections. Is 5 enough? */ + local_gotno = (loadable_size >> 16) + 5; g->local_gotno += local_gotno; s->size += g->local_gotno * MIPS_ELF_GOT_SIZE (output_bfd); @@ -6645,7 +7130,10 @@ _bfd_mips_elf_always_size_sections (bfd *output_bfd, mips_elf_resolve_final_got_entries (g); - if (s->size > MIPS_ELF_GOT_MAX_SIZE (output_bfd)) + /* VxWorks does not support multiple GOTs. It initializes $gp to + __GOTT_BASE__[__GOTT_INDEX__], the value of which is set by the + dynamic loader. */ + if (!htab->is_vxworks && s->size > MIPS_ELF_GOT_MAX_SIZE (info)) { if (! mips_elf_multi_got (output_bfd, info, g, s, local_gotno)) return FALSE; @@ -6667,9 +7155,11 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) { bfd *dynobj; - asection *s; + asection *s, *sreldyn; bfd_boolean reltext; + struct mips_elf_link_hash_table *htab; + htab = mips_elf_hash_table (info); dynobj = elf_hash_table (info)->dynobj; BFD_ASSERT (dynobj != NULL); @@ -6691,6 +7181,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd, determined the sizes of the various dynamic sections. Allocate memory for them. */ reltext = FALSE; + sreldyn = NULL; for (s = dynobj->sections; s != NULL; s = s->next) { const char *name; @@ -6711,7 +7202,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd, /* If this relocation section applies to a read only section, then we probably need a DT_TEXTREL entry. - If the relocation section is .rel.dyn, we always + If the relocation section is .rel(a).dyn, we always assert a DT_TEXTREL entry rather than testing whether there exists a relocation to a read only section or not. */ @@ -6721,12 +7212,12 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd, if ((target != NULL && (target->flags & SEC_READONLY) != 0 && (target->flags & SEC_ALLOC) != 0) - || strcmp (outname, ".rel.dyn") == 0) + || strcmp (outname, MIPS_ELF_REL_DYN_NAME (info)) == 0) reltext = TRUE; /* We use the reloc_count field as a counter if we need to copy relocs into the output file. */ - if (strcmp (name, ".rel.dyn") != 0) + if (strcmp (name, MIPS_ELF_REL_DYN_NAME (info)) != 0) s->reloc_count = 0; /* If combreloc is enabled, elf_link_sort_relocs() will @@ -6738,7 +7229,23 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd, info->combreloc = 0; } } - else if (strncmp (name, ".got", 4) == 0) + else if (htab->is_vxworks && strcmp (name, ".got") == 0) + { + /* Executables do not need a GOT. */ + if (info->shared) + { + /* Allocate relocations for all but the reserved entries. */ + struct mips_got_info *g; + unsigned int count; + + g = mips_elf_got_info (dynobj, NULL); + count = (g->global_gotno + + g->local_gotno + - MIPS_RESERVED_GOTNO (info)); + mips_elf_allocate_dynamic_relocations (dynobj, info, count); + } + } + else if (!htab->is_vxworks && strncmp (name, ".got", 4) == 0) { /* _bfd_mips_elf_always_size_sections() has already done most of the work, but some symbols may have been mapped @@ -6783,7 +7290,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd, BFD_ASSERT (g->assigned_gotno == g->next->local_gotno + g->next->global_gotno + g->next->tls_gotno - + MIPS_RESERVED_GOTNO); + + MIPS_RESERVED_GOTNO (info)); } } } @@ -6803,7 +7310,8 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd, } if (needed_relocs) - mips_elf_allocate_dynamic_relocations (dynobj, needed_relocs); + mips_elf_allocate_dynamic_relocations (dynobj, info, + needed_relocs); } else if (strcmp (name, MIPS_ELF_STUB_SECTION_NAME (output_bfd)) == 0) { @@ -6822,7 +7330,9 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd, else if (SGI_COMPAT (output_bfd) && strncmp (name, ".compact_rel", 12) == 0) s->size += mips_elf_hash_table (info)->compact_rel_size; - else if (strncmp (name, ".init", 5) != 0) + else if (strncmp (name, ".init", 5) != 0 + && s != htab->sgotplt + && s != htab->splt) { /* It's not one of our sections, so don't allocate space. */ continue; @@ -6837,6 +7347,14 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd, if ((s->flags & SEC_HAS_CONTENTS) == 0) continue; + /* Allocate memory for this section last, since we may increase its + size above. */ + if (strcmp (name, MIPS_ELF_REL_DYN_NAME (info)) == 0) + { + sreldyn = s; + continue; + } + /* Allocate memory for the section contents. */ s->contents = bfd_zalloc (dynobj, s->size); if (s->contents == NULL) @@ -6846,6 +7364,17 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd, } } + /* Allocate memory for the .rel(a).dyn section. */ + if (sreldyn != NULL) + { + sreldyn->contents = bfd_zalloc (dynobj, sreldyn->size); + if (sreldyn->contents == NULL) + { + bfd_set_error (bfd_error_no_memory); + return FALSE; + } + } + if (elf_hash_table (info)->dynamic_sections_created) { /* Add some entries to the .dynamic section. We fill in the @@ -6875,7 +7404,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd, } } - if (reltext && SGI_COMPAT (output_bfd)) + if (reltext && (SGI_COMPAT (output_bfd) || htab->is_vxworks)) info->flags |= DF_TEXTREL; if ((info->flags & DF_TEXTREL) != 0) @@ -6887,48 +7416,78 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd, if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTGOT, 0)) return FALSE; - if (mips_elf_rel_dyn_section (dynobj, FALSE)) + if (htab->is_vxworks) { - if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_REL, 0)) - return FALSE; + /* VxWorks uses .rela.dyn instead of .rel.dyn. It does not + use any of the DT_MIPS_* tags. */ + if (mips_elf_rel_dyn_section (info, FALSE)) + { + if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELA, 0)) + return FALSE; - if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELSZ, 0)) - return FALSE; + if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELASZ, 0)) + return FALSE; - if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELENT, 0)) - return FALSE; + if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELAENT, 0)) + return FALSE; + } + if (htab->splt->size > 0) + { + if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTREL, 0)) + return FALSE; + + if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_JMPREL, 0)) + return FALSE; + + if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTRELSZ, 0)) + return FALSE; + } } + else + { + if (mips_elf_rel_dyn_section (info, FALSE)) + { + if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_REL, 0)) + return FALSE; - if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_RLD_VERSION, 0)) - return FALSE; + if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELSZ, 0)) + return FALSE; - if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_FLAGS, 0)) - return FALSE; + if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELENT, 0)) + return FALSE; + } - if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_BASE_ADDRESS, 0)) - return FALSE; + if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_RLD_VERSION, 0)) + return FALSE; - if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_LOCAL_GOTNO, 0)) - return FALSE; + if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_FLAGS, 0)) + return FALSE; - if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_SYMTABNO, 0)) - return FALSE; + if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_BASE_ADDRESS, 0)) + return FALSE; - if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_UNREFEXTNO, 0)) - return FALSE; + if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_LOCAL_GOTNO, 0)) + return FALSE; - if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_GOTSYM, 0)) - return FALSE; + if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_SYMTABNO, 0)) + return FALSE; - if (IRIX_COMPAT (dynobj) == ict_irix5 - && ! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_HIPAGENO, 0)) - return FALSE; + if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_UNREFEXTNO, 0)) + return FALSE; - if (IRIX_COMPAT (dynobj) == ict_irix6 - && (bfd_get_section_by_name - (dynobj, MIPS_ELF_OPTIONS_SECTION_NAME (dynobj))) - && !MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_OPTIONS, 0)) - return FALSE; + if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_GOTSYM, 0)) + return FALSE; + + if (IRIX_COMPAT (dynobj) == ict_irix5 + && ! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_HIPAGENO, 0)) + return FALSE; + + if (IRIX_COMPAT (dynobj) == ict_irix6 + && (bfd_get_section_by_name + (dynobj, MIPS_ELF_OPTIONS_SECTION_NAME (dynobj))) + && !MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_OPTIONS, 0)) + return FALSE; + } } return TRUE; @@ -7584,6 +8143,268 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd, return TRUE; } +/* Likewise, for VxWorks. */ + +bfd_boolean +_bfd_mips_vxworks_finish_dynamic_symbol (bfd *output_bfd, + struct bfd_link_info *info, + struct elf_link_hash_entry *h, + Elf_Internal_Sym *sym) +{ + bfd *dynobj; + asection *sgot; + struct mips_got_info *g; + struct mips_elf_link_hash_table *htab; + + htab = mips_elf_hash_table (info); + dynobj = elf_hash_table (info)->dynobj; + + if (h->plt.offset != (bfd_vma) -1) + { + char *loc; + bfd_vma plt_address, plt_index, got_address, got_offset, branch_offset; + Elf_Internal_Rela rel; + static const bfd_vma *plt_entry; + + BFD_ASSERT (h->dynindx != -1); + BFD_ASSERT (htab->splt != NULL); + BFD_ASSERT (h->plt.offset <= htab->splt->size); + + /* Calculate the address of the .plt entry. */ + plt_address = (htab->splt->output_section->vma + + htab->splt->output_offset + + h->plt.offset); + + /* Calculate the index of the entry. */ + plt_index = ((h->plt.offset - htab->plt_header_size) + / htab->plt_entry_size); + + /* Calculate the address of the .got.plt entry. */ + got_address = (htab->sgotplt->output_section->vma + + htab->sgotplt->output_offset + + plt_index * 4); + + /* Calculate the offset of the .got.plt entry from + _GLOBAL_OFFSET_TABLE_. */ + got_offset = mips_elf_gotplt_index (info, h); + + /* Calculate the offset for the branch at the start of the PLT + entry. The branch jumps to the beginning of .plt. */ + branch_offset = -(h->plt.offset / 4 + 1) & 0xffff; + + /* Fill in the initial value of the .got.plt entry. */ + bfd_put_32 (output_bfd, plt_address, + htab->sgotplt->contents + plt_index * 4); + + /* Find out where the .plt entry should go. */ + loc = htab->splt->contents + h->plt.offset; + + if (info->shared) + { + plt_entry = mips_vxworks_shared_plt_entry; + bfd_put_32 (output_bfd, plt_entry[0] | branch_offset, loc); + bfd_put_32 (output_bfd, plt_entry[1] | plt_index, loc + 4); + } + else + { + bfd_vma got_address_high, got_address_low; + + plt_entry = mips_vxworks_exec_plt_entry; + got_address_high = ((got_address + 0x8000) >> 16) & 0xffff; + got_address_low = got_address & 0xffff; + + bfd_put_32 (output_bfd, plt_entry[0] | branch_offset, loc); + bfd_put_32 (output_bfd, plt_entry[1] | plt_index, loc + 4); + bfd_put_32 (output_bfd, plt_entry[2] | got_address_high, loc + 8); + bfd_put_32 (output_bfd, plt_entry[3] | got_address_low, loc + 12); + bfd_put_32 (output_bfd, plt_entry[4], loc + 16); + bfd_put_32 (output_bfd, plt_entry[5], loc + 20); + bfd_put_32 (output_bfd, plt_entry[6], loc + 24); + bfd_put_32 (output_bfd, plt_entry[7], loc + 28); + + loc = (htab->srelplt2->contents + + (plt_index * 3 + 2) * sizeof (Elf32_External_Rela)); + + /* Emit a relocation for the .got.plt entry. */ + rel.r_offset = got_address; + rel.r_info = ELF32_R_INFO (htab->root.hplt->indx, R_MIPS_32); + rel.r_addend = h->plt.offset; + bfd_elf32_swap_reloca_out (output_bfd, &rel, loc); + + /* Emit a relocation for the lui of %hi(<.got.plt slot>). */ + loc += sizeof (Elf32_External_Rela); + rel.r_offset = plt_address + 8; + rel.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_MIPS_HI16); + rel.r_addend = got_offset; + bfd_elf32_swap_reloca_out (output_bfd, &rel, loc); + + /* Emit a relocation for the addiu of %lo(<.got.plt slot>). */ + loc += sizeof (Elf32_External_Rela); + rel.r_offset += 4; + rel.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_MIPS_LO16); + bfd_elf32_swap_reloca_out (output_bfd, &rel, loc); + } + + /* Emit an R_MIPS_JUMP_SLOT relocation against the .got.plt entry. */ + loc = htab->srelplt->contents + plt_index * sizeof (Elf32_External_Rela); + rel.r_offset = got_address; + rel.r_info = ELF32_R_INFO (h->dynindx, R_MIPS_JUMP_SLOT); + rel.r_addend = 0; + bfd_elf32_swap_reloca_out (output_bfd, &rel, loc); + + if (!h->def_regular) + sym->st_shndx = SHN_UNDEF; + } + + BFD_ASSERT (h->dynindx != -1 || h->forced_local); + + sgot = mips_elf_got_section (dynobj, FALSE); + BFD_ASSERT (sgot != NULL); + BFD_ASSERT (mips_elf_section_data (sgot) != NULL); + g = mips_elf_section_data (sgot)->u.got_info; + BFD_ASSERT (g != NULL); + + /* See if this symbol has an entry in the GOT. */ + if (g->global_gotsym != NULL + && h->dynindx >= g->global_gotsym->dynindx) + { + bfd_vma offset; + Elf_Internal_Rela outrel; + bfd_byte *loc; + asection *s; + + /* Install the symbol value in the GOT. */ + offset = mips_elf_global_got_index (dynobj, output_bfd, h, + R_MIPS_GOT16, info); + MIPS_ELF_PUT_WORD (output_bfd, sym->st_value, sgot->contents + offset); + + /* Add a dynamic relocation for it. */ + s = mips_elf_rel_dyn_section (info, FALSE); + loc = s->contents + (s->reloc_count++ * sizeof (Elf32_External_Rela)); + outrel.r_offset = (sgot->output_section->vma + + sgot->output_offset + + offset); + outrel.r_info = ELF32_R_INFO (h->dynindx, R_MIPS_32); + outrel.r_addend = 0; + bfd_elf32_swap_reloca_out (dynobj, &outrel, loc); + } + + /* Emit a copy reloc, if needed. */ + if (h->needs_copy) + { + Elf_Internal_Rela rel; + + BFD_ASSERT (h->dynindx != -1); + + rel.r_offset = (h->root.u.def.section->output_section->vma + + h->root.u.def.section->output_offset + + h->root.u.def.value); + rel.r_info = ELF32_R_INFO (h->dynindx, R_MIPS_COPY); + rel.r_addend = 0; + bfd_elf32_swap_reloca_out (output_bfd, &rel, + htab->srelbss->contents + + (htab->srelbss->reloc_count + * sizeof (Elf32_External_Rela))); + ++htab->srelbss->reloc_count; + } + + /* If this is a mips16 symbol, force the value to be even. */ + if (sym->st_other == STO_MIPS16) + sym->st_value &= ~1; + + return TRUE; +} + +/* Install the PLT header for a VxWorks executable and finalize the + contents of .rela.plt.unloaded. */ + +static void +mips_vxworks_finish_exec_plt (bfd *output_bfd, struct bfd_link_info *info) +{ + Elf_Internal_Rela rela; + bfd_byte *loc; + bfd_vma got_value, got_value_high, got_value_low, plt_address; + static const bfd_vma *plt_entry; + struct mips_elf_link_hash_table *htab; + + htab = mips_elf_hash_table (info); + plt_entry = mips_vxworks_exec_plt0_entry; + + /* Calculate the value of _GLOBAL_OFFSET_TABLE_. */ + got_value = (htab->root.hgot->root.u.def.section->output_section->vma + + htab->root.hgot->root.u.def.section->output_offset + + htab->root.hgot->root.u.def.value); + + got_value_high = ((got_value + 0x8000) >> 16) & 0xffff; + got_value_low = got_value & 0xffff; + + /* Calculate the address of the PLT header. */ + plt_address = htab->splt->output_section->vma + htab->splt->output_offset; + + /* Install the PLT header. */ + loc = htab->splt->contents; + bfd_put_32 (output_bfd, plt_entry[0] | got_value_high, loc); + bfd_put_32 (output_bfd, plt_entry[1] | got_value_low, loc + 4); + bfd_put_32 (output_bfd, plt_entry[2], loc + 8); + bfd_put_32 (output_bfd, plt_entry[3], loc + 12); + bfd_put_32 (output_bfd, plt_entry[4], loc + 16); + bfd_put_32 (output_bfd, plt_entry[5], loc + 20); + + /* Output the relocation for the lui of %hi(_GLOBAL_OFFSET_TABLE_). */ + loc = htab->srelplt2->contents; + rela.r_offset = plt_address; + rela.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_MIPS_HI16); + rela.r_addend = 0; + bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); + loc += sizeof (Elf32_External_Rela); + + /* Output the relocation for the following addiu of + %lo(_GLOBAL_OFFSET_TABLE_). */ + rela.r_offset += 4; + rela.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_MIPS_LO16); + bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); + loc += sizeof (Elf32_External_Rela); + + /* Fix up the remaining relocations. They may have the wrong + symbol index for _G_O_T_ or _P_L_T_ depending on the order + in which symbols were output. */ + while (loc < htab->srelplt2->contents + htab->srelplt2->size) + { + Elf_Internal_Rela rel; + + bfd_elf32_swap_reloca_in (output_bfd, loc, &rel); + rel.r_info = ELF32_R_INFO (htab->root.hplt->indx, R_MIPS_32); + bfd_elf32_swap_reloca_out (output_bfd, &rel, loc); + loc += sizeof (Elf32_External_Rela); + + bfd_elf32_swap_reloca_in (output_bfd, loc, &rel); + rel.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_MIPS_HI16); + bfd_elf32_swap_reloca_out (output_bfd, &rel, loc); + loc += sizeof (Elf32_External_Rela); + + bfd_elf32_swap_reloca_in (output_bfd, loc, &rel); + rel.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_MIPS_LO16); + bfd_elf32_swap_reloca_out (output_bfd, &rel, loc); + loc += sizeof (Elf32_External_Rela); + } +} + +/* Install the PLT header for a VxWorks shared library. */ + +static void +mips_vxworks_finish_shared_plt (bfd *output_bfd, struct bfd_link_info *info) +{ + unsigned int i; + struct mips_elf_link_hash_table *htab; + + htab = mips_elf_hash_table (info); + + /* We just need to copy the entry byte-by-byte. */ + for (i = 0; i < ARRAY_SIZE (mips_vxworks_shared_plt0_entry); i++) + bfd_put_32 (output_bfd, mips_vxworks_shared_plt0_entry[i], + htab->splt->contents + i * 4); +} + /* Finish up the dynamic sections. */ bfd_boolean @@ -7594,7 +8415,9 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd, asection *sdyn; asection *sgot; struct mips_got_info *gg, *g; + struct mips_elf_link_hash_table *htab; + htab = mips_elf_hash_table (info); dynobj = elf_hash_table (info)->dynobj; sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); @@ -7637,11 +8460,14 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd, switch (dyn.d_tag) { case DT_RELENT: - s = mips_elf_rel_dyn_section (dynobj, FALSE); - BFD_ASSERT (s != NULL); dyn.d_un.d_val = MIPS_ELF_REL_SIZE (dynobj); break; + case DT_RELAENT: + BFD_ASSERT (htab->is_vxworks); + dyn.d_un.d_val = MIPS_ELF_RELA_SIZE (dynobj); + break; + case DT_STRSZ: /* Rewrite DT_STRSZ. */ dyn.d_un.d_val = @@ -7650,9 +8476,20 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd, case DT_PLTGOT: name = ".got"; - s = bfd_get_section_by_name (output_bfd, name); - BFD_ASSERT (s != NULL); - dyn.d_un.d_ptr = s->vma; + if (htab->is_vxworks) + { + /* _GLOBAL_OFFSET_TABLE_ is defined to be the beginning + of the ".got" section in DYNOBJ. */ + s = bfd_get_section_by_name (dynobj, name); + BFD_ASSERT (s != NULL); + dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; + } + else + { + s = bfd_get_section_by_name (output_bfd, name); + BFD_ASSERT (s != NULL); + dyn.d_un.d_ptr = s->vma; + } break; case DT_MIPS_RLD_VERSION: @@ -7718,7 +8555,7 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd, break; case DT_MIPS_HIPAGENO: - dyn.d_un.d_val = g->local_gotno - MIPS_RESERVED_GOTNO; + dyn.d_un.d_val = g->local_gotno - MIPS_RESERVED_GOTNO (info); break; case DT_MIPS_RLD_MAP: @@ -7731,6 +8568,29 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd, dyn.d_un.d_ptr = s->vma; break; + case DT_RELASZ: + BFD_ASSERT (htab->is_vxworks); + /* The count does not include the JUMP_SLOT relocations. */ + if (htab->srelplt) + dyn.d_un.d_val -= htab->srelplt->size; + break; + + case DT_PLTREL: + BFD_ASSERT (htab->is_vxworks); + dyn.d_un.d_val = DT_RELA; + break; + + case DT_PLTRELSZ: + BFD_ASSERT (htab->is_vxworks); + dyn.d_un.d_val = htab->srelplt->size; + break; + + case DT_JMPREL: + BFD_ASSERT (htab->is_vxworks); + dyn.d_un.d_val = (htab->srelplt->output_section->vma + + htab->srelplt->output_offset); + break; + default: swap_out_p = FALSE; break; @@ -7742,14 +8602,33 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd, } } - /* The first entry of the global offset table will be filled at - runtime. The second entry will be used by some runtime loaders. - This isn't the case of IRIX rld. */ if (sgot != NULL && sgot->size > 0) { - MIPS_ELF_PUT_WORD (output_bfd, 0, sgot->contents); - MIPS_ELF_PUT_WORD (output_bfd, 0x80000000, - sgot->contents + MIPS_ELF_GOT_SIZE (output_bfd)); + if (htab->is_vxworks) + { + /* The first entry of the global offset table points to the + ".dynamic" section. The second is initialized by the + loader and contains the shared library identifier. + The third is also initialized by the loader and points + to the lazy resolution stub. */ + MIPS_ELF_PUT_WORD (output_bfd, + sdyn->output_offset + sdyn->output_section->vma, + sgot->contents); + MIPS_ELF_PUT_WORD (output_bfd, 0, + sgot->contents + MIPS_ELF_GOT_SIZE (output_bfd)); + MIPS_ELF_PUT_WORD (output_bfd, 0, + sgot->contents + + 2 * MIPS_ELF_GOT_SIZE (output_bfd)); + } + else + { + /* The first entry of the global offset table will be filled at + runtime. The second entry will be used by some runtime loaders. + This isn't the case of IRIX rld. */ + MIPS_ELF_PUT_WORD (output_bfd, (bfd_vma) 0, sgot->contents); + MIPS_ELF_PUT_WORD (output_bfd, (bfd_vma) 0x80000000, + sgot->contents + MIPS_ELF_GOT_SIZE (output_bfd)); + } } if (sgot != NULL) @@ -7823,7 +8702,7 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd, decided not to make. This is for the n64 irix rld, which doesn't seem to apply any relocations if there are trailing null entries. */ - s = mips_elf_rel_dyn_section (dynobj, FALSE); + s = mips_elf_rel_dyn_section (info, FALSE); dyn.d_un.d_val = (s->reloc_count * (ABI_64_P (output_bfd) ? sizeof (Elf64_Mips_External_Rel) @@ -7877,24 +8756,37 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd, } } - /* We need to sort the entries of the dynamic relocation section. */ - - s = mips_elf_rel_dyn_section (dynobj, FALSE); - - if (s != NULL - && s->size > (bfd_vma)2 * MIPS_ELF_REL_SIZE (output_bfd)) + /* The psABI says that the dynamic relocations must be sorted in + increasing order of r_symndx. The VxWorks EABI doesn't require + this, and because the code below handles REL rather than RELA + relocations, using it for VxWorks would be outright harmful. */ + if (!htab->is_vxworks) { - reldyn_sorting_bfd = output_bfd; + s = mips_elf_rel_dyn_section (info, FALSE); + if (s != NULL + && s->size > (bfd_vma)2 * MIPS_ELF_REL_SIZE (output_bfd)) + { + reldyn_sorting_bfd = output_bfd; - if (ABI_64_P (output_bfd)) - qsort ((Elf64_External_Rel *) s->contents + 1, s->reloc_count - 1, - sizeof (Elf64_Mips_External_Rel), sort_dynamic_relocs_64); - else - qsort ((Elf32_External_Rel *) s->contents + 1, s->reloc_count - 1, - sizeof (Elf32_External_Rel), sort_dynamic_relocs); + if (ABI_64_P (output_bfd)) + qsort ((Elf64_External_Rel *) s->contents + 1, + s->reloc_count - 1, sizeof (Elf64_Mips_External_Rel), + sort_dynamic_relocs_64); + else + qsort ((Elf32_External_Rel *) s->contents + 1, + s->reloc_count - 1, sizeof (Elf32_External_Rel), + sort_dynamic_relocs); + } } } + if (htab->is_vxworks && htab->splt->size > 0) + { + if (info->shared) + mips_vxworks_finish_shared_plt (output_bfd, info); + else + mips_vxworks_finish_exec_plt (output_bfd, info); + } return TRUE; } @@ -8962,9 +9854,36 @@ _bfd_mips_elf_link_hash_table_create (bfd *abfd) ret->use_rld_obj_head = FALSE; ret->rld_value = 0; ret->mips16_stubs_seen = FALSE; + ret->is_vxworks = FALSE; + ret->srelbss = NULL; + ret->sdynbss = NULL; + ret->srelplt = NULL; + ret->srelplt2 = NULL; + ret->sgotplt = NULL; + ret->splt = NULL; + ret->plt_header_size = 0; + ret->plt_entry_size = 0; return &ret->root.root; } + +/* Likewise, but indicate that the target is VxWorks. */ + +struct bfd_link_hash_table * +_bfd_mips_vxworks_link_hash_table_create (bfd *abfd) +{ + struct bfd_link_hash_table *ret; + + ret = _bfd_mips_elf_link_hash_table_create (abfd); + if (ret) + { + struct mips_elf_link_hash_table *htab; + + htab = (struct mips_elf_link_hash_table *) ret; + htab->is_vxworks = 1; + } + return ret; +} /* We need to use a special link routine to handle the .reginfo and the .mdebug sections. We need to merge all instances of these @@ -8987,6 +9906,7 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info) EXTR esym; unsigned int i; bfd_size_type amt; + struct mips_elf_link_hash_table *htab; static const char * const secname[] = { @@ -9003,6 +9923,7 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info) generic size_dynamic_sections renumbered them out from under us. Rather than trying somehow to prevent the renumbering, just do the sort again. */ + htab = mips_elf_hash_table (info); if (elf_hash_table (info)->dynamic_sections_created) { bfd *dynobj; @@ -9053,6 +9974,14 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info) elf_gp (abfd) = (h->u.def.value + h->u.def.section->output_section->vma + h->u.def.section->output_offset); + else if (htab->is_vxworks + && (h = bfd_link_hash_lookup (info->hash, + "_GLOBAL_OFFSET_TABLE_", + FALSE, FALSE, TRUE)) + && h->type == bfd_link_hash_defined) + elf_gp (abfd) = (h->u.def.section->output_section->vma + + h->u.def.section->output_offset + + h->u.def.value); else if (info->relocatable) { bfd_vma lo = MINUS_ONE; @@ -9064,7 +9993,7 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info) lo = o->vma; /* And calculate GP relative to that. */ - elf_gp (abfd) = lo + ELF_MIPS_GP_OFFSET (abfd); + elf_gp (abfd) = lo + ELF_MIPS_GP_OFFSET (info); } else { @@ -9796,6 +10725,12 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) new_flags &= ~EF_MIPS_UCODE; old_flags &= ~EF_MIPS_UCODE; + /* Don't care about the PIC flags from dynamic objects; they are + PIC by design. */ + if ((new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0 + && (ibfd->flags & DYNAMIC) != 0) + new_flags &= ~ (EF_MIPS_PIC | EF_MIPS_CPIC); + if (new_flags == old_flags) return TRUE; diff --git a/bfd/elfxx-mips.h b/bfd/elfxx-mips.h index 07e661d81c0..6c3c9a30f6e 100644 --- a/bfd/elfxx-mips.h +++ b/bfd/elfxx-mips.h @@ -48,6 +48,8 @@ extern bfd_boolean _bfd_mips_elf_check_relocs (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *); extern bfd_boolean _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *, struct elf_link_hash_entry *); +extern bfd_boolean _bfd_mips_vxworks_adjust_dynamic_symbol + (struct bfd_link_info *, struct elf_link_hash_entry *); extern bfd_boolean _bfd_mips_elf_always_size_sections (bfd *, struct bfd_link_info *); extern bfd_boolean _bfd_mips_elf_size_dynamic_sections @@ -58,6 +60,9 @@ extern bfd_boolean _bfd_mips_elf_relocate_section extern bfd_boolean _bfd_mips_elf_finish_dynamic_symbol (bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, Elf_Internal_Sym *); +extern bfd_boolean _bfd_mips_vxworks_finish_dynamic_symbol + (bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, + Elf_Internal_Sym *); extern bfd_boolean _bfd_mips_elf_finish_dynamic_sections (bfd *, struct bfd_link_info *); extern void _bfd_mips_elf_final_write_processing @@ -90,6 +95,8 @@ extern bfd_byte *_bfd_elf_mips_get_relocated_section_contents bfd_byte *, bfd_boolean, asymbol **); extern struct bfd_link_hash_table *_bfd_mips_elf_link_hash_table_create (bfd *); +extern struct bfd_link_hash_table *_bfd_mips_vxworks_link_hash_table_create + (bfd *); extern bfd_boolean _bfd_mips_elf_final_link (bfd *, struct bfd_link_info *); extern bfd_boolean _bfd_mips_elf_merge_private_bfd_data diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 6d48036f823..0c188688cd4 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -972,6 +972,9 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_MIPS_TLS_TPREL_HI16", "BFD_RELOC_MIPS_TLS_TPREL_LO16", + "BFD_RELOC_MIPS_COPY", + "BFD_RELOC_MIPS_JUMP_SLOT", + "BFD_RELOC_FRV_LABEL16", "BFD_RELOC_FRV_LABEL24", "BFD_RELOC_FRV_LO16", diff --git a/bfd/reloc.c b/bfd/reloc.c index 31314e7246f..d0c3f304341 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -2139,6 +2139,14 @@ ENUMDOC MIPS ELF relocations. COMMENT +ENUM + BFD_RELOC_MIPS_COPY +ENUMX + BFD_RELOC_MIPS_JUMP_SLOT +ENUMDOC + MIPS ELF relocations (VxWorks extensions). +COMMENT + ENUM BFD_RELOC_FRV_LABEL16 ENUMX diff --git a/bfd/targets.c b/bfd/targets.c index 99f300644d1..0cbddb30795 100644 --- a/bfd/targets.c +++ b/bfd/targets.c @@ -560,6 +560,7 @@ extern const bfd_target bfd_elf32_bigarm_vec; extern const bfd_target bfd_elf32_bigarm_symbian_vec; extern const bfd_target bfd_elf32_bigarm_vxworks_vec; extern const bfd_target bfd_elf32_bigmips_vec; +extern const bfd_target bfd_elf32_bigmips_vxworks_vec; extern const bfd_target bfd_elf32_cr16c_vec; extern const bfd_target bfd_elf32_cris_vec; extern const bfd_target bfd_elf32_crx_vec; @@ -590,6 +591,7 @@ extern const bfd_target bfd_elf32_littlearm_vec; extern const bfd_target bfd_elf32_littlearm_symbian_vec; extern const bfd_target bfd_elf32_littlearm_vxworks_vec; extern const bfd_target bfd_elf32_littlemips_vec; +extern const bfd_target bfd_elf32_littlemips_vxworks_vec; extern const bfd_target bfd_elf32_m32c_vec; extern const bfd_target bfd_elf32_m32r_vec; extern const bfd_target bfd_elf32_m32rle_vec; @@ -863,6 +865,7 @@ static const bfd_target * const _bfd_target_vector[] = { &bfd_elf32_bigarm_symbian_vec, &bfd_elf32_bigarm_vxworks_vec, &bfd_elf32_bigmips_vec, + &bfd_elf32_bigmips_vxworks_vec, &bfd_elf32_cr16c_vec, &bfd_elf32_cris_vec, &bfd_elf32_crx_vec, @@ -897,6 +900,7 @@ static const bfd_target * const _bfd_target_vector[] = { &bfd_elf32_littlearm_symbian_vec, &bfd_elf32_littlearm_vxworks_vec, &bfd_elf32_littlemips_vec, + &bfd_elf32_littlemips_vxworks_vec, &bfd_elf32_m32c_vec, &bfd_elf32_m32r_vec, &bfd_elf32_m32rle_vec, diff --git a/gas/ChangeLog b/gas/ChangeLog index 10a88e5398d..4b5091f4cb1 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,26 @@ +2006-03-22 Richard Sandiford + Daniel Jacobowitz + Phil Edwards + Zack Weinberg + Mark Mitchell + Nathan Sidwell + + * config/tc-mips.c (mips_target_format): Handle vxworks targets. + (md_begin): Complain about -G being used for PIC. Don't change + the text, data and bss alignments on VxWorks. + (reloc_needs_lo_p): Don't return true for R_MIPS_GOT16 when + generating VxWorks PIC. + (load_address): Extend SVR4_PIC handling to VXWORKS_PIC. + (macro): Likewise, but do not treat la $25 specially for + VxWorks PIC, and do not handle jal. + (OPTION_MVXWORKS_PIC): New macro. + (md_longopts): Add -mvxworks-pic. + (md_parse_option): Don't complain about using PIC and -G together here. + Handle OPTION_MVXWORKS_PIC. + (md_estimate_size_before_relax): Always use the first relaxation + sequence on VxWorks. + * config/tc-mips.h (VXWORKS_PIC): New. + 2006-03-21 Paul Brook * config/tc-arm.c (md_apply_fix): Fix typo in offset mask. diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index 557fb4007c1..89416c9b488 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -1191,6 +1191,12 @@ mips_target_format (void) case bfd_target_coff_flavour: return "pe-mips"; case bfd_target_elf_flavour: +#ifdef TE_VXWORKS + if (!HAVE_64BIT_OBJECTS && !HAVE_NEWABI) + return (target_big_endian + ? "elf32-bigmips-vxworks" + : "elf32-littlemips-vxworks"); +#endif #ifdef TE_TMIPS /* This is traditional mips. */ return (target_big_endian @@ -1397,6 +1403,13 @@ md_begin (void) int i = 0; int broken = 0; + if (mips_pic != NO_PIC) + { + if (g_switch_seen && g_switch_value != 0) + as_bad (_("-G may not be used in position-independent code")); + g_switch_value = 0; + } + if (! bfd_set_arch_mach (stdoutput, bfd_arch_mips, file_mips_arch)) as_warn (_("Could not set architecture and machine")); @@ -1524,10 +1537,11 @@ md_begin (void) if (OUTPUT_FLAVOR == bfd_target_elf_flavour) { - /* On a native system, sections must be aligned to 16 byte - boundaries. When configured for an embedded ELF target, we - don't bother. */ - if (strcmp (TARGET_OS, "elf") != 0) + /* On a native system other than VxWorks, sections must be aligned + to 16 byte boundaries. When configured for an embedded ELF + target, we don't bother. */ + if (strcmp (TARGET_OS, "elf") != 0 + && strcmp (TARGET_OS, "vxworks") != 0) { (void) bfd_set_section_alignment (stdoutput, text_section, 4); (void) bfd_set_section_alignment (stdoutput, data_section, 4); @@ -1680,16 +1694,18 @@ md_assemble (char *str) } /* Return true if the given relocation might need a matching %lo(). - Note that R_MIPS_GOT16 relocations only need a matching %lo() when - applied to local symbols. */ + This is only "might" because SVR4 R_MIPS_GOT16 relocations only + need a matching %lo() when applied to local symbols. */ static inline bfd_boolean reloc_needs_lo_p (bfd_reloc_code_real_type reloc) { return (HAVE_IN_PLACE_ADDENDS && (reloc == BFD_RELOC_HI16_S - || reloc == BFD_RELOC_MIPS_GOT16 - || reloc == BFD_RELOC_MIPS16_HI16_S)); + || reloc == BFD_RELOC_MIPS16_HI16_S + /* VxWorks R_MIPS_GOT16 relocs never need a matching %lo(); + all GOT16 relocations evaluate to "G". */ + || (reloc == BFD_RELOC_MIPS_GOT16 && mips_pic != VXWORKS_PIC))); } /* Return true if the given fixup is followed by a matching R_MIPS_LO16 @@ -3898,7 +3914,7 @@ load_address (int reg, expressionS *ep, int *used_at) relax_end (); } } - else if (mips_pic == SVR4_PIC && ! mips_big_got) + else if (!mips_big_got) { expressionS ex; @@ -3959,7 +3975,7 @@ load_address (int reg, expressionS *ep, int *used_at) } } } - else if (mips_pic == SVR4_PIC) + else if (mips_big_got) { expressionS ex; @@ -5011,7 +5027,7 @@ macro (struct mips_cl_insn *ip) relax_end (); } } - else if (mips_pic == SVR4_PIC && ! mips_big_got && ! HAVE_NEWABI) + else if (!mips_big_got && !HAVE_NEWABI) { int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT16; @@ -5047,7 +5063,9 @@ macro (struct mips_cl_insn *ip) if (offset_expr.X_add_number == 0) { - if (breg == 0 && (call || tempreg == PIC_CALL_REG)) + if (mips_pic == SVR4_PIC + && breg == 0 + && (call || tempreg == PIC_CALL_REG)) lw_reloc_type = (int) BFD_RELOC_MIPS_CALL16; relax_start (offset_expr.X_add_symbol); @@ -5104,7 +5122,7 @@ macro (struct mips_cl_insn *ip) used_at = 1; } } - else if (mips_pic == SVR4_PIC && ! mips_big_got && HAVE_NEWABI) + else if (!mips_big_got && HAVE_NEWABI) { int add_breg_early = 0; @@ -5207,7 +5225,7 @@ macro (struct mips_cl_insn *ip) BFD_RELOC_MIPS_GOT_DISP, mips_gp_register); } } - else if (mips_pic == SVR4_PIC && ! HAVE_NEWABI) + else if (mips_big_got && !HAVE_NEWABI) { int gpdelay; int lui_reloc_type = (int) BFD_RELOC_MIPS_GOT_HI16; @@ -5364,7 +5382,7 @@ macro (struct mips_cl_insn *ip) } relax_end (); } - else if (mips_pic == SVR4_PIC && HAVE_NEWABI) + else if (mips_big_got && HAVE_NEWABI) { int lui_reloc_type = (int) BFD_RELOC_MIPS_GOT_HI16; int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT_LO16; @@ -5497,13 +5515,13 @@ macro (struct mips_cl_insn *ip) case M_JAL_2: if (mips_pic == NO_PIC) macro_build (NULL, "jalr", "d,s", dreg, sreg); - else if (mips_pic == SVR4_PIC) + else { if (sreg != PIC_CALL_REG) as_warn (_("MIPS PIC call to register other than $25")); macro_build (NULL, "jalr", "d,s", dreg, sreg); - if (! HAVE_NEWABI) + if (mips_pic == SVR4_PIC && !HAVE_NEWABI) { if (mips_cprestore_offset < 0) as_warn (_("No .cprestore pseudo-op used in PIC code")); @@ -5529,8 +5547,6 @@ macro (struct mips_cl_insn *ip) } } } - else - abort (); break; @@ -5666,6 +5682,8 @@ macro (struct mips_cl_insn *ip) } } } + else if (mips_pic == VXWORKS_PIC) + as_bad (_("Non-PIC jump used in PIC library")); else abort (); @@ -6026,7 +6044,7 @@ macro (struct mips_cl_insn *ip) relax_end (); } } - else if (mips_pic == SVR4_PIC && ! mips_big_got) + else if (!mips_big_got) { int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT16; @@ -6080,7 +6098,7 @@ macro (struct mips_cl_insn *ip) tempreg, tempreg, breg); macro_build (&expr1, s, fmt, treg, BFD_RELOC_LO16, tempreg); } - else if (mips_pic == SVR4_PIC && ! HAVE_NEWABI) + else if (mips_big_got && !HAVE_NEWABI) { int gpdelay; @@ -6129,7 +6147,7 @@ macro (struct mips_cl_insn *ip) tempreg, tempreg, breg); macro_build (&expr1, s, fmt, treg, BFD_RELOC_LO16, tempreg); } - else if (mips_pic == SVR4_PIC && HAVE_NEWABI) + else if (mips_big_got && HAVE_NEWABI) { /* If this is a reference to an external symbol, we want lui $tempreg, (BFD_RELOC_MIPS_GOT_HI16) @@ -6249,14 +6267,12 @@ macro (struct mips_cl_insn *ip) macro_build_lui (&offset_expr, AT); used_at = 1; } - else if (mips_pic == SVR4_PIC) + else { macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", AT, BFD_RELOC_MIPS_GOT16, mips_gp_register); used_at = 1; } - else - abort (); /* Now we load the register(s). */ if (HAVE_64BIT_GPRS) @@ -6328,7 +6344,7 @@ macro (struct mips_cl_insn *ip) { assert (strcmp (s, RDATA_SECTION_NAME) == 0); used_at = 1; - if (mips_pic == SVR4_PIC) + if (mips_pic != NO_PIC) macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", AT, BFD_RELOC_MIPS_GOT16, mips_gp_register); else @@ -6547,7 +6563,7 @@ macro (struct mips_cl_insn *ip) if (mips_relax.sequence) relax_end (); } - else if (mips_pic == SVR4_PIC && ! mips_big_got) + else if (!mips_big_got) { /* If this is a reference to an external symbol, we want lw $at,($gp) (BFD_RELOC_MIPS_GOT16) @@ -6594,7 +6610,7 @@ macro (struct mips_cl_insn *ip) mips_optimize = hold_mips_optimize; } - else if (mips_pic == SVR4_PIC) + else if (mips_big_got) { int gpdelay; @@ -10646,6 +10662,8 @@ struct option md_longopts[] = {"mpdr", no_argument, NULL, OPTION_PDR}, #define OPTION_NO_PDR (OPTION_ELF_BASE + 10) {"mno-pdr", no_argument, NULL, OPTION_NO_PDR}, +#define OPTION_MVXWORKS_PIC (OPTION_ELF_BASE + 11) + {"mvxworks-pic", no_argument, NULL, OPTION_MVXWORKS_PIC}, #endif /* OBJ_ELF */ {NULL, no_argument, NULL, 0} @@ -10887,12 +10905,6 @@ md_parse_option (int c, char *arg) } mips_pic = SVR4_PIC; mips_abicalls = TRUE; - if (g_switch_seen && g_switch_value != 0) - { - as_bad (_("-G may not be used with SVR4 PIC code")); - return 0; - } - g_switch_value = 0; break; case OPTION_NON_SHARED: @@ -10916,11 +10928,6 @@ md_parse_option (int c, char *arg) case 'G': g_switch_value = atoi (arg); g_switch_seen = 1; - if (mips_pic == SVR4_PIC && g_switch_value != 0) - { - as_bad (_("-G may not be used with SVR4 PIC code")); - return 0; - } break; #ifdef OBJ_ELF @@ -11026,6 +11033,10 @@ md_parse_option (int c, char *arg) case OPTION_NO_PDR: mips_flag_pdr = FALSE; break; + + case OPTION_MVXWORKS_PIC: + mips_pic = VXWORKS_PIC; + break; #endif /* OBJ_ELF */ default: @@ -13166,6 +13177,9 @@ md_estimate_size_before_relax (fragS *fragp, asection *segtype) change = nopic_need_relax (fragp->fr_symbol, 0); else if (mips_pic == SVR4_PIC) change = pic_need_relax (fragp->fr_symbol, segtype); + else if (mips_pic == VXWORKS_PIC) + /* For vxworks, GOT16 relocations never have a corresponding LO16. */ + change = 0; else abort (); diff --git a/gas/config/tc-mips.h b/gas/config/tc-mips.h index bc642b0a177..5665d3decdd 100644 --- a/gas/config/tc-mips.h +++ b/gas/config/tc-mips.h @@ -75,6 +75,9 @@ enum mips_pic_level /* Generate PIC code as in the SVR4 MIPS ABI. */ SVR4_PIC, + + /* VxWorks's PIC model. */ + VXWORKS_PIC }; extern enum mips_pic_level mips_pic; diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index b47b13e9c1f..f235c3c935a 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2006-03-22 Richard Sandiford + + * gas/mips/vxworks1.s, gas/mips/vxworks1.d, + * gas/mips/vxworks1-xgot.d: New tests. + * gas/mips/mips.exp: Run them. Do not run other tests on VxWorks. + 2006-03-21 Paul Brook * gas/arm/thumb32.d: Correct expected output. diff --git a/gas/testsuite/gas/mips/mips.exp b/gas/testsuite/gas/mips/mips.exp index 25997775cf3..7843f2a9742 100644 --- a/gas/testsuite/gas/mips/mips.exp +++ b/gas/testsuite/gas/mips/mips.exp @@ -383,12 +383,14 @@ mips_arch_create sb1 64 mips64 { mips3d } \ { -march=sb1 -mtune=sb1 } { -mmips:sb1 } \ { mipsisa64sb1-*-* mipsisa64sb1el-*-* } - # -# And now begin the actual tests! +# And now begin the actual tests! VxWorks uses RELA rather than REL +# relocations, so most of the generic dump tests will not work there. # - -if { [istarget mips*-*-*] } then { +if { [istarget mips*-*-vxworks*] } { + run_dump_test "vxworks1" + run_dump_test "vxworks1-xgot" +} elseif { [istarget mips*-*-*] } { set no_mips16 0 set elf [expr [istarget *-*-elf*] || [istarget *-*-irix5*] || [istarget *-*-irix6* ] || [istarget *-*-linux*] || [istarget *-*-netbsd*] ] set ecoff [expr [istarget *-*-ecoff*] || [istarget *-*-ultrix*] || [istarget *-*-irix\[1-4\]*] ] @@ -777,4 +779,6 @@ if { [istarget mips*-*-*] } then { run_dump_test "mips16e-jrc" run_dump_test "mips16e-save" } + run_dump_test "vxworks1" + run_dump_test "vxworks1-xgot" } diff --git a/gas/testsuite/gas/mips/vxworks1-xgot.d b/gas/testsuite/gas/mips/vxworks1-xgot.d new file mode 100644 index 00000000000..5737a571658 --- /dev/null +++ b/gas/testsuite/gas/mips/vxworks1-xgot.d @@ -0,0 +1,102 @@ +#as: -mips2 -mvxworks-pic -xgot -mabi=32 +#source: vxworks1.s +#objdump: -dr + +.*: file format .* + +Disassembly of section \.text: + +00000000 <\.text>: +# +# la $4,local +# +.*: 3c040000 lui a0,0x0 + .*: R_MIPS_GOT_HI16 \.data +.*: 009c2021 addu a0,a0,gp +.*: 8c840000 lw a0,0\(a0\) + .*: R_MIPS_GOT_LO16 \.data +# +# la $4,global +# +.*: 3c040000 lui a0,0x0 + .*: R_MIPS_GOT_HI16 global +.*: 009c2021 addu a0,a0,gp +.*: 8c840000 lw a0,0\(a0\) + .*: R_MIPS_GOT_LO16 global +# +# lw $4,local +# +.*: 3c040000 lui a0,0x0 + .*: R_MIPS_GOT_HI16 \.data +.*: 009c2021 addu a0,a0,gp +.*: 8c840000 lw a0,0\(a0\) + .*: R_MIPS_GOT_LO16 \.data +.*: 8c840000 lw a0,0\(a0\) +# +# lw $4,global +# +.*: 3c040000 lui a0,0x0 + .*: R_MIPS_GOT_HI16 global +.*: 009c2021 addu a0,a0,gp +.*: 8c840000 lw a0,0\(a0\) + .*: R_MIPS_GOT_LO16 global +.*: 8c840000 lw a0,0\(a0\) +# +# sw $4,local +# +.*: 3c010000 lui at,0x0 + .*: R_MIPS_GOT_HI16 \.data +.*: 003c0821 addu at,at,gp +.*: 8c210000 lw at,0\(at\) + .*: R_MIPS_GOT_LO16 \.data +.*: ac240000 sw a0,0\(at\) +# +# sw $4,global +# +.*: 3c010000 lui at,0x0 + .*: R_MIPS_GOT_HI16 global +.*: 003c0821 addu at,at,gp +.*: 8c210000 lw at,0\(at\) + .*: R_MIPS_GOT_LO16 global +.*: ac240000 sw a0,0\(at\) +# +# ulw $4,local +# +.*: 3c010000 lui at,0x0 + .*: R_MIPS_GOT_HI16 \.data +.*: 003c0821 addu at,at,gp +.*: 8c210000 lw at,0\(at\) + .*: R_MIPS_GOT_LO16 \.data +.*: 88240000 lwl a0,0\(at\) +.*: 98240003 lwr a0,3\(at\) +# +# ulw $4,global +# +.*: 3c010000 lui at,0x0 + .*: R_MIPS_GOT_HI16 global +.*: 003c0821 addu at,at,gp +.*: 8c210000 lw at,0\(at\) + .*: R_MIPS_GOT_LO16 global +.*: 88240000 lwl a0,0\(at\) +.*: 98240003 lwr a0,3\(at\) +# +# usw $4,local +# +.*: 3c010000 lui at,0x0 + .*: R_MIPS_GOT_HI16 \.data +.*: 003c0821 addu at,at,gp +.*: 8c210000 lw at,0\(at\) + .*: R_MIPS_GOT_LO16 \.data +.*: a8240000 swl a0,0\(at\) +.*: b8240003 swr a0,3\(at\) +# +# usw $4,global +# +.*: 3c010000 lui at,0x0 + .*: R_MIPS_GOT_HI16 global +.*: 003c0821 addu at,at,gp +.*: 8c210000 lw at,0\(at\) + .*: R_MIPS_GOT_LO16 global +.*: a8240000 swl a0,0\(at\) +.*: b8240003 swr a0,3\(at\) + \.\.\. diff --git a/gas/testsuite/gas/mips/vxworks1.d b/gas/testsuite/gas/mips/vxworks1.d new file mode 100644 index 00000000000..2ca762e430f --- /dev/null +++ b/gas/testsuite/gas/mips/vxworks1.d @@ -0,0 +1,71 @@ +#as: -mips2 -mvxworks-pic -mabi=32 +#objdump: -dr + +.*: file format .* + +Disassembly of section \.text: + +00000000 <\.text>: +# +# la $4,local +# +.*: 8f840000 lw a0,0\(gp\) + .*: R_MIPS_GOT16 \.data +# +# la $4,global +# +.*: 8f840000 lw a0,0\(gp\) + .*: R_MIPS_GOT16 global +# +# lw $4,local +# +.*: 8f840000 lw a0,0\(gp\) + .*: R_MIPS_GOT16 \.data +.*: 8c840000 lw a0,0\(a0\) +# +# lw $4,global +# +.*: 8f840000 lw a0,0\(gp\) + .*: R_MIPS_GOT16 global +.*: 8c840000 lw a0,0\(a0\) +# +# sw $4,local +# +.*: 8f810000 lw at,0\(gp\) + .*: R_MIPS_GOT16 \.data +.*: ac240000 sw a0,0\(at\) +# +# sw $4,global +# +.*: 8f810000 lw at,0\(gp\) + .*: R_MIPS_GOT16 global +.*: ac240000 sw a0,0\(at\) +# +# ulw $4,local +# +.*: 8f810000 lw at,0\(gp\) + .*: R_MIPS_GOT16 \.data +.*: 88240000 lwl a0,0\(at\) +.*: 98240003 lwr a0,3\(at\) +# +# ulw $4,global +# +.*: 8f810000 lw at,0\(gp\) + .*: R_MIPS_GOT16 global +.*: 88240000 lwl a0,0\(at\) +.*: 98240003 lwr a0,3\(at\) +# +# usw $4,local +# +.*: 8f810000 lw at,0\(gp\) + .*: R_MIPS_GOT16 \.data +.*: a8240000 swl a0,0\(at\) +.*: b8240003 swr a0,3\(at\) +# +# usw $4,global +# +.*: 8f810000 lw at,0\(gp\) + .*: R_MIPS_GOT16 global +.*: a8240000 swl a0,0\(at\) +.*: b8240003 swr a0,3\(at\) + \.\.\. diff --git a/gas/testsuite/gas/mips/vxworks1.s b/gas/testsuite/gas/mips/vxworks1.s new file mode 100644 index 00000000000..4d670a320cd --- /dev/null +++ b/gas/testsuite/gas/mips/vxworks1.s @@ -0,0 +1,16 @@ + la $4,local + la $4,global + lw $4,local + lw $4,global + sw $4,local + sw $4,global + ulw $4,local + ulw $4,global + usw $4,local + usw $4,global + .space 16 + + .data + .global global +local: .word 4 +global: .word 8 diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog index 9d47ffbac89..48ce81c1354 100644 --- a/include/elf/ChangeLog +++ b/include/elf/ChangeLog @@ -1,3 +1,12 @@ +2006-03-22 Richard Sandiford + Daniel Jacobowitz + Phil Edwards + Zack Weinberg + Mark Mitchell + Nathan Sidwell + + * mips.h (R_MIPS_COPY, R_MIPS_JUMP_SLOT): New relocs. + 2006-03-19 John David Anglin * hppa.h (SHF_HP_TLS, SHF_HP_NEAR_SHARED, SHF_HP_FAR_SHARED, diff --git a/include/elf/mips.h b/include/elf/mips.h index 6afc12ffe83..f22bd4d4213 100644 --- a/include/elf/mips.h +++ b/include/elf/mips.h @@ -97,6 +97,9 @@ START_RELOC_NUMBERS (elf_mips_reloc_type) RELOC_NUMBER (R_MIPS16_HI16, 104) RELOC_NUMBER (R_MIPS16_LO16, 105) FAKE_RELOC (R_MIPS16_max, 106) + /* These relocations are specific to VxWorks. */ + RELOC_NUMBER (R_MIPS_COPY, 126) + RELOC_NUMBER (R_MIPS_JUMP_SLOT, 127) /* This was a GNU extension used by embedded-PIC. It was co-opted by mips-linux for exception-handling data. It is no longer used, but should continue to be supported by the linker for backward diff --git a/ld/ChangeLog b/ld/ChangeLog index 9005e8f2d70..3918cc0d204 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,19 @@ +2006-03-22 Richard Sandiford + Daniel Jacobowitz + Phil Edwards + Zack Weinberg + Mark Mitchell + Nathan Sidwell + + * configure.tgt (mips*el-*-vxworks*, mips*-*-vxworks*): Use + separate VxWorks emulations. + * emulparams/elf32ebmipvxworks.sh: New file. + * emulparams/elf32elmipvxworks.sh: New file. + * Makefile.am (ALL_EMULATIONS): Add eelf32ebmipvxworks.o and + eelf32elmipvxworks.o. + (eelf32ebmipvxworks.c, eelf32elmipvxworks.c): New rules. + * Makefile.in: Regenerate. + 2006-03-16 Alan Modra PR 2434 diff --git a/ld/Makefile.am b/ld/Makefile.am index db64da4d966..d59d73498ad 100644 --- a/ld/Makefile.am +++ b/ld/Makefile.am @@ -158,7 +158,9 @@ ALL_EMULATIONS = \ eelf32ltsmip.o \ eelf32ltsmipn32.o \ eelf32ebmip.o \ + eelf32ebmipvxworks.o \ eelf32elmip.o \ + eelf32elmipvxworks.o \ eelf32fr30.o \ eelf32frv.o \ eelf32i370.o \ @@ -725,10 +727,20 @@ eelf32ebmip.c: $(srcdir)/emulparams/elf32ebmip.sh \ $(srcdir)/emulparams/elf32bmip.sh \ $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} ${GENSCRIPTS} elf32ebmip "$(tdir_elf32ebmip)" +eelf32ebmipvxworks.c: $(srcdir)/emulparams/elf32ebmipvxworks.sh \ + $(srcdir)/emulparams/elf32ebmip.sh $(srcdir)/emulparams/vxworks.sh \ + $(srcdir)/emultempl/elf32.em $(srcdir)/emultempl/vxworks.em \ + $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ${GENSCRIPTS} elf32ebmipvxworks "$(tdir_elf32ebmipvxworks)" eelf32elmip.c: $(srcdir)/emulparams/elf32elmip.sh \ $(srcdir)/emulparams/elf32lmip.sh $(srcdir)/emulparams/elf32bmip.sh \ $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} ${GENSCRIPTS} elf32elmip "$(tdir_elf32elmip)" +eelf32elmipvxworks.c: $(srcdir)/emulparams/elf32elmipvxworks.sh \ + $(srcdir)/emulparams/elf32elmip.sh $(srcdir)/emulparams/vxworks.sh \ + $(srcdir)/emultempl/elf32.em $(srcdir)/emultempl/vxworks.em \ + $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ${GENSCRIPTS} elf32elmipvxworks "$(tdir_elf32elmipvxworks)" eelf32bmipn32.c: $(srcdir)/emulparams/elf32bmipn32.sh \ $(srcdir)/emultempl/irix.em \ $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} diff --git a/ld/Makefile.in b/ld/Makefile.in index dff417394dc..fde6f7c73a6 100644 --- a/ld/Makefile.in +++ b/ld/Makefile.in @@ -381,7 +381,9 @@ ALL_EMULATIONS = \ eelf32ltsmip.o \ eelf32ltsmipn32.o \ eelf32ebmip.o \ + eelf32ebmipvxworks.o \ eelf32elmip.o \ + eelf32elmipvxworks.o \ eelf32fr30.o \ eelf32frv.o \ eelf32i370.o \ @@ -1531,10 +1533,20 @@ eelf32ebmip.c: $(srcdir)/emulparams/elf32ebmip.sh \ $(srcdir)/emulparams/elf32bmip.sh \ $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} ${GENSCRIPTS} elf32ebmip "$(tdir_elf32ebmip)" +eelf32ebmipvxworks.c: $(srcdir)/emulparams/elf32ebmipvxworks.sh \ + $(srcdir)/emulparams/elf32ebmip.sh $(srcdir)/emulparams/vxworks.sh \ + $(srcdir)/emultempl/elf32.em $(srcdir)/emultempl/vxworks.em \ + $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ${GENSCRIPTS} elf32ebmipvxworks "$(tdir_elf32ebmipvxworks)" eelf32elmip.c: $(srcdir)/emulparams/elf32elmip.sh \ $(srcdir)/emulparams/elf32lmip.sh $(srcdir)/emulparams/elf32bmip.sh \ $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} ${GENSCRIPTS} elf32elmip "$(tdir_elf32elmip)" +eelf32elmipvxworks.c: $(srcdir)/emulparams/elf32elmipvxworks.sh \ + $(srcdir)/emulparams/elf32elmip.sh $(srcdir)/emulparams/vxworks.sh \ + $(srcdir)/emultempl/elf32.em $(srcdir)/emultempl/vxworks.em \ + $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ${GENSCRIPTS} elf32elmipvxworks "$(tdir_elf32elmipvxworks)" eelf32bmipn32.c: $(srcdir)/emulparams/elf32bmipn32.sh \ $(srcdir)/emultempl/irix.em \ $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} diff --git a/ld/configure.tgt b/ld/configure.tgt index 56e1ae47559..95116661044 100644 --- a/ld/configure.tgt +++ b/ld/configure.tgt @@ -324,9 +324,10 @@ mips*vr5000-*-elf*) targ_emul=elf32b4300 ;; mips*el-*-elf*) targ_emul=elf32elmip ;; mips*-*-elf*) targ_emul=elf32ebmip ;; mips*-*-rtems*) targ_emul=elf32ebmip ;; -mips*el-*-vxworks*) targ_emul=elf32elmip ;; -mips*-*-vxworks*) targ_emul=elf32ebmip - targ_extra_emuls="elf32elmip" ;; +mips*el-*-vxworks*) targ_emul=elf32elmipvxworks + targ_extra_emuls="elf32ebmipvxworks" ;; +mips*-*-vxworks*) targ_emul=elf32ebmipvxworks + targ_extra_emuls="elf32elmipvxworks" ;; mips*-*-windiss) targ_emul=elf32mipswindiss ;; mips64*el-*-linux-*) targ_emul=elf32ltsmipn32 targ_extra_emuls="elf32btsmipn32 elf32ltsmip elf32btsmip elf64ltsmip elf64btsmip" diff --git a/ld/emulparams/elf32ebmipvxworks.sh b/ld/emulparams/elf32ebmipvxworks.sh new file mode 100644 index 00000000000..4145488ae28 --- /dev/null +++ b/ld/emulparams/elf32ebmipvxworks.sh @@ -0,0 +1,11 @@ +. ${srcdir}/emulparams/elf32bmip.sh + +OUTPUT_FORMAT="elf32-bigmips-vxworks" +BIG_OUTPUT_FORMAT="elf32-bigmips-vxworks" +LITTLE_OUTPUT_FORMAT="elf32-littlemips-vxworks" +unset OTHER_GOT_SYMBOLS +SHLIB_TEXT_START_ADDR=0 +unset TEXT_DYNAMIC +unset DATA_ADDR + +. ${srcdir}/emulparams/vxworks.sh diff --git a/ld/emulparams/elf32elmipvxworks.sh b/ld/emulparams/elf32elmipvxworks.sh new file mode 100644 index 00000000000..c1239441c4e --- /dev/null +++ b/ld/emulparams/elf32elmipvxworks.sh @@ -0,0 +1,11 @@ +. ${srcdir}/emulparams/elf32bmip.sh + +OUTPUT_FORMAT="elf32-littlemips-vxworks" +BIG_OUTPUT_FORMAT="elf32-bigmips-vxworks" +LITTLE_OUTPUT_FORMAT="elf32-littlemips-vxworks" +unset OTHER_GOT_SYMBOLS +SHLIB_TEXT_START_ADDR=0 +unset TEXT_DYNAMIC +unset DATA_ADDR + +. ${srcdir}/emulparams/vxworks.sh diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index f968b4ce178..763c325786d 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2006-03-22 Richard Sandiford + + * ld-mips/vxworks1.dd, ld-mips/vxworks1.ld, ld-mips/vxworks1-lib.dd, + * ld-mips/vxworks1-lib.nd, ld-mips/vxworks1-lib.rd, + * ld-mips/vxworks1-lib.s, ld-mips/vxworks1.rd, ld-mips/vxworks1.s, + * ld-mips/vxworks1-static.d, ld-mips/vxworks2.s, ld-mips/vxworks2.sd, + * ld-mips/vxworks2-static.sd: New tests. + * ld-mips/mips-elf.exp: Run them. + 2006-03-17 Alexandre Oliva * ld-powerpc/tls32.s: Verify that +32768 @plt addend is diff --git a/ld/testsuite/ld-mips-elf/mips-elf.exp b/ld/testsuite/ld-mips-elf/mips-elf.exp index aac341894b0..add2060acd6 100644 --- a/ld/testsuite/ld-mips-elf/mips-elf.exp +++ b/ld/testsuite/ld-mips-elf/mips-elf.exp @@ -16,6 +16,34 @@ # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. # +if {[istarget "mips*-*-vxworks"]} { + set mipsvxtests { + {"VxWorks shared library test 1" "-shared -Tvxworks1.ld" + "-mips2" {vxworks1-lib.s} + {{readelf --relocs vxworks1-lib.rd} {objdump -dr vxworks1-lib.dd} + {readelf --symbols vxworks1-lib.nd}} + "libvxworks1.so"} + {"VxWorks executable test 1 (dynamic)" \ + "tmpdir/libvxworks1.so -Tvxworks1.ld -q --force-dynamic" + "-mips2" {vxworks1.s} + {{readelf --relocs vxworks1.rd} {objdump -dr vxworks1.dd}} + "vxworks1"} + {"VxWorks executable test 2 (dynamic)" \ + "-Tvxworks1.ld -q --force-dynamic" + "-mips2" {vxworks2.s} + {{readelf --segments vxworks2.sd}} + "vxworks2"} + {"VxWorks executable test 2 (static)" + "-Tvxworks1.ld" + "-mips2" {vxworks2.s} + {{readelf --segments vxworks2-static.sd}} + "vxworks2"} + } + run_ld_link_tests $mipsvxtests + run_dump_test "vxworks1-static" + return +} + if {![istarget mips*-*-*] || ![is_elf_format]} { return } diff --git a/ld/testsuite/ld-mips-elf/vxworks1-lib.dd b/ld/testsuite/ld-mips-elf/vxworks1-lib.dd new file mode 100644 index 00000000000..ab060d98dd4 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/vxworks1-lib.dd @@ -0,0 +1,50 @@ + +.*: file format .* + +Disassembly of section \.plt: + +00080800 <_PROCEDURE_LINKAGE_TABLE_>: + 80800: 8f990008 lw t9,8\(gp\) + 80804: 00000000 nop + 80808: 03200008 jr t9 + 8080c: 00000000 nop + \.\.\. + 80818: 1000fff9 b 80800 <_PROCEDURE_LINKAGE_TABLE_> + 8081c: 24180000 li t8,0 + 80820: 1000fff7 b 80800 <_PROCEDURE_LINKAGE_TABLE_> + 80824: 24180001 li t8,1 +Disassembly of section \.text: + +00080c00 : + 80c00: 27bdffe0 addiu sp,sp,-32 + 80c04: afbf0000 sw ra,0\(sp\) + 80c08: afbc0004 sw gp,4\(sp\) + 80c0c: 3c1c0000 lui gp,0x0 + 80c10: 8f9c0000 lw gp,0\(gp\) + 80c14: 8f9c0000 lw gp,0\(gp\) + 80c18: 8f820014 lw v0,20\(gp\) + 80c1c: 8c430000 lw v1,0\(v0\) + 80c20: 24630001 addiu v1,v1,1 + 80c24: ac430000 sw v1,0\(v0\) + 80c28: 8f99000c lw t9,12\(gp\) + 80c2c: 0320f809 jalr t9 + 80c30: 00000000 nop + 80c34: 8f99fff4 lw t9,-12\(gp\) + 80c38: 0320f809 jalr t9 + 80c3c: 00000000 nop + 80c40: 8f99fff0 lw t9,-16\(gp\) + 80c44: 0320f809 jalr t9 + 80c48: 00000000 nop + 80c4c: 8fbf0000 lw ra,0\(sp\) + 80c50: 8fbc0004 lw gp,4\(sp\) + 80c54: 03e00008 jr ra + 80c58: 27bd0020 addiu sp,sp,32 + +00080c5c : + 80c5c: 03e00008 jr ra + 80c60: 00000000 nop + +00080c64 : + 80c64: 03e00008 jr ra + 80c68: 00000000 nop +#pass diff --git a/ld/testsuite/ld-mips-elf/vxworks1-lib.nd b/ld/testsuite/ld-mips-elf/vxworks1-lib.nd new file mode 100644 index 00000000000..adbf7d77a32 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/vxworks1-lib.nd @@ -0,0 +1,9 @@ +#... +Symbol table '\.dynsym' .*: +#... +.*: 00081410 * 0 * OBJECT * GLOBAL * DEFAULT * [0-9]+ _GLOBAL_OFFSET_TABLE_ +#... +Symbol table '\.symtab' .*: +#... +.*: 00081410 * 0 * OBJECT * GLOBAL * DEFAULT * [0-9]+ _GLOBAL_OFFSET_TABLE_ +#pass diff --git a/ld/testsuite/ld-mips-elf/vxworks1-lib.rd b/ld/testsuite/ld-mips-elf/vxworks1-lib.rd new file mode 100644 index 00000000000..9a8b35e7802 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/vxworks1-lib.rd @@ -0,0 +1,18 @@ + +Relocation section '\.rela\.dyn' at offset .* contains .* entries: + Offset Info Type Sym\.Value Sym\. Name \+ Addend +00080c0c .*05 R_MIPS_HI16 00000000 __GOTT_BASE__ \+ 0 +00080c10 .*06 R_MIPS_LO16 00000000 __GOTT_BASE__ \+ 0 +00080c14 .*01 R_MIPS_16 00000000 __GOTT_INDEX__ \+ 0 +0008141c .*02 R_MIPS_32 00080c00 \.text \+ 5c +00081c00 00000002 R_MIPS_32 00080c5c +00081c04 00000002 R_MIPS_32 00081c00 +00081c08 .*02 R_MIPS_32 00081c08 dglobal \+ 0 +00081c0c .*02 R_MIPS_32 00000000 dexternal \+ 0 +00081424 .*02 R_MIPS_32 00081800 x \+ 0 +00000000 00000000 R_MIPS_NONE 00000000 +#... +Relocation section '\.rela\.plt' at offset .* contains 2 entries: + Offset Info Type Sym\.Value Sym\. Name \+ Addend +00081400 .*7f R_MIPS_JUMP_SLOT 00000000 sexternal \+ 0 +00081404 .*7f R_MIPS_JUMP_SLOT 00080c64 sglobal \+ 0 diff --git a/ld/testsuite/ld-mips-elf/vxworks1-lib.s b/ld/testsuite/ld-mips-elf/vxworks1-lib.s new file mode 100644 index 00000000000..827332c0c18 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/vxworks1-lib.s @@ -0,0 +1,52 @@ + .text + .globl foo + .type foo, @function +foo: + addiu $sp,$sp,-32 + sw $31,($sp) + sw $28,4($sp) + lui $28,%hi(__GOTT_BASE__) + lw $28,%lo(__GOTT_BASE__)($28) + lw $28,%half(__GOTT_INDEX__)($28) + lw $2,%got(x)($28) + lw $3,($2) + addiu $3,$3,1 + sw $3,($2) + lw $25,%got(slocal)($gp) + jalr $25 + lw $25,%call16(sglobal)($gp) + jalr $25 + lw $25,%call16(sexternal)($gp) + jalr $25 + lw $31,($sp) + lw $28,4($sp) + addiu $sp,$sp,32 + jr $31 + .size foo, .-foo + + .type slocal, @function +slocal: + jr $31 + .size slocal, .-slocal + + .globl sglobal + .type sglobal, @function +sglobal: + jr $31 + .size sglobal, .-sglobal + + .comm x,4,4 + + .data + .type dlocal, @object +dlocal: + .word slocal + .word dlocal + .size dlocal, .-dlocal + + .globl dglobal + .type dglobal, @object +dglobal: + .word dglobal + .word dexternal + .size dglobal, .-dglobal diff --git a/ld/testsuite/ld-mips-elf/vxworks1-static.d b/ld/testsuite/ld-mips-elf/vxworks1-static.d new file mode 100644 index 00000000000..88c0baf1bbb --- /dev/null +++ b/ld/testsuite/ld-mips-elf/vxworks1-static.d @@ -0,0 +1,4 @@ +#name: VxWorks executable test 1 (static) +#source: vxworks1.s +#ld: tmpdir/libvxworks1.so -Tvxworks1.ld +#error: Dynamic sections created in non-dynamic link diff --git a/ld/testsuite/ld-mips-elf/vxworks1.dd b/ld/testsuite/ld-mips-elf/vxworks1.dd new file mode 100644 index 00000000000..af9e3543240 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/vxworks1.dd @@ -0,0 +1,51 @@ + +.*: file format .* + +Disassembly of section \.plt: + +00080800 <_PROCEDURE_LINKAGE_TABLE_>: + 80800: 3c190008 lui t9,0x8 + 80800: R_MIPS_HI16 _GLOBAL_OFFSET_TABLE_ + 80804: 27391410 addiu t9,t9,5136 + 80804: R_MIPS_LO16 _GLOBAL_OFFSET_TABLE_ + 80808: 8f390008 lw t9,8\(t9\) + 8080c: 00000000 nop + 80810: 03200008 jr t9 + 80814: 00000000 nop + 80818: 1000fff9 b 80800 <_PROCEDURE_LINKAGE_TABLE_> + 8081c: 24180000 li t8,0 + 80820: 3c190008 lui t9,0x8 + 80820: R_MIPS_HI16 _GLOBAL_OFFSET_TABLE_\+0xfffffff0 + 80824: 27391400 addiu t9,t9,5120 + 80824: R_MIPS_LO16 _GLOBAL_OFFSET_TABLE_\+0xfffffff0 + 80828: 8f390000 lw t9,0\(t9\) + 8082c: 00000000 nop + 80830: 03200008 jr t9 + 80834: 00000000 nop + 80838: 1000fff1 b 80800 <_PROCEDURE_LINKAGE_TABLE_> + 8083c: 24180001 li t8,1 + 80840: 3c190008 lui t9,0x8 + 80840: R_MIPS_HI16 _GLOBAL_OFFSET_TABLE_\+0xfffffff4 + 80844: 27391404 addiu t9,t9,5124 + 80844: R_MIPS_LO16 _GLOBAL_OFFSET_TABLE_\+0xfffffff4 + 80848: 8f390000 lw t9,0\(t9\) + 8084c: 00000000 nop + 80850: 03200008 jr t9 + 80854: 00000000 nop +Disassembly of section \.text: + +00080c00 <_start>: + 80c00: 0c020210 jal 80840 <_PROCEDURE_LINKAGE_TABLE_\+0x40> + 80c00: R_MIPS_26 \.plt\+0x40 + 80c04: 00000000 nop + 80c08: 0c020306 jal 80c18 + 80c08: R_MIPS_26 sexternal + 80c0c: 00000000 nop + 80c10: 08020208 j 80820 <_PROCEDURE_LINKAGE_TABLE_\+0x20> + 80c10: R_MIPS_26 \.plt\+0x20 + 80c14: 00000000 nop + +00080c18 : + 80c18: 03e00008 jr ra + 80c1c: 00000000 nop +#pass diff --git a/ld/testsuite/ld-mips-elf/vxworks1.ld b/ld/testsuite/ld-mips-elf/vxworks1.ld new file mode 100644 index 00000000000..74e2c2612a9 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/vxworks1.ld @@ -0,0 +1,32 @@ +SECTIONS +{ + . = 0x80000; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + + . = ALIGN (0x400); + .rela.dyn : { *(.rela.dyn) } + .rela.plt : { *(.rela.plt) } + + . = ALIGN (0x400); + .plt : { *(.plt) } + + . = ALIGN (0x400); + .text : { *(.text) } + + . = ALIGN (0x1000); + .dynamic : { *(.dynamic) } + + . = ALIGN (0x400); + .got : { *(.got.plt) *(.got) } + + . = ALIGN (0x400); + .bss : { *(.bss) *(.dynbss) } + + . = ALIGN (0x400); + .data : { *(.data) } + + /DISCARD/ : { *(.reginfo) } +} diff --git a/ld/testsuite/ld-mips-elf/vxworks1.rd b/ld/testsuite/ld-mips-elf/vxworks1.rd new file mode 100644 index 00000000000..f4793a22e0d --- /dev/null +++ b/ld/testsuite/ld-mips-elf/vxworks1.rd @@ -0,0 +1,32 @@ + +Relocation section '\.rela\.dyn' at offset .* contains 1 entries: + Offset Info Type Sym.Value Sym. Name \+ Addend +00081800 .*7e R_MIPS_COPY 00081800 dglobal \+ 0 + +Relocation section '\.rela\.plt' at offset .* contains 2 entries: + Offset Info Type Sym\.Value Sym\. Name \+ Addend +00081400 .*7f R_MIPS_JUMP_SLOT 00080820 sglobal \+ 0 +00081404 .*7f R_MIPS_JUMP_SLOT 00080840 foo \+ 0 + +Relocation section '\.rela\.text' at offset .* contains 3 entries: + Offset Info Type Sym\.Value Sym\. Name \+ Addend +00080c00 .*04 R_MIPS_26 00080800 \.plt \+ 40 +00080c08 .*04 R_MIPS_26 00080c18 sexternal \+ 0 +00080c10 .*04 R_MIPS_26 00080800 \.plt \+ 20 + +Relocation section '\.rela\.data' at offset .* contains 3 entries: + Offset Info Type Sym.Value Sym. Name \+ Addend +00081c00 .*02 R_MIPS_32 00081c00 .data \+ 0 +00081c04 .*02 R_MIPS_32 00081800 .bss \+ 0 +00081c08 .*02 R_MIPS_32 00081c04 dexternal \+ 0 + +Relocation section '\.rela\.plt\.unloaded' at offset .* contains 8 entries: + Offset Info Type Sym\.Value Sym\. Name \+ Addend +00080800 .*05 R_MIPS_HI16 00081410 _GLOBAL_OFFSET_TABLE_ \+ 0 +00080804 .*06 R_MIPS_LO16 00081410 _GLOBAL_OFFSET_TABLE_ \+ 0 +00081400 .*02 R_MIPS_32 00080800 _PROCEDURE_LINKAGE_TAB.* \+ 18 +00080820 .*05 R_MIPS_HI16 00081410 _GLOBAL_OFFSET_TABLE_ \+ fffffff0 +00080824 .*06 R_MIPS_LO16 00081410 _GLOBAL_OFFSET_TABLE_ \+ fffffff0 +00081404 .*02 R_MIPS_32 00080800 _PROCEDURE_LINKAGE_TAB.* \+ 38 +00080840 .*05 R_MIPS_HI16 00081410 _GLOBAL_OFFSET_TABLE_ \+ fffffff4 +00080844 .*06 R_MIPS_LO16 00081410 _GLOBAL_OFFSET_TABLE_ \+ fffffff4 diff --git a/ld/testsuite/ld-mips-elf/vxworks1.s b/ld/testsuite/ld-mips-elf/vxworks1.s new file mode 100644 index 00000000000..33a247f7f69 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/vxworks1.s @@ -0,0 +1,27 @@ + .text + .globl _start + .type _start, @function +_start: + jal foo + jal sexternal + j sglobal + .size _start, .-_start + + .globl sexternal + .type sexternal, @function +sexternal: + jr $31 + .size sexternal, .-sexternal + + .data + .type dlocal, @object +dlocal: + .word dlocal + .size dlocal, .-dlocal + + .globl dexternal + .type dexternal, @object +dexternal: + .word dglobal + .word dexternal + .size dexternal, .-dexternal diff --git a/ld/testsuite/ld-mips-elf/vxworks2-static.sd b/ld/testsuite/ld-mips-elf/vxworks2-static.sd new file mode 100644 index 00000000000..912755bc472 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/vxworks2-static.sd @@ -0,0 +1,9 @@ +#... +Elf file type is EXEC \(Executable file\) +Entry point 0x80000 +#... +Program Headers: + Type .* + LOAD .* 0x00080000 0x00080000 .* R E 0x1000 + +#... diff --git a/ld/testsuite/ld-mips-elf/vxworks2.s b/ld/testsuite/ld-mips-elf/vxworks2.s new file mode 100644 index 00000000000..25f078e8acd --- /dev/null +++ b/ld/testsuite/ld-mips-elf/vxworks2.s @@ -0,0 +1,5 @@ + .globl _start + .type _start, @function +_start: + jr $31 + .size _start, .-_start diff --git a/ld/testsuite/ld-mips-elf/vxworks2.sd b/ld/testsuite/ld-mips-elf/vxworks2.sd new file mode 100644 index 00000000000..5ff87d3bef8 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/vxworks2.sd @@ -0,0 +1,13 @@ +#... +Elf file type is EXEC \(Executable file\) +Entry point 0x80400 +#... +Program Headers: + Type .* + PHDR .* +#... + LOAD .* 0x00080000 0x00080000 .* R E 0x1000 + LOAD .* 0x00081000 0x00081000 .* RW 0x1000 + DYNAMIC .* + +#...