* elfcode.h (elf_slurp_reloc_table): Add dynamic parameter.
authorIan Lance Taylor <ian@airs.com>
Sun, 15 Dec 1996 19:59:18 +0000 (19:59 +0000)
committerIan Lance Taylor <ian@airs.com>
Sun, 15 Dec 1996 19:59:18 +0000 (19:59 +0000)
* elf.c (_bfd_elf_canonicalize_reloc): Pass new argument to
slurp_reloc_table.
(_bfd_elf_get_dynamic_reloc_upper_bound): New function.
(_bfd_elf_canonicalize_dynamic_reloc): New function.
* elf-bfd.h (struct elf_size_info): Update declaration of
slurp_reloc_table.
(_bfd_elf_get_dynamic_reloc_upper_bound): Declare.
(_bfd_elf_canonicalize_dynamic_reloc): Declare.
* elfxx-target.h: Use new dynamic reloc routines by default.
* elf64-mips.c (mips_elf64_slurp_reloc_table): Add dynamic
parameter.

bfd/ChangeLog
bfd/elf-bfd.h
bfd/elf.c
bfd/elf64-mips.c
bfd/elfcode.h
bfd/elfxx-target.h

index 152a7f7420e35d40e9f4ba6c2b5fa0fb2f533dca..3fe46ffbc6c775ce7a51c427003fe9e264c64e26 100644 (file)
@@ -1,3 +1,18 @@
+Sun Dec 15 14:46:06 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * elfcode.h (elf_slurp_reloc_table): Add dynamic parameter.
+       * elf.c (_bfd_elf_canonicalize_reloc): Pass new argument to
+       slurp_reloc_table.
+       (_bfd_elf_get_dynamic_reloc_upper_bound): New function.
+       (_bfd_elf_canonicalize_dynamic_reloc): New function.
+       * elf-bfd.h (struct elf_size_info): Update declaration of
+       slurp_reloc_table.
+       (_bfd_elf_get_dynamic_reloc_upper_bound): Declare.
+       (_bfd_elf_canonicalize_dynamic_reloc): Declare.
+       * elfxx-target.h: Use new dynamic reloc routines by default.
+       * elf64-mips.c (mips_elf64_slurp_reloc_table): Add dynamic
+       parameter.
+
 Fri Dec 13 13:18:49 1996  Dan Wilder  <dan@gasboy.com>
 
        * coffcode.h (coff_set_flags): Use MC68KBCSMAGIC for bfd_arch_m68k
index 4592386ae6d6d3ebc9bfd845f90ad4a29f57a680..ac27d1fe4e4140f6e2cd70868dfc7bb95e83647b 100644 (file)
@@ -110,6 +110,9 @@ struct elf_link_hash_entry
   /* Symbol type (STT_NOTYPE, STT_OBJECT, etc.).  */
   char type;
 
+  /* Symbol st_other value.  */
+  unsigned char other;
+
   /* Some flags; legal values follow.  */
   unsigned char elf_link_hash_flags;
   /* Symbol is referenced by a non-shared object.  */
@@ -193,7 +196,8 @@ struct elf_size_info {
   boolean (*write_shdrs_and_ehdr) PARAMS ((bfd *));
   void (*write_relocs) PARAMS ((bfd *, asection *, PTR));
   void (*swap_symbol_out) PARAMS ((bfd *, const Elf_Internal_Sym *, PTR));
-  boolean (*slurp_reloc_table) PARAMS ((bfd *, asection *, asymbol **));
+  boolean (*slurp_reloc_table)
+    PARAMS ((bfd *, asection *, asymbol **, boolean));
   long (*slurp_symbol_table) PARAMS ((bfd *, asymbol **, boolean));
   void (*swap_dyn_in) PARAMS ((bfd *, const PTR, Elf_Internal_Dyn *));
 };
@@ -698,6 +702,9 @@ extern long _bfd_elf_canonicalize_dynamic_symtab PARAMS ((bfd *, asymbol **));
 extern long _bfd_elf_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr));
 extern long _bfd_elf_canonicalize_reloc PARAMS ((bfd *, sec_ptr,
                                                  arelent **, asymbol **));
+extern long _bfd_elf_get_dynamic_reloc_upper_bound PARAMS ((bfd *));
+extern long _bfd_elf_canonicalize_dynamic_reloc PARAMS ((bfd *, arelent **,
+                                                        asymbol **));
 extern asymbol *_bfd_elf_make_empty_symbol PARAMS ((bfd *));
 extern void _bfd_elf_get_symbol_info PARAMS ((bfd *, asymbol *,
                                               symbol_info *));
@@ -719,6 +726,7 @@ extern void _bfd_elf_no_info_to_howto PARAMS ((bfd *, arelent *,
                                               Elf_Internal_Rela *));
 
 extern boolean bfd_section_from_shdr PARAMS ((bfd *, unsigned int shindex));
+extern boolean bfd_section_from_phdr PARAMS ((bfd *, Elf_Internal_Phdr *, int));
 
 extern int _bfd_elf_symbol_from_bfd_symbol PARAMS ((bfd *, asymbol **));
 
