* aix386-core.c: Remove use of PTR and PARAMS macros.
[deliverable/binutils-gdb.git] / bfd / elf32-cris.c
index 8c9a79b084b468b358c8d1dbaac3074c76aa46b5..c9316ee1958ee7cc35784f128be62f24b6477faf 100644 (file)
@@ -1,6 +1,6 @@
 /* CRIS-specific support for 32-bit ELF.
-   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
-   Free Software Foundation, Inc.
+   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+   2010, 2011, 2012 Free Software Foundation, Inc.
    Contributed by Axis Communications AB.
    Written by Hans-Peter Nilsson, based on elf32-fr30.c
    PIC and shlib bits based primarily on elf32-m68k.c and elf32-i386.c.
 #include "elf/cris.h"
 #include <limits.h>
 
-/* Forward declarations.  */
-static reloc_howto_type * cris_reloc_type_lookup
-  PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
-
-static void cris_info_to_howto_rela
-  PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
-
-static bfd_reloc_status_type cris_elf_pcrel_reloc
-  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-
-static bfd_boolean cris_elf_grok_prstatus
-  PARAMS ((bfd *abfd, Elf_Internal_Note *note));
-
-static bfd_boolean cris_elf_grok_psinfo
-  PARAMS ((bfd *abfd, Elf_Internal_Note *note));
-
-static bfd_boolean cris_elf_relocate_section
-  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
-          Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
-
-static bfd_reloc_status_type cris_final_link_relocate
-  PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
-          Elf_Internal_Rela *, bfd_vma));
-
-static bfd_boolean cris_elf_object_p PARAMS ((bfd *));
-
-static void cris_elf_final_write_processing PARAMS ((bfd *, bfd_boolean));
-
-static bfd_boolean cris_elf_set_mach_from_flags
-  PARAMS ((bfd *, unsigned long int));
-
-static bfd_boolean cris_elf_print_private_bfd_data PARAMS ((bfd *, PTR));
-
-static bfd_boolean cris_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *));
-static bfd_boolean cris_elf_copy_private_bfd_data PARAMS ((bfd *, bfd *));
-
-struct elf_cris_link_hash_entry;
-static bfd_boolean elf_cris_discard_excess_dso_dynamics
-  PARAMS ((struct elf_cris_link_hash_entry *, PTR));
-static bfd_boolean elf_cris_discard_excess_program_dynamics
-  PARAMS ((struct elf_cris_link_hash_entry *, PTR));
-static bfd_boolean elf_cris_adjust_gotplt_to_got
-  PARAMS ((struct elf_cris_link_hash_entry *, PTR));
-static bfd_boolean elf_cris_try_fold_plt_to_got
-  PARAMS ((struct elf_cris_link_hash_entry *, PTR));
-static struct bfd_hash_entry *elf_cris_link_hash_newfunc
-  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
-static struct bfd_link_hash_table *elf_cris_link_hash_table_create
-  PARAMS ((bfd *));
-static bfd_boolean elf_cris_adjust_dynamic_symbol
-  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
-static bfd_boolean cris_elf_check_relocs
-  PARAMS ((bfd *, struct bfd_link_info *, asection *,
-          const Elf_Internal_Rela *));
-
-static bfd_boolean elf_cris_size_dynamic_sections
-  PARAMS ((bfd *, struct bfd_link_info *));
-static bfd_boolean elf_cris_finish_dynamic_symbol
-  PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
-          Elf_Internal_Sym *));
-static bfd_boolean elf_cris_finish_dynamic_sections
-  PARAMS ((bfd *, struct bfd_link_info *));
-static void elf_cris_hide_symbol
-  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *, bfd_boolean));
-static enum elf_reloc_type_class elf_cris_reloc_type_class
-  PARAMS ((const Elf_Internal_Rela *));
+bfd_reloc_status_type
+cris_elf_pcrel_reloc (bfd *, arelent *, asymbol *, void *,
+                     asection *, bfd *, char **);
+static bfd_boolean
+cris_elf_set_mach_from_flags (bfd *, unsigned long);
 
+/* Forward declarations.  */
 static reloc_howto_type cris_elf_howto_table [] =
 {
   /* This reloc does nothing.  */
@@ -436,7 +376,8 @@ static reloc_howto_type cris_elf_howto_table [] =
   TLSHOWTO16S (R_CRIS_16_GOT_TPREL),
   TLSHOWTO32 (R_CRIS_32_TPREL),
   TLSHOWTO16S (R_CRIS_16_TPREL),
-  TLSHOWTO32 (R_CRIS_DTPMOD)
+  TLSHOWTO32 (R_CRIS_DTPMOD),
+  TLSHOWTO32 (R_CRIS_32_IE)
 };
 \f
 /* Map BFD reloc types to CRIS ELF reloc types.  */
@@ -479,13 +420,13 @@ static const struct cris_reloc_map cris_reloc_map [] =
   { 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_DTPMOD,     R_CRIS_DTPMOD },
+  { BFD_RELOC_CRIS_32_IE,      R_CRIS_32_IE }
 };
 
 static reloc_howto_type *
-cris_reloc_type_lookup (abfd, code)
-     bfd * abfd ATTRIBUTE_UNUSED;
-     bfd_reloc_code_real_type code;
+cris_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
+                       bfd_reloc_code_real_type code)
 {
   unsigned int i;
 
@@ -514,10 +455,9 @@ cris_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
 /* Set the howto pointer for an CRIS ELF reloc.  */
 
 static void
-cris_info_to_howto_rela (abfd, cache_ptr, dst)
-     bfd * abfd ATTRIBUTE_UNUSED;
-     arelent * cache_ptr;
-     Elf_Internal_Rela * dst;
+cris_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED,
+                        arelent * cache_ptr,
+                        Elf_Internal_Rela * dst)
 {
   enum elf_cris_reloc_type r_type;
 
@@ -527,15 +467,13 @@ cris_info_to_howto_rela (abfd, cache_ptr, dst)
 }
 
 bfd_reloc_status_type
-cris_elf_pcrel_reloc (abfd, reloc_entry, symbol, data, input_section,
-                     output_bfd, error_message)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     arelent *reloc_entry;
-     asymbol *symbol;
-     PTR data ATTRIBUTE_UNUSED;
-     asection *input_section;
-     bfd *output_bfd;
-     char **error_message ATTRIBUTE_UNUSED;
+cris_elf_pcrel_reloc (bfd *abfd ATTRIBUTE_UNUSED,
+                     arelent *reloc_entry,
+                     asymbol *symbol,
+                     void * data ATTRIBUTE_UNUSED,
+                     asection *input_section,
+                     bfd *output_bfd,
+                     char **error_message ATTRIBUTE_UNUSED)
 {
   /* By default (using only bfd_elf_generic_reloc when linking to
      non-ELF formats) PC-relative relocs are relative to the beginning
@@ -560,9 +498,7 @@ cris_elf_pcrel_reloc (abfd, reloc_entry, symbol, data, input_section,
    changes, while still keeping Linux/CRIS and Linux/CRISv32 code apart.  */
 
 static bfd_boolean
-cris_elf_grok_prstatus (abfd, note)
-     bfd *abfd;
-     Elf_Internal_Note *note;
+cris_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
 {
   int offset;
   size_t size;
@@ -578,7 +514,7 @@ cris_elf_grok_prstatus (abfd, note)
        elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
 
        /* pr_pid */
-       elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 22);
+       elf_tdata (abfd)->core_lwpid = bfd_get_32 (abfd, note->descdata + 22);
 
        /* pr_reg */
        offset = 70;
@@ -597,7 +533,7 @@ cris_elf_grok_prstatus (abfd, note)
        elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
 
        /* pr_pid */
-       elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 22);
+       elf_tdata (abfd)->core_lwpid = bfd_get_32 (abfd, note->descdata + 22);
 
        /* pr_reg */
        offset = 70;
