2008-08-08 Richard Sandiford <rdsandiford@googlemail.com>
authorDaniel Jacobowitz <drow@false.org>
Fri, 8 Aug 2008 19:24:49 +0000 (19:24 +0000)
committerDaniel Jacobowitz <drow@false.org>
Fri, 8 Aug 2008 19:24:49 +0000 (19:24 +0000)
    Daniel Jacobowitz  <dan@codesourcery.com>
    Catherine Moore  <clm@codesourcery.com>
    Mark Shinwell  <shinwell@codesourcery.com>
    Maxim Kuvyrkov  <maxim@codesourcery.com>

* 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.
(elf_backend_got_symbol_offset): Don't define.
* 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, _bfd_mips_post_process_headers): 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 "has_nonpic_branches" 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_o32_exec_plt0_entry, mips_n32_exec_plt0_entry)
(mips_n64_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_create_stub_symbol): New function.
(mips_elf_la25_stub_hash, mips_elf_la25_stub_eq): New functions.
(_bfd_mips_elf_init_stubs, mips_elf_local_pic_function_p): Likewise.
(mips_elf_add_la25_intro, mips_elf_add_la25_trampoline): Likewise.
(mips_elf_add_la25_stub, mips_elf_check_symbols): New functions.
(mips_elf_gotplt_index): Check for VxWorks.
(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_relocation_needs_la25_stub): New function.
(mips_elf_calculate_relocation): Redirect branches and jumps to
a non-PIC stub if one exists.  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.
(_bfd_mips_elf_check_relocs): Set pointer_equality_needed for
non-branch static relocations.  Set has_nonpic_branches when an la25
stub might be required.  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.
Reject non-PIC static relocations in shared objects.
(_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.
Skip reserved .got.plt entries.
(_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): 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.  Create a symbol for the
PLT.  Allocate a nop at the end of the PLT.  Allocate DT_MIPS_PLTGOT.
(mips_elf_create_la25_stub_info): New function.
(_bfd_mips_elf_finish_dynamic_symbol): Write out PLT entries
and copy relocs where necessary.  Check pointer_equality_needed.
(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.  Set
DT_MIPS_PLTGOT.
(_bfd_mips_elf_copy_indirect_symbol): Copy has_static_relocs
from the indirect symbol to the direct symbol.  Also copy
has_nonpic_branches for indirect symbols.
(_bfd_mips_elf_get_target_dtag): Handle DT_MIPS_PLTGOT and
DT_MIPS_RWPLT.
(_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, _bfd_mips_post_process_headers): New
functions.
* reloc.c: Update comment near BFD_RELOC_MIPS_JUMP_SLOT.
* bfd-in2.h: Regenerated.

2008-08-08  Richard Sandiford  <rdsandiford@googlemail.com>
    Daniel Jacobowitz  <dan@codesourcery.com>
    Catherine Moore  <clm@codesourcery.com>
    Mark Shinwell  <shinwell@codesourcery.com>

* readelf.c (get_mips_symbol_other): Handle STO_MIPS_PLT and
STO_MIPS_PIC.
(slurp_rela_relocs, slurp_rel_relocs): Handle MIPS ELF64 here.
(dump_relocations, debug_apply_relocations): Don't handle it here.
(get_mips_dynamic_type): Handle DT_MIPS_PLTGOT and DT_MIPS_RWPLT.
(print_mips_pltgot_entry): New function.
(process_mips_specific): Dump the PLT GOT.

2008-08-08  Richard Sandiford  <rdsandiford@googlemail.com>
    Daniel Jacobowitz  <dan@codesourcery.com>

* 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.

2008-08-08  Richard Sandiford  <rdsandiford@googlemail.com>

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

2008-08-08  Richard Sandiford  <rdsandiford@googlemail.com>
    Daniel Jacobowitz  <dan@codesourcery.com>
    Catherine Moore  <clm@codesourcery.com>
    Mark Shinwell  <shinwell@codesourcery.com>

* mips.h (STO_MIPS_PLT, ELF_ST_IS_MIPS_PLT, ELF_ST_SET_MIPS_PLT)
(STO_MIPS_PIC, DT_MIPS_PLTGOT, DT_MIPS_RWPLT): New macros.

2008-08-08  Richard Sandiford  <rdsandiford@googlemail.com>
    Daniel Jacobowitz  <dan@codesourcery.com>

* 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.

2008-08-08  Richard Sandiford  <rdsandiford@googlemail.com>
    Daniel Jacobowitz  <dan@codesourcery.com>

* 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.

106 files changed:
bfd/ChangeLog
bfd/bfd-in2.h
bfd/elf32-mips.c
bfd/elf64-mips.c
bfd/elfn32-mips.c
bfd/elfxx-mips.c
bfd/elfxx-mips.h
bfd/reloc.c
binutils/ChangeLog
binutils/readelf.c
gas/ChangeLog
gas/config/tc-mips.c
gas/testsuite/ChangeLog
gas/testsuite/gas/mips/call-nonpic-1.d [new file with mode: 0644]
gas/testsuite/gas/mips/call-nonpic-1.s [new file with mode: 0644]
gas/testsuite/gas/mips/mips.exp
include/elf/ChangeLog
include/elf/mips.h
ld/ChangeLog
ld/emulparams/elf32bmip.sh
ld/emulparams/elf32bmipn32-defs.sh
ld/emultempl/mipself.em
ld/testsuite/ChangeLog
ld/testsuite/ld-mips-elf/mips-elf.exp
ld/testsuite/ld-mips-elf/mips16-pic-3.dd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/mips16-pic-3.gd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/mips16-pic-3.inc [new file with mode: 0644]
ld/testsuite/ld-mips-elf/mips16-pic-3.rd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/mips16-pic-3a.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/mips16-pic-3b.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-1-rel.dd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-1-rel.nd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-1.dd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-1.ld [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-1.nd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-1a.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-1b.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-2.d [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-2a.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-2b.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-3-error.d [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-3a.dd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-3a.gd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-3a.ld [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-3a.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-3a.sd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.ad [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.dd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.gd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.ld [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.nd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.pd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.rd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.sd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-4-error.d [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-4a.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.ad [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.dd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.gd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.ld [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.nd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.rd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.sd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-5a.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.ad [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.dd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.gd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.ld [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.nd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.pd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.rd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.sd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.ad [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.dd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.gd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.nd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.pd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.rd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.sd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32a.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32b.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32c.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.ad [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.dd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.gd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.nd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.pd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.rd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.sd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64a.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64b.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64c.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.ad [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.dd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.gd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.nd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.pd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.rd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.sd [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32a.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32b.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32c.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-and-nonpic-6.ld [new file with mode: 0644]

index bf4cad152edfe66593a5651c34eda58d31225a9a..a705ca73110e49189eae025a6fd8b6e528615533 100644 (file)
@@ -1,3 +1,157 @@
+2008-08-08  Richard Sandiford  <rdsandiford@googlemail.com>
+           Daniel Jacobowitz  <dan@codesourcery.com>
+           Catherine Moore  <clm@codesourcery.com>
+           Mark Shinwell  <shinwell@codesourcery.com>
+           Maxim Kuvyrkov  <maxim@codesourcery.com>
+
+       * 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.
+       (elf_backend_got_symbol_offset): Don't define.
+       * 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, _bfd_mips_post_process_headers): 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 "has_nonpic_branches" 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_o32_exec_plt0_entry, mips_n32_exec_plt0_entry)
+       (mips_n64_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_create_stub_symbol): New function.
+       (mips_elf_la25_stub_hash, mips_elf_la25_stub_eq): New functions.
+       (_bfd_mips_elf_init_stubs, mips_elf_local_pic_function_p): Likewise.
+       (mips_elf_add_la25_intro, mips_elf_add_la25_trampoline): Likewise.
+       (mips_elf_add_la25_stub, mips_elf_check_symbols): New functions.
+       (mips_elf_gotplt_index): Check for VxWorks.
+       (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_relocation_needs_la25_stub): New function.
+       (mips_elf_calculate_relocation): Redirect branches and jumps to
+       a non-PIC stub if one exists.  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.
+       (_bfd_mips_elf_check_relocs): Set pointer_equality_needed for
+       non-branch static relocations.  Set has_nonpic_branches when an la25
+       stub might be required.  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.
+       Reject non-PIC static relocations in shared objects.
+       (_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.
+       Skip reserved .got.plt entries.
+       (_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): 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.  Create a symbol for the
+       PLT.  Allocate a nop at the end of the PLT.  Allocate DT_MIPS_PLTGOT.
+       (mips_elf_create_la25_stub_info): New function.
+       (_bfd_mips_elf_finish_dynamic_symbol): Write out PLT entries
+       and copy relocs where necessary.  Check pointer_equality_needed.
+       (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.  Set
+       DT_MIPS_PLTGOT.
+       (_bfd_mips_elf_copy_indirect_symbol): Copy has_static_relocs
+       from the indirect symbol to the direct symbol.  Also copy
+       has_nonpic_branches for indirect symbols.
+       (_bfd_mips_elf_get_target_dtag): Handle DT_MIPS_PLTGOT and
+       DT_MIPS_RWPLT.
+       (_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, _bfd_mips_post_process_headers): New
+       functions.
+       * reloc.c: Update comment near BFD_RELOC_MIPS_JUMP_SLOT.
+       * bfd-in2.h: Regenerated.
+
 2008-08-08  Alan Modra  <amodra@bigpond.net.au>
 
        * elf.c (bfd_elf_get_elf_syms): Don't leak memory on error.
index edd0e2a2a19267fd96be14afb356eae9b78e20fa..9b0dcff7ea061ccf88a6915ce660bdbf6148b928 100644 (file)
@@ -2661,7 +2661,7 @@ to compensate for the borrow when the low bits are added.  */
   BFD_RELOC_MIPS_TLS_TPREL_LO16,
 
 
-/* MIPS ELF relocations (VxWorks extensions).  */
+/* MIPS ELF relocations (VxWorks and PLT extensions).  */
   BFD_RELOC_MIPS_COPY,
   BFD_RELOC_MIPS_JUMP_SLOT,
 
index e04e797c8069000774083589558e59f6ea51058f..6c09ce5c4577158cef6c115e2db935210599aafc 100644 (file)
@@ -899,6 +899,38 @@ static reloc_howto_type elf_mips_gnu_vtentry_howto =
         0,                     /* dst_mask */
         FALSE);                /* pcrel_offset */
 
+/* Originally a VxWorks extension, but now used for other systems 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 other systems 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 *abfd, bfd_reloc_code_real_type code)
       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 *abfd ATTRIBUTE_UNUSED,
     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 r_type,
       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 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = {
 #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 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = {
 /* Include the target file again for this target.  */
 #include "elf32-target.h"
 
-
-/* Specific to VxWorks.  */
-static reloc_howto_type mips_vxworks_copy_howto_rela =
-  HOWTO (R_MIPS_COPY,          /* type */
-        0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        32,                    /* bitsize */
-        FALSE,                 /* pc_relative */
-        0,                     /* bitpos */
-        complain_overflow_bitfield, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
-        "R_MIPS_COPY",         /* name */
-        FALSE,                 /* partial_inplace */
-        0x0,                   /* src_mask */
-        0x0,                   /* dst_mask */
-        FALSE);                /* pcrel_offset */
-
-/* Specific to VxWorks.  */
-static reloc_howto_type mips_vxworks_jump_slot_howto_rela =
-  HOWTO (R_MIPS_JUMP_SLOT,     /* type */
-        0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        32,                    /* bitsize */
-        FALSE,                 /* pc_relative */
-        0,                     /* bitpos */
-        complain_overflow_bitfield, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
-        "R_MIPS_JUMP_SLOT",    /* name */
-        FALSE,                 /* partial_inplace */
-        0x0,                   /* src_mask */
-        0x0,                   /* dst_mask */
-        FALSE);                /* pcrel_offset */
-
-/* Implement elf_backend_bfd_reloc_type_lookup for VxWorks.  */
-
-static reloc_howto_type *
-mips_vxworks_bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code)
-{
-  switch (code)
-    {
-    case BFD_RELOC_MIPS_COPY:
-      return &mips_vxworks_copy_howto_rela;
-    case BFD_RELOC_MIPS_JUMP_SLOT:
-      return &mips_vxworks_jump_slot_howto_rela;
-    default:
-      return bfd_elf32_bfd_reloc_type_lookup (abfd, code);
-    }
-}
-
-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
@@ -1787,10 +1757,6 @@ mips_vxworks_final_write_processing (bfd *abfd, bfd_boolean linker)
 #define elf_backend_want_got_plt               1
 #undef elf_backend_want_plt_sym
 #define elf_backend_want_plt_sym               1
-#undef elf_backend_got_symbol_offset
-#define elf_backend_got_symbol_offset          0
-#undef elf_backend_want_dynbss
-#define elf_backend_want_dynbss                        1
 #undef elf_backend_may_use_rel_p
 #define elf_backend_may_use_rel_p              0
 #undef elf_backend_may_use_rela_p
@@ -1799,21 +1765,8 @@ mips_vxworks_final_write_processing (bfd *abfd, bfd_boolean linker)
 #define elf_backend_default_use_rela_p         1
 #undef elf_backend_got_header_size
 #define elf_backend_got_header_size            (4 * 3)
-#undef elf_backend_plt_readonly
-#define elf_backend_plt_readonly               1
-
-#undef bfd_elf32_bfd_reloc_type_lookup
-#define bfd_elf32_bfd_reloc_type_lookup \
-  mips_vxworks_bfd_reloc_type_lookup
-#undef 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_plt_sym_val
+
 #undef elf_backend_finish_dynamic_symbol
 #define elf_backend_finish_dynamic_symbol \
   _bfd_mips_vxworks_finish_dynamic_symbol
index 61db0f8cd17df16349a8ad7ec88ce01c0bf00d63..ad00a3db19b4a36e646080904fc3365f03b8a4e7 100644 (file)
@@ -1724,6 +1724,38 @@ static reloc_howto_type elf_mips_gnu_rela16_s2 =
         0x0000ffff,            /* dst_mask */
         TRUE);                 /* pcrel_offset */
 \f
+/* Originally a VxWorks extension, but now used for other systems 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 other systems 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 */
+\f
 /* Swap in a MIPS 64-bit Rel reloc.  */
 
 static void
@@ -2283,6 +2315,10 @@ bfd_elf64_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
       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 *abfd ATTRIBUTE_UNUSED,
     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 r_type, bfd_boolean rela_p)
        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 @@ const struct elf_size_info mips_elf64_size_info =
 #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 4e8a8d7a58c9e549b4ad36b8601f12dadcd835ff..aea3e5af2ae75889101bb85541f2494abc7bd07a 100644 (file)
@@ -1717,6 +1717,38 @@ static reloc_howto_type elf_mips_gnu_rela16_s2 =
         0x0000ffff,            /* dst_mask */
         TRUE);                 /* pcrel_offset */
 \f
+/* Originally a VxWorks extension, but now used for other systems 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 other systems 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 */
+\f
 /* 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 *abfd ATTRIBUTE_UNUSED,
       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 *abfd ATTRIBUTE_UNUSED,
     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 int r_type, bfd_boolean rela_p)
        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 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = {
 #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 5c87ecde07adcef380b48fc799b9c46fcba74ab3..80ce5b23aad424aa0c2cbf28381eb85cbd401793 100644 (file)
@@ -269,6 +269,41 @@ struct _mips_elf_section_data
 #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 generated section that contains this stub.  */
+  asection *stub_section;
+
+  /* The offset of the stub from the start of STUB_SECTION.  */
+  bfd_vma offset;
+
+  /* One symbol for the original function.  Its location 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 +334,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 +376,11 @@ struct mips_elf_link_hash_entry
      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 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,11 +391,10 @@ struct mips_elf_link_hash_entry
      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;
+  /* True if this symbol is referenced by branch relocations from
+     any non-PIC input file.  This is used to determine whether an
+     la25 stub is required.  */
+  unsigned int has_nonpic_branches : 1;
 
   /* Does this symbol need a traditional MIPS lazy-binding stub
      (as opposed to a PLT entry)?  */
@@ -369,21 +411,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 +447,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).  */
+
+  /* The size of the PLT header in bytes.  */
   bfd_vma plt_header_size;
-  /* The size of a PLT entry in bytes (VxWorks only).  */
+
+  /* The size of a PLT entry in bytes.  */
   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 +662,10 @@ static struct mips_got_info *mips_elf_got_for_ibfd
 /* 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 +736,10 @@ static bfd *reldyn_sorting_bfd;
    ? 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 +773,6 @@ static bfd *reldyn_sorting_bfd;
 #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 +877,52 @@ static bfd *reldyn_sorting_bfd;
 #define CALL_STUB_P(name) CONST_STRNEQ (name, CALL_STUB)
 #define CALL_FP_STUB_P(name) CONST_STRNEQ (name, CALL_FP_STUB)
 \f
+/* The format of the first PLT entry in an O32 executable.  */
+static const bfd_vma mips_o32_exec_plt0_entry[] = {
+  0x3c1c0000,  /* lui $28, %hi(&GOTPLT[0])                             */
+  0x8f990000,  /* lw $25, %lo(&GOTPLT[0])($28)                         */
+  0x279c0000,  /* addiu $28, $28, %lo(&GOTPLT[0])                      */
+  0x031cc023,  /* subu $24, $24, $28                                   */
+  0x03e07821,  /* move $15, $31                                        */
+  0x0018c082,  /* srl $24, $24, 2                                      */
+  0x0320f809,  /* jalr $25                                             */
+  0x2718fffe   /* subu $24, $24, 2                                     */
+};
+
+/* The format of the first PLT entry in an N32 executable.  Different
+   because gp ($28) is not available; we use t2 ($14) instead.  */
+static const bfd_vma mips_n32_exec_plt0_entry[] = {
+  0x3c0e0000,  /* lui $14, %hi(&GOTPLT[0])                             */
+  0x8dd90000,  /* lw $25, %lo(&GOTPLT[0])($14)                         */
+  0x25ce0000,  /* addiu $14, $14, %lo(&GOTPLT[0])                      */
+  0x030ec023,  /* subu $24, $24, $14                                   */
+  0x03e07821,  /* move $15, $31                                        */
+  0x0018c082,  /* srl $24, $24, 2                                      */
+  0x0320f809,  /* jalr $25                                             */
+  0x2718fffe   /* subu $24, $24, 2                                     */
+};
+
+/* The format of the first PLT entry in an N64 executable.  Different
+   from N32 because of the increased size of GOT entries.  */
+static const bfd_vma mips_n64_exec_plt0_entry[] = {
+  0x3c0e0000,  /* lui $14, %hi(&GOTPLT[0])                             */
+  0xddd90000,  /* ld $25, %lo(&GOTPLT[0])($14)                         */
+  0x25ce0000,  /* addiu $14, $14, %lo(&GOTPLT[0])                      */
+  0x030ec023,  /* subu $24, $24, $14                                   */
+  0x03e07821,  /* move $15, $31                                        */
+  0x0018c0c2,  /* srl $24, $24, 3                                      */
+  0x0320f809,  /* jalr $25                                             */
+  0x2718fffe   /* subu $24, $24, 2                                     */
+};
+
+/* The format of subsequent PLT entries.  */
+static const bfd_vma mips_exec_plt_entry[] = {
+  0x3c0f0000,  /* lui $15, %hi(.got.plt entry)                 */
+  0x01f90000,  /* l[wd] $25, %lo(.got.plt entry)($15)          */
+  0x25f80000,  /* addiu $24, $15, %lo(.got.plt entry)          */
+  0x03200008   /* jr $25                                       */
+};
+
 /* 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 +1032,7 @@ mips_elf_link_hash_newfunc (struct bfd_hash_entry *entry,
       /* 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 +1040,10 @@ mips_elf_link_hash_newfunc (struct bfd_hash_entry *entry,
       ret->tls_type = GOT_NORMAL;
       ret->global_got_area = GGA_NONE;
       ret->readonly_reloc = FALSE;
+      ret->has_static_relocs = FALSE;
       ret->no_fn_stub = FALSE;
       ret->need_fn_stub = FALSE;
-      ret->is_relocation_target = FALSE;
-      ret->is_branch_target = FALSE;
+      ret->has_nonpic_branches = FALSE;
       ret->needs_lazy_stub = FALSE;
     }
 
@@ -1183,6 +1322,35 @@ mips_elf_create_procedure_table (void *handle, bfd *abfd,
   return FALSE;
 }
 \f
+/* We're going to create a stub for H.  Create a symbol for the stub's
+   value and size, to help make the disassembly easier to read.  */
+
+static bfd_boolean
+mips_elf_create_stub_symbol (struct bfd_link_info *info,
+                            struct mips_elf_link_hash_entry *h,
+                            const char *prefix, asection *s, bfd_vma value,
+                            bfd_vma size)
+{
+  struct bfd_link_hash_entry *bh;
+  struct elf_link_hash_entry *elfh;
+  const char *name;
+
+  /* Create a new symbol.  */
+  name = ACONCAT ((prefix, h->root.root.root.string, NULL));
+  bh = NULL;
+  if (!_bfd_generic_link_add_one_symbol (info, s->owner, name,
+                                        BSF_LOCAL, s, value, NULL,
+                                        TRUE, FALSE, &bh))
+    return FALSE;
+
+  /* Make it a local function.  */
+  elfh = (struct elf_link_hash_entry *) bh;
+  elfh->type = ELF_ST_INFO (STB_LOCAL, STT_FUNC);
+  elfh->size = size;
+  elfh->forced_local = 1;
+  return TRUE;
+}
+
 /* We're about to redefine H.  Create a symbol to represent H's
    current value and size, to help make the disassembly easier
    to read.  */
@@ -1262,15 +1430,10 @@ mips16_stub_symndx (asection *sec, const Elf_Internal_Rela *relocs,
 /* 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,7 +1478,236 @@ mips_elf_check_mips16_stubs (struct mips_elf_link_hash_entry *h, void *data)
       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->h->root.root.u.def.section->id
+    + entry->h->root.root.u.def.value;
+}
+
+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->h->root.root.u.def.section
+          == entry2->h->root.root.u.def.section)
+         && (entry1->h->root.root.u.def.value
+             == entry2->h->root.root.u.def.value));
+}
+
+/* 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
+         && !bfd_is_abs_section (h->root.root.u.def.section)
+         && !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, *input_section;
+  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.  */
+  input_section = stub->h->root.root.u.def.section;
+  s = htab->add_stub_section (name, input_section,
+                             input_section->output_section);
+  if (s == NULL)
+    return FALSE;
+
+  /* Make sure that any padding goes before the stub.  */
+  align = input_section->alignment_power;
+  if (!bfd_set_section_alignment (s->owner, s, align))
+    return FALSE;
+  if (align > 3)
+    s->size = (1 << align) - 8;
+
+  /* Create a symbol for the stub.  */
+  mips_elf_create_stub_symbol (info, stub->h, ".pic.", s, s->size, 8);
+  stub->stub_section = s;
+  stub->offset = 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)
+    {
+      asection *input_section = stub->h->root.root.u.def.section;
+      s = htab->add_stub_section (".text", NULL,
+                                 input_section->output_section);
+      if (s == NULL || !bfd_set_section_alignment (s->owner, s, 4))
+       return FALSE;
+      htab->strampoline = s;
+    }
+
+  /* Create a symbol for the stub.  */
+  mips_elf_create_stub_symbol (info, stub->h, ".pic.", s, s->size, 16);
+  stub->stub_section = s;
+  stub->offset = s->size;
+
+  /* Allocate room for it.  */
+  s->size += 16;
+  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;
+
+  /* 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.  */
+  s = h->root.root.u.def.section;
+  value = h->root.root.u.def.value;
+  use_trampoline_p = (value != 0 || s->alignment_power > 4);
+
+  /* Describe the stub we want.  */
+  search.stub_section = NULL;
+  search.offset = 0;
+  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.  */
+      h->la25_stub = stub;
+      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 branches and jumps 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->has_nonpic_branches && !mips_elf_add_la25_stub (hti->info, h))
+       {
+         hti->error = TRUE;
+         return FALSE;
+       }
+    }
   return TRUE;
 }
 \f
@@ -2382,6 +2774,7 @@ mips_elf_count_global_tls_relocs (void *arg1, void *arg2)
 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 +2791,13 @@ mips_elf_output_dynamic_relocation (bfd *output_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 +2855,13 @@ mips_elf_initialize_tls_slots (bfd *abfd, bfd_vma got_offset,
       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 +2894,7 @@ mips_elf_initialize_tls_slots (bfd *abfd, bfd_vma got_offset,
                               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 +2916,7 @@ mips_elf_initialize_tls_slots (bfd *abfd, bfd_vma got_offset,
                           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);
     }
@@ -2585,6 +2977,10 @@ mips_elf_gotplt_index (struct bfd_link_info *info,
   htab = mips_elf_hash_table (info);
   BFD_ASSERT (h->plt.offset != (bfd_vma) -1);
 
+  /* This function only works for VxWorks, because a non-VxWorks .got.plt
+     section starts with reserved entries.  */
+  BFD_ASSERT (htab->is_vxworks);
+
   /* Calculate the index of the symbol's PLT entry.  */
   plt_index = (h->plt.offset - htab->plt_header_size) / htab->plt_entry_size;
 
@@ -3882,7 +4278,7 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
   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 +4389,7 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
     {
       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 +4446,7 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
          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 +4669,9 @@ mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
   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 +4687,14 @@ mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
   mips_elf_section_data (s)->elf.this_hdr.sh_flags
     |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
 
-  /* VxWorks also needs a .got.plt section.  */
-  if (htab->is_vxworks)
-    {
-      s = bfd_make_section_with_flags (abfd, ".got.plt",
-                                      SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
-                                      | SEC_IN_MEMORY | SEC_LINKER_CREATED);
-      if (s == NULL || !bfd_set_section_alignment (abfd, s, 4))
-       return FALSE;
+  /* 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;
 }
 \f
@@ -4317,6 +4710,34 @@ is_gott_symbol (struct bfd_link_info *info, struct elf_link_hash_entry *h)
          && (strcmp (h->root.root.string, "__GOTT_BASE__") == 0
              || strcmp (h->root.root.string, "__GOTT_INDEX__") == 0));
 }
+
+/* Return TRUE if a relocation of type R_TYPE from INPUT_BFD might
+   require an la25 stub.  See also mips_elf_local_pic_function_p,
+   which determines whether the destination function ever requires a
+   stub.  */
+
+static bfd_boolean
+mips_elf_relocation_needs_la25_stub (bfd *input_bfd, int r_type)
+{
+  /* We specifically ignore branches and jumps from EF_PIC objects,
+     where the onus is on the compiler or programmer to perform any
+     necessary initialization of $25.  Sometimes such initialization
+     is unnecessary; for example, -mno-shared functions do not use
+     the incoming value of $25, and may therefore be called directly.  */
+  if (PIC_OBJECT_P (input_bfd))
+    return FALSE;
+
+  switch (r_type)
+    {
+    case R_MIPS_26:
+    case R_MIPS_PC16:
+    case R_MIPS16_26:
+      return TRUE;
+
+    default:
+      return FALSE;
+    }
+}
 \f
 /* Calculate the value produced by the RELOCATION (which comes from
    the INPUT_BFD).  The ADDEND is the addend to use for this
@@ -4617,6 +5038,13 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
       BFD_ASSERT (sec->size > 0);
       symbol = sec->output_section->vma + sec->output_offset;
     }
+  /* If this is a direct call to a PIC function, redirect to the
+     non-PIC stub.  */
+  else if (h != NULL && h->la25_stub
+          && mips_elf_relocation_needs_la25_stub (input_bfd, r_type))
+    symbol = (h->la25_stub->stub_section->output_section->vma
+             + h->la25_stub->stub_section->output_offset
+             + h->la25_stub->offset);
 
   /* Calls from 16-bit code to 32-bit code and vice versa require the
      special jalx instruction.  */
@@ -4761,26 +5189,23 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
     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 +6950,29 @@ _bfd_mips_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
        }
     }
 
+  /* 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 +6993,12 @@ _bfd_mips_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
            = 4 * ARRAY_SIZE (mips_vxworks_exec_plt_entry);
        }
     }
+  else if (!info->shared)
+    {
+      /* All variants of the plt0 entry are the same size.  */
+      htab->plt_header_size = 4 * ARRAY_SIZE (mips_o32_exec_plt0_entry);
+      htab->plt_entry_size = 4 * ARRAY_SIZE (mips_exec_plt_entry);
+    }
 
   return TRUE;
 }
@@ -6979,6 +7415,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
       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);
@@ -6996,69 +7433,89 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
       else
        {
          h = sym_hashes[r_symndx - extsymoff];
+         while (h->root.type == bfd_link_hash_indirect
+                || h->root.type == bfd_link_hash_warning)
+           h = (struct elf_link_hash_entry *) h->root.u.i.link;
+       }
 
-         /* This may be an indirect symbol created because of a version.  */
-         if (h != 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)
+       {
+       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)
            {
-             while (h->root.type == bfd_link_hash_indirect)
-               h = (struct elf_link_hash_entry *) h->root.u.i.link;
+             (*_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;
 
-      /* Some relocs require a global offset table.  */
-      if (dynobj == NULL || htab->sgot == NULL)
-       {
-         switch (r_type)
+       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.
+
+            For executables that use PLTs and copy-relocs, 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)
            {
-           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:
+             can_make_dynamic_p = TRUE;
              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;
+           }
+         /* Fall through.  */
 
-           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;
+       default:
+         /* Most static relocations require pointer equality, except
+            for branches.  */
+         if (h)
+           h->pointer_equality_needed = TRUE;
+         /* Fall through.  */
 
-           default:
-             break;
-           }
+       case R_MIPS_26:
+       case R_MIPS_PC16:
+       case R_MIPS16_26:
+         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.  */
@@ -7095,6 +7552,9 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
            return FALSE;
        }
 
+      if (h != NULL && mips_elf_relocation_needs_la25_stub (abfd, r_type))
+       ((struct mips_elf_link_hash_entry *) h)->has_nonpic_branches = TRUE;
+
       switch (r_type)
        {
        case R_MIPS_CALL16:
@@ -7136,11 +7596,6 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
              struct mips_elf_link_hash_entry *hmips =
                (struct mips_elf_link_hash_entry *) h;
 
-             while (hmips->root.root.type == bfd_link_hash_indirect
-                    || hmips->root.root.type == bfd_link_hash_warning)
-               hmips = (struct mips_elf_link_hash_entry *)
-                 hmips->root.root.u.i.link;
-
              /* This symbol is definitely not overridable.  */
              if (hmips->root.def_regular
                  && ! (info->shared && ! info->symbolic
@@ -7236,9 +7691,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
          /* 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)
                {
@@ -7286,16 +7739,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
              sizeof (Elf32_External_crinfo);
          break;
 
-       case R_MIPS_PC16:
-         if (h)
-           ((struct mips_elf_link_hash_entry *) h)->is_branch_target = TRUE;
-         break;
-
        case R_MIPS_26:
-         if (h)
-           ((struct mips_elf_link_hash_entry *) h)->is_branch_target = TRUE;
-         /* Fall through.  */
-
        case R_MIPS_GPREL16:
        case R_MIPS_LITERAL:
        case R_MIPS_GPREL32:
@@ -7355,6 +7799,46 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
          mh = (struct mips_elf_link_hash_entry *) h;
          mh->need_fn_stub = TRUE;
        }
+
+      /* Refuse some position-dependent relocations when creating a
+        shared library.  Do not refuse R_MIPS_32 / R_MIPS_64; they're
+        not PIC, but we can create dynamic relocations and the result
+        will be fine.  Also do not refuse R_MIPS_LO16, which can be
+        combined with R_MIPS_GOT16.  */
+      if (info->shared)
+       {
+         switch (r_type)
+           {
+           case R_MIPS16_HI16:
+           case R_MIPS_HI16:
+           case R_MIPS_HIGHER:
+           case R_MIPS_HIGHEST:
+             /* Don't refuse a high part relocation if it's against
+                no symbol (e.g. part of a compound relocation).  */
+             if (r_symndx == 0)
+               break;
+
+             /* R_MIPS_HI16 against _gp_disp is used for $gp setup,
+                and has a special meaning.  */
+             if (!NEWABI_P (abfd) && h != NULL
+                 && strcmp (h->root.root.string, "_gp_disp") == 0)
+               break;
+
+             /* FALLTHROUGH */
+
+           case R_MIPS16_26:
+           case R_MIPS_26:
+             howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, r_type, FALSE);
+             (*_bfd_error_handler)
+               (_("%B: relocation %s against `%s' can not be used when making a shared object; recompile with -fPIC"),
+                abfd, howto->name,
+                (h) ? h->root.root.string : "a local symbol");
+             bfd_set_error (bfd_error_bad_value);
+             return FALSE;
+           default:
+             break;
+           }
+       }
     }
 
   return TRUE;
@@ -7609,6 +8093,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
 
   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
@@ -7620,9 +8105,15 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
 
   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;
@@ -7638,90 +8129,53 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
          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)
+     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))
     {
-      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.  */
+      /* If this is the first symbol to need a PLT entry, allocate room
+        for the header.  */
+      if (htab->splt->size == 0)
+       {
+         BFD_ASSERT (htab->sgotplt->size == 0);
 
-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;
+         /* If we're using the PLT additions to the psABI, each PLT
+            entry is 16 bytes and the PLT0 entry is 32 bytes.
+            Encourage better cache usage by aligning.  We do this
+            lazily to avoid pessimizing traditional objects.  */
+         if (!htab->is_vxworks
+             && !bfd_set_section_alignment (dynobj, htab->splt, 5))
+           return FALSE;
 
-  htab = mips_elf_hash_table (info);
-  dynobj = elf_hash_table (info)->dynobj;
-  hmips = (struct mips_elf_link_hash_entry *) h;
+         /* 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;
 
-  /* 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)));
+         htab->splt->size += htab->plt_header_size;
 
-  /* 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;
-    }
+         /* On non-VxWorks targets, the first two entries in .got.plt
+            are reserved.  */
+         if (!htab->is_vxworks)
+           htab->sgotplt->size += 2 * MIPS_ELF_GOT_SIZE (dynobj);
 
-  if (h->needs_plt)
-    {
-      /* If this is the first symbol to need a PLT entry, allocate room
-        for the header, and for the header's .rela.plt.unloaded entries.  */
-      if (htab->splt->size == 0)
-       {
-         htab->splt->size += htab->plt_header_size;
-         if (!info->shared)
+         /* 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);
        }
 
@@ -7730,35 +8184,33 @@ _bfd_mips_vxworks_adjust_dynamic_symbol (struct bfd_link_info *info,
       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;
     }
 
@@ -7774,11 +8226,27 @@ _bfd_mips_vxworks_adjust_dynamic_symbol (struct bfd_link_info *info,
       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
@@ -7791,10 +8259,17 @@ _bfd_mips_vxworks_adjust_dynamic_symbol (struct bfd_link_info *info,
 
   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);
 }
 \f
@@ -7808,6 +8283,7 @@ _bfd_mips_elf_always_size_sections (bfd *output_bfd,
 {
   asection *ri;
   struct mips_elf_link_hash_table *htab;
+  struct mips_htab_traverse_info hti;
 
   htab = mips_elf_hash_table (info);
 
@@ -7816,10 +8292,13 @@ _bfd_mips_elf_always_size_sections (bfd *output_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;
 }
@@ -7846,6 +8325,16 @@ mips_elf_lay_out_got (bfd *output_bfd, struct bfd_link_info *info)
   dynobj = elf_hash_table (info)->dynobj;
   g = htab->got_info;
 
+  /* Allocate room for the reserved entries.  VxWorks always reserves
+     3 entries; other objects only reserve 2 entries.  */
+  BFD_ASSERT (g->assigned_gotno == 0);
+  if (htab->is_vxworks)
+    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))
@@ -7913,7 +8402,7 @@ mips_elf_lay_out_got (bfd *output_bfd, struct bfd_link_info *info)
          /* 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);
        }
@@ -8023,7 +8512,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
                                     struct bfd_link_info *info)
 {
   bfd *dynobj;
-  asection *s;
+  asection *s, *sreldyn;
   bfd_boolean reltext;
   struct mips_elf_link_hash_table *htab;
 
@@ -8043,7 +8532,22 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
          s->contents
            = (bfd_byte *) ELF_DYNAMIC_INTERPRETER (output_bfd);
        }
-      }
+
+      /* Create a symbol for the PLT, if we know that we are using it.  */
+      if (htab->splt && htab->splt->size > 0 && htab->root.hplt == NULL)
+       {
+         struct elf_link_hash_entry *h;
+
+         BFD_ASSERT (htab->use_plts_and_copy_relocs);
+
+         h = _bfd_elf_define_linkage_sym (dynobj, info, htab->splt,
+                                          "_PROCEDURE_LINKAGE_TABLE_");
+         htab->root.hplt = h;
+         if (h == NULL)
+           return FALSE;
+         h->type = STT_FUNC;
+       }
+    }
 
   /* Allocate space for global sym dynamic relocs.  */
   elf_link_hash_traverse (&htab->root, allocate_dynrelocs, (PTR) info);
@@ -8117,11 +8621,18 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
       else if (SGI_COMPAT (output_bfd)
               && CONST_STRNEQ (name, ".compact_rel"))
        s->size += mips_elf_hash_table (info)->compact_rel_size;
+      else if (s == htab->splt)
+       {
+         /* If the last PLT entry has a branch delay slot, allocate
+            room for an extra nop to fill the delay slot.  */
+         if (!htab->is_vxworks && s->size > 0)
+           s->size += 4;
+       }
       else if (! CONST_STRNEQ (name, ".init")
               && 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;
@@ -8185,11 +8696,12 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_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;
@@ -8200,21 +8712,10 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_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;
@@ -8257,6 +8758,20 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_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 (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_PLTGOT, 0))
+           return FALSE;
+       }
       if (htab->is_vxworks
          && !elf_vxworks_add_dynamic_entries (output_bfd, info))
        return FALSE;
@@ -8651,6 +9166,68 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
   return TRUE;
 }
 \f
+/* 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->stub_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->offset;
+
+  /* Work out the target address.  */
+  target = (stub->h->root.root.u.def.section->output_section->vma
+           + stub->h->root.root.u.def.section->output_offset
+           + stub->h->root.root.u.def.value);
+  target_high = ((target + 0x8000) >> 16) & 0xffff;
+  target_low = (target & 0xffff);
+
+  if (stub->stub_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.  */
 
@@ -8722,8 +9299,76 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
   dynobj = elf_hash_table (info)->dynobj;
   hmips = (struct mips_elf_link_hash_entry *) h;
 
-  if (h->plt.offset != MINUS_ONE)
+  BFD_ASSERT (!htab->is_vxworks);
+
+  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;
+      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
+                    + (2 + 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
+            + (2 + 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] | got_address_low, loc + 8);
+      bfd_put_32 (output_bfd, plt_entry[3], 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.  Set the
+        flag and leave the value if there are any relocations in the
+        binary where pointer equality matters.  */
+      sym->st_shndx = SHN_UNDEF;
+      if (h->pointer_equality_needed)
+       sym->st_other = STO_MIPS_PLT;
+      else
+       sym->st_value = 0;
+    }
+  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.  */
@@ -8910,6 +9555,23 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_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);
@@ -9120,6 +9782,47 @@ _bfd_mips_vxworks_finish_dynamic_symbol (bfd *output_bfd,
   return TRUE;
 }
 
+/* Write out a 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 gotplt_value, gotplt_value_high, gotplt_value_low;
+  static const bfd_vma *plt_entry;
+  struct mips_elf_link_hash_table *htab;
+
+  htab = mips_elf_hash_table (info);
+  if (ABI_64_P (output_bfd))
+    plt_entry = mips_n64_exec_plt0_entry;
+  else if (ABI_N32_P (output_bfd))
+    plt_entry = mips_n32_exec_plt0_entry;
+  else
+    plt_entry = mips_o32_exec_plt0_entry;
+
+  /* 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;
+
+  /* The PLT sequence is not safe for N64 if .got.plt's address can
+     not be loaded in two instructions.  */
+  BFD_ASSERT ((gotplt_value & ~(bfd_vma) 0x7fffffff) == 0
+             || ~(gotplt_value | 0x7fffffff) == 0);
+
+  /* Install the PLT header.  */
+  loc = htab->splt->contents;
+  bfd_put_32 (output_bfd, plt_entry[0] | gotplt_value_high, loc);
+  bfd_put_32 (output_bfd, plt_entry[1] | gotplt_value_low, loc + 4);
+  bfd_put_32 (output_bfd, plt_entry[2] | gotplt_value_low, loc + 8);
+  bfd_put_32 (output_bfd, plt_entry[3], loc + 12);
+  bfd_put_32 (output_bfd, plt_entry[4], loc + 16);
+  bfd_put_32 (output_bfd, plt_entry[5], loc + 20);
+  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.  */
 
@@ -9275,21 +9978,13 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
              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_PLTGOT:
+             s = htab->sgotplt;
+             dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
              break;
 
            case DT_MIPS_RLD_VERSION:
@@ -9355,7 +10050,7 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
              break;
 
            case DT_MIPS_HIPAGENO:
-             dyn.d_un.d_val = g->local_gotno - MIPS_RESERVED_GOTNO (info);
+             dyn.d_un.d_val = g->local_gotno - htab->reserved_gotno;
              break;
 
            case DT_MIPS_RLD_MAP:
@@ -9376,18 +10071,21 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
              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);
-             dyn.d_un.d_val = (htab->srelplt->output_section->vma
+             BFD_ASSERT (htab->use_plts_and_copy_relocs);
+             dyn.d_un.d_ptr = (htab->srelplt->output_section->vma
                                + htab->srelplt->output_offset);
              break;
 
@@ -9615,12 +10313,20 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
       }
   }
 
-  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;
 }
@@ -10201,11 +10907,16 @@ _bfd_mips_elf_copy_indirect_symbol (struct bfd_link_info *info,
 
   _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;
@@ -10215,6 +10926,8 @@ _bfd_mips_elf_copy_indirect_symbol (struct bfd_link_info *info,
     dirmips->global_got_area = indmips->global_got_area;
   if (indmips->global_got_area < GGA_NONE)
     indmips->global_got_area = GGA_NONE;
+  if (indmips->has_nonpic_branches)
+    dirmips->has_nonpic_branches = TRUE;
 
   if (dirmips->tls_type == 0)
     dirmips->tls_type = indmips->tls_type;
@@ -10684,6 +11397,7 @@ _bfd_mips_elf_link_hash_table_create (bfd *abfd)
   ret->use_rld_obj_head = FALSE;
   ret->rld_value = 0;
   ret->mips16_stubs_seen = FALSE;
+  ret->use_plts_and_copy_relocs = FALSE;
   ret->is_vxworks = FALSE;
   ret->small_data_overflow_reported = FALSE;
   ret->srelbss = NULL;
@@ -10699,6 +11413,9 @@ _bfd_mips_elf_link_hash_table_create (bfd *abfd)
   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;
 }
@@ -10716,10 +11433,20 @@ _bfd_mips_vxworks_link_hash_table_create (bfd *abfd)
       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;
+}
 \f
 /* We need to use a special link routine to handle the .reginfo and
    the .mdebug sections.  We need to merge all instances of these
@@ -10734,6 +11461,7 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   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;
@@ -10761,6 +11489,14 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   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)
     {
@@ -11676,11 +12412,9 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
   new_flags &= ~EF_MIPS_UCODE;
   old_flags &= ~EF_MIPS_UCODE;
 
-  /* Don't care about the PIC flags from dynamic objects; they are
-     PIC by design.  */
-  if ((new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0
-      && (ibfd->flags & DYNAMIC) != 0)
-    new_flags &= ~ (EF_MIPS_PIC | EF_MIPS_CPIC);
+  /* 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;
@@ -11712,7 +12446,7 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
       != ((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;
     }
@@ -11923,6 +12657,10 @@ _bfd_mips_elf_get_target_dtag (bfd_vma dtag)
       return "DT_MIPS_GP_VALUE";
     case DT_MIPS_AUX_DYNAMIC:
       return "DT_MIPS_AUX_DYNAMIC";
+    case DT_MIPS_PLTGOT:
+      return "DT_MIPS_PLTGOT";
+    case DT_MIPS_RWPLT:
+      return "DT_MIPS_RWPLT";
     }
 }
 
@@ -12057,3 +12795,30 @@ _bfd_mips_elf_common_definition (Elf_Internal_Sym *sym)
          || 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_o32_exec_plt0_entry)
+         + i * 4 * ARRAY_SIZE (mips_exec_plt_entry));
+}
+
+void
+_bfd_mips_post_process_headers (bfd *abfd, struct bfd_link_info *link_info)
+{
+  struct mips_elf_link_hash_table *htab;
+  Elf_Internal_Ehdr *i_ehdrp;
+
+  i_ehdrp = elf_elfheader (abfd);
+  if (link_info)
+    {
+      htab = mips_elf_hash_table (link_info);
+      if (htab->use_plts_and_copy_relocs && !htab->is_vxworks)
+       i_ehdrp->e_ident[EI_ABIVERSION] = 1;
+    }
+}
index 5b791731369acd8eb95478db369fd250b9bff3fb..15bd4be606aa62b9d62632efdaaaf9926a8fcee4 100644 (file)
@@ -50,8 +50,6 @@ extern bfd_boolean _bfd_mips_elf_check_relocs
   (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *);
 extern bfd_boolean _bfd_mips_elf_adjust_dynamic_symbol
   (struct bfd_link_info *, struct elf_link_hash_entry *);
-extern bfd_boolean _bfd_mips_vxworks_adjust_dynamic_symbol
-  (struct bfd_link_info *, struct elf_link_hash_entry *);
 extern bfd_boolean _bfd_mips_elf_always_size_sections
   (bfd *, struct bfd_link_info *);
 extern bfd_boolean _bfd_mips_elf_size_dynamic_sections
@@ -141,6 +139,15 @@ extern void _bfd_mips_elf_merge_symbol_attribute
 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 void _bfd_mips_post_process_headers
+  (bfd *abfd, struct bfd_link_info *link_info);
 
 extern const struct bfd_elf_special_section _bfd_mips_elf_special_sections [];
 
@@ -153,3 +160,4 @@ extern bfd_boolean _bfd_mips_elf_common_definition (Elf_Internal_Sym *);
 #define elf_backend_eh_frame_address_size _bfd_mips_elf_eh_frame_address_size
 #define elf_backend_merge_symbol_attribute  _bfd_mips_elf_merge_symbol_attribute
 #define elf_backend_ignore_undef_symbol _bfd_mips_elf_ignore_undef_symbol
+#define elf_backend_post_process_headers _bfd_mips_post_process_headers
index 8881f8f23bfc1684a2244da04963dbea592e01da..03b46bf809284ccda1de4da903211443af5c306e 100644 (file)
@@ -2258,7 +2258,7 @@ ENUM
 ENUMX
   BFD_RELOC_MIPS_JUMP_SLOT
 ENUMDOC
-  MIPS ELF relocations (VxWorks extensions).
+  MIPS ELF relocations (VxWorks and PLT extensions).
 COMMENT
 
 ENUM
index 9cb36ce386d9323c43e1a3d793d8d5ad1288a2e0..f169cab0be907929d9f08f84993761cef76b7db4 100644 (file)
@@ -1,3 +1,16 @@
+2008-08-08  Richard Sandiford  <rdsandiford@googlemail.com>
+           Daniel Jacobowitz  <dan@codesourcery.com>
+           Catherine Moore  <clm@codesourcery.com>
+           Mark Shinwell  <shinwell@codesourcery.com>
+
+       * readelf.c (get_mips_symbol_other): Handle STO_MIPS_PLT and
+       STO_MIPS_PIC.
+       (slurp_rela_relocs, slurp_rel_relocs): Handle MIPS ELF64 here.
+       (dump_relocations, debug_apply_relocations): Don't handle it here.
+       (get_mips_dynamic_type): Handle DT_MIPS_PLTGOT and DT_MIPS_RWPLT.
+       (print_mips_pltgot_entry): New function.
+       (process_mips_specific): Dump the PLT GOT.
+
 2008-08-08  Alan Modra  <amodra@bigpond.net.au>
 
        * readelf.c (is_64bit_abs_reloc): Return true for R_MIPS_64.
index ce1203e2ed2086d12b4906ba6c9209e5205c8f99..609edc6f88bc1faabc4f536c89c3598a465b1496 100644 (file)
@@ -707,6 +707,28 @@ slurp_rela_relocs (FILE *file,
          relas[i].r_offset = BYTE_GET (erelas[i].r_offset);
          relas[i].r_info   = BYTE_GET (erelas[i].r_info);
          relas[i].r_addend = BYTE_GET (erelas[i].r_addend);
+
+         /* The #ifdef BFD64 below is to prevent a compile time
+            warning.  We know that if we do not have a 64 bit data
+            type that we will never execute this code anyway.  */
+#ifdef BFD64
+         if (elf_header.e_machine == EM_MIPS
+             && elf_header.e_ident[EI_DATA] != ELFDATA2MSB)
+           {
+             /* In little-endian objects, r_info isn't really a
+                64-bit little-endian value: it has a 32-bit
+                little-endian symbol index followed by four
+                individual byte fields.  Reorder INFO
+                accordingly.  */
+             bfd_vma info = relas[i].r_info;
+             info = (((info & 0xffffffff) << 32)
+                     | ((info >> 56) & 0xff)
+                     | ((info >> 40) & 0xff00)
+                     | ((info >> 24) & 0xff0000)
+                     | ((info >> 8) & 0xff000000));
+             relas[i].r_info = info;
+           }
+#endif /* BFD64 */
        }
 
       free (erelas);
@@ -779,6 +801,28 @@ slurp_rel_relocs (FILE *file,
          rels[i].r_offset = BYTE_GET (erels[i].r_offset);
          rels[i].r_info   = BYTE_GET (erels[i].r_info);
          rels[i].r_addend = 0;
+
+         /* The #ifdef BFD64 below is to prevent a compile time
+            warning.  We know that if we do not have a 64 bit data
+            type that we will never execute this code anyway.  */
+#ifdef BFD64
+         if (elf_header.e_machine == EM_MIPS
+             && elf_header.e_ident[EI_DATA] != ELFDATA2MSB)
+           {
+             /* In little-endian objects, r_info isn't really a
+                64-bit little-endian value: it has a 32-bit
+                little-endian symbol index followed by four
+                individual byte fields.  Reorder INFO
+                accordingly.  */
+             bfd_vma info = rels[i].r_info;
+             info = (((info & 0xffffffff) << 32)
+                     | ((info >> 56) & 0xff)
+                     | ((info >> 40) & 0xff00)
+                     | ((info >> 24) & 0xff0000)
+                     | ((info >> 8) & 0xff000000));
+             rels[i].r_info = info;
+           }
+#endif /* BFD64 */
        }
 
       free (erels);
@@ -895,26 +939,6 @@ dump_relocations (FILE *file,
       offset = rels[i].r_offset;
       info   = rels[i].r_info;
 
-      /* The #ifdef BFD64 below is to prevent a compile time warning.
-        We know that if we do not have a 64 bit data type that we
-        will never execute this code anyway.  */
-#ifdef BFD64
-      if (!is_32bit_elf
-         && elf_header.e_machine == EM_MIPS
-         && elf_header.e_ident[EI_DATA] != ELFDATA2MSB)
-       {
-         /* In little-endian objects, r_info isn't really a 64-bit
-            little-endian value: it has a 32-bit little-endian
-            symbol index followed by four individual byte fields.
-            Reorder INFO accordingly.  */
-         info = (((info & 0xffffffff) << 32)
-                 | ((info >> 56) & 0xff)
-                 | ((info >> 40) & 0xff00)
-                 | ((info >> 24) & 0xff0000)
-                 | ((info >> 8) & 0xff000000));
-       }
-#endif /* BFD64 */
-
       type = get_reloc_type (info);
       symtab_index = get_reloc_symindex  (info);
 
@@ -1366,6 +1390,8 @@ get_mips_dynamic_type (unsigned long type)
     case DT_MIPS_COMPACT_SIZE: return "MIPS_COMPACT_SIZE";
     case DT_MIPS_GP_VALUE: return "MIPS_GP_VALUE";
     case DT_MIPS_AUX_DYNAMIC: return "MIPS_AUX_DYNAMIC";
+    case DT_MIPS_PLTGOT: return "MIPS_PLTGOT";
+    case DT_MIPS_RWPLT: return "MIPS_RWPLT";
     default:
       return NULL;
     }
@@ -7020,6 +7046,8 @@ get_mips_symbol_other (unsigned int other)
     {
     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;
     }
 }