@@ -835,6 +843,8 @@ extern boolean bfd_elf32_add_dynamic_entry
   PARAMS ((struct bfd_link_info *, bfd_vma, bfd_vma));
 extern boolean bfd_elf32_link_create_dynamic_sections
   PARAMS ((bfd *, struct bfd_link_info *));
+extern Elf_Internal_Rela *_bfd_elf32_link_read_relocs
+  PARAMS ((bfd *, asection *, PTR, Elf_Internal_Rela *, boolean));
 
 extern const bfd_target *bfd_elf64_object_p PARAMS ((bfd *));
 extern const bfd_target *bfd_elf64_core_file_p PARAMS ((bfd *));
@@ -876,6 +886,8 @@ extern boolean bfd_elf64_add_dynamic_entry
   PARAMS ((struct bfd_link_info *, bfd_vma, bfd_vma));
 extern boolean bfd_elf64_link_create_dynamic_sections
   PARAMS ((bfd *, struct bfd_link_info *));
+extern Elf_Internal_Rela *_bfd_elf64_link_read_relocs
+  PARAMS ((bfd *, asection *, PTR, Elf_Internal_Rela *, boolean));
 
 #define bfd_elf32_link_record_dynamic_symbol _bfd_elf_link_record_dynamic_symbol
 #define bfd_elf64_link_record_dynamic_symbol _bfd_elf_link_record_dynamic_symbol
@@ -895,5 +907,23 @@ extern void _bfd_mips_elf_symbol_processing PARAMS ((bfd *, asymbol *));
 extern boolean _bfd_mips_elf_read_ecoff_info
   PARAMS ((bfd *, asection *, struct ecoff_debug_info *));
 extern void _bfd_mips_elf_final_write_processing PARAMS ((bfd *, boolean));
+extern bfd_reloc_status_type _bfd_mips_elf_hi16_reloc
+  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+extern bfd_reloc_status_type _bfd_mips_elf_lo16_reloc
+  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+extern bfd_reloc_status_type _bfd_mips_elf_gprel16_reloc
+  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+extern bfd_reloc_status_type _bfd_mips_elf_got16_reloc
+  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+extern bfd_reloc_status_type _bfd_mips_elf_gprel32_reloc
+  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+extern boolean _bfd_mips_elf_set_private_flags PARAMS ((bfd *, flagword));
+extern boolean _bfd_mips_elf_copy_private_bfd_data PARAMS ((bfd *, bfd *));
+extern boolean _bfd_mips_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *));
+extern boolean _bfd_mips_elf_find_nearest_line
+  PARAMS ((bfd *, asection *, asymbol **, bfd_vma, const char **,
+          const char **, unsigned int *));
+extern boolean _bfd_mips_elf_set_section_contents
+  PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
 
 #endif /* _LIBELF_H_ */
index 73c60d311791697f0f34a5c6072fd8845cc105eb..94d953f5a9fd9e0bc658159135d0d8eba780762a 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -868,6 +868,7 @@ bfd_section_from_shdr (abfd, shindex)
            if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
              return false;
            if (hdr->bfd_section != NULL
+               && hdr->sh_info > 0
                && bfd_section_from_shdr (abfd, hdr->sh_info))
              {
                target_sect = bfd_section_from_elf_index (abfd, hdr->sh_info);
@@ -3249,7 +3250,10 @@ _bfd_elf_canonicalize_reloc (abfd, section, relptr, symbols)
   arelent *tblptr;
   unsigned int i;
 
-  if (! get_elf_backend_data (abfd)->s->slurp_reloc_table (abfd, section, symbols))
+  if (! get_elf_backend_data (abfd)->s->slurp_reloc_table (abfd,
+                                                          section,
+                                                          symbols,
+                                                          false))
     return -1;
 
   tblptr = section->relocation;
@@ -3281,6 +3285,86 @@ _bfd_elf_canonicalize_dynamic_symtab (abfd, alocation)
   return get_elf_backend_data (abfd)->s->slurp_symbol_table (abfd, alocation, true);
 }
 
