64-bit MIPS ELF ABI objdump support:
authorIan Lance Taylor <ian@airs.com>
Wed, 29 May 1996 20:33:00 +0000 (20:33 +0000)
committerIan Lance Taylor <ian@airs.com>
Wed, 29 May 1996 20:33:00 +0000 (20:33 +0000)
* elf64-mips.c: New file.
* Makefile.in: Rebuild dependencies.
  (BFD64_BACKENDS): Add elf64-mips.o.
(BFD64_BACKENDS_CFILES): Add elf64-mips.c.
* config.bfd (mips*el-*-elf*) Add bfd_elf64_bigmips_vec and
bfd_elf64_littlemips_vec to targ_selvecs.
(mips*-*-elf*): Likewise.
* confingure.in: Add bfd_elf64_bigmips_vec and
bfd_elf64_littlemips_vec to vector switch.
* configure: Rebuild.
* elf32-mips.c (_bfd_mips_elf_section_from_shdr): New function,
broken out of mips_elf_section_from_shdr.
(mips_elf32_section_from_shdr): Rename from
mips_elf_section_from_shdr.  Call new function.
(elf_backend_section_from_shdr): Update name of renamed function.
* elf-bfd.h (struct elf_size_info): Change second parameter of
write_out_phdrs to be const.  Likewise for second parameter of
swap_symbol_out.
(struct bfd_elf_section_data): Add rel_hdr2 field.
(bfd_elf32_swap_symbol_in): Change second parameter to be const.
(bfd_elf32_swap_symbol_out): Likewise.
(bfd_elf32_swap_reloc_in): Likewise.
(bfd_elf32_swap_reloc_out): Likewise.
(bfd_elf32_swap_reloca_in): Likewise.
(bfd_elf32_swap_reloca_out): Likewise.
(bfd_elf32_swap_phdr_in): Likewise.
(bfd_elf32_swap_phdr_out): Likewise.
(bfd_elf32_swap_dyn_in): Likewise.
(bfd_elf32_swap_dyn_out): Likewise.
(bfd_elf32_slurp_symbol_table): Declare.
(bfd_elf32_write_shdrs_and_ehdr): Declare.
(bfd_elf32_write_out_phdrs): Declare.
(bfd_elf64_swap_symbol_in): Change second parameter to be const.
(bfd_elf64_swap_symbol_out): Likewise.
(bfd_elf64_swap_reloc_in): Likewise.
(bfd_elf64_swap_reloc_out): Likewise.
(bfd_elf64_swap_reloca_in): Likewise.
(bfd_elf64_swap_reloca_out): Likewise.
(bfd_elf64_swap_phdr_in): Likewise.
(bfd_elf64_swap_phdr_out): Likewise.
(bfd_elf64_swap_dyn_in): Likewise.
(bfd_elf64_swap_dyn_out): Likewise.
(bfd_elf64_slurp_symbol_table): Declare.
(bfd_elf64_write_shdrs_and_ehdr): Declare.
(bfd_elf64_write_out_phdrs): Declare.
(_bfd_mips_elf_section_from_shdr): Declare.
* elf.c (bfd_section_from_shdr): Remove assertion requiring
SHT_REL/SHT_RELA to match use_rela_p.  If there is already a reloc
section for the section, add the new one to rel_hdr2.  Increment
reloc_count rather than setting it.
* elfcode.h (elf_slurp_symbol_table): Define name as macro.
Remove static declaration.
(elf_write_shdrs_and_ehdr): Define name as macro.
(elf_write_out_phdrs): Likewise.
(elf_swap_ehdr_in, elf_swap_ehdr_out): Declare.
(elf_swap_shdr_in, elf_swap_shdr_out): Declare.
(elf_swap_symbol_in): Change second parameter to be const.
(elf_swap_symbol_out): Likewise.
(elf_swap_ehdr_in, elf_swap_ehdr_out): Likewise.
(elf_swap_shdr_in, elf_swap_shdr_out): Likewise.
(elf_swap_phdr_in, elf_swap_phdr_out): Likewise.
(elf_swap_reloc_in, elf_swap_reloc_out): Likewise.
(elf_swap_reloca_in, elf_swap_reloca_out): Likewise.
(elf_write_out_phdrs): Rename from write_out_phdrs.  Change second
parameter to be const.  Make non-static.
(elf_write_shdrs_and_ehdr): Rename from write_shdrs_and_ehdr.
Make non-static.
(elf_slurp_symbol_table): Make non-static.
(NAME(_bfd_elf,size_info)): Update names of renamed functions.
* elfxx-target.h (elf_info_to_howto): Define if not defined.
(elf_backend_size_info): Likewise.
(elfNN_bed): Use elf_backend_size_info.
* targets.c (bfd_elf64_bigmips_vec): Declare.
(bfd_elf64_littlemips_vec): Declare.
(bfd_target_vector): Add bfd_elf64_bigmips_vec and
bfd_elf64_littlemips_vec if BFD64 is defined.

bfd/.Sanitize
bfd/ChangeLog
bfd/Makefile.in
bfd/configure
bfd/configure.in
bfd/elf-bfd.h
bfd/elf.c
bfd/elf32-mips.c
bfd/elf64-mips.c [new file with mode: 0644]
bfd/elfcode.h
bfd/elfxx-target.h

index 4e9e373e86c900a671adbbb0ed727ba413ebf8de..583ab699245a7aed7b776fc95b70e0154d4e2cbc 100644 (file)
@@ -147,6 +147,7 @@ elf32-ppc.c
 elf32-sparc.c
 elf32.c
 elf64-gen.c
+elf64-mips.c
 elf64-sparc.c
 elf64.c
 elfxx-target.h
index ce7eabcded28a55e61fa18ae3a6b3c2421f385a6..26c512b1e4b23ae6cc2164ccfc1b336a2757cca1 100644 (file)
@@ -1,3 +1,85 @@
+Wed May 29 16:15:29 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       64-bit MIPS ELF ABI objdump support:
+       * elf64-mips.c: New file.
+       * Makefile.in: Rebuild dependencies.
+       (BFD64_BACKENDS): Add elf64-mips.o.
+       (BFD64_BACKENDS_CFILES): Add elf64-mips.c.
+       * config.bfd (mips*el-*-elf*) Add bfd_elf64_bigmips_vec and
+       bfd_elf64_littlemips_vec to targ_selvecs.
+       (mips*-*-elf*): Likewise.
+       * confingure.in: Add bfd_elf64_bigmips_vec and
+       bfd_elf64_littlemips_vec to vector switch.
+       * configure: Rebuild.
+       * elf32-mips.c (_bfd_mips_elf_section_from_shdr): New function,
+       broken out of mips_elf_section_from_shdr.
+       (mips_elf32_section_from_shdr): Rename from
+       mips_elf_section_from_shdr.  Call new function.
+       (elf_backend_section_from_shdr): Update name of renamed function.
+       * elf-bfd.h (struct elf_size_info): Change second parameter of
+       write_out_phdrs to be const.  Likewise for second parameter of
+       swap_symbol_out.
+       (struct bfd_elf_section_data): Add rel_hdr2 field.
+       (bfd_elf32_swap_symbol_in): Change second parameter to be const.
+       (bfd_elf32_swap_symbol_out): Likewise.
+       (bfd_elf32_swap_reloc_in): Likewise.
+       (bfd_elf32_swap_reloc_out): Likewise.
+       (bfd_elf32_swap_reloca_in): Likewise.
+       (bfd_elf32_swap_reloca_out): Likewise.
+       (bfd_elf32_swap_phdr_in): Likewise.
+       (bfd_elf32_swap_phdr_out): Likewise.
+       (bfd_elf32_swap_dyn_in): Likewise.
+       (bfd_elf32_swap_dyn_out): Likewise.
+       (bfd_elf32_slurp_symbol_table): Declare.
+       (bfd_elf32_write_shdrs_and_ehdr): Declare.
+       (bfd_elf32_write_out_phdrs): Declare.
+       (bfd_elf64_swap_symbol_in): Change second parameter to be const.
+       (bfd_elf64_swap_symbol_out): Likewise.
+       (bfd_elf64_swap_reloc_in): Likewise.
+       (bfd_elf64_swap_reloc_out): Likewise.
+       (bfd_elf64_swap_reloca_in): Likewise.
+       (bfd_elf64_swap_reloca_out): Likewise.
+       (bfd_elf64_swap_phdr_in): Likewise.
+       (bfd_elf64_swap_phdr_out): Likewise.
+       (bfd_elf64_swap_dyn_in): Likewise.
+       (bfd_elf64_swap_dyn_out): Likewise.
+       (bfd_elf64_slurp_symbol_table): Declare.
+       (bfd_elf64_write_shdrs_and_ehdr): Declare.
+       (bfd_elf64_write_out_phdrs): Declare.
+       (_bfd_mips_elf_section_from_shdr): Declare.
+       * elf.c (bfd_section_from_shdr): Remove assertion requiring
+       SHT_REL/SHT_RELA to match use_rela_p.  If there is already a reloc
+       section for the section, add the new one to rel_hdr2.  Increment
+       reloc_count rather than setting it.
+       * elfcode.h (elf_slurp_symbol_table): Define name as macro.
+       Remove static declaration.
+       (elf_write_shdrs_and_ehdr): Define name as macro.
+       (elf_write_out_phdrs): Likewise.
+       (elf_swap_ehdr_in, elf_swap_ehdr_out): Declare.
+       (elf_swap_shdr_in, elf_swap_shdr_out): Declare.
+       (elf_swap_symbol_in): Change second parameter to be const.
+       (elf_swap_symbol_out): Likewise.
+       (elf_swap_ehdr_in, elf_swap_ehdr_out): Likewise.
+       (elf_swap_shdr_in, elf_swap_shdr_out): Likewise.
+       (elf_swap_phdr_in, elf_swap_phdr_out): Likewise.
+       (elf_swap_reloc_in, elf_swap_reloc_out): Likewise.
+       (elf_swap_reloca_in, elf_swap_reloca_out): Likewise.
+       (elf_write_out_phdrs): Rename from write_out_phdrs.  Change second
+       parameter to be const.  Make non-static.
+       (elf_write_shdrs_and_ehdr): Rename from write_shdrs_and_ehdr.
+       Make non-static.
+       (elf_slurp_symbol_table): Make non-static.
+       (NAME(_bfd_elf,size_info)): Update names of renamed functions.
+       * elfxx-target.h (elf_info_to_howto): Define if not defined.
+       (elf_backend_size_info): Likewise.
+       (elfNN_bed): Use elf_backend_size_info.
+       * targets.c (bfd_elf64_bigmips_vec): Declare.
+       (bfd_elf64_littlemips_vec): Declare.
+       (bfd_target_vector): Add bfd_elf64_bigmips_vec and
+       bfd_elf64_littlemips_vec if BFD64 is defined.
+       
+       * libbfd.c (bfd_get_file_window): Add cast to fprintf argument.
+
 Tue May 28 11:42:08 1996  Ian Lance Taylor  <ian@cygnus.com>
 
        * coff-sh.c (sh_relax_delete_bytes): Insert nop instructions, not
