Back to index

cell-binutils  2.17cvs20070401
Defines | Functions
elfxx-mips.h File Reference
#include "elf/common.h"
#include "elf/internal.h"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define elf_backend_common_definition   _bfd_mips_elf_common_definition
#define elf_backend_name_local_section_symbols   _bfd_mips_elf_name_local_section_symbols
#define elf_backend_special_sections   _bfd_mips_elf_special_sections
#define elf_backend_eh_frame_address_size   _bfd_mips_elf_eh_frame_address_size
#define elf_backend_merge_symbol_attribute   _bfd_mips_elf_merge_symbol_attribute
#define elf_backend_ignore_undef_symbol   _bfd_mips_elf_ignore_undef_symbol

Functions

bfd_boolean _bfd_mips_elf_new_section_hook (bfd *, asection *)
void _bfd_mips_elf_symbol_processing (bfd *, asymbol *)
unsigned int _bfd_mips_elf_eh_frame_address_size (bfd *, asection *)
bfd_boolean _bfd_mips_elf_name_local_section_symbols (bfd *)
bfd_boolean _bfd_mips_elf_section_processing (bfd *, Elf_Internal_Shdr *)
bfd_boolean _bfd_mips_elf_section_from_shdr (bfd *, Elf_Internal_Shdr *, const char *, int)
bfd_boolean _bfd_mips_elf_fake_sections (bfd *, Elf_Internal_Shdr *, asection *)
bfd_boolean _bfd_mips_elf_section_from_bfd_section (bfd *, asection *, int *)
bfd_boolean _bfd_mips_elf_add_symbol_hook (bfd *, struct bfd_link_info *, Elf_Internal_Sym *, const char **, flagword *, asection **, bfd_vma *)
bfd_boolean _bfd_mips_elf_link_output_symbol_hook (struct bfd_link_info *, const char *, Elf_Internal_Sym *, asection *, struct elf_link_hash_entry *)
bfd_boolean _bfd_mips_elf_create_dynamic_sections (bfd *, struct bfd_link_info *)
bfd_boolean _bfd_mips_elf_check_relocs (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *)
bfd_boolean _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *, struct elf_link_hash_entry *)
bfd_boolean _bfd_mips_vxworks_adjust_dynamic_symbol (struct bfd_link_info *, struct elf_link_hash_entry *)
bfd_boolean _bfd_mips_elf_always_size_sections (bfd *, struct bfd_link_info *)
bfd_boolean _bfd_mips_elf_size_dynamic_sections (bfd *, struct bfd_link_info *)
bfd_boolean _bfd_mips_elf_relocate_section (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)
bfd_boolean _bfd_mips_elf_finish_dynamic_symbol (bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, Elf_Internal_Sym *)
bfd_boolean _bfd_mips_vxworks_finish_dynamic_symbol (bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, Elf_Internal_Sym *)
bfd_boolean _bfd_mips_elf_finish_dynamic_sections (bfd *, struct bfd_link_info *)
void _bfd_mips_elf_final_write_processing (bfd *, bfd_boolean)
int _bfd_mips_elf_additional_program_headers (bfd *, struct bfd_link_info *)
bfd_boolean _bfd_mips_elf_modify_segment_map (bfd *, struct bfd_link_info *)
asection_bfd_mips_elf_gc_mark_hook (asection *, struct bfd_link_info *, Elf_Internal_Rela *, struct elf_link_hash_entry *, Elf_Internal_Sym *)
bfd_boolean _bfd_mips_elf_gc_sweep_hook (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *)
void _bfd_mips_elf_copy_indirect_symbol (struct bfd_link_info *, struct elf_link_hash_entry *, struct elf_link_hash_entry *)
void _bfd_mips_elf_hide_symbol (struct bfd_link_info *, struct elf_link_hash_entry *, bfd_boolean)
bfd_boolean _bfd_mips_elf_ignore_discarded_relocs (asection *)
bfd_boolean _bfd_mips_elf_find_nearest_line (bfd *, asection *, asymbol **, bfd_vma, const char **, const char **, unsigned int *)
bfd_boolean _bfd_mips_elf_find_inliner_info (bfd *, const char **, const char **, unsigned int *)
bfd_boolean _bfd_mips_elf_set_section_contents (bfd *, asection *, const void *, file_ptr, bfd_size_type)
bfd_byte_bfd_elf_mips_get_relocated_section_contents (bfd *, struct bfd_link_info *, struct bfd_link_order *, bfd_byte *, bfd_boolean, asymbol **)
struct bfd_link_hash_table_bfd_mips_elf_link_hash_table_create (bfd *)
struct bfd_link_hash_table_bfd_mips_vxworks_link_hash_table_create (bfd *)
bfd_boolean _bfd_mips_elf_final_link (bfd *, struct bfd_link_info *)
bfd_boolean _bfd_mips_elf_merge_private_bfd_data (bfd *, bfd *)
bfd_boolean _bfd_mips_elf_set_private_flags (bfd *, flagword)
bfd_boolean _bfd_mips_elf_print_private_bfd_data (bfd *, void *)
bfd_boolean _bfd_mips_elf_discard_info (bfd *, struct elf_reloc_cookie *, struct bfd_link_info *)
bfd_boolean _bfd_mips_elf_write_section (bfd *, struct bfd_link_info *, asection *, bfd_byte *)
bfd_boolean _bfd_mips_elf_read_ecoff_info (bfd *, asection *, struct ecoff_debug_info *)
void _bfd_mips16_elf_reloc_unshuffle (bfd *, int, bfd_boolean, bfd_byte *)
void _bfd_mips16_elf_reloc_shuffle (bfd *, int, bfd_boolean, bfd_byte *)
bfd_reloc_status_type _bfd_mips_elf_gprel16_with_gp (bfd *, asymbol *, arelent *, asection *, bfd_boolean, void *, bfd_vma)
bfd_reloc_status_type _bfd_mips_elf32_gprel16_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **)
bfd_reloc_status_type _bfd_mips_elf_hi16_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **)
bfd_reloc_status_type _bfd_mips_elf_got16_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **)
bfd_reloc_status_type _bfd_mips_elf_lo16_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **)
bfd_reloc_status_type _bfd_mips_elf_generic_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **)
unsigned long _bfd_elf_mips_mach (flagword)
bfd_boolean _bfd_mips_relax_section (bfd *, asection *, struct bfd_link_info *, bfd_boolean *)
bfd_vma _bfd_mips_elf_sign_extend (bfd_vma, int)
void _bfd_mips_elf_merge_symbol_attribute (struct elf_link_hash_entry *, const Elf_Internal_Sym *, bfd_boolean, bfd_boolean)
bfd_boolean _bfd_mips_elf_ignore_undef_symbol (struct elf_link_hash_entry *)
bfd_boolean _bfd_mips_elf_common_definition (Elf_Internal_Sym *)

Define Documentation

Definition at line 147 of file elfxx-mips.h.

Definition at line 151 of file elfxx-mips.h.

Definition at line 153 of file elfxx-mips.h.

Definition at line 152 of file elfxx-mips.h.

Definition at line 148 of file elfxx-mips.h.

#define elf_backend_special_sections   _bfd_mips_elf_special_sections

Definition at line 150 of file elfxx-mips.h.


Function Documentation

Definition at line 10011 of file elfxx-mips.c.

{
  /* Get enough memory to hold the stuff */
  bfd *input_bfd = link_order->u.indirect.section->owner;
  asection *input_section = link_order->u.indirect.section;
  bfd_size_type sz;

  long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
  arelent **reloc_vector = NULL;
  long reloc_count;

  if (reloc_size < 0)
    goto error_return;

  reloc_vector = bfd_malloc (reloc_size);
  if (reloc_vector == NULL && reloc_size != 0)
    goto error_return;

  /* read in the section */
  sz = input_section->rawsize ? input_section->rawsize : input_section->size;
  if (!bfd_get_section_contents (input_bfd, input_section, data, 0, sz))
    goto error_return;

  reloc_count = bfd_canonicalize_reloc (input_bfd,
                                   input_section,
                                   reloc_vector,
                                   symbols);
  if (reloc_count < 0)
    goto error_return;

  if (reloc_count > 0)
    {
      arelent **parent;
      /* for mips */
      int gp_found;
      bfd_vma gp = 0x12345678;     /* initialize just to shut gcc up */

      {
       struct bfd_hash_entry *h;
       struct bfd_link_hash_entry *lh;
       /* Skip all this stuff if we aren't mixing formats.  */
       if (abfd && input_bfd
           && abfd->xvec == input_bfd->xvec)
         lh = 0;
       else
         {
           h = bfd_hash_lookup (&link_info->hash->table, "_gp", FALSE, FALSE);
           lh = (struct bfd_link_hash_entry *) h;
         }
      lookup:
       if (lh)
         {
           switch (lh->type)
             {
             case bfd_link_hash_undefined:
             case bfd_link_hash_undefweak:
             case bfd_link_hash_common:
              gp_found = 0;
              break;
             case bfd_link_hash_defined:
             case bfd_link_hash_defweak:
              gp_found = 1;
              gp = lh->u.def.value;
              break;
             case bfd_link_hash_indirect:
             case bfd_link_hash_warning:
              lh = lh->u.i.link;
              /* @@FIXME  ignoring warning for now */
              goto lookup;
             case bfd_link_hash_new:
             default:
              abort ();
             }
         }
       else
         gp_found = 0;
      }
      /* end mips */
      for (parent = reloc_vector; *parent != NULL; parent++)
       {
         char *error_message = NULL;
         bfd_reloc_status_type r;

         /* Specific to MIPS: Deal with relocation types that require
            knowing the gp of the output bfd.  */
         asymbol *sym = *(*parent)->sym_ptr_ptr;

         /* If we've managed to find the gp and have a special
            function for the relocation then go ahead, else default
            to the generic handling.  */
         if (gp_found
             && (*parent)->howto->special_function
             == _bfd_mips_elf32_gprel16_reloc)
           r = _bfd_mips_elf_gprel16_with_gp (input_bfd, sym, *parent,
                                          input_section, relocatable,
                                          data, gp);
         else
           r = bfd_perform_relocation (input_bfd, *parent, data,
                                   input_section,
                                   relocatable ? abfd : NULL,
                                   &error_message);

         if (relocatable)
           {
             asection *os = input_section->output_section;

             /* A partial link, so keep the relocs */
             os->orelocation[os->reloc_count] = *parent;
             os->reloc_count++;
           }

         if (r != bfd_reloc_ok)
           {
             switch (r)
              {
              case bfd_reloc_undefined:
                if (!((*link_info->callbacks->undefined_symbol)
                     (link_info, bfd_asymbol_name (*(*parent)->sym_ptr_ptr),
                      input_bfd, input_section, (*parent)->address, TRUE)))
                  goto error_return;
                break;
              case bfd_reloc_dangerous:
                BFD_ASSERT (error_message != NULL);
                if (!((*link_info->callbacks->reloc_dangerous)
                     (link_info, error_message, input_bfd, input_section,
                      (*parent)->address)))
                  goto error_return;
                break;
              case bfd_reloc_overflow:
                if (!((*link_info->callbacks->reloc_overflow)
                     (link_info, NULL,
                      bfd_asymbol_name (*(*parent)->sym_ptr_ptr),
                      (*parent)->howto->name, (*parent)->addend,
                      input_bfd, input_section, (*parent)->address)))
                  goto error_return;
                break;
              case bfd_reloc_outofrange:
              default:
                abort ();
                break;
              }

           }
       }
    }
  if (reloc_vector != NULL)
    free (reloc_vector);
  return data;

error_return:
  if (reloc_vector != NULL)
    free (reloc_vector);
  return NULL;
}

Here is the call graph for this function:

Definition at line 4975 of file elfxx-mips.c.

Here is the caller graph for this function:

void _bfd_mips16_elf_reloc_shuffle ( bfd ,
int  ,
bfd_boolean  ,
bfd_byte  
)

Definition at line 1276 of file elfxx-mips.c.

{
  bfd_vma extend, insn, val;

  if (r_type != R_MIPS16_26 && r_type != R_MIPS16_GPREL
      && r_type != R_MIPS16_HI16 && r_type != R_MIPS16_LO16)
    return;

  val = bfd_get_32 (abfd, data);
  if (r_type == R_MIPS16_26)
    {
      if (jal_shuffle)
       {
         insn = val & 0xffff;
         extend = ((val >> 16) & 0xfc00) | ((val >> 11) & 0x3e0)
                 | ((val >> 21) & 0x1f);
       }
      else
       {
         insn = val & 0xffff;
         extend = val >> 16;
       }
    }
  else
    {
      insn = ((val >> 11) & 0xffe0) | (val & 0x1f);
      extend = ((val >> 16) & 0xf800) | ((val >> 11) & 0x1f) | (val & 0x7e0);
    }
  bfd_put_16 (abfd, insn, data + 2);
  bfd_put_16 (abfd, extend, data);
}

Here is the caller graph for this function:

Definition at line 1249 of file elfxx-mips.c.

{
  bfd_vma extend, insn, val;

  if (r_type != R_MIPS16_26 && r_type != R_MIPS16_GPREL
      && r_type != R_MIPS16_HI16 && r_type != R_MIPS16_LO16)
    return;

  /* Pick up the mips16 extend instruction and the real instruction.  */
  extend = bfd_get_16 (abfd, data);
  insn = bfd_get_16 (abfd, data + 2);
  if (r_type == R_MIPS16_26)
    {
      if (jal_shuffle)
       val = ((extend & 0xfc00) << 16) | ((extend & 0x3e0) << 11)
             | ((extend & 0x1f) << 21) | insn;
      else
       val = extend << 16 | insn;
    }
  else
    val = ((extend & 0xf800) << 16) | ((insn & 0xffe0) << 11)
         | ((extend & 0x1f) << 11) | (extend & 0x7e0) | (insn & 0x1f);
  bfd_put_32 (abfd, val, data);
}

Here is the caller graph for this function:

bfd_reloc_status_type _bfd_mips_elf32_gprel16_reloc ( bfd ,
arelent ,
asymbol ,
void *  ,
asection ,
bfd ,
char **   
)

Definition at line 971 of file elf32-mips.c.

{
  bfd_boolean relocatable;
  bfd_reloc_status_type ret;
  bfd_vma gp;

  /* R_MIPS_LITERAL relocations are defined for local symbols only.  */
  if (reloc_entry->howto->type == R_MIPS_LITERAL
      && output_bfd != NULL
      && (symbol->flags & BSF_SECTION_SYM) == 0
      && (symbol->flags & BSF_LOCAL) != 0)
    {
      *error_message = (char *)
       _("literal relocation occurs for an external symbol");
      return bfd_reloc_outofrange;
    }

  if (output_bfd != NULL)
    relocatable = TRUE;
  else
    {
      relocatable = FALSE;
      output_bfd = symbol->section->output_section->owner;
    }

  ret = mips_elf_final_gp (output_bfd, symbol, relocatable, error_message,
                        &gp);
  if (ret != bfd_reloc_ok)
    return ret;

  return _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
                                   input_section, relocatable,
                                   data, gp);
}

Here is the call graph for this function:

Here is the caller graph for this function:

bfd_boolean _bfd_mips_elf_add_symbol_hook ( bfd ,
struct bfd_link_info ,
Elf_Internal_Sym *  ,
const char **  ,
flagword ,
asection **  ,
bfd_vma  
)

Definition at line 6930 of file elfxx-mips.c.

{
  bfd *dynobj;
  struct mips_elf_link_hash_entry *hmips;
  asection *s;
  struct mips_elf_link_hash_table *htab;

  htab = mips_elf_hash_table (info);
  dynobj = elf_hash_table (info)->dynobj;

  /* Make sure we know what is going on here.  */
  BFD_ASSERT (dynobj != NULL
             && (h->needs_plt
                || h->u.weakdef != NULL
                || (h->def_dynamic
                    && h->ref_regular
                    && !h->def_regular)));

  /* If this symbol is defined in a dynamic object, we need to copy
     any R_MIPS_32 or R_MIPS_REL32 relocs against it into the output
     file.  */
  hmips = (struct mips_elf_link_hash_entry *) h;
  if (! info->relocatable
      && hmips->possibly_dynamic_relocs != 0
      && (h->root.type == bfd_link_hash_defweak
         || !h->def_regular))
    {
      mips_elf_allocate_dynamic_relocations
       (dynobj, info, 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
      && h->needs_plt)
    {
      if (! elf_hash_table (info)->dynamic_sections_created)
       return TRUE;

      /* If this symbol is not defined in a regular file, then set
        the symbol to the stub location.  This is required to make
        function pointers compare as equal between the normal
        executable and the shared library.  */
      if (!h->def_regular)
       {
         /* We need .stub section.  */
         s = bfd_get_section_by_name (dynobj,
                                   MIPS_ELF_STUB_SECTION_NAME (dynobj));
         BFD_ASSERT (s != NULL);

         h->root.u.def.section = s;
         h->root.u.def.value = s->size;

         /* XXX Write this stub address somewhere.  */
         h->plt.offset = s->size;

         /* Make room for this stub code.  */
         s->size += htab->function_stub_size;

         /* The last half word of the stub will be filled with the index
            of this symbol in .dynsym section.  */
         return TRUE;
       }
    }
  else if ((h->type == STT_FUNC)
          && !h->needs_plt)
    {
      /* This will set the entry for this symbol in the GOT to 0, and
         the dynamic linker will take care of this.  */
      h->root.u.def.value = 0;
      return TRUE;
    }

  /* If this is a weak symbol, and there is a real definition, the
     processor independent code will have arranged for us to see the
     real definition first, and we can just use the same value.  */
  if (h->u.weakdef != NULL)
    {
      BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
                || h->u.weakdef->root.type == bfd_link_hash_defweak);
      h->root.u.def.section = h->u.weakdef->root.u.def.section;
      h->root.u.def.value = h->u.weakdef->root.u.def.value;
      return TRUE;
    }

  /* This is a reference to a symbol defined by a dynamic object which
     is not a function.  */

  return TRUE;
}

Here is the call graph for this function:

Definition at line 7210 of file elfxx-mips.c.

{
  asection *ri;

  bfd *dynobj;
  asection *s;
  struct mips_got_info *g;
  int i;
  bfd_size_type loadable_size = 0;
  bfd_size_type local_gotno;
  bfd_size_type dynsymcount;
  bfd *sub;
  struct mips_elf_count_tls_arg count_tls_arg;
  struct mips_elf_link_hash_table *htab;

  htab = mips_elf_hash_table (info);

  /* The .reginfo section has a fixed size.  */
  ri = bfd_get_section_by_name (output_bfd, ".reginfo");
  if (ri != NULL)
    bfd_set_section_size (output_bfd, ri, sizeof (Elf32_External_RegInfo));

  if (! (info->relocatable
        || ! mips_elf_hash_table (info)->mips16_stubs_seen))
    mips_elf_link_hash_traverse (mips_elf_hash_table (info),
                             mips_elf_check_mips16_stubs, NULL);

  dynobj = elf_hash_table (info)->dynobj;
  if (dynobj == NULL)
    /* Relocatable links don't have it.  */
    return TRUE;

  g = mips_elf_got_info (dynobj, &s);
  if (s == NULL)
    return TRUE;

  /* Calculate the total loadable size of the output.  That
     will give us the maximum number of GOT_PAGE entries
     required.  */
  for (sub = info->input_bfds; sub; sub = sub->link_next)
    {
      asection *subsection;

      for (subsection = sub->sections;
          subsection;
          subsection = subsection->next)
       {
         if ((subsection->flags & SEC_ALLOC) == 0)
           continue;
         loadable_size += ((subsection->size + 0xf)
                         &~ (bfd_size_type) 0xf);
       }
    }

  /* There has to be a global GOT entry for every symbol with
     a dynamic symbol table index of DT_MIPS_GOTSYM or
     higher.  Therefore, it make sense to put those symbols
     that need GOT entries at the end of the symbol table.  We
     do that here.  */
  if (! mips_elf_sort_hash_table (info, 1))
    return FALSE;

  if (g->global_gotsym != NULL)
    i = elf_hash_table (info)->dynsymcount - g->global_gotsym->dynindx;
  else
    /* If there are no global symbols, or none requiring
       relocations, then GLOBAL_GOTSYM will be NULL.  */
    i = 0;

  /* Get a worst-case estimate of the number of dynamic symbols needed.
     At this point, dynsymcount does not account for section symbols
     and count_section_dynsyms may overestimate the number that will
     be needed.  */
  dynsymcount = (elf_hash_table (info)->dynsymcount
               + count_section_dynsyms (output_bfd, info));

  /* Determine the size of one stub entry.  */
  htab->function_stub_size = (dynsymcount > 0x10000
                           ? MIPS_FUNCTION_STUB_BIG_SIZE
                           : MIPS_FUNCTION_STUB_NORMAL_SIZE);

  /* In the worst case, we'll get one stub per dynamic symbol, plus
     one to account for the dummy entry at the end required by IRIX
     rld.  */
  loadable_size += htab->function_stub_size * (i + 1);

  if (htab->is_vxworks)
    /* There's no need to allocate page entries for VxWorks; R_MIPS_GOT16
       relocations against local symbols evaluate to "G", and the EABI does
       not include R_MIPS_GOT_PAGE.  */
    local_gotno = 0;
  else
    /* Assume there are two loadable segments consisting of contiguous
       sections.  Is 5 enough?  */
    local_gotno = (loadable_size >> 16) + 5;

  g->local_gotno += local_gotno;
  s->size += g->local_gotno * MIPS_ELF_GOT_SIZE (output_bfd);

  g->global_gotno = i;
  s->size += i * MIPS_ELF_GOT_SIZE (output_bfd);

  /* We need to calculate tls_gotno for global symbols at this point
     instead of building it up earlier, to avoid doublecounting
     entries for one global symbol from multiple input files.  */
  count_tls_arg.info = info;
  count_tls_arg.needed = 0;
  elf_link_hash_traverse (elf_hash_table (info),
                       mips_elf_count_global_tls_entries,
                       &count_tls_arg);
  g->tls_gotno += count_tls_arg.needed;
  s->size += g->tls_gotno * MIPS_ELF_GOT_SIZE (output_bfd);

  mips_elf_resolve_final_got_entries (g);

  /* VxWorks does not support multiple GOTs.  It initializes $gp to
     __GOTT_BASE__[__GOTT_INDEX__], the value of which is set by the
     dynamic loader.  */
  if (!htab->is_vxworks && s->size > MIPS_ELF_GOT_MAX_SIZE (info))
    {
      if (! mips_elf_multi_got (output_bfd, info, g, s, local_gotno))
       return FALSE;
    }
  else
    {
      /* Set up TLS entries for the first GOT.  */
      g->tls_assigned_gotno = g->global_gotno + g->local_gotno;
      htab_traverse (g->got_entries, mips_elf_initialize_tls_index, g);
    }

  return TRUE;
}

