OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [bfd/] [elf32-cris.c] - Diff between revs 157 and 225

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 157 Rev 225
Line 1... Line 1...
/* CRIS-specific support for 32-bit ELF.
/* CRIS-specific support for 32-bit ELF.
   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
   Free Software Foundation, Inc.
   Free Software Foundation, Inc.
   Contributed by Axis Communications AB.
   Contributed by Axis Communications AB.
   Written by Hans-Peter Nilsson, based on elf32-fr30.c
   Written by Hans-Peter Nilsson, based on elf32-fr30.c
   PIC and shlib bits based primarily on elf32-m68k.c and elf32-i386.c.
   PIC and shlib bits based primarily on elf32-m68k.c and elf32-i386.c.
 
 
Line 25... Line 25...
#include "sysdep.h"
#include "sysdep.h"
#include "bfd.h"
#include "bfd.h"
#include "libbfd.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf-bfd.h"
#include "elf/cris.h"
#include "elf/cris.h"
 
#include <limits.h>
 
 
/* Forward declarations.  */
/* Forward declarations.  */
static reloc_howto_type * cris_reloc_type_lookup
static reloc_howto_type * cris_reloc_type_lookup
  PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
  PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
 
 
Line 407... Line 408...
         cris_elf_pcrel_reloc,  /* special_function */
         cris_elf_pcrel_reloc,  /* special_function */
         "R_CRIS_32_PLT_PCREL", /* name */
         "R_CRIS_32_PLT_PCREL", /* name */
         FALSE,                 /* partial_inplace */
         FALSE,                 /* partial_inplace */
         0,                      /* src_mask */
         0,                      /* src_mask */
         0xffffffff,            /* dst_mask */
         0xffffffff,            /* dst_mask */
         TRUE)                  /* pcrel_offset */
         TRUE),                 /* pcrel_offset */
 
 
 
  /* We don't handle these in any special manner and cross-format
 
     linking is not supported; just recognize them enough to pass them
 
     around.  FIXME: do the same for most PIC relocs and add sanity
 
     tests to actually refuse gracefully to handle these and PIC
 
     relocs for cross-format linking.  */
 
#define TLSHOWTO32(name) \
 
 HOWTO (name, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, \
 
        bfd_elf_generic_reloc, #name, FALSE, 0, 0xffffffff, FALSE)
 
#define TLSHOWTO16X(name, X)         \
 
 HOWTO (name, 0, 1, 16, FALSE, 0, complain_overflow_ ## X, \
 
        bfd_elf_generic_reloc, #name, FALSE, 0, 0xffff, FALSE)
 
#define TLSHOWTO16(name) TLSHOWTO16X(name, unsigned)
 
#define TLSHOWTO16S(name) TLSHOWTO16X(name, signed)
 
 
 
  TLSHOWTO32 (R_CRIS_32_GOT_GD),
 
  TLSHOWTO16 (R_CRIS_16_GOT_GD),
 
  TLSHOWTO32 (R_CRIS_32_GD),
 
  TLSHOWTO32 (R_CRIS_DTP),
 
  TLSHOWTO32 (R_CRIS_32_DTPREL),
 
  TLSHOWTO16S (R_CRIS_16_DTPREL),
 
  TLSHOWTO32 (R_CRIS_32_GOT_TPREL),
 
  TLSHOWTO16S (R_CRIS_16_GOT_TPREL),
 
  TLSHOWTO32 (R_CRIS_32_TPREL),
 
  TLSHOWTO16S (R_CRIS_16_TPREL),
 
  TLSHOWTO32 (R_CRIS_DTPMOD),
 
  TLSHOWTO32 (R_CRIS_32_IE)
};
};


/* Map BFD reloc types to CRIS ELF reloc types.  */
/* Map BFD reloc types to CRIS ELF reloc types.  */
 
 
struct cris_reloc_map
struct cris_reloc_map
Line 439... Line 467...
  { BFD_RELOC_CRIS_32_GOT,      R_CRIS_32_GOT },
  { BFD_RELOC_CRIS_32_GOT,      R_CRIS_32_GOT },
  { BFD_RELOC_CRIS_16_GOTPLT,   R_CRIS_16_GOTPLT },
  { BFD_RELOC_CRIS_16_GOTPLT,   R_CRIS_16_GOTPLT },
  { BFD_RELOC_CRIS_32_GOTPLT,   R_CRIS_32_GOTPLT },
  { BFD_RELOC_CRIS_32_GOTPLT,   R_CRIS_32_GOTPLT },
  { BFD_RELOC_CRIS_32_GOTREL,   R_CRIS_32_GOTREL },
  { BFD_RELOC_CRIS_32_GOTREL,   R_CRIS_32_GOTREL },
  { BFD_RELOC_CRIS_32_PLT_GOTREL, R_CRIS_32_PLT_GOTREL },
  { BFD_RELOC_CRIS_32_PLT_GOTREL, R_CRIS_32_PLT_GOTREL },
  { BFD_RELOC_CRIS_32_PLT_PCREL, R_CRIS_32_PLT_PCREL }
  { BFD_RELOC_CRIS_32_PLT_PCREL, R_CRIS_32_PLT_PCREL },
 
  { BFD_RELOC_CRIS_32_GOT_GD,   R_CRIS_32_GOT_GD },
 
  { BFD_RELOC_CRIS_16_GOT_GD,   R_CRIS_16_GOT_GD },
 
  { BFD_RELOC_CRIS_32_GD,       R_CRIS_32_GD },
 
  { BFD_RELOC_CRIS_DTP, R_CRIS_DTP },
 
  { BFD_RELOC_CRIS_32_DTPREL,   R_CRIS_32_DTPREL },
 
  { BFD_RELOC_CRIS_16_DTPREL,   R_CRIS_16_DTPREL },
 
  { BFD_RELOC_CRIS_32_GOT_TPREL, R_CRIS_32_GOT_TPREL },
 
  { BFD_RELOC_CRIS_16_GOT_TPREL, R_CRIS_16_GOT_TPREL },
 
  { BFD_RELOC_CRIS_32_TPREL,    R_CRIS_32_TPREL },
 
  { BFD_RELOC_CRIS_16_TPREL,    R_CRIS_16_TPREL },
 
  { BFD_RELOC_CRIS_DTPMOD,      R_CRIS_DTPMOD },
 
  { BFD_RELOC_CRIS_32_IE,       R_CRIS_32_IE }
};
};
 
 
static reloc_howto_type *
static reloc_howto_type *
cris_reloc_type_lookup (abfd, code)
cris_reloc_type_lookup (abfd, code)
     bfd * abfd ATTRIBUTE_UNUSED;
     bfd * abfd ATTRIBUTE_UNUSED;
Line 479... Line 519...
cris_info_to_howto_rela (abfd, cache_ptr, dst)
cris_info_to_howto_rela (abfd, cache_ptr, dst)
     bfd * abfd ATTRIBUTE_UNUSED;
     bfd * abfd ATTRIBUTE_UNUSED;
     arelent * cache_ptr;
     arelent * cache_ptr;
     Elf_Internal_Rela * dst;
     Elf_Internal_Rela * dst;
{
{
  unsigned int r_type;
  enum elf_cris_reloc_type r_type;
 
 
  r_type = ELF32_R_TYPE (dst->r_info);
  r_type = ELF32_R_TYPE (dst->r_info);
  BFD_ASSERT (r_type < (unsigned int) R_CRIS_max);
  BFD_ASSERT (r_type < (unsigned int) R_CRIS_max);
  cache_ptr->howto = & cris_elf_howto_table [r_type];
  cache_ptr->howto = & cris_elf_howto_table [r_type];
}
}
Line 754... Line 794...
 
 
struct elf_cris_pcrel_relocs_copied
struct elf_cris_pcrel_relocs_copied
{
{
  /* Next section.  */
  /* Next section.  */
  struct elf_cris_pcrel_relocs_copied *next;
  struct elf_cris_pcrel_relocs_copied *next;
 
 
  /* A section in dynobj.  */
  /* A section in dynobj.  */
  asection *section;
  asection *section;
 
 
  /* Number of relocs copied in this section.  */
  /* Number of relocs copied in this section.  */
  bfd_size_type count;
  bfd_size_type count;
 
 
 
  /* Example of reloc being copied, for message.  */
 
  enum elf_cris_reloc_type r_type;
};
};
 
 
/* CRIS ELF linker hash entry.  */
/* CRIS ELF linker hash entry.  */
 
 
struct elf_cris_link_hash_entry
struct elf_cris_link_hash_entry
Line 781... Line 826...
  /* Actual GOTPLT index for this symbol, if applicable, or zero if not
  /* Actual GOTPLT index for this symbol, if applicable, or zero if not
     (zero is never used as an index).  FIXME: We should be able to fold
     (zero is never used as an index).  FIXME: We should be able to fold
     this with gotplt_refcount in a union, like the got and plt unions in
     this with gotplt_refcount in a union, like the got and plt unions in
     elf_link_hash_entry.  */
     elf_link_hash_entry.  */
  bfd_size_type gotplt_offset;
  bfd_size_type gotplt_offset;
 
 
 
  /* The root.got.refcount is the sum of the regular reference counts
 
     (this) and those members below.  We have to keep a separate count
 
     to track when we've found the first (or last) reference to a
 
     regular got entry.  The offset is in root.got.offset.  */
 
  bfd_signed_vma reg_got_refcount;
 
 
 
  /* Similar to the above, the number of reloc references to this
 
     symbols that need a R_CRIS_32_TPREL slot.  The offset is in
 
     root.got.offset, because this and .dtp_refcount can't validly
 
     happen when there's also a regular GOT entry; that's invalid
 
     input for which an error is emitted.  */
 
  bfd_signed_vma tprel_refcount;
 
 
 
  /* Similar to the above, the number of reloc references to this
 
     symbols that need a R_CRIS_DTP slot.  The offset is in
 
     root.got.offset; plus 4 if .tprel_refcount > 0.  */
 
  bfd_signed_vma dtp_refcount;
};
};
 
 
 
/* The local_got_refcounts and local_got_offsets are a multiple of
 
   LSNUM in size, namely LGOT_ALLOC_NELTS_FOR(LSNUM) (plus one for the
 
   refcount for GOT itself, see code), with the summary / group offset
 
   for local symbols located at offset N, reference counts for
 
   ordinary (address) relocs at offset N + LSNUM, for R_CRIS_DTP
 
   relocs at offset N + 2*LSNUM, and for R_CRIS_32_TPREL relocs at N +
 
   3*LSNUM.  */
 
 
 
#define LGOT_REG_NDX(x) ((x) + symtab_hdr->sh_info)
 
#define LGOT_DTP_NDX(x) ((x) + 2 * symtab_hdr->sh_info)
 
#define LGOT_TPREL_NDX(x) ((x) + 3 * symtab_hdr->sh_info)
 
#define LGOT_ALLOC_NELTS_FOR(x) ((x) * 4)
 
 
/* CRIS ELF linker hash table.  */
/* CRIS ELF linker hash table.  */
 
 
struct elf_cris_link_hash_table
struct elf_cris_link_hash_table
{
{
  struct elf_link_hash_table root;
  struct elf_link_hash_table root;
 
 
  /* We can't use the PLT offset and calculate to get the GOTPLT offset,
  /* We can't use the PLT offset and calculate to get the GOTPLT offset,
     since we try and avoid creating GOTPLT:s when there's already a GOT.
     since we try and avoid creating GOTPLT:s when there's already a GOT.
     Instead, we keep and update the next available index here.  */
     Instead, we keep and update the next available index here.  */
  bfd_size_type next_gotplt_entry;
  bfd_size_type next_gotplt_entry;
 
 
 
  /* The number of R_CRIS_32_DTPREL and R_CRIS_16_DTPREL that have
 
     been seen for any input; if != 0, then the constant-offset
 
     R_CRIS_DTPMOD is needed for this DSO/executable.  This turns
 
     negative at relocation, so that we don't need an extra flag for
 
     when the reloc is output.  */
 
  bfd_signed_vma dtpmod_refcount;
};
};
 
 
/* Traverse a CRIS ELF linker hash table.  */
/* Traverse a CRIS ELF linker hash table.  */
 
 
#define elf_cris_link_hash_traverse(table, func, info)                  \
#define elf_cris_link_hash_traverse(table, func, info)                  \
Line 808... Line 891...
/* Get the CRIS ELF linker hash table from a link_info structure.  */
/* Get the CRIS ELF linker hash table from a link_info structure.  */
 
 
#define elf_cris_hash_table(p) \
#define elf_cris_hash_table(p) \
  ((struct elf_cris_link_hash_table *) (p)->hash)
  ((struct elf_cris_link_hash_table *) (p)->hash)
 
 
 
