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


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

PATCH for MIPS 64-bit ABI suport



This patch contains the remainder of the 64-bit MIPS ABI support, with
the exception of the linker emulation bits, which I will send once
these are approved.  Although large, this patch is very simple: many
32-bit functions are made public, 32-bit hardwiring in them replaced
with generic code, and the elf64-mips.c then makes use of these
functions.

OK to check in?

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

1999-07-07  Mark Mitchell  <mark@codesourcery.com>

	* elf-bfd.h (_bfd_mips_elf_section_from_shdr): Constify.
	(_bfd_mips_elf_create_dynamic_sections): New function.
	(_bfd_mips_elf_add_symbol_hook): Likewise.
	(_bfd_mips_elf_adjust_dynamic_symbol): Likewise.
	(_bfd_mips_elf_finish_dynamic_symbol): Likewise.	
	(_bfd_mips_elf_finish_dynamic_sections): Likewise.
	(_bfd_mips_elf_gc_mark_hook): Likewise.
	(_bfd_mips_elf_gc_sweep_hook): Likewise.
	(_bfd_mips_elf_always_size_sections): Likewise.
	(_bfd_mips_elf_size_dynamic_sections): Likewise.
	(_bfd_mips_elf_check_relocs): Likewise.
	(_bfd_mips_elf_link_hash_table_create): Likewise.
	(_bfd_mips_elf_print_private_data): Likewise.
	(_bfd_mips_elf_link_output_symbol_hook): Likewise.
	(_bfd_mips_elf_final_link): Likewise.
	(_bfd_mips_elf_additional_program_headers): Likewise.
	(_bfd_mips_elf_modify_segment_map): Likewise.
	(_bfd_mips_elf_relocate_section): Likewise.
	* elf32-mips.c (mips_elf32_object_p): Move contents into
	_bfd_mips_elf_object_p.
	(mips_elf_additional_program_headers): Rename to
	_bfd_mips_elf_additional_program_headers.
	(mips_elf_modify_segment_map): Rename to
	_bfd_mips_elf_modify_segment_map.
	(elf_mips_abi_name): Change prototype.
	(mips_elf32_section_from_shdr): Merge into
	_bfd_mips_elf_section_from_shdr.
	(mips_elf32_section_processing): Merge into
	_bfd_mips_elf_section_processing.
	(mips_elf_final_link): Rename to _bfd_mips_elf_final_link.  Invoke
	the right back-end ELF linker.
	(mips_elf_relocate_section): Rename to
	_bfd_mips_elf_relocate_section.  Clean up.  Adjust for 64-bit code.
	(mips_elf_link_output_symbol_hook): Rename to
	_bfd_mips_elf_link_output_symbol_hook.
	(mips_elf_create_dynamic_section): Rename to
	_bfd_mips_elf_create_dynamic_section.
	(mips_elf_check_relocs): Rename to _bfd_mips_elf_check_relocs.
	Adjust for 64-bit code.  Use mips_elf_got_section.
	(mips_elf_adjust_dynamic_symbol): Rename to
	_bfd_mips_elf_adjust_dynamic_symbol.  Use
	mips_elf_allocate_dynamic_relocations.
	(mips_elf_finish_dynamic_symbol): Rename to
	_bfd_mips_elf_finish_dynamic_symbol.  Use mips_elf_got_section.
	Adjust for 64-bit code.
	(mips_elf_finish_dynamic_sections): Rename to
	_bfd_mips_elf_finish_dynamic_sections.  Adjust for 64-bit code.
	(mips_elf_always_size_sections): Rename to
	_bfd_mips_elf_always_size_sections.
	(mips_elf_add_symbol_hook): Rename to
	_bfd_mips_elf_add_symbol_hook.
	(mips_elf_next_lo16_addend): Constify.
	(mips_elf_calculate_relocation): Likewise.
	(mips_elf_obtain_contents): Likewise.
	(mips_elf_perform_relocation): Likewise.
	(mips_elf_create_dynamic_relocation): Likewise.
	(mips_elf_allocate_dynamic_relocations): New function.
	(MIPS_ELF_REL_DYN_SECTION_NAME): New macro.
	(MIPS_ELF_REL_SIZE): Likewise.
	(MIPS_ELF_DYN_SIZE): Likewise.
	(MIPS_ELF_GOT_SIZE): Likewise.
	(MIPS_ELF_SYM_SIZE): Likewise.
	(MIPS_ELF_LOG_FILE_ALIGN): Likewise.
	(MIPS_ELF_GET_WORD): Likewise.
	(MIPS_ELF_PUT_WORD): Likewise.
	(MIPS_ELF_ADD_DYNAMIC_ENTRY): Likewise.
	(STUB_LW): Conditionalize for 64-bit value.
	(elf_mips_howto_table): Add R_MIPS_HIGHER and R_MIPS_HIGHEST
	entries.
	(_bfd_mips_elf_merge_private_bfd_data): Merge e_ident[EI_CLASS].
	Check it for inconsistency.
	(_bfd_mips_elf_print_private_bfd_data): Print ABI=64 for 64-bit
	ABI.
	(_bfd_mips_elf_fake_sections): Remove duplicate handling of
	.msym. 
	(mips_elf_global_got_index): Use MIPS_ELF_GOT_SIZE.
	(mips_elf_got_offset_from_index): Use misp_elf_got_section.
	(mips_elf_create_local_got_entry): Use MIPS_ELF_GOT_SIZE.
	(mips_elf_local_got_index): Likewise.
	(mips_elf_got_page): Likewise.
	(mips_elf_got_info): Likewise.
	(mips_elf_create_dynamic_relocation): Handle 32-bit/64-bit split.
	(ELF_DYNAMIC_INTERPRETER): Handle 64-bit code.
	(mips_elf_create_dynamic_sections): Use MIPS_ELF_LOG_FILE_ALIGN,
	instead of constant `2'.
	(mips_elf_create_got_section): Tidy.  Use MIPS_ELF_GOT_SIZE.
	(mips_elf_create_msym_section): Use MIPS_ELF_LOG_FILE_ALIGN.
	(mips_elf_size_dynamic_sections): Use
	MIPS_ELF_REL_DYN_SECTION_NAME, MIPS_ELF_GOT_SIZE,
	MIPS_ELF_ADD_DYNAMIC_ENTRY.  Remove #if 0'd code.
	Adjust all releveant entries in elf backend table.
	* elf64-mips.c (mips_elf64_section_from_shdr): Remove.
	(mips_elf64_section_processing): Likewise.
	Adjust elf backend entries to use _bfd_mips_elf variants now
	publicly available.

Index: elf-bfd.h
===================================================================
RCS file: /cvs/binutils/binutils/bfd/elf-bfd.h,v
retrieving revision 1.8
diff -u -p -r1.8 elf-bfd.h
--- elf-bfd.h	1999/07/07 17:50:53	1.8
+++ elf-bfd.h	1999/07/08 01:01:22
@@ -1147,7 +1147,7 @@ boolean _bfd_elf64_gc_record_vtentry
 
 extern boolean _bfd_mips_elf_object_p PARAMS ((bfd *));
 extern boolean _bfd_mips_elf_section_from_shdr
-  PARAMS ((bfd *, Elf_Internal_Shdr *, const char *));
+  PARAMS ((bfd *, Elf_Internal_Shdr *, char *));
 extern boolean _bfd_mips_elf_fake_sections
   PARAMS ((bfd *, Elf_Internal_Shdr *, asection *));
 extern boolean _bfd_mips_elf_section_from_bfd_section
@@ -1176,5 +1176,44 @@ extern boolean _bfd_mips_elf_find_neares
 	   const char **, unsigned int *));
 extern boolean _bfd_mips_elf_set_section_contents
   PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
+extern boolean _bfd_mips_elf_create_dynamic_sections
+  PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean _bfd_mips_elf_add_symbol_hook
+  PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
+	   const char **, flagword *, asection **, bfd_vma *));
+extern boolean _bfd_mips_elf_adjust_dynamic_symbol
+  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
+extern boolean _bfd_mips_elf_finish_dynamic_symbol
+  PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
+	   Elf_Internal_Sym *));
+extern boolean _bfd_mips_elf_finish_dynamic_sections
+  PARAMS ((bfd *, struct bfd_link_info *));
+extern asection * _bfd_mips_elf_gc_mark_hook 
+  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
+extern boolean _bfd_mips_elf_gc_sweep_hook 
+  PARAMS ((bfd *, struct bfd_link_info *, asection *, 
+	   const Elf_Internal_Rela *));
+extern boolean _bfd_mips_elf_always_size_sections
+  PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean _bfd_mips_elf_size_dynamic_sections
+  PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean _bfd_mips_elf_check_relocs
+  PARAMS ((bfd *, struct bfd_link_info *, asection *,
+	   const Elf_Internal_Rela *));
+extern struct bfd_link_hash_table *_bfd_mips_elf_link_hash_table_create
+  PARAMS ((bfd *));
+extern boolean _bfd_mips_elf_print_private_bfd_data 
+  PARAMS ((bfd *, PTR));
+extern boolean _bfd_mips_elf_link_output_symbol_hook
+  PARAMS ((bfd *, struct bfd_link_info *, const char *, Elf_Internal_Sym *,
+	   asection *));
+extern boolean _bfd_mips_elf_final_link
+  PARAMS ((bfd *, struct bfd_link_info *));
+extern int _bfd_mips_elf_additional_program_headers PARAMS ((bfd *));
+extern boolean _bfd_mips_elf_modify_segment_map PARAMS ((bfd *));
+extern boolean _bfd_mips_elf_relocate_section
+  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+	   Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
 
 #endif /* _LIBELF_H_ */
Index: elf32-mips.c
===================================================================
RCS file: /cvs/binutils/binutils/bfd/elf32-mips.c,v
retrieving revision 1.13
diff -u -p -r1.13 elf32-mips.c
--- elf32-mips.c	1999/07/02 21:03:53	1.13
+++ elf32-mips.c	1999/07/08 01:01:26
@@ -3,6 +3,8 @@
 
    Most of the information added by Ian Lance Taylor, Cygnus Support,
    <ian@cygnus.com>.
+   N32/64 ABI support added by Mark Mitchell, CodeSourcery, LLC.
+   <mark@codesourcery.com>
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -106,19 +108,12 @@ static void bfd_mips_elf_swap_msym_in 
 static void bfd_mips_elf_swap_msym_out
   PARAMS ((bfd *, const Elf32_Internal_Msym *, Elf32_External_Msym *));
 static boolean mips_elf_sym_is_global PARAMS ((bfd *, asymbol *));
-static boolean mips_elf32_object_p PARAMS ((bfd *));
 static boolean mips_elf_create_procedure_table
   PARAMS ((PTR, bfd *, struct bfd_link_info *, asection *,
 	   struct ecoff_debug_info *));
-static int mips_elf_additional_program_headers PARAMS ((bfd *));
-static boolean mips_elf_modify_segment_map PARAMS ((bfd *));
 static INLINE int elf_mips_isa PARAMS ((flagword));
 static INLINE int elf_mips_mach PARAMS ((flagword));
-static INLINE char* elf_mips_abi_name PARAMS ((flagword));
-static boolean mips_elf32_section_from_shdr
-  PARAMS ((bfd *, Elf32_Internal_Shdr *, char *));
-static boolean mips_elf32_section_processing
-  PARAMS ((bfd *, Elf32_Internal_Shdr *));
+static INLINE char* elf_mips_abi_name PARAMS ((bfd *));
 static boolean mips_elf_is_local_label_name
   PARAMS ((bfd *, const char *));
 static struct bfd_hash_entry *mips_elf_link_hash_newfunc
@@ -126,8 +121,6 @@ static struct bfd_hash_entry *mips_elf_l
 static struct bfd_link_hash_table *mips_elf_link_hash_table_create
   PARAMS ((bfd *));
 static int gptab_compare PARAMS ((const void *, const void *));
-static boolean mips_elf_final_link
-  PARAMS ((bfd *, struct bfd_link_info *));
 static void mips_elf_relocate_hi16
   PARAMS ((bfd *, Elf_Internal_Rela *, Elf_Internal_Rela *, bfd_byte *,
 	   bfd_vma));
@@ -140,35 +133,10 @@ static bfd_reloc_status_type mips16_jump
   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
 static bfd_reloc_status_type mips16_gprel_reloc
   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-static boolean mips_elf_relocate_section
-  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
-	   Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
-static boolean mips_elf_link_output_symbol_hook
-  PARAMS ((bfd *, struct bfd_link_info *, const char *, Elf_Internal_Sym *,
-	   asection *));
-static boolean mips_elf_create_dynamic_sections
-  PARAMS ((bfd *, struct bfd_link_info *));
 static boolean mips_elf_create_compact_rel_section
   PARAMS ((bfd *, struct bfd_link_info *));
 static boolean mips_elf_create_got_section
   PARAMS ((bfd *, struct bfd_link_info *));
-static boolean mips_elf_check_relocs
-  PARAMS ((bfd *, struct bfd_link_info *, asection *,
-	   const Elf_Internal_Rela *));
-static boolean mips_elf_adjust_dynamic_symbol
-  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
-static boolean mips_elf_always_size_sections
-  PARAMS ((bfd *, struct bfd_link_info *));
-static boolean mips_elf_size_dynamic_sections
-  PARAMS ((bfd *, struct bfd_link_info *));
-static boolean mips_elf_finish_dynamic_symbol
-  PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
-	   Elf_Internal_Sym *));
-static boolean mips_elf_finish_dynamic_sections
-  PARAMS ((bfd *, struct bfd_link_info *));
-static boolean mips_elf_add_symbol_hook
-  PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
-	   const char **, flagword *, asection **, bfd_vma *));
 static bfd_reloc_status_type mips_elf_final_gp
   PARAMS ((bfd *, asymbol *, boolean, char **, bfd_vma *));
 static bfd_byte *elf32_mips_get_relocated_section_contents
@@ -195,16 +163,15 @@ static boolean mips_elf_record_global_go
 static bfd_vma mips_elf_got_page
   PARAMS ((bfd *, struct bfd_link_info *, bfd_vma, bfd_vma *));
 static boolean mips_elf_next_lo16_addend
-  PARAMS ((Elf_Internal_Rela *, Elf_Internal_Rela *, bfd_vma *));
+  PARAMS ((const Elf_Internal_Rela *, const Elf_Internal_Rela *, bfd_vma *));
 static bfd_reloc_status_type mips_elf_calculate_relocation
   PARAMS ((bfd *, bfd *, asection *, struct bfd_link_info *,
-	   Elf_Internal_Rela *, bfd_vma, reloc_howto_type *,
-	   Elf_Internal_Rela *, Elf_Internal_Sym *, asection **,
-	   bfd_vma *, const char **));
+	   const Elf_Internal_Rela *, bfd_vma, reloc_howto_type *,
+	   Elf_Internal_Sym *, asection **, bfd_vma *, const char **));
 static bfd_vma mips_elf_obtain_contents
-  PARAMS ((reloc_howto_type *, Elf_Internal_Rela *, bfd *, bfd_byte *));
+  PARAMS ((reloc_howto_type *, const Elf_Internal_Rela *, bfd *, bfd_byte *));
 static void mips_elf_perform_relocation
-  PARAMS ((reloc_howto_type *, Elf_Internal_Rela *, bfd_vma,
+  PARAMS ((reloc_howto_type *, const Elf_Internal_Rela *, bfd_vma,
 	   bfd *, bfd_byte *));
 static boolean mips_elf_assign_gp PARAMS ((bfd *, bfd_vma *));
 static boolean mips_elf_sort_hash_table_f 
@@ -219,8 +186,10 @@ static bfd_vma mips_elf_create_local_got
 static bfd_vma mips_elf_got16_entry 
   PARAMS ((bfd *, struct bfd_link_info *, bfd_vma));
 static unsigned int mips_elf_create_dynamic_relocation 
-  PARAMS ((bfd *, struct bfd_link_info *, Elf32_Internal_Rela *,
+  PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Rela *,
 	   long, bfd_vma, asection *));
+static void mips_elf_allocate_dynamic_relocations 
+  PARAMS ((bfd *, unsigned int));
 
 /* The level of IRIX compatibility we're striving for.  */
 
@@ -266,15 +235,56 @@ typedef enum {
 #define MIPS_ELF_STUB_SECTION_NAME(abfd) \
   (IRIX_COMPAT (abfd) == ict_irix6 ? ".MIPS.stubs" : ".stub")
 
+/* The name of the dynamic relocation section.  */
+#define MIPS_ELF_REL_DYN_SECTION_NAME(abfd) ".rel.dyn"
+
+/* The size of an external REL relocation.  */
+#define MIPS_ELF_REL_SIZE(abfd) \
+  (get_elf_backend_data (abfd)->s->sizeof_rel)
+
+/* The size of an external dynamic table entry.  */
+#define MIPS_ELF_DYN_SIZE(abfd) \
+  (get_elf_backend_data (abfd)->s->sizeof_dyn)
+
+/* The size of a GOT entry.  */
+#define MIPS_ELF_GOT_SIZE(abfd) \
+  (get_elf_backend_data (abfd)->s->arch_size / 8)
+
+/* The size of a symbol-table entry.  */
+#define MIPS_ELF_SYM_SIZE(abfd) \
+  (get_elf_backend_data (abfd)->s->sizeof_sym)
+
+/* The default alignment for sections, as a power of two.  */
+#define MIPS_ELF_LOG_FILE_ALIGN(abfd)				\
+  (get_elf_backend_data (abfd)->s->file_align == 8 ? 3 : 2)
+
+/* Get word-sized data.  */
+#define MIPS_ELF_GET_WORD(abfd, ptr) \
+  (ABI_64_P (abfd) ? bfd_get_64 (abfd, ptr) : bfd_get_32 (abfd, ptr))
+
+/* Put out word-sized data.  */
+#define MIPS_ELF_PUT_WORD(abfd, val, ptr)	\
+  (ABI_64_P (abfd) 				\
+   ? bfd_put_64 (abfd, val, ptr) 		\
+   : bfd_put_32 (abfd, val, ptr))
+
+/* Add a dynamic symbol table-entry.  */
+#define MIPS_ELF_ADD_DYNAMIC_ENTRY(info, tag, val) \
+  (ABI_64_P (elf_hash_table (info)->dynobj)	   \
+   ? bfd_elf64_add_dynamic_entry (info, tag, val)  \
+   : bfd_elf32_add_dynamic_entry (info, tag, val))
+
 /* The number of local .got entries we reserve.  */
 #define MIPS_RESERVED_GOTNO (2)
 
 /* Instructions which appear in a stub.  For some reason the stub is
    slightly different on an SGI system.  */
 #define ELF_MIPS_GP_OFFSET(abfd) (SGI_COMPAT (abfd) ? 0x7ff0 : 0x8000)
-#define STUB_LW(abfd)					\
-  (SGI_COMPAT (abfd)					\
-   ? 0x8f998010			/* lw t9,0x8010(gp) */	\
+#define STUB_LW(abfd)						\
+  (SGI_COMPAT (abfd)						\
+   ? (ABI_64_P (abfd)  						\
+      ? 0xdf998010		/* ld t9,0x8010(gp) */		\
+      : 0x8f998010)             /* lw t9,0x8010(gp) */		\
    : 0x8f998000)		/* lw t9,0x8000(gp) */
 #define STUB_MOVE 0x03e07825	/* move t7,ra */
 #define STUB_JALR 0x0320f809	/* jal t9 */
@@ -775,11 +785,36 @@ static reloc_howto_type elf_mips_howto_t
   { R_MIPS_INSERT_A },
   { R_MIPS_INSERT_B },
   { R_MIPS_DELETE },
+
+  /* Get the higher value of a 64 bit addend.  */
+  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 higher values of a 64 bit addend.  Presumably not used in
-     32 bit ELF.  */
-  { R_MIPS_HIGHER },
-  { R_MIPS_HIGHEST },
+  /* Get the highest value of a 64 bit addend.  */
+  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.  */
   HOWTO (R_MIPS_CALL_HI16,	/* type */
@@ -1741,12 +1776,20 @@ elf_mips_mach (flags)
   return 0;
 }
 
-/* Return printable name for ABI from flagword. */
+/* Return printable name for ABI. */
 
 static INLINE char*
-elf_mips_abi_name (flags)
-     flagword flags;
+elf_mips_abi_name (abfd)
+     bfd *abfd;
 {
+  flagword flags;
+
+  if (ABI_N32_P (abfd))
+    return "N32";
+  else if (ABI_64_P (abfd))
+    return "64";
+      
+  flags = elf_elfheader (abfd)->e_flags;
   switch (flags & EF_MIPS_ABI)
     {
     case 0:
@@ -2108,23 +2151,15 @@ boolean
 _bfd_mips_elf_object_p (abfd)
      bfd *abfd;
 {
-  bfd_default_set_arch_mach (abfd, bfd_arch_mips,
-			     elf_mips_mach (elf_elfheader (abfd)->e_flags));
-  return true;
-}
-
-/* Set the right machine number for a 32-bit MIPS ELF file.  */
-
-static boolean
-mips_elf32_object_p (abfd)
-     bfd *abfd;
-{
-  /* Irix 5 is broken.  Object file symbol tables are not always
+  /* Irix 5 and 6 is broken.  Object file symbol tables are not always
      sorted correctly such that local symbols precede global symbols,
      and the sh_info field in the symbol table is not always right.  */
-  elf_bad_symtab (abfd) = true;
+  if (SGI_COMPAT (abfd))
+    elf_bad_symtab (abfd) = true;
 
-  return _bfd_mips_elf_object_p (abfd);
+  bfd_default_set_arch_mach (abfd, bfd_arch_mips,
+			     elf_mips_mach (elf_elfheader (abfd)->e_flags));
+  return true;
 }
 
 /* The final processing done just before writing out a MIPS ELF object
@@ -2333,6 +2368,8 @@ _bfd_mips_elf_merge_private_bfd_data (ib
     {
       elf_flags_init (obfd) = true;
       elf_elfheader (obfd)->e_flags = new_flags;
+      elf_elfheader (obfd)->e_ident[EI_CLASS] 
+	= elf_elfheader (ibfd)->e_ident[EI_CLASS];
 
       if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
 	  && bfd_get_arch_info (obfd)->the_default)
@@ -2420,18 +2457,22 @@ _bfd_mips_elf_merge_private_bfd_data (ib
       old_flags &= ~ (EF_MIPS_ARCH | EF_MIPS_MACH);
     }
 
-  /* Compare ABI's */
-  if ((new_flags & EF_MIPS_ABI) != (old_flags & EF_MIPS_ABI))
+  /* Compare ABI's.  The 64-bit ABI does not use EF_MIPS_ABI.  But, it
+     does set EI_CLASS differently from any 32-bit ABI.  */
+  if ((new_flags & EF_MIPS_ABI) != (old_flags & EF_MIPS_ABI)
+      || (elf_elfheader (ibfd)->e_ident[EI_CLASS] 
+	  != elf_elfheader (obfd)->e_ident[EI_CLASS]))
     {
       /* Only error if both are set (to different values). */
-      if ((new_flags & EF_MIPS_ABI)
-	  && (old_flags & EF_MIPS_ABI))
+      if (((new_flags & EF_MIPS_ABI) && (old_flags & EF_MIPS_ABI))
+	  || (elf_elfheader (ibfd)->e_ident[EI_CLASS] 
+	      != elf_elfheader (obfd)->e_ident[EI_CLASS]))
 	{
 	  (*_bfd_error_handler)
 	    (_("%s: ABI mismatch: linking %s module with previous %s modules"),
 	     bfd_get_filename (ibfd),
-	     elf_mips_abi_name (new_flags),
-	     elf_mips_abi_name (old_flags));
+	     elf_mips_abi_name (ibfd),
+	     elf_mips_abi_name (obfd));
 	  ok = false;
 	}
       new_flags &= ~EF_MIPS_ABI;
@@ -2457,7 +2498,7 @@ _bfd_mips_elf_merge_private_bfd_data (ib
   return true;
 }
 
-static boolean
+boolean
 _bfd_mips_elf_print_private_bfd_data (abfd, ptr)
      bfd *abfd;
      PTR ptr;
@@ -2482,8 +2523,10 @@ _bfd_mips_elf_print_private_bfd_data (ab
     fprintf (file, _ (" [abi=EABI64]"));
   else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI))
     fprintf (file, _ (" [abi unknown]"));
-  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI2))
+  else if (ABI_N32_P (abfd))
     fprintf (file, _ (" [abi=N32]"));
+  else if (ABI_64_P (abfd))
+    fprintf (file, _ (" [abi=64]"));
   else
     fprintf (file, _ (" [no abi set]"));
 
@@ -2519,7 +2562,7 @@ boolean
 _bfd_mips_elf_section_from_shdr (abfd, hdr, name)
      bfd *abfd;
      Elf_Internal_Shdr *hdr;
-     const char *name;
+     char *name;
 {
   flagword flags = 0;
 
@@ -2603,20 +2646,6 @@ _bfd_mips_elf_section_from_shdr (abfd, h
 	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
@@ -2660,7 +2689,18 @@ mips_elf32_section_from_shdr (abfd, hdr,
 
 	  bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l,
 					&intopt);
-	  if (intopt.kind == ODK_REGINFO)
+	  if (ABI_64_P (abfd) && intopt.kind == ODK_REGINFO)
+	    {
+	      Elf64_Internal_RegInfo intreg;
+
+	      bfd_mips_elf64_swap_reginfo_in
+		(abfd,
+		 ((Elf64_External_RegInfo *)
+		  (l + sizeof (Elf_External_Options))),
+		 &intreg);
+	      elf_gp (abfd) = intreg.ri_gp_value;
+	    }
+	  else if (intopt.kind == ODK_REGINFO)
 	    {
 	      Elf32_RegInfo intreg;
 
@@ -2699,12 +2739,6 @@ _bfd_mips_elf_fake_sections (abfd, hdr, 
       hdr->sh_info = sec->_raw_size / sizeof (Elf32_Lib);
       /* The sh_link field is set in final_write_processing.  */
     }
-  else if (strcmp (name, MIPS_ELF_MSYM_SECTION_NAME (abfd)) == 0)
-    {
-      hdr->sh_type = SHT_MIPS_MSYM;
-      hdr->sh_entsize = 8;
-      /* FIXME: Set the sh_info field.  */
-    }
   else if (strcmp (name, ".conflict") == 0)
     hdr->sh_type = SHT_MIPS_CONFLICT;
   else if (strncmp (name, ".gptab.", sizeof ".gptab." - 1) == 0)
@@ -2894,57 +2929,6 @@ _bfd_mips_elf_section_processing (abfd, 
      bfd *abfd;
      Elf_Internal_Shdr *hdr;
 {
-  if (hdr->bfd_section != NULL)
-    {
-      const char *name = bfd_get_section_name (abfd, hdr->bfd_section);
-
-      if (strcmp (name, ".sdata") == 0
-	  || strcmp (name, ".lit8") == 0
-	  || strcmp (name, ".lit4") == 0)
-	{
-	  hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
-	  hdr->sh_type = SHT_PROGBITS;
-	}
-      else if (strcmp (name, ".sbss") == 0)
-	{
-	  hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
-	  hdr->sh_type = SHT_NOBITS;
-	}
-      else if (strcmp (name, MIPS_ELF_SRDATA_SECTION_NAME (abfd)) == 0)
-	{
-	  hdr->sh_flags |= SHF_ALLOC | SHF_MIPS_GPREL;
-	  hdr->sh_type = SHT_PROGBITS;
-	}
-      else if (strcmp (name, ".compact_rel") == 0)
-	{
-	  hdr->sh_flags = 0;
-	  hdr->sh_type = SHT_PROGBITS;
-	}
-      else if (strcmp (name, ".rtproc") == 0)
-	{
-	  if (hdr->sh_addralign != 0 && hdr->sh_entsize == 0)
-	    {
-	      unsigned int adjust;
-
-	      adjust = hdr->sh_size % hdr->sh_addralign;
-	      if (adjust != 0)
-		hdr->sh_size += hdr->sh_addralign - adjust;
-	    }
-	}
-    }
-
-  return true;
-}
-
-/* Work over a section just before writing it out.  We update the GP
-   value in the SHT_MIPS_REGINFO and SHT_MIPS_OPTIONS sections based
-   on the value we are using.  */
-
-static boolean
-mips_elf32_section_processing (abfd, hdr)
-     bfd *abfd;
-     Elf32_Internal_Shdr *hdr;
-{
   if (hdr->sh_type == SHT_MIPS_REGINFO
       && hdr->sh_size > 0)
     {
@@ -2985,7 +2969,22 @@ mips_elf32_section_processing (abfd, hdr
 
 	  bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l,
 					&intopt);
-	  if (intopt.kind == ODK_REGINFO)
+	  if (ABI_64_P (abfd) && intopt.kind == ODK_REGINFO)
+	    {
+	      bfd_byte buf[8];
+
+	      if (bfd_seek (abfd,
+			    (hdr->sh_offset
+			     + (l - contents)
+			     + sizeof (Elf_External_Options)
+			     + (sizeof (Elf64_External_RegInfo) - 8)),
+			     SEEK_SET) == -1)
+		return false;
+	      bfd_h_put_64 (abfd, elf_gp (abfd), buf);
+	      if (bfd_write (buf, 1, 8, abfd) != 8)
+		return false;
+	    }
+	  else if (intopt.kind == ODK_REGINFO)
 	    {
 	      bfd_byte buf[4];
 
@@ -3003,9 +3002,49 @@ mips_elf32_section_processing (abfd, hdr
 	  l += intopt.size;
 	}
     }
+
+  if (hdr->bfd_section != NULL)
+    {
+      const char *name = bfd_get_section_name (abfd, hdr->bfd_section);
+
+      if (strcmp (name, ".sdata") == 0
+	  || strcmp (name, ".lit8") == 0
+	  || strcmp (name, ".lit4") == 0)
+	{
+	  hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
+	  hdr->sh_type = SHT_PROGBITS;
+	}
+      else if (strcmp (name, ".sbss") == 0)
+	{
+	  hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
+	  hdr->sh_type = SHT_NOBITS;
+	}
+      else if (strcmp (name, MIPS_ELF_SRDATA_SECTION_NAME (abfd)) == 0)
+	{
+	  hdr->sh_flags |= SHF_ALLOC | SHF_MIPS_GPREL;
+	  hdr->sh_type = SHT_PROGBITS;
+	}
+      else if (strcmp (name, ".compact_rel") == 0)
+	{
+	  hdr->sh_flags = 0;
+	  hdr->sh_type = SHT_PROGBITS;
+	}
+      else if (strcmp (name, ".rtproc") == 0)
+	{
+	  if (hdr->sh_addralign != 0 && hdr->sh_entsize == 0)
+	    {
+	      unsigned int adjust;
+
+	      adjust = hdr->sh_size % hdr->sh_addralign;
+	      if (adjust != 0)
+		hdr->sh_size += hdr->sh_addralign - adjust;
+	    }
+	}
+    }
 
-  return _bfd_mips_elf_section_processing (abfd, hdr);
+  return true;
 }
+
 
 /* MIPS ELF uses two common sections.  One is the usual one, and the
    other is for small objects.  All the small objects are kept
@@ -3114,8 +3153,8 @@ _bfd_mips_elf_symbol_processing (abfd, a
 /* When creating an Irix 5 executable, we need REGINFO and RTPROC
    segments.  */
 
-static int
-mips_elf_additional_program_headers (abfd)
+int
+_bfd_mips_elf_additional_program_headers (abfd)
      bfd *abfd;
 {
   asection *s;
@@ -3146,8 +3185,8 @@ mips_elf_additional_program_headers (abf
 
 /* Modify the segment map for an Irix 5 executable.  */
 
-static boolean
-mips_elf_modify_segment_map (abfd)
+boolean
+_bfd_mips_elf_modify_segment_map (abfd)
      bfd *abfd;
 {
   asection *s;
@@ -3737,8 +3776,8 @@ mips_elf_link_hash_newfunc (entry, table
 
 /* Create a MIPS ELF linker hash table.  */
 
-static struct bfd_link_hash_table *
-mips_elf_link_hash_table_create (abfd)
+struct bfd_link_hash_table *
+_bfd_mips_elf_link_hash_table_create (abfd)
      bfd *abfd;
 {
   struct mips_elf_link_hash_table *ret;
@@ -3773,8 +3812,8 @@ mips_elf_link_hash_table_create (abfd)
    file.  We must handle the special MIPS section numbers here.  */
 
 /*ARGSUSED*/
-static boolean
-mips_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
+boolean
+_bfd_mips_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
      bfd *abfd;
      struct bfd_link_info *info;
      const Elf_Internal_Sym *sym;
@@ -4251,8 +4290,8 @@ gptab_compare (p1, p2)
    the .mdebug sections.  We need to merge all instances of these
    sections together, not write them all out sequentially.  */
 
-static boolean
-mips_elf_final_link (abfd, info)
+boolean
+_bfd_mips_elf_final_link (abfd, info)
      bfd *abfd;
      struct bfd_link_info *info;
 {
@@ -4854,8 +4893,10 @@ mips_elf_final_link (abfd, info)
     }
 
   /* Invoke the regular ELF backend linker to do all the work.  */
-  if (! bfd_elf32_bfd_final_link (abfd, info))
-    return false;
+  if (!(ABI_64_P (abfd) 
+	? bfd_elf64_bfd_final_link (abfd, info)
+	: bfd_elf32_bfd_final_link (abfd, info)))
+      return false;
 
   /* Now write out the computed sections.  */
 
@@ -5155,7 +5196,8 @@ mips_elf_global_got_index (abfd, h)
      indices into the GOT.  That makes it easy to calculate the GOT
      offset.  */
   BFD_ASSERT (h->dynindx >= g->global_gotsym->dynindx);
-  index = (h->dynindx - g->global_gotsym->dynindx + g->local_gotno) * 4;
+  index = ((h->dynindx - g->global_gotsym->dynindx + g->local_gotno) 
+	   * MIPS_ELF_GOT_SIZE (abfd));
   BFD_ASSERT (index < sgot->_raw_size);
 
   return index;
@@ -5174,7 +5216,7 @@ mips_elf_got_offset_from_index (dynobj, 
   bfd_vma gp;
   char *error_message;
 
-  sgot = bfd_get_section_by_name (dynobj, ".got");
+  sgot = mips_elf_got_section (dynobj);
   gp = _bfd_get_gp_value (output_bfd);
   return (sgot->output_section->vma + sgot->output_offset + index - 
 	  gp);
@@ -5305,8 +5347,10 @@ mips_elf_create_local_got_entry (abfd, g
       return (bfd_vma) -1;
     }
 
-  bfd_put_32 (abfd, value, sgot->contents + 4 * g->assigned_gotno);
-  return 4 * g->assigned_gotno++;
+  MIPS_ELF_PUT_WORD (abfd, value,
+		     (sgot->contents 
+		      + MIPS_ELF_GOT_SIZE (abfd) * g->assigned_gotno));
+  return MIPS_ELF_GOT_SIZE (abfd) * g->assigned_gotno++;
 }
 
 /* Returns the GOT offset at which the indicated address can be found.
@@ -5326,12 +5370,12 @@ mips_elf_local_got_index (abfd, info, va
   g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot);
 
   /* Look to see if we already have an appropriate entry.  */
-  for (entry = sgot->contents + 4 * MIPS_RESERVED_GOTNO; 
-       entry != sgot->contents + 4 * g->assigned_gotno;
-       entry += 4)
+  for (entry = (sgot->contents 
+		+ MIPS_ELF_GOT_SIZE (abfd) * MIPS_RESERVED_GOTNO); 
+       entry != sgot->contents + MIPS_ELF_GOT_SIZE (abfd) * g->assigned_gotno;
+       entry += MIPS_ELF_GOT_SIZE (abfd))
     {
-      bfd_vma address = bfd_get_32 (abfd, entry);
-
+      bfd_vma address = MIPS_ELF_GET_WORD (abfd, entry);
       if (address == value)
 	return entry - sgot->contents;
     }
@@ -5362,12 +5406,14 @@ mips_elf_got_page (abfd, info, value, of
   g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot);
 
   /* Look to see if we aleady have an appropriate entry.  */
-  last_entry = sgot->contents + 4 * g->assigned_gotno;
-  for (entry = sgot->contents + 4 * MIPS_RESERVED_GOTNO; 
+  last_entry = sgot->contents + MIPS_ELF_GOT_SIZE (abfd) * g->assigned_gotno;
+  for (entry = (sgot->contents 
+		+ MIPS_ELF_GOT_SIZE (abfd) * MIPS_RESERVED_GOTNO);
        entry != last_entry;
-       entry += 4)
+       entry += MIPS_ELF_GOT_SIZE (abfd))
     {
-      address = bfd_get_32 (abfd, entry);
+      address = MIPS_ELF_GET_WORD (abfd, entry);
+
       if (!mips_elf_overflow_p (value - address, 16))
 	{
 	  /* This entry will serve as the page pointer.  We can add a
@@ -5383,7 +5429,7 @@ mips_elf_got_page (abfd, info, value, of
 
   if (offsetp)
     {
-      address = bfd_get_32 (abfd, entry);
+      address = MIPS_ELF_GET_WORD (abfd, entry);
       *offsetp = value - address;
     }
 
@@ -5410,16 +5456,17 @@ mips_elf_got16_entry (abfd, info, value)
   g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot);
 
   /* Look to see if we already have an appropriate entry.  */
-  last_entry = sgot->contents + 4 * g->assigned_gotno;
-  for (entry = sgot->contents + 4 * MIPS_RESERVED_GOTNO; 
+  last_entry = sgot->contents + MIPS_ELF_GOT_SIZE (abfd) * g->assigned_gotno;
+  for (entry = (sgot->contents 
+		+ MIPS_ELF_GOT_SIZE (abfd) * MIPS_RESERVED_GOTNO);
        entry != last_entry;
-       entry += 4)
+       entry += MIPS_ELF_GOT_SIZE (abfd))
     {
-      address = bfd_get_32 (abfd, entry);
+      address = MIPS_ELF_GET_WORD (abfd, entry);
       if (address & 0xffff0000 == value)
 	{
 	  /* This entry has the right high-order 16 bits.  */
-	  index = 4 * (entry - sgot->contents);
+	  index = MIPS_ELF_GOT_SIZE (abfd) * (entry - sgot->contents);
 	  break;
 	}
     }
@@ -5437,8 +5484,8 @@ mips_elf_got16_entry (abfd, info, value)
 
 static boolean
 mips_elf_next_lo16_addend (relocation, relend, addendp)
-     Elf_Internal_Rela *relocation;
-     Elf_Internal_Rela *relend;
+     const Elf_Internal_Rela *relocation;
+     const Elf_Internal_Rela *relend;
      bfd_vma *addendp;
 {
   /* According to the MIPS ELF ABI, the R_MIPS_LO16 relocation must be
@@ -5472,7 +5519,7 @@ mips_elf_create_dynamic_relocation (outp
 				    addend, input_section)
      bfd *output_bfd;
      struct bfd_link_info *info;
-     Elf_Internal_Rela *rel;
+     const Elf_Internal_Rela *rel;
      long dynindx;
      bfd_vma addend;
      asection *input_section;
@@ -5485,7 +5532,9 @@ mips_elf_create_dynamic_relocation (outp
 
   r_type = ELF32_R_TYPE (rel->r_info);
   dynobj = elf_hash_table (info)->dynobj;
-  sreloc = bfd_get_section_by_name (dynobj, ".rel.dyn");
+  sreloc 
+    = bfd_get_section_by_name (dynobj,
+			       MIPS_ELF_REL_DYN_SECTION_NAME (output_bfd));
   BFD_ASSERT (sreloc != NULL);
 
   skip = false;
@@ -5520,10 +5569,18 @@ mips_elf_create_dynamic_relocation (outp
   if (skip)
     memset (&outrel, 0, sizeof (outrel));
 
-  bfd_elf32_swap_reloc_out (output_bfd, &outrel,
-			    (((Elf32_External_Rel *)
-			      sreloc->contents)
-			     + sreloc->reloc_count));
+  if (ABI_64_P (output_bfd))
+    {
+      (*get_elf_backend_data (output_bfd)->s->swap_reloc_out)
+	(output_bfd, &outrel,
+	 (sreloc->contents 
+	  + sreloc->reloc_count * sizeof (Elf64_Mips_External_Rel)));
+    }
+  else
+    bfd_elf32_swap_reloc_out (output_bfd, &outrel,
+			      (((Elf32_External_Rel *)
+				sreloc->contents)
+			       + sreloc->reloc_count));
   ++sreloc->reloc_count;
 
   /* Make sure the output section is writable.  The dynamic linker
@@ -5583,7 +5640,6 @@ mips_elf_calculate_relocation (abfd, 
 			       relocation,
 			       addend,
 			       howto,
-			       relend,
 			       local_syms,
 			       local_sections,
 			       valuep,
@@ -5592,10 +5648,9 @@ mips_elf_calculate_relocation (abfd, 
      bfd *input_bfd;
      asection *input_section;
      struct bfd_link_info *info;
-     Elf_Internal_Rela *relocation;
+     const Elf_Internal_Rela *relocation;
      bfd_vma addend;
      reloc_howto_type *howto;
-     Elf_Internal_Rela *relend;
      Elf_Internal_Sym *local_syms;
      asection **local_sections;
      bfd_vma *valuep;
@@ -5622,12 +5677,17 @@ mips_elf_calculate_relocation (abfd, 
      located.  */
   asection *sec = NULL;
   struct mips_elf_link_hash_entry* h = NULL;
-  unsigned long r_symndx;
+  /* True if the symbol referred to by this relocation is a local
+     symbol.  */
   boolean local_p;
+  /* True if the symbol referred to by this relocation is "_gp_disp".  */
   boolean gp_disp_p = false;
   Elf_Internal_Shdr *symtab_hdr;
   size_t extsymoff;
+  unsigned long r_symndx;
   int r_type;
+  /* True if overflow occurred during the calculation of the
+     relocation value.  */
   boolean overflowed_p;
 
   /* Parse the relocation.  */
@@ -5976,7 +6036,7 @@ mips_elf_calculate_relocation (abfd, 
 static bfd_vma
 mips_elf_obtain_contents (howto, relocation, input_bfd, contents)
      reloc_howto_type *howto;
-     Elf_Internal_Rela *relocation;
+     const Elf_Internal_Rela *relocation;
      bfd *input_bfd;
      bfd_byte *contents;
 {
@@ -6027,7 +6087,7 @@ mips_elf_obtain_contents (howto, relocat
 static void
 mips_elf_perform_relocation (howto, relocation, value, input_bfd, contents)
      reloc_howto_type *howto;
-     Elf_Internal_Rela *relocation;
+     const Elf_Internal_Rela *relocation;
      bfd_vma value;
      bfd *input_bfd;
      bfd_byte *contents;
@@ -6079,9 +6139,9 @@ mips_elf_perform_relocation (howto, relo
 
 /* Relocate a MIPS ELF section.  */
 
-static boolean
-mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
-			   contents, relocs, local_syms, local_sections)
+boolean
+_bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
+				contents, relocs, local_syms, local_sections)
      bfd *output_bfd;
      struct bfd_link_info *info;
      bfd *input_bfd;
@@ -6091,46 +6151,17 @@ mips_elf_relocate_section (output_bfd, i
      Elf_Internal_Sym *local_syms;
      asection **local_sections;
 {
-  Elf_Internal_Shdr *symtab_hdr;
-  size_t locsymcount;
-  size_t extsymoff;
-  asection *sgot, *sreloc, *scpt;
-  bfd *dynobj;
-  bfd_vma gp;
-  Elf_Internal_Rela *rel;
-  Elf_Internal_Rela *relend;
-  struct mips_got_info *g;
+  const Elf_Internal_Rela *rel;
+  const Elf_Internal_Rela *relend;
   bfd_vma addend;
   bfd_vma last_hi16_addend;
   boolean next_relocation_for_same_address_p = false;
   boolean use_saved_addend_p = false;
   boolean last_hi16_addend_valid_p = false;
+  struct elf_backend_data *bed;
 
-  dynobj = elf_hash_table (info)->dynobj;
-  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
-
-  sgot = NULL;
-  sreloc = NULL;
-  if (dynobj == NULL || ! SGI_COMPAT (output_bfd))
-    scpt = NULL;
-  else
-    scpt = bfd_get_section_by_name (dynobj, ".compact_rel");
-  g = NULL;
-
-  if (elf_bad_symtab (input_bfd))
-    {
-      locsymcount = symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
-      extsymoff = 0;
-    }
-  else
-    {
-      locsymcount = symtab_hdr->sh_info;
-      extsymoff = symtab_hdr->sh_info;
-    }
-
-  gp = _bfd_get_gp_value (output_bfd);
-  relend = relocs + input_section->reloc_count;
-  
+  bed = get_elf_backend_data (output_bfd);
+  relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel;
   for (rel = relocs; rel < relend; ++rel)
     {
       const char *name;
@@ -6152,9 +6183,11 @@ mips_elf_relocate_section (output_bfd, i
 	     this is, we depend on the fact that the INPUT_SECTION's
 	     REL_HDR is read before its REL_HDR2.  */
 	  rel_hdr = &elf_section_data (input_section)->rel_hdr;
-	  if (rel - relocs >= rel_hdr->sh_size / rel_hdr->sh_entsize)
+	  if (rel - relocs 
+	      >= (rel_hdr->sh_size / rel_hdr->sh_entsize
+		  * bed->s->int_rels_per_ext_rel))
 	    rel_hdr = elf_section_data (input_section)->rel_hdr2;
-	  if (rel_hdr->sh_entsize == sizeof (Elf32_External_Rel))
+	  if (rel_hdr->sh_entsize == MIPS_ELF_REL_SIZE (input_bfd))
 	    {
 	      int r_type = ELF32_R_TYPE (rel->r_info);
 
@@ -6202,7 +6235,9 @@ mips_elf_relocate_section (output_bfd, i
 	 relocations for the same offset.  In that case we are
 	 supposed to treat the output of each relocation as the addend
 	 for the next.  */
-      if (rel + 1 < relend && rel->r_offset == (rel + 1)->r_offset)
+      if (rel + 1 < relend 
+	  && rel->r_offset == rel[1].r_offset
+	  && ELF32_R_TYPE (rel[1].r_info) != R_MIPS_NONE)
 	use_saved_addend_p = true;
       else
 	use_saved_addend_p = false;
@@ -6215,7 +6250,6 @@ mips_elf_relocate_section (output_bfd, i
 					     rel,
 					     addend,
 					     howto,
-					     relend,
 					     local_syms,
 					     local_sections,
 					     &value,
@@ -6274,8 +6308,8 @@ mips_elf_relocate_section (output_bfd, i
    also where we undo the increment of the value for a mips16 symbol.  */
 
 /*ARGSIGNORED*/
-static boolean
-mips_elf_link_output_symbol_hook (abfd, info, name, sym, input_sec)
+boolean
+_bfd_mips_elf_link_output_symbol_hook (abfd, info, name, sym, input_sec)
      bfd *abfd;
      struct bfd_link_info *info;
      const char *name;
@@ -6301,13 +6335,15 @@ mips_elf_link_output_symbol_hook (abfd, 
 /* The name of the dynamic interpreter.  This is put in the .interp
    section.  */
 
-#define ELF_DYNAMIC_INTERPRETER(abfd) \
-   (ABI_N32_P (abfd) ? "/usr/lib32/libc.so.1" : "/usr/lib/libc.so.1")
+#define ELF_DYNAMIC_INTERPRETER(abfd) 		\
+   (ABI_N32_P (abfd) ? "/usr/lib32/libc.so.1" 	\
+    : ABI_64_P (abfd) ? "/usr/lib64/libc.so.1" 	\
+    : "/usr/lib/libc.so.1")
 
 /* Create dynamic sections when linking against a dynamic object.  */
 
-static boolean
-mips_elf_create_dynamic_sections (abfd, info)
+boolean
+_bfd_mips_elf_create_dynamic_sections (abfd, info)
      bfd *abfd;
      struct bfd_link_info *info;
 {
@@ -6345,7 +6381,8 @@ mips_elf_create_dynamic_sections (abfd, 
       s = bfd_make_section (abfd, MIPS_ELF_STUB_SECTION_NAME (abfd));
       if (s == NULL
 	  || ! bfd_set_section_flags (abfd, s, flags | SEC_CODE)
-	  || ! bfd_set_section_alignment (abfd, s, 2))
+	  || ! bfd_set_section_alignment (abfd, s,
+					  MIPS_ELF_LOG_FILE_ALIGN (abfd)))
 	return false;
     }
 
@@ -6356,7 +6393,8 @@ mips_elf_create_dynamic_sections (abfd, 
       s = bfd_make_section (abfd, ".rld_map");
       if (s == NULL
 	  || ! bfd_set_section_flags (abfd, s, flags & ~SEC_READONLY)
-	  || ! bfd_set_section_alignment (abfd, s, 2))
+	  || ! bfd_set_section_alignment (abfd, s,
+					  MIPS_ELF_LOG_FILE_ALIGN (abfd)))
 	return false;
     }
 
@@ -6467,7 +6505,8 @@ mips_elf_create_compact_rel_section (abf
       s = bfd_make_section (abfd, ".compact_rel");
       if (s == NULL
 	  || ! bfd_set_section_flags (abfd, s, flags)
-	  || ! bfd_set_section_alignment (abfd, s, 2))
+	  || ! bfd_set_section_alignment (abfd, s,
+					  MIPS_ELF_LOG_FILE_ALIGN (abfd)))
 	return false;
 
       s->_raw_size = sizeof (Elf32_External_compact_rel);
@@ -6489,7 +6528,7 @@ mips_elf_create_got_section (abfd, info)
   struct mips_got_info *g;
 
   /* This function may be called more than once.  */
-  if (bfd_get_section_by_name (abfd, ".got") != NULL)
+  if (mips_elf_got_section (abfd))
     return true;
 
   flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
@@ -6520,7 +6559,7 @@ mips_elf_create_got_section (abfd, info)
     return false;
 
   /* The first several global offset table entries are reserved.  */
-  s->_raw_size = MIPS_RESERVED_GOTNO * 4;
+  s->_raw_size = MIPS_RESERVED_GOTNO * MIPS_ELF_GOT_SIZE (abfd);
 
   g = (struct mips_got_info *) bfd_alloc (abfd,
 					  sizeof (struct mips_got_info));
@@ -6563,18 +6602,40 @@ mips_elf_create_msym_section (abfd)
 				     | SEC_HAS_CONTENTS
 				     | SEC_LINKER_CREATED 
 				     | SEC_READONLY)
-	  || !bfd_set_section_alignment (abfd, s, 2))
+	  || !bfd_set_section_alignment (abfd, s,
+					 MIPS_ELF_LOG_FILE_ALIGN (abfd)))
 	return NULL;
     }
 
   return s;
 }
 
+/* Add room for N relocations to the .rel.dyn section in ABFD.  */
+
+static void
+mips_elf_allocate_dynamic_relocations (abfd, n)
+     bfd *abfd;
+     unsigned int n;
+{
+  asection *s;
+
+  s = bfd_get_section_by_name (abfd, MIPS_ELF_REL_DYN_SECTION_NAME (abfd));
+  BFD_ASSERT (s != NULL);
+  
+  if (s->_raw_size == 0)
+    {
+      /* Make room for a null element. */
+      s->_raw_size += MIPS_ELF_REL_SIZE (abfd);
+      ++s->reloc_count;
+    }
+  s->_raw_size += n * MIPS_ELF_REL_SIZE (abfd);
+}
+
 /* Look through the relocs for a section during the first phase, and
    allocate space in the global offset table.  */
 
-static boolean
-mips_elf_check_relocs (abfd, info, sec, relocs)
+boolean
+_bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
      bfd *abfd;
      struct bfd_link_info *info;
      asection *sec;
@@ -6590,6 +6651,7 @@ mips_elf_check_relocs (abfd, info, sec, 
   const Elf_Internal_Rela *rel_end;
   asection *sgot;
   asection *sreloc;
+  struct elf_backend_data *bed;
 
   if (info->relocateable)
     return true;
@@ -6674,7 +6736,7 @@ mips_elf_check_relocs (abfd, info, sec, 
 	      asection **n;
 
 	      if (elf_bad_symtab (abfd))
-		symcount = symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
+		symcount = symtab_hdr->sh_size / symtab_hdr->sh_entsize;
 	      else
 		symcount = symtab_hdr->sh_info;
 	      n = (asection **) bfd_zalloc (abfd,
@@ -6764,7 +6826,7 @@ mips_elf_check_relocs (abfd, info, sec, 
     }
   else
     {
-      sgot = bfd_get_section_by_name (dynobj, ".got");
+      sgot = mips_elf_got_section (dynobj);
       if (sgot == NULL)
 	g = NULL;
       else
@@ -6776,9 +6838,9 @@ mips_elf_check_relocs (abfd, info, sec, 
     }
 
   sreloc = NULL;
-
-  rel_end = relocs + sec->reloc_count;
-  for (rel = relocs; rel < rel_end; rel++)
+  bed = get_elf_backend_data (abfd);
+  rel_end = relocs + sec->reloc_count * bed->s->int_rels_per_ext_rel;
+  for (rel = relocs; rel < rel_end; ++rel)
     {
       unsigned long r_symndx;
       int r_type;
@@ -6894,7 +6956,7 @@ mips_elf_check_relocs (abfd, info, sec, 
 	    {
 	      if (sreloc == NULL)
 		{
-		  const char *name = ".rel.dyn";
+		  const char *name = MIPS_ELF_REL_DYN_SECTION_NAME (dynobj);
 
 		  sreloc = bfd_get_section_by_name (dynobj, name);
 		  if (sreloc == NULL)
@@ -6914,19 +6976,11 @@ mips_elf_check_relocs (abfd, info, sec, 
 		    }
 		}
 	      if (info->shared)
-		{
-		  /* When creating a shared object, we must copy these
-		     reloc types into the output file as R_MIPS_REL32
-		     relocs.  We make room for this reloc in the
-		     .rel.dyn reloc section */
-		  if (sreloc->_raw_size == 0)
-		    {
-		      /* Add a null element. */
-		      sreloc->_raw_size += sizeof (Elf32_External_Rel);
-		      ++sreloc->reloc_count;
-		    }
-		  sreloc->_raw_size += sizeof (Elf32_External_Rel);
-		}
+		/* When creating a shared object, we must copy these
+		   reloc types into the output file as R_MIPS_REL32
+		   relocs.  We make room for this reloc in the
+		   .rel.dyn reloc section.  */
+		mips_elf_allocate_dynamic_relocations (dynobj, 1);
 	      else
 		{
 		  struct mips_elf_link_hash_entry *hmips;
@@ -6945,17 +6999,16 @@ mips_elf_check_relocs (abfd, info, sec, 
 		return false;
 	    }
 
-	  if (SGI_COMPAT (abfd))
+	  if (SGI_COMPAT (dynobj))
 	    mips_elf_hash_table (info)->compact_rel_size +=
 	      sizeof (Elf32_External_crinfo);
-
 	  break;
 
 	case R_MIPS_26:
 	case R_MIPS_GPREL16:
 	case R_MIPS_LITERAL:
 	case R_MIPS_GPREL32:
-	  if (SGI_COMPAT (abfd))
+	  if (SGI_COMPAT (dynobj))
 	    mips_elf_hash_table (info)->compact_rel_size +=
 	      sizeof (Elf32_External_crinfo);
 	  break;
@@ -7003,8 +7056,8 @@ mips_elf_check_relocs (abfd, info, sec, 
 /* Return the section that should be marked against GC for a given
    relocation.  */
 
-static asection *
-mips_elf_gc_mark_hook (abfd, info, rel, h, sym)
+asection *
+_bfd_mips_elf_gc_mark_hook (abfd, info, rel, h, sym)
      bfd *abfd;
      struct bfd_link_info *info;
      Elf_Internal_Rela *rel;
@@ -7052,8 +7105,8 @@ mips_elf_gc_mark_hook (abfd, info, rel, 
 
 /* Update the got entry reference counts for the section being removed.  */
 
-static boolean
-mips_elf_gc_sweep_hook (abfd, info, sec, relocs)
+boolean
+_bfd_mips_elf_gc_sweep_hook (abfd, info, sec, relocs)
      bfd *abfd;
      struct bfd_link_info *info;
      asection *sec;
@@ -7101,8 +7154,8 @@ mips_elf_gc_sweep_hook (abfd, info, sec,
    change the definition to something the rest of the link can
    understand.  */
 
-static boolean
-mips_elf_adjust_dynamic_symbol (info, h)
+boolean
+_bfd_mips_elf_adjust_dynamic_symbol (info, h)
      struct bfd_link_info *info;
      struct elf_link_hash_entry *h;
 {
@@ -7130,19 +7183,8 @@ mips_elf_adjust_dynamic_symbol (info, h)
   if (! info->relocateable
       && hmips->mips_32_relocs != 0
       && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
-    {
-      s = bfd_get_section_by_name (dynobj, ".rel.dyn");
-      BFD_ASSERT (s != NULL);
+    mips_elf_allocate_dynamic_relocations (dynobj, hmips->mips_32_relocs);
 
-      if (s->_raw_size == 0)
-	{
-	  /* Make room for a null element. */
-	  s->_raw_size += sizeof (Elf32_External_Rel);
-	  ++s->reloc_count;
-	}
-      s->_raw_size += hmips->mips_32_relocs * sizeof (Elf32_External_Rel);
-    }
-
   /* For a function, create a stub, if needed. */
   if (h->type == STT_FUNC
       || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
@@ -7201,8 +7243,8 @@ mips_elf_adjust_dynamic_symbol (info, h)
 static boolean mips_elf_check_mips16_stubs
   PARAMS ((struct mips_elf_link_hash_entry *, PTR));
 
-static boolean
-mips_elf_always_size_sections (output_bfd, info)
+boolean
+_bfd_mips_elf_always_size_sections (output_bfd, info)
      bfd *output_bfd;
      struct bfd_link_info *info;
 {
@@ -7277,8 +7319,8 @@ mips_elf_check_mips16_stubs (h, data)
 
 /* Set the sizes of the dynamic sections.  */
 
-static boolean
-mips_elf_size_dynamic_sections (output_bfd, info)
+boolean
+_bfd_mips_elf_size_dynamic_sections (output_bfd, info)
      bfd *output_bfd;
      struct bfd_link_info *info;
 {
@@ -7354,12 +7396,14 @@ mips_elf_size_dynamic_sections (output_b
 	      if ((target != NULL
 		   && (target->flags & SEC_READONLY) != 0
 		   && (target->flags & SEC_ALLOC) != 0)
-		  || strcmp (outname, ".rel.dyn") == 0)
+		  || strcmp (outname, 
+			     MIPS_ELF_REL_DYN_SECTION_NAME (output_bfd)) == 0)
 		reltext = true;
 
 	      /* We use the reloc_count field as a counter if we need
 		 to copy relocs into the output file.  */
-	      if (strcmp (name, ".rel.dyn") != 0)
+	      if (strcmp (name, 
+			  MIPS_ELF_REL_DYN_SECTION_NAME (output_bfd)) != 0)
 		s->reloc_count = 0;
 	    }
 	}
@@ -7396,7 +7440,7 @@ mips_elf_size_dynamic_sections (output_b
  	     contiguous sections.  Is 5 enough? */
  	  local_gotno = (loadable_size >> 16) + 5;
  	  g->local_gotno += local_gotno;
- 	  s->_raw_size += local_gotno * 4;
+ 	  s->_raw_size += local_gotno * MIPS_ELF_GOT_SIZE (dynobj);
 
  	  /* There has to be a global GOT entry for every symbol with
  	     a dynamic symbol table index of DT_MIPS_GOTSYM or
@@ -7407,7 +7451,7 @@ mips_elf_size_dynamic_sections (output_b
  	    return false;
 
  	  i = elf_hash_table (info)->dynsymcount - g->global_gotsym->dynindx;
-	  s->_raw_size += i * 4;
+	  s->_raw_size += i * MIPS_ELF_GOT_SIZE (dynobj);
 	}
       else if (strcmp (name, MIPS_ELF_STUB_SECTION_NAME (output_bfd)) == 0)
 	{
@@ -7465,103 +7509,104 @@ mips_elf_size_dynamic_sections (output_b
 	    {
 	      /* SGI object has the equivalence of DT_DEBUG in the
 		 DT_MIPS_RLD_MAP entry.  */
-	      if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_RLD_MAP, 0))
+	      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_RLD_MAP, 0))
 		return false;
 	    }
 	  else
-	    if (! bfd_elf32_add_dynamic_entry (info, DT_DEBUG, 0))
+	    if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_DEBUG, 0))
 	      return false;
 	}
 
       if (reltext)
 	{
-	  if (! bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))
+	  if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_TEXTREL, 0))
 	    return false;
 	}
 
-      if (! bfd_elf32_add_dynamic_entry (info, DT_PLTGOT, 0))
+      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTGOT, 0))
 	return false;
 
-      if (bfd_get_section_by_name (dynobj, ".rel.dyn"))
+      if (bfd_get_section_by_name (dynobj,
+				   MIPS_ELF_REL_DYN_SECTION_NAME (dynobj)))
 	{
-	  if (! bfd_elf32_add_dynamic_entry (info, DT_REL, 0))
+	  if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_REL, 0))
 	    return false;
 
-	  if (! bfd_elf32_add_dynamic_entry (info, DT_RELSZ, 0))
+	  if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELSZ, 0))
 	    return false;
 
-	  if (! bfd_elf32_add_dynamic_entry (info, DT_RELENT, 0))
+	  if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELENT, 0))
 	    return false;
 	}
 
-      if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_CONFLICTNO, 0))
+      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_CONFLICTNO, 0))
 	return false;
 
-      if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_LIBLISTNO, 0))
+      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_LIBLISTNO, 0))
 	return false;
 
       if (bfd_get_section_by_name (dynobj, ".conflict") != NULL)
 	{
-	  if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_CONFLICT, 0))
+	  if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_CONFLICT, 0))
 	    return false;
 
 	  s = bfd_get_section_by_name (dynobj, ".liblist");
 	  BFD_ASSERT (s != NULL);
 
-	  if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_LIBLIST, 0))
+	  if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_LIBLIST, 0))
 	    return false;
 	}
 
-      if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_RLD_VERSION, 0))
+      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_RLD_VERSION, 0))
 	return false;
 
-      if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_FLAGS, 0))
+      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_FLAGS, 0))
 	return false;
 
 #if 0
       /* Time stamps in executable files are a bad idea.  */
-      if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_TIME_STAMP, 0))
+      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_TIME_STAMP, 0))
 	return false;
 #endif
 
 #if 0 /* FIXME  */
-      if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_ICHECKSUM, 0))
+      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_ICHECKSUM, 0))
 	return false;
 #endif
 
 #if 0 /* FIXME  */
-      if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_IVERSION, 0))
+      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_IVERSION, 0))
 	return false;
 #endif
 
-      if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_BASE_ADDRESS, 0))
+      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_BASE_ADDRESS, 0))
 	return false;
 
-      if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_LOCAL_GOTNO, 0))
+      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_LOCAL_GOTNO, 0))
 	return false;
 
-      if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_SYMTABNO, 0))
+      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_SYMTABNO, 0))
 	return false;
 
-      if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_UNREFEXTNO, 0))
+      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_UNREFEXTNO, 0))
 	return false;
 
-      if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_GOTSYM, 0))
+      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_GOTSYM, 0))
 	return false;
 
       if (IRIX_COMPAT (dynobj) == ict_irix5
-	  && ! bfd_elf32_add_dynamic_entry (info, DT_MIPS_HIPAGENO, 0))
+	  && ! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_HIPAGENO, 0))
 	return false;
 
       if (IRIX_COMPAT (dynobj) == ict_irix6
 	  && (bfd_get_section_by_name 
 	      (dynobj, MIPS_ELF_OPTIONS_SECTION_NAME (dynobj)))
-	  && !bfd_elf32_add_dynamic_entry (info, DT_MIPS_OPTIONS, 0))
+	  && !MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_OPTIONS, 0))
 	return false;
 
       if (bfd_get_section_by_name (dynobj, 
 				   MIPS_ELF_MSYM_SECTION_NAME (dynobj))
-	  && !bfd_elf32_add_dynamic_entry (info, DT_MIPS_MSYM, 0))
+	  && !MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_MSYM, 0))
 	return false;
     }
 
@@ -7577,55 +7622,17 @@ mips_elf_size_dynamic_sections (output_b
     c = 0;
     if (elf_hash_table (info)->dynamic_sections_created)
       {
-#if 0
-	/* We no longer try to restrict the set of sections which get
-           dynamic symbol table entries, since it fails if we have
-           other random sections which need dynamic relocations.  */
-	const char * const *namep;
-	bfd_size_type strindex;
-	struct bfd_strtab_hash *dynstr;
-
-	if (SGI_COMPAT (output_bfd))
-	  {
-	    c = SIZEOF_MIPS_DYNSYM_SECNAMES - 1;
-	    elf_link_hash_traverse (elf_hash_table (info),
-				    mips_elf_adjust_dynindx,
-				    (PTR) &c);
-	    elf_hash_table (info)->dynsymcount += c;
-
-	    dynstr = elf_hash_table (info)->dynstr;
-	    BFD_ASSERT (dynstr != NULL);
-
-	    for (i = 1, namep = mips_elf_dynsym_sec_names;
-		 *namep != NULL;
-		 i++, namep++)
-	      {
-		s = bfd_get_section_by_name (output_bfd, *namep);
-		if (s != NULL)
-		  elf_section_data (s)->dynindx = i;
-
-		strindex = _bfd_stringtab_add (dynstr, *namep, true, false);
-		if (strindex == (bfd_size_type) -1)
-		  return false;
+	c = bfd_count_sections (output_bfd);
+	elf_link_hash_traverse (elf_hash_table (info),
+				_bfd_elf_link_adjust_dynindx,
+				(PTR) &c);
+	elf_hash_table (info)->dynsymcount += c;
 
-		mips_elf_hash_table (info)->dynsym_sec_strindex[i] = strindex;
-	      }
-	  }
-	else
-#endif /* 0 */
+	for (i = 1, s = output_bfd->sections; s != NULL; s = s->next, i++)
 	  {
-	    c = bfd_count_sections (output_bfd);
-	    elf_link_hash_traverse (elf_hash_table (info),
-				    _bfd_elf_link_adjust_dynindx,
-				    (PTR) &c);
-	    elf_hash_table (info)->dynsymcount += c;
-
-	    for (i = 1, s = output_bfd->sections; s != NULL; s = s->next, i++)
-	      {
-		elf_section_data (s)->dynindx = i;
-		/* These symbols will have no names, so we don't need to
-		   fiddle with dynstr_index.  */
-	      }
+	    elf_section_data (s)->dynindx = i;
+	    /* These symbols will have no names, so we don't need to
+	       fiddle with dynstr_index.  */
 	  }
       }
   }
@@ -7687,8 +7694,8 @@ mips_elf_irix6_finish_dynamic_symbol (ab
 /* Finish up dynamic symbol handling.  We set the contents of various
    dynamic sections here.  */
 
-static boolean
-mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
+boolean
+_bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
      bfd *output_bfd;
      struct bfd_link_info *info;
      struct elf_link_hash_entry *h;
@@ -7751,7 +7758,7 @@ mips_elf_finish_dynamic_symbol (output_b
 
   BFD_ASSERT (h->dynindx != -1);
 
-  sgot = bfd_get_section_by_name (dynobj, ".got");
+  sgot = mips_elf_got_section (dynobj);
   BFD_ASSERT (sgot != NULL);
   BFD_ASSERT (elf_section_data (sgot) != NULL);
   g = (struct mips_got_info *) elf_section_data (sgot)->tdata;
@@ -7775,7 +7782,7 @@ mips_elf_finish_dynamic_symbol (output_b
 	value = h->root.u.def.value;
 
       offset = mips_elf_global_got_index (dynobj, h);
-      bfd_put_32 (output_bfd, value, sgot->contents + offset);
+      MIPS_ELF_PUT_WORD (output_bfd, value, sgot->contents + offset);
     }
 
   /* Create a .msym entry, if appropriate.  */
@@ -7875,8 +7882,8 @@ mips_elf_finish_dynamic_symbol (output_b
 
 /* Finish up the dynamic sections.  */
 
-static boolean
-mips_elf_finish_dynamic_sections (output_bfd, info)
+boolean
+_bfd_mips_elf_finish_dynamic_sections (output_bfd, info)
      bfd *output_bfd;
      struct bfd_link_info *info;
 {
@@ -7889,7 +7896,7 @@ mips_elf_finish_dynamic_sections (output
 
   sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
 
-  sgot = bfd_get_section_by_name (dynobj, ".got");
+  sgot = mips_elf_got_section (dynobj);
   if (sgot == NULL)
     g = NULL;
   else
@@ -7901,39 +7908,41 @@ mips_elf_finish_dynamic_sections (output
 
   if (elf_hash_table (info)->dynamic_sections_created)
     {
-      Elf32_External_Dyn *dyncon, *dynconend;
+      bfd_byte *b;
 
       BFD_ASSERT (sdyn != NULL);
       BFD_ASSERT (g != NULL);
 
-      dyncon = (Elf32_External_Dyn *) sdyn->contents;
-      dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
-      for (; dyncon < dynconend; dyncon++)
+      for (b = sdyn->contents;
+	   b < sdyn->contents + sdyn->_raw_size;
+	   b += MIPS_ELF_DYN_SIZE (dynobj))
 	{
 	  Elf_Internal_Dyn dyn;
 	  const char *name;
 	  size_t elemsize;
 	  asection *s;
+	  boolean swap_out_p;
 
-	  bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
+	  /* Read in the current dynamic entry.  */
+	  (*get_elf_backend_data (dynobj)->s->swap_dyn_in) (dynobj, b, &dyn);
+	  
+	  /* Assume that we're going to modify it and write it out.  */
+	  swap_out_p = true;
 
 	  switch (dyn.d_tag)
 	    {
-	    default:
-	      break;
-
 	    case DT_RELENT:
-	      s = bfd_get_section_by_name (dynobj, ".rel.dyn");
+	      s = (bfd_get_section_by_name 
+		   (dynobj,
+		    MIPS_ELF_REL_DYN_SECTION_NAME (dynobj)));
 	      BFD_ASSERT (s != NULL);
-	      dyn.d_un.d_val = sizeof (Elf32_External_Rel);
-	      bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+	      dyn.d_un.d_val = MIPS_ELF_REL_SIZE (dynobj);
 	      break;
 
 	    case DT_STRSZ:
 	      /* Rewrite DT_STRSZ.  */
 	      dyn.d_un.d_val =
 		_bfd_stringtab_size (elf_hash_table (info)->dynstr);
-	      bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
 	      break;
 
 	    case DT_PLTGOT:
@@ -7948,17 +7957,14 @@ mips_elf_finish_dynamic_sections (output
 	      s = bfd_get_section_by_name (output_bfd, name);
 	      BFD_ASSERT (s != NULL);
 	      dyn.d_un.d_ptr = s->vma;
-	      bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
 	      break;
 
 	    case DT_MIPS_RLD_VERSION:
 	      dyn.d_un.d_val = 1; /* XXX */
-	      bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
 	      break;
 
 	    case DT_MIPS_FLAGS:
 	      dyn.d_un.d_val = RHF_NOTPOT; /* XXX */
-	      bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
 	      break;
 
 	    case DT_MIPS_CONFLICTNO:
@@ -7980,38 +7986,35 @@ mips_elf_finish_dynamic_sections (output
 		}
 	      else
 		    dyn.d_un.d_val = 0;
-
-	      bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
 	      break;
 
 	    case DT_MIPS_TIME_STAMP:
 	      time ((time_t *) &dyn.d_un.d_val);
-	      bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
 	      break;
 
 	    case DT_MIPS_ICHECKSUM:
 	      /* XXX FIXME: */
+	      swap_out_p = false;
 	      break;
 
 	    case DT_MIPS_IVERSION:
 	      /* XXX FIXME: */
+	      swap_out_p = false;
 	      break;
 
 	    case DT_MIPS_BASE_ADDRESS:
 	      s = output_bfd->sections;
 	      BFD_ASSERT (s != NULL);
 	      dyn.d_un.d_ptr = s->vma & ~(0xffff);
-	      bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
 	      break;
 
 	    case DT_MIPS_LOCAL_GOTNO:
 	      dyn.d_un.d_val = g->local_gotno;
-	      bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
 	      break;
 
 	    case DT_MIPS_SYMTABNO:
 	      name = ".dynsym";
-	      elemsize = sizeof (Elf32_External_Sym);
+	      elemsize = MIPS_ELF_SYM_SIZE (output_bfd);
 	      s = bfd_get_section_by_name (output_bfd, name);
 	      BFD_ASSERT (s != NULL);
 
@@ -8019,7 +8022,6 @@ mips_elf_finish_dynamic_sections (output
 		dyn.d_un.d_val = s->_cooked_size / elemsize;
 	      else
 		dyn.d_un.d_val = s->_raw_size / elemsize;
-	      bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
 	      break;
 
 	    case DT_MIPS_UNREFEXTNO:
@@ -8027,38 +8029,40 @@ mips_elf_finish_dynamic_sections (output
 		 entry of the first external symbol that is not
 		 referenced within the same object.  */
 	      dyn.d_un.d_val = bfd_count_sections (output_bfd) + 1;
-	      bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
 	      break;
 
 	    case DT_MIPS_GOTSYM:
 	      dyn.d_un.d_val = g->global_gotsym->dynindx;
-	      bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
 	      break;
 
 	    case DT_MIPS_HIPAGENO:
 	      dyn.d_un.d_val = g->local_gotno - MIPS_RESERVED_GOTNO;
-	      bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
 	      break;
 
 	    case DT_MIPS_RLD_MAP:
 	      dyn.d_un.d_ptr = mips_elf_hash_table (info)->rld_value;
-	      bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
 	      break;
 
 	    case DT_MIPS_OPTIONS:
 	      s = (bfd_get_section_by_name 
 		   (output_bfd, MIPS_ELF_OPTIONS_SECTION_NAME (output_bfd)));
 	      dyn.d_un.d_ptr = s->vma;
-	      bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
 	      break;
 
 	    case DT_MIPS_MSYM:
 	      s = (bfd_get_section_by_name 
 		   (output_bfd, MIPS_ELF_MSYM_SECTION_NAME (output_bfd)));
 	      dyn.d_un.d_ptr = s->vma;
-	      bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
 	      break;
+
+	    default:
+	      swap_out_p = false;
+	      break;
 	    }
+
+	  if (swap_out_p)
+	    (*get_elf_backend_data (dynobj)->s->swap_dyn_out) 
+	      (dynobj, &dyn, b);
 	}
     }
 
@@ -8067,12 +8071,14 @@ mips_elf_finish_dynamic_sections (output
      This isn't the case of Irix rld. */
   if (sgot != NULL && sgot->_raw_size > 0)
     {
-      bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
-      bfd_put_32 (output_bfd, (bfd_vma) 0x80000000, sgot->contents + 4);
+      MIPS_ELF_PUT_WORD (output_bfd, (bfd_vma) 0, sgot->contents);
+      MIPS_ELF_PUT_WORD (output_bfd, (bfd_vma) 0x80000000, 
+			 sgot->contents + MIPS_ELF_GOT_SIZE (output_bfd));
     }
 
   if (sgot != NULL)
-    elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
+    elf_section_data (sgot->output_section)->this_hdr.sh_entsize
+      = MIPS_ELF_GOT_SIZE (output_bfd);
 
   {
     asection *sdynsym;
@@ -8089,102 +8095,45 @@ mips_elf_finish_dynamic_sections (output
 				     MIPS_ELF_MSYM_SECTION_NAME (dynobj));
     if (sdynsym != NULL)
       {
-#if 0
-	const char *name;
-	const char * const * namep = mips_elf_dynsym_sec_names;
-	unsigned int i;
-	bfd_vma last;
-	long dindx;
-
-	/* We no longer try to restrict the set of sections which get
-           dynamic symbol table entries, since it fails if we have
-           other random sections which need dynamic relocations.  */
-	if (SGI_COMPAT (output_bfd))
-	  {
-	    sym.st_size = 0;
-	    sym.st_name = 0;
-	    sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_NOTYPE);
-	    sym.st_other = 0;
-
-	    i = 0;
-	    last = 0;
-	    dindx = 0;
-	    while ((name = *namep++) != NULL)
-	      {
-		s = bfd_get_section_by_name (output_bfd, name);
-		if (s != NULL)
-		  {
-		    sym.st_value = s->vma;
-		    dindx = elf_section_data (s)->dynindx;
-		    last = s->vma + s->_raw_size;
-		  }
-		else
-		  {
-		    sym.st_value = last;
-		    dindx++;
-		  }
-
-		sym.st_shndx = (i < MIPS_TEXT_DYNSYM_SECNO
-				? SHN_MIPS_TEXT
-				: SHN_MIPS_DATA);
-		++i;
-		sym.st_name =
-		  mips_elf_hash_table (info)->dynsym_sec_strindex[dindx];
-
-		bfd_elf32_swap_symbol_out (output_bfd, &sym,
-					   (((Elf32_External_Sym *)
-					     sdynsym->contents)
-					    + dindx));
-	      }
-
-	    /* Set the sh_info field of the output .dynsym section to
-	       the index of the first global symbol.  */
-	    elf_section_data (sdynsym->output_section)->this_hdr.sh_info =
-	      SIZEOF_MIPS_DYNSYM_SECNAMES;
-	  }
-	else
-#endif /* 0 */
-	  {
-	    Elf32_Internal_Msym msym;
+	Elf32_Internal_Msym msym;
 
-	    sym.st_size = 0;
-	    sym.st_name = 0;
-	    sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
-	    sym.st_other = 0;
+	sym.st_size = 0;
+	sym.st_name = 0;
+	sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
+	sym.st_other = 0;
 
-	    msym.ms_hash_value = 0;
-	    msym.ms_info = ELF32_MS_INFO (0, 1);
+	msym.ms_hash_value = 0;
+	msym.ms_info = ELF32_MS_INFO (0, 1);
 
-	    for (s = output_bfd->sections; s != NULL; s = s->next)
-	      {
-		int indx;
-		long dynindx;
+	for (s = output_bfd->sections; s != NULL; s = s->next)
+	  {
+	    int indx;
+	    long dynindx;
 
-		sym.st_value = s->vma;
+	    sym.st_value = s->vma;
 
-		indx = elf_section_data (s)->this_idx;
-		BFD_ASSERT (indx > 0);
-		sym.st_shndx = indx;
+	    indx = elf_section_data (s)->this_idx;
+	    BFD_ASSERT (indx > 0);
+	    sym.st_shndx = indx;
 		
-		dynindx  = elf_section_data (s)->dynindx;
+	    dynindx  = elf_section_data (s)->dynindx;
 
-		bfd_elf32_swap_symbol_out 
-		  (output_bfd, &sym,
-		   (((Elf32_External_Sym *) sdynsym->contents)
-		    + dynindx));
+	    (*get_elf_backend_data (output_bfd)->s->swap_symbol_out)
+	      (output_bfd, &sym, 
+	       sdynsym->contents 
+	       + (dynindx * MIPS_ELF_SYM_SIZE (output_bfd)));
 		
-		if (smsym)
-		  bfd_mips_elf_swap_msym_out 
-		    (output_bfd, &msym,
-		     (((Elf32_External_Msym *) smsym->contents)
-		      + dynindx));
-	      }
+	    if (smsym)
+	      bfd_mips_elf_swap_msym_out 
+		(output_bfd, &msym,
+		 (((Elf32_External_Msym *) smsym->contents)
+		  + dynindx));
+	  }
 
-	    /* Set the sh_info field of the output .dynsym section to
+	/* Set the sh_info field of the output .dynsym section to
 	       the index of the first global symbol.  */
-	    elf_section_data (sdynsym->output_section)->this_hdr.sh_info =
-	      bfd_count_sections (output_bfd) + 1;
-	  }
+	elf_section_data (sdynsym->output_section)->this_hdr.sh_info =
+	  bfd_count_sections (output_bfd) + 1;
       }
 
     if (SGI_COMPAT (output_bfd))
@@ -8220,9 +8169,10 @@ mips_elf_finish_dynamic_sections (output
       }
 
     /* Clean up a first relocation in .rel.dyn.  */
-    s = bfd_get_section_by_name (dynobj, ".rel.dyn");
+    s = bfd_get_section_by_name (dynobj, 
+				 MIPS_ELF_REL_DYN_SECTION_NAME (dynobj));
     if (s != NULL && s->_raw_size > 0)
-      memset (s->contents, 0, sizeof (Elf32_External_Rel));
+      memset (s->contents, 0, MIPS_ELF_REL_SIZE (dynobj));
   }
 
   return true;
@@ -8473,27 +8423,49 @@ static const struct ecoff_debug_swap mip
 #define elf_info_to_howto		mips_info_to_howto_rela
 #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_elf32_object_p
-#define elf_backend_section_from_shdr	mips_elf32_section_from_shdr
+#define elf_backend_object_p		_bfd_mips_elf_object_p
+#define elf_backend_section_from_shdr	_bfd_mips_elf_section_from_shdr
 #define elf_backend_fake_sections	_bfd_mips_elf_fake_sections
 #define elf_backend_section_from_bfd_section \
 					_bfd_mips_elf_section_from_bfd_section
-#define elf_backend_section_processing	mips_elf32_section_processing
+#define elf_backend_section_processing	_bfd_mips_elf_section_processing
 #define elf_backend_symbol_processing	_bfd_mips_elf_symbol_processing
 #define elf_backend_additional_program_headers \
-					mips_elf_additional_program_headers
-#define elf_backend_modify_segment_map	mips_elf_modify_segment_map
+					_bfd_mips_elf_additional_program_headers
+#define elf_backend_modify_segment_map	_bfd_mips_elf_modify_segment_map
 #define elf_backend_final_write_processing \
 					_bfd_mips_elf_final_write_processing
 #define elf_backend_ecoff_debug_swap	&mips_elf32_ecoff_debug_swap
+#define elf_backend_add_symbol_hook	_bfd_mips_elf_add_symbol_hook
+#define elf_backend_create_dynamic_sections \
+					_bfd_mips_elf_create_dynamic_sections
+#define elf_backend_check_relocs	_bfd_mips_elf_check_relocs
+#define elf_backend_adjust_dynamic_symbol \
+					_bfd_mips_elf_adjust_dynamic_symbol
+#define elf_backend_always_size_sections \
+					_bfd_mips_elf_always_size_sections
+#define elf_backend_size_dynamic_sections \
+					_bfd_mips_elf_size_dynamic_sections
+#define elf_backend_relocate_section	_bfd_mips_elf_relocate_section
+#define elf_backend_link_output_symbol_hook \
+					_bfd_mips_elf_link_output_symbol_hook
+#define elf_backend_finish_dynamic_symbol \
+					_bfd_mips_elf_finish_dynamic_symbol
+#define elf_backend_finish_dynamic_sections \
+					_bfd_mips_elf_finish_dynamic_sections
+#define elf_backend_gc_mark_hook	_bfd_mips_elf_gc_mark_hook
+#define elf_backend_gc_sweep_hook	_bfd_mips_elf_gc_sweep_hook
 
+#define elf_backend_got_header_size	(4*MIPS_RESERVED_GOTNO)
+#define elf_backend_plt_header_size	0
+
 #define bfd_elf32_bfd_is_local_label_name \
 					mips_elf_is_local_label_name
 #define bfd_elf32_find_nearest_line	_bfd_mips_elf_find_nearest_line
 #define bfd_elf32_set_section_contents	_bfd_mips_elf_set_section_contents
 #define bfd_elf32_bfd_link_hash_table_create \
-					mips_elf_link_hash_table_create
-#define bfd_elf32_bfd_final_link	mips_elf_final_link
+					_bfd_mips_elf_link_hash_table_create
+#define bfd_elf32_bfd_final_link	_bfd_mips_elf_final_link
 #define bfd_elf32_bfd_copy_private_bfd_data \
 					_bfd_mips_elf_copy_private_bfd_data
 #define bfd_elf32_bfd_merge_private_bfd_data \
@@ -8501,27 +8473,4 @@ static const struct ecoff_debug_swap mip
 #define bfd_elf32_bfd_set_private_flags	_bfd_mips_elf_set_private_flags
 #define bfd_elf32_bfd_print_private_bfd_data \
 					_bfd_mips_elf_print_private_bfd_data
-#define elf_backend_add_symbol_hook	mips_elf_add_symbol_hook
-#define elf_backend_create_dynamic_sections \
-					mips_elf_create_dynamic_sections
-#define elf_backend_check_relocs	mips_elf_check_relocs
-#define elf_backend_adjust_dynamic_symbol \
-					mips_elf_adjust_dynamic_symbol
-#define elf_backend_always_size_sections \
-					mips_elf_always_size_sections
-#define elf_backend_size_dynamic_sections \
-					mips_elf_size_dynamic_sections
-#define elf_backend_relocate_section	mips_elf_relocate_section
-#define elf_backend_link_output_symbol_hook \
-					mips_elf_link_output_symbol_hook
-#define elf_backend_finish_dynamic_symbol \
-					mips_elf_finish_dynamic_symbol
-#define elf_backend_finish_dynamic_sections \
-					mips_elf_finish_dynamic_sections
-#define elf_backend_gc_mark_hook	mips_elf_gc_mark_hook
-#define elf_backend_gc_sweep_hook	mips_elf_gc_sweep_hook
-
-#define elf_backend_got_header_size	(4*MIPS_RESERVED_GOTNO)
-#define elf_backend_plt_header_size	0
-
 #include "elf32-target.h"
Index: elf64-mips.c
===================================================================
RCS file: /cvs/binutils/binutils/bfd/elf64-mips.c,v
retrieving revision 1.5
diff -u -p -r1.5 elf64-mips.c
--- elf64-mips.c	1999/07/07 17:50:56	1.5
+++ elf64-mips.c	1999/07/08 01:01:27
@@ -1,6 +1,8 @@
 /* MIPS-specific support for 64-bit ELF
    Copyright 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
    Ian Lance Taylor, Cygnus Support
+   Linker support added by Mark Mitchell, CodeSourcery, LLC.
+   <mark@codesourcery.com>
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -74,10 +76,6 @@ static boolean mips_elf64_slurp_one_relo
 static boolean mips_elf64_slurp_reloc_table
   PARAMS ((bfd *, asection *, asymbol **, boolean));
 static void mips_elf64_write_relocs PARAMS ((bfd *, asection *, PTR));
-static boolean mips_elf64_section_from_shdr
-  PARAMS ((bfd *, Elf_Internal_Shdr *, char *));
-static boolean mips_elf64_section_processing
-  PARAMS ((bfd *, Elf_Internal_Shdr *));
 static boolean mips_elf64_slurp_armap PARAMS ((bfd *));
 static boolean mips_elf64_write_armap
   PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int));
@@ -86,6 +84,9 @@ static boolean mips_elf64_write_armap
    from smaller values.  Start with zero, widen, *then* decrement.  */
 #define MINUS_ONE	(((bfd_vma)0) - 1)
 
+/* The number of local .got entries we reserve.  */
+#define MIPS_RESERVED_GOTNO (2)
+
 /* The relocation table used for SHT_REL sections.  */
 
 static reloc_howto_type mips_elf64_howto_table_rel[] =
@@ -1814,115 +1815,6 @@ mips_elf64_write_relocs (abfd, sec, data
 	      == count);
 }
 
-/* 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;
-
-  /* For a SHT_MIPS_OPTIONS section, look for a ODK_REGINFO entry, and
-     set the gp value based on what we find.  We may see both
-     SHT_MIPS_REGINFO and SHT_MIPS_OPTIONS/ODK_REGINFO; in that case,
-     they should agree.  */
-  if (hdr->sh_type == SHT_MIPS_OPTIONS)
-    {
-      bfd_byte *contents, *l, *lend;
-
-      contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
-      if (contents == NULL)
-	return false;
-      if (! bfd_get_section_contents (abfd, hdr->bfd_section, contents,
-				      (file_ptr) 0, hdr->sh_size))
-	{
-	  free (contents);
-	  return false;
-	}
-      l = contents;
-      lend = contents + hdr->sh_size;
-      while (l + sizeof (Elf_External_Options) <= lend)
-	{
-	  Elf_Internal_Options intopt;
-
-	  bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l,
-					&intopt);
-	  if (intopt.kind == ODK_REGINFO)
-	    {
-	      Elf64_Internal_RegInfo intreg;
-
-	      bfd_mips_elf64_swap_reginfo_in
-		(abfd,
-		 ((Elf64_External_RegInfo *)
-		  (l + sizeof (Elf_External_Options))),
-		 &intreg);
-	      elf_gp (abfd) = intreg.ri_gp_value;
-	    }
-	  l += intopt.size;
-	}
-      free (contents);
-    }
-
-  return true;
-}
-
-/* Work over a section just before writing it out.  We update the GP
-   value in the SHT_MIPS_OPTIONS section based on the value we are
-   using.  */
-
-static boolean
-mips_elf64_section_processing (abfd, hdr)
-     bfd *abfd;
-     Elf_Internal_Shdr *hdr;
-{
-  if (hdr->sh_type == SHT_MIPS_OPTIONS
-      && hdr->bfd_section != NULL
-      && elf_section_data (hdr->bfd_section) != NULL
-      && elf_section_data (hdr->bfd_section)->tdata != NULL)
-    {
-      bfd_byte *contents, *l, *lend;
-
-      /* We stored the section contents in the elf_section_data tdata
-	 field in the set_section_contents routine.  We save the
-	 section contents so that we don't have to read them again.
-	 At this point we know that elf_gp is set, so we can look
-	 through the section contents to see if there is an
-	 ODK_REGINFO structure.  */
-
-      contents = (bfd_byte *) elf_section_data (hdr->bfd_section)->tdata;
-      l = contents;
-      lend = contents + hdr->sh_size;
-      while (l + sizeof (Elf_External_Options) <= lend)
-	{
-	  Elf_Internal_Options intopt;
-
-	  bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l,
-					&intopt);
-	  if (intopt.kind == ODK_REGINFO)
-	    {
-	      bfd_byte buf[8];
-
-	      if (bfd_seek (abfd,
-			    (hdr->sh_offset
-			     + (l - contents)
-			     + sizeof (Elf_External_Options)
-			     + (sizeof (Elf64_External_RegInfo) - 8)),
-			     SEEK_SET) == -1)
-		return false;
-	      bfd_h_put_64 (abfd, elf_gp (abfd), buf);
-	      if (bfd_write (buf, 1, 8, abfd) != 8)
-		return false;
-	    }
-	  l += intopt.size;
-	}
-    }
-
-  return _bfd_mips_elf_section_processing (abfd, hdr);
-}
-
 /* Irix 6 defines a brand new archive map format, so that they can
    have archives more than 4 GB in size.  */
 
@@ -2215,29 +2107,66 @@ const struct elf_size_info mips_elf64_si
 #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_collect		true
+#define elf_backend_type_change_ok	true
+#define elf_backend_can_gc_sections	true
 #define elf_backend_size_info		mips_elf64_size_info
 #define elf_backend_object_p		_bfd_mips_elf_object_p
-#define elf_backend_section_from_shdr	mips_elf64_section_from_shdr
+#define elf_backend_section_from_shdr	_bfd_mips_elf_section_from_shdr
 #define elf_backend_fake_sections	_bfd_mips_elf_fake_sections
 #define elf_backend_section_from_bfd_section \
 					_bfd_mips_elf_section_from_bfd_section
-#define elf_backend_section_processing	mips_elf64_section_processing
+#define elf_backend_section_processing	_bfd_mips_elf_section_processing
 #define elf_backend_symbol_processing	_bfd_mips_elf_symbol_processing
+#define elf_backend_additional_program_headers \
+					_bfd_mips_elf_additional_program_headers
+#define elf_backend_modify_segment_map	_bfd_mips_elf_modify_segment_map
 #define elf_backend_final_write_processing \
 					_bfd_mips_elf_final_write_processing
 #define elf_backend_ecoff_debug_swap	&mips_elf64_ecoff_debug_swap
-
+#define elf_backend_add_symbol_hook	_bfd_mips_elf_add_symbol_hook
+#define elf_backend_create_dynamic_sections \
+					_bfd_mips_elf_create_dynamic_sections
+#define elf_backend_check_relocs	_bfd_mips_elf_check_relocs
+#define elf_backend_adjust_dynamic_symbol \
+					_bfd_mips_elf_adjust_dynamic_symbol
+#define elf_backend_always_size_sections \
+					_bfd_mips_elf_always_size_sections
+#define elf_backend_size_dynamic_sections \
+					_bfd_mips_elf_size_dynamic_sections
+#define elf_backend_relocate_section    _bfd_mips_elf_relocate_section
+#define elf_backend_link_output_symbol_hook \
+					_bfd_mips_elf_link_output_symbol_hook
+#define elf_backend_finish_dynamic_symbol \
+					_bfd_mips_elf_finish_dynamic_symbol
+#define elf_backend_finish_dynamic_sections \
+					_bfd_mips_elf_finish_dynamic_sections
+#define elf_backend_gc_mark_hook	_bfd_mips_elf_gc_mark_hook
+#define elf_backend_gc_sweep_hook	_bfd_mips_elf_gc_sweep_hook
+#define elf_backend_got_header_size	(4*MIPS_RESERVED_GOTNO)
+#define elf_backend_plt_header_size	0
+
+/* We don't set bfd_elf64_bfd_is_local_label_name because the 32-bit 
+   MIPS-specific function only applies to IRIX5, which had no 64-bit
+   ABI.  */
 #define bfd_elf64_find_nearest_line	_bfd_mips_elf_find_nearest_line
-#define bfd_elf64_get_reloc_upper_bound mips_elf64_get_reloc_upper_bound
-#define bfd_elf64_bfd_reloc_type_lookup	mips_elf64_reloc_type_lookup
 #define bfd_elf64_set_section_contents	_bfd_mips_elf_set_section_contents
+#define bfd_elf64_bfd_link_hash_table_create \
+					_bfd_mips_elf_link_hash_table_create
+#define bfd_elf64_bfd_final_link	_bfd_mips_elf_final_link
 #define bfd_elf64_bfd_copy_private_bfd_data \
 					_bfd_mips_elf_copy_private_bfd_data
 #define bfd_elf64_bfd_merge_private_bfd_data \
 					_bfd_mips_elf_merge_private_bfd_data
 #define bfd_elf64_bfd_set_private_flags	_bfd_mips_elf_set_private_flags
+#define bfd_elf64_bfd_print_private_bfd_data \
+					_bfd_mips_elf_print_private_bfd_data
 
+#define bfd_elf64_get_reloc_upper_bound mips_elf64_get_reloc_upper_bound
+#define bfd_elf64_bfd_reloc_type_lookup	mips_elf64_reloc_type_lookup
 #define bfd_elf64_archive_functions
 #define bfd_elf64_archive_slurp_armap	mips_elf64_slurp_armap
 #define bfd_elf64_archive_slurp_extended_name_table \

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