X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felf32-sparc.c;h=4c9b3d45aaa41f0a70d9726c68c5cdce87a4449b;hb=341026c1c143611e52a7bae351f7a886a8cc19a3;hp=60a4dc76fa5023e52871d6a4ce51742f9d693f97;hpb=2e549b45b82d7d3191799b7650221fb3ebb03293;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-sparc.c b/bfd/elf32-sparc.c index 60a4dc76fa..4c9b3d45aa 100644 --- a/bfd/elf32-sparc.c +++ b/bfd/elf32-sparc.c @@ -1,5 +1,5 @@ /* SPARC-specific support for 32-bit ELF - Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 + Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -55,7 +55,7 @@ static void elf32_sparc_final_write_processing static enum elf_reloc_type_class elf32_sparc_reloc_type_class PARAMS ((const Elf_Internal_Rela *)); static asection * elf32_sparc_gc_mark_hook - PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *, + PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *, struct elf_link_hash_entry *, Elf_Internal_Sym *)); static boolean elf32_sparc_gc_sweep_hook PARAMS ((bfd *, struct bfd_link_info *, asection *, @@ -76,7 +76,7 @@ reloc_howto_type _bfd_sparc_elf_howto_table[] = HOWTO(R_SPARC_32, 0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_32", false,0,0xffffffff,true), HOWTO(R_SPARC_DISP8, 0,0, 8,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP8", false,0,0x000000ff,true), HOWTO(R_SPARC_DISP16, 0,1,16,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP16", false,0,0x0000ffff,true), - HOWTO(R_SPARC_DISP32, 0,2,32,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP32", false,0,0x00ffffff,true), + HOWTO(R_SPARC_DISP32, 0,2,32,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP32", false,0,0xffffffff,true), HOWTO(R_SPARC_WDISP30, 2,2,30,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP30", false,0,0x3fffffff,true), HOWTO(R_SPARC_WDISP22, 2,2,22,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP22", false,0,0x003fffff,true), HOWTO(R_SPARC_HI22, 10,2,22,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HI22", false,0,0x003fffff,true), @@ -94,7 +94,7 @@ reloc_howto_type _bfd_sparc_elf_howto_table[] = HOWTO(R_SPARC_JMP_SLOT, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_JMP_SLOT",false,0,0x00000000,true), HOWTO(R_SPARC_RELATIVE, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_RELATIVE",false,0,0x00000000,true), HOWTO(R_SPARC_UA32, 0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_UA32", false,0,0xffffffff,true), - HOWTO(R_SPARC_PLT32, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PLT32", false,0,0x00000000,true), + HOWTO(R_SPARC_PLT32, 0,0,00,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_PLT32", false,0,0xffffffff,true), HOWTO(R_SPARC_HIPLT22, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_HIPLT22", false,0,0x00000000,true), HOWTO(R_SPARC_LOPLT10, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_LOPLT10", false,0,0x00000000,true), HOWTO(R_SPARC_PCPLT32, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PCPLT32", false,0,0x00000000,true), @@ -146,6 +146,7 @@ static const struct elf_reloc_map sparc_reloc_map[] = { { BFD_RELOC_NONE, R_SPARC_NONE, }, { BFD_RELOC_16, R_SPARC_16, }, + { BFD_RELOC_16_PCREL, R_SPARC_DISP16 }, { BFD_RELOC_8, R_SPARC_8 }, { BFD_RELOC_8_PCREL, R_SPARC_DISP8 }, { BFD_RELOC_CTOR, R_SPARC_32 }, @@ -154,6 +155,7 @@ static const struct elf_reloc_map sparc_reloc_map[] = { BFD_RELOC_HI22, R_SPARC_HI22 }, { BFD_RELOC_LO10, R_SPARC_LO10, }, { BFD_RELOC_32_PCREL_S2, R_SPARC_WDISP30 }, + { BFD_RELOC_SPARC_PLT32, R_SPARC_PLT32 }, { BFD_RELOC_SPARC22, R_SPARC_22 }, { BFD_RELOC_SPARC13, R_SPARC_13 }, { BFD_RELOC_SPARC_GOT10, R_SPARC_GOT10 }, @@ -494,6 +496,7 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs) break; + case R_SPARC_PLT32: case R_SPARC_WPLT30: /* This symbol requires a procedure linkage table entry. We actually build the entry in adjust_dynamic_symbol, @@ -507,6 +510,8 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs) reloc for a local symbol if you assemble a call from one section to another when using -K pic. We treat it as WDISP30. */ + if (ELF32_R_TYPE (rel->r_info) != R_SPARC_WPLT30) + goto r_sparc_plt32; break; } @@ -519,6 +524,8 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs) h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; + if (ELF32_R_TYPE (rel->r_info) != R_SPARC_WPLT30) + goto r_sparc_plt32; break; case R_SPARC_PC10: @@ -566,6 +573,7 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs) if (h != NULL) h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF; + r_sparc_plt32: if (info->shared && (sec->flags & SEC_ALLOC)) { /* When creating a shared object, we must copy these @@ -629,14 +637,13 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs) } static asection * -elf32_sparc_gc_mark_hook (abfd, info, rel, h, sym) - bfd *abfd; +elf32_sparc_gc_mark_hook (sec, info, rel, h, sym) + asection *sec; struct bfd_link_info *info ATTRIBUTE_UNUSED; Elf_Internal_Rela *rel; struct elf_link_hash_entry *h; Elf_Internal_Sym *sym; { - if (h != NULL) { switch (ELF32_R_TYPE (rel->r_info)) @@ -661,15 +668,7 @@ elf32_sparc_gc_mark_hook (abfd, info, rel, h, sym) } } else - { - if (!(elf_bad_symtab (abfd) - && ELF_ST_BIND (sym->st_info) != STB_LOCAL) - && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE) - && sym->st_shndx != SHN_COMMON)) - { - return bfd_section_from_elf_index (abfd, sym->st_shndx); - } - } + return bfd_section_from_elf_index (sec->owner, sym->st_shndx); return NULL; } @@ -1082,6 +1081,17 @@ elf32_sparc_relax_section (abfd, section, link_info, again) return true; } +/* This is the condition under which finish_dynamic_symbol will be called + from elflink.h. If elflink.h doesn't call our finish_dynamic_symbol + routine, we'll need to do something about initializing any .plt and .got + entries in relocate_section. */ +#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H) \ + ((DYN) \ + && ((INFO)->shared \ + || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \ + && ((H)->dynindx != -1 \ + || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)) + /* Relocate a SPARC ELF section. */ static boolean @@ -1107,6 +1117,9 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, Elf_Internal_Rela *rel; Elf_Internal_Rela *relend; + if (info->relocateable) + return true; + dynobj = elf_hash_table (info)->dynobj; symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; sym_hashes = elf_sym_hashes (input_bfd); @@ -1131,8 +1144,10 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, struct elf_link_hash_entry *h; Elf_Internal_Sym *sym; asection *sec; - bfd_vma relocation; + bfd_vma relocation, off; bfd_reloc_status_type r; + boolean is_plt = false; + boolean unresolved_reloc; r_type = ELF32_R_TYPE (rel->r_info); @@ -1147,31 +1162,12 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, } howto = _bfd_sparc_elf_howto_table + r_type; - r_symndx = ELF32_R_SYM (rel->r_info); - - if (info->relocateable) - { - /* This is a relocateable link. We don't have to change - anything, unless the reloc is against a section symbol, - in which case we have to adjust according to where the - section symbol winds up in the output section. */ - if (r_symndx < symtab_hdr->sh_info) - { - sym = local_syms + r_symndx; - if (ELF_ST_TYPE (sym->st_info) == STT_SECTION) - { - sec = local_sections[r_symndx]; - rel->r_addend += sec->output_offset + sym->st_value; - } - } - - continue; - } - /* This is a final link. */ + r_symndx = ELF32_R_SYM (rel->r_info); h = NULL; sym = NULL; sec = NULL; + unresolved_reloc = false; if (r_symndx < symtab_hdr->sh_info) { sym = local_syms + r_symndx; @@ -1184,70 +1180,30 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, 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; + + relocation = 0; if (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) { sec = h->root.u.def.section; - if ((r_type == R_SPARC_WPLT30 - && h->plt.offset != (bfd_vma) -1) - || ((r_type == R_SPARC_GOT10 - || r_type == R_SPARC_GOT13 - || r_type == R_SPARC_GOT22) - && elf_hash_table (info)->dynamic_sections_created - && (! info->shared - || (! info->symbolic && h->dynindx != -1) - || (h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_REGULAR) == 0)) - || (info->shared - && ((! info->symbolic && h->dynindx != -1) - || (h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_REGULAR) == 0) - && (r_type == R_SPARC_8 - || r_type == R_SPARC_16 - || r_type == R_SPARC_32 - || r_type == R_SPARC_DISP8 - || r_type == R_SPARC_DISP16 - || r_type == R_SPARC_DISP32 - || r_type == R_SPARC_WDISP30 - || r_type == R_SPARC_WDISP22 - || r_type == R_SPARC_WDISP19 - || r_type == R_SPARC_WDISP16 - || r_type == R_SPARC_HI22 - || r_type == R_SPARC_22 - || r_type == R_SPARC_13 - || r_type == R_SPARC_LO10 - || r_type == R_SPARC_UA16 - || r_type == R_SPARC_UA32 - || ((r_type == R_SPARC_PC10 - || r_type == R_SPARC_PC22) - && strcmp (h->root.root.string, - "_GLOBAL_OFFSET_TABLE_") != 0)) - && ((input_section->flags & SEC_ALLOC) != 0 - /* DWARF will emit R_SPARC_32 relocations in its - sections against symbols defined externally - in shared libraries. We can't do anything - with them here. */ - || ((input_section->flags & SEC_DEBUGGING) != 0 - && (h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_DYNAMIC) != 0)))) - { - /* In these cases, we don't need the relocation - value. We check specially because in some - obscure cases sec->output_section will be NULL. */ - relocation = 0; - } + if (sec->output_section == NULL) + /* Set a flag that will be cleared later if we find a + relocation value for this symbol. output_section + is typically NULL for symbols satisfied by a shared + library. */ + unresolved_reloc = true; else relocation = (h->root.u.def.value + sec->output_section->vma + sec->output_offset); } else if (h->root.type == bfd_link_hash_undefweak) - relocation = 0; + ; else if (info->shared && (!info->symbolic || info->allow_shlib_undefined) && !info->no_undefined && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) - relocation = 0; + ; else { if (! ((*info->callbacks->undefined_symbol) @@ -1256,7 +1212,6 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, (!info->shared || info->no_undefined || ELF_ST_VISIBILITY (h->other))))) return false; - relocation = 0; } } @@ -1275,14 +1230,17 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, if (h != NULL) { - bfd_vma off; + boolean dyn; off = h->got.offset; BFD_ASSERT (off != (bfd_vma) -1); + dyn = elf_hash_table (info)->dynamic_sections_created; - if (! elf_hash_table (info)->dynamic_sections_created + if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h) || (info->shared - && (info->symbolic || h->dynindx == -1) + && (info->symbolic + || h->dynindx == -1 + || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)) && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))) { /* This is actually a static link, or it is a @@ -1306,13 +1264,11 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, h->got.offset |= 1; } } - - relocation = sgot->output_offset + off - got_base; + else + unresolved_reloc = false; } else { - bfd_vma off; - BFD_ASSERT (local_got_offsets != NULL && local_got_offsets[r_symndx] != (bfd_vma) -1); @@ -1351,12 +1307,17 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, local_got_offsets[r_symndx] |= 1; } - - relocation = sgot->output_offset + off - got_base; } - + relocation = sgot->output_offset + off - got_base; break; + case R_SPARC_PLT32: + if (h == NULL || h->plt.offset == (bfd_vma) -1) + { + r_type = R_SPARC_32; + goto r_sparc_plt32; + } + /* Fall through. */ case R_SPARC_WPLT30: /* Relocation is to the entry for this symbol in the procedure linkage table. */ @@ -1385,6 +1346,13 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, relocation = (splt->output_section->vma + splt->output_offset + h->plt.offset); + unresolved_reloc = false; + if (r_type == R_SPARC_PLT32) + { + r_type = R_SPARC_32; + is_plt = true; + goto r_sparc_plt32; + } break; case R_SPARC_PC10: @@ -1415,12 +1383,13 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, case R_SPARC_LO10: case R_SPARC_UA16: case R_SPARC_UA32: + r_sparc_plt32: if (info->shared && r_symndx != 0 && (input_section->flags & SEC_ALLOC)) { Elf_Internal_Rela outrel; - boolean skip; + boolean skip, relocate = false; /* When generating a shared object, these relocations are copied into the output file to be resolved at run @@ -1448,22 +1417,13 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, skip = false; - if (elf_section_data (input_section)->stab_info == NULL) - outrel.r_offset = rel->r_offset; - else - { - bfd_vma off; - - off = (_bfd_stab_section_offset - (output_bfd, &elf_hash_table (info)->stab_info, - input_section, - &elf_section_data (input_section)->stab_info, - rel->r_offset)); - if (off == (bfd_vma) -1) - skip = true; - outrel.r_offset = off; - } - + outrel.r_offset = + _bfd_elf_section_offset (output_bfd, info, input_section, + rel->r_offset); + if (outrel.r_offset == (bfd_vma) -1) + skip = true; + else if (outrel.r_offset == (bfd_vma) -2) + skip = true, relocate = true; outrel.r_offset += (input_section->output_section->vma + input_section->output_offset); @@ -1487,13 +1447,24 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, if (!(outrel.r_offset & 3)) r_type = R_SPARC_32; break; + case R_SPARC_DISP8: + case R_SPARC_DISP16: + case R_SPARC_DISP32: + /* If the symbol is not dynamic, we should not keep + a dynamic relocation. But an .rela.* slot has been + allocated for it, output R_SPARC_NONE. + FIXME: Add code tracking needed dynamic relocs as + e.g. i386 has. */ + if (h->dynindx == -1) + skip = true, relocate = true; + break; } if (skip) memset (&outrel, 0, sizeof outrel); /* h->dynindx may be -1 if the symbol was marked to become local. */ - else if (h != NULL + else if (h != NULL && ! is_plt && ((! info->symbolic && h->dynindx != -1) || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)) @@ -1504,7 +1475,7 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, } else { - if (r_type == R_SPARC_32 || r_type == R_SPARC_UA32) + if (r_type == R_SPARC_32) { outrel.r_info = ELF32_R_INFO (0, R_SPARC_RELATIVE); outrel.r_addend = relocation + rel->r_addend; @@ -1513,7 +1484,9 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, { long indx; - if (h == NULL) + if (is_plt) + sec = splt; + else if (h == NULL) sec = local_sections[r_symndx]; else { @@ -1562,7 +1535,8 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, /* This reloc will be computed at runtime, so there's no need to do anything now. */ - continue; + if (! relocate) + continue; } break; @@ -1570,6 +1544,19 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, break; } + /* Dynamic relocs are not propagated for SEC_DEBUGGING sections + because such sections are not SEC_ALLOC and thus ld.so will + not process them. */ + if (unresolved_reloc + && !((input_section->flags & SEC_DEBUGGING) != 0 + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0)) + (*_bfd_error_handler) + (_("%s(%s+0x%lx): unresolvable relocation against symbol `%s'"), + bfd_archive_filename (input_bfd), + bfd_get_section_name (input_bfd, input_section), + (long) rel->r_offset, + h->root.root.string); + r = bfd_reloc_continue; if (r_type == R_SPARC_WDISP16) { @@ -2143,5 +2130,6 @@ elf32_sparc_reloc_type_class (rela) #define elf_backend_want_plt_sym 1 #define elf_backend_got_header_size 4 #define elf_backend_plt_header_size (4*PLT_ENTRY_SIZE) +#define elf_backend_rela_normal 1 #include "elf32-target.h"