/* Get the CRIS ELF linker hash entry from a regular hash entry (the
 
   "parent class").  The .root reference is just a simple type
 
   check on the argument.  */
 
 
 
#define elf_cris_hash_entry(p) \
 
 ((struct elf_cris_link_hash_entry *) (&(p)->root))
 
 
/* Create an entry in a CRIS ELF linker hash table.  */
/* Create an entry in a CRIS ELF linker hash table.  */
 
 
static struct bfd_hash_entry *
static struct bfd_hash_entry *
elf_cris_link_hash_newfunc (entry, table, string)
elf_cris_link_hash_newfunc (entry, table, string)
     struct bfd_hash_entry *entry;
     struct bfd_hash_entry *entry;
Line 837... Line 927...
  if (ret != (struct elf_cris_link_hash_entry *) NULL)
  if (ret != (struct elf_cris_link_hash_entry *) NULL)
    {
    {
      ret->pcrel_relocs_copied = NULL;
      ret->pcrel_relocs_copied = NULL;
      ret->gotplt_refcount = 0;
      ret->gotplt_refcount = 0;
      ret->gotplt_offset = 0;
      ret->gotplt_offset = 0;
 
      ret->dtp_refcount = 0;
 
      ret->tprel_refcount = 0;
 
      ret->reg_got_refcount = 0;
    }
    }
 
 
  return (struct bfd_hash_entry *) ret;
  return (struct bfd_hash_entry *) ret;
}
}
 
 
Line 867... Line 960...
 
 
  /* Initialize to skip over the first three entries in the gotplt; they
  /* Initialize to skip over the first three entries in the gotplt; they
     are used for run-time symbol evaluation.  */
     are used for run-time symbol evaluation.  */
  ret->next_gotplt_entry = 12;
  ret->next_gotplt_entry = 12;
 
 
 
  /* We haven't seen any R_CRIS_nn_GOT_TPREL initially.  */
 
  ret->dtpmod_refcount = 0;
 
 
  return &ret->root.root;
  return &ret->root.root;
}
}


/* Perform a single relocation.  By default we use the standard BFD
/* Perform a single relocation.  By default we use the standard BFD
   routines, with a few tweaks.  */
   routines, with a few tweaks.  */
Line 884... Line 980...
     bfd_byte *          contents;
     bfd_byte *          contents;
     Elf_Internal_Rela * rel;
     Elf_Internal_Rela * rel;
     bfd_vma             relocation;
     bfd_vma             relocation;
{
{
  bfd_reloc_status_type r;
  bfd_reloc_status_type r;
 
  enum elf_cris_reloc_type r_type = ELF32_R_TYPE (rel->r_info);
 
 
  /* PC-relative relocations are relative to the position *after*
  /* PC-relative relocations are relative to the position *after*
     the reloc.  Note that for R_CRIS_8_PCREL the adjustment is
     the reloc.  Note that for R_CRIS_8_PCREL the adjustment is
     not a single byte, since PC must be 16-bit-aligned.  */
     not a single byte, since PC must be 16-bit-aligned.  */
  switch (ELF32_R_TYPE (rel->r_info))
  switch (r_type)
    {
    {
      /* Check that the 16-bit GOT relocs are positive.  */
      /* Check that the 16-bit GOT relocs are positive.  */
    case R_CRIS_16_GOTPLT:
    case R_CRIS_16_GOTPLT:
    case R_CRIS_16_GOT:
    case R_CRIS_16_GOT:
      if ((bfd_signed_vma) relocation < 0)
      if ((bfd_signed_vma) relocation < 0)
Line 916... Line 1013...
                                contents, rel->r_offset,
                                contents, rel->r_offset,
                                relocation, rel->r_addend);
                                relocation, rel->r_addend);
  return r;
  return r;
}
}


 
 
 
/* The number of errors left before we stop outputting reloc-specific
 
   explanatory messages.  By coincidence, this works nicely together
 
   with the default number of messages you'll get from LD about
 
   "relocation truncated to fit" messages before you get an
 
   "additional relocation overflows omitted from the output".  */
 
static int additional_relocation_error_msg_count = 10;
 
 
/* Relocate an CRIS ELF section.  See elf32-fr30.c, from where this was
/* Relocate an CRIS ELF section.  See elf32-fr30.c, from where this was
   copied, for further comments.  */
   copied, for further comments.  */
 
 
