* elflink.h (elf_link_create_dynamic_sections): Handle non-standard
authorMark Mitchell <mark@codesourcery.com>
Wed, 7 Jul 1999 17:50:56 +0000 (17:50 +0000)
committerMark Mitchell <mark@codesourcery.com>
Wed, 7 Jul 1999 17:50:56 +0000 (17:50 +0000)
hash-entry sizes.
(size_dynamic_sections): Likewise.
(elf_link_output_extsym): Likewise.
* elf.c: (elf_fake_sections): Likewise.
* libbfd.c (bfd_get): New macro.
(bfd_put): Likewise.
* bfd-in2.h: Regenerated.
* elf-bfd.h (elf_size_info): Add hash_entry_size,
int_rels_per_ext_rel, swap_dyn_out, swap_reloc_in, swap_reloc_out,
wap_reloca_in, and swap_reloca_out.
* elflink.h (elf_link_read_relocs_from_section): Adjust to handle
multiple internal relocations per external relocation.
(link_read_relocs): Likewise.
(elf_bfd_final_link): Likewise.
(elf_link_input_bfd): Likewise.
(elf_gc_mark): Likewise.
(elf_gc_smash_unused_vtentry_relocs): Likewise.
* elfcode.h (elf_swap_dyn_out): Adjust type to match
elf_swap_dyn_in.
(size_info): Add entries for new fields.
* elf64-mips.c (mips_elf64_swap_reloc_out): Enable.
(mips_elf64_be_swap_reloc_in): New function.
(mips_elf64_be_swap_reloc_out): Likewise.
(mips_elf64_be_swap_reloca_in): Likewise.
(mips_elf64_be_swap_reloca_out): Likewise.
(mips_elf64_size_info): Add entries for new fields.

bfd/ChangeLog
bfd/bfd-in2.h
bfd/elf-bfd.h
bfd/elf.c
bfd/elf64-mips.c
bfd/elfcode.h
bfd/elflink.h
bfd/libbfd.c

index 1babf26..22232e8 100644 (file)
@@ -1,3 +1,36 @@
+1999-07-07  Mark Mitchell  <mark@codesourcery.com>
+
+       * elflink.h (elf_link_create_dynamic_sections): Handle non-standard
+       hash-entry sizes.
+       (size_dynamic_sections): Likewise.
+       (elf_link_output_extsym): Likewise.
+       * elf.c: (elf_fake_sections): Likewise.
+       * libbfd.c (bfd_get): New macro.
+       (bfd_put): Likewise.
+       * bfd-in2.h: Regenerated.
+
+1999-07-07  Mark Mitchell  <mark@codesourcery.com>
+
+       * elf-bfd.h (elf_size_info): Add hash_entry_size,
+       int_rels_per_ext_rel, swap_dyn_out, swap_reloc_in, swap_reloc_out,
+       wap_reloca_in, and swap_reloca_out. 
+       * elflink.h (elf_link_read_relocs_from_section): Adjust to handle
+       multiple internal relocations per external relocation.
+       (link_read_relocs): Likewise.
+       (elf_bfd_final_link): Likewise.
+       (elf_link_input_bfd): Likewise.
+       (elf_gc_mark): Likewise.
+       (elf_gc_smash_unused_vtentry_relocs): Likewise.
+       * elfcode.h (elf_swap_dyn_out): Adjust type to match
+       elf_swap_dyn_in.
+       (size_info): Add entries for new fields.
+       * elf64-mips.c (mips_elf64_swap_reloc_out): Enable.
+       (mips_elf64_be_swap_reloc_in): New function.
+       (mips_elf64_be_swap_reloc_out): Likewise.
+       (mips_elf64_be_swap_reloca_in): Likewise.
+       (mips_elf64_be_swap_reloca_out): Likewise.
+       (mips_elf64_size_info): Add entries for new fields.
+       
 1999-07-07  Ian Lance Taylor  <ian@zembu.com>
 
        * elflink.h (elf_bfd_final_link): Assert that section reloc_count
