* elf32-i386.c (elf_i386_relocate_section): If -Bsymbolic, when
authorIan Lance Taylor <ian@airs.com>
Mon, 29 Jan 1996 20:01:29 +0000 (20:01 +0000)
committerIan Lance Taylor <ian@airs.com>
Mon, 29 Jan 1996 20:01:29 +0000 (20:01 +0000)
copying relocs into a shared object, treat a defined global symbol
as a local symbol.
* elf32-m68k.c (elf_m68k_relocate_section): Likewise.
* elf32-mips.c (mips_elf_relocate_section): Likewise.
* elf32-sparc.c (elf32_sparc_relocate_section): Likewise.

bfd/ChangeLog
bfd/elf32-i386.c
bfd/elf32-m68k.c
bfd/elf32-mips.c
bfd/elf32-sparc.c

index cd48dd65546861b1cc37a4542472fa91d4277574..f18d32e568ef8f249c5781f659e1ac43fa5a24a0 100644 (file)
@@ -7,6 +7,13 @@ Mon Jan 29 14:27:24 1996  Kim Knuttila  <krk@cygnus.com>
 
 Mon Jan 29 13:06:28 1996  Ian Lance Taylor  <ian@cygnus.com>
 
+       * elf32-i386.c (elf_i386_relocate_section): If -Bsymbolic, when
+       copying relocs into a shared object, treat a defined global symbol
+       as a local symbol.
+       * elf32-m68k.c (elf_m68k_relocate_section): Likewise.
+       * elf32-mips.c (mips_elf_relocate_section): Likewise.
+       * elf32-sparc.c (elf32_sparc_relocate_section): Likewise.
+
        * elflink.h (elf_link_add_object_symbols): Only set weakdef to a
        real defined symbol, not to a weak defined symbol.
 
index 82f0ccded01dca3a86c74d2df0c0d342b34d344c..cb2a3dc75dc00a57bfee36708f4bcae4dfc6bf4f 100644 (file)
@@ -1,5 +1,5 @@
 /* Intel 80386/80486-specific support for 32-bit ELF
-   Copyright 1993, 1994, 1995 Free Software Foundation, Inc.
+   Copyright 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -916,6 +916,9 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
                          || (h->elf_link_hash_flags
                              & ELF_LINK_HASH_DEF_REGULAR) == 0))
                  || (info->shared
+                     && (! info->symbolic
+                         || (h->elf_link_hash_flags
+                             & ELF_LINK_HASH_DEF_REGULAR) == 0)
                      && (r_type == R_386_32
                          || r_type == R_386_PC32)
                      && (input_section->flags & SEC_ALLOC) != 0))
@@ -1100,9 +1103,14 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
        case R_386_PC32:
          if (info->shared
              && (input_section->flags & SEC_ALLOC) != 0
-             && (r_type != R_386_PC32 || h != NULL))
+             && (r_type != R_386_PC32
+                 || (h != NULL
+                     && (! info->symbolic
+                         || (h->elf_link_hash_flags
+                             & ELF_LINK_HASH_DEF_REGULAR) == 0))))
            {
              Elf_Internal_Rel outrel;
+             boolean relocate;
 
              /* When generating a shared object, these relocations
                 are copied into the output file to be resolved at run
@@ -1134,15 +1142,23 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
              if (r_type == R_386_PC32)
                {
                  BFD_ASSERT (h != NULL && h->dynindx != -1);
+                 relocate = false;
                  outrel.r_info = ELF32_R_INFO (h->dynindx, R_386_PC32);
                }
              else
                {
-                 if (h == NULL)
-                   outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
+                 if (h == NULL
+                     || (info->symbolic
+                         && (h->elf_link_hash_flags
+                             & ELF_LINK_HASH_DEF_REGULAR) != 0))
+                   {
+                     relocate = true;
+                     outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
+                   }
                  else
                    {
                      BFD_ASSERT (h->dynindx != -1);
+                     relocate = false;
                      outrel.r_info = ELF32_R_INFO (h->dynindx, R_386_32);
                    }
                }
@@ -1157,7 +1173,7 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
                 not want to fiddle with the addend.  Otherwise, we
                 need to include the symbol value so that it becomes
                 an addend for the dynamic reloc.  */
-             if (h != NULL)
+             if (! relocate)
                continue;
            }
 