static bfd_boolean
static bfd_boolean
cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
Line 940... Line 1045...
  asection *sgot;
  asection *sgot;
  asection *splt;
  asection *splt;
  asection *sreloc;
  asection *sreloc;
  Elf_Internal_Rela *rel;
  Elf_Internal_Rela *rel;
  Elf_Internal_Rela *relend;
  Elf_Internal_Rela *relend;
 
  asection *srelgot;
 
 
  dynobj = elf_hash_table (info)->dynobj;
  dynobj = elf_hash_table (info)->dynobj;
  local_got_offsets = elf_local_got_offsets (input_bfd);
  local_got_offsets = elf_local_got_offsets (input_bfd);
  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
  sym_hashes = elf_sym_hashes (input_bfd);
  sym_hashes = elf_sym_hashes (input_bfd);
  relend     = relocs + input_section->reloc_count;
  relend     = relocs + input_section->reloc_count;
 
 
  sgot = NULL;
  sgot = NULL;
  splt = NULL;
  splt = NULL;
  sreloc = NULL;
  sreloc = NULL;
 
  srelgot = NULL;
 
 
  if (dynobj != NULL)
  if (dynobj != NULL)
    {
    {
      splt = bfd_get_section_by_name (dynobj, ".plt");
      splt = bfd_get_section_by_name (dynobj, ".plt");
      sgot = bfd_get_section_by_name (dynobj, ".got");
      sgot = bfd_get_section_by_name (dynobj, ".got");
Line 967... Line 1074...
      asection *sec;
      asection *sec;
      struct elf_link_hash_entry *h;
      struct elf_link_hash_entry *h;
      bfd_vma relocation;
      bfd_vma relocation;
      bfd_reloc_status_type r;
      bfd_reloc_status_type r;
      const char *symname = NULL;
      const char *symname = NULL;
      int r_type;
      enum elf_cris_reloc_type r_type;
 
 
      r_type = ELF32_R_TYPE (rel->r_info);
      r_type = ELF32_R_TYPE (rel->r_info);
 
 
      if (   r_type == R_CRIS_GNU_VTINHERIT
      if (   r_type == R_CRIS_GNU_VTINHERIT
          || r_type == R_CRIS_GNU_VTENTRY)
          || r_type == R_CRIS_GNU_VTENTRY)
Line 1002... Line 1109...
          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
                                   r_symndx, symtab_hdr, sym_hashes,
                                   r_symndx, symtab_hdr, sym_hashes,
                                   h, sec, relocation,
                                   h, sec, relocation,
                                   unresolved_reloc, warned);
                                   unresolved_reloc, warned);
 
 
 
          symname = h->root.root.string;
 
 
          if (unresolved_reloc
          if (unresolved_reloc
              /* Perhaps we should detect the cases that
              /* Perhaps we should detect the cases that
                 sec->output_section is expected to be NULL like i386 and
                 sec->output_section is expected to be NULL like i386 and
                 m68k, but apparently (and according to elfxx-ia64.c) all
                 m68k, but apparently (and according to elfxx-ia64.c) all
                 valid cases are where the symbol is defined in a shared
                 valid cases are where the symbol is defined in a shared
Line 1220... Line 1329...
                  {
                  {
                    bfd_put_32 (output_bfd, relocation, sgot->contents + off);
                    bfd_put_32 (output_bfd, relocation, sgot->contents + off);
 
 
                    if (info->shared)
                    if (info->shared)
                      {
                      {
                        asection *s;
 
                        Elf_Internal_Rela outrel;
                        Elf_Internal_Rela outrel;
                        bfd_byte *loc;
                        bfd_byte *loc;
 
 
                        s = bfd_get_section_by_name (dynobj, ".rela.got");
                        if (srelgot == NULL)
                        BFD_ASSERT (s != NULL);
                          srelgot
 
                            = bfd_get_section_by_name (dynobj, ".rela.got");
 
                        BFD_ASSERT (srelgot != NULL);
 
 
                        outrel.r_offset = (sgot->output_section->vma
                        outrel.r_offset = (sgot->output_section->vma
                                           + sgot->output_offset
                                           + sgot->output_offset
                                           + off);
                                           + off);
                        outrel.r_info = ELF32_R_INFO (0, R_CRIS_RELATIVE);
                        outrel.r_info = ELF32_R_INFO (0, R_CRIS_RELATIVE);
                        outrel.r_addend = relocation;
                        outrel.r_addend = relocation;
                        loc = s->contents;
                        loc = srelgot->contents;
                        loc += s->reloc_count++ * sizeof (Elf32_External_Rela);
                        loc += srelgot->reloc_count++ * sizeof (Elf32_External_Rela);
                        bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
                        bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
                      }
                      }
 
 
                    local_got_offsets[r_symndx] |= 1;
                    local_got_offsets[r_symndx] |= 1;
                  }
                  }
Line 1369... Line 1479...
 
 
        case R_CRIS_8_PCREL:
        case R_CRIS_8_PCREL:
        case R_CRIS_16_PCREL:
        case R_CRIS_16_PCREL:
        case R_CRIS_32_PCREL:
        case R_CRIS_32_PCREL:
          /* If the symbol was local, we need no shlib-specific handling.  */
          /* If the symbol was local, we need no shlib-specific handling.  */
          if (h == NULL || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
          if (h == NULL || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
 
              || h->dynindx == -1)
            break;
            break;
 
 
          /* Fall through.  */
          /* Fall through.  */
        case R_CRIS_8:
        case R_CRIS_8:
        case R_CRIS_16:
        case R_CRIS_16:
Line 1383... Line 1494...
              && (input_section->flags & SEC_ALLOC) != 0
              && (input_section->flags & SEC_ALLOC) != 0
              && ((r_type != R_CRIS_8_PCREL
              && ((r_type != R_CRIS_8_PCREL
                   && r_type != R_CRIS_16_PCREL
                   && r_type != R_CRIS_16_PCREL
                   && r_type != R_CRIS_32_PCREL)
                   && r_type != R_CRIS_32_PCREL)
                  || (!info->symbolic
                  || (!info->symbolic
                      || !h->def_regular)))
                      || (h != NULL && !h->def_regular))))
            {
            {
              Elf_Internal_Rela outrel;
              Elf_Internal_Rela outrel;
              bfd_byte *loc;
              bfd_byte *loc;
              bfd_boolean skip, relocate;
              bfd_boolean skip, relocate;
 
 
Line 1395... Line 1506...
                 are copied into the output file to be resolved at run
                 are copied into the output file to be resolved at run
                 time.  */
                 time.  */
 
 
              if (sreloc == NULL)
              if (sreloc == NULL)
                {
                {
                  const char *name;
                  sreloc = _bfd_elf_get_dynamic_reloc_section
 
                    (input_bfd, input_section, /*rela?*/ TRUE);
                  name = (bfd_elf_string_from_elf_section
                  /* The section should have been created in cris_elf_check_relocs,
                          (input_bfd,
                     but that function will not be called for objects which fail in
                           elf_elfheader (input_bfd)->e_shstrndx,
 
                           elf_section_data (input_section)->rel_hdr.sh_name));
 
                  if (name == NULL)
 
                    return FALSE;
 
 
 
                  BFD_ASSERT (CONST_STRNEQ (name, ".rela")
 
                              && strcmp (bfd_get_section_name (input_bfd,
 
                                                               input_section),
 
                                         name + 5) == 0);
 
 
 
                  sreloc = bfd_get_section_by_name (dynobj, name);
 
 
 
                  /* That section should have been created in
 
                     cris_elf_check_relocs, but that function will not be
 
                     called for objects which fail in
 
                     cris_elf_merge_private_bfd_data.  */
                     cris_elf_merge_private_bfd_data.  */
                  if (sreloc == NULL)
                  if (sreloc == NULL)
                    {
                    {
                      (*_bfd_error_handler)
 
                        (_("%B: Internal inconsistency; no relocation section %s"),
 
                         input_bfd,
 
                         name);
 
 
 
                      bfd_set_error (bfd_error_bad_value);
                      bfd_set_error (bfd_error_bad_value);
                      return FALSE;
                      return FALSE;
                    }
                    }
                }
                }
 
 
Line 1435... Line 1526...
              outrel.r_offset =
              outrel.r_offset =
                _bfd_elf_section_offset (output_bfd, info, input_section,
                _bfd_elf_section_offset (output_bfd, info, input_section,
                                         rel->r_offset);
                                         rel->r_offset);
              if (outrel.r_offset == (bfd_vma) -1)
              if (outrel.r_offset == (bfd_vma) -1)
                skip = TRUE;
                skip = TRUE;
              else if (outrel.r_offset == (bfd_vma) -2)
              else if (outrel.r_offset == (bfd_vma) -2
 
                       /* For now, undefined weak symbols with non-default
 
                          visibility (yielding 0), like exception info for
 
                          discarded sections, will get a R_CRIS_NONE
 
                          relocation rather than no relocation, because we
 
                          notice too late that the symbol doesn't need a
 
                          relocation.  */
 
                       || (h != NULL
 
                           && h->root.type == bfd_link_hash_undefweak
 
                           && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT))
                skip = TRUE, relocate = TRUE;
                skip = TRUE, relocate = TRUE;
              outrel.r_offset += (input_section->output_section->vma
              outrel.r_offset += (input_section->output_section->vma
                                  + input_section->output_offset);
                                  + input_section->output_offset);
 
 
              if (skip)
              if (skip)
Line 1509... Line 1609...
              if (!relocate)
              if (!relocate)
                continue;
                continue;
            }
            }
 
 
          break;
          break;
 
 
 
        case R_CRIS_16_DTPREL:
 
        case R_CRIS_32_DTPREL:
 
          /* This relocation must only be performed against local
 
             symbols, or to sections that are not loadable.  It's also
 
             ok when we link a program and the symbol is defined in an
 
             ordinary (non-DSO) object (if it's undefined there, we've
 
             already seen an error).  */
 
          if (h != NULL
 
              && (input_section->flags & SEC_ALLOC) != 0
 
              && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
 
              && (info->shared
 
                  || (!h->def_regular
 
                      && h->root.type != bfd_link_hash_undefined)))
 
            {
 
              (*_bfd_error_handler)
 
                ((h->root.type == bfd_link_hash_undefined)
 
                 /* We shouldn't get here for GCC-emitted code.  */
 
                 ? _("%B, section %A: relocation %s has an undefined"
 
                     " reference to `%s', perhaps a declaration mixup?")
 
                 : ("%B, section %A: relocation %s is"
 
                     " not allowed for `%s', a global symbol with default"
 
                     " visibility, perhaps a declaration mixup?"),
 
                 input_bfd,
 
                 input_section,
 
                 cris_elf_howto_table[r_type].name,
 
                 symname != NULL && symname[0] != '\0'
 
                 ? symname : _("[whose name is lost]"));
 
              bfd_set_error (bfd_error_bad_value);
 
              return FALSE;
 
            }
 
 
 
          BFD_ASSERT ((input_section->flags & SEC_ALLOC) == 0
 
                      || elf_cris_hash_table (info)->dtpmod_refcount != 0);
 
 
 
          /* Fill in a R_CRIS_DTPMOD reloc at offset 3 if we haven't
 
             already done so.  Note that we do this in .got.plt, not
 
             in .got, as .got.plt contains the first part, still the
 
             reloc is against .got, because the linker script directs
 
             (is required to direct) them both into .got.  */
 
          if (elf_cris_hash_table (info)->dtpmod_refcount > 0
 
              && (input_section->flags & SEC_ALLOC) != 0)
 
            {
 
              asection *sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
 
              BFD_ASSERT (sgotplt != NULL);
 
 
 
              if (info->shared)
 
                {
 
                  Elf_Internal_Rela outrel;
 
                  bfd_byte *loc;
 
 
 
                  if (srelgot == NULL)
 
                    srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
 
                  BFD_ASSERT (srelgot != NULL);
 
                  loc = srelgot->contents;
 
                  loc += srelgot->reloc_count++ * sizeof (Elf32_External_Rela);
 
 
 
                  bfd_put_32 (output_bfd, (bfd_vma) 0, sgotplt->contents + 12);
 
                  bfd_put_32 (output_bfd, (bfd_vma) 0, sgotplt->contents + 16);
 
                  outrel.r_offset = (sgotplt->output_section->vma
 
                                     + sgotplt->output_offset
 
                                     + 12);
 
                  outrel.r_info = ELF32_R_INFO (0, R_CRIS_DTPMOD);
 
                  outrel.r_addend = 0;
 
                  bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
 
                }
 
              else
 
                {
 
                  /* For an executable, the GOT entry contents is known.  */
 
                  bfd_put_32 (output_bfd, (bfd_vma) 1, sgotplt->contents + 12);
 
                  bfd_put_32 (output_bfd, (bfd_vma) 0, sgotplt->contents + 16);
 
                }
 
 
 
              /* Reverse the sign to mark that we've emitted the
 
                 required GOT entry.  */
 
              elf_cris_hash_table (info)->dtpmod_refcount
 
                = -elf_cris_hash_table (info)->dtpmod_refcount;
 
            }
 
 
 
          /* The relocation is the offset from the start of the module
 
             TLS block to the (local) symbol.  */
 
          relocation -= elf_hash_table (info)->tls_sec == NULL
 
            ? 0 : elf_hash_table (info)->tls_sec->vma;
 
          break;
 
 
 
        case R_CRIS_32_GD:
 
          if (info->shared)
 
            {
 
              bfd_set_error (bfd_error_invalid_operation);
 
 
 
              /* We've already informed in cris_elf_check_relocs that
 
                 this is an error.  */
 
              return FALSE;
 
            }
 
          /* Fall through.  */
 
 
 
        case R_CRIS_16_GOT_GD:
 
        case R_CRIS_32_GOT_GD:
 
          if (rel->r_addend != 0)
 
            {
 
              /* We can't do anything for a relocation which is against a
 
                 symbol *plus offset*.  The GOT holds relocations for
 
                 symbols.  Make this an error; the compiler isn't allowed
 
                 to pass us these kinds of things.  */
 
              (*_bfd_error_handler)
 
                (_("%B, section %A: relocation %s with non-zero addend %d"
 
                   " against symbol `%s'"),
 
                 input_bfd,
 
                 input_section,
 
                 cris_elf_howto_table[r_type].name,
 
                 rel->r_addend,
 
                 symname[0] != '\0' ? symname : _("[whose name is lost]"));
 
 
 
              bfd_set_error (bfd_error_bad_value);
 
              return FALSE;
 
            }
 
 
 
          if (!info->shared
 
              && (h == NULL || h->def_regular || ELF_COMMON_DEF_P (h)))
 
            {
 
              /* Known contents of the GOT.  */
 
              bfd_vma off;
 
 
 
              /* The symbol is defined in the program, so just write
 
                 (1, known_tpoffset) into the GOT.  */
 
              relocation -= elf_hash_table (info)->tls_sec->vma;
 
 
 
              if (h != NULL)
 
                {
 
                  off = elf_cris_hash_entry (h)->tprel_refcount > 0
 
                    ? h->got.offset + 4 : h->got.offset;
 
                }
 
              else
 
                {
 
                  off = local_got_offsets[r_symndx];
 
                  if (local_got_offsets[LGOT_TPREL_NDX (r_symndx)])
 
                    off += 4;
 
                }
 
 
 
              /* We use bit 1 of the offset as a flag for GOT entry with
 
                 the R_CRIS_DTP reloc, setting it when we've emitted the
 
                 GOT entry and reloc.  Bit 0 is used for R_CRIS_32_TPREL
 
                 relocs.  */
 
              if ((off & 2) == 0)
 
                {
 
                  off &= ~3;
 
 
 
                  if (h != NULL)
 
                    h->got.offset |= 2;
 
                  else
 
                    local_got_offsets[r_symndx] |= 2;
 
 
 
                  bfd_put_32 (output_bfd, 1, sgot->contents + off);
 
                  bfd_put_32 (output_bfd, relocation, sgot->contents + off + 4);
 
                }
 
              else
 
                off &= ~3;
 
 
 
              relocation = sgot->output_offset + off
 
                + (r_type == R_CRIS_32_GD ? sgot->output_section->vma : 0);
 
            }
 
          else
 
            {
 
              /* Not all parts of the GOT entry are known; emit a real
 
                 relocation.  */
 
              bfd_vma off;
 
 
 
              if (h != NULL)
 
                off = elf_cris_hash_entry (h)->tprel_refcount > 0
 
                  ? h->got.offset + 4 : h->got.offset;
 
              else
 
                {
 
                  off = local_got_offsets[r_symndx];
 
                  if (local_got_offsets[LGOT_TPREL_NDX (r_symndx)])
 
                    off += 4;
 
                }
 
 
 
              /* See above re bit 1 and bit 0 usage.  */
 
              if ((off & 2) == 0)
 
                {
 
                  Elf_Internal_Rela outrel;
 
                  bfd_byte *loc;
 
 
 
                  off &= ~3;
 
 
 
                  if (h != NULL)
 
                    h->got.offset |= 2;
 
                  else
 
                    local_got_offsets[r_symndx] |= 2;
 
 
 
                  /* Clear the target contents of the GOT (just as a
 
                     gesture; it's already cleared on allocation): this
 
                     relocation is not like the other dynrelocs.  */
 
                  bfd_put_32 (output_bfd, 0, sgot->contents + off);
 
                  bfd_put_32 (output_bfd, 0, sgot->contents + off + 4);
 
 
 
                  if (srelgot == NULL)
 
                    srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
 
                  BFD_ASSERT (srelgot != NULL);
 
 
 
                  if (h != NULL && h->dynindx != -1)
 
                    {
 
                      outrel.r_info = ELF32_R_INFO (h->dynindx, R_CRIS_DTP);
 
                      relocation = 0;
 
                    }
 
                  else
 
                    {
 
                      outrel.r_info = ELF32_R_INFO (0, R_CRIS_DTP);
 
 
 
                      /* NULL if we had an error.  */
 
                      relocation -= elf_hash_table (info)->tls_sec == NULL
 
                        ? 0 : elf_hash_table (info)->tls_sec->vma;
 
                    }
 
 
 
                  outrel.r_offset = (sgot->output_section->vma
 
                                     + sgot->output_offset
 
                                     + off);
 
                  outrel.r_addend = relocation;
 
                  loc = srelgot->contents;
 
                  loc += srelgot->reloc_count++ * sizeof (Elf32_External_Rela);
 
 
 
                  /* NULL if we had an error.  */
 
                  if (srelgot->contents != NULL)
 
                    bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
 
                }
 
              else
 
                off &= ~3;
 
 
 
              relocation = sgot->output_offset + off
 
                + (r_type == R_CRIS_32_GD ? sgot->output_section->vma : 0);
 
            }
 
 
 
          /* The GOT-relative offset to the GOT entry is the
 
             relocation, or for R_CRIS_32_GD, the actual address of
 
             the GOT entry.  */
 
          break;
 
 
 
        case R_CRIS_32_IE:
 
          if (info->shared)
 
            {
 
              bfd_set_error (bfd_error_invalid_operation);
 
 
 
              /* We've already informed in cris_elf_check_relocs that
 
                 this is an error.  */
 
              return FALSE;
 
            }
 
          /* Fall through.  */
 
 
 
        case R_CRIS_32_GOT_TPREL:
 
        case R_CRIS_16_GOT_TPREL:
 
          if (rel->r_addend != 0)
 
            {
 
              /* We can't do anything for a relocation which is
 
                 against a symbol *plus offset*.  GOT holds
 
                 relocations for symbols.  Make this an error; the
 
                 compiler isn't allowed to pass us these kinds of
 
                 things.  */
 
              (*_bfd_error_handler)
 
                (_("%B, section %A: relocation %s with non-zero addend %d"
 
                   " against symbol `%s'"),
 
                 input_bfd,
 
                 input_section,
 
                 cris_elf_howto_table[r_type].name,
 
                 rel->r_addend,
 
                 symname[0] != '\0' ? symname : _("[whose name is lost]"));
 
              bfd_set_error (bfd_error_bad_value);
 
              return FALSE;
 
            }
 
 
 
          if (!info->shared && (h == NULL || h->def_regular))
 
            {
 
              /* Known contents of the GOT.  */
 
              bfd_vma off;
 
 
 
              /* The symbol is defined in the program, so just write
 
                 the -prog_tls_size+known_tpoffset into the GOT.  */
 
              relocation -= elf_hash_table (info)->tls_sec->vma;
 
              relocation -= elf_hash_table (info)->tls_size;
 
 
 
              if (h != NULL)
 
                off = h->got.offset;
 
              else
 
                off = local_got_offsets[r_symndx];
 
 
 
              /* Bit 0 is used to mark whether we've emitted the required
 
                 entry (and if needed R_CRIS_32_TPREL reloc).  Bit 1
 
                 is used similarly for R_CRIS_DTP, see above.  */
 
              if ((off & 1) == 0)
 
                {
 
                  off &= ~3;
 
 
 
                  if (h != NULL)
 
                    h->got.offset |= 1;
 
                  else
 
                    local_got_offsets[r_symndx] |= 1;
 
 
 
                  bfd_put_32 (output_bfd, relocation, sgot->contents + off);
 
                }
 
              else
 
                off &= ~3;
 
 
 
              relocation = sgot->output_offset + off
 
                + (r_type == R_CRIS_32_IE ? sgot->output_section->vma : 0);
 
            }
 
          else
 
            {
 
              /* Emit a real relocation.  */
 
              bfd_vma off;
 
 
 
              if (h != NULL)
 
                off = h->got.offset;
 
              else
 
                off = local_got_offsets[r_symndx];
 
 
 
              /* See above re usage of bit 0 and 1.  */
 
              if ((off & 1) == 0)
 
                {
 
                  Elf_Internal_Rela outrel;
 
                  bfd_byte *loc;
 
 
 
                  off &= ~3;
 
 
 
                  if (h != NULL)
 
                    h->got.offset |= 1;
 
                  else
 
                    local_got_offsets[r_symndx] |= 1;
 
 
 
                  if (srelgot == NULL)
 
                    srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
 
                  BFD_ASSERT (srelgot != NULL);
 
 
 
                  if (h != NULL && h->dynindx != -1)
 
                    {
 
                      outrel.r_info = ELF32_R_INFO (h->dynindx, R_CRIS_32_TPREL);
 
                      relocation = 0;
 
                    }
 
                  else
 
                    {
 
                      outrel.r_info = ELF32_R_INFO (0, R_CRIS_32_TPREL);
 
 
 
                      /* NULL if we had an error.  */
 
                      relocation -= elf_hash_table (info)->tls_sec == NULL
 
                        ? 0 : elf_hash_table (info)->tls_sec->vma;
 
                    }
 
 
 
                  /* Just "define" the initial contents in some
 
                     semi-logical way.  */
 
                  bfd_put_32 (output_bfd, relocation, sgot->contents + off);
 
 
 
                  outrel.r_offset = (sgot->output_section->vma
 
                                     + sgot->output_offset
 
                                     + off);
 
                  outrel.r_addend = relocation;
 
                  loc = srelgot->contents;
 
                  loc += srelgot->reloc_count++ * sizeof (Elf32_External_Rela);
 
                  /* NULL if we had an error.  */
 
                  if (srelgot->contents != NULL)
 
                    bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
 
                }
 
              else
 
                off &= ~3;
 
 
 
              relocation = sgot->output_offset + off
 
                + (r_type == R_CRIS_32_IE ? sgot->output_section->vma : 0);
 
            }
 
 
 
          /* The GOT-relative offset to the GOT entry is the relocation,
 
             or for R_CRIS_32_GD, the actual address of the GOT entry.  */
 
          break;
 
 
 
        case R_CRIS_16_TPREL:
 
        case R_CRIS_32_TPREL:
 
          /* This relocation must only be performed against symbols
 
             defined in an ordinary (non-DSO) object.  */
 
          if (info->shared)
 
            {
 
              bfd_set_error (bfd_error_invalid_operation);
 
 
 
              /* We've already informed in cris_elf_check_relocs that
 
                 this is an error.  */
 
              return FALSE;
 
            }
 
 
 
          if (h != NULL
 
              && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
 
              && !(h->def_regular || ELF_COMMON_DEF_P (h))
 
              /* If it's undefined, then an error message has already
 
                 been emitted.  */
 
              && h->root.type != bfd_link_hash_undefined)
 
            {
 
              (*_bfd_error_handler)
 
                (_("%B, section %A: relocation %s is"
 
                   " not allowed for symbol: `%s'"
 
                   " which is defined outside the program,"
 
                   " perhaps a declaration mixup?"),
 
                 input_bfd,
 
                 input_section,
 
                 cris_elf_howto_table[r_type].name,
 
                 symname);
 
              bfd_set_error (bfd_error_bad_value);
 
              return FALSE;
 
            }
 
 
 
          /* NULL if we had an error.  */
 
          relocation -= elf_hash_table (info)->tls_sec == NULL
 
            ? 0
 
            : (elf_hash_table (info)->tls_sec->vma
 
               + elf_hash_table (info)->tls_size);
 
 
 
          /* The TLS-relative offset is the relocation.  */
 
          break;
 
 
 
        default:
 
          BFD_FAIL ();
 
          return FALSE;
        }
        }
 
 
      r = cris_final_link_relocate (howto, input_bfd, input_section,
      r = cris_final_link_relocate (howto, input_bfd, input_section,
                                     contents, rel, relocation);
                                     contents, rel, relocation);
 
 