index 11d337c1d03a6bafab65934d31ac62515ca153e5..7245d7ac6964c26aa1e4e7b17d5a32252e78a95c 100644 (file)
@@ -99,13 +99,13 @@ BFD_LIBS = \
        archive.o archures.o bfd.o cache.o coffgen.o corefile.o \
        format.o init.o libbfd.o opncls.o reloc.o \
        section.o syms.o targets.o hash.o linker.o \
-       elf.o srec.o binary.o tekhex.o ihex.o stab-syms.o
+       elf.o srec.o binary.o tekhex.o ihex.o stabs.o stab-syms.o
 
 BFD_LIBS_CFILES = \
        archive.c archures.c bfd.c cache.c coffgen.c corefile.c \
        format.c init.c libbfd.c opncls.c reloc.c \
        section.c syms.c targets.c hash.c linker.c \
-       elf.c srec.c binary.c tekhex.c ihex.c stab-syms.c
+       elf.c srec.c binary.c tekhex.c ihex.c stabs.c stab-syms.c
 
 # This list is alphabetized to make it easier to keep in sync
 # with the decls and initializer in archures.c.
@@ -345,6 +345,7 @@ BFD64_BACKENDS = \
        coff-alpha.o \
        demo64.o \
        elf64-gen.o \
+       elf64-mips.o \
        elf64-sparc.o \
        elf64.o \
        nlm32-alpha.o \
@@ -355,6 +356,7 @@ BFD64_BACKENDS_CFILES = \
        coff-alpha.c \
        demo64.c \
        elf64-gen.c \
+       elf64-mips.c \
        elf64-sparc.c \
        elf64.c \
        nlm32-alpha.c \
@@ -825,6 +827,7 @@ srec.o: srec.c $(INCDIR)/libiberty.h
 binary.o: binary.c
 tekhex.o: tekhex.c $(INCDIR)/libiberty.h
 ihex.o: ihex.c $(INCDIR)/libiberty.h
+stabs.o: stabs.c $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def
 stab-syms.o: stab-syms.c libaout.h $(INCDIR)/bfdlink.h \
   $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab.def
 cpu-a29k.o: cpu-a29k.c
@@ -1079,6 +1082,9 @@ demo64.o: demo64.c aoutf1.h $(INCDIR)/aout/sun4.h libaout.h \
 elf64-gen.o: elf64-gen.c elf-bfd.h $(INCDIR)/elf/common.h \
   $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h \
   elf64-target.h
+elf64-mips.o: elf64-mips.c $(INCDIR)/bfdlink.h genlink.h \
+  elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
+  $(INCDIR)/elf/external.h $(INCDIR)/elf/mips.h elf64-target.h
 elf64-sparc.o: elf64-sparc.c elf-bfd.h $(INCDIR)/elf/common.h \
   $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h \
   $(INCDIR)/elf/sparc.h elf64-target.h
index e4168c937bcbbe143e459f36a2ebdeb5952348ff..3b325a3031f57f29e1bb32f21a01ef3234f0b639 100755 (executable)
@@ -1766,11 +1766,15 @@ do
 # end-sanitize-arc
     bfd_elf32_big_generic_vec)         tb="$tb elf32-gen.o elf32.o $elf" ;;
     bfd_elf32_bigmips_vec)     tb="$tb elf32-mips.o elf32.o $elf ecofflink.o" ;;
+    bfd_elf64_bigmips_vec)     tb="$tb elf64-mips.o elf64.o elf32-mips.o elf32.o $elf ecofflink.o"
+                               target64=true ;;
     bfd_elf32_hppa_vec)                tb="$tb elf32-hppa.o elf32.o $elf" ;;
     bfd_elf32_i386_vec)                tb="$tb elf32-i386.o elf32.o $elf" ;;
     bfd_elf32_i860_vec)                tb="$tb elf32-i860.o elf32.o $elf" ;;
     bfd_elf32_little_generic_vec) tb="$tb elf32-gen.o elf32.o $elf" ;;
     bfd_elf32_littlemips_vec)  tb="$tb elf32-mips.o elf32.o $elf ecofflink.o" ;;
+    bfd_elf64_littlemips_vec)  tb="$tb elf64-mips.o elf64.o elf32-mips.o elf32.o $elf ecofflink.o"
+                               target64=true ;;
     bfd_elf32_m68k_vec)                tb="$tb elf32-m68k.o elf32.o $elf" ;;
     bfd_elf32_m88k_vec)                tb="$tb elf32-m88k.o elf32.o $elf" ;;
     bfd_elf32_powerpc_vec)     tb="$tb elf32-ppc.o elf32.o $elf" ;;
@@ -1928,7 +1932,7 @@ if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1932 "configure"
+#line 1936 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -1952,7 +1956,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:1956: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:1960: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -1982,7 +1986,7 @@ else
   ac_cv_func_mmap=no
 else
 cat > conftest.$ac_ext <<EOF
-#line 1986 "configure"
+#line 1990 "configure"
 #include "confdefs.h"
 
 /* Thanks to Mike Haertel and Jim Avera for this test. */
@@ -2051,7 +2055,7 @@ main()
 }
 
 EOF
-{ (eval echo configure:2055: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
+{ (eval echo configure:2059: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
 if test -s conftest && (./conftest; exit) 2>/dev/null; then
   ac_cv_func_mmap=yes
 else
@@ -2076,7 +2080,7 @@ if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2080 "configure"
+#line 2084 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -2100,7 +2104,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:2104: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2108: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
index 7c27e1d4d77721d7b3a148d0fe9ec41e17cdbb9f..b04ca1ac0146b5d41f71860b60d15d0dfa694f60 100644 (file)
@@ -23,7 +23,8 @@ AC_ARG_ENABLE(shared,
 [case "${enableval}" in
   yes) shared=true ;;
   no)  shared=false ;;
-  *)   AC_MSG_ERROR([bad value ${enableval} for BFD shared option]) ;;
+  *bfd*) shared=true ;;
+  *) shared=false ;;
 esac])dnl
 AC_ARG_ENABLE(commonbfdlib,
 [  --enable-commonbfdlib   build shared BFD/opcodes/libiberty library],
@@ -418,11 +419,15 @@ do
 # end-sanitize-arc
     bfd_elf32_big_generic_vec)         tb="$tb elf32-gen.o elf32.o $elf" ;;
     bfd_elf32_bigmips_vec)     tb="$tb elf32-mips.o elf32.o $elf ecofflink.o" ;;
+    bfd_elf64_bigmips_vec)     tb="$tb elf64-mips.o elf64.o elf32-mips.o elf32.o $elf ecofflink.o"
+                               target64=true ;;
     bfd_elf32_hppa_vec)                tb="$tb elf32-hppa.o elf32.o $elf" ;;
     bfd_elf32_i386_vec)                tb="$tb elf32-i386.o elf32.o $elf" ;;
     bfd_elf32_i860_vec)                tb="$tb elf32-i860.o elf32.o $elf" ;;
     bfd_elf32_little_generic_vec) tb="$tb elf32-gen.o elf32.o $elf" ;;
     bfd_elf32_littlemips_vec)  tb="$tb elf32-mips.o elf32.o $elf ecofflink.o" ;;
+    bfd_elf64_littlemips_vec)  tb="$tb elf64-mips.o elf64.o elf32-mips.o elf32.o $elf ecofflink.o"
+                               target64=true ;;
     bfd_elf32_m68k_vec)                tb="$tb elf32-m68k.o elf32.o $elf" ;;
     bfd_elf32_m88k_vec)                tb="$tb elf32-m88k.o elf32.o $elf" ;;
     bfd_elf32_powerpc_vec)     tb="$tb elf32-ppc.o elf32.o $elf" ;;
@@ -488,6 +493,7 @@ do
     bfd_powerpcle_pe_vec)       tb="$tb pe-ppc.o cofflink.o" ;;  
     bfd_powerpc_pei_vec)        tb="$tb pei-ppc.o cofflink.o" ;;
     bfd_powerpcle_pei_vec)      tb="$tb pei-ppc.o cofflink.o" ;;
+    ppcboot_vec)               tb="$tb ppcboot.o" ;;
     shcoff_vec)                        tb="$tb coff-sh.o cofflink.o" ;;
 # start-sanitize-rce
     rce_aout_vec)              tb="$tb aout-rce.o aout32.o" ;;
index 987425ea7eb5407440ac03be4df211c15b894cf2..7b9b2432214689feb7dd50b0374f67a0081cc4b0 100644 (file)
@@ -158,6 +158,8 @@ struct elf_link_hash_table
   struct bfd_link_needed_list *needed;
   /* The _GLOBAL_OFFSET_TABLE_ symbol.  */
   struct elf_link_hash_entry *hgot;
+  /* A pointer to information used to link stabs in sections.  */
+  PTR stab_info;
 };
 
 /* Look up an entry in an ELF linker hash table.  */
@@ -187,10 +189,10 @@ struct elf_size_info {
 
   unsigned char arch_size, file_align;
   unsigned char elfclass, ev_current;
-  int (*write_out_phdrs) PARAMS ((bfd *, Elf_Internal_Phdr *, int));
+  int (*write_out_phdrs) PARAMS ((bfd *, const Elf_Internal_Phdr *, int));
   boolean (*write_shdrs_and_ehdr) PARAMS ((bfd *));
   void (*write_relocs) PARAMS ((bfd *, asection *, PTR));
-  void (*swap_symbol_out) PARAMS ((bfd *, Elf_Internal_Sym *, PTR));
+  void (*swap_symbol_out) PARAMS ((bfd *, const Elf_Internal_Sym *, PTR));
   boolean (*slurp_reloc_table) PARAMS ((bfd *, asection *, asymbol **));
   long (*slurp_symbol_table) PARAMS ((bfd *, asymbol **, boolean));
   void (*swap_dyn_in) PARAMS ((bfd *, const PTR, Elf_Internal_Dyn *));
@@ -464,6 +466,9 @@ struct bfd_elf_section_data
   /* The ELF header for the reloc section associated with this
      section, if any.  */
   Elf_Internal_Shdr rel_hdr;
+  /* If there is a second reloc section associated with this section,
+     as can happen on Irix 6, this field points to the header.  */
+  Elf_Internal_Shdr *rel_hdr2;
   /* The ELF section number of this section.  Only used for an output
      file.  */
   int this_idx;
@@ -481,6 +486,8 @@ struct bfd_elf_section_data
      record the dynamic symbol index for a section symbol
      corresponding to this section.  */
   long dynindx;
+  /* A pointer used for .stab linking optimizations.  */
+  PTR stab_info;
   /* A pointer available for the processor specific ELF backend.  */
   PTR tdata;
 };
