* gdb.arch/i386-sse.exp, gdb.arch/i386-sse.c: New tests.
[deliverable/binutils-gdb.git] / bfd / elf32-frv.c
index 78a4a4c129f656845b4c274abcc07b925ed6cfd8..cf3195acd7b49c906db2a8d666039400a794c8c4 100644 (file)
@@ -1,5 +1,5 @@
 /* FRV-specific support for 32-bit ELF.
-   Copyright 2002, 2003 Free Software Foundation, Inc.
+   Copyright 2002, 2003, 2004 Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "elf/frv.h"
+#include "elf/dwarf2.h"
 #include "hashtab.h"
 
 /* Forward declarations.  */
@@ -51,7 +52,7 @@ static bfd_boolean elf32_frv_relocate_section
   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
           Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
 static bfd_boolean elf32_frv_add_symbol_hook
-  PARAMS (( bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
+  PARAMS (( bfd *, struct bfd_link_info *, Elf_Internal_Sym *,
            const char **, flagword *, asection **, bfd_vma *));
 static bfd_reloc_status_type frv_final_link_relocate
   PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
@@ -582,10 +583,12 @@ static const struct frv_reloc_map frv_reloc_map [] =
 };
 #endif
 
+extern const bfd_target bfd_elf32_frvfdpic_vec;
+#define IS_FDPIC(bfd) ((bfd)->xvec == &bfd_elf32_frvfdpic_vec)
 
 /* An extension of the elf hash table data structure, containing some
    additional FRV-specific data.  */
-struct frv_elf_link_hash_table
+struct frvfdpic_elf_link_hash_table
 {
   struct elf_link_hash_table elf;
 
@@ -611,33 +614,33 @@ struct frv_elf_link_hash_table
 
 /* Get the FRV ELF linker hash table from a link_info structure.  */
 
-#define frv_hash_table(info) \
-  ((struct frv_elf_link_hash_table *) ((info)->hash))
-
-#define frv_got_section(info) \
-  (frv_hash_table (info)->sgot)
-#define frv_gotrel_section(info) \
-  (frv_hash_table (info)->sgotrel)
-#define frv_gotfixup_section(info) \
-  (frv_hash_table (info)->sgotfixup)
-#define frv_plt_section(info) \
-  (frv_hash_table (info)->splt)
-#define frv_pltrel_section(info) \
-  (frv_hash_table (info)->spltrel)
-#define frv_relocs_info(info) \
-  (frv_hash_table (info)->relocs_info)
-#define frv_got_initial_offset(info) \
-  (frv_hash_table (info)->got0)
-#define frv_plt_initial_offset(info) \
-  (frv_hash_table (info)->plt0)
+#define frvfdpic_hash_table(info) \
+  ((struct frvfdpic_elf_link_hash_table *) ((info)->hash))
+
+#define frvfdpic_got_section(info) \
+  (frvfdpic_hash_table (info)->sgot)
+#define frvfdpic_gotrel_section(info) \
+  (frvfdpic_hash_table (info)->sgotrel)
+#define frvfdpic_gotfixup_section(info) \
+  (frvfdpic_hash_table (info)->sgotfixup)
+#define frvfdpic_plt_section(info) \
+  (frvfdpic_hash_table (info)->splt)
+#define frvfdpic_pltrel_section(info) \
+  (frvfdpic_hash_table (info)->spltrel)
+#define frvfdpic_relocs_info(info) \
+  (frvfdpic_hash_table (info)->relocs_info)
+#define frvfdpic_got_initial_offset(info) \
+  (frvfdpic_hash_table (info)->got0)
+#define frvfdpic_plt_initial_offset(info) \
+  (frvfdpic_hash_table (info)->plt0)
 
 /* Create an FRV ELF linker hash table.  */
 
 static struct bfd_link_hash_table *
-frv_elf_link_hash_table_create (bfd *abfd)
+frvfdpic_elf_link_hash_table_create (bfd *abfd)
 {
-  struct frv_elf_link_hash_table *ret;
-  bfd_size_type amt = sizeof (struct frv_elf_link_hash_table);
+  struct frvfdpic_elf_link_hash_table *ret;
+  bfd_size_type amt = sizeof (struct frvfdpic_elf_link_hash_table);
 
   ret = bfd_zalloc (abfd, amt);
   if (ret == NULL)
@@ -656,7 +659,7 @@ frv_elf_link_hash_table_create (bfd *abfd)
 /* Decide whether a reference to a symbol can be resolved locally or
    not.  If the symbol is protected, we want the local address, but
    its function descriptor must be assigned by the dynamic linker.  */
-#define FRV_SYM_LOCAL(INFO, H) \
+#define FRVFDPIC_SYM_LOCAL(INFO, H) \
   (_bfd_elf_symbol_refs_local_p ((H), (INFO), 1) \
    || ! elf_hash_table (INFO)->dynamic_sections_created \
    || (/* The condition below is an ugly hack to get .scommon data to
@@ -669,13 +672,13 @@ frv_elf_link_hash_table_create (bfd *abfd)
        || (H)->root.type == bfd_link_hash_defweak) \
        && (H)->root.u.def.section->output_section \
        && ((H)->root.u.def.section->flags & SEC_LINKER_CREATED)))
-#define FRV_FUNCDESC_LOCAL(INFO, H) \
+#define FRVFDPIC_FUNCDESC_LOCAL(INFO, H) \
   ((H)->dynindx == -1 || ! elf_hash_table (INFO)->dynamic_sections_created)
 
 /* This structure collects information on what kind of GOT, PLT or
    function descriptors are required by relocations that reference a
    certain symbol.  */
-struct frv_pic_relocs_info
+struct frvfdpic_relocs_info
 {
   /* The index of the symbol, as stored in the relocation r_info, if
      we have a local symbol; -1 otherwise.  */
@@ -726,17 +729,17 @@ struct frv_pic_relocs_info
   unsigned sym:1;
   /* Whether we need a PLT entry for a symbol.  Should be implied by
      something like:
-     (call && symndx == -1 && ! FRV_SYM_LOCAL (info, d.h))  */
+     (call && symndx == -1 && ! FRVFDPIC_SYM_LOCAL (info, d.h))  */
   unsigned plt:1;
   /* Whether a function descriptor should be created in this link unit
      for symbol+addend.  Should be implied by something like:
      (plt || fdgotoff12 || fdgotofflos || fdgotofflohi
       || ((fd || fdgot12 || fdgotlos || fdgothilo)
-          && (symndx != -1 || FRV_FUNCDESC_LOCAL (info, d.h))))  */
+          && (symndx != -1 || FRVFDPIC_FUNCDESC_LOCAL (info, d.h))))  */
   unsigned privfd:1;
   /* Whether a lazy PLT entry is needed for this symbol+addend.
      Should be implied by something like:
-     (privfd && symndx == -1 && ! FRV_SYM_LOCAL (info, d.h)
+     (privfd && symndx == -1 && ! FRVFDPIC_SYM_LOCAL (info, d.h)
       && ! (info->flags & DF_BIND_NOW))  */
   unsigned lazyplt:1;
   /* Whether we've already emitted GOT relocations and PLT entries as
@@ -747,6 +750,10 @@ struct frv_pic_relocs_info
      relocations referencing the symbol.  */
   unsigned relocs32, relocsfd, relocsfdv;
 
+  /* The number of .rofixups entries and dynamic relocations allocated
+     for this symbol, minus any that might have already been used.  */
+  unsigned fixups, dynrelocs;
+
   /* The offsets of the GOT entries assigned to symbol+addend, to the
      function descriptor's address, and to a function descriptor,
      respectively.  Should be zero if unassigned.  The offsets are
@@ -759,24 +766,24 @@ struct frv_pic_relocs_info
   bfd_vma plt_entry, lzplt_entry;
 };
 
-/* Compute a hash with the key fields of an frv_pic_relocs_info entry.  */
+/* Compute a hash with the key fields of an frvfdpic_relocs_info entry.  */
 static hashval_t
-frv_pic_relocs_info_hash (const void *entry_)
+frvfdpic_relocs_info_hash (const void *entry_)
 {
-  const struct frv_pic_relocs_info *entry = entry_;
+  const struct frvfdpic_relocs_info *entry = entry_;
 
   return (entry->symndx == -1
          ? entry->d.h->root.root.hash
          : entry->symndx + entry->d.abfd->id * 257) + entry->addend;
 }
 
-/* Test whether the key fields of two frv_pic_relocs_info entries are
+/* Test whether the key fields of two frvfdpic_relocs_info entries are
    identical.  */
 static int
-frv_pic_relocs_info_eq (const void *entry1, const void *entry2)
+frvfdpic_relocs_info_eq (const void *entry1, const void *entry2)
 {
-  const struct frv_pic_relocs_info *e1 = entry1;
-  const struct frv_pic_relocs_info *e2 = entry2;
+  const struct frvfdpic_relocs_info *e1 = entry1;
+  const struct frvfdpic_relocs_info *e2 = entry2;
 
   return e1->symndx == e2->symndx && e1->addend == e2->addend
     && (e1->symndx == -1 ? e1->d.h == e2->d.h : e1->d.abfd == e2->d.abfd);
@@ -785,13 +792,17 @@ frv_pic_relocs_info_eq (const void *entry1, const void *entry2)
 /* Find or create an entry in a hash table HT that matches the key
    fields of the given ENTRY.  If it's not found, memory for a new
    entry is allocated in ABFD's obstack.  */
-static struct frv_pic_relocs_info *
-frv_pic_relocs_info_find (struct htab *ht,
-                         bfd *abfd,
-                         const struct frv_pic_relocs_info *entry)
+static struct frvfdpic_relocs_info *
+frvfdpic_relocs_info_find (struct htab *ht,
+                          bfd *abfd,
+                          const struct frvfdpic_relocs_info *entry,
+                          enum insert_option insert)
 {
-  struct frv_pic_relocs_info **loc =
-    (struct frv_pic_relocs_info **) htab_find_slot (ht, entry, INSERT);
+  struct frvfdpic_relocs_info **loc =
+    (struct frvfdpic_relocs_info **) htab_find_slot (ht, entry, insert);
+
+  if (! loc)
+    return NULL;
 
   if (*loc)
     return *loc;
@@ -813,37 +824,91 @@ frv_pic_relocs_info_find (struct htab *ht,
 /* Obtain the address of the entry in HT associated with H's symbol +
    addend, creating a new entry if none existed.  ABFD is only used
    for memory allocation purposes.  */
-inline static struct frv_pic_relocs_info *
-frv_pic_relocs_info_for_global (struct htab *ht,
-                               bfd *abfd,
-                               struct elf_link_hash_entry *h,
-                               bfd_vma addend)
+inline static struct frvfdpic_relocs_info *
+frvfdpic_relocs_info_for_global (struct htab *ht,
+                                bfd *abfd,
+                                struct elf_link_hash_entry *h,
+                                bfd_vma addend,
+                                enum insert_option insert)
 {
-  struct frv_pic_relocs_info entry;
+  struct frvfdpic_relocs_info entry;
 
   entry.symndx = -1;
   entry.d.h = h;
   entry.addend = addend;
 
-  return frv_pic_relocs_info_find (ht, abfd, &entry);
+  return frvfdpic_relocs_info_find (ht, abfd, &entry, insert);
 }
 
 /* Obtain the address of the entry in HT associated with the SYMNDXth
    local symbol of the input bfd ABFD, plus the addend, creating a new
    entry if none existed.  */  
-inline static struct frv_pic_relocs_info *
-frv_pic_relocs_info_for_local (struct htab *ht,
-                              bfd *abfd,
-                              long symndx,
-                              bfd_vma addend)
+inline static struct frvfdpic_relocs_info *
+frvfdpic_relocs_info_for_local (struct htab *ht,
+                               bfd *abfd,
+                               long symndx,
+                               bfd_vma addend,
+                               enum insert_option insert)
 {
-  struct frv_pic_relocs_info entry;
+  struct frvfdpic_relocs_info entry;
 
   entry.symndx = symndx;
   entry.d.abfd = abfd;
   entry.addend = addend;
 
-  return frv_pic_relocs_info_find (ht, abfd, &entry);
+  return frvfdpic_relocs_info_find (ht, abfd, &entry, insert);
+}
+
+/* Merge fields set by check_relocs() of two entries that end up being
+   mapped to the same (presumably global) symbol.  */
+
+inline static void
+frvfdpic_pic_merge_early_relocs_info (struct frvfdpic_relocs_info *e2,
+                                     struct frvfdpic_relocs_info const *e1)
+{
+  e2->got12 |= e1->got12;
+  e2->gotlos |= e1->gotlos;
+  e2->gothilo |= e1->gothilo;
+  e2->fd |= e1->fd;
+  e2->fdgot12 |= e1->fdgot12;
+  e2->fdgotlos |= e1->fdgotlos;
+  e2->fdgothilo |= e1->fdgothilo;
+  e2->fdgoff12 |= e1->fdgoff12;
+  e2->fdgofflos |= e1->fdgofflos;
+  e2->fdgoffhilo |= e1->fdgoffhilo;
+  e2->gotoff |= e1->gotoff;
+  e2->call |= e1->call;
+  e2->sym |= e1->sym;
+
+#if 0
+  /* These are set in _frvfdpic_count_got_plt_entries() or later, and this
+     function is only called in _frvfdpic_resolve_final_relocs_info(), that
+     runs just before it, so we don't have to worry about the fields
+     below.  */
+
+  e2->plt |= e1->plt;
+  e2->privfd |= e1->privfd;
+  e2->lazyplt |= e1->lazyplt;
+  e2->done |= e1->done;
+
+  e2->relocs32 += e1->relocs32;
+  e2->relocsfd += e1->relocsfd;
+  e2->relocsfdv += e1->relocsfdv;
+  e2->fixups += e1->fixups;
+  e2->dynrelocs += e1->dynrelocs;
+
+  if (abs (e1->got_entry) < abs (e2->got_entry))
+    e2->got_entry = e1->got_entry;
+  if (abs (e1->fdgot_entry) < abs (e2->fdgot_entry))
+    e2->fdgot_entry = e1->fdgot_entry;
+  if (abs (e1->fd_entry) < abs (e2->fd_entry))
+    e2->fd_entry = e1->fd_entry;
+
+  if (e1->plt_entry < e2->plt_entry)
+    e2->plt_entry = e1->plt_entry;
+  if (e1->lzplt_entry < e2->lzplt_entry)
+    e2->lzplt_entry = e1->lzplt_entry;
+#endif
 }
 
 /* Every block of 65535 lazy PLT entries shares a single call to the
@@ -851,14 +916,15 @@ frv_pic_relocs_info_for_local (struct htab *ht,
    32767, counting from 0).  All other lazy PLT entries branch to it
    in a single instruction.  */
 
-#define FRV_LZPLT_BLOCK_SIZE ((bfd_vma) 8 * 65535 + 4)
-#define FRV_LZPLT_RESOLV_LOC (8 * 32767)
+#define FRVFDPIC_LZPLT_BLOCK_SIZE ((bfd_vma) 8 * 65535 + 4)
+#define FRVFDPIC_LZPLT_RESOLV_LOC (8 * 32767)
 
 /* Add a dynamic relocation to the SRELOC section.  */
 
 inline static bfd_vma
-_frv_add_dyn_reloc (bfd *output_bfd, asection *sreloc, bfd_vma offset,
-                   int reloc_type, long dynindx, bfd_vma addend)
+_frvfdpic_add_dyn_reloc (bfd *output_bfd, asection *sreloc, bfd_vma offset,
+                        int reloc_type, long dynindx, bfd_vma addend,
+                        struct frvfdpic_relocs_info *entry)
 {
   Elf_Internal_Rela outrel;
   bfd_vma reloc_offset;
@@ -873,13 +939,27 @@ _frv_add_dyn_reloc (bfd *output_bfd, asection *sreloc, bfd_vma offset,
                            sreloc->contents + reloc_offset);
   sreloc->reloc_count++;
 
+  /* If the entry's index is zero, this relocation was probably to a
+     linkonce section that got discarded.  We reserved a dynamic
+     relocation, but it was for another entry than the one we got at
+     the time of emitting the relocation.  Unfortunately there's no
+     simple way for us to catch this situation, since the relocation
+     is cleared right before calling relocate_section, at which point
+     we no longer know what the relocation used to point to.  */
+  if (entry->symndx)
+    {
+      BFD_ASSERT (entry->dynrelocs > 0);
+      entry->dynrelocs--;
+    }
+
   return reloc_offset;
 }
 
 /* Add a fixup to the ROFIXUP section.  */
 
 static bfd_vma
-_frv_add_rofixup (bfd *output_bfd, asection *rofixup, bfd_vma offset)
+_frvfdpic_add_rofixup (bfd *output_bfd, asection *rofixup, bfd_vma offset,
+                      struct frvfdpic_relocs_info *entry)
 {
   bfd_vma fixup_offset;
 
@@ -893,7 +973,15 @@ _frv_add_rofixup (bfd *output_bfd, asection *rofixup, bfd_vma offset)
       bfd_put_32 (output_bfd, offset, rofixup->contents + fixup_offset);
     }
   rofixup->reloc_count++;
-             
+
+  if (entry && entry->symndx)
+    {
+      /* See discussion about symndx == 0 in _frvfdpic_add_dyn_reloc
+        above.  */
+      BFD_ASSERT (entry->fixups > 0);
+      entry->fixups--;
+    }
+
   return fixup_offset;
 }
 
@@ -901,7 +989,7 @@ _frv_add_rofixup (bfd *output_bfd, asection *rofixup, bfd_vma offset)
    located.  */
 
 static unsigned
-_frv_osec_to_segment (bfd *output_bfd, asection *osec)
+_frvfdpic_osec_to_segment (bfd *output_bfd, asection *osec)
 {
   struct elf_segment_map *m;
   Elf_Internal_Phdr *p;
@@ -926,9 +1014,9 @@ _frv_osec_to_segment (bfd *output_bfd, asection *osec)
 }
 
 inline static bfd_boolean
-_frv_osec_readonly_p (bfd *output_bfd, asection *osec)
+_frvfdpic_osec_readonly_p (bfd *output_bfd, asection *osec)
 {
-  unsigned seg = _frv_osec_to_segment (output_bfd, osec);
+  unsigned seg = _frvfdpic_osec_to_segment (output_bfd, osec);
 
   return ! (elf_tdata (output_bfd)->phdr[seg].p_flags & PF_W);
 }
@@ -937,12 +1025,12 @@ _frv_osec_readonly_p (bfd *output_bfd, asection *osec)
    code for PLT and lazy PLT entries.  */
 
 inline static bfd_boolean
-_frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
-                                 bfd *output_bfd,
-                                 struct bfd_link_info *info,
-                                 asection *sec,
-                                 Elf_Internal_Sym *sym,
-                                 bfd_vma addend)
+_frvfdpic_emit_got_relocs_plt_entries (struct frvfdpic_relocs_info *entry,
+                                      bfd *output_bfd,
+                                      struct bfd_link_info *info,
+                                      asection *sec,
+                                      Elf_Internal_Sym *sym,
+                                      bfd_vma addend)
                                  
 {
   bfd_vma fd_lazy_rel_offset = (bfd_vma)-1;
@@ -977,7 +1065,8 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
 
       /* If the symbol is dynamic but binds locally, use
         section+offset.  */
-      if (sec && (entry->symndx != -1 || FRV_SYM_LOCAL (info, entry->d.h)))
+      if (sec && (entry->symndx != -1
+                 || FRVFDPIC_SYM_LOCAL (info, entry->d.h)))
        {
          if (entry->symndx == -1)
            ad += entry->d.h->root.u.def.value;
@@ -994,32 +1083,36 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
         omit the dynamic relocation as long as the symbol is local to
         this module.  */
       if (info->executable && !info->pie
-         && (entry->symndx != -1 || FRV_SYM_LOCAL (info, entry->d.h)))
+         && (entry->symndx != -1
+             || FRVFDPIC_SYM_LOCAL (info, entry->d.h)))
        {
          if (sec)
            ad += sec->output_section->vma;
-         if (entry->symndx != -1 ||
-             entry->d.h->root.type != bfd_link_hash_undefweak)
-           _frv_add_rofixup (output_bfd, frv_gotfixup_section (info),
-                             frv_got_section (info)->output_section->vma
-                             + frv_got_section (info)->output_offset
-                             + frv_got_initial_offset (info)
-                             + entry->got_entry);
+         if (entry->symndx != -1
+             || entry->d.h->root.type != bfd_link_hash_undefweak)
+           _frvfdpic_add_rofixup (output_bfd,
+                                  frvfdpic_gotfixup_section (info),
+                                  frvfdpic_got_section (info)->output_section
+                                  ->vma
+                                  + frvfdpic_got_section (info)->output_offset
+                                  + frvfdpic_got_initial_offset (info)
+                                  + entry->got_entry, entry);
        }
       else
-       _frv_add_dyn_reloc (output_bfd, frv_gotrel_section (info),
-                           _bfd_elf_section_offset
-                           (output_bfd, info,
-                            frv_got_section (info),
-                            frv_got_initial_offset (info)
-                            + entry->got_entry)
-                           + frv_got_section (info)->output_section->vma
-                           + frv_got_section (info)->output_offset,
-                           R_FRV_32, idx, ad);
+       _frvfdpic_add_dyn_reloc (output_bfd, frvfdpic_gotrel_section (info),
+                                _bfd_elf_section_offset
+                                (output_bfd, info,
+                                 frvfdpic_got_section (info),
+                                 frvfdpic_got_initial_offset (info)
+                                 + entry->got_entry)
+                                + frvfdpic_got_section (info)
+                                ->output_section->vma
+                                + frvfdpic_got_section (info)->output_offset,
+                                R_FRV_32, idx, ad, entry);
        
       bfd_put_32 (output_bfd, ad,
-                 frv_got_section (info)->contents
-                 + frv_got_initial_offset (info)
+                 frvfdpic_got_section (info)->contents
+                 + frvfdpic_got_initial_offset (info)
                  + entry->got_entry);
     }
 
@@ -1032,7 +1125,7 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
       
       if (! (entry->symndx == -1
             && entry->d.h->root.type == bfd_link_hash_undefweak
-            && FRV_SYM_LOCAL (info, entry->d.h)))
+            && FRVFDPIC_SYM_LOCAL (info, entry->d.h)))
        {
          /* If the symbol is dynamic and there may be dynamic symbol
             resolution because we are, or are linked with, a shared
@@ -1041,8 +1134,9 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
             symbol needs a non-local function descriptor but binds
             locally (e.g., its visibility is protected, emit a
             dynamic relocation decayed to section+offset.  */
-         if (entry->symndx == -1 && ! FRV_FUNCDESC_LOCAL (info, entry->d.h)
-             && FRV_SYM_LOCAL (info, entry->d.h)
+         if (entry->symndx == -1
+             && ! FRVFDPIC_FUNCDESC_LOCAL (info, entry->d.h)
+             && FRVFDPIC_SYM_LOCAL (info, entry->d.h)
              && !(info->executable && !info->pie))
            {
              reloc = R_FRV_FUNCDESC;
@@ -1052,7 +1146,7 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
                + entry->d.h->root.u.def.value;
            }
          else if (entry->symndx == -1
-                  && ! FRV_FUNCDESC_LOCAL (info, entry->d.h))
+                  && ! FRVFDPIC_FUNCDESC_LOCAL (info, entry->d.h))
            {
              reloc = R_FRV_FUNCDESC;
              idx = dynindx;
@@ -1067,10 +1161,10 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
              if (elf_hash_table (info)->dynamic_sections_created)
                BFD_ASSERT (entry->privfd);
              reloc = R_FRV_32;
-             idx = elf_section_data (frv_got_section (info)
+             idx = elf_section_data (frvfdpic_got_section (info)
                                      ->output_section)->dynindx;
-             ad = frv_got_section (info)->output_offset
-               + frv_got_initial_offset (info) + entry->fd_entry;
+             ad = frvfdpic_got_section (info)->output_offset
+               + frvfdpic_got_initial_offset (info) + entry->fd_entry;
            }
 
          /* If there is room for dynamic symbol resolution, emit the
@@ -1081,30 +1175,36 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
             of the private descriptor ourselves.  */
          if (info->executable && !info->pie
              && (entry->symndx != -1
-                 || FRV_FUNCDESC_LOCAL (info, entry->d.h)))
+                 || FRVFDPIC_FUNCDESC_LOCAL (info, entry->d.h)))
            {
-             ad += frv_got_section (info)->output_section->vma;
-             _frv_add_rofixup (output_bfd, frv_gotfixup_section (info),
-                               frv_got_section (info)->output_section->vma
-                               + frv_got_section (info)->output_offset
-                               + frv_got_initial_offset (info)
-                               + entry->fdgot_entry);
+             ad += frvfdpic_got_section (info)->output_section->vma;
+             _frvfdpic_add_rofixup (output_bfd,
+                                    frvfdpic_gotfixup_section (info),
+                                    frvfdpic_got_section (info)
+                                    ->output_section->vma
+                                    + frvfdpic_got_section (info)
+                                    ->output_offset
+                                    + frvfdpic_got_initial_offset (info)
+                                    + entry->fdgot_entry, entry);
            }
          else
-           _frv_add_dyn_reloc (output_bfd, frv_gotrel_section (info),
-                               _bfd_elf_section_offset
-                               (output_bfd, info,
-                                frv_got_section (info),
-                                frv_got_initial_offset (info)
-                                + entry->fdgot_entry)
-                               + frv_got_section (info)->output_section->vma
-                               + frv_got_section (info)->output_offset,
-                               reloc, idx, ad);
+           _frvfdpic_add_dyn_reloc (output_bfd,
+                                    frvfdpic_gotrel_section (info),
+                                    _bfd_elf_section_offset
+                                    (output_bfd, info,
+                                     frvfdpic_got_section (info),
+                                     frvfdpic_got_initial_offset (info)
+                                     + entry->fdgot_entry)
+                                    + frvfdpic_got_section (info)
+                                    ->output_section->vma
+                                    + frvfdpic_got_section (info)
+                                    ->output_offset,
+                                    reloc, idx, ad, entry);
        }
 
       bfd_put_32 (output_bfd, ad,
-                 frv_got_section (info)->contents
-                 + frv_got_initial_offset (info)
+                 frvfdpic_got_section (info)->contents
+                 + frvfdpic_got_initial_offset (info)
                  + entry->fdgot_entry);
     }
 
@@ -1119,7 +1219,8 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
 
       /* If the symbol is dynamic but binds locally, use
         section+offset.  */
-      if (sec && (entry->symndx != -1 || FRV_SYM_LOCAL (info, entry->d.h)))
+      if (sec && (entry->symndx != -1
+                 || FRVFDPIC_SYM_LOCAL (info, entry->d.h)))
        {
          if (entry->symndx == -1)
            ad += entry->d.h->root.u.def.value;
@@ -1136,40 +1237,49 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
         omit the dynamic relocation as long as the symbol is local to
         this module.  */
       if (info->executable && !info->pie
-         && (entry->symndx != -1 || FRV_SYM_LOCAL (info, entry->d.h)))
+         && (entry->symndx != -1 || FRVFDPIC_SYM_LOCAL (info, entry->d.h)))
        {
          if (sec)
            ad += sec->output_section->vma;
          ofst = 0;
-         if (entry->symndx != -1 ||
-             entry->d.h->root.type != bfd_link_hash_undefweak)
+         if (entry->symndx != -1
+             || entry->d.h->root.type != bfd_link_hash_undefweak)
            {
-             _frv_add_rofixup (output_bfd, frv_gotfixup_section (info),
-                               frv_got_section (info)->output_section->vma
-                               + frv_got_section (info)->output_offset
-                               + frv_got_initial_offset (info)
-                               + entry->fd_entry);
-             _frv_add_rofixup (output_bfd, frv_gotfixup_section (info),
-                               frv_got_section (info)->output_section->vma
-                               + frv_got_section (info)->output_offset
-                               + frv_got_initial_offset (info)
-                               + entry->fd_entry + 4);
+             _frvfdpic_add_rofixup (output_bfd,
+                                    frvfdpic_gotfixup_section (info),
+                                    frvfdpic_got_section (info)
+                                    ->output_section->vma
+                                    + frvfdpic_got_section (info)
+                                    ->output_offset
+                                    + frvfdpic_got_initial_offset (info)
+                                    + entry->fd_entry, entry);
+             _frvfdpic_add_rofixup (output_bfd,
+                                    frvfdpic_gotfixup_section (info),
+                                    frvfdpic_got_section (info)
+                                    ->output_section->vma
+                                    + frvfdpic_got_section (info)
+                                    ->output_offset
+                                    + frvfdpic_got_initial_offset (info)
+                                    + entry->fd_entry + 4, entry);
            }
        }
       else
        {
          ofst =
-           _frv_add_dyn_reloc (output_bfd,
-                               entry->lazyplt ? frv_pltrel_section (info)
-                               : frv_gotrel_section (info),
-                               _bfd_elf_section_offset
-                               (output_bfd, info,
-                                frv_got_section (info),
-                                frv_got_initial_offset (info)
-                                + entry->fd_entry)
-                               + frv_got_section (info)->output_section->vma
-                               + frv_got_section (info)->output_offset,
-                               R_FRV_FUNCDESC_VALUE, idx, ad);
+           _frvfdpic_add_dyn_reloc (output_bfd,
+                                    entry->lazyplt
+                                    ? frvfdpic_pltrel_section (info)
+                                    : frvfdpic_gotrel_section (info),
+                                    _bfd_elf_section_offset
+                                    (output_bfd, info,
+                                     frvfdpic_got_section (info),
+                                     frvfdpic_got_initial_offset (info)
+                                     + entry->fd_entry)
+                                    + frvfdpic_got_section (info)
+                                    ->output_section->vma
+                                    + frvfdpic_got_section (info)
+                                    ->output_offset,
+                                    R_FRV_FUNCDESC_VALUE, idx, ad, entry);
        }
 
       /* If we've omitted the dynamic relocation, just emit the fixed
@@ -1177,9 +1287,9 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
       if (info->executable && !info->pie && sec && sec->output_section)
        {
          lowword = ad;
-         highword = frv_got_section (info)->output_section->vma
-           + frv_got_section (info)->output_offset
-           + frv_got_initial_offset (info);
+         highword = frvfdpic_got_section (info)->output_section->vma
+           + frvfdpic_got_section (info)->output_offset
+           + frvfdpic_got_initial_offset (info);
        }
       else if (entry->lazyplt)
        {
@@ -1195,10 +1305,10 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
             entry point, that must be within the memory region
             assigned to that section.  */
          lowword = entry->lzplt_entry + 4
-           + frv_plt_section (info)->output_offset
-           + frv_plt_section (info)->output_section->vma;
-         highword = _frv_osec_to_segment 
-           (output_bfd, frv_plt_section (info)->output_section);
+           + frvfdpic_plt_section (info)->output_offset
+           + frvfdpic_plt_section (info)->output_section->vma;
+         highword = _frvfdpic_osec_to_segment 
+           (output_bfd, frvfdpic_plt_section (info)->output_section);
        }
       else
        {
@@ -1210,23 +1320,25 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
              && entry->d.h->dynindx == idx)
            highword = 0;
          else