@@ -8359,19 +8387,6 @@ debug_apply_relocations (void *file,
          unsigned int    reloc_size;
          unsigned char * loc;
 
-         /* In MIPS little-endian objects, r_info isn't really a
-            64-bit little-endian value: it has a 32-bit little-endian
-            symbol index followed by four individual byte fields.
-            Reorder INFO accordingly.  */
-         if (!is_32bit_elf
-             && elf_header.e_machine == EM_MIPS
-             && elf_header.e_ident[EI_DATA] != ELFDATA2MSB)
-           rp->r_info = (((rp->r_info & 0xffffffff) << 32)
-                         | ((rp->r_info >> 56) & 0xff)
-                         | ((rp->r_info >> 40) & 0xff00)
-                         | ((rp->r_info >> 24) & 0xff0000)
-                         | ((rp->r_info >> 8) & 0xff000000));
-
          reloc_type = get_reloc_type (rp->r_info);
 
          if (is_32bit_abs_reloc (reloc_type)
@@ -9204,6 +9219,28 @@ print_mips_got_entry (unsigned char *data, bfd_vma pltgot, bfd_vma addr)
   return addr + (is_32bit_elf ? 4 : 8);
 }
 
+/* DATA points to the contents of a MIPS PLT GOT that starts at VMA
+   PLTGOT.  Print the Address and Initial fields of an entry at VMA
+   ADDR and return the VMA of the next entry.  */
+
+static bfd_vma
+print_mips_pltgot_entry (unsigned char *data, bfd_vma pltgot, bfd_vma addr)
+{
+  printf ("  ");
+  print_vma (addr, LONG_HEX);
+  printf (" ");
+  if (data == NULL)
+    printf ("%*s", is_32bit_elf ? 8 : 16, "<unknown>");
+  else
+    {
+      bfd_vma entry;
+
+      entry = byte_get (data + addr - pltgot, is_32bit_elf ? 4 : 8);
+      print_vma (entry, LONG_HEX);
+    }
+  return addr + (is_32bit_elf ? 4 : 8);
+}
+
 static int
 process_mips_specific (FILE *file)
 {
@@ -9213,7 +9250,11 @@ process_mips_specific (FILE *file)
   size_t conflictsno = 0;
   size_t options_offset = 0;
   size_t conflicts_offset = 0;
+  size_t pltrelsz = 0;
+  size_t pltrel = 0;
   bfd_vma pltgot = 0;
+  bfd_vma mips_pltgot = 0;
+  bfd_vma jmprel = 0;
   bfd_vma local_gotno = 0;
   bfd_vma gotsym = 0;
   bfd_vma symtabno = 0;
@@ -9249,7 +9290,8 @@ process_mips_specific (FILE *file)
        conflictsno = entry->d_un.d_val;
        break;
       case DT_PLTGOT:
-       pltgot = entry->d_un.d_val;
+       pltgot = entry->d_un.d_ptr;
+       break;
       case DT_MIPS_LOCAL_GOTNO:
        local_gotno = entry->d_un.d_val;
        break;
@@ -9259,6 +9301,18 @@ process_mips_specific (FILE *file)
       case DT_MIPS_SYMTABNO:
        symtabno = entry->d_un.d_val;
        break;
+      case DT_MIPS_PLTGOT:
+       mips_pltgot = entry->d_un.d_ptr;
+       break;
+      case DT_PLTREL:
+       pltrel = entry->d_un.d_val;
+       break;
+      case DT_PLTRELSZ:
+       pltrelsz = entry->d_un.d_val;
+       break;
+      case DT_JMPREL:
+       jmprel = entry->d_un.d_ptr;
+       break;
       default:
        break;
       }
@@ -9691,6 +9745,73 @@ process_mips_specific (FILE *file)
        free (data);
     }
 
