s/struct _serial_t/struct serial/
[deliverable/binutils-gdb.git] / bfd / elf32-mips.c
index f1a1ac37bfa7851d014f785e4510bb1f87d85d79..baeb01fc12216da9758ea45832631b098cd42d5b 100644 (file)
@@ -76,6 +76,10 @@ struct mips_elf_link_hash_entry
      this symbol.  */
   unsigned int possibly_dynamic_relocs;
 
+  /* If the R_MIPS_32, R_MIPS_REL32, or R_MIPS_64 reloc is against
+     a readonly section.  */
+  boolean readonly_reloc;
+
   /* The index of the first dynamic relocation (in the .rel.dyn
      section) against this symbol.  */
   unsigned int min_dyn_reloc_index;
@@ -208,6 +212,11 @@ static int sort_dynamic_relocs
   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.  */
 
@@ -225,20 +234,27 @@ static bfd *reldyn_sorting_bfd;
 #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.  */
-
+#ifdef BFD64
+#define IRIX_COMPAT(abfd) \
+  (((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))
+#else
 #define IRIX_COMPAT(abfd) \
-  (abfd->xvec == &bfd_elf32_tradbigmips_vec ? ict_none : \
+  (((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) \
   (IRIX_COMPAT (abfd) != ict_none)
 
@@ -527,7 +543,7 @@ static reloc_howto_type elf_mips_howto_table[] =
         0xffffffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
-  /* 26 bit branch address.  */
+  /* 26 bit jump address.  */
   HOWTO (R_MIPS_26,            /* type */
         2,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
@@ -1655,7 +1671,7 @@ gprel32_with_gp (abfd, symbol, reloc_entry, input_section, relocateable, data,
 }
 
 /* Handle a 64 bit reloc in a 32 bit MIPS ELF file.  These are
-   generated when addreses are 64 bits.  The upper 32 bits are a simle
+   generated when addresses are 64 bits.  The upper 32 bits are a simple
    sign extension.  */
 
 static bfd_reloc_status_type
@@ -2301,7 +2317,12 @@ mips_elf_sym_is_global (abfd, 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;
+  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
@@ -2314,7 +2335,8 @@ _bfd_mips_elf_object_p (abfd)
   /* Irix 5 and 6 is broken.  Object file symbol tables are not always
      sorted correctly such that local symbols precede global symbols,
      and the sh_info field in the symbol table is not always right.  */
-  elf_bad_symtab (abfd) = true;
+  if (SGI_COMPAT(abfd))
+    elf_bad_symtab (abfd) = true;
 
   bfd_default_set_arch_mach (abfd, bfd_arch_mips,
                             elf_mips_mach (elf_elfheader (abfd)->e_flags));
@@ -2353,6 +2375,8 @@ _bfd_mips_elf_final_write_processing (abfd, linker)
 
     case bfd_mach_mips4000:
     case bfd_mach_mips4300:
+    case bfd_mach_mips4400:
+    case bfd_mach_mips4600:
       val = E_MIPS_ARCH_3;
       break;
 
@@ -2372,7 +2396,10 @@ _bfd_mips_elf_final_write_processing (abfd, linker)
       val = E_MIPS_ARCH_3 | E_MIPS_MACH_4650;
       break;
 
+    case bfd_mach_mips5000:
     case bfd_mach_mips8000:
+    case bfd_mach_mips10000:
+    case bfd_mach_mips12000:
       val = E_MIPS_ARCH_4;
       break;
 
@@ -3055,7 +3082,7 @@ _bfd_mips_elf_fake_sections (abfd, hdr, sec)
 boolean
 _bfd_mips_elf_section_from_bfd_section (abfd, hdr, sec, retval)
      bfd *abfd ATTRIBUTE_UNUSED;
-     Elf32_Internal_Shdr *hdr ATTRIBUTE_UNUSED;
+     Elf_Internal_Shdr *hdr ATTRIBUTE_UNUSED;
      asection *sec;
      int *retval;
 {
@@ -3960,6 +3987,7 @@ mips_elf_link_hash_newfunc (entry, table, string)
         not been set.  -1 means there is no associated ifd.  */
       ret->esym.ifd = -2;
       ret->possibly_dynamic_relocs = 0;
+      ret->readonly_reloc = false;
       ret->min_dyn_reloc_index = 0;
       ret->no_fn_stub = false;
       ret->fn_stub = NULL;
@@ -3985,7 +4013,8 @@ _bfd_mips_elf_hide_symbol (info, h)
 
   h->root.elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
   h->root.plt.offset = (bfd_vma) -1;
-  h->root.dynindx = -1;
+  if ((h->root.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)
+    h->root.dynindx = -1;
 
   /* FIXME: Do we allocate too much GOT space here?  */
   g->local_gotno++;
@@ -6771,6 +6800,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);
+      const char * msg = (const char *) NULL;
 
       /* Find the relocation howto for this relocation.  */
       if (r_type == R_MIPS_64 && !ABI_64_P (output_bfd))
@@ -6803,8 +6833,7 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
             REL_HDR is read before its REL_HDR2.  */
          rel_hdr = &elf_section_data (input_section)->rel_hdr;
          if ((size_t) (rel - relocs)
-             >= (rel_hdr->sh_size / rel_hdr->sh_entsize
-                 * bed->s->int_rels_per_ext_rel))
+             >= (NUM_SHDR_ENTRIES (rel_hdr) * bed->s->int_rels_per_ext_rel))
            rel_hdr = elf_section_data (input_section)->rel_hdr2;
          if (rel_hdr->sh_entsize == MIPS_ELF_REL_SIZE (input_bfd))
            {
@@ -7025,8 +7054,10 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
          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)
@@ -7571,7 +7602,7 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
              asection **n;
 
              if (elf_bad_symtab (abfd))
-               symcount = symtab_hdr->sh_size / symtab_hdr->sh_entsize;
+               symcount = NUM_SHDR_ENTRIES (symtab_hdr);
              else
                symcount = symtab_hdr->sh_info;
              n = (asection **) bfd_zalloc (abfd,
@@ -7686,7 +7717,7 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
 
       if (r_symndx < extsymoff)
        h = NULL;
-      else if (r_symndx >= extsymoff + (symtab_hdr->sh_size / symtab_hdr->sh_entsize))
+      else if (r_symndx >= extsymoff + NUM_SHDR_ENTRIES (symtab_hdr))
        {
          (*_bfd_error_handler)
            (_("Malformed reloc detected for section %s"), name);
@@ -7825,12 +7856,20 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
                        return false;
                    }
                }
+#define MIPS_READONLY_SECTION (SEC_ALLOC | SEC_LOAD | SEC_READONLY)
              if (info->shared)
-               /* When creating a shared object, we must copy these
-                  reloc types into the output file as R_MIPS_REL32
-                  relocs.  We make room for this reloc in the
-                  .rel.dyn reloc section.  */
-               mips_elf_allocate_dynamic_relocations (dynobj, 1);
+               {
+                 /* When creating a shared object, we must copy these
+                    reloc types into the output file as R_MIPS_REL32
+                    relocs.  We make room for this reloc in the
+                    .rel.dyn reloc section.  */
+                 mips_elf_allocate_dynamic_relocations (dynobj, 1);
+                 if ((sec->flags & MIPS_READONLY_SECTION)
+                     == MIPS_READONLY_SECTION)
+                   /* We tell the dynamic linker that there are
+                      relocations against the text segment.  */
+                   info->flags |= DF_TEXTREL;
+               }
              else
                {
                  struct mips_elf_link_hash_entry *hmips;
@@ -7839,6 +7878,11 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
                      defined in a dynamic object.  */
                  hmips = (struct mips_elf_link_hash_entry *) h;
                  ++hmips->possibly_dynamic_relocs;
+                 if ((sec->flags & MIPS_READONLY_SECTION)
+                     == MIPS_READONLY_SECTION)
+                   /* We need it to tell the dynamic linker if there
+                      are relocations against the text segment.  */
+                   hmips->readonly_reloc = true;
                }
 
              /* Even though we don't directly need a GOT entry for
@@ -8032,6 +8076,8 @@ _bfd_mips_elf_copy_indirect_symbol (dir, ind)
   dirmips = (struct mips_elf_link_hash_entry *) dir;
   indmips = (struct mips_elf_link_hash_entry *) ind;
   dirmips->possibly_dynamic_relocs += indmips->possibly_dynamic_relocs;
+  if (indmips->readonly_reloc)
+    dirmips->readonly_reloc = true;
   if (dirmips->min_dyn_reloc_index == 0
       || (indmips->min_dyn_reloc_index != 0
          && indmips->min_dyn_reloc_index < dirmips->min_dyn_reloc_index))
@@ -8075,8 +8121,14 @@ _bfd_mips_elf_adjust_dynamic_symbol (info, h)
   if (! info->relocateable
       && hmips->possibly_dynamic_relocs != 0
       && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
-    mips_elf_allocate_dynamic_relocations (dynobj,
-                                          hmips->possibly_dynamic_relocs);
+    {
+      mips_elf_allocate_dynamic_relocations (dynobj,
+                                            hmips->possibly_dynamic_relocs);
+      if (hmips->readonly_reloc)
+       /* We tell the dynamic linker that there are relocations
+          against the text segment.  */
+       info->flags |= DF_TEXTREL;
+    }
 
   /* For a function, create a stub, if allowed.  */
   if (! hmips->no_fn_stub
@@ -8312,7 +8364,7 @@ _bfd_mips_elf_size_dynamic_sections (output_bfd, info)
          int i;
          bfd_size_type loadable_size = 0;
          bfd_size_type local_gotno;
-         struct _bfd *sub;
+         bfd *sub;
 
          BFD_ASSERT (elf_section_data (s) != NULL);
          g = (struct mips_got_info *) elf_section_data (s)->tdata;
@@ -8436,11 +8488,14 @@ _bfd_mips_elf_size_dynamic_sections (output_bfd, info)
                return false;
            }
        }
+
       if (reltext && SGI_COMPAT (output_bfd))
+       info->flags |= DF_TEXTREL;
+
+      if ((info->flags & DF_TEXTREL) != 0)
        {
          if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_TEXTREL, 0))
            return false;
-         info->flags |= DF_TEXTREL;
        }
 
       if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTGOT, 0))
