From 7194b91a0fa7f996316c99fb97eeea87078c2628 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 11 Sep 1998 20:15:54 +0000 Subject: [PATCH] 1998-09-10 Geoff Keating * elf32-ppc.c (ppc_elf_relocate_section): If dynobj is NULL, assume there is no PLT or GOT. --- bfd/ChangeLog | 5 ++ bfd/elf32-ppc.c | 177 ++++++++++++++++++++++++++---------------------- 2 files changed, 102 insertions(+), 80 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 69e53d9c334..e21f8a47549 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,8 @@ +1998-09-10 Geoff Keating + + * elf32-ppc.c (ppc_elf_relocate_section): If dynobj is NULL, + assume there is no PLT or GOT. + Wed Sep 9 14:24:12 1998 Nick Clifton * elf32-arm.c (elf32_arm_find_nearest_line): New function: just diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index a1ff1e1681e..1b8a8f02c31 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -953,7 +953,7 @@ ppc_elf_reloc_type_lookup (abfd, code) bfd *abfd; bfd_reloc_code_real_type code; { - enum ppc_reloc_type ppc_reloc = R_PPC_NONE; + enum elf_ppc_reloc_type ppc_reloc = R_PPC_NONE; if (!ppc_elf_howto_table[R_PPC_ADDR32]) /* Initialize howto table if needed */ @@ -1431,27 +1431,26 @@ ppc_elf_adjust_dynamic_symbol (info, h) if (h->type == STT_FUNC || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0) { - if (! info->shared - && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0 - && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0) + if (! 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 && h->plt.refcount <= 0)) { - /* This case can occur if we saw a PLT32 reloc in an input - file, but the symbol was never referred to by a dynamic - object. In such a case, we don't actually need to build - a procedure linkage table, and we can just do a PC32 - reloc instead. */ - BFD_ASSERT ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0); - return true; - } + /* A PLT entry is not required/allowed when: - /* GC may have rendered this entry unused. Note, however, that in - an executable all references to the symbol go to the PLT, so we - can't turn it off in that case. - ??? The correct thing to do here is to reference count all uses - of the symbol, not just those to the GOT or PLT. */ + 1. We are not using ld.so; because then the PLT entry + can't be set up, so we can't use one. - if (h->plt.refcount <= 0 && info->shared) - { + 2. We know for certain that a symbol is defined in + this object, because this object is the application, + is linked with -Bsymbolic, or because the symbol is local. + + 3. GC has rendered the entry unused. + Note, however, that in an executable all references to the + symbol go to the PLT, so we can't turn it off in that case. + ??? The correct thing to do here is to reference count + all uses of the symbol, not just those to the GOT or PLT. */ h->plt.offset = (bfd_vma) -1; h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; return true; @@ -1860,7 +1859,7 @@ ppc_elf_check_relocs (abfd, info, sec, relocs) elf_linker_section_t *sdata; elf_linker_section_t *sdata2; asection *sreloc; - asection *sgot; + asection *sgot = NULL; asection *srelgot = NULL; if (info->relocateable) @@ -1913,6 +1912,22 @@ ppc_elf_check_relocs (abfd, info, sec, relocs) else h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + /* If a relocation refers to _GLOBAL_OFFSET_TABLE_, create the .got. + This shows up in particular in an R_PPC_ADDR32 in the eabi + startup code. */ + if (h && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) + { + if (sgot == NULL) + { + if (dynobj == NULL) + elf_hash_table (info)->dynobj = dynobj = abfd; + if (! _bfd_elf_create_got_section (dynobj, info)) + return false; + sgot = bfd_get_section_by_name (dynobj, ".got"); + BFD_ASSERT (sgot != NULL); + } + } + switch (ELF32_R_TYPE (rel->r_info)) { /* GOT16 relocations */ @@ -1925,11 +1940,9 @@ ppc_elf_check_relocs (abfd, info, sec, relocs) if (sgot == NULL) { if (dynobj == NULL) - { - elf_hash_table (info)->dynobj = dynobj = abfd; - if (! _bfd_elf_create_got_section (dynobj, info)) - return false; - } + elf_hash_table (info)->dynobj = dynobj = abfd; + if (! _bfd_elf_create_got_section (dynobj, info)) + return false; sgot = bfd_get_section_by_name (dynobj, ".got"); BFD_ASSERT (sgot != NULL); } @@ -2720,8 +2733,8 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, Elf_Internal_Rela *rel = relocs; Elf_Internal_Rela *relend = relocs + input_section->reloc_count; asection *sreloc = NULL; - asection *splt = NULL; - asection *sgot = NULL; + asection *splt; + asection *sgot; bfd_vma *local_got_offsets; boolean ret = true; long insn; @@ -2739,9 +2752,16 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, local_got_offsets = elf_local_got_offsets (input_bfd); + splt = sgot = NULL; + if (dynobj != NULL) + { + splt = bfd_get_section_by_name (dynobj, ".plt"); + sgot = bfd_get_section_by_name (dynobj, ".got"); + } + for (; rel < relend; rel++) { - enum ppc_reloc_type r_type = (enum ppc_reloc_type)ELF32_R_TYPE (rel->r_info); + enum elf_ppc_reloc_type r_type = (enum ppc_reloc_type)ELF32_R_TYPE (rel->r_info); bfd_vma offset = rel->r_offset; bfd_vma addend = rel->r_addend; bfd_reloc_status_type r = bfd_reloc_other; @@ -3126,11 +3146,7 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, case (int)R_PPC_GOT16_HA: /* Relocation is to the entry for this symbol in the global offset table. */ - if (sgot == NULL) - { - sgot = bfd_get_section_by_name (dynobj, ".got"); - BFD_ASSERT (sgot != NULL); - } + BFD_ASSERT (sgot != NULL); if (h != NULL) { @@ -3248,7 +3264,8 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, procedure linkage table. */ BFD_ASSERT (h != NULL); - if (h->plt.offset == (bfd_vma) -1) + if (h->plt.offset == (bfd_vma) -1 + || splt == NULL) { /* We didn't make a PLT entry for this symbol. This happens when statically linking PIC code, or when @@ -3256,12 +3273,6 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, break; } - if (splt == NULL) - { - splt = bfd_get_section_by_name (dynobj, ".plt"); - BFD_ASSERT (splt != NULL); - } - relocation = (splt->output_section->vma + splt->output_offset + h->plt.offset); @@ -3269,46 +3280,53 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, /* relocate against _SDA_BASE_ */ case (int)R_PPC_SDAREL16: - BFD_ASSERT (sec != (asection *)0); - if (strcmp (bfd_get_section_name (abfd, sec), ".sdata") != 0 - && strcmp (bfd_get_section_name (abfd, sec), ".dynsbss") != 0 - && strcmp (bfd_get_section_name (abfd, sec), ".sbss") != 0) - { - (*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong section (%s)"), - bfd_get_filename (input_bfd), - sym_name, - ppc_elf_howto_table[ (int)r_type ]->name, - bfd_get_section_name (abfd, sec)); + { + const char *name; - bfd_set_error (bfd_error_bad_value); - ret = false; - continue; - } - addend -= (sdata->sym_hash->root.u.def.value - + sdata->sym_hash->root.u.def.section->output_section->vma - + sdata->sym_hash->root.u.def.section->output_offset); + BFD_ASSERT (sec != (asection *)0); + name = bfd_get_section_name (abfd, sec->output_section); + if (strcmp (name, ".sdata") != 0 + && strcmp (name, ".dynsbss") != 0 + && strcmp (name, ".sbss") != 0) + { + (*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"), + bfd_get_filename (input_bfd), + sym_name, + ppc_elf_howto_table[ (int)r_type ]->name, + name); + + bfd_set_error (bfd_error_bad_value); + ret = false; + continue; + } + addend -= (sdata->sym_hash->root.u.def.value + + sec->output_section->vma); + } break; /* relocate against _SDA2_BASE_ */ case (int)R_PPC_EMB_SDA2REL: - BFD_ASSERT (sec != (asection *)0); - if (strcmp (bfd_get_section_name (abfd, sec), ".sdata2") != 0 - && strcmp (bfd_get_section_name (abfd, sec), ".sbss2") != 0) - { - (*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong section (%s)"), - bfd_get_filename (input_bfd), - sym_name, - ppc_elf_howto_table[ (int)r_type ]->name, - bfd_get_section_name (abfd, sec)); + { + const char *name; - bfd_set_error (bfd_error_bad_value); - ret = false; - continue; - } - addend -= (sdata2->sym_hash->root.u.def.value - + sdata2->sym_hash->root.u.def.section->output_section->vma - + sdata2->sym_hash->root.u.def.section->output_offset); + BFD_ASSERT (sec != (asection *)0); + name = bfd_get_section_name (abfd, sec->output_section); + if (strcmp (name, ".sdata2") != 0 && strcmp (name, ".sbss2") != 0) + { + (*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"), + bfd_get_filename (input_bfd), + sym_name, + ppc_elf_howto_table[ (int)r_type ]->name, + name); + + bfd_set_error (bfd_error_bad_value); + ret = false; + continue; + } + addend -= (sdata2->sym_hash->root.u.def.value + + sec->output_section->vma); + } break; @@ -3316,24 +3334,23 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, case (int)R_PPC_EMB_SDA21: case (int)R_PPC_EMB_RELSDA: { - const char *name = bfd_get_section_name (abfd, sec); + const char *name; int reg; BFD_ASSERT (sec != (asection *)0); + name = bfd_get_section_name (abfd, sec->output_section); if (strcmp (name, ".sdata") == 0 || strcmp (name, ".sbss") == 0) { reg = 13; addend -= (sdata->sym_hash->root.u.def.value - + sdata->sym_hash->root.u.def.section->output_section->vma - + sdata->sym_hash->root.u.def.section->output_offset); + + sec->output_section->vma); } else if (strcmp (name, ".sdata2") == 0 || strcmp (name, ".sbss2") == 0) { reg = 2; addend -= (sdata2->sym_hash->root.u.def.value - + sdata2->sym_hash->root.u.def.section->output_section->vma - + sdata2->sym_hash->root.u.def.section->output_offset); + + sec->output_section->vma); } else if (strcmp (name, ".PPC.EMB.sdata0") == 0 || strcmp (name, ".PPC.EMB.sbss0") == 0) @@ -3343,11 +3360,11 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, else { - (*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong section (%s)"), + (*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"), bfd_get_filename (input_bfd), sym_name, ppc_elf_howto_table[ (int)r_type ]->name, - bfd_get_section_name (abfd, sec)); + name); bfd_set_error (bfd_error_bad_value); ret = false; -- 2.30.2