@@ -612,9 +548,7 @@ cris_elf_grok_prstatus (abfd, note)
 }
 
 static bfd_boolean
-cris_elf_grok_psinfo (abfd, note)
-     bfd *abfd;
-     Elf_Internal_Note *note;
+cris_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
 {
   if (bfd_get_mach (abfd) == bfd_mach_cris_v32)
     switch (note->descsz)
@@ -846,6 +780,13 @@ struct elf_cris_link_hash_entry
   bfd_signed_vma dtp_refcount;
 };
 
+static bfd_boolean
+elf_cris_discard_excess_dso_dynamics (struct elf_cris_link_hash_entry *,
+                                     void * );
+static bfd_boolean
+elf_cris_discard_excess_program_dynamics (struct elf_cris_link_hash_entry *,
+                                         void *);
+
 /* 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
@@ -883,13 +824,14 @@ struct elf_cris_link_hash_table
 #define elf_cris_link_hash_traverse(table, func, info)                 \
   (elf_link_hash_traverse                                              \
    (&(table)->root,                                                    \
-    (bfd_boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func), \
+    (bfd_boolean (*) (struct elf_link_hash_entry *, void *)) (func),   \
     (info)))
 
 /* Get the CRIS ELF linker hash table from a link_info structure.  */
 
 #define elf_cris_hash_table(p) \
-  ((struct elf_cris_link_hash_table *) (p)->hash)
+  (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
+  == CRIS_ELF_DATA ? ((struct elf_cris_link_hash_table *) ((p)->hash)) : NULL)
 
 /* Get the CRIS ELF linker hash entry from a regular hash entry (the
    "parent class").  The .root reference is just a simple type
@@ -901,10 +843,9 @@ struct elf_cris_link_hash_table
 /* Create an entry in a CRIS ELF linker hash table.  */
 
 static struct bfd_hash_entry *
-elf_cris_link_hash_newfunc (entry, table, string)
-     struct bfd_hash_entry *entry;
-     struct bfd_hash_table *table;
-     const char *string;
+elf_cris_link_hash_newfunc (struct bfd_hash_entry *entry,
+                           struct bfd_hash_table *table,
+                           const char *string)
 {
   struct elf_cris_link_hash_entry *ret =
     (struct elf_cris_link_hash_entry *) entry;
@@ -938,8 +879,7 @@ elf_cris_link_hash_newfunc (entry, table, string)
 /* Create a CRIS ELF linker hash table.  */
 
 static struct bfd_link_hash_table *
-elf_cris_link_hash_table_create (abfd)
-     bfd *abfd;
+elf_cris_link_hash_table_create (bfd *abfd)
 {
   struct elf_cris_link_hash_table *ret;
   bfd_size_type amt = sizeof (struct elf_cris_link_hash_table);
@@ -950,7 +890,8 @@ elf_cris_link_hash_table_create (abfd)
 
   if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
                                      elf_cris_link_hash_newfunc,
-                                     sizeof (struct elf_cris_link_hash_entry)))
+                                     sizeof (struct elf_cris_link_hash_entry),
+                                     CRIS_ELF_DATA))
     {
       free (ret);
       return NULL;
@@ -970,14 +911,12 @@ elf_cris_link_hash_table_create (abfd)
    routines, with a few tweaks.  */
 
 static bfd_reloc_status_type
-cris_final_link_relocate (howto, input_bfd, input_section, contents, rel,
-                         relocation)
-     reloc_howto_type *  howto;
-     bfd *               input_bfd;
-     asection *          input_section;
-     bfd_byte *          contents;
-     Elf_Internal_Rela * rel;
-     bfd_vma             relocation;
+cris_final_link_relocate (reloc_howto_type *  howto,
+                         bfd *               input_bfd,
+                         asection *          input_section,
+                         bfd_byte *          contents,
+                         Elf_Internal_Rela * rel,
+                         bfd_vma             relocation)
 {
   bfd_reloc_status_type r;
   enum elf_cris_reloc_type r_type = ELF32_R_TYPE (rel->r_info);
@@ -1025,17 +964,16 @@ static int additional_relocation_error_msg_count = 10;
    copied, for further comments.  */
 
 static bfd_boolean
-cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
-                          contents, relocs, local_syms, local_sections)
-     bfd *output_bfd ATTRIBUTE_UNUSED;
-     struct bfd_link_info *info;
-     bfd *input_bfd;
-     asection *input_section;
-     bfd_byte *contents;
-     Elf_Internal_Rela *relocs;
-     Elf_Internal_Sym *local_syms;
-     asection **local_sections;
+cris_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
+                          struct bfd_link_info *info,
+                          bfd *input_bfd,
+                          asection *input_section,
+                          bfd_byte *contents,
+                          Elf_Internal_Rela *relocs,
+                          Elf_Internal_Sym *local_syms,
+                          asection **local_sections)
 {
+  struct elf_cris_link_hash_table * htab;
   bfd *dynobj;
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_link_hash_entry **sym_hashes;
@@ -1047,6 +985,10 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
   Elf_Internal_Rela *relend;
   asection *srelgot;
 
+  htab = elf_cris_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
   dynobj = elf_hash_table (info)->dynobj;
   local_got_offsets = elf_local_got_offsets (input_bfd);
   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
@@ -1060,8 +1002,8 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
   if (dynobj != NULL)
     {
-      splt = bfd_get_section_by_name (dynobj, ".plt");
-      sgot = bfd_get_section_by_name (dynobj, ".got");
+      splt = bfd_get_linker_section (dynobj, ".plt");
+      sgot = bfd_get_linker_section (dynobj, ".got");
     }
 
   for (rel = relocs; rel < relend; rel ++)
@@ -1161,7 +1103,11 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                      || r_type == R_CRIS_16_PCREL
                      || r_type == R_CRIS_32_PCREL))
                relocation = 0;
-             else if (!info->relocatable && unresolved_reloc)
+             else if (!info->relocatable && unresolved_reloc
+                      && (_bfd_elf_section_offset (output_bfd, info,
+                                                   input_section,
+                                                   rel->r_offset)
+                          != (bfd_vma) -1))
                {
                  _bfd_error_handler
                    (_("%B, section %A: unresolvable relocation %s against symbol `%s'"),
@@ -1175,16 +1121,9 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
            }
        }
 
