This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

mips-vxworks support


This patch adds MIPS VxWorks support.  VxWorks uses the same style
of ABI for all architectures, which means that for MIPS, it's very
different from SVR4-based ports.  The main differences are:

  - VxWorks uses a "normal" PLT (with JUMP_SLOT relocs, etc.).
  - VxWorks uses copy relocs.
  - Because of the above, executables do not use PIC, and do not use a GOT.
  - R_MIPS_CALL16 relocations point to a .got.plt entry instead of a
    normal .got entry.
  - R_MIPS_GOT16 relocations evaluate to "G" for all symbols, not just
    global ones.

I've tried to make the comments as descriptive as possible.  Note that
the second half of _bfd_mips_vxworks_adjust_dynamic_symbol (the bit
after the "h->needs_plt" block) is boiler-plate.  There's similar
code in many ports.

The different handling of R_MIPS_GOT16 means that we need to use
different macro expansions for VxWorks.  The patch adds a VXWORKS_PIC
enumeration for this.  Most of the code is similar to SVR4_PIC,
and since that's the only other PIC model we support these days,
it usually redundant to check the value of mips_pic when handling
mips_pic != NO_PIC.  Most of the checks are left over from
EMBEDDED_PIC days.

Tested on mips64-elf, mips64-linux-gnu, mips-elf, mipsisa32-elf,
mipsisa64-elf, mips-linux-gnu and mips-vxworks.  OK to install?

Richard


2006-03-13 Richard Sandiford  <richard@codesourcery.com>
	   Daniel Jacobowitz  <dan@codesourcery.com>
	   Phil Edwards  <phil@codesourcery.com>
	   Zack Weinberg  <zack@codesourcery.com>
	   Mark Mitchell  <mark@codesourcery.com>
	   Nathan Sidwell  <nathan@codesourcery.com>

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.  Calculcate 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 --exclude='*.info' -uprN ../src.3/bfd/bfd-in2.h ./bfd/bfd-in2.h
--- ./bfd/bfd-in2.h	2006-03-07 07:43:15.000000000 +0000
+++ ./bfd/bfd-in2.h	2006-03-13 19:44:28.000000000 +0000
@@ -2585,6 +2585,11 @@ to compensate for the borrow when the lo
   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 --exclude='*.info' -uprN ../src.3/bfd/config.bfd ./bfd/config.bfd