index 78cadab..aa20c08 100644 (file)
@@ -803,6 +803,20 @@ bfd_make_readable PARAMS ((bfd *abfd));
 #define bfd_get_signed_64(abfd, ptr) \
                 BFD_SEND(abfd, bfd_getx_signed_64, (ptr))
 
+#define bfd_get(bits, abfd, ptr)                               \
+                ((bits) == 8 ? bfd_get_8 (abfd, ptr)           \
+                : (bits) == 16 ? bfd_get_16 (abfd, ptr)        \
+                : (bits) == 32 ? bfd_get_32 (abfd, ptr)        \
+                : (bits) == 64 ? bfd_get_64 (abfd, ptr)        \
+                : (abort (), (bfd_vma) - 1))
+
+#define bfd_put(bits, abfd, val, ptr)                          \
+                ((bits) == 8 ? bfd_put_8 (abfd, val, ptr)      \
+                : (bits) == 16 ? bfd_put_16 (abfd, val, ptr)   \
+                : (bits) == 32 ? bfd_put_32 (abfd, val, ptr)   \
+                : (bits) == 64 ? bfd_put_64 (abfd, val, ptr)   \
+                : (abort (), (void) 0))
+
 
  /* Byte swapping macros for file header data.  */
 
index 05667bd..303f0a8 100644 (file)
@@ -236,6 +236,13 @@ struct elf_size_info {
   unsigned char sizeof_ehdr, sizeof_phdr, sizeof_shdr;
   unsigned char sizeof_rel, sizeof_rela, sizeof_sym, sizeof_dyn, sizeof_note;
 
+  /* The size of entries in the .hash section.  */
+  unsigned char sizeof_hash_entry;
+
+  /* The number of internal relocations to allocate per external
+     relocation entry.  */
+  unsigned char int_rels_per_ext_rel;
+
   unsigned char arch_size, file_align;
   unsigned char elfclass, ev_current;
   int (*write_out_phdrs) PARAMS ((bfd *, const Elf_Internal_Phdr *, int));
@@ -246,6 +253,32 @@ struct elf_size_info {
     PARAMS ((bfd *, asection *, asymbol **, boolean));
   long (*slurp_symbol_table) PARAMS ((bfd *, asymbol **, boolean));
   void (*swap_dyn_in) PARAMS ((bfd *, const PTR, Elf_Internal_Dyn *));
+  void (*swap_dyn_out) PARAMS ((bfd *, const Elf_Internal_Dyn *, PTR));
+
+  /* This function, if defined, is called to swap in a REL
+     relocation.  If an external relocation corresponds to more than
+     one internal relocation, then all relocations are swapped in at
+     once.  */
+  void (*swap_reloc_in)
+    PARAMS ((bfd *, const bfd_byte *, Elf_Internal_Rel *));
+
+  /* This function, if defined, is called to swap out a REL
+     relocation.  */
+  void (*swap_reloc_out)
+    PARAMS ((bfd *, const Elf_Internal_Rel *, bfd_byte *));
+
+  /* This function, if defined, is called to swap in a RELA
+     relocation.  If an external relocation corresponds to more than
+     one internal relocation, then all relocations are swapped in at
+     once.  */
+  void (*swap_reloca_in)
+    PARAMS ((bfd *, const bfd_byte *, Elf_Internal_Rela *));
+
+  /* This function, if defined, is called to swap out a RELA
+     relocation.  */
+  void (*swap_reloca_out)
+    PARAMS ((bfd *, const Elf_Internal_Rela *, bfd_byte *));
+
 };
 
 #define elf_symbol_from(ABFD,S) \
@@ -1024,7 +1057,7 @@ extern void bfd_elf32_swap_phdr_out
 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 *));