-      if (sec != NULL && elf_discarded_section (sec))
-       {
-         /* For relocs against symbols from removed linkonce sections,
-            or sections discarded by a linker script, we just want the
-            section contents zeroed.  Avoid any special processing.  */
-         _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
-         rel->r_info = 0;
-         rel->r_addend = 0;
-         continue;
-       }
+      if (sec != NULL && discarded_section (sec))
+       RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+                                        rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
        continue;
@@ -1202,7 +1141,7 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
              && ((struct elf_cris_link_hash_entry *) h)->gotplt_offset != 0)
            {
              asection *sgotplt
-               = bfd_get_section_by_name (dynobj, ".got.plt");
+               = bfd_get_linker_section (dynobj, ".got.plt");
              bfd_vma got_offset;
 
              BFD_ASSERT (h->dynindx != -1);
@@ -1334,7 +1273,7 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
                        if (srelgot == NULL)
                          srelgot
-                           = bfd_get_section_by_name (dynobj, ".rela.got");
+                           = bfd_get_linker_section (dynobj, ".rela.got");
                        BFD_ASSERT (srelgot != NULL);
 
                        outrel.r_offset = (sgot->output_section->vma
@@ -1488,13 +1427,13 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
        case R_CRIS_16:
        case R_CRIS_32:
          if (info->shared
-             && r_symndx != 0
+             && r_symndx != STN_UNDEF
              && (input_section->flags & SEC_ALLOC) != 0
              && ((r_type != R_CRIS_8_PCREL
                   && r_type != R_CRIS_16_PCREL
                   && r_type != R_CRIS_32_PCREL)
                  || (!info->symbolic
-                     || !h->def_regular)))
+                     || (h != NULL && !h->def_regular))))
            {
              Elf_Internal_Rela outrel;
              bfd_byte *loc;
@@ -1507,7 +1446,7 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
              if (sreloc == NULL)
                {
                  sreloc = _bfd_elf_get_dynamic_reloc_section
-                   (input_bfd, input_section, /*rela?*/ TRUE);
+                   (dynobj, input_section, /*rela?*/ TRUE);
                  /* The 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.  */
@@ -1526,7 +1465,16 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                                         rel->r_offset);
              if (outrel.r_offset == (bfd_vma) -1)
                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;
              outrel.r_offset += (input_section->output_section->vma
                                  + input_section->output_offset);
@@ -1576,8 +1524,6 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                          indx = elf_section_data (osec)->dynindx;
                          if (indx == 0)
                            {
-                             struct elf_cris_link_hash_table *htab;
-                             htab = elf_cris_hash_table (info);
                              osec = htab->root.text_index_section;
                              indx = elf_section_data (osec)->dynindx;
                            }
@@ -1604,10 +1550,12 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
        case R_CRIS_16_DTPREL:
        case R_CRIS_32_DTPREL:
          /* This relocation must only be performed against local
-            symbols.  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).  */
+            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
@@ -1630,16 +1578,18 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
              return FALSE;
            }
 
-         BFD_ASSERT (elf_cris_hash_table (info)->dtpmod_refcount != 0);
+         BFD_ASSERT ((input_section->flags & SEC_ALLOC) == 0
+                     || htab->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)
+         if (htab->dtpmod_refcount > 0
+             && (input_section->flags & SEC_ALLOC) != 0)
            {
-             asection *sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
+             asection *sgotplt = bfd_get_linker_section (dynobj, ".got.plt");
              BFD_ASSERT (sgotplt != NULL);
 
              if (info->shared)
@@ -1648,7 +1598,7 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                  bfd_byte *loc;
 
                  if (srelgot == NULL)
-                   srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+                   srelgot = bfd_get_linker_section (dynobj, ".rela.got");
                  BFD_ASSERT (srelgot != NULL);
                  loc = srelgot->contents;
                  loc += srelgot->reloc_count++ * sizeof (Elf32_External_Rela);
@@ -1671,12 +1621,11 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
              /* 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;
+             htab->dtpmod_refcount = - htab->dtpmod_refcount;
            }
 
-         /* The thread-based offset to the local symbol is the
-            relocation.  */
+         /* 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;
@@ -1713,7 +1662,8 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
              return FALSE;
            }
 
-         if (!info->shared && (h == NULL || h->def_regular))
+         if (!info->shared
+             && (h == NULL || h->def_regular || ELF_COMMON_DEF_P (h)))
            {
              /* Known contents of the GOT.  */
              bfd_vma off;
@@ -1792,7 +1742,7 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                  bfd_put_32 (output_bfd, 0, sgot->contents + off + 4);
 
                  if (srelgot == NULL)
-                   srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+                   srelgot = bfd_get_linker_section (dynobj, ".rela.got");
                  BFD_ASSERT (srelgot != NULL);
 
                  if (h != NULL && h->dynindx != -1)
@@ -1832,6 +1782,17 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
             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)
@@ -1853,14 +1814,16 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
              return FALSE;
            }
 
-         if (!info->shared && (h == NULL || h->def_regular))
+         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
-                the known_tpoffset into the GOT.  */
+                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;
@@ -1884,7 +1847,8 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
              else
                off &= ~3;
 