--- ./bfd/config.bfd	2006-03-13 19:01:23.000000000 +0000
+++ ./bfd/config.bfd	2006-03-13 19:44:28.000000000 +0000
@@ -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 --exclude='*.info' -uprN ../src.3/bfd/configure ./bfd/configure
--- ./bfd/configure	2006-03-13 19:01:23.000000000 +0000
+++ ./bfd/configure	2006-03-13 19:46:23.000000000 +0000
@@ -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 --exclude='*.info' -uprN ../src.3/bfd/configure.in ./bfd/configure.in
--- ./bfd/configure.in	2006-03-13 19:01:23.000000000 +0000
+++ ./bfd/configure.in	2006-03-13 19:46:11.000000000 +0000
@@ -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 --exclude='*.info' -uprN ../src.3/bfd/elf32-mips.c ./bfd/elf32-mips.c
--- ./bfd/elf32-mips.c	2005-11-25 10:54:53.000000000 +0000
+++ ./bfd/elf32-mips.c	2006-03-13 19:59:19.000000000 +0000
@@ -37,6 +37,7 @@ Foundation, Inc., 51 Franklin Street - F
 #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 
 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 mip
 
 /* 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 --exclude='*.info' -uprN ../src.3/bfd/elfxx-mips.c ./bfd/elfxx-mips.c
--- ./bfd/elfxx-mips.c	2006-03-13 19:23:39.000000000 +0000
+++ ./bfd/elfxx-mips.c	2006-03-13 20:14:26.000000000 +0000
@@ -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, <pltindex>			*/
+  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, <pltindex>	*/
+};
+
 /* 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_h
       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 
 	: 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
 	      || 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 g
   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
 
   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, bf
   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,
   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 *dyn
   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 *ab
   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_, vo
     {
       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 bf
   /* 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 bf
     {
       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_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, 
   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, 
   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_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
       /* 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)))
-	    {
-	      /* 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);
-	    }
-	}
-      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.  */
+	  /* 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
+	    {
+	      /* 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 (!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
     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
   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
     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
 	     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
 
     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
 	 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 ATTRI
 	  || 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 
   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 
   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 
 	 (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 (b
   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 (b
 	}
     }
 
+  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, s
   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, s
 	      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, s
 	    }
 	}
 
-      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, s
 	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, s
 	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, 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, s
 		{
 		  /* 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, s
 	      /* 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, s
 	      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, s
 	}
 
       /* 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 (str
       && (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 (str
 
   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 
   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 
      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 
 
   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
 				     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
      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
 
 	      /* 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
 	      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
 	      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
 		      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
 	    }
 
 	  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
       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
       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
 	}
     }
 
+  /* 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
 	    }
 	}
 
-      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
       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
   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 (b
   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 (b
 	  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 (b
 
 	    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 (b
 	      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 (b
 	      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 (b
 	}
     }
 
-  /* 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 (b
 		 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 (b
 	  }
       }
 
-    /* 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;
 }
 
@@ -8961,9 +9853,36 @@ _bfd_mips_elf_link_hash_table_create (bf
   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
@@ -8986,6 +9905,7 @@ _bfd_mips_elf_final_link (bfd *abfd, str
   EXTR esym;
   unsigned int i;
   bfd_size_type amt;
+  struct mips_elf_link_hash_table *htab;
 
   static const char * const secname[] =
   {
@@ -9002,6 +9922,7 @@ _bfd_mips_elf_final_link (bfd *abfd, str
      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;
@@ -9052,6 +9973,14 @@ _bfd_mips_elf_final_link (bfd *abfd, str
 	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;
@@ -9063,7 +9992,7 @@ _bfd_mips_elf_final_link (bfd *abfd, str
 	      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
 	{
@@ -9795,6 +10724,12 @@ _bfd_mips_elf_merge_private_bfd_data (bf
   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 --exclude='*.info' -uprN ../src.3/bfd/elfxx-mips.h ./bfd/elfxx-mips.h
--- ./bfd/elfxx-mips.h	2006-02-02 20:24:30.000000000 +0000
+++ ./bfd/elfxx-mips.h	2006-03-13 20:00:14.000000000 +0000
@@ -48,6 +48,8 @@ extern bfd_boolean _bfd_mips_elf_check_r
   (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_relocat
 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_reloc
    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 --exclude='*.info' -uprN ../src.3/bfd/libbfd.h ./bfd/libbfd.h
--- ./bfd/libbfd.h	2006-03-07 07:43:16.000000000 +0000
+++ ./bfd/libbfd.h	2006-03-13 19:44:28.000000000 +0000
@@ -965,6 +965,9 @@ static const char *const bfd_reloc_code_
   "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 --exclude='*.info' -uprN ../src.3/bfd/Makefile.am ./bfd/Makefile.am
--- ./bfd/Makefile.am	2006-03-13 19:01:23.000000000 +0000
+++ ./bfd/Makefile.am	2006-03-13 19:44:28.000000000 +0000
@@ -1347,14 +1347,14 @@ elfxx-mips.lo: elfxx-mips.c $(INCDIR)/fi
   $(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 --exclude='*.info' -uprN ../src.3/bfd/Makefile.in ./bfd/Makefile.in
--- ./bfd/Makefile.in	2006-03-13 19:01:23.000000000 +0000
+++ ./bfd/Makefile.in	2006-03-13 19:44:29.000000000 +0000
@@ -1914,14 +1914,14 @@ elfxx-mips.lo: elfxx-mips.c $(INCDIR)/fi
   $(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 --exclude='*.info' -uprN ../src.3/bfd/reloc.c ./bfd/reloc.c
--- ./bfd/reloc.c	2006-03-07 07:43:16.000000000 +0000
+++ ./bfd/reloc.c	2006-03-13 19:44:29.000000000 +0000
@@ -2140,6 +2140,14 @@ ENUMDOC
 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
   BFD_RELOC_FRV_LABEL24
diff --exclude='*.info' -uprN ../src.3/bfd/targets.c ./bfd/targets.c
--- ./bfd/targets.c	2006-03-13 19:01:23.000000000 +0000
+++ ./bfd/targets.c	2006-03-13 19:44:29.000000000 +0000
@@ -560,6 +560,7 @@ extern const bfd_target bfd_elf32_bigarm
 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_little
 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_tar
 	&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_tar
 	&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 --exclude='*.info' -uprN ../src.3/gas/config/tc-mips.c ./gas/config/tc-mips.c
--- ./gas/config/tc-mips.c	2005-11-25 10:55:03.000000000 +0000
+++ ./gas/config/tc-mips.c	2006-03-13 19:44:29.000000000 +0000
@@ -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, 
 	    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, 
 	    }
 	}
     }
-  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,<sym>		(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,<sym>($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 *fr
     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 --exclude='*.info' -uprN ../src.3/gas/config/tc-mips.h ./gas/config/tc-mips.h
--- ./gas/config/tc-mips.h	2005-11-25 10:55:03.000000000 +0000
+++ ./gas/config/tc-mips.h	2006-03-13 19:44:29.000000000 +0000
@@ -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 --exclude='*.info' -uprN ../src.3/gas/testsuite/gas/mips/mips.exp ./gas/testsuite/gas/mips/mips.exp
--- ./gas/testsuite/gas/mips/mips.exp	2005-11-25 10:55:06.000000000 +0000
+++ ./gas/testsuite/gas/mips/mips.exp	2006-03-13 19:44:29.000000000 +0000
@@ -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 --exclude='*.info' -uprN ../src.3/gas/testsuite/gas/mips/vxworks1.d ./gas/testsuite/gas/mips/vxworks1.d
--- ./gas/testsuite/gas/mips/vxworks1.d	1970-01-01 01:00:00.000000000 +0100
+++ ./gas/testsuite/gas/mips/vxworks1.d	2006-03-13 19:44:29.000000000 +0000
@@ -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 --exclude='*.info' -uprN ../src.3/gas/testsuite/gas/mips/vxworks1.s ./gas/testsuite/gas/mips/vxworks1.s
--- ./gas/testsuite/gas/mips/vxworks1.s	1970-01-01 01:00:00.000000000 +0100
+++ ./gas/testsuite/gas/mips/vxworks1.s	2006-03-13 19:44:29.000000000 +0000
@@ -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 --exclude='*.info' -uprN ../src.3/gas/testsuite/gas/mips/vxworks1-xgot.d ./gas/testsuite/gas/mips/vxworks1-xgot.d
--- ./gas/testsuite/gas/mips/vxworks1-xgot.d	1970-01-01 01:00:00.000000000 +0100
+++ ./gas/testsuite/gas/mips/vxworks1-xgot.d	2006-03-13 19:44:29.000000000 +0000
@@ -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 --exclude='*.info' -uprN ../src.3/include/elf/mips.h ./include/elf/mips.h
--- ./include/elf/mips.h	2005-11-25 10:54:57.000000000 +0000
+++ ./include/elf/mips.h	2006-03-13 19:44:29.000000000 +0000
@@ -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 --exclude='*.info' -uprN ../src.3/ld/configure.tgt ./ld/configure.tgt
--- ./ld/configure.tgt	2006-03-13 19:01:46.000000000 +0000
+++ ./ld/configure.tgt	2006-03-13 19:44:29.000000000 +0000
@@ -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 --exclude='*.info' -uprN ../src.3/ld/emulparams/elf32ebmipvxworks.sh ./ld/emulparams/elf32ebmipvxworks.sh
--- ./ld/emulparams/elf32ebmipvxworks.sh	1970-01-01 01:00:00.000000000 +0100
+++ ./ld/emulparams/elf32ebmipvxworks.sh	2006-03-13 19:44:29.000000000 +0000
@@ -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 --exclude='*.info' -uprN ../src.3/ld/emulparams/elf32elmipvxworks.sh ./ld/emulparams/elf32elmipvxworks.sh
--- ./ld/emulparams/elf32elmipvxworks.sh	1970-01-01 01:00:00.000000000 +0100
+++ ./ld/emulparams/elf32elmipvxworks.sh	2006-03-13 19:44:29.000000000 +0000
@@ -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 --exclude='*.info' -uprN ../src.3/ld/Makefile.am ./ld/Makefile.am
--- ./ld/Makefile.am	2006-03-13 19:01:46.000000000 +0000
+++ ./ld/Makefile.am	2006-03-13 19:44:29.000000000 +0000
@@ -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/elf3
   $(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 --exclude='*.info' -uprN ../src.3/ld/Makefile.in ./ld/Makefile.in
--- ./ld/Makefile.in	2006-03-13 19:01:46.000000000 +0000
+++ ./ld/Makefile.in	2006-03-13 19:44:29.000000000 +0000
@@ -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/elf3
   $(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 --exclude='*.info' -uprN ../src.3/ld/testsuite/ld-mips-elf/mips-elf.exp ./ld/testsuite/ld-mips-elf/mips-elf.exp
--- ./ld/testsuite/ld-mips-elf/mips-elf.exp	2006-03-13 19:23:39.000000000 +0000
+++ ./ld/testsuite/ld-mips-elf/mips-elf.exp	2006-03-13 19:44:29.000000000 +0000
@@ -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 --exclude='*.info' -uprN ../src.3/ld/testsuite/ld-mips-elf/vxworks1.dd ./ld/testsuite/ld-mips-elf/vxworks1.dd
--- ./ld/testsuite/ld-mips-elf/vxworks1.dd	1970-01-01 01:00:00.000000000 +0100
+++ ./ld/testsuite/ld-mips-elf/vxworks1.dd	2006-03-13 19:44:29.000000000 +0000
@@ -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 <sexternal>
+			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 <sexternal>:
+   80c18:	03e00008 	jr	ra
+   80c1c:	00000000 	nop
+#pass
diff --exclude='*.info' -uprN ../src.3/ld/testsuite/ld-mips-elf/vxworks1.ld ./ld/testsuite/ld-mips-elf/vxworks1.ld
--- ./ld/testsuite/ld-mips-elf/vxworks1.ld	1970-01-01 01:00:00.000000000 +0100
+++ ./ld/testsuite/ld-mips-elf/vxworks1.ld	2006-03-13 19:44:29.000000000 +0000
@@ -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 --exclude='*.info' -uprN ../src.3/ld/testsuite/ld-mips-elf/vxworks1-lib.dd ./ld/testsuite/ld-mips-elf/vxworks1-lib.dd
--- ./ld/testsuite/ld-mips-elf/vxworks1-lib.dd	1970-01-01 01:00:00.000000000 +0100
+++ ./ld/testsuite/ld-mips-elf/vxworks1-lib.dd	2006-03-13 19:44:29.000000000 +0000
@@ -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 <foo>:
+   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 <slocal>:
+   80c5c:	03e00008 	jr	ra
+   80c60:	00000000 	nop
+
+00080c64 <sglobal>:
+   80c64:	03e00008 	jr	ra
+   80c68:	00000000 	nop
+#pass
diff --exclude='*.info' -uprN ../src.3/ld/testsuite/ld-mips-elf/vxworks1-lib.nd ./ld/testsuite/ld-mips-elf/vxworks1-lib.nd
--- ./ld/testsuite/ld-mips-elf/vxworks1-lib.nd	1970-01-01 01:00:00.000000000 +0100
+++ ./ld/testsuite/ld-mips-elf/vxworks1-lib.nd	2006-03-13 19:44:29.000000000 +0000
@@ -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 --exclude='*.info' -uprN ../src.3/ld/testsuite/ld-mips-elf/vxworks1-lib.rd ./ld/testsuite/ld-mips-elf/vxworks1-lib.rd
--- ./ld/testsuite/ld-mips-elf/vxworks1-lib.rd	1970-01-01 01:00:00.000000000 +0100
+++ ./ld/testsuite/ld-mips-elf/vxworks1-lib.rd	2006-03-13 19:44:29.000000000 +0000
@@ -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 --exclude='*.info' -uprN ../src.3/ld/testsuite/ld-mips-elf/vxworks1-lib.s ./ld/testsuite/ld-mips-elf/vxworks1-lib.s
--- ./ld/testsuite/ld-mips-elf/vxworks1-lib.s	1970-01-01 01:00:00.000000000 +0100
+++ ./ld/testsuite/ld-mips-elf/vxworks1-lib.s	2006-03-13 19:44:29.000000000 +0000
@@ -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 --exclude='*.info' -uprN ../src.3/ld/testsuite/ld-mips-elf/vxworks1.rd ./ld/testsuite/ld-mips-elf/vxworks1.rd
--- ./ld/testsuite/ld-mips-elf/vxworks1.rd	1970-01-01 01:00:00.000000000 +0100
+++ ./ld/testsuite/ld-mips-elf/vxworks1.rd	2006-03-13 19:44:29.000000000 +0000
@@ -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 --exclude='*.info' -uprN ../src.3/ld/testsuite/ld-mips-elf/vxworks1.s ./ld/testsuite/ld-mips-elf/vxworks1.s
--- ./ld/testsuite/ld-mips-elf/vxworks1.s	1970-01-01 01:00:00.000000000 +0100
+++ ./ld/testsuite/ld-mips-elf/vxworks1.s	2006-03-13 19:44:29.000000000 +0000
@@ -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 --exclude='*.info' -uprN ../src.3/ld/testsuite/ld-mips-elf/vxworks1-static.d ./ld/testsuite/ld-mips-elf/vxworks1-static.d
--- ./ld/testsuite/ld-mips-elf/vxworks1-static.d	1970-01-01 01:00:00.000000000 +0100
+++ ./ld/testsuite/ld-mips-elf/vxworks1-static.d	2006-03-13 19:44:29.000000000 +0000
@@ -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 --exclude='*.info' -uprN ../src.3/ld/testsuite/ld-mips-elf/vxworks2.s ./ld/testsuite/ld-mips-elf/vxworks2.s
--- ./ld/testsuite/ld-mips-elf/vxworks2.s	1970-01-01 01:00:00.000000000 +0100
+++ ./ld/testsuite/ld-mips-elf/vxworks2.s	2006-03-13 19:44:29.000000000 +0000
@@ -0,0 +1,5 @@
+	.globl	_start
+	.type	_start, @function
+_start:
+	jr	$31
+	.size	_start, .-_start
diff --exclude='*.info' -uprN ../src.3/ld/testsuite/ld-mips-elf/vxworks2.sd ./ld/testsuite/ld-mips-elf/vxworks2.sd
--- ./ld/testsuite/ld-mips-elf/vxworks2.sd	1970-01-01 01:00:00.000000000 +0100
+++ ./ld/testsuite/ld-mips-elf/vxworks2.sd	2006-03-13 19:44:29.000000000 +0000
@@ -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 .*
+
+#...
diff --exclude='*.info' -uprN ../src.3/ld/testsuite/ld-mips-elf/vxworks2-static.sd ./ld/testsuite/ld-mips-elf/vxworks2-static.sd
--- ./ld/testsuite/ld-mips-elf/vxworks2-static.sd	1970-01-01 01:00:00.000000000 +0100
+++ ./ld/testsuite/ld-mips-elf/vxworks2-static.sd	2006-03-13 19:44:29.000000000 +0000
@@ -0,0 +1,9 @@
+#...
+Elf file type is EXEC \(Executable file\)
+Entry point 0x80000
+#...
+Program Headers:
+  Type .*
+  LOAD .* 0x00080000 0x00080000 .* R E 0x1000
+
+#...


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]