+  PARAMS ((bfd *, const Elf_Internal_Dyn *, PTR));
 extern long bfd_elf32_slurp_symbol_table
   PARAMS ((bfd *, asymbol **, boolean));
 extern boolean bfd_elf32_write_shdrs_and_ehdr PARAMS ((bfd *));
@@ -1067,7 +1100,7 @@ extern void bfd_elf64_swap_phdr_out
 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 *));
+  PARAMS ((bfd *, const Elf_Internal_Dyn *, PTR));
 extern long bfd_elf64_slurp_symbol_table
   PARAMS ((bfd *, asymbol **, boolean));
 extern boolean bfd_elf64_write_shdrs_and_ehdr PARAMS ((bfd *));
index f3d23c4..4db37c4 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1532,7 +1532,7 @@ elf_fake_sections (abfd, asect, failedptrarg)
   else if (strcmp (asect->name, ".hash") == 0)
     {
       this_hdr->sh_type = SHT_HASH;
-      this_hdr->sh_entsize = bed->s->arch_size / 8;
+      this_hdr->sh_entsize = bed->s->sizeof_hash_entry;
     }
   else if (strcmp (asect->name, ".dynsym") == 0)
     {
index 36e6075..79b172f 100644 (file)
@@ -52,14 +52,20 @@ static void mips_elf64_swap_reloc_in
 static void mips_elf64_swap_reloca_in
   PARAMS ((bfd *, const Elf64_Mips_External_Rela *,
           Elf64_Mips_Internal_Rela *));
-#if 0
 static void mips_elf64_swap_reloc_out
   PARAMS ((bfd *, const Elf64_Mips_Internal_Rel *,
           Elf64_Mips_External_Rel *));
-#endif
 static void mips_elf64_swap_reloca_out
   PARAMS ((bfd *, const Elf64_Mips_Internal_Rela *,
           Elf64_Mips_External_Rela *));
+static void mips_elf64_be_swap_reloc_in
+  PARAMS ((bfd *, const bfd_byte *, Elf_Internal_Rel *));
+static void mips_elf64_be_swap_reloc_out
+  PARAMS ((bfd *, const Elf_Internal_Rel *, bfd_byte *));
+static void mips_elf64_be_swap_reloca_in
+  PARAMS ((bfd *, const bfd_byte *, Elf_Internal_Rela *));
+static void mips_elf64_be_swap_reloca_out
+  PARAMS ((bfd *, const Elf_Internal_Rela *, bfd_byte *));
 static reloc_howto_type *mips_elf64_reloc_type_lookup
   PARAMS ((bfd *, bfd_reloc_code_real_type));
 static long mips_elf64_get_reloc_upper_bound PARAMS ((bfd *, asection *));
@@ -1220,10 +1226,6 @@ mips_elf64_swap_reloca_in (abfd, src, dst)
   dst->r_addend = bfd_h_get_signed_64 (abfd, (bfd_byte *) src->r_addend);
 }
 
-#if 0
-
-/* This is not currently used.  */
-
 /* Swap out a MIPS 64-bit Rel reloc.  */
 
 static void
@@ -1240,8 +1242,6 @@ mips_elf64_swap_reloc_out (abfd, src, dst)
   bfd_h_put_8 (abfd, src->r_type, (bfd_byte *) dst->r_type);
 }
 
-#endif /* 0 */
-
 /* Swap out a MIPS 64-bit Rela reloc.  */
 
 static void
@@ -1259,6 +1259,96 @@ mips_elf64_swap_reloca_out (abfd, src, dst)
   bfd_h_put_64 (abfd, src->r_addend, (bfd_byte *) dst->r_addend);
 }
 