@@ -794,25 +801,30 @@ extern boolean bfd_elf32_bfd_final_link
   PARAMS ((bfd *, struct bfd_link_info *));
 
 extern void bfd_elf32_swap_symbol_in
-  PARAMS ((bfd *, Elf32_External_Sym *, Elf_Internal_Sym *));
+  PARAMS ((bfd *, const Elf32_External_Sym *, Elf_Internal_Sym *));
 extern void bfd_elf32_swap_symbol_out
-  PARAMS ((bfd *, Elf_Internal_Sym *, PTR));
+  PARAMS ((bfd *, const Elf_Internal_Sym *, PTR));
 extern void bfd_elf32_swap_reloc_in
-  PARAMS ((bfd *, Elf32_External_Rel *, Elf_Internal_Rel *));
+  PARAMS ((bfd *, const Elf32_External_Rel *, Elf_Internal_Rel *));
 extern void bfd_elf32_swap_reloc_out
-  PARAMS ((bfd *, Elf_Internal_Rel *, Elf32_External_Rel *));
+  PARAMS ((bfd *, const Elf_Internal_Rel *, Elf32_External_Rel *));
 extern void bfd_elf32_swap_reloca_in
-  PARAMS ((bfd *, Elf32_External_Rela *, Elf_Internal_Rela *));
+  PARAMS ((bfd *, const Elf32_External_Rela *, Elf_Internal_Rela *));
 extern void bfd_elf32_swap_reloca_out
-  PARAMS ((bfd *, Elf_Internal_Rela *, Elf32_External_Rela *));
+  PARAMS ((bfd *, const Elf_Internal_Rela *, Elf32_External_Rela *));
 extern void bfd_elf32_swap_phdr_in
-  PARAMS ((bfd *, Elf32_External_Phdr *, Elf_Internal_Phdr *));
+  PARAMS ((bfd *, const Elf32_External_Phdr *, Elf_Internal_Phdr *));
 extern void bfd_elf32_swap_phdr_out
-  PARAMS ((bfd *, Elf_Internal_Phdr *, Elf32_External_Phdr *));
+  PARAMS ((bfd *, const Elf_Internal_Phdr *, Elf32_External_Phdr *));
 extern void bfd_elf32_swap_dyn_in
   PARAMS ((bfd *, const PTR, Elf_Internal_Dyn *));
 extern void bfd_elf32_swap_dyn_out
   PARAMS ((bfd *, const Elf_Internal_Dyn *, Elf32_External_Dyn *));
+extern long bfd_elf32_slurp_symbol_table
+  PARAMS ((bfd *, asymbol **, boolean));
+extern boolean bfd_elf32_write_shdrs_and_ehdr PARAMS ((bfd *));
+extern int bfd_elf32_write_out_phdrs
+  PARAMS ((bfd *, const Elf_Internal_Phdr *, int));
 extern boolean bfd_elf32_add_dynamic_entry
   PARAMS ((struct bfd_link_info *, bfd_vma, bfd_vma));
 extern boolean bfd_elf32_link_create_dynamic_sections
@@ -830,25 +842,30 @@ extern boolean bfd_elf64_bfd_final_link
   PARAMS ((bfd *, struct bfd_link_info *));
 
 extern void bfd_elf64_swap_symbol_in
-  PARAMS ((bfd *, Elf64_External_Sym *, Elf_Internal_Sym *));
+  PARAMS ((bfd *, const Elf64_External_Sym *, Elf_Internal_Sym *));
 extern void bfd_elf64_swap_symbol_out
-  PARAMS ((bfd *, Elf_Internal_Sym *, PTR));
+  PARAMS ((bfd *, const Elf_Internal_Sym *, PTR));
 extern void bfd_elf64_swap_reloc_in
-  PARAMS ((bfd *, Elf64_External_Rel *, Elf_Internal_Rel *));
+  PARAMS ((bfd *, const Elf64_External_Rel *, Elf_Internal_Rel *));
 extern void bfd_elf64_swap_reloc_out
-  PARAMS ((bfd *, Elf_Internal_Rel *, Elf64_External_Rel *));
+  PARAMS ((bfd *, const Elf_Internal_Rel *, Elf64_External_Rel *));
 extern void bfd_elf64_swap_reloca_in
-  PARAMS ((bfd *, Elf64_External_Rela *, Elf_Internal_Rela *));
+  PARAMS ((bfd *, const Elf64_External_Rela *, Elf_Internal_Rela *));
 extern void bfd_elf64_swap_reloca_out
-  PARAMS ((bfd *, Elf_Internal_Rela *, Elf64_External_Rela *));
+  PARAMS ((bfd *, const Elf_Internal_Rela *, Elf64_External_Rela *));
 extern void bfd_elf64_swap_phdr_in
-  PARAMS ((bfd *, Elf64_External_Phdr *, Elf_Internal_Phdr *));
+  PARAMS ((bfd *, const Elf64_External_Phdr *, Elf_Internal_Phdr *));
 extern void bfd_elf64_swap_phdr_out
-  PARAMS ((bfd *, Elf_Internal_Phdr *, Elf64_External_Phdr *));
+  PARAMS ((bfd *, const Elf_Internal_Phdr *, Elf64_External_Phdr *));
 extern void bfd_elf64_swap_dyn_in
   PARAMS ((bfd *, const PTR, Elf_Internal_Dyn *));
 extern void bfd_elf64_swap_dyn_out
   PARAMS ((bfd *, const Elf_Internal_Dyn *, Elf64_External_Dyn *));
+extern long bfd_elf64_slurp_symbol_table
+  PARAMS ((bfd *, asymbol **, boolean));
+extern boolean bfd_elf64_write_shdrs_and_ehdr PARAMS ((bfd *));
+extern int bfd_elf64_write_out_phdrs
+  PARAMS ((bfd *, const Elf_Internal_Phdr *, int));
 extern boolean bfd_elf64_add_dynamic_entry
   PARAMS ((struct bfd_link_info *, bfd_vma, bfd_vma));
 extern boolean bfd_elf64_link_create_dynamic_sections
@@ -857,4 +874,9 @@ extern boolean bfd_elf64_link_create_dynamic_sections
 #define bfd_elf32_link_record_dynamic_symbol _bfd_elf_link_record_dynamic_symbol
 #define bfd_elf64_link_record_dynamic_symbol _bfd_elf_link_record_dynamic_symbol
 
+/* MIPS ELF specific routines.  */
+
+extern boolean _bfd_mips_elf_section_from_shdr
+  PARAMS ((bfd *, Elf_Internal_Shdr *, const char *));
+
 #endif /* _LIBELF_H_ */
index 6ede06aec843d75b1b29a31692647efdad18983d..599706794b3aea220aadadeaedc437e045783f7e 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -584,6 +584,7 @@ _bfd_elf_link_hash_table_init (table, abfd, newfunc)
   table->bucketcount = 0;
   table->needed = NULL;
   table->hgot = NULL;
+  table->stab_info = NULL;
   return _bfd_link_hash_table_init (&table->root, abfd, newfunc);
 }
 
@@ -800,7 +801,6 @@ bfd_section_from_shdr (abfd, shindex)
       {
        asection *target_sect;
        Elf_Internal_Shdr *hdr2;
-       int use_rela_p = get_elf_backend_data (abfd)->use_rela_p;
 
        /* For some incomprehensible reason Oracle distributes
           libraries for Solaris in which some of the objects have
@@ -845,30 +845,24 @@ bfd_section_from_shdr (abfd, shindex)
        if (hdr->sh_link != elf_onesymtab (abfd))
          return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
 
-       /* Don't allow REL relocations on a machine that uses RELA and
-          vice versa.  */
-       /* @@ Actually, the generic ABI does suggest that both might be
-          used in one file.  But the four ABI Processor Supplements I
-          have access to right now all specify that only one is used on
-          each of those architectures.  It's conceivable that, e.g., a
-          bunch of absolute 32-bit relocs might be more compact in REL
-          form even on a RELA machine...  */
-       BFD_ASSERT (use_rela_p
-                   ? (hdr->sh_type == SHT_RELA
-                      && hdr->sh_entsize == bed->s->sizeof_rela)
-                   : (hdr->sh_type == SHT_REL
-                      && hdr->sh_entsize == bed->s->sizeof_rel));
-
        if (! bfd_section_from_shdr (abfd, hdr->sh_info))
          return false;
        target_sect = bfd_section_from_elf_index (abfd, hdr->sh_info);
        if (target_sect == NULL)
          return false;
 
-       hdr2 = &elf_section_data (target_sect)->rel_hdr;
+       if ((target_sect->flags & SEC_RELOC) == 0
+           || target_sect->reloc_count == 0)
+         hdr2 = &elf_section_data (target_sect)->rel_hdr;
+       else
+         {
+           BFD_ASSERT (elf_section_data (target_sect)->rel_hdr2 == NULL);
+           hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, sizeof (*hdr2));
+           elf_section_data (target_sect)->rel_hdr2 = hdr2;
+         }
        *hdr2 = *hdr;
        elf_elfsections (abfd)[shindex] = hdr2;
-       target_sect->reloc_count = hdr->sh_size / hdr->sh_entsize;
+       target_sect->reloc_count += hdr->sh_size / hdr->sh_entsize;
        target_sect->flags |= SEC_RELOC;
        target_sect->relocation = NULL;
        target_sect->rel_filepos = hdr->sh_offset;
index f049ef4a6570f5735a53aa0aead999538ce5cffb..88be8529d77ee27a719cbc4edcb2fbea03b05931 100644 (file)
@@ -96,7 +96,7 @@ static void mips_elf_final_write_processing
 static boolean mips_elf_set_private_flags PARAMS ((bfd *, flagword));
 static boolean mips_elf_copy_private_bfd_data PARAMS ((bfd *, bfd *));
 static boolean mips_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *));
-static boolean mips_elf_section_from_shdr
+static boolean mips_elf32_section_from_shdr
   PARAMS ((bfd *, Elf32_Internal_Shdr *, char *));
 static boolean mips_elf_fake_sections
   PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *));
@@ -1564,6 +1564,7 @@ mips_elf_copy_private_bfd_data (ibfd, obfd)
              || (elf_elfheader (obfd)->e_flags
                  == elf_elfheader (ibfd)->e_flags));
 
