Fix autoconf breakage + commit target.c, omitted in previous delta
[deliverable/binutils-gdb.git] / bfd / elf32-mips.c
index b9b99c76b2ef0dbcc4e0fce538c2323ee1438d68..efbcbfab293e3b2ea4f9835a0f1c72e9eed37c9c 100644 (file)
@@ -1,5 +1,5 @@
 /* MIPS-specific support for 32-bit ELF
 /* MIPS-specific support for 32-bit ELF
-   Copyright 1993, 94, 95, 96, 97, 98, 99, 2000
+   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
    Free Software Foundation, Inc.
 
    Most of the information added by Ian Lance Taylor, Cygnus Support,
    Free Software Foundation, Inc.
 
    Most of the information added by Ian Lance Taylor, Cygnus Support,
@@ -49,7 +49,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 /* This structure is used to hold .got information when linking.  It
    is stored in the tdata field of the bfd_elf_section_data structure.  */
 
 /* This structure is used to hold .got information when linking.  It
    is stored in the tdata field of the bfd_elf_section_data structure.  */
 
-struct mips_got_info {
+struct mips_got_info
+{
   /* The global symbol in the GOT with the lowest index in the dynamic
      symbol table.  */
   struct elf_link_hash_entry *global_gotsym;
   /* The global symbol in the GOT with the lowest index in the dynamic
      symbol table.  */
   struct elf_link_hash_entry *global_gotsym;
@@ -64,7 +65,8 @@ struct mips_got_info {
 /* The MIPS ELF linker needs additional information for each symbol in
    the global hash table.  */
 
 /* The MIPS ELF linker needs additional information for each symbol in
    the global hash table.  */
 
-struct mips_elf_link_hash_entry {
+struct mips_elf_link_hash_entry
+{
   struct elf_link_hash_entry root;
 
   /* External symbol information.  */
   struct elf_link_hash_entry root;
 
   /* External symbol information.  */
@@ -78,6 +80,12 @@ struct mips_elf_link_hash_entry {
      section) against this symbol.  */
   unsigned int min_dyn_reloc_index;
 
      section) against this symbol.  */
   unsigned int min_dyn_reloc_index;
 
+  /* We must not create a stub for a symbol that has relocations
+     related to taking the function's address, i.e. any but
+     R_MIPS_CALL*16 ones -- see "MIPS ABI Supplement, 3rd Edition",
+     p. 4-20.  */
+  boolean no_fn_stub;
+
   /* If there is a stub that 32 bit functions should use to call this
      16 bit function, this points to the section containing the stub.  */
   asection *fn_stub;
   /* If there is a stub that 32 bit functions should use to call this
      16 bit function, this points to the section containing the stub.  */
   asection *fn_stub;
@@ -191,7 +199,7 @@ static bfd_vma mips_elf_got16_entry
 static boolean mips_elf_create_dynamic_relocation
   PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Rela *,
           struct mips_elf_link_hash_entry *, asection *,
 static boolean mips_elf_create_dynamic_relocation
   PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Rela *,
           struct mips_elf_link_hash_entry *, asection *,
-          bfd_vma, bfd_vma *, asection *, boolean local_p));
+          bfd_vma, bfd_vma *, asection *));
 static void mips_elf_allocate_dynamic_relocations
   PARAMS ((bfd *, unsigned int));
 static boolean mips_elf_stub_section_p
 static void mips_elf_allocate_dynamic_relocations
   PARAMS ((bfd *, unsigned int));
 static boolean mips_elf_stub_section_p
@@ -200,6 +208,11 @@ static int sort_dynamic_relocs
   PARAMS ((const void *, const void *));
 
 extern const bfd_target bfd_elf32_tradbigmips_vec;
   PARAMS ((const void *, const void *));
 
 extern const bfd_target bfd_elf32_tradbigmips_vec;
+extern const bfd_target bfd_elf32_tradlittlemips_vec;
+#ifdef BFD64
+extern const bfd_target bfd_elf64_tradbigmips_vec;
+extern const bfd_target bfd_elf64_tradlittlemips_vec;
+#endif
 
 /* The level of IRIX compatibility we're striving for.  */
 
 
 /* The level of IRIX compatibility we're striving for.  */
 
@@ -217,18 +230,25 @@ static bfd *reldyn_sorting_bfd;
 #define ABI_N32_P(abfd) \
   ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI2) != 0)
 
 #define ABI_N32_P(abfd) \
   ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI2) != 0)
 
-/* Nonzero if ABFD is using the 64-bit ABI.  FIXME: This is never
-   true, yet.  */
+/* Nonzero if ABFD is using the 64-bit ABI. */
 #define ABI_64_P(abfd) \
   ((elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64) != 0)
 
 /* Depending on the target vector we generate some version of Irix
    executables or "normal" MIPS ELF ABI executables.  */
 #define ABI_64_P(abfd) \
   ((elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64) != 0)
 
 /* Depending on the target vector we generate some version of Irix
    executables or "normal" MIPS ELF ABI executables.  */