Here is the call graph for this function:

Definition at line 6121 of file elfxx-mips.c.

{
  const char *name;
  bfd *dynobj;
  Elf_Internal_Shdr *symtab_hdr;
  struct elf_link_hash_entry **sym_hashes;
  struct mips_got_info *g;
  size_t extsymoff;
  const Elf_Internal_Rela *rel;
  const Elf_Internal_Rela *rel_end;
  asection *sgot;
  asection *sreloc;
  const struct elf_backend_data *bed;
  struct mips_elf_link_hash_table *htab;

  if (info->relocatable)
    return TRUE;

  htab = mips_elf_hash_table (info);
  dynobj = elf_hash_table (info)->dynobj;
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
  sym_hashes = elf_sym_hashes (abfd);
  extsymoff = (elf_bad_symtab (abfd)) ? 0 : symtab_hdr->sh_info;

  /* Check for the mips16 stub sections.  */

  name = bfd_get_section_name (abfd, sec);
  if (FN_STUB_P (name))
    {
      unsigned long r_symndx;

      /* Look at the relocation information to figure out which symbol
         this is for.  */

      r_symndx = ELF_R_SYM (abfd, relocs->r_info);

      if (r_symndx < extsymoff
         || sym_hashes[r_symndx - extsymoff] == NULL)
       {
         asection *o;

         /* This stub is for a local symbol.  This stub will only be
             needed if there is some relocation in this BFD, other
             than a 16 bit function call, which refers to this symbol.  */
         for (o = abfd->sections; o != NULL; o = o->next)
           {
             Elf_Internal_Rela *sec_relocs;
             const Elf_Internal_Rela *r, *rend;

             /* We can ignore stub sections when looking for relocs.  */
             if ((o->flags & SEC_RELOC) == 0
                || o->reloc_count == 0
                || mips16_stub_section_p (abfd, o))
              continue;

             sec_relocs
              = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL,
                                        info->keep_memory);
             if (sec_relocs == NULL)
              return FALSE;

             rend = sec_relocs + o->reloc_count;
             for (r = sec_relocs; r < rend; r++)
              if (ELF_R_SYM (abfd, r->r_info) == r_symndx
                  && ELF_R_TYPE (abfd, r->r_info) != R_MIPS16_26)
                break;

             if (elf_section_data (o)->relocs != sec_relocs)
              free (sec_relocs);

             if (r < rend)
              break;
           }

         if (o == NULL)
           {
             /* There is no non-call reloc for this stub, so we do
                 not need it.  Since this function is called before
                 the linker maps input sections to output sections, we
                 can easily discard it by setting the SEC_EXCLUDE
                 flag.  */
             sec->flags |= SEC_EXCLUDE;
             return TRUE;
           }

         /* Record this stub in an array of local symbol stubs for
             this BFD.  */
         if (elf_tdata (abfd)->local_stubs == NULL)
           {
             unsigned long symcount;
             asection **n;
             bfd_size_type amt;

             if (elf_bad_symtab (abfd))
              symcount = NUM_SHDR_ENTRIES (symtab_hdr);
             else
              symcount = symtab_hdr->sh_info;
             amt = symcount * sizeof (asection *);
             n = bfd_zalloc (abfd, amt);
             if (n == NULL)
              return FALSE;
             elf_tdata (abfd)->local_stubs = n;
           }

         sec->flags |= SEC_KEEP;
         elf_tdata (abfd)->local_stubs[r_symndx] = sec;

         /* We don't need to set mips16_stubs_seen in this case.
             That flag is used to see whether we need to look through
             the global symbol table for stubs.  We don't need to set
             it here, because we just have a local stub.  */
       }
      else
       {
         struct mips_elf_link_hash_entry *h;

         h = ((struct mips_elf_link_hash_entry *)
              sym_hashes[r_symndx - extsymoff]);

         while (h->root.root.type == bfd_link_hash_indirect
               || h->root.root.type == bfd_link_hash_warning)
           h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;

         /* H is the symbol this stub is for.  */

         /* If we already have an appropriate stub for this function, we
            don't need another one, so we can discard this one.  Since
            this function is called before the linker maps input sections
            to output sections, we can easily discard it by setting the
            SEC_EXCLUDE flag.  */
         if (h->fn_stub != NULL)
           {
             sec->flags |= SEC_EXCLUDE;
             return TRUE;
           }

         sec->flags |= SEC_KEEP;
         h->fn_stub = sec;
         mips_elf_hash_table (info)->mips16_stubs_seen = TRUE;
       }
    }
  else if (CALL_STUB_P (name) || CALL_FP_STUB_P (name))
    {
      unsigned long r_symndx;
      struct mips_elf_link_hash_entry *h;
      asection **loc;

      /* Look at the relocation information to figure out which symbol
         this is for.  */

      r_symndx = ELF_R_SYM (abfd, relocs->r_info);

      if (r_symndx < extsymoff
         || sym_hashes[r_symndx - extsymoff] == NULL)
       {
         asection *o;

         /* This stub is for a local symbol.  This stub will only be
             needed if there is some relocation (R_MIPS16_26) in this BFD
             that refers to this symbol.  */
         for (o = abfd->sections; o != NULL; o = o->next)
           {
             Elf_Internal_Rela *sec_relocs;
             const Elf_Internal_Rela *r, *rend;

             /* We can ignore stub sections when looking for relocs.  */
             if ((o->flags & SEC_RELOC) == 0
                || o->reloc_count == 0
                || mips16_stub_section_p (abfd, o))
              continue;

             sec_relocs
              = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL,
                                        info->keep_memory);
             if (sec_relocs == NULL)
              return FALSE;

             rend = sec_relocs + o->reloc_count;
             for (r = sec_relocs; r < rend; r++)
              if (ELF_R_SYM (abfd, r->r_info) == r_symndx
                  && ELF_R_TYPE (abfd, r->r_info) == R_MIPS16_26)
                  break;

             if (elf_section_data (o)->relocs != sec_relocs)
              free (sec_relocs);

             if (r < rend)
              break;
           }

         if (o == NULL)
           {
             /* There is no non-call reloc for this stub, so we do
                 not need it.  Since this function is called before
                 the linker maps input sections to output sections, we
                 can easily discard it by setting the SEC_EXCLUDE
                 flag.  */
             sec->flags |= SEC_EXCLUDE;
             return TRUE;
           }

         /* Record this stub in an array of local symbol call_stubs for
             this BFD.  */
         if (elf_tdata (abfd)->local_call_stubs == NULL)
           {
             unsigned long symcount;
             asection **n;
             bfd_size_type amt;

             if (elf_bad_symtab (abfd))
              symcount = NUM_SHDR_ENTRIES (symtab_hdr);
             else
              symcount = symtab_hdr->sh_info;
             amt = symcount * sizeof (asection *);
             n = bfd_zalloc (abfd, amt);
             if (n == NULL)
              return FALSE;
             elf_tdata (abfd)->local_call_stubs = n;
           }

         sec->flags |= SEC_KEEP;
         elf_tdata (abfd)->local_call_stubs[r_symndx] = sec;

         /* We don't need to set mips16_stubs_seen in this case.
             That flag is used to see whether we need to look through
             the global symbol table for stubs.  We don't need to set
             it here, because we just have a local stub.  */
       }
      else
       {
         h = ((struct mips_elf_link_hash_entry *)
              sym_hashes[r_symndx - extsymoff]);
         
         /* H is the symbol this stub is for.  */
         
         if (CALL_FP_STUB_P (name))
           loc = &h->call_fp_stub;
         else
           loc = &h->call_stub;
         
         /* If we already have an appropriate stub for this function, we
            don't need another one, so we can discard this one.  Since
            this function is called before the linker maps input sections
            to output sections, we can easily discard it by setting the
            SEC_EXCLUDE flag.  */
         if (*loc != NULL)
           {
             sec->flags |= SEC_EXCLUDE;
             return TRUE;
           }

         sec->flags |= SEC_KEEP;
         *loc = sec;
         mips_elf_hash_table (info)->mips16_stubs_seen = TRUE;
       }
    }

  if (dynobj == NULL)
    {
      sgot = NULL;
      g = NULL;
    }
  else
    {
      sgot = mips_elf_got_section (dynobj, FALSE);
      if (sgot == NULL)
       g = NULL;
      else
       {
         BFD_ASSERT (mips_elf_section_data (sgot) != NULL);
         g = mips_elf_section_data (sgot)->u.got_info;
         BFD_ASSERT (g != NULL);
       }
    }

  sreloc = NULL;
  bed = get_elf_backend_data (abfd);
  rel_end = relocs + sec->reloc_count * bed->s->int_rels_per_ext_rel;
  for (rel = relocs; rel < rel_end; ++rel)
    {
      unsigned long r_symndx;
      unsigned int r_type;
      struct elf_link_hash_entry *h;

      r_symndx = ELF_R_SYM (abfd, rel->r_info);
      r_type = ELF_R_TYPE (abfd, rel->r_info);

      if (r_symndx < extsymoff)
       h = NULL;
      else if (r_symndx >= extsymoff + NUM_SHDR_ENTRIES (symtab_hdr))
       {
         (*_bfd_error_handler)
           (_("%B: Malformed reloc detected for section %s"),
            abfd, name);
         bfd_set_error (bfd_error_bad_value);
         return FALSE;
       }
      else
       {
         h = sym_hashes[r_symndx - extsymoff];

         /* This may be an indirect symbol created because of a version.  */
         if (h != NULL)
           {
             while (h->root.type == bfd_link_hash_indirect)
              h = (struct elf_link_hash_entry *) h->root.u.i.link;
           }
       }

      /* Some relocs require a global offset table.  */
      if (dynobj == NULL || sgot == NULL)
       {
         switch (r_type)
           {
           case R_MIPS_GOT16:
           case R_MIPS_CALL16:
           case R_MIPS_CALL_HI16:
           case R_MIPS_CALL_LO16:
           case R_MIPS_GOT_HI16:
           case R_MIPS_GOT_LO16:
           case R_MIPS_GOT_PAGE:
           case R_MIPS_GOT_OFST:
           case R_MIPS_GOT_DISP:
           case R_MIPS_TLS_GOTTPREL:
           case R_MIPS_TLS_GD:
           case R_MIPS_TLS_LDM:
             if (dynobj == NULL)
              elf_hash_table (info)->dynobj = dynobj = abfd;
             if (! mips_elf_create_got_section (dynobj, info, FALSE))
              return FALSE;
             g = mips_elf_got_info (dynobj, &sgot);
             if (htab->is_vxworks && !info->shared)
              {
                (*_bfd_error_handler)
                  (_("%B: GOT reloc at 0x%lx not expected in executables"),
                   abfd, (unsigned long) rel->r_offset);
                bfd_set_error (bfd_error_bad_value);
                return FALSE;
              }
             break;

           case R_MIPS_32:
           case R_MIPS_REL32:
           case R_MIPS_64:
             /* In VxWorks executables, references to external symbols
               are handled using copy relocs or PLT stubs, so there's
               no need to add a dynamic relocation here.  */
             if (dynobj == NULL
                && (info->shared || (h != NULL && !htab->is_vxworks))
                && (sec->flags & SEC_ALLOC) != 0)
              elf_hash_table (info)->dynobj = dynobj = abfd;
             break;

           default:
             break;
           }
       }

      if (h)
       {
         ((struct mips_elf_link_hash_entry *) h)->is_relocation_target = TRUE;

         /* Relocations against the special VxWorks __GOTT_BASE__ and
            __GOTT_INDEX__ symbols must be left to the loader.  Allocate
            room for them in .rela.dyn.  */
         if (is_gott_symbol (info, h))
           {
             if (sreloc == NULL)
              {
                sreloc = mips_elf_rel_dyn_section (info, TRUE);
                if (sreloc == NULL)
                  return FALSE;
              }
             mips_elf_allocate_dynamic_relocations (dynobj, info, 1);
           }
       }
      else if (r_type == R_MIPS_CALL_LO16
              || r_type == R_MIPS_GOT_LO16
              || r_type == R_MIPS_GOT_DISP
              || (r_type == R_MIPS_GOT16 && htab->is_vxworks))
       {
         /* 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 and
            R_MIPS_CALL16, except on VxWorks, where GOT relocations
            always evaluate to "G".  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.  */
         if (! mips_elf_record_local_got_symbol (abfd, r_symndx,
                                            rel->r_addend, g, 0))
           return FALSE;
       }

      switch (r_type)
       {
       case R_MIPS_CALL16:
         if (h == NULL)
           {
             (*_bfd_error_handler)
              (_("%B: CALL16 reloc at 0x%lx not against global symbol"),
               abfd, (unsigned long) rel->r_offset);
             bfd_set_error (bfd_error_bad_value);
             return FALSE;
           }
         /* Fall through.  */

       case R_MIPS_CALL_HI16:
       case R_MIPS_CALL_LO16:
         if (h != NULL)
           {
             /* VxWorks call relocations point the function's .got.plt
               entry, which will be allocated by adjust_dynamic_symbol.
               Otherwise, this symbol requires a global GOT entry.  */
             if (!htab->is_vxworks
                && !mips_elf_record_global_got_symbol (h, abfd, info, g, 0))
              return FALSE;

             /* We need a stub, not a plt entry for the undefined
               function.  But we record it as if it needs plt.  See
               _bfd_elf_adjust_dynamic_symbol.  */
             h->needs_plt = 1;
             h->type = STT_FUNC;
           }
         break;

       case R_MIPS_GOT_PAGE:
         /* If this is a global, overridable symbol, GOT_PAGE will
            decay to GOT_DISP, so we'll need a GOT entry for it.  */
         if (h == NULL)
           break;
         else
           {
             struct mips_elf_link_hash_entry *hmips =
              (struct mips_elf_link_hash_entry *) h;

             while (hmips->root.root.type == bfd_link_hash_indirect
                   || hmips->root.root.type == bfd_link_hash_warning)
              hmips = (struct mips_elf_link_hash_entry *)
                hmips->root.root.u.i.link;

             if (hmips->root.def_regular
                && ! (info->shared && ! info->symbolic
                     && ! hmips->root.forced_local))
              break;
           }
         /* Fall through.  */

       case R_MIPS_GOT16:
       case R_MIPS_GOT_HI16:
       case R_MIPS_GOT_LO16:
       case R_MIPS_GOT_DISP:
         if (h && ! mips_elf_record_global_got_symbol (h, abfd, info, g, 0))
           return FALSE;
         break;

       case R_MIPS_TLS_GOTTPREL:
         if (info->shared)
           info->flags |= DF_STATIC_TLS;
         /* Fall through */

       case R_MIPS_TLS_LDM:
         if (r_type == R_MIPS_TLS_LDM)
           {
             r_symndx = 0;
             h = NULL;
           }
         /* Fall through */

       case R_MIPS_TLS_GD:
         /* This symbol requires a global offset table entry, or two
            for TLS GD relocations.  */
         {
           unsigned char flag = (r_type == R_MIPS_TLS_GD
                              ? GOT_TLS_GD
                              : r_type == R_MIPS_TLS_LDM
                              ? GOT_TLS_LDM
                              : GOT_TLS_IE);
           if (h != NULL)
             {
              struct mips_elf_link_hash_entry *hmips =
                (struct mips_elf_link_hash_entry *) h;
              hmips->tls_type |= flag;

              if (h && ! mips_elf_record_global_got_symbol (h, abfd, info, g, flag))
                return FALSE;
             }
           else
             {
              BFD_ASSERT (flag == GOT_TLS_LDM || r_symndx != 0);

              if (! mips_elf_record_local_got_symbol (abfd, r_symndx,
                                                 rel->r_addend, g, flag))
                return FALSE;
             }
         }
         break;

       case R_MIPS_32:
       case R_MIPS_REL32:
       case R_MIPS_64:
         /* In VxWorks executables, references to external symbols
            are handled using copy relocs or PLT stubs, so there's
            no need to add a .rela.dyn entry for this relocation.  */
         if ((info->shared || (h != NULL && !htab->is_vxworks))
             && (sec->flags & SEC_ALLOC) != 0)
           {
             if (sreloc == NULL)
              {
                sreloc = mips_elf_rel_dyn_section (info, TRUE);
                if (sreloc == NULL)
                  return FALSE;
              }
             if (info->shared)
              {
                /* When creating a shared object, we must copy these
                   reloc types into the output file as R_MIPS_REL32
                   relocs.  Make room for this reloc in .rel(a).dyn.  */
                mips_elf_allocate_dynamic_relocations (dynobj, info, 1);
                if (MIPS_ELF_READONLY_SECTION (sec))
                  /* 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;

                /* We only need to copy this reloc if the symbol is
                     defined in a dynamic object.  */
                hmips = (struct mips_elf_link_hash_entry *) h;
                ++hmips->possibly_dynamic_relocs;
                if (MIPS_ELF_READONLY_SECTION (sec))
                  /* 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
               this symbol, a symbol must have a dynamic symbol
               table index greater that DT_MIPS_GOTSYM if there are
               dynamic relocations against it.  This does not apply
               to VxWorks, which does not have the usual coupling
               between global GOT entries and .dynsym entries.  */
             if (h != NULL && !htab->is_vxworks)
              {
                if (dynobj == NULL)
                  elf_hash_table (info)->dynobj = dynobj = abfd;
                if (! mips_elf_create_got_section (dynobj, info, TRUE))
                  return FALSE;
                g = mips_elf_got_info (dynobj, &sgot);
                if (! mips_elf_record_global_got_symbol (h, abfd, info, g, 0))
                  return FALSE;
              }
           }

         if (SGI_COMPAT (abfd))
           mips_elf_hash_table (info)->compact_rel_size +=
             sizeof (Elf32_External_crinfo);
         break;

       case R_MIPS_PC16:
         if (h)
           ((struct mips_elf_link_hash_entry *) h)->is_branch_target = TRUE;
         break;

       case R_MIPS_26:
         if (h)
           ((struct mips_elf_link_hash_entry *) h)->is_branch_target = TRUE;
         /* Fall through.  */

       case R_MIPS_GPREL16:
       case R_MIPS_LITERAL:
       case R_MIPS_GPREL32:
         if (SGI_COMPAT (abfd))
           mips_elf_hash_table (info)->compact_rel_size +=
             sizeof (Elf32_External_crinfo);
         break;

         /* This relocation describes the C++ object vtable hierarchy.
            Reconstruct it for later use during GC.  */
       case R_MIPS_GNU_VTINHERIT:
         if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
           return FALSE;
         break;

         /* This relocation describes which C++ vtable entries are actually
            used.  Record for later use during GC.  */
       case R_MIPS_GNU_VTENTRY:
         if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
           return FALSE;
         break;

       default:
         break;
       }

      /* We must not create a stub for a symbol that has relocations
        related to taking the function's address.  This doesn't apply to
        VxWorks, where CALL relocs refer to a .got.plt entry instead of
        a normal .got entry.  */
      if (!htab->is_vxworks && h != NULL)
       switch (r_type)
         {
         default:
           ((struct mips_elf_link_hash_entry *) h)->no_fn_stub = TRUE;
           break;
         case R_MIPS_CALL16:
         case R_MIPS_CALL_HI16:
         case R_MIPS_CALL_LO16:
         case R_MIPS_JALR:
           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 (h != NULL
         && r_type != R_MIPS16_26
         && !mips16_stub_section_p (abfd, sec))
       {
         struct mips_elf_link_hash_entry *mh;

         mh = (struct mips_elf_link_hash_entry *) h;
         mh->need_fn_stub = TRUE;
       }
    }

  return TRUE;
}

Here is the call graph for this function:

bfd_boolean _bfd_mips_elf_common_definition ( Elf_Internal_Sym *  )

Definition at line 11344 of file elfxx-mips.c.

{
  return (sym->st_shndx == SHN_COMMON
         || sym->st_shndx == SHN_MIPS_ACOMMON
         || sym->st_shndx == SHN_MIPS_SCOMMON);
}

Definition at line 9651 of file elfxx-mips.c.

{
  struct mips_elf_link_hash_entry *dirmips, *indmips;

  _bfd_elf_link_hash_copy_indirect (info, dir, ind);

  if (ind->root.type != bfd_link_hash_indirect)
    return;

  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 (indmips->no_fn_stub)
    dirmips->no_fn_stub = TRUE;

  if (dirmips->tls_type == 0)
    dirmips->tls_type = indmips->tls_type;
}

Here is the call graph for this function:

Definition at line 5925 of file elfxx-mips.c.

{
  struct elf_link_hash_entry *h;
  struct bfd_link_hash_entry *bh;
  flagword flags;
  register asection *s;
  const char * const *namep;
  struct mips_elf_link_hash_table *htab;

  htab = mips_elf_hash_table (info);
  flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
          | SEC_LINKER_CREATED | SEC_READONLY);

  /* The psABI requires a read-only .dynamic section, but the VxWorks
     EABI doesn't.  */
  if (!htab->is_vxworks)
    {
      s = bfd_get_section_by_name (abfd, ".dynamic");
      if (s != NULL)
       {
         if (! bfd_set_section_flags (abfd, s, flags))
           return FALSE;
       }
    }

  /* We need to create .got section.  */
  if (! mips_elf_create_got_section (abfd, info, FALSE))
    return FALSE;

  if (! mips_elf_rel_dyn_section (info, TRUE))
    return FALSE;

  /* Create .stub section.  */
  if (bfd_get_section_by_name (abfd,
                            MIPS_ELF_STUB_SECTION_NAME (abfd)) == NULL)
    {
      s = bfd_make_section_with_flags (abfd,
                                   MIPS_ELF_STUB_SECTION_NAME (abfd),
                                   flags | SEC_CODE);
      if (s == NULL
         || ! bfd_set_section_alignment (abfd, s,
                                     MIPS_ELF_LOG_FILE_ALIGN (abfd)))
       return FALSE;
    }

  if ((IRIX_COMPAT (abfd) == ict_irix5 || IRIX_COMPAT (abfd) == ict_none)
      && !info->shared
      && bfd_get_section_by_name (abfd, ".rld_map") == NULL)
    {
      s = bfd_make_section_with_flags (abfd, ".rld_map",
                                   flags &~ (flagword) SEC_READONLY);
      if (s == NULL
         || ! bfd_set_section_alignment (abfd, s,
                                     MIPS_ELF_LOG_FILE_ALIGN (abfd)))
       return FALSE;
    }

  /* On IRIX5, we adjust add some additional symbols and change the
     alignments of several sections.  There is no ABI documentation
     indicating that this is necessary on IRIX6, nor any evidence that
     the linker takes such action.  */
  if (IRIX_COMPAT (abfd) == ict_irix5)
    {
      for (namep = mips_elf_dynsym_rtproc_names; *namep != NULL; namep++)
       {
         bh = NULL;
         if (! (_bfd_generic_link_add_one_symbol
               (info, abfd, *namep, BSF_GLOBAL, bfd_und_section_ptr, 0,
                NULL, FALSE, get_elf_backend_data (abfd)->collect, &bh)))
           return FALSE;

         h = (struct elf_link_hash_entry *) bh;
         h->non_elf = 0;
         h->def_regular = 1;
         h->type = STT_SECTION;

         if (! bfd_elf_link_record_dynamic_symbol (info, h))
           return FALSE;
       }

      /* We need to create a .compact_rel section.  */
      if (SGI_COMPAT (abfd))
       {
         if (!mips_elf_create_compact_rel_section (abfd, info))
           return FALSE;
       }

      /* Change alignments of some sections.  */
      s = bfd_get_section_by_name (abfd, ".hash");
      if (s != NULL)
       bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
      s = bfd_get_section_by_name (abfd, ".dynsym");
      if (s != NULL)
       bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
      s = bfd_get_section_by_name (abfd, ".dynstr");
      if (s != NULL)
       bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
      s = bfd_get_section_by_name (abfd, ".reginfo");
      if (s != NULL)
       bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
      s = bfd_get_section_by_name (abfd, ".dynamic");
      if (s != NULL)
       bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
    }

  if (!info->shared)
    {
      const char *name;

      name = SGI_COMPAT (abfd) ? "_DYNAMIC_LINK" : "_DYNAMIC_LINKING";
      bh = NULL;
      if (!(_bfd_generic_link_add_one_symbol
           (info, abfd, name, BSF_GLOBAL, bfd_abs_section_ptr, 0,
            NULL, FALSE, get_elf_backend_data (abfd)->collect, &bh)))
       return FALSE;

      h = (struct elf_link_hash_entry *) bh;
      h->non_elf = 0;
      h->def_regular = 1;
      h->type = STT_SECTION;

      if (! bfd_elf_link_record_dynamic_symbol (info, h))
       return FALSE;

      if (! mips_elf_hash_table (info)->use_rld_obj_head)
       {
         /* __rld_map is a four byte word located in the .data section
            and is filled in by the rtld to contain a pointer to
            the _r_debug structure. Its symbol value will be set in
            _bfd_mips_elf_finish_dynamic_symbol.  */
         s = bfd_get_section_by_name (abfd, ".rld_map");
         BFD_ASSERT (s != NULL);

         name = SGI_COMPAT (abfd) ? "__rld_map" : "__RLD_MAP";
         bh = NULL;
         if (!(_bfd_generic_link_add_one_symbol
              (info, abfd, name, BSF_GLOBAL, s, 0, NULL, FALSE,
               get_elf_backend_data (abfd)->collect, &bh)))
           return FALSE;

         h = (struct elf_link_hash_entry *) bh;
         h->non_elf = 0;
         h->def_regular = 1;
         h->type = STT_OBJECT;

         if (! bfd_elf_link_record_dynamic_symbol (info, h))
           return FALSE;
       }
    }

  if (htab->is_vxworks)
    {
      /* Create the .plt, .rela.plt, .dynbss and .rela.bss sections.
        Also create the _PROCEDURE_LINKAGE_TABLE symbol.  */
      if (!_bfd_elf_create_dynamic_sections (abfd, info))
       return FALSE;

      /* Cache the sections created above.  */
      htab->sdynbss = bfd_get_section_by_name (abfd, ".dynbss");
      htab->srelbss = bfd_get_section_by_name (abfd, ".rela.bss");
      htab->srelplt = bfd_get_section_by_name (abfd, ".rela.plt");
      htab->splt = bfd_get_section_by_name (abfd, ".plt");
      if (!htab->sdynbss
         || (!htab->srelbss && !info->shared)
         || !htab->srelplt
         || !htab->splt)
       abort ();

      /* Do the usual VxWorks handling.  */
      if (!elf_vxworks_create_dynamic_sections (abfd, info, &htab->srelplt2))
       return FALSE;

      /* Work out the PLT sizes.  */
      if (info->shared)
       {
         htab->plt_header_size
           = 4 * ARRAY_SIZE (mips_vxworks_shared_plt0_entry);
         htab->plt_entry_size
           = 4 * ARRAY_SIZE (mips_vxworks_shared_plt_entry);
       }
      else
       {
         htab->plt_header_size
           = 4 * ARRAY_SIZE (mips_vxworks_exec_plt0_entry);
         htab->plt_entry_size
           = 4 * ARRAY_SIZE (mips_vxworks_exec_plt_entry);
       }
    }

  return TRUE;
}