+/* Return the size required for the dynamic reloc entries.  Any
+   section that was actually installed in the BFD, and has type
+   SHT_REL or SHT_RELA, and uses the dynamic symbol table, is
+   considered to be a dynamic reloc section.  */
+
+long
+_bfd_elf_get_dynamic_reloc_upper_bound (abfd)
+     bfd *abfd;
+{
+  long ret;
+  asection *s;
+
+  if (elf_dynsymtab (abfd) == 0)
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return -1;
+    }
+
+  ret = sizeof (arelent *);
+  for (s = abfd->sections; s != NULL; s = s->next)
+    if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
+       && (elf_section_data (s)->this_hdr.sh_type == SHT_REL
+           || elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
+      ret += ((s->_raw_size / elf_section_data (s)->this_hdr.sh_entsize)
+             * sizeof (arelent *));
+
+  return ret;
+}
+
+/* Canonicalize the dynamic relocation entries.  Note that we return
+   the dynamic relocations as a single block, although they are
+   actually associated with particular sections; the interface, which
+   was designed for SunOS style shared libraries, expects that there
+   is only one set of dynamic relocs.  Any section that was actually
+   installed in the BFD, and has type SHT_REL or SHT_RELA, and uses
+   the dynamic symbol table, is considered to be a dynamic reloc
+   section.  */
+
+long
+_bfd_elf_canonicalize_dynamic_reloc (abfd, storage, syms)
+     bfd *abfd;
+     arelent **storage;
+     asymbol **syms;
+{
+  boolean (*slurp_relocs) PARAMS ((bfd *, asection *, asymbol **, boolean));
+  asection *s;
+  long ret;
+
+  if (elf_dynsymtab (abfd) == 0)
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return -1;
+    }
+
+  slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table;
+  ret = 0;
+  for (s = abfd->sections; s != NULL; s = s->next)
+    {
+      if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
+         && (elf_section_data (s)->this_hdr.sh_type == SHT_REL
+             || elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
+       {
+         arelent *p;
+         long count, i;
+
+         if (! (*slurp_relocs) (abfd, s, syms, true))
+           return -1;
+         count = s->_raw_size / elf_section_data (s)->this_hdr.sh_entsize;
+         p = s->relocation;
+         for (i = 0; i < count; i++)
+           *storage++ = p++;
+         ret += count;
+       }
+    }
+
+  *storage = NULL;
+
+  return ret;
+}
+
 asymbol *
 _bfd_elf_make_empty_symbol (abfd)
      bfd *abfd;
index ff0b0f242ff78be2d1ecc5f0e2b65a225188b8d2..30ea6a767379e94fe49337d3f8fd5caf79afde6d 100644 (file)
@@ -22,11 +22,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
    The MIPS 64-bit ELF ABI uses an unusual reloc format.  This file
    overrides the usual ELF reloc handling, and handles reading and
-   writing the relocations here.  */
+   writing the relocations here.
+
+   The MIPS 64-bit ELF ABI also uses an unusual archive map format.  */
 
 #include "bfd.h"
 #include "sysdep.h"
 #include "libbfd.h"
+#include "aout/ar.h"
 #include "bfdlink.h"
 #include "genlink.h"
 #include "elf-bfd.h"
@@ -69,6 +72,9 @@ 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));
 
 /* The relocation types.  */
 
@@ -1537,13 +1543,20 @@ mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, rel_hdr)
    associated with a single data section.  */
 
 static boolean
-mips_elf64_slurp_reloc_table (abfd, asect, symbols)
+mips_elf64_slurp_reloc_table (abfd, asect, symbols, dynamic)
      bfd *abfd;
      asection *asect;
      asymbol **symbols;
+     boolean dynamic;
 {
   struct bfd_elf_section_data * const d = elf_section_data (asect);
 
+  if (dynamic)
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return false;
+    }
+
   if (asect->relocation != NULL
       || (asect->flags & SEC_RELOC) == 0
       || asect->reloc_count == 0)
@@ -1720,47 +1733,6 @@ mips_elf64_write_relocs (abfd, sec, data)
              == count);
 }
 \f
-/* The .MIPS.options section holds register information in an
-   Elf64_Reginfo structure.  These routines swap them in and out.
-   They are globally visible because they are used outside of BFD.  */
-
-void
-bfd_mips_elf64_swap_reginfo_in (abfd, ex, in)
-     bfd *abfd;
-     const Elf64_External_RegInfo *ex;
-     Elf64_Internal_RegInfo *in;
-{
-  in->ri_gprmask = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_gprmask);
-  in->ri_pad = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_pad);
-  in->ri_cprmask[0] = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_cprmask[0]);
-  in->ri_cprmask[1] = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_cprmask[1]);
-  in->ri_cprmask[2] = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_cprmask[2]);
-  in->ri_cprmask[3] = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_cprmask[3]);
-  in->ri_gp_value = bfd_h_get_64 (abfd, (bfd_byte *) ex->ri_gp_value);
-}
-
-void
-bfd_mips_elf64_swap_reginfo_out (abfd, in, ex)
-     bfd *abfd;
-     const Elf64_Internal_RegInfo *in;
-     Elf64_External_RegInfo *ex;
-{
-  bfd_h_put_32 (abfd, (bfd_vma) in->ri_gprmask,
-               (bfd_byte *) ex->ri_gprmask);
-  bfd_h_put_32 (abfd, (bfd_vma) in->ri_pad,
-               (bfd_byte *) ex->ri_pad);
-  bfd_h_put_32 (abfd, (bfd_vma) in->ri_cprmask[0],
-               (bfd_byte *) ex->ri_cprmask[0]);
-  bfd_h_put_32 (abfd, (bfd_vma) in->ri_cprmask[1],
-               (bfd_byte *) ex->ri_cprmask[1]);
-  bfd_h_put_32 (abfd, (bfd_vma) in->ri_cprmask[2],
-               (bfd_byte *) ex->ri_cprmask[2]);
-  bfd_h_put_32 (abfd, (bfd_vma) in->ri_cprmask[3],
-               (bfd_byte *) ex->ri_cprmask[3]);
-  bfd_h_put_64 (abfd, (bfd_vma) in->ri_gp_value,
-               (bfd_byte *) ex->ri_gp_value);
-}
-
 /* Handle a 64-bit MIPS ELF specific section.  */
 
 static boolean