+  if (mips_pltgot != 0 && jmprel != 0 && pltrel != 0 && pltrelsz != 0)
+    {
+      bfd_vma entry, end;
+      size_t offset, rel_offset;
+      unsigned long count, i;
+      unsigned char *data;
+      int addr_size, sym_width;
+      Elf_Internal_Rela *rels;
+
+      rel_offset = offset_from_vma (file, jmprel, pltrelsz);
+      if (pltrel == DT_RELA)
+       {
+         if (!slurp_rela_relocs (file, rel_offset, pltrelsz, &rels, &count))
+           return 0;
+       }
+      else
+       {
+         if (!slurp_rel_relocs (file, rel_offset, pltrelsz, &rels, &count))
+           return 0;
+       }
+
+      entry = mips_pltgot;
+      addr_size = (is_32bit_elf ? 4 : 8);
+      end = mips_pltgot + (2 + count) * addr_size;
+
+      offset = offset_from_vma (file, mips_pltgot, end - mips_pltgot);
+      data = get_data (NULL, file, offset, end - mips_pltgot, 1, _("PLT GOT"));
+      printf (_("\nPLT GOT:\n\n"));
+      printf (_(" Reserved entries:\n"));
+      printf (_("  %*s %*s Purpose\n"),
+             addr_size * 2, "Address", addr_size * 2, "Initial");
+      entry = print_mips_pltgot_entry (data, mips_pltgot, entry);
+      printf (" PLT lazy resolver\n");
+      entry = print_mips_pltgot_entry (data, mips_pltgot, entry);
+      printf (" Module pointer\n");
+      printf ("\n");
+
+      printf (_(" Entries:\n"));
+      printf (_("  %*s %*s %*s %-7s %3s %s\n"),
+             addr_size * 2, "Address",
+             addr_size * 2, "Initial",
+             addr_size * 2, "Sym.Val.", "Type", "Ndx", "Name");
+      sym_width = (is_32bit_elf ? 80 : 160) - 17 - addr_size * 6 - 1;
+      for (i = 0; i < count; i++)
+       {
+         Elf_Internal_Sym *psym;
+
+         psym = dynamic_symbols + get_reloc_symindex (rels[i].r_info);
+         entry = print_mips_pltgot_entry (data, mips_pltgot, entry);
+         printf (" ");
+         print_vma (psym->st_value, LONG_HEX);
+         printf (" %-7s %3s ",
+                 get_symbol_type (ELF_ST_TYPE (psym->st_info)),
+                 get_symbol_index_type (psym->st_shndx));
+         if (VALID_DYNAMIC_NAME (psym->st_name))
+           print_symbol (sym_width, GET_DYNAMIC_NAME (psym->st_name));
+         else
+           printf ("<corrupt: %14ld>", psym->st_name);
+         printf ("\n");
+       }
+      printf ("\n");
+
+      if (data)
+       free (data);
+      free (rels);
+    }
+
   return 1;
 }
 