Here is the call graph for this function:

Definition at line 9749 of file elfxx-mips.c.

{
  asection *o;
  bfd_boolean ret = FALSE;
  unsigned char *tdata;
  size_t i, skip;

  o = bfd_get_section_by_name (abfd, ".pdr");
  if (! o)
    return FALSE;
  if (o->size == 0)
    return FALSE;
  if (o->size % PDR_SIZE != 0)
    return FALSE;
  if (o->output_section != NULL
      && bfd_is_abs_section (o->output_section))
    return FALSE;

  tdata = bfd_zmalloc (o->size / PDR_SIZE);
  if (! tdata)
    return FALSE;

  cookie->rels = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL,
                                       info->keep_memory);
  if (!cookie->rels)
    {
      free (tdata);
      return FALSE;
    }

  cookie->rel = cookie->rels;
  cookie->relend = cookie->rels + o->reloc_count;

  for (i = 0, skip = 0; i < o->size / PDR_SIZE; i ++)
    {
      if (bfd_elf_reloc_symbol_deleted_p (i * PDR_SIZE, cookie))
       {
         tdata[i] = 1;
         skip ++;
       }
    }

  if (skip != 0)
    {
      mips_elf_section_data (o)->u.tdata = tdata;
      o->size -= skip * PDR_SIZE;
      ret = TRUE;
    }
  else
    free (tdata);

  if (! info->keep_memory)
    free (cookie->rels);

  return ret;
}

Here is the call graph for this function:

Definition at line 5226 of file elfxx-mips.c.

{
  if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64)
    return 8;
  if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI) == E_MIPS_ABI_EABI64)
    {
      bfd_boolean long32_p, long64_p;

      long32_p = bfd_get_section_by_name (abfd, ".gcc_compiled_long32") != 0;
      long64_p = bfd_get_section_by_name (abfd, ".gcc_compiled_long64") != 0;
      if (long32_p && long64_p)
       return 0;
      if (long32_p)
       return 4;
      if (long64_p)
       return 8;

      if (sec->reloc_count > 0
         && elf_section_data (sec)->relocs != NULL
         && (ELF32_R_TYPE (elf_section_data (sec)->relocs[0].r_info)
             == R_MIPS_64))
       return 8;

      return 0;
    }
  return 4;
}

Here is the call graph for this function:

Definition at line 5584 of file elfxx-mips.c.

{
  register const char *name;
  unsigned int sh_type;

  name = bfd_get_section_name (abfd, sec);
  sh_type = hdr->sh_type;

  if (strcmp (name, ".liblist") == 0)
    {
      hdr->sh_type = SHT_MIPS_LIBLIST;
      hdr->sh_info = sec->size / sizeof (Elf32_Lib);
      /* The sh_link field is set in final_write_processing.  */
    }
  else if (strcmp (name, ".conflict") == 0)
    hdr->sh_type = SHT_MIPS_CONFLICT;
  else if (CONST_STRNEQ (name, ".gptab."))
    {
      hdr->sh_type = SHT_MIPS_GPTAB;
      hdr->sh_entsize = sizeof (Elf32_External_gptab);
      /* The sh_info field is set in final_write_processing.  */
    }
  else if (strcmp (name, ".ucode") == 0)
    hdr->sh_type = SHT_MIPS_UCODE;
  else if (strcmp (name, ".mdebug") == 0)
    {
      hdr->sh_type = SHT_MIPS_DEBUG;
      /* In a shared object on IRIX 5.3, the .mdebug section has an
         entsize of 0.  FIXME: Does this matter?  */
      if (SGI_COMPAT (abfd) && (abfd->flags & DYNAMIC) != 0)
       hdr->sh_entsize = 0;
      else
       hdr->sh_entsize = 1;
    }
  else if (strcmp (name, ".reginfo") == 0)
    {
      hdr->sh_type = SHT_MIPS_REGINFO;
      /* In a shared object on IRIX 5.3, the .reginfo section has an
         entsize of 0x18.  FIXME: Does this matter?  */
      if (SGI_COMPAT (abfd))
       {
         if ((abfd->flags & DYNAMIC) != 0)
           hdr->sh_entsize = sizeof (Elf32_External_RegInfo);
         else
           hdr->sh_entsize = 1;
       }
      else
       hdr->sh_entsize = sizeof (Elf32_External_RegInfo);
    }
  else if (SGI_COMPAT (abfd)
          && (strcmp (name, ".hash") == 0
              || strcmp (name, ".dynamic") == 0
              || strcmp (name, ".dynstr") == 0))
    {
      if (SGI_COMPAT (abfd))
       hdr->sh_entsize = 0;
#if 0
      /* This isn't how the IRIX6 linker behaves.  */
      hdr->sh_info = SIZEOF_MIPS_DYNSYM_SECNAMES;
#endif
    }
  else if (strcmp (name, ".got") == 0
          || strcmp (name, ".srdata") == 0
          || strcmp (name, ".sdata") == 0
          || strcmp (name, ".sbss") == 0
          || strcmp (name, ".lit4") == 0
          || strcmp (name, ".lit8") == 0)
    hdr->sh_flags |= SHF_MIPS_GPREL;
  else if (strcmp (name, ".MIPS.interfaces") == 0)
    {
      hdr->sh_type = SHT_MIPS_IFACE;
      hdr->sh_flags |= SHF_MIPS_NOSTRIP;
    }
  else if (CONST_STRNEQ (name, ".MIPS.content"))
    {
      hdr->sh_type = SHT_MIPS_CONTENT;
      hdr->sh_flags |= SHF_MIPS_NOSTRIP;
      /* The sh_info field is set in final_write_processing.  */
    }
  else if (MIPS_ELF_OPTIONS_SECTION_NAME_P (name))
    {
      hdr->sh_type = SHT_MIPS_OPTIONS;
      hdr->sh_entsize = 1;
      hdr->sh_flags |= SHF_MIPS_NOSTRIP;
    }
  else if (CONST_STRNEQ (name, ".debug_"))
    hdr->sh_type = SHT_MIPS_DWARF;
  else if (strcmp (name, ".MIPS.symlib") == 0)
    {
      hdr->sh_type = SHT_MIPS_SYMBOL_LIB;
      /* The sh_link and sh_info fields are set in
         final_write_processing.  */
    }
  else if (CONST_STRNEQ (name, ".MIPS.events")
          || CONST_STRNEQ (name, ".MIPS.post_rel"))
    {
      hdr->sh_type = SHT_MIPS_EVENTS;
      hdr->sh_flags |= SHF_MIPS_NOSTRIP;
      /* The sh_link field is set in final_write_processing.  */
    }
  else if (strcmp (name, ".msym") == 0)
    {
      hdr->sh_type = SHT_MIPS_MSYM;
      hdr->sh_flags |= SHF_ALLOC;
      hdr->sh_entsize = 8;
    }

  /* In the unlikely event a special section is empty it has to lose its
     special meaning.  This may happen e.g. when using `strip' with the
     "--only-keep-debug" option.  */
  if (sec->size > 0 && !(sec->flags & SEC_HAS_CONTENTS))
    hdr->sh_type = sh_type;

  /* The generic elf_fake_sections will set up REL_HDR using the default
   kind of relocations.  We used to set up a second header for the
   non-default kind of relocations here, but only NewABI would use
   these, and the IRIX ld doesn't like resulting empty RELA sections.
   Thus we create those header only on demand now.  */

  return TRUE;
}

Here is the call graph for this function:

Definition at line 10238 of file elfxx-mips.c.