Line 1524... Line 2039...
            {
            {
            case bfd_reloc_overflow:
            case bfd_reloc_overflow:
              r = info->callbacks->reloc_overflow
              r = info->callbacks->reloc_overflow
                (info, (h ? &h->root : NULL), symname, howto->name,
                (info, (h ? &h->root : NULL), symname, howto->name,
                 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
                 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
 
              if (additional_relocation_error_msg_count > 0)
 
                {
 
                  additional_relocation_error_msg_count--;
 
                  switch (r_type)
 
                    {
 
                    case R_CRIS_16_GOTPLT:
 
                    case R_CRIS_16_GOT:
 
 
 
                      /* Not just TLS is involved here, so we make
 
                         generation and message depend on -fPIC/-fpic
 
                         only.  */
 
                    case R_CRIS_16_GOT_TPREL:
 
                    case R_CRIS_16_GOT_GD:
 
                      (*_bfd_error_handler)
 
                        (_("(too many global variables for -fpic:"
 
                           " recompile with -fPIC)"));
 
                      break;
 
 
 
                    case R_CRIS_16_TPREL:
 
                    case R_CRIS_16_DTPREL:
 
                      (*_bfd_error_handler)
 
                        (_("(thread-local data too big for -fpic or"
 
                           " -msmall-tls: recompile with -fPIC or"
 
                           " -mno-small-tls)"));
 
                      break;
 
 
 
                      /* No known cause for overflow for other relocs.  */
 
                    default:
 
                      break;
 
                    }
 
                }
              break;
              break;
 
 
            case bfd_reloc_undefined:
            case bfd_reloc_undefined:
              r = info->callbacks->undefined_symbol
              r = info->callbacks->undefined_symbol
                (info, symname, input_bfd, input_section, rel->r_offset,
                (info, symname, input_bfd, input_section, rel->r_offset,
Line 1610... Line 2156...
      asection *sgot;
      asection *sgot;
      asection *srela;
      asection *srela;
      bfd_vma got_base;
      bfd_vma got_base;
 
 
      bfd_vma gotplt_offset
      bfd_vma gotplt_offset
        = ((struct elf_cris_link_hash_entry *) h)->gotplt_offset;
        = elf_cris_hash_entry (h)->gotplt_offset;
      Elf_Internal_Rela rela;
      Elf_Internal_Rela rela;
      bfd_byte *loc;
      bfd_byte *loc;
      bfd_boolean has_gotplt = gotplt_offset != 0;
      bfd_boolean has_gotplt = gotplt_offset != 0;
 
 
      /* Get the index in the procedure linkage table which
      /* Get the index in the .rela.plt relocations for the .got.plt
         corresponds to this symbol.  This is the index of this symbol
         entry that corresponds to this symbol.
         in all the symbols for which we are making plt entries.  The
         We have to count backwards here, and the result is only valid
         first entry in the procedure linkage table is reserved.  */
         as an index into .rela.plt.  We also have to undo the effect
      /* We have to count backwards here, and the result is only valid as
         of the R_CRIS_DTPMOD entry at .got index 3 (offset 12 into
         an index into .got.plt and its relocations.  FIXME: Constants...  */
         .got.plt) for which gotplt_offset is adjusted, because while
      bfd_vma gotplt_index = gotplt_offset/4 - 3;
         that entry goes into .got.plt, its relocation goes into
 
         .rela.got, not .rela.plt.  (It's not PLT-specific; not to be
 
         processed as part of the runtime lazy .rela.plt relocation).
 
         FIXME: There be literal constants here...  */
 
      bfd_vma rela_plt_index
 
        = (elf_cris_hash_table (info)->dtpmod_refcount != 0
 
           ? gotplt_offset/4 - 2 - 3 : gotplt_offset/4 - 3);
 
 
      /* Get the offset into the .got table of the entry that corresponds
      /* Get the offset into the .got table of the entry that corresponds
         to this function.  Note that we embed knowledge that "incoming"
         to this function.  Note that we embed knowledge that "incoming"
         .got goes after .got.plt in the output without padding (pointer
         .got goes after .got.plt in the output without padding (pointer
         aligned).  However, that knowledge is present in several other
         aligned).  However, that knowledge is present in several other
Line 1671... Line 2223...
         PLT entry.  */
         PLT entry.  */
      if (has_gotplt)
      if (has_gotplt)
        {
        {
          /* Fill in the offset to the reloc table.  */
          /* Fill in the offset to the reloc table.  */
          bfd_put_32 (output_bfd,
          bfd_put_32 (output_bfd,
                      gotplt_index * sizeof (Elf32_External_Rela),
                      rela_plt_index * sizeof (Elf32_External_Rela),
                      splt->contents + h->plt.offset + plt_off2);
                      splt->contents + h->plt.offset + plt_off2);
 
 
          /* Fill in the offset to the first PLT entry, where to "jump".  */
          /* Fill in the offset to the first PLT entry, where to "jump".  */
          bfd_put_32 (output_bfd,
          bfd_put_32 (output_bfd,
                      - (h->plt.offset + plt_off3 + plt_off3_value_bias),
                      - (h->plt.offset + plt_off3 + plt_off3_value_bias),
Line 1694... Line 2246...
          rela.r_offset = (sgotplt->output_section->vma
          rela.r_offset = (sgotplt->output_section->vma
                           + sgotplt->output_offset
                           + sgotplt->output_offset
                           + got_offset);
                           + got_offset);
          rela.r_info = ELF32_R_INFO (h->dynindx, R_CRIS_JUMP_SLOT);
          rela.r_info = ELF32_R_INFO (h->dynindx, R_CRIS_JUMP_SLOT);
          rela.r_addend = 0;
          rela.r_addend = 0;
          loc = srela->contents + gotplt_index * sizeof (Elf32_External_Rela);
          loc = srela->contents + rela_plt_index * sizeof (Elf32_External_Rela);
          bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
          bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
        }
        }
 
 
      if (!h->def_regular)
      if (!h->def_regular)
        {
        {
Line 1723... Line 2275...
     are in the dynamic-symbols table and are either defined by the
     are in the dynamic-symbols table and are either defined by the
     program or are undefined weak symbols, or are function symbols
     program or are undefined weak symbols, or are function symbols
     where we do not output a PLT: the PLT reloc was output above and all
     where we do not output a PLT: the PLT reloc was output above and all
     references to the function symbol are redirected to the PLT.  */
     references to the function symbol are redirected to the PLT.  */
  if (h->got.offset != (bfd_vma) -1
  if (h->got.offset != (bfd_vma) -1
 
      && (elf_cris_hash_entry (h)->reg_got_refcount > 0)
      && (info->shared
      && (info->shared
          || (h->dynindx != -1
          || (h->dynindx != -1
              && h->plt.offset == (bfd_vma) -1
              && h->plt.offset == (bfd_vma) -1
              && !h->def_regular
              && !h->def_regular
              && h->root.type != bfd_link_hash_undefweak)))
              && h->root.type != bfd_link_hash_undefweak)))
Line 1804... Line 2357...
    sym->st_shndx = SHN_ABS;
    sym->st_shndx = SHN_ABS;
 
 
  return TRUE;
  return TRUE;
}
}


/* Finish up the dynamic sections.  */
/* Finish up the dynamic sections.  Do *not* emit relocs here, as their
 
   offsets were changed, as part of -z combreloc handling, from those we
 
   computed.  */
 
 
static bfd_boolean
static bfd_boolean
elf_cris_finish_dynamic_sections (output_bfd, info)
elf_cris_finish_dynamic_sections (output_bfd, info)
     bfd *output_bfd;
     bfd *output_bfd;
     struct bfd_link_info *info;
     struct bfd_link_info *info;
Line 1957... Line 2512...
                       struct bfd_link_info *info,
                       struct bfd_link_info *info,
                       Elf_Internal_Rela *rel,
                       Elf_Internal_Rela *rel,
                       struct elf_link_hash_entry *h,
                       struct elf_link_hash_entry *h,
                       Elf_Internal_Sym *sym)
                       Elf_Internal_Sym *sym)
{
{
 
  enum elf_cris_reloc_type r_type = ELF32_R_TYPE (rel->r_info);
  if (h != NULL)
  if (h != NULL)
    switch (ELF32_R_TYPE (rel->r_info))
    switch (r_type)
      {
      {
      case R_CRIS_GNU_VTINHERIT:
      case R_CRIS_GNU_VTINHERIT:
      case R_CRIS_GNU_VTENTRY:
      case R_CRIS_GNU_VTENTRY:
        return NULL;
        return NULL;
 
 
 
      default:
 
        break;
      }
      }
 
 
  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
}
}
 
 
Line 2003... Line 2562...
  relend = relocs + sec->reloc_count;
  relend = relocs + sec->reloc_count;
  for (rel = relocs; rel < relend; rel++)
  for (rel = relocs; rel < relend; rel++)
    {
    {
      unsigned long r_symndx;
      unsigned long r_symndx;
      struct elf_link_hash_entry *h = NULL;
      struct elf_link_hash_entry *h = NULL;
 
      bfd_signed_vma got_element_size = 4;
 
      bfd_signed_vma *specific_refcount = NULL;
 
      enum elf_cris_reloc_type r_type;
 
 
      r_symndx = ELF32_R_SYM (rel->r_info);
      r_symndx = ELF32_R_SYM (rel->r_info);
      if (r_symndx >= symtab_hdr->sh_info)
      if (r_symndx >= symtab_hdr->sh_info)
        {
        {
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
          while (h->root.type == bfd_link_hash_indirect
          while (h->root.type == bfd_link_hash_indirect
                 || h->root.type == bfd_link_hash_warning)
                 || h->root.type == bfd_link_hash_warning)
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
        }
        }
 
 
      switch (ELF32_R_TYPE (rel->r_info))
      r_type = ELF32_R_TYPE (rel->r_info);
 
      switch (r_type)
 
        {
 
        case R_CRIS_32_GOT:
 
        case R_CRIS_16_GOT:
 
        case R_CRIS_16_GOTPLT:
 
        case R_CRIS_32_GOTPLT:
 
          specific_refcount = h != NULL
 
            ? &((struct elf_cris_link_hash_entry *) h)->reg_got_refcount
 
            : &local_got_refcounts[LGOT_REG_NDX (r_symndx)];
 
          break;
 
 
 
        case R_CRIS_32_GD:
 
        case R_CRIS_32_GOT_GD:
 
        case R_CRIS_16_GOT_GD:
 
          got_element_size = 8;
 
          specific_refcount = h != NULL
 
            ? &((struct elf_cris_link_hash_entry *) h)->dtp_refcount
 
            : &local_got_refcounts[LGOT_DTP_NDX (r_symndx)];
 
          break;
 
 
 
        case R_CRIS_32_IE:
 
        case R_CRIS_16_GOT_TPREL:
 
        case R_CRIS_32_GOT_TPREL:
 
          specific_refcount = h != NULL
 
            ? &((struct elf_cris_link_hash_entry *) h)->tprel_refcount
 
            : &local_got_refcounts[LGOT_TPREL_NDX (r_symndx)];
 
          break;
 
 
 
        default:
 
          break;
 
        }
 
 
 
      switch (r_type)
        {
        {
 
        case R_CRIS_32_IE:
 
        case R_CRIS_32_GD:
 
        case R_CRIS_16_GOT_TPREL:
 
        case R_CRIS_32_GOT_TPREL:
 
        case R_CRIS_32_GOT_GD:
 
        case R_CRIS_16_GOT_GD:
        case R_CRIS_16_GOT:
        case R_CRIS_16_GOT:
        case R_CRIS_32_GOT:
        case R_CRIS_32_GOT:
          if (h != NULL)
          if (h != NULL)
            {
            {
              if (h->got.refcount > 0)
              /* If the counters are 0 when we got here, we've
                {
                 miscounted somehow somewhere, an internal error.  */
 
              BFD_ASSERT (h->got.refcount > 0);
                  --h->got.refcount;
                  --h->got.refcount;
                  if (h->got.refcount == 0)
 
 
              BFD_ASSERT (*specific_refcount > 0);
 
              --*specific_refcount;
 
              if (*specific_refcount == 0)
                    {
                    {
                      /* We don't need the .got entry any more.  */
                      /* We don't need the .got entry any more.  */
                      sgot->size -= 4;
                  sgot->size -= got_element_size;
                      srelgot->size -= sizeof (Elf32_External_Rela);
                      srelgot->size -= sizeof (Elf32_External_Rela);
                    }
                    }
                }
 
              break;
              break;
            }
            }
 
 
        local_got_reloc:
        local_got_reloc:
          if (local_got_refcounts != NULL)
          if (local_got_refcounts != NULL)
            {
            {
              if (local_got_refcounts[r_symndx] > 0)
              /* If the counters are 0 when we got here, we've
                {
                 miscounted somehow somewhere, an internal error.  */
 
              BFD_ASSERT (local_got_refcounts[r_symndx] > 0);
                  --local_got_refcounts[r_symndx];
                  --local_got_refcounts[r_symndx];
                  if (local_got_refcounts[r_symndx] == 0)
 
 
              BFD_ASSERT (*specific_refcount > 0);
 
              --*specific_refcount;
 
              if (*specific_refcount == 0)
                    {
                    {
                      /* We don't need the .got entry any more.  */
                      /* We don't need the .got entry any more.  */
                      sgot->size -= 4;
                  sgot->size -= got_element_size;
                      if (info->shared)
                      if (info->shared)
                        srelgot->size -= sizeof (Elf32_External_Rela);
                        srelgot->size -= sizeof (Elf32_External_Rela);
                    }
                    }
                }
                }
            }
 
          break;
          break;
 
 
        case R_CRIS_16_GOTPLT:
        case R_CRIS_16_GOTPLT:
        case R_CRIS_32_GOTPLT:
        case R_CRIS_32_GOTPLT:
          /* For local symbols, treat these like GOT relocs.  */
          /* For local symbols, treat these like GOT relocs.  */
Line 2074... Line 2681...
                  && h->plt.refcount > 0)
                  && h->plt.refcount > 0)
                --h->plt.refcount;
                --h->plt.refcount;
            }
            }
          break;
          break;
 
 
 
        case R_CRIS_32_DTPREL:
 
          /* This'd be a .dtpreld entry in e.g. debug info.  */
 
          if ((sec->flags & SEC_ALLOC) == 0)
 
            break;
 
          /* Fall through.  */
 
        case R_CRIS_16_DTPREL:
 
          elf_cris_hash_table (info)->dtpmod_refcount--;
 
          if (elf_cris_hash_table (info)->dtpmod_refcount == 0)
 
            elf_cris_hash_table (info)->next_gotplt_entry -= 8;
 
          BFD_ASSERT (local_got_refcounts != NULL);
 
          local_got_refcounts[-1]--;
 
          break;
 
 
        default:
        default:
          break;
          break;
        }
        }
    }
    }
 
 