+/* Swap in a MIPS 64-bit Rel reloc.  */
+
+static void
+mips_elf64_be_swap_reloc_in (abfd, src, dst)
+     bfd *abfd;
+     const bfd_byte *src;
+     Elf_Internal_Rel *dst;
+{
+  Elf64_Mips_Internal_Rel mirel;
+
+  mips_elf64_swap_reloc_in (abfd, 
+                           (const Elf64_Mips_External_Rel *) src,
+                           &mirel);
+
+  dst[0].r_offset = mirel.r_offset;
+  dst[0].r_info = ELF32_R_INFO (mirel.r_sym, mirel.r_type);
+  dst[1].r_offset = mirel.r_offset;
+  dst[1].r_info = ELF32_R_INFO (mirel.r_ssym, mirel.r_type2);
+  dst[2].r_offset = mirel.r_offset;
+  dst[2].r_info = ELF32_R_INFO (STN_UNDEF, mirel.r_type3);
+}
+
+/* Swap in a MIPS 64-bit Rela reloc.  */
+
+static void
+mips_elf64_be_swap_reloca_in (abfd, src, dst)
+     bfd *abfd;
+     const bfd_byte *src;
+     Elf_Internal_Rela *dst;
+{
+  Elf64_Mips_Internal_Rela mirela;
+
+  mips_elf64_swap_reloca_in (abfd, 
+                            (const Elf64_Mips_External_Rela *) src,
+                            &mirela);
+
+  dst[0].r_offset = mirela.r_offset;
+  dst[0].r_info = ELF32_R_INFO (mirela.r_sym, mirela.r_type);
+  dst[0].r_addend = mirela.r_addend;
+  dst[1].r_offset = mirela.r_offset;
+  dst[1].r_info = ELF32_R_INFO (mirela.r_ssym, mirela.r_type2);
+  dst[1].r_addend = 0;
+  dst[2].r_offset = mirela.r_offset;
+  dst[2].r_info = ELF32_R_INFO (STN_UNDEF, mirela.r_type3);
+  dst[2].r_addend = 0;
+}
+
+/* Swap out a MIPS 64-bit Rel reloc.  */
+
+static void
+mips_elf64_be_swap_reloc_out (abfd, src, dst)
+     bfd *abfd;
+     const Elf_Internal_Rel *src;
+     bfd_byte *dst;
+{
+  Elf64_Mips_Internal_Rel mirel;
+
+  mirel.r_offset = src->r_offset;
+  mirel.r_type = ELF32_R_TYPE (src->r_info);
+  mirel.r_sym = ELF32_R_SYM (src->r_info);
+  mirel.r_type2 = R_MIPS_NONE;
+  mirel.r_ssym = STN_UNDEF;
+  mirel.r_type3 = R_MIPS_NONE;
+
+  mips_elf64_swap_reloc_out (abfd, &mirel, 
+                            (Elf64_Mips_External_Rel *) dst);
+}
+
+/* Swap out a MIPS 64-bit Rela reloc.  */
+
+static void
+mips_elf64_be_swap_reloca_out (abfd, src, dst)
+     bfd *abfd;
+     const Elf_Internal_Rela *src;
+     bfd_byte *dst;
+{
+  Elf64_Mips_Internal_Rela mirela;
+
+  mirela.r_offset = src->r_offset;
+  mirela.r_type = ELF32_R_TYPE (src->r_info);
+  mirela.r_addend = src->r_addend;
+  mirela.r_sym = ELF32_R_SYM (src->r_info);
+  mirela.r_type2 = R_MIPS_NONE;
+  mirela.r_ssym = STN_UNDEF;
+  mirela.r_type3 = R_MIPS_NONE;
+
+  mips_elf64_swap_reloca_out (abfd, &mirela, 
+                             (Elf64_Mips_External_Rela *) dst);
+}
+
 /* A mapping from BFD reloc types to MIPS ELF reloc types.  */
 
 struct elf_reloc_map
@@ -2099,6 +2189,8 @@ const struct elf_size_info mips_elf64_size_info =
   sizeof (Elf64_External_Sym),
   sizeof (Elf64_External_Dyn),
   sizeof (Elf_External_Note),