index 35d6c097b247cc754c5b438e1019c8f72e56ded6..d712569d3918d489541a40dd392298c5ae9bde65 100644 (file)
@@ -1,5 +1,5 @@
 /* Motorola 68k series support for 32-bit ELF
-   Copyright 1993 Free Software Foundation, Inc.
+   Copyright 1993, 1995, 1996 Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -898,6 +898,9 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
                          || (h->elf_link_hash_flags
                              & ELF_LINK_HASH_DEF_REGULAR) == 0))
                  || (info->shared
+                     && (! info->symbolic
+                         || (h->elf_link_hash_flags
+                             & ELF_LINK_HASH_DEF_REGULAR) == 0)
                      && (input_section->flags & SEC_ALLOC) != 0
                      && (r_type == R_68K_8
                          || r_type == R_68K_16
@@ -1142,7 +1145,10 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
              outrel.r_offset = (rel->r_offset
                                 + input_section->output_section->vma
                                 + input_section->output_offset);
-             if (h != NULL)
+             if (h != NULL
+                 && (! info->symbolic
+                     || (h->elf_link_hash_flags
+                         & ELF_LINK_HASH_DEF_REGULAR) == 0))
                {
                  BFD_ASSERT (h->dynindx != -1);
                  outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
@@ -1159,11 +1165,15 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
                    {
                      long indx;
 
-                     sym = local_syms + r_symndx;
-
-                     BFD_ASSERT (ELF_ST_TYPE (sym->st_info) == STT_SECTION);
-
-                     sec = local_sections[r_symndx];
+                     if (h == NULL)
+                       sec = local_sections[r_symndx];
+                     else
+                       {
+                         BFD_ASSERT (h->root.type == bfd_link_hash_defined
+                                     || (h->root.type
+                                         == bfd_link_hash_defweak));
+                         sec = h->root.u.def.section;
+                       }
                      if (sec != NULL && bfd_is_abs_section (sec))
                        indx = 0;
                      else if (sec == NULL || sec->owner == NULL)
index c254ecf8d76274ba65a09c47d5634c658dc7cfdc..b6c544a99abe8d8421fdc383a5c192ca0bfcadf7 100644 (file)
@@ -80,6 +80,10 @@ static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
   PARAMS ((bfd *, bfd_reloc_code_real_type));
 static void mips_info_to_howto_rel
   PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
+static void bfd_mips_elf32_swap_gptab_in
+  PARAMS ((bfd *, const Elf32_External_gptab *, Elf32_gptab *));
+static void bfd_mips_elf32_swap_gptab_out
+  PARAMS ((bfd *, const Elf32_gptab *, Elf32_External_gptab *));
 static boolean mips_elf_sym_is_global PARAMS ((bfd *, asymbol *));
 static boolean mips_elf_object_p PARAMS ((bfd *));
 static boolean mips_elf_create_procedure_table
@@ -89,6 +93,9 @@ static int mips_elf_additional_program_headers PARAMS ((bfd *));
 static boolean mips_elf_modify_segment_map PARAMS ((bfd *));
 static void mips_elf_final_write_processing
   PARAMS ((bfd *, boolean));
+static boolean mips_elf_set_private_flags PARAMS ((bfd *, flagword));
+static boolean mips_elf_copy_private_bfd_data PARAMS ((bfd *, bfd *));
+static boolean mips_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *));
 static boolean mips_elf_section_from_shdr
   PARAMS ((bfd *, Elf32_Internal_Shdr *, char *));
 static boolean mips_elf_fake_sections
@@ -125,11 +132,32 @@ static boolean mips_elf_adjust_dynindx
 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_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_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 **));
+static bfd_byte *elf32_mips_get_relocated_section_contents
+  PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
+          bfd_byte *, boolean, asymbol **));
 
 /* This is true for Irix 5 executables, false for normal MIPS ELF ABI
    executables.  FIXME: At the moment, we default to always generating
@@ -289,6 +317,11 @@ typedef struct
 #define mips_elf_set_cr_dist2to(x,v)           ((x).dist2to = (v))
 #define mips_elf_set_cr_relvaddr(x,d)          ((x).relvaddr = (d)<<2)
 
+static void bfd_elf32_swap_compact_rel_out
+  PARAMS ((bfd *, const Elf32_compact_rel *, Elf32_External_compact_rel *));
+static void bfd_elf32_swap_crinfo_out
+  PARAMS ((bfd *, const Elf32_crinfo *, Elf32_External_crinfo *));
+
 #define USE_REL        1               /* MIPS uses REL relocations instead of RELA */
 
 enum reloc_type
@@ -1327,7 +1360,7 @@ bfd_mips_elf32_swap_gptab_out (abfd, in, ex)
 static void
 bfd_elf32_swap_compact_rel_out (abfd, in, ex)
      bfd *abfd;