@@ -1870,6 +1842,215 @@ mips_elf64_section_processing (abfd, hdr)
   return _bfd_mips_elf_section_processing (abfd, hdr);
 }
 \f
+/* Irix 6 defines a brand new archive map format, so that they can
+   have archives more than 4 GB in size.  */
+
+/* Read an Irix 6 armap.  */
+
+static boolean
+mips_elf64_slurp_armap (abfd)
+     bfd *abfd;
+{
+  struct artdata *ardata = bfd_ardata (abfd);
+  char nextname[17];
+  file_ptr arhdrpos;
+  bfd_size_type i, parsed_size, nsymz, stringsize, carsym_size, ptrsize;
+  struct areltdata *mapdata;
+  bfd_byte int_buf[8];
+  char *stringbase;
+  bfd_byte *raw_armap = NULL;
+  carsym *carsyms;
+
+  ardata->symdefs = NULL;
+
+  /* Get the name of the first element.  */
+  arhdrpos = bfd_tell (abfd);
+  i = bfd_read ((PTR) nextname, 1, 16, abfd);
+  if (i == 0)
+    return true;
+  if (i != 16)
+    return false;
+
+  if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) != 0)
+    return false;
+
+  /* Archives with traditional armaps are still permitted.  */
+  if (strncmp (nextname, "/               ", 16) == 0)
+    return bfd_slurp_armap (abfd);
+
+  if (strncmp (nextname, "/SYM64/         ", 16) != 0)
+    {
+      bfd_has_map (abfd) = false;
+      return true;
+    }
+
+  mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
+  if (mapdata == NULL)
+    return false;
+  parsed_size = mapdata->parsed_size;
+  bfd_release (abfd, (PTR) mapdata);
+
+  if (bfd_read (int_buf, 1, 8, abfd) != 8)
+    {
+      if (bfd_get_error () != bfd_error_system_call)
+       bfd_set_error (bfd_error_malformed_archive);
+      return false;
+    }
+
+  nsymz = bfd_getb64 (int_buf);
+  stringsize = parsed_size - 8 * nsymz - 8;
+
+  carsym_size = nsymz * sizeof (carsym);
+  ptrsize = 8 * nsymz;
+
+  ardata->symdefs = (carsym *) bfd_zalloc (abfd, carsym_size + stringsize + 1);
+  if (ardata->symdefs == NULL)
+    return false;
+  carsyms = ardata->symdefs;
+  stringbase = ((char *) ardata->symdefs) + carsym_size;
+
+  raw_armap = (bfd_byte *) bfd_alloc (abfd, ptrsize);
+  if (raw_armap == NULL)
+    goto error_return;
+
+  if (bfd_read (raw_armap, 1, ptrsize, abfd) != ptrsize
+      || bfd_read (stringbase, 1, stringsize, abfd) != stringsize)
+    {
+      if (bfd_get_error () != bfd_error_system_call)
+       bfd_set_error (bfd_error_malformed_archive);
+      goto error_return;
+    }
+
+  for (i = 0; i < nsymz; i++)
+    {
+      carsyms->file_offset = bfd_getb64 (raw_armap + i * 8);
+      carsyms->name = stringbase;
+      stringbase += strlen (stringbase) + 1;
+      ++carsyms;
+    }
+  *stringbase = '\0';
+
+  ardata->symdef_count = nsymz;
+  ardata->first_file_filepos = arhdrpos + sizeof (struct ar_hdr) + parsed_size;
+
+  bfd_has_map (abfd) = true;
+  bfd_release (abfd, raw_armap);
+
+  return true;
+
+ error_return:
+  if (raw_armap != NULL)
+    bfd_release (abfd, raw_armap);
+  if (ardata->symdefs != NULL)
+    bfd_release (abfd, ardata->symdefs);
+  return false;
+}
+
+/* Write out an Irix 6 armap.  The Irix 6 tools are supposed to be
+   able to handle ordinary ELF armaps, but at least on Irix 6.2 the
+   linker crashes.  */
+
+static boolean
+mips_elf64_write_armap (arch, elength, map, symbol_count, stridx)
+     bfd *arch;
+     unsigned int elength;
+     struct orl *map;
+     unsigned int symbol_count;
+     int stridx;
+{
+  unsigned int ranlibsize = (symbol_count * 8) + 8;
+  unsigned int stringsize = stridx;
+  unsigned int mapsize = stringsize + ranlibsize;
+  file_ptr archive_member_file_ptr;
+  bfd *current = arch->archive_head;
+  unsigned int count;
+  struct ar_hdr hdr;
+  unsigned int i;
+  int padding;
+  bfd_byte buf[8];
+
+  padding = BFD_ALIGN (mapsize, 8) - mapsize;
+  mapsize += padding;
+
+  /* work out where the first object file will go in the archive */
+  archive_member_file_ptr = (mapsize
+                            + elength
+                            + sizeof (struct ar_hdr)
+                            + SARMAG);
+
+  memset ((char *) (&hdr), 0, sizeof (struct ar_hdr));
+  strcpy (hdr.ar_name, "/SYM64/");
+  sprintf (hdr.ar_size, "%-10d", (int) mapsize);
+  sprintf (hdr.ar_date, "%ld", (long) time (NULL));
+  /* This, at least, is what Intel coff sets the values to.: */
+  sprintf ((hdr.ar_uid), "%d", 0);
+  sprintf ((hdr.ar_gid), "%d", 0);
+  sprintf ((hdr.ar_mode), "%-7o", (unsigned) 0);
+  strncpy (hdr.ar_fmag, ARFMAG, 2);
+
+  for (i = 0; i < sizeof (struct ar_hdr); i++)
+    if (((char *) (&hdr))[i] == '\0')
+      (((char *) (&hdr))[i]) = ' ';
+
+  /* Write the ar header for this item and the number of symbols */
+
+  if (bfd_write ((PTR) &hdr, 1, sizeof (struct ar_hdr), arch)
+      != sizeof (struct ar_hdr))
+    return false;
+
+  bfd_putb64 (symbol_count, buf);
+  if (bfd_write (buf, 1, 8, arch) != 8)
+    return false;
+
+  /* Two passes, first write the file offsets for each symbol -
+     remembering that each offset is on a two byte boundary.  */
+
+  /* Write out the file offset for the file associated with each
+     symbol, and remember to keep the offsets padded out.  */
+
+  current = arch->archive_head;
+  count = 0;
+  while (current != (bfd *) NULL && count < symbol_count)
+    {
+      /* For each symbol which is used defined in this object, write out
+        the object file's address in the archive */
+
+      while (((bfd *) (map[count]).pos) == current)
+       {
+         bfd_putb64 (archive_member_file_ptr, buf);
+         if (bfd_write (buf, 1, 8, arch) != 8)
+           return false;
+         count++;
+       }
+      /* Add size of this archive entry */
+      archive_member_file_ptr += (arelt_size (current)
+                                 + sizeof (struct ar_hdr));
+      /* remember about the even alignment */
+      archive_member_file_ptr += archive_member_file_ptr % 2;
+      current = current->next;
+    }
+
+  /* now write the strings themselves */
+  for (count = 0; count < symbol_count; count++)
+    {
+      size_t len = strlen (*map[count].name) + 1;
+
+      if (bfd_write (*map[count].name, 1, len, arch) != len)
+       return false;
+    }
+
+  /* The spec says that this should be padded to an 8 byte boundary.
+     However, the Irix 6.2 tools do not appear to do this.  */
+  while (padding != 0)
+    {
+      if (bfd_write ("", 1, 1, arch) != 1)
+       return false;
+      --padding;
+    }
+
+  return true;
+}
+\f
 /* ECOFF swapping routines.  These are used when dealing with the
    .mdebug section, which is in the ECOFF debugging format.  */
 static const struct ecoff_debug_swap mips_elf64_ecoff_debug_swap =