-             relocation = sgot->output_offset + off;
+             relocation = sgot->output_offset + off
+               + (r_type == R_CRIS_32_IE ? sgot->output_section->vma : 0);
            }
          else
            {
@@ -1910,7 +1874,7 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                    local_got_offsets[r_symndx] |= 1;
 
                  if (srelgot == NULL)
-                   srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+                   srelgot = bfd_get_linker_section (dynobj, ".rela.got");
                  BFD_ASSERT (srelgot != NULL);
 
                  if (h != NULL && h->dynindx != -1)
@@ -1944,10 +1908,12 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
              else
                off &= ~3;
 
-             relocation = sgot->output_offset + off;
+             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.  */
+         /* 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:
@@ -1965,7 +1931,7 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
          if (h != NULL
              && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-             && !h->def_regular
+             && !(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)
@@ -1985,7 +1951,9 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
          /* NULL if we had an error.  */
          relocation -= elf_hash_table (info)->tls_sec == NULL
-           ? 0 : elf_hash_table (info)->tls_sec->vma;
+           ? 0
+           : (elf_hash_table (info)->tls_sec->vma
+              + elf_hash_table (info)->tls_size);
 
          /* The TLS-relative offset is the relocation.  */
          break;
@@ -2080,12 +2048,12 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
    dynamic sections here.  */
 
 static bfd_boolean
-elf_cris_finish_dynamic_symbol (output_bfd, info, h, sym)
-     bfd *output_bfd;
-     struct bfd_link_info *info;
-     struct elf_link_hash_entry *h;
-     Elf_Internal_Sym *sym;
+elf_cris_finish_dynamic_symbol (bfd *output_bfd,
+                               struct bfd_link_info *info,
+                               struct elf_link_hash_entry *h,
+                               Elf_Internal_Sym *sym)
 {
+  struct elf_cris_link_hash_table * htab;
   bfd *dynobj;
 
   /* Where in the plt entry to put values.  */
@@ -2102,6 +2070,10 @@ elf_cris_finish_dynamic_symbol (output_bfd, info, h, sym)
   const bfd_byte *plt_entry = elf_cris_plt_entry;
   const bfd_byte *plt_pic_entry = elf_cris_pic_plt_entry;
 
+  htab = elf_cris_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
   /* Adjust the various PLT entry offsets.  */
   if (bfd_get_mach (output_bfd) == bfd_mach_cris_v32)
     {
@@ -2120,7 +2092,6 @@ elf_cris_finish_dynamic_symbol (output_bfd, info, h, sym)
     {
       asection *splt;
       asection *sgotplt;
-      asection *sgot;
       asection *srela;
       bfd_vma got_base;
 
@@ -2130,13 +2101,19 @@ elf_cris_finish_dynamic_symbol (output_bfd, info, h, sym)
       bfd_byte *loc;
       bfd_boolean has_gotplt = gotplt_offset != 0;
 
-      /* Get the index in the procedure linkage table which
-        corresponds to this symbol.  This is the index of this symbol
-        in all the symbols for which we are making plt entries.  The
-        first entry in the procedure linkage table is reserved.  */
-      /* We have to count backwards here, and the result is only valid as
-        an index into .got.plt and its relocations.  FIXME: Constants...  */
-      bfd_vma gotplt_index = gotplt_offset/4 - 3;
+      /* Get the index in the .rela.plt relocations for the .got.plt
+        entry that corresponds to this symbol.
+        We have to count backwards here, and the result is only valid
+        as an index into .rela.plt.  We also have to undo the effect
+        of the R_CRIS_DTPMOD entry at .got index 3 (offset 12 into
+        .got.plt) for which gotplt_offset is adjusted, because while
+        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
+       = (htab->dtpmod_refcount != 0
+          ? gotplt_offset/4 - 2 - 3 : gotplt_offset/4 - 3);
 
       /* Get the offset into the .got table of the entry that corresponds
         to this function.  Note that we embed knowledge that "incoming"
@@ -2146,17 +2123,16 @@ elf_cris_finish_dynamic_symbol (output_bfd, info, h, sym)
       bfd_vma got_offset
        = (has_gotplt
           ? gotplt_offset
-          : h->got.offset + elf_cris_hash_table(info)->next_gotplt_entry);
+          : h->got.offset + htab->next_gotplt_entry);
 
       /* This symbol has an entry in the procedure linkage table.  Set it
         up.  */
 
       BFD_ASSERT (h->dynindx != -1);
 
-      splt = bfd_get_section_by_name (dynobj, ".plt");
-      sgot = bfd_get_section_by_name (dynobj, ".got");
-      sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
-      srela = bfd_get_section_by_name (dynobj, ".rela.plt");
+      splt = bfd_get_linker_section (dynobj, ".plt");
+      sgotplt = bfd_get_linker_section (dynobj, ".got.plt");
+      srela = bfd_get_linker_section (dynobj, ".rela.plt");
       BFD_ASSERT (splt != NULL && sgotplt != NULL
                  && (! has_gotplt || srela != NULL));
 
@@ -2186,7 +2162,7 @@ elf_cris_finish_dynamic_symbol (output_bfd, info, h, sym)
        {
          /* Fill in the offset to the reloc table.  */
          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);
 
          /* Fill in the offset to the first PLT entry, where to "jump".  */
@@ -2209,7 +2185,7 @@ elf_cris_finish_dynamic_symbol (output_bfd, info, h, sym)
                           + got_offset);
          rela.r_info = ELF32_R_INFO (h->dynindx, R_CRIS_JUMP_SLOT);
          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);
        }
 
@@ -2253,8 +2229,8 @@ elf_cris_finish_dynamic_symbol (output_bfd, info, h, sym)
 
       /* This symbol has an entry in the global offset table.  Set it up.  */
 
-      sgot = bfd_get_section_by_name (dynobj, ".got");
-      srela = bfd_get_section_by_name (dynobj, ".rela.got");
+      sgot = bfd_get_linker_section (dynobj, ".got");
+      srela = bfd_get_linker_section (dynobj, ".rela.got");
       BFD_ASSERT (sgot != NULL && srela != NULL);
 
       rela.r_offset = (sgot->output_section->vma
@@ -2299,8 +2275,7 @@ elf_cris_finish_dynamic_symbol (output_bfd, info, h, sym)
                  && (h->root.type == bfd_link_hash_defined
                      || h->root.type == bfd_link_hash_defweak));
 
-      s = bfd_get_section_by_name (h->root.u.def.section->owner,
-                                  ".rela.bss");
+      s = bfd_get_linker_section (dynobj, ".rela.bss");
       BFD_ASSERT (s != NULL);
 
       rela.r_offset = (h->root.u.def.value
@@ -2325,9 +2300,8 @@ elf_cris_finish_dynamic_symbol (output_bfd, info, h, sym)
    computed.  */
 
 static bfd_boolean
-elf_cris_finish_dynamic_sections (output_bfd, info)
-     bfd *output_bfd;
-     struct bfd_link_info *info;
+elf_cris_finish_dynamic_sections (bfd *output_bfd,
+                                 struct bfd_link_info *info)
 {
   bfd *dynobj;
   asection *sgot;
@@ -2335,16 +2309,16 @@ elf_cris_finish_dynamic_sections (output_bfd, info)
 
   dynobj = elf_hash_table (info)->dynobj;
 
-  sgot = bfd_get_section_by_name (dynobj, ".got.plt");
+  sgot = bfd_get_linker_section (dynobj, ".got.plt");
   BFD_ASSERT (sgot != NULL);
-  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+  sdyn = bfd_get_linker_section (dynobj, ".dynamic");
 
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       asection *splt;
       Elf32_External_Dyn *dyncon, *dynconend;
 
-      splt = bfd_get_section_by_name (dynobj, ".plt");
+      splt = bfd_get_linker_section (dynobj, ".plt");
       BFD_ASSERT (splt != NULL && sdyn != NULL);
 
       dyncon = (Elf32_External_Dyn *) sdyn->contents;
@@ -2498,6 +2472,7 @@ cris_elf_gc_sweep_hook (bfd *abfd,
                        asection *sec,
                        const Elf_Internal_Rela *relocs)
 {
+  struct elf_cris_link_hash_table * htab;
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_link_hash_entry **sym_hashes;
   bfd_signed_vma *local_got_refcounts;
@@ -2513,12 +2488,16 @@ cris_elf_gc_sweep_hook (bfd *abfd,
   if (dynobj == NULL)
     return TRUE;
 
+  htab = elf_cris_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (abfd);
   local_got_refcounts = elf_local_got_refcounts (abfd);
 
-  sgot = bfd_get_section_by_name (dynobj, ".got");
-  srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+  sgot = bfd_get_linker_section (dynobj, ".got");
+  srelgot = bfd_get_linker_section (dynobj, ".rela.got");
 
   relend = relocs + sec->reloc_count;
   for (rel = relocs; rel < relend; rel++)
@@ -2559,6 +2538,7 @@ cris_elf_gc_sweep_hook (bfd *abfd,
            : &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
@@ -2572,6 +2552,7 @@ cris_elf_gc_sweep_hook (bfd *abfd,
 
       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:
@@ -2622,6 +2603,9 @@ cris_elf_gc_sweep_hook (bfd *abfd,
          /* For local symbols, treat these like GOT relocs.  */
          if (h == NULL)
            goto local_got_reloc;
+         else
+           /* For global symbols, adjust the reloc-specific refcount.  */
+           elf_cris_hash_entry (h)->gotplt_refcount--;
          /* Fall through.  */
 
        case R_CRIS_32_PLT_GOTREL:
@@ -2630,10 +2614,14 @@ cris_elf_gc_sweep_hook (bfd *abfd,
            local_got_refcounts[-1]--;
          /* Fall through.  */
 
+       case R_CRIS_8:
+       case R_CRIS_16:
+       case R_CRIS_32:
        case R_CRIS_8_PCREL:
        case R_CRIS_16_PCREL:
        case R_CRIS_32_PCREL:
        case R_CRIS_32_PLT_PCREL:
+         /* Negate the increment we did in cris_elf_check_relocs.  */
          if (h != NULL)
            {
              if (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
@@ -2643,10 +2631,14 @@ cris_elf_gc_sweep_hook (bfd *abfd,
          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;
+         htab->dtpmod_refcount--;
+         if (htab->dtpmod_refcount == 0)
+           htab->next_gotplt_entry -= 8;
          BFD_ASSERT (local_got_refcounts != NULL);
          local_got_refcounts[-1]--;
          break;
@@ -2659,6 +2651,69 @@ cris_elf_gc_sweep_hook (bfd *abfd,
   return TRUE;
 }
 
+/* The elf_backend_plt_sym_val hook function.  */
+
+static bfd_vma
+cris_elf_plt_sym_val (bfd_vma i ATTRIBUTE_UNUSED, const asection *plt,
+                     const arelent *rel)
+{
+  bfd_size_type plt_entry_size;
+  bfd_size_type pltoffs;
+  bfd *abfd = plt->owner;
+
+  /* Same for CRIS and CRIS v32; see elf_cris_(|pic_)plt_entry(|_v32)[].  */
+  bfd_size_type plt_entry_got_offset = 2;
+  bfd_size_type plt_sec_size;
+  bfd_size_type got_vma_for_dyn;
+  asection *got;
+
+  /* FIXME: the .got section should be readily available also when
+     we're not linking.  */
+  if ((got = bfd_get_section_by_name (abfd, ".got")) == NULL)
+    return (bfd_vma) -1;
+
+  plt_sec_size =  bfd_section_size (plt->owner, plt);
+  plt_entry_size
+    = (bfd_get_mach (abfd) == bfd_mach_cris_v32
+       ? PLT_ENTRY_SIZE_V32 : PLT_ENTRY_SIZE);
+
+  /* Data in PLT is GOT-relative for DYN, but absolute for EXE.  */
+  got_vma_for_dyn = (abfd->flags & EXEC_P) ? 0 : got->vma;
+
+  /* Because we can have merged GOT entries; a single .got entry for
+     both GOT and the PLT part of the GOT (.got.plt), the index of the
+     reloc in .rela.plt is not the same as the index in the PLT.
+     Instead, we have to hunt down the GOT offset in the PLT that
+     corresponds to that of this reloc.  Unfortunately, we will only
+     be called for the .rela.plt relocs, so we'll miss synthetic
+     symbols for .plt entries with merged GOT entries.  (FIXME:
+     fixable by providing our own bfd_elf32_get_synthetic_symtab.
+     Doesn't seem worthwile at time of this writing.)  FIXME: we've
+     gone from O(1) to O(N) (N number of PLT entries) for finding each
+     PLT address.  Shouldn't matter in practice though.  */
+
+  for (pltoffs = plt_entry_size;
+       pltoffs < plt_sec_size;
+       pltoffs += plt_entry_size)
+    {
+      bfd_size_type got_offset;
+      bfd_byte gotoffs_raw[4];
+      
+      if (!bfd_get_section_contents (abfd, (asection *) plt, gotoffs_raw,
+                                    pltoffs + plt_entry_got_offset,
+                                    sizeof (gotoffs_raw)))
+       return (bfd_vma) -1;
+
+      got_offset = bfd_get_32 (abfd, gotoffs_raw);
+      if (got_offset + got_vma_for_dyn == rel->address)
+       return plt->vma + pltoffs;
+    }
+
+  /* While it's tempting to BFD_ASSERT that we shouldn't get here,
+     that'd not be graceful behavior for invalid input.  */
+  return (bfd_vma) -1;
+}
+
 /* Make sure we emit a GOT entry if the symbol was supposed to have a PLT
    entry but we found we will not create any.  Called when we find we will
    not have any PLT for this symbol, by for example
@@ -2667,14 +2722,14 @@ cris_elf_gc_sweep_hook (bfd *abfd,
    created (we're only linking static objects).  */
 
 static bfd_boolean
-elf_cris_adjust_gotplt_to_got (h, p)
-     struct elf_cris_link_hash_entry *h;
-     PTR p;
+elf_cris_adjust_gotplt_to_got (struct elf_cris_link_hash_entry *h, void * p)
 {
   struct bfd_link_info *info = (struct bfd_link_info *) p;
 
-  if (h->root.root.type == bfd_link_hash_warning)
-    h = (struct elf_cris_link_hash_entry *) h->root.root.u.i.link;
+  /* A GOTPLT reloc, when activated, is supposed to be included into
+     the PLT refcount.  */
+  BFD_ASSERT (h->gotplt_refcount == 0
+             || h->gotplt_refcount <= h->root.plt.refcount);
 
   /* If nobody wanted a GOTPLT with this symbol, we're done.  */
   if (h->gotplt_refcount <= 0)
@@ -2697,8 +2752,8 @@ elf_cris_adjust_gotplt_to_got (h, p)
       asection *srelgot;
 
       BFD_ASSERT (dynobj != NULL);
-      sgot = bfd_get_section_by_name (dynobj, ".got");
-      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+      sgot = bfd_get_linker_section (dynobj, ".got");
+      srelgot = bfd_get_linker_section (dynobj, ".rela.got");
 
       /* Put accurate refcounts there.  */
       h->root.got.refcount += h->gotplt_refcount;
@@ -2745,9 +2800,7 @@ elf_cris_adjust_gotplt_to_got (h, p)
    elf_cris_hide_symbol.  */
 
 static bfd_boolean
-elf_cris_try_fold_plt_to_got (h, p)
-     struct elf_cris_link_hash_entry *h;
-     PTR p;
+elf_cris_try_fold_plt_to_got (struct elf_cris_link_hash_entry *h, void * p)
 {
   struct bfd_link_info *info = (struct bfd_link_info *) p;
 
@@ -2779,10 +2832,9 @@ elf_cris_try_fold_plt_to_got (h, p)
    entry.  */
 
 static void
-elf_cris_hide_symbol (info, h, force_local)
-     struct bfd_link_info *info;
-     struct elf_link_hash_entry *h;
-     bfd_boolean force_local;
+elf_cris_hide_symbol (struct bfd_link_info *info,
+                     struct elf_link_hash_entry *h,
+                     bfd_boolean force_local)
 {
   elf_cris_adjust_gotplt_to_got ((struct elf_cris_link_hash_entry *) h, info);
 
@@ -2796,14 +2848,18 @@ elf_cris_hide_symbol (info, h, force_local)
    understand.  */
 
 static bfd_boolean
-elf_cris_adjust_dynamic_symbol (info, h)
-     struct bfd_link_info *info;
-     struct elf_link_hash_entry *h;
+elf_cris_adjust_dynamic_symbol (struct bfd_link_info *info,
+                               struct elf_link_hash_entry *h)
 {
+  struct elf_cris_link_hash_table * htab;
   bfd *dynobj;
   asection *s;
   bfd_size_type plt_entry_size;
 
+  htab = elf_cris_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
   dynobj = elf_hash_table (info)->dynobj;
 
   /* Make sure we know what is going on here.  */
@@ -2872,7 +2928,7 @@ elf_cris_adjust_dynamic_symbol (info, h)
            return FALSE;
        }
 
-      s = bfd_get_section_by_name (dynobj, ".plt");
+      s = bfd_get_linker_section (dynobj, ".plt");
       BFD_ASSERT (s != NULL);
 
       /* If this is the first .plt entry, make room for the special
@@ -2928,16 +2984,16 @@ elf_cris_adjust_dynamic_symbol (info, h)
       /* We also need to make an entry in the .got.plt section, which
         will be placed in the .got section by the linker script.  */
       ((struct elf_cris_link_hash_entry *) h)->gotplt_offset
-       = elf_cris_hash_table (info)->next_gotplt_entry;
-      elf_cris_hash_table (info)->next_gotplt_entry += 4;
+       = htab->next_gotplt_entry;
+      htab->next_gotplt_entry += 4;
 
-      s = bfd_get_section_by_name (dynobj, ".got.plt");
+      s = bfd_get_linker_section (dynobj, ".got.plt");
       BFD_ASSERT (s != NULL);
       s->size += 4;
 
       /* We also need to make an entry in the .rela.plt section.  */
 
-      s = bfd_get_section_by_name (dynobj, ".rela.plt");
+      s = bfd_get_linker_section (dynobj, ".rela.plt");
       BFD_ASSERT (s != NULL);
       s->size += sizeof (Elf32_External_Rela);
 
@@ -2975,13 +3031,6 @@ elf_cris_adjust_dynamic_symbol (info, h)
   if (!h->non_got_ref)
     return TRUE;
 
-  if (h->size == 0)
-    {
-      (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"),
-                            h->root.root.string);
-      return TRUE;
-    }
-
   /* We must allocate the symbol in our .dynbss section, which will
      become part of the .bss section of the executable.  There will be
      an entry for this symbol in the .dynsym section.  The dynamic
@@ -2992,18 +3041,18 @@ elf_cris_adjust_dynamic_symbol (info, h)
      both the dynamic object and the regular object will refer to the
      same memory location for the variable.  */
 
-  s = bfd_get_section_by_name (dynobj, ".dynbss");
+  s = bfd_get_linker_section (dynobj, ".dynbss");
   BFD_ASSERT (s != NULL);
 
   /* We must generate a R_CRIS_COPY reloc to tell the dynamic linker to
      copy the initial value out of the dynamic object and into the
      runtime process image.  We need to remember the offset into the
      .rela.bss section we are going to use.  */
-  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
+  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
     {
       asection *srel;
 
-      srel = bfd_get_section_by_name (dynobj, ".rela.bss");
+      srel = bfd_get_linker_section (dynobj, ".rela.bss");
       BFD_ASSERT (srel != NULL);
       srel->size += sizeof (Elf32_External_Rela);
       h->needs_copy = 1;
@@ -3012,15 +3061,78 @@ elf_cris_adjust_dynamic_symbol (info, h)
   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->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)
+  if (eind->pcrel_relocs_copied != NULL)
+    {
+      if (edir->pcrel_relocs_copied != NULL)
+       {
+         struct elf_cris_pcrel_relocs_copied **pp;
+         struct elf_cris_pcrel_relocs_copied *p;
+
+         /* Add reloc counts against the indirect sym to the direct sym
+            list.  Merge any entries against the same section.  */
+         for (pp = &eind->pcrel_relocs_copied; *pp != NULL;)
+           {
+             struct elf_cris_pcrel_relocs_copied *q;
+             p = *pp;
+             for (q = edir->pcrel_relocs_copied; q != NULL; q = q->next)
+               if (q->section == p->section)
+                 {
+                   q->count += p->count;
+                   *pp = p->next;
+                   break;
+                 }
+             if (q == NULL)
+               pp = &p->next;
+           }
+         *pp = edir->pcrel_relocs_copied;
+       }
+      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.  */
 
 static bfd_boolean
-cris_elf_check_relocs (abfd, info, sec, relocs)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     asection *sec;
-     const Elf_Internal_Rela *relocs;
+cris_elf_check_relocs (bfd *abfd,
+                      struct bfd_link_info *info,
+                      asection *sec,
+                      const Elf_Internal_Rela *relocs)
 {
+  struct elf_cris_link_hash_table * htab;
   bfd *dynobj;
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_link_hash_entry **sym_hashes;
@@ -3034,6 +3146,10 @@ cris_elf_check_relocs (abfd, info, sec, relocs)
   if (info->relocatable)
     return TRUE;
 
+  htab = elf_cris_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
   dynobj = elf_hash_table (info)->dynobj;
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (abfd);
@@ -3072,15 +3188,26 @@ cris_elf_check_relocs (abfd, info, sec, relocs)
         on the first input bfd we found that contained dynamic relocs.  */
       switch (r_type)
        {
-       case R_CRIS_16_DTPREL:
        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++;
+         if (htab->dtpmod_refcount == 0)
+           htab->next_gotplt_entry += 8;
+
+         htab->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:
@@ -3116,7 +3243,7 @@ cris_elf_check_relocs (abfd, info, sec, relocs)
            }
 
          if (sgot == NULL)
-           sgot = bfd_get_section_by_name (dynobj, ".got");
+           sgot = bfd_get_linker_section (dynobj, ".got");
 
          if (local_got_refcounts == NULL)
            {
@@ -3154,6 +3281,7 @@ cris_elf_check_relocs (abfd, info, sec, relocs)
            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:
@@ -3175,17 +3303,15 @@ cris_elf_check_relocs (abfd, info, sec, relocs)
          if (srelgot == NULL
              && (h != NULL || info->shared))
            {
-             srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+             srelgot = bfd_get_linker_section (dynobj, ".rela.got");
              if (srelgot == NULL)
                {
-                 srelgot = bfd_make_section_with_flags (dynobj,
-                                                        ".rela.got",
-                                                        (SEC_ALLOC
-                                                         | SEC_LOAD
-                                                         | SEC_HAS_CONTENTS
-                                                         | SEC_IN_MEMORY
-                                                         | SEC_LINKER_CREATED
-                                                         | SEC_READONLY));
+                 flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
+                                   | SEC_IN_MEMORY | SEC_LINKER_CREATED
+                                   | SEC_READONLY);
+                 srelgot = bfd_make_section_anyway_with_flags (dynobj,
+                                                               ".rela.got",
+                                                               flags);
                  if (srelgot == NULL
                      || !bfd_set_section_alignment (dynobj, srelgot, 2))
                    return FALSE;
@@ -3200,6 +3326,7 @@ cris_elf_check_relocs (abfd, info, sec, relocs)
       /* Warn and error for invalid input.  */
       switch (r_type)
        {
+       case R_CRIS_32_IE:
        case R_CRIS_32_TPREL:
        case R_CRIS_16_TPREL:
        case R_CRIS_32_GD:
@@ -3237,11 +3364,12 @@ cris_elf_check_relocs (abfd, info, sec, relocs)
             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 two relocs also require that a DSO is of type
+         /* 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)
@@ -3272,6 +3400,7 @@ cris_elf_check_relocs (abfd, info, sec, relocs)
             GOT entry for it, so handle it like a GOT reloc.  */
          /* Fall through.  */
 
+       case R_CRIS_32_IE:
        case R_CRIS_32_GD:
        case R_CRIS_16_GOT_GD:
        case R_CRIS_32_GOT_GD:
@@ -3322,6 +3451,7 @@ cris_elf_check_relocs (abfd, info, sec, relocs)
                  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)
@@ -3423,6 +3553,12 @@ cris_elf_check_relocs (abfd, info, sec, relocs)
                 sec,
                 cris_elf_howto_table[r_type].name);
            }
+
+         /* We don't need to handle relocs into sections not going into
+            the "real" output.  */
+         if ((sec->flags & SEC_ALLOC) == 0)
+           break;
+
          if (h != NULL)
            {
              h->non_got_ref = 1;
@@ -3452,11 +3588,6 @@ cris_elf_check_relocs (abfd, info, sec, relocs)
          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)
@@ -3551,7 +3682,7 @@ cris_elf_check_relocs (abfd, info, sec, relocs)
            eh = elf_cris_hash_entry (h);
 
            for (p = eh->pcrel_relocs_copied; p != NULL; p = p->next)
-             if (p->section == sreloc)
+             if (p->section == sec)
                break;
 
            if (p == NULL)
@@ -3562,7 +3693,7 @@ cris_elf_check_relocs (abfd, info, sec, relocs)
                  return FALSE;
                p->next = eh->pcrel_relocs_copied;
                eh->pcrel_relocs_copied = p;
-               p->section = sreloc;
+               p->section = sec;
                p->count = 0;
                p->r_type = r_type;
              }
@@ -3605,15 +3736,19 @@ cris_elf_check_relocs (abfd, info, sec, relocs)
 /* Set the sizes of the dynamic sections.  */
 
 static bfd_boolean
-elf_cris_size_dynamic_sections (output_bfd, info)
-     bfd *output_bfd ATTRIBUTE_UNUSED;
-     struct bfd_link_info *info;
+elf_cris_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+                               struct bfd_link_info *info)
 {
+  struct elf_cris_link_hash_table * htab;
   bfd *dynobj;
   asection *s;
   bfd_boolean plt;
   bfd_boolean relocs;
 
+  htab = elf_cris_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
   dynobj = elf_hash_table (info)->dynobj;
   BFD_ASSERT (dynobj != NULL);
 
@@ -3622,7 +3757,7 @@ elf_cris_size_dynamic_sections (output_bfd, info)
       /* Set the contents of the .interp section to the interpreter.  */
       if (info->executable)
        {
-         s = bfd_get_section_by_name (dynobj, ".interp");
+         s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
          s->size = sizeof ELF_DYNAMIC_INTERPRETER;
          s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
@@ -3631,16 +3766,15 @@ elf_cris_size_dynamic_sections (output_bfd, info)
   else
     {
       /* Adjust all expected GOTPLT uses to use a GOT entry instead.  */
-      elf_cris_link_hash_traverse (elf_cris_hash_table (info),
-                                  elf_cris_adjust_gotplt_to_got,
-                                  (PTR) info);
+      elf_cris_link_hash_traverse (htab, elf_cris_adjust_gotplt_to_got,
+                                  info);
 
       /* We may have created entries in the .rela.got section.
         However, if we are not creating the dynamic sections, we will
         not actually use these entries.  Reset the size of .rela.got,
         which will cause it to get stripped from the output file
         below.  */
-      s = bfd_get_section_by_name (dynobj, ".rela.got");
+      s = bfd_get_linker_section (dynobj, ".rela.got");
       if (s != NULL)
        s->size = 0;
     }
@@ -3653,13 +3787,13 @@ elf_cris_size_dynamic_sections (output_bfd, info)
      visibility changes.  For programs, we discard space for relocs for
      symbols not referenced by any dynamic object.  */
   if (info->shared)
-    elf_cris_link_hash_traverse (elf_cris_hash_table (info),
+    elf_cris_link_hash_traverse (htab,
                                 elf_cris_discard_excess_dso_dynamics,
-                                (PTR) info);
+                                info);
   else
-    elf_cris_link_hash_traverse (elf_cris_hash_table (info),
+    elf_cris_link_hash_traverse (htab,
                                 elf_cris_discard_excess_program_dynamics,
-                                (PTR) info);
+                                info);
 
   /* The check_relocs and adjust_dynamic_symbol entry points have
      determined the sizes of the various dynamic sections.  Allocate
@@ -3687,13 +3821,13 @@ elf_cris_size_dynamic_sections (output_bfd, info)
          /* 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
+         s->size += htab->dtpmod_refcount != 0
            ? 8 : 0;
        }
       else if (CONST_STRNEQ (name, ".rela"))
        {
          if (strcmp (name, ".rela.got") == 0
-             && elf_cris_hash_table (info)->dtpmod_refcount != 0
+             && htab->dtpmod_refcount != 0
              && info->shared)
            s->size += sizeof (Elf32_External_Rela);
 
@@ -3799,16 +3933,12 @@ elf_cris_size_dynamic_sections (output_bfd, info)
    relocate_section routine.  */
 
 static bfd_boolean
-elf_cris_discard_excess_dso_dynamics (h, inf)
-     struct elf_cris_link_hash_entry *h;
-     PTR inf;
+elf_cris_discard_excess_dso_dynamics (struct elf_cris_link_hash_entry *h,
+                                     void * inf)
 {
   struct elf_cris_pcrel_relocs_copied *s;
   struct bfd_link_info *info = (struct bfd_link_info *) inf;
 
-  if (h->root.root.type == bfd_link_hash_warning)
-    h = (struct elf_cris_link_hash_entry *) h->root.root.u.i.link;
-
   /* If a symbol has been forced local or we have found a regular
      definition for the symbolic link case, then we won't be needing
      any relocs.  */
@@ -3817,8 +3947,14 @@ elf_cris_discard_excess_dso_dynamics (h, inf)
          || info->symbolic))
     {
       for (s = h->pcrel_relocs_copied; s != NULL; s = s->next)
-       s->section->size -= s->count * sizeof (Elf32_External_Rela);
-
+       {
+         asection *sreloc
+           = _bfd_elf_get_dynamic_reloc_section (elf_hash_table (info)
+                                                 ->dynobj,
+                                                 s->section,
+                                                 /*rela?*/ TRUE);
+         sreloc->size -= s->count * sizeof (Elf32_External_Rela);
+       }
       return TRUE;
     }
 
@@ -3829,21 +3965,20 @@ elf_cris_discard_excess_dso_dynamics (h, inf)
      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;
-    }
+    if ((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;
 }
@@ -3853,15 +3988,11 @@ elf_cris_discard_excess_dso_dynamics (h, inf)
    in the .got, but which we found we do not have to resolve at run-time.  */
 
 static bfd_boolean
-elf_cris_discard_excess_program_dynamics (h, inf)
-     struct elf_cris_link_hash_entry *h;
-     PTR inf;
+elf_cris_discard_excess_program_dynamics (struct elf_cris_link_hash_entry *h,
+                                         void * inf)
 {
   struct bfd_link_info *info = (struct bfd_link_info *) inf;
 
-  if (h->root.root.type == bfd_link_hash_warning)
-    h = (struct elf_cris_link_hash_entry *) h->root.root.u.i.link;
-
   /* If we're not creating a shared library and have a symbol which is
      referred to by .got references, but the symbol is defined locally,
      (or rather, not defined by a DSO) then lose the reloc for the .got
@@ -3881,7 +4012,7 @@ elf_cris_discard_excess_program_dynamics (h, inf)
 
          BFD_ASSERT (dynobj != NULL);
 
-         srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+         srelgot = bfd_get_linker_section (dynobj, ".rela.got");
 
          BFD_ASSERT (srelgot != NULL);
 
@@ -3911,8 +4042,7 @@ elf_cris_discard_excess_program_dynamics (h, inf)
    underscores on symbols.  */
 
 static bfd_boolean
-cris_elf_object_p (abfd)
-     bfd *abfd;
+cris_elf_object_p (bfd *abfd)
 {
   if (! cris_elf_set_mach_from_flags (abfd, elf_elfheader (abfd)->e_flags))
     return FALSE;
@@ -3927,9 +4057,8 @@ cris_elf_object_p (abfd)
    flags from mach type.  */
 
 static void
-cris_elf_final_write_processing (abfd, linker)
-     bfd *abfd;
-     bfd_boolean linker ATTRIBUTE_UNUSED;
+cris_elf_final_write_processing (bfd *abfd,
+                                bfd_boolean linker ATTRIBUTE_UNUSED)
 {
   unsigned long e_flags = elf_elfheader (abfd)->e_flags;
 
@@ -3962,9 +4091,8 @@ cris_elf_final_write_processing (abfd, linker)
 /* Set the mach type from e_flags value.  */
 
 static bfd_boolean
-cris_elf_set_mach_from_flags (abfd, flags)
-     bfd *abfd;
-     unsigned long flags;
+cris_elf_set_mach_from_flags (bfd *abfd,
+                             unsigned long flags)
 {
   switch (flags & EF_CRIS_VARIANT_MASK)
     {
@@ -3994,9 +4122,7 @@ cris_elf_set_mach_from_flags (abfd, flags)
 /* Display the flags field.  */
 
 static bfd_boolean
-cris_elf_print_private_bfd_data (abfd, ptr)
-     bfd *abfd;
-     PTR ptr;
+cris_elf_print_private_bfd_data (bfd *abfd, void * ptr)
 {
   FILE *file = (FILE *) ptr;
 
@@ -4022,9 +4148,7 @@ cris_elf_print_private_bfd_data (abfd, ptr)
 /* Don't mix files with and without a leading underscore.  */
 
 static bfd_boolean
-cris_elf_merge_private_bfd_data (ibfd, obfd)
-     bfd *ibfd;
-     bfd *obfd;
+cris_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
 {
   int imach, omach;
 
@@ -4101,9 +4225,7 @@ cris_elf_merge_private_bfd_data (ibfd, obfd)
 /* Do side-effects of e_flags copying to obfd.  */
 
 static bfd_boolean
-cris_elf_copy_private_bfd_data (ibfd, obfd)
-     bfd *ibfd;
-     bfd *obfd;
+cris_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
 {
   /* Call the base function.  */
   if (!_bfd_elf_copy_private_bfd_data (ibfd, obfd))
@@ -4122,8 +4244,7 @@ cris_elf_copy_private_bfd_data (ibfd, obfd)
 }
 
 static enum elf_reloc_type_class
-elf_cris_reloc_type_class (rela)
-     const Elf_Internal_Rela *rela;
+elf_cris_reloc_type_class (const Elf_Internal_Rela *rela)
 {
   enum elf_cris_reloc_type r_type = ELF32_R_TYPE (rela->r_info);
   switch (r_type)
@@ -4202,6 +4323,7 @@ elf_cris_got_elt_size (bfd *abfd ATTRIBUTE_UNUSED,
 }
 \f
 #define ELF_ARCH               bfd_arch_cris
+#define ELF_TARGET_ID          CRIS_ELF_DATA
 #define ELF_MACHINE_CODE       EM_CRIS
 #define ELF_MAXPAGESIZE                0x2000
 
@@ -4214,6 +4336,7 @@ elf_cris_got_elt_size (bfd *abfd ATTRIBUTE_UNUSED,
 #define elf_backend_relocate_section           cris_elf_relocate_section
 #define elf_backend_gc_mark_hook               cris_elf_gc_mark_hook
 #define elf_backend_gc_sweep_hook              cris_elf_gc_sweep_hook
+#define elf_backend_plt_sym_val                        cris_elf_plt_sym_val
 #define elf_backend_check_relocs                cris_elf_check_relocs
 #define elf_backend_grok_prstatus              cris_elf_grok_prstatus
 #define elf_backend_grok_psinfo                        cris_elf_grok_psinfo
@@ -4238,6 +4361,8 @@ elf_cris_got_elt_size (bfd *abfd ATTRIBUTE_UNUSED,
        elf_cris_link_hash_table_create
 #define elf_backend_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 \
        elf_cris_size_dynamic_sections
 #define elf_backend_init_index_section         _bfd_elf_init_1_index_section
This page took 0.046988 seconds and 4 git commands to generate.