X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf32-sparc.c;h=a11db81c305300fcd8ca1304d2995345263c10c0;hb=86fb1dece37497b267579ed4f062d280cd5760cd;hp=d540efed9d93f210ee7f3c3378d084e7b457186c;hpb=1fbc4a84a3764dd04760128c5666348c0fa070eb;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-sparc.c b/bfd/elf32-sparc.c index d540efed9d..a11db81c30 100644 --- a/bfd/elf32-sparc.c +++ b/bfd/elf32-sparc.c @@ -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 @@ -662,14 +670,8 @@ 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 (abfd, sym->st_shndx); + } return NULL; } @@ -1082,6 +1084,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 @@ -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); @@ -1172,6 +1187,7 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, h = NULL; sym = NULL; sec = NULL; + unresolved_reloc = false; if (r_symndx < symtab_hdr->sh_info) { sym = local_syms + r_symndx; @@ -1184,70 +1200,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 +1232,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 +1250,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 +1284,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 +1327,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 +1366,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 +1403,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 @@ -1453,6 +1442,8 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, 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); @@ -1476,13 +1467,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)) @@ -1502,7 +1504,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 { @@ -1551,7 +1555,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; @@ -1559,6 +1564,18 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, break; } + /* ??? Copied from elf32-i386.c, debugging section check and all. */ + if (unresolved_reloc + && !(info->shared + && (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) {