@@ -1969,4 +2150,23 @@ const struct elf_size_info mips_elf64_size_info =
                                        _bfd_mips_elf_merge_private_bfd_data
 #define bfd_elf64_bfd_set_private_flags        _bfd_mips_elf_set_private_flags
 
+#define bfd_elf64_archive_functions
+#define bfd_elf64_archive_slurp_armap  mips_elf64_slurp_armap
+#define bfd_elf64_archive_slurp_extended_name_table \
+                               _bfd_archive_coff_slurp_extended_name_table
+#define bfd_elf64_archive_construct_extended_name_table \
+                               _bfd_archive_coff_construct_extended_name_table
+#define bfd_elf64_archive_truncate_arname \
+                                       _bfd_archive_coff_truncate_arname
+#define bfd_elf64_archive_write_armap  mips_elf64_write_armap
+#define bfd_elf64_archive_read_ar_hdr  _bfd_archive_coff_read_ar_hdr
+#define bfd_elf64_archive_openr_next_archived_file \
+                               _bfd_archive_coff_openr_next_archived_file
+#define bfd_elf64_archive_get_elt_at_index \
+                                       _bfd_archive_coff_get_elt_at_index
+#define bfd_elf64_archive_generic_stat_arch_elt \
+                                       _bfd_archive_coff_generic_stat_arch_elt
+#define bfd_elf64_archive_update_armap_timestamp \
+                               _bfd_archive_coff_update_armap_timestamp
+
 #include "elf64-target.h"
index 405e79f6ce8970bb00cc7e1de800bd181b48c1b5..87e02f2523604e61e8d3ed29f97f9a0451f4de7e 100644 (file)
@@ -154,21 +154,13 @@ static void elf_swap_shdr_out
 
 #define elf_stringtab_init _bfd_elf_stringtab_init
 