-
+#ifdef BFD64
 #define IRIX_COMPAT(abfd) \
 #define IRIX_COMPAT(abfd) \
-  (abfd->xvec == &bfd_elf32_tradbigmips_vec ? ict_none : \
+  (((abfd->xvec == &bfd_elf64_tradbigmips_vec) || \
+    (abfd->xvec == &bfd_elf64_tradlittlemips_vec) || \
+    (abfd->xvec == &bfd_elf32_tradbigmips_vec) || \
+    (abfd->xvec == &bfd_elf32_tradlittlemips_vec)) ? ict_none : \
   ((ABI_N32_P (abfd) || ABI_64_P (abfd)) ? ict_irix6 : ict_irix5))
   ((ABI_N32_P (abfd) || ABI_64_P (abfd)) ? ict_irix6 : ict_irix5))
-
+#else
+#define IRIX_COMPAT(abfd) \
+  (((abfd->xvec == &bfd_elf32_tradbigmips_vec) || \
+    (abfd->xvec == &bfd_elf32_tradlittlemips_vec)) ? ict_none : \
+  ((ABI_N32_P (abfd) || ABI_64_P (abfd)) ? ict_irix6 : ict_irix5))
+#endif
 /* Whether we are trying to be compatible with IRIX at all.  */
 
 #define SGI_COMPAT(abfd) \
 /* Whether we are trying to be compatible with IRIX at all.  */
 
 #define SGI_COMPAT(abfd) \
@@ -321,7 +341,8 @@ static bfd *reldyn_sorting_bfd;
 /* Names of sections which appear in the .dynsym section in an Irix 5
    executable.  */
 
 /* Names of sections which appear in the .dynsym section in an Irix 5
    executable.  */
 