+  elf_gp (obfd) = elf_gp (ibfd);
   elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
   elf_flags_init (obfd) = true;
   return true;
@@ -1647,17 +1648,17 @@ mips_elf_merge_private_bfd_data (ibfd, obfd)
 \f
 /* Handle a MIPS specific section when reading an object file.  This
    is called when elfcode.h finds a section with an unknown type.
+   This routine supports both the 32-bit and 64-bit ELF ABI.
+
    FIXME: We need to handle the SHF_MIPS_GPREL flag, but I'm not sure
    how to.  */
 
-static boolean
-mips_elf_section_from_shdr (abfd, hdr, name)
+boolean
+_bfd_mips_elf_section_from_shdr (abfd, hdr, name)
      bfd *abfd;
-     Elf32_Internal_Shdr *hdr;
-     char *name;
+     Elf_Internal_Shdr *hdr;
+     const char *name;
 {
-  asection *newsect;
-
   /* There ought to be a place to keep ELF backend specific flags, but
      at the moment there isn't one.  We just keep track of the
      sections by their name, instead.  Fortunately, the ABI gives
@@ -1712,27 +1713,42 @@ mips_elf_section_from_shdr (abfd, hdr, name)
 
   if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
     return false;
-  newsect = hdr->bfd_section;
 
   if (hdr->sh_type == SHT_MIPS_DEBUG)
     {
-      if (! bfd_set_section_flags (abfd, newsect,
-                                  (bfd_get_section_flags (abfd, newsect)
+      if (! bfd_set_section_flags (abfd, hdr->bfd_section,
+                                  (bfd_get_section_flags (abfd,
+                                                          hdr->bfd_section)
                                    | SEC_DEBUGGING)))
        return false;
     }
 
+  return true;
+}
+
+/* Handle a 32-bit MIPS ELF specific section.  */
+
+static boolean
+mips_elf32_section_from_shdr (abfd, hdr, name)
+     bfd *abfd;
+     Elf_Internal_Shdr *hdr;
+     char *name;
+{
+  if (! _bfd_mips_elf_section_from_shdr (abfd, hdr, name))
+    return false;
+
   /* FIXME: We should record sh_info for a .gptab section.  */
 
   /* For a .reginfo section, set the gp value in the tdata information
      from the contents of this section.  We need the gp value while
-     processing relocs, so we just get it now.  */
+     processing relocs, so we just get it now.  The .reginfo section
+     is not used in the 64-bit MIPS ELF ABI.  */
   if (hdr->sh_type == SHT_MIPS_REGINFO)
     {
       Elf32_External_RegInfo ext;
       Elf32_RegInfo s;
 
-      if (! bfd_get_section_contents (abfd, newsect, (PTR) &ext,
+      if (! bfd_get_section_contents (abfd, hdr->bfd_section, (PTR) &ext,
                                      (file_ptr) 0, sizeof ext))
        return false;
       bfd_mips_elf32_swap_reginfo_in (abfd, &ext, &s);
@@ -5923,7 +5939,7 @@ static const struct ecoff_debug_swap mips_elf_ecoff_debug_swap =
 #define elf_info_to_howto_rel          mips_info_to_howto_rel
 #define elf_backend_sym_is_global      mips_elf_sym_is_global
 #define elf_backend_object_p           mips_elf_object_p
-#define elf_backend_section_from_shdr  mips_elf_section_from_shdr
+#define elf_backend_section_from_shdr  mips_elf32_section_from_shdr
 #define elf_backend_fake_sections      mips_elf_fake_sections
 #define elf_backend_section_from_bfd_section \
                                        mips_elf_section_from_bfd_section
diff --git a/bfd/elf64-mips.c b/bfd/elf64-mips.c
new file mode 100644 (file)
index 0000000..ae444aa
--- /dev/null
@@ -0,0 +1,1554 @@
+/* MIPS-specific support for 64-bit ELF
+   Copyright 1996 Free Software Foundation, Inc.
+   Ian Lance Taylor, Cygnus Support
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "bfdlink.h"
+#include "genlink.h"
+#include "elf-bfd.h"
+#include "elf/mips.h"
+
+/* This file supports the 64-bit MIPS ELF ABI.
+
+   The MIPS 64-bit ELF ABI uses an unusual reloc format.  This file
+   overrides the usual ELF reloc handling, and handles reading and
+   writing the relocations here.  */
+
+static void mips_elf64_swap_reloc_in
+  PARAMS ((bfd *, const Elf64_Mips_External_Rel *,
+          Elf64_Mips_Internal_Rel *));
+static void mips_elf64_swap_reloca_in
+  PARAMS ((bfd *, const Elf64_Mips_External_Rela *,
+          Elf64_Mips_Internal_Rela *));
+static void mips_elf64_swap_reloc_out
+  PARAMS ((bfd *, const Elf64_Mips_Internal_Rel *,
+          Elf64_Mips_External_Rel *));
+static void mips_elf64_swap_reloca_out
+  PARAMS ((bfd *, const Elf64_Mips_Internal_Rela *,
+          Elf64_Mips_External_Rela *));
+static reloc_howto_type *mips_elf64_reloc_type_lookup
+  PARAMS ((bfd *, bfd_reloc_code_real_type));
+static boolean mips_elf64_slurp_one_reloc_table
+  PARAMS ((bfd *, asection *, asymbol **, const Elf_Internal_Shdr *));
+static boolean mips_elf64_slurp_reloc_table
+  PARAMS ((bfd *, asection *, asymbol **));
+static void mips_elf64_write_relocs PARAMS ((bfd *, asection *, PTR));
+static boolean mips_elf64_section_from_shdr
+  PARAMS ((bfd *, Elf_Internal_Shdr *, char *));
+
+/* The relocation types.  */
+
+enum mips_elf64_reloc_type
+{
+  R_MIPS_NONE = 0,
+  R_MIPS_16 = 1,
+  R_MIPS_32 = 2,
+  R_MIPS_ADD = 2,
+  R_MIPS_REL32 = 3,
+  R_MIPS_REL = 3,
+  R_MIPS_26 = 4,
+  R_MIPS_HI16 = 5,
+  R_MIPS_LO16 = 6,
+  R_MIPS_GPREL16 = 7,
+  R_MIPS_GPREL = 7,
+  R_MIPS_LITERAL = 8,
+  R_MIPS_GOT16 = 9,
+  R_MIPS_GOT = 9,
+  R_MIPS_PC16 = 10,
+  R_MIPS_CALL16 = 11,
+  R_MIPS_CALL = 11,
+  R_MIPS_GPREL32 = 12,
+  R_MIPS_SHIFT5 = 16,
+  R_MIPS_SHIFT6 = 17,
+  R_MIPS_64 = 18,
+  R_MIPS_GOT_DISP = 19,
+  R_MIPS_GOT_PAGE = 20,
+  R_MIPS_GOT_OFST = 21,
+  R_MIPS_GOT_HI16 = 22,
+  R_MIPS_GOT_LO16 = 23,
+  R_MIPS_SUB = 24,
+  R_MIPS_INSERT_A = 25,
+  R_MIPS_INSERT_B = 26,
+  R_MIPS_DELETE = 27,
+  R_MIPS_HIGHER = 28,
+  R_MIPS_HIGHEST = 29,
+  R_MIPS_CALL_HI16 = 30,
+  R_MIPS_CALL_LO16 = 31,
+  R_MIPS_SCN_DISP = 32,
+  R_MIPS_REL16 = 33,
+  R_MIPS_ADD_IMMEDIATE = 34
+};
+
+/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
+   from smaller values.  Start with zero, widen, *then* decrement.  */
+#define MINUS_ONE      (((bfd_vma)0) - 1)
+
+/* FIXME: These need to be rewritten, or we need to use the versions
+   in elf32-mips.c.  */
+#define mips_elf_hi16_reloc bfd_elf_generic_reloc
+#define mips_elf_lo16_reloc bfd_elf_generic_reloc
+#define mips_elf_gprel16_reloc bfd_elf_generic_reloc
+#define mips_elf_got16_reloc bfd_elf_generic_reloc
+#define mips_elf_gprel32_reloc bfd_elf_generic_reloc
+
+/* The relocation table used for SHT_REL sections.  */
+
+static reloc_howto_type mips_elf64_howto_table_rel[] =
+{
+  /* No relocation.  */
+  HOWTO (R_MIPS_NONE,          /* type */
+        0,                     /* rightshift */
+        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        0,                     /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_NONE",         /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0,                     /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 16 bit relocation.  */
+  HOWTO (R_MIPS_16,            /* type */
+        0,                     /* rightshift */
+        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_16",           /* name */
+        true,                  /* partial_inplace */
+        0xffff,                /* src_mask */
+        0xffff,                /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 32 bit relocation.  */
+  HOWTO (R_MIPS_32,            /* 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_32",           /* name */
+        true,                  /* partial_inplace */
+        0xffffffff,            /* src_mask */
+        0xffffffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 32 bit symbol relative relocation.  */
+  HOWTO (R_MIPS_REL32,         /* 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_REL32",        /* name */
+        true,                  /* partial_inplace */
+        0xffffffff,            /* src_mask */
+        0xffffffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 26 bit branch address.  */
+  HOWTO (R_MIPS_26,            /* type */
+        2,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        26,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+                               /* This needs complex overflow
+                                  detection, because the upper four
+                                  bits must match the PC.  */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_26",           /* name */
+        true,                  /* partial_inplace */
+        0x3ffffff,             /* src_mask */
+        0x3ffffff,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* High 16 bits of symbol value.  */
+  HOWTO (R_MIPS_HI16,          /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        mips_elf_hi16_reloc,   /* special_function */
+        "R_MIPS_HI16",         /* name */
+        true,                  /* partial_inplace */
+        0xffff,                /* src_mask */
+        0xffff,                /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Low 16 bits of symbol value.  */
+  HOWTO (R_MIPS_LO16,          /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        mips_elf_lo16_reloc,   /* special_function */
+        "R_MIPS_LO16",         /* name */
+        true,                  /* partial_inplace */
+        0xffff,                /* src_mask */
+        0xffff,                /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* GP relative reference.  */
+  HOWTO (R_MIPS_GPREL16,       /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        mips_elf_gprel16_reloc, /* special_function */
+        "R_MIPS_GPREL16",      /* name */
+        true,                  /* partial_inplace */
+        0xffff,                /* src_mask */
+        0xffff,                /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Reference to literal section.  */
+  HOWTO (R_MIPS_LITERAL,       /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        mips_elf_gprel16_reloc, /* special_function */
+        "R_MIPS_LITERAL",      /* name */
+        true,                  /* partial_inplace */
+        0xffff,                /* src_mask */
+        0xffff,                /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Reference to global offset table.  */
+  HOWTO (R_MIPS_GOT16,         /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        mips_elf_got16_reloc,  /* special_function */
+        "R_MIPS_GOT16",        /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0xffff,                /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 16 bit PC relative reference.  */
+  HOWTO (R_MIPS_PC16,          /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        true,                  /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_PC16",         /* name */
+        true,                  /* partial_inplace */
+        0xffff,                /* src_mask */
+        0xffff,                /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 16 bit call through global offset table.  */
+  /* FIXME: This is not handled correctly.  */
+  HOWTO (R_MIPS_CALL16,                /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_CALL16",       /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0xffff,                /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 32 bit GP relative reference.  */
+  HOWTO (R_MIPS_GPREL32,       /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        32,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        mips_elf_gprel32_reloc, /* special_function */
+        "R_MIPS_GPREL32",      /* name */
+        true,                  /* partial_inplace */
+        0xffffffff,            /* src_mask */
+        0xffffffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+    { 13 },
+    { 14 },
+    { 15 },
+
+  /* A 5 bit shift field.  */
+  HOWTO (R_MIPS_SHIFT5,                /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        5,                     /* bitsize */
+        false,                 /* pc_relative */
+        6,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_SHIFT5",       /* name */
+        true,                  /* partial_inplace */
+        0x000007c0,            /* src_mask */
+        0x000007c0,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* A 6 bit shift field.  */
+  /* FIXME: This is not handled correctly; a special function is
+     needed to put the most significant bit in the right place.  */
+  HOWTO (R_MIPS_SHIFT6,                /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        6,                     /* bitsize */
+        false,                 /* pc_relative */
+        6,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_SHIFT6",       /* name */
+        true,                  /* partial_inplace */
+        0x000007c4,            /* src_mask */
+        0x000007c4,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 64 bit relocation.  */
+  HOWTO (R_MIPS_64,            /* 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_64",           /* name */
+        true,                  /* partial_inplace */
+        MINUS_ONE,             /* src_mask */
+        MINUS_ONE,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Displacement in the global offset table.  */
+  /* FIXME: Not handled correctly.  */
+  HOWTO (R_MIPS_GOT_DISP,      /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_GOT_DISP",     /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Displacement to page pointer in the global offset table.  */
+  /* FIXME: Not handled correctly.  */
+  HOWTO (R_MIPS_GOT_PAGE,      /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_GOT_PAGE",     /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Offset from page pointer in the global offset table.  */
+  /* FIXME: Not handled correctly.  */
+  HOWTO (R_MIPS_GOT_OFST,      /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_GOT_OFST",     /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* High 16 bits of displacement in global offset table.  */
+  /* FIXME: Not handled correctly.  */
+  HOWTO (R_MIPS_GOT_HI16,      /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_GOT_HI16",     /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Low 16 bits of displacement in global offset table.  */
+  /* FIXME: Not handled correctly.  */
+  HOWTO (R_MIPS_GOT_LO16,      /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_GOT_LO16",     /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 64 bit substraction.  */
+  /* FIXME: Not handled correctly.  */
+  HOWTO (R_MIPS_SUB,           /* 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_SUB",          /* name */
+        true,                  /* partial_inplace */
+        MINUS_ONE,             /* src_mask */
+        MINUS_ONE,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Insert the addend as an instruction.  */
+  /* FIXME: Not handled correctly.  */
+  HOWTO (R_MIPS_INSERT_A,      /* type */
+        0,                     /* rightshift */
+        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        0,                     /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_INSERT_A",     /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0,                     /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Insert the addend as an instruction, and change all relocations
+     to refer to the old instruction at the address.  */
+  /* FIXME: Not handled correctly.  */
+  HOWTO (R_MIPS_INSERT_B,      /* type */
+        0,                     /* rightshift */
+        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        0,                     /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_INSERT_B",     /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0,                     /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Delete a 32 bit instruction.  */
+  /* FIXME: Not handled correctly.  */
+  HOWTO (R_MIPS_DELETE,                /* type */
+        0,                     /* rightshift */
+        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        0,                     /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_DELETE",       /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0,                     /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Get the higher value of a 64 bit addend.  */
+  /* FIXME: Not handled correctly.  */
+  HOWTO (R_MIPS_HIGHER,                /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_HIGHER",       /* name */
+        true,                  /* partial_inplace */
+        0xffff,                /* src_mask */
+        0xffff,                /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Get the highest value of a 64 bit addend.  */
+  /* FIXME: Not handled correctly.  */
+  HOWTO (R_MIPS_HIGHEST,       /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_HIGHEST",      /* name */
+        true,                  /* partial_inplace */
+        0xffff,                /* src_mask */
+        0xffff,                /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* High 16 bits of displacement in global offset table.  */
+  /* FIXME: Not handled correctly.  */
+  HOWTO (R_MIPS_CALL_HI16,     /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_CALL_HI16",    /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Low 16 bits of displacement in global offset table.  */
+  /* FIXME: Not handled correctly.  */
+  HOWTO (R_MIPS_CALL_LO16,     /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_CALL_LO16",    /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* I'm not sure what the remaining relocs are, but they are defined
+     on Irix 6.  */
+
+  HOWTO (R_MIPS_SCN_DISP,      /* type */
+        0,                     /* rightshift */
+        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        0,                     /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_SCN_DISP",     /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0,                     /* dst_mask */
+        false),                /* pcrel_offset */
+
+  HOWTO (R_MIPS_REL16,         /* type */
+        0,                     /* rightshift */
+        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        0,                     /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_REL16",        /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0,                     /* dst_mask */
+        false),                /* pcrel_offset */
+
+  HOWTO (R_MIPS_ADD_IMMEDIATE, /* type */
+        0,                     /* rightshift */
+        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        0,                     /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_ADD_IMMEDIATE", /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0,                     /* dst_mask */
+        false)                 /* pcrel_offset */
+};
+
+/* The relocation table used for SHT_RELA sections.  */
+
+static reloc_howto_type mips_elf64_howto_table_rela[] =
+{
+  /* No relocation.  */
+  HOWTO (R_MIPS_NONE,          /* type */
+        0,                     /* rightshift */
+        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        0,                     /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_NONE",         /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0,                     /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 16 bit relocation.  */
+  HOWTO (R_MIPS_16,            /* type */
+        0,                     /* rightshift */
+        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_16",           /* name */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
+        0xffff,                /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 32 bit relocation.  */
+  HOWTO (R_MIPS_32,            /* 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_32",           /* name */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
+        0xffffffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 32 bit symbol relative relocation.  */
+  HOWTO (R_MIPS_REL32,         /* 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_REL32",        /* name */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
+        0xffffffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 26 bit branch address.  */
+  HOWTO (R_MIPS_26,            /* type */
+        2,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        26,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+                               /* This needs complex overflow
+                                  detection, because the upper four
+                                  bits must match the PC.  */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_26",           /* name */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
+        0x3ffffff,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* High 16 bits of symbol value.  */
+  HOWTO (R_MIPS_HI16,          /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_HI16",         /* name */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
+        0xffff,                /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Low 16 bits of symbol value.  */
+  HOWTO (R_MIPS_LO16,          /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_LO16",         /* name */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
+        0xffff,                /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* GP relative reference.  */
+  HOWTO (R_MIPS_GPREL16,       /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        mips_elf_gprel16_reloc, /* special_function */
+        "R_MIPS_GPREL16",      /* name */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
+        0xffff,                /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Reference to literal section.  */
+  HOWTO (R_MIPS_LITERAL,       /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        mips_elf_gprel16_reloc, /* special_function */
+        "R_MIPS_LITERAL",      /* name */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
+        0xffff,                /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Reference to global offset table.  */
+  HOWTO (R_MIPS_GOT16,         /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        mips_elf_got16_reloc,  /* special_function */
+        "R_MIPS_GOT16",        /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0xffff,                /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 16 bit PC relative reference.  */
+  HOWTO (R_MIPS_PC16,          /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        true,                  /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_PC16",         /* name */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
+        0xffff,                /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 16 bit call through global offset table.  */
+  /* FIXME: This is not handled correctly.  */
+  HOWTO (R_MIPS_CALL16,                /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_CALL16",       /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0xffff,                /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 32 bit GP relative reference.  */
+  HOWTO (R_MIPS_GPREL32,       /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        32,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        mips_elf_gprel32_reloc, /* special_function */
+        "R_MIPS_GPREL32",      /* name */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
+        0xffffffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+    { 13 },
+    { 14 },
+    { 15 },
+
+  /* A 5 bit shift field.  */
+  HOWTO (R_MIPS_SHIFT5,                /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        5,                     /* bitsize */
+        false,                 /* pc_relative */
+        6,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_SHIFT5",       /* name */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
+        0x000007c0,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* A 6 bit shift field.  */
+  /* FIXME: This is not handled correctly; a special function is
+     needed to put the most significant bit in the right place.  */
+  HOWTO (R_MIPS_SHIFT6,                /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        6,                     /* bitsize */
+        false,                 /* pc_relative */
+        6,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_SHIFT6",       /* name */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
+        0x000007c4,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 64 bit relocation.  */
+  HOWTO (R_MIPS_64,            /* 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_64",           /* name */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
+        MINUS_ONE,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Displacement in the global offset table.  */
+  /* FIXME: Not handled correctly.  */
+  HOWTO (R_MIPS_GOT_DISP,      /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_GOT_DISP",     /* name */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Displacement to page pointer in the global offset table.  */
+  /* FIXME: Not handled correctly.  */
+  HOWTO (R_MIPS_GOT_PAGE,      /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_GOT_PAGE",     /* name */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Offset from page pointer in the global offset table.  */
+  /* FIXME: Not handled correctly.  */
+  HOWTO (R_MIPS_GOT_OFST,      /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_GOT_OFST",     /* name */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* High 16 bits of displacement in global offset table.  */
+  /* FIXME: Not handled correctly.  */
+  HOWTO (R_MIPS_GOT_HI16,      /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_GOT_HI16",     /* name */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Low 16 bits of displacement in global offset table.  */
+  /* FIXME: Not handled correctly.  */
+  HOWTO (R_MIPS_GOT_LO16,      /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_GOT_LO16",     /* name */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 64 bit substraction.  */
+  /* FIXME: Not handled correctly.  */
+  HOWTO (R_MIPS_SUB,           /* 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_SUB",          /* name */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
+        MINUS_ONE,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Insert the addend as an instruction.  */
+  /* FIXME: Not handled correctly.  */
+  HOWTO (R_MIPS_INSERT_A,      /* type */
+        0,                     /* rightshift */
+        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        0,                     /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_INSERT_A",     /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0,                     /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Insert the addend as an instruction, and change all relocations
+     to refer to the old instruction at the address.  */
+  /* FIXME: Not handled correctly.  */
+  HOWTO (R_MIPS_INSERT_B,      /* type */
+        0,                     /* rightshift */
+        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        0,                     /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_INSERT_B",     /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0,                     /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Delete a 32 bit instruction.  */
+  /* FIXME: Not handled correctly.  */
+  HOWTO (R_MIPS_DELETE,                /* type */
+        0,                     /* rightshift */
+        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        0,                     /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_DELETE",       /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0,                     /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Get the higher value of a 64 bit addend.  */
+  /* FIXME: Not handled correctly.  */
+  HOWTO (R_MIPS_HIGHER,                /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_HIGHER",       /* name */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
+        0xffff,                /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Get the highest value of a 64 bit addend.  */
+  /* FIXME: Not handled correctly.  */
+  HOWTO (R_MIPS_HIGHEST,       /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_HIGHEST",      /* name */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
+        0xffff,                /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* High 16 bits of displacement in global offset table.  */
+  /* FIXME: Not handled correctly.  */
+  HOWTO (R_MIPS_CALL_HI16,     /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_CALL_HI16",    /* name */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Low 16 bits of displacement in global offset table.  */
+  /* FIXME: Not handled correctly.  */
+  HOWTO (R_MIPS_CALL_LO16,     /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_CALL_LO16",    /* name */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* I'm not sure what the remaining relocs are, but they are defined
+     on Irix 6.  */
+
+  HOWTO (R_MIPS_SCN_DISP,      /* type */
+        0,                     /* rightshift */
+        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        0,                     /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_SCN_DISP",     /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0,                     /* dst_mask */
+        false),                /* pcrel_offset */
+
+  HOWTO (R_MIPS_REL16,         /* type */
+        0,                     /* rightshift */
+        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        0,                     /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_REL16",        /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0,                     /* dst_mask */
+        false),                /* pcrel_offset */
+
+  HOWTO (R_MIPS_ADD_IMMEDIATE, /* type */
+        0,                     /* rightshift */
+        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        0,                     /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_MIPS_ADD_IMMEDIATE", /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0,                     /* dst_mask */
+        false)                 /* pcrel_offset */
+};
+
+/* Swap in a MIPS 64-bit Rel reloc.  */
+
+static void
+mips_elf64_swap_reloc_in (abfd, src, dst)
+     bfd *abfd;
+     const Elf64_Mips_External_Rel *src;
+     Elf64_Mips_Internal_Rel *dst;
+{
+  dst->r_offset = bfd_h_get_64 (abfd, (bfd_byte *) src->r_offset);
+  dst->r_sym = bfd_h_get_32 (abfd, (bfd_byte *) src->r_sym);
+  dst->r_ssym = bfd_h_get_8 (abfd, (bfd_byte *) src->r_ssym);
+  dst->r_type3 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type3);
+  dst->r_type2 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type2);
+  dst->r_type = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type);
+}
+
+/* Swap in a MIPS 64-bit Rela reloc.  */
+
+static void
+mips_elf64_swap_reloca_in (abfd, src, dst)
+     bfd *abfd;
+     const Elf64_Mips_External_Rela *src;
+     Elf64_Mips_Internal_Rela *dst;
+{
+  dst->r_offset = bfd_h_get_64 (abfd, (bfd_byte *) src->r_offset);
+  dst->r_sym = bfd_h_get_32 (abfd, (bfd_byte *) src->r_sym);
+  dst->r_ssym = bfd_h_get_8 (abfd, (bfd_byte *) src->r_ssym);
+  dst->r_type3 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type3);
+  dst->r_type2 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type2);
+  dst->r_type = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type);
+  dst->r_addend = bfd_h_get_64 (abfd, (bfd_byte *) src->r_addend);
+}
+
+/* Swap out a MIPS 64-bit Rel reloc.  */
+
+static void
+mips_elf64_swap_reloc_out (abfd, src, dst)
+     bfd *abfd;
+     const Elf64_Mips_Internal_Rel *src;
+     Elf64_Mips_External_Rel *dst;
+{
+  bfd_h_put_64 (abfd, src->r_offset, (bfd_byte *) dst->r_offset);
+  bfd_h_put_32 (abfd, src->r_sym, (bfd_byte *) dst->r_sym);
+  bfd_h_put_8 (abfd, src->r_ssym, (bfd_byte *) dst->r_ssym);
+  bfd_h_put_8 (abfd, src->r_type3, (bfd_byte *) dst->r_type3);
+  bfd_h_put_8 (abfd, src->r_type2, (bfd_byte *) dst->r_type2);
+  bfd_h_put_8 (abfd, src->r_type, (bfd_byte *) dst->r_type);
+}
+
+/* Swap out a MIPS 64-bit Rela reloc.  */
+
+static void
+mips_elf64_swap_reloca_out (abfd, src, dst)
+     bfd *abfd;
+     const Elf64_Mips_Internal_Rela *src;
+     Elf64_Mips_External_Rela *dst;
+{
+  bfd_h_put_64 (abfd, src->r_offset, (bfd_byte *) dst->r_offset);
+  bfd_h_put_32 (abfd, src->r_sym, (bfd_byte *) dst->r_sym);
+  bfd_h_put_8 (abfd, src->r_ssym, (bfd_byte *) dst->r_ssym);
+  bfd_h_put_8 (abfd, src->r_type3, (bfd_byte *) dst->r_type3);
+  bfd_h_put_8 (abfd, src->r_type2, (bfd_byte *) dst->r_type2);
+  bfd_h_put_8 (abfd, src->r_type, (bfd_byte *) dst->r_type);
+  bfd_h_put_64 (abfd, src->r_offset, (bfd_byte *) dst->r_offset);
+}
+
+/* A mapping from BFD reloc types to MIPS ELF reloc types.  */
+
+struct elf_reloc_map
+{
+  bfd_reloc_code_real_type bfd_reloc_val;
+  enum mips_elf64_reloc_type elf_reloc_val;
+};
+
+static CONST struct elf_reloc_map mips_reloc_map[] =
+{
+  { BFD_RELOC_NONE, R_MIPS_NONE, },
+  { BFD_RELOC_16, R_MIPS_16 },
+  { BFD_RELOC_32, R_MIPS_32 },
+  { BFD_RELOC_64, R_MIPS_64 },
+  { BFD_RELOC_CTOR, R_MIPS_64 },
+  { BFD_RELOC_32_PCREL, R_MIPS_REL32 },
+  { BFD_RELOC_MIPS_JMP, R_MIPS_26 },
+  { BFD_RELOC_HI16_S, R_MIPS_HI16 },
+  { BFD_RELOC_LO16, R_MIPS_LO16 },
+  { BFD_RELOC_MIPS_GPREL, R_MIPS_GPREL16 },
+  { BFD_RELOC_MIPS_LITERAL, R_MIPS_LITERAL },
+  { BFD_RELOC_MIPS_GOT16, R_MIPS_GOT16 },
+  { BFD_RELOC_16_PCREL, R_MIPS_PC16 },
+  { BFD_RELOC_MIPS_CALL16, R_MIPS_CALL16 },
+  { BFD_RELOC_MIPS_GPREL32, R_MIPS_GPREL32 },
+  { BFD_RELOC_MIPS_GOT_HI16, R_MIPS_GOT_HI16 },
+  { BFD_RELOC_MIPS_GOT_LO16, R_MIPS_GOT_LO16 },
+  { BFD_RELOC_MIPS_CALL_HI16, R_MIPS_CALL_HI16 },
+  { BFD_RELOC_MIPS_CALL_LO16, R_MIPS_CALL_LO16 }
+};
+
+/* Given a BFD reloc type, return a howto structure.  */
+
+static reloc_howto_type *
+mips_elf64_reloc_type_lookup (abfd, code)
+     bfd *abfd;
+     bfd_reloc_code_real_type code;
+{
+  unsigned int i;
+
+  for (i = 0; i < sizeof (mips_reloc_map) / sizeof (struct elf_reloc_map); i++)
+    {
+      if (mips_reloc_map[i].bfd_reloc_val == code)
+       {
+         int v;
+
+         v = (int) mips_reloc_map[i].elf_reloc_val;
+         return &mips_elf64_howto_table_rel[v];
+       }
+    }
+
+  return NULL;
+}
+
+/* Read the relocations from one reloc section.  */
+
+static boolean
+mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, rel_hdr)
+     bfd *abfd;
+     asection *asect;
+     asymbol **symbols;
+     const Elf_Internal_Shdr *rel_hdr;
+{
+  PTR allocated = NULL;
+  bfd_byte *native_relocs;
+  arelent *relents;
+  arelent *relent;
+  unsigned int count;
+  unsigned int i;
+  int entsize;
+  reloc_howto_type *howto_table;
+
+  allocated = (PTR) bfd_malloc (rel_hdr->sh_size);
+  if (allocated == NULL)
+    goto error_return;
+
+  if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0
+      || (bfd_read (allocated, 1, rel_hdr->sh_size, abfd) != rel_hdr->sh_size))
+    goto error_return;
+
+  native_relocs = (bfd_byte *) allocated;
+
+  relents = asect->relocation + asect->reloc_count;
+
+  entsize = rel_hdr->sh_entsize;
+  BFD_ASSERT (entsize == sizeof (Elf64_Mips_External_Rel)
+             || entsize == sizeof (Elf64_Mips_External_Rela));
+
+  count = rel_hdr->sh_size / entsize;
+
+  if (entsize == sizeof (Elf64_Mips_External_Rel))
+    howto_table = mips_elf64_howto_table_rel;
+  else
+    howto_table = mips_elf64_howto_table_rela;
+
+  relent = relents;
+  for (i = 0; i < count; i++, native_relocs += entsize)
+    {
+      Elf64_Mips_Internal_Rela rela;
+      boolean used_sym, used_ssym;
+      int ir;
+
+      if (entsize == sizeof (Elf64_Mips_External_Rela))
+       mips_elf64_swap_reloca_in (abfd,
+                                  (Elf64_Mips_External_Rela *) native_relocs,
+                                  &rela);
+      else
+       {
+         Elf64_Mips_Internal_Rel rel;
+
+         mips_elf64_swap_reloc_in (abfd,
+                                   (Elf64_Mips_External_Rel *) native_relocs,
+                                   &rel);
+         rela.r_offset = rel.r_offset;
+         rela.r_sym = rel.r_sym;
+         rela.r_ssym = rel.r_ssym;
+         rela.r_type3 = rel.r_type3;
+         rela.r_type2 = rel.r_type2;
+         rela.r_type = rel.r_type;
+         rela.r_addend = 0;
+       }
+
+      /* Each entry represents up to three actual relocations.  */
+
+      used_sym = false;
+      used_ssym = false;
+      for (ir = 0; ir < 3; ir++)
+       {
+         enum mips_elf64_reloc_type type;
+
+         switch (ir)
+           {
+           default:
+             abort ();
+           case 0:
+             type = (enum mips_elf64_reloc_type) rela.r_type;
+             break;
+           case 1:
+             type = (enum mips_elf64_reloc_type) rela.r_type2;
+             break;
+           case 2:
+             type = (enum mips_elf64_reloc_type) rela.r_type3;
+             break;
+           }
+
+         if (type == R_MIPS_NONE)
+           {
+             /* There are no more relocations in this entry.  If this
+                 is the first entry, we need to generate a dummy
+                 relocation so that the generic linker knows that
+                 there has been a break in the sequence of relocations
+                 applying to a particular address.  */
+             if (ir == 0)
+               {
+                 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+                 if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+                   relent->address = rela.r_offset;
+                 else
+                   relent->address = rela.r_offset - asect->vma;
+                 relent->addend = 0;
+                 relent->howto = &howto_table[(int) R_MIPS_NONE];
+                 ++relent;
+               }
+             break;
+           }
+
+         /* Some types require symbols, whereas some do not.  */
+         switch (type)
+           {
+           case R_MIPS_NONE:
+           case R_MIPS_LITERAL:
+           case R_MIPS_INSERT_A:
+           case R_MIPS_INSERT_B:
+           case R_MIPS_DELETE:
+             relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+             break;
+
+           default:
+             if (! used_sym)
+               {
+                 if (rela.r_sym == 0)
+                   relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+                 else
+                   {
+                     asymbol **ps, *s;
+
+                     ps = symbols + rela.r_sym - 1;
+                     s = *ps;
+                     if ((s->flags & BSF_SECTION_SYM) == 0)
+                       relent->sym_ptr_ptr = ps;
+                     else
+                       relent->sym_ptr_ptr = s->section->symbol_ptr_ptr;
+                   }
+
+                 used_sym = true;
+               }
+             else if (! used_ssym)
+               {
+                 switch (rela.r_ssym)
+                   {
+                   case RSS_UNDEF:
+                     relent->sym_ptr_ptr =
+                       bfd_abs_section_ptr->symbol_ptr_ptr;
+                     break;
+
+                   case RSS_GP:
+                   case RSS_GP0:
+                   case RSS_LOC:
+                     /* FIXME: I think these need to be handled using
+                         special howto structures.  */
+                     BFD_ASSERT (0);
+                     break;
+
+                   default:
+                     BFD_ASSERT (0);
+                     break;
+                   }
+
+                 used_ssym = true;
+               }
+             else
+               relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+
+             break;
+           }
+
+         /* The address of an ELF reloc is section relative for an
+            object file, and absolute for an executable file or
+            shared library.  The address of a BFD reloc is always
+            section relative.  */
+         if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+           relent->address = rela.r_offset;
+         else
+           relent->address = rela.r_offset - asect->vma;
+
+         relent->addend = rela.r_addend;
+
+         relent->howto = &howto_table[(int) type];
+
+         ++relent;
+       }
+    }
+
+  asect->reloc_count += relent - relents;
+
+  if (allocated != NULL)
+    free (allocated);
+
+  return true;
+
+ error_return:
+  if (allocated != NULL)
+    free (allocated);
+  return false;
+}
+
+/* Read the relocations.  On Irix 6, there can be two reloc sections
+   associated with a single data section.  */
+
+static boolean
+mips_elf64_slurp_reloc_table (abfd, asect, symbols)
+     bfd *abfd;
+     asection *asect;
+     asymbol **symbols;
+{
+  struct bfd_elf_section_data * const d = elf_section_data (asect);
+
+  if (asect->relocation != NULL
+      || (asect->flags & SEC_RELOC) == 0
+      || asect->reloc_count == 0)
+    return true;
+
+  /* Allocate space for 3 arelent structures for each Rel structure.  */
+  asect->relocation = ((arelent *)
+                      bfd_alloc (abfd,
+                                 asect->reloc_count * 3 * sizeof (arelent)));
+  if (asect->relocation == NULL)
+    return false;
+
+  /* The slurp_one_reloc_table routine increments reloc_count.  */
+  asect->reloc_count = 0;
+
+  if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, &d->rel_hdr))
+    return false;
+  if (d->rel_hdr2 != NULL)
+    {
+      if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols,
+                                             d->rel_hdr2))
+       return false;
+    }
+
+  return true;
+}
+
+/* Write out the relocations.  */
+
+static void
+mips_elf64_write_relocs (abfd, sec, data)
+     bfd *abfd;
+     asection *sec;
+     PTR data;
+{
+  /* FIXME.  */
+  abort ();
+}
+\f
+/* Handle a 64-bit MIPS ELF specific section.  */
+
+static boolean
+mips_elf64_section_from_shdr (abfd, hdr, name)
+     bfd *abfd;
+     Elf_Internal_Shdr *hdr;
+     char *name;
+{
+  if (! _bfd_mips_elf_section_from_shdr (abfd, hdr, name))
+    return false;
+
+  return true;
+}
+
+/* Relocations in the 64 bit MIPS ELF ABI are more complex than in
+   standard ELF.  This structure is used to redirect the relocation
+   handling routines.  */
+
+const struct elf_size_info mips_elf64_size_info =
+{
+  sizeof (Elf64_External_Ehdr),
+  sizeof (Elf64_External_Phdr),
+  sizeof (Elf64_External_Shdr),
+  sizeof (Elf64_Mips_External_Rel),
+  sizeof (Elf64_Mips_External_Rela),
+  sizeof (Elf64_External_Sym),
+  sizeof (Elf64_External_Dyn),
+  sizeof (Elf_External_Note),
+  64,          /* arch_size */
+  8,           /* file_align */
+  ELFCLASS64,
+  EV_CURRENT,
+  bfd_elf64_write_out_phdrs,
+  bfd_elf64_write_shdrs_and_ehdr,
+  mips_elf64_write_relocs,
+  bfd_elf64_swap_symbol_out,
+  mips_elf64_slurp_reloc_table,
+  bfd_elf64_slurp_symbol_table,
+  bfd_elf64_swap_dyn_in
+};
+
+#define TARGET_LITTLE_SYM              bfd_elf64_littlemips_vec
+#define TARGET_LITTLE_NAME             "elf64-littlemips"
+#define TARGET_BIG_SYM                 bfd_elf64_bigmips_vec
+#define TARGET_BIG_NAME                        "elf64-bigmips"
+#define ELF_ARCH                       bfd_arch_mips
+#define ELF_MACHINE_CODE               EM_MIPS
+#define ELF_MAXPAGESIZE                        0x1000
+#define elf_backend_size_info          mips_elf64_size_info
+#define elf_backend_section_from_shdr  mips_elf64_section_from_shdr
+#define bfd_elf64_bfd_reloc_type_lookup        mips_elf64_reloc_type_lookup
+
+#include "elf64-target.h"
index 85d991d3a399ef71702ffc854b1c5d2fd7b1ef46..405e79f6ce8970bb00cc7e1de800bd181b48c1b5 100644 (file)
@@ -63,7 +63,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
        it's cast in stone.
  */
 
-#include <string.h>            /* For strrchr and friends */
 #include "bfd.h"
 #include "sysdep.h"
 #include "bfdlink.h"
@@ -100,6 +99,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define elf_swap_dyn_out               NAME(bfd_elf,swap_dyn_out)
 #define elf_get_reloc_upper_bound      NAME(bfd_elf,get_reloc_upper_bound)
 #define elf_canonicalize_reloc         NAME(bfd_elf,canonicalize_reloc)
+#define elf_slurp_symbol_table         NAME(bfd_elf,slurp_symbol_table)
 #define elf_get_symtab                 NAME(bfd_elf,get_symtab)
 #define elf_canonicalize_dynamic_symtab \
   NAME(bfd_elf,canonicalize_dynamic_symtab)
@@ -115,6 +115,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define elf_find_section               NAME(bfd_elf,find_section)
 #define elf_bfd_link_add_symbols       NAME(bfd_elf,bfd_link_add_symbols)
 #define elf_add_dynamic_entry          NAME(bfd_elf,add_dynamic_entry)
+#define elf_write_shdrs_and_ehdr       NAME(bfd_elf,write_shdrs_and_ehdr)
+#define elf_write_out_phdrs            NAME(bfd_elf,write_out_phdrs)
 #define elf_link_create_dynamic_sections \
   NAME(bfd_elf,link_create_dynamic_sections)
 #define elf_link_record_dynamic_symbol  _bfd_elf_link_record_dynamic_symbol
@@ -141,6 +143,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 /* Forward declarations of static functions */
 
+static void elf_swap_ehdr_in
+  PARAMS ((bfd *, const Elf_External_Ehdr *, Elf_Internal_Ehdr *));
+static void elf_swap_ehdr_out
+  PARAMS ((bfd *, const Elf_Internal_Ehdr *, Elf_External_Ehdr *));
+static void elf_swap_shdr_in
+  PARAMS ((bfd *, const Elf_External_Shdr *, Elf_Internal_Shdr *));
+static void elf_swap_shdr_out
+  PARAMS ((bfd *, const Elf_Internal_Shdr *, Elf_External_Shdr *));
+
 #define elf_stringtab_init _bfd_elf_stringtab_init
 
 extern struct bfd_strtab_hash *_bfd_elf_stringtab_init PARAMS ((void));
@@ -148,8 +159,6 @@ extern struct bfd_strtab_hash *_bfd_elf_stringtab_init PARAMS ((void));
 extern boolean bfd_section_from_phdr PARAMS ((bfd *, Elf_Internal_Phdr *,
                                              int));
 
-static long elf_slurp_symbol_table PARAMS ((bfd *, asymbol **, boolean));
-
 static boolean elf_slurp_reloc_table PARAMS ((bfd *, asection *, asymbol **));
 
  int _bfd_elf_symbol_from_bfd_symbol PARAMS ((bfd *,
@@ -185,7 +194,7 @@ static char *elf_symbol_flags PARAMS ((flagword));
 void
 elf_swap_symbol_in (abfd, src, dst)
      bfd *abfd;
-     Elf_External_Sym *src;
+     const Elf_External_Sym *src;
      Elf_Internal_Sym *dst;
 {
   dst->st_name = bfd_h_get_32 (abfd, (bfd_byte *) src->st_name);
@@ -202,7 +211,7 @@ elf_swap_symbol_in (abfd, src, dst)
 void
 elf_swap_symbol_out (abfd, src, cdst)
      bfd *abfd;
-     Elf_Internal_Sym *src;
+     const Elf_Internal_Sym *src;
      PTR cdst;
 {
   Elf_External_Sym *dst = (Elf_External_Sym *) cdst;
@@ -221,7 +230,7 @@ elf_swap_symbol_out (abfd, src, cdst)
 static void
 elf_swap_ehdr_in (abfd, src, dst)
      bfd *abfd;
-     Elf_External_Ehdr *src;
+     const Elf_External_Ehdr *src;
      Elf_Internal_Ehdr *dst;
 {
   memcpy (dst->e_ident, src->e_ident, EI_NIDENT);
@@ -246,7 +255,7 @@ elf_swap_ehdr_in (abfd, src, dst)
 static void
 elf_swap_ehdr_out (abfd, src, dst)
      bfd *abfd;
-     Elf_Internal_Ehdr *src;
+     const Elf_Internal_Ehdr *src;
      Elf_External_Ehdr *dst;
 {
   memcpy (dst->e_ident, src->e_ident, EI_NIDENT);
@@ -273,7 +282,7 @@ elf_swap_ehdr_out (abfd, src, dst)
 static void
 elf_swap_shdr_in (abfd, src, dst)
      bfd *abfd;
-     Elf_External_Shdr *src;
+     const Elf_External_Shdr *src;
      Elf_Internal_Shdr *dst;
 {
   dst->sh_name = bfd_h_get_32 (abfd, (bfd_byte *) src->sh_name);
@@ -296,7 +305,7 @@ elf_swap_shdr_in (abfd, src, dst)
 static void
 elf_swap_shdr_out (abfd, src, dst)
      bfd *abfd;
-     Elf_Internal_Shdr *src;
+     const Elf_Internal_Shdr *src;
      Elf_External_Shdr *dst;
 {
   /* note that all elements of dst are *arrays of unsigned char* already... */
@@ -319,7 +328,7 @@ elf_swap_shdr_out (abfd, src, dst)
 void
 elf_swap_phdr_in (abfd, src, dst)
      bfd *abfd;
-     Elf_External_Phdr *src;
+     const Elf_External_Phdr *src;
      Elf_Internal_Phdr *dst;
 {
   dst->p_type = bfd_h_get_32 (abfd, (bfd_byte *) src->p_type);
@@ -335,7 +344,7 @@ elf_swap_phdr_in (abfd, src, dst)
 void
 elf_swap_phdr_out (abfd, src, dst)
      bfd *abfd;
-     Elf_Internal_Phdr *src;
+     const Elf_Internal_Phdr *src;
      Elf_External_Phdr *dst;
 {
   /* note that all elements of dst are *arrays of unsigned char* already... */
@@ -353,7 +362,7 @@ elf_swap_phdr_out (abfd, src, dst)
 INLINE void
 elf_swap_reloc_in (abfd, src, dst)
      bfd *abfd;
-     Elf_External_Rel *src;
+     const Elf_External_Rel *src;
      Elf_Internal_Rel *dst;
 {
   dst->r_offset = get_word (abfd, (bfd_byte *) src->r_offset);
@@ -363,7 +372,7 @@ elf_swap_reloc_in (abfd, src, dst)
 INLINE void
 elf_swap_reloca_in (abfd, src, dst)
      bfd *abfd;
-     Elf_External_Rela *src;
+     const Elf_External_Rela *src;
      Elf_Internal_Rela *dst;
 {
   dst->r_offset = get_word (abfd, (bfd_byte *) src->r_offset);
@@ -375,7 +384,7 @@ elf_swap_reloca_in (abfd, src, dst)
 INLINE void
 elf_swap_reloc_out (abfd, src, dst)
      bfd *abfd;
-     Elf_Internal_Rel *src;
+     const Elf_Internal_Rel *src;
      Elf_External_Rel *dst;
 {
   put_word (abfd, src->r_offset, dst->r_offset);
@@ -385,7 +394,7 @@ elf_swap_reloc_out (abfd, src, dst)
 INLINE void
 elf_swap_reloca_out (abfd, src, dst)
      bfd *abfd;
-     Elf_Internal_Rela *src;
+     const Elf_Internal_Rela *src;
      Elf_External_Rela *dst;
 {
   put_word (abfd, src->r_offset, dst->r_offset);
@@ -540,7 +549,11 @@ elf_object_p (abfd)
          if ((*target_ptr)->flavour != bfd_target_elf_flavour)
            continue;
          back = (struct elf_backend_data *) (*target_ptr)->backend_data;
-         if (back->elf_machine_code == i_ehdrp->e_machine)
+         if (back->elf_machine_code == i_ehdrp->e_machine
+             || (back->elf_machine_alt1 != 0
+                 && back->elf_machine_alt1 == i_ehdrp->e_machine)
+             || (back->elf_machine_alt2 != 0
+                 && back->elf_machine_alt2 == i_ehdrp->e_machine))
            {
              /* target_ptr is an ELF backend which matches this
                 object file, so reject the generic ELF target.  */
@@ -776,7 +789,7 @@ write_relocs (abfd, sec, data)
   unsigned int idx;
   int use_rela_p = get_elf_backend_data (abfd)->use_rela_p;
   asymbol *last_sym = 0;
-  int last_sym_idx = 9999999;  /* should always be written before use */
+  int last_sym_idx = 0;
 
   /* If we have already failed, don't do anything.  */
   if (*failedp)
@@ -832,10 +845,16 @@ write_relocs (abfd, sec, data)
          else
            {
              last_sym = sym;
-             last_sym_idx = n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
+             n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
+             if (n < 0)
+               {
+                 *failedp = true;
+                 return;
+               }
+             last_sym_idx = n;
            }
 
-         if ((*areloc->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
+         if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
              && ! validate_reloc (abfd, ptr))
            {
              *failedp = true;
@@ -878,10 +897,16 @@ write_relocs (abfd, sec, data)
          else
            {
              last_sym = sym;
-             last_sym_idx = n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
+             n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
+             if (n < 0)
+               {
+                 *failedp = true;
+                 return;
+               }
+             last_sym_idx = n;
            }
 
-         if ((*areloc->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
+         if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
              && ! validate_reloc (abfd, ptr))
            {
              *failedp = true;
@@ -895,10 +920,12 @@ write_relocs (abfd, sec, data)
     }
 }
 
-static int
-write_out_phdrs (abfd, phdr, count)
+/* Write out the program headers.  */
+
+int
+elf_write_out_phdrs (abfd, phdr, count)
      bfd *abfd;
-     Elf_Internal_Phdr *phdr;
+     const Elf_Internal_Phdr *phdr;
      int count;
 {
   while (count--)
@@ -913,8 +940,10 @@ write_out_phdrs (abfd, phdr, count)
   return 0;
 }
 
-static boolean
-write_shdrs_and_ehdr (abfd)
+/* Write out the section headers and the ELF file header.  */
+
+boolean
+elf_write_shdrs_and_ehdr (abfd)
      bfd *abfd;
 {
   Elf_External_Ehdr x_ehdr;    /* Elf file header, external form */
@@ -960,7 +989,7 @@ write_shdrs_and_ehdr (abfd)
   return true;
 }
 
-static long
+long
 elf_slurp_symbol_table (abfd, symptrs, dynamic)
      bfd *abfd;
      asymbol **symptrs;                /* Buffer for generated bfd symbols */
@@ -1384,8 +1413,8 @@ const struct elf_size_info NAME(_bfd_elf,size_info) = {
 
   ARCH_SIZE, FILE_ALIGN,
   ELFCLASS, EV_CURRENT,
-  write_out_phdrs,
-  write_shdrs_and_ehdr,
+  elf_write_out_phdrs,
+  elf_write_shdrs_and_ehdr,
   write_relocs,
   elf_swap_symbol_out,
   elf_slurp_reloc_table,
index f1573f4b0a0edc0828f6a0c202fed0fc06443f9f..b4e68ecc2bef2d814c11cdf6e498ab8c808a439f 100644 (file)
@@ -1,5 +1,5 @@
 /* Target definitions for NN-bit ELF
-   Copyright 1993, 1994, 1995 Free Software Foundation, Inc.
+   Copyright 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -69,10 +69,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define elf_backend_want_plt_sym 0
 #endif
 
-#ifndef elf_backend_want_hdr_in_seg
-#define elf_backend_want_hdr_in_seg 0
-#endif
-
 #define bfd_elfNN_bfd_debug_info_start bfd_void
 #define bfd_elfNN_bfd_debug_info_end   bfd_void
 #define bfd_elfNN_bfd_debug_info_accumulate    (PROTO(void,(*),(bfd*, struct sec *))) bfd_void
@@ -145,6 +141,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define bfd_elfNN_bfd_link_split_section _bfd_generic_link_split_section
 #endif
 
+#ifndef elf_symbol_leading_char
+#define elf_symbol_leading_char 0
+#endif
+
+#ifndef elf_info_to_howto
+#define elf_info_to_howto 0
+#endif
+
 #ifndef elf_info_to_howto_rel
 #define elf_info_to_howto_rel 0
 #endif
@@ -235,6 +239,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define ELF_MACHINE_ALT2 0
 #endif
 
+#ifndef elf_backend_size_info
+#define elf_backend_size_info _bfd_elfNN_size_info
+#endif
+
 extern const struct elf_size_info _bfd_elfNN_size_info;
 
 static CONST struct elf_backend_data elfNN_bed =
@@ -275,11 +283,10 @@ static CONST struct elf_backend_data elfNN_bed =
   elf_backend_ecoff_debug_swap,
   ELF_MACHINE_ALT1,
   ELF_MACHINE_ALT2,
-  &_bfd_elfNN_size_info,
+  &elf_backend_size_info,
   elf_backend_want_got_plt,
   elf_backend_plt_readonly,
-  elf_backend_want_plt_sym,
-  elf_backend_want_hdr_in_seg,
+  elf_backend_want_plt_sym
 };
 
 #ifdef TARGET_BIG_SYM
@@ -307,7 +314,7 @@ const bfd_target TARGET_BIG_SYM =
 
    /* leading_symbol_char: is the first char of a user symbol
       predictable, and if so what is it */
-   0,
+  elf_symbol_leading_char,
 
   /* ar_pad_char: pad character for filenames within an archive header
      FIXME:  this really has nothing to do with ELF, this is a characteristic
@@ -391,7 +398,7 @@ const bfd_target TARGET_LITTLE_SYM =
 
    /* leading_symbol_char: is the first char of a user symbol
       predictable, and if so what is it */
-   0,
+  elf_symbol_leading_char,
 
   /* ar_pad_char: pad character for filenames within an archive header
      FIXME:  this really has nothing to do with ELF, this is a characteristic