-extern struct bfd_strtab_hash *_bfd_elf_stringtab_init PARAMS ((void));
 #define section_from_elf_index bfd_section_from_elf_index
-extern boolean bfd_section_from_phdr PARAMS ((bfd *, Elf_Internal_Phdr *,
-                                             int));
 
-static boolean elf_slurp_reloc_table PARAMS ((bfd *, asection *, asymbol **));
+static boolean elf_slurp_reloc_table
+  PARAMS ((bfd *, asection *, asymbol **, boolean));
 
- int _bfd_elf_symbol_from_bfd_symbol PARAMS ((bfd *,
-                                            struct symbol_cache_entry **));
-
-static boolean validate_reloc PARAMS ((bfd *, arelent *));
 static void write_relocs PARAMS ((bfd *, asection *, PTR));
 
- boolean bfd_section_from_shdr PARAMS ((bfd *, unsigned int shindex));
-
 #ifdef DEBUG
 static void elf_debug_section PARAMS ((int, Elf_Internal_Shdr *));
 static void elf_debug_file PARAMS ((Elf_Internal_Ehdr *));
@@ -594,6 +586,15 @@ elf_object_p (abfd)
        goto got_no_match;
       elf_swap_shdr_in (abfd, &x_shdr, i_shdrp + shindex);
       elf_elfsections (abfd)[shindex] = i_shdrp + shindex;
+
+      /* If the section is loaded, but not page aligned, clear
+         D_PAGED.  */
+      if ((i_shdrp[shindex].sh_flags & SHF_ALLOC) != 0
+         && i_shdrp[shindex].sh_type != SHT_NOBITS
+         && (((i_shdrp[shindex].sh_addr - i_shdrp[shindex].sh_offset)
+              % ebd->maxpagesize)
+             != 0))
+       abfd->flags &= ~D_PAGED;
     }
   if (i_ehdrp->e_shstrndx)
     {
@@ -676,104 +677,6 @@ got_no_match:
 \f
 /* ELF .o/exec file writing */
 
-/* Try to convert a non-ELF reloc into an ELF one.  */
-
-static boolean
-validate_reloc (abfd, areloc)
-     bfd *abfd;
-     arelent *areloc;
-{
-  /* Check whether we really have an ELF howto. */
-
-  if ((*areloc->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec) 
-    {
-      bfd_reloc_code_real_type code;
-      reloc_howto_type *howto;
-      
-      /* Alien reloc: Try to determine its type to replace it with an
-        equivalent ELF reloc. */
-
-      if (areloc->howto->pc_relative)
-       {
-         switch (areloc->howto->bitsize)
-           {
-           case 8:
-             code = BFD_RELOC_8_PCREL; 
-             break;
-           case 12:
-             code = BFD_RELOC_12_PCREL; 
-             break;
-           case 16:
-             code = BFD_RELOC_16_PCREL; 
-             break;
-           case 24:
-             code = BFD_RELOC_24_PCREL; 
-             break;
-           case 32:
-             code = BFD_RELOC_32_PCREL; 
-             break;
-           case 64:
-             code = BFD_RELOC_64_PCREL; 
-             break;
-           default:
-             goto fail;
-           }
-
-         howto = bfd_reloc_type_lookup (abfd, code);
-
-         if (areloc->howto->pcrel_offset != howto->pcrel_offset)
-           {
-             if (howto->pcrel_offset)
-               areloc->addend += areloc->address;
-             else
-               areloc->addend -= areloc->address; /* addend is unsigned!! */
-           }
-       }
-      else
-       {
-         switch (areloc->howto->bitsize)
-           {
-           case 8:
-             code = BFD_RELOC_8; 
-             break;
-           case 14:
-             code = BFD_RELOC_14; 
-             break;
-           case 16:
-             code = BFD_RELOC_16; 
-             break;
-           case 26:
-             code = BFD_RELOC_26; 
-             break;
-           case 32:
-             code = BFD_RELOC_32; 
-             break;
-           case 64:
-             code = BFD_RELOC_64; 
-             break;
-           default:
-             goto fail;
-           }
-
-         howto = bfd_reloc_type_lookup (abfd, code);
-       }
-
-      if (howto)
-       areloc->howto = howto;
-      else
-       goto fail;
-    }
-
-  return true;
-
- fail:
-  (*_bfd_error_handler)
-    ("%s: unsupported relocation type %s",
-     bfd_get_filename (abfd), areloc->howto->name);
-  bfd_set_error (bfd_error_bad_value);
-  return false;
-}
-
 /* Write out the relocs.  */
 
 static void
@@ -842,6 +745,8 @@ write_relocs (abfd, sec, data)
          sym = *ptr->sym_ptr_ptr;
          if (sym == last_sym)
            n = last_sym_idx;
+         else if (bfd_is_abs_section (sym->section) && sym->value == 0)
+           n = STN_UNDEF;
          else
            {
              last_sym = sym;
@@ -854,8 +759,9 @@ write_relocs (abfd, sec, data)
              last_sym_idx = n;
            }
 
-         if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
-             && ! validate_reloc (abfd, ptr))
+         if ((*ptr->sym_ptr_ptr)->the_bfd != NULL
+             && (*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
+             && ! _bfd_elf_validate_reloc (abfd, ptr))
            {
              *failedp = true;
              return;
@@ -907,7 +813,7 @@ write_relocs (abfd, sec, data)
            }
 
          if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
-             && ! validate_reloc (abfd, ptr))
+             && ! _bfd_elf_validate_reloc (abfd, ptr))
            {
              *failedp = true;
              return;
@@ -1177,13 +1083,16 @@ error_return:
 /* Read in and swap the external relocs.  */
 
 static boolean
-elf_slurp_reloc_table (abfd, asect, symbols)
+elf_slurp_reloc_table (abfd, asect, symbols, dynamic)
      bfd *abfd;
      asection *asect;
      asymbol **symbols;
+     boolean dynamic;
 {
   struct elf_backend_data * const ebd = get_elf_backend_data (abfd);
   struct bfd_elf_section_data * const d = elf_section_data (asect);
+  Elf_Internal_Shdr *rel_hdr;
+  bfd_size_type reloc_count;
   PTR allocated = NULL;
   bfd_byte *native_relocs;
   arelent *relents;
@@ -1191,37 +1100,51 @@ elf_slurp_reloc_table (abfd, asect, symbols)
   unsigned int i;
   int entsize;
 
-  if (asect->relocation != NULL
-      || (asect->flags & SEC_RELOC) == 0
-      || asect->reloc_count == 0)
+  if (asect->relocation != NULL)
     return true;
 
-  BFD_ASSERT (asect->rel_filepos == d->rel_hdr.sh_offset
-             && (asect->reloc_count
-                 == d->rel_hdr.sh_size / d->rel_hdr.sh_entsize));
+  if (! dynamic)
+    {
+      if ((asect->flags & SEC_RELOC) == 0
+         || asect->reloc_count == 0)
+       return true;
+
+      rel_hdr = &d->rel_hdr;
+      reloc_count = asect->reloc_count;
+
+      BFD_ASSERT (asect->rel_filepos == rel_hdr->sh_offset
+                 && reloc_count == rel_hdr->sh_size / rel_hdr->sh_entsize);
+    }
+  else
+    {
+      if (asect->_raw_size == 0)
+       return true;
+
+      rel_hdr = &d->this_hdr;
+      reloc_count = rel_hdr->sh_size / rel_hdr->sh_entsize;
+    }
 
-  allocated = (PTR) bfd_malloc ((size_t) d->rel_hdr.sh_size);
+  allocated = (PTR) bfd_malloc ((size_t) rel_hdr->sh_size);
   if (allocated == NULL)
     goto error_return;
 
-  if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0
-      || (bfd_read (allocated, 1, d->rel_hdr.sh_size, abfd)
-         != d->rel_hdr.sh_size))
+  if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0
+      || (bfd_read (allocated, 1, rel_hdr->sh_size, abfd)
+         != rel_hdr->sh_size))
     goto error_return;
 
   native_relocs = (bfd_byte *) allocated;
 