-           highword = _frv_osec_to_segment (output_bfd, sec->output_section);
+           highword = _frvfdpic_osec_to_segment
+             (output_bfd, sec->output_section);
        }
 
       bfd_put_32 (output_bfd, lowword,
-                 frv_got_section (info)->contents
-                 + frv_got_initial_offset (info)
+                 frvfdpic_got_section (info)->contents
+                 + frvfdpic_got_initial_offset (info)
                  + entry->fd_entry);
       bfd_put_32 (output_bfd, highword,
-                 frv_got_section (info)->contents
-                 + frv_got_initial_offset (info)
+                 frvfdpic_got_section (info)->contents
+                 + frvfdpic_got_initial_offset (info)
                  + entry->fd_entry + 4);
     }
 
   /* Generate code for the PLT entry.  */
   if (entry->plt_entry != (bfd_vma) -1)
     {
-      bfd_byte *plt_code = frv_plt_section (info)->contents + entry->plt_entry;
+      bfd_byte *plt_code = frvfdpic_plt_section (info)->contents
+       + entry->plt_entry;
 
       BFD_ASSERT (entry->fd_entry);
 
@@ -1279,17 +1391,17 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
   /* Generate code for the lazy PLT entry.  */
   if (entry->lzplt_entry != (bfd_vma) -1)
     {
-      bfd_byte *lzplt_code = frv_plt_section (info)->contents
+      bfd_byte *lzplt_code = frvfdpic_plt_section (info)->contents
        + entry->lzplt_entry;
       bfd_vma resolverStub_addr;
 
       bfd_put_32 (output_bfd, fd_lazy_rel_offset, lzplt_code);
       lzplt_code += 4;
 
-      resolverStub_addr = entry->lzplt_entry / FRV_LZPLT_BLOCK_SIZE
-       * FRV_LZPLT_BLOCK_SIZE + FRV_LZPLT_RESOLV_LOC;
-      if (resolverStub_addr >= frv_plt_initial_offset (info))
-       resolverStub_addr = frv_plt_initial_offset (info) - 12;
+      resolverStub_addr = entry->lzplt_entry / FRVFDPIC_LZPLT_BLOCK_SIZE
+       * FRVFDPIC_LZPLT_BLOCK_SIZE + FRVFDPIC_LZPLT_RESOLV_LOC;
+      if (resolverStub_addr >= frvfdpic_plt_initial_offset (info))
+       resolverStub_addr = frvfdpic_plt_initial_offset (info) - 12;
 
       if (entry->lzplt_entry == resolverStub_addr)
        {
@@ -1693,8 +1805,8 @@ frv_info_to_howto_rela (abfd, cache_ptr, dst)
 
 /* Set the howto pointer for an FRV ELF REL reloc.  */
 static void
-frv_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
-                      arelent *cache_ptr, Elf_Internal_Rela *dst)
+frvfdpic_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
+                           arelent *cache_ptr, Elf_Internal_Rela *dst)
 {
   unsigned int r_type;
 
@@ -1795,24 +1907,24 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
   sym_hashes = elf_sym_hashes (input_bfd);
   relend     = relocs + input_section->reloc_count;
 
-  isec_segment = _frv_osec_to_segment (output_bfd,
-                                      input_section->output_section);
-  if (frv_got_section (info))
-    got_segment = _frv_osec_to_segment (output_bfd,
-                                       frv_got_section (info)
-                                       ->output_section);
+  isec_segment = _frvfdpic_osec_to_segment (output_bfd,
+                                           input_section->output_section);
+  if (IS_FDPIC (output_bfd) && frvfdpic_got_section (info))
+    got_segment = _frvfdpic_osec_to_segment (output_bfd,
+                                            frvfdpic_got_section (info)
+                                            ->output_section);
   else
     got_segment = -1;
-  if (frv_gotfixup_section (info))
-    gprel_segment = _frv_osec_to_segment (output_bfd,
-                                         frv_gotfixup_section (info)
-                                         ->output_section);
+  if (IS_FDPIC (output_bfd) && frvfdpic_gotfixup_section (info))
+    gprel_segment = _frvfdpic_osec_to_segment (output_bfd,
+                                              frvfdpic_gotfixup_section (info)
+                                              ->output_section);
   else
     gprel_segment = -1;
-  if (elf_hash_table (info)->dynamic_sections_created)
-    plt_segment = _frv_osec_to_segment (output_bfd,
-                                       frv_plt_section (info)
-                                       ->output_section);
+  if (IS_FDPIC (output_bfd) && elf_hash_table (info)->dynamic_sections_created)
+    plt_segment = _frvfdpic_osec_to_segment (output_bfd,
+                                            frvfdpic_plt_section (info)
+                                            ->output_section);
   else
     plt_segment = -1;
 
@@ -1828,7 +1940,7 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
       const char * name = NULL;
       int r_type;
       asection *osec;
-      struct frv_pic_relocs_info *picrel;
+      struct frvfdpic_relocs_info *picrel;
       bfd_vma orig_addend = rel->r_addend;
 
       r_type = ELF32_R_TYPE (rel->r_info);
@@ -1866,7 +1978,7 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
 
          if ((h->root.type == bfd_link_hash_defined
               || h->root.type == bfd_link_hash_defweak)
-             && ! FRV_SYM_LOCAL (info, h))
+             && ! FRVFDPIC_SYM_LOCAL (info, h))
            {
              sec = NULL;
              relocation = 0;
@@ -1884,16 +1996,16 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
            {
              relocation = 0;
            }
-         else if (   ! info->executable
-                  && ! info->symbolic
-                  && info->unresolved_syms_in_objects == RM_IGNORE
+         else if (info->unresolved_syms_in_objects == RM_IGNORE
                   && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
            relocation = 0;
          else
            {
              if (! ((*info->callbacks->undefined_symbol)
                     (info, h->root.root.string, input_bfd,
-                     input_section, rel->r_offset, TRUE)))
+                     input_section, rel->r_offset,
+                     (info->unresolved_syms_in_objects == RM_GENERATE_ERROR
+                      || ELF_ST_VISIBILITY (h->other)))))
                return FALSE;
              relocation = 0;
            }
@@ -1904,6 +2016,9 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
        {
        case R_FRV_LABEL24:
        case R_FRV_32:
+         if (! IS_FDPIC (output_bfd))
+           goto non_fdpic;
+
        case R_FRV_GOT12:
        case R_FRV_GOTHI:
        case R_FRV_GOTLO:
@@ -1919,25 +2034,27 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
        case R_FRV_FUNCDESC:
        case R_FRV_FUNCDESC_VALUE:
          if (h != NULL)
-           picrel = frv_pic_relocs_info_for_global (frv_relocs_info (info),
-                                                    input_bfd, h,
-                                                    orig_addend);
+           picrel = frvfdpic_relocs_info_for_global (frvfdpic_relocs_info
+                                                     (info), input_bfd, h,
+                                                     orig_addend, INSERT);
          else
            /* In order to find the entry we created before, we must
               use the original addend, not the one that may have been
               modified by _bfd_elf_rela_local_sym().  */
-           picrel = frv_pic_relocs_info_for_local (frv_relocs_info (info),
-                                                   input_bfd, r_symndx,
-                                                   orig_addend);
+           picrel = frvfdpic_relocs_info_for_local (frvfdpic_relocs_info
+                                                    (info), input_bfd, r_symndx,
+                                                    orig_addend, INSERT);
          if (! picrel)
            return FALSE;
 
-         if (!_frv_emit_got_relocs_plt_entries (picrel, output_bfd, info,
-                                                osec, sym, rel->r_addend))
+         if (!_frvfdpic_emit_got_relocs_plt_entries (picrel, output_bfd, info,
+                                                     osec, sym,
+                                                     rel->r_addend))
            {
-             info->callbacks->warning
-               (info, _("Dynamic relocation references symbol with nonzero addend"),
-                name, input_bfd, input_section, rel->r_offset);
+             (*_bfd_error_handler)
+               (_("%s: relocation at `%s+0x%x' references symbol `%s' with nonzero addend"),
+                bfd_archive_filename (input_bfd), input_section->name,
+                rel->r_offset, name);
              return FALSE;
 
            }
@@ -1945,8 +2062,9 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
          break;
 
        default:
+       non_fdpic:
          picrel = NULL;
-         if (h && ! FRV_SYM_LOCAL (info, h))
+         if (h && ! FRVFDPIC_SYM_LOCAL (info, h))
            {
              info->callbacks->warning
                (info, _("relocation references symbol not defined in the module"),
@@ -1960,10 +2078,12 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
        {
        case R_FRV_LABEL24:
          check_segment[0] = isec_segment;
-         if (picrel->plt)
+         if (! IS_FDPIC (output_bfd))
+           check_segment[1] = isec_segment;
+         else if (picrel->plt)
            {
-             relocation = frv_plt_section (info)->output_section->vma
-               + frv_plt_section (info)->output_offset
+             relocation = frvfdpic_plt_section (info)->output_section->vma
+               + frvfdpic_plt_section (info)->output_offset
                + picrel->plt_entry;
              check_segment[1] = plt_segment;
            }
@@ -1976,7 +2096,7 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
            check_segment[1] = check_segment[0];
          else
            check_segment[1] = sec
-             ? _frv_osec_to_segment (output_bfd, sec->output_section)
+             ? _frvfdpic_osec_to_segment (output_bfd, sec->output_section)
              : (unsigned)-1;
          break;
 
@@ -1997,12 +2117,12 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
        case R_FRV_GOTOFFHI:
        case R_FRV_GOTOFF12:
        case R_FRV_GOTOFFLO:
-         relocation -= frv_got_section (info)->output_section->vma
-           + frv_got_section (info)->output_offset
-           + frv_got_initial_offset (info);
+         relocation -= frvfdpic_got_section (info)->output_section->vma
+           + frvfdpic_got_section (info)->output_offset
+           + frvfdpic_got_initial_offset (info);
          check_segment[0] = got_segment;
          check_segment[1] = sec
-           ? _frv_osec_to_segment (output_bfd, sec->output_section)
+           ? _frvfdpic_osec_to_segment (output_bfd, sec->output_section)
            : (unsigned)-1;
          break;
 
@@ -2019,7 +2139,7 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
            bfd_vma addend = rel->r_addend;
 
            if (! (h && h->root.type == bfd_link_hash_undefweak
-                  && FRV_SYM_LOCAL (info, h)))
+                  && FRVFDPIC_SYM_LOCAL (info, h)))
              {
                /* If the symbol is dynamic and there may be dynamic
                   symbol resolution because we are or are linked with a
@@ -2029,8 +2149,8 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
                   descriptor but binds locally (e.g., its visibility is
                   protected, emit a dynamic relocation decayed to
                   section+offset.  */
-               if (h && ! FRV_FUNCDESC_LOCAL (info, h)
-                   && FRV_SYM_LOCAL (info, h)
+               if (h && ! FRVFDPIC_FUNCDESC_LOCAL (info, h)
+                   && FRVFDPIC_SYM_LOCAL (info, h)
                    && !(info->executable && !info->pie))
                  {
                    dynindx = elf_section_data (h->root.u.def.section
@@ -2038,7 +2158,7 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
                    addend += h->root.u.def.section->output_offset
                      + h->root.u.def.value;
                  }
-               else if (h && ! FRV_FUNCDESC_LOCAL (info, h))
+               else if (h && ! FRVFDPIC_FUNCDESC_LOCAL (info, h))
                  {
                    if (addend)
                      {
@@ -2055,10 +2175,10 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
                       descriptor, so reference it directly.  */
                    BFD_ASSERT (picrel->privfd);
                    r_type = R_FRV_32;
-                   dynindx = elf_section_data (frv_got_section (info)
+                   dynindx = elf_section_data (frvfdpic_got_section (info)
                                                ->output_section)->dynindx;
-                   addend = frv_got_section (info)->output_offset
-                     + frv_got_initial_offset (info)
+                   addend = frvfdpic_got_section (info)->output_offset
+                     + frvfdpic_got_initial_offset (info)
                      + picrel->fd_entry;
                  }
 
@@ -2069,15 +2189,16 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
                   be zero, which means we can and should compute the
                   address of the private descriptor ourselves.  */
                if (info->executable && !info->pie
-                   && (!h || FRV_FUNCDESC_LOCAL (info, h)))
+                   && (!h || FRVFDPIC_FUNCDESC_LOCAL (info, h)))
                  {
-                   addend += frv_got_section (info)->output_section->vma;
+                   addend += frvfdpic_got_section (info)->output_section->vma;
                    if ((bfd_get_section_flags (output_bfd,
                                                input_section->output_section)
                         & (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD))
                      {
-                       if (_frv_osec_readonly_p (output_bfd,
-                                                 input_section->output_section))
+                       if (_frvfdpic_osec_readonly_p (output_bfd,
+                                                      input_section
+                                                      ->output_section))
                          {
                            info->callbacks->warning
                              (info,
@@ -2085,21 +2206,25 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
                               name, input_bfd, input_section, rel->r_offset);
                            return FALSE;
                          }
-                       _frv_add_rofixup (output_bfd,
-                                         frv_gotfixup_section (info),
-                                         _bfd_elf_section_offset
-                                         (output_bfd, info,
-                                          input_section, rel->r_offset)
-                                         + input_section->output_section->vma
-                                         + input_section->output_offset);
+                       _frvfdpic_add_rofixup (output_bfd,
+                                              frvfdpic_gotfixup_section
+                                              (info),
+                                              _bfd_elf_section_offset
+                                              (output_bfd, info,
+                                               input_section, rel->r_offset)
+                                              + input_section
+                                              ->output_section->vma
+                                              + input_section->output_offset,
+                                              picrel);
                      }
                  }
                else if ((bfd_get_section_flags (output_bfd,
                                                 input_section->output_section)
                          & (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD))
                  {
-                   if (_frv_osec_readonly_p (output_bfd,
-                                             input_section->output_section))
+                   if (_frvfdpic_osec_readonly_p (output_bfd,
+                                                  input_section
+                                                  ->output_section))
                      {
                        info->callbacks->warning
                          (info,
@@ -2107,14 +2232,18 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
                           name, input_bfd, input_section, rel->r_offset);
                        return FALSE;
                      }
-                   _frv_add_dyn_reloc (output_bfd, frv_gotrel_section (info),
-                                       _bfd_elf_section_offset
-                                       (output_bfd, info,
-                                        input_section, rel->r_offset)
-                                       + input_section->output_section->vma
-                                       + input_section->output_offset,
-                                       r_type, dynindx, addend);
+                   _frvfdpic_add_dyn_reloc (output_bfd,
+                                            frvfdpic_gotrel_section (info),
+                                            _bfd_elf_section_offset
+                                            (output_bfd, info,
+                                             input_section, rel->r_offset)
+                                            + input_section
+                                            ->output_section->vma
+                                            + input_section->output_offset,
+                                            r_type, dynindx, addend, picrel);
                  }
+               else
+                 addend += frvfdpic_got_section (info)->output_section->vma;
              }
 
            /* We want the addend in-place because dynamic
@@ -2126,6 +2255,12 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
          break;
 
        case R_FRV_32:
+         if (! IS_FDPIC (output_bfd))
+           {
+             check_segment[0] = check_segment[1] = -1;
+             break;
+           }
+         /* Fall through.  */
        case R_FRV_FUNCDESC_VALUE:
          {
            int dynindx;
@@ -2133,7 +2268,7 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
 
            /* If the symbol is dynamic but binds locally, use
               section+offset.  */
-           if (h && ! FRV_SYM_LOCAL (info, h))
+           if (h && ! FRVFDPIC_SYM_LOCAL (info, h))
              {
                if (addend && r_type == R_FRV_FUNCDESC_VALUE)
                  {
@@ -2165,17 +2300,18 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
               is defined in the current link unit (which is implied
               by its output section not being NULL).  */
            if (info->executable && !info->pie
-               && (!h || FRV_SYM_LOCAL (info, h)))
+               && (!h || FRVFDPIC_SYM_LOCAL (info, h)))
              {
                if (osec)
                  addend += osec->output_section->vma;
-               if ((elf_elfheader (input_bfd)->e_flags & EF_FRV_FDPIC)
+               if (IS_FDPIC (input_bfd)
                    && (bfd_get_section_flags (output_bfd,
                                               input_section->output_section)
                        & (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD))
                  {
-                   if (_frv_osec_readonly_p (output_bfd,
-                                             input_section->output_section))
+                   if (_frvfdpic_osec_readonly_p (output_bfd,
+                                                  input_section
+                                                  ->output_section))
                      {
                        info->callbacks->warning
                          (info,
@@ -2185,22 +2321,25 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
                      }
                    if (!h || h->root.type != bfd_link_hash_undefweak)
                      {
-                       _frv_add_rofixup (output_bfd,
-                                         frv_gotfixup_section (info),
-                                         _bfd_elf_section_offset
-                                         (output_bfd, info,
-                                          input_section, rel->r_offset)
-                                         + input_section->output_section->vma
-                                         + input_section->output_offset);
+                       _frvfdpic_add_rofixup (output_bfd,
+                                              frvfdpic_gotfixup_section
+                                              (info),
+                                              _bfd_elf_section_offset
+                                              (output_bfd, info,
+                                               input_section, rel->r_offset)
+                                              + input_section
+                                              ->output_section->vma
+                                              + input_section->output_offset,
+                                              picrel);
                        if (r_type == R_FRV_FUNCDESC_VALUE)
-                         _frv_add_rofixup
+                         _frvfdpic_add_rofixup
                            (output_bfd,
-                            frv_gotfixup_section (info),
+                            frvfdpic_gotfixup_section (info),
                             _bfd_elf_section_offset
                             (output_bfd, info,
                              input_section, rel->r_offset)
                             + input_section->output_section->vma
-                            + input_section->output_offset + 4);
+                            + input_section->output_offset + 4, picrel);
                      }
                  }
              }
@@ -2210,8 +2349,9 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
                                            input_section->output_section)
                     & (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD))
                  {
-                   if (_frv_osec_readonly_p (output_bfd,
-                                             input_section->output_section))
+                   if (_frvfdpic_osec_readonly_p (output_bfd,
+                                                  input_section
+                                                  ->output_section))
                      {
                        info->callbacks->warning
                          (info,
@@ -2219,14 +2359,18 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
                           name, input_bfd, input_section, rel->r_offset);
                        return FALSE;
                      }
-                   _frv_add_dyn_reloc (output_bfd, frv_gotrel_section (info),
-                                       _bfd_elf_section_offset
-                                       (output_bfd, info,
-                                        input_section, rel->r_offset)
-                                       + input_section->output_section->vma
-                                       + input_section->output_offset,
-                                       r_type, dynindx, addend);
+                   _frvfdpic_add_dyn_reloc (output_bfd,
+                                            frvfdpic_gotrel_section (info),
+                                            _bfd_elf_section_offset
+                                            (output_bfd, info,
+                                             input_section, rel->r_offset)
+                                            + input_section
+                                            ->output_section->vma
+                                            + input_section->output_offset,
+                                            r_type, dynindx, addend, picrel);
                  }
+               else if (osec)
+                 addend += osec->output_section->vma;
                /* We want the addend in-place because dynamic
                   relocations are REL.  Setting relocation to it
                   should arrange for it to be installed.  */
@@ -2239,11 +2383,11 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
                   the fixed addresses of the symbol and of the local
                   GOT base offset.  */
                if (info->executable && !info->pie
-                   && (!h || FRV_SYM_LOCAL (info, h)))
+                   && (!h || FRVFDPIC_SYM_LOCAL (info, h)))
                  bfd_put_32 (output_bfd,
-                             frv_got_section (info)->output_section->vma
-                             + frv_got_section (info)->output_offset
-                             + frv_got_initial_offset (info),
+                             frvfdpic_got_section (info)->output_section->vma
+                             + frvfdpic_got_section (info)->output_offset
+                             + frvfdpic_got_initial_offset (info),
                              contents + rel->r_offset + 4);
                else
                  /* A function descriptor used for lazy or local
@@ -2253,10 +2397,11 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
                     contains the offset of the lazy PLT entry entry
                     point into that section.  */
                  bfd_put_32 (output_bfd,
-                             h && ! FRV_SYM_LOCAL (info, h)
+                             h && ! FRVFDPIC_SYM_LOCAL (info, h)
                              ? 0
-                             : _frv_osec_to_segment (output_bfd,
-                                                     sec->output_section),
+                             : _frvfdpic_osec_to_segment (output_bfd,
+                                                          sec
+                                                          ->output_section),
                              contents + rel->r_offset + 4);
              }
          }
@@ -2270,22 +2415,22 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
        case R_FRV_GPRELLO:
          check_segment[0] = gprel_segment;
          check_segment[1] = sec
-           ? _frv_osec_to_segment (output_bfd, sec->output_section)
+           ? _frvfdpic_osec_to_segment (output_bfd, sec->output_section)
            : (unsigned)-1;
          break;
 
        default:
          check_segment[0] = isec_segment;
          check_segment[1] = sec
-           ? _frv_osec_to_segment (output_bfd, sec->output_section)
+           ? _frvfdpic_osec_to_segment (output_bfd, sec->output_section)
            : (unsigned)-1;
          break;
        }
 
-      if (check_segment[0] != check_segment[1]
-         && (elf_elfheader (output_bfd)->e_flags & EF_FRV_FDPIC))
+      if (check_segment[0] != check_segment[1] && IS_FDPIC (output_bfd))
        {
-#if 1
+#if 1 /* If you take this out, remove the #error from fdpic-static-6.d
+        in the ld testsuite.  */
          /* This helps catch problems in GCC while we can't do more
             than static linking.  The idea is to test whether the
             input file basename is crt0.o only once.  */
@@ -2342,7 +2487,7 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
       switch (r_type)
        {
        case R_FRV_LABEL24:
-         if (! picrel->plt)
+         if (! IS_FDPIC (output_bfd) || ! picrel->plt)
            break;
          /* Fall through.  */
          
@@ -2508,7 +2653,7 @@ static bfd_boolean
 elf32_frv_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
      bfd *abfd;
      struct bfd_link_info *info;
-     const Elf_Internal_Sym *sym;
+     Elf_Internal_Sym *sym;
      const char **namep ATTRIBUTE_UNUSED;
      flagword *flagsp ATTRIBUTE_UNUSED;
      asection **secp;
@@ -2539,7 +2684,8 @@ elf32_frv_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
 
   return TRUE;
 }
-/* Create a .got section, as well as its additional info field.  This
+
+/* Create  a .got section, as well as its additional info field.  This
    is almost entirely copied from
    elflink.c:_bfd_elf_create_got_section().  */
 
@@ -2552,6 +2698,7 @@ _frv_create_got_section (bfd *abfd, struct bfd_link_info *info)
   struct bfd_link_hash_entry *bh;
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   int ptralign;
+  int offset;
 
   /* This function may be called more than once.  */
   s = bfd_get_section_by_name (abfd, ".got");
@@ -2600,7 +2747,7 @@ _frv_create_got_section (bfd *abfd, struct bfd_link_info *info)
 
       /* Machine-specific: we want the symbol for executables as
         well.  */
-      if (! _bfd_elf_link_record_dynamic_symbol (info, h))
+      if (! bfd_elf_link_record_dynamic_symbol (info, h))
        return FALSE;
 
       elf_hash_table (info)->hgot = h;
@@ -2611,36 +2758,46 @@ _frv_create_got_section (bfd *abfd, struct bfd_link_info *info)
 
   /* This is the machine-specific part.  Create and initialize section
      data for the got.  */
-  frv_got_section (info) = s;
-  frv_relocs_info (info) = htab_try_create (1, frv_pic_relocs_info_hash,
-                                           frv_pic_relocs_info_eq,
-                                           (htab_del) NULL);
-  if (! frv_relocs_info (info))
-    return FALSE;
+  if (IS_FDPIC (abfd))
+    {
+      frvfdpic_got_section (info) = s;
+      frvfdpic_relocs_info (info) = htab_try_create (1, frvfdpic_relocs_info_hash,
+                                                    frvfdpic_relocs_info_eq,
+                                                    (htab_del) NULL);
+      if (! frvfdpic_relocs_info (info))
+       return FALSE;
 
-  s = bfd_make_section (abfd, ".rel.got");
-  if (s == NULL
-      || ! bfd_set_section_flags (abfd, s, (flags | SEC_READONLY))
-      || ! bfd_set_section_alignment (abfd, s, 2))
-    return FALSE;
+      s = bfd_make_section (abfd, ".rel.got");
+      if (s == NULL
+         || ! bfd_set_section_flags (abfd, s, (flags | SEC_READONLY))
+         || ! bfd_set_section_alignment (abfd, s, 2))
+       return FALSE;
 
-  frv_gotrel_section (info) = s;
+      frvfdpic_gotrel_section (info) = s;
 
-  /* Machine-specific.  */
-  s = bfd_make_section (abfd, ".rofixup");
-  if (s == NULL
-      || ! bfd_set_section_flags (abfd, s, (flags | SEC_READONLY))
-      || ! bfd_set_section_alignment (abfd, s, 2))
-    return FALSE;
+      /* Machine-specific.  */
+      s = bfd_make_section (abfd, ".rofixup");
+      if (s == NULL
+         || ! bfd_set_section_flags (abfd, s, (flags | SEC_READONLY))
+         || ! bfd_set_section_alignment (abfd, s, 2))
+       return FALSE;
 
-  frv_gotfixup_section (info) = s;
+      frvfdpic_gotfixup_section (info) = s;
+      offset = -2048;
+      flags = BSF_GLOBAL;
+    }
+  else
+    {
+      offset = 2048;
+      flags = BSF_GLOBAL | BSF_WEAK;
+    }
 
-  /* Define _gp in .rofixup, for FDPIC.  If it turns out that
-     we're linking with a different linker script, the linker script
-     will override it.  */
+  /* Define _gp in .rofixup, for FDPIC, or .got otherwise.  If it
+     turns out that we're linking with a different linker script, the
+     linker script will override it.  */
   bh = NULL;
   if (!(_bfd_generic_link_add_one_symbol
-       (info, abfd, "_gp", BSF_GLOBAL, s, -2048, (const char *) NULL, FALSE,
+       (info, abfd, "_gp", flags, s, offset, (const char *) NULL, FALSE,
         bed->collect, &bh)))
     return FALSE;
   h = (struct elf_link_hash_entry *) bh;
@@ -2648,9 +2805,9 @@ _frv_create_got_section (bfd *abfd, struct bfd_link_info *info)
   h->type = STT_OBJECT;
 
   /* Machine-specific: we want the symbol for executables as well.  */
-  if (! _bfd_elf_link_record_dynamic_symbol (info, h))
+  if (IS_FDPIC (abfd) && ! bfd_elf_link_record_dynamic_symbol (info, h))
     return FALSE;
-  
+
   return TRUE;
 }
 
@@ -2658,7 +2815,7 @@ _frv_create_got_section (bfd *abfd, struct bfd_link_info *info)
    the link hash table point to them.  */
 
 static bfd_boolean
-elf32_frv_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
+elf32_frvfdpic_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
 {
   /* This is mostly copied from
      elflink.c:_bfd_elf_create_dynamic_sections().  */
@@ -2685,7 +2842,7 @@ elf32_frv_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
       || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
     return FALSE;
   /* FRV-specific: remember it.  */
-  frv_plt_section (info) = s;
+  frvfdpic_plt_section (info) = s;
 
   if (bed->want_plt_sym)
     {
@@ -2703,7 +2860,7 @@ elf32_frv_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
       h->type = STT_OBJECT;
 
       if (! info->executable
-         && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+         && ! bfd_elf_link_record_dynamic_symbol (info, h))
        return FALSE;
     }
 
@@ -2714,16 +2871,17 @@ elf32_frv_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
       || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
     return FALSE;
   /* FRV-specific: remember it.  */
-  frv_pltrel_section (info) = s;
+  frvfdpic_pltrel_section (info) = s;
 
   /* FRV-specific: we want to create the GOT in the FRV way.  */
   if (! _frv_create_got_section (abfd, info))
     return FALSE;
 
   /* FRV-specific: make sure we created everything we wanted.  */
-  BFD_ASSERT (frv_got_section (info) && frv_gotrel_section (info)
-             && frv_gotfixup_section (info)
-             && frv_plt_section (info) && frv_pltrel_section (info));
+  BFD_ASSERT (frvfdpic_got_section (info) && frvfdpic_gotrel_section (info)
+             && frvfdpic_gotfixup_section (info)
+             && frvfdpic_plt_section (info)
+             && frvfdpic_pltrel_section (info));
 
   if (bed->want_dynbss)
     {
@@ -2773,7 +2931,7 @@ elf32_frv_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
 
 /* This structure is used to collect the number of entries present in
    each addressable range of the got.  */
-struct _frv_dynamic_got_info
+struct _frvfdpic_dynamic_got_info
 {
   /* Several bits of information about the current link.  */
   struct bfd_link_info *info;
@@ -2801,10 +2959,11 @@ struct _frv_dynamic_got_info
    private function descriptors taking two words.  */
 
 static int
-_frv_count_got_plt_entries (void **entryp, void *dinfo_)
+_frvfdpic_count_got_plt_entries (void **entryp, void *dinfo_)
 {
-  struct frv_pic_relocs_info *entry = *entryp;
-  struct _frv_dynamic_got_info *dinfo = dinfo_;
+  struct frvfdpic_relocs_info *entry = *entryp;
+  struct _frvfdpic_dynamic_got_info *dinfo = dinfo_;
+  unsigned relocs = 0, fixups = 0;
 
   /* Allocate space for a GOT entry pointing to the symbol.  */
   if (entry->got12)
@@ -2832,15 +2991,15 @@ _frv_count_got_plt_entries (void **entryp, void *dinfo_)
   /* Decide whether we need a PLT entry, a function descriptor in the
      GOT, and a lazy PLT entry for this symbol.  */
   entry->plt = entry->call
-    && entry->symndx == -1 && ! FRV_SYM_LOCAL (dinfo->info, entry->d.h)
+    && entry->symndx == -1 && ! FRVFDPIC_SYM_LOCAL (dinfo->info, entry->d.h)
     && elf_hash_table (dinfo->info)->dynamic_sections_created;
   entry->privfd = entry->plt
     || entry->fdgoff12 || entry->fdgofflos || entry->fdgoffhilo
     || ((entry->fd || entry->fdgot12 || entry->fdgotlos || entry->fdgothilo)
        && (entry->symndx != -1
-           || FRV_FUNCDESC_LOCAL (dinfo->info, entry->d.h)));
+           || FRVFDPIC_FUNCDESC_LOCAL (dinfo->info, entry->d.h)));
   entry->lazyplt = entry->privfd
-    && entry->symndx == -1 && ! FRV_SYM_LOCAL (dinfo->info, entry->d.h)
+    && entry->symndx == -1 && ! FRVFDPIC_SYM_LOCAL (dinfo->info, entry->d.h)
     && ! (dinfo->info->flags & DF_BIND_NOW)
     && elf_hash_table (dinfo->info)->dynamic_sections_created;
 
@@ -2861,37 +3020,44 @@ _frv_count_got_plt_entries (void **entryp, void *dinfo_)
     dinfo->lzplt += 8;
 
   if (!dinfo->info->executable || dinfo->info->pie)
-    dinfo->relocs += entry->relocs32 + entry->relocsfd + entry->relocsfdv;
+    relocs = entry->relocs32 + entry->relocsfd + entry->relocsfdv;
   else
     {
-      if (entry->symndx != -1 || FRV_SYM_LOCAL (dinfo->info, entry->d.h))
+      if (entry->symndx != -1 || FRVFDPIC_SYM_LOCAL (dinfo->info, entry->d.h))
        {
          if (entry->symndx != -1
-             || entry->d.h->root.type != bfd_link_hash_undefweak)        
-           dinfo->fixups += entry->relocs32 + 2 * entry->relocsfdv;
+             || entry->d.h->root.type != bfd_link_hash_undefweak)
+           fixups += entry->relocs32 + 2 * entry->relocsfdv;
        }
       else
-       dinfo->relocs += entry->relocs32 + entry->relocsfdv;
-      if (entry->symndx != -1 || FRV_FUNCDESC_LOCAL (dinfo->info, entry->d.h))
+       relocs += entry->relocs32 + entry->relocsfdv;
+
+      if (entry->symndx != -1
+         || FRVFDPIC_FUNCDESC_LOCAL (dinfo->info, entry->d.h))
        {
          if (entry->symndx != -1
              || entry->d.h->root.type != bfd_link_hash_undefweak)
-           dinfo->fixups += entry->relocsfd;
+           fixups += entry->relocsfd;
        }
       else
-       dinfo->relocs += entry->relocsfd;
+       relocs += entry->relocsfd;
     }
 
+  entry->dynrelocs += relocs;
+  entry->fixups += fixups;
+  dinfo->relocs += relocs;
+  dinfo->fixups += fixups;
+
   return 1;
 }
 
 /* This structure is used to assign offsets to got entries, function
    descriptors, plt entries and lazy plt entries.  */
 
-struct _frv_dynamic_got_plt_info
+struct _frvfdpic_dynamic_got_plt_info
 {
-  /* Summary information collected with _frv_count_got_plt_entries.  */
-  struct _frv_dynamic_got_info g;
+  /* Summary information collected with _frvfdpic_count_got_plt_entries.  */
+  struct _frvfdpic_dynamic_got_info g;
 
   /* For each addressable range, we record a MAX (positive) and MIN
      (negative) value.  CUR is used to assign got entries, and it's
@@ -2907,7 +3073,7 @@ struct _frv_dynamic_got_plt_info
      descriptor is chosen.  FDPLT indicates the number of remaining
      slots that can be used for function descriptors used only by PLT
      entries.  */
-  struct _frv_dynamic_got_alloc_data
+  struct _frvfdpic_dynamic_got_alloc_data
   {
     bfd_signed_vma max, cur, odd, fdcur, min;
     bfd_vma fdplt;
@@ -2925,14 +3091,14 @@ struct _frv_dynamic_got_plt_info
    descriptors.  */
 
 inline static bfd_signed_vma
-_frv_compute_got_alloc_data (struct _frv_dynamic_got_alloc_data *gad,
-                            bfd_signed_vma fdcur,
-                            bfd_signed_vma odd,
-                            bfd_signed_vma cur,
-                            bfd_vma got,
-                            bfd_vma fd,
-                            bfd_vma fdplt,
-                            bfd_vma wrap)
+_frvfdpic_compute_got_alloc_data (struct _frvfdpic_dynamic_got_alloc_data *gad,
+                                 bfd_signed_vma fdcur,
+                                 bfd_signed_vma odd,
+                                 bfd_signed_vma cur,
+                                 bfd_vma got,
+                                 bfd_vma fd,
+                                 bfd_vma fdplt,
+                                 bfd_vma wrap)
 {
   bfd_signed_vma wrapmin = -wrap;
 
@@ -3026,7 +3192,7 @@ _frv_compute_got_alloc_data (struct _frv_dynamic_got_alloc_data *gad,
   if (odd > gad->max)
     odd = gad->min + odd - gad->max;
 
-  /* _frv_get_got_entry() below will always wrap gad->cur if needed
+  /* _frvfdpic_get_got_entry() below will always wrap gad->cur if needed
      before returning, so do it here too.  This guarantees that,
      should cur and fdcur meet at the wrap point, they'll both be
      equal to min.  */
@@ -3040,7 +3206,7 @@ _frv_compute_got_alloc_data (struct _frv_dynamic_got_alloc_data *gad,
    data for a range.  */
 
 inline static bfd_signed_vma
-_frv_get_got_entry (struct _frv_dynamic_got_alloc_data *gad)
+_frvfdpic_get_got_entry (struct _frvfdpic_dynamic_got_alloc_data *gad)
 {
   bfd_signed_vma ret;
   
@@ -3069,7 +3235,7 @@ _frv_get_got_entry (struct _frv_dynamic_got_alloc_data *gad)
    GOT, given the allocation data for a range.  */
 
 inline static bfd_signed_vma
-_frv_get_fd_entry (struct _frv_dynamic_got_alloc_data *gad)
+_frvfdpic_get_fd_entry (struct _frvfdpic_dynamic_got_alloc_data *gad)
 {
   /* If we're at the bottom, wrap around, and only then allocate the
      next pair of words.  */
@@ -3082,46 +3248,46 @@ _frv_get_fd_entry (struct _frv_dynamic_got_alloc_data *gad)
    Doing everything in a single pass is tricky.  */
 
 static int
-_frv_assign_got_entries (void **entryp, void *info_)
+_frvfdpic_assign_got_entries (void **entryp, void *info_)
 {
-  struct frv_pic_relocs_info *entry = *entryp;
-  struct _frv_dynamic_got_plt_info *dinfo = info_;
+  struct frvfdpic_relocs_info *entry = *entryp;
+  struct _frvfdpic_dynamic_got_plt_info *dinfo = info_;
 
   if (entry->got12)
-    entry->got_entry = _frv_get_got_entry (&dinfo->got12);
+    entry->got_entry = _frvfdpic_get_got_entry (&dinfo->got12);
   else if (entry->gotlos)
-    entry->got_entry = _frv_get_got_entry (&dinfo->gotlos);
+    entry->got_entry = _frvfdpic_get_got_entry (&dinfo->gotlos);
   else if (entry->gothilo)
-    entry->got_entry = _frv_get_got_entry (&dinfo->gothilo);
+    entry->got_entry = _frvfdpic_get_got_entry (&dinfo->gothilo);
 
   if (entry->fdgot12)
-    entry->fdgot_entry = _frv_get_got_entry (&dinfo->got12);
+    entry->fdgot_entry = _frvfdpic_get_got_entry (&dinfo->got12);
   else if (entry->fdgotlos)
-    entry->fdgot_entry = _frv_get_got_entry (&dinfo->gotlos);
+    entry->fdgot_entry = _frvfdpic_get_got_entry (&dinfo->gotlos);
   else if (entry->fdgothilo)
-    entry->fdgot_entry = _frv_get_got_entry (&dinfo->gothilo);
+    entry->fdgot_entry = _frvfdpic_get_got_entry (&dinfo->gothilo);
 
   if (entry->fdgoff12)
-    entry->fd_entry = _frv_get_fd_entry (&dinfo->got12);
+    entry->fd_entry = _frvfdpic_get_fd_entry (&dinfo->got12);
   else if (entry->plt && dinfo->got12.fdplt)
     {
       dinfo->got12.fdplt -= 8;
-      entry->fd_entry = _frv_get_fd_entry (&dinfo->got12);
+      entry->fd_entry = _frvfdpic_get_fd_entry (&dinfo->got12);
     }
   else if (entry->fdgofflos)
-    entry->fd_entry = _frv_get_fd_entry (&dinfo->gotlos);
+    entry->fd_entry = _frvfdpic_get_fd_entry (&dinfo->gotlos);
   else if (entry->plt && dinfo->gotlos.fdplt)
     {
       dinfo->gotlos.fdplt -= 8;
-      entry->fd_entry = _frv_get_fd_entry (&dinfo->gotlos);
+      entry->fd_entry = _frvfdpic_get_fd_entry (&dinfo->gotlos);
     }
   else if (entry->plt)
     {
       dinfo->gothilo.fdplt -= 8;
-      entry->fd_entry = _frv_get_fd_entry (&dinfo->gothilo);
+      entry->fd_entry = _frvfdpic_get_fd_entry (&dinfo->gothilo);
     }
   else if (entry->privfd)
-    entry->fd_entry = _frv_get_fd_entry (&dinfo->gothilo);
+    entry->fd_entry = _frvfdpic_get_fd_entry (&dinfo->gothilo);
   
   return 1;
 }
@@ -3131,10 +3297,10 @@ _frv_assign_got_entries (void **entryp, void *info_)
    and lazy PLT entries.  */
 
 static int
-_frv_assign_plt_entries (void **entryp, void *info_)
+_frvfdpic_assign_plt_entries (void **entryp, void *info_)
 {
-  struct frv_pic_relocs_info *entry = *entryp;
-  struct _frv_dynamic_got_plt_info *dinfo = info_;
+  struct frvfdpic_relocs_info *entry = *entryp;
+  struct _frvfdpic_dynamic_got_plt_info *dinfo = info_;
 
   /* If this symbol requires a local function descriptor, allocate
      one.  */
@@ -3142,18 +3308,18 @@ _frv_assign_plt_entries (void **entryp, void *info_)
     {
       if (dinfo->got12.fdplt)
        {
-         entry->fd_entry = _frv_get_fd_entry (&dinfo->got12);
+         entry->fd_entry = _frvfdpic_get_fd_entry (&dinfo->got12);
          dinfo->got12.fdplt -= 8;
        }
       else if (dinfo->gotlos.fdplt)
        {
-         entry->fd_entry = _frv_get_fd_entry (&dinfo->gotlos);
+         entry->fd_entry = _frvfdpic_get_fd_entry (&dinfo->gotlos);
          dinfo->gotlos.fdplt -= 8;
        }
       else
        {
          BFD_ASSERT (dinfo->gothilo.fdplt)
-         entry->fd_entry = _frv_get_fd_entry (&dinfo->gothilo);
+         entry->fd_entry = _frvfdpic_get_fd_entry (&dinfo->gothilo);
          dinfo->gothilo.fdplt -= 8;
        }
     }
@@ -3164,7 +3330,7 @@ _frv_assign_plt_entries (void **entryp, void *info_)
 
       /* We use the section's raw size to mark the location of the
         next PLT entry.  */
-      entry->plt_entry = frv_plt_section (dinfo->g.info)->_raw_size;
+      entry->plt_entry = frvfdpic_plt_section (dinfo->g.info)->_raw_size;
 
       /* Figure out the length of this PLT entry based on the
         addressing mode we need to reach the function descriptor.  */
@@ -3178,7 +3344,7 @@ _frv_assign_plt_entries (void **entryp, void *info_)
       else
        size = 16;
 
-      frv_plt_section (dinfo->g.info)->_raw_size += size;
+      frvfdpic_plt_section (dinfo->g.info)->_raw_size += size;
     }
 
   if (entry->lazyplt)
@@ -3187,7 +3353,8 @@ _frv_assign_plt_entries (void **entryp, void *info_)
       dinfo->g.lzplt += 8;
       /* If this entry is the one that gets the resolver stub, account
         for the additional instruction.  */
-      if (entry->lzplt_entry % FRV_LZPLT_BLOCK_SIZE == FRV_LZPLT_RESOLV_LOC)
+      if (entry->lzplt_entry % FRVFDPIC_LZPLT_BLOCK_SIZE
+         == FRVFDPIC_LZPLT_RESOLV_LOC)
        dinfo->g.lzplt += 4;
     }
       
@@ -3201,14 +3368,15 @@ _frv_assign_plt_entries (void **entryp, void *info_)
    we've made a potentially-destructive change to the hash table, so
    the traversal must be restarted.  */
 static int
-_frv_resolve_final_relocs_info (void **entryp, void *p)
+_frvfdpic_resolve_final_relocs_info (void **entryp, void *p)
 {
-  struct frv_pic_relocs_info *entry = *entryp;
+  struct frvfdpic_relocs_info *entry = *entryp;
   htab_t *htab = p;
 
   if (entry->symndx == -1)
     {
       struct elf_link_hash_entry *h = entry->d.h;
+      struct frvfdpic_relocs_info *oentry;
 
       while (h->root.type == bfd_link_hash_indirect
             || h->root.type == bfd_link_hash_warning)
@@ -3217,6 +3385,17 @@ _frv_resolve_final_relocs_info (void **entryp, void *p)
       if (entry->d.h == h)
        return 1;
 
+      oentry = frvfdpic_relocs_info_for_global (*htab, 0, h, entry->addend,
+                                               NO_INSERT);
+
+      if (oentry)
+       {
+         /* Merge the two entries.  */
+         frvfdpic_pic_merge_early_relocs_info (oentry, entry);
+         htab_clear_slot (*htab, entryp);
+         return 1;
+       }
+
       entry->d.h = h;
 
       /* If we can't find this entry with the new bfd hash, re-insert
@@ -3241,12 +3420,12 @@ _frv_resolve_final_relocs_info (void **entryp, void *p)
 /* Set the sizes of the dynamic sections.  */
 
 static bfd_boolean
-elf32_frv_size_dynamic_sections (bfd *output_bfd,
-                                struct bfd_link_info *info)
+elf32_frvfdpic_size_dynamic_sections (bfd *output_bfd,
+                                     struct bfd_link_info *info)
 {
   bfd *dynobj;
   asection *s;
-  struct _frv_dynamic_got_plt_info gpinfo;
+  struct _frvfdpic_dynamic_got_plt_info gpinfo;
   bfd_signed_vma odd;
   bfd_vma limit;
 
@@ -3270,15 +3449,15 @@ elf32_frv_size_dynamic_sections (bfd *output_bfd,
 
   for (;;)
     {
-      htab_t relocs = frv_relocs_info (info);
+      htab_t relocs = frvfdpic_relocs_info (info);
 
-      htab_traverse (relocs, _frv_resolve_final_relocs_info, &relocs);
+      htab_traverse (relocs, _frvfdpic_resolve_final_relocs_info, &relocs);
 
-      if (relocs == frv_relocs_info (info))
+      if (relocs == frvfdpic_relocs_info (info))
        break;
     }
 
-  htab_traverse (frv_relocs_info (info), _frv_count_got_plt_entries,
+  htab_traverse (frvfdpic_relocs_info (info), _frvfdpic_count_got_plt_entries,
                 &gpinfo.g);
 
   odd = 12;
@@ -3297,164 +3476,171 @@ elf32_frv_size_dynamic_sections (bfd *output_bfd,
 
   /* Determine the ranges of GOT offsets that we can use for each
      range of addressing modes.  */
-  odd = _frv_compute_got_alloc_data (&gpinfo.got12,
-                                    0,
-                                    odd,
-                                    16,
-                                    gpinfo.g.got12,
-                                    gpinfo.g.fd12,
-                                    limit,
-                                    (bfd_vma)1 << (12-1));
-  odd = _frv_compute_got_alloc_data (&gpinfo.gotlos,
-                                    gpinfo.got12.min,
-                                    odd,
-                                    gpinfo.got12.max,
-                                    gpinfo.g.gotlos,
-                                    gpinfo.g.fdlos,
-                                    gpinfo.g.fdplt - gpinfo.got12.fdplt,
-                                    (bfd_vma)1 << (16-1));
-  odd = _frv_compute_got_alloc_data (&gpinfo.gothilo,
-                                    gpinfo.gotlos.min,
-                                    odd,
-                                    gpinfo.gotlos.max,
-                                    gpinfo.g.gothilo,
-                                    gpinfo.g.fdhilo,
-                                    gpinfo.g.fdplt - gpinfo.got12.fdplt
-                                    - gpinfo.gotlos.fdplt,
-                                    (bfd_vma)1 << (32-1));
+  odd = _frvfdpic_compute_got_alloc_data (&gpinfo.got12,
+                                         0,
+                                         odd,
+                                         16,
+                                         gpinfo.g.got12,
+                                         gpinfo.g.fd12,
+                                         limit,
+                                         (bfd_vma)1 << (12-1));
+  odd = _frvfdpic_compute_got_alloc_data (&gpinfo.gotlos,
+                                         gpinfo.got12.min,
+                                         odd,
+                                         gpinfo.got12.max,
+                                         gpinfo.g.gotlos,
+                                         gpinfo.g.fdlos,
+                                         gpinfo.g.fdplt - gpinfo.got12.fdplt,
+                                         (bfd_vma)1 << (16-1));
+  odd = _frvfdpic_compute_got_alloc_data (&gpinfo.gothilo,
+                                         gpinfo.gotlos.min,
+                                         odd,
+                                         gpinfo.gotlos.max,
+                                         gpinfo.g.gothilo,
+                                         gpinfo.g.fdhilo,
+                                         gpinfo.g.fdplt - gpinfo.got12.fdplt
+                                         - gpinfo.gotlos.fdplt,
+                                         (bfd_vma)1 << (32-1));
 
   /* Now assign (most) GOT offsets.  */
-  htab_traverse (frv_relocs_info (info), _frv_assign_got_entries, &gpinfo);
+  htab_traverse (frvfdpic_relocs_info (info), _frvfdpic_assign_got_entries,
+                &gpinfo);
 
-  frv_got_section (info)->_raw_size = gpinfo.gothilo.max - gpinfo.gothilo.min
+  frvfdpic_got_section (info)->_raw_size = gpinfo.gothilo.max
+    - gpinfo.gothilo.min
     /* If an odd word is the last word of the GOT, we don't need this
        word to be part of the GOT.  */
     - (odd + 4 == gpinfo.gothilo.max ? 4 : 0);
-  if (frv_got_section (info)->_raw_size == 0)
-    frv_got_section (info)->flags |= SEC_EXCLUDE;
-  else if (frv_got_section (info)->_raw_size == 12
+  if (frvfdpic_got_section (info)->_raw_size == 0)
+    frvfdpic_got_section (info)->flags |= SEC_EXCLUDE;
+  else if (frvfdpic_got_section (info)->_raw_size == 12
           && ! elf_hash_table (info)->dynamic_sections_created)
     {
-      frv_got_section (info)->flags |= SEC_EXCLUDE;
-      frv_got_section (info)->_raw_size = 0;
+      frvfdpic_got_section (info)->flags |= SEC_EXCLUDE;
+      frvfdpic_got_section (info)->_raw_size = 0;
     }
   else
     {
-      frv_got_section (info)->contents =
-       (bfd_byte *) bfd_zalloc (dynobj, frv_got_section (info)->_raw_size);
-      if (frv_got_section (info)->contents == NULL)
+      frvfdpic_got_section (info)->contents =
+       (bfd_byte *) bfd_zalloc (dynobj,
+                                frvfdpic_got_section (info)->_raw_size);
+      if (frvfdpic_got_section (info)->contents == NULL)
        return FALSE;
     }
   
   if (elf_hash_table (info)->dynamic_sections_created)
     /* Subtract the number of lzplt entries, since those will generate
        relocations in the pltrel section.  */
-    frv_gotrel_section (info)->_raw_size =
+    frvfdpic_gotrel_section (info)->_raw_size =
       (gpinfo.g.relocs - gpinfo.g.lzplt / 8)
       * get_elf_backend_data (output_bfd)->s->sizeof_rel;
   else
     BFD_ASSERT (gpinfo.g.relocs == 0);
-  if (frv_gotrel_section (info)->_raw_size == 0)
-    frv_gotrel_section (info)->flags |= SEC_EXCLUDE;
+  if (frvfdpic_gotrel_section (info)->_raw_size == 0)
+    frvfdpic_gotrel_section (info)->flags |= SEC_EXCLUDE;
   else
     {
-      frv_gotrel_section (info)->contents =
-       (bfd_byte *) bfd_zalloc (dynobj, frv_gotrel_section (info)->_raw_size);
-      if (frv_gotrel_section (info)->contents == NULL)
+      frvfdpic_gotrel_section (info)->contents =
+       (bfd_byte *) bfd_zalloc (dynobj,
+                                frvfdpic_gotrel_section (info)->_raw_size);
+      if (frvfdpic_gotrel_section (info)->contents == NULL)
        return FALSE;
     }
 
-  if (elf_elfheader (output_bfd)->e_flags & EF_FRV_FDPIC)
-    frv_gotfixup_section (info)->_raw_size = (gpinfo.g.fixups + 1) * 4;
-  if (frv_gotfixup_section (info)->_raw_size == 0)
-    frv_gotfixup_section (info)->flags |= SEC_EXCLUDE;
+  frvfdpic_gotfixup_section (info)->_raw_size = (gpinfo.g.fixups + 1) * 4;
+  if (frvfdpic_gotfixup_section (info)->_raw_size == 0)
+    frvfdpic_gotfixup_section (info)->flags |= SEC_EXCLUDE;
   else
     {
-      frv_gotfixup_section (info)->contents =
+      frvfdpic_gotfixup_section (info)->contents =
        (bfd_byte *) bfd_zalloc (dynobj,
-                                frv_gotfixup_section (info)->_raw_size);
-      if (frv_gotfixup_section (info)->contents == NULL)
+                                frvfdpic_gotfixup_section (info)->_raw_size);
+      if (frvfdpic_gotfixup_section (info)->contents == NULL)
        return FALSE;
     }
   
   if (elf_hash_table (info)->dynamic_sections_created)
     {
-      frv_pltrel_section (info)->_raw_size =
+      frvfdpic_pltrel_section (info)->_raw_size =
        gpinfo.g.lzplt / 8 * get_elf_backend_data (output_bfd)->s->sizeof_rel;
-      if (frv_pltrel_section (info)->_raw_size == 0)
-       frv_pltrel_section (info)->flags |= SEC_EXCLUDE;
+      if (frvfdpic_pltrel_section (info)->_raw_size == 0)
+       frvfdpic_pltrel_section (info)->flags |= SEC_EXCLUDE;
       else
        {
-         frv_pltrel_section (info)->contents =
+         frvfdpic_pltrel_section (info)->contents =
            (bfd_byte *) bfd_zalloc (dynobj,
-                                    frv_pltrel_section (info)->_raw_size);
-         if (frv_pltrel_section (info)->contents == NULL)
+                                    frvfdpic_pltrel_section (info)
+                                    ->_raw_size);
+         if (frvfdpic_pltrel_section (info)->contents == NULL)
            return FALSE;
        }
     }
   
   /* Add 4 bytes for every block of at most 65535 lazy PLT entries,
      such that there's room for the additional instruction needed to
-     call the resolver.  Since _frv_assign_got_entries didn't account
-     for them, our block size is 4 bytes smaller than the real block
-     size.  */
+     call the resolver.  Since _frvfdpic_assign_got_entries didn't
+     account for them, our block size is 4 bytes smaller than the real
+     block size.  */
   if (elf_hash_table (info)->dynamic_sections_created)
     {
-      frv_plt_section (info)->_raw_size = gpinfo.g.lzplt
-       + ((gpinfo.g.lzplt + (FRV_LZPLT_BLOCK_SIZE - 4) - 8)
-          / (FRV_LZPLT_BLOCK_SIZE - 4) * 4);
+      frvfdpic_plt_section (info)->_raw_size = gpinfo.g.lzplt
+       + ((gpinfo.g.lzplt + (FRVFDPIC_LZPLT_BLOCK_SIZE - 4) - 8)
+          / (FRVFDPIC_LZPLT_BLOCK_SIZE - 4) * 4);
     }
 
-  /* Reset it, such that _frv_assign_plt_entries() can use it to
+  /* Reset it, such that _frvfdpic_assign_plt_entries() can use it to
      actually assign lazy PLT entries addresses.  */
   gpinfo.g.lzplt = 0;
 
   /* Save information that we're going to need to generate GOT and PLT
      entries.  */
-  frv_got_initial_offset (info) = -gpinfo.gothilo.min;
+  frvfdpic_got_initial_offset (info) = -gpinfo.gothilo.min;
 
   if (get_elf_backend_data (output_bfd)->want_got_sym)
     elf_hash_table (info)->hgot->root.u.def.value
-      += frv_got_initial_offset (info);
+      += frvfdpic_got_initial_offset (info);
 
   if (elf_hash_table (info)->dynamic_sections_created)
-    frv_plt_initial_offset (info) = frv_plt_section (info)->_raw_size;
+    frvfdpic_plt_initial_offset (info) =
+      frvfdpic_plt_section (info)->_raw_size;
 
-  htab_traverse (frv_relocs_info (info), _frv_assign_plt_entries, &gpinfo);
+  htab_traverse (frvfdpic_relocs_info (info), _frvfdpic_assign_plt_entries,
+                &gpinfo);
 
   /* Allocate the PLT section contents only after
-     _frv_assign_plt_entries has a chance to add the size of the
+     _frvfdpic_assign_plt_entries has a chance to add the size of the
      non-lazy PLT entries.  */
   if (elf_hash_table (info)->dynamic_sections_created)
     {
-      if (frv_plt_section (info)->_raw_size == 0)
-       frv_plt_section (info)->flags |= SEC_EXCLUDE;
+      if (frvfdpic_plt_section (info)->_raw_size == 0)
+       frvfdpic_plt_section (info)->flags |= SEC_EXCLUDE;
       else
        {
-         frv_plt_section (info)->contents =
-           (bfd_byte *) bfd_zalloc (dynobj, frv_plt_section (info)->_raw_size);
-         if (frv_plt_section (info)->contents == NULL)
+         frvfdpic_plt_section (info)->contents =
+           (bfd_byte *) bfd_zalloc (dynobj,
+                                    frvfdpic_plt_section (info)->_raw_size);
+         if (frvfdpic_plt_section (info)->contents == NULL)
            return FALSE;
        }
     }
 
   if (elf_hash_table (info)->dynamic_sections_created)
     {
-      if (frv_got_section (info)->_raw_size)
-       if (! bfd_elf32_add_dynamic_entry (info, DT_PLTGOT, 0))
+      if (frvfdpic_got_section (info)->_raw_size)
+       if (!_bfd_elf_add_dynamic_entry (info, DT_PLTGOT, 0))
          return FALSE;
 
-      if (frv_pltrel_section (info)->_raw_size)
-       if (! bfd_elf32_add_dynamic_entry (info, DT_PLTRELSZ, 0)
-           || ! bfd_elf32_add_dynamic_entry (info, DT_PLTREL, DT_REL)
-           || ! bfd_elf32_add_dynamic_entry (info, DT_JMPREL, 0))
+      if (frvfdpic_pltrel_section (info)->_raw_size)
+       if (!_bfd_elf_add_dynamic_entry (info, DT_PLTRELSZ, 0)
+           || !_bfd_elf_add_dynamic_entry (info, DT_PLTREL, DT_REL)
+           || !_bfd_elf_add_dynamic_entry (info, DT_JMPREL, 0))
          return FALSE;
 
-      if (frv_gotrel_section (info)->_raw_size)
-       if (! bfd_elf32_add_dynamic_entry (info, DT_REL, 0)
-           || ! bfd_elf32_add_dynamic_entry (info, DT_RELSZ, 0)
-           || ! bfd_elf32_add_dynamic_entry (info, DT_RELENT,
-                                             sizeof (Elf32_External_Rel)))
+      if (frvfdpic_gotrel_section (info)->_raw_size)
+       if (!_bfd_elf_add_dynamic_entry (info, DT_REL, 0)
+           || !_bfd_elf_add_dynamic_entry (info, DT_RELSZ, 0)
+           || !_bfd_elf_add_dynamic_entry (info, DT_RELENT,
+                                           sizeof (Elf32_External_Rel)))
          return FALSE;
     }
 
@@ -3462,11 +3648,10 @@ elf32_frv_size_dynamic_sections (bfd *output_bfd,
 }
 
 static bfd_boolean
-elf32_frv_always_size_sections (bfd *output_bfd,
-                               struct bfd_link_info *info)
+elf32_frvfdpic_always_size_sections (bfd *output_bfd,
+                                    struct bfd_link_info *info)
 {
-  if (!info->relocatable
-      && elf_elfheader (output_bfd)->e_flags & EF_FRV_FDPIC)
+  if (!info->relocatable)
     {
       struct elf_link_hash_entry *h;
       asection *sec;
@@ -3508,45 +3693,47 @@ elf32_frv_always_size_sections (bfd *output_bfd,
 }
 
 static bfd_boolean
-elf32_frv_modify_segment_map (bfd *output_bfd,
-                             struct bfd_link_info *info)
+elf32_frvfdpic_modify_segment_map (bfd *output_bfd,
+                                  struct bfd_link_info *info)
 {
-  if (elf_elfheader (output_bfd)->e_flags & EF_FRV_FDPIC)
-    {
-      struct elf_segment_map *m;
+  struct elf_segment_map *m;
 
-      for (m = elf_tdata (output_bfd)->segment_map; m != NULL; m = m->next)
-       if (m->p_type == PT_GNU_STACK)
-         break;
+  /* objcopy and strip preserve what's already there using
+     elf32_frvfdpic_copy_private_bfd_data ().  */
+  if (! info)
+    return TRUE;
 
-      if (m)
+  for (m = elf_tdata (output_bfd)->segment_map; m != NULL; m = m->next)
+    if (m->p_type == PT_GNU_STACK)
+      break;
+
+  if (m)
+    {
+      asection *sec = bfd_get_section_by_name (output_bfd, ".stack");
+      struct elf_link_hash_entry *h;
+
+      if (sec)
        {
-         asection *sec = bfd_get_section_by_name (output_bfd, ".stack");
-         struct elf_link_hash_entry *h;
+         /* Obtain the pointer to the __stacksize symbol.  */
+         h = elf_link_hash_lookup (elf_hash_table (info), "__stacksize",
+                                   FALSE, FALSE, FALSE);
+         while (h->root.type == bfd_link_hash_indirect
+                || h->root.type == bfd_link_hash_warning)
+           h = (struct elf_link_hash_entry *)h->root.u.i.link;
+         BFD_ASSERT (h->root.type == bfd_link_hash_defined);
 
-         if (sec)
-           {
-             /* Obtain the pointer to the __stacksize symbol.  */
-             h = elf_link_hash_lookup (elf_hash_table (info), "__stacksize",
-                                       FALSE, FALSE, FALSE);
-             while (h->root.type == bfd_link_hash_indirect
-                    || h->root.type == bfd_link_hash_warning)
-               h = (struct elf_link_hash_entry *)h->root.u.i.link;
-             BFD_ASSERT (h->root.type == bfd_link_hash_defined);
-
-             /* Set the section size from the symbol value.  We
-                intentionally ignore the symbol section.  */
-             if (h->root.type == bfd_link_hash_defined)
-               sec->_raw_size = h->root.u.def.value;
-             else
-               sec->_raw_size = DEFAULT_STACK_SIZE;
+         /* Set the section size from the symbol value.  We
+            intentionally ignore the symbol section.  */
+         if (h->root.type == bfd_link_hash_defined)
+           sec->_raw_size = h->root.u.def.value;
+         else
+           sec->_raw_size = DEFAULT_STACK_SIZE;
 
-             /* Add the stack section to the PT_GNU_STACK segment,
-                such that its size and alignment requirements make it
-                to the segment.  */
-             m->sections[m->count] = sec;
-             m->count++;
-           }
+         /* Add the stack section to the PT_GNU_STACK segment,
+            such that its size and alignment requirements make it
+            to the segment.  */
+         m->sections[m->count] = sec;
+         m->count++;
        }
     }
 
@@ -3556,51 +3743,51 @@ elf32_frv_modify_segment_map (bfd *output_bfd,
 /* Fill in code and data in dynamic sections.  */
 
 static bfd_boolean
-elf32_frv_finish_dynamic_sections (bfd *output_bfd,
-                                  struct bfd_link_info *info)
+elf32_frv_finish_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+                                  struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+  /* Nothing to be done for non-FDPIC.  */
+  return TRUE;
+}
+
+static bfd_boolean
+elf32_frvfdpic_finish_dynamic_sections (bfd *output_bfd,
+                                       struct bfd_link_info *info)
 {
   bfd *dynobj;
   asection *sdyn;
 
   dynobj = elf_hash_table (info)->dynobj;
 
-  if (frv_got_section (info))
+  if (frvfdpic_got_section (info))
     {
-      BFD_ASSERT (frv_gotrel_section (info)->_raw_size
-                 == (frv_gotrel_section (info)->reloc_count
+      BFD_ASSERT (frvfdpic_gotrel_section (info)->_raw_size
+                 == (frvfdpic_gotrel_section (info)->reloc_count
                      * sizeof (Elf32_External_Rel)));
 
-      if (frv_gotfixup_section (info))
+      if (frvfdpic_gotfixup_section (info))
        {
-         if (elf_elfheader (output_bfd)->e_flags & EF_FRV_FDPIC)
-           {
-             struct elf_link_hash_entry *hgot = elf_hash_table (info)->hgot;
-             bfd_vma got_value = hgot->root.u.def.value
-               + hgot->root.u.def.section->output_section->vma
-               + hgot->root.u.def.section->output_offset;
+         struct elf_link_hash_entry *hgot = elf_hash_table (info)->hgot;
+         bfd_vma got_value = hgot->root.u.def.value
+           + hgot->root.u.def.section->output_section->vma
+           + hgot->root.u.def.section->output_offset;
 
-             _frv_add_rofixup (output_bfd, frv_gotfixup_section (info),
-                               got_value);
-           }
+         _frvfdpic_add_rofixup (output_bfd, frvfdpic_gotfixup_section (info),
+                                got_value, 0);
 
-         if (frv_gotfixup_section (info)->_raw_size
-             != (frv_gotfixup_section (info)->reloc_count * 4))
+         if (frvfdpic_gotfixup_section (info)->_raw_size
+             != (frvfdpic_gotfixup_section (info)->reloc_count * 4))
            {
-             if (!elf_hash_table (info)->dynamic_sections_created)
-               {
-                 info->callbacks->warning
-                   (info, "no dynamic sections, missing -melf32frvfd?",
-                    ".rofixup", NULL, NULL, 0);
-                 return FALSE;
-               }
-             BFD_ASSERT (0);
+             (*_bfd_error_handler)
+               ("LINKER BUG: .rofixup section size mismatch");
+             return FALSE;
            }
        }
     }
   if (elf_hash_table (info)->dynamic_sections_created)
     {
-      BFD_ASSERT (frv_pltrel_section (info)->_raw_size
-                 == (frv_pltrel_section (info)->reloc_count
+      BFD_ASSERT (frvfdpic_pltrel_section (info)->_raw_size
+                 == (frvfdpic_pltrel_section (info)->reloc_count
                      * sizeof (Elf32_External_Rel)));
     }
 
@@ -3628,23 +3815,24 @@ elf32_frv_finish_dynamic_sections (bfd *output_bfd,
              break;
 
            case DT_PLTGOT:
-             dyn.d_un.d_ptr = frv_got_section (info)->output_section->vma
-               + frv_got_section (info)->output_offset
-               + frv_got_initial_offset (info);
+             dyn.d_un.d_ptr = frvfdpic_got_section (info)->output_section->vma
+               + frvfdpic_got_section (info)->output_offset
+               + frvfdpic_got_initial_offset (info);
              bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
              break;
 
            case DT_JMPREL:
-             dyn.d_un.d_ptr = frv_pltrel_section (info)->output_section->vma
-               + frv_pltrel_section (info)->output_offset;
+             dyn.d_un.d_ptr = frvfdpic_pltrel_section (info)
+               ->output_section->vma
+               + frvfdpic_pltrel_section (info)->output_offset;
              bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
              break;
 
            case DT_PLTRELSZ:
-             if (frv_pltrel_section (info)->_cooked_size != 0)
-               dyn.d_un.d_val = frv_pltrel_section (info)->_cooked_size;
+             if (frvfdpic_pltrel_section (info)->_cooked_size != 0)
+               dyn.d_un.d_val = frvfdpic_pltrel_section (info)->_cooked_size;
              else
-               dyn.d_un.d_val = frv_pltrel_section (info)->_raw_size;
+               dyn.d_un.d_val = frvfdpic_pltrel_section (info)->_raw_size;
              bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
              break;
            }
@@ -3658,8 +3846,9 @@ elf32_frv_finish_dynamic_sections (bfd *output_bfd,
    regular object.  */
 
 static bfd_boolean
-elf32_frv_adjust_dynamic_symbol (struct bfd_link_info *info ATTRIBUTE_UNUSED,
-                                struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
+elf32_frvfdpic_adjust_dynamic_symbol
+(struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
 {
   bfd * dynobj;
 
@@ -3692,14 +3881,59 @@ elf32_frv_adjust_dynamic_symbol (struct bfd_link_info *info ATTRIBUTE_UNUSED,
 /* Perform any actions needed for dynamic symbols.  */
 
 static bfd_boolean
-elf32_frv_finish_dynamic_symbol (bfd *output_bfd ATTRIBUTE_UNUSED,
-                                struct bfd_link_info *info ATTRIBUTE_UNUSED,
-                                struct elf_link_hash_entry *h ATTRIBUTE_UNUSED,
-                                Elf_Internal_Sym *sym ATTRIBUTE_UNUSED)
+elf32_frvfdpic_finish_dynamic_symbol
+(bfd *output_bfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ struct elf_link_hash_entry *h ATTRIBUTE_UNUSED,
+ Elf_Internal_Sym *sym ATTRIBUTE_UNUSED)
 {
   return TRUE;
 }
 
+/* Decide whether to attempt to turn absptr or lsda encodings in
+   shared libraries into pcrel within the given input section.  */
+
+static bfd_boolean
+frvfdpic_elf_use_relative_eh_frame
+(bfd *input_bfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ asection *eh_frame_section ATTRIBUTE_UNUSED)
+{
+  /* We can't use PC-relative encodings in FDPIC binaries, in general.  */
+  return FALSE;
+}
+
+/* Adjust the contents of an eh_frame_hdr section before they're output.  */
+
+static bfd_byte
+frvfdpic_elf_encode_eh_address (bfd *abfd,
+                               struct bfd_link_info *info,
+                               asection *osec, bfd_vma offset,
+                               asection *loc_sec, bfd_vma loc_offset,
+                               bfd_vma *encoded)
+{
+  struct elf_link_hash_entry *h;
+
+  h = elf_hash_table (info)->hgot;
+  BFD_ASSERT (h && h->root.type == bfd_link_hash_defined);
+
+  if (! h || (_frvfdpic_osec_to_segment (abfd, osec)
+             == _frvfdpic_osec_to_segment (abfd, loc_sec->output_section)))
+    return _bfd_elf_encode_eh_address (abfd, info, osec, offset,
+                                      loc_sec, loc_offset, encoded);
+
+  BFD_ASSERT (_frvfdpic_osec_to_segment (abfd, osec)
+             == (_frvfdpic_osec_to_segment
+                 (abfd, h->root.u.def.section->output_section)));
+
+  *encoded = osec->vma + offset
+    - (h->root.u.def.value
+       + h->root.u.def.section->output_section->vma
+       + h->root.u.def.section->output_offset);
+
+  return DW_EH_PE_datarel | DW_EH_PE_sdata4;
+}
+
 /* Look through the relocs for a section during the first phase.
 
    Besides handling virtual table relocs for gc, we have to deal with
@@ -3816,7 +4050,7 @@ elf32_frv_check_relocs (abfd, info, sec, relocs)
   const Elf_Internal_Rela *rel;
   const Elf_Internal_Rela *rel_end;
   bfd *dynobj;
-  struct frv_pic_relocs_info *picrel;
+  struct frvfdpic_relocs_info *picrel;
 
   if (info->relocatable)
     return TRUE;
@@ -3842,8 +4076,6 @@ elf32_frv_check_relocs (abfd, info, sec, relocs)
 
       switch (ELF32_R_TYPE (rel->r_info))
        {
-       case R_FRV_LABEL24:
-       case R_FRV_32:
        case R_FRV_GOT12:
        case R_FRV_GOTHI:
        case R_FRV_GOTLO:
@@ -3858,12 +4090,26 @@ elf32_frv_check_relocs (abfd, info, sec, relocs)
        case R_FRV_FUNCDESC_GOTOFFLO:
        case R_FRV_FUNCDESC:
        case R_FRV_FUNCDESC_VALUE:
+         if (! IS_FDPIC (abfd))
+           goto bad_reloc;
+         /* Fall through.  */
+       case R_FRV_GPREL12:
+       case R_FRV_GPRELU12:
+       case R_FRV_GPRELHI:
+       case R_FRV_GPRELLO:
+       case R_FRV_LABEL24:
+       case R_FRV_32:
          if (! dynobj)
            {
              elf_hash_table (info)->dynobj = dynobj = abfd;
              if (! _frv_create_got_section (abfd, info))
                return FALSE;
            }
+         if (! IS_FDPIC (abfd))
+           {
+             picrel = NULL;
+             break;
+           }
          if (h != NULL)
            {
              if (h->dynindx == -1)
@@ -3873,18 +4119,18 @@ elf32_frv_check_relocs (abfd, info, sec, relocs)
                  case STV_HIDDEN:
                    break;
                  default:
-                   bfd_elf32_link_record_dynamic_symbol (info, h);
+                   bfd_elf_link_record_dynamic_symbol (info, h);
                    break;
                  }
              picrel
-               = frv_pic_relocs_info_for_global (frv_relocs_info (info),
-                                                 abfd, h,
-                                                 rel->r_addend);
+               = frvfdpic_relocs_info_for_global (frvfdpic_relocs_info (info),
+                                                  abfd, h,
+                                                  rel->r_addend, INSERT);
            }
          else
-           picrel = frv_pic_relocs_info_for_local (frv_relocs_info (info),
-                                                   abfd, r_symndx,
-                                                   rel->r_addend);
+           picrel = frvfdpic_relocs_info_for_local (frvfdpic_relocs_info
+                                                    (info), abfd, r_symndx,
+                                                    rel->r_addend, INSERT);
          if (! picrel)
            return FALSE;
          break;
@@ -3897,7 +4143,8 @@ elf32_frv_check_relocs (abfd, info, sec, relocs)
       switch (ELF32_R_TYPE (rel->r_info))
         {
        case R_FRV_LABEL24:
-         picrel->call = 1;
+         if (IS_FDPIC (abfd))
+           picrel->call = 1;
          break;
                
        case R_FRV_FUNCDESC_VALUE:
@@ -3905,7 +4152,11 @@ elf32_frv_check_relocs (abfd, info, sec, relocs)
          if (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)
            picrel->relocs32--;
          /* Fall through.  */
+
        case R_FRV_32:
+         if (! IS_FDPIC (abfd))
+           break;
+
          picrel->sym = 1;
          if (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)
            picrel->relocs32++;
@@ -3952,16 +4203,33 @@ elf32_frv_check_relocs (abfd, info, sec, relocs)
         /* This relocation describes the C++ object vtable hierarchy.
            Reconstruct it for later use during GC.  */
         case R_FRV_GNU_VTINHERIT:
-          if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+          if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
             return FALSE;
           break;
 
         /* This relocation describes which C++ vtable entries are actually
            used.  Record for later use during GC.  */
         case R_FRV_GNU_VTENTRY:
-          if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+          if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
             return FALSE;
           break;
+
+       case R_FRV_LABEL16:
+       case R_FRV_LO16:
+       case R_FRV_HI16:
+       case R_FRV_GPREL12:
+       case R_FRV_GPRELU12:
+       case R_FRV_GPREL32:
+       case R_FRV_GPRELHI:
+       case R_FRV_GPRELLO:
+         break;
+
+       default:
+       bad_reloc:
+         (*_bfd_error_handler)
+           (_("%s: unsupported relocation type %i"),
+            bfd_archive_filename (abfd), ELF32_R_TYPE (rel->r_info));
+         return FALSE;
         }
     }
 
@@ -3980,6 +4248,8 @@ elf32_frv_machine (abfd)
     default:               break;
     case EF_FRV_CPU_FR550:  return bfd_mach_fr550;
     case EF_FRV_CPU_FR500:  return bfd_mach_fr500;
+    case EF_FRV_CPU_FR450:  return bfd_mach_fr450;
+    case EF_FRV_CPU_FR405:  return bfd_mach_fr400;
     case EF_FRV_CPU_FR400:  return bfd_mach_fr400;
     case EF_FRV_CPU_FR300:  return bfd_mach_fr300;
     case EF_FRV_CPU_SIMPLE: return bfd_mach_frvsimple;
@@ -3996,7 +4266,8 @@ elf32_frv_object_p (abfd)
      bfd *abfd;
 {
   bfd_default_set_arch_mach (abfd, bfd_arch_frv, elf32_frv_machine (abfd));
-  return TRUE;
+  return (((elf_elfheader (abfd)->e_flags & EF_FRV_FDPIC) != 0)
+         == (IS_FDPIC (abfd)));
 }
 \f
 /* Function to set the ELF flag bits.  */
@@ -4030,6 +4301,77 @@ frv_elf_copy_private_bfd_data (ibfd, obfd)
   return TRUE;
 }
 
+/* Return true if the architecture described by elf header flag
+   EXTENSION is an extension of the architecture described by BASE.  */
+
+static bfd_boolean
+frv_elf_arch_extension_p (flagword base, flagword extension)
+{
+  if (base == extension)
+    return TRUE;
+
+  /* CPU_GENERIC code can be merged with code for a specific
+     architecture, in which case the result is marked as being
+     for the specific architecture.  Everything is therefore
+     an extension of CPU_GENERIC.  */
+  if (base == EF_FRV_CPU_GENERIC)
+    return TRUE;
+
+  if (extension == EF_FRV_CPU_FR450)
+    if (base == EF_FRV_CPU_FR400 || base == EF_FRV_CPU_FR405)
+      return TRUE;
+
+  if (extension == EF_FRV_CPU_FR405)
+    if (base == EF_FRV_CPU_FR400)
+      return TRUE;
+
+  return FALSE;
+}
+
+static bfd_boolean
+elf32_frvfdpic_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
+{
+  unsigned i;
+
+  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+    return TRUE;
+
+  if (! frv_elf_copy_private_bfd_data (ibfd, obfd))
+    return FALSE;
+
+  if (! elf_tdata (ibfd) || ! elf_tdata (ibfd)->phdr
+      || ! elf_tdata (obfd) || ! elf_tdata (obfd)->phdr)
+    return TRUE;
+
+  /* Copy the stack size.  */
+  for (i = 0; i < elf_elfheader (ibfd)->e_phnum; i++)
+    if (elf_tdata (ibfd)->phdr[i].p_type == PT_GNU_STACK)
+      {
+       Elf_Internal_Phdr *iphdr = &elf_tdata (ibfd)->phdr[i];
+
+       for (i = 0; i < elf_elfheader (obfd)->e_phnum; i++)
+         if (elf_tdata (obfd)->phdr[i].p_type == PT_GNU_STACK)
+           {
+             memcpy (&elf_tdata (obfd)->phdr[i], iphdr, sizeof (*iphdr));
+
+             /* Rewrite the phdrs, since we're only called after they
+                were first written.  */
+             if (bfd_seek (obfd, (bfd_signed_vma) get_elf_backend_data (obfd)
+                           ->s->sizeof_ehdr, SEEK_SET) != 0
+                 || get_elf_backend_data (obfd)->s
+                 ->write_out_phdrs (obfd, elf_tdata (obfd)->phdr,
+                                    elf_elfheader (obfd)->e_phnum) != 0)
+               return FALSE;
+             break;
+           }
+
+       break;
+      }
+
+  return TRUE;
+}
+
 /* Merge backend specific data from an object file to the output
    object file when linking.  */
 
@@ -4214,13 +4556,10 @@ frv_elf_merge_private_bfd_data (ibfd, obfd)
         the generic cpu).  */
       new_partial = (new_flags & EF_FRV_CPU_MASK);
       old_partial = (old_flags & EF_FRV_CPU_MASK);
-      if (new_partial == old_partial)
+      if (frv_elf_arch_extension_p (new_partial, old_partial))
        ;
 
-      else if (new_partial == EF_FRV_CPU_GENERIC)
-       ;
-
-      else if (old_partial == EF_FRV_CPU_GENERIC)
+      else if (frv_elf_arch_extension_p (old_partial, new_partial))
        old_flags = (old_flags & ~EF_FRV_CPU_MASK) | new_partial;
 
       else
@@ -4232,6 +4571,8 @@ frv_elf_merge_private_bfd_data (ibfd, obfd)
            case EF_FRV_CPU_SIMPLE:  strcat (new_opt, " -mcpu=simple"); break;
            case EF_FRV_CPU_FR550:   strcat (new_opt, " -mcpu=fr550");  break;
            case EF_FRV_CPU_FR500:   strcat (new_opt, " -mcpu=fr500");  break;
+           case EF_FRV_CPU_FR450:   strcat (new_opt, " -mcpu=fr450");  break;
+           case EF_FRV_CPU_FR405:   strcat (new_opt, " -mcpu=fr405");  break;
            case EF_FRV_CPU_FR400:   strcat (new_opt, " -mcpu=fr400");  break;
            case EF_FRV_CPU_FR300:   strcat (new_opt, " -mcpu=fr300");  break;
            case EF_FRV_CPU_TOMCAT:  strcat (new_opt, " -mcpu=tomcat"); break;
@@ -4244,6 +4585,8 @@ frv_elf_merge_private_bfd_data (ibfd, obfd)
            case EF_FRV_CPU_SIMPLE:  strcat (old_opt, " -mcpu=simple"); break;
            case EF_FRV_CPU_FR550:   strcat (old_opt, " -mcpu=fr550");  break;
            case EF_FRV_CPU_FR500:   strcat (old_opt, " -mcpu=fr500");  break;
+           case EF_FRV_CPU_FR450:   strcat (old_opt, " -mcpu=fr450");  break;
+           case EF_FRV_CPU_FR405:   strcat (old_opt, " -mcpu=fr405");  break;
            case EF_FRV_CPU_FR400:   strcat (old_opt, " -mcpu=fr400");  break;
            case EF_FRV_CPU_FR300:   strcat (old_opt, " -mcpu=fr300");  break;
            case EF_FRV_CPU_TOMCAT:  strcat (old_opt, " -mcpu=tomcat"); break;
@@ -4282,6 +4625,20 @@ frv_elf_merge_private_bfd_data (ibfd, obfd)
   if (old_partial != (old_flags & EF_FRV_CPU_MASK))
     bfd_default_set_arch_mach (obfd, bfd_arch_frv, elf32_frv_machine (obfd));
 
+  if (((new_flags & EF_FRV_FDPIC) == 0)
+      != (! IS_FDPIC (ibfd)))
+    {
+      error = TRUE;
+      if (IS_FDPIC (obfd))
+       (*_bfd_error_handler)
+         (_("%s: cannot link non-fdpic object file into fdpic executable"),
+          bfd_get_filename (ibfd));
+      else
+       (*_bfd_error_handler)
+         (_("%s: cannot link fdpic object file into non-fdpic executable"),
+          bfd_get_filename (ibfd));
+    }
+
   if (error)
     bfd_set_error (bfd_error_bad_value);
 
@@ -4311,6 +4668,8 @@ frv_elf_print_private_bfd_data (abfd, ptr)
     case EF_FRV_CPU_SIMPLE: fprintf (file, " -mcpu=simple");   break;
     case EF_FRV_CPU_FR550:  fprintf (file, " -mcpu=fr550");    break;
     case EF_FRV_CPU_FR500:  fprintf (file, " -mcpu=fr500");    break;
+    case EF_FRV_CPU_FR450:  fprintf (file, " -mcpu=fr450");    break;
+    case EF_FRV_CPU_FR405:  fprintf (file, " -mcpu=fr405");    break;
     case EF_FRV_CPU_FR400:  fprintf (file, " -mcpu=fr400");    break;
     case EF_FRV_CPU_FR300:  fprintf (file, " -mcpu=fr300");    break;
     case EF_FRV_CPU_TOMCAT: fprintf (file, " -mcpu=tomcat");   break;
@@ -4377,7 +4736,6 @@ frv_elf_print_private_bfd_data (abfd, ptr)
 #define TARGET_BIG_SYM          bfd_elf32_frv_vec
 #define TARGET_BIG_NAME                "elf32-frv"
 
-#define elf_info_to_howto_rel                  frv_info_to_howto_rel
 #define elf_info_to_howto                      frv_info_to_howto_rela
 #define elf_backend_relocate_section           elf32_frv_relocate_section
 #define elf_backend_gc_mark_hook               elf32_frv_gc_mark_hook
@@ -4395,33 +4753,76 @@ frv_elf_print_private_bfd_data (abfd, ptr)
 #define bfd_elf32_bfd_merge_private_bfd_data   frv_elf_merge_private_bfd_data
 #define bfd_elf32_bfd_print_private_bfd_data   frv_elf_print_private_bfd_data
 
-#define bfd_elf32_bfd_link_hash_table_create  frv_elf_link_hash_table_create
+#define elf_backend_want_got_sym       1
+#define elf_backend_got_header_size    0
+#define elf_backend_want_got_plt       0
+#define elf_backend_plt_readonly       1
+#define elf_backend_want_plt_sym       0
+#define elf_backend_plt_header_size    0
+
+#define elf_backend_finish_dynamic_sections \
+               elf32_frv_finish_dynamic_sections
+
+#include "elf32-target.h"
+
+#undef ELF_MAXPAGESIZE
+#define ELF_MAXPAGESIZE                0x4000
+
+#undef TARGET_BIG_SYM
+#define TARGET_BIG_SYM          bfd_elf32_frvfdpic_vec
+#undef TARGET_BIG_NAME
+#define TARGET_BIG_NAME                "elf32-frvfdpic"
+#undef elf32_bed
+#define        elf32_bed               elf32_frvfdpic_bed
+
+#undef elf_info_to_howto_rel
+#define elf_info_to_howto_rel  frvfdpic_info_to_howto_rel
+
+#undef bfd_elf32_bfd_link_hash_table_create
+#define bfd_elf32_bfd_link_hash_table_create \
+               frvfdpic_elf_link_hash_table_create
+#undef elf_backend_always_size_sections
 #define elf_backend_always_size_sections \
-               elf32_frv_always_size_sections
+               elf32_frvfdpic_always_size_sections
+#undef elf_backend_modify_segment_map
 #define elf_backend_modify_segment_map \
-               elf32_frv_modify_segment_map
+               elf32_frvfdpic_modify_segment_map
+#undef bfd_elf32_bfd_copy_private_bfd_data
+#define bfd_elf32_bfd_copy_private_bfd_data \
+               elf32_frvfdpic_copy_private_bfd_data
 
+#undef elf_backend_create_dynamic_sections
 #define elf_backend_create_dynamic_sections \
-               elf32_frv_create_dynamic_sections
+               elf32_frvfdpic_create_dynamic_sections
+#undef elf_backend_adjust_dynamic_symbol
 #define elf_backend_adjust_dynamic_symbol \
-               elf32_frv_adjust_dynamic_symbol
+               elf32_frvfdpic_adjust_dynamic_symbol
+#undef elf_backend_size_dynamic_sections
 #define elf_backend_size_dynamic_sections \
-               elf32_frv_size_dynamic_sections
+               elf32_frvfdpic_size_dynamic_sections
+#undef elf_backend_finish_dynamic_symbol
 #define elf_backend_finish_dynamic_symbol \
-               elf32_frv_finish_dynamic_symbol
+               elf32_frvfdpic_finish_dynamic_symbol
+#undef elf_backend_finish_dynamic_sections
 #define elf_backend_finish_dynamic_sections \
-               elf32_frv_finish_dynamic_sections
-
-#define elf_backend_want_got_sym       1
-#define elf_backend_got_header_size    0
-#define elf_backend_want_got_plt       0
-#define elf_backend_plt_readonly       1
-#define elf_backend_want_plt_sym       0
-#define elf_backend_plt_header_size    0
-
+               elf32_frvfdpic_finish_dynamic_sections
+
+#undef elf_backend_can_make_relative_eh_frame
+#define elf_backend_can_make_relative_eh_frame \
+               frvfdpic_elf_use_relative_eh_frame
+#undef elf_backend_can_make_lsda_relative_eh_frame
+#define elf_backend_can_make_lsda_relative_eh_frame \
+               frvfdpic_elf_use_relative_eh_frame
+#undef elf_backend_encode_eh_address
+#define elf_backend_encode_eh_address \
+               frvfdpic_elf_encode_eh_address
+
+#undef elf_backend_may_use_rel_p
 #define elf_backend_may_use_rel_p       1
+#undef elf_backend_may_use_rela_p
 #define elf_backend_may_use_rela_p      1
 /* We use REL for dynamic relocations only.  */
+#undef elf_backend_default_use_rela_p
 #define elf_backend_default_use_rela_p  1
 
 #include "elf32-target.h"
This page took 0.065644 seconds and 4 git commands to generate.