{
  asection *o;
  struct bfd_link_order *p;
  asection *reginfo_sec, *mdebug_sec, *gptab_data_sec, *gptab_bss_sec;
  asection *rtproc_sec;
  Elf32_RegInfo reginfo;
  struct ecoff_debug_info debug;
  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
  const struct ecoff_debug_swap *swap = bed->elf_backend_ecoff_debug_swap;
  HDRR *symhdr = &debug.symbolic_header;
  void *mdebug_handle = NULL;
  asection *s;
  EXTR esym;
  unsigned int i;
  bfd_size_type amt;
  struct mips_elf_link_hash_table *htab;

  static const char * const secname[] =
  {
    ".text", ".init", ".fini", ".data",
    ".rodata", ".sdata", ".sbss", ".bss"
  };
  static const int sc[] =
  {
    scText, scInit, scFini, scData,
    scRData, scSData, scSBss, scBss
  };

  /* We'd carefully arranged the dynamic symbol indices, and then the
     generic size_dynamic_sections renumbered them out from under us.
     Rather than trying somehow to prevent the renumbering, just do
     the sort again.  */
  htab = mips_elf_hash_table (info);
  if (elf_hash_table (info)->dynamic_sections_created)
    {
      bfd *dynobj;
      asection *got;
      struct mips_got_info *g;
      bfd_size_type dynsecsymcount;

      /* When we resort, we must tell mips_elf_sort_hash_table what
        the lowest index it may use is.  That's the number of section
        symbols we're going to add.  The generic ELF linker only
        adds these symbols when building a shared object.  Note that
        we count the sections after (possibly) removing the .options
        section above.  */

      dynsecsymcount = count_section_dynsyms (abfd, info);
      if (! mips_elf_sort_hash_table (info, dynsecsymcount + 1))
       return FALSE;

      /* Make sure we didn't grow the global .got region.  */
      dynobj = elf_hash_table (info)->dynobj;
      got = mips_elf_got_section (dynobj, FALSE);
      g = mips_elf_section_data (got)->u.got_info;

      if (g->global_gotsym != NULL)
       BFD_ASSERT ((elf_hash_table (info)->dynsymcount
                   - g->global_gotsym->dynindx)
                  <= g->global_gotno);
    }

  /* Get a value for the GP register.  */
  if (elf_gp (abfd) == 0)
    {
      struct bfd_link_hash_entry *h;

      h = bfd_link_hash_lookup (info->hash, "_gp", FALSE, FALSE, TRUE);
      if (h != NULL && h->type == bfd_link_hash_defined)
       elf_gp (abfd) = (h->u.def.value
                      + h->u.def.section->output_section->vma
                      + h->u.def.section->output_offset);
      else if (htab->is_vxworks
              && (h = bfd_link_hash_lookup (info->hash,
                                        "_GLOBAL_OFFSET_TABLE_",
                                        FALSE, FALSE, TRUE))
              && h->type == bfd_link_hash_defined)
       elf_gp (abfd) = (h->u.def.section->output_section->vma
                      + h->u.def.section->output_offset
                      + h->u.def.value);
      else if (info->relocatable)
       {
         bfd_vma lo = MINUS_ONE;

         /* Find the GP-relative section with the lowest offset.  */
         for (o = abfd->sections; o != NULL; o = o->next)
           if (o->vma < lo
              && (elf_section_data (o)->this_hdr.sh_flags & SHF_MIPS_GPREL))
             lo = o->vma;

         /* And calculate GP relative to that.  */
         elf_gp (abfd) = lo + ELF_MIPS_GP_OFFSET (info);
       }
      else
       {
         /* If the relocate_section function needs to do a reloc
            involving the GP value, it should make a reloc_dangerous
            callback to warn that GP is not defined.  */
       }
    }

  /* Go through the sections and collect the .reginfo and .mdebug
     information.  */
  reginfo_sec = NULL;
  mdebug_sec = NULL;
  gptab_data_sec = NULL;
  gptab_bss_sec = NULL;
  for (o = abfd->sections; o != NULL; o = o->next)
    {
      if (strcmp (o->name, ".reginfo") == 0)
       {
         memset (&reginfo, 0, sizeof reginfo);

         /* We have found the .reginfo section in the output file.
            Look through all the link_orders comprising it and merge
            the information together.  */
         for (p = o->map_head.link_order; p != NULL; p = p->next)
           {
             asection *input_section;
             bfd *input_bfd;
             Elf32_External_RegInfo ext;
             Elf32_RegInfo sub;

             if (p->type != bfd_indirect_link_order)
              {
                if (p->type == bfd_data_link_order)
                  continue;
                abort ();
              }

             input_section = p->u.indirect.section;
             input_bfd = input_section->owner;

             if (! bfd_get_section_contents (input_bfd, input_section,
                                         &ext, 0, sizeof ext))
              return FALSE;

             bfd_mips_elf32_swap_reginfo_in (input_bfd, &ext, &sub);

             reginfo.ri_gprmask |= sub.ri_gprmask;
             reginfo.ri_cprmask[0] |= sub.ri_cprmask[0];
             reginfo.ri_cprmask[1] |= sub.ri_cprmask[1];
             reginfo.ri_cprmask[2] |= sub.ri_cprmask[2];
             reginfo.ri_cprmask[3] |= sub.ri_cprmask[3];

             /* ri_gp_value is set by the function
               mips_elf32_section_processing when the section is
               finally written out.  */

             /* Hack: reset the SEC_HAS_CONTENTS flag so that
               elf_link_input_bfd ignores this section.  */
             input_section->flags &= ~SEC_HAS_CONTENTS;
           }

         /* Size has been set in _bfd_mips_elf_always_size_sections.  */
         BFD_ASSERT(o->size == sizeof (Elf32_External_RegInfo));

         /* Skip this section later on (I don't think this currently
            matters, but someday it might).  */
         o->map_head.link_order = NULL;

         reginfo_sec = o;
       }

      if (strcmp (o->name, ".mdebug") == 0)
       {
         struct extsym_info einfo;
         bfd_vma last;

         /* We have found the .mdebug section in the output file.
            Look through all the link_orders comprising it and merge
            the information together.  */
         symhdr->magic = swap->sym_magic;
         /* FIXME: What should the version stamp be?  */
         symhdr->vstamp = 0;
         symhdr->ilineMax = 0;
         symhdr->cbLine = 0;
         symhdr->idnMax = 0;
         symhdr->ipdMax = 0;
         symhdr->isymMax = 0;
         symhdr->ioptMax = 0;
         symhdr->iauxMax = 0;
         symhdr->issMax = 0;
         symhdr->issExtMax = 0;
         symhdr->ifdMax = 0;
         symhdr->crfd = 0;
         symhdr->iextMax = 0;

         /* We accumulate the debugging information itself in the
            debug_info structure.  */
         debug.line = NULL;
         debug.external_dnr = NULL;
         debug.external_pdr = NULL;
         debug.external_sym = NULL;
         debug.external_opt = NULL;
         debug.external_aux = NULL;
         debug.ss = NULL;
         debug.ssext = debug.ssext_end = NULL;
         debug.external_fdr = NULL;
         debug.external_rfd = NULL;
         debug.external_ext = debug.external_ext_end = NULL;

         mdebug_handle = bfd_ecoff_debug_init (abfd, &debug, swap, info);
         if (mdebug_handle == NULL)
           return FALSE;

         esym.jmptbl = 0;
         esym.cobol_main = 0;
         esym.weakext = 0;
         esym.reserved = 0;
         esym.ifd = ifdNil;
         esym.asym.iss = issNil;
         esym.asym.st = stLocal;
         esym.asym.reserved = 0;
         esym.asym.index = indexNil;
         last = 0;
         for (i = 0; i < sizeof (secname) / sizeof (secname[0]); i++)
           {
             esym.asym.sc = sc[i];
             s = bfd_get_section_by_name (abfd, secname[i]);
             if (s != NULL)
              {
                esym.asym.value = s->vma;
                last = s->vma + s->size;
              }
             else
              esym.asym.value = last;
             if (!bfd_ecoff_debug_one_external (abfd, &debug, swap,
                                           secname[i], &esym))
              return FALSE;
           }

         for (p = o->map_head.link_order; p != NULL; p = p->next)
           {
             asection *input_section;
             bfd *input_bfd;
             const struct ecoff_debug_swap *input_swap;
             struct ecoff_debug_info input_debug;
             char *eraw_src;
             char *eraw_end;

             if (p->type != bfd_indirect_link_order)
              {
                if (p->type == bfd_data_link_order)
                  continue;
                abort ();
              }

             input_section = p->u.indirect.section;
             input_bfd = input_section->owner;

             if (bfd_get_flavour (input_bfd) != bfd_target_elf_flavour
                || (get_elf_backend_data (input_bfd)
                    ->elf_backend_ecoff_debug_swap) == NULL)
              {
                /* I don't know what a non MIPS ELF bfd would be
                   doing with a .mdebug section, but I don't really
                   want to deal with it.  */
                continue;
              }

             input_swap = (get_elf_backend_data (input_bfd)
                         ->elf_backend_ecoff_debug_swap);

             BFD_ASSERT (p->size == input_section->size);

             /* The ECOFF linking code expects that we have already
               read in the debugging information and set up an
               ecoff_debug_info structure, so we do that now.  */
             if (! _bfd_mips_elf_read_ecoff_info (input_bfd, input_section,
                                             &input_debug))
              return FALSE;

             if (! (bfd_ecoff_debug_accumulate
                   (mdebug_handle, abfd, &debug, swap, input_bfd,
                    &input_debug, input_swap, info)))
              return FALSE;

             /* Loop through the external symbols.  For each one with
               interesting information, try to find the symbol in
               the linker global hash table and save the information
               for the output external symbols.  */
             eraw_src = input_debug.external_ext;
             eraw_end = (eraw_src
                       + (input_debug.symbolic_header.iextMax
                          * input_swap->external_ext_size));
             for (;
                 eraw_src < eraw_end;
                 eraw_src += input_swap->external_ext_size)
              {
                EXTR ext;
                const char *name;
                struct mips_elf_link_hash_entry *h;

                (*input_swap->swap_ext_in) (input_bfd, eraw_src, &ext);
                if (ext.asym.sc == scNil
                    || ext.asym.sc == scUndefined
                    || ext.asym.sc == scSUndefined)
                  continue;

                name = input_debug.ssext + ext.asym.iss;
                h = mips_elf_link_hash_lookup (mips_elf_hash_table (info),
                                           name, FALSE, FALSE, TRUE);
                if (h == NULL || h->esym.ifd != -2)
                  continue;

                if (ext.ifd != -1)
                  {
                    BFD_ASSERT (ext.ifd
                              < input_debug.symbolic_header.ifdMax);
                    ext.ifd = input_debug.ifdmap[ext.ifd];
                  }

                h->esym = ext;
              }

             /* Free up the information we just read.  */
             free (input_debug.line);
             free (input_debug.external_dnr);
             free (input_debug.external_pdr);
             free (input_debug.external_sym);
             free (input_debug.external_opt);
             free (input_debug.external_aux);
             free (input_debug.ss);
             free (input_debug.ssext);
             free (input_debug.external_fdr);
             free (input_debug.external_rfd);
             free (input_debug.external_ext);

             /* Hack: reset the SEC_HAS_CONTENTS flag so that
               elf_link_input_bfd ignores this section.  */
             input_section->flags &= ~SEC_HAS_CONTENTS;
           }

         if (SGI_COMPAT (abfd) && info->shared)
           {
             /* Create .rtproc section.  */
             rtproc_sec = bfd_get_section_by_name (abfd, ".rtproc");
             if (rtproc_sec == NULL)
              {
                flagword flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY
                                | SEC_LINKER_CREATED | SEC_READONLY);

                rtproc_sec = bfd_make_section_with_flags (abfd,
                                                     ".rtproc",
                                                     flags);
                if (rtproc_sec == NULL
                    || ! bfd_set_section_alignment (abfd, rtproc_sec, 4))
                  return FALSE;
              }

             if (! mips_elf_create_procedure_table (mdebug_handle, abfd,
                                               info, rtproc_sec,
                                               &debug))
              return FALSE;
           }

         /* Build the external symbol information.  */
         einfo.abfd = abfd;
         einfo.info = info;
         einfo.debug = &debug;
         einfo.swap = swap;
         einfo.failed = FALSE;
         mips_elf_link_hash_traverse (mips_elf_hash_table (info),
                                   mips_elf_output_extsym, &einfo);
         if (einfo.failed)
           return FALSE;

         /* Set the size of the .mdebug section.  */
         o->size = bfd_ecoff_debug_size (abfd, &debug, swap);

         /* Skip this section later on (I don't think this currently
            matters, but someday it might).  */
         o->map_head.link_order = NULL;

         mdebug_sec = o;
       }

      if (CONST_STRNEQ (o->name, ".gptab."))
       {
         const char *subname;
         unsigned int c;
         Elf32_gptab *tab;
         Elf32_External_gptab *ext_tab;
         unsigned int j;

         /* The .gptab.sdata and .gptab.sbss sections hold
            information describing how the small data area would
            change depending upon the -G switch.  These sections
            not used in executables files.  */
         if (! info->relocatable)
           {
             for (p = o->map_head.link_order; p != NULL; p = p->next)
              {
                asection *input_section;

                if (p->type != bfd_indirect_link_order)
                  {
                    if (p->type == bfd_data_link_order)
                     continue;
                    abort ();
                  }

                input_section = p->u.indirect.section;

                /* Hack: reset the SEC_HAS_CONTENTS flag so that
                   elf_link_input_bfd ignores this section.  */
                input_section->flags &= ~SEC_HAS_CONTENTS;
              }

             /* Skip this section later on (I don't think this
               currently matters, but someday it might).  */
             o->map_head.link_order = NULL;

             /* Really remove the section.  */
             bfd_section_list_remove (abfd, o);
             --abfd->section_count;

             continue;
           }

         /* There is one gptab for initialized data, and one for
            uninitialized data.  */
         if (strcmp (o->name, ".gptab.sdata") == 0)
           gptab_data_sec = o;
         else if (strcmp (o->name, ".gptab.sbss") == 0)
           gptab_bss_sec = o;
         else
           {
             (*_bfd_error_handler)
              (_("%s: illegal section name `%s'"),
               bfd_get_filename (abfd), o->name);
             bfd_set_error (bfd_error_nonrepresentable_section);
             return FALSE;
           }

         /* The linker script always combines .gptab.data and
            .gptab.sdata into .gptab.sdata, and likewise for
            .gptab.bss and .gptab.sbss.  It is possible that there is
            no .sdata or .sbss section in the output file, in which
            case we must change the name of the output section.  */
         subname = o->name + sizeof ".gptab" - 1;
         if (bfd_get_section_by_name (abfd, subname) == NULL)
           {
             if (o == gptab_data_sec)
              o->name = ".gptab.data";
             else
              o->name = ".gptab.bss";
             subname = o->name + sizeof ".gptab" - 1;
             BFD_ASSERT (bfd_get_section_by_name (abfd, subname) != NULL);
           }

         /* Set up the first entry.  */
         c = 1;
         amt = c * sizeof (Elf32_gptab);
         tab = bfd_malloc (amt);
         if (tab == NULL)
           return FALSE;
         tab[0].gt_header.gt_current_g_value = elf_gp_size (abfd);
         tab[0].gt_header.gt_unused = 0;

         /* Combine the input sections.  */
         for (p = o->map_head.link_order; p != NULL; p = p->next)
           {
             asection *input_section;
             bfd *input_bfd;
             bfd_size_type size;
             unsigned long last;
             bfd_size_type gpentry;

             if (p->type != bfd_indirect_link_order)
              {
                if (p->type == bfd_data_link_order)
                  continue;
                abort ();
              }

             input_section = p->u.indirect.section;
             input_bfd = input_section->owner;

             /* Combine the gptab entries for this input section one
               by one.  We know that the input gptab entries are
               sorted by ascending -G value.  */
             size = input_section->size;
             last = 0;
             for (gpentry = sizeof (Elf32_External_gptab);
                 gpentry < size;
                 gpentry += sizeof (Elf32_External_gptab))
              {
                Elf32_External_gptab ext_gptab;
                Elf32_gptab int_gptab;
                unsigned long val;
                unsigned long add;
                bfd_boolean exact;
                unsigned int look;

                if (! (bfd_get_section_contents
                      (input_bfd, input_section, &ext_gptab, gpentry,
                       sizeof (Elf32_External_gptab))))
                  {
                    free (tab);
                    return FALSE;
                  }

                bfd_mips_elf32_swap_gptab_in (input_bfd, &ext_gptab,
                                          &int_gptab);
                val = int_gptab.gt_entry.gt_g_value;
                add = int_gptab.gt_entry.gt_bytes - last;

                exact = FALSE;
                for (look = 1; look < c; look++)
                  {
                    if (tab[look].gt_entry.gt_g_value >= val)
                     tab[look].gt_entry.gt_bytes += add;

                    if (tab[look].gt_entry.gt_g_value == val)
                     exact = TRUE;
                  }

                if (! exact)
                  {
                    Elf32_gptab *new_tab;
                    unsigned int max;

                    /* We need a new table entry.  */
                    amt = (bfd_size_type) (c + 1) * sizeof (Elf32_gptab);
                    new_tab = bfd_realloc (tab, amt);
                    if (new_tab == NULL)
                     {
                       free (tab);
                       return FALSE;
                     }
                    tab = new_tab;
                    tab[c].gt_entry.gt_g_value = val;
                    tab[c].gt_entry.gt_bytes = add;

                    /* Merge in the size for the next smallest -G
                      value, since that will be implied by this new
                      value.  */
                    max = 0;
                    for (look = 1; look < c; look++)
                     {
                       if (tab[look].gt_entry.gt_g_value < val
                           && (max == 0
                              || (tab[look].gt_entry.gt_g_value
                                  > tab[max].gt_entry.gt_g_value)))
                         max = look;
                     }
                    if (max != 0)
                     tab[c].gt_entry.gt_bytes +=
                       tab[max].gt_entry.gt_bytes;

                    ++c;
                  }

                last = int_gptab.gt_entry.gt_bytes;
              }

             /* Hack: reset the SEC_HAS_CONTENTS flag so that
               elf_link_input_bfd ignores this section.  */
             input_section->flags &= ~SEC_HAS_CONTENTS;
           }

         /* The table must be sorted by -G value.  */
         if (c > 2)
           qsort (tab + 1, c - 1, sizeof (tab[0]), gptab_compare);

         /* Swap out the table.  */
         amt = (bfd_size_type) c * sizeof (Elf32_External_gptab);
         ext_tab = bfd_alloc (abfd, amt);
         if (ext_tab == NULL)
           {
             free (tab);
             return FALSE;
           }

         for (j = 0; j < c; j++)
           bfd_mips_elf32_swap_gptab_out (abfd, tab + j, ext_tab + j);
         free (tab);

         o->size = c * sizeof (Elf32_External_gptab);
         o->contents = (bfd_byte *) ext_tab;

         /* Skip this section later on (I don't think this currently
            matters, but someday it might).  */
         o->map_head.link_order = NULL;
       }
    }

  /* Invoke the regular ELF backend linker to do all the work.  */
  if (!bfd_elf_final_link (abfd, info))
    return FALSE;

  /* Now write out the computed sections.  */

  if (reginfo_sec != NULL)
    {
      Elf32_External_RegInfo ext;

      bfd_mips_elf32_swap_reginfo_out (abfd, &reginfo, &ext);
      if (! bfd_set_section_contents (abfd, reginfo_sec, &ext, 0, sizeof ext))
       return FALSE;
    }

  if (mdebug_sec != NULL)
    {
      BFD_ASSERT (abfd->output_has_begun);
      if (! bfd_ecoff_write_accumulated_debug (mdebug_handle, abfd, &debug,
                                          swap, info,
                                          mdebug_sec->filepos))
       return FALSE;

      bfd_ecoff_debug_free (mdebug_handle, abfd, &debug, swap, info);
    }

  if (gptab_data_sec != NULL)
    {
      if (! bfd_set_section_contents (abfd, gptab_data_sec,
                                  gptab_data_sec->contents,
                                  0, gptab_data_sec->size))
       return FALSE;
    }

  if (gptab_bss_sec != NULL)
    {
      if (! bfd_set_section_contents (abfd, gptab_bss_sec,
                                  gptab_bss_sec->contents,
                                  0, gptab_bss_sec->size))
       return FALSE;
    }

  if (SGI_COMPAT (abfd))
    {
      rtproc_sec = bfd_get_section_by_name (abfd, ".rtproc");
      if (rtproc_sec != NULL)
       {
         if (! bfd_set_section_contents (abfd, rtproc_sec,
                                     rtproc_sec->contents,
                                     0, rtproc_sec->size))
           return FALSE;
       }
    }

  return TRUE;
}

Here is the call graph for this function:

bfd_boolean _bfd_mips_elf_find_inliner_info ( bfd ,
const char **  ,
const char **  ,
unsigned int  
)

Definition at line 9957 of file elfxx-mips.c.

{
  bfd_boolean found;
  found = _bfd_dwarf2_find_inliner_info (abfd, filename_ptr,
                                    functionname_ptr, line_ptr,
                                    & elf_tdata (abfd)->dwarf2_find_line_info);
  return found;
}

Here is the call graph for this function:

bfd_boolean _bfd_mips_elf_find_nearest_line ( bfd ,
asection ,
asymbol **  ,
bfd_vma  ,
const char **  ,
const char **  ,
unsigned int  
)

Definition at line 9856 of file elfxx-mips.c.

{
  asection *msec;

  if (_bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset,
                                 filename_ptr, functionname_ptr,
                                 line_ptr))
    return TRUE;

  if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
                                 filename_ptr, functionname_ptr,
                                 line_ptr, ABI_64_P (abfd) ? 8 : 0,
                                 &elf_tdata (abfd)->dwarf2_find_line_info))
    return TRUE;

  msec = bfd_get_section_by_name (abfd, ".mdebug");
  if (msec != NULL)
    {
      flagword origflags;
      struct mips_elf_find_line *fi;
      const struct ecoff_debug_swap * const swap =
       get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;

      /* If we are called during a link, mips_elf_final_link may have
        cleared the SEC_HAS_CONTENTS field.  We force it back on here
        if appropriate (which it normally will be).  */
      origflags = msec->flags;
      if (elf_section_data (msec)->this_hdr.sh_type != SHT_NOBITS)
       msec->flags |= SEC_HAS_CONTENTS;

      fi = elf_tdata (abfd)->find_line_info;
      if (fi == NULL)
       {
         bfd_size_type external_fdr_size;
         char *fraw_src;
         char *fraw_end;
         struct fdr *fdr_ptr;
         bfd_size_type amt = sizeof (struct mips_elf_find_line);

         fi = bfd_zalloc (abfd, amt);
         if (fi == NULL)
           {
             msec->flags = origflags;
             return FALSE;
           }

         if (! _bfd_mips_elf_read_ecoff_info (abfd, msec, &fi->d))
           {
             msec->flags = origflags;
             return FALSE;
           }

         /* Swap in the FDR information.  */
         amt = fi->d.symbolic_header.ifdMax * sizeof (struct fdr);
         fi->d.fdr = bfd_alloc (abfd, amt);
         if (fi->d.fdr == NULL)
           {
             msec->flags = origflags;
             return FALSE;
           }
         external_fdr_size = swap->external_fdr_size;
         fdr_ptr = fi->d.fdr;
         fraw_src = (char *) fi->d.external_fdr;
         fraw_end = (fraw_src
                    + fi->d.symbolic_header.ifdMax * external_fdr_size);
         for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++)
           (*swap->swap_fdr_in) (abfd, fraw_src, fdr_ptr);

         elf_tdata (abfd)->find_line_info = fi;

         /* Note that we don't bother to ever free this information.
             find_nearest_line is either called all the time, as in
             objdump -l, so the information should be saved, or it is
             rarely called, as in ld error messages, so the memory
             wasted is unimportant.  Still, it would probably be a
             good idea for free_cached_info to throw it away.  */
       }

      if (_bfd_ecoff_locate_line (abfd, section, offset, &fi->d, swap,
                              &fi->i, filename_ptr, functionname_ptr,
                              line_ptr))
       {
         msec->flags = origflags;
         return TRUE;
       }

      msec->flags = origflags;
    }

  /* Fall back on the generic ELF find_nearest_line routine.  */

  return _bfd_elf_find_nearest_line (abfd, section, symbols, offset,
                                 filename_ptr, functionname_ptr,
                                 line_ptr);
}

Here is the call graph for this function:

Definition at line 8689 of file elfxx-mips.c.

{
  bfd *dynobj;
  asection *sdyn;
  asection *sgot;
  struct mips_got_info *gg, *g;
  struct mips_elf_link_hash_table *htab;

  htab = mips_elf_hash_table (info);
  dynobj = elf_hash_table (info)->dynobj;

  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");

  sgot = mips_elf_got_section (dynobj, FALSE);
  if (sgot == NULL)
    gg = g = NULL;
  else
    {
      BFD_ASSERT (mips_elf_section_data (sgot) != NULL);
      gg = mips_elf_section_data (sgot)->u.got_info;
      BFD_ASSERT (gg != NULL);
      g = mips_elf_got_for_ibfd (gg, output_bfd);
      BFD_ASSERT (g != NULL);
    }

  if (elf_hash_table (info)->dynamic_sections_created)
    {
      bfd_byte *b;
      int dyn_to_skip = 0, dyn_skipped = 0;

      BFD_ASSERT (sdyn != NULL);
      BFD_ASSERT (g != NULL);

      for (b = sdyn->contents;
          b < sdyn->contents + sdyn->size;
          b += MIPS_ELF_DYN_SIZE (dynobj))
       {
         Elf_Internal_Dyn dyn;
         const char *name;
         size_t elemsize;
         asection *s;
         bfd_boolean swap_out_p;

         /* Read in the current dynamic entry.  */
         (*get_elf_backend_data (dynobj)->s->swap_dyn_in) (dynobj, b, &dyn);

         /* Assume that we're going to modify it and write it out.  */
         swap_out_p = TRUE;

         switch (dyn.d_tag)
           {
           case DT_RELENT:
             dyn.d_un.d_val = MIPS_ELF_REL_SIZE (dynobj);
             break;

           case DT_RELAENT:
             BFD_ASSERT (htab->is_vxworks);
             dyn.d_un.d_val = MIPS_ELF_RELA_SIZE (dynobj);
             break;

           case DT_STRSZ:
             /* Rewrite DT_STRSZ.  */
             dyn.d_un.d_val =
              _bfd_elf_strtab_size (elf_hash_table (info)->dynstr);
             break;

           case DT_PLTGOT:
             name = ".got";
             if (htab->is_vxworks)
              {
                /* _GLOBAL_OFFSET_TABLE_ is defined to be the beginning
                   of the ".got" section in DYNOBJ.  */
                s = bfd_get_section_by_name (dynobj, name);
                BFD_ASSERT (s != NULL);
                dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
              }
             else
              {
                s = bfd_get_section_by_name (output_bfd, name);
                BFD_ASSERT (s != NULL);
                dyn.d_un.d_ptr = s->vma;
              }
             break;

           case DT_MIPS_RLD_VERSION:
             dyn.d_un.d_val = 1; /* XXX */
             break;

           case DT_MIPS_FLAGS:
             dyn.d_un.d_val = RHF_NOTPOT; /* XXX */
             break;

           case DT_MIPS_TIME_STAMP:
             {
              time_t t;
              time (&t);
              dyn.d_un.d_val = t;
             }
             break;

           case DT_MIPS_ICHECKSUM:
             /* XXX FIXME: */
             swap_out_p = FALSE;
             break;

           case DT_MIPS_IVERSION:
             /* XXX FIXME: */
             swap_out_p = FALSE;
             break;

           case DT_MIPS_BASE_ADDRESS:
             s = output_bfd->sections;
             BFD_ASSERT (s != NULL);
             dyn.d_un.d_ptr = s->vma & ~(bfd_vma) 0xffff;
             break;

           case DT_MIPS_LOCAL_GOTNO:
             dyn.d_un.d_val = g->local_gotno;
             break;

           case DT_MIPS_UNREFEXTNO:
             /* The index into the dynamic symbol table which is the
               entry of the first external symbol that is not
               referenced within the same object.  */
             dyn.d_un.d_val = bfd_count_sections (output_bfd) + 1;
             break;

           case DT_MIPS_GOTSYM:
             if (gg->global_gotsym)
              {
                dyn.d_un.d_val = gg->global_gotsym->dynindx;
                break;
              }
             /* In case if we don't have global got symbols we default
               to setting DT_MIPS_GOTSYM to the same value as
               DT_MIPS_SYMTABNO, so we just fall through.  */

           case DT_MIPS_SYMTABNO:
             name = ".dynsym";
             elemsize = MIPS_ELF_SYM_SIZE (output_bfd);
             s = bfd_get_section_by_name (output_bfd, name);
             BFD_ASSERT (s != NULL);

             dyn.d_un.d_val = s->size / elemsize;
             break;

           case DT_MIPS_HIPAGENO:
             dyn.d_un.d_val = g->local_gotno - MIPS_RESERVED_GOTNO (info);
             break;

           case DT_MIPS_RLD_MAP:
             dyn.d_un.d_ptr = mips_elf_hash_table (info)->rld_value;
             break;

           case DT_MIPS_OPTIONS:
             s = (bfd_get_section_by_name
                 (output_bfd, MIPS_ELF_OPTIONS_SECTION_NAME (output_bfd)));
             dyn.d_un.d_ptr = s->vma;
             break;

           case DT_RELASZ:
             BFD_ASSERT (htab->is_vxworks);
             /* The count does not include the JUMP_SLOT relocations.  */
             if (htab->srelplt)
              dyn.d_un.d_val -= htab->srelplt->size;
             break;

           case DT_PLTREL:
             BFD_ASSERT (htab->is_vxworks);
             dyn.d_un.d_val = DT_RELA;
             break;

           case DT_PLTRELSZ:
             BFD_ASSERT (htab->is_vxworks);
             dyn.d_un.d_val = htab->srelplt->size;
             break;

           case DT_JMPREL:
             BFD_ASSERT (htab->is_vxworks);
             dyn.d_un.d_val = (htab->srelplt->output_section->vma
                            + htab->srelplt->output_offset);
             break;

           case DT_TEXTREL:
             /* If we didn't need any text relocations after all, delete
               the dynamic tag.  */
             if (!(info->flags & DF_TEXTREL))
              {
                dyn_to_skip = MIPS_ELF_DYN_SIZE (dynobj);
                swap_out_p = FALSE;
              }
             break;

           case DT_FLAGS:
             /* If we didn't need any text relocations after all, clear
               DF_TEXTREL from DT_FLAGS.  */
             if (!(info->flags & DF_TEXTREL))
              dyn.d_un.d_val &= ~DF_TEXTREL;
             else
              swap_out_p = FALSE;
             break;

           default:
             swap_out_p = FALSE;
             break;
           }

         if (swap_out_p || dyn_skipped)
           (*get_elf_backend_data (dynobj)->s->swap_dyn_out)
             (dynobj, &dyn, b - dyn_skipped);

         if (dyn_to_skip)
           {
             dyn_skipped += dyn_to_skip;
             dyn_to_skip = 0;
           }
       }

      /* Wipe out any trailing entries if we shifted down a dynamic tag.  */
      if (dyn_skipped > 0)
       memset (b - dyn_skipped, 0, dyn_skipped);
    }

  if (sgot != NULL && sgot->size > 0)
    {
      if (htab->is_vxworks)
       {
         /* The first entry of the global offset table points to the
            ".dynamic" section.  The second is initialized by the
            loader and contains the shared library identifier.
            The third is also initialized by the loader and points
            to the lazy resolution stub.  */
         MIPS_ELF_PUT_WORD (output_bfd,
                          sdyn->output_offset + sdyn->output_section->vma,
                          sgot->contents);
         MIPS_ELF_PUT_WORD (output_bfd, 0,
                          sgot->contents + MIPS_ELF_GOT_SIZE (output_bfd));
         MIPS_ELF_PUT_WORD (output_bfd, 0,
                          sgot->contents
                          + 2 * MIPS_ELF_GOT_SIZE (output_bfd));
       }
      else
       {
         /* The first entry of the global offset table will be filled at
            runtime. The second entry will be used by some runtime loaders.
            This isn't the case of IRIX rld.  */
         MIPS_ELF_PUT_WORD (output_bfd, (bfd_vma) 0, sgot->contents);
         MIPS_ELF_PUT_WORD (output_bfd, (bfd_vma) 0x80000000,
                          sgot->contents + MIPS_ELF_GOT_SIZE (output_bfd));
       }

      elf_section_data (sgot->output_section)->this_hdr.sh_entsize
        = MIPS_ELF_GOT_SIZE (output_bfd);
    }

  /* Generate dynamic relocations for the non-primary gots.  */
  if (gg != NULL && gg->next)
    {
      Elf_Internal_Rela rel[3];
      bfd_vma addend = 0;

      memset (rel, 0, sizeof (rel));
      rel[0].r_info = ELF_R_INFO (output_bfd, 0, R_MIPS_REL32);

      for (g = gg->next; g->next != gg; g = g->next)
       {
         bfd_vma index = g->next->local_gotno + g->next->global_gotno
           + g->next->tls_gotno;

         MIPS_ELF_PUT_WORD (output_bfd, 0, sgot->contents
                          + index++ * MIPS_ELF_GOT_SIZE (output_bfd));
         MIPS_ELF_PUT_WORD (output_bfd, 0x80000000, sgot->contents
                          + index++ * MIPS_ELF_GOT_SIZE (output_bfd));

         if (! info->shared)
           continue;

         while (index < g->assigned_gotno)
           {
             rel[0].r_offset = rel[1].r_offset = rel[2].r_offset
              = index++ * MIPS_ELF_GOT_SIZE (output_bfd);
             if (!(mips_elf_create_dynamic_relocation
                  (output_bfd, info, rel, NULL,
                   bfd_abs_section_ptr,
                   0, &addend, sgot)))
              return FALSE;
             BFD_ASSERT (addend == 0);
           }
       }
    }

  /* The generation of dynamic relocations for the non-primary gots
     adds more dynamic relocations.  We cannot count them until
     here.  */

  if (elf_hash_table (info)->dynamic_sections_created)
    {
      bfd_byte *b;
      bfd_boolean swap_out_p;

      BFD_ASSERT (sdyn != NULL);

      for (b = sdyn->contents;
          b < sdyn->contents + sdyn->size;
          b += MIPS_ELF_DYN_SIZE (dynobj))
       {
         Elf_Internal_Dyn dyn;
         asection *s;

         /* Read in the current dynamic entry.  */
         (*get_elf_backend_data (dynobj)->s->swap_dyn_in) (dynobj, b, &dyn);

         /* Assume that we're going to modify it and write it out.  */
         swap_out_p = TRUE;

         switch (dyn.d_tag)
           {
           case DT_RELSZ:
             /* Reduce DT_RELSZ to account for any relocations we
               decided not to make.  This is for the n64 irix rld,
               which doesn't seem to apply any relocations if there
               are trailing null entries.  */
             s = mips_elf_rel_dyn_section (info, FALSE);
             dyn.d_un.d_val = (s->reloc_count
                            * (ABI_64_P (output_bfd)
                               ? sizeof (Elf64_Mips_External_Rel)
                               : sizeof (Elf32_External_Rel)));
             /* Adjust the section size too.  Tools like the prelinker
               can reasonably expect the values to the same.  */
             elf_section_data (s->output_section)->this_hdr.sh_size
              = dyn.d_un.d_val;
             break;

           default:
             swap_out_p = FALSE;
             break;
           }

         if (swap_out_p)
           (*get_elf_backend_data (dynobj)->s->swap_dyn_out)
             (dynobj, &dyn, b);
       }
    }

  {
    asection *s;
    Elf32_compact_rel cpt;

    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,
                                    MIPS_ELF_STUB_SECTION_NAME (dynobj));
           if (s != NULL)
             {
              file_ptr dummy_offset;

              BFD_ASSERT (s->size >= htab->function_stub_size);
              dummy_offset = s->size - htab->function_stub_size;
              memset (s->contents + dummy_offset, 0,
                     htab->function_stub_size);
             }
         }
      }

    /* The psABI says that the dynamic relocations must be sorted in
       increasing order of r_symndx.  The VxWorks EABI doesn't require
       this, and because the code below handles REL rather than RELA
       relocations, using it for VxWorks would be outright harmful.  */
    if (!htab->is_vxworks)
      {
       s = mips_elf_rel_dyn_section (info, FALSE);
       if (s != NULL
           && s->size > (bfd_vma)2 * MIPS_ELF_REL_SIZE (output_bfd))
         {
           reldyn_sorting_bfd = output_bfd;

           if (ABI_64_P (output_bfd))
             qsort ((Elf64_External_Rel *) s->contents + 1,
                   s->reloc_count - 1, sizeof (Elf64_Mips_External_Rel),
                   sort_dynamic_relocs_64);
           else
             qsort ((Elf32_External_Rel *) s->contents + 1,
                   s->reloc_count - 1, sizeof (Elf32_External_Rel),
                   sort_dynamic_relocs);
         }
      }
  }

  if (htab->is_vxworks && htab->splt->size > 0)
    {
      if (info->shared)
       mips_vxworks_finish_shared_plt (output_bfd, info);
      else
       mips_vxworks_finish_exec_plt (output_bfd, info);
    }
  return TRUE;
}