+  4,            /* hash-table entry size */
+  3,            /* internal relocations per external relocations */
   64,          /* arch_size */
   8,           /* file_align */
   ELFCLASS64,
@@ -2109,7 +2201,12 @@ const struct elf_size_info mips_elf64_size_info =
   bfd_elf64_swap_symbol_out,
   mips_elf64_slurp_reloc_table,
   bfd_elf64_slurp_symbol_table,
-  bfd_elf64_swap_dyn_in
+  bfd_elf64_swap_dyn_in,
+  bfd_elf64_swap_dyn_out,
+  mips_elf64_be_swap_reloc_in,
+  mips_elf64_be_swap_reloc_out,
+  mips_elf64_be_swap_reloca_in,
+  mips_elf64_be_swap_reloca_out
 };
 
 #define TARGET_LITTLE_SYM              bfd_elf64_littlemips_vec
index 29a1943..49e156e 100644 (file)
@@ -423,11 +423,13 @@ elf_swap_dyn_in (abfd, p, dst)
 }
 
 INLINE void
-elf_swap_dyn_out (abfd, src, dst)
+elf_swap_dyn_out (abfd, src, p)
      bfd *abfd;
      const Elf_Internal_Dyn *src;
-     Elf_External_Dyn *dst;
+     PTR p;
 {
+  Elf_External_Dyn *dst = (Elf_External_Dyn *) p;
+
   put_word (abfd, src->d_tag, dst->d_tag);
   put_word (abfd, src->d_un.d_val, dst->d_un.d_val);
 }
@@ -1500,7 +1502,8 @@ const struct elf_size_info NAME(_bfd_elf,size_info) = {
   sizeof (Elf_External_Sym),
   sizeof (Elf_External_Dyn),
   sizeof (Elf_External_Note),
-
+  ARCH_SIZE / 8,
+  1,
   ARCH_SIZE, FILE_ALIGN,
   ELFCLASS, EV_CURRENT,
   elf_write_out_phdrs,
@@ -1509,5 +1512,10 @@ const struct elf_size_info NAME(_bfd_elf,size_info) = {
   elf_swap_symbol_out,
   elf_slurp_reloc_table,
   elf_slurp_symbol_table,
-  elf_swap_dyn_in
+  elf_swap_dyn_in,
+  elf_swap_dyn_out,
+  NULL,
+  NULL,
+  NULL,
+  NULL
 };
index c2debca..057dc5e 100644 (file)
@@ -1997,16 +1997,18 @@ elf_link_create_dynamic_sections (abfd, info)
       && ! _bfd_elf_link_record_dynamic_symbol (info, h))
     return false;
 
+  bed = get_elf_backend_data (abfd);
+
   s = bfd_make_section (abfd, ".hash");
   if (s == NULL
       || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
       || ! bfd_set_section_alignment (abfd, s, LOG_FILE_ALIGN))
     return false;
+  elf_section_data (s)->this_hdr.sh_entsize = bed->s->sizeof_hash_entry;
 
   /* Let the backend create the rest of the sections.  This lets the
      backend set the right flags.  The backend will normally create
      the .got and .plt sections.  */
-  bed = get_elf_backend_data (abfd);
   if (! (*bed->elf_backend_create_dynamic_sections) (abfd, info))
     return false;
 