Line 2103... Line 2723...
 
 
  /* If nobody wanted a GOTPLT with this symbol, we're done.  */
  /* If nobody wanted a GOTPLT with this symbol, we're done.  */
  if (h->gotplt_refcount <= 0)
  if (h->gotplt_refcount <= 0)
    return TRUE;
    return TRUE;
 
 
  if (h->root.got.refcount > 0)
  if (h->reg_got_refcount > 0)
    {
    {
      /* There's a GOT entry for this symbol.  Just adjust the refcount.
      /* There's a GOT entry for this symbol.  Just adjust the refcounts.
         Probably not necessary at this stage, but keeping it accurate
         Probably not necessary at this stage, but keeping them accurate
         helps avoiding surprises later.  */
         helps avoiding surprises later.  */
      h->root.got.refcount += h->gotplt_refcount;
      h->root.got.refcount += h->gotplt_refcount;
 
      h->reg_got_refcount += h->gotplt_refcount;
      h->gotplt_refcount = 0;
      h->gotplt_refcount = 0;
    }
    }
  else
  else
    {
    {
      /* No GOT entry for this symbol.  We need to create one.  */
      /* No GOT entry for this symbol.  We need to create one.  */
Line 2122... Line 2743...
 
 
      BFD_ASSERT (dynobj != NULL);
      BFD_ASSERT (dynobj != NULL);
      sgot = bfd_get_section_by_name (dynobj, ".got");
      sgot = bfd_get_section_by_name (dynobj, ".got");
      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
 
 
      /* Put an accurate refcount there.  */
      /* Put accurate refcounts there.  */
      h->root.got.refcount = h->gotplt_refcount;
      h->root.got.refcount += h->gotplt_refcount;
 
      h->reg_got_refcount = h->gotplt_refcount;
 
 
      h->gotplt_refcount = 0;
      h->gotplt_refcount = 0;
 
 
      /* We always have a .got and a .rela.got section if there were
      /* We always have a .got and a .rela.got section if there were
         GOTPLT relocs in input.  */
         GOTPLT relocs in input.  */
Line 2433... Line 3055...
    }
    }
 
 
  return _bfd_elf_adjust_dynamic_copy (h, s);
  return _bfd_elf_adjust_dynamic_copy (h, s);
}
}
 
 
 
/* Adjust our "subclass" elements for an indirect symbol.  */
 
 
 
static void
 
elf_cris_copy_indirect_symbol (struct bfd_link_info *info,
 
                               struct elf_link_hash_entry *dir,
 
                               struct elf_link_hash_entry *ind)
 
{
 
  struct elf_cris_link_hash_entry *edir, *eind;
 
 
 
