diff options
Diffstat (limited to 'bfd/elf32-cris.c')
-rw-r--r-- | bfd/elf32-cris.c | 110 |
1 files changed, 76 insertions, 34 deletions
diff --git a/bfd/elf32-cris.c b/bfd/elf32-cris.c index e2a51f6..775fd0e 100644 --- a/bfd/elf32-cris.c +++ b/bfd/elf32-cris.c @@ -1,5 +1,5 @@ /* CRIS-specific support for 32-bit ELF. - Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Copyright 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Contributed by Axis Communications AB. Written by Hans-Peter Nilsson, based on elf32-fr30.c PIC and shlib bits based primarily on elf32-m68k.c and elf32-i386.c. @@ -859,7 +859,10 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section, bfd_boolean warned; bfd_boolean unresolved_reloc; - RELOC_FOR_GLOBAL_SYMBOL (h, sym_hashes, r_symndx, symtab_hdr, relocation, sec, unresolved_reloc, info, warned); + RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, + r_symndx, symtab_hdr, sym_hashes, + h, sec, relocation, + unresolved_reloc, warned); if (unresolved_reloc /* Perhaps we should detect the cases that @@ -957,11 +960,25 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section, statically linking PIC code, or when using -Bsymbolic. Check that we instead have a GOT entry as done for us by elf_cris_adjust_dynamic_symbol, and drop through into the - ordinary GOT cases. */ - if (h != NULL && h->got.offset == (bfd_vma) -1) + ordinary GOT cases. This must not happen for the + executable, because any reference it does to a function + that is satisfied by a DSO must generate a PLT. We assume + these call-specific relocs don't address non-functions. */ + if (h != NULL + && (h->got.offset == (bfd_vma) -1 + || (!info->shared + && !((h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) != 0 + || ((h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_DYNAMIC) == 0 + && h->root.type == bfd_link_hash_undefweak))))) { (*_bfd_error_handler) - (_("%s: No PLT nor GOT for relocation %s against symbol `%s' from %s section"), + ((h->got.offset == (bfd_vma) -1) + ? _("%s: No PLT nor GOT for relocation %s against\ + symbol `%s' from %s section") + : _("%s: No PLT for relocation %s against\ + symbol `%s' from %s section"), bfd_archive_filename (input_bfd), cris_elf_howto_table[r_type].name, symname[0] != '\0' ? symname : _("[whose name is lost]"), @@ -993,18 +1010,25 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section, if (!elf_hash_table (info)->dynamic_sections_created || (! info->shared - && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)) + && ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) + || h->type == STT_FUNC + || (h->elf_link_hash_flags + & ELF_LINK_HASH_NEEDS_PLT))) || (info->shared && (info->symbolic || h->dynindx == -1) && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))) { /* This wasn't checked above for ! info->shared, but - must hold there if we get here; the symbol must be - defined in the regular program, or be undefweak. */ + must hold there if we get here; the symbol must + be defined in the regular program or be undefweak + or be a function or otherwise need a PLT. */ BFD_ASSERT (!elf_hash_table (info)->dynamic_sections_created || info->shared || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0 + || h->type == STT_FUNC + || (h->elf_link_hash_flags + & ELF_LINK_HASH_NEEDS_PLT) || h->root.type == bfd_link_hash_undefweak); /* This is actually a static link, or it is a @@ -1418,7 +1442,7 @@ elf_cris_finish_dynamic_symbol (output_bfd, info, h, sym) to this function. Note that we embed knowledge that "incoming" .got goes after .got.plt in the output without padding (pointer aligned). However, that knowledge is present in several other - places too, here and in elflink.h at least. */ + places too. */ bfd_vma got_offset = (has_gotplt ? gotplt_offset @@ -1508,12 +1532,15 @@ elf_cris_finish_dynamic_symbol (output_bfd, info, h, sym) } } - /* We don't emit .got relocs for symbols that aren't in the - dynamic-symbols table for an ordinary program and are either defined - by the program or are undefined weak symbols. */ + /* For an ordinary program, we emit .got relocs only for symbols that + are in the dynamic-symbols table and are either defined by the + program or are undefined weak symbols, or are function symbols + where we do not output a PLT: the PLT reloc was output above and all + references to the function symbol are redirected to the PLT. */ if (h->got.offset != (bfd_vma) -1 && (info->shared || (h->dynindx != -1 + && h->plt.offset == (bfd_vma) -1 && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0 && h->root.type != bfd_link_hash_undefweak))) { @@ -1835,13 +1862,12 @@ cris_elf_gc_sweep_hook (abfd, info, sec, relocs) r_symndx = ELF32_R_SYM (rel->r_info); if (r_symndx < symtab_hdr->sh_info) goto local_got_reloc; - + /* Fall through. */ case R_CRIS_32_PLT_GOTREL: /* FIXME: We don't garbage-collect away the .got section. */ if (local_got_refcounts != NULL) local_got_refcounts[-1]--; /* Fall through. */ - case R_CRIS_8_PCREL: case R_CRIS_16_PCREL: case R_CRIS_32_PCREL: @@ -1926,16 +1952,22 @@ elf_cris_adjust_gotplt_to_got (h, p) want to do this: - When all PLT references are GOTPLT references, and there are GOT - references. We don't have to generate a PLT at all. + references, and this is not the executable. We don't have to + generate a PLT at all. - - When there are both (ordinary) PLT references and GOT references. + - When there are both (ordinary) PLT references and GOT references, + and this isn't the executable. We want to make the PLT reference use the ordinary GOT entry rather - than a run-time dynamically resolved GOTPLT entry (since the GOT - entry will have to be resolved at startup anyway). + than R_CRIS_JUMP_SLOT, a run-time dynamically resolved GOTPLT entry, + since the GOT entry will have to be resolved at startup anyway. Though the latter case is handled when room for the PLT is allocated, not here. + By folding into the GOT, we may need a round-trip to a PLT in the + executable for calls, a loss in performance. Still, losing a + reloc is a win in size and at least in start-up time. + Note that this function is called before symbols are forced local by version scripts. The differing cases are handled by elf_cris_hide_symbol. */ @@ -2042,10 +2074,14 @@ elf_cris_adjust_dynamic_symbol (info, h) info); } - /* If there are only GOT references and GOTPLT references to this - PLT entry, get rid of the PLT. */ - if (! elf_cris_try_fold_plt_to_got ((struct elf_cris_link_hash_entry *) - h, info)) + /* If we had a R_CRIS_GLOB_DAT that didn't have to point to a PLT; + where a pointer-equivalent symbol was unimportant (i.e. more + like R_CRIS_JUMP_SLOT after symbol evaluation) we could get rid + of the PLT. We can't for the executable, because the GOT + entries will point to the PLT there (and be constant). */ + if (info->shared + && !elf_cris_try_fold_plt_to_got ((struct elf_cris_link_hash_entry*) + h, info)) return FALSE; /* GC or folding may have rendered this entry unused. */ @@ -2059,7 +2095,7 @@ elf_cris_adjust_dynamic_symbol (info, h) /* Make sure this symbol is output as a dynamic symbol. */ if (h->dynindx == -1) { - if (! bfd_elf32_link_record_dynamic_symbol (info, h)) + if (! bfd_elf_link_record_dynamic_symbol (info, h)) return FALSE; } @@ -2083,8 +2119,11 @@ elf_cris_adjust_dynamic_symbol (info, h) /* If there's already a GOT entry, use that, not a .got.plt. A GOT field still has a reference count when we get here; it's - not yet changed to an offset. */ - if (h->got.refcount > 0) + not yet changed to an offset. We can't do this for an + executable, because then the reloc associated with the PLT + would get a non-PLT reloc pointing to the PLT. FIXME: Move + this to elf_cris_try_fold_plt_to_got. */ + if (info->shared && h->got.refcount > 0) { h->got.refcount += h->plt.refcount; @@ -2383,7 +2422,7 @@ cris_elf_check_relocs (abfd, info, sec, relocs) /* Make sure this symbol is output as a dynamic symbol. */ if (h->dynindx == -1) { - if (!bfd_elf32_link_record_dynamic_symbol (info, h)) + if (!bfd_elf_link_record_dynamic_symbol (info, h)) return FALSE; } @@ -2600,14 +2639,14 @@ cris_elf_check_relocs (abfd, info, sec, relocs) /* This relocation describes the C++ object vtable hierarchy. Reconstruct it for later use during GC. */ case R_CRIS_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_CRIS_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; @@ -2770,7 +2809,7 @@ elf_cris_size_dynamic_sections (output_bfd, info) the .dynamic section. The DT_DEBUG entry is filled in by the dynamic linker and used by the debugger. */ #define add_dynamic_entry(TAG, VAL) \ - bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL)) + _bfd_elf_add_dynamic_entry (info, TAG, VAL) if (!info->shared) { @@ -2857,9 +2896,11 @@ elf_cris_discard_excess_program_dynamics (h, inf) /* If we're not creating a shared library and have a symbol which is referred to by .got references, but the symbol is defined locally, - (or rather, not not defined by a DSO) then lose the reloc for the - .got (don't allocate room for it). */ - if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0) + (or rather, not defined by a DSO) then lose the reloc for the .got + (don't allocate room for it). Likewise for relocs for something + for which we create a PLT. */ + if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0 + || h->root.plt.refcount > 0) { if (h->root.got.refcount > 0 /* The size of this section is only valid and in sync with the @@ -2885,7 +2926,8 @@ elf_cris_discard_excess_program_dynamics (h, inf) introduce new problems. Of course we don't do this if we're exporting all dynamic symbols. */ if (! info->export_dynamic - && (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0) + && (h->root.elf_link_hash_flags + & (ELF_LINK_HASH_DEF_DYNAMIC|ELF_LINK_HASH_REF_DYNAMIC)) == 0) { h->root.dynindx = -1; _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr, @@ -3048,7 +3090,7 @@ elf_cris_reloc_type_class (rela) #define elf_backend_create_dynamic_sections \ _bfd_elf_create_dynamic_sections #define bfd_elf32_bfd_final_link \ - _bfd_elf32_gc_common_final_link + bfd_elf_gc_common_final_link #define elf_backend_hide_symbol elf_cris_hide_symbol #define elf_backend_reloc_type_class elf_cris_reloc_type_class |