@@ -2068,6 +2070,8 @@ elf_link_read_relocs_from_section (abfd, shdr, external_relocs,
      PTR external_relocs;
      Elf_Internal_Rela *internal_relocs;
 {
+  struct elf_backend_data *bed;
+
   /* If there aren't any relocations, that's OK.  */
   if (!shdr)
     return true;
@@ -2081,24 +2085,36 @@ elf_link_read_relocs_from_section (abfd, shdr, external_relocs,
       != shdr->sh_size)
     return false;
 
+  bed = get_elf_backend_data (abfd);
+
   /* Convert the external relocations to the internal format.  */
   if (shdr->sh_entsize == sizeof (Elf_External_Rel))
     {
       Elf_External_Rel *erel;
       Elf_External_Rel *erelend;
       Elf_Internal_Rela *irela;
+      Elf_Internal_Rel *irel;
 
       erel = (Elf_External_Rel *) external_relocs;
       erelend = erel + shdr->sh_size / shdr->sh_entsize;
       irela = internal_relocs;
-      for (; erel < erelend; erel++, irela++)
+      irel = bfd_alloc (abfd, (bed->s->int_rels_per_ext_rel
+                              * sizeof (Elf_Internal_Rel)));
+      for (; erel < erelend; erel++, irela += bed->s->int_rels_per_ext_rel)
        {
-         Elf_Internal_Rel irel;
+         int i;
+
+         if (bed->s->swap_reloc_in)
+           (*bed->s->swap_reloc_in) (abfd, (bfd_byte *) erel, irel);
+         else
+           elf_swap_reloc_in (abfd, erel, irel);
 
-         elf_swap_reloc_in (abfd, erel, &irel);
-         irela->r_offset = irel.r_offset;
-         irela->r_info = irel.r_info;
-         irela->r_addend = 0;
+         for (i = 0; i < bed->s->int_rels_per_ext_rel; ++i)
+           {
+             irela[i].r_offset = irel[i].r_offset;
+             irela[i].r_info = irel[i].r_info;
+             irela[i].r_addend = 0;
+           }
        }
     }
   else
@@ -2112,8 +2128,13 @@ elf_link_read_relocs_from_section (abfd, shdr, external_relocs,
       erela = (Elf_External_Rela *) external_relocs;
       erelaend = erela + shdr->sh_size / shdr->sh_entsize;
       irela = internal_relocs;
-      for (; erela < erelaend; erela++, irela++)
-       elf_swap_reloca_in (abfd, erela, irela);
+      for (; erela < erelaend; erela++, irela += bed->s->int_rels_per_ext_rel)
+       {
+         if (bed->s->swap_reloca_in)
+           (*bed->s->swap_reloca_in) (abfd, (bfd_byte *) erela, irela);
+         else
+           elf_swap_reloca_in (abfd, erela, irela);
+       }
     }
 
   return true;
@@ -2141,6 +2162,7 @@ NAME(_bfd_elf,link_read_relocs) (abfd, o, external_relocs, internal_relocs,
   Elf_Internal_Shdr *rel_hdr;
   PTR alloc1 = NULL;
   Elf_Internal_Rela *alloc2 = NULL;
+  struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
   if (elf_section_data (o)->relocs != NULL)
     return elf_section_data (o)->relocs;
@@ -2154,7 +2176,8 @@ NAME(_bfd_elf,link_read_relocs) (abfd, o, external_relocs, internal_relocs,
     {
       size_t size;
 
-      size = o->reloc_count * sizeof (Elf_Internal_Rela);
+      size = (o->reloc_count * bed->s->int_rels_per_ext_rel 
+             * sizeof (Elf_Internal_Rela));
       if (keep_memory)
        internal_relocs = (Elf_Internal_Rela *) bfd_alloc (abfd, size);
       else
@@ -2183,7 +2206,8 @@ NAME(_bfd_elf,link_read_relocs) (abfd, o, external_relocs, internal_relocs,
       (abfd, 
        elf_section_data (o)->rel_hdr2,
        ((bfd_byte *) external_relocs) + rel_hdr->sh_size,
-       internal_relocs + rel_hdr->sh_size / rel_hdr->sh_entsize))
+       internal_relocs + (rel_hdr->sh_size / rel_hdr->sh_entsize
+                         * bed->s->int_rels_per_ext_rel)))
     goto error_return;
 
   /* Cache the results for next time, if we can.  */
@@ -2699,6 +2723,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
       asection *s;
       size_t bucketcount = 0;
       Elf_Internal_Sym isym;
+      size_t hash_entry_size;
 
       /* Set up the version definition section.  */
       s = bfd_get_section_by_name (dynobj, ".gnu.version_d");
@@ -3047,14 +3072,16 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
 
       s = bfd_get_section_by_name (dynobj, ".hash");
       BFD_ASSERT (s != NULL);
-      s->_raw_size = (2 + bucketcount + dynsymcount) * (ARCH_SIZE / 8);
+      hash_entry_size = elf_section_data (s)->this_hdr.sh_entsize;
+      s->_raw_size = ((2 + bucketcount + dynsymcount) * hash_entry_size);
       s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
       if (s->contents == NULL)
        return false;
       memset (s->contents, 0, (size_t) s->_raw_size);
 
-      put_word (output_bfd, bucketcount, s->contents);
-      put_word (output_bfd, dynsymcount, s->contents + (ARCH_SIZE / 8));
+      bfd_put (8 * hash_entry_size, output_bfd, bucketcount, s->contents);
+      bfd_put (8 * hash_entry_size, output_bfd, dynsymcount, 
+              s->contents + hash_entry_size);
 
       elf_hash_table (info)->bucketcount = bucketcount;
 
@@ -4043,7 +4070,8 @@ elf_bfd_final_link (abfd, info)
   finfo.external_relocs = (PTR) bfd_malloc (max_external_reloc_size);
   finfo.internal_relocs = ((Elf_Internal_Rela *)
                           bfd_malloc (max_internal_reloc_count
-                                      * sizeof (Elf_Internal_Rela)));
+                                      * sizeof (Elf_Internal_Rela)
+                                      * bed->s->int_rels_per_ext_rel));
   finfo.external_syms = ((Elf_External_Sym *)
                         bfd_malloc (max_sym_count
                                     * sizeof (Elf_External_Sym)));
@@ -4738,6 +4766,7 @@ elf_link_output_extsym (h, data)
     {
       size_t bucketcount;
       size_t bucket;
+      size_t hash_entry_size;
       bfd_byte *bucketpos;
       bfd_vma chain;
 
@@ -4750,13 +4779,15 @@ elf_link_output_extsym (h, data)
 
       bucketcount = elf_hash_table (finfo->info)->bucketcount;
       bucket = h->elf_hash_value % bucketcount;
+      hash_entry_size 
+       = elf_section_data (finfo->hash_sec)->this_hdr.sh_entsize;
       bucketpos = ((bfd_byte *) finfo->hash_sec->contents
-                  + (bucket + 2) * (ARCH_SIZE / 8));
-      chain = get_word (finfo->output_bfd, bucketpos);
-      put_word (finfo->output_bfd, h->dynindx, bucketpos);
-      put_word (finfo->output_bfd, chain,
-               ((bfd_byte *) finfo->hash_sec->contents
-                + (bucketcount + 2 + h->dynindx) * (ARCH_SIZE / 8)));
+                  + (bucket + 2) * hash_entry_size);
+      chain = bfd_get (8 * hash_entry_size, finfo->output_bfd, bucketpos);
+      bfd_put (8 * hash_entry_size, finfo->output_bfd, h->dynindx, bucketpos);
+      bfd_put (8 * hash_entry_size, finfo->output_bfd, chain,
+              ((bfd_byte *) finfo->hash_sec->contents
+               + (bucketcount + 2 + h->dynindx) * hash_entry_size));
 
       if (finfo->symver_sec != NULL && finfo->symver_sec->contents != NULL)
        {
@@ -4898,10 +4929,11 @@ elf_link_input_bfd (finfo, input_bfd)
   long *pindex;
   asection **ppsection;
   asection *o;
+  struct elf_backend_data *bed;
 
   output_bfd = finfo->output_bfd;
-  relocate_section =
-    get_elf_backend_data (output_bfd)->elf_backend_relocate_section;
+  bed = get_elf_backend_data (output_bfd);
+  relocate_section = bed->elf_backend_relocate_section;
 
   /* If this is a dynamic object, we don't want to do anything here:
      we don't want the local symbols, and we don't want the section
@@ -5138,7 +5170,8 @@ elf_link_input_bfd (finfo, input_bfd)
              /* Adjust the reloc addresses and symbol indices.  */
 
              irela = internal_relocs;
-             irelaend = irela + o->reloc_count;
+             irelaend = 
+               irela + o->reloc_count * bed->s->int_rels_per_ext_rel;
              rel_hash = (elf_section_data (o->output_section)->rel_hashes
                          + elf_section_data (o->output_section)->rel_count);
              for (; irela < irelaend; irela++, rel_hash++)
@@ -5748,6 +5781,7 @@ elf_gc_mark (info, sec, gc_mark_hook)
       size_t extsymoff;
       Elf_External_Sym *locsyms, *freesyms = NULL;
       bfd *input_bfd = sec->owner;
+      struct elf_backend_data *bed = get_elf_backend_data (input_bfd);
 
       /* GCFIXME: how to arrange so that relocs and symbols are not
         reread continually?  */
@@ -5791,7 +5825,7 @@ elf_gc_mark (info, sec, gc_mark_hook)
          ret = false;
          goto out1;
        }
-      relend = relstart + sec->reloc_count;
+      relend = relstart + sec->reloc_count * bed->s->int_rels_per_ext_rel;
 
       for (rel = relstart; rel < relend; rel++)
        {
@@ -5997,6 +6031,7 @@ elf_gc_smash_unused_vtentry_relocs (h, okp)
   asection *sec;
   bfd_vma hstart, hend;
   Elf_Internal_Rela *relstart, *relend, *rel;
+  struct elf_backend_data *bed;
 
   /* Take care of both those symbols that do not describe vtables as
      well as those that are not loaded.  */
@@ -6014,7 +6049,8 @@ elf_gc_smash_unused_vtentry_relocs (h, okp)
              (sec->owner, sec, NULL, (Elf_Internal_Rela *) NULL, true));
   if (!relstart)
     return *(boolean *)okp = false;
-  relend = relstart + sec->reloc_count;
+  bed = get_elf_backend_data (sec->owner);
+  relend = relstart + sec->reloc_count * bed->s->int_rels_per_ext_rel;
 
   for (rel = relstart; rel < relend; ++rel)
     if (rel->r_offset >= hstart && rel->r_offset < hend)
index 8da3de0..23a27e3 100644 (file)
@@ -827,6 +827,20 @@ DESCRIPTION
 .#define bfd_get_signed_64(abfd, ptr) \
 .               BFD_SEND(abfd, bfd_getx_signed_64, (ptr))
 .
+.#define bfd_get(bits, abfd, ptr)                              \
+.                ((bits) == 8 ? bfd_get_8 (abfd, ptr)          \
+.               : (bits) == 16 ? bfd_get_16 (abfd, ptr)        \
+.               : (bits) == 32 ? bfd_get_32 (abfd, ptr)        \
+.               : (bits) == 64 ? bfd_get_64 (abfd, ptr)        \
+.               : (abort (), (bfd_vma) - 1))
+.
+.#define bfd_put(bits, abfd, val, ptr)                         \
+.                ((bits) == 8 ? bfd_put_8 (abfd, val, ptr)     \
+.               : (bits) == 16 ? bfd_put_16 (abfd, val, ptr)   \
+.               : (bits) == 32 ? bfd_put_32 (abfd, val, ptr)   \
+.               : (bits) == 64 ? bfd_put_64 (abfd, val, ptr)   \
+.               : (abort (), (void) 0))
+.
 */ 
 
 /*