Here is the call graph for this function:

Definition at line 8193 of file elfxx-mips.c.

{
  bfd *dynobj;
  asection *sgot;
  struct mips_got_info *g, *gg;
  const char *name;
  int idx;
  struct mips_elf_link_hash_table *htab;

  htab = mips_elf_hash_table (info);
  dynobj = elf_hash_table (info)->dynobj;

  if (h->plt.offset != MINUS_ONE)
    {
      asection *s;
      bfd_byte stub[MIPS_FUNCTION_STUB_BIG_SIZE];

      /* This symbol has a stub.  Set it up.  */

      BFD_ASSERT (h->dynindx != -1);

      s = bfd_get_section_by_name (dynobj,
                               MIPS_ELF_STUB_SECTION_NAME (dynobj));
      BFD_ASSERT (s != NULL);

      BFD_ASSERT ((htab->function_stub_size == MIPS_FUNCTION_STUB_BIG_SIZE)
                  || (h->dynindx <= 0xffff));

      /* Values up to 2^31 - 1 are allowed.  Larger values would cause
        sign extension at runtime in the stub, resulting in a negative
        index value.  */
      if (h->dynindx & ~0x7fffffff)
       return FALSE;

      /* Fill the stub.  */
      idx = 0;
      bfd_put_32 (output_bfd, STUB_LW (output_bfd), stub + idx);
      idx += 4;
      bfd_put_32 (output_bfd, STUB_MOVE (output_bfd), stub + idx);
      idx += 4;
      if (htab->function_stub_size == MIPS_FUNCTION_STUB_BIG_SIZE)
        {
          bfd_put_32 (output_bfd, STUB_LUI ((h->dynindx >> 16) & 0x7fff),
                      stub + idx);
          idx += 4;
        }
      bfd_put_32 (output_bfd, STUB_JALR, stub + idx);
      idx += 4;

      /* If a large stub is not required and sign extension is not a
         problem, then use legacy code in the stub.  */
      if (htab->function_stub_size == MIPS_FUNCTION_STUB_BIG_SIZE)
       bfd_put_32 (output_bfd, STUB_ORI (h->dynindx & 0xffff), stub + idx);
      else if (h->dynindx & ~0x7fff)
        bfd_put_32 (output_bfd, STUB_LI16U (h->dynindx & 0xffff), stub + idx);
      else
        bfd_put_32 (output_bfd, STUB_LI16S (output_bfd, h->dynindx),
                  stub + idx);

      BFD_ASSERT (h->plt.offset <= s->size);
      memcpy (s->contents + h->plt.offset, stub, htab->function_stub_size);

      /* Mark the symbol as undefined.  plt.offset != -1 occurs
        only for the referenced symbol.  */
      sym->st_shndx = SHN_UNDEF;

      /* The run-time linker uses the st_value field of the symbol
        to reset the global offset table entry for this external
        to its stub address when unlinking a shared object.  */
      sym->st_value = (s->output_section->vma + s->output_offset
                     + h->plt.offset);
    }

  BFD_ASSERT (h->dynindx != -1
             || h->forced_local);

  sgot = mips_elf_got_section (dynobj, FALSE);
  BFD_ASSERT (sgot != NULL);
  BFD_ASSERT (mips_elf_section_data (sgot) != NULL);
  g = mips_elf_section_data (sgot)->u.got_info;
  BFD_ASSERT (g != NULL);

  /* Run through the global symbol table, creating GOT entries for all
     the symbols that need them.  */
  if (g->global_gotsym != NULL
      && h->dynindx >= g->global_gotsym->dynindx)
    {
      bfd_vma offset;
      bfd_vma value;

      value = sym->st_value;
      offset = mips_elf_global_got_index (dynobj, output_bfd, h, R_MIPS_GOT16, info);
      MIPS_ELF_PUT_WORD (output_bfd, value, sgot->contents + offset);
    }

  if (g->next && h->dynindx != -1 && h->type != STT_TLS)
    {
      struct mips_got_entry e, *p;
      bfd_vma entry;
      bfd_vma offset;

      gg = g;

      e.abfd = output_bfd;
      e.symndx = -1;
      e.d.h = (struct mips_elf_link_hash_entry *)h;
      e.tls_type = 0;

      for (g = g->next; g->next != gg; g = g->next)
       {
         if (g->got_entries
             && (p = (struct mips_got_entry *) htab_find (g->got_entries,
                                                    &e)))
           {
             offset = p->gotidx;
             if (info->shared
                || (elf_hash_table (info)->dynamic_sections_created
                    && p->d.h != NULL
                    && p->d.h->root.def_dynamic
                    && !p->d.h->root.def_regular))
              {
                /* Create an R_MIPS_REL32 relocation for this entry.  Due to
                   the various compatibility problems, it's easier to mock
                   up an R_MIPS_32 or R_MIPS_64 relocation and leave
                   mips_elf_create_dynamic_relocation to calculate the
                   appropriate addend.  */
                Elf_Internal_Rela rel[3];

                memset (rel, 0, sizeof (rel));
                if (ABI_64_P (output_bfd))
                  rel[0].r_info = ELF_R_INFO (output_bfd, 0, R_MIPS_64);
                else
                  rel[0].r_info = ELF_R_INFO (output_bfd, 0, R_MIPS_32);
                rel[0].r_offset = rel[1].r_offset = rel[2].r_offset = offset;

                entry = 0;
                if (! (mips_elf_create_dynamic_relocation
                      (output_bfd, info, rel,
                       e.d.h, NULL, sym->st_value, &entry, sgot)))
                  return FALSE;
              }
             else
              entry = sym->st_value;
             MIPS_ELF_PUT_WORD (output_bfd, entry, sgot->contents + offset);
           }
       }
    }

  /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  */
  name = h->root.root.string;
  if (strcmp (name, "_DYNAMIC") == 0
      || h == elf_hash_table (info)->hgot)
    sym->st_shndx = SHN_ABS;
  else if (strcmp (name, "_DYNAMIC_LINK") == 0
          || strcmp (name, "_DYNAMIC_LINKING") == 0)
    {
      sym->st_shndx = SHN_ABS;
      sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
      sym->st_value = 1;
    }
  else if (strcmp (name, "_gp_disp") == 0 && ! NEWABI_P (output_bfd))
    {
      sym->st_shndx = SHN_ABS;
      sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
      sym->st_value = elf_gp (output_bfd);
    }
  else if (SGI_COMPAT (output_bfd))
    {
      if (strcmp (name, mips_elf_dynsym_rtproc_names[0]) == 0
         || strcmp (name, mips_elf_dynsym_rtproc_names[1]) == 0)
       {
         sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
         sym->st_other = STO_PROTECTED;
         sym->st_value = 0;
         sym->st_shndx = SHN_MIPS_DATA;
       }
      else if (strcmp (name, mips_elf_dynsym_rtproc_names[2]) == 0)
       {
         sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
         sym->st_other = STO_PROTECTED;
         sym->st_value = mips_elf_hash_table (info)->procedure_count;
         sym->st_shndx = SHN_ABS;
       }
      else if (sym->st_shndx != SHN_UNDEF && sym->st_shndx != SHN_ABS)
       {
         if (h->type == STT_FUNC)
           sym->st_shndx = SHN_MIPS_TEXT;
         else if (h->type == STT_OBJECT)
           sym->st_shndx = SHN_MIPS_DATA;
       }
    }

  /* Handle the IRIX6-specific symbols.  */
  if (IRIX_COMPAT (output_bfd) == ict_irix6)
    mips_elf_irix6_finish_dynamic_symbol (output_bfd, name, sym);

  if (! info->shared)
    {
      if (! mips_elf_hash_table (info)->use_rld_obj_head
         && (strcmp (name, "__rld_map") == 0
             || strcmp (name, "__RLD_MAP") == 0))
       {
         asection *s = bfd_get_section_by_name (dynobj, ".rld_map");
         BFD_ASSERT (s != NULL);
         sym->st_value = s->output_section->vma + s->output_offset;
         bfd_put_32 (output_bfd, 0, s->contents);
         if (mips_elf_hash_table (info)->rld_value == 0)
           mips_elf_hash_table (info)->rld_value = sym->st_value;
       }
      else if (mips_elf_hash_table (info)->use_rld_obj_head
              && strcmp (name, "__rld_obj_head") == 0)
       {
         /* IRIX6 does not use a .rld_map section.  */
         if (IRIX_COMPAT (output_bfd) == ict_irix5
              || IRIX_COMPAT (output_bfd) == ict_none)
           BFD_ASSERT (bfd_get_section_by_name (dynobj, ".rld_map")
                     != NULL);
         mips_elf_hash_table (info)->rld_value = sym->st_value;
       }
    }

  /* If this is a mips16 symbol, force the value to be even.  */
  if (sym->st_other == STO_MIPS16)
    sym->st_value &= ~1;

  return TRUE;
}

Here is the call graph for this function:

Definition at line 9580 of file elfxx-mips.c.

{
  /* ??? Do mips16 stub sections need to be handled special?  */

  if (h != NULL)
    switch (ELF_R_TYPE (sec->owner, rel->r_info))
      {
      case R_MIPS_GNU_VTINHERIT:
      case R_MIPS_GNU_VTENTRY:
       return NULL;
      }

  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
}

Here is the call graph for this function:

bfd_reloc_status_type _bfd_mips_elf_generic_reloc ( bfd ,
arelent ,
asymbol ,
void *  ,
asection ,
bfd ,
char **   
)
bfd_reloc_status_type _bfd_mips_elf_got16_reloc ( bfd ,
arelent ,
asymbol ,
void *  ,
asection ,
bfd ,
char **   
)

Definition at line 1416 of file elfxx-mips.c.

{
  if ((symbol->flags & (BSF_GLOBAL | BSF_WEAK)) != 0
      || bfd_is_und_section (bfd_get_section (symbol))
      || bfd_is_com_section (bfd_get_section (symbol)))
    /* The relocation is against a global symbol.  */
    return _bfd_mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
                                   input_section, output_bfd,
                                   error_message);

  return _bfd_mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data,
                               input_section, output_bfd, error_message);
}

Here is the call graph for this function:

Definition at line 1310 of file elfxx-mips.c.

{
  bfd_vma relocation;
  bfd_signed_vma val;
  bfd_reloc_status_type status;

  if (bfd_is_com_section (symbol->section))
    relocation = 0;
  else
    relocation = symbol->value;

  relocation += symbol->section->output_section->vma;
  relocation += symbol->section->output_offset;

  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
    return bfd_reloc_outofrange;

  /* Set val to the offset into the section or symbol.  */
  val = reloc_entry->addend;

  _bfd_mips_elf_sign_extend (val, 16);

  /* Adjust val for the final section location and GP value.  If we
     are producing relocatable output, we don't want to do this for
     an external symbol.  */
  if (! relocatable
      || (symbol->flags & BSF_SECTION_SYM) != 0)
    val += relocation - gp;

  if (reloc_entry->howto->partial_inplace)
    {
      status = _bfd_relocate_contents (reloc_entry->howto, abfd, val,
                                   (bfd_byte *) data
                                   + reloc_entry->address);
      if (status != bfd_reloc_ok)
       return status;
    }
  else
    reloc_entry->addend = val;

  if (relocatable)
    reloc_entry->address += input_section->output_offset;

  return bfd_reloc_ok;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bfd_reloc_status_type _bfd_mips_elf_hi16_reloc ( bfd ,
arelent ,
asymbol ,
void *  ,
asection ,
bfd ,
char **   
)

Definition at line 9675 of file elfxx-mips.c.

{
  bfd *dynobj;
  asection *got;
  struct mips_got_info *g;
  struct mips_elf_link_hash_entry *h;

  h = (struct mips_elf_link_hash_entry *) entry;
  if (h->forced_local)
    return;
  h->forced_local = force_local;

  dynobj = elf_hash_table (info)->dynobj;
  if (dynobj != NULL && force_local && h->root.type != STT_TLS
      && (got = mips_elf_got_section (dynobj, TRUE)) != NULL
      && (g = mips_elf_section_data (got)->u.got_info) != NULL)
    {
      if (g->next)
       {
         struct mips_got_entry e;
         struct mips_got_info *gg = g;

         /* Since we're turning what used to be a global symbol into a
            local one, bump up the number of local entries of each GOT
            that had an entry for it.  This will automatically decrease
            the number of global entries, since global_gotno is actually
            the upper limit of global entries.  */
         e.abfd = dynobj;
         e.symndx = -1;
         e.d.h = h;
         e.tls_type = 0;

         for (g = g->next; g != gg; g = g->next)
           if (htab_find (g->got_entries, &e))
             {
              BFD_ASSERT (g->global_gotno > 0);
              g->local_gotno++;
              g->global_gotno--;
             }

         /* If this was a global symbol forced into the primary GOT, we
            no longer need an entry for it.  We can't release the entry
            at this point, but we must at least stop counting it as one
            of the symbols that required a forced got entry.  */
         if (h->root.got.offset == 2)
           {
             BFD_ASSERT (gg->assigned_gotno > 0);
             gg->assigned_gotno--;
           }
       }
      else if (g->global_gotno == 0 && g->global_gotsym == NULL)
       /* If we haven't got through GOT allocation yet, just bump up the
          number of local entries, as this symbol won't be counted as
          global.  */
       g->local_gotno++;
      else if (h->root.got.offset == 1)
       {
         /* If we're past non-multi-GOT allocation and this symbol had
            been marked for a global got entry, give it a local entry
            instead.  */
         BFD_ASSERT (g->global_gotno > 0);
         g->local_gotno++;
         g->global_gotno--;
       }
    }

  _bfd_elf_link_hash_hide_symbol (info, &h->root, force_local);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 9808 of file elfxx-mips.c.

{
  if (strcmp (sec->name, ".pdr") == 0)
    return TRUE;
  return FALSE;
}

Here is the call graph for this function:

Definition at line 11338 of file elfxx-mips.c.

{
  return ELF_MIPS_IS_OPTIONAL (h->other) ? TRUE : FALSE;
}

Definition at line 10174 of file elfxx-mips.c.

{
  struct mips_elf_link_hash_table *ret;
  bfd_size_type amt = sizeof (struct mips_elf_link_hash_table);

  ret = bfd_malloc (amt);
  if (ret == NULL)
    return NULL;

  if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
                                  mips_elf_link_hash_newfunc,
                                  sizeof (struct mips_elf_link_hash_entry)))
    {
      free (ret);
      return NULL;
    }

#if 0
  /* We no longer use this.  */
  for (i = 0; i < SIZEOF_MIPS_DYNSYM_SECNAMES; i++)
    ret->dynsym_sec_strindex[i] = (bfd_size_type) -1;
#endif
  ret->procedure_count = 0;
  ret->compact_rel_size = 0;
  ret->use_rld_obj_head = FALSE;
  ret->rld_value = 0;
  ret->mips16_stubs_seen = FALSE;
  ret->is_vxworks = FALSE;
  ret->srelbss = NULL;
  ret->sdynbss = NULL;
  ret->srelplt = NULL;
  ret->srelplt2 = NULL;
  ret->sgotplt = NULL;
  ret->splt = NULL;
  ret->plt_header_size = 0;
  ret->plt_entry_size = 0;
  ret->function_stub_size = 0;

  return &ret->root.root;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bfd_reloc_status_type _bfd_mips_elf_lo16_reloc ( bfd ,
arelent ,
asymbol ,
void *  ,
asection ,
bfd ,
char **   
)

Definition at line 1437 of file elfxx-mips.c.

{
  bfd_vma vallo;
  bfd_byte *location = (bfd_byte *) data + reloc_entry->address;

  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
    return bfd_reloc_outofrange;

  _bfd_mips16_elf_reloc_unshuffle (abfd, reloc_entry->howto->type, FALSE,
                               location);
  vallo = bfd_get_32 (abfd, location);
  _bfd_mips16_elf_reloc_shuffle (abfd, reloc_entry->howto->type, FALSE,
                             location);

  while (mips_hi16_list != NULL)
    {
      bfd_reloc_status_type ret;
      struct mips_hi16 *hi;

      hi = mips_hi16_list;

      /* R_MIPS_GOT16 relocations are something of a special case.  We
        want to install the addend in the same way as for a R_MIPS_HI16
        relocation (with a rightshift of 16).  However, since GOT16
        relocations can also be used with global symbols, their howto
        has a rightshift of 0.  */
      if (hi->rel.howto->type == R_MIPS_GOT16)
       hi->rel.howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, R_MIPS_HI16, FALSE);

      /* VALLO is a signed 16-bit number.  Bias it by 0x8000 so that any
        carry or borrow will induce a change of +1 or -1 in the high part.  */
      hi->rel.addend += (vallo + 0x8000) & 0xffff;

      ret = _bfd_mips_elf_generic_reloc (abfd, &hi->rel, symbol, hi->data,
                                    hi->input_section, output_bfd,
                                    error_message);
      if (ret != bfd_reloc_ok)
       return ret;

      mips_hi16_list = hi->next;
      free (hi);
    }

  return _bfd_mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
                                  input_section, output_bfd,
                                  error_message);
}

Here is the call graph for this function:

Definition at line 10996 of file elfxx-mips.c.