  edir = (struct elf_cris_link_hash_entry *) dir;
 
  eind = (struct elf_cris_link_hash_entry *) ind;
 
 
 
  /* Only indirect symbols are replaced; we're not interested in
 
     updating any of EIND's fields for other symbols.  */
 
  if (eind->root.root.type != bfd_link_hash_indirect)
 
    {
 
      /* Still, we need to copy flags for e.g. weak definitions.  */
 
      _bfd_elf_link_hash_copy_indirect (info, dir, ind);
 
      return;
 
    }
 
 
 
  BFD_ASSERT (edir->pcrel_relocs_copied == NULL);
 
  BFD_ASSERT (edir->gotplt_offset == 0 || eind->gotplt_offset == 0);
 
 
 
#define XMOVOPZ(F, OP, Z) edir->F OP eind->F; eind->F = Z
 
#define XMOVE(F) XMOVOPZ (F, +=, 0)
 
  XMOVOPZ (pcrel_relocs_copied, =, NULL);
 
  XMOVE (gotplt_refcount);
 
  XMOVE (gotplt_offset);
 
  XMOVE (reg_got_refcount);
 
  XMOVE (tprel_refcount);
 
  XMOVE (dtp_refcount);
 
#undef XMOVE
 
#undef XMOVOPZ
 
 
 
  _bfd_elf_link_hash_copy_indirect (info, dir, ind);
 
}
 
 
/* Look through the relocs for a section during the first phase.  */
/* Look through the relocs for a section during the first phase.  */
 
 
static bfd_boolean
static bfd_boolean
cris_elf_check_relocs (abfd, info, sec, relocs)
cris_elf_check_relocs (abfd, info, sec, relocs)
     bfd *abfd;
     bfd *abfd;
Line 2470... Line 3130...
  for (rel = relocs; rel < rel_end; rel++)
  for (rel = relocs; rel < rel_end; rel++)
    {
    {
      struct elf_link_hash_entry *h;
      struct elf_link_hash_entry *h;
      unsigned long r_symndx;
      unsigned long r_symndx;
      enum elf_cris_reloc_type r_type;
      enum elf_cris_reloc_type r_type;
 
      bfd_signed_vma got_element_size = 4;
 
      unsigned long r_symndx_lgot = INT_MAX;
 
 
      r_symndx = ELF32_R_SYM (rel->r_info);
      r_symndx = ELF32_R_SYM (rel->r_info);
      if (r_symndx < symtab_hdr->sh_info)
      if (r_symndx < symtab_hdr->sh_info)
 
        {
        h = NULL;
        h = NULL;
 
          r_symndx_lgot = LGOT_REG_NDX (r_symndx);
 
        }
      else
      else
        {
        {
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
          while (h->root.type == bfd_link_hash_indirect
          while (h->root.type == bfd_link_hash_indirect
                 || h->root.type == bfd_link_hash_warning)
                 || h->root.type == bfd_link_hash_warning)
Line 2488... Line 3153...
 
 
      /* Some relocs require linker-created sections; we need to hang them
      /* Some relocs require linker-created sections; we need to hang them
         on the first input bfd we found that contained dynamic relocs.  */
         on the first input bfd we found that contained dynamic relocs.  */
      switch (r_type)
      switch (r_type)
        {
        {
 
        case R_CRIS_32_DTPREL:
 
          if ((sec->flags & SEC_ALLOC) == 0)
 
            /* This'd be a .dtpreld entry in e.g. debug info.  We have
 
               several different switch statements below, but none of
 
               that is needed; we need no preparations for resolving
 
               R_CRIS_32_DTPREL into a non-allocated section (debug
 
               info), so let's just move on to the next
 
               relocation.  */
 
            continue;
 
          /* Fall through.  */
 
        case R_CRIS_16_DTPREL:
 
          /* The first .got.plt entry is right after the R_CRIS_DTPMOD
 
             entry at index 3. */
 
          if (elf_cris_hash_table (info)->dtpmod_refcount == 0)
 
            elf_cris_hash_table (info)->next_gotplt_entry += 8;
 
          elf_cris_hash_table (info)->dtpmod_refcount++;
 
          /* Fall through.  */
 
 
 
        case R_CRIS_32_IE:
 
        case R_CRIS_32_GD:
 
        case R_CRIS_16_GOT_GD:
 
        case R_CRIS_32_GOT_GD:
 
        case R_CRIS_32_GOT_TPREL:
 
        case R_CRIS_16_GOT_TPREL:
        case R_CRIS_16_GOT:
        case R_CRIS_16_GOT:
        case R_CRIS_32_GOT:
        case R_CRIS_32_GOT:
        case R_CRIS_32_GOTREL:
        case R_CRIS_32_GOTREL:
        case R_CRIS_32_PLT_GOTREL:
        case R_CRIS_32_PLT_GOTREL:
        case R_CRIS_32_PLT_PCREL:
        case R_CRIS_32_PLT_PCREL:
Line 2516... Line 3205...
              /* Create the .got section, so we can assume it's always
              /* Create the .got section, so we can assume it's always
                 present whenever there's a dynobj.  */
                 present whenever there's a dynobj.  */
              if (!_bfd_elf_create_got_section (dynobj, info))
              if (!_bfd_elf_create_got_section (dynobj, info))
                return FALSE;
                return FALSE;
            }
            }
 
 
 
          if (sgot == NULL)
 
            sgot = bfd_get_section_by_name (dynobj, ".got");
 
 
 
          if (local_got_refcounts == NULL)
 
            {
 
              bfd_size_type amt;
 
 
 
              /* We use index local_got_refcounts[-1] to count all
 
                 GOT-relative relocations that do not have explicit
 
                 GOT entries.  */
 
              amt = LGOT_ALLOC_NELTS_FOR (symtab_hdr->sh_info) + 1;
 
              amt *= sizeof (bfd_signed_vma);
 
              local_got_refcounts = ((bfd_signed_vma *) bfd_zalloc (abfd, amt));
 
              if (local_got_refcounts == NULL)
 
                return FALSE;
 
 
 
              local_got_refcounts++;
 
              elf_local_got_refcounts (abfd) = local_got_refcounts;
 
            }
          break;
          break;
 
 
        default:
        default:
          break;
          break;
        }
        }
 
 
      /* Some relocs require a global offset table (but perhaps not a
      /* Some relocs require a global offset table (but perhaps not a
         specific GOT entry).  */
         specific GOT entry).  */
      switch (r_type)
      switch (r_type)
        {
        {
 
        case R_CRIS_16_DTPREL:
 
        case R_CRIS_32_DTPREL:
 
          /* Not requesting .got.rela for an executable: the contents
 
             of the first entry is constant there.  For a shared
 
             library, we need .got.rela for the R_CRIS_DTPMOD
 
             relocation at index 3.  */
 
          if (!info->shared)
 
            break;
 
          /* Fall through.  */
 
 
 
        case R_CRIS_32_IE:
 
        case R_CRIS_32_GD:
 
        case R_CRIS_16_GOT_GD:
 
        case R_CRIS_32_GOT_GD:
 
        case R_CRIS_32_GOT_TPREL:
 
        case R_CRIS_16_GOT_TPREL:
 
          /* Fall through.  */
 
 
          /* For R_CRIS_16_GOTPLT and R_CRIS_32_GOTPLT, we need a GOT
          /* For R_CRIS_16_GOTPLT and R_CRIS_32_GOTPLT, we need a GOT
             entry only for local symbols.  Unfortunately, we don't know
             entry only for local symbols.  Unfortunately, we don't know
             until later on if there's a version script that forces the
             until later on if there's a version script that forces the
             symbol local.  We must have the .rela.got section in place
             symbol local.  We must have the .rela.got section in place
             before we know if the symbol looks global now, so we need
             before we know if the symbol looks global now, so we need
Line 2556... Line 3283...
                  if (srelgot == NULL
                  if (srelgot == NULL
                      || !bfd_set_section_alignment (dynobj, srelgot, 2))
                      || !bfd_set_section_alignment (dynobj, srelgot, 2))
                    return FALSE;
                    return FALSE;
                }
                }
            }
            }
          /* Fall through.  */
          break;
 
 
        case R_CRIS_32_GOTREL:
        default:
        case R_CRIS_32_PLT_GOTREL:
          break;
          if (sgot == NULL)
        }
            sgot = bfd_get_section_by_name (dynobj, ".got");
 
 
 
          if (local_got_refcounts == NULL)
      /* Warn and error for invalid input.  */
 
      switch (r_type)
            {
            {
              bfd_size_type amt;
        case R_CRIS_32_IE:
 
        case R_CRIS_32_TPREL:
              /* We use index local_got_refcounts[-1] to count all
        case R_CRIS_16_TPREL:
                 GOT-relative relocations that do not have explicit
        case R_CRIS_32_GD:
                 GOT entries.  */
          if (info->shared)
              amt = symtab_hdr->sh_info + 1;
            {
              amt *= sizeof (bfd_signed_vma);
              (*_bfd_error_handler)
              local_got_refcounts = ((bfd_signed_vma *) bfd_zalloc (abfd, amt));
                (_("%B, section %A:\n  relocation %s not valid"
              if (local_got_refcounts == NULL)
                   " in a shared object;"
                return FALSE;
                   " typically an option mixup, recompile with -fPIC"),
 
                 abfd,
              local_got_refcounts++;
                 sec,
              elf_local_got_refcounts (abfd) = local_got_refcounts;
                 cris_elf_howto_table[r_type].name);
 
              /* Don't return FALSE here; we want messages for all of
 
                 these and the error behavior is ungraceful
 
                 anyway.  */
 
            }
 
        default:
 
          break;
            }
            }
 
 
 
      switch (r_type)
 
        {
 
        case R_CRIS_32_GD:
 
        case R_CRIS_16_GOT_GD:
 
        case R_CRIS_32_GOT_GD:
 
          /* These are requests for tls_index entries, run-time R_CRIS_DTP.  */
 
          got_element_size = 8;
 
          r_symndx_lgot = LGOT_DTP_NDX (r_symndx);
 
          break;
 
 
 
        case R_CRIS_16_DTPREL:
 
        case R_CRIS_32_DTPREL:
 
          /* These two just request for the constant-index
 
             module-local tls_index-sized GOT entry, which we add
 
             elsewhere.  */
 
          break;
 
 
 
        case R_CRIS_32_IE:
 
        case R_CRIS_32_GOT_TPREL:
 
        case R_CRIS_16_GOT_TPREL:
 
          r_symndx_lgot = LGOT_TPREL_NDX (r_symndx);
 
 
 
          /* Those relocs also require that a DSO is of type
 
             Initial Exec.  Like other targets, we don't reset this
 
             flag even if the relocs are GC:ed away.  */
 
          if (info->shared)
 
            info->flags |= DF_STATIC_TLS;
          break;
          break;
 
 
 
          /* Let's list the other assembler-generated TLS-relocs too,
 
             just to show that they're not forgotten. */
 
        case R_CRIS_16_TPREL:
 
        case R_CRIS_32_TPREL:
        default:
        default:
          break;
          break;
        }
        }
 
 
      switch (r_type)
      switch (r_type)
Line 2594... Line 3359...
          /* Mark that we need a GOT entry if the PLT entry (and its GOT
          /* Mark that we need a GOT entry if the PLT entry (and its GOT
             entry) is eliminated.  We can only do this for a non-local
             entry) is eliminated.  We can only do this for a non-local
             symbol.  */
             symbol.  */
          if (h != NULL)
          if (h != NULL)
            {
            {
              ((struct elf_cris_link_hash_entry *) h)->gotplt_refcount++;
              elf_cris_hash_entry (h)->gotplt_refcount++;
              goto handle_gotplt_reloc;
              goto handle_gotplt_reloc;
            }
            }
          /* If h is NULL then this is a local symbol, and we must make a
          /* If h is NULL then this is a local symbol, and we must make a
             GOT entry for it, so handle it like a GOT reloc.  */
             GOT entry for it, so handle it like a GOT reloc.  */
          /* Fall through.  */
          /* Fall through.  */
 
 
 
        case R_CRIS_32_IE:
 
        case R_CRIS_32_GD:
 
        case R_CRIS_16_GOT_GD:
 
        case R_CRIS_32_GOT_GD:
 
        case R_CRIS_32_GOT_TPREL:
 
        case R_CRIS_16_GOT_TPREL:
        case R_CRIS_16_GOT:
        case R_CRIS_16_GOT:
        case R_CRIS_32_GOT:
        case R_CRIS_32_GOT:
          /* This symbol requires a global offset table entry.  */
          /* This symbol requires a global offset table entry.  */
          if (h != NULL)
          if (h != NULL)
            {
            {
Line 2614... Line 3385...
                  if (h->dynindx == -1)
                  if (h->dynindx == -1)
                    {
                    {
                      if (!bfd_elf_link_record_dynamic_symbol (info, h))
                      if (!bfd_elf_link_record_dynamic_symbol (info, h))
                        return FALSE;
                        return FALSE;
                    }
                    }
 
                }
 
 
 
              /* Update the sum of reloc counts for this symbol.  */
 
              h->got.refcount++;
 
 
 
              switch (r_type)
 
                {
 
                case R_CRIS_16_GOT:
 
                case R_CRIS_32_GOT:
 
                  if (elf_cris_hash_entry (h)->reg_got_refcount == 0)
 
                    {
 
                      /* Allocate space in the .got section.  */
 
                      sgot->size += got_element_size;
 
                      /* Allocate relocation space.  */
 
                      srelgot->size += sizeof (Elf32_External_Rela);
 
                    }
 
                  elf_cris_hash_entry (h)->reg_got_refcount++;
 
                  break;
 
 
 
                case R_CRIS_32_GD:
 
                case R_CRIS_16_GOT_GD:
 
                case R_CRIS_32_GOT_GD:
 
                  if (elf_cris_hash_entry (h)->dtp_refcount == 0)
 
                    {
                  /* Allocate space in the .got section.  */
                  /* Allocate space in the .got section.  */
                  sgot->size += 4;
                      sgot->size += got_element_size;
                  /* Allocate relocation space.  */
                  /* Allocate relocation space.  */
                  srelgot->size += sizeof (Elf32_External_Rela);
                  srelgot->size += sizeof (Elf32_External_Rela);
                }
                }
              h->got.refcount++;
                  elf_cris_hash_entry (h)->dtp_refcount++;
 
                  break;
 
 
 
                case R_CRIS_32_IE:
 
                case R_CRIS_32_GOT_TPREL:
 
                case R_CRIS_16_GOT_TPREL:
 
                  if (elf_cris_hash_entry (h)->tprel_refcount == 0)
 
                    {
 
                      /* Allocate space in the .got section.  */
 
                      sgot->size += got_element_size;
 
                      /* Allocate relocation space.  */
 
                      srelgot->size += sizeof (Elf32_External_Rela);
 
                    }
 
                  elf_cris_hash_entry (h)->tprel_refcount++;
 
                  break;
 
 
 
                default:
 
                  BFD_FAIL ();
 
                  break;
 
                }
            }
            }
          else
          else
            {
            {
              /* This is a global offset table entry for a local symbol.  */
              /* This is a global offset table entry for a local symbol.  */
              if (local_got_refcounts[r_symndx] == 0)
              if (local_got_refcounts[r_symndx_lgot] == 0)
                {
                {
                  sgot->size += 4;
                  sgot->size += got_element_size;
                  if (info->shared)
                  if (info->shared)
                    {
                    {
                      /* If we are generating a shared object, we need to
                      /* If we are generating a shared object, we need
                         output a R_CRIS_RELATIVE reloc so that the dynamic
                         to output a R_CRIS_RELATIVE reloc so that the
                         linker can adjust this GOT entry.  */
                         dynamic linker can adjust this GOT entry.
 
                         Similarly for non-regular got entries.  */
                      srelgot->size += sizeof (Elf32_External_Rela);
                      srelgot->size += sizeof (Elf32_External_Rela);
                    }
                    }
                }
                }
 
              /* Update the reloc-specific count.  */
 
              local_got_refcounts[r_symndx_lgot]++;
 
 
 
              /* This one is the sum of all the others.  */
              local_got_refcounts[r_symndx]++;
              local_got_refcounts[r_symndx]++;
            }
            }
          break;
          break;
 
 
 
        case R_CRIS_16_DTPREL:
 
        case R_CRIS_32_DTPREL:
        case R_CRIS_32_GOTREL:
        case R_CRIS_32_GOTREL:
          /* This reference requires a global offset table.
          /* This reference requires a global offset table.
             FIXME: The actual refcount isn't used currently; the .got
             FIXME: The actual refcount isn't used currently; the .got
             section can't be removed if there were any references in the
             section can't be removed if there were any references in the
             input.  */
             input.  */
