* elf64-x86-64.c (elf64_x86_64_relocate_section): For -fno-pic
[deliverable/binutils-gdb.git] / bfd / elf32-frv.c
index 039b4a3b479770afaa801e1d29d053e5caea5b87..69d20bfe5698497e4cac25b11c32b8d2eb0b773e 100644 (file)
@@ -583,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;
 
@@ -612,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)
@@ -657,26 +659,16 @@ 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
-         be regarded as local.  For some reason the
-         ELF_LINK_HASH_DEF_REGULAR bit is not set on such common
-         symbols, and the SEC_IS_COMMON bit is not set any longer
-         when we need to perform this test.  Hopefully this
-         approximation is good enough.  */ \
-       ((H)->root.type == bfd_link_hash_defined \
-       || (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) \
+   || ! elf_hash_table (INFO)->dynamic_sections_created)
+#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.  */
@@ -727,17 +719,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
@@ -764,24 +756,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);
@@ -790,14 +782,14 @@ 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,
-                         enum insert_option insert)
+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;
@@ -822,47 +814,47 @@ 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,
-                               enum insert_option insert)
+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, insert);
+  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,
-                              enum insert_option insert)
+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, insert);
+  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
-frv_pic_merge_early_relocs_info (struct frv_pic_relocs_info *e2,
-                                struct frv_pic_relocs_info const *e1)
+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;
@@ -879,8 +871,8 @@ frv_pic_merge_early_relocs_info (struct frv_pic_relocs_info *e2,
   e2->sym |= e1->sym;
 
 #if 0
-  /* These are set in _frv_count_got_plt_entries() or later, and this
-     function is only called in _frv_resolve_final_relocs_info(), that
+  /* 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.  */
 
@@ -914,15 +906,15 @@ frv_pic_merge_early_relocs_info (struct frv_pic_relocs_info *e2,
    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,
-                   struct frv_pic_relocs_info *entry)
+_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;
@@ -932,13 +924,23 @@ _frv_add_dyn_reloc (bfd *output_bfd, asection *sreloc, bfd_vma offset,
   outrel.r_addend = addend;
 
   reloc_offset = sreloc->reloc_count * sizeof (Elf32_External_Rel);
-  BFD_ASSERT (reloc_offset < sreloc->_raw_size);
+  BFD_ASSERT (reloc_offset < sreloc->size);
   bfd_elf32_swap_reloc_out (output_bfd, &outrel,
                            sreloc->contents + reloc_offset);
   sreloc->reloc_count++;
 
-  BFD_ASSERT (entry->dynrelocs > 0);
-  entry->dynrelocs--;
+  /* 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;
 }
@@ -946,8 +948,8 @@ _frv_add_dyn_reloc (bfd *output_bfd, asection *sreloc, bfd_vma offset,
 /* Add a fixup to the ROFIXUP section.  */
 
 static bfd_vma
-_frv_add_rofixup (bfd *output_bfd, asection *rofixup, bfd_vma offset,
-                 struct frv_pic_relocs_info *entry)
+_frvfdpic_add_rofixup (bfd *output_bfd, asection *rofixup, bfd_vma offset,
+                      struct frvfdpic_relocs_info *entry)
 {
   bfd_vma fixup_offset;
 
@@ -957,13 +959,15 @@ _frv_add_rofixup (bfd *output_bfd, asection *rofixup, bfd_vma offset,
   fixup_offset = rofixup->reloc_count * 4;
   if (rofixup->contents)
     {
-      BFD_ASSERT (fixup_offset < rofixup->_raw_size);
+      BFD_ASSERT (fixup_offset < rofixup->size);
       bfd_put_32 (output_bfd, offset, rofixup->contents + fixup_offset);
     }
   rofixup->reloc_count++;
 
-  if (entry)
+  if (entry && entry->symndx)
     {
+      /* See discussion about symndx == 0 in _frvfdpic_add_dyn_reloc
+        above.  */
       BFD_ASSERT (entry->fixups > 0);
       entry->fixups--;
     }
@@ -975,7 +979,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;
@@ -1000,9 +1004,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);
 }
@@ -1011,12 +1015,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;
@@ -1051,7 +1055,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;
@@ -1068,32 +1073,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, 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->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, entry);
+       _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);
     }
 