{
  flagword old_flags;
  flagword new_flags;
  bfd_boolean ok;
  bfd_boolean null_input_bfd = TRUE;
  asection *sec;

  /* Check if we have the same endianess */
  if (! _bfd_generic_verify_endian_match (ibfd, obfd))
    {
      (*_bfd_error_handler)
       (_("%B: endianness incompatible with that of the selected emulation"),
        ibfd);
      return FALSE;
    }

  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
    return TRUE;

  if (strcmp (bfd_get_target (ibfd), bfd_get_target (obfd)) != 0)
    {
      (*_bfd_error_handler)
       (_("%B: ABI is incompatible with that of the selected emulation"),
        ibfd);
      return FALSE;
    }

  new_flags = elf_elfheader (ibfd)->e_flags;
  elf_elfheader (obfd)->e_flags |= new_flags & EF_MIPS_NOREORDER;
  old_flags = elf_elfheader (obfd)->e_flags;

  if (! elf_flags_init (obfd))
    {
      elf_flags_init (obfd) = TRUE;
      elf_elfheader (obfd)->e_flags = new_flags;
      elf_elfheader (obfd)->e_ident[EI_CLASS]
       = elf_elfheader (ibfd)->e_ident[EI_CLASS];

      if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
         && (bfd_get_arch_info (obfd)->the_default
             || mips_mach_extends_p (bfd_get_mach (obfd), 
                                  bfd_get_mach (ibfd))))
       {
         if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
                               bfd_get_mach (ibfd)))
           return FALSE;
       }

      return TRUE;
    }

  /* Check flag compatibility.  */

  new_flags &= ~EF_MIPS_NOREORDER;
  old_flags &= ~EF_MIPS_NOREORDER;

  /* Some IRIX 6 BSD-compatibility objects have this bit set.  It
     doesn't seem to matter.  */
  new_flags &= ~EF_MIPS_XGOT;
  old_flags &= ~EF_MIPS_XGOT;

  /* MIPSpro generates ucode info in n64 objects.  Again, we should
     just be able to ignore this.  */
  new_flags &= ~EF_MIPS_UCODE;
  old_flags &= ~EF_MIPS_UCODE;

  /* Don't care about the PIC flags from dynamic objects; they are
     PIC by design.  */
  if ((new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0
      && (ibfd->flags & DYNAMIC) != 0)
    new_flags &= ~ (EF_MIPS_PIC | EF_MIPS_CPIC);

  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")
         && (sec->size != 0
             || (strcmp (sec->name, ".text")
                && strcmp (sec->name, ".data")
                && strcmp (sec->name, ".bss"))))
       {
         null_input_bfd = FALSE;
         break;
       }
    }
  if (null_input_bfd)
    return TRUE;

  ok = TRUE;

  if (((new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0)
      != ((old_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0))
    {
      (*_bfd_error_handler)
       (_("%B: warning: linking PIC files with non-PIC files"),
        ibfd);
      ok = TRUE;
    }

  if (new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC))
    elf_elfheader (obfd)->e_flags |= EF_MIPS_CPIC;
  if (! (new_flags & EF_MIPS_PIC))
    elf_elfheader (obfd)->e_flags &= ~EF_MIPS_PIC;

  new_flags &= ~ (EF_MIPS_PIC | EF_MIPS_CPIC);
  old_flags &= ~ (EF_MIPS_PIC | EF_MIPS_CPIC);

  /* Compare the ISAs.  */
  if (mips_32bit_flags_p (old_flags) != mips_32bit_flags_p (new_flags))
    {
      (*_bfd_error_handler)
       (_("%B: linking 32-bit code with 64-bit code"),
        ibfd);
      ok = FALSE;
    }
  else if (!mips_mach_extends_p (bfd_get_mach (ibfd), bfd_get_mach (obfd)))
    {
      /* OBFD's ISA isn't the same as, or an extension of, IBFD's.  */
      if (mips_mach_extends_p (bfd_get_mach (obfd), bfd_get_mach (ibfd)))
       {
         /* Copy the architecture info from IBFD to OBFD.  Also copy
            the 32-bit flag (if set) so that we continue to recognise
            OBFD as a 32-bit binary.  */
         bfd_set_arch_info (obfd, bfd_get_arch_info (ibfd));
         elf_elfheader (obfd)->e_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH);
         elf_elfheader (obfd)->e_flags
           |= new_flags & (EF_MIPS_ARCH | EF_MIPS_MACH | EF_MIPS_32BITMODE);

         /* Copy across the ABI flags if OBFD doesn't use them
            and if that was what caused us to treat IBFD as 32-bit.  */
         if ((old_flags & EF_MIPS_ABI) == 0
             && mips_32bit_flags_p (new_flags)
             && !mips_32bit_flags_p (new_flags & ~EF_MIPS_ABI))
           elf_elfheader (obfd)->e_flags |= new_flags & EF_MIPS_ABI;
       }
      else
       {
         /* The ISAs aren't compatible.  */
         (*_bfd_error_handler)
           (_("%B: linking %s module with previous %s modules"),
            ibfd,
            bfd_printable_name (ibfd),
            bfd_printable_name (obfd));
         ok = FALSE;
       }
    }

  new_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH | EF_MIPS_32BITMODE);
  old_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH | EF_MIPS_32BITMODE);

  /* Compare ABIs.  The 64-bit ABI does not use EF_MIPS_ABI.  But, it
     does set EI_CLASS differently from any 32-bit ABI.  */
  if ((new_flags & EF_MIPS_ABI) != (old_flags & EF_MIPS_ABI)
      || (elf_elfheader (ibfd)->e_ident[EI_CLASS]
         != elf_elfheader (obfd)->e_ident[EI_CLASS]))
    {
      /* Only error if both are set (to different values).  */
      if (((new_flags & EF_MIPS_ABI) && (old_flags & EF_MIPS_ABI))
         || (elf_elfheader (ibfd)->e_ident[EI_CLASS]
             != elf_elfheader (obfd)->e_ident[EI_CLASS]))
       {
         (*_bfd_error_handler)
           (_("%B: ABI mismatch: linking %s module with previous %s modules"),
            ibfd,
            elf_mips_abi_name (ibfd),
            elf_mips_abi_name (obfd));
         ok = FALSE;
       }
      new_flags &= ~EF_MIPS_ABI;
      old_flags &= ~EF_MIPS_ABI;
    }

  /* For now, allow arbitrary mixing of ASEs (retain the union).  */
  if ((new_flags & EF_MIPS_ARCH_ASE) != (old_flags & EF_MIPS_ARCH_ASE))
    {
      elf_elfheader (obfd)->e_flags |= new_flags & EF_MIPS_ARCH_ASE;

      new_flags &= ~ EF_MIPS_ARCH_ASE;
      old_flags &= ~ EF_MIPS_ARCH_ASE;
    }

  /* Warn about any other mismatches */
  if (new_flags != old_flags)
    {
      (*_bfd_error_handler)
       (_("%B: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
        ibfd, (unsigned long) new_flags,
        (unsigned long) old_flags);
      ok = FALSE;
    }

  if (! ok)
    {
      bfd_set_error (bfd_error_bad_value);
      return FALSE;
    }

  return TRUE;
}

Here is the call graph for this function:

Definition at line 5269 of file elfxx-mips.c.

{
  return SGI_COMPAT (abfd);
}

Definition at line 843 of file elfxx-mips.c.

{
  if (!sec->used_by_bfd)
    {
      struct _mips_elf_section_data *sdata;
      bfd_size_type amt = sizeof (*sdata);

      sdata = bfd_zalloc (abfd, amt);
      if (sdata == NULL)
       return FALSE;
      sec->used_by_bfd = sdata;
    }

  return _bfd_elf_new_section_hook (abfd, sec);
}

Here is the call graph for this function:

Definition at line 11220 of file elfxx-mips.c.

{
  FILE *file = ptr;

  BFD_ASSERT (abfd != NULL && ptr != NULL);

  /* Print normal ELF private data.  */
  _bfd_elf_print_private_bfd_data (abfd, ptr);

  /* xgettext:c-format */
  fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);

  if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI) == E_MIPS_ABI_O32)
    fprintf (file, _(" [abi=O32]"));
  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI) == E_MIPS_ABI_O64)
    fprintf (file, _(" [abi=O64]"));
  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI) == E_MIPS_ABI_EABI32)
    fprintf (file, _(" [abi=EABI32]"));
  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI) == E_MIPS_ABI_EABI64)
    fprintf (file, _(" [abi=EABI64]"));
  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI))
    fprintf (file, _(" [abi unknown]"));
  else if (ABI_N32_P (abfd))
    fprintf (file, _(" [abi=N32]"));
  else if (ABI_64_P (abfd))
    fprintf (file, _(" [abi=64]"));
  else
    fprintf (file, _(" [no abi set]"));

  if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_1)
    fprintf (file, " [mips1]");
  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_2)
    fprintf (file, " [mips2]");
  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_3)
    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 if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32R2)
    fprintf (file, " [mips32r2]");
  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_64R2)
    fprintf (file, " [mips64r2]");
  else
    fprintf (file, _(" [unknown ISA]"));

  if (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH_ASE_MDMX)
    fprintf (file, " [mdmx]");

  if (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH_ASE_M16)
    fprintf (file, " [mips16]");

  if (elf_elfheader (abfd)->e_flags & EF_MIPS_32BITMODE)
    fprintf (file, " [32bitmode]");
  else
    fprintf (file, _(" [not 32bitmode]"));

  if (elf_elfheader (abfd)->e_flags & EF_MIPS_NOREORDER)
    fprintf (file, " [noreorder]");

  if (elf_elfheader (abfd)->e_flags & EF_MIPS_PIC)
    fprintf (file, " [PIC]");

  if (elf_elfheader (abfd)->e_flags & EF_MIPS_CPIC)
    fprintf (file, " [CPIC]");

  if (elf_elfheader (abfd)->e_flags & EF_MIPS_XGOT)
    fprintf (file, " [XGOT]");

  if (elf_elfheader (abfd)->e_flags & EF_MIPS_UCODE)
    fprintf (file, " [UCODE]");

  fputc ('\n', file);

  return TRUE;
}

Here is the call graph for this function:

Definition at line 863 of file elfxx-mips.c.

{
  HDRR *symhdr;
  const struct ecoff_debug_swap *swap;
  char *ext_hdr;

  swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
  memset (debug, 0, sizeof (*debug));

  ext_hdr = bfd_malloc (swap->external_hdr_size);
  if (ext_hdr == NULL && swap->external_hdr_size != 0)
    goto error_return;

  if (! bfd_get_section_contents (abfd, section, ext_hdr, 0,
                              swap->external_hdr_size))
    goto error_return;

  symhdr = &debug->symbolic_header;
  (*swap->swap_hdr_in) (abfd, ext_hdr, symhdr);

  /* The symbolic header contains absolute file offsets and sizes to
     read.  */
#define READ(ptr, offset, count, size, type)                          \
  if (symhdr->count == 0)                                      \
    debug->ptr = NULL;                                                \
  else                                                         \
    {                                                          \
      bfd_size_type amt = (bfd_size_type) size * symhdr->count;              \
      debug->ptr = bfd_malloc (amt);                                  \
      if (debug->ptr == NULL)                                         \
       goto error_return;                                      \
      if (bfd_seek (abfd, symhdr->offset, SEEK_SET) != 0              \
         || bfd_bread (debug->ptr, amt, abfd) != amt)                 \
       goto error_return;                                      \
    }

  READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *);
  READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, void *);
  READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, void *);
  READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, void *);
  READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, void *);
  READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext),
       union aux_ext *);
  READ (ss, cbSsOffset, issMax, sizeof (char), char *);
  READ (ssext, cbSsExtOffset, issExtMax, sizeof (char), char *);
  READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, void *);
  READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, void *);
  READ (external_ext, cbExtOffset, iextMax, swap->external_ext_size, void *);
#undef READ

  debug->fdr = NULL;

  return TRUE;

 error_return:
  if (ext_hdr != NULL)
    free (ext_hdr);
  if (debug->line != NULL)
    free (debug->line);
  if (debug->external_dnr != NULL)
    free (debug->external_dnr);
  if (debug->external_pdr != NULL)
    free (debug->external_pdr);
  if (debug->external_sym != NULL)
    free (debug->external_sym);
  if (debug->external_opt != NULL)
    free (debug->external_opt);
  if (debug->external_aux != NULL)
    free (debug->external_aux);
  if (debug->ss != NULL)
    free (debug->ss);
  if (debug->ssext != NULL)
    free (debug->ssext);
  if (debug->external_fdr != NULL)
    free (debug->external_fdr);
  if (debug->external_rfd != NULL)
    free (debug->external_rfd);
  if (debug->external_ext != NULL)
    free (debug->external_ext);
  return FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bfd_boolean _bfd_mips_elf_relocate_section ( bfd ,
struct bfd_link_info ,
bfd ,
asection ,
bfd_byte ,
Elf_Internal_Rela ,
Elf_Internal_Sym *  ,
asection **   
)

Definition at line 7731 of file elfxx-mips.c.

{
  Elf_Internal_Rela *rel;
  const Elf_Internal_Rela *relend;
  bfd_vma addend = 0;
  bfd_boolean use_saved_addend_p = FALSE;
  const struct elf_backend_data *bed;

  bed = get_elf_backend_data (output_bfd);
  relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel;
  for (rel = relocs; rel < relend; ++rel)
    {
      const char *name;
      bfd_vma value = 0;
      reloc_howto_type *howto;
      bfd_boolean require_jalx;
      /* TRUE if the relocation is a RELA relocation, rather than a
         REL relocation.  */
      bfd_boolean rela_relocation_p = TRUE;
      unsigned int r_type = ELF_R_TYPE (output_bfd, rel->r_info);
      const char *msg;
      unsigned long r_symndx;
      asection *sec;
      Elf_Internal_Shdr *symtab_hdr;
      struct elf_link_hash_entry *h;

      /* Find the relocation howto for this relocation.  */
      howto = MIPS_ELF_RTYPE_TO_HOWTO (input_bfd, r_type,
                                   NEWABI_P (input_bfd)
                                   && (MIPS_RELOC_RELA_P
                                      (input_bfd, input_section,
                                       rel - relocs)));

      r_symndx = ELF_R_SYM (input_bfd, rel->r_info);
      symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
      if (mips_elf_local_relocation_p (input_bfd, rel, local_sections, FALSE))
       {
         sec = local_sections[r_symndx];
         h = NULL;
       }
      else
       {
         unsigned long extsymoff;

         extsymoff = 0;
         if (!elf_bad_symtab (input_bfd))
           extsymoff = symtab_hdr->sh_info;
         h = elf_sym_hashes (input_bfd) [r_symndx - extsymoff];
         while (h->root.type == bfd_link_hash_indirect
               || h->root.type == bfd_link_hash_warning)
           h = (struct elf_link_hash_entry *) h->root.u.i.link;

         sec = NULL;
         if (h->root.type == bfd_link_hash_defined
             || h->root.type == bfd_link_hash_defweak)
           sec = h->root.u.def.section;
       }

      if (sec != NULL && elf_discarded_section (sec))
       {
         /* For relocs against symbols from removed linkonce sections,
            or sections discarded by a linker script, we just want the
            section contents zeroed.  Avoid any special processing.  */
         _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
         rel->r_info = 0;
         rel->r_addend = 0;
         continue;
       }

      if (r_type == R_MIPS_64 && ! NEWABI_P (input_bfd))
       {
         /* Some 32-bit code uses R_MIPS_64.  In particular, people use
            64-bit code, but make sure all their addresses are in the
            lowermost or uppermost 32-bit section of the 64-bit address
            space.  Thus, when they use an R_MIPS_64 they mean what is
            usually meant by R_MIPS_32, with the exception that the
            stored value is sign-extended to 64 bits.  */
         howto = MIPS_ELF_RTYPE_TO_HOWTO (input_bfd, R_MIPS_32, FALSE);

         /* On big-endian systems, we need to lie about the position
            of the reloc.  */
         if (bfd_big_endian (input_bfd))
           rel->r_offset += 4;
       }

      if (!use_saved_addend_p)
       {
         Elf_Internal_Shdr *rel_hdr;

         /* If these relocations were originally of the REL variety,
            we must pull the addend out of the field that will be
            relocated.  Otherwise, we simply use the contents of the
            RELA relocation.  To determine which flavor or relocation
            this is, we depend on the fact that the INPUT_SECTION's
            REL_HDR is read before its REL_HDR2.  */
         rel_hdr = &elf_section_data (input_section)->rel_hdr;
         if ((size_t) (rel - relocs)
             >= (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))
           {
             bfd_byte *location = contents + rel->r_offset;

             /* Note that this is a REL relocation.  */
             rela_relocation_p = FALSE;

             /* Get the addend, which is stored in the input file.  */
             _bfd_mips16_elf_reloc_unshuffle (input_bfd, r_type, FALSE,
                                          location);
             addend = mips_elf_obtain_contents (howto, rel, input_bfd,
                                           contents);
             _bfd_mips16_elf_reloc_shuffle(input_bfd, r_type, FALSE,
                                       location);

             addend &= howto->src_mask;

             /* For some kinds of relocations, the ADDEND is a
               combination of the addend stored in two different
               relocations.   */
             if (r_type == R_MIPS_HI16 || r_type == R_MIPS16_HI16
                || (r_type == R_MIPS_GOT16
                    && mips_elf_local_relocation_p (input_bfd, rel,
                                                local_sections, FALSE)))
              {
                const Elf_Internal_Rela *lo16_relocation;
                reloc_howto_type *lo16_howto;
                int lo16_type;

                if (r_type == R_MIPS16_HI16)
                  lo16_type = R_MIPS16_LO16;
                else
                  lo16_type = R_MIPS_LO16;

                /* The combined value is the sum of the HI16 addend,
                   left-shifted by sixteen bits, and the LO16
                   addend, sign extended.  (Usually, the code does
                   a `lui' of the HI16 value, and then an `addiu' of
                   the LO16 value.)

                   Scan ahead to find a matching LO16 relocation.

                   According to the MIPS ELF ABI, the R_MIPS_LO16
                   relocation must be immediately following.
                   However, for the IRIX6 ABI, the next relocation
                   may be a composed relocation consisting of
                   several relocations for the same address.  In
                   that case, the R_MIPS_LO16 relocation may occur
                   as one of these.  We permit a similar extension
                   in general, as that is useful for GCC.

                   In some cases GCC dead code elimination removes
                   the LO16 but keeps the corresponding HI16.  This
                   is strictly speaking a violation of the ABI but
                   not immediately harmful.  */
                lo16_relocation = mips_elf_next_relocation (input_bfd,
                                                       lo16_type,
                                                       rel, relend);
                if (lo16_relocation == NULL)
                  {
                    const char *name;

                    if (h)
                     name = h->root.root.string;
                    else
                     name = bfd_elf_sym_name (input_bfd, symtab_hdr,
                                           local_syms + r_symndx,
                                           sec);
                    (*_bfd_error_handler)
                     (_("%B: Can't find matching LO16 reloc against `%s' for %s at 0x%lx in section `%A'"),
                      input_bfd, input_section, name, howto->name,
                      rel->r_offset);
                  }
                else
                  {
                    bfd_byte *lo16_location;
                    bfd_vma l;

                    lo16_location = contents + lo16_relocation->r_offset;

                    /* Obtain the addend kept there.  */
                    lo16_howto = MIPS_ELF_RTYPE_TO_HOWTO (input_bfd,
                                                     lo16_type, FALSE);
                    _bfd_mips16_elf_reloc_unshuffle (input_bfd, lo16_type,
                                                 FALSE, lo16_location);
                    l = mips_elf_obtain_contents (lo16_howto,
                                              lo16_relocation,
                                              input_bfd, contents);
                    _bfd_mips16_elf_reloc_shuffle (input_bfd, lo16_type,
                                               FALSE, lo16_location);
                    l &= lo16_howto->src_mask;
                    l <<= lo16_howto->rightshift;
                    l = _bfd_mips_elf_sign_extend (l, 16);

                    addend <<= 16;

                    /* Compute the combined addend.  */
                    addend += l;
                  }
              }
             else
              addend <<= howto->rightshift;
           }
         else
           addend = rel->r_addend;
         mips_elf_adjust_addend (output_bfd, info, input_bfd,
                              local_syms, local_sections, rel);
       }

      if (info->relocatable)
       {
         if (r_type == R_MIPS_64 && ! NEWABI_P (output_bfd)
             && bfd_big_endian (input_bfd))
           rel->r_offset -= 4;

         if (!rela_relocation_p && rel->r_addend)
           {
             addend += rel->r_addend;
             if (r_type == R_MIPS_HI16
                || r_type == R_MIPS_GOT16)
              addend = mips_elf_high (addend);
             else if (r_type == R_MIPS_HIGHER)
              addend = mips_elf_higher (addend);
             else if (r_type == R_MIPS_HIGHEST)
              addend = mips_elf_highest (addend);
             else
              addend >>= howto->rightshift;

             /* We use the source mask, rather than the destination
               mask because the place to which we are writing will be
               source of the addend in the final link.  */
             addend &= howto->src_mask;

             if (r_type == R_MIPS_64 && ! NEWABI_P (output_bfd))
              /* See the comment above about using R_MIPS_64 in the 32-bit
                 ABI.  Here, we need to update the addend.  It would be
                 possible to get away with just using the R_MIPS_32 reloc
                 but for endianness.  */
              {
                bfd_vma sign_bits;
                bfd_vma low_bits;
                bfd_vma high_bits;

                if (addend & ((bfd_vma) 1 << 31))
#ifdef BFD64
                  sign_bits = ((bfd_vma) 1 << 32) - 1;
#else
                  sign_bits = -1;
#endif
                else
                  sign_bits = 0;

                /* If we don't know that we have a 64-bit type,
                   do two separate stores.  */
                if (bfd_big_endian (input_bfd))
                  {
                    /* Store the sign-bits (which are most significant)
                      first.  */
                    low_bits = sign_bits;
                    high_bits = addend;
                  }
                else
                  {
                    low_bits = addend;
                    high_bits = sign_bits;
                  }
                bfd_put_32 (input_bfd, low_bits,
                           contents + rel->r_offset);
                bfd_put_32 (input_bfd, high_bits,
                           contents + rel->r_offset + 4);
                continue;
              }

             if (! mips_elf_perform_relocation (info, howto, rel, addend,
                                           input_bfd, input_section,
                                           contents, FALSE))
              return FALSE;
           }

         /* Go on to the next relocation.  */
         continue;
       }

      /* In the N32 and 64-bit ABIs there may be multiple consecutive
        relocations for the same offset.  In that case we are
        supposed to treat the output of each relocation as the addend
        for the next.  */
      if (rel + 1 < relend
         && rel->r_offset == rel[1].r_offset
         && ELF_R_TYPE (input_bfd, rel[1].r_info) != R_MIPS_NONE)
       use_saved_addend_p = TRUE;
      else
       use_saved_addend_p = FALSE;

      /* Figure out what value we are supposed to relocate.  */
      switch (mips_elf_calculate_relocation (output_bfd, input_bfd,
                                        input_section, info, rel,
                                        addend, howto, local_syms,
                                        local_sections, &value,
                                        &name, &require_jalx,
                                        use_saved_addend_p))
       {
       case bfd_reloc_continue:
         /* There's nothing to do.  */
         continue;

       case bfd_reloc_undefined:
         /* mips_elf_calculate_relocation already called the
            undefined_symbol callback.  There's no real point in
            trying to perform the relocation at this point, so we
            just skip ahead to the next relocation.  */
         continue;

       case bfd_reloc_notsupported:
         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)
           /* Ignore overflow until we reach the last relocation for
              a given location.  */
           ;
         else
           {
             BFD_ASSERT (name != NULL);
             if (! ((*info->callbacks->reloc_overflow)
                   (info, NULL, name, howto->name, (bfd_vma) 0,
                    input_bfd, input_section, rel->r_offset)))
              return FALSE;
           }
         break;

       case bfd_reloc_ok:
         break;

       default:
         abort ();
         break;
       }

      /* If we've got another relocation for the address, keep going
        until we reach the last one.  */
      if (use_saved_addend_p)
       {
         addend = value;
         continue;
       }

      if (r_type == R_MIPS_64 && ! NEWABI_P (output_bfd))
       /* See the comment above about using R_MIPS_64 in the 32-bit
          ABI.  Until now, we've been using the HOWTO for R_MIPS_32;
          that calculated the right value.  Now, however, we
          sign-extend the 32-bit result to 64-bits, and store it as a
          64-bit value.  We are especially generous here in that we
          go to extreme lengths to support this usage on systems with
          only a 32-bit VMA.  */
       {
         bfd_vma sign_bits;
         bfd_vma low_bits;
         bfd_vma high_bits;

         if (value & ((bfd_vma) 1 << 31))
#ifdef BFD64
           sign_bits = ((bfd_vma) 1 << 32) - 1;
#else
           sign_bits = -1;
#endif
         else
           sign_bits = 0;

         /* If we don't know that we have a 64-bit type,
            do two separate stores.  */
         if (bfd_big_endian (input_bfd))
           {
             /* Undo what we did above.  */
             rel->r_offset -= 4;
             /* Store the sign-bits (which are most significant)
               first.  */
             low_bits = sign_bits;
             high_bits = value;
           }
         else
           {
             low_bits = value;
             high_bits = sign_bits;
           }
         bfd_put_32 (input_bfd, low_bits,
                    contents + rel->r_offset);
         bfd_put_32 (input_bfd, high_bits,
                    contents + rel->r_offset + 4);
         continue;
       }

      /* Actually perform the relocation.  */
      if (! mips_elf_perform_relocation (info, howto, rel, value,
                                    input_bfd, input_section,
                                    contents, require_jalx))
       return FALSE;
    }

  return TRUE;
}