Line 2680... Line 3500...
 
 
        case R_CRIS_8:
        case R_CRIS_8:
        case R_CRIS_16:
        case R_CRIS_16:
        case R_CRIS_32:
        case R_CRIS_32:
          /* Let's help debug shared library creation.  Any of these
          /* Let's help debug shared library creation.  Any of these
             relocs can be used in shared libs, but pages containing them
             relocs *can* be used in shared libs, but pages containing
             cannot be shared.  Don't warn for sections we don't care
             them cannot be shared, so they're not appropriate for
             about, such as debug sections or non-constant sections.  We
             common use.  Don't warn for sections we don't care about,
             can't help tables of (global) function pointers, for example,
             such as debug sections or non-constant sections.  We
             though they must be emitted in a data section to avoid having
             can't help tables of (global) function pointers, for
             impure text sections.  */
             example, though they must be emitted in a (writable) data
 
             section to avoid having impure text sections.  */
          if (info->shared
          if (info->shared
              && (sec->flags & SEC_ALLOC) != 0
              && (sec->flags & SEC_ALLOC) != 0
              && (sec->flags & SEC_READONLY) != 0)
              && (sec->flags & SEC_READONLY) != 0)
            {
            {
              /* FIXME: How do we make this optionally a warning only?  */
              /* FIXME: How do we make this optionally a warning only?  */
Line 2698... Line 3519...
                   " be used in a shared object; recompile with -fPIC"),
                   " be used in a shared object; recompile with -fPIC"),
                 abfd,
                 abfd,
                 sec,
                 sec,
                 cris_elf_howto_table[r_type].name);
                 cris_elf_howto_table[r_type].name);
            }
            }
          /* Fall through.  */
          if (h != NULL)
 
            {
 
              h->non_got_ref = 1;
 
 
 
              /* Make sure a plt entry is created for this symbol if it
 
                 turns out to be a function defined by a dynamic object.  */
 
              if (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
 
                h->plt.refcount++;
 
            }
 
 
 
          /* If we are creating a shared library and this is not a local
 
             symbol, we need to copy the reloc into the shared library.
 
             However when linking with -Bsymbolic and this is a global
 
             symbol which is defined in an object we are including in the
 
             link (i.e., DEF_REGULAR is set), then we can resolve the
 
             reloc directly.  At this point we have not seen all the input
 
             files, so it is possible that DEF_REGULAR is not set now but
 
             will be set later (it is never cleared).  In case of a weak
 
             definition, DEF_REGULAR may be cleared later by a strong
 
             definition in a shared library.  We account for that
 
             possibility below by storing information in the relocs_copied
 
             field of the hash table entry.  A similar situation occurs
 
             when creating shared libraries and symbol visibility changes
 
             render the symbol local.  */
 
 
 
          /* No need to do anything if we're not creating a shared object.  */
 
          if (! info->shared)
 
            break;
 
 
 
          /* We don't need to handle relocs into sections not going into
 
             the "real" output.  */
 
          if ((sec->flags & SEC_ALLOC) == 0)
 
            break;
 
 
 
          /* We may need to create a reloc section in the dynobj and made room
 
             for this reloc.  */
 
          if (sreloc == NULL)
 
            {
 
              sreloc = _bfd_elf_make_dynamic_reloc_section
 
                (sec, dynobj, 2, abfd, /*rela?*/ TRUE);
 
 
 
              if (sreloc == NULL)
 
                return FALSE;
 
            }
 
 
 
          if (sec->flags & SEC_READONLY)
 
            info->flags |= DF_TEXTREL;
 
 
 
          sreloc->size += sizeof (Elf32_External_Rela);
 
          break;
 
 
        case R_CRIS_8_PCREL:
        case R_CRIS_8_PCREL:
        case R_CRIS_16_PCREL:
        case R_CRIS_16_PCREL:
        case R_CRIS_32_PCREL:
        case R_CRIS_32_PCREL:
          if (h != NULL)
          if (h != NULL)
Line 2737... Line 3607...
          /* We don't need to handle relocs into sections not going into
          /* We don't need to handle relocs into sections not going into
             the "real" output.  */
             the "real" output.  */
          if ((sec->flags & SEC_ALLOC) == 0)
          if ((sec->flags & SEC_ALLOC) == 0)
            break;
            break;
 
 
          /* We can only eliminate PC-relative relocs.  */
          /* If the symbol is local, then we know already we can
          if (r_type == R_CRIS_8_PCREL
             eliminate the reloc.  */
              || r_type == R_CRIS_16_PCREL
 
              || r_type == R_CRIS_32_PCREL)
 
            {
 
              /* If the symbol is local, then we can eliminate the reloc.  */
 
              if (h == NULL || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
              if (h == NULL || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
                break;
                break;
 
 
              /* If this is with -Bsymbolic and the symbol isn't weak, and
              /* If this is with -Bsymbolic and the symbol isn't weak, and
                 is defined by an ordinary object (the ones we include in
                 is defined by an ordinary object (the ones we include in
Line 2756... Line 3622...
              if (info->symbolic
              if (info->symbolic
                  && h->root.type != bfd_link_hash_defweak
                  && h->root.type != bfd_link_hash_defweak
                  && h->def_regular)
                  && h->def_regular)
                break;
                break;
 
 
              if ((sec->flags & SEC_READONLY) != 0)
          /* We may need to create a reloc section in the dynobj and made room
                {
             for this reloc.  */
                  /* FIXME: How do we make this optionally a warning only?  */
 
                  (*_bfd_error_handler)
 
                    (_("%B, section %A:\n  relocation %s should not be used"
 
                       " in a shared object; recompile with -fPIC"),
 
                     abfd,
 
                     sec,
 
                     cris_elf_howto_table[r_type].name);
 
                }
 
            }
 
 
 
          /* We create a reloc section in dynobj and make room for this
 
             reloc.  */
 
          if (sreloc == NULL)
          if (sreloc == NULL)
            {
            {
              const char *name;
              sreloc = _bfd_elf_make_dynamic_reloc_section
 
                (sec, dynobj, 2, abfd, /*rela?*/ TRUE);
              name = (bfd_elf_string_from_elf_section
 
                      (abfd,
 
                       elf_elfheader (abfd)->e_shstrndx,
 
                       elf_section_data (sec)->rel_hdr.sh_name));
 
              if (name == NULL)
 
                return FALSE;
 
 
 
              BFD_ASSERT (CONST_STRNEQ (name, ".rela")
 
                          && strcmp (bfd_get_section_name (abfd, sec),
 
                                     name + 5) == 0);
 
 
 
              sreloc = bfd_get_section_by_name (dynobj, name);
 
              if (sreloc == NULL)
              if (sreloc == NULL)
                {
 
                  sreloc = bfd_make_section_with_flags (dynobj, name,
 
                                                        (SEC_ALLOC
 
                                                         | SEC_LOAD
 
                                                         | SEC_HAS_CONTENTS
 
                                                         | SEC_IN_MEMORY
 
                                                         | SEC_LINKER_CREATED
 
                                                         | SEC_READONLY));
 
                  if (sreloc == NULL
 
                      || !bfd_set_section_alignment (dynobj, sreloc, 2))
 
                    return FALSE;
                    return FALSE;
                }
                }
              if (sec->flags & SEC_READONLY)
 
                info->flags |= DF_TEXTREL;
 
            }
 
 
 
          sreloc->size += sizeof (Elf32_External_Rela);
          sreloc->size += sizeof (Elf32_External_Rela);
 
 
          /* If we are linking with -Bsymbolic, we count the number of PC
          /* We count the number of PC relative relocations we have
             relative relocations we have entered for this symbol, so that
             entered for this symbol, so that we can discard them
             we can discard them again if the symbol is later defined by a
             again if the symbol is later defined by a regular object.
             regular object.  We know that h is really a pointer to an
             We know that h is really a pointer to an
             elf_cris_link_hash_entry.  */
             elf_cris_link_hash_entry.  */
          if ((r_type == R_CRIS_8_PCREL
 
               || r_type == R_CRIS_16_PCREL
 
               || r_type == R_CRIS_32_PCREL)
 
              && info->symbolic)
 
            {
            {
              struct elf_cris_link_hash_entry *eh;
              struct elf_cris_link_hash_entry *eh;
              struct elf_cris_pcrel_relocs_copied *p;
              struct elf_cris_pcrel_relocs_copied *p;
 
 
              eh = (struct elf_cris_link_hash_entry *) h;
            eh = elf_cris_hash_entry (h);
 
 
              for (p = eh->pcrel_relocs_copied; p != NULL; p = p->next)
              for (p = eh->pcrel_relocs_copied; p != NULL; p = p->next)
                if (p->section == sreloc)
                if (p->section == sreloc)
                  break;
                  break;
 
 
Line 2834... Line 3660...
                    return FALSE;
                    return FALSE;
                  p->next = eh->pcrel_relocs_copied;
                  p->next = eh->pcrel_relocs_copied;
                  eh->pcrel_relocs_copied = p;
                  eh->pcrel_relocs_copied = p;
                  p->section = sreloc;
                  p->section = sreloc;
                  p->count = 0;
                  p->count = 0;
 
                p->r_type = r_type;
                }
                }
 
 
              ++p->count;
              ++p->count;
            }
            }
          break;
          break;