-  relents = ((arelent *)
-            bfd_alloc (abfd, asect->reloc_count * sizeof (arelent)));
+  relents = (arelent *) bfd_alloc (abfd, reloc_count * sizeof (arelent));
   if (relents == NULL)
     goto error_return;
 
-  entsize = d->rel_hdr.sh_entsize;
+  entsize = rel_hdr->sh_entsize;
   BFD_ASSERT (entsize == sizeof (Elf_External_Rel)
              || entsize == sizeof (Elf_External_Rela));
 
   for (i = 0, relent = relents;
-       i < asect->reloc_count;
+       i < reloc_count;
        i++, relent++, native_relocs += entsize)
     {
       Elf_Internal_Rela rela;
@@ -1239,8 +1162,9 @@ elf_slurp_reloc_table (abfd, asect, symbols)
 
       /* The address of an ELF reloc is section relative for an object
         file, and absolute for an executable file or shared library.
-        The address of a BFD reloc is always section relative.  */
-      if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+        The address of a normal BFD reloc is always section relative,
+        and the address of a dynamic reloc is absolute..  */
+      if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0 || dynamic)
        relent->address = rela.r_offset;
       else
        relent->address = rela.r_offset - asect->vma;
index b4e68ecc2bef2d814c11cdf6e498ab8c808a439f..291e3c9459300c73839bff573ff859bf6c39ca68 100644 (file)
@@ -40,7 +40,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define bfd_elfNN_minisymbol_to_symbol _bfd_elf_minisymbol_to_symbol
 #define bfd_elfNN_get_dynamic_symtab_upper_bound _bfd_elf_get_dynamic_symtab_upper_bound
 #define bfd_elfNN_get_lineno           _bfd_elf_get_lineno
+#ifndef bfd_elfNN_get_reloc_upper_bound
 #define bfd_elfNN_get_reloc_upper_bound _bfd_elf_get_reloc_upper_bound