@@ -9082,6 +9137,70 @@ _bfd_mips_elf_finish_dynamic_sections (output_bfd, info)
   return true;
 }
 \f
+/* Support for core dump NOTE sections */
+static boolean
+_bfd_elf32_mips_grok_prstatus (abfd, note)
+     bfd *abfd;
+     Elf_Internal_Note *note;
+{
+  int offset;
+  int raw_size;
+
+  switch (note->descsz)
+    {
+      default:
+       return false;
+
+      case 256:                /* Linux/MIPS */
+       /* pr_cursig */
+       elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
+
+       /* pr_pid */
+       elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24);
+
+       /* pr_reg */
+       offset = 72;
+       raw_size = 180;
+
+       break;
+    }
+
+  /* Make a ".reg/999" section.  */
+  return _bfd_elfcore_make_pseudosection (abfd, ".reg",
+                                         raw_size, note->descpos + offset);
+}
+
+static boolean _bfd_elf32_mips_grok_psinfo (abfd, note)
+     bfd *abfd;
+     Elf_Internal_Note *note;
+{
+  switch (note->descsz)
+    {
+      default:
+       return false;
+
+      case 128:                /* Linux/MIPS elf_prpsinfo */
+       elf_tdata (abfd)->core_program
+        = _bfd_elfcore_strndup (abfd, note->descdata + 32, 16);
+       elf_tdata (abfd)->core_command
+        = _bfd_elfcore_strndup (abfd, note->descdata + 48, 80);
+    }
+
+  /* Note that for some reason, a spurious space is tacked
+     onto the end of the args in some (at least one anyway)
+     implementations, so strip it off if it exists.  */
+
+  {
+    char *command = elf_tdata (abfd)->core_command;
+    int n = strlen (command);
+
+    if (0 < n && command[n - 1] == ' ')
+      command[n - 1] = '\0';
+  }
+
+  return true;
+}
+\f
 /* This is almost identical to bfd_generic_get_... except that some
    MIPS relocations need to be handled specially.  Sigh.  */
 
@@ -9369,6 +9488,8 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = {
                                        _bfd_mips_elf_copy_indirect_symbol
 
 #define elf_backend_hide_symbol                _bfd_mips_elf_hide_symbol
+#define elf_backend_grok_prstatus      _bfd_elf32_mips_grok_prstatus
+#define elf_backend_grok_psinfo                _bfd_elf32_mips_grok_psinfo
 
 #define bfd_elf32_bfd_is_local_label_name \
                                        mips_elf_is_local_label_name
This page took 0.0673 seconds and 4 git commands to generate.