@@ -1106,7 +1115,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
@@ -1115,8 +1124,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;
@@ -1126,7 +1136,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;
@@ -1141,10 +1151,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
@@ -1155,30 +1165,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, 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, entry);
+           _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);
     }
 
@@ -1193,7 +1209,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;
@@ -1210,7 +1227,7 @@ _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;
@@ -1218,32 +1235,41 @@ _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_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, 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, 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, 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, entry);
+           _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
@@ -1251,9 +1277,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)
        {
@@ -1269,10 +1295,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
        {
@@ -1284,23 +1310,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);
 
@@ -1353,17 +1381,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)
        {
@@ -1767,8 +1795,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;
 
@@ -1869,24 +1897,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;
 
@@ -1902,7 +1930,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);
@@ -1940,7 +1968,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;
@@ -1978,6 +2006,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:
@@ -1993,25 +2024,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, INSERT);
+           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, INSERT);
+           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;
 
            }
@@ -2019,8 +2052,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"),
@@ -2034,10 +2068,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;
            }
@@ -2050,7 +2086,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;
 
@@ -2071,12 +2107,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;
 
@@ -2093,7 +2129,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
@@ -2103,8 +2139,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
@@ -2112,7 +2148,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)
                      {
@@ -2129,10 +2165,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;
                  }
 
@@ -2143,15 +2179,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,
@@ -2159,22 +2196,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,
-                                         picrel);
+                       _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,
@@ -2182,14 +2222,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, picrel);
+                   _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
@@ -2201,6 +2245,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;
@@ -2208,7 +2258,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)
                  {
@@ -2240,17 +2290,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,
@@ -2260,18 +2311,20 @@ 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,
-                                         picrel);
+                       _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)
@@ -2286,8 +2339,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,
@@ -2295,14 +2349,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, picrel);
+                   _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.  */
@@ -2315,11 +2373,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
@@ -2329,10 +2387,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);
              }
          }
@@ -2346,22 +2405,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.  */
@@ -2418,7 +2477,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.  */
          
@@ -2615,7 +2674,32 @@ 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
+
+/* We need dynamic symbols for every section, since segments can
+   relocate independently.  */
+static bfd_boolean
+_frvfdpic_link_omit_section_dynsym (bfd *output_bfd ATTRIBUTE_UNUSED,
+                                   struct bfd_link_info *info
+                                   ATTRIBUTE_UNUSED,
+                                   asection *p ATTRIBUTE_UNUSED)
+{
+  switch (elf_section_data (p)->this_hdr.sh_type)
+    {
+    case SHT_PROGBITS:
+    case SHT_NOBITS:
+      /* If sh_type is yet undecided, assume it could be
+        SHT_PROGBITS/SHT_NOBITS.  */
+    case SHT_NULL:
+      return FALSE;
+
+      /* There shouldn't be section relative relocations
+        against any other section.  */
+    default:
+      return TRUE;
+    }
+}
+
+/* Create  a .got section, as well as its additional info field.  This
    is almost entirely copied from
    elflink.c:_bfd_elf_create_got_section().  */
 
@@ -2628,6 +2712,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");
@@ -2676,47 +2761,57 @@ _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;
     }
 
   /* The first bit of the global offset table is the header.  */
-  s->_raw_size += bed->got_header_size + bed->got_symbol_offset;
+  s->size += bed->got_header_size + bed->got_symbol_offset;
 
   /* 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;
@@ -2724,9 +2819,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;
 }
 
@@ -2734,7 +2829,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().  */
@@ -2761,7 +2856,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)
     {
@@ -2779,7 +2874,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;
     }
 
@@ -2790,16 +2885,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)
     {
@@ -2849,7 +2945,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;
@@ -2877,10 +2973,10 @@ 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.  */
@@ -2909,15 +3005,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;
 
@@ -2941,7 +3037,7 @@ _frv_count_got_plt_entries (void **entryp, void *dinfo_)
     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)
@@ -2950,7 +3046,8 @@ _frv_count_got_plt_entries (void **entryp, void *dinfo_)
       else
        relocs += entry->relocs32 + entry->relocsfdv;
 
-      if (entry->symndx != -1 || FRV_FUNCDESC_LOCAL (dinfo->info, entry->d.h))
+      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)
@@ -2971,10 +3068,10 @@ _frv_count_got_plt_entries (void **entryp, void *dinfo_)
 /* 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
@@ -2990,7 +3087,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;
@@ -3008,14 +3105,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;
 
@@ -3109,7 +3206,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.  */
@@ -3123,7 +3220,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;
   
@@ -3152,7 +3249,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.  */
@@ -3165,46 +3262,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;
 }
@@ -3214,10 +3311,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.  */
@@ -3225,18 +3322,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;
        }
     }
@@ -3247,7 +3344,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)->size;
 
       /* Figure out the length of this PLT entry based on the
         addressing mode we need to reach the function descriptor.  */
@@ -3261,7 +3358,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)->size += size;
     }
 
   if (entry->lazyplt)
@@ -3270,7 +3367,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;
     }
       
@@ -3284,15 +3382,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 frv_pic_relocs_info *oentry;
+      struct frvfdpic_relocs_info *oentry;
 
       while (h->root.type == bfd_link_hash_indirect
             || h->root.type == bfd_link_hash_warning)
@@ -3301,13 +3399,13 @@ _frv_resolve_final_relocs_info (void **entryp, void *p)
       if (entry->d.h == h)
        return 1;
 
-      oentry = frv_pic_relocs_info_for_global (*htab, 0, h, entry->addend,
-                                              NO_INSERT);
+      oentry = frvfdpic_relocs_info_for_global (*htab, 0, h, entry->addend,
+                                               NO_INSERT);
 
       if (oentry)
        {
          /* Merge the two entries.  */
-         frv_pic_merge_early_relocs_info (oentry, entry);
+         frvfdpic_pic_merge_early_relocs_info (oentry, entry);
          htab_clear_slot (*htab, entryp);
          return 1;
        }
@@ -3336,12 +3434,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;
 
@@ -3355,7 +3453,7 @@ elf32_frv_size_dynamic_sections (bfd *output_bfd,
        {
          s = bfd_get_section_by_name (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
-         s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
+         s->size = sizeof ELF_DYNAMIC_INTERPRETER;
          s->contents = (bfd_byte *) ELF_DYNAMIC_INTERPRETER;
        }
     }
@@ -3365,15 +3463,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;
@@ -3392,160 +3490,166 @@ 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)->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)->size == 0)
+    frvfdpic_got_section (info)->flags |= SEC_EXCLUDE;
+  else if (frvfdpic_got_section (info)->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)->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)->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)->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)->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)->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)->size = (gpinfo.g.fixups + 1) * 4;
+  if (frvfdpic_gotfixup_section (info)->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)->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)->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)->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)->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)->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)->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)->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)->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 (frvfdpic_got_section (info)->size)
        if (!_bfd_elf_add_dynamic_entry (info, DT_PLTGOT, 0))
          return FALSE;
 
-      if (frv_pltrel_section (info)->_raw_size)
+      if (frvfdpic_pltrel_section (info)->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 (frvfdpic_gotrel_section (info)->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,
@@ -3557,11 +3661,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;
@@ -3603,45 +3706,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;
+
+  for (m = elf_tdata (output_bfd)->segment_map; m != NULL; m = m->next)
+    if (m->p_type == PT_GNU_STACK)
+      break;
 
-      if (m)
+  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;
-
-             /* 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++;
-           }
+         /* Set the section size from the symbol value.  We
+            intentionally ignore the symbol section.  */
+         if (h->root.type == bfd_link_hash_defined)
+           sec->size = h->root.u.def.value;
+         else
+           sec->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++;
        }
     }
 
@@ -3651,60 +3756,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)->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, 0);
-           }
+         _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)->size
+             != (frvfdpic_gotfixup_section (info)->reloc_count * 4))
            {
-             if (frv_gotfixup_section (info)->_raw_size
-                 < frv_gotfixup_section (info)->reloc_count * 4)
-               {
-                 info->callbacks->warning
-                   (info, "LINKER BUG: .rofixup section size mismatch",
-                    ".rofixup", NULL, NULL, 0);
-                 abort ();
-                 return FALSE;
-               }
-             else 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)->size
+                 == (frvfdpic_pltrel_section (info)->reloc_count
                      * sizeof (Elf32_External_Rel)));
     }
 
@@ -3718,7 +3814,7 @@ elf32_frv_finish_dynamic_sections (bfd *output_bfd,
       BFD_ASSERT (sdyn != NULL);
 
       dyncon = (Elf32_External_Dyn *) sdyn->contents;
-      dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
+      dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
 
       for (; dyncon < dynconend; dyncon++)
        {
@@ -3732,23 +3828,21 @@ 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;
-             else
-               dyn.d_un.d_val = frv_pltrel_section (info)->_raw_size;
+             dyn.d_un.d_val = frvfdpic_pltrel_section (info)->size;
              bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
              break;
            }
@@ -3762,8 +3856,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;
 
@@ -3796,10 +3891,11 @@ 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;
 }
@@ -3808,44 +3904,37 @@ elf32_frv_finish_dynamic_symbol (bfd *output_bfd ATTRIBUTE_UNUSED,
    shared libraries into pcrel within the given input section.  */
 
 static bfd_boolean
-frv_elf_use_relative_eh_frame (bfd *input_bfd,
-                              struct bfd_link_info *info ATTRIBUTE_UNUSED,
-                              asection *eh_frame_section ATTRIBUTE_UNUSED)
+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.  */
-  if (elf_elfheader (input_bfd)->e_flags & EF_FRV_FDPIC)
-    return FALSE;
-
-  return TRUE;
+  return FALSE;
 }
 
 /* Adjust the contents of an eh_frame_hdr section before they're output.  */
 
 static bfd_byte
-frv_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)
+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;
 
-  /* Non-FDPIC binaries can use PC-relative encodings.  */
-  if (! (elf_elfheader (abfd)->e_flags & EF_FRV_FDPIC))
-    return _bfd_elf_encode_eh_address (abfd, info, osec, offset,
-                                      loc_sec, loc_offset, encoded);
-
   h = elf_hash_table (info)->hgot;
   BFD_ASSERT (h && h->root.type == bfd_link_hash_defined);
 
-  if (! h || (_frv_osec_to_segment (abfd, osec)
-             == _frv_osec_to_segment (abfd, loc_sec->output_section)))
+  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 (_frv_osec_to_segment (abfd, osec)
-             == _frv_osec_to_segment (abfd,
-                                      h->root.u.def.section->output_section));
+  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
@@ -3971,7 +4060,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;
@@ -3997,8 +4086,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:
@@ -4013,12 +4100,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)
@@ -4028,18 +4129,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, INSERT);
+               = 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, INSERT);
+           picrel = frvfdpic_relocs_info_for_local (frvfdpic_relocs_info
+                                                    (info), abfd, r_symndx,
+                                                    rel->r_addend, INSERT);
          if (! picrel)
            return FALSE;
          break;
@@ -4052,7 +4153,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:
@@ -4060,7 +4162,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++;
@@ -4107,16 +4213,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;
         }
     }
 
@@ -4153,7 +4276,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.  */
@@ -4214,6 +4338,50 @@ frv_elf_arch_extension_p (flagword base, flagword extension)
   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.  */
 
@@ -4467,6 +4635,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);
 
@@ -4564,7 +4746,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
@@ -4582,39 +4763,79 @@ 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 \
-               frv_elf_use_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 \
-               frv_elf_use_relative_eh_frame
-#define elf_backend_encode_eh_address  frv_elf_encode_eh_address
+               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
 
+#undef elf_backend_omit_section_dynsym
+#define elf_backend_omit_section_dynsym _frvfdpic_link_omit_section_dynsym
+
 #include "elf32-target.h"
This page took 0.065103 seconds and 4 git commands to generate.