+#endif
 #define bfd_elfNN_get_symbol_info      _bfd_elf_get_symbol_info
 #define bfd_elfNN_get_symtab           _bfd_elf_get_symtab
 #define bfd_elfNN_get_symtab_upper_bound _bfd_elf_get_symtab_upper_bound
@@ -78,7 +80,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
  bfd_generic_get_relocated_section_contents
 #endif
 
+#ifndef bfd_elfNN_bfd_relax_section
 #define bfd_elfNN_bfd_relax_section bfd_generic_relax_section
+#endif
+
 #define bfd_elfNN_bfd_make_debug_symbol \
   ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr)
 
@@ -113,11 +118,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #ifndef bfd_elfNN_get_dynamic_reloc_upper_bound
 #define bfd_elfNN_get_dynamic_reloc_upper_bound \
-  _bfd_nodynamic_get_dynamic_reloc_upper_bound
+  _bfd_elf_get_dynamic_reloc_upper_bound
 #endif
 #ifndef bfd_elfNN_canonicalize_dynamic_reloc
 #define bfd_elfNN_canonicalize_dynamic_reloc \
-  _bfd_nodynamic_canonicalize_dynamic_reloc
+  _bfd_elf_canonicalize_dynamic_reloc
 #endif
 
 #ifdef elf_backend_relocate_section
@@ -141,6 +146,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define bfd_elfNN_bfd_link_split_section _bfd_generic_link_split_section
 #endif
 
+#ifndef bfd_elfNN_archive_p
+#define bfd_elfNN_archive_p bfd_generic_archive_p
+#endif
+
+#ifndef bfd_elfNN_write_archive_contents
+#define bfd_elfNN_write_archive_contents _bfd_write_archive_contents
+#endif
+
+#ifndef bfd_elfNN_mkarchive
+#define bfd_elfNN_mkarchive _bfd_generic_mkarchive
+#endif
+
 #ifndef elf_symbol_leading_char
 #define elf_symbol_leading_char 0
 #endif
@@ -340,28 +357,32 @@ const bfd_target TARGET_BIG_SYM =
   /* bfd_check_format: check the format of a file being read */
   { _bfd_dummy_target,         /* unknown format */
     bfd_elfNN_object_p,                /* assembler/linker output (object file) */
-    bfd_generic_archive_p,     /* an archive */
+    bfd_elfNN_archive_p,       /* an archive */
     bfd_elfNN_core_file_p      /* a core file */
   },
 
   /* bfd_set_format: set the format of a file being written */
   { bfd_false,
     bfd_elf_mkobject,
-    _bfd_generic_mkarchive,
+    bfd_elfNN_mkarchive,
     bfd_false
   },
 
   /* bfd_write_contents: write cached information into a file being written */
   { bfd_false,
     bfd_elfNN_write_object_contents,
-    _bfd_write_archive_contents,
+    bfd_elfNN_write_archive_contents,
     bfd_false
   },
 
       BFD_JUMP_TABLE_GENERIC (bfd_elfNN),
       BFD_JUMP_TABLE_COPY (bfd_elfNN),
       BFD_JUMP_TABLE_CORE (bfd_elfNN),
+#ifdef bfd_elfNN_archive_functions
+      BFD_JUMP_TABLE_ARCHIVE (bfd_elfNN_archive),
+#else
       BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+#endif
       BFD_JUMP_TABLE_SYMBOLS (bfd_elfNN),
       BFD_JUMP_TABLE_RELOCS (bfd_elfNN),
       BFD_JUMP_TABLE_WRITE (bfd_elfNN),
@@ -424,28 +445,32 @@ const bfd_target TARGET_LITTLE_SYM =
   /* bfd_check_format: check the format of a file being read */
   { _bfd_dummy_target,         /* unknown format */
     bfd_elfNN_object_p,                /* assembler/linker output (object file) */
-    bfd_generic_archive_p,     /* an archive */
+    bfd_elfNN_archive_p,       /* an archive */
     bfd_elfNN_core_file_p      /* a core file */
   },
 
   /* bfd_set_format: set the format of a file being written */
   { bfd_false,
     bfd_elf_mkobject,
-    _bfd_generic_mkarchive,
+    bfd_elfNN_mkarchive,
     bfd_false
   },
 
   /* bfd_write_contents: write cached information into a file being written */
   { bfd_false,
     bfd_elfNN_write_object_contents,
-    _bfd_write_archive_contents,
+    bfd_elfNN_write_archive_contents,
     bfd_false
   },
 
       BFD_JUMP_TABLE_GENERIC (bfd_elfNN),
       BFD_JUMP_TABLE_COPY (bfd_elfNN),
       BFD_JUMP_TABLE_CORE (bfd_elfNN),
+#ifdef bfd_elfNN_archive_functions
+      BFD_JUMP_TABLE_ARCHIVE (bfd_elfNN_archive),
+#else
       BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+#endif
       BFD_JUMP_TABLE_SYMBOLS (bfd_elfNN),
       BFD_JUMP_TABLE_RELOCS (bfd_elfNN),
       BFD_JUMP_TABLE_WRITE (bfd_elfNN),