Here is the call graph for this function:

Definition at line 5413 of file elfxx-mips.c.

{
  flagword flags = 0;

  /* There ought to be a place to keep ELF backend specific flags, but
     at the moment there isn't one.  We just keep track of the
     sections by their name, instead.  Fortunately, the ABI gives
     suggested names for all the MIPS specific sections, so we will
     probably get away with this.  */
  switch (hdr->sh_type)
    {
    case SHT_MIPS_LIBLIST:
      if (strcmp (name, ".liblist") != 0)
       return FALSE;
      break;
    case SHT_MIPS_MSYM:
      if (strcmp (name, ".msym") != 0)
       return FALSE;
      break;
    case SHT_MIPS_CONFLICT:
      if (strcmp (name, ".conflict") != 0)
       return FALSE;
      break;
    case SHT_MIPS_GPTAB:
      if (! CONST_STRNEQ (name, ".gptab."))
       return FALSE;
      break;
    case SHT_MIPS_UCODE:
      if (strcmp (name, ".ucode") != 0)
       return FALSE;
      break;
    case SHT_MIPS_DEBUG:
      if (strcmp (name, ".mdebug") != 0)
       return FALSE;
      flags = SEC_DEBUGGING;
      break;
    case SHT_MIPS_REGINFO:
      if (strcmp (name, ".reginfo") != 0
         || hdr->sh_size != sizeof (Elf32_External_RegInfo))
       return FALSE;
      flags = (SEC_LINK_ONCE | SEC_LINK_DUPLICATES_SAME_SIZE);
      break;
    case SHT_MIPS_IFACE:
      if (strcmp (name, ".MIPS.interfaces") != 0)
       return FALSE;
      break;
    case SHT_MIPS_CONTENT:
      if (! CONST_STRNEQ (name, ".MIPS.content"))
       return FALSE;
      break;
    case SHT_MIPS_OPTIONS:
      if (!MIPS_ELF_OPTIONS_SECTION_NAME_P (name))
       return FALSE;
      break;
    case SHT_MIPS_DWARF:
      if (! CONST_STRNEQ (name, ".debug_"))
       return FALSE;
      break;
    case SHT_MIPS_SYMBOL_LIB:
      if (strcmp (name, ".MIPS.symlib") != 0)
       return FALSE;
      break;
    case SHT_MIPS_EVENTS:
      if (! CONST_STRNEQ (name, ".MIPS.events")
         && ! CONST_STRNEQ (name, ".MIPS.post_rel"))
       return FALSE;
      break;
    default:
      break;
    }

  if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
    return FALSE;

  if (flags)
    {
      if (! bfd_set_section_flags (abfd, hdr->bfd_section,
                               (bfd_get_section_flags (abfd,
                                                    hdr->bfd_section)
                                | flags)))
       return FALSE;
    }

  /* FIXME: We should record sh_info for a .gptab section.  */

  /* For a .reginfo section, set the gp value in the tdata information
     from the contents of this section.  We need the gp value while
     processing relocs, so we just get it now.  The .reginfo section
     is not used in the 64-bit MIPS ELF ABI.  */
  if (hdr->sh_type == SHT_MIPS_REGINFO)
    {
      Elf32_External_RegInfo ext;
      Elf32_RegInfo s;

      if (! bfd_get_section_contents (abfd, hdr->bfd_section,
                                  &ext, 0, sizeof ext))
       return FALSE;
      bfd_mips_elf32_swap_reginfo_in (abfd, &ext, &s);
      elf_gp (abfd) = s.ri_gp_value;
    }

  /* For a SHT_MIPS_OPTIONS section, look for a ODK_REGINFO entry, and
     set the gp value based on what we find.  We may see both
     SHT_MIPS_REGINFO and SHT_MIPS_OPTIONS/ODK_REGINFO; in that case,
     they should agree.  */
  if (hdr->sh_type == SHT_MIPS_OPTIONS)
    {
      bfd_byte *contents, *l, *lend;

      contents = bfd_malloc (hdr->sh_size);
      if (contents == NULL)
       return FALSE;
      if (! bfd_get_section_contents (abfd, hdr->bfd_section, contents,
                                  0, hdr->sh_size))
       {
         free (contents);
         return FALSE;
       }
      l = contents;
      lend = contents + hdr->sh_size;
      while (l + sizeof (Elf_External_Options) <= lend)
       {
         Elf_Internal_Options intopt;

         bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l,
                                   &intopt);
         if (intopt.size < sizeof (Elf_External_Options))
           {
             (*_bfd_error_handler)
              (_("%B: Warning: bad `%s' option size %u smaller than its header"),
              abfd, MIPS_ELF_OPTIONS_SECTION_NAME (abfd), intopt.size);
             break;
           }
         if (ABI_64_P (abfd) && intopt.kind == ODK_REGINFO)
           {
             Elf64_Internal_RegInfo intreg;

             bfd_mips_elf64_swap_reginfo_in
              (abfd,
               ((Elf64_External_RegInfo *)
                (l + sizeof (Elf_External_Options))),
               &intreg);
             elf_gp (abfd) = intreg.ri_gp_value;
           }
         else if (intopt.kind == ODK_REGINFO)
           {
             Elf32_RegInfo intreg;

             bfd_mips_elf32_swap_reginfo_in
              (abfd,
               ((Elf32_External_RegInfo *)
                (l + sizeof (Elf_External_Options))),
               &intreg);
             elf_gp (abfd) = intreg.ri_gp_value;
           }
         l += intopt.size;
       }
      free (contents);
    }

  return TRUE;
}

Here is the call graph for this function:

Definition at line 5280 of file elfxx-mips.c.

{
  if (hdr->sh_type == SHT_MIPS_REGINFO
      && hdr->sh_size > 0)
    {
      bfd_byte buf[4];

      BFD_ASSERT (hdr->sh_size == sizeof (Elf32_External_RegInfo));
      BFD_ASSERT (hdr->contents == NULL);

      if (bfd_seek (abfd,
                  hdr->sh_offset + sizeof (Elf32_External_RegInfo) - 4,
                  SEEK_SET) != 0)
       return FALSE;
      H_PUT_32 (abfd, elf_gp (abfd), buf);
      if (bfd_bwrite (buf, 4, abfd) != 4)
       return FALSE;
    }

  if (hdr->sh_type == SHT_MIPS_OPTIONS
      && hdr->bfd_section != NULL
      && mips_elf_section_data (hdr->bfd_section) != NULL
      && mips_elf_section_data (hdr->bfd_section)->u.tdata != NULL)
    {
      bfd_byte *contents, *l, *lend;

      /* We stored the section contents in the tdata field in the
        set_section_contents routine.  We save the section contents
        so that we don't have to read them again.
        At this point we know that elf_gp is set, so we can look
        through the section contents to see if there is an
        ODK_REGINFO structure.  */

      contents = mips_elf_section_data (hdr->bfd_section)->u.tdata;
      l = contents;
      lend = contents + hdr->sh_size;
      while (l + sizeof (Elf_External_Options) <= lend)
       {
         Elf_Internal_Options intopt;

         bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l,
                                   &intopt);
         if (intopt.size < sizeof (Elf_External_Options))
           {
             (*_bfd_error_handler)
              (_("%B: Warning: bad `%s' option size %u smaller than its header"),
              abfd, MIPS_ELF_OPTIONS_SECTION_NAME (abfd), intopt.size);
             break;
           }
         if (ABI_64_P (abfd) && intopt.kind == ODK_REGINFO)
           {
             bfd_byte buf[8];

             if (bfd_seek (abfd,
                         (hdr->sh_offset
                          + (l - contents)
                          + sizeof (Elf_External_Options)
                          + (sizeof (Elf64_External_RegInfo) - 8)),
                          SEEK_SET) != 0)
              return FALSE;
             H_PUT_64 (abfd, elf_gp (abfd), buf);
             if (bfd_bwrite (buf, 8, abfd) != 8)
              return FALSE;
           }
         else if (intopt.kind == ODK_REGINFO)
           {
             bfd_byte buf[4];

             if (bfd_seek (abfd,
                         (hdr->sh_offset
                          + (l - contents)
                          + sizeof (Elf_External_Options)
                          + (sizeof (Elf32_External_RegInfo) - 4)),
                         SEEK_SET) != 0)
              return FALSE;
             H_PUT_32 (abfd, elf_gp (abfd), buf);
             if (bfd_bwrite (buf, 4, abfd) != 4)
              return FALSE;
           }
         l += intopt.size;
       }
    }

  if (hdr->bfd_section != NULL)
    {
      const char *name = bfd_get_section_name (abfd, hdr->bfd_section);

      if (strcmp (name, ".sdata") == 0
         || strcmp (name, ".lit8") == 0
         || strcmp (name, ".lit4") == 0)
       {
         hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
         hdr->sh_type = SHT_PROGBITS;
       }
      else if (strcmp (name, ".sbss") == 0)
       {
         hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
         hdr->sh_type = SHT_NOBITS;
       }
      else if (strcmp (name, ".srdata") == 0)
       {
         hdr->sh_flags |= SHF_ALLOC | SHF_MIPS_GPREL;
         hdr->sh_type = SHT_PROGBITS;
       }
      else if (strcmp (name, ".compact_rel") == 0)
       {
         hdr->sh_flags = 0;
         hdr->sh_type = SHT_PROGBITS;
       }
      else if (strcmp (name, ".rtproc") == 0)
       {
         if (hdr->sh_addralign != 0 && hdr->sh_entsize == 0)
           {
             unsigned int adjust;

             adjust = hdr->sh_size % hdr->sh_addralign;
             if (adjust != 0)
              hdr->sh_size += hdr->sh_addralign - adjust;
           }
       }
    }

  return TRUE;
}

Here is the call graph for this function:

Definition at line 11209 of file elfxx-mips.c.

{
  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;
}

Definition at line 3663 of file elfxx-mips.c.

{
  if (value & ((bfd_vma) 1 << (bits - 1)))
    /* VALUE is negative.  */
    value |= ((bfd_vma) - 1) << bits;

  return value;
}

Here is the caller graph for this function:

Definition at line 7347 of file elfxx-mips.c.

{
  bfd *dynobj;
  asection *s, *sreldyn;
  bfd_boolean reltext;
  struct mips_elf_link_hash_table *htab;

  htab = mips_elf_hash_table (info);
  dynobj = elf_hash_table (info)->dynobj;
  BFD_ASSERT (dynobj != NULL);

  if (elf_hash_table (info)->dynamic_sections_created)
    {
      /* Set the contents of the .interp section to the interpreter.  */
      if (info->executable)
       {
         s = bfd_get_section_by_name (dynobj, ".interp");
         BFD_ASSERT (s != NULL);
         s->size
           = strlen (ELF_DYNAMIC_INTERPRETER (output_bfd)) + 1;
         s->contents
           = (bfd_byte *) ELF_DYNAMIC_INTERPRETER (output_bfd);
       }
    }

  /* The check_relocs and adjust_dynamic_symbol entry points have
     determined the sizes of the various dynamic sections.  Allocate
     memory for them.  */
  reltext = FALSE;
  sreldyn = NULL;
  for (s = dynobj->sections; s != NULL; s = s->next)
    {
      const char *name;

      /* It's OK to base decisions on the section name, because none
        of the dynobj section names depend upon the input files.  */
      name = bfd_get_section_name (dynobj, s);

      if ((s->flags & SEC_LINKER_CREATED) == 0)
       continue;

      if (CONST_STRNEQ (name, ".rel"))
       {
         if (s->size != 0)
           {
             const char *outname;
             asection *target;

             /* If this relocation section applies to a read only
                 section, then we probably need a DT_TEXTREL entry.
                 If the relocation section is .rel(a).dyn, we always
                 assert a DT_TEXTREL entry rather than testing whether
                 there exists a relocation to a read only section or
                 not.  */
             outname = bfd_get_section_name (output_bfd,
                                         s->output_section);
             target = bfd_get_section_by_name (output_bfd, outname + 4);
             if ((target != NULL
                 && (target->flags & SEC_READONLY) != 0
                 && (target->flags & SEC_ALLOC) != 0)
                || strcmp (outname, MIPS_ELF_REL_DYN_NAME (info)) == 0)
              reltext = TRUE;

             /* We use the reloc_count field as a counter if we need
               to copy relocs into the output file.  */
             if (strcmp (name, MIPS_ELF_REL_DYN_NAME (info)) != 0)
              s->reloc_count = 0;

             /* If combreloc is enabled, elf_link_sort_relocs() will
               sort relocations, but in a different way than we do,
               and before we're done creating relocations.  Also, it
               will move them around between input sections'
               relocation's contents, so our sorting would be
               broken, so don't let it run.  */
             info->combreloc = 0;
           }
       }
      else if (htab->is_vxworks && strcmp (name, ".got") == 0)
       {
         /* Executables do not need a GOT.  */
         if (info->shared)
           {
             /* Allocate relocations for all but the reserved entries.  */
             struct mips_got_info *g;
             unsigned int count;

             g = mips_elf_got_info (dynobj, NULL);
             count = (g->global_gotno
                     + g->local_gotno
                     - MIPS_RESERVED_GOTNO (info));
             mips_elf_allocate_dynamic_relocations (dynobj, info, count);
           }
       }
      else if (!htab->is_vxworks && CONST_STRNEQ (name, ".got"))
       {
         /* _bfd_mips_elf_always_size_sections() has already done
            most of the work, but some symbols may have been mapped
            to versions that we must now resolve in the got_entries
            hash tables.  */
         struct mips_got_info *gg = mips_elf_got_info (dynobj, NULL);
         struct mips_got_info *g = gg;
         struct mips_elf_set_global_got_offset_arg set_got_offset_arg;
         unsigned int needed_relocs = 0;

         if (gg->next)
           {
             set_got_offset_arg.value = MIPS_ELF_GOT_SIZE (output_bfd);
             set_got_offset_arg.info = info;

             /* NOTE 2005-02-03: How can this call, or the next, ever
               find any indirect entries to resolve?  They were all
               resolved in mips_elf_multi_got.  */
             mips_elf_resolve_final_got_entries (gg);
             for (g = gg->next; g && g->next != gg; g = g->next)
              {
                unsigned int save_assign;

                mips_elf_resolve_final_got_entries (g);

                /* Assign offsets to global GOT entries.  */
                save_assign = g->assigned_gotno;
                g->assigned_gotno = g->local_gotno;
                set_got_offset_arg.g = g;
                set_got_offset_arg.needed_relocs = 0;
                htab_traverse (g->got_entries,
                             mips_elf_set_global_got_offset,
                             &set_got_offset_arg);
                needed_relocs += set_got_offset_arg.needed_relocs;
                BFD_ASSERT (g->assigned_gotno - g->local_gotno
                           <= g->global_gotno);

                g->assigned_gotno = save_assign;
                if (info->shared)
                  {
                    needed_relocs += g->local_gotno - g->assigned_gotno;
                    BFD_ASSERT (g->assigned_gotno == g->next->local_gotno
                              + g->next->global_gotno
                              + g->next->tls_gotno
                              + MIPS_RESERVED_GOTNO (info));
                  }
              }
           }
         else
           {
             struct mips_elf_count_tls_arg arg;
             arg.info = info;
             arg.needed = 0;

             htab_traverse (gg->got_entries, mips_elf_count_local_tls_relocs,
                          &arg);
             elf_link_hash_traverse (elf_hash_table (info),
                                  mips_elf_count_global_tls_relocs,
                                  &arg);

             needed_relocs += arg.needed;
           }

         if (needed_relocs)
           mips_elf_allocate_dynamic_relocations (dynobj, info,
                                             needed_relocs);
       }
      else if (strcmp (name, MIPS_ELF_STUB_SECTION_NAME (output_bfd)) == 0)
       {
         /* IRIX rld assumes that the function stub isn't at the end
            of .text section.  So put a dummy.  XXX  */
         s->size += htab->function_stub_size;
       }
      else if (! info->shared
              && ! mips_elf_hash_table (info)->use_rld_obj_head
              && CONST_STRNEQ (name, ".rld_map"))
       {
         /* We add a room for __rld_map.  It will be filled in by the
            rtld to contain a pointer to the _r_debug structure.  */
         s->size += 4;
       }
      else if (SGI_COMPAT (output_bfd)
              && CONST_STRNEQ (name, ".compact_rel"))
       s->size += mips_elf_hash_table (info)->compact_rel_size;
      else if (! CONST_STRNEQ (name, ".init")
              && s != htab->sgotplt
              && s != htab->splt)
       {
         /* It's not one of our sections, so don't allocate space.  */
         continue;
       }

      if (s->size == 0)
       {
         s->flags |= SEC_EXCLUDE;
         continue;
       }

      if ((s->flags & SEC_HAS_CONTENTS) == 0)
       continue;

      /* Allocate memory for this section last, since we may increase its
        size above.  */
      if (strcmp (name, MIPS_ELF_REL_DYN_NAME (info)) == 0)
       {
         sreldyn = s;
         continue;
       }

      /* Allocate memory for the section contents.  */
      s->contents = bfd_zalloc (dynobj, s->size);
      if (s->contents == NULL)
       {
         bfd_set_error (bfd_error_no_memory);
         return FALSE;
       }
    }

  /* Allocate memory for the .rel(a).dyn section.  */
  if (sreldyn != NULL)
    {
      sreldyn->contents = bfd_zalloc (dynobj, sreldyn->size);
      if (sreldyn->contents == NULL)
       {
         bfd_set_error (bfd_error_no_memory);
         return FALSE;
       }
    }

  if (elf_hash_table (info)->dynamic_sections_created)
    {
      /* Add some entries to the .dynamic section.  We fill in the
        values later, in _bfd_mips_elf_finish_dynamic_sections, but we
        must add the entries now so that we get the correct size for
        the .dynamic section.  The DT_DEBUG entry is filled in by the
        dynamic linker and used by the debugger.  */
      if (info->executable)
       {
         /* SGI object has the equivalence of DT_DEBUG in the
            DT_MIPS_RLD_MAP entry.  */
         if (!MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_RLD_MAP, 0))
           return FALSE;
         if (!SGI_COMPAT (output_bfd))
           {
             if (!MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_DEBUG, 0))
              return FALSE;
           }
       }

      if (reltext && (SGI_COMPAT (output_bfd) || htab->is_vxworks))
       info->flags |= DF_TEXTREL;

      if ((info->flags & DF_TEXTREL) != 0)
       {
         if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_TEXTREL, 0))
           return FALSE;

         /* Clear the DF_TEXTREL flag.  It will be set again if we
            write out an actual text relocation; we may not, because
            at this point we do not know whether e.g. any .eh_frame
            absolute relocations have been converted to PC-relative.  */
         info->flags &= ~DF_TEXTREL;
       }

      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTGOT, 0))
       return FALSE;

      if (htab->is_vxworks)
       {
         /* VxWorks uses .rela.dyn instead of .rel.dyn.  It does not
            use any of the DT_MIPS_* tags.  */
         if (mips_elf_rel_dyn_section (info, FALSE))
           {
             if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELA, 0))
              return FALSE;

             if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELASZ, 0))
              return FALSE;

             if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELAENT, 0))
              return FALSE;
           }
         if (htab->splt->size > 0)
           {
             if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTREL, 0))
              return FALSE;

             if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_JMPREL, 0))
              return FALSE;

             if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTRELSZ, 0))
              return FALSE;
           }
       }
      else
       {
         if (mips_elf_rel_dyn_section (info, FALSE))
           {
             if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_REL, 0))
              return FALSE;

             if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELSZ, 0))
              return FALSE;

             if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELENT, 0))
              return FALSE;
           }

         if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_RLD_VERSION, 0))
           return FALSE;

         if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_FLAGS, 0))
           return FALSE;

         if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_BASE_ADDRESS, 0))
           return FALSE;

         if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_LOCAL_GOTNO, 0))
           return FALSE;

         if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_SYMTABNO, 0))
           return FALSE;

         if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_UNREFEXTNO, 0))
           return FALSE;

         if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_GOTSYM, 0))
           return FALSE;

         if (IRIX_COMPAT (dynobj) == ict_irix5
             && ! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_HIPAGENO, 0))
           return FALSE;

         if (IRIX_COMPAT (dynobj) == ict_irix6
             && (bfd_get_section_by_name
                (dynobj, MIPS_ELF_OPTIONS_SECTION_NAME (dynobj)))
             && !MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_OPTIONS, 0))
           return FALSE;
       }
    }

  return TRUE;
}