index a62f032398f9cf48d632ce15dec0da78d147e726..da59bd8c21e156d0a21de74670e8dc953c204566 100644 (file)
@@ -1,3 +1,14 @@
+2008-08-08  Richard Sandiford  <rdsandiford@googlemail.com>
+           Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * 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.
+
 2008-08-08  Sterling Augustine  <sterling@tensilica.com>
        
        * config/tc-xtensa.c (exclude_section_from_property_tables): New.
index c03cca2e0465d55087198d71c4a8631be8bf1f16..f55961b413d7f2778dcf9e460aa5e8884ae3d04c 100644 (file)
@@ -11231,27 +11231,29 @@ struct option md_longopts[] =
 #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 @@ MIPS options:\n\
 #ifdef OBJ_ELF
   fprintf (stream, _("\
 -KPIC, -call_shared    generate SVR4 position independent code\n\
+-call_nonpic           generate non-PIC code that can 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 can 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 e75b7cf50a49445fc0204964d57e07a7aa3b4554..2dc0d384d7faf75018c65d4a0a98b66d9b4c1ad3 100644 (file)
@@ -1,3 +1,8 @@
+2008-08-08  Richard Sandiford  <rdsandiford@googlemail.com>
+
+       * gas/mips/call-nonpic-1.s, gas/mips/call-nonpic-1.d: New test.
+       * gas/mips/mips.exp: Run it.
+
 2008-08-06  Richard Sandiford  <rdsandiford@googlemail.com>
 
        * gas/mips/elf-rel8-mips16.d, gas/mips/elf-rel8-mips16.s,
diff --git a/gas/testsuite/gas/mips/call-nonpic-1.d b/gas/testsuite/gas/mips/call-nonpic-1.d
new file mode 100644 (file)
index 0000000..61d2b09
--- /dev/null
@@ -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
diff --git a/gas/testsuite/gas/mips/call-nonpic-1.s b/gas/testsuite/gas/mips/call-nonpic-1.s
new file mode 100644 (file)
index 0000000..27239d4
--- /dev/null
@@ -0,0 +1,2 @@
+       la      $25,foo
+       jalr    $25
index 3c4a9192079af95bdcecad256d7bc4bdd8a47f04..a037a998a5e8ca541dcd45c2cf74a4d6b73d4e71 100644 (file)
@@ -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 92b888a01779b886674a59808caa7ec50cdc6177..407c5ec67155839042429612ec3bac74bc906d0a 100644 (file)
@@ -1,3 +1,11 @@
+2008-08-08  Richard Sandiford  <rdsandiford@googlemail.com>
+           Daniel Jacobowitz  <dan@codesourcery.com>
+           Catherine Moore  <clm@codesourcery.com>
+           Mark Shinwell  <shinwell@codesourcery.com>
+
+       * mips.h (STO_MIPS_PLT, ELF_ST_IS_MIPS_PLT, ELF_ST_SET_MIPS_PLT)
+       (STO_MIPS_PIC, DT_MIPS_PLTGOT, DT_MIPS_RWPLT): New macros.
+
 2008-08-04  Markus Weiss  <weissms@aros.org>
 
        * common.h (ELFOSABI_AROS): Update comment.
index 474f54ff4e803f1e1fbde632fc89283630feb9f1..4ec7816f4b74562a7abce1d6865571eb1e25340a 100644 (file)
@@ -662,6 +662,12 @@ extern void bfd_mips_elf32_swap_reginfo_out
 
 /* Address of auxiliary .dynamic.  */
 #define DT_MIPS_AUX_DYNAMIC    0x70000031
+
+/* Address of the base of the PLTGOT.  */
+#define DT_MIPS_PLTGOT         0x70000032
+
+/* Points to the base of a writable PLT.  */
+#define DT_MIPS_RWPLT          0x70000034
 \f
 /* Flags which may appear in a DT_MIPS_FLAGS entry.  */
 
@@ -723,6 +729,20 @@ extern void bfd_mips_elf32_swap_reginfo_out
 #define STO_HIDDEN             STV_HIDDEN
 #define STO_PROTECTED          STV_PROTECTED
 
+/* The MIPS psABI was updated in 2008 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           0x8
+
+/* 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 a6a68042082edf5418001d16506d7a3dd6721b2d..41f43fbfcfa86dfa45930db7f568d3437a881f05 100644 (file)
@@ -1,3 +1,25 @@
+2008-08-08  Richard Sandiford  <rdsandiford@googlemail.com>
+           Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * 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.
+
 2008-08-08  Alan Modra  <amodra@bigpond.net.au>
 
        * ldfile.c (ldfile_open_file_search): Use concat.
index bcb850900124c78d6e388447d52206685f824727..44a0b8a16eecbf64ae65b21af4c19e254d7c630d 100644 (file)
@@ -35,6 +35,25 @@ OTHER_GOT_SYMBOLS='
   . = .;
   _gp = ALIGN(16) + 0x7ff0;
 '
+# .got.plt is only used for the PLT psABI extension.  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 49d2f8545da5e3a36d7294325a621517af9120f5..45bfd5d7883f3c836375f1e8da8c82a536545d95 100644 (file)
@@ -53,6 +53,25 @@ OTHER_GOT_SYMBOLS='
   . = .;
   _gp = ALIGN(16) + 0x7ff0;
 '
+# .got.plt is only used for the PLT psABI extension.  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 e7a1be84fb4210ceaa9bc673c59d254b97f0851a..9144c10bebe963327804ca254eab4018ea8f2c4e 100644 (file)
 # 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 92947721ea65e6919297e7fe420b515676f61c57..37e6fc2dc0c60451f22e05f53c27684ebacc70de 100644 (file)
@@ -1,3 +1,90 @@
+2008-08-08  Richard Sandiford  <rdsandiford@googlemail.com>
+           Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * 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.
+
 2008-08-07  Richard Sandiford  <rdsandiford@googlemail.com>
 
        * ld-mips-elf/tls-hidden4.got, ld-mips-elf/tls-hidden4.r: We have
index 368335a39b052775788525a994ed8796c966eafa..72964f93b424c8daaf57f5928b583460c7aca2b8 100644 (file)
@@ -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,114 @@ 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 -A pic-and-nonpic-5b.gd}
+         {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 -A pic-and-nonpic-6-${abi}.gd" \
+                     "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 } {
diff --git a/ld/testsuite/ld-mips-elf/mips16-pic-3.dd b/ld/testsuite/ld-mips-elf/mips16-pic-3.dd
new file mode 100644 (file)
index 0000000..93ba085
--- /dev/null
@@ -0,0 +1,265 @@
+
+.*
+
+
+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 <.*>:
+.*:    3c1c0005        lui     gp,0x5
+.*:    8f990400        lw      t9,1024\(gp\)
+.*:    279c0400        addiu   gp,gp,1024
+.*:    031cc023        subu    t8,t8,gp
+.*:    03e07821        move    t7,ra
+.*:    0018c082        srl     t8,t8,0x2
+.*:    0320f809        jalr    t9
+.*:    2718fffe        addiu   t8,t8,-2
+
+00040620 <extern3@plt>:
+.*:    3c0f0005        lui     t7,0x5
+.*:    8df90408        lw      t9,1032\(t7\)
+.*:    25f80408        addiu   t8,t7,1032
+.*:    03200008        jr      t9
+
+00040630 <extern2@plt>:
+.*:    3c0f0005        lui     t7,0x5
+.*:    8df9040c        lw      t9,1036\(t7\)
+.*:    25f8040c        addiu   t8,t7,1036
+.*:    03200008        jr      t9
+
+00040640 <extern4@plt>:
+.*:    3c0f0005        lui     t7,0x5
+.*:    8df90410        lw      t9,1040\(t7\)
+.*:    25f80410        addiu   t8,t7,1040
+.*:    03200008        jr      t9
+
+00040650 <extern1@plt>:
+.*:    3c0f0005        lui     t7,0x5
+.*:    8df90414        lw      t9,1044\(t7\)
+.*:    25f80414        addiu   t8,t7,1044
+.*:    03200008        jr      t9
+.*:    00000000        nop
diff --git a/ld/testsuite/ld-mips-elf/mips16-pic-3.gd b/ld/testsuite/ld-mips-elf/mips16-pic-3.gd
new file mode 100644 (file)
index 0000000..9297fe6
--- /dev/null
@@ -0,0 +1,23 @@
+
+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\)
+
+
+PLT GOT:
+
+ Reserved entries:
+   Address  Initial Purpose
+  00050400 00000000 PLT lazy resolver
+  00050404 00000000 Module pointer
+
+ Entries:
+   Address  Initial Sym.Val. Type    Ndx Name
+  00050408 00040600 00040620 FUNC    UND extern3
+  0005040c 00040600 00040630 FUNC    UND extern2
+  00050410 00040600 00040640 FUNC    UND extern4
+  00050414 00040600 00040650 FUNC    UND extern1
diff --git a/ld/testsuite/ld-mips-elf/mips16-pic-3.inc b/ld/testsuite/ld-mips-elf/mips16-pic-3.inc
new file mode 100644 (file)
index 0000000..9611611
--- /dev/null
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/mips16-pic-3.rd b/ld/testsuite/ld-mips-elf/mips16-pic-3.rd
new file mode 100644 (file)
index 0000000..6293cf7
--- /dev/null
@@ -0,0 +1,7 @@
+
+Relocation section '\.rel\.plt' at offset .* contains 4 entries:
+ Offset     Info    Type            Sym\.Value  Sym\. Name
+00050408  .*7f R_MIPS_JUMP_SLOT  00040620   extern3
+0005040c  .*7f R_MIPS_JUMP_SLOT  00040630   extern2
+00050410  .*7f R_MIPS_JUMP_SLOT  00040640   extern4
+00050414  .*7f R_MIPS_JUMP_SLOT  00040650   extern1
diff --git a/ld/testsuite/ld-mips-elf/mips16-pic-3a.s b/ld/testsuite/ld-mips-elf/mips16-pic-3a.s
new file mode 100644 (file)
index 0000000..bbe3a67
--- /dev/null
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/mips16-pic-3b.s b/ld/testsuite/ld-mips-elf/mips16-pic-3b.s
new file mode 100644 (file)
index 0000000..3003145
--- /dev/null
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-1-rel.dd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-1-rel.dd
new file mode 100644 (file)
index 0000000..4d15a58
--- /dev/null
@@ -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
+       ...
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-1-rel.nd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-1-rel.nd
new file mode 100644 (file)
index 0000000..c5f0b51
--- /dev/null
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-1.dd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-1.dd
new file mode 100644 (file)
index 0000000..9d5b1db
--- /dev/null
@@ -0,0 +1,46 @@
+
+.*
+
+Disassembly of section \.text:
+
+00041000 <\.pic\.f2>:
+   41000:      3c190004        lui     t9,0x4
+   41004:      0801040f        j       4103c <f2>
+   41008:      2739103c        addiu   t9,t9,4156
+       \.\.\.
+
+00041018 <\.pic\.f1>:
+   41018:      3c190004        lui     t9,0x4
+   4101c:      27391020        addiu   t9,t9,4128
+
+00041020 <f1>:
+   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 <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 <\.pic\.f1>
+   41064:      00000000        nop
+   41068:      0c010400        jal     41000 <\.pic\.f2>
+   4106c:      00000000        nop
+   41070:      74010414        jalx    41050 <f3>
+   41074:      00000000        nop
+       \.\.\.
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-1.ld b/ld/testsuite/ld-mips-elf/pic-and-nonpic-1.ld
new file mode 100644 (file)
index 0000000..3aa140e
--- /dev/null
@@ -0,0 +1,9 @@
+SECTIONS
+{
+  . = 0x40000;
+  .reginfo : { *(.reginfo) }
+  .pdr : { *(.pdr) }
+  . = 0x41000;
+  .text : { *(.text) }
+  _gp = 0x68000;
+}
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-1.nd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-1.nd
new file mode 100644 (file)
index 0000000..506685a
--- /dev/null
@@ -0,0 +1,9 @@
+#...
+.*: 00041018     8 FUNC    LOCAL  DEFAULT .* .pic.f1
+.*: 00041000    16 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
+.*: 0004103c    20 FUNC    GLOBAL DEFAULT .* f2
+.*: 00041020    28 FUNC    GLOBAL DEFAULT .* f1
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-1a.s b/ld/testsuite/ld-mips-elf/pic-and-nonpic-1a.s
new file mode 100644 (file)
index 0000000..c54030e
--- /dev/null
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-1b.s b/ld/testsuite/ld-mips-elf/pic-and-nonpic-1b.s
new file mode 100644 (file)
index 0000000..5739fef
--- /dev/null
@@ -0,0 +1,9 @@
+       .abicalls
+       .option pic0
+       .global __start
+       .ent    __start
+__start:
+       jal     f1
+       jal     f2
+       jal     f3
+       .end    __start
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-2.d b/ld/testsuite/ld-mips-elf/pic-and-nonpic-2.d
new file mode 100644 (file)
index 0000000..da28cc3
--- /dev/null
@@ -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 <\.pic\.foo@@V2>
+   41004:      00000000        nop
+       \.\.\.
+
+00041018 <\.pic\.foo@@V2>:
+   41018:      3c190004        lui     t9,0x4
+   4101c:      27391020        addiu   t9,t9,4128
+
+00041020 <foo2>:
+   41020:      03e00008        jr      ra
+   41024:      00000000        nop
+       \.\.\.
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-2a.s b/ld/testsuite/ld-mips-elf/pic-and-nonpic-2a.s
new file mode 100644 (file)
index 0000000..45a490f
--- /dev/null
@@ -0,0 +1,7 @@
+       .abicalls
+       .option pic0
+       .global __start
+       .ent    __start
+__start:
+       jal     foo
+       .end    __start
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-2b.s b/ld/testsuite/ld-mips-elf/pic-and-nonpic-2b.s
new file mode 100644 (file)
index 0000000..4770b22
--- /dev/null
@@ -0,0 +1,6 @@
+       .abicalls
+       .symver foo2,foo@@V2
+       .global foo2
+       .ent    foo2
+foo2:  jr      $31
+       .end    foo2
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-3-error.d b/ld/testsuite/ld-mips-elf/pic-and-nonpic-3-error.d
new file mode 100644 (file)
index 0000000..975ffa7
--- /dev/null
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-3a.dd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-3a.dd
new file mode 100644 (file)
index 0000000..320e4ca
--- /dev/null
@@ -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
+       \.\.\.
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-3a.gd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-3a.gd
new file mode 100644 (file)
index 0000000..aa9579b
--- /dev/null
@@ -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
+
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-3a.ld b/ld/testsuite/ld-mips-elf/pic-and-nonpic-3a.ld
new file mode 100644 (file)
index 0000000..cc4bd55
--- /dev/null
@@ -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) }
+}
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-3a.s b/ld/testsuite/ld-mips-elf/pic-and-nonpic-3a.s
new file mode 100644 (file)
index 0000000..385e7fd
--- /dev/null
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-3a.sd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-3a.sd
new file mode 100644 (file)
index 0000000..58b50c3
--- /dev/null
@@ -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 *
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.ad b/ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.ad
new file mode 100644 (file)
index 0000000..fdcc0b1
--- /dev/null
@@ -0,0 +1,27 @@
+
+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\) * 3
+# 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\)
+ 0x70000032 \(MIPS_PLTGOT\) * 0x81000
+ 0x00000000 \(NULL\) * 0x0
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.dd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.dd
new file mode 100644 (file)
index 0000000..b0dfafc
--- /dev/null
@@ -0,0 +1,53 @@
+# GOT layout:
+#
+# -32752: lazy resolution function
+# -32748: reserved for module pointer
+# -32744: GOT page entry.
+# -32740: bar's GOT entry
+
+.*
+
+Disassembly of section \.plt:
+
+00043020 <.*>:
+.*:    3c1c0008        lui     gp,0x8
+.*:    8f991000        lw      t9,4096\(gp\)
+.*:    279c1000        addiu   gp,gp,4096
+.*:    031cc023        subu    t8,t8,gp
+.*:    03e07821        move    t7,ra
+.*:    0018c082        srl     t8,t8,0x2
+.*:    0320f809        jalr    t9
+.*:    2718fffe        addiu   t8,t8,-2
+
+00043040 <foo@plt>:
+.*:    3c0f0008        lui     t7,0x8
+.*:    8df91008        lw      t9,4104\(t7\)
+.*:    25f81008        addiu   t8,t7,4104
+.*:    03200008        jr      t9
+.*:    00000000        nop
+
+Disassembly of section \.text:
+
+00044000 <__start>:
+.*:    0c010c10        jal     43040 <foo@plt>
+.*:    00000000        nop
+.*:    08011004        j       44010 <ext>
+.*:    00000000        nop
+
+00044010 <ext>:
+.*:    3c1c000a        lui     gp,0xa
+.*:    279c7ff0        addiu   gp,gp,32752
+.*:    8f828018        lw      v0,-32744\(gp\)
+.*:    24421000        addiu   v0,v0,4096
+.*:    8f99801c        lw      t9,-32740\(gp\)
+.*:    03200008        jr      t9
+.*:    00000000        nop
+.*:    00000000        nop
+Disassembly of section .MIPS.stubs:
+
+00044030 <\.MIPS\.stubs>:
+.*:    8f998010        lw      t9,-32752\(gp\)
+.*:    03e07821        move    t7,ra
+.*:    0320f809        jalr    t9
+.*:    24180007        li      t8,7
+       \.\.\.
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.gd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.gd
new file mode 100644 (file)
index 0000000..6d3d677
--- /dev/null
@@ -0,0 +1,28 @@
+
+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\)
+
+ Local entries:
+   Address     Access  Initial
+  000a0008 -32744\(gp\) 000a0000
+
+ Global entries:
+   Address     Access  Initial Sym\.Val\. Type    Ndx Name
+  000a000c -32740\(gp\) 00044030 00044030 FUNC    UND bar
+
+
+PLT GOT:
+
+ Reserved entries:
+   Address  Initial Purpose
+  00081000 00000000 PLT lazy resolver
+  00081004 00000000 Module pointer
+
+ Entries:
+   Address  Initial Sym.Val. Type    Ndx Name
+  00081008 00043020 00000000 FUNC    UND foo
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.ld b/ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.ld
new file mode 100644 (file)
index 0000000..d41c8f9
--- /dev/null
@@ -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) }
+}
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.nd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.nd
new file mode 100644 (file)
index 0000000..f115be5
--- /dev/null
@@ -0,0 +1,9 @@
+
+Symbol table '\.dynsym' contains .*:
+#...
+.*: 00000000 * 0 * FUNC * GLOBAL * DEFAULT * UND * foo
+# The index on the next line should correspond to MIPS_GOTSYM.
+#...
+ *7: 00044030 * 0 * FUNC * GLOBAL * DEFAULT * UND * bar
+
+#pass
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.pd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.pd
new file mode 100644 (file)
index 0000000..00f8713
--- /dev/null
@@ -0,0 +1,5 @@
+
+.*
+
+Contents of section \.got\.plt:
+ 81000 00000000 00000000 00043020          .*
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.rd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.rd
new file mode 100644 (file)
index 0000000..d3418db
--- /dev/null
@@ -0,0 +1,4 @@
+
+Relocation section '\.rel\.plt' at offset .* contains .*:
+ * Offset * Info * Type * Sym\.Value * Sym\. Name
+00081008 * 0000057f * R_MIPS_JUMP_SLOT * 00000000 * foo
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.s b/ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.s
new file mode 100644 (file)
index 0000000..571c774
--- /dev/null
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.sd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-3b.sd
new file mode 100644 (file)
index 0000000..c73ac59
--- /dev/null
@@ -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 *
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-4-error.d b/ld/testsuite/ld-mips-elf/pic-and-nonpic-4-error.d
new file mode 100644 (file)
index 0000000..7bc0c25
--- /dev/null
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-4a.s b/ld/testsuite/ld-mips-elf/pic-and-nonpic-4a.s
new file mode 100644 (file)
index 0000000..54b285a
--- /dev/null
@@ -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
+
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.ad b/ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.ad
new file mode 100644 (file)
index 0000000..ad300b4
--- /dev/null
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.dd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.dd
new file mode 100644 (file)
index 0000000..d276098
--- /dev/null
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.gd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.gd
new file mode 100644 (file)
index 0000000..0a8a77d
--- /dev/null
@@ -0,0 +1,7 @@
+
+.*
+
+Contents of section \.got:
+ a0000 00000000 80000000 00000000           .*
+Contents of section \.data:
+ a1000 000a2008 00000000 00000000 00000000  .*
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.ld b/ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.ld
new file mode 100644 (file)
index 0000000..bcf9e3a
--- /dev/null
@@ -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) }
+}
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.nd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.nd
new file mode 100644 (file)
index 0000000..d63426c
--- /dev/null
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.rd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.rd
new file mode 100644 (file)
index 0000000..452d9c7
--- /dev/null
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.s b/ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.s
new file mode 100644 (file)
index 0000000..7e25bf4
--- /dev/null
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.sd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-4b.sd
new file mode 100644 (file)
index 0000000..14b13ed
--- /dev/null
@@ -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 *
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-5a.s b/ld/testsuite/ld-mips-elf/pic-and-nonpic-5a.s
new file mode 100644 (file)
index 0000000..7452f5e
--- /dev/null
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.ad b/ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.ad
new file mode 100644 (file)
index 0000000..e448ec2
--- /dev/null
@@ -0,0 +1,32 @@
+
+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\) * 2
+# 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\)
+ 0x70000032 \(MIPS_PLTGOT\) * 0x81000
+ 0x00000000 \(NULL\) * 0x0
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.dd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.dd
new file mode 100644 (file)
index 0000000..ff18883
--- /dev/null
@@ -0,0 +1,35 @@
+
+.*
+
+Disassembly of section \.plt:
+
+00043040 <.*>:
+.*:    3c1c0008        lui     gp,0x8
+.*:    8f991000        lw      t9,4096\(gp\)
+.*:    279c1000        addiu   gp,gp,4096
+.*:    031cc023        subu    t8,t8,gp
+.*:    03e07821        move    t7,ra
+.*:    0018c082        srl     t8,t8,0x2
+.*:    0320f809        jalr    t9
+.*:    2718fffe        addiu   t8,t8,-2
+
+00043060 <foo@plt>:
+.*:    3c0f0008        lui     t7,0x8
+.*:    8df91008        lw      t9,4104\(t7\)
+.*:    25f81008        addiu   t8,t7,4104
+.*:    03200008        jr      t9
+.*:    00000000        nop
+
+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        .*
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.gd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.gd
new file mode 100644 (file)
index 0000000..6919a69
--- /dev/null
@@ -0,0 +1,26 @@
+
+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\)
+
+# There must be GOT entries for the R_MIPS_REL32 relocation symbols.
+ Global entries:
+   Address     Access  Initial Sym\.Val\. Type    Ndx Name
+  000a0008 -32744\(gp\) 00000000 00000000 OBJECT  UND obj2
+  000a000c -32740\(gp\) 00000000 00000000 FUNC    UND bar
+
+
+PLT GOT:
+
+ Reserved entries:
+   Address  Initial Purpose
+  00081000 00000000 PLT lazy resolver
+  00081004 00000000 Module pointer
+
+ Entries:
+   Address  Initial Sym.Val. Type    Ndx Name
+  00081008 00043040 00043060 FUNC    UND foo
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.ld b/ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.ld
new file mode 100644 (file)
index 0000000..6cb7530
--- /dev/null
@@ -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) }
+}
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.nd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.nd
new file mode 100644 (file)
index 0000000..5622f91
--- /dev/null
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.pd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.pd
new file mode 100644 (file)
index 0000000..73b2059
--- /dev/null
@@ -0,0 +1,7 @@
+
+.*
+
+Contents of section \.got\.plt:
+ 81000 00000000 00000000 00043040           .*
+Contents of section \.data:
+ a1000 00043060 00000000 000a2000 00000000  .*
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.rd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.rd
new file mode 100644 (file)
index 0000000..21b2961
--- /dev/null
@@ -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
+00081008 * [^ ]*7f * R_MIPS_JUMP_SLOT * 00043060 * foo
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.s b/ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.s
new file mode 100644 (file)
index 0000000..73b518f
--- /dev/null
@@ -0,0 +1,9 @@
+       .abicalls
+       .global ext
+       .ent    ext
+ext:
+       .word   foo
+       .word   bar
+       .word   obj1
+       .word   obj2
+       .end    ext
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.sd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-5b.sd
new file mode 100644 (file)
index 0000000..b7d7e3a
--- /dev/null
@@ -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 *
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.ad b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.ad
new file mode 100644 (file)
index 0000000..4be2ac0
--- /dev/null
@@ -0,0 +1,27 @@
+
+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\) * 2
+ 0x70000011 \(MIPS_SYMTABNO\) * 14
+ 0x70000012 \(MIPS_UNREFEXTNO\) * .*
+ 0x70000013 \(MIPS_GOTSYM\) * 0x7
+ 0x00000014 \(PLTREL\) * REL
+ 0x00000017 \(JMPREL\) * 0x43028
+ 0x00000002 \(PLTRELSZ\) * 24 \(bytes\)
+ 0x70000032 \(MIPS_PLTGOT\) * 0x81000
+ 0x00000000 \(NULL\) * 0x0
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.dd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.dd
new file mode 100644 (file)
index 0000000..068e5b3
--- /dev/null
@@ -0,0 +1,102 @@
+# GOT layout:
+#
+# -32752: lazy resolution function
+# -32748: reserved for module pointer
+# -32744: extf2's GOT entry (undefined 0)
+# -32740: extf3's GOT entry (PLT entry)
+# -32736: extd2's GOT entry (copy reloc)
+# -32732: extf1's GOT entry (.MIPS.stubs entry)
+# -32728: extd1's GOT entry (undefined 0)
+# -32724: extf4's GOT entry (PLT entry)
+# -32620: extd4's GOT entry (undefined 0, reloc only)
+
+.*
+
+Disassembly of section \.plt:
+
+00043040 <.*>:
+.*:    3c0e0008        lui     t2,0x8
+.*:    8dd91000        lw      t9,4096\(t2\)
+.*:    25ce1000        addiu   t2,t2,4096
+.*:    030ec023        subu    t8,t8,t2
+.*:    03e07821        move    t3,ra
+.*:    0018c082        srl     t8,t8,0x2
+.*:    0320f809        jalr    t9
+.*:    2718fffe        addiu   t8,t8,-2
+
+00043060 <extf4@plt>:
+.*:    3c0f0008        lui     t3,0x8
+.*:    8df91008        lw      t9,4104\(t3\)
+.*:    25f81008        addiu   t8,t3,4104
+.*:    03200008        jr      t9
+
+00043070 <extf5@plt>:
+.*:    3c0f0008        lui     t3,0x8
+.*:    8df9100c        lw      t9,4108\(t3\)
+.*:    25f8100c        addiu   t8,t3,4108
+.*:    03200008        jr      t9
+
+00043080 <extf3@plt>:
+.*:    3c0f0008        lui     t3,0x8
+.*:    8df91010        lw      t9,4112\(t3\)
+.*:    25f81010        addiu   t8,t3,4112
+.*:    03200008        jr      t9
+.*:    00000000        nop
+
+Disassembly of section \.text:
+
+00044000 <.*>:
+       \.\.\.
+
+00044008 <\.pic\.f1>:
+   44008:      3c190004        lui     t9,0x4
+   4400c:      27394010        addiu   t9,t9,16400
+
+00044010 <f1>:
+   44010:      0c011013        jal     4404c <f3>
+   44014:      3c020004        lui     v0,0x4
+   44018:      03e00008        jr      ra
+   4401c:      24424020        addiu   v0,v0,16416
+
+00044020 <f2>:
+   44020:      3c1c0006        lui     gp,0x6
+   44024:      0399e021        addu    gp,gp,t9
+   44028:      279c3fd0        addiu   gp,gp,16336
+   4402c:      8f998024        lw      t9,-32732\(gp\)
+   44030:      8f848018        lw      a0,-32744\(gp\)
+   44034:      8f858028        lw      a1,-32728\(gp\)
+   44038:      0320f809        jalr    t9
+   4403c:      8f868020        lw      a2,-32736\(gp\)
+   44040:      8f99801c        lw      t9,-32740\(gp\)
+   44044:      03200008        jr      t9
+   44048:      8f84802c        lw      a0,-32724\(gp\)
+
+0004404c <f3>:
+   4404c:      03e00008        jr      ra
+   44050:      00000000        nop
+       \.\.\.
+
+00044060 <__start>:
+   44060:      0c011002        jal     44008 <\.pic\.f1>
+   44064:      00000000        nop
+   44068:      3c020004        lui     v0,0x4
+   4406c:      24424020        addiu   v0,v0,16416
+   44070:      0c010c20        jal     43080 <extf3@plt>
+   44074:      00000000        nop
+   44078:      0c010c18        jal     43060 <extf4@plt>
+   4407c:      00000000        nop
+   44080:      0c010c1c        jal     43070 <extf5@plt>
+   44084:      00000000        nop
+   44088:      3c02000a        lui     v0,0xa
+   4408c:      24422000        addiu   v0,v0,8192
+   44090:      3c02000a        lui     v0,0xa
+   44094:      24422018        addiu   v0,v0,8216
+       \.\.\.
+Disassembly of section \.MIPS\.stubs:
+
+000440a0 <\.MIPS\.stubs>:
+   440a0:      8f998010        lw      t9,-32752\(gp\)
+   440a4:      03e07821        move    t3,ra
+   440a8:      0320f809        jalr    t9
+   440ac:      2418000a        li      t8,10
+       \.\.\.
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.gd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.gd
new file mode 100644 (file)
index 0000000..8b6b5a0
--- /dev/null
@@ -0,0 +1,32 @@
+
+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\)
+
+ Global entries:
+   Address     Access  Initial Sym\.Val\. Type    Ndx Name
+  000a0008 -32744\(gp\) 00000000 00000000 FUNC    UND extf2
+  000a000c -32740\(gp\) 00000000 00000000 FUNC    UND extf3
+  000a0010 -32736\(gp\) 000a2000 000a2000 OBJECT   16 extd2
+  000a0014 -32732\(gp\) 000440a0 000440a0 FUNC    UND extf1
+  000a0018 -32728\(gp\) 00000000 00000000 OBJECT  UND extd1
+  000a001c -32724\(gp\) 00000000 00000000 FUNC    UND extf4
+  000a0020 -32720\(gp\) 00000000 00000000 OBJECT  UND extd4
+
+
+PLT GOT:
+
+ Reserved entries:
+   Address  Initial Purpose
+  00081000 00000000 PLT lazy resolver
+  00081004 00000000 Module pointer
+
+ Entries:
+   Address  Initial Sym.Val. Type    Ndx Name
+  00081008 00043040 00000000 FUNC    UND extf4
+  0008100c 00043040 00000000 FUNC    UND extf5
+  00081010 00043040 00000000 FUNC    UND extf3
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.nd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.nd
new file mode 100644 (file)
index 0000000..8b0d0a6
--- /dev/null
@@ -0,0 +1,17 @@
+
+Symbol table '\.dynsym' contains .*:
+#...
+.*: 00000000 * 0 * FUNC * GLOBAL * DEFAULT * 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+ * 0 * * FUNC * GLOBAL * DEFAULT * UND * extf3
+ *9: 0+a2000 * 24 * OBJECT * GLOBAL * DEFAULT * [0-9]+ * extd2
+ *10: 0+440a0 * 0 * FUNC * GLOBAL * DEFAULT * UND * extf1
+ *11: 0+ * 0 * OBJECT * GLOBAL * DEFAULT * UND * extd1
+ *12: 0+ * 0 * FUNC * GLOBAL * DEFAULT * UND * extf4
+ *13: 0+ * 0 * OBJECT * GLOBAL * DEFAULT * UND * extd4
+
+#pass
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.pd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.pd
new file mode 100644 (file)
index 0000000..5f5de62
--- /dev/null
@@ -0,0 +1,6 @@
+
+.*
+
+Contents of section \.got\.plt:
+ 81000 00000000 00000000 00043040 00043040  .*
+ 81010 00043040                             .*
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.rd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.rd
new file mode 100644 (file)
index 0000000..0fd5b7e
--- /dev/null
@@ -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
+00081008 * [^ ]*7f * R_MIPS_JUMP_SLOT * 00000000 * extf4
+0008100c * [^ ]*7f * R_MIPS_JUMP_SLOT * 00000000 * extf5
+00081010 * [^ ]*7f * R_MIPS_JUMP_SLOT * 00000000 * extf3
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.sd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32.sd
new file mode 100644 (file)
index 0000000..b5d51b3
--- /dev/null
@@ -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 *
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32a.s b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32a.s
new file mode 100644 (file)
index 0000000..a4c0075
--- /dev/null
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32b.s b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32b.s
new file mode 100644 (file)
index 0000000..48cf97f
--- /dev/null
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32c.s b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n32c.s
new file mode 100644 (file)
index 0000000..578626a
--- /dev/null
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.ad b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.ad
new file mode 100644 (file)
index 0000000..2ccb8b8
--- /dev/null
@@ -0,0 +1,27 @@
+
+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\) * 2
+ 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+70000032 \(MIPS_PLTGOT\) * 0x81000
+ 0x0+00000000 \(NULL\) * 0x0
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.dd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.dd
new file mode 100644 (file)
index 0000000..c1a5681
--- /dev/null
@@ -0,0 +1,102 @@
+# GOT layout:
+#
+# -32752: lazy resolution function
+# -32744: reserved for module pointer
+# -32736: extf2's GOT entry (undefined 0)
+# -32728: extf3's GOT entry (PLT entry)
+# -32720: extd2's GOT entry (copy reloc)
+# -32712: extf1's GOT entry (.MIPS.stubs entry)
+# -32704: extd1's GOT entry (undefined 0)
+# -32696: extf4's GOT entry (PLT entry)
+# -32688: extd4's GOT entry (undefined 0, reloc only)
+
+.*
+
+Disassembly of section \.plt:
+
+0+43080 <.*>:
+.*:    3c0e0008        lui     t2,0x8
+.*:    ddd91000        ld      t9,4096\(t2\)
+.*:    25ce1000        addiu   t2,t2,4096
+.*:    030ec023        subu    t8,t8,t2
+.*:    03e07821        move    t3,ra
+.*:    0018c0c2        srl     t8,t8,0x3
+.*:    0320f809        jalr    t9
+.*:    2718fffe        addiu   t8,t8,-2
+
+0+430a0 <extf4@plt>:
+.*:    3c0f0008        lui     t3,0x8
+.*:    ddf91010        ld      t9,4112\(t3\)
+.*:    25f81010        addiu   t8,t3,4112
+.*:    03200008        jr      t9
+
+0+430b0 <extf5@plt>:
+.*:    3c0f0008        lui     t3,0x8
+.*:    ddf91018        ld      t9,4120\(t3\)
+.*:    25f81018        addiu   t8,t3,4120
+.*:    03200008        jr      t9
+
+0+430c0 <extf3@plt>:
+.*:    3c0f0008        lui     t3,0x8
+.*:    ddf91020        ld      t9,4128\(t3\)
+.*:    25f81020        addiu   t8,t3,4128
+.*:    03200008        jr      t9
+.*:    00000000        nop
+
+Disassembly of section \.text:
+
+0+44000 <.*>:
+       \.\.\.
+
+0+44008 <\.pic\.f1>:
+   44008:      3c190004        lui     t9,0x4
+   4400c:      27394010        addiu   t9,t9,16400
+
+0+44010 <f1>:
+   44010:      0c011013        jal     4404c <f3>
+   44014:      3c020004        lui     v0,0x4
+   44018:      03e00008        jr      ra
+   4401c:      24424020        addiu   v0,v0,16416
+
+0+44020 <f2>:
+   44020:      3c1c0006        lui     gp,0x6
+   44024:      0399e021        addu    gp,gp,t9
+   44028:      279c3fd0        addiu   gp,gp,16336
+   4402c:      df998038        ld      t9,-32712\(gp\)
+   44030:      df848020        ld      a0,-32736\(gp\)
+   44034:      df858040        ld      a1,-32704\(gp\)
+   44038:      0320f809        jalr    t9
+   4403c:      df868030        ld      a2,-32720\(gp\)
+   44040:      df998028        ld      t9,-32728\(gp\)
+   44044:      03200008        jr      t9
+   44048:      df848048        ld      a0,-32696\(gp\)
+
+0+4404c <f3>:
+   4404c:      03e00008        jr      ra
+   44050:      00000000        nop
+       \.\.\.
+
+0+44060 <__start>:
+   44060:      0c011002        jal     44008 <\.pic\.f1>
+   44064:      00000000        nop
+   44068:      3c020004        lui     v0,0x4
+   4406c:      24424020        addiu   v0,v0,16416
+   44070:      0c010c30        jal     430c0 <extf3@plt>
+   44074:      00000000        nop
+   44078:      0c010c28        jal     430a0 <extf4@plt>
+   4407c:      00000000        nop
+   44080:      0c010c2c        jal     430b0 <extf5@plt>
+   44084:      00000000        nop
+   44088:      3c02000a        lui     v0,0xa
+   4408c:      24422000        addiu   v0,v0,8192
+   44090:      3c02000a        lui     v0,0xa
+   44094:      24422018        addiu   v0,v0,8216
+       \.\.\.
+Disassembly of section \.MIPS\.stubs:
+
+0+440a0 <\.MIPS\.stubs>:
+   440a0:      df998010        ld      t9,-32752\(gp\)
+   440a4:      03e0782d        move    t3,ra
+   440a8:      0320f809        jalr    t9
+   440ac:      6418000a        daddiu  t8,zero,10
+       \.\.\.
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.gd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.gd
new file mode 100644 (file)
index 0000000..767d150
--- /dev/null
@@ -0,0 +1,32 @@
+
+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\)
+
+ Global entries:
+           Address     Access          Initial         Sym\.Val\. Type    Ndx Name
+  00000000000a0010 -32736\(gp\) 0000000000000000 0000000000000000 FUNC    UND extf2
+  00000000000a0018 -32728\(gp\) 0000000000000000 0000000000000000 FUNC    UND extf3
+  00000000000a0020 -32720\(gp\) 00000000000a2000 00000000000a2000 OBJECT   16 extd2
+  00000000000a0028 -32712\(gp\) 00000000000440a0 00000000000440a0 FUNC    UND extf1
+  00000000000a0030 -32704\(gp\) 0000000000000000 0000000000000000 OBJECT  UND extd1
+  00000000000a0038 -32696\(gp\) 0000000000000000 0000000000000000 FUNC    UND extf4
+  00000000000a0040 -32688\(gp\) 0000000000000000 0000000000000000 OBJECT  UND extd4
+
+
+PLT GOT:
+
+ Reserved entries:
+           Address          Initial Purpose
+  0000000000081000 0000000000000000 PLT lazy resolver
+  0000000000081008 0000000000000000 Module pointer
+
+ Entries:
+           Address          Initial         Sym.Val. Type    Ndx Name
+  0000000000081010 0000000000043080 0000000000000000 FUNC    UND extf4
+  0000000000081018 0000000000043080 0000000000000000 FUNC    UND extf5
+  0000000000081020 0000000000043080 0000000000000000 FUNC    UND extf3
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.nd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.nd
new file mode 100644 (file)
index 0000000..8ee90e4
--- /dev/null
@@ -0,0 +1,17 @@
+
+Symbol table '\.dynsym' contains .*:
+#...
+.*: 0+ * 0 * FUNC * GLOBAL * DEFAULT * 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+ * 0 * FUNC * GLOBAL * DEFAULT * UND * extf3
+ *9: 0+a2000 * 24 * OBJECT * GLOBAL * DEFAULT * [0-9]+ * extd2
+ *10: 0+440a0 * 0 * FUNC * GLOBAL * DEFAULT * UND * extf1
+ *11: 0+ * 0 * OBJECT * GLOBAL * DEFAULT * UND * extd1
+ *12: 0+ * 0 * FUNC * GLOBAL * DEFAULT * UND * extf4
+ *13: 0+ * 0 * OBJECT * GLOBAL * DEFAULT * UND * extd4
+
+#pass
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.pd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.pd
new file mode 100644 (file)
index 0000000..fed9d94
--- /dev/null
@@ -0,0 +1,7 @@
+
+.*
+
+Contents of section \.got\.plt:
+ 81000 00000000 00000000 00000000 00000000  .*
+ 81010 00000000 00043080 00000000 00043080  .*
+ 81020 00000000 00043080                    .*
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.rd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.rd
new file mode 100644 (file)
index 0000000..666785e
--- /dev/null
@@ -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+81010 * [^ ]*7f * R_MIPS_JUMP_SLOT * 0+00000 * extf4
+ *Type2: R_MIPS_NONE *
+ *Type3: R_MIPS_NONE *
+0+81018 * [^ ]*7f * R_MIPS_JUMP_SLOT * 0+00000 * extf5
+ *Type2: R_MIPS_NONE *
+ *Type3: R_MIPS_NONE *
+0+81020 * [^ ]*7f * R_MIPS_JUMP_SLOT * 0+00000 * extf3
+ *Type2: R_MIPS_NONE *
+ *Type3: R_MIPS_NONE *
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.sd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64.sd
new file mode 100644 (file)
index 0000000..3842baa
--- /dev/null
@@ -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 *
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64a.s b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64a.s
new file mode 100644 (file)
index 0000000..a4c0075
--- /dev/null
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64b.s b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64b.s
new file mode 100644 (file)
index 0000000..7a7979c
--- /dev/null
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64c.s b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-n64c.s
new file mode 100644 (file)
index 0000000..578626a
--- /dev/null
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.ad b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.ad
new file mode 100644 (file)
index 0000000..4be2ac0
--- /dev/null
@@ -0,0 +1,27 @@
+
+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\) * 2
+ 0x70000011 \(MIPS_SYMTABNO\) * 14
+ 0x70000012 \(MIPS_UNREFEXTNO\) * .*
+ 0x70000013 \(MIPS_GOTSYM\) * 0x7
+ 0x00000014 \(PLTREL\) * REL
+ 0x00000017 \(JMPREL\) * 0x43028
+ 0x00000002 \(PLTRELSZ\) * 24 \(bytes\)
+ 0x70000032 \(MIPS_PLTGOT\) * 0x81000
+ 0x00000000 \(NULL\) * 0x0
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.dd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.dd
new file mode 100644 (file)
index 0000000..731b8ed
--- /dev/null
@@ -0,0 +1,102 @@
+# GOT layout:
+#
+# -32752: lazy resolution function
+# -32748: reserved for module pointer
+# -32744: extf2's GOT entry (undefined 0)
+# -32740: extf3's GOT entry (PLT entry)
+# -32736: extd2's GOT entry (copy reloc)
+# -32732: extf1's GOT entry (.MIPS.stubs entry)
+# -32728: extd1's GOT entry (undefined 0)
+# -32724: extf4's GOT entry (PLT entry)
+# -32620: extd4's GOT entry (undefined 0, reloc only)
+
+.*
+
+Disassembly of section \.plt:
+
+00043040 <.*>:
+.*:    3c1c0008        lui     gp,0x8
+.*:    8f991000        lw      t9,4096\(gp\)
+.*:    279c1000        addiu   gp,gp,4096
+.*:    031cc023        subu    t8,t8,gp
+.*:    03e07821        move    t7,ra
+.*:    0018c082        srl     t8,t8,0x2
+.*:    0320f809        jalr    t9
+.*:    2718fffe        addiu   t8,t8,-2
+
+00043060 <extf4@plt>:
+.*:    3c0f0008        lui     t7,0x8
+.*:    8df91008        lw      t9,4104\(t7\)
+.*:    25f81008        addiu   t8,t7,4104
+.*:    03200008        jr      t9
+
+00043070 <extf5@plt>:
+.*:    3c0f0008        lui     t7,0x8
+.*:    8df9100c        lw      t9,4108\(t7\)
+.*:    25f8100c        addiu   t8,t7,4108
+.*:    03200008        jr      t9
+
+00043080 <extf3@plt>:
+.*:    3c0f0008        lui     t7,0x8
+.*:    8df91010        lw      t9,4112\(t7\)
+.*:    25f81010        addiu   t8,t7,4112
+.*:    03200008        jr      t9
+.*:    00000000        nop
+
+Disassembly of section \.text:
+
+00044000 <.*>:
+       \.\.\.
+
+00044008 <\.pic\.f1>:
+   44008:      3c190004        lui     t9,0x4
+   4400c:      27394010        addiu   t9,t9,16400
+
+00044010 <f1>:
+   44010:      0c011013        jal     4404c <f3>
+   44014:      3c020004        lui     v0,0x4
+   44018:      03e00008        jr      ra
+   4401c:      24424020        addiu   v0,v0,16416
+
+00044020 <f2>:
+   44020:      3c1c0006        lui     gp,0x6
+   44024:      279c3fd0        addiu   gp,gp,16336
+   44028:      0399e021        addu    gp,gp,t9
+   4402c:      8f998024        lw      t9,-32732\(gp\)
+   44030:      8f848018        lw      a0,-32744\(gp\)
+   44034:      8f858028        lw      a1,-32728\(gp\)
+   44038:      0320f809        jalr    t9
+   4403c:      8f868020        lw      a2,-32736\(gp\)
+   44040:      8f99801c        lw      t9,-32740\(gp\)
+   44044:      03200008        jr      t9
+   44048:      8f84802c        lw      a0,-32724\(gp\)
+
+0004404c <f3>:
+   4404c:      03e00008        jr      ra
+   44050:      00000000        nop
+       \.\.\.
+
+00044060 <__start>:
+   44060:      0c011002        jal     44008 <\.pic\.f1>
+   44064:      00000000        nop
+   44068:      3c020004        lui     v0,0x4
+   4406c:      24424020        addiu   v0,v0,16416
+   44070:      0c010c20        jal     43080 <extf3@plt>
+   44074:      00000000        nop
+   44078:      0c010c18        jal     43060 <extf4@plt>
+   4407c:      00000000        nop
+   44080:      0c010c1c        jal     43070 <extf5@plt>
+   44084:      00000000        nop
+   44088:      3c02000a        lui     v0,0xa
+   4408c:      24422000        addiu   v0,v0,8192
+   44090:      3c02000a        lui     v0,0xa
+   44094:      24422018        addiu   v0,v0,8216
+       \.\.\.
+Disassembly of section \.MIPS\.stubs:
+
+000440a0 <\.MIPS\.stubs>:
+   440a0:      8f998010        lw      t9,-32752\(gp\)
+   440a4:      03e07821        move    t7,ra
+   440a8:      0320f809        jalr    t9
+   440ac:      2418000a        li      t8,10
+       \.\.\.
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.gd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.gd
new file mode 100644 (file)
index 0000000..8b6b5a0
--- /dev/null
@@ -0,0 +1,32 @@
+
+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\)
+
+ Global entries:
+   Address     Access  Initial Sym\.Val\. Type    Ndx Name
+  000a0008 -32744\(gp\) 00000000 00000000 FUNC    UND extf2
+  000a000c -32740\(gp\) 00000000 00000000 FUNC    UND extf3
+  000a0010 -32736\(gp\) 000a2000 000a2000 OBJECT   16 extd2
+  000a0014 -32732\(gp\) 000440a0 000440a0 FUNC    UND extf1
+  000a0018 -32728\(gp\) 00000000 00000000 OBJECT  UND extd1
+  000a001c -32724\(gp\) 00000000 00000000 FUNC    UND extf4
+  000a0020 -32720\(gp\) 00000000 00000000 OBJECT  UND extd4
+
+
+PLT GOT:
+
+ Reserved entries:
+   Address  Initial Purpose
+  00081000 00000000 PLT lazy resolver
+  00081004 00000000 Module pointer
+
+ Entries:
+   Address  Initial Sym.Val. Type    Ndx Name
+  00081008 00043040 00000000 FUNC    UND extf4
+  0008100c 00043040 00000000 FUNC    UND extf5
+  00081010 00043040 00000000 FUNC    UND extf3
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.nd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.nd
new file mode 100644 (file)
index 0000000..15ace17
--- /dev/null
@@ -0,0 +1,17 @@
+
+Symbol table '\.dynsym' contains .*:
+#...
+.*: 00000000 * 0 * FUNC * GLOBAL * DEFAULT * 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+ * 0 * FUNC * GLOBAL * DEFAULT * UND * extf3
+ *9: 0+a2000 * 24 * OBJECT * GLOBAL * DEFAULT * [0-9]+ * extd2
+ *10: 0+440a0 * 0 * FUNC * GLOBAL * DEFAULT * UND * extf1
+ *11: 0+ * 0 * OBJECT * GLOBAL * DEFAULT * UND * extd1
+ *12: 0+ * 0 * FUNC * GLOBAL * DEFAULT * UND * extf4
+ *13: 0+ * 0 * OBJECT * GLOBAL * DEFAULT * UND * extd4
+
+#pass
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.pd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.pd
new file mode 100644 (file)
index 0000000..5f5de62
--- /dev/null
@@ -0,0 +1,6 @@
+
+.*
+
+Contents of section \.got\.plt:
+ 81000 00000000 00000000 00043040 00043040  .*
+ 81010 00043040                             .*
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.rd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.rd
new file mode 100644 (file)
index 0000000..0fd5b7e
--- /dev/null
@@ -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
+00081008 * [^ ]*7f * R_MIPS_JUMP_SLOT * 00000000 * extf4
+0008100c * [^ ]*7f * R_MIPS_JUMP_SLOT * 00000000 * extf5
+00081010 * [^ ]*7f * R_MIPS_JUMP_SLOT * 00000000 * extf3
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.sd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32.sd
new file mode 100644 (file)
index 0000000..b5d51b3
--- /dev/null
@@ -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 *
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32a.s b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32a.s
new file mode 100644 (file)
index 0000000..a4c0075
--- /dev/null
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32b.s b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32b.s
new file mode 100644 (file)
index 0000000..4f8816b
--- /dev/null
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32c.s b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6-o32c.s
new file mode 100644 (file)
index 0000000..578626a
--- /dev/null
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-6.ld b/ld/testsuite/ld-mips-elf/pic-and-nonpic-6.ld
new file mode 100644 (file)
index 0000000..aff900e
--- /dev/null
@@ -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) }
+}