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]

Re: [PATCH 5/5] Defer allocation of R_MIPS_REL32 GOT slots


Daniel Jacobowitz <drow@false.org> writes:
> On Wed, Aug 06, 2008 at 09:05:26PM +0100, Richard Sandiford wrote:
>> bfd/
>> 	* elfxx-mips.c (mips_elf_record_relocs): Defer allocation of a
>> 	global GOT entry when deferring allocation of dynamic relocations.
>> 	(allocate_dynrelocs): When allocating deferred dynamic relocations,
>> 	also do the deferred allocation of a GOT entry.
>
> OK.

Thanks to you, Nick and Dan for the reviews.  I've now applied everything
except the n64 start address patch and the main non-PIC patch.

I'm prepared to put the n64 patch to one side if need be.  I don't think
it should hold up everything else.

It only really makes sense to apply the non-PIC patch at the same time
as the CS one (maybe even as one commit).  Dan, do you agree?  If so,
would you mind doing the honours?  I've attached a mainline version of my
non-PIC patch, in case the last one has bitrotted.  For avoidance of doubt,
this patch hasn't been reviewed as such, but I assume that (as a maintainer)
you're happy with the post-CS version.

In response to the recent undefined weak patch, I asked whether the
allocate_dynrelocs call to bfd_elf_link_record_dynamic_symbol was dead
given the "current" code's call to mips_elf_record_global_got_symbol.
That question's now moot, since it's the current code no longer.
(I'm still curious about the undefweak/STV_DEFAULT/forced_local thing,
but I can live with being curious.)

Richard


include/elf/
	* mips.h (STO_MIPS_PLT, ELF_ST_IS_MIPS_PLT, ELF_ST_SET_MIPS_PLT)
	(STO_MIPS_PIC, ELF_ST_IS_MIPS_PIC, ELF_ST_SET_MIPS_PIC): New macros.

bfd/
	* elf32-mips.c (mips_vxworks_copy_howto_rela): Replace with...
	(elf_mips_copy_howto): ...this howto.  Clear the size fields.
	(mips_vxworks_jump_slot_howto_rela): Replace with...
	(elf_mips_jump_slot_howto): ...this howto.
	(bfd_elf32_bfd_reloc_type_lookup): Handle BFD_RELOC_MIPS_COPY
	and BFD_RELOC_MIPS_JUMP_SLOT.
	(bfd_elf32_bfd_reloc_name_lookup): Handle "R_MIPS_COPY" and
	"R_MIPS_JUMP_SLOT".
	(mips_elf32_rtype_to_howto): Handle R_MIPS_COPY and R_MIPS_JUMP_SLOT.
	(elf_backend_plt_readonly): Define.
	(elf_backend_plt_sym_val): Define for non-VxWorks targets.
	(mips_vxworks_bfd_reloc_type_lookup): Delete.
	(mips_vxworks_bfd_reloc_name_lookup): Likewise.
	(mips_vxworks_rtype_to_howto): Likewise.
	(elf_backend_want_dynbss): Don't define for VxWorks.
	(elf_backend_plt_readonly): Likewise.
	(bfd_elf32_bfd_reloc_type_lookup): Likewise.
	(bfd_elf32_bfd_reloc_name_lookup): Likewise.
	(elf_backend_mips_rtype_to_howto): Likewise.
	(elf_backend_adjust_dynamic_symbol): Likewise.
	* elfn32-mips.c (elf_mips_copy_howto, elf_mips_jump_slot_howto): New.
	(bfd_elf32_bfd_reloc_type_lookup): Handle BFD_RELOC_MIPS_COPY
	and BFD_RELOC_MIPS_JUMP_SLOT.
	(bfd_elf32_bfd_reloc_name_lookup): Handle "R_MIPS_COPY" and
	"R_MIPS_JUMP_SLOT".
	(mips_elf32_n32_rtype_to_howto): Handle R_MIPS_COPY and
	R_MIPS_JUMP_SLOT.
	(elf_backend_rela_plts_and_copies_p, elf_backend_plt_readonly)
	(elf_backend_plt_sym_val): Define.
	* elf64-mips.c (elf_mips_copy_howto, elf_mips_jump_slot_howto): New.
	(bfd_elf64_bfd_reloc_type_lookup): Handle BFD_RELOC_MIPS_COPY
	and BFD_RELOC_MIPS_JUMP_SLOT.
	(bfd_elf64_bfd_reloc_name_lookup): Handle "R_MIPS_COPY" and
	"R_MIPS_JUMP_SLOT".
	(mips_elf64_rtype_to_howto): Handle R_MIPS_COPY and R_MIPS_JUMP_SLOT.
	(elf_backend_rela_plts_and_copies_p, elf_backend_plt_readonly)
	(elf_backend_plt_sym_val): Define.
	* elfxx-mips.h (_bfd_mips_vxworks_adjust_dynamic_symbol): Delete.
	(_bfd_mips_elf_use_plts_and_copy_relocs, _bfd_mips_elf_init_stubs)
	(_bfd_mips_elf_plt_sym_val): Declare.
	* elfxx-mips.c (mips_elf_la25_stub): New structure.
	(LA25_LUI, LA25_J, LA25_ADDIU): New macros.
	(mips_elf_link_hash_entry): Add "la25_stubs", "has_static_relocs"
	and "non_pic_ref" fields.  Remove "is_relocation_target" and
	"is_branch_target".
	(mips_elf_link_hash_table): Add blank lines.  Add
	"use_plts_and_copy_relocs", "reserved_gotno", "strampoline",
	"la25_stubs" and "add_stub_section" fields.
	(mips_htab_traverse_info): New structure.
	(PIC_OBJECT_P, MIPS_ELF_LOAD_WORD): New macros.
	(MIPS_RESERVED_GOTNO): Delete.
	(mips_exec_plt0_entry, mips_exec_plt_entry): New tables.
	(mips_elf_link_hash_newfunc): Update after the changes to
	mips_elf_link_hash_entry.
	(mips_elf_check_mips16_stubs): Replace the DATA parameter with
	an INFO parameter.  Don't look through warnings symbols here;
	do it in mips_elf_check_symbols instead.
	(mips_elf_la25_stub_hash, mips_elf_la25_stub_eq): New functions.
	(_bfd_mips_elf_init_stubs, mips_elf_local_pic_symbol_p): Likewise.
	(mips_elf_add_la25_intro, mips_elf_add_la25_trampoline): Likewise.
	(mips_elf_add_la25_stub, mips_elf_check_symbols): New function.
	(mips_elf_output_dynamic_relocation): Take the relocation index
	as an extra parameter.  Do not increment reloc_count here.
	(mips_elf_initialize_tls_slots): Update the calls to
	mips_elf_output_dynamic_relocation accordingly.
	(mips_elf_multi_got): Use htab->reserved_gotno instead of
	MIPS_RESERVED_GOTNO.
	(mips_elf_create_got_section): Don't allocate reserved GOT
	entries here.  Unconditionally create .got.plt, but don't
	set its alignment here.
	(mips_elf_calculate_relocation): If a compound relocation
	starts with %gp_rel(...), and the target is a PIC function with
	a non-PIC stub, assume that we need the unadjusted symbol value.
	Check !h->has_static_relocs instead of !htab->is_vxworks when
	deciding whether to create dynamic relocations for R_MIPS_32,
	R_MIPS_REL32 and R_MIPS_64.
	(_bfd_mips_elf_create_dynamic_sections): Unconditionally call
	_bfd_elf_create_dynamic_sections.  Unconditionally set up
	htab->splt and htab->sdynbss.  Set htab->srelplt to ".rel.plt"
	if !htab->is_vxworks.  Add non-VxWorks values of
	htab->plt_header_size and htab->plt_entry_size.
	(mips_elf_check_relocs): Set h->non_pic_ref if the input bfd
	is not a PIC one.  Set can_make_dynamic_p to TRUE if R_MIPS_32,
	R_MIPS_REL32 and R_MIPS_64 relocations can be made dynamic,
	rather than duplicating the condition.  Do not make them dynamic
	for read-only sections in non-PIC executable objects.
	Do not protect this code with dynobj == NULL || htab->sgot == NULL;
	handle each group of cases separately.  Add a default case that
	sets has_static_relocs for non-GOT relocations that cannot be
	made dynamic.  Don't set is_relocation_target and is_branch_target.
	(_bfd_mips_vxworks_adjust_dynamic_symbol): Fold into...
	(_bfd_mips_elf_adjust_dynamic_symbol): ...here, using
	htab->use_plts_and_copy_relocs instead of htab->is_vxworks
	to select PLT and copy-reloc handling.  Set the alignment of
	.plt and .got.plt when allocating the first entry.  Generalize
	code to handle REL as well as RELA sections and 64-bit as well as
	32-bit GOT entries.  Complain if we find a static-only reloc
	against an externally-defined symbol and if we cannot create
	dynamic relocations for it.  Allocate copy relocs using
	mips_elf_allocate_dynamic_relocations on non-VxWorks targets.
	Set possibly_dynamic_relocs to 0 when using PLTs or copy relocs.
	(_bfd_mips_elf_always_size_sections): Use mips_elf_check_symbols
	instead of mips_elf_check_mips16_stubs to process each symbol.
	Do the traversal for relocatable objects too.
	(mips_elf_lay_out_got): Allocate the reserved GOT entries here.
	Use htab->reserved_gotno instead of MIPS_RESERVED_GOTNO.
	(_bfd_mips_elf_size_dynamic_sections): Exclude sdynbss if it
	is empty.  Extend the DT_PLTREL, DT_JMPREL and DT_PLTRELSZ handling
	to non-VxWorks targets.  Only add DT_REL{,A}, DT_REL{,A}SZ and
	DT_REL{,A}ENT if .rel.dyn is nonempty.
	(mips_elf_create_la25_stub_info): New function.
	(_bfd_mips_elf_finish_dynamic_symbol): Write out PLT entries
	and copy relocs where necessary.
	(mips_finish_exec_plt): New function.
	(_bfd_mips_elf_finish_dynamic_sections): Always set DT_PLTGOT
	to the beginning of htab->sgot.  Use htab->reserved_gotno instead
	of MIPS_RESERVED_GOTNO.  Assert htab->use_plts_and_copy_relocs
	instead of htab->is_vxworks for DT_PLTREL, DT_PLTRELSZ and DT_JMPREL.
	Set DT_PLTREL to DT_REL instead of DT_RELA on non-VxWorks targets.
	Use mips_finish_exec_plt to create non-VxWorks PLT headers.
	(_bfd_mips_elf_copy_indirect_symbol): Copy has_static_relocs
	from the indirect symbol to the direct symbol.  Also copy
	non_pic_ref for indirect symbols.
	(_bfd_mips_elf_link_hash_table_create): Initialize the new
	mips_elf_link_hash_table fields.
	(_bfd_mips_vxworks_link_hash_table_create): Set
	use_plts_and_copy_relocs to TRUE.  Use TRUE rather than 1
	when setting is_vxworks.
	(_bfd_mips_elf_use_plts_and_copy_relocs): New function.
	(_bfd_mips_elf_final_link): Call mips_elf_create_la25_stub for
	each la25_stub.
	(_bfd_mips_elf_merge_private_bfd_data): Treat dynamic objects
	as PIC.  Generalize message about linking PIC and non-PIC.
	(_bfd_mips_elf_plt_sym_val): New function.

binutils/
	* readelf.c (get_mips_symbol_other): Handle STO_MIPS_PLT and
	STO_MIPS_PIC.

gas/
	* config/tc-mips.c (OPTION_CALL_NONPIC): New macro.
	(OPTION_NON_SHARED, OPTION_XGOT, OPTION_MABI, OPTION_32)
	(OPTION_N32, OPTION_64, OPTION_MDEBUG, OPTION_NO_MDEBUG)
	(OPTION_PDR, OPTION_NO_PDR, OPTION_MVXWORKS_PIC): Bump by 1.
	(md_longopts): Add -call_nonpic.
	(md_parse_option): Handle OPTION_CALL_NONPIC.
	(md_show_usage): Add -call_nonpic.

gas/testsuite/
	* gas/mips/call-nonpic-1.s, gas/mips/call-nonpic-1.d: New test.
	* gas/mips/mips.exp: Run it.

ld/
	* emulparams/elf32bmip.sh (GOT): Define, moving .got.plt to...
	(OTHER_RELRO_SECTIONS, OTHER_READWRITE_SECTIONS): ...one of these
	two variables.
	* emulparams/elf32bmipn32-defs.sh: Likewise.
	* emultempl/mipself.em: Include ldctor.h, elf/mips.h and elfxx-mips.h.
	(is_mips_elf): New macro.
	(stub_file, stub_bfd): New variables.
	(hook_stub_info): New structure.
	(hook_in_stub): New function.
	(mips_add_stub_section): Likewise.
	(mips_create_output_section_statements): Likewise.
	(mips_before_allocation): Likewise.
	(real_func): New variable.
	(mips_for_each_input_file_wrapper): New function.
	(mips_lang_for_each_input_file): Likewise.
	(lang_for_each_input_file): Define.
	(LDEMUL_BEFORE_ALLOCATION): Likewise.
	(LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS): Likewise.

ld/testsuite/
	* ld-mips-elf/mips16-pic-3a.s,
	ld-mips-elf/mips16-pic-3b.s,
	ld-mips-elf/mips16-pic-3.dd,
	ld-mips-elf/mips16-pic-3.gd,
	ld-mips-elf/mips16-pic-3.rd,
	ld-mips-elf/mips16-pic-3.inc,
	ld-mips-elf/pic-and-nonpic-1a.s,
	ld-mips-elf/pic-and-nonpic-1b.s,
	ld-mips-elf/pic-and-nonpic-1.ld,
	ld-mips-elf/pic-and-nonpic-1.dd,
	ld-mips-elf/pic-and-nonpic-1.nd,
	ld-mips-elf/pic-and-nonpic-1-rel.dd,
	ld-mips-elf/pic-and-nonpic-1-rel.nd,
	ld-mips-elf/pic-and-nonpic-2a.s,
	ld-mips-elf/pic-and-nonpic-2b.s,
	ld-mips-elf/pic-and-nonpic-2.d,
	ld-mips-elf/pic-and-nonpic-3a.s,
	ld-mips-elf/pic-and-nonpic-3a.ld,
	ld-mips-elf/pic-and-nonpic-3a.dd,
	ld-mips-elf/pic-and-nonpic-3a.gd,
	ld-mips-elf/pic-and-nonpic-3a.sd,
	ld-mips-elf/pic-and-nonpic-3b.s,
	ld-mips-elf/pic-and-nonpic-3b.ld,
	ld-mips-elf/pic-and-nonpic-3b.ad,
	ld-mips-elf/pic-and-nonpic-3b.dd,
	ld-mips-elf/pic-and-nonpic-3b.gd,
	ld-mips-elf/pic-and-nonpic-3b.nd,
	ld-mips-elf/pic-and-nonpic-3b.pd,
	ld-mips-elf/pic-and-nonpic-3b.rd,
	ld-mips-elf/pic-and-nonpic-3b.sd,
	ld-mips-elf/pic-and-nonpic-3-error.d,
	ld-mips-elf/pic-and-nonpic-4a.s,
	ld-mips-elf/pic-and-nonpic-4b.s,
	ld-mips-elf/pic-and-nonpic-4b.ld,
	ld-mips-elf/pic-and-nonpic-4b.ad,
	ld-mips-elf/pic-and-nonpic-4b.dd,
	ld-mips-elf/pic-and-nonpic-4b.gd,
	ld-mips-elf/pic-and-nonpic-4b.nd,
	ld-mips-elf/pic-and-nonpic-4b.rd,
	ld-mips-elf/pic-and-nonpic-4b.sd,
	ld-mips-elf/pic-and-nonpic-4-error.d,
	ld-mips-elf/pic-and-nonpic-5a.s,
	ld-mips-elf/pic-and-nonpic-5b.s,
	ld-mips-elf/pic-and-nonpic-5b.ld,
	ld-mips-elf/pic-and-nonpic-5b.ad,
	ld-mips-elf/pic-and-nonpic-5b.dd,
	ld-mips-elf/pic-and-nonpic-5b.gd,
	ld-mips-elf/pic-and-nonpic-5b.nd,
	ld-mips-elf/pic-and-nonpic-5b.rd,
	ld-mips-elf/pic-and-nonpic-5b.sd,
	ld-mips-elf/pic-and-nonpic-5b.pd,
	ld-mips-elf/pic-and-nonpic-6.ld,
	ld-mips-elf/pic-and-nonpic-6-o32a.s,
	ld-mips-elf/pic-and-nonpic-6-o32b.s,
	ld-mips-elf/pic-and-nonpic-6-o32c.s,
	ld-mips-elf/pic-and-nonpic-6-o32.ad,
	ld-mips-elf/pic-and-nonpic-6-o32.dd,
	ld-mips-elf/pic-and-nonpic-6-o32.gd,
	ld-mips-elf/pic-and-nonpic-6-o32.nd,
	ld-mips-elf/pic-and-nonpic-6-o32.pd,
	ld-mips-elf/pic-and-nonpic-6-o32.rd,
	ld-mips-elf/pic-and-nonpic-6-o32.sd,
	ld-mips-elf/pic-and-nonpic-6-n32a.s,
	ld-mips-elf/pic-and-nonpic-6-n32b.s,
	ld-mips-elf/pic-and-nonpic-6-n32c.s,
	ld-mips-elf/pic-and-nonpic-6-n32.ad,
	ld-mips-elf/pic-and-nonpic-6-n32.dd,
	ld-mips-elf/pic-and-nonpic-6-n32.gd,
	ld-mips-elf/pic-and-nonpic-6-n32.nd,
	ld-mips-elf/pic-and-nonpic-6-n32.pd,
	ld-mips-elf/pic-and-nonpic-6-n32.rd,
	ld-mips-elf/pic-and-nonpic-6-n32.sd,
	ld-mips-elf/pic-and-nonpic-6-n64a.s,
	ld-mips-elf/pic-and-nonpic-6-n64b.s,
	ld-mips-elf/pic-and-nonpic-6-n64c.s,
	ld-mips-elf/pic-and-nonpic-6-n64.ad,
	ld-mips-elf/pic-and-nonpic-6-n64.dd,
	ld-mips-elf/pic-and-nonpic-6-n64.gd,
	ld-mips-elf/pic-and-nonpic-6-n64.nd,
	ld-mips-elf/pic-and-nonpic-6-n64.pd,
	ld-mips-elf/pic-and-nonpic-6-n64.rd,
	ld-mips-elf/pic-and-nonpic-6-n64.sd: New tests.
	* ld-mips-elf/mips-elf.exp: Run them.

Index: include/elf/mips.h
===================================================================
--- include/elf/mips.h	2008-08-03 13:12:34.000000000 +0100
+++ include/elf/mips.h	2008-08-03 13:15:44.000000000 +0100
@@ -723,6 +723,24 @@ #define STO_INTERNAL		STV_INTERNAL
 #define STO_HIDDEN		STV_HIDDEN
 #define STO_PROTECTED		STV_PROTECTED
 
+/* The GNU tools extend the MIPS psABI with support for PLTs and copy
+   relocs.  There are therefore two types of nonzero SHN_UNDEF functions:
+   PLT entries and traditional MIPS lazy binding stubs.  We mark the former
+   with STO_MIPS_PLT to distinguish them from the latter.  */
+#define STO_MIPS_PLT		0x10
+#define ELF_ST_IS_MIPS_PLT(OTHER)			\
+  (((OTHER) & ~ELF_ST_VISIBILITY (-1)) == STO_MIPS_PLT)
+#define ELF_ST_SET_MIPS_PLT(OTHER)		\
+  (STO_MIPS_PLT | ELF_ST_VISIBILITY (OTHER))
+
+/* This value is used to mark PIC functions in an object that mixes
+   PIC and non-PIC.  */
+#define STO_MIPS_PIC		0x20
+#define ELF_ST_IS_MIPS_PIC(OTHER) \
+  (((OTHER) & ~ELF_ST_VISIBILITY (-1)) == STO_MIPS_PIC)
+#define ELF_ST_SET_MIPS_PIC(OTHER) \
+  (STO_MIPS_PIC | ELF_ST_VISIBILITY (OTHER))
+
 /* This value is used for a mips16 .text symbol.  */
 #define STO_MIPS16		0xf0
 #define ELF_ST_IS_MIPS16(OTHER) (((OTHER) & 0xf0) == STO_MIPS16)
Index: bfd/elf32-mips.c
===================================================================
--- bfd/elf32-mips.c	2008-08-03 13:15:41.000000000 +0100
+++ bfd/elf32-mips.c	2008-08-03 13:15:44.000000000 +0100
@@ -899,6 +899,38 @@ static reloc_howto_type elf_mips_gnu_vte
 	 0,			/* dst_mask */
 	 FALSE);		/* pcrel_offset */
 
+/* Originally a VxWorks extension, but now used for GNU extensions too.  */
+static reloc_howto_type elf_mips_copy_howto =
+  HOWTO (R_MIPS_COPY,		/* type */
+	 0,			/* rightshift */
+	 0,			/* this one is variable size */
+	 0,			/* 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 */
+
+/* Originally a VxWorks extension, but now used for GNU extensions too.  */
+static reloc_howto_type elf_mips_jump_slot_howto =
+  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 */
+
 /* Set the GP value for OUTPUT_BFD.  Returns FALSE if this is a
    dangerous relocation.  */
 
@@ -1299,6 +1331,10 @@ bfd_elf32_bfd_reloc_type_lookup (bfd *ab
       return &elf_mips_gnu_vtentry_howto;
     case BFD_RELOC_32_PCREL:
       return &elf_mips_gnu_pcrel32;
+    case BFD_RELOC_MIPS_COPY:
+      return &elf_mips_copy_howto;
+    case BFD_RELOC_MIPS_JUMP_SLOT:
+      return &elf_mips_jump_slot_howto;
     }
 }
 
@@ -1332,6 +1368,10 @@ bfd_elf32_bfd_reloc_name_lookup (bfd *ab
     return &elf_mips_gnu_vtinherit_howto;
   if (strcasecmp (elf_mips_gnu_vtentry_howto.name, r_name) == 0)
     return &elf_mips_gnu_vtentry_howto;
+  if (strcasecmp (elf_mips_copy_howto.name, r_name) == 0)
+    return &elf_mips_copy_howto;
+  if (strcasecmp (elf_mips_jump_slot_howto.name, r_name) == 0)
+    return &elf_mips_jump_slot_howto;
 
   return NULL;
 }
@@ -1352,6 +1392,10 @@ mips_elf32_rtype_to_howto (unsigned int 
       return &elf_mips_gnu_rel16_s2;
     case R_MIPS_PC32:
       return &elf_mips_gnu_pcrel32;
+    case R_MIPS_COPY:
+      return &elf_mips_copy_howto;
+    case R_MIPS_JUMP_SLOT:
+      return &elf_mips_jump_slot_howto;
     default:
       if (r_type >= R_MIPS16_min && r_type < R_MIPS16_max)
         return &elf_mips16_howto_table_rel[r_type - R_MIPS16_min];
@@ -1615,6 +1659,8 @@ #define elf_backend_may_use_rel_p	1
 #define elf_backend_may_use_rela_p	0
 #define elf_backend_default_use_rela_p	0
 #define elf_backend_sign_extend_vma	TRUE
+#define elf_backend_plt_readonly	1
+#define elf_backend_plt_sym_val		_bfd_mips_elf_plt_sym_val
 
 #define elf_backend_discard_info	_bfd_mips_elf_discard_info
 #define elf_backend_ignore_discarded_relocs \
@@ -1679,82 +1725,6 @@ #define elf32_bed			elf32_tradbed
 /* 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);
-    }
-}
-
-static reloc_howto_type *
-mips_vxworks_bfd_reloc_name_lookup (bfd *abfd, const char *r_name)
-{
-  if (strcasecmp (mips_vxworks_copy_howto_rela.name, r_name) == 0)
-    return &mips_vxworks_copy_howto_rela;
-  if (strcasecmp (mips_vxworks_jump_slot_howto_rela.name, r_name) == 0)
-    return &mips_vxworks_jump_slot_howto_rela;
-
-  return bfd_elf32_bfd_reloc_name_lookup (abfd, r_name);
-}
-
-/* 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
@@ -1789,8 +1759,6 @@ #define elf_backend_want_got_plt		1
 #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
@@ -1799,21 +1767,8 @@ #define elf_backend_may_use_rela_p		1
 #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 elf_backend_plt_sym_val
 
-#undef bfd_elf32_bfd_reloc_type_lookup
-#define bfd_elf32_bfd_reloc_type_lookup \
-  mips_vxworks_bfd_reloc_type_lookup
-#undef bfd_elf32_bfd_reloc_name_lookup
-#define bfd_elf32_bfd_reloc_name_lookup \
-  mips_vxworks_bfd_reloc_name_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
Index: bfd/elfn32-mips.c
===================================================================
--- bfd/elfn32-mips.c	2008-08-03 13:15:41.000000000 +0100
+++ bfd/elfn32-mips.c	2008-08-03 13:15:44.000000000 +0100
@@ -1717,6 +1717,38 @@ static reloc_howto_type elf_mips_gnu_rel
 	 0x0000ffff,		/* dst_mask */
 	 TRUE);			/* pcrel_offset */
 
+/* Originally a VxWorks extension, but now used for GNU extensions too.  */
+static reloc_howto_type elf_mips_copy_howto =
+  HOWTO (R_MIPS_COPY,		/* type */
+	 0,			/* rightshift */
+	 0,			/* this one is variable size */
+	 0,			/* 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 */
+
+/* Originally a VxWorks extension, but now used for GNU extensions too.  */
+static reloc_howto_type elf_mips_jump_slot_howto =
+  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 */
+
 /* Set the GP value for OUTPUT_BFD.  Returns FALSE if this is a
    dangerous relocation.  */
 
@@ -2127,6 +2159,10 @@ bfd_elf32_bfd_reloc_type_lookup (bfd *ab
       return &elf_mips_gnu_vtinherit_howto;
     case BFD_RELOC_VTABLE_ENTRY:
       return &elf_mips_gnu_vtentry_howto;
+    case BFD_RELOC_MIPS_COPY:
+      return &elf_mips_copy_howto;
+    case BFD_RELOC_MIPS_JUMP_SLOT:
+      return &elf_mips_jump_slot_howto;
     default:
       bfd_set_error (bfd_error_bad_value);
       return NULL;
@@ -2163,6 +2199,10 @@ bfd_elf32_bfd_reloc_name_lookup (bfd *ab
     return &elf_mips_gnu_rel16_s2;
   if (strcasecmp (elf_mips_gnu_rela16_s2.name, r_name) == 0)
     return &elf_mips_gnu_rela16_s2;
+  if (strcasecmp (elf_mips_copy_howto.name, r_name) == 0)
+    return &elf_mips_copy_howto;
+  if (strcasecmp (elf_mips_jump_slot_howto.name, r_name) == 0)
+    return &elf_mips_jump_slot_howto;
 
   return NULL;
 }
@@ -2183,6 +2223,10 @@ mips_elf_n32_rtype_to_howto (unsigned in
 	return &elf_mips_gnu_rela16_s2;
       else
 	return &elf_mips_gnu_rel16_s2;
+    case R_MIPS_COPY:
+      return &elf_mips_copy_howto;
+    case R_MIPS_JUMP_SLOT:
+      return &elf_mips_jump_slot_howto;
     default:
       if (r_type >= R_MIPS16_min && r_type < R_MIPS16_max)
 	{
@@ -2444,7 +2488,10 @@ #define elf_backend_got_header_size	(4 *
 #define elf_backend_may_use_rel_p	1
 #define elf_backend_may_use_rela_p	1
 #define elf_backend_default_use_rela_p	1
+#define elf_backend_rela_plts_and_copies_p 0
 #define elf_backend_sign_extend_vma	TRUE
+#define elf_backend_plt_readonly	1
+#define elf_backend_plt_sym_val		_bfd_mips_elf_plt_sym_val
 
 #define elf_backend_discard_info	_bfd_mips_elf_discard_info
 #define elf_backend_ignore_discarded_relocs \
Index: bfd/elf64-mips.c
===================================================================
--- bfd/elf64-mips.c	2008-08-03 13:15:41.000000000 +0100
+++ bfd/elf64-mips.c	2008-08-03 13:15:44.000000000 +0100
@@ -1724,6 +1724,38 @@ static reloc_howto_type elf_mips_gnu_rel
 	 0x0000ffff,		/* dst_mask */
 	 TRUE);			/* pcrel_offset */
 
+/* Originally a VxWorks extension, but now used for GNU extensions too.  */
+static reloc_howto_type elf_mips_copy_howto =
+  HOWTO (R_MIPS_COPY,		/* type */
+	 0,			/* rightshift */
+	 0,			/* this one is variable size */
+	 0,			/* 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 */
+
+/* Originally a VxWorks extension, but now used for GNU extensions too.  */
+static reloc_howto_type elf_mips_jump_slot_howto =
+  HOWTO (R_MIPS_JUMP_SLOT,	/* type */
+	 0,			/* rightshift */
+	 4,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* 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 */
+
 /* Swap in a MIPS 64-bit Rel reloc.  */
 
 static void
@@ -2283,6 +2315,10 @@ bfd_elf64_bfd_reloc_type_lookup (bfd *ab
       return &elf_mips_gnu_vtinherit_howto;
     case BFD_RELOC_VTABLE_ENTRY:
       return &elf_mips_gnu_vtentry_howto;
+    case BFD_RELOC_MIPS_COPY:
+      return &elf_mips_copy_howto;
+    case BFD_RELOC_MIPS_JUMP_SLOT:
+      return &elf_mips_jump_slot_howto;
     default:
       bfd_set_error (bfd_error_bad_value);
       return NULL;
@@ -2318,6 +2354,10 @@ bfd_elf64_bfd_reloc_name_lookup (bfd *ab
     return &elf_mips_gnu_rel16_s2;
   if (strcasecmp (elf_mips_gnu_rela16_s2.name, r_name) == 0)
     return &elf_mips_gnu_rela16_s2;
+  if (strcasecmp (elf_mips_copy_howto.name, r_name) == 0)
+    return &elf_mips_copy_howto;
+  if (strcasecmp (elf_mips_jump_slot_howto.name, r_name) == 0)
+    return &elf_mips_jump_slot_howto;
 
   return NULL;
 }
@@ -2338,6 +2378,10 @@ mips_elf64_rtype_to_howto (unsigned int 
 	return &elf_mips_gnu_rela16_s2;
       else
 	return &elf_mips_gnu_rel16_s2;
+    case R_MIPS_COPY:
+      return &elf_mips_copy_howto;
+    case R_MIPS_JUMP_SLOT:
+      return &elf_mips_jump_slot_howto;
     default:
       if (r_type >= R_MIPS16_min && r_type < R_MIPS16_max)
 	{
@@ -3196,6 +3240,9 @@ #define elf_backend_got_header_size	(4 *
 #define elf_backend_may_use_rel_p	1
 #define elf_backend_may_use_rela_p	1
 #define elf_backend_default_use_rela_p	1
+#define elf_backend_rela_plts_and_copies_p 0
+#define elf_backend_plt_readonly	1
+#define elf_backend_plt_sym_val		_bfd_mips_elf_plt_sym_val
 
 #define elf_backend_sign_extend_vma	TRUE
 
Index: bfd/elfxx-mips.h
===================================================================
--- bfd/elfxx-mips.h	2008-08-03 13:15:41.000000000 +0100
+++ bfd/elfxx-mips.h	2008-08-03 13:15:44.000000000 +0100
@@ -50,8 +50,6 @@
   (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
@@ -141,6 +139,13 @@
 extern char *_bfd_mips_elf_get_target_dtag (bfd_vma);
 extern bfd_boolean _bfd_mips_elf_ignore_undef_symbol
   (struct elf_link_hash_entry *);
+extern void _bfd_mips_elf_use_plts_and_copy_relocs
+  (struct bfd_link_info *);
+extern bfd_boolean _bfd_mips_elf_init_stubs
+  (struct bfd_link_info *,
+   asection *(*) (const char *, asection *, asection *));
+extern bfd_vma _bfd_mips_elf_plt_sym_val
+  (bfd_vma, const asection *, const arelent *rel);
 
 extern const struct bfd_elf_special_section _bfd_mips_elf_special_sections [];
 
Index: bfd/elfxx-mips.c
===================================================================
--- bfd/elfxx-mips.c	2008-08-03 13:15:41.000000000 +0100
+++ bfd/elfxx-mips.c	2008-08-03 14:54:40.000000000 +0100
@@ -269,6 +269,42 @@ #define GGA_NORMAL 0
 #define GGA_RELOC_ONLY 1
 #define GGA_NONE 2
 
+/* Information about a non-PIC interface to a PIC function.  There are
+   two ways of creating these interfaces.  The first is to add:
+
+	lui	$25,%hi(func)
+	addiu	$25,$25,%lo(func)
+
+   immediately before a PIC function "func".  The second is to add:
+
+	lui	$25,%hi(func)
+	j	func
+	addiu	$25,$25,%lo(func)
+
+   to a separate trampoline section.
+
+   Stubs of the first kind go in a new section immediately before the
+   target function.  Stubs of the second kind go in a single section
+   pointed to by the hash table's "strampoline" field.  */
+struct mips_elf_la25_stub {
+  /* The input section that contains the PIC function.  */
+  asection *input_section;
+
+  /* The offset of the PIC function from the start of INPUT_SECTION.  */
+  bfd_vma offset;
+
+  /* One symbol that has been redirected from the original function
+     to a stub.  The symbol's value has been changed to the stub's
+     address and is available in H->root.root.u.def.  */
+  struct mips_elf_link_hash_entry *h;
+};
+
+/* Macros for populating a mips_elf_la25_stub.  */
+
+#define LA25_LUI(VAL) (0x3c190000 | (VAL))	/* lui t9,VAL */
+#define LA25_J(VAL) (0x08000000 | (((VAL) >> 2) & 0x3ffffff)) /* j VAL */
+#define LA25_ADDIU(VAL) (0x27390000 | (VAL))	/* addiu t9,t9,VAL */
+
 /* This structure is passed to mips_elf_sort_hash_table_f when sorting
    the dynamic symbols.  */
 
@@ -299,6 +335,9 @@ struct mips_elf_link_hash_entry
   /* External symbol information.  */
   EXTR esym;
 
+  /* The la25 stub we have created for ths symbol, if any.  */
+  struct mips_elf_la25_stub *la25_stub;
+
   /* Number of R_MIPS_32, R_MIPS_REL32, or R_MIPS_64 relocs against
      this symbol.  */
   unsigned int possibly_dynamic_relocs;
@@ -338,6 +377,14 @@ #define GOT_TLS_DONE    0x80
      is against a readonly section.  */
   unsigned int readonly_reloc : 1;
 
+  /* True if there is a relocation against this symbol that must be
+     resolved by the static linker (in other words, if the relocation
+     cannot possibly be made dynamic).  */
+  unsigned int has_static_relocs : 1;
+
+  /* True if the symbol is referenced by a non-PIC object.  */
+  unsigned int non_pic_ref : 1;
+
   /* True if we must not create a .MIPS.stubs entry for this symbol.
      This is set, for example, if there are relocations related to
      taking the function's address, i.e. any but R_MIPS_CALL*16 ones.
@@ -348,12 +395,6 @@ #define GOT_TLS_DONE    0x80
      in any relocs other than a 16 bit call.  */
   unsigned int need_fn_stub : 1;
 
-  /* Are we referenced by some kind of relocation?  */
-  unsigned int is_relocation_target : 1;
-
-  /* Are we referenced by branch relocations?  */
-  unsigned int is_branch_target : 1;
-
   /* Does this symbol need a traditional MIPS lazy-binding stub
      (as opposed to a PLT entry)?  */
   unsigned int needs_lazy_stub : 1;
@@ -369,21 +410,32 @@ struct mips_elf_link_hash_table
   /* String section indices for the dynamic section symbols.  */
   bfd_size_type dynsym_sec_strindex[SIZEOF_MIPS_DYNSYM_SECNAMES];
 #endif
+
   /* The number of .rtproc entries.  */
   bfd_size_type procedure_count;
+
   /* The size of the .compact_rel section (if SGI_COMPAT).  */
   bfd_size_type compact_rel_size;
+
   /* This flag indicates that the value of DT_MIPS_RLD_MAP dynamic
      entry is set to the address of __rld_obj_head as in IRIX5.  */
   bfd_boolean use_rld_obj_head;
+
   /* This is the value of the __rld_map or __rld_obj_head symbol.  */
   bfd_vma rld_value;
+
   /* This is set if we see any mips16 stub sections.  */
   bfd_boolean mips16_stubs_seen;
+
+  /* True if we can generate copy relocs and PLTs.  */
+  bfd_boolean use_plts_and_copy_relocs;
+
   /* True if we're generating code for VxWorks.  */
   bfd_boolean is_vxworks;
+
   /* True if we already reported the small-data section overflow.  */
   bfd_boolean small_data_overflow_reported;
+
   /* Shortcuts to some dynamic sections, or NULL if they are not
      being used.  */
   asection *srelbss;
@@ -394,16 +446,51 @@ struct mips_elf_link_hash_table
   asection *splt;
   asection *sstubs;
   asection *sgot;
+
   /* The master GOT information.  */
   struct mips_got_info *got_info;
+
   /* 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;
+
   /* The number of functions that need a lazy-binding stub.  */
   bfd_vma lazy_stub_count;
+
   /* The size of a function stub entry in bytes.  */
   bfd_vma function_stub_size;
+
+  /* The number of reserved entries at the beginning of the GOT.  */
+  unsigned int reserved_gotno;
+
+  /* The section used for mips_elf_la25_stub trampolines.
+     See the comment above that structure for details.  */
+  asection *strampoline;
+
+  /* A table of mips_elf_la25_stubs, indexed by (input_section, offset)
+     pairs.  */
+  htab_t la25_stubs;
+
+  /* A function FN (NAME, IS, OS) that creates a new input section
+     called NAME and links it to output section OS.  If IS is nonnull,
+     the new section should go immediately before it, otherwise it
+     should go at the (current) beginning of OS.
+
+     The function returns the new section on success, otherwise it
+     returns null.  */
+  asection *(*add_stub_section) (const char *, asection *, asection *);
+};
+
+/* A structure used to communicate with htab_traverse callbacks.  */
+struct mips_htab_traverse_info {
+  /* The usual link-wide information.  */
+  struct bfd_link_info *info;
+  bfd *output_bfd;
+
+  /* Starts off FALSE and is set to TRUE if the link should be aborted.  */
+  bfd_boolean error;
 };
 
 #define TLS_RELOC_P(r_type) \
@@ -574,6 +661,10 @@ #define rpdNil ((pRPDR) 0)
 /* This will be used when we sort the dynamic relocation records.  */
 static bfd *reldyn_sorting_bfd;
 
+/* True if ABFD is a PIC object.  */
+#define PIC_OBJECT_P(abfd) \
+  ((elf_elfheader (abfd)->e_flags & EF_MIPS_PIC) != 0)
+
 /* Nonzero if ABFD is using the N32 ABI.  */
 #define ABI_N32_P(abfd) \
   ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI2) != 0)
@@ -644,6 +735,10 @@ #define MIPS_ELF_PUT_WORD(abfd, val, ptr
    ? bfd_put_64 (abfd, val, ptr) 		\
    : bfd_put_32 (abfd, val, ptr))
 
+/* The opcode for word-sized loads (LW or LD).  */
+#define MIPS_ELF_LOAD_WORD(abfd) \
+  (ABI_64_P (abfd) ? 0xdc000000 : 0x8c000000)
+
 /* Add a dynamic symbol table-entry.  */
 #define MIPS_ELF_ADD_DYNAMIC_ENTRY(info, tag, val)	\
   _bfd_elf_add_dynamic_entry (info, tag, val)
@@ -677,10 +772,6 @@ #define MIPS_ELF_REL_DYN_NAME(INFO) \
 #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(INFO) \
-  (mips_elf_hash_table (INFO)->is_vxworks ? 3 : 2)
-
 /* The value to write into got[1] for SVR4 targets, to identify it is
    a GNU object.  The dynamic linker can then use got[1] to store the
    module pointer.  */
@@ -785,6 +876,26 @@ #define FN_STUB_P(name) CONST_STRNEQ (na
 #define CALL_STUB_P(name) CONST_STRNEQ (name, CALL_STUB)
 #define CALL_FP_STUB_P(name) CONST_STRNEQ (name, CALL_FP_STUB)
 
+/* The format of the first PLT entry in a GNU executable.  */
+static const bfd_vma mips_exec_plt0_entry[] = {
+  0x3c0f0000,	/* lui $15, %hi(&_GLOBAL_OFFSET_TABLE_[2])		*/
+  0x01f90000,	/* l[wd] $25, %lo(&_GLOBAL_OFFSET_TABLE_[2])($15)	*/
+  0x25ef0000,	/* addiu $15, $15, %lo(&_GLOBAL_OFFSET_TABLE_[2])	*/
+  0x3c0e0000,	/* lui $14, %hi(.got.plt)				*/
+  0x03200008,	/* jr $25						*/
+  0x25ce0000,	/* addiu $14, $14, %lo(.got.plt)			*/
+  0x00000000,	/* padding						*/
+  0x00000000	/* ...							*/
+};
+
+/* The format of subsequent PLT entries.  */
+static const bfd_vma mips_exec_plt_entry[] = {
+  0x3c180000,	/* lui $24, %hi(.got.plt entry)			*/
+  0x03190000,	/* l[wd] $25, %lo(.got.plt entry)($24)		*/
+  0x03200008,	/* jr $25					*/
+  0x27180000	/* addiu $24, $24, %lo(.got.plt entry)		*/
+};
+
 /* 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_)		*/
@@ -894,6 +1005,7 @@ mips_elf_link_hash_newfunc (struct bfd_h
       /* We use -2 as a marker to indicate that the information has
 	 not been set.  -1 means there is no associated ifd.  */
       ret->esym.ifd = -2;
+      ret->la25_stub = 0;
       ret->possibly_dynamic_relocs = 0;
       ret->fn_stub = NULL;
       ret->call_stub = NULL;
@@ -901,10 +1013,10 @@ mips_elf_link_hash_newfunc (struct bfd_h
       ret->tls_type = GOT_NORMAL;
       ret->global_got_area = GGA_NONE;
       ret->readonly_reloc = FALSE;
+      ret->has_static_relocs = FALSE;
+      ret->non_pic_ref = FALSE;
       ret->no_fn_stub = FALSE;
       ret->need_fn_stub = FALSE;
-      ret->is_relocation_target = FALSE;
-      ret->is_branch_target = FALSE;
       ret->needs_lazy_stub = FALSE;
     }
 
@@ -1262,15 +1374,10 @@ mips16_stub_symndx (asection *sec, const
 /* Check the mips16 stubs for a particular symbol, and see if we can
    discard them.  */
 
-static bfd_boolean
-mips_elf_check_mips16_stubs (struct mips_elf_link_hash_entry *h, void *data)
+static void
+mips_elf_check_mips16_stubs (struct bfd_link_info *info,
+			     struct mips_elf_link_hash_entry *h)
 {
-  struct bfd_link_info *info;
-
-  info = (struct bfd_link_info *) data;
-  if (h->root.root.type == bfd_link_hash_warning)
-    h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
-
   /* Dynamic symbols must use the standard call interface, in case other
      objects try to call them.  */
   if (h->fn_stub != NULL
@@ -1315,9 +1422,247 @@ mips_elf_check_mips16_stubs (struct mips
       h->call_fp_stub->reloc_count = 0;
       h->call_fp_stub->flags |= SEC_EXCLUDE;
     }
+}
+
+/* Hashtable callbacks for mips_elf_la25_stubs.  */
+
+static hashval_t
+mips_elf_la25_stub_hash (const void *entry_)
+{
+  const struct mips_elf_la25_stub *entry;
+
+  entry = (struct mips_elf_la25_stub *) entry_;
+  return entry->input_section->id + entry->offset;
+}
+
+static int
+mips_elf_la25_stub_eq (const void *entry1_, const void *entry2_)
+{
+  const struct mips_elf_la25_stub *entry1, *entry2;
+
+  entry1 = (struct mips_elf_la25_stub *) entry1_;
+  entry2 = (struct mips_elf_la25_stub *) entry2_;
+  return (entry1->input_section == entry2->input_section
+	  && entry1->offset == entry2->offset);
+}
+
+/* Called by the linker to set up the la25 stub-creation code.  FN is
+   the linker's implementation of add_stub_function.  Return true on
+   success.  */
+
+bfd_boolean
+_bfd_mips_elf_init_stubs (struct bfd_link_info *info,
+			  asection *(*fn) (const char *, asection *,
+					   asection *))
+{
+  struct mips_elf_link_hash_table *htab;
+
+  htab = mips_elf_hash_table (info);
+  htab->add_stub_section = fn;
+  htab->la25_stubs = htab_try_create (1, mips_elf_la25_stub_hash,
+				      mips_elf_la25_stub_eq, NULL);
+  if (htab->la25_stubs == NULL)
+    return FALSE;
 
   return TRUE;
 }
+
+/* Return true if H is a locally-defined PIC function, in the sense
+   that it might need $25 to be valid on entry.  Note that MIPS16
+   functions never need $25 to be valid on entry; they set up $gp
+   using PC-relative instructions instead.  */
+
+static bfd_boolean
+mips_elf_local_pic_function_p (struct mips_elf_link_hash_entry *h)
+{
+  return ((h->root.root.type == bfd_link_hash_defined
+	   || h->root.root.type == bfd_link_hash_defweak)
+	  && h->root.def_regular
+	  && h->root.type == STT_FUNC
+	  && !ELF_ST_IS_MIPS16 (h->root.other)
+	  && (PIC_OBJECT_P (h->root.root.u.def.section->owner)
+	      || ELF_ST_IS_MIPS_PIC (h->root.other)));
+}
+
+/* STUB describes an la25 stub that we have decided to implement
+   by inserting an LUI/ADDIU pair before the target function.
+   Create the section and redirect the function symbol to it.  */
+
+static bfd_boolean
+mips_elf_add_la25_intro (struct mips_elf_la25_stub *stub,
+			 struct bfd_link_info *info)
+{
+  struct mips_elf_link_hash_table *htab;
+  char *name;
+  asection *s;
+  unsigned int align;
+
+  htab = mips_elf_hash_table (info);
+
+  /* Create a unique name for the new section.  */
+  name = bfd_malloc (11 + sizeof (".text.stub."));
+  if (name == NULL)
+    return FALSE;
+  sprintf (name, ".text.stub.%d", (int) htab_elements (htab->la25_stubs));
+
+  /* Create the section.  */
+  s = htab->add_stub_section (name, stub->input_section,
+			      stub->input_section->output_section);
+  if (s == NULL)
+    return FALSE;
+
+  /* Make sure that any padding goes before the stub.  */
+  align = stub->input_section->alignment_power;
+  if (!bfd_set_section_alignment (s->owner, s, align))
+    return FALSE;
+  if (align > 3)
+    s->size = (1 << align) - 8;
+
+  /* Redirect the symbol to the stub.  */
+  stub->h->root.root.u.def.section = s;
+  stub->h->root.root.u.def.value = s->size;
+
+  /* Allocate room for it.  */
+  s->size += 8;
+  return TRUE;
+}
+
+/* STUB describes an la25 stub that we have decided to implement
+   with a separate trampoline.  Allocate room for it and redirect
+   the function symbol to it.  */
+
+static bfd_boolean
+mips_elf_add_la25_trampoline (struct mips_elf_la25_stub *stub,
+			      struct bfd_link_info *info)
+{
+  struct mips_elf_link_hash_table *htab;
+  asection *s;
+
+  htab = mips_elf_hash_table (info);
+
+  /* Create a trampoline section, if we haven't already.  */
+  s = htab->strampoline;
+  if (s == NULL)
+    {
+      s = htab->add_stub_section (".text", NULL,
+				  stub->input_section->output_section);
+      if (s == NULL || !bfd_set_section_alignment (s->owner, s, 4))
+	return FALSE;
+      htab->strampoline = s;
+    }
+
+  /* Redirect the symbol to the stub.  */
+  stub->h->root.root.u.def.section = s;
+  stub->h->root.root.u.def.value = s->size;
+
+  /* Allocate room for it.  */
+  s->size += stub->h->root.size;
+  return TRUE;
+}
+
+/* H describes a symbol that needs an la25 stub.  Make sure that an
+   appropriate stub exists and point H at it.  */
+
+static bfd_boolean
+mips_elf_add_la25_stub (struct bfd_link_info *info,
+			struct mips_elf_link_hash_entry *h)
+{
+  struct mips_elf_link_hash_table *htab;
+  struct mips_elf_la25_stub search, *stub;
+  bfd_boolean use_trampoline_p;
+  asection *s;
+  bfd_vma value;
+  void **slot;
+
+  /* Remember the symbol's original value.  */
+  s = h->root.root.u.def.section;
+  value = h->root.root.u.def.value;
+
+  /* Prefer to use LUI/ADDIU stubs if the function is at the beginning
+     of the section and if we would need no more than 2 nops.  */
+  use_trampoline_p = (h->root.root.u.def.value != 0 || s->alignment_power > 4);
+  if (use_trampoline_p)
+    {
+      /* Add a ".pic.FN" symbol to cover the original function.  */
+      mips_elf_create_shadow_symbol (info, h, ".pic.");
+
+      /* Set the function's new size.  */
+      h->root.size = 16;
+    }
+  else
+    {
+      /* Add the LUI and ADDIU to the function's size.  */
+      h->root.size += 8;
+    }
+
+  /* Describe the stub we want.  */
+  search.input_section = s;
+  search.offset = value;
+  search.h = h;
+
+  /* See if we've already created an equivalent stub.  */
+  htab = mips_elf_hash_table (info);
+  slot = htab_find_slot (htab->la25_stubs, &search, INSERT);
+  if (slot == NULL)
+    return FALSE;
+
+  stub = (struct mips_elf_la25_stub *) *slot;
+  if (stub != NULL)
+    {
+      /* We can reuse the existing stub.  Copy the stub symbol's
+	 new value to H.  */
+      h->la25_stub = stub;
+      h->root.root.u.def = stub->h->root.root.u.def;
+      return TRUE;
+    }
+
+  /* Create a permanent copy of ENTRY and add it to the hash table.  */
+  stub = bfd_malloc (sizeof (search));
+  if (stub == NULL)
+    return FALSE;
+  *stub = search;
+  *slot = stub;
+
+  h->la25_stub = stub;
+  return (use_trampoline_p
+	  ? mips_elf_add_la25_trampoline (stub, info)
+	  : mips_elf_add_la25_intro (stub, info));
+}
+
+/* A mips_elf_link_hash_traverse callback that is called before sizing
+   sections.  DATA points to a mips_htab_traverse_info structure.  */
+
+static bfd_boolean
+mips_elf_check_symbols (struct mips_elf_link_hash_entry *h, void *data)
+{
+  struct mips_htab_traverse_info *hti;
+
+  hti = (struct mips_htab_traverse_info *) data;
+  if (h->root.root.type == bfd_link_hash_warning)
+    h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
+
+  if (!hti->info->relocatable)
+    mips_elf_check_mips16_stubs (hti->info, h);
+
+  if (mips_elf_local_pic_function_p (h))
+    {
+      /* H is a function that might need $25 to be valid on entry.
+	 If we're creating a non-PIC relocatable object, mark H as
+	 being PIC.  If we're creating a non-relocatable object with
+	 non-PIC references to H, make sure that H has an la25 stub.  */
+      if (hti->info->relocatable)
+	{
+	  if (!PIC_OBJECT_P (hti->output_bfd))
+	    h->root.other = ELF_ST_SET_MIPS_PIC (h->root.other);
+	}
+      else if (h->non_pic_ref && !mips_elf_add_la25_stub (hti->info, h))
+	{
+	  hti->error = TRUE;
+	  return FALSE;
+	}
+    }
+  return TRUE;
+}
 
 /* R_MIPS16_26 is used for the mips16 jal and jalx instructions.
    Most mips16 instructions are 16 bits, but these instructions
@@ -2382,6 +2727,7 @@ mips_elf_count_global_tls_relocs (void *
 static void
 mips_elf_output_dynamic_relocation (bfd *output_bfd,
 				    asection *sreloc,
+				    unsigned long reloc_index,
 				    unsigned long indx,
 				    int r_type,
 				    bfd_vma offset)
@@ -2398,14 +2744,13 @@ mips_elf_output_dynamic_relocation (bfd 
       (*get_elf_backend_data (output_bfd)->s->swap_reloc_out)
 	(output_bfd, &rel[0],
 	 (sreloc->contents
-	  + sreloc->reloc_count * sizeof (Elf64_Mips_External_Rel)));
+	  + reloc_index * sizeof (Elf64_Mips_External_Rel)));
     }
   else
     bfd_elf32_swap_reloc_out
       (output_bfd, &rel[0],
        (sreloc->contents
-	+ sreloc->reloc_count * sizeof (Elf32_External_Rel)));
-  ++sreloc->reloc_count;
+	+ reloc_index * sizeof (Elf32_External_Rel)));
 }
 
 /* Initialize a set of TLS GOT entries for one symbol.  */
@@ -2463,13 +2808,13 @@ mips_elf_initialize_tls_slots (bfd *abfd
       if (need_relocs)
 	{
 	  mips_elf_output_dynamic_relocation
-	    (abfd, sreloc, indx,
+	    (abfd, sreloc, sreloc->reloc_count++, indx,
 	     ABI_64_P (abfd) ? R_MIPS_TLS_DTPMOD64 : R_MIPS_TLS_DTPMOD32,
 	     sgot->output_offset + sgot->output_section->vma + offset);
 
 	  if (indx)
 	    mips_elf_output_dynamic_relocation
-	      (abfd, sreloc, indx,
+	      (abfd, sreloc, sreloc->reloc_count++, indx,
 	       ABI_64_P (abfd) ? R_MIPS_TLS_DTPREL64 : R_MIPS_TLS_DTPREL32,
 	       sgot->output_offset + sgot->output_section->vma + offset2);
 	  else
@@ -2502,7 +2847,7 @@ mips_elf_initialize_tls_slots (bfd *abfd
 			       sgot->contents + offset);
 
 	  mips_elf_output_dynamic_relocation
-	    (abfd, sreloc, indx,
+	    (abfd, sreloc, sreloc->reloc_count++, indx,
 	     ABI_64_P (abfd) ? R_MIPS_TLS_TPREL64 : R_MIPS_TLS_TPREL32,
 	     sgot->output_offset + sgot->output_section->vma + offset);
 	}
@@ -2524,7 +2869,7 @@ mips_elf_initialize_tls_slots (bfd *abfd
 			   sgot->contents + got_offset);
       else
 	mips_elf_output_dynamic_relocation
-	  (abfd, sreloc, indx,
+	  (abfd, sreloc, sreloc->reloc_count++, indx,
 	   ABI_64_P (abfd) ? R_MIPS_TLS_DTPMOD64 : R_MIPS_TLS_DTPMOD32,
 	   sgot->output_offset + sgot->output_section->vma + got_offset);
     }
@@ -3882,7 +4227,7 @@ mips_elf_multi_got (bfd *abfd, struct bf
   got_per_bfd_arg.primary = NULL;
   got_per_bfd_arg.max_count = ((MIPS_ELF_GOT_MAX_SIZE (info)
 				/ MIPS_ELF_GOT_SIZE (abfd))
-			       - MIPS_RESERVED_GOTNO (info));
+			       - htab->reserved_gotno);
   got_per_bfd_arg.max_pages = 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
@@ -3993,7 +4338,7 @@ mips_elf_multi_got (bfd *abfd, struct bf
     {
       struct mips_got_info *gn;
 
-      assign += MIPS_RESERVED_GOTNO (info);
+      assign += htab->reserved_gotno;
       g->assigned_gotno = assign;
       g->local_gotno += assign;
       g->local_gotno += (pages < g->page_gotno ? pages : g->page_gotno);
@@ -4050,7 +4395,7 @@ mips_elf_multi_got (bfd *abfd, struct bf
 	  BFD_ASSERT (g->assigned_gotno == g->next->local_gotno
 		      + g->next->global_gotno
 		      + g->next->tls_gotno
-		      + MIPS_RESERVED_GOTNO (info));
+		      + htab->reserved_gotno);
 	}
     }
 
@@ -4273,9 +4618,9 @@ mips_elf_create_got_section (bfd *abfd, 
   g->global_gotno = 0;
   g->reloc_only_gotno = 0;
   g->tls_gotno = 0;
-  g->local_gotno = MIPS_RESERVED_GOTNO (info);
+  g->local_gotno = 0;
   g->page_gotno = 0;
-  g->assigned_gotno = MIPS_RESERVED_GOTNO (info);
+  g->assigned_gotno = 0;
   g->bfd2got = NULL;
   g->next = NULL;
   g->tls_ldm_offset = MINUS_ONE;
@@ -4291,17 +4636,14 @@ 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;
+  /* We also need a .got.plt section when generating PLTs.  */
+  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)
+    return FALSE;
+  htab->sgotplt = s;
 
-      htab->sgotplt = s;
-    }
   return TRUE;
 }
 
@@ -4459,10 +4801,20 @@ mips_elf_calculate_relocation (bfd *abfd
       /* Record the name of this symbol, for our caller.  */
       *namep = h->root.root.root.string;
 
+      /* If a compound relocation starts with %gp_rel(...), and the
+	 target is a PIC function with a non-PIC stub, assume that
+	 we need the unadjusted symbol value.  */
+      if (save_addend
+	  && h->la25_stub
+	  && r_type == R_MIPS_GPREL16)
+	symbol = (h->la25_stub->input_section->output_section->vma
+		  + h->la25_stub->input_section->output_offset
+		  + h->la25_stub->offset);
+
       /* See if this is the special _gp_disp symbol.  Note that such a
 	 symbol must always be a global symbol.  */
-      if (strcmp (*namep, "_gp_disp") == 0
-	  && ! NEWABI_P (input_bfd))
+      else if (strcmp (*namep, "_gp_disp") == 0
+	       && ! NEWABI_P (input_bfd))
 	{
 	  /* Relocations against _gp_disp are permitted only with
 	     R_MIPS_HI16 and R_MIPS_LO16 relocations.  */
@@ -4761,26 +5113,23 @@ mips_elf_calculate_relocation (bfd *abfd
     case R_MIPS_REL32:
     case R_MIPS_64:
       if ((info->shared
-	   || (!htab->is_vxworks
-	       && htab->root.dynamic_sections_created
+	   || (htab->root.dynamic_sections_created
 	       && h != NULL
 	       && h->root.def_dynamic
-	       && !h->root.def_regular))
+	       && !h->root.def_regular
+	       && !h->has_static_relocs))
 	  && r_symndx != 0
 	  && (h == NULL
 	      || h->root.root.type != bfd_link_hash_undefweak
 	      || ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT)
 	  && (input_section->flags & SEC_ALLOC) != 0)
 	{
-	  /* If we're creating a shared library, or this relocation is
-	     against a symbol in a shared library, then we can't know
+	  /* If we're creating 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.
-
-	     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.  */
+	     linker.  We must do the same for executable references to
+	     shared library symbols, unless we've decided to use copy
+	     relocs or PLTs instead.  */
 	  value = addend;
 	  if (!mips_elf_create_dynamic_relocation (abfd,
 						   info,
@@ -6525,24 +6874,29 @@ _bfd_mips_elf_create_dynamic_sections (b
 	}
     }
 
+  /* Create the .plt, .rel(a).plt, .dynbss and .rel(a).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->splt = bfd_get_section_by_name (abfd, ".plt");
+  htab->sdynbss = bfd_get_section_by_name (abfd, ".dynbss");
   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 ();
+    }
+  else
+    htab->srelplt = bfd_get_section_by_name (abfd, ".rel.plt");
+  if (!htab->sdynbss
+      || (htab->is_vxworks && !htab->srelbss && !info->shared)
+      || !htab->srelplt
+      || !htab->splt)
+    abort ();
 
+  if (htab->is_vxworks)
+    {
       /* Do the usual VxWorks handling.  */
       if (!elf_vxworks_create_dynamic_sections (abfd, info, &htab->srelplt2))
 	return FALSE;
@@ -6563,6 +6917,11 @@ _bfd_mips_elf_create_dynamic_sections (b
 	    = 4 * ARRAY_SIZE (mips_vxworks_exec_plt_entry);
 	}
     }
+  else if (!info->shared)
+    {
+      htab->plt_header_size = 4 * ARRAY_SIZE (mips_exec_plt0_entry);
+      htab->plt_entry_size = 4 * ARRAY_SIZE (mips_exec_plt_entry);
+    }
 
   return TRUE;
 }
@@ -6983,6 +7342,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
       unsigned long r_symndx;
       unsigned int r_type;
       struct elf_link_hash_entry *h;
+      bfd_boolean can_make_dynamic_p;
 
       r_symndx = ELF_R_SYM (abfd, rel->r_info);
       r_type = ELF_R_TYPE (abfd, rel->r_info);
@@ -7007,62 +7367,79 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
 	      while (h->root.type == bfd_link_hash_indirect)
 		h = (struct elf_link_hash_entry *) h->root.u.i.link;
 	    }
+	  if (!PIC_OBJECT_P (abfd))
+	    ((struct mips_elf_link_hash_entry *) h)->non_pic_ref = TRUE;
 	}
 
-      /* Some relocs require a global offset table.  */
-      if (dynobj == NULL || htab->sgot == NULL)
+      /* Set CAN_MAKE_DYNAMIC_P to true if we can convert this
+	 relocation into a dynamic one.  */
+      can_make_dynamic_p = FALSE;
+      switch (r_type)
 	{
-	  switch (r_type)
+	case R_MIPS16_GOT16:
+	case R_MIPS16_CALL16:
+	case R_MIPS_GOT16:
+	case R_MIPS_CALL16:
+	case R_MIPS_CALL_HI16:
+	case R_MIPS_CALL_LO16:
+	case R_MIPS_GOT_HI16:
+	case R_MIPS_GOT_LO16:
+	case R_MIPS_GOT_PAGE:
+	case R_MIPS_GOT_OFST:
+	case R_MIPS_GOT_DISP:
+	case R_MIPS_TLS_GOTTPREL:
+	case R_MIPS_TLS_GD:
+	case R_MIPS_TLS_LDM:
+	  if (dynobj == NULL)
+	    elf_hash_table (info)->dynobj = dynobj = abfd;
+	  if (!mips_elf_create_got_section (dynobj, info))
+	    return FALSE;
+	  if (htab->is_vxworks && !info->shared)
 	    {
-	    case R_MIPS16_GOT16:
-	    case R_MIPS16_CALL16:
-	    case R_MIPS_GOT16:
-	    case R_MIPS_CALL16:
-	    case R_MIPS_CALL_HI16:
-	    case R_MIPS_CALL_LO16:
-	    case R_MIPS_GOT_HI16:
-	    case R_MIPS_GOT_LO16:
-	    case R_MIPS_GOT_PAGE:
-	    case R_MIPS_GOT_OFST:
-	    case R_MIPS_GOT_DISP:
-	    case R_MIPS_TLS_GOTTPREL:
-	    case R_MIPS_TLS_GD:
-	    case R_MIPS_TLS_LDM:
-	      if (dynobj == NULL)
-		elf_hash_table (info)->dynobj = dynobj = abfd;
-	      if (!mips_elf_create_got_section (dynobj, info))
-		return FALSE;
-	      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;
+	      (*_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 && !htab->is_vxworks))
-		  && (sec->flags & SEC_ALLOC) != 0)
-		elf_hash_table (info)->dynobj = dynobj = abfd;
-	      break;
+	case R_MIPS_32:
+	case R_MIPS_REL32:
+	case R_MIPS_64:
+	  /* In VxWorks executables, references to external symbols
+	     must be handled using copy relocs or PLT entries; it is not
+	     possible to convert this relocation into a dynamic one.
 
-	    default:
+	     For executables that use the GNU PLT and copy-reloc extensions,
+	     we have a choice between converting the relocation into
+	     a dynamic one or using copy relocations or PLT entries.
+	     It is usually better to do the former, unless the relocation
+	     is against a read-only section.  */
+	  if ((info->shared
+	       || (h != NULL
+		   && !htab->is_vxworks
+		   && strcmp (h->root.root.string, "__gnu_local_gp") != 0
+		   && !(!info->nocopyreloc
+			&& !PIC_OBJECT_P (abfd)
+			&& MIPS_ELF_READONLY_SECTION (sec))))
+	      && (sec->flags & SEC_ALLOC) != 0)
+	    {
+	      can_make_dynamic_p = TRUE;
+	      if (dynobj == NULL)
+		elf_hash_table (info)->dynobj = dynobj = abfd;
 	      break;
 	    }
+	  /* Fall through  */
+
+	default:
+	  if (h)
+	    ((struct mips_elf_link_hash_entry *) h)->has_static_relocs = TRUE;
+	  break;
 	}
 
       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.  */
@@ -7240,9 +7617,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
 	  /* In VxWorks executables, references to external symbols
 	     are handled using copy relocs or PLT stubs, so there's
 	     no need to add a .rela.dyn entry for this relocation.  */
-	  if ((info->shared || (h != NULL && !htab->is_vxworks))
-	      && !(h && strcmp (h->root.root.string, "__gnu_local_gp") == 0)
-	      && (sec->flags & SEC_ALLOC) != 0)
+	  if (can_make_dynamic_p)
 	    {
 	      if (sreloc == NULL)
 		{
@@ -7290,16 +7665,7 @@ _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:
@@ -7607,6 +7973,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (str
 
   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
@@ -7618,9 +7985,15 @@ _bfd_mips_elf_adjust_dynamic_symbol (str
 
   hmips = (struct mips_elf_link_hash_entry *) h;
 
-  /* For a function, create a stub, if allowed.  */
-  if (! hmips->no_fn_stub
-      && h->needs_plt)
+  /* If there are call relocations against an externally-defined symbol,
+     see whether we can create a MIPS lazy-binding stub for it.  We can
+     only do this if all references to the function are through call
+     relocations, and in that case, the traditional lazy-binding stubs
+     are much more efficient than PLT entries.
+
+     Traditional stubs are only available on SVR4 psABI-based systems;
+     VxWorks always uses PLTs instead.  */
+  if (!htab->is_vxworks && h->needs_plt && !hmips->no_fn_stub)
     {
       if (! elf_hash_table (info)->dynamic_sections_created)
 	return TRUE;
@@ -7636,90 +8009,46 @@ _bfd_mips_elf_adjust_dynamic_symbol (str
 	  return TRUE;
 	}
     }
-  else if ((h->type == STT_FUNC)
-	   && !h->needs_plt)
-    {
-      /* This will set the entry for this symbol in the GOT to 0, and
-         the dynamic linker will take care of this.  */
-      h->root.u.def.value = 0;
-      return TRUE;
-    }
+  /* As above, VxWorks requires PLT entries for externally-defined
+     functions that are only accessed through call relocations.
 
-  /* 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.  */
-
-  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;
-
-  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)
+     Both VxWorks and non-VxWorks targets also need PLT entries if there
+     are static-only relocations against an externally-defined function.
+     This can technically occur for shared libraries if there are
+     branches to the symbol, although it is unlikely that this will be
+     used in practice due to the short ranges involved.  It can occur
+     for any relative or absolute relocation in executables; in that
+     case, the PLT entry becomes the function's canonical address.  */
+  else if (((h->needs_plt && !hmips->no_fn_stub)
+	    || (h->type == STT_FUNC && hmips->has_static_relocs))
+	   && htab->use_plts_and_copy_relocs
+	   && !SYMBOL_CALLS_LOCAL (info, h)
+	   && !(ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+		&& h->root.type == bfd_link_hash_undefweak))
     {
       /* 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.  */
+	 for the header.  */
       if (htab->splt->size == 0)
 	{
+	  /* If we're using the GNU extensions to the psABI, each PLT
+	     entry is a multiple of 16 bytes.  Encourage better cache
+	     usage by aligning to that boundary.  We do this lazily to
+	     avoid pessimizing traditional objects.  */
+	  if (!htab->is_vxworks
+	      && !bfd_set_section_alignment (dynobj, htab->splt, 4))
+	    return FALSE;
+
+	  /* Make sure that .got.plt is word-aligned.  We do this lazily
+	     for the same reason as above.  */
+	  if (!bfd_set_section_alignment (dynobj, htab->sgotplt,
+					  MIPS_ELF_LOG_FILE_ALIGN (dynobj)))
+	    return FALSE;
+
 	  htab->splt->size += htab->plt_header_size;
-	  if (!info->shared)
+
+	  /* On VxWorks, also allocate room for the header's
+	     .rela.plt.unloaded entries.  */
+	  if (htab->is_vxworks && !info->shared)
 	    htab->srelplt2->size += 2 * sizeof (Elf32_External_Rela);
 	}
 
@@ -7728,35 +8057,33 @@ _bfd_mips_vxworks_adjust_dynamic_symbol 
       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.  Point at the PLT
-	 load stub rather than the lazy resolution stub; this stub
-	 will become the canonical function address.  */
+	 symbol's value to the address of the stub.  */
       if (!info->shared && !h->def_regular)
 	{
 	  h->root.u.def.section = htab->splt;
 	  h->root.u.def.value = h->plt.offset;
-	  h->root.u.def.value += 8;
+	  /* For VxWorks, point at the PLT load stub rather than the
+	     lazy resolution stub; this stub will become the canonical
+	     function address.  */
+	  if (htab->is_vxworks)
+	    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 .got.plt entry and the R_MIPS_JUMP_SLOT
+	 relocation.  */
+      htab->sgotplt->size += MIPS_ELF_GOT_SIZE (dynobj);
+      htab->srelplt->size += (htab->is_vxworks
+			      ? MIPS_ELF_RELA_SIZE (dynobj)
+			      : MIPS_ELF_REL_SIZE (dynobj));
 
       /* Make room for the .rela.plt.unloaded relocations.  */
-      if (!info->shared)
+      if (htab->is_vxworks && !info->shared)
 	htab->srelplt2->size += 3 * sizeof (Elf32_External_Rela);
 
-      return TRUE;
-    }
+      /* All relocations against this symbol that could have been made
+	 dynamic will now refer to the PLT entry instead.  */
+      hmips->possibly_dynamic_relocs = 0;
 
-  /* 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;
     }
 
@@ -7772,11 +8099,27 @@ _bfd_mips_vxworks_adjust_dynamic_symbol 
       return TRUE;
     }
 
-  /* This is a reference to a symbol defined by a dynamic object which
-     is not a function.  */
-  if (info->shared)
+  /* Otherwise, there is nothing further to do for symbols defined
+     in regular objects.  */
+  if (h->def_regular)
     return TRUE;
 
+  /* There's also nothing more to do if we'll convert all relocations
+     against this symbol into dynamic relocations.  */
+  if (!hmips->has_static_relocs)
+    return TRUE;
+
+  /* We're now relying on copy relocations.  Complain if we have
+     some that we can't convert.  */
+  if (!htab->use_plts_and_copy_relocs || info->shared)
+    {
+      (*_bfd_error_handler) (_("non-dynamic relocations refer to "
+			       "dynamic symbol %s"),
+			     h->root.root.string);
+      bfd_set_error (bfd_error_bad_value);
+      return FALSE;
+    }
+
   /* 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
@@ -7789,10 +8132,17 @@ _bfd_mips_vxworks_adjust_dynamic_symbol 
 
   if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
     {
-      htab->srelbss->size += sizeof (Elf32_External_Rela);
+      if (htab->is_vxworks)
+	htab->srelbss->size += sizeof (Elf32_External_Rela);
+      else
+	mips_elf_allocate_dynamic_relocations (dynobj, info, 1);
       h->needs_copy = 1;
     }
 
+  /* All relocations against this symbol that could have been made
+     dynamic will now refer to the local copy instead.  */
+  hmips->possibly_dynamic_relocs = 0;
+
   return _bfd_elf_adjust_dynamic_copy (h, htab->sdynbss);
 }
 
@@ -7806,6 +8156,7 @@ _bfd_mips_elf_always_size_sections (bfd 
 {
   asection *ri;
   struct mips_elf_link_hash_table *htab;
+  struct mips_htab_traverse_info hti;
 
   htab = mips_elf_hash_table (info);
 
@@ -7814,10 +8165,13 @@ _bfd_mips_elf_always_size_sections (bfd 
   if (ri != NULL)
     bfd_set_section_size (output_bfd, ri, sizeof (Elf32_External_RegInfo));
 
-  if (! (info->relocatable
-	 || ! mips_elf_hash_table (info)->mips16_stubs_seen))
-    mips_elf_link_hash_traverse (mips_elf_hash_table (info),
-				 mips_elf_check_mips16_stubs, info);
+  hti.info = info;
+  hti.output_bfd = output_bfd;
+  hti.error = FALSE;
+  mips_elf_link_hash_traverse (mips_elf_hash_table (info),
+			       mips_elf_check_symbols, &hti);
+  if (hti.error)
+    return FALSE;
 
   return TRUE;
 }
@@ -7844,6 +8198,19 @@ mips_elf_lay_out_got (bfd *output_bfd, s
   dynobj = elf_hash_table (info)->dynobj;
   g = htab->got_info;
 
+  /* Allocate room for the reserved entries.  VxWorks always reserves
+     3 entries.  Other objects are assumed to use the GNU PLT extensions
+     iff they have a DT_JMPREL tag.  When an object does use the extensions,
+     _GLOBAL_OFFSET_TABLE_[2] points to the PLT resolver, otherwise only
+     2 entries are reserved.  */
+  BFD_ASSERT (g->assigned_gotno == 0);
+  if (htab->is_vxworks || (htab->splt && htab->splt->size > 0))
+    htab->reserved_gotno = 3;
+  else
+    htab->reserved_gotno = 2;
+  g->local_gotno += htab->reserved_gotno;
+  g->assigned_gotno = htab->reserved_gotno;
+
   /* Replace entries for indirect and warning symbols with entries for
      the target symbol.  */
   if (!mips_elf_resolve_final_got_entries (g))
@@ -7911,7 +8278,7 @@ mips_elf_lay_out_got (bfd *output_bfd, s
 	  /* Each VxWorks GOT entry needs an explicit relocation.  */
 	  unsigned int count;
 
-	  count = g->global_gotno + g->local_gotno - MIPS_RESERVED_GOTNO (info);
+	  count = g->global_gotno + g->local_gotno - htab->reserved_gotno;
 	  if (count)
 	    mips_elf_allocate_dynamic_relocations (dynobj, info, count);
 	}
@@ -8021,7 +8388,7 @@ _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;
 
@@ -8119,7 +8486,8 @@ _bfd_mips_elf_size_dynamic_sections (bfd
 	       && s != htab->sgot
 	       && s != htab->sgotplt
 	       && s != htab->splt
-	       && s != htab->sstubs)
+	       && s != htab->sstubs
+	       && s != htab->sdynbss)
 	{
 	  /* It's not one of our sections, so don't allocate space.  */
 	  continue;
@@ -8183,11 +8551,12 @@ _bfd_mips_elf_size_dynamic_sections (bfd
       if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTGOT, 0))
 	return FALSE;
 
+      sreldyn = mips_elf_rel_dyn_section (info, FALSE);
       if (htab->is_vxworks)
 	{
 	  /* 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 (sreldyn && sreldyn->size > 0)
 	    {
 	      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELA, 0))
 		return FALSE;
@@ -8198,21 +8567,10 @@ _bfd_mips_elf_size_dynamic_sections (bfd
 	      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 (sreldyn && sreldyn->size > 0)
 	    {
 	      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_REL, 0))
 		return FALSE;
@@ -8255,6 +8613,17 @@ _bfd_mips_elf_size_dynamic_sections (bfd
 	      && !MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_OPTIONS, 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;
+	}
       if (htab->is_vxworks
 	  && !elf_vxworks_add_dynamic_entries (output_bfd, info))
 	return FALSE;
@@ -8649,6 +9018,68 @@ _bfd_mips_elf_relocate_section (bfd *out
   return TRUE;
 }
 
+/* A function that iterates over each entry in la25_stubs and fills
+   in the code for each one.  DATA points to a mips_htab_traverse_info.  */
+
+static int
+mips_elf_create_la25_stub (void **slot, void *data)
+{
+  struct mips_htab_traverse_info *hti;
+  struct mips_elf_link_hash_table *htab;
+  struct mips_elf_la25_stub *stub;
+  asection *s;
+  bfd_byte *loc;
+  bfd_vma offset, target, target_high, target_low;
+
+  stub = (struct mips_elf_la25_stub *) *slot;
+  hti = (struct mips_htab_traverse_info *) data;
+  htab = mips_elf_hash_table (hti->info);
+
+  /* Create the section contents, if we haven't already.  */
+  s = stub->h->root.root.u.def.section;
+  loc = s->contents;
+  if (loc == NULL)
+    {
+      loc = bfd_malloc (s->size);
+      if (loc == NULL)
+	{
+	  hti->error = TRUE;
+	  return FALSE;
+	}
+      s->contents = loc;
+    }
+
+  /* Work out where in the section this stub should go.  */
+  offset = stub->h->root.root.u.def.value;
+
+  /* Work out the target address.  */
+  target = (stub->input_section->output_section->vma
+	    + stub->input_section->output_offset
+	    + stub->offset);
+  target_high = ((target + 0x8000) >> 16) & 0xffff;
+  target_low = (target & 0xffff);
+
+  if (stub->h->root.root.u.def.section != htab->strampoline)
+    {
+      /* This is a simple LUI/ADIDU stub.  Zero out the beginning
+	 of the section and write the two instructions at the end.  */
+      memset (loc, 0, offset);
+      loc += offset;
+      bfd_put_32 (hti->output_bfd, LA25_LUI (target_high), loc);
+      bfd_put_32 (hti->output_bfd, LA25_ADDIU (target_low), loc + 4);
+    }
+  else
+    {
+      /* This is trampoline.  */
+      loc += offset;
+      bfd_put_32 (hti->output_bfd, LA25_LUI (target_high), loc);
+      bfd_put_32 (hti->output_bfd, LA25_J (target), loc + 4);
+      bfd_put_32 (hti->output_bfd, LA25_ADDIU (target_low), loc + 8);
+      bfd_put_32 (hti->output_bfd, 0, loc + 12);
+    }
+  return TRUE;
+}
+
 /* If NAME is one of the special IRIX6 symbols defined by the linker,
    adjust it appropriately now.  */
 
@@ -8720,8 +9151,68 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd
   dynobj = elf_hash_table (info)->dynobj;
   hmips = (struct mips_elf_link_hash_entry *) h;
 
-  if (h->plt.offset != MINUS_ONE)
+  if (h->plt.offset != MINUS_ONE && hmips->no_fn_stub)
     {
+      /* We've decided to create a PLT entry for this symbol.  */
+      bfd_byte *loc;
+      bfd_vma header_address, plt_index, got_address;
+      bfd_vma got_address_high, got_address_low, load;
+      static const bfd_vma *plt_entry;
+
+      BFD_ASSERT (htab->use_plts_and_copy_relocs);
+      BFD_ASSERT (h->dynindx != -1);
+      BFD_ASSERT (htab->splt != NULL);
+      BFD_ASSERT (h->plt.offset <= htab->splt->size);
+      BFD_ASSERT (!h->def_regular);
+
+      /* Calculate the address of the PLT header.  */
+      header_address = (htab->splt->output_section->vma
+			+ htab->splt->output_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 * MIPS_ELF_GOT_SIZE (dynobj));
+      got_address_high = ((got_address + 0x8000) >> 16) & 0xffff;
+      got_address_low = got_address & 0xffff;
+
+      /* Initially point the .got.plt entry at the PLT header.  */
+      loc = htab->sgotplt->contents + plt_index * MIPS_ELF_GOT_SIZE (dynobj);
+      if (ABI_64_P (output_bfd))
+	bfd_put_64 (output_bfd, header_address, loc);
+      else
+	bfd_put_32 (output_bfd, header_address, loc);
+
+      /* Find out where the .plt entry should go.  */
+      loc = htab->splt->contents + h->plt.offset;
+
+      /* Pick the load opcode.  */
+      load = MIPS_ELF_LOAD_WORD (output_bfd);
+
+      /* Fill in the PLT entry itself.  */
+      plt_entry = mips_exec_plt_entry;
+      bfd_put_32 (output_bfd, plt_entry[0] | got_address_high, loc);
+      bfd_put_32 (output_bfd, plt_entry[1] | got_address_low | load, loc + 4);
+      bfd_put_32 (output_bfd, plt_entry[2], loc + 8);
+      bfd_put_32 (output_bfd, plt_entry[3] | got_address_low, loc + 12);
+
+      /* Emit an R_MIPS_JUMP_SLOT relocation against the .got.plt entry.  */
+      mips_elf_output_dynamic_relocation (output_bfd, htab->srelplt,
+					  plt_index, h->dynindx,
+					  R_MIPS_JUMP_SLOT, got_address);
+
+      /* We distinguish between PLT entries and lazy-binding stubs by
+	 giving the former an st_other value of STO_MIPS_PLT.  */
+      sym->st_shndx = SHN_UNDEF;
+      sym->st_other = ELF_ST_SET_MIPS_PLT (sym->st_other);
+    }
+  else if (h->plt.offset != MINUS_ONE)
+    {
+      /* We've decided to create a lazy-binding stub.  */
       bfd_byte stub[MIPS_FUNCTION_STUB_BIG_SIZE];
 
       /* This symbol has a stub.  Set it up.  */
@@ -8908,6 +9399,23 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd
 	}
     }
 
+  /* Emit a copy reloc, if needed.  */
+  if (h->needs_copy)
+    {
+      asection *s;
+      bfd_vma symval;
+
+      BFD_ASSERT (h->dynindx != -1);
+      BFD_ASSERT (htab->use_plts_and_copy_relocs);
+
+      s = mips_elf_rel_dyn_section (info, FALSE);
+      symval = (h->root.u.def.section->output_section->vma
+		+ h->root.u.def.section->output_offset
+		+ h->root.u.def.value);
+      mips_elf_output_dynamic_relocation (output_bfd, s, s->reloc_count++,
+					  h->dynindx, R_MIPS_COPY, symval);
+    }
+
   /* Handle the IRIX6-specific symbols.  */
   if (IRIX_COMPAT (output_bfd) == ict_irix6)
     mips_elf_irix6_finish_dynamic_symbol (output_bfd, name, sym);
@@ -9118,6 +9626,49 @@ _bfd_mips_vxworks_finish_dynamic_symbol 
   return TRUE;
 }
 
+/* Write out a mips_exec_plt0_entry to the beginning of .plt.  */
+
+static void
+mips_finish_exec_plt (bfd *output_bfd, struct bfd_link_info *info)
+{
+  bfd_byte *loc;
+  bfd_vma got_value, got_value_high, got_value_low;
+  bfd_vma gotplt_value, gotplt_value_high, gotplt_value_low, load;
+  static const bfd_vma *plt_entry;
+  struct mips_elf_link_hash_table *htab;
+
+  htab = mips_elf_hash_table (info);
+  plt_entry = mips_exec_plt0_entry;
+
+  /* Calculate the value of &_GLOBAL_OFFSET_TABLE_[2].  */
+  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
+	       + MIPS_ELF_GOT_SIZE (output_bfd) * 2);
+  got_value_high = ((got_value + 0x8000) >> 16) & 0xffff;
+  got_value_low = got_value & 0xffff;
+
+  /* Calculate the value of .got.plt.  */
+  gotplt_value = (htab->sgotplt->output_section->vma
+		  + htab->sgotplt->output_offset);
+  gotplt_value_high = ((gotplt_value + 0x8000) >> 16) & 0xffff;
+  gotplt_value_low = gotplt_value & 0xffff;
+
+  /* Pick the load opcode.  */
+  load = MIPS_ELF_LOAD_WORD (output_bfd);
+
+  /* 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 | load, loc + 4);
+  bfd_put_32 (output_bfd, plt_entry[2] | got_value_low, loc + 8);
+  bfd_put_32 (output_bfd, plt_entry[3] | gotplt_value_high, loc + 12);
+  bfd_put_32 (output_bfd, plt_entry[4], loc + 16);
+  bfd_put_32 (output_bfd, plt_entry[5] | gotplt_value_low, loc + 20);
+  bfd_put_32 (output_bfd, plt_entry[6], loc + 24);
+  bfd_put_32 (output_bfd, plt_entry[7], loc + 28);
+}
+
 /* Install the PLT header for a VxWorks executable and finalize the
    contents of .rela.plt.unloaded.  */
 
@@ -9273,21 +9824,8 @@ _bfd_mips_elf_finish_dynamic_sections (b
 	      break;
 
 	    case DT_PLTGOT:
-	      name = ".got";
-	      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;
-		}
+	      s = htab->sgot;
+	      dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
 	      break;
 
 	    case DT_MIPS_RLD_VERSION:
@@ -9353,7 +9891,7 @@ _bfd_mips_elf_finish_dynamic_sections (b
 	      break;
 
 	    case DT_MIPS_HIPAGENO:
-	      dyn.d_un.d_val = g->local_gotno - MIPS_RESERVED_GOTNO (info);
+	      dyn.d_un.d_val = g->local_gotno - htab->reserved_gotno;
 	      break;
 
 	    case DT_MIPS_RLD_MAP:
@@ -9374,17 +9912,20 @@ _bfd_mips_elf_finish_dynamic_sections (b
 	      break;
 
 	    case DT_PLTREL:
-	      BFD_ASSERT (htab->is_vxworks);
-	      dyn.d_un.d_val = DT_RELA;
+	      BFD_ASSERT (htab->use_plts_and_copy_relocs);
+	      if (htab->is_vxworks)
+		dyn.d_un.d_val = DT_RELA;
+	      else
+		dyn.d_un.d_val = DT_REL;
 	      break;
 
 	    case DT_PLTRELSZ:
-	      BFD_ASSERT (htab->is_vxworks);
+	      BFD_ASSERT (htab->use_plts_and_copy_relocs);
 	      dyn.d_un.d_val = htab->srelplt->size;
 	      break;
 
 	    case DT_JMPREL:
-	      BFD_ASSERT (htab->is_vxworks);
+	      BFD_ASSERT (htab->use_plts_and_copy_relocs);
 	      dyn.d_un.d_val = (htab->srelplt->output_section->vma
 				+ htab->srelplt->output_offset);
 	      break;
@@ -9613,12 +10154,20 @@ _bfd_mips_elf_finish_dynamic_sections (b
       }
   }
 
-  if (htab->is_vxworks && htab->splt->size > 0)
+  if (htab->splt && htab->splt->size > 0)
     {
-      if (info->shared)
-	mips_vxworks_finish_shared_plt (output_bfd, info);
+      if (htab->is_vxworks)
+	{
+	  if (info->shared)
+	    mips_vxworks_finish_shared_plt (output_bfd, info);
+	  else
+	    mips_vxworks_finish_exec_plt (output_bfd, info);
+	}
       else
-	mips_vxworks_finish_exec_plt (output_bfd, info);
+	{
+	  BFD_ASSERT (!info->shared);
+	  mips_finish_exec_plt (output_bfd, info);
+	}
     }
   return TRUE;
 }
@@ -10199,11 +10748,16 @@ _bfd_mips_elf_copy_indirect_symbol (stru
 
   _bfd_elf_link_hash_copy_indirect (info, dir, ind);
 
+  dirmips = (struct mips_elf_link_hash_entry *) dir;
+  indmips = (struct mips_elf_link_hash_entry *) ind;
+  /* Any absolute non-dynamic relocations against an indirect or weak
+     definition will be against the target symbol.  */
+  if (indmips->has_static_relocs)
+    dirmips->has_static_relocs = TRUE;
+
   if (ind->root.type != bfd_link_hash_indirect)
     return;
 
-  dirmips = (struct mips_elf_link_hash_entry *) dir;
-  indmips = (struct mips_elf_link_hash_entry *) ind;
   dirmips->possibly_dynamic_relocs += indmips->possibly_dynamic_relocs;
   if (indmips->readonly_reloc)
     dirmips->readonly_reloc = TRUE;
@@ -10213,6 +10767,8 @@ _bfd_mips_elf_copy_indirect_symbol (stru
     dirmips->global_got_area = indmips->global_got_area;
   if (indmips->global_got_area < GGA_NONE)
     indmips->global_got_area = GGA_NONE;
+  if (indmips->non_pic_ref)
+    dirmips->non_pic_ref = TRUE;
 
   if (dirmips->tls_type == 0)
     dirmips->tls_type = indmips->tls_type;
@@ -10682,6 +11238,7 @@ _bfd_mips_elf_link_hash_table_create (bf
   ret->use_rld_obj_head = FALSE;
   ret->rld_value = 0;
   ret->mips16_stubs_seen = FALSE;
+  ret->use_plts_and_copy_relocs = FALSE;
   ret->is_vxworks = FALSE;
   ret->small_data_overflow_reported = FALSE;
   ret->srelbss = NULL;
@@ -10697,6 +11254,9 @@ _bfd_mips_elf_link_hash_table_create (bf
   ret->plt_entry_size = 0;
   ret->lazy_stub_count = 0;
   ret->function_stub_size = 0;
+  ret->strampoline = NULL;
+  ret->la25_stubs = NULL;
+  ret->add_stub_section = NULL;
 
   return &ret->root.root;
 }
@@ -10714,10 +11274,20 @@ _bfd_mips_vxworks_link_hash_table_create
       struct mips_elf_link_hash_table *htab;
 
       htab = (struct mips_elf_link_hash_table *) ret;
-      htab->is_vxworks = 1;
+      htab->use_plts_and_copy_relocs = TRUE;
+      htab->is_vxworks = TRUE;
     }
   return ret;
 }
+
+/* A function that the linker calls if we are allowed to use PLTs
+   and copy relocs.  */
+
+void
+_bfd_mips_elf_use_plts_and_copy_relocs (struct bfd_link_info *info)
+{
+  mips_elf_hash_table (info)->use_plts_and_copy_relocs = TRUE;
+}
 
 /* We need to use a special link routine to handle the .reginfo and
    the .mdebug sections.  We need to merge all instances of these
@@ -10732,6 +11302,7 @@ _bfd_mips_elf_final_link (bfd *abfd, str
   asection *rtproc_sec;
   Elf32_RegInfo reginfo;
   struct ecoff_debug_info debug;
+  struct mips_htab_traverse_info hti;
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   const struct ecoff_debug_swap *swap = bed->elf_backend_ecoff_debug_swap;
   HDRR *symhdr = &debug.symbolic_header;
@@ -10759,6 +11330,14 @@ _bfd_mips_elf_final_link (bfd *abfd, str
   if (!mips_elf_sort_hash_table (abfd, info))
     return FALSE;
 
+  /* Create any scheduled LA25 stubs.  */
+  hti.info = info;
+  hti.output_bfd = abfd;
+  hti.error = FALSE;
+  htab_traverse (htab->la25_stubs, mips_elf_create_la25_stub, &hti);
+  if (hti.error)
+    return FALSE;
+
   /* Get a value for the GP register.  */
   if (elf_gp (abfd) == 0)
     {
@@ -11674,11 +12253,9 @@ _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);
+  /* DSOs should only be linked with CPIC code.  */
+  if ((ibfd->flags & DYNAMIC) != 0)
+    new_flags |= EF_MIPS_PIC | EF_MIPS_CPIC;
 
   if (new_flags == old_flags)
     return TRUE;
@@ -11710,7 +12287,7 @@ _bfd_mips_elf_merge_private_bfd_data (bf
       != ((old_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0))
     {
       (*_bfd_error_handler)
-	(_("%B: warning: linking PIC files with non-PIC files"),
+	(_("%B: warning: linking abicalls files with non-abicalls files"),
 	 ibfd);
       ok = TRUE;
     }
@@ -12055,3 +12632,15 @@ _bfd_mips_elf_common_definition (Elf_Int
 	  || sym->st_shndx == SHN_MIPS_ACOMMON
 	  || sym->st_shndx == SHN_MIPS_SCOMMON);
 }
+
+/* Return address for Ith PLT stub in section PLT, for relocation REL
+   or (bfd_vma) -1 if it should not be included.  */
+
+bfd_vma
+_bfd_mips_elf_plt_sym_val (bfd_vma i, const asection *plt,
+			   const arelent *rel ATTRIBUTE_UNUSED)
+{
+  return (plt->vma
+	  + 4 * ARRAY_SIZE (mips_exec_plt0_entry)
+	  + i * 4 * ARRAY_SIZE (mips_exec_plt_entry));
+}
Index: binutils/readelf.c
===================================================================
--- binutils/readelf.c	2008-08-03 13:12:34.000000000 +0100
+++ binutils/readelf.c	2008-08-03 13:15:44.000000000 +0100
@@ -7020,6 +7020,8 @@ get_mips_symbol_other (unsigned int othe
     {
     case STO_OPTIONAL:  return "OPTIONAL";
     case STO_MIPS16:    return "MIPS16";
+    case STO_MIPS_PLT:	return "MIPS PLT";
+    case STO_MIPS_PIC:	return "MIPS PIC";
     default:      	return NULL;
     }
 }
@@ -9215,6 +9217,7 @@ process_mips_specific (FILE *file)
   bfd_vma local_gotno = 0;
   bfd_vma gotsym = 0;
   bfd_vma symtabno = 0;
+  bfd_boolean has_jmprel = FALSE;
 
   process_attributes (file, NULL, SHT_GNU_ATTRIBUTES, NULL,
 		      display_mips_gnu_attribute);
@@ -9257,6 +9260,9 @@ process_mips_specific (FILE *file)
       case DT_MIPS_SYMTABNO:
 	symtabno = entry->d_un.d_val;
 	break;
+      case DT_JMPREL:
+	has_jmprel = TRUE;
+	break;
       default:
 	break;
       }
@@ -9638,6 +9644,11 @@ process_mips_specific (FILE *file)
 	{
 	  entry = print_mips_got_entry (data, pltgot, entry);
 	  printf (" Module pointer (GNU extension)\n");
+	  if (has_jmprel)
+	    {
+	      entry = print_mips_got_entry (data, pltgot, entry);
+	      printf (" PLT lazy resolver (GNU extension)\n");
+	    }
 	}
       printf ("\n");
 
Index: gas/config/tc-mips.c
===================================================================
--- gas/config/tc-mips.c	2008-08-03 13:12:34.000000000 +0100
+++ gas/config/tc-mips.c	2008-08-03 13:15:44.000000000 +0100
@@ -11231,27 +11231,29 @@ #define OPTION_ELF_BASE    (OPTION_MISC_
 #define OPTION_CALL_SHARED (OPTION_ELF_BASE + 0)
   {"KPIC",        no_argument, NULL, OPTION_CALL_SHARED},
   {"call_shared", no_argument, NULL, OPTION_CALL_SHARED},
-#define OPTION_NON_SHARED  (OPTION_ELF_BASE + 1)
+#define OPTION_CALL_NONPIC (OPTION_ELF_BASE + 1)
+  {"call_nonpic", no_argument, NULL, OPTION_CALL_NONPIC},
+#define OPTION_NON_SHARED  (OPTION_ELF_BASE + 2)
   {"non_shared",  no_argument, NULL, OPTION_NON_SHARED},
-#define OPTION_XGOT        (OPTION_ELF_BASE + 2)
+#define OPTION_XGOT        (OPTION_ELF_BASE + 3)
   {"xgot",        no_argument, NULL, OPTION_XGOT},
-#define OPTION_MABI        (OPTION_ELF_BASE + 3)
+#define OPTION_MABI        (OPTION_ELF_BASE + 4)
   {"mabi", required_argument, NULL, OPTION_MABI},
-#define OPTION_32 	   (OPTION_ELF_BASE + 4)
+#define OPTION_32 	   (OPTION_ELF_BASE + 5)
   {"32",          no_argument, NULL, OPTION_32},
-#define OPTION_N32 	   (OPTION_ELF_BASE + 5)
+#define OPTION_N32 	   (OPTION_ELF_BASE + 6)
   {"n32",         no_argument, NULL, OPTION_N32},
-#define OPTION_64          (OPTION_ELF_BASE + 6)
+#define OPTION_64          (OPTION_ELF_BASE + 7)
   {"64",          no_argument, NULL, OPTION_64},
-#define OPTION_MDEBUG      (OPTION_ELF_BASE + 7)
+#define OPTION_MDEBUG      (OPTION_ELF_BASE + 8)
   {"mdebug", no_argument, NULL, OPTION_MDEBUG},
-#define OPTION_NO_MDEBUG   (OPTION_ELF_BASE + 8)
+#define OPTION_NO_MDEBUG   (OPTION_ELF_BASE + 9)
   {"no-mdebug", no_argument, NULL, OPTION_NO_MDEBUG},
-#define OPTION_PDR	   (OPTION_ELF_BASE + 9)
+#define OPTION_PDR	   (OPTION_ELF_BASE + 10)
   {"mpdr", no_argument, NULL, OPTION_PDR},
-#define OPTION_NO_PDR	   (OPTION_ELF_BASE + 10)
+#define OPTION_NO_PDR	   (OPTION_ELF_BASE + 11)
   {"mno-pdr", no_argument, NULL, OPTION_NO_PDR},
-#define OPTION_MVXWORKS_PIC (OPTION_ELF_BASE + 11)
+#define OPTION_MVXWORKS_PIC (OPTION_ELF_BASE + 12)
   {"mvxworks-pic", no_argument, NULL, OPTION_MVXWORKS_PIC},
 #endif /* OBJ_ELF */
 
@@ -11515,6 +11517,16 @@ md_parse_option (int c, char *arg)
       mips_abicalls = TRUE;
       break;
 
+    case OPTION_CALL_NONPIC:
+      if (!IS_ELF)
+	{
+	  as_bad (_("-call_nonpic is supported only for ELF format"));
+	  return 0;
+	}
+      mips_pic = NO_PIC;
+      mips_abicalls = TRUE;
+      break;
+
     case OPTION_NON_SHARED:
       if (!IS_ELF)
 	{
@@ -15401,8 +15413,9 @@ md_show_usage (FILE *stream)
 #ifdef OBJ_ELF
   fprintf (stream, _("\
 -KPIC, -call_shared	generate SVR4 position independent code\n\
+-call_nonpic		generate non-PIC code that operate with DSOs\n\
 -mvxworks-pic		generate VxWorks position independent code\n\
--non_shared		do not generate position independent code\n\
+-non_shared		do not generate code that cannot operate with DSOs\n\
 -xgot			assume a 32 bit GOT\n\
 -mpdr, -mno-pdr		enable/disable creation of .pdr sections\n\
 -mshared, -mno-shared   disable/enable .cpload optimization for\n\
Index: gas/testsuite/gas/mips/call-nonpic-1.s
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ gas/testsuite/gas/mips/call-nonpic-1.s	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,2 @@
+	la	$25,foo
+	jalr	$25
Index: gas/testsuite/gas/mips/call-nonpic-1.d
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ gas/testsuite/gas/mips/call-nonpic-1.d	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,16 @@
+#as: -mabi=32 -mips2 -call_nonpic
+#objdump: -pdr
+
+.*
+private flags = 10001004: .*
+
+
+Disassembly of section \.text:
+
+0+0 <\.text>:
+.* 	lui	t9,0x0
+.*: R_MIPS_HI16	foo
+.* 	addiu	t9,t9,0
+.*: R_MIPS_LO16	foo
+.* 	jalr	t9
+.* 	nop
Index: gas/testsuite/gas/mips/mips.exp
===================================================================
--- gas/testsuite/gas/mips/mips.exp	2008-08-03 13:12:34.000000000 +0100
+++ gas/testsuite/gas/mips/mips.exp	2008-08-03 13:15:44.000000000 +0100
@@ -832,4 +832,5 @@ if { [istarget mips*-*-vxworks*] } {
 					[mips_arch_list_matching mips1]
 
     run_dump_test "mips16-vis-1"
+    run_dump_test "call-nonpic-1"
 }
Index: ld/emulparams/elf32bmip.sh
===================================================================
--- ld/emulparams/elf32bmip.sh	2008-08-03 13:12:35.000000000 +0100
+++ ld/emulparams/elf32bmip.sh	2008-08-03 13:15:44.000000000 +0100
@@ -35,6 +35,25 @@ OTHER_GOT_SYMBOLS='
   . = .;
   _gp = ALIGN(16) + 0x7ff0;
 '
+# .got.plt is only used for the GNU PLT extensions.  It should not be
+# included in the .sdata block with .got, as there is no need to access
+# the section from _gp.  Note that the traditional:
+#
+#      . = .
+#      _gp = ALIGN (16) + 0x7ff0;
+#      .got : { *(.got.plt) *(.got) }
+#
+# would set _gp to the wrong value; _gp - 0x7ff0 must point to the start
+# of *(.got).
+GOT=".got          ${RELOCATING-0} : { *(.got) }"
+unset OTHER_READWRITE_SECTIONS
+unset OTHER_RELRO_SECTIONS
+if test -n "$RELRO_NOW"; then
+  OTHER_RELRO_SECTIONS=".got.plt      ${RELOCATING-0} : { *(.got.plt) }"
+else
+  OTHER_READWRITE_SECTIONS=".got.plt      ${RELOCATING-0} : { *(.got.plt) }"
+fi
+
 OTHER_SDATA_SECTIONS="
   .lit8         ${RELOCATING-0} : { *(.lit8) }
   .lit4         ${RELOCATING-0} : { *(.lit4) }
Index: ld/emulparams/elf32bmipn32-defs.sh
===================================================================
--- ld/emulparams/elf32bmipn32-defs.sh	2008-08-03 13:12:35.000000000 +0100
+++ ld/emulparams/elf32bmipn32-defs.sh	2008-08-03 13:15:44.000000000 +0100
@@ -53,6 +53,25 @@ OTHER_GOT_SYMBOLS='
   . = .;
   _gp = ALIGN(16) + 0x7ff0;
 '
+# .got.plt is only used for the GNU PLT extensions.  It should not be
+# included in the .sdata block with .got, as there is no need to access
+# the section from _gp.  Note that the traditional:
+#
+#      . = .
+#      _gp = ALIGN (16) + 0x7ff0;
+#      .got : { *(.got.plt) *(.got) }
+#
+# would set _gp to the wrong value; _gp - 0x7ff0 must point to the start
+# of *(.got).
+GOT=".got          ${RELOCATING-0} : { *(.got) }"
+unset OTHER_READWRITE_SECTIONS
+unset OTHER_RELRO_SECTIONS
+if test -n "$RELRO_NOW"; then
+  OTHER_RELRO_SECTIONS=".got.plt      ${RELOCATING-0} : { *(.got.plt) }"
+else
+  OTHER_READWRITE_SECTIONS=".got.plt      ${RELOCATING-0} : { *(.got.plt) }"
+fi
+
 OTHER_SDATA_SECTIONS="
   .lit8         ${RELOCATING-0} : { *(.lit8) }
   .lit4         ${RELOCATING-0} : { *(.lit4) }
Index: ld/emultempl/mipself.em
===================================================================
--- ld/emultempl/mipself.em	2008-08-03 13:12:34.000000000 +0100
+++ ld/emultempl/mipself.em	2008-08-03 13:15:44.000000000 +0100
@@ -19,6 +19,20 @@
 # MA 02110-1301, USA.
 
 fragment <<EOF
+
+#include "ldctor.h"
+#include "elf/mips.h"
+#include "elfxx-mips.h"
+
+#define is_mips_elf(bfd)				\
+  (bfd_get_flavour (bfd) == bfd_target_elf_flavour	\
+   && elf_tdata (bfd) != NULL				\
+   && elf_object_id (bfd) == MIPS_ELF_TDATA)
+
+/* Fake input file for stubs.  */
+static lang_input_statement_type *stub_file;
+static bfd *stub_bfd;
+
 static void
 mips_after_parse (void)
 {
@@ -33,6 +47,195 @@ mips_after_parse (void)
     }
   after_parse_default ();
 }
+
+struct hook_stub_info
+{
+  lang_statement_list_type add;
+  asection *input_section;
+};
+
+/* Traverse the linker tree to find the spot where the stub goes.  */
+
+static bfd_boolean
+hook_in_stub (struct hook_stub_info *info, lang_statement_union_type **lp)
+{
+  lang_statement_union_type *l;
+  bfd_boolean ret;
+
+  for (; (l = *lp) != NULL; lp = &l->header.next)
+    {
+      switch (l->header.type)
+	{
+	case lang_constructors_statement_enum:
+	  ret = hook_in_stub (info, &constructor_list.head);
+	  if (ret)
+	    return ret;
+	  break;
+
+	case lang_output_section_statement_enum:
+	  ret = hook_in_stub (info,
+			      &l->output_section_statement.children.head);
+	  if (ret)
+	    return ret;
+	  break;
+
+	case lang_wild_statement_enum:
+	  ret = hook_in_stub (info, &l->wild_statement.children.head);
+	  if (ret)
+	    return ret;
+	  break;
+
+	case lang_group_statement_enum:
+	  ret = hook_in_stub (info, &l->group_statement.children.head);
+	  if (ret)
+	    return ret;
+	  break;
+
+	case lang_input_section_enum:
+	  if (info->input_section == NULL
+	      || l->input_section.section == info->input_section)
+	    {
+	      /* We've found our section.  Insert the stub immediately
+		 before its associated input section.  */
+	      *lp = info->add.head;
+	      *(info->add.tail) = l;
+	      return TRUE;
+	    }
+	  break;
+
+	case lang_data_statement_enum:
+	case lang_reloc_statement_enum:
+	case lang_object_symbols_statement_enum:
+	case lang_output_statement_enum:
+	case lang_target_statement_enum:
+	case lang_input_statement_enum:
+	case lang_assignment_statement_enum:
+	case lang_padding_statement_enum:
+	case lang_address_statement_enum:
+	case lang_fill_statement_enum:
+	  break;
+
+	default:
+	  FAIL ();
+	  break;
+	}
+    }
+  return FALSE;
+}
+
+/* Create a new stub section called STUB_SEC_NAME and arrange for it to
+   be linked in OUTPUT_SECTION.  The section should go at the beginning of
+   OUTPUT_SECTION if INPUT_SECTION is null, otherwise it must go immediately
+   before INPUT_SECTION.  */
+
+static asection *
+mips_add_stub_section (const char *stub_sec_name, asection *input_section,
+		       asection *output_section)
+{
+  asection *stub_sec;
+  flagword flags;
+  const char *secname;
+  lang_output_section_statement_type *os;
+  struct hook_stub_info info;
+
+  /* Create the stub file, if we haven't already.  */
+  if (stub_file == NULL)
+    {
+      stub_file = lang_add_input_file ("linker stubs",
+				       lang_input_file_is_fake_enum,
+				       NULL);
+      stub_bfd = bfd_create ("linker stubs", link_info.output_bfd);
+      if (stub_bfd == NULL
+	  || !bfd_set_arch_mach (stub_bfd,
+				 bfd_get_arch (link_info.output_bfd),
+				 bfd_get_mach (link_info.output_bfd)))
+	{
+	  einfo ("%F%P: can not create BFD %E\n");
+	  return NULL;
+	}
+      stub_bfd->flags |= BFD_LINKER_CREATED;
+      stub_file->the_bfd = stub_bfd;
+      ldlang_add_file (stub_file);
+    }
+
+  /* Create the section.  */
+  stub_sec = bfd_make_section_anyway (stub_bfd, stub_sec_name);
+  if (stub_sec == NULL)
+    goto err_ret;
+
+  /* Set the flags.  */
+  flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
+	   | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_KEEP);
+  if (!bfd_set_section_flags (stub_bfd, stub_sec, flags))
+    goto err_ret;
+
+  /* Create an output section statement.  */
+  secname = bfd_get_section_name (output_section->owner, output_section);
+  os = lang_output_section_find (secname);
+
+  /* Initialize a statement list that contains only the new statement.  */
+  lang_list_init (&info.add);
+  lang_add_section (&info.add, stub_sec, os);
+  if (info.add.head == NULL)
+    goto err_ret;
+
+  /* Insert the new statement in the appropriate place.  */
+  info.input_section = input_section;
+  if (hook_in_stub (&info, &os->children.head))
+    return stub_sec;
+
+ err_ret:
+  einfo ("%X%P: can not make stub section: %E\n");
+  return NULL;
+}
+
+/* This is called before the input files are opened.  */
+
+static void
+mips_create_output_section_statements (void)
+{
+  if (is_mips_elf (link_info.output_bfd))
+    _bfd_mips_elf_init_stubs (&link_info, mips_add_stub_section);
+}
+
+/* This is called after we have merged the private data of the input bfds.  */
+
+static void
+mips_before_allocation (void)
+{
+  flagword flags;
+
+  flags = elf_elfheader (link_info.output_bfd)->e_flags;
+  if (!link_info.shared
+      && !link_info.nocopyreloc
+      && (flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) == EF_MIPS_CPIC)
+    _bfd_mips_elf_use_plts_and_copy_relocs (&link_info);
+
+  gld${EMULATION_NAME}_before_allocation ();
+}
+
+/* Avoid processing the fake stub_file in vercheck, stat_needed and
+   check_needed routines.  */
+
+static void (*real_func) (lang_input_statement_type *);
+
+static void mips_for_each_input_file_wrapper (lang_input_statement_type *l)
+{
+  if (l != stub_file)
+    (*real_func) (l);
+}
+
+static void
+mips_lang_for_each_input_file (void (*func) (lang_input_statement_type *))
+{
+  real_func = func;
+  lang_for_each_input_file (&mips_for_each_input_file_wrapper);
+}
+
+#define lang_for_each_input_file mips_lang_for_each_input_file
+
 EOF
 
 LDEMUL_AFTER_PARSE=mips_after_parse
+LDEMUL_BEFORE_ALLOCATION=mips_before_allocation
+LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=mips_create_output_section_statements
Index: ld/testsuite/ld-mips-elf/mips16-pic-3a.s
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/mips16-pic-3a.s	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,59 @@
+	.abicalls
+	.option	pic0
+	.set	noreorder
+	.include "mips16-pic-3.inc"
+
+	# For symbols called by a .call stub in this file.
+	hstub	unused1,mips16
+
+	# For symbols called by a .call.fp stub in this file.
+	hstub	unused2,mips16
+
+	# For symbols called by a .call stub in another file.
+	hstub	unused3,mips16
+
+	# For symbols called by a .call.fp stub in another file.
+	hstub	unused4,mips16
+
+
+	# For symbols called by a .call stub in this file.
+	lstub	used1,nomips16
+
+	# For symbols called by a .call.fp stub in this file.
+	lstub	used2,nomips16
+
+	# For symbols called by a .call stub in this file.
+	hstub	used3,nomips16
+
+	# For symbols called by a .call.fp stub in this file.
+	hstub	used4,nomips16
+
+	# For symbols called by a .call stub in another file.
+	hstub	used5,nomips16
+
+	# For symbols called by a .call.fp stub in another file.
+	hstub	used6,nomips16
+
+	# For symbols called by a .call stub in this file.
+	gstub	used7,nomips16
+
+	# For symbols called by a .call.fp stub in this file.
+	gstub	used8,nomips16
+
+	# For symbols called by a .call stub in another file.
+	gstub	used9,nomips16
+
+	# For symbols called by a .call.fp stub in another file.
+	gstub	used10,nomips16
+
+	call_stub unused1
+	call_stub used1
+	call_stub used3
+	call_stub used7
+	call_stub extern1
+
+	call_fp_stub unused2
+	call_fp_stub used2
+	call_fp_stub used4
+	call_fp_stub used8
+	call_fp_stub extern2
Index: ld/testsuite/ld-mips-elf/mips16-pic-3b.s
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/mips16-pic-3b.s	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,14 @@
+	.abicalls
+	.option	pic0
+	.set	noreorder
+	.include "mips16-pic-3.inc"
+
+	call_stub unused3
+	call_stub used5
+	call_stub used9
+	call_stub extern3
+
+	call_fp_stub unused4
+	call_fp_stub used6
+	call_fp_stub used10
+	call_fp_stub extern4
Index: ld/testsuite/ld-mips-elf/mips16-pic-3.dd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/mips16-pic-3.dd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,263 @@
+
+.*
+
+
+Disassembly of section \.text:
+
+00040400 <unused1>:
+.*:	e820      	jr	ra
+.*:	6500      	nop
+
+00040404 <unused2>:
+.*:	e820      	jr	ra
+.*:	6500      	nop
+
+00040408 <unused3>:
+.*:	e820      	jr	ra
+.*:	6500      	nop
+
+0004040c <unused4>:
+.*:	e820      	jr	ra
+.*:	6500      	nop
+
+00040410 <used1>:
+.*:	03e00008 	jr	ra
+.*:	00000000 	nop
+
+00040418 <used2>:
+.*:	03e00008 	jr	ra
+.*:	00000000 	nop
+
+00040420 <used3>:
+.*:	03e00008 	jr	ra
+.*:	00000000 	nop
+
+00040428 <used4>:
+.*:	03e00008 	jr	ra
+.*:	00000000 	nop
+
+00040430 <used5>:
+.*:	03e00008 	jr	ra
+.*:	00000000 	nop
+
+00040438 <used6>:
+.*:	03e00008 	jr	ra
+.*:	00000000 	nop
+
+00040440 <used7>:
+.*:	03e00008 	jr	ra
+.*:	00000000 	nop
+
+00040448 <used8>:
+.*:	03e00008 	jr	ra
+.*:	00000000 	nop
+
+00040450 <used9>:
+.*:	03e00008 	jr	ra
+.*:	00000000 	nop
+
+00040458 <used10>:
+.*:	03e00008 	jr	ra
+.*:	00000000 	nop
+
+00040460 <test_unused1>:
+.*:	.*	jal	.* <unused1>
+
+00040464 <test_used1>:
+.*:	.*	jalx	.* <__call_used1>
+
+00040468 <test_used3>:
+.*:	.*	jalx	.* <__call_used3>
+
+0004046c <test_used7>:
+.*:	.*	jalx	.* <__call_used7>
+
+00040470 <test_extern1>:
+.*:	.*	jalx	.* <__call_extern1>
+
+00040474 <test_unused2>:
+.*:	.*	jal	.* <unused2>
+
+00040478 <test_used2>:
+.*:	.*	jalx	.* <__call_fp_used2>
+
+0004047c <test_used4>:
+.*:	.*	jalx	.* <__call_fp_used4>
+
+00040480 <test_used8>:
+.*:	.*	jalx	.* <__call_fp_used8>
+
+00040484 <test_extern2>:
+.*:	.*	jalx	.* <__call_fp_extern2>
+#...
+
+00040490 <test_unused3>:
+.*:	.*	jal	.* <unused3>
+
+00040494 <test_used5>:
+.*:	.*	jalx	.* <__call_used5>
+
+00040498 <test_used9>:
+.*:	.*	jalx	.* <__call_used9>
+
+0004049c <test_extern3>:
+.*:	.*	jalx	.* <__call_extern3>
+
+000404a0 <test_unused4>:
+.*:	.*	jal	.* <unused4>
+
+000404a4 <test_used6>:
+.*:	.*	jalx	.* <__call_fp_used6>
+
+000404a8 <test_used10>:
+.*:	.*	jalx	.* <__call_fp_used10>
+
+000404ac <test_extern4>:
+.*:	.*	jalx	.* <__call_fp_extern4>
+
+000404b0 <__call_used1>:
+.*:	3c190004 	lui	t9,.*
+.*:	27390410 	addiu	t9,t9,.*
+.*:	03200008 	jr	t9
+.*:	44846000 	mtc1	a0,\$f12
+
+000404c0 <__call_used3>:
+.*:	3c190004 	lui	t9,.*
+.*:	27390420 	addiu	t9,t9,.*
+.*:	03200008 	jr	t9
+.*:	44846000 	mtc1	a0,\$f12
+
+000404d0 <__call_used7>:
+.*:	3c190004 	lui	t9,.*
+.*:	27390440 	addiu	t9,t9,.*
+.*:	03200008 	jr	t9
+.*:	44846000 	mtc1	a0,\$f12
+
+000404e0 <__call_extern1>:
+.*:	3c190004 	lui	t9,.*
+.*:	27390650 	addiu	t9,t9,.*
+.*:	03200008 	jr	t9
+.*:	44846000 	mtc1	a0,\$f12
+
+000404f0 <__call_fp_used2>:
+.*:	03e09021 	move	s2,ra
+.*:	3c190004 	lui	t9,.*
+.*:	27390418 	addiu	t9,t9,.*
+.*:	0320f809 	jalr	t9
+.*:	44846000 	mtc1	a0,\$f12
+.*:	44020000 	mfc1	v0,\$f0
+.*:	02400008 	jr	s2
+.*:	00000000 	nop
+
+00040510 <__call_fp_used4>:
+.*:	03e09021 	move	s2,ra
+.*:	3c190004 	lui	t9,.*
+.*:	27390428 	addiu	t9,t9,.*
+.*:	0320f809 	jalr	t9
+.*:	44846000 	mtc1	a0,\$f12
+.*:	44020000 	mfc1	v0,\$f0
+.*:	02400008 	jr	s2
+.*:	00000000 	nop
+
+00040530 <__call_fp_used8>:
+.*:	03e09021 	move	s2,ra
+.*:	3c190004 	lui	t9,.*
+.*:	27390448 	addiu	t9,t9,.*
+.*:	0320f809 	jalr	t9
+.*:	44846000 	mtc1	a0,\$f12
+.*:	44020000 	mfc1	v0,\$f0
+.*:	02400008 	jr	s2
+.*:	00000000 	nop
+
+00040550 <__call_fp_extern2>:
+.*:	03e09021 	move	s2,ra
+.*:	3c190004 	lui	t9,.*
+.*:	27390630 	addiu	t9,t9,.*
+.*:	0320f809 	jalr	t9
+.*:	44846000 	mtc1	a0,\$f12
+.*:	44020000 	mfc1	v0,\$f0
+.*:	02400008 	jr	s2
+.*:	00000000 	nop
+
+00040570 <__call_used5>:
+.*:	3c190004 	lui	t9,.*
+.*:	27390430 	addiu	t9,t9,.*
+.*:	03200008 	jr	t9
+.*:	44846000 	mtc1	a0,\$f12
+
+00040580 <__call_used9>:
+.*:	3c190004 	lui	t9,.*
+.*:	27390450 	addiu	t9,t9,.*
+.*:	03200008 	jr	t9
+.*:	44846000 	mtc1	a0,\$f12
+
+00040590 <__call_extern3>:
+.*:	3c190004 	lui	t9,.*
+.*:	27390620 	addiu	t9,t9,.*
+.*:	03200008 	jr	t9
+.*:	44846000 	mtc1	a0,\$f12
+
+000405a0 <__call_fp_used6>:
+.*:	03e09021 	move	s2,ra
+.*:	3c190004 	lui	t9,.*
+.*:	27390438 	addiu	t9,t9,.*
+.*:	0320f809 	jalr	t9
+.*:	44846000 	mtc1	a0,\$f12
+.*:	44020000 	mfc1	v0,\$f0
+.*:	02400008 	jr	s2
+.*:	00000000 	nop
+
+000405c0 <__call_fp_used10>:
+.*:	03e09021 	move	s2,ra
+.*:	3c190004 	lui	t9,.*
+.*:	27390458 	addiu	t9,t9,.*
+.*:	0320f809 	jalr	t9
+.*:	44846000 	mtc1	a0,\$f12
+.*:	44020000 	mfc1	v0,\$f0
+.*:	02400008 	jr	s2
+.*:	00000000 	nop
+
+000405e0 <__call_fp_extern4>:
+.*:	03e09021 	move	s2,ra
+.*:	3c190004 	lui	t9,.*
+.*:	27390640 	addiu	t9,t9,.*
+.*:	0320f809 	jalr	t9
+.*:	44846000 	mtc1	a0,\$f12
+.*:	44020000 	mfc1	v0,\$f0
+.*:	02400008 	jr	s2
+.*:	00000000 	nop
+
+Disassembly of section \.plt:
+
+00040600 <.*>:
+.*:	3c0f0005 	lui	t7,0x5
+.*:	8df90008 	lw	t9,8\(t7\)
+.*:	25ef0008 	addiu	t7,t7,8
+.*:	3c0e0005 	lui	t6,0x5
+.*:	03200008 	jr	t9
+.*:	25ce0400 	addiu	t6,t6,1024
+	\.\.\.
+
+00040620 <extern3@plt>:
+.*:	3c180005 	lui	t8,0x5
+.*:	8f190400 	lw	t9,1024\(t8\)
+.*:	03200008 	jr	t9
+.*:	27180400 	addiu	t8,t8,1024
+
+00040630 <extern2@plt>:
+.*:	3c180005 	lui	t8,0x5
+.*:	8f190404 	lw	t9,1028\(t8\)
+.*:	03200008 	jr	t9
+.*:	27180404 	addiu	t8,t8,1028
+
+00040640 <extern4@plt>:
+.*:	3c180005 	lui	t8,0x5
+.*:	8f190408 	lw	t9,1032\(t8\)
+.*:	03200008 	jr	t9
+.*:	27180408 	addiu	t8,t8,1032
+
+00040650 <extern1@plt>:
+.*:	3c180005 	lui	t8,0x5
+.*:	8f19040c 	lw	t9,1036\(t8\)
+.*:	03200008 	jr	t9
+.*:	2718040c 	addiu	t8,t8,1036
Index: ld/testsuite/ld-mips-elf/mips16-pic-3.gd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/mips16-pic-3.gd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,9 @@
+
+Primary GOT:
+ Canonical gp value: 00057ff0
+
+ Reserved entries:
+   Address     Access  Initial Purpose
+  00050000 -32752\(gp\) 00000000 Lazy resolver
+  00050004 -32748\(gp\) 80000000 Module pointer \(GNU extension\)
+  00050008 -32744\(gp\) 00000000 PLT lazy resolver \(GNU extension\)
Index: ld/testsuite/ld-mips-elf/mips16-pic-3.rd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/mips16-pic-3.rd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,7 @@
+
+Relocation section '\.rel\.plt' at offset .* contains 4 entries:
+ Offset     Info    Type            Sym\.Value  Sym\. Name
+00050400  .*7f R_MIPS_JUMP_SLOT  00040620   extern3
+00050404  .*7f R_MIPS_JUMP_SLOT  00040630   extern2
+00050408  .*7f R_MIPS_JUMP_SLOT  00040640   extern4
+0005040c  .*7f R_MIPS_JUMP_SLOT  00040650   extern1
Index: ld/testsuite/ld-mips-elf/mips16-pic-3.inc
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/mips16-pic-3.inc	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,59 @@
+	.macro	test_call,name
+	.set	mips16
+	.text
+	.ent	test_\name
+test_\name:
+	jal	\name
+	.end	test_\name
+	.endm
+
+	.macro	call_stub,name
+	.set	nomips16
+	.section .mips16.call.\name, "ax", @progbits
+	.ent	__call_\name
+__call_\name:
+	la	$25,\name
+	jr	$25
+	mtc1	$4,$f12
+	.end	__call_\name
+
+	test_call \name
+	.endm
+
+	.macro	call_fp_stub,name
+	.set	nomips16
+	.section .mips16.call.fp.\name, "ax", @progbits
+	.ent	__call_fp_\name
+__call_fp_\name:
+	move	$18,$31
+	la	$25,\name
+	jalr	$25
+	mtc1	$4,$f12
+	mfc1	$2,$f0
+	jr	$18
+	nop
+	.end	__call_fp_\name
+
+	test_call \name
+	.endm
+
+	.macro	lstub,name,mode
+	.set	\mode
+	.text
+	.ent	\name
+\name:
+	jr	$31
+	nop
+	.end	\name
+	.endm
+
+	.macro	hstub,name,mode
+	.globl	\name
+	.hidden	\name
+	lstub	\name, \mode
+	.endm
+
+	.macro	gstub,name,mode
+	.globl	\name
+	lstub	\name, \mode
+	.endm
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-1a.s
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-1a.s	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,31 @@
+	.abicalls
+	.global	f1
+	.global	f2
+	.global	f3
+	.ent	f1
+f1:
+	.set	noreorder
+	.cpload	$25
+	.set	reorder
+	.option	pic0
+	jal	f3
+	.option	pic2
+	jr	$31
+	.end	f1
+
+	.ent	f2
+f2:
+	.set	noreorder
+	.cpload	$25
+	.set	reorder
+	jr	$31
+	.end	f2
+
+	.set	mips16
+	.ent	f3
+f3:
+	li	$2,%hi(_gp_disp)
+	addiu	$3,$pc,%lo(_gp_disp)
+	sll	$2,16
+	addu	$2,$2,$3
+	.end	f3
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-1b.s
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-1b.s	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,9 @@
+	.abicalls
+	.option	pic0
+	.global	__start
+	.ent	__start
+__start:
+	jal	f1
+	jal	f2
+	jal	f3
+	.end	__start
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-1.ld
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-1.ld	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,9 @@
+SECTIONS
+{
+  . = 0x40000;
+  .reginfo : { *(.reginfo) }
+  .pdr : { *(.pdr) }
+  . = 0x41000;
+  .text : { *(.text) }
+  _gp = 0x68000;
+}
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-1.dd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-1.dd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,44 @@
+
+.*
+
+Disassembly of section \.text:
+
+00041000 <f2>:
+   41000:	3c190004 	lui	t9,0x4
+   41004:	0801040f 	j	4103c <\.pic\.f2>
+   41008:	2739103c 	addiu	t9,t9,4156
+	\.\.\.
+
+00041018 <f1>:
+   41018:	3c190004 	lui	t9,0x4
+   4101c:	27391020 	addiu	t9,t9,4128
+   41020:	3c1c0002 	lui	gp,0x2
+   41024:	279c6fe0 	addiu	gp,gp,28640
+   41028:	0399e021 	addu	gp,gp,t9
+   4102c:	74010414 	jalx	41050 <f3>
+   41030:	00000000 	nop
+   41034:	03e00008 	jr	ra
+   41038:	00000000 	nop
+
+0004103c <\.pic\.f2>:
+   4103c:	3c1c0002 	lui	gp,0x2
+   41040:	279c6fc4 	addiu	gp,gp,28612
+   41044:	0399e021 	addu	gp,gp,t9
+   41048:	03e00008 	jr	ra
+   4104c:	00000000 	nop
+
+00041050 <f3>:
+   41050:	f000 6a02 	li	v0,2
+   41054:	f7ad 0b0c 	la	v1,48000 .*
+   41058:	f400 3240 	sll	v0,16
+   4105c:	e269      	addu	v0,v1
+   4105e:	6500      	nop
+
+00041060 <__start>:
+   41060:	0c010406 	jal	41018 <f1>
+   41064:	00000000 	nop
+   41068:	0c010400 	jal	41000 <f2>
+   4106c:	00000000 	nop
+   41070:	74010414 	jalx	41050 <f3>
+   41074:	00000000 	nop
+	\.\.\.
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-1.nd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-1.nd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,8 @@
+#...
+.*: 0004103c    20 FUNC    LOCAL  DEFAULT .* .pic.f2
+.*: 00000000     0 OBJECT  GLOBAL DEFAULT  UND _gp_disp
+.*: 00068000     0 NOTYPE  GLOBAL DEFAULT  ABS _gp
+.*: 00041050    14 FUNC    GLOBAL DEFAULT \[MIPS16\] .* f3
+.*: 00041060    24 FUNC    GLOBAL DEFAULT .* __start
+.*: 00041000    16 FUNC    GLOBAL DEFAULT .* f2
+.*: 00041018    36 FUNC    GLOBAL DEFAULT .* f1
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-1-rel.dd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-1-rel.dd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,46 @@
+
+.*
+
+Disassembly of section \.text:
+
+00000000 <f1>:
+   0:	3c1c0000 	lui	gp,0x0
+			0: R_MIPS_HI16	_gp_disp
+   4:	279c0000 	addiu	gp,gp,0
+			4: R_MIPS_LO16	_gp_disp
+   8:	0399e021 	addu	gp,gp,t9
+   c:	0c000000 	jal	0 .*
+			c: R_MIPS_26	f3
+  10:	00000000 	nop
+  14:	03e00008 	jr	ra
+  18:	00000000 	nop
+
+0000001c <f2>:
+  1c:	3c1c0000 	lui	gp,0x0
+			1c: R_MIPS_HI16	_gp_disp
+  20:	279c0000 	addiu	gp,gp,0
+			20: R_MIPS_LO16	_gp_disp
+  24:	0399e021 	addu	gp,gp,t9
+  28:	03e00008 	jr	ra
+  2c:	00000000 	nop
+
+00000030 <f3>:
+  30:	f000 6a00 	li	v0,0
+			30: R_MIPS16_HI16	_gp_disp
+  34:	f000 0b00 	la	v1,34 .*
+			34: R_MIPS16_LO16	_gp_disp
+  38:	f400 3240 	sll	v0,16
+  3c:	e269      	addu	v0,v1
+  3e:	6500      	nop
+
+00000040 <__start>:
+  40:	0c000000 	jal	0 .*
+			40: R_MIPS_26	f1
+  44:	00000000 	nop
+  48:	0c000000 	jal	0 .*
+			48: R_MIPS_26	f2
+  4c:	00000000 	nop
+  50:	0c000000 	jal	0 .*
+			50: R_MIPS_26	f3
+  54:	00000000 	nop
+	...
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-1-rel.nd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-1-rel.nd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,5 @@
+#...
+.*: 00000030    14 FUNC    GLOBAL DEFAULT \[MIPS16\] .* f3
+.*: 00000040    24 FUNC    GLOBAL DEFAULT .* __start
+.*: 0000001c    20 FUNC    GLOBAL DEFAULT \[MIPS PIC\] .* f2
+.*: 00000000    28 FUNC    GLOBAL DEFAULT \[MIPS PIC\] .* f1
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-2a.s
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-2a.s	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,7 @@
+	.abicalls
+	.option	pic0
+	.global	__start
+	.ent	__start
+__start:
+	jal	foo
+	.end	__start
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-2b.s
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-2b.s	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,6 @@
+	.abicalls
+	.symver	foo2,foo@@V2
+	.global	foo2
+	.ent	foo2
+foo2:	jr	$31
+	.end	foo2
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-2.d
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-2.d	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,23 @@
+#source: pic-and-nonpic-2a.s
+#source: pic-and-nonpic-2b.s
+#as: -32 -EB
+#ld: -melf32btsmip -Tpic-and-nonpic-1.ld
+#objdump: -dr
+
+.*
+
+Disassembly of section \.text:
+
+00041000 <__start>:
+   41000:	0c010406 	jal	41018 <foo@@V2>
+   41004:	00000000 	nop
+	\.\.\.
+
+00041018 <foo@@V2>:
+   41018:	3c190004 	lui	t9,0x4
+   4101c:	27391020 	addiu	t9,t9,4128
+
+00041020 <foo2>:
+   41020:	03e00008 	jr	ra
+   41024:	00000000 	nop
+	\.\.\.
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-3a.s
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-3a.s	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,29 @@
+	.abicalls
+	.set	noreorder
+	.set	nomips16
+	.global	foo
+	.ent	foo
+foo:
+	.cpload	$25
+	lw	$25,%call16(foo)($28)
+	lw	$2,%got(data)($28)
+	jr	$25
+	addiu	$2,$2,%lo(data)
+	.end	foo
+
+	.set	mips16
+	.global	bar
+	.ent	bar
+bar:
+	li	$2,%hi(_gp_disp)
+	addiu	$2,$pc,%lo(_gp_disp)
+	sll	$2,16
+	addu	$2,$2,$3
+	lw	$3,%call16(ext)($2)
+	move	$28,$2
+	jr	$3
+	move	$25,$3
+	.end	bar
+
+	.data
+data:	.word	0x12345678
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-3a.ld
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-3a.ld	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,23 @@
+SECTIONS
+{
+  . = 0;
+  .reginfo : { *(.reginfo) }
+
+  . = ALIGN (0x400);
+  .dynamic : { *(.dynamic) }
+  .dynsym : { *(.dynsym) }
+  .dynstr : { *(.dynstr) }
+
+  . = ALIGN (0x400);
+  .text : { *(.text) }
+
+  . = ALIGN (0x400);
+  .MIPS.stubs : { *(.MIPS.stubs) }
+
+  . = ALIGN (0x10000);
+  .data : { *(.data) }
+
+  . = ALIGN (0x400);
+  _gp = . + 0x7ff0;
+  .got : { *(.got) }
+}
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-3a.dd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-3a.dd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,39 @@
+# GOT layout:
+#
+# -32752: lazy resolution function
+# -32748: reserved for module pointer
+# -32744: the GOT page entry
+# -32740: foo's GOT entry
+# -32736: ext's GOT entry
+
+.*
+
+Disassembly of section \.text:
+
+00000800 <foo>:
+ 800:	3c1c0001 	lui	gp,0x1
+ 804:	279c7bf0 	addiu	gp,gp,31728
+ 808:	0399e021 	addu	gp,gp,t9
+ 80c:	8f99801c 	lw	t9,-32740\(gp\)
+ 810:	8f828018 	lw	v0,-32744\(gp\)
+ 814:	03200008 	jr	t9
+ 818:	24420000 	addiu	v0,v0,0
+
+0000081c <bar>:
+ 81c:	f000 6a01 	li	v0,1
+ 820:	f3cf 0a10 	la	v0,83f0 .*
+ 824:	f400 3240 	sll	v0,16
+ 828:	e269      	addu	v0,v1
+ 82a:	f030 9a60 	lw	v1,-32736\(v0\)
+ 82e:	659a      	move	gp,v0
+ 830:	eb00      	jr	v1
+ 832:	653b      	move	t9,v1
+#...
+Disassembly of section \.MIPS\.stubs:
+
+00000c00 <.MIPS.stubs>:
+ c00:	8f998010 	lw	t9,-32752\(gp\)
+ c04:	03e07821 	move	t7,ra
+ c08:	0320f809 	jalr	t9
+ c0c:	24180007 	li	t8,7
+	\.\.\.
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-3a.gd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-3a.gd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,18 @@
+
+Primary GOT:
+ Canonical gp value: 000183f0
+
+ Reserved entries:
+   Address     Access  Initial Purpose
+  00010400 -32752\(gp\) 00000000 Lazy resolver
+  00010404 -32748\(gp\) 80000000 Module pointer \(GNU extension\)
+
+ Local entries:
+   Address     Access  Initial
+  00010408 -32744\(gp\) 00010000
+
+ Global entries:
+   Address     Access  Initial Sym\.Val\. Type    Ndx Name
+  0001040c -32740\(gp\) 00000800 00000800 FUNC      6 foo
+  00010410 -32736\(gp\) 00000c00 00000c00 FUNC    UND ext
+
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-3a.sd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-3a.sd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,20 @@
+
+Elf file type is DYN \(Shared object file\)
+Entry point .*
+There are 5 program headers, starting at offset .*
+
+Program Headers:
+ * Type * Offset * VirtAddr * PhysAddr * FileSiz * MemSiz * Flg * Align
+ * REGINFO * [^ ]+ * 0x0+00000 * 0x0+00000 [^ ]+ * [^ ]+ * R * 0x.*
+ * LOAD * [^ ]+ * 0x0+00000 * 0x0+00000 [^ ]+ * [^ ]+ * R E * 0x.*
+ * LOAD * [^ ]+ * 0x0+10000 * 0x0+10000 [^ ]+ * [^ ]+ * RW  * 0x.*
+ * DYNAMIC * [^ ]+ * 0x0+00400 * 0x0+00400 .*
+ * NULL * .*
+
+ *Section to Segment mapping:
+ *Segment Sections\.\.\.
+ *0*0 * \.reginfo *
+ *0*1 * \.reginfo \.dynamic \.dynsym \.dynstr \.hash \.text \.MIPS.stubs *
+ *0*2 * \.data \.got *
+ *0*3 * \.dynamic *
+ *0*4 *
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.s
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.s	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,22 @@
+	.abicalls
+	.option	pic0
+	.global	__start
+	.ent	__start
+__start:
+	jal	foo
+	j	ext
+	.end	__start
+
+	.global	ext
+	.ent	ext
+ext:
+	lui	$gp,%hi(__gnu_local_gp)
+	addiu	$gp,$gp,%lo(__gnu_local_gp)
+	lw	$2,%got(local)($gp)
+	addiu	$2,$2,%lo(local)
+	lw	$25,%call16(bar)($gp)
+	jr	$25
+	.end	ext
+
+	.data
+local:	.word	1
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.ld
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.ld	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,35 @@
+SECTIONS
+{
+  . = 0x40000 + SIZEOF_HEADERS;
+  .interp : { *(.interp) }
+
+  . = 0x41000;
+  .reginfo : { *(.reginfo) }
+  .hash : { *(.hash) }
+  .dynsym : { *(.dynsym) }
+  .dynstr : { *(.dynstr) }
+
+  . = 0x42000;
+  .dynamic : { *(.dynamic) }
+
+  . = 0x43000;
+  .rel.plt : { *(.rel.plt) }
+  .plt : { *(.plt) }
+
+  . = 0x44000;
+  .text : { *(.text) }
+  .MIPS.stubs : { *(.MIPS.stubs) }
+
+  . = 0x80000;
+  .rld_map : { *(.rld_map) }
+
+  . = 0x81000;
+  .got.plt : { *(.got.plt) }
+
+  . = 0xa0000;
+  _gp = . + 0x7ff0;
+  .got : { *(.got) }
+
+  . = 0xa1000;
+  .data : { *(.data) }
+}
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.ad
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.ad	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,26 @@
+
+Dynamic section at offset .* contains .*:
+ * Tag * Type * Name/Value
+ 0x00000001 \(NEEDED\) .*
+ 0x00000004 \(HASH\) .*
+ 0x00000005 \(STRTAB\) .*
+ 0x00000006 \(SYMTAB\) .*
+ 0x0000000a \(STRSZ\) .*
+ 0x0000000b \(SYMENT\) .*
+ 0x70000016 \(MIPS_RLD_MAP\) * 0x80000
+ 0x00000015 \(DEBUG\) * 0x0
+ 0x00000003 \(PLTGOT\) * 0xa0000
+ 0x70000001 \(MIPS_RLD_VERSION\) * 1
+ 0x70000005 \(MIPS_FLAGS\) * NOTPOT
+ 0x70000006 \(MIPS_BASE_ADDRESS\) * 0x40000
+# This must be the number of GOT entries - 1, the last entry being for "bar".
+ 0x7000000a \(MIPS_LOCAL_GOTNO\) * 4
+# This must be MIPS_GOTSYM + 1.
+ 0x70000011 \(MIPS_SYMTABNO\) * 8
+ 0x70000012 \(MIPS_UNREFEXTNO\) .*
+# This must be the index of "bar".
+ 0x70000013 \(MIPS_GOTSYM\) * 0x7
+ 0x00000014 \(PLTREL\) * REL
+ 0x00000017 \(JMPREL\) * 0x43000
+ 0x00000002 \(PLTRELSZ\) * 8 \(bytes\)
+ 0x00000000 \(NULL\) * 0x0
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.dd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.dd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,51 @@
+# GOT layout:
+#
+# -32752: lazy resolution function
+# -32748: reserved for module pointer
+# -32744: PLT resolution function
+# -32740: GOT page entry.
+# -32736: bar's GOT entry
+
+.*
+
+Disassembly of section \.plt:
+
+00043010 <.*>:
+   43010:	3c0f000a 	lui	t7,0xa
+   43014:	8df90008 	lw	t9,8\(t7\)
+   43018:	25ef0008 	addiu	t7,t7,8
+   4301c:	3c0e0008 	lui	t6,0x8
+   43020:	03200008 	jr	t9
+   43024:	25ce1000 	addiu	t6,t6,4096
+	\.\.\.
+
+00043030 <foo@plt>:
+   43030:	3c180008 	lui	t8,0x8
+   43034:	8f191000 	lw	t9,4096\(t8\)
+   43038:	03200008 	jr	t9
+   4303c:	27181000 	addiu	t8,t8,4096
+Disassembly of section \.text:
+
+00044000 <__start>:
+   44000:	0c010c0c 	jal	43030 <foo@plt>
+   44004:	00000000 	nop
+   44008:	08011004 	j	44010 <ext>
+   4400c:	00000000 	nop
+
+00044010 <ext>:
+   44010:	3c1c000a 	lui	gp,0xa
+   44014:	279c7ff0 	addiu	gp,gp,32752
+   44018:	8f82801c 	lw	v0,-32740\(gp\)
+   4401c:	24421000 	addiu	v0,v0,4096
+   44020:	8f998020 	lw	t9,-32736\(gp\)
+   44024:	03200008 	jr	t9
+   44028:	00000000 	nop
+   4402c:	00000000 	nop
+Disassembly of section .MIPS.stubs:
+
+00044030 <\.MIPS\.stubs>:
+   44030:	8f998010 	lw	t9,-32752\(gp\)
+   44034:	03e07821 	move	t7,ra
+   44038:	0320f809 	jalr	t9
+   4403c:	24180007 	li	t8,7
+	\.\.\.
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.gd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.gd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,18 @@
+
+Primary GOT:
+ Canonical gp value: 000a7ff0
+
+ Reserved entries:
+   Address     Access  Initial Purpose
+  000a0000 -32752\(gp\) 00000000 Lazy resolver
+  000a0004 -32748\(gp\) 80000000 Module pointer \(GNU extension\)
+  000a0008 -32744\(gp\) 00000000 PLT lazy resolver \(GNU extension\)
+
+ Local entries:
+   Address     Access  Initial
+  000a000c -32740\(gp\) 000a0000
+
+ Global entries:
+   Address     Access  Initial Sym\.Val\. Type    Ndx Name
+  000a0010 -32736\(gp\) 00044030 00044030 FUNC    UND bar
+
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.nd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.nd	2008-08-03 13:47:24.000000000 +0100
@@ -0,0 +1,9 @@
+
+Symbol table '\.dynsym' contains .*:
+#...
+.*: 00043030 * 0 * FUNC * GLOBAL * DEFAULT * \[MIPS PLT\] * UND * foo
+# The index on the next line should correspond to MIPS_GOTSYM.
+#...
+ *7: 00044030 * 0 * FUNC * GLOBAL * DEFAULT * UND * bar
+
+#pass
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.pd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.pd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,5 @@
+
+.*
+
+Contents of section \.got\.plt:
+ 81000 00043010                            .*
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.rd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.rd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,4 @@
+
+Relocation section '\.rel\.plt' at offset .* contains .*:
+ * Offset * Info * Type * Sym\.Value * Sym\. Name
+00081000 * 0000057f * R_MIPS_JUMP_SLOT * 00043030 * foo
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.sd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.sd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,27 @@
+
+Elf file type is EXEC \(Executable file\)
+Entry point 0x44000
+There are 8 program headers, starting at offset .*
+
+Program Headers:
+ * Type * Offset * VirtAddr * PhysAddr * FileSiz * MemSiz * Flg * Align
+ * PHDR * .*
+ * INTERP * .*
+.*
+ * REGINFO * [^ ]+ * 0x0+41000 * 0x0+41000 * [^ ]+ * [^ ]+ * R * 0x.*
+ * LOAD * [^ ]+ * 0x0+40000 * 0x0+40000 [^ ]+ * [^ ]+ * R E * 0x.*
+ * LOAD * [^ ]+ * 0x0+80000 * 0x0+80000 [^ ]+ * [^ ]+ * RW  * 0x.*
+ * LOAD * [^ ]+ * 0x0+a0000 * 0x0+a0000 [^ ]+ * [^ ]+ * RW  * 0x.*
+ * DYNAMIC * [^ ]+ * 0x0+42000 * 0x0+42000 .*
+ * NULL * .*
+
+ *Section to Segment mapping:
+ *Segment Sections\.\.\.
+ *0*0 *
+ *0*1 *\.interp *
+ *0*2 *\.reginfo *
+ *0*3 *\.interp \.reginfo \.hash \.dynsym \.dynstr \.dynamic \.rel\.plt \.plt \.text \.MIPS.stubs *
+ *0*4 *\.rld_map \.got\.plt *
+ *0*5 *\.got \.data *
+ *0*6 *\.dynamic *
+ *0*7 *
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-3-error.d
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-3-error.d	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,5 @@
+#name: PIC and non-PIC test 3 (error)
+#source: pic-and-nonpic-3b.s
+#as: -EB -32 -mips2
+#ld: tmpdir/pic-and-nonpic-3a.so -melf32btsmip -znocopyreloc
+#error: .*: non-dynamic relocations refer to dynamic symbol foo
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-4a.s
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-4a.s	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,22 @@
+	.abicalls
+	.option	pic0
+	.global	obj1
+	.global	obj2
+	.global	obj3
+
+	.type	obj1,%object
+	.type	obj2,%object
+	.type	obj3,%object
+
+	.size	obj1,8
+	.size	obj2,4
+	.size	obj3,16
+
+	.data
+obj1:
+	.word	1, 2
+obj2:
+	.word	3
+obj3:
+	.word	5, 6, 7, 8
+
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.s
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.s	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,13 @@
+	.abicalls
+	.option	pic0
+	.global	__start
+	.ent	__start
+__start:
+	lui	$2,%hi(obj1)
+	addiu	$2,$2,%lo(obj1)
+	.end	__start
+	.word	obj2
+
+	.data
+	.word	obj2
+	.word	obj3
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.ld
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.ld	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,33 @@
+SECTIONS
+{
+  . = 0x40000 + SIZEOF_HEADERS;
+  .interp : { *(.interp) }
+
+  . = 0x41000;
+  .reginfo : { *(.reginfo) }
+  .hash : { *(.hash) }
+  .dynsym : { *(.dynsym) }
+  .dynstr : { *(.dynstr) }
+
+  . = 0x42000;
+  .dynamic : { *(.dynamic) }
+
+  . = 0x43000;
+  .rel.dyn : { *(.rel.dyn) }
+
+  . = 0x44000;
+  .text : { *(.text) }
+
+  . = 0x80000;
+  .rld_map : { *(.rld_map) }
+
+  . = 0xa0000;
+  _gp = . + 0x7ff0;
+  .got : { *(.got) }
+
+  . = 0xa1000;
+  .data : { *(.data) }
+
+  . = 0xa2000;
+  .bss : { *(.dynbss) }
+}
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.ad
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.ad	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,26 @@
+
+Dynamic section at offset .* contains .*:
+ * Tag * Type * Name/Value
+ 0x00000001 \(NEEDED\) .*
+ 0x00000004 \(HASH\) .*
+ 0x00000005 \(STRTAB\) .*
+ 0x00000006 \(SYMTAB\) .*
+ 0x0000000a \(STRSZ\) .*
+ 0x0000000b \(SYMENT\) .*
+ 0x70000016 \(MIPS_RLD_MAP\) * 0x80000
+ 0x00000015 \(DEBUG\) * 0x0
+ 0x00000003 \(PLTGOT\) * 0xa0000
+ 0x00000011 \(REL\) * 0x43000
+ 0x00000012 \(RELSZ\) * 32 \(bytes\)
+ 0x00000013 \(RELENT\) * 8 \(bytes\)
+ 0x70000001 \(MIPS_RLD_VERSION\) * 1
+ 0x70000005 \(MIPS_FLAGS\) * NOTPOT
+ 0x70000006 \(MIPS_BASE_ADDRESS\) * 0x40000
+# This must be the number of GOT entries - 1, the last entry being for "obj3".
+ 0x7000000a \(MIPS_LOCAL_GOTNO\) * 2
+# This must be MIPS_GOTSYM + 1.
+ 0x70000011 \(MIPS_SYMTABNO\) * 8
+ 0x70000012 \(MIPS_UNREFEXTNO\) .*
+# This must be the index of "obj3".
+ 0x70000013 \(MIPS_GOTSYM\) * 0x7
+ 0x00000000 \(NULL\) * 0x0
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.dd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.dd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,10 @@
+
+.*
+
+Disassembly of section \.text:
+
+00044000 <__start>:
+   44000:	3c02000a 	lui	v0,0xa
+   44004:	24422000 	addiu	v0,v0,8192
+   44008:	000a2008 	.*
+   4400c:	00000000 	nop
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.gd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.gd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,7 @@
+
+.*
+
+Contents of section \.got:
+ a0000 00000000 80000000 00000000           .*
+Contents of section \.data:
+ a1000 000a2008 00000000 00000000 00000000  .*
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.nd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.nd	2008-08-03 13:41:38.000000000 +0100
@@ -0,0 +1,12 @@
+
+Symbol table '\.dynsym' contains .*:
+# The order of the next two symbols is not important.
+#...
+.*: 000a2000 * 8 * OBJECT * GLOBAL * DEFAULT * [0-9]+ * obj1
+#...
+.*: 000a2008 * 4 * OBJECT * GLOBAL * DEFAULT * [0-9]+ * obj2
+# The index on the next line should correspond to MIPS_GOTSYM.
+#...
+ *7: 0+ * 0 * OBJECT * GLOBAL * DEFAULT * UND * obj3
+
+#pass
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.rd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.rd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,7 @@
+
+Relocation section '\.rel\.dyn' at offset .* contains .*:
+ * Offset * Info * Type * Sym\.Value * Sym\. Name
+00000000 * 00000000 * R_MIPS_NONE *
+000a2000 * 0000017e * R_MIPS_COPY * 000a2000 * obj1
+000a2008 * 0000047e * R_MIPS_COPY * 000a2008 * obj2
+000a1004 * 00000703 * R_MIPS_REL32 * 00000000 * obj3
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.sd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.sd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,27 @@
+
+Elf file type is EXEC \(Executable file\)
+Entry point 0x44000
+There are 8 program headers, starting at offset .*
+
+Program Headers:
+ * Type * Offset * VirtAddr * PhysAddr * FileSiz * MemSiz * Flg * Align
+ * PHDR * .*
+ * INTERP * .*
+.*
+ * REGINFO * [^ ]+ * 0x0+41000 * 0x0+41000 * [^ ]+ * [^ ]+ * R * 0x.*
+ * LOAD * [^ ]+ * 0x0+40000 * 0x0+40000 [^ ]+ * [^ ]+ * R E * 0x.*
+ * LOAD * [^ ]+ * 0x0+80000 * 0x0+80000 [^ ]+ * [^ ]+ * RW  * 0x.*
+ * LOAD * [^ ]+ * 0x0+a0000 * 0x0+a0000 [^ ]+ * [^ ]+ * RW  * 0x.*
+ * DYNAMIC * [^ ]+ * 0x0+42000 * 0x0+42000 .*
+ * NULL * .*
+
+ *Section to Segment mapping:
+ *Segment Sections\.\.\.
+ *0*0 *
+ *0*1 * \.interp *
+ *0*2 * \.reginfo *
+ *0*3 * \.interp \.reginfo \.hash \.dynsym \.dynstr \.dynamic \.rel\.dyn \.text *
+ *0*4 * \.rld_map *
+ *0*5 * \.got \.data \.bss *
+ *0*6 * \.dynamic *
+ *0*7 *
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-4-error.d
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-4-error.d	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,5 @@
+#name: PIC and non-PIC test 4 (error)
+#source: pic-and-nonpic-4b.s
+#as: -EB -32 -mips2
+#ld: tmpdir/pic-and-nonpic-4a.so -melf32btsmip -znocopyreloc
+#error: .*: non-dynamic relocations refer to dynamic symbol obj1
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-5a.s
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-5a.s	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,16 @@
+	.abicalls
+	.option	pic0
+	.global	__start
+	.ent	__start
+__start:
+	lui	$2,%hi(foo)
+	addiu	$2,$2,%lo(foo)
+	lui	$2,%hi(obj1)
+	addiu	$2,$2,%lo(obj1)
+	.end	__start
+
+	.data
+	.word	foo
+	.word	bar
+	.word	obj1
+	.word	obj2
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.s
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.s	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,9 @@
+	.abicalls
+	.global	ext
+	.ent	ext
+ext:
+	.word	foo
+	.word	bar
+	.word	obj1
+	.word	obj2
+	.end	ext
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.ld
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.ld	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,38 @@
+SECTIONS
+{
+  . = 0x40000 + SIZEOF_HEADERS;
+  .interp : { *(.interp) }
+
+  . = 0x41000;
+  .reginfo : { *(.reginfo) }
+  .hash : { *(.hash) }
+  .dynsym : { *(.dynsym) }
+  .dynstr : { *(.dynstr) }
+
+  . = 0x42000;
+  .dynamic : { *(.dynamic) }
+
+  . = 0x43000;
+  .rel.dyn : { *(.rel.dyn) }
+  .rel.plt : { *(.rel.plt) }
+  .plt : { *(.plt) }
+
+  . = 0x44000;
+  .text : { *(.text) }
+
+  . = 0x80000;
+  .rld_map : { *(.rld_map) }
+
+  . = 0x81000;
+  .got.plt : { *(.got.plt) }
+
+  . = 0xa0000;
+  _gp = . + 0x7ff0;
+  .got : { *(.got) }
+
+  . = 0xa1000;
+  .data : { *(.data) }
+
+  . = 0xa2000;
+  .bss : { *(.dynbss) }
+}
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.ad
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.ad	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,31 @@
+
+Dynamic section at offset .* contains .*:
+ * Tag * Type * Name/Value
+ 0x00000001 \(NEEDED\) .*
+ 0x00000001 \(NEEDED\) .*
+ 0x00000004 \(HASH\) .*
+ 0x00000005 \(STRTAB\) .*
+ 0x00000006 \(SYMTAB\) .*
+ 0x0000000a \(STRSZ\) .*
+ 0x0000000b \(SYMENT\) .*
+ 0x70000016 \(MIPS_RLD_MAP\) * 0x80000
+ 0x00000015 \(DEBUG\) * 0x0
+ 0x00000016 \(TEXTREL\) * 0x0
+ 0x00000003 \(PLTGOT\) * 0xa0000
+ 0x00000011 \(REL\) * 0x43000
+ 0x00000012 \(RELSZ\) * 48 \(bytes\)
+ 0x00000013 \(RELENT\) * 8 \(bytes\)
+ 0x70000001 \(MIPS_RLD_VERSION\) * 1
+ 0x70000005 \(MIPS_FLAGS\) * NOTPOT
+ 0x70000006 \(MIPS_BASE_ADDRESS\) * 0x40000
+# This must be the number of GOT entries - 2.  The last two entries are
+# for "bar" and "obj2".
+ 0x7000000a \(MIPS_LOCAL_GOTNO\) * 3
+# This must be MIPS_GOTSYM + 2.
+ 0x70000011 \(MIPS_SYMTABNO\) * 10
+ 0x70000012 \(MIPS_UNREFEXTNO\) * .*
+ 0x70000013 \(MIPS_GOTSYM\) * 0x8
+ 0x00000014 \(PLTREL\) * REL
+ 0x00000017 \(JMPREL\) * 0x43030
+ 0x00000002 \(PLTRELSZ\) * 8 \(bytes\)
+ 0x00000000 \(NULL\) * 0x0
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.dd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.dd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,32 @@
+
+.*
+
+Disassembly of section \.plt:
+
+00043040 <.*>:
+   43040:	3c0f000a 	lui	t7,0xa
+   43044:	8df90008 	lw	t9,8\(t7\)
+   43048:	25ef0008 	addiu	t7,t7,8
+   4304c:	3c0e0008 	lui	t6,0x8
+   43050:	03200008 	jr	t9
+   43054:	25ce1000 	addiu	t6,t6,4096
+	...
+
+00043060 <foo@plt>:
+   43060:	3c180008 	lui	t8,0x8
+   43064:	8f191000 	lw	t9,4096\(t8\)
+   43068:	03200008 	jr	t9
+   4306c:	27181000 	addiu	t8,t8,4096
+Disassembly of section .text:
+
+00044000 <__start>:
+   44000:	3c020004 	lui	v0,0x4
+   44004:	24423060 	addiu	v0,v0,12384
+   44008:	3c02000a 	lui	v0,0xa
+   4400c:	24422000 	addiu	v0,v0,8192
+
+00044010 <ext>:
+   44010:	00043060 	.*
+   44014:	00000000 	.*
+   44018:	000a2000 	.*
+   4401c:	00000000 	.*
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.gd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.gd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,16 @@
+
+Primary GOT:
+ Canonical gp value: 000a7ff0
+
+ Reserved entries:
+   Address     Access  Initial Purpose
+  000a0000 -32752\(gp\) 00000000 Lazy resolver
+  000a0004 -32748\(gp\) 80000000 Module pointer \(GNU extension\)
+  000a0008 -32744\(gp\) 00000000 PLT lazy resolver \(GNU extension\)
+
+# There must be GOT entries for the R_MIPS_REL32 relocation symbols.
+ Global entries:
+   Address     Access  Initial Sym\.Val\. Type    Ndx Name
+  000a000c -32740\(gp\) 00000000 00000000 OBJECT  UND obj2
+  000a0010 -32736\(gp\) 00000000 00000000 FUNC    UND bar
+
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.nd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.nd	2008-08-03 13:48:13.000000000 +0100
@@ -0,0 +1,10 @@
+
+Symbol table '\.dynsym' contains .*:
+#...
+.*: 00043060 * 0 * FUNC * GLOBAL * DEFAULT * \[MIPS PLT\] * UND * foo
+# The index on the next line should correspond to MIPS_GOTSYM.
+#...
+ *8: 0+ * 0 * OBJECT * GLOBAL * DEFAULT * UND * obj2
+ *9: 0+ * 0 * FUNC * GLOBAL * DEFAULT * UND * bar
+
+#pass
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.rd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.rd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,13 @@
+
+Relocation section '\.rel\.dyn' at offset .* contains .*:
+ * Offset * Info * Type * Sym\.Value * Sym\. Name
+00000000 * 00000000 * R_MIPS_NONE *
+000a2000 * [^ ]*7e * R_MIPS_COPY * 000a2000 * obj1
+0004401c * [^ ]*03 * R_MIPS_REL32 * 00000000 * obj2
+000a100c * [^ ]*03 * R_MIPS_REL32 * 00000000 * obj2
+00044014 * [^ ]*03 * R_MIPS_REL32 * 00000000 * bar
+000a1004 * [^ ]*03 * R_MIPS_REL32 * 00000000 * bar
+
+Relocation section '\.rel\.plt' at offset .* contains .*:
+ * Offset * Info * Type * Sym\.Value * Sym\. Name
+00081000 * [^ ]*7f * R_MIPS_JUMP_SLOT * 00043060 * foo
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.sd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.sd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,27 @@
+
+Elf file type is EXEC \(Executable file\)
+Entry point 0x44000
+There are 8 program headers, starting at offset .*
+
+Program Headers:
+ * Type * Offset * VirtAddr * PhysAddr * FileSiz * MemSiz * Flg * Align
+ * PHDR * .*
+ * INTERP * .*
+.*
+ * REGINFO * [^ ]+ * 0x0+41000 * 0x0+41000 * [^ ]+ * [^ ]+ * R * 0x.*
+ * LOAD * [^ ]+ * 0x0+40000 * 0x0+40000 [^ ]+ * [^ ]+ * R E * 0x.*
+ * LOAD * [^ ]+ * 0x0+80000 * 0x0+80000 [^ ]+ * [^ ]+ * RW  * 0x.*
+ * LOAD * [^ ]+ * 0x0+a0000 * 0x0+a0000 [^ ]+ * [^ ]+ * RW  * 0x.*
+ * DYNAMIC * [^ ]+ * 0x0+42000 * 0x0+42000 .*
+ * NULL * .*
+
+ *Section to Segment mapping:
+ *Segment Sections\.\.\.
+ *0*0 *
+ *0*1 * \.interp *
+ *0*2 * \.reginfo *
+ *0*3 * \.interp \.reginfo \.hash \.dynsym \.dynstr \.dynamic \.rel\.dyn \.rel\.plt \.plt \.text *
+ *0*4 * \.rld_map \.got\.plt *
+ *0*5 * \.got \.data \.bss *
+ *0*6 * \.dynamic *
+ *0*7 *
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.pd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.pd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,7 @@
+
+.*
+
+Contents of section \.got\.plt:
+ 81000 00043040                             .*
+Contents of section \.data:
+ a1000 00043060 00000000 000a2000 00000000  .*
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6.ld
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6.ld	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,40 @@
+SECTIONS
+{
+  . = 0x40000 + SIZEOF_HEADERS;
+  .interp : { *(.interp) }
+
+  . = 0x41000;
+  .reginfo : { *(.reginfo) }
+  .hash : { *(.hash) }
+  .dynsym : { *(.dynsym) }
+  .dynstr : { *(.dynstr) }
+
+  . = 0x42000;
+  .dynamic : { *(.dynamic) }
+
+  . = 0x43000;
+  .rel.dyn : { *(.rel.dyn) }
+  .rel.plt : { *(.rel.plt) }
+  .plt : { *(.plt) }
+
+  . = 0x44000;
+  .text : { *(.text) }
+  .MIPS.stubs : { *(.MIPS.stubs) }
+  .MIPS.options : { *(.MIPS.options) }
+
+  . = 0x80000;
+  .rld_map : { *(.rld_map) }
+
+  . = 0x81000;
+  .got.plt : { *(.got.plt) }
+
+  . = 0xa0000;
+  _gp = . + 0x7ff0;
+  .got : { *(.got) }
+
+  . = 0xa1000;
+  .data : { *(.data) }
+
+  . = 0xa2000;
+  .bss : { *(.dynbss) }
+}
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32a.s
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32a.s	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,48 @@
+	.abicalls
+	.global	extf1
+	.ent	extf1
+extf1:
+	jr	$31
+	.end	extf1
+
+	.global	extf2
+	.ent	extf2
+extf2:
+	jr	$31
+	.end	extf2
+
+	.global	extf3
+	.ent	extf3
+extf3:
+	jr	$31
+	.end	extf3
+
+	.global	extf4
+	.ent	extf4
+extf4:
+	jr	$31
+	.end	extf4
+
+	.global	extf5
+	.ent	extf5
+extf5:
+	jr	$31
+	.end	extf5
+
+	.data
+	.global	extd1
+	.global	extd2
+	.global	extd3
+	.global	extd4
+	.type	extd1,%object
+	.type	extd2,%object
+	.type	extd3,%object
+	.type	extd4,%object
+	.size	extd1,20
+	.size	extd2,24
+	.size	extd3,28
+	.size	extd4,8
+extd1:	.space	20
+extd2:	.space	24
+extd3:	.space	28
+extd4:	.space	8
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32b.s
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32b.s	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,37 @@
+	.set	noreorder
+	.abicalls
+	.global	f1
+	.ent	f1
+f1:
+	.option	pic0
+	jal	f3
+	.option	pic2
+	lui	$2,%hi(f2)
+	jr	$31
+	addiu	$2,$2,%lo(f2)
+	.end	f1
+
+	.global	f2
+	.ent	f2
+f2:
+	.cpload	$25
+	lw	$25,%call16(extf1)($28)
+	lw	$4,%got(extf2)($28)
+	lw	$5,%got(extd1)($28)
+	jalr	$25
+	lw	$6,%got(extd2)($28)
+	lw	$25,%call16(extf3)($28)
+	jr	$25
+	lw	$4,%got(extf4)($28)
+	.end	f2
+
+	.global	f3
+	.ent	f3
+f3:
+	jr	$31
+	nop
+	.end	f3
+
+	.data
+	.word	extd1
+	.word	extd3
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32c.s
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32c.s	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,25 @@
+	.abicalls
+	.option	pic0
+	.set	noreorder
+	.global	__start
+	.ent	__start
+__start:
+	jal	f1
+	nop
+	lui	$2,%hi(f2)
+	addiu	$2,$2,%lo(f2)
+	jal	extf3
+	nop
+	jal	extf4
+	nop
+	jal	extf5
+	nop
+	lui	$2,%hi(extd2)
+	addiu	$2,$2,%lo(extd2)
+	lui	$2,%hi(extd3)
+	addiu	$2,$2,%lo(extd3)
+	.end	__start
+
+	.data
+	.word	extd2
+	.word	extd4
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.ad
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.ad	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,26 @@
+
+Dynamic section at offset .* contains .*:
+ * Tag * Type * Name/Value
+ 0x00000001 \(NEEDED\) .*
+ 0x00000004 \(HASH\) .*
+ 0x00000005 \(STRTAB\) .*
+ 0x00000006 \(SYMTAB\) .*
+ 0x0000000a \(STRSZ\) .*
+ 0x0000000b \(SYMENT\) .*
+ 0x70000016 \(MIPS_RLD_MAP\) * 0x80000
+ 0x00000015 \(DEBUG\) * 0x0
+ 0x00000003 \(PLTGOT\) * 0xa0000
+ 0x00000011 \(REL\) * 0x43000
+ 0x00000012 \(RELSZ\) * 40 \(bytes\)
+ 0x00000013 \(RELENT\) * 8 \(bytes\)
+ 0x70000001 \(MIPS_RLD_VERSION\) * 1
+ 0x70000005 \(MIPS_FLAGS\) * NOTPOT
+ 0x70000006 \(MIPS_BASE_ADDRESS\) * 0x40000
+ 0x7000000a \(MIPS_LOCAL_GOTNO\) * 3
+ 0x70000011 \(MIPS_SYMTABNO\) * 14
+ 0x70000012 \(MIPS_UNREFEXTNO\) * .*
+ 0x70000013 \(MIPS_GOTSYM\) * 0x7
+ 0x00000014 \(PLTREL\) * REL
+ 0x00000017 \(JMPREL\) * 0x43028
+ 0x00000002 \(PLTRELSZ\) * 24 \(bytes\)
+ 0x00000000 \(NULL\) * 0x0
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.dd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.dd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,102 @@
+# GOT layout:
+#
+# -32752: lazy resolution function
+# -32748: reserved for module pointer
+# -32744: PLT resolution function
+# -32740 ... -32724: useless local GOT entries (fixed on mainline)
+# -32720: extf2's GOT entry (undefined 0)
+# -32716: extf3's GOT entry (PLT entry)
+# -32712: extd2's GOT entry (copy reloc)
+# -32708: extf1's GOT entry (.MIPS.stubs entry)
+# -32704: extd1's GOT entry (undefined 0)
+# -32700: extf4's GOT entry (PLT entry)
+# -32696: extd4's GOT entry (undefined 0, reloc only)
+
+.*
+
+Disassembly of section \.plt:
+
+00043040 <.*>:
+   43040:	3c0f000a 	lui	t7,0xa
+   43044:	8df90008 	lw	t9,8\(t7\)
+   43048:	25ef0008 	addiu	t7,t7,8
+   4304c:	3c0e0008 	lui	t6,0x8
+   43050:	03200008 	jr	t9
+   43054:	25ce1000 	addiu	t6,t6,4096
+	\.\.\.
+
+00043060 <extf4@plt>:
+   43060:	3c180008 	lui	t8,0x8
+   43064:	8f191000 	lw	t9,4096\(t8\)
+   43068:	03200008 	jr	t9
+   4306c:	27181000 	addiu	t8,t8,4096
+
+00043070 <extf5@plt>:
+   43070:	3c180008 	lui	t8,0x8
+   43074:	8f191004 	lw	t9,4100\(t8\)
+   43078:	03200008 	jr	t9
+   4307c:	27181004 	addiu	t8,t8,4100
+
+00043080 <extf3@plt>:
+   43080:	3c180008 	lui	t8,0x8
+   43084:	8f191008 	lw	t9,4104\(t8\)
+   43088:	03200008 	jr	t9
+   4308c:	27181008 	addiu	t8,t8,4104
+Disassembly of section \.text:
+
+00044000 <f2>:
+   44000:	3c190004 	lui	t9,0x4
+   44004:	0801100c 	j	44030 <\.pic\.f2>
+   44008:	27394030 	addiu	t9,t9,16432
+	\.\.\.
+
+00044018 <f1>:
+   44018:	3c190004 	lui	t9,0x4
+   4401c:	27394020 	addiu	t9,t9,16416
+   44020:	0c011017 	jal	4405c <f3>
+   44024:	3c020004 	lui	v0,0x4
+   44028:	03e00008 	jr	ra
+   4402c:	24424000 	addiu	v0,v0,16384
+
+00044030 <\.pic\.f2>:
+   44030:	3c1c0006 	lui	gp,0x6
+   44034:	279c3fc0 	addiu	gp,gp,16320
+   44038:	0399e021 	addu	gp,gp,t9
+   4403c:	8f998028 	lw	t9,-32728\(gp\)
+   44040:	8f84801c 	lw	a0,-32740\(gp\)
+   44044:	8f85802c 	lw	a1,-32724\(gp\)
+   44048:	0320f809 	jalr	t9
+   4404c:	8f868024 	lw	a2,-32732\(gp\)
+   44050:	8f998020 	lw	t9,-32736\(gp\)
+   44054:	03200008 	jr	t9
+   44058:	8f848030 	lw	a0,-32720\(gp\)
+
+0004405c <f3>:
+   4405c:	03e00008 	jr	ra
+   44060:	00000000 	nop
+	\.\.\.
+
+00044070 <__start>:
+   44070:	0c011006 	jal	44018 <f1>
+   44074:	00000000 	nop
+   44078:	3c020004 	lui	v0,0x4
+   4407c:	24424000 	addiu	v0,v0,16384
+   44080:	0c010c20 	jal	43080 <extf3@plt>
+   44084:	00000000 	nop
+   44088:	0c010c18 	jal	43060 <extf4@plt>
+   4408c:	00000000 	nop
+   44090:	0c010c1c 	jal	43070 <extf5@plt>
+   44094:	00000000 	nop
+   44098:	3c02000a 	lui	v0,0xa
+   4409c:	24422000 	addiu	v0,v0,8192
+   440a0:	3c02000a 	lui	v0,0xa
+   440a4:	24422018 	addiu	v0,v0,8216
+	\.\.\.
+Disassembly of section \.MIPS\.stubs:
+
+000440b0 <\.MIPS\.stubs>:
+   440b0:	8f998010 	lw	t9,-32752\(gp\)
+   440b4:	03e07821 	move	t7,ra
+   440b8:	0320f809 	jalr	t9
+   440bc:	2418000a 	li	t8,10
+	\.\.\.
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.gd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.gd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,20 @@
+
+Primary GOT:
+ Canonical gp value: 000a7ff0
+
+ Reserved entries:
+   Address     Access  Initial Purpose
+  000a0000 -32752\(gp\) 00000000 Lazy resolver
+  000a0004 -32748\(gp\) 80000000 Module pointer \(GNU extension\)
+  000a0008 -32744\(gp\) 00000000 PLT lazy resolver \(GNU extension\)
+
+ Global entries:
+   Address     Access  Initial Sym\.Val\. Type    Ndx Name
+  000a000c -32740\(gp\) 00000000 00000000 FUNC    UND extf2
+  000a0010 -32736\(gp\) 00043080 00043080 FUNC    UND extf3
+  000a0014 -32732\(gp\) 000a2000 000a2000 OBJECT   16 extd2
+  000a0018 -32728\(gp\) 000440b0 000440b0 FUNC    UND extf1
+  000a001c -32724\(gp\) 00000000 00000000 OBJECT  UND extd1
+  000a0020 -32720\(gp\) 00043060 00043060 FUNC    UND extf4
+  000a0024 -32716\(gp\) 00000000 00000000 OBJECT  UND extd4
+
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.nd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.nd	2008-08-03 13:49:33.000000000 +0100
@@ -0,0 +1,17 @@
+
+Symbol table '\.dynsym' contains .*:
+#...
+.*: 00043070 * 0 * FUNC * GLOBAL * DEFAULT * \[MIPS PLT\] * UND * extf5
+# The index on the next line should correspond to MIPS_GOTSYM,
+# and the remaining symbols should have the same order as the
+# GOT layout given in the *.dd dump.
+#...
+ *7: 0+ * 0 * FUNC * GLOBAL * DEFAULT * UND * extf2
+ *8: 0+43080 * 0 * FUNC * GLOBAL * DEFAULT \[MIPS PLT\] * UND * extf3
+ *9: 0+a2000 * 24 * OBJECT * GLOBAL * DEFAULT * [0-9]+ * extd2
+ *10: 0+440b0 * 0 * FUNC * GLOBAL * DEFAULT * UND * extf1
+ *11: 0+ * 0 * OBJECT * GLOBAL * DEFAULT * UND * extd1
+ *12: 0+43060 * 0 * FUNC * GLOBAL * DEFAULT \[MIPS PLT\] * UND * extf4
+ *13: 0+ * 0 * OBJECT * GLOBAL * DEFAULT * UND * extd4
+
+#pass
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.pd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.pd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,5 @@
+
+.*
+
+Contents of section \.got\.plt:
+ 81000 00043040 00043040 00043040           .*
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.rd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.rd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,14 @@
+
+Relocation section '\.rel\.dyn' at offset .* contains .*:
+ * Offset * Info * Type * Sym\.Value * Sym\. Name
+00000000 * 00000000 * R_MIPS_NONE *
+000a2018 * [^ ]*7e * R_MIPS_COPY * 000a2018 * extd3
+000a2000 * [^ ]*7e * R_MIPS_COPY * 000a2000 * extd2
+000a1000 * [^ ]*03 * R_MIPS_REL32 * 00000000 * extd1
+000a1014 * [^ ]*03 * R_MIPS_REL32 * 00000000 * extd4
+
+Relocation section '\.rel\.plt' at offset .* contains .*:
+ * Offset * Info * Type * Sym\.Value * Sym\. Name
+00081000 * [^ ]*7f * R_MIPS_JUMP_SLOT * 00043060 * extf4
+00081004 * [^ ]*7f * R_MIPS_JUMP_SLOT * 00043070 * extf5
+00081008 * [^ ]*7f * R_MIPS_JUMP_SLOT * 00043080 * extf3
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.sd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.sd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,27 @@
+
+Elf file type is EXEC \(Executable file\)
+Entry point 0x44000
+There are 8 program headers, starting at offset .*
+
+Program Headers:
+ * Type * Offset * VirtAddr * PhysAddr * FileSiz * MemSiz * Flg * Align
+ * PHDR * .*
+ * INTERP * .*
+.*
+ * REGINFO * [^ ]+ * 0x0+41000 * 0x0+41000 * [^ ]+ * [^ ]+ * R * 0x.*
+ * LOAD * [^ ]+ * 0x0+40000 * 0x0+40000 [^ ]+ * [^ ]+ * R E * 0x.*
+ * LOAD * [^ ]+ * 0x0+80000 * 0x0+80000 [^ ]+ * [^ ]+ * RW  * 0x.*
+ * LOAD * [^ ]+ * 0x0+a0000 * 0x0+a0000 [^ ]+ * [^ ]+ * RW  * 0x.*
+ * DYNAMIC * [^ ]+ * 0x0+42000 * 0x0+42000 .*
+ * NULL * .*
+
+ *Section to Segment mapping:
+ *Segment Sections\.\.\.
+ *0*0 *
+ *0*1 * \.interp *
+ *0*2 * \.reginfo *
+ *0*3 * \.interp \.reginfo \.hash \.dynsym \.dynstr \.dynamic \.rel\.dyn \.rel\.plt \.plt \.text \.MIPS\.stubs *
+ *0*4 * \.rld_map \.got\.plt *
+ *0*5 * \.got \.data \.bss *
+ *0*6 * \.dynamic *
+ *0*7 *
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32a.s
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32a.s	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,48 @@
+	.abicalls
+	.global	extf1
+	.ent	extf1
+extf1:
+	jr	$31
+	.end	extf1
+
+	.global	extf2
+	.ent	extf2
+extf2:
+	jr	$31
+	.end	extf2
+
+	.global	extf3
+	.ent	extf3
+extf3:
+	jr	$31
+	.end	extf3
+
+	.global	extf4
+	.ent	extf4
+extf4:
+	jr	$31
+	.end	extf4
+
+	.global	extf5
+	.ent	extf5
+extf5:
+	jr	$31
+	.end	extf5
+
+	.data
+	.global	extd1
+	.global	extd2
+	.global	extd3
+	.global	extd4
+	.type	extd1,%object
+	.type	extd2,%object
+	.type	extd3,%object
+	.type	extd4,%object
+	.size	extd1,20
+	.size	extd2,24
+	.size	extd3,28
+	.size	extd4,8
+extd1:	.space	20
+extd2:	.space	24
+extd3:	.space	28
+extd4:	.space	8
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32b.s
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32b.s	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,39 @@
+	.set	noreorder
+	.abicalls
+	.global	f1
+	.ent	f1
+f1:
+	.option	pic0
+	jal	f3
+	.option	pic2
+	lui	$2,%hi(f2)
+	jr	$31
+	addiu	$2,$2,%lo(f2)
+	.end	f1
+
+	.global	f2
+	.ent	f2
+f2:
+	lui	$28,%hi(%neg(%gp_rel(f2)))
+	addu	$28,$28,$25
+	addiu	$28,$28,%lo(%neg(%gp_rel(f2)))
+	lw	$25,%call16(extf1)($28)
+	lw	$4,%got_disp(extf2)($28)
+	lw	$5,%got_disp(extd1)($28)
+	jalr	$25
+	lw	$6,%got_disp(extd2)($28)
+	lw	$25,%call16(extf3)($28)
+	jr	$25
+	lw	$4,%got_disp(extf4)($28)
+	.end	f2
+
+	.global	f3
+	.ent	f3
+f3:
+	jr	$31
+	nop
+	.end	f3
+
+	.data
+	.word	extd1
+	.word	extd3
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32c.s
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32c.s	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,25 @@
+	.abicalls
+	.option	pic0
+	.set	noreorder
+	.global	__start
+	.ent	__start
+__start:
+	jal	f1
+	nop
+	lui	$2,%hi(f2)
+	addiu	$2,$2,%lo(f2)
+	jal	extf3
+	nop
+	jal	extf4
+	nop
+	jal	extf5
+	nop
+	lui	$2,%hi(extd2)
+	addiu	$2,$2,%lo(extd2)
+	lui	$2,%hi(extd3)
+	addiu	$2,$2,%lo(extd3)
+	.end	__start
+
+	.data
+	.word	extd2
+	.word	extd4
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.ad
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.ad	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,26 @@
+
+Dynamic section at offset .* contains .*:
+ * Tag * Type * Name/Value
+ 0x00000001 \(NEEDED\) .*
+ 0x00000004 \(HASH\) .*
+ 0x00000005 \(STRTAB\) .*
+ 0x00000006 \(SYMTAB\) .*
+ 0x0000000a \(STRSZ\) .*
+ 0x0000000b \(SYMENT\) .*
+ 0x70000016 \(MIPS_RLD_MAP\) * 0x80000
+ 0x00000015 \(DEBUG\) * 0x0
+ 0x00000003 \(PLTGOT\) * 0xa0000
+ 0x00000011 \(REL\) * 0x43000
+ 0x00000012 \(RELSZ\) * 40 \(bytes\)
+ 0x00000013 \(RELENT\) * 8 \(bytes\)
+ 0x70000001 \(MIPS_RLD_VERSION\) * 1
+ 0x70000005 \(MIPS_FLAGS\) * NOTPOT
+ 0x70000006 \(MIPS_BASE_ADDRESS\) * 0x40000
+ 0x7000000a \(MIPS_LOCAL_GOTNO\) * 3
+ 0x70000011 \(MIPS_SYMTABNO\) * 14
+ 0x70000012 \(MIPS_UNREFEXTNO\) * .*
+ 0x70000013 \(MIPS_GOTSYM\) * 0x7
+ 0x00000014 \(PLTREL\) * REL
+ 0x00000017 \(JMPREL\) * 0x43028
+ 0x00000002 \(PLTRELSZ\) * 24 \(bytes\)
+ 0x00000000 \(NULL\) * 0x0
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.dd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.dd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,102 @@
+# GOT layout:
+#
+# -32752: lazy resolution function
+# -32748: reserved for module pointer
+# -32744: PLT resolution function
+# -32740 ... -32724: useless local GOT entries (fixed on mainline)
+# -32720: extf2's GOT entry (undefined 0)
+# -32716: extf3's GOT entry (PLT entry)
+# -32712: extd2's GOT entry (copy reloc)
+# -32708: extf1's GOT entry (.MIPS.stubs entry)
+# -32704: extd1's GOT entry (undefined 0)
+# -32700: extf4's GOT entry (PLT entry)
+# -32696: extd4's GOT entry (undefined 0, reloc only)
+
+.*
+
+Disassembly of section \.plt:
+
+00043040 <.*>:
+   43040:	3c0f000a 	lui	t3,0xa
+   43044:	8df90008 	lw	t9,8\(t3\)
+   43048:	25ef0008 	addiu	t3,t3,8
+   4304c:	3c0e0008 	lui	t2,0x8
+   43050:	03200008 	jr	t9
+   43054:	25ce1000 	addiu	t2,t2,4096
+	\.\.\.
+
+00043060 <extf4@plt>:
+   43060:	3c180008 	lui	t8,0x8
+   43064:	8f191000 	lw	t9,4096\(t8\)
+   43068:	03200008 	jr	t9
+   4306c:	27181000 	addiu	t8,t8,4096
+
+00043070 <extf5@plt>:
+   43070:	3c180008 	lui	t8,0x8
+   43074:	8f191004 	lw	t9,4100\(t8\)
+   43078:	03200008 	jr	t9
+   4307c:	27181004 	addiu	t8,t8,4100
+
+00043080 <extf3@plt>:
+   43080:	3c180008 	lui	t8,0x8
+   43084:	8f191008 	lw	t9,4104\(t8\)
+   43088:	03200008 	jr	t9
+   4308c:	27181008 	addiu	t8,t8,4104
+Disassembly of section \.text:
+
+00044000 <f2>:
+   44000:	3c190004 	lui	t9,0x4
+   44004:	0801100c 	j	44030 <\.pic\.f2>
+   44008:	27394030 	addiu	t9,t9,16432
+	\.\.\.
+
+00044018 <f1>:
+   44018:	3c190004 	lui	t9,0x4
+   4401c:	27394020 	addiu	t9,t9,16416
+   44020:	0c011017 	jal	4405c <f3>
+   44024:	3c020004 	lui	v0,0x4
+   44028:	03e00008 	jr	ra
+   4402c:	24424000 	addiu	v0,v0,16384
+
+00044030 <\.pic\.f2>:
+   44030:	3c1c0006 	lui	gp,0x6
+   44034:	0399e021 	addu	gp,gp,t9
+   44038:	279c3fc0 	addiu	gp,gp,16320
+   4403c:	8f998028 	lw	t9,-32728\(gp\)
+   44040:	8f84801c 	lw	a0,-32740\(gp\)
+   44044:	8f85802c 	lw	a1,-32724\(gp\)
+   44048:	0320f809 	jalr	t9
+   4404c:	8f868024 	lw	a2,-32732\(gp\)
+   44050:	8f998020 	lw	t9,-32736\(gp\)
+   44054:	03200008 	jr	t9
+   44058:	8f848030 	lw	a0,-32720\(gp\)
+
+0004405c <f3>:
+   4405c:	03e00008 	jr	ra
+   44060:	00000000 	nop
+	\.\.\.
+
+00044070 <__start>:
+   44070:	0c011006 	jal	44018 <f1>
+   44074:	00000000 	nop
+   44078:	3c020004 	lui	v0,0x4
+   4407c:	24424000 	addiu	v0,v0,16384
+   44080:	0c010c20 	jal	43080 <extf3@plt>
+   44084:	00000000 	nop
+   44088:	0c010c18 	jal	43060 <extf4@plt>
+   4408c:	00000000 	nop
+   44090:	0c010c1c 	jal	43070 <extf5@plt>
+   44094:	00000000 	nop
+   44098:	3c02000a 	lui	v0,0xa
+   4409c:	24422000 	addiu	v0,v0,8192
+   440a0:	3c02000a 	lui	v0,0xa
+   440a4:	24422018 	addiu	v0,v0,8216
+	\.\.\.
+Disassembly of section \.MIPS\.stubs:
+
+000440b0 <\.MIPS\.stubs>:
+   440b0:	8f998010 	lw	t9,-32752\(gp\)
+   440b4:	03e07821 	move	t3,ra
+   440b8:	0320f809 	jalr	t9
+   440bc:	2418000a 	li	t8,10
+	\.\.\.
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.gd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.gd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,20 @@
+
+Primary GOT:
+ Canonical gp value: 000a7ff0
+
+ Reserved entries:
+   Address     Access  Initial Purpose
+  000a0000 -32752\(gp\) 00000000 Lazy resolver
+  000a0004 -32748\(gp\) 80000000 Module pointer \(GNU extension\)
+  000a0008 -32744\(gp\) 00000000 PLT lazy resolver \(GNU extension\)
+
+ Global entries:
+   Address     Access  Initial Sym\.Val\. Type    Ndx Name
+  000a000c -32740\(gp\) 00000000 00000000 FUNC    UND extf2
+  000a0010 -32736\(gp\) 00043080 00043080 FUNC    UND extf3
+  000a0014 -32732\(gp\) 000a2000 000a2000 OBJECT   16 extd2
+  000a0018 -32728\(gp\) 000440b0 000440b0 FUNC    UND extf1
+  000a001c -32724\(gp\) 00000000 00000000 OBJECT  UND extd1
+  000a0020 -32720\(gp\) 00043060 00043060 FUNC    UND extf4
+  000a0024 -32716\(gp\) 00000000 00000000 OBJECT  UND extd4
+
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.nd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.nd	2008-08-03 13:48:43.000000000 +0100
@@ -0,0 +1,17 @@
+
+Symbol table '\.dynsym' contains .*:
+#...
+.*: 00043070 * 0 * FUNC * GLOBAL * DEFAULT * \[MIPS PLT\] * UND * extf5
+# The index on the next line should correspond to MIPS_GOTSYM,
+# and the remaining symbols should have the same order as the
+# GOT layout given in the *.dd dump.
+#...
+ *7: 0+ * 0 * FUNC * GLOBAL * DEFAULT * UND * extf2
+ *8: 0+43080 * 0 * * FUNC * GLOBAL * DEFAULT \[MIPS PLT\] * UND * extf3
+ *9: 0+a2000 * 24 * OBJECT * GLOBAL * DEFAULT * [0-9]+ * extd2
+ *10: 0+440b0 * 0 * FUNC * GLOBAL * DEFAULT * UND * extf1
+ *11: 0+ * 0 * OBJECT * GLOBAL * DEFAULT * UND * extd1
+ *12: 0+43060 * 0 * FUNC * GLOBAL * DEFAULT \[MIPS PLT\] * UND * extf4
+ *13: 0+ * 0 * OBJECT * GLOBAL * DEFAULT * UND * extd4
+
+#pass
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.pd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.pd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,5 @@
+
+.*
+
+Contents of section \.got\.plt:
+ 81000 00043040 00043040 00043040           .*
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.rd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.rd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,14 @@
+
+Relocation section '\.rel\.dyn' at offset .* contains .*:
+ * Offset * Info * Type * Sym\.Value * Sym\. Name
+00000000 * 00000000 * R_MIPS_NONE *
+000a2018 * [^ ]*7e * R_MIPS_COPY * 000a2018 * extd3
+000a2000 * [^ ]*7e * R_MIPS_COPY * 000a2000 * extd2
+000a1000 * [^ ]*03 * R_MIPS_REL32 * 00000000 * extd1
+000a1014 * [^ ]*03 * R_MIPS_REL32 * 00000000 * extd4
+
+Relocation section '\.rel\.plt' at offset .* contains .*:
+ * Offset * Info * Type * Sym\.Value * Sym\. Name
+00081000 * [^ ]*7f * R_MIPS_JUMP_SLOT * 00043060 * extf4
+00081004 * [^ ]*7f * R_MIPS_JUMP_SLOT * 00043070 * extf5
+00081008 * [^ ]*7f * R_MIPS_JUMP_SLOT * 00043080 * extf3
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.sd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.sd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,27 @@
+
+Elf file type is EXEC \(Executable file\)
+Entry point 0x44000
+There are 8 program headers, starting at offset .*
+
+Program Headers:
+ * Type * Offset * VirtAddr * PhysAddr * FileSiz * MemSiz * Flg * Align
+ * PHDR * .*
+ * INTERP * .*
+.*
+ * REGINFO * [^ ]+ * 0x0+41000 * 0x0+41000 * [^ ]+ * [^ ]+ * R * 0x.*
+ * LOAD * [^ ]+ * 0x0+40000 * 0x0+40000 [^ ]+ * [^ ]+ * R E * 0x.*
+ * LOAD * [^ ]+ * 0x0+80000 * 0x0+80000 [^ ]+ * [^ ]+ * RW  * 0x.*
+ * LOAD * [^ ]+ * 0x0+a0000 * 0x0+a0000 [^ ]+ * [^ ]+ * RW  * 0x.*
+ * DYNAMIC * [^ ]+ * 0x0+42000 * 0x0+42000 .*
+ * NULL * .*
+
+ *Section to Segment mapping:
+ *Segment Sections\.\.\.
+ *0*0 *
+ *0*1 * \.interp *
+ *0*2 * \.reginfo *
+ *0*3 * \.interp \.reginfo \.hash \.dynsym \.dynstr \.dynamic \.rel\.dyn \.rel\.plt \.plt \.text \.MIPS\.stubs *
+ *0*4 * \.rld_map \.got\.plt *
+ *0*5 * \.got \.data \.bss *
+ *0*6 * \.dynamic *
+ *0*7 *
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64a.s
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64a.s	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,48 @@
+	.abicalls
+	.global	extf1
+	.ent	extf1
+extf1:
+	jr	$31
+	.end	extf1
+
+	.global	extf2
+	.ent	extf2
+extf2:
+	jr	$31
+	.end	extf2
+
+	.global	extf3
+	.ent	extf3
+extf3:
+	jr	$31
+	.end	extf3
+
+	.global	extf4
+	.ent	extf4
+extf4:
+	jr	$31
+	.end	extf4
+
+	.global	extf5
+	.ent	extf5
+extf5:
+	jr	$31
+	.end	extf5
+
+	.data
+	.global	extd1
+	.global	extd2
+	.global	extd3
+	.global	extd4
+	.type	extd1,%object
+	.type	extd2,%object
+	.type	extd3,%object
+	.type	extd4,%object
+	.size	extd1,20
+	.size	extd2,24
+	.size	extd3,28
+	.size	extd4,8
+extd1:	.space	20
+extd2:	.space	24
+extd3:	.space	28
+extd4:	.space	8
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64b.s
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64b.s	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,39 @@
+	.set	noreorder
+	.abicalls
+	.global	f1
+	.ent	f1
+f1:
+	.option	pic0
+	jal	f3
+	.option	pic2
+	lui	$2,%hi(f2)
+	jr	$31
+	addiu	$2,$2,%lo(f2)
+	.end	f1
+
+	.global	f2
+	.ent	f2
+f2:
+	lui	$28,%hi(%neg(%gp_rel(f2)))
+	addu	$28,$28,$25
+	addiu	$28,$28,%lo(%neg(%gp_rel(f2)))
+	ld	$25,%call16(extf1)($28)
+	ld	$4,%got_disp(extf2)($28)
+	ld	$5,%got_disp(extd1)($28)
+	jalr	$25
+	ld	$6,%got_disp(extd2)($28)
+	ld	$25,%call16(extf3)($28)
+	jr	$25
+	ld	$4,%got_disp(extf4)($28)
+	.end	f2
+
+	.global	f3
+	.ent	f3
+f3:
+	jr	$31
+	nop
+	.end	f3
+
+	.data
+	.word	extd1
+	.word	extd3
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64c.s
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64c.s	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,25 @@
+	.abicalls
+	.option	pic0
+	.set	noreorder
+	.global	__start
+	.ent	__start
+__start:
+	jal	f1
+	nop
+	lui	$2,%hi(f2)
+	addiu	$2,$2,%lo(f2)
+	jal	extf3
+	nop
+	jal	extf4
+	nop
+	jal	extf5
+	nop
+	lui	$2,%hi(extd2)
+	addiu	$2,$2,%lo(extd2)
+	lui	$2,%hi(extd3)
+	addiu	$2,$2,%lo(extd3)
+	.end	__start
+
+	.data
+	.word	extd2
+	.word	extd4
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.ad
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.ad	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,26 @@
+
+Dynamic section at offset .* contains .*:
+ * Tag * Type * Name/Value
+ 0x0+00000001 \(NEEDED\) .*
+ 0x0+00000004 \(HASH\) .*
+ 0x0+00000005 \(STRTAB\) .*
+ 0x0+00000006 \(SYMTAB\) .*
+ 0x0+0000000a \(STRSZ\) .*
+ 0x0+0000000b \(SYMENT\) .*
+ 0x0+70000016 \(MIPS_RLD_MAP\) * 0x80000
+ 0x0+00000015 \(DEBUG\) * 0x0
+ 0x0+00000003 \(PLTGOT\) * 0xa0000
+ 0x0+00000011 \(REL\) * 0x43000
+ 0x0+00000012 \(RELSZ\) * 80 \(bytes\)
+ 0x0+00000013 \(RELENT\) * 16 \(bytes\)
+ 0x0+70000001 \(MIPS_RLD_VERSION\) * 1
+ 0x0+70000005 \(MIPS_FLAGS\) * NOTPOT
+ 0x0+70000006 \(MIPS_BASE_ADDRESS\) * 0x40000
+ 0x0+7000000a \(MIPS_LOCAL_GOTNO\) * 3
+ 0x0+70000011 \(MIPS_SYMTABNO\) * 14
+ 0x0+70000012 \(MIPS_UNREFEXTNO\) * .*
+ 0x0+70000013 \(MIPS_GOTSYM\) * 0x7
+ 0x0+00000014 \(PLTREL\) * REL
+ 0x0+00000017 \(JMPREL\) * 0x43050
+ 0x0+00000002 \(PLTRELSZ\) * 48 \(bytes\)
+ 0x0+00000000 \(NULL\) * 0x0
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.dd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.dd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,102 @@
+# GOT layout:
+#
+# -32752: lazy resolution function
+# -32744: reserved for module pointer
+# -32736: PLT resolution function
+# -32728 ... -32696: useless local GOT entries (fixed on mainline)
+# -32688: extf2's GOT entry (undefined 0)
+# -32680: extf3's GOT entry (PLT entry)
+# -32672: extd2's GOT entry (copy reloc)
+# -32664: extf1's GOT entry (.MIPS.stubs entry)
+# -32656: extd1's GOT entry (undefined 0)
+# -32648: extf4's GOT entry (PLT entry)
+# -32640: extd4's GOT entry (undefined 0, reloc only)
+
+.*
+
+Disassembly of section \.plt:
+
+0+43080 <.*>:
+   43080:	3c0f000a 	lui	t3,0xa
+   43084:	ddf90010 	ld	t9,16\(t3\)
+   43088:	25ef0010 	addiu	t3,t3,16
+   4308c:	3c0e0008 	lui	t2,0x8
+   43090:	03200008 	jr	t9
+   43094:	25ce1000 	addiu	t2,t2,4096
+	\.\.\.
+
+0+430a0 <extf4@plt>:
+   430a0:	3c180008 	lui	t8,0x8
+   430a4:	df191000 	ld	t9,4096\(t8\)
+   430a8:	03200008 	jr	t9
+   430ac:	27181000 	addiu	t8,t8,4096
+
+0+430b0 <extf5@plt>:
+   430b0:	3c180008 	lui	t8,0x8
+   430b4:	df191008 	ld	t9,4104\(t8\)
+   430b8:	03200008 	jr	t9
+   430bc:	27181008 	addiu	t8,t8,4104
+
+0+430c0 <extf3@plt>:
+   430c0:	3c180008 	lui	t8,0x8
+   430c4:	df191010 	ld	t9,4112\(t8\)
+   430c8:	03200008 	jr	t9
+   430cc:	27181010 	addiu	t8,t8,4112
+Disassembly of section \.text:
+
+0+44000 <f2>:
+   44000:	3c190004 	lui	t9,0x4
+   44004:	0801100c 	j	44030 <\.pic\.f2>
+   44008:	27394030 	addiu	t9,t9,16432
+	\.\.\.
+
+0+44018 <f1>:
+   44018:	3c190004 	lui	t9,0x4
+   4401c:	27394020 	addiu	t9,t9,16416
+   44020:	0c011017 	jal	4405c <f3>
+   44024:	3c020004 	lui	v0,0x4
+   44028:	03e00008 	jr	ra
+   4402c:	24424000 	addiu	v0,v0,16384
+
+0+44030 <\.pic\.f2>:
+   44030:	3c1c0006 	lui	gp,0x6
+   44034:	0399e021 	addu	gp,gp,t9
+   44038:	279c3fc0 	addiu	gp,gp,16320
+   4403c:	df998040 	ld	t9,-32704\(gp\)
+   44040:	df848028 	ld	a0,-32728\(gp\)
+   44044:	df858048 	ld	a1,-32696\(gp\)
+   44048:	0320f809 	jalr	t9
+   4404c:	df868038 	ld	a2,-32712\(gp\)
+   44050:	df998030 	ld	t9,-32720\(gp\)
+   44054:	03200008 	jr	t9
+   44058:	df848050 	ld	a0,-32688\(gp\)
+
+0+4405c <f3>:
+   4405c:	03e00008 	jr	ra
+   44060:	00000000 	nop
+	\.\.\.
+
+0+44070 <__start>:
+   44070:	0c011006 	jal	44018 <f1>
+   44074:	00000000 	nop
+   44078:	3c020004 	lui	v0,0x4
+   4407c:	24424000 	addiu	v0,v0,16384
+   44080:	0c010c30 	jal	430c0 <extf3@plt>
+   44084:	00000000 	nop
+   44088:	0c010c28 	jal	430a0 <extf4@plt>
+   4408c:	00000000 	nop
+   44090:	0c010c2c 	jal	430b0 <extf5@plt>
+   44094:	00000000 	nop
+   44098:	3c02000a 	lui	v0,0xa
+   4409c:	24422000 	addiu	v0,v0,8192
+   440a0:	3c02000a 	lui	v0,0xa
+   440a4:	24422018 	addiu	v0,v0,8216
+	\.\.\.
+Disassembly of section \.MIPS\.stubs:
+
+0+440b0 <\.MIPS\.stubs>:
+   440b0:	df998010 	ld	t9,-32752\(gp\)
+   440b4:	03e0782d 	move	t3,ra
+   440b8:	0320f809 	jalr	t9
+   440bc:	6418000a 	daddiu	t8,zero,10
+	\.\.\.
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.gd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.gd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,20 @@
+
+Primary GOT:
+ Canonical gp value: 00000000000a7ff0
+
+ Reserved entries:
+           Address     Access          Initial Purpose
+  00000000000a0000 -32752\(gp\) 0000000000000000 Lazy resolver
+  00000000000a0008 -32744\(gp\) 8000000000000000 Module pointer \(GNU extension\)
+  00000000000a0010 -32736\(gp\) 0000000000000000 PLT lazy resolver \(GNU extension\)
+
+ Global entries:
+           Address     Access          Initial         Sym\.Val\. Type    Ndx Name
+  00000000000a0018 -32728\(gp\) 0000000000000000 0000000000000000 FUNC    UND extf2
+  00000000000a0020 -32720\(gp\) 00000000000430c0 00000000000430c0 FUNC    UND extf3
+  00000000000a0028 -32712\(gp\) 00000000000a2000 00000000000a2000 OBJECT   16 extd2
+  00000000000a0030 -32704\(gp\) 00000000000440b0 00000000000440b0 FUNC    UND extf1
+  00000000000a0038 -32696\(gp\) 0000000000000000 0000000000000000 OBJECT  UND extd1
+  00000000000a0040 -32688\(gp\) 00000000000430a0 00000000000430a0 FUNC    UND extf4
+  00000000000a0048 -32680\(gp\) 0000000000000000 0000000000000000 OBJECT  UND extd4
+
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.nd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.nd	2008-08-03 13:49:07.000000000 +0100
@@ -0,0 +1,17 @@
+
+Symbol table '\.dynsym' contains .*:
+#...
+.*: 0+430b0 * 0 * FUNC * GLOBAL * DEFAULT * \[MIPS PLT\] * UND * extf5
+# The index on the next line should correspond to MIPS_GOTSYM,
+# and the remaining symbols should have the same order as the
+# GOT layout given in the *.dd dump.
+#...
+ *7: 0+ * 0 * FUNC * GLOBAL * DEFAULT * UND * extf2
+ *8: 0+430c0 * 0 * FUNC * GLOBAL * DEFAULT \[MIPS PLT\] * UND * extf3
+ *9: 0+a2000 * 24 * OBJECT * GLOBAL * DEFAULT * [0-9]+ * extd2
+ *10: 0+440b0 * 0 * FUNC * GLOBAL * DEFAULT * UND * extf1
+ *11: 0+ * 0 * OBJECT * GLOBAL * DEFAULT * UND * extd1
+ *12: 0+430a0 * 0 * FUNC * GLOBAL * DEFAULT \[MIPS PLT\] * UND * extf4
+ *13: 0+ * 0 * OBJECT * GLOBAL * DEFAULT * UND * extd4
+
+#pass
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.pd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.pd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,6 @@
+
+.*
+
+Contents of section \.got\.plt:
+ 81000 00000000 00043080 00000000 00043080  .*
+ 81010 00000000 00043080                    .*
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.rd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.rd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,30 @@
+
+Relocation section '\.rel\.dyn' at offset .* contains .*:
+ * Offset * Info * Type * Sym\. Value * Sym\. Name
+0+00000 * 0+ * R_MIPS_NONE *
+ *Type2: R_MIPS_NONE *
+ *Type3: R_MIPS_NONE *
+0+a2018 * [^ ]*7e * R_MIPS_COPY * 0+a2018 * extd3
+ *Type2: R_MIPS_NONE *
+ *Type3: R_MIPS_NONE *
+0+a2000 * [^ ]*7e * R_MIPS_COPY * 0+a2000 * extd2
+ *Type2: R_MIPS_NONE *
+ *Type3: R_MIPS_NONE *
+0+a1000 * [^ ]*03 * R_MIPS_REL32 * 0+00000 * extd1
+ *Type2: R_MIPS_64 *
+ *Type3: R_MIPS_NONE *
+0+a1014 * [^ ]*03 * R_MIPS_REL32 * 0+00000 * extd4
+ *Type2: R_MIPS_64 *
+ *Type3: R_MIPS_NONE *
+
+Relocation section '\.rel\.plt' at offset .* contains .*:
+ * Offset * Info * Type * Sym\. Value * Sym\. Name
+0+81000 * [^ ]*7f * R_MIPS_JUMP_SLOT * 0+430a0 * extf4
+ *Type2: R_MIPS_NONE *
+ *Type3: R_MIPS_NONE *
+0+81008 * [^ ]*7f * R_MIPS_JUMP_SLOT * 0+430b0 * extf5
+ *Type2: R_MIPS_NONE *
+ *Type3: R_MIPS_NONE *
+0+81010 * [^ ]*7f * R_MIPS_JUMP_SLOT * 0+430c0 * extf3
+ *Type2: R_MIPS_NONE *
+ *Type3: R_MIPS_NONE *
Index: ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.sd
===================================================================
--- /dev/null	2008-08-03 10:51:42.544096500 +0100
+++ ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.sd	2008-08-03 13:15:44.000000000 +0100
@@ -0,0 +1,25 @@
+
+Elf file type is EXEC \(Executable file\)
+Entry point 0x44000
+There are 7 program headers, starting at offset .*
+
+Program Headers:
+ * Type * Offset * VirtAddr * PhysAddr * FileSiz * MemSiz * Flg * Align
+ * PHDR * .*
+ * INTERP * .*
+.*
+ * LOAD * [^ ]+ * 0x0+40000 * 0x0+40000 [^ ]+ * [^ ]+ * R E * 0x.*
+ * LOAD * [^ ]+ * 0x0+80000 * 0x0+80000 [^ ]+ * [^ ]+ * RW  * 0x.*
+ * LOAD * [^ ]+ * 0x0+a0000 * 0x0+a0000 [^ ]+ * [^ ]+ * RW  * 0x.*
+ * DYNAMIC * [^ ]+ * 0x0+42000 * 0x0+42000 .*
+ * NULL * .*
+
+ *Section to Segment mapping:
+ *Segment Sections\.\.\.
+ *0*0 *
+ *0*1 * \.interp *
+ *0*2 * \.interp \.hash \.dynsym \.dynstr \.dynamic \.rel\.dyn \.rel\.plt \.plt \.text \.MIPS\.stubs \.MIPS\.options *
+ *0*3 * \.rld_map \.got\.plt *
+ *0*4 * \.got \.data \.bss *
+ *0*5 * \.dynamic *
+ *0*6 *
Index: ld/testsuite/ld-mips-elf/mips-elf.exp
===================================================================
--- ld/testsuite/ld-mips-elf/mips-elf.exp	2008-08-03 13:12:34.000000000 +0100
+++ ld/testsuite/ld-mips-elf/mips-elf.exp	2008-08-03 13:15:44.000000000 +0100
@@ -77,7 +77,14 @@ if { $linux_gnu } {
 	        { readelf --symbols mips16-pic-2.nd } \
 		{ readelf --relocs mips16-pic-2.rd } \
 		{ readelf -d mips16-pic-2.ad } } \
-	     "mips16-pic-2"]]
+	     "mips16-pic-2"] \
+	[list "MIPS16 PIC test 3" \
+	      "-melf32btsmip -T mips16-pic-1.ld tmpdir/mips16-pic-1-dummy.so" \
+	      "-EB -32 -I $srcdir/$subdir" { mips16-pic-3a.s mips16-pic-3b.s } \
+	      { { objdump -dr mips16-pic-3.dd } \
+		{ readelf --relocs mips16-pic-3.rd } \
+		{ readelf -A mips16-pic-3.gd } } \
+	      "mips16-pic-3"]]
 }
 
 if { [istarget mips64*-linux-gnu] } {
@@ -133,6 +140,112 @@ if { $linux_gnu } {
     run_dump_test "rel32-o32"
     run_dump_test "rel32-n32"
     run_dump_test "rel64"
+    # The first test checks that a mixed PIC/non-PIC relocatable link
+    # will not introduce any stubs itself, but will flag PIC functions
+    # for the final link.
+    #
+    # The second test checks that we insert stubs for calls from
+    # non-PIC functions to PIC functions when linking the original
+    # two objects together.
+    #
+    # The third test checks that we do the same when linking the
+    # result of the first link (with no other source files).
+    run_ld_link_tests {
+	{"PIC and non-PIC test 1 (relocatable)" "-r -melf32btsmip"
+	 "-32 -EB -mips2" {pic-and-nonpic-1a.s pic-and-nonpic-1b.s}
+	 {{objdump -dr pic-and-nonpic-1-rel.dd}
+	  {readelf --symbols pic-and-nonpic-1-rel.nd}}
+	 "pic-and-nonpic-1-rel.o"}
+	{"PIC and non-PIC test 1 (static 1)"
+	 "-melf32btsmip -Tpic-and-nonpic-1.ld"
+	 "-32 -EB -mips2" {pic-and-nonpic-1a.s pic-and-nonpic-1b.s}
+	 {{objdump -dr pic-and-nonpic-1.dd}
+	  {readelf --symbols pic-and-nonpic-1.nd}}
+	 "pic-and-nonpic-1-static1.o"}
+	{"PIC and non-PIC test 1 (static 2)"
+	 "-melf32btsmip -Tpic-and-nonpic-1.ld tmpdir/pic-and-nonpic-1-rel.o"
+	 "" {}
+	 {{objdump -dr pic-and-nonpic-1.dd}
+	  {readelf --symbols pic-and-nonpic-1.nd}}
+	 "pic-and-nonpic-1-static2.o"}
+    }
+    run_dump_test "pic-and-nonpic-2"
+    run_ld_link_tests {
+	{"PIC and non-PIC test 3 (shared library)"
+	 "-melf32btsmip -shared -Tpic-and-nonpic-3a.ld"
+	 "-32 -EB -mips2" {pic-and-nonpic-3a.s}
+	 {{readelf --segments pic-and-nonpic-3a.sd}
+	  {readelf -A pic-and-nonpic-3a.gd}
+	  {objdump -dr pic-and-nonpic-3a.dd}}
+	 "pic-and-nonpic-3a.so"}
+	{"PIC and non-PIC test 3 (executable)"
+	 "-melf32btsmip -Tpic-and-nonpic-3b.ld tmpdir/pic-and-nonpic-3a.so"
+	 "-32 -EB -mips2" {pic-and-nonpic-3b.s}
+	 {{readelf --segments pic-and-nonpic-3b.sd}
+	  {objdump -dr pic-and-nonpic-3b.dd}
+	  {objdump {-s -j.got.plt} pic-and-nonpic-3b.pd}
+	  {readelf -A pic-and-nonpic-3b.gd}
+	  {readelf --relocs pic-and-nonpic-3b.rd}
+	  {readelf --symbols pic-and-nonpic-3b.nd}
+	  {readelf -d pic-and-nonpic-3b.ad}}
+	 "pic-and-nonpic-3b"}
+    }
+    run_dump_test "pic-and-nonpic-3-error"
+    run_ld_link_tests {
+	{"PIC and non-PIC test 4 (shared library)"
+	 "-melf32btsmip -shared -Tpic-and-nonpic-3a.ld"
+	 "-32 -EB -mips2" {pic-and-nonpic-4a.s}
+	 {}
+	 "pic-and-nonpic-4a.so"}
+	{"PIC and non-PIC test 4 (executable)"
+	 "-melf32btsmip -Tpic-and-nonpic-4b.ld tmpdir/pic-and-nonpic-4a.so"
+	 "-32 -EB -mips2" {pic-and-nonpic-4b.s}
+	 {{readelf --segments pic-and-nonpic-4b.sd}
+	  {objdump -dr pic-and-nonpic-4b.dd}
+	  {objdump {-s -j.got -j.data} pic-and-nonpic-4b.gd}
+	  {readelf --relocs pic-and-nonpic-4b.rd}
+	  {readelf --symbols pic-and-nonpic-4b.nd}
+	  {readelf -d pic-and-nonpic-4b.ad}}
+	 "pic-and-nonpic-4b"}
+    }
+    run_dump_test "pic-and-nonpic-4-error"
+    run_ld_link_tests {
+	{"PIC and non-PIC test 5 (executable)"
+	 "-melf32btsmip -Tpic-and-nonpic-5b.ld tmpdir/pic-and-nonpic-3a.so tmpdir/pic-and-nonpic-4a.so"
+	 "-32 -EB -mips2" {pic-and-nonpic-5a.s pic-and-nonpic-5b.s}
+	 {{readelf --segments pic-and-nonpic-5b.sd}
+	  {objdump -dr pic-and-nonpic-5b.dd}
+	  {objdump {-s -j.got.plt -j.data} pic-and-nonpic-5b.pd}
+	  {readelf --relocs pic-and-nonpic-5b.rd}
+	  {readelf --symbols pic-and-nonpic-5b.nd}
+	  {readelf -d pic-and-nonpic-5b.ad}}
+	 "pic-and-nonpic-5b"}
+    }
+    set abis { o32 -32 elf32btsmip }
+    if $has_newabi {
+	lappend abis n32 -n32 elf32btsmipn32
+	lappend abis n64 -64 elf64btsmip
+    }
+    foreach { abi flag emul } $abis {
+	run_ld_link_tests [list \
+	    [list "PIC and non-PIC test 6 ($abi shared library)" \
+		 "-m$emul -shared -Tpic-and-nonpic-3a.ld" \
+		 "$flag -EB -mips3" \
+		 [list "pic-and-nonpic-6-${abi}a.s"] {} \
+		 "pic-and-nonpic-6-${abi}.so"] \
+	    [list "PIC and non-PIC test 6 ($abi executable)" \
+		 "-m$emul -Tpic-and-nonpic-6.ld tmpdir/pic-and-nonpic-6-${abi}.so" \
+		 "$flag -EB -mips3" \
+		 [list "pic-and-nonpic-6-${abi}b.s" \
+		      "pic-and-nonpic-6-${abi}c.s"] \
+		 [list "readelf {--wide --segments} pic-and-nonpic-6-${abi}.sd" \
+		      "objdump -dr pic-and-nonpic-6-${abi}.dd" \
+		      "objdump {-s -j.got.plt} pic-and-nonpic-6-${abi}.pd" \
+		      "readelf --relocs pic-and-nonpic-6-${abi}.rd" \
+		      "readelf --symbols pic-and-nonpic-6-${abi}.nd" \
+		      "readelf -d pic-and-nonpic-6-${abi}.ad"] \
+		 "pic-and-nonpic-6-${abi}"]]
+    }
 }
 
 if { $embedded_elf } {


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