Here is the call graph for this function:

Definition at line 5095 of file elfxx-mips.c.

{
  elf_symbol_type *elfsym;

  elfsym = (elf_symbol_type *) asym;
  switch (elfsym->internal_elf_sym.st_shndx)
    {
    case SHN_MIPS_ACOMMON:
      /* This section is used in a dynamically linked executable file.
        It is an allocated common section.  The dynamic linker can
        either resolve these symbols to something in a shared
        library, or it can just leave them here.  For our purposes,
        we can consider these symbols to be in a new section.  */
      if (mips_elf_acom_section.name == NULL)
       {
         /* Initialize the acommon section.  */
         mips_elf_acom_section.name = ".acommon";
         mips_elf_acom_section.flags = SEC_ALLOC;
         mips_elf_acom_section.output_section = &mips_elf_acom_section;
         mips_elf_acom_section.symbol = &mips_elf_acom_symbol;
         mips_elf_acom_section.symbol_ptr_ptr = &mips_elf_acom_symbol_ptr;
         mips_elf_acom_symbol.name = ".acommon";
         mips_elf_acom_symbol.flags = BSF_SECTION_SYM;
         mips_elf_acom_symbol.section = &mips_elf_acom_section;
         mips_elf_acom_symbol_ptr = &mips_elf_acom_symbol;
       }
      asym->section = &mips_elf_acom_section;
      break;

    case SHN_COMMON:
      /* Common symbols less than the GP size are automatically
        treated as SHN_MIPS_SCOMMON symbols on IRIX5.  */
      if (asym->value > elf_gp_size (abfd)
         || ELF_ST_TYPE (elfsym->internal_elf_sym.st_info) == STT_TLS
         || IRIX_COMPAT (abfd) == ict_irix6)
       break;
      /* Fall through.  */
    case SHN_MIPS_SCOMMON:
      if (mips_elf_scom_section.name == NULL)
       {
         /* Initialize the small common section.  */
         mips_elf_scom_section.name = ".scommon";
         mips_elf_scom_section.flags = SEC_IS_COMMON;
         mips_elf_scom_section.output_section = &mips_elf_scom_section;
         mips_elf_scom_section.symbol = &mips_elf_scom_symbol;
         mips_elf_scom_section.symbol_ptr_ptr = &mips_elf_scom_symbol_ptr;
         mips_elf_scom_symbol.name = ".scommon";
         mips_elf_scom_symbol.flags = BSF_SECTION_SYM;
         mips_elf_scom_symbol.section = &mips_elf_scom_section;
         mips_elf_scom_symbol_ptr = &mips_elf_scom_symbol;
       }
      asym->section = &mips_elf_scom_section;
      asym->value = elfsym->internal_elf_sym.st_size;
      break;

    case SHN_MIPS_SUNDEFINED:
      asym->section = bfd_und_section_ptr;
      break;

    case SHN_MIPS_TEXT:
      {
       asection *section = bfd_get_section_by_name (abfd, ".text");

       BFD_ASSERT (SGI_COMPAT (abfd));
       if (section != NULL)
         {
           asym->section = section;
           /* MIPS_TEXT is a bit special, the address is not an offset
              to the base of the .text section.  So substract the section
              base address to make it an offset.  */
           asym->value -= section->vma;
         }
      }
      break;

    case SHN_MIPS_DATA:
      {
       asection *section = bfd_get_section_by_name (abfd, ".data");

       BFD_ASSERT (SGI_COMPAT (abfd));
       if (section != NULL)
         {
           asym->section = section;
           /* MIPS_DATA is a bit special, the address is not an offset
              to the base of the .data section.  So substract the section
              base address to make it an offset.  */
           asym->value -= section->vma;
         }
      }
      break;
    }
}

Here is the call graph for this function:

Definition at line 6754 of file elfxx-mips.c.

{
  Elf_Internal_Rela *internal_relocs;
  Elf_Internal_Rela *irel, *irelend;
  Elf_Internal_Shdr *symtab_hdr;
  bfd_byte *contents = NULL;
  size_t extsymoff;
  bfd_boolean changed_contents = FALSE;
  bfd_vma sec_start = sec->output_section->vma + sec->output_offset;
  Elf_Internal_Sym *isymbuf = NULL;

  /* We are not currently changing any sizes, so only one pass.  */
  *again = FALSE;

  if (link_info->relocatable)
    return TRUE;

  internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
                                          link_info->keep_memory);
  if (internal_relocs == NULL)
    return TRUE;

  irelend = internal_relocs + sec->reloc_count
    * get_elf_backend_data (abfd)->s->int_rels_per_ext_rel;
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
  extsymoff = (elf_bad_symtab (abfd)) ? 0 : symtab_hdr->sh_info;

  for (irel = internal_relocs; irel < irelend; irel++)
    {
      bfd_vma symval;
      bfd_signed_vma sym_offset;
      unsigned int r_type;
      unsigned long r_symndx;
      asection *sym_sec;
      unsigned long instruction;

      /* Turn jalr into bgezal, and jr into beq, if they're marked
        with a JALR relocation, that indicate where they jump to.
        This saves some pipeline bubbles.  */
      r_type = ELF_R_TYPE (abfd, irel->r_info);
      if (r_type != R_MIPS_JALR)
       continue;

      r_symndx = ELF_R_SYM (abfd, irel->r_info);
      /* Compute the address of the jump target.  */
      if (r_symndx >= extsymoff)
       {
         struct mips_elf_link_hash_entry *h
           = ((struct mips_elf_link_hash_entry *)
              elf_sym_hashes (abfd) [r_symndx - extsymoff]);

         while (h->root.root.type == bfd_link_hash_indirect
               || h->root.root.type == bfd_link_hash_warning)
           h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;

         /* If a symbol is undefined, or if it may be overridden,
            skip it.  */
         if (! ((h->root.root.type == bfd_link_hash_defined
                || h->root.root.type == bfd_link_hash_defweak)
               && h->root.root.u.def.section)
             || (link_info->shared && ! link_info->symbolic
                && !h->root.forced_local))
           continue;

         sym_sec = h->root.root.u.def.section;
         if (sym_sec->output_section)
           symval = (h->root.root.u.def.value
                    + sym_sec->output_section->vma
                    + sym_sec->output_offset);
         else
           symval = h->root.root.u.def.value;
       }
      else
       {
         Elf_Internal_Sym *isym;

         /* Read this BFD's symbols if we haven't done so already.  */
         if (isymbuf == NULL && symtab_hdr->sh_info != 0)
           {
             isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
             if (isymbuf == NULL)
              isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
                                          symtab_hdr->sh_info, 0,
                                          NULL, NULL, NULL);
             if (isymbuf == NULL)
              goto relax_return;
           }

         isym = isymbuf + r_symndx;
         if (isym->st_shndx == SHN_UNDEF)
           continue;
         else if (isym->st_shndx == SHN_ABS)
           sym_sec = bfd_abs_section_ptr;
         else if (isym->st_shndx == SHN_COMMON)
           sym_sec = bfd_com_section_ptr;
         else
           sym_sec
             = bfd_section_from_elf_index (abfd, isym->st_shndx);
         symval = isym->st_value
           + sym_sec->output_section->vma
           + sym_sec->output_offset;
       }

      /* Compute branch offset, from delay slot of the jump to the
        branch target.  */
      sym_offset = (symval + irel->r_addend)
       - (sec_start + irel->r_offset + 4);

      /* Branch offset must be properly aligned.  */
      if ((sym_offset & 3) != 0)
       continue;

      sym_offset >>= 2;

      /* Check that it's in range.  */
      if (sym_offset < -0x8000 || sym_offset >= 0x8000)
       continue;

      /* Get the section contents if we haven't done so already.  */
      if (contents == NULL)
       {
         /* Get cached copy if it exists.  */
         if (elf_section_data (sec)->this_hdr.contents != NULL)
           contents = elf_section_data (sec)->this_hdr.contents;
         else
           {
             if (!bfd_malloc_and_get_section (abfd, sec, &contents))
              goto relax_return;
           }
       }

      instruction = bfd_get_32 (abfd, contents + irel->r_offset);

      /* If it was jalr <reg>, turn it into bgezal $zero, <target>.  */
      if ((instruction & 0xfc1fffff) == 0x0000f809)
       instruction = 0x04110000;
      /* If it was jr <reg>, turn it into b <target>.  */
      else if ((instruction & 0xfc1fffff) == 0x00000008)
       instruction = 0x10000000;
      else
       continue;

      instruction |= (sym_offset & 0xffff);
      bfd_put_32 (abfd, instruction, contents + irel->r_offset);
      changed_contents = TRUE;
    }

  if (contents != NULL
      && elf_section_data (sec)->this_hdr.contents != contents)
    {
      if (!changed_contents && !link_info->keep_memory)
        free (contents);
      else
        {
          /* Cache the section contents for elf_link_input_bfd.  */
          elf_section_data (sec)->this_hdr.contents = contents;
        }
    }
  return TRUE;

 relax_return:
  if (contents != NULL
      && elf_section_data (sec)->this_hdr.contents != contents)
    free (contents);
  return FALSE;
}

Here is the call graph for this function:

Definition at line 7028 of file elfxx-mips.c.

{
  bfd *dynobj;
  struct mips_elf_link_hash_entry *hmips;
  struct mips_elf_link_hash_table *htab;
  unsigned int power_of_two;

  htab = mips_elf_hash_table (info);
  dynobj = elf_hash_table (info)->dynobj;
  hmips = (struct mips_elf_link_hash_entry *) h;

  /* Make sure we know what is going on here.  */
  BFD_ASSERT (dynobj != NULL
             && (h->needs_plt
                || h->needs_copy
                || h->u.weakdef != NULL
                || (h->def_dynamic
                    && h->ref_regular
                    && !h->def_regular)));

  /* If the symbol is defined by a dynamic object, we need a PLT stub if
     either (a) we want to branch to the symbol or (b) we're linking an
     executable that needs a canonical function address.  In the latter
     case, the canonical address will be the address of the executable's
     load stub.  */
  if ((hmips->is_branch_target
       || (!info->shared
          && h->type == STT_FUNC
          && hmips->is_relocation_target))
      && h->def_dynamic
      && h->ref_regular
      && !h->def_regular
      && !h->forced_local)
    h->needs_plt = 1;

  /* Locally-binding symbols do not need a PLT stub; we can refer to
     the functions directly.  */
  else if (h->needs_plt
          && (SYMBOL_CALLS_LOCAL (info, h)
              || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
                 && h->root.type == bfd_link_hash_undefweak)))
    {
      h->needs_plt = 0;
      return TRUE;
    }

  if (h->needs_plt)
    {
      /* If this is the first symbol to need a PLT entry, allocate room
        for the header, and for the header's .rela.plt.unloaded entries.  */
      if (htab->splt->size == 0)
       {
         htab->splt->size += htab->plt_header_size;
         if (!info->shared)
           htab->srelplt2->size += 2 * sizeof (Elf32_External_Rela);
       }

      /* Assign the next .plt entry to this symbol.  */
      h->plt.offset = htab->splt->size;
      htab->splt->size += htab->plt_entry_size;

      /* If the output file has no definition of the symbol, set the
        symbol's value to the address of the stub.  For executables,
        point at the PLT load stub rather than the lazy resolution stub;
        this stub will become the canonical function address.  */
      if (!h->def_regular)
       {
         h->root.u.def.section = htab->splt;
         h->root.u.def.value = h->plt.offset;
         if (!info->shared)
           h->root.u.def.value += 8;
       }

      /* Make room for the .got.plt entry and the R_JUMP_SLOT relocation.  */
      htab->sgotplt->size += 4;
      htab->srelplt->size += sizeof (Elf32_External_Rela);

      /* Make room for the .rela.plt.unloaded relocations.  */
      if (!info->shared)
       htab->srelplt2->size += 3 * sizeof (Elf32_External_Rela);

      return TRUE;
    }

  /* If a function symbol is defined by a dynamic object, and we do not
     need a PLT stub for it, the symbol's value should be zero.  */
  if (h->type == STT_FUNC
      && h->def_dynamic
      && h->ref_regular
      && !h->def_regular)
    {
      h->root.u.def.value = 0;
      return TRUE;
    }

  /* If this is a weak symbol, and there is a real definition, the
     processor independent code will have arranged for us to see the
     real definition first, and we can just use the same value.  */
  if (h->u.weakdef != NULL)
    {
      BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
                || h->u.weakdef->root.type == bfd_link_hash_defweak);
      h->root.u.def.section = h->u.weakdef->root.u.def.section;
      h->root.u.def.value = h->u.weakdef->root.u.def.value;
      return TRUE;
    }

  /* This is a reference to a symbol defined by a dynamic object which
     is not a function.  */
  if (info->shared)
    return TRUE;

  /* We must allocate the symbol in our .dynbss section, which will
     become part of the .bss section of the executable.  There will be
     an entry for this symbol in the .dynsym section.  The dynamic
     object will contain position independent code, so all references
     from the dynamic object to this symbol will go through the global
     offset table.  The dynamic linker will use the .dynsym entry to
     determine the address it must put in the global offset table, so
     both the dynamic object and the regular object will refer to the
     same memory location for the variable.  */

  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
    {
      htab->srelbss->size += sizeof (Elf32_External_Rela);
      h->needs_copy = 1;
    }

  /* We need to figure out the alignment required for this symbol.  */
  power_of_two = bfd_log2 (h->size);
  if (power_of_two > 4)
    power_of_two = 4;

  /* Apply the required alignment.  */
  htab->sdynbss->size = BFD_ALIGN (htab->sdynbss->size,
                               (bfd_size_type) 1 << power_of_two);
  if (power_of_two > bfd_get_section_alignment (dynobj, htab->sdynbss)
      && !bfd_set_section_alignment (dynobj, htab->sdynbss, power_of_two))
    return FALSE;

  /* Define the symbol as being at this point in the section.  */
  h->root.u.def.section = htab->sdynbss;
  h->root.u.def.value = htab->sdynbss->size;

  /* Increment the section size to make room for the symbol.  */
  htab->sdynbss->size += h->size;

  return TRUE;
}

Here is the call graph for this function:

Definition at line 8427 of file elfxx-mips.c.

{
  bfd *dynobj;
  asection *sgot;
  struct mips_got_info *g;
  struct mips_elf_link_hash_table *htab;

  htab = mips_elf_hash_table (info);
  dynobj = elf_hash_table (info)->dynobj;

  if (h->plt.offset != (bfd_vma) -1)
    {
      bfd_byte *loc;
      bfd_vma plt_address, plt_index, got_address, got_offset, branch_offset;
      Elf_Internal_Rela rel;
      static const bfd_vma *plt_entry;

      BFD_ASSERT (h->dynindx != -1);
      BFD_ASSERT (htab->splt != NULL);
      BFD_ASSERT (h->plt.offset <= htab->splt->size);

      /* Calculate the address of the .plt entry.  */
      plt_address = (htab->splt->output_section->vma
                   + htab->splt->output_offset
                   + h->plt.offset);

      /* Calculate the index of the entry.  */
      plt_index = ((h->plt.offset - htab->plt_header_size)
                 / htab->plt_entry_size);

      /* Calculate the address of the .got.plt entry.  */
      got_address = (htab->sgotplt->output_section->vma
                   + htab->sgotplt->output_offset
                   + plt_index * 4);

      /* Calculate the offset of the .got.plt entry from
        _GLOBAL_OFFSET_TABLE_.  */
      got_offset = mips_elf_gotplt_index (info, h);

      /* Calculate the offset for the branch at the start of the PLT
        entry.  The branch jumps to the beginning of .plt.  */
      branch_offset = -(h->plt.offset / 4 + 1) & 0xffff;

      /* Fill in the initial value of the .got.plt entry.  */
      bfd_put_32 (output_bfd, plt_address,
                htab->sgotplt->contents + plt_index * 4);

      /* Find out where the .plt entry should go.  */
      loc = htab->splt->contents + h->plt.offset;

      if (info->shared)
       {
         plt_entry = mips_vxworks_shared_plt_entry;
         bfd_put_32 (output_bfd, plt_entry[0] | branch_offset, loc);
         bfd_put_32 (output_bfd, plt_entry[1] | plt_index, loc + 4);
       }
      else
       {
         bfd_vma got_address_high, got_address_low;

         plt_entry = mips_vxworks_exec_plt_entry;
         got_address_high = ((got_address + 0x8000) >> 16) & 0xffff;
         got_address_low = got_address & 0xffff;

         bfd_put_32 (output_bfd, plt_entry[0] | branch_offset, loc);
         bfd_put_32 (output_bfd, plt_entry[1] | plt_index, loc + 4);
         bfd_put_32 (output_bfd, plt_entry[2] | got_address_high, loc + 8);
         bfd_put_32 (output_bfd, plt_entry[3] | got_address_low, loc + 12);
         bfd_put_32 (output_bfd, plt_entry[4], loc + 16);
         bfd_put_32 (output_bfd, plt_entry[5], loc + 20);
         bfd_put_32 (output_bfd, plt_entry[6], loc + 24);
         bfd_put_32 (output_bfd, plt_entry[7], loc + 28);

         loc = (htab->srelplt2->contents
               + (plt_index * 3 + 2) * sizeof (Elf32_External_Rela));

         /* Emit a relocation for the .got.plt entry.  */
         rel.r_offset = got_address;
         rel.r_info = ELF32_R_INFO (htab->root.hplt->indx, R_MIPS_32);
         rel.r_addend = h->plt.offset;
         bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);

         /* Emit a relocation for the lui of %hi(<.got.plt slot>).  */
         loc += sizeof (Elf32_External_Rela);
         rel.r_offset = plt_address + 8;
         rel.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_MIPS_HI16);
         rel.r_addend = got_offset;
         bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);

         /* Emit a relocation for the addiu of %lo(<.got.plt slot>).  */
         loc += sizeof (Elf32_External_Rela);
         rel.r_offset += 4;
         rel.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_MIPS_LO16);
         bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);
       }

      /* Emit an R_MIPS_JUMP_SLOT relocation against the .got.plt entry.  */
      loc = htab->srelplt->contents + plt_index * sizeof (Elf32_External_Rela);
      rel.r_offset = got_address;
      rel.r_info = ELF32_R_INFO (h->dynindx, R_MIPS_JUMP_SLOT);
      rel.r_addend = 0;
      bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);

      if (!h->def_regular)
       sym->st_shndx = SHN_UNDEF;
    }

  BFD_ASSERT (h->dynindx != -1 || h->forced_local);

  sgot = mips_elf_got_section (dynobj, FALSE);
  BFD_ASSERT (sgot != NULL);
  BFD_ASSERT (mips_elf_section_data (sgot) != NULL);
  g = mips_elf_section_data (sgot)->u.got_info;
  BFD_ASSERT (g != NULL);

  /* See if this symbol has an entry in the GOT.  */
  if (g->global_gotsym != NULL
      && h->dynindx >= g->global_gotsym->dynindx)
    {
      bfd_vma offset;
      Elf_Internal_Rela outrel;
      bfd_byte *loc;
      asection *s;

      /* Install the symbol value in the GOT.   */
      offset = mips_elf_global_got_index (dynobj, output_bfd, h,
                                     R_MIPS_GOT16, info);
      MIPS_ELF_PUT_WORD (output_bfd, sym->st_value, sgot->contents + offset);

      /* Add a dynamic relocation for it.  */
      s = mips_elf_rel_dyn_section (info, FALSE);
      loc = s->contents + (s->reloc_count++ * sizeof (Elf32_External_Rela));
      outrel.r_offset = (sgot->output_section->vma
                      + sgot->output_offset
                      + offset);
      outrel.r_info = ELF32_R_INFO (h->dynindx, R_MIPS_32);
      outrel.r_addend = 0;
      bfd_elf32_swap_reloca_out (dynobj, &outrel, loc);
    }

  /* Emit a copy reloc, if needed.  */
  if (h->needs_copy)
    {
      Elf_Internal_Rela rel;

      BFD_ASSERT (h->dynindx != -1);

      rel.r_offset = (h->root.u.def.section->output_section->vma
                    + h->root.u.def.section->output_offset
                    + h->root.u.def.value);
      rel.r_info = ELF32_R_INFO (h->dynindx, R_MIPS_COPY);
      rel.r_addend = 0;
      bfd_elf32_swap_reloca_out (output_bfd, &rel,
                             htab->srelbss->contents
                             + (htab->srelbss->reloc_count
                                * sizeof (Elf32_External_Rela)));
      ++htab->srelbss->reloc_count;
    }

  /* If this is a mips16 symbol, force the value to be even.  */
  if (sym->st_other == STO_MIPS16)
    sym->st_value &= ~1;

  return TRUE;
}

Here is the call graph for this function:

Definition at line 10218 of file elfxx-mips.c.

{
  struct bfd_link_hash_table *ret;

  ret = _bfd_mips_elf_link_hash_table_create (abfd);
  if (ret)
    {
      struct mips_elf_link_hash_table *htab;

      htab = (struct mips_elf_link_hash_table *) ret;
      htab->is_vxworks = 1;
    }
  return ret;
}

Here is the call graph for this function: