diff options
Diffstat (limited to 'bfd/elf32-frv.c')
-rw-r--r-- | bfd/elf32-frv.c | 1406 |
1 files changed, 813 insertions, 593 deletions
diff --git a/bfd/elf32-frv.c b/bfd/elf32-frv.c index 6412acdfb1f..9341fe8acca 100644 --- a/bfd/elf32-frv.c +++ b/bfd/elf32-frv.c @@ -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,26 @@ 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) + (_("%B: relocation at `%A+0x%x' references symbol `%s' with nonzero addend"), + input_bfd, input_section, rel->r_offset, name); return FALSE; } @@ -2019,8 +2051,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 +2067,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 +2085,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 +2106,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 +2128,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 +2138,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 +2147,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 +2164,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 +2178,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 +2195,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 +2221,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 +2244,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 +2257,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 +2289,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 +2310,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 +2338,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 +2348,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 +2372,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 +2386,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 +2404,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 +2476,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 +2673,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 +2711,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"); @@ -2683,40 +2767,50 @@ _frv_create_got_section (bfd *abfd, struct bfd_link_info *info) } /* 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 +2818,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 +2828,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 +2855,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) { @@ -2790,16 +2884,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 +2944,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 +2972,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 +3004,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 +3036,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 +3045,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 +3067,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 +3086,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 +3104,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 +3205,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 +3219,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 +3248,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 +3261,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 +3310,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 +3321,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 +3343,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 +3357,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 +3366,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 +3381,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 +3398,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 +3433,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 +3452,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 +3462,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 +3489,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 +3660,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 +3705,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 +3755,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 +3813,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 +3827,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 +3855,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 +3890,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 +3903,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 +4059,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 +4085,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 +4099,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) @@ -4032,14 +4132,14 @@ elf32_frv_check_relocs (abfd, info, sec, relocs) 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 +4152,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 +4161,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++; @@ -4117,6 +4222,23 @@ elf32_frv_check_relocs (abfd, info, sec, relocs) 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) + (_("%B: unsupported relocation type %i"), + abfd, ELF32_R_TYPE (rel->r_info)); + return FALSE; } } @@ -4153,7 +4275,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))); } /* Function to set the ELF flag bits. */ @@ -4214,6 +4337,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 +4634,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 +4745,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 +4762,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" |