Line 2856... Line 3683...
          if (h != NULL
          if (h != NULL
              && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
              && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
            return FALSE;
            return FALSE;
          break;
          break;
 
 
 
        case R_CRIS_16_TPREL:
 
        case R_CRIS_32_TPREL:
 
          /* Already warned above, when necessary.  */
 
          break;
 
 
        default:
        default:
          /* Other relocs do not appear here.  */
          /* Other relocs do not appear here.  */
          bfd_set_error (bfd_error_bad_value);
          bfd_set_error (bfd_error_bad_value);
          return FALSE;
          return FALSE;
        }
        }
Line 2946... Line 3778...
      if (strcmp (name, ".plt") == 0)
      if (strcmp (name, ".plt") == 0)
        {
        {
          /* Remember whether there is a PLT.  */
          /* Remember whether there is a PLT.  */
          plt = s->size != 0;
          plt = s->size != 0;
        }
        }
 
      else if (strcmp (name, ".got.plt") == 0)
 
        {
 
          /* The .got.plt contains the .got header as well as the
 
             actual .got.plt contents.  The .got header may contain a
 
             R_CRIS_DTPMOD entry at index 3.  */
 
          s->size += elf_cris_hash_table (info)->dtpmod_refcount != 0
 
            ? 8 : 0;
 
        }
      else if (CONST_STRNEQ (name, ".rela"))
      else if (CONST_STRNEQ (name, ".rela"))
        {
        {
 
          if (strcmp (name, ".rela.got") == 0
 
              && elf_cris_hash_table (info)->dtpmod_refcount != 0
 
              && info->shared)
 
            s->size += sizeof (Elf32_External_Rela);
 
 
          if (s->size != 0)
          if (s->size != 0)
            {
            {
              /* Remember whether there are any reloc sections other
              /* Remember whether there are any reloc sections other
                 than .rela.plt.  */
                 than .rela.plt.  */
              if (strcmp (name, ".rela.plt") != 0)
              if (strcmp (name, ".rela.plt") != 0)
Line 3069... Line 3914...
      && (h->root.forced_local
      && (h->root.forced_local
          || info->symbolic))
          || info->symbolic))
    {
    {
      for (s = h->pcrel_relocs_copied; s != NULL; s = s->next)
      for (s = h->pcrel_relocs_copied; s != NULL; s = s->next)
        s->section->size -= s->count * sizeof (Elf32_External_Rela);
        s->section->size -= s->count * sizeof (Elf32_External_Rela);
 
 
 
      return TRUE;
 
    }
 
 
 
  /* If we have accounted for PC-relative relocs for read-only
 
     sections, now is the time to warn for them.  We can't do it in
 
     cris_elf_check_relocs, because we don't know the status of all
 
     symbols at that time (and it's common to force symbols local
 
     late).  */
 
 
 
  for (s = h->pcrel_relocs_copied; s != NULL; s = s->next)
 
    {
 
      BFD_ASSERT ((s->section->flags & SEC_READONLY) != 0);
 
 
 
      /* FIXME: How do we make this optionally a warning only?  */
 
      (*_bfd_error_handler)
 
        (_("%B, section `%A', to symbol `%s':\n"
 
           "  relocation %s should not be used"
 
           " in a shared object; recompile with -fPIC"),
 
         s->section->owner,
 
         s->section,
 
         h->root.root.root.string,
 
         cris_elf_howto_table[s->r_type].name);
 
 
 
      info->flags |= DF_TEXTREL;
    }
    }
 
 
  return TRUE;
  return TRUE;
}
}
 
 
Line 3096... Line 3966...
     (don't allocate room for it).  Likewise for relocs for something
     (don't allocate room for it).  Likewise for relocs for something
     for which we create a PLT.  */
     for which we create a PLT.  */
  if (!h->root.def_dynamic
  if (!h->root.def_dynamic
      || h->root.plt.refcount > 0)
      || h->root.plt.refcount > 0)
    {
    {
      if (h->root.got.refcount > 0
      if (h->reg_got_refcount > 0
          /* The size of this section is only valid and in sync with the
          /* The size of this section is only valid and in sync with the
             various reference counts if we do dynamic; don't decrement it
             various reference counts if we do dynamic; don't decrement it
             otherwise.  */
             otherwise.  */
          && elf_hash_table (info)->dynamic_sections_created)
          && elf_hash_table (info)->dynamic_sections_created)
        {
        {
Line 3351... Line 4221...
 
 
static enum elf_reloc_type_class
static enum elf_reloc_type_class
elf_cris_reloc_type_class (rela)
elf_cris_reloc_type_class (rela)
     const Elf_Internal_Rela *rela;
     const Elf_Internal_Rela *rela;
{
{
  switch ((int) ELF32_R_TYPE (rela->r_info))
  enum elf_cris_reloc_type r_type = ELF32_R_TYPE (rela->r_info);
 
  switch (r_type)
    {
    {
    case R_CRIS_RELATIVE:
    case R_CRIS_RELATIVE:
      return reloc_class_relative;
      return reloc_class_relative;
    case R_CRIS_JUMP_SLOT:
    case R_CRIS_JUMP_SLOT:
      return reloc_class_plt;
      return reloc_class_plt;
Line 3363... Line 4234...
      return reloc_class_copy;
      return reloc_class_copy;
    default:
    default:
      return reloc_class_normal;
      return reloc_class_normal;
    }
    }
}
}
 
 
 
/* The elf_backend_got_elt_size worker.  For one symbol, we can have up to
 
   two GOT entries from three types with two different sizes.  We handle
 
   it as a single entry, so we can use the regular offset-calculation
 
   machinery.  */
 
 
 
static bfd_vma
 
elf_cris_got_elt_size (bfd *abfd ATTRIBUTE_UNUSED,
 
                       struct bfd_link_info *info ATTRIBUTE_UNUSED,
 
                       struct elf_link_hash_entry *hr,
 
                       bfd *ibfd,
 
                       unsigned long symndx)
 
{
 
  struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) hr;
 
  bfd_vma eltsiz = 0;
 
 
 
  /* We may have one regular GOT entry or up to two TLS GOT
 
     entries.  */
 
  if (h == NULL)
 
    {
 
      Elf_Internal_Shdr *symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
 
      bfd_signed_vma *local_got_refcounts = elf_local_got_refcounts (ibfd);
 
 
 
      BFD_ASSERT (local_got_refcounts != NULL);
 
 
 
      if (local_got_refcounts[LGOT_REG_NDX (symndx)] > 0)
 
        {
 
          /* We can't have a variable referred to both as a regular
 
             variable and through TLS relocs.  */
 
          BFD_ASSERT (local_got_refcounts[LGOT_DTP_NDX (symndx)] == 0
 
                      && local_got_refcounts[LGOT_TPREL_NDX (symndx)] == 0);
 
          return 4;
 
        }
 
 
 
      if (local_got_refcounts[LGOT_DTP_NDX (symndx)] > 0)
 
        eltsiz += 8;
 
 
 
      if (local_got_refcounts[LGOT_TPREL_NDX (symndx)] > 0)
 
        eltsiz += 4;
 
    }
 
  else
 
    {
 
      struct elf_cris_link_hash_entry *hh = elf_cris_hash_entry (h);
 
      if (hh->reg_got_refcount > 0)
 
        {
 
          /* The actual error-on-input is emitted elsewhere.  */
 
          BFD_ASSERT (hh->dtp_refcount == 0 && hh->tprel_refcount == 0);
 
          return 4;
 
        }
 
 
 
      if (hh->dtp_refcount > 0)
 
        eltsiz += 8;
 
 
 
      if (hh->tprel_refcount > 0)
 
        eltsiz += 4;
 
    }
 
 
 
  /* We're only called when h->got.refcount is non-zero, so we must
 
     have a non-zero size.  */
 
  BFD_ASSERT (eltsiz != 0);
 
  return eltsiz;
 
}


#define ELF_ARCH                bfd_arch_cris
#define ELF_ARCH                bfd_arch_cris
#define ELF_MACHINE_CODE        EM_CRIS
#define ELF_MACHINE_CODE        EM_CRIS
#define ELF_MAXPAGESIZE         0x2000
#define ELF_MAXPAGESIZE         0x2000
 
 
Line 3401... Line 4334...
 
 
#define bfd_elf32_bfd_link_hash_table_create \
#define bfd_elf32_bfd_link_hash_table_create \
        elf_cris_link_hash_table_create
        elf_cris_link_hash_table_create
#define elf_backend_adjust_dynamic_symbol \
#define elf_backend_adjust_dynamic_symbol \
        elf_cris_adjust_dynamic_symbol
        elf_cris_adjust_dynamic_symbol
 
#define elf_backend_copy_indirect_symbol \
 
        elf_cris_copy_indirect_symbol
#define elf_backend_size_dynamic_sections \
#define elf_backend_size_dynamic_sections \
        elf_cris_size_dynamic_sections
        elf_cris_size_dynamic_sections
#define elf_backend_init_index_section          _bfd_elf_init_1_index_section
#define elf_backend_init_index_section          _bfd_elf_init_1_index_section
#define elf_backend_finish_dynamic_symbol \
#define elf_backend_finish_dynamic_symbol \
        elf_cris_finish_dynamic_symbol
        elf_cris_finish_dynamic_symbol
Line 3419... Line 4354...
 
 
#define elf_backend_want_got_plt        1
#define elf_backend_want_got_plt        1
#define elf_backend_plt_readonly        1
#define elf_backend_plt_readonly        1
#define elf_backend_want_plt_sym        0
#define elf_backend_want_plt_sym        0
#define elf_backend_got_header_size     12
#define elf_backend_got_header_size     12
 
#define elf_backend_got_elt_size elf_cris_got_elt_size
 
 
/* Later, we my want to optimize RELA entries into REL entries for dynamic
/* Later, we my want to optimize RELA entries into REL entries for dynamic
   linking and libraries (if it's a win of any significance).  Until then,
   linking and libraries (if it's a win of any significance).  Until then,
   take the easy route.  */
   take the easy route.  */
#define elf_backend_may_use_rel_p 0
#define elf_backend_may_use_rel_p 0

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.