-static const char * const mips_elf_dynsym_sec_names[] = {
+static const char * const mips_elf_dynsym_sec_names[] =
+{
   ".text",
   ".init",
   ".fini",
   ".text",
   ".init",
   ".fini",
@@ -345,7 +366,8 @@ static const char * const mips_elf_dynsym_sec_names[] = {
 
 /* The names of the runtime procedure table symbols used on Irix 5.  */
 
 
 /* The names of the runtime procedure table symbols used on Irix 5.  */
 
-static const char * const mips_elf_dynsym_rtproc_names[] = {
+static const char * const mips_elf_dynsym_rtproc_names[] =
+{
   "_procedure_table",
   "_procedure_string_table",
   "_procedure_table_size",
   "_procedure_table",
   "_procedure_string_table",
   "_procedure_table_size",
@@ -355,7 +377,8 @@ static const char * const mips_elf_dynsym_rtproc_names[] = {
 /* These structures are used to generate the .compact_rel section on
    Irix 5.  */
 
 /* These structures are used to generate the .compact_rel section on
    Irix 5.  */
 
-typedef struct {
+typedef struct
+{
   unsigned long id1;           /* Always one?  */
   unsigned long num;           /* Number of compact relocation entries.  */
   unsigned long id2;           /* Always two?  */
   unsigned long id1;           /* Always one?  */
   unsigned long num;           /* Number of compact relocation entries.  */
   unsigned long id2;           /* Always two?  */
@@ -364,7 +387,8 @@ typedef struct {
   unsigned long reserved1;     /* Zero?  */
 } Elf32_compact_rel;
 
   unsigned long reserved1;     /* Zero?  */
 } Elf32_compact_rel;
 
-typedef struct {
+typedef struct
+{
   bfd_byte id1[4];
   bfd_byte num[4];
   bfd_byte id2[4];
   bfd_byte id1[4];
   bfd_byte num[4];
   bfd_byte id2[4];
@@ -373,7 +397,8 @@ typedef struct {
   bfd_byte reserved1[4];
 } Elf32_External_compact_rel;
 
   bfd_byte reserved1[4];
 } Elf32_External_compact_rel;
 
-typedef struct {
+typedef struct
+{
   unsigned int ctype : 1;      /* 1: long 0: short format. See below.  */
   unsigned int rtype : 4;      /* Relocation types. See below.  */
   unsigned int dist2to : 8;
   unsigned int ctype : 1;      /* 1: long 0: short format. See below.  */
   unsigned int rtype : 4;      /* Relocation types. See below.  */
   unsigned int dist2to : 8;
@@ -382,7 +407,8 @@ typedef struct {
   unsigned long vaddr;         /* VADDR to be relocated.  */
 } Elf32_crinfo;
 
   unsigned long vaddr;         /* VADDR to be relocated.  */
 } Elf32_crinfo;
 
-typedef struct {
+typedef struct
+{
   unsigned int ctype : 1;      /* 1: long 0: short format. See below.  */
   unsigned int rtype : 4;      /* Relocation types. See below.  */
   unsigned int dist2to : 8;
   unsigned int ctype : 1;      /* 1: long 0: short format. See below.  */
   unsigned int rtype : 4;      /* Relocation types. See below.  */
   unsigned int dist2to : 8;
@@ -390,13 +416,15 @@ typedef struct {
   unsigned long konst;         /* KONST field. See below.  */
 } Elf32_crinfo2;
 
   unsigned long konst;         /* KONST field. See below.  */
 } Elf32_crinfo2;
 
-typedef struct {
+typedef struct
+{
   bfd_byte info[4];
   bfd_byte konst[4];
   bfd_byte vaddr[4];
 } Elf32_External_crinfo;
 
   bfd_byte info[4];
   bfd_byte konst[4];
   bfd_byte vaddr[4];
 } Elf32_External_crinfo;
 
-typedef struct {
+typedef struct
+{
   bfd_byte info[4];
   bfd_byte konst[4];
 } Elf32_External_crinfo2;
   bfd_byte info[4];
   bfd_byte konst[4];
 } Elf32_External_crinfo2;
@@ -449,7 +477,8 @@ static void bfd_elf32_swap_crinfo_out
    from smaller values.  Start with zero, widen, *then* decrement.  */
 #define MINUS_ONE      (((bfd_vma)0) - 1)
 
    from smaller values.  Start with zero, widen, *then* decrement.  */
 #define MINUS_ONE      (((bfd_vma)0) - 1)
 
-static reloc_howto_type elf_mips_howto_table[] = {
+static reloc_howto_type elf_mips_howto_table[] =
+{
   /* No relocation.  */
   HOWTO (R_MIPS_NONE,          /* type */
         0,                     /* rightshift */
   /* No relocation.  */
   HOWTO (R_MIPS_NONE,          /* type */
         0,                     /* rightshift */
@@ -520,7 +549,7 @@ static reloc_howto_type elf_mips_howto_table[] = {
         complain_overflow_dont, /* complain_on_overflow */
                                /* This needs complex overflow
                                   detection, because the upper four
         complain_overflow_dont, /* complain_on_overflow */
                                /* This needs complex overflow
                                   detection, because the upper four
-                                  bits must match the PC.  */
+                                  bits must match the PC + 4.  */
         bfd_elf_generic_reloc, /* special_function */
         "R_MIPS_26",           /* name */
         true,                  /* partial_inplace */
         bfd_elf_generic_reloc, /* special_function */
         "R_MIPS_26",           /* name */
         true,                  /* partial_inplace */
@@ -1067,7 +1096,8 @@ static reloc_howto_type elf_mips_gnu_vtentry_howto =
    reloc.  This extension permits gcc to output the HI and LO relocs
    itself.  */
 
    reloc.  This extension permits gcc to output the HI and LO relocs
    itself.  */
 
-struct mips_hi16 {
+struct mips_hi16
+{
   struct mips_hi16 *next;
   bfd_byte *addr;
   bfd_vma addend;
   struct mips_hi16 *next;
   bfd_byte *addr;
   bfd_vma addend;
@@ -1810,6 +1840,12 @@ elf_mips_isa (flags)
       return 3;
     case E_MIPS_ARCH_4:
       return 4;
       return 3;
     case E_MIPS_ARCH_4:
       return 4;
+    case E_MIPS_ARCH_5:
+      return 5;
+    case E_MIPS_ARCH_32:
+      return 32;
+    case E_MIPS_ARCH_64:
+      return 64;
     }
   return 4;
 }
     }
   return 4;
 }
@@ -1837,8 +1873,11 @@ elf_mips_mach (flags)
     case E_MIPS_MACH_4650:
       return bfd_mach_mips4650;
 
     case E_MIPS_MACH_4650:
       return bfd_mach_mips4650;
 
-    case E_MIPS_MACH_MIPS32:
-      return bfd_mach_mips4K;
+    case E_MIPS_MACH_MIPS32_4K:
+      return bfd_mach_mips32_4k;
+
+    case E_MIPS_MACH_SB1:
+      return bfd_mach_mips_sb1;
 
     default:
       switch (flags & EF_MIPS_ARCH)
 
     default:
       switch (flags & EF_MIPS_ARCH)
@@ -1859,6 +1898,18 @@ elf_mips_mach (flags)
        case E_MIPS_ARCH_4:
          return bfd_mach_mips8000;
          break;
        case E_MIPS_ARCH_4:
          return bfd_mach_mips8000;
          break;
+
+       case E_MIPS_ARCH_5:
+         return bfd_mach_mips5;
+         break;
+
+       case E_MIPS_ARCH_32:
+         return bfd_mach_mips32;
+         break;
+
+       case E_MIPS_ARCH_64:
+         return bfd_mach_mips64;
+         break;
        }
     }
 
        }
     }
 
@@ -1903,7 +1954,8 @@ struct elf_reloc_map {
   enum elf_mips_reloc_type elf_reloc_val;
 };
 
   enum elf_mips_reloc_type elf_reloc_val;
 };
 
-static CONST struct elf_reloc_map mips_reloc_map[] = {
+static CONST struct elf_reloc_map mips_reloc_map[] =
+{
   { BFD_RELOC_NONE, R_MIPS_NONE, },
   { BFD_RELOC_16, R_MIPS_16 },
   { BFD_RELOC_32, R_MIPS_32 },
   { BFD_RELOC_NONE, R_MIPS_NONE, },
   { BFD_RELOC_16, R_MIPS_16 },
   { BFD_RELOC_32, R_MIPS_32 },
@@ -2261,7 +2313,12 @@ mips_elf_sym_is_global (abfd, sym)
      bfd *abfd ATTRIBUTE_UNUSED;
      asymbol *sym;
 {
      bfd *abfd ATTRIBUTE_UNUSED;
      asymbol *sym;
 {
-  return (sym->flags & BSF_SECTION_SYM) == 0 ? true : false;
+  if (SGI_COMPAT(abfd))
+    return (sym->flags & BSF_SECTION_SYM) == 0 ? true : false;
+  else
+    return ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0
+            || bfd_is_und_section (bfd_get_section (sym))
+            || bfd_is_com_section (bfd_get_section (sym)));
 }
 \f
 /* Set the right machine number for a MIPS ELF file.  This is used for
 }
 \f
 /* Set the right machine number for a MIPS ELF file.  This is used for
@@ -2336,8 +2393,24 @@ _bfd_mips_elf_final_write_processing (abfd, linker)
       val = E_MIPS_ARCH_4;
       break;
 
       val = E_MIPS_ARCH_4;
       break;
 
-    case bfd_mach_mips4K:
-      val = E_MIPS_ARCH_2 | E_MIPS_MACH_MIPS32;
+    case bfd_mach_mips32:
+      val = E_MIPS_ARCH_32;
+      break;
+
+    case bfd_mach_mips32_4k:
+      val = E_MIPS_ARCH_32 | E_MIPS_MACH_MIPS32_4K;
+      break;
+
+    case bfd_mach_mips5:
+      val = E_MIPS_ARCH_5;
+      break;
+
+    case bfd_mach_mips64:
+      val = E_MIPS_ARCH_64;
+      break;
+
+    case bfd_mach_mips_sb1:
+      val = E_MIPS_ARCH_64 | E_MIPS_MACH_SB1;
       break;
     }
 
       break;
     }
 
@@ -2460,6 +2533,8 @@ _bfd_mips_elf_merge_private_bfd_data (ibfd, obfd)
   flagword old_flags;
   flagword new_flags;
   boolean ok;
   flagword old_flags;
   flagword new_flags;
   boolean ok;
+  boolean null_input_bfd = true;
+  asection *sec;
 
   /* Check if we have the same endianess */
   if (_bfd_generic_verify_endian_match (ibfd, obfd) == false)
 
   /* Check if we have the same endianess */
   if (_bfd_generic_verify_endian_match (ibfd, obfd) == false)
@@ -2499,6 +2574,27 @@ _bfd_mips_elf_merge_private_bfd_data (ibfd, obfd)
   if (new_flags == old_flags)
     return true;
 
   if (new_flags == old_flags)
     return true;
 
+  /* Check to see if the input BFD actually contains any sections.
+     If not, its flags may not have been initialised either, but it cannot
+     actually cause any incompatibility.  */
+  for (sec = ibfd->sections; sec != NULL; sec = sec->next)
+    {
+      /* Ignore synthetic sections and empty .text, .data and .bss sections
+         which are automatically generated by gas.  */
+      if (strcmp (sec->name, ".reginfo")
+         && strcmp (sec->name, ".mdebug")
+         && ((!strcmp (sec->name, ".text")
+              || !strcmp (sec->name, ".data")
+              || !strcmp (sec->name, ".bss"))
+             && sec->_raw_size != 0))
+       {
+         null_input_bfd = false;
+         break;
+       }
+    }
+  if (null_input_bfd)
+    return true;
+
   ok = true;
 
   if ((new_flags & EF_MIPS_PIC) != (old_flags & EF_MIPS_PIC))
   ok = true;
 
   if ((new_flags & EF_MIPS_PIC) != (old_flags & EF_MIPS_PIC))
@@ -2537,13 +2633,12 @@ _bfd_mips_elf_merge_private_bfd_data (ibfd, obfd)
          || new_mach == old_mach
          )
        {
          || new_mach == old_mach
          )
        {
-         /* Don't warn about mixing -mips1 and -mips2 code, or mixing -mips3
-            and -mips4 code.  They will normally use the same data sizes and
-            calling conventions.  */
+         /* Don't warn about mixing code using 32-bit ISAs, or mixing code
+            using 64-bit ISAs.  They will normally use the same data sizes
+            and calling conventions.  */
 
 
-         if ((new_isa == 1 || new_isa == 2)
-             ? (old_isa != 1 && old_isa != 2)
-             : (old_isa == 1 || old_isa == 2))
+         if ((  (new_isa == 1 || new_isa == 2 || new_isa == 32)
+              ^ (old_isa == 1 || old_isa == 2 || old_isa == 32)) != 0)
            {
              (*_bfd_error_handler)
               (_("%s: ISA mismatch (-mips%d) with previous modules (-mips%d)"),
            {
              (*_bfd_error_handler)
               (_("%s: ISA mismatch (-mips%d) with previous modules (-mips%d)"),
@@ -2647,6 +2742,12 @@ _bfd_mips_elf_print_private_bfd_data (abfd, ptr)
     fprintf (file, _(" [mips3]"));
   else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_4)
     fprintf (file, _(" [mips4]"));
     fprintf (file, _(" [mips3]"));
   else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_4)
     fprintf (file, _(" [mips4]"));
+  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_5)
+    fprintf (file, _ (" [mips5]"));
+  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32)
+    fprintf (file, _ (" [mips32]"));
+  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_64)
+    fprintf (file, _ (" [mips64]"));
   else
     fprintf (file, _(" [unknown ISA]"));
 
   else
     fprintf (file, _(" [unknown ISA]"));
 
@@ -3426,7 +3527,8 @@ _bfd_mips_elf_modify_segment_map (abfd)
       if (m != NULL
          && m->count == 1 && strcmp (m->sections[0]->name, ".dynamic") == 0)
        {
       if (m != NULL
          && m->count == 1 && strcmp (m->sections[0]->name, ".dynamic") == 0)
        {
-         static const char *sec_names[] = {
+         static const char *sec_names[] =
+         {
            ".dynamic", ".dynstr", ".dynsym", ".hash"
          };
          bfd_vma low, high;
            ".dynamic", ".dynstr", ".dynsym", ".hash"
          };
          bfd_vma low, high;
@@ -3645,7 +3747,8 @@ mips_elf_is_local_label_name (abfd, name)
 /* MIPS ELF uses a special find_nearest_line routine in order the
    handle the ECOFF debugging information.  */
 
 /* MIPS ELF uses a special find_nearest_line routine in order the
    handle the ECOFF debugging information.  */
 
-struct mips_elf_find_line {
+struct mips_elf_find_line
+{
   struct ecoff_debug_info d;
   struct ecoff_find_line i;
 };
   struct ecoff_debug_info d;
   struct ecoff_find_line i;
 };
@@ -3671,7 +3774,8 @@ _bfd_mips_elf_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
   if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
                                     filename_ptr, functionname_ptr,
                                     line_ptr,
   if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
                                     filename_ptr, functionname_ptr,
                                     line_ptr,
-                                    ABI_64_P (abfd) ? 8 : 0))
+                                    ABI_64_P (abfd) ? 8 : 0,
+                                    &elf_tdata (abfd)->dwarf2_find_line_info))
     return true;
 
   msec = bfd_get_section_by_name (abfd, ".mdebug");
     return true;
 
   msec = bfd_get_section_by_name (abfd, ".mdebug");
@@ -3797,7 +3901,8 @@ _bfd_mips_elf_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
 
 /* MIPS ELF linker hash table.  */
 
 
 /* MIPS ELF linker hash table.  */
 
-struct mips_elf_link_hash_table {
+struct mips_elf_link_hash_table
+{
   struct elf_link_hash_table root;
 #if 0
   /* We no longer use this.  */
   struct elf_link_hash_table root;
 #if 0
   /* We no longer use this.  */
@@ -3873,6 +3978,7 @@ mips_elf_link_hash_newfunc (entry, table, string)
       ret->esym.ifd = -2;
       ret->possibly_dynamic_relocs = 0;
       ret->min_dyn_reloc_index = 0;
       ret->esym.ifd = -2;
       ret->possibly_dynamic_relocs = 0;
       ret->min_dyn_reloc_index = 0;
+      ret->no_fn_stub = false;
       ret->fn_stub = NULL;
       ret->need_fn_stub = false;
       ret->call_stub = NULL;
       ret->fn_stub = NULL;
       ret->need_fn_stub = false;
       ret->call_stub = NULL;
@@ -4091,7 +4197,8 @@ _bfd_mips_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
 
 /* Structure used to pass information to mips_elf_output_extsym.  */
 
 
 /* Structure used to pass information to mips_elf_output_extsym.  */
 
-struct extsym_info {
+struct extsym_info
+{
   bfd *abfd;
   struct bfd_link_info *info;
   struct ecoff_debug_info *debug;
   bfd *abfd;
   struct bfd_link_info *info;
   struct ecoff_debug_info *debug;
@@ -4247,24 +4354,36 @@ mips_elf_output_extsym (h, data)
     }
   else if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
     {
     }
   else if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
     {
-      /* Set type and value for a symbol with a function stub.  */
-      h->esym.asym.st = stProc;
-      sec = h->root.root.u.def.section;
-      if (sec == NULL)
-       h->esym.asym.value = 0;
-      else
+      struct mips_elf_link_hash_entry *hd = h;
+      boolean no_fn_stub = h->no_fn_stub;
+
+      while (hd->root.root.type == bfd_link_hash_indirect)
        {
        {
-         output_section = sec->output_section;
-         if (output_section != NULL)
-           h->esym.asym.value = (h->root.plt.offset
-                                 + sec->output_offset
-                                 + output_section->vma);
-         else
-           h->esym.asym.value = 0;
+         hd = (struct mips_elf_link_hash_entry *)h->root.root.u.i.link;
+         no_fn_stub = no_fn_stub || hd->no_fn_stub;
        }
        }
+
+      if (!no_fn_stub)
+       {
+         /* Set type and value for a symbol with a function stub.  */
+         h->esym.asym.st = stProc;
+         sec = hd->root.root.u.def.section;
+         if (sec == NULL)
+           h->esym.asym.value = 0;
+         else
+           {
+             output_section = sec->output_section;
+             if (output_section != NULL)
+               h->esym.asym.value = (hd->root.plt.offset
+                                     + sec->output_offset
+                                     + output_section->vma);
+             else
+               h->esym.asym.value = 0;
+           }
 #if 0 /* FIXME?  */
 #if 0 /* FIXME?  */
-      h->esym.ifd = 0;
+         h->esym.ifd = 0;
 #endif
 #endif
+       }
     }
 
   if (! bfd_ecoff_debug_one_external (einfo->abfd, einfo->debug, einfo->swap,
     }
 
   if (! bfd_ecoff_debug_one_external (einfo->abfd, einfo->debug, einfo->swap,
@@ -4466,11 +4585,13 @@ _bfd_mips_elf_final_link (abfd, info)
   EXTR esym;
   bfd_vma last;
   unsigned int i;
   EXTR esym;
   bfd_vma last;
   unsigned int i;
-  static const char * const name[] = {
+  static const char * const name[] =
+  {
     ".text", ".init", ".fini", ".data",
     ".rodata", ".sdata", ".sbss", ".bss"
   };
     ".text", ".init", ".fini", ".data",
     ".rodata", ".sdata", ".sbss", ".bss"
   };
-  static const int sc[] = {
+  static const int sc[] =
+  {
     scText, scInit, scFini, scData,
     scRData, scSData, scSBss, scBss
   };
     scText, scInit, scFini, scData,
     scRData, scSData, scSBss, scBss
   };
@@ -5389,7 +5510,8 @@ mips_elf_record_global_got_symbol (h, info, g)
 /* This structure is passed to mips_elf_sort_hash_table_f when sorting
    the dynamic symbols.  */
 
 /* This structure is passed to mips_elf_sort_hash_table_f when sorting
    the dynamic symbols.  */
 
-struct mips_elf_hash_sort_data {
+struct mips_elf_hash_sort_data
+{
   /* The symbol in the global GOT with the lowest dynamic symbol table
      index.  */
   struct elf_link_hash_entry *low;
   /* The symbol in the global GOT with the lowest dynamic symbol table
      index.  */
   struct elf_link_hash_entry *low;
@@ -5662,7 +5784,7 @@ mips_elf_next_relocation (r_type, relocation, relend)
 
 static boolean
 mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
 
 static boolean
 mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
-                                   symbol, addendp, input_section, local_p)
+                                   symbol, addendp, input_section)
      bfd *output_bfd;
      struct bfd_link_info *info;
      const Elf_Internal_Rela *rel;
      bfd *output_bfd;
      struct bfd_link_info *info;
      const Elf_Internal_Rela *rel;
@@ -5671,7 +5793,6 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
      bfd_vma symbol;
      bfd_vma *addendp;
      asection *input_section;
      bfd_vma symbol;
      bfd_vma *addendp;
      asection *input_section;
-     boolean local_p;
 {
   Elf_Internal_Rel outrel;
   boolean skip;
 {
   Elf_Internal_Rel outrel;
   boolean skip;
@@ -5756,15 +5877,16 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
          /* The relocation we're building is section-relative.
             Therefore, the original addend must be adjusted by the
             section offset.  */
          /* The relocation we're building is section-relative.
             Therefore, the original addend must be adjusted by the
             section offset.  */
-         *addendp += symbol - sec->output_section->vma;
+         *addendp += section_offset;
          /* Now, the relocation is just against the section.  */
          symbol = sec->output_section->vma;
        }
 
          /* Now, the relocation is just against the section.  */
          symbol = sec->output_section->vma;
        }
 
-      /* If the relocation is against a local symbol was previously an
-        absolute relocation, we must adjust it by the value we give
-        it in the dynamic symbol table.  */
-      if (local_p && r_type != R_MIPS_REL32)
+      /* If the relocation was previously an absolute relocation and
+        this symbol will not be referred to by the relocation, we must
+        adjust it by the value we give it in the dynamic symbol table.
+        Otherwise leave the job up to the dynamic linker.  */
+      if (!indx && r_type != R_MIPS_REL32)
        *addendp += symbol;
 
       /* The relocation is always an REL32 relocation because we don't
        *addendp += symbol;
 
       /* The relocation is always an REL32 relocation because we don't
@@ -6139,7 +6261,7 @@ mips_elf_calculate_relocation (abfd,
                                 symbol + addend, sgot->contents + g);
            }
        }
                                 symbol + addend, sgot->contents + g);
            }
        }
-      else if (r_type == R_MIPS_GOT16)
+      else if (r_type == R_MIPS_GOT16 || r_type == R_MIPS_CALL16)
        /* There's no need to create a local GOT entry here; the
           calculation for a local GOT16 entry does not involve G.  */
        break;
        /* There's no need to create a local GOT entry here; the
           calculation for a local GOT16 entry does not involve G.  */
        break;
@@ -6202,7 +6324,7 @@ mips_elf_calculate_relocation (abfd,
                                                   sec,
                                                   symbol,
                                                   &value,
                                                   sec,
                                                   symbol,
                                                   &value,
-                                                  input_section, local_p))
+                                                  input_section))
            return false;
        }
       else
            return false;
        }
       else
@@ -6234,14 +6356,14 @@ mips_elf_calculate_relocation (abfd,
       break;
 
     case R_MIPS16_26:
       break;
 
     case R_MIPS16_26:
-      /* The calculation for R_MIPS_26 is just the same as for an
+      /* The calculation for R_MIPS16_26 is just the same as for an
         R_MIPS_26.  It's only the storage of the relocated field into
         the output file that's different.  That's handled in
         mips_elf_perform_relocation.  So, we just fall through to the
         R_MIPS_26 case here.  */
     case R_MIPS_26:
       if (local_p)
         R_MIPS_26.  It's only the storage of the relocated field into
         the output file that's different.  That's handled in
         mips_elf_perform_relocation.  So, we just fall through to the
         R_MIPS_26 case here.  */
     case R_MIPS_26:
       if (local_p)
-       value = (((addend << 2) | (p & 0xf0000000)) + symbol) >> 2;
+       value = (((addend << 2) | ((p + 4) & 0xf0000000)) + symbol) >> 2;
       else
        value = (mips_elf_sign_extend (addend << 2, 28) + symbol) >> 2;
       value &= howto->dst_mask;
       else
        value = (mips_elf_sign_extend (addend << 2, 28) + symbol) >> 2;
       value &= howto->dst_mask;
@@ -6307,6 +6429,7 @@ mips_elf_calculate_relocation (abfd,
       break;
 
     case R_MIPS_GOT16:
       break;
 
     case R_MIPS_GOT16:
+    case R_MIPS_CALL16:
       if (local_p)
        {
          boolean forced;
       if (local_p)
        {
          boolean forced;
@@ -6329,7 +6452,6 @@ mips_elf_calculate_relocation (abfd,
 
       /* Fall through.  */
 
 
       /* Fall through.  */
 
-    case R_MIPS_CALL16:
     case R_MIPS_GOT_DISP:
       value = g;
       overflowed_p = mips_elf_overflow_p (value, 16);
     case R_MIPS_GOT_DISP:
       value = g;
       overflowed_p = mips_elf_overflow_p (value, 16);
@@ -6534,9 +6656,9 @@ mips_elf_perform_relocation (info, howto, relocation, value,
         ((sub1 << 16) | sub2)).
 
         When producing a relocateable object file, the calculation is
         ((sub1 << 16) | sub2)).
 
         When producing a relocateable object file, the calculation is
-        (((A < 2) | (P & 0xf0000000) + S) >> 2)
+        (((A < 2) | ((P + 4) & 0xf0000000) + S) >> 2)
         When producing a fully linked file, the calculation is
         When producing a fully linked file, the calculation is
-        let R = (((A < 2) | (P & 0xf0000000) + S) >> 2)
+        let R = (((A < 2) | ((P + 4) & 0xf0000000) + S) >> 2)
         ((R & 0x1f0000) << 5) | ((R & 0x3e00000) >> 5) | (R & 0xffff)  */
 
       if (!info->relocateable)
         ((R & 0x1f0000) << 5) | ((R & 0x3e00000) >> 5) | (R & 0xffff)  */
 
       if (!info->relocateable)
@@ -6544,7 +6666,6 @@ mips_elf_perform_relocation (info, howto, relocation, value,
        value = (((value & 0x1f0000) << 5)
                 | ((value & 0x3e00000) >> 5)
                 | (value & 0xffff));
        value = (((value & 0x1f0000) << 5)
                 | ((value & 0x3e00000) >> 5)
                 | (value & 0xffff));
-
     }
   else if (r_type == R_MIPS16_GPREL)
     {
     }
   else if (r_type == R_MIPS16_GPREL)
     {
@@ -6667,6 +6788,7 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
          REL relocation.  */
       boolean rela_relocation_p = true;
       int r_type = ELF32_R_TYPE (rel->r_info);
          REL relocation.  */
       boolean rela_relocation_p = true;
       int r_type = ELF32_R_TYPE (rel->r_info);
+      const char * msg = (const char *) NULL;
 
       /* Find the relocation howto for this relocation.  */
       if (r_type == R_MIPS_64 && !ABI_64_P (output_bfd))
 
       /* Find the relocation howto for this relocation.  */
       if (r_type == R_MIPS_64 && !ABI_64_P (output_bfd))
@@ -6921,8 +7043,10 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
          continue;
 
        case bfd_reloc_notsupported:
          continue;
 
        case bfd_reloc_notsupported:
-         abort ();
-         break;
+         msg = _("internal error: unsupported relocation error");
+         info->callbacks->warning
+           (info, msg, name, input_bfd, input_section, rel->r_offset);
+         return false;
 
        case bfd_reloc_overflow:
          if (use_saved_addend_p)
 
        case bfd_reloc_overflow:
          if (use_saved_addend_p)
@@ -7643,10 +7767,10 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
          /* We may need a local GOT entry for this relocation.  We
             don't count R_MIPS_GOT_PAGE because we can estimate the
             maximum number of pages needed by looking at the size of
          /* We may need a local GOT entry for this relocation.  We
             don't count R_MIPS_GOT_PAGE because we can estimate the
             maximum number of pages needed by looking at the size of
-            the segment.  Similar comments apply to R_MIPS_GOT16.  We
-            don't count R_MIPS_GOT_HI16, or R_MIPS_CALL_HI16 because
-            these are always followed by an R_MIPS_GOT_LO16 or
-            R_MIPS_CALL_LO16.
+            the segment.  Similar comments apply to R_MIPS_GOT16 and
+            R_MIPS_CALL16.  We don't count R_MIPS_GOT_HI16, or
+            R_MIPS_CALL_HI16 because these are always followed by an
+            R_MIPS_GOT_LO16 or R_MIPS_CALL_LO16.
 
             This estimation is very conservative since we can merge
             duplicate entries in the GOT.  In order to be less
 
             This estimation is very conservative since we can merge
             duplicate entries in the GOT.  In order to be less
@@ -7778,6 +7902,25 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
          break;
        }
 
          break;
        }
 
+      /* We must not create a stub for a symbol that has relocations
+         related to taking the function's address.  */
+      switch (r_type)
+       {
+       default:
+         if (h != NULL)
+           {
+             struct mips_elf_link_hash_entry *mh;
+
+             mh = (struct mips_elf_link_hash_entry *) h;
+             mh->no_fn_stub = true;
+           }
+         break;
+       case R_MIPS_CALL16:
+       case R_MIPS_CALL_HI16:
+       case R_MIPS_CALL_LO16:
+         break;
+       }
+
       /* If this reloc is not a 16 bit call, and it has a global
          symbol, then we will need the fn_stub if there is one.
          References from a stub section do not count.  */
       /* If this reloc is not a 16 bit call, and it has a global
          symbol, then we will need the fn_stub if there is one.
          References from a stub section do not count.  */
@@ -7913,6 +8056,8 @@ _bfd_mips_elf_copy_indirect_symbol (dir, ind)
       || (indmips->min_dyn_reloc_index != 0
          && indmips->min_dyn_reloc_index < dirmips->min_dyn_reloc_index))
     dirmips->min_dyn_reloc_index = indmips->min_dyn_reloc_index;
       || (indmips->min_dyn_reloc_index != 0
          && indmips->min_dyn_reloc_index < dirmips->min_dyn_reloc_index))
     dirmips->min_dyn_reloc_index = indmips->min_dyn_reloc_index;
+  if (indmips->no_fn_stub)
+    dirmips->no_fn_stub = true;
 }
 
 /* Adjust a symbol defined by a dynamic object and referenced by a
 }
 
 /* Adjust a symbol defined by a dynamic object and referenced by a
@@ -7953,8 +8098,9 @@ _bfd_mips_elf_adjust_dynamic_symbol (info, h)
     mips_elf_allocate_dynamic_relocations (dynobj,
                                           hmips->possibly_dynamic_relocs);
 
     mips_elf_allocate_dynamic_relocations (dynobj,
                                           hmips->possibly_dynamic_relocs);
 
-  /* For a function, create a stub, if needed.  */
-  if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
+  /* For a function, create a stub, if allowed.  */
+  if (! hmips->no_fn_stub
+      && (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
     {
       if (! elf_hash_table (info)->dynamic_sections_created)
        return true;
     {
       if (! elf_hash_table (info)->dynamic_sections_created)
        return true;
This page took 0.031737 seconds and 4 git commands to generate.