-     Elf32_compact_rel *in;
+     const Elf32_compact_rel *in;
      Elf32_External_compact_rel *ex;
 {
   bfd_h_put_32 (abfd, (bfd_vma) in->id1, ex->id1);
@@ -1341,7 +1374,7 @@ bfd_elf32_swap_compact_rel_out (abfd, in, ex)
 static void
 bfd_elf32_swap_crinfo_out (abfd, in, ex)
      bfd *abfd;
-     Elf32_crinfo *in;
+     const Elf32_crinfo *in;
      Elf32_External_crinfo *ex;
 {
   unsigned long l;
@@ -1968,8 +2001,7 @@ mips_elf_additional_program_headers (abfd)
       ++ret;
     }
 
-  if (bfd_get_section_by_name (abfd, ".interp") == NULL
-      && bfd_get_section_by_name (abfd, ".dynamic") != NULL
+  if (bfd_get_section_by_name (abfd, ".dynamic") != NULL
       && bfd_get_section_by_name (abfd, ".mdebug") != NULL)
     {
       /* We need a PT_MIPS_RTPROC segment.  */
@@ -2409,6 +2441,8 @@ struct mips_elf_link_hash_table
   bfd_size_type dynsym_sec_strindex[SIZEOF_MIPS_DYNSYM_SECNAMES];
   /* The number of .rtproc entries.  */
   bfd_size_type procedure_count;
+  /* The size of the .compact_rel section (if SGI_COMPAT).  */
+  bfd_size_type compact_rel_size;
 };
 
 /* Look up an entry in a MIPS ELF linker hash table.  */
@@ -2494,6 +2528,7 @@ mips_elf_link_hash_table_create (abfd)
   for (i = 0; i < SIZEOF_MIPS_DYNSYM_SECNAMES; i++)
     ret->dynsym_sec_strindex[i] = (bfd_size_type) -1;
   ret->procedure_count = 0;
+  ret->compact_rel_size = 0;
 
   return &ret->root.root;
 }
@@ -2512,6 +2547,15 @@ mips_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
      asection **secp;
      bfd_vma *valp;
 {
+  if (SGI_COMPAT (abfd)
+      && (abfd->flags & DYNAMIC) != 0
+      && strcmp (*namep, "_rld_new_interface") == 0)
+    {
+      /* Skip Irix 5 rld entry name.  */
+      *namep = NULL;
+      return true;
+    }
+
   switch (sym->st_shndx)
     {
     case SHN_COMMON:
@@ -2549,6 +2593,8 @@ mips_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
        *secp = mips_elf_text_section_ptr;
       break;
 
+    case SHN_MIPS_ACOMMON:
+      /* Fall through. XXX Can we treat this as allocated data?  */
     case SHN_MIPS_DATA:
       /* This section is used in a shared object.  */
       if (mips_elf_data_section_ptr == NULL)
@@ -3865,7 +3911,7 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                  /* If this is HI16 or GOT16 with an associated LO16,
                     adjust the addend accordingly.  Otherwise, just
                     relocate.  */
-                 if ((r_type != R_MIPS_HI16 || r_type == R_MIPS_GOT16)
+                 if ((r_type != R_MIPS_HI16 && r_type != R_MIPS_GOT16)
                      || (rel + 1) >= relend
                      || ELF32_R_TYPE ((rel + 1)->r_info) != R_MIPS_LO16)
                    r = _bfd_relocate_contents (howto, input_bfd,
@@ -3953,6 +3999,19 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                relocation = 0;
              else if (info->shared && ! info->symbolic)
                relocation = 0;
+             else if (strcmp (h->root.root.string, "_DYNAMIC_LINK") == 0)
+               {
+                 /* If this is a dynamic link, we should have created
+                     a _DYNAMIC_LINK symbol in
+                     mips_elf_create_dynamic_sections.  Otherwise, we
+                     should define the symbol with a value of 0.
+                     FIXME: It should probably get into the symbol
+                     table somehow as well.  */
+                 BFD_ASSERT (! info->shared);
+                 BFD_ASSERT (bfd_get_section_by_name (output_bfd,
+                                                      ".dynamic") == NULL);
+                 relocation = 0;
+               }
              else
                {
                  if (! ((*info->callbacks->undefined_symbol)
@@ -4065,7 +4124,10 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
                  addend = bfd_get_32 (input_bfd, contents + rel->r_offset);
 
-                 if (h != NULL)
+                 if (h != NULL
+                     && (! info->symbolic
+                         || (h->elf_link_hash_flags
+                             & ELF_LINK_HASH_DEF_REGULAR) == 0))
                    {
                      BFD_ASSERT (h->dynindx != -1);
                      outrel.r_info = ELF32_R_INFO (h->dynindx, R_MIPS_REL32);
@@ -4075,11 +4137,15 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                    {
                      long indx;
 
-                     sym = local_syms + r_symndx;
-
-                     BFD_ASSERT (ELF_ST_TYPE (sym->st_info) == STT_SECTION);
-
-                     sec = local_sections[r_symndx];
+                     if (h == NULL)
+                       sec = local_sections[r_symndx];
+                     else
+                       {
+                         BFD_ASSERT (h->root.type == bfd_link_hash_defined
+                                     || (h->root.type
+                                         == bfd_link_hash_defweak));
+                         sec = h->root.u.def.section;
+                       }
                      if (sec != NULL && bfd_is_abs_section (sec))
                        indx = 0;
                      else if (sec == NULL || sec->owner == NULL)
@@ -4122,6 +4188,7 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                        mips_elf_set_cr_type (cptrel, CRT_MIPS_REL32);
                      else
                        mips_elf_set_cr_type (cptrel, CRT_MIPS_WORD);
+                     mips_elf_set_cr_dist2to (cptrel, 0);
                      cptrel.konst = addend;
 
                      cr = (scpt->contents
@@ -4163,7 +4230,9 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                {
                case R_MIPS_26:
                  mips_elf_set_cr_type (cptrel, CRT_MIPS_JMPAD);
-                 cptrel.konst = addend;
+                 /* XXX How should we set dist2to in this case. */
+                 mips_elf_set_cr_dist2to (cptrel, 8);
+                 cptrel.konst = addend + relocation;
                  cr = scpt->contents + sizeof (Elf32_External_compact_rel);
                  bfd_elf32_swap_crinfo_out (output_bfd, &cptrel,
                                             ((Elf32_External_crinfo *) cr
@@ -4176,6 +4245,7 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                case R_MIPS_GPREL32:
                  mips_elf_set_cr_type (cptrel, CRT_MIPS_GPHI_LO);
                  cptrel.konst = elf_gp (output_bfd) - cptrel.vaddr;
+                 mips_elf_set_cr_dist2to (cptrel, 4);
                  cr = scpt->contents + sizeof (Elf32_External_compact_rel);
                  bfd_elf32_swap_crinfo_out (output_bfd, &cptrel,
                                             ((Elf32_External_crinfo *) cr
@@ -4233,7 +4303,6 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 #define ELF_DYNAMIC_INTERPRETER "/usr/lib/libc.so.1"
 
 /* Create dynamic sections when linking against a dynamic object.  */
-static boolean mips_elf_create_got_section (bfd *, struct bfd_link_info *);
 
 static boolean
 mips_elf_create_dynamic_sections (abfd, info)
@@ -4284,24 +4353,13 @@ mips_elf_create_dynamic_sections (abfd, info)
          h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
          h->type = STT_SECTION;
 
-         if (info->shared
-             && ! bfd_elf32_link_record_dynamic_symbol (info, h))
-           return false;
-       }
-
-      /* Create .compact_rel section.  */
-      if (bfd_get_section_by_name (abfd, ".compact_rel") == NULL)
-       {
-         flags = SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_READONLY;
-
-         s = bfd_make_section (abfd, ".compact_rel");
-         if (s == NULL
-             || ! bfd_set_section_flags (abfd, s, flags)
-             || ! bfd_set_section_alignment (abfd, s, 2))
+         if (! bfd_elf32_link_record_dynamic_symbol (info, h))
            return false;
        }
 
-      s->_raw_size = sizeof (Elf32_compact_rel);
+      /* We need to create a .compact_rel section.  */
+      if (! mips_elf_create_compact_rel_section (abfd, info))
+       return false;
 
       /* Change aligments of some sections.  */
       s = bfd_get_section_by_name (abfd, ".hash");
@@ -4321,9 +4379,51 @@ mips_elf_create_dynamic_sections (abfd, info)
        bfd_set_section_alignment (abfd, s, 4);
     }
 
+  if (!info->shared)
+    {
+      h = NULL;
+      if (! (_bfd_generic_link_add_one_symbol
+            (info, abfd, "_DYNAMIC_LINK", BSF_GLOBAL, bfd_abs_section_ptr,
+             (bfd_vma) 0, (const char *) NULL, false,
+             get_elf_backend_data (abfd)->collect,
+             (struct bfd_link_hash_entry **) &h)))
+       return false;
+      h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+      h->type = STT_SECTION;
+
+      if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+       return false;
+    }
+
   return true;
 }
 
+/* Create the .compact_rel section.  */
+
+static boolean
+mips_elf_create_compact_rel_section (abfd, info)
+     bfd *abfd;
+     struct bfd_link_info *info;
+{
+  flagword flags;
+  register asection *s;
+
+  if (bfd_get_section_by_name (abfd, ".compact_rel") == NULL)
+    {
+      flags = SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_READONLY;
+
+      s = bfd_make_section (abfd, ".compact_rel");
+      if (s == NULL
+         || ! bfd_set_section_flags (abfd, s, flags)
+         || ! bfd_set_section_alignment (abfd, s, 2))
+       return false;
+
+      s->_raw_size = sizeof (Elf32_External_compact_rel);
+    }
+
+  return true;
+}
+  
 /* Create the .got section to hold the global offset table. */
 
 static boolean
@@ -4350,9 +4450,7 @@ mips_elf_create_got_section (abfd, info)
 
   /* Define the symbol _GLOBAL_OFFSET_TABLE_.  We don't do this in the
      linker script because we don't want to define the symbol if we
-     are not creating a global offset table.  XXX Should this be
-     defined at the start of the .got section, even if .got section is
-     accessed by using 16 bit signed offset?  */
+     are not creating a global offset table.  */
   h = NULL;
   if (! (_bfd_generic_link_add_one_symbol
         (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s,
@@ -4407,7 +4505,6 @@ mips_elf_check_relocs (abfd, info, sec, relocs)
   const Elf_Internal_Rela *rel_end;
   asection *sgot;
   asection *sreloc;
-  asection *scpt;
 
   if (info->relocateable)
     return true;
@@ -4419,10 +4516,6 @@ mips_elf_check_relocs (abfd, info, sec, relocs)
 
   sgot = NULL;
   sreloc = NULL;
-  if (SGI_COMPAT (abfd) && dynobj != NULL)
-    scpt = bfd_get_section_by_name (dynobj, ".compact_rel");
-  else
-    scpt = NULL;
 
   rel_end = relocs + sec->reloc_count;
   for (rel = relocs; rel < rel_end; rel++)
@@ -4577,19 +4670,21 @@ mips_elf_check_relocs (abfd, info, sec, relocs)
                }
 
              sreloc->_raw_size += sizeof (Elf32_External_Rel);
-
-             if (scpt != NULL)
-               scpt->_raw_size += sizeof (Elf32_External_crinfo);
            }
 
+         if (SGI_COMPAT (abfd))
+           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 (scpt != NULL)
-           scpt->_raw_size += sizeof (Elf32_External_crinfo);
+         if (SGI_COMPAT (abfd))
+           mips_elf_hash_table (info)->compact_rel_size +=
+             sizeof (Elf32_External_crinfo);
          break;
 
        default:
@@ -4800,9 +4895,10 @@ mips_elf_size_dynamic_sections (output_bfd, info)
             of .text section. So put a dummy. XXX  */
          s->_raw_size += MIPS_FUNCTION_STUB_SIZE;
        }
-      else if (strncmp (name, ".init", 5) != 0
-              && (! SGI_COMPAT (output_bfd)
-                  || strncmp (name, ".compact_rel", 12) != 0))
+      else if (SGI_COMPAT (output_bfd)
+              && strncmp (name, ".compact_rel", 12) == 0)
+       s->_raw_size += mips_elf_hash_table (info)->compact_rel_size;
+      else if (strncmp (name, ".init", 5) != 0)
        {
          /* It's not one of our sections, so don't allocate space.  */
          continue;
@@ -4872,7 +4968,7 @@ mips_elf_size_dynamic_sections (output_bfd, info)
       if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_LIBLISTNO, 0))
        return false;
 
-      if (bfd_get_section_by_name (dynobj, ".conflict"))
+      if (bfd_get_section_by_name (dynobj, ".conflict") != NULL)
        {
          if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_CONFLICT, 0))
            return false;
@@ -4890,8 +4986,11 @@ mips_elf_size_dynamic_sections (output_bfd, info)
       if (! bfd_elf32_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))
        return false;
+#endif
 
 #if 0 /* FIXME  */
       if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_ICHECKSUM, 0))
@@ -4932,74 +5031,76 @@ mips_elf_size_dynamic_sections (output_bfd, info)
 #endif
     }
 
-  /* If we are generating a shared library, we generate a section
-     symbol for each output section.  These are local symbols, which
-     means that they must come first in the dynamic symbol table.
+  /* If we use dynamic linking, we generate a section symbol for each
+     output section.  These are local symbols, which means that they
+     must come first in the dynamic symbol table.
      That means we must increment the dynamic symbol index of every
      other dynamic symbol.  */
-  if (info->shared)
-    {
-      const char * const *namep;
-      int c, i;
-      bfd_size_type strindex;
-      struct bfd_strtab_hash *dynstr;
-      struct mips_got_info *g;
-
-      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;
+  {
+    const char * const *namep;
+    unsigned int c, i;
+    bfd_size_type strindex;
+    struct bfd_strtab_hash *dynstr;
+    struct mips_got_info *g;
+
+    if (elf_hash_table (info)->dynamic_sections_created)
+      {
+       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;
+               strindex = _bfd_stringtab_add (dynstr, *namep, true, false);
+               if (strindex == (bfd_size_type) -1)
+                 return false;
 
-             mips_elf_hash_table (info)->dynsym_sec_strindex[i] = strindex;
-           }
-       }
-      else
-       {
-         c = bfd_count_sections (output_bfd);
-         elf_link_hash_traverse (elf_hash_table (info),
-                                 mips_elf_adjust_dynindx,
-                                 (PTR) &c);
-         elf_hash_table (info)->dynsymcount += c;
+               mips_elf_hash_table (info)->dynsym_sec_strindex[i] = strindex;
+             }
+         }
+       else
+         {
+           c = bfd_count_sections (output_bfd);
+           elf_link_hash_traverse (elf_hash_table (info),
+                                   mips_elf_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.  */
-           }
-       }
+           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.  */
+             }
+         }
+      }
 
-      s = bfd_get_section_by_name (dynobj, ".got");
-      BFD_ASSERT (s != NULL);
-      BFD_ASSERT (elf_section_data (s) != NULL);
-      g = (struct mips_got_info *) elf_section_data (s)->tdata;
-      BFD_ASSERT (g != NULL);
+    s = bfd_get_section_by_name (dynobj, ".got");
+    BFD_ASSERT (s != NULL);
+    BFD_ASSERT (elf_section_data (s) != NULL);
+    g = (struct mips_got_info *) elf_section_data (s)->tdata;
+    BFD_ASSERT (g != NULL);
 
-      /* If there are no global got symbols, fake the last symbol so for
-        safety.  */
-      if (g->global_gotsym)
-       g->global_gotsym += c;
-      else
-       g->global_gotsym = elf_hash_table (info)->dynsymcount - 1;
-    }
+    /* If there are no global got symbols, fake the last symbol so for
+       safety.  */
+    if (g->global_gotsym)
+      g->global_gotsym += c;
+    else
+      g->global_gotsym = elf_hash_table (info)->dynsymcount - 1;
+  }
 
   return true;
 }
@@ -5012,7 +5113,7 @@ mips_elf_adjust_dynindx (h, cparg)
      struct elf_link_hash_entry *h;
      PTR cparg;
 {
-  int *cp = (int *) cparg;
+  unsigned int *cp = (unsigned int *) cparg;
 
   if (h->dynindx != -1)
     h->dynindx += *cp;
@@ -5108,8 +5209,13 @@ mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
   if (strcmp (name, "_DYNAMIC") == 0
       || strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
     sym->st_shndx = SHN_ABS;
-
-  if (SGI_COMPAT (output_bfd))
+  else if (strcmp (name, "_DYNAMIC_LINK") == 0)
+    {
+      sym->st_shndx = SHN_ABS;
+      sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
+      sym->st_value = 1;
+    }
+  else if (SGI_COMPAT (output_bfd))
     {
       if (strcmp (name, "_gp_disp") == 0)
        {
@@ -5132,8 +5238,7 @@ mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
          sym->st_value = mips_elf_hash_table (info)->procedure_count;
          sym->st_shndx = SHN_ABS;
        }
-
-      if (sym->st_shndx != SHN_UNDEF)
+      else if (sym->st_shndx != SHN_UNDEF)
        {
          if (h->type == STT_FUNC)
            sym->st_shndx = SHN_MIPS_TEXT;
@@ -5321,128 +5426,130 @@ mips_elf_finish_dynamic_sections (output_bfd, info)
 
   elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
 
-  if (info->shared)
-    {
-      asection *sdynsym;
-      asection *s;
-      unsigned int i;
-      bfd_vma last;
-      Elf_Internal_Sym sym;
-      long dindx;
-      const char *name;
-      const char * const * namep = mips_elf_dynsym_sec_names;
-      Elf32_compact_rel cpt;
-
-      /* Set up the section symbols for the output sections. SGI set
-        STT_NOTYPE attribute for these symbols.  Should we do so?  */
-
-      sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
-      BFD_ASSERT (sdynsym != NULL);
-
-      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;
-         while ((name = *namep++) != NULL)
-           {
-             s = bfd_get_section_by_name (output_bfd, name);
-             if (s)
-               {
-                 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];
+  {
+    asection *sdynsym;
+    asection *s;
+    unsigned int i;
+    bfd_vma last;
+    Elf_Internal_Sym sym;
+    long dindx;
+    const char *name;
+    const char * const * namep = mips_elf_dynsym_sec_names;
+    Elf32_compact_rel cpt;
+
+    /* Set up the section symbols for the output sections. SGI sets
+       the STT_NOTYPE attribute for these symbols.  Should we do so?  */
+
+    sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
+    if (sdynsym != NULL)
+      {
+       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;
 
-             bfd_elf32_swap_symbol_out (output_bfd, &sym,
-                                        (((Elf32_External_Sym *)
-                                          sdynsym->contents)
-                                         + dindx));
-           }
+           i = 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++;
+                 }
 
-         /* 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
-       {
-         sym.st_size = 0;
-         sym.st_name = 0;
-         sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
-         sym.st_other = 0;
+               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));
+             }
 
-         for (s = output_bfd->sections; s != NULL; s = s->next)
-           {
-             int indx;
+           /* 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
+         {
+           sym.st_size = 0;
+           sym.st_name = 0;
+           sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
+           sym.st_other = 0;
 
-             sym.st_value = s->vma;
+           for (s = output_bfd->sections; s != NULL; s = s->next)
+             {
+               int indx;
 
-             indx = elf_section_data (s)->this_idx;
-             BFD_ASSERT (indx > 0);
-             sym.st_shndx = indx;
+               sym.st_value = s->vma;
 
-             bfd_elf32_swap_symbol_out (output_bfd, &sym,
-                                        (((Elf32_External_Sym *)
-                                          sdynsym->contents)
-                                         + elf_section_data (s)->dynindx));
-           }
+               indx = elf_section_data (s)->this_idx;
+               BFD_ASSERT (indx > 0);
+               sym.st_shndx = indx;
 
-         /* 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;
-       }
+               bfd_elf32_swap_symbol_out (output_bfd, &sym,
+                                          (((Elf32_External_Sym *)
+                                            sdynsym->contents)
+                                           + elf_section_data (s)->dynindx));
+             }
 
-      if (SGI_COMPAT (output_bfd))
-       {
-         /* Write .compact_rel section out.  */
-         s = bfd_get_section_by_name (dynobj, ".compact_rel");
-         BFD_ASSERT (s != NULL);
+           /* 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;
+         }
+      }
 
-         cpt.id1 = 1;
-         cpt.num = s->reloc_count;
-         cpt.id2 = 2;
-         cpt.offset = (s->output_section->filepos
-                       + sizeof (Elf32_External_compact_rel));
-         cpt.reserved0 = 0;
-         cpt.reserved1 = 0;
-         bfd_elf32_swap_compact_rel_out (output_bfd, &cpt, 
-                                         ((Elf32_External_compact_rel *)
-                                          s->contents));
-
-         /* Clean up a dummy stub function entry in .text.  */
-         s = bfd_get_section_by_name (dynobj, ".stub");
-         if (s != NULL)
-           {
-             file_ptr dummy_offset;
+    if (SGI_COMPAT (output_bfd))
+      {
+       /* Write .compact_rel section out.  */
+       s = bfd_get_section_by_name (dynobj, ".compact_rel");
+       if (s != NULL)
+         {
+           cpt.id1 = 1;
+           cpt.num = s->reloc_count;
+           cpt.id2 = 2;
+           cpt.offset = (s->output_section->filepos
+                         + sizeof (Elf32_External_compact_rel));
+           cpt.reserved0 = 0;
+           cpt.reserved1 = 0;
+           bfd_elf32_swap_compact_rel_out (output_bfd, &cpt, 
+                                           ((Elf32_External_compact_rel *)
+                                            s->contents));
+
+           /* Clean up a dummy stub function entry in .text.  */
+           s = bfd_get_section_by_name (dynobj, ".stub");
+           if (s != NULL)
+             {
+               file_ptr dummy_offset;
 
-             BFD_ASSERT (s->_raw_size >= MIPS_FUNCTION_STUB_SIZE);
-             dummy_offset = s->_raw_size - MIPS_FUNCTION_STUB_SIZE;
-             memset (s->contents + dummy_offset, 0, MIPS_FUNCTION_STUB_SIZE);
-           }
-       }
+               BFD_ASSERT (s->_raw_size >= MIPS_FUNCTION_STUB_SIZE);
+               dummy_offset = s->_raw_size - MIPS_FUNCTION_STUB_SIZE;
+               memset (s->contents + dummy_offset, 0,
+                       MIPS_FUNCTION_STUB_SIZE);
+             }
+         }
+      }
 
-      /* Clean up a first relocation in .rel.dyn.  */
-      s = bfd_get_section_by_name (dynobj, ".rel.dyn");
-      if (s)
-       memset (s->contents, 0, sizeof (Elf32_External_Rel));
-    }
+    /* Clean up a first relocation in .rel.dyn.  */
+    s = bfd_get_section_by_name (dynobj, ".rel.dyn");
+    if (s != NULL)
+      memset (s->contents, 0, sizeof (Elf32_External_Rel));
+  }
 
   return true;
 }
@@ -5712,7 +5819,6 @@ static const struct ecoff_debug_swap mips_elf_ecoff_debug_swap =
 #define bfd_elf32_bfd_merge_private_bfd_data \
                                        mips_elf_merge_private_bfd_data
 #define bfd_elf32_bfd_set_private_flags        mips_elf_set_private_flags
-#define elf_backend_relocate_section   mips_elf_relocate_section
 #define elf_backend_add_symbol_hook    mips_elf_add_symbol_hook
 #define elf_backend_create_dynamic_sections \
                                        mips_elf_create_dynamic_sections
index f759881276715987f7f94d6dc1c2caca766ddb09..b4327b7c54a4836932f8b8cb51fe7e7b02264341 100644 (file)
@@ -22,9 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "bfdlink.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
-/* start-sanitize-v8plus */
 #include "elf/sparc.h"
-/* end-sanitize-v8plus */
 
 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
   PARAMS ((bfd *, bfd_reloc_code_real_type));
@@ -47,15 +45,11 @@ static boolean elf32_sparc_finish_dynamic_symbol
           Elf_Internal_Sym *));
 static boolean elf32_sparc_finish_dynamic_sections
   PARAMS ((bfd *, struct bfd_link_info *));
-/* start-sanitize-v8plus */
-static boolean elf32_sparc_set_private_flags PARAMS ((bfd *, flagword));
-static boolean elf32_sparc_copy_private_bfd_data PARAMS ((bfd *, bfd *));
 static boolean elf32_sparc_merge_private_bfd_data PARAMS ((bfd *, bfd *));
 static boolean elf32_sparc_object_p
   PARAMS ((bfd *));
 static void elf32_sparc_final_write_processing
   PARAMS ((bfd *, boolean));
-/* end-sanitize-v8plus */
 
 enum reloc_type
   {
@@ -914,6 +908,9 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
                          || (h->elf_link_hash_flags
                              & ELF_LINK_HASH_DEF_REGULAR) == 0))
                  || (info->shared
+                     && (! info->symbolic
+                         || (h->elf_link_hash_flags
+                             & ELF_LINK_HASH_DEF_REGULAR) == 0)
                      && (input_section->flags & SEC_ALLOC) != 0
                      && (r_type == R_SPARC_8
                          || r_type == R_SPARC_16
@@ -1131,7 +1128,10 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
              outrel.r_offset = (rel->r_offset
                                 + input_section->output_section->vma
                                 + input_section->output_offset);
-             if (h != NULL)
+             if (h != NULL
+                 && (! info->symbolic
+                     || (h->elf_link_hash_flags
+                         & ELF_LINK_HASH_DEF_REGULAR) == 0))
                {
                  BFD_ASSERT (h->dynindx != -1);
                  outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
@@ -1148,8 +1148,15 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
                    {
                      long indx;
 
-                     sym = local_syms + r_symndx;
-                     sec = local_sections[r_symndx];
+                     if (h == NULL)
+                       sec = local_sections[r_symndx];
+                     else
+                       {
+                         BFD_ASSERT (h->root.type == bfd_link_hash_defined
+                                     || (h->root.type
+                                         == bfd_link_hash_defweak));
+                         sec = h->root.u.def.section;
+                       }
                      if (sec != NULL && bfd_is_abs_section (sec))
                        indx = 0;
                      else if (sec == NULL || sec->owner == NULL)
@@ -1491,45 +1498,13 @@ elf32_sparc_finish_dynamic_sections (output_bfd, info)
 
   return true;
 }
-/* start-sanitize-v8plus */
 \f
-/* Function to set e_flags.  */
-
-static boolean
-elf32_sparc_set_private_flags (abfd, flags)
-     bfd *abfd;
-     flagword flags;
-{
-  /* Once the flags have been set, you (apparently) can't change them.  */
-  BFD_ASSERT (!elf_flags_init (abfd)
-             || elf_elfheader (abfd)->e_flags == flags);
-
-  elf_elfheader (abfd)->e_flags = flags;
-  elf_flags_init (abfd) = true;
-  return true;
-}
-
-/* Copy backend specific data from one object module to another.  */
-
-static boolean
-elf32_sparc_copy_private_bfd_data (ibfd, obfd)
-     bfd *ibfd;
-     bfd *obfd;
-{
-  /* This function is selected based on the input vector.  We only
-     want to copy information over if the output BFD also uses Elf
-     format.  */
-  if (bfd_get_flavour (obfd) != bfd_target_elf_flavour)
-    return true;
+/* Functions for dealing with the e_flags field.
 
-  /* Once the flags have been set, you (apparently) can't change them.  */
-  BFD_ASSERT (!elf_flags_init (obfd)
-             || elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags);
-
-  elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
-  elf_flags_init (obfd) = true;
-  return true;
-}
+   We don't define set_private_flags or copy_private_bfd_data because
+   the only currently defined values are based on the bfd mach number,
+   so we use the latter instead and defer setting e_flags until the
+   file is written out.  */
 
 /* Merge backend specific data from an object file to the output
    object file when linking.  */
@@ -1539,8 +1514,6 @@ elf32_sparc_merge_private_bfd_data (ibfd, obfd)
      bfd *ibfd;
      bfd *obfd;
 {
-  flagword old_flags;
-  flagword new_flags;
   boolean error;
 
   /* This function is selected based on the input vector.  We only
@@ -1551,6 +1524,13 @@ elf32_sparc_merge_private_bfd_data (ibfd, obfd)
 
   error = false;
 
+#if 0
+  /* ??? The native linker doesn't do this so we can't (otherwise gcc would
+     have to know which linker is being used).  Instead, the native linker
+     bumps up the architecture level when it has to.  However, I still think
+     warnings like these are good, so it would be nice to have them turned on
+     by some option.  */
+
   /* If the output machine is normal sparc, we can't allow v9 input files.  */
   if (bfd_get_mach (obfd) == bfd_mach_sparc
       && (bfd_get_mach (ibfd) == bfd_mach_sparc_v8plus
@@ -1570,30 +1550,17 @@ elf32_sparc_merge_private_bfd_data (ibfd, obfd)
        ("%s: compiled for a v8plusa system and target is v8plus",
         bfd_get_filename (ibfd));
     }
-
-  new_flags = elf_elfheader (ibfd)->e_flags;
-  old_flags = elf_elfheader (obfd)->e_flags;
-  if (!elf_flags_init (obfd))  /* First call, no flags set */
+#else
+  if (bfd_get_mach (ibfd) >= bfd_mach_sparc_v9)
     {
-      elf_flags_init (obfd) = true;
-      elf_elfheader (obfd)->e_flags = new_flags;
-    }
-  else if (new_flags == old_flags)     /* Compatible flags are ok */
-    ;
-  else                                 /* Potentially incompatible flags */
-    {
-      new_flags &= ~ (EF_SPARC_32PLUS | EF_SPARC_SUN_US1);
-      old_flags &= ~ (EF_SPARC_32PLUS | EF_SPARC_SUN_US1);
-
-      /* Warn about any other mismatches */
-      if (new_flags != old_flags)
-       {
-         error = true;
-         (*_bfd_error_handler)
-           ("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)",
-            bfd_get_filename (ibfd), (long) new_flags, (long) old_flags);
-       }
+      error = true;
+      (*_bfd_error_handler)
+       ("%s: compiled for a 64 bit system and target is 32 bit",
+        bfd_get_filename (ibfd));
     }
+  else if (bfd_get_mach (obfd) < bfd_get_mach (ibfd))
+    bfd_set_arch_mach (obfd, bfd_arch_sparc, bfd_get_mach (ibfd));
+#endif
 
   if (error)
     {
@@ -1611,7 +1578,16 @@ elf32_sparc_object_p (abfd)
      bfd *abfd;
 {
   if (elf_elfheader (abfd)->e_machine == EM_SPARC32PLUS)
-    return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc_v8plus);
+    {
+      if (elf_elfheader (abfd)->e_flags & EF_SPARC_SUN_US1)
+       return bfd_default_set_arch_mach (abfd, bfd_arch_sparc,
+                                         bfd_mach_sparc_v8plusa);
+      else if (elf_elfheader (abfd)->e_flags & EF_SPARC_32PLUS)
+       return bfd_default_set_arch_mach (abfd, bfd_arch_sparc,
+                                         bfd_mach_sparc_v8plus);
+      else
+       return false;
+    }
   else
     return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc);
 }
@@ -1624,24 +1600,30 @@ elf32_sparc_final_write_processing (abfd, linker)
      bfd *abfd;
      boolean linker;
 {
-  if (bfd_get_mach (abfd) == bfd_mach_sparc_v8plus)
+  switch (bfd_get_mach (abfd))
     {
+    case bfd_mach_sparc :
+      break; /* nothing to do */
+    case bfd_mach_sparc_v8plus :
       elf_elfheader (abfd)->e_machine = EM_SPARC32PLUS;
-#if 0 /* FIXME: Not sure how to handle EF_SPARC_32PLUS_US1 */
       elf_elfheader (abfd)->e_flags &=~ EF_SPARC_32PLUS_MASK;
-#endif
       elf_elfheader (abfd)->e_flags |= EF_SPARC_32PLUS;
+      break;
+    case bfd_mach_sparc_v8plusa :
+      elf_elfheader (abfd)->e_machine = EM_SPARC32PLUS;
+      elf_elfheader (abfd)->e_flags &=~ EF_SPARC_32PLUS_MASK;
+      elf_elfheader (abfd)->e_flags |= EF_SPARC_32PLUS | EF_SPARC_SUN_US1;
+      break;
+    default :
+      abort ();
     }
 }
-/* end-sanitize-v8plus */
 \f
 #define TARGET_BIG_SYM bfd_elf32_sparc_vec
 #define TARGET_BIG_NAME        "elf32-sparc"
 #define ELF_ARCH       bfd_arch_sparc
 #define ELF_MACHINE_CODE EM_SPARC
-/* start-sanitize-v8plus */
 #define ELF_MACHINE_ALT1 EM_SPARC32PLUS
-/* end-sanitize-v8plus */
 #define ELF_MAXPAGESIZE 0x10000
 #define elf_backend_create_dynamic_sections \
                                        _bfd_elf_create_dynamic_sections
@@ -1655,16 +1637,11 @@ elf32_sparc_final_write_processing (abfd, linker)
                                        elf32_sparc_finish_dynamic_symbol
 #define elf_backend_finish_dynamic_sections \
                                        elf32_sparc_finish_dynamic_sections
-/* start-sanitize-v8plus */
-#define bfd_elf32_bfd_set_private_flags        elf32_sparc_set_private_flags
-#define bfd_elf32_bfd_copy_private_bfd_data \
-                                       elf32_sparc_copy_private_bfd_data
 #define bfd_elf32_bfd_merge_private_bfd_data \
                                        elf32_sparc_merge_private_bfd_data
 #define elf_backend_object_p           elf32_sparc_object_p
 #define elf_backend_final_write_processing \
                                        elf32_sparc_final_write_processing
-/* end-sanitize-v8plus */
 #define elf_backend_want_got_plt 0
 #define elf_backend_plt_readonly 0
 #define elf_backend_want_plt_sym 1