1998-09-10 Geoff Keating <geoffk@ozemail.com.au>

* elf32-ppc.c (ppc_elf_relocate_section): If dynobj is NULL,
        assume there is no PLT or GOT.
This commit is contained in:
Richard Henderson
1998-09-11 20:15:54 +00:00
parent 05f1989d85
commit 7194b91a0f
2 changed files with 102 additions and 80 deletions

View File

@ -1,3 +1,8 @@
1998-09-10 Geoff Keating <geoffk@ozemail.com.au>
* 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 <nickc@cygnus.com> Wed Sep 9 14:24:12 1998 Nick Clifton <nickc@cygnus.com>
* elf32-arm.c (elf32_arm_find_nearest_line): New function: just * elf32-arm.c (elf32_arm_find_nearest_line): New function: just

View File

@ -953,7 +953,7 @@ ppc_elf_reloc_type_lookup (abfd, code)
bfd *abfd; bfd *abfd;
bfd_reloc_code_real_type code; 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]) if (!ppc_elf_howto_table[R_PPC_ADDR32])
/* Initialize howto table if needed */ /* Initialize howto table if needed */
@ -1431,27 +1431,26 @@ ppc_elf_adjust_dynamic_symbol (info, h)
if (h->type == STT_FUNC if (h->type == STT_FUNC
|| (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0) || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
{ {
if (! info->shared if (! elf_hash_table (info)->dynamic_sections_created
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0 || ((!info->shared || info->symbolic || h->dynindx == -1)
&& (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0) && (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 /* A PLT entry is not required/allowed when:
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;
}
/* GC may have rendered this entry unused. Note, however, that in 1. We are not using ld.so; because then the PLT entry
an executable all references to the symbol go to the PLT, so we can't be set up, so we can't use one.
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. */
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->plt.offset = (bfd_vma) -1;
h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
return true; return true;
@ -1860,7 +1859,7 @@ ppc_elf_check_relocs (abfd, info, sec, relocs)
elf_linker_section_t *sdata; elf_linker_section_t *sdata;
elf_linker_section_t *sdata2; elf_linker_section_t *sdata2;
asection *sreloc; asection *sreloc;
asection *sgot; asection *sgot = NULL;
asection *srelgot = NULL; asection *srelgot = NULL;
if (info->relocateable) if (info->relocateable)
@ -1913,6 +1912,22 @@ ppc_elf_check_relocs (abfd, info, sec, relocs)
else else
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 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)) switch (ELF32_R_TYPE (rel->r_info))
{ {
/* GOT16 relocations */ /* GOT16 relocations */
@ -1925,11 +1940,9 @@ ppc_elf_check_relocs (abfd, info, sec, relocs)
if (sgot == NULL) if (sgot == NULL)
{ {
if (dynobj == NULL) if (dynobj == NULL)
{
elf_hash_table (info)->dynobj = dynobj = abfd; elf_hash_table (info)->dynobj = dynobj = abfd;
if (! _bfd_elf_create_got_section (dynobj, info)) if (! _bfd_elf_create_got_section (dynobj, info))
return false; return false;
}
sgot = bfd_get_section_by_name (dynobj, ".got"); sgot = bfd_get_section_by_name (dynobj, ".got");
BFD_ASSERT (sgot != NULL); 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 *rel = relocs;
Elf_Internal_Rela *relend = relocs + input_section->reloc_count; Elf_Internal_Rela *relend = relocs + input_section->reloc_count;
asection *sreloc = NULL; asection *sreloc = NULL;
asection *splt = NULL; asection *splt;
asection *sgot = NULL; asection *sgot;
bfd_vma *local_got_offsets; bfd_vma *local_got_offsets;
boolean ret = true; boolean ret = true;
long insn; 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); 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++) 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 offset = rel->r_offset;
bfd_vma addend = rel->r_addend; bfd_vma addend = rel->r_addend;
bfd_reloc_status_type r = bfd_reloc_other; 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: case (int)R_PPC_GOT16_HA:
/* Relocation is to the entry for this symbol in the global /* Relocation is to the entry for this symbol in the global
offset table. */ offset table. */
if (sgot == NULL)
{
sgot = bfd_get_section_by_name (dynobj, ".got");
BFD_ASSERT (sgot != NULL); BFD_ASSERT (sgot != NULL);
}
if (h != NULL) if (h != NULL)
{ {
@ -3248,7 +3264,8 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
procedure linkage table. */ procedure linkage table. */
BFD_ASSERT (h != NULL); 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 /* We didn't make a PLT entry for this symbol. This
happens when statically linking PIC code, or when happens when statically linking PIC code, or when
@ -3256,12 +3273,6 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
break; break;
} }
if (splt == NULL)
{
splt = bfd_get_section_by_name (dynobj, ".plt");
BFD_ASSERT (splt != NULL);
}
relocation = (splt->output_section->vma relocation = (splt->output_section->vma
+ splt->output_offset + splt->output_offset
+ h->plt.offset); + h->plt.offset);
@ -3269,46 +3280,53 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
/* relocate against _SDA_BASE_ */ /* relocate against _SDA_BASE_ */
case (int)R_PPC_SDAREL16: 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)"), const char *name;
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), bfd_get_filename (input_bfd),
sym_name, sym_name,
ppc_elf_howto_table[ (int)r_type ]->name, ppc_elf_howto_table[ (int)r_type ]->name,
bfd_get_section_name (abfd, sec)); name);
bfd_set_error (bfd_error_bad_value); bfd_set_error (bfd_error_bad_value);
ret = false; ret = false;
continue; continue;
} }
addend -= (sdata->sym_hash->root.u.def.value addend -= (sdata->sym_hash->root.u.def.value
+ sdata->sym_hash->root.u.def.section->output_section->vma + sec->output_section->vma);
+ sdata->sym_hash->root.u.def.section->output_offset); }
break; break;
/* relocate against _SDA2_BASE_ */ /* relocate against _SDA2_BASE_ */
case (int)R_PPC_EMB_SDA2REL: 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)"), const char *name;
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), bfd_get_filename (input_bfd),
sym_name, sym_name,
ppc_elf_howto_table[ (int)r_type ]->name, ppc_elf_howto_table[ (int)r_type ]->name,
bfd_get_section_name (abfd, sec)); name);
bfd_set_error (bfd_error_bad_value); bfd_set_error (bfd_error_bad_value);
ret = false; ret = false;
continue; continue;
} }
addend -= (sdata2->sym_hash->root.u.def.value addend -= (sdata2->sym_hash->root.u.def.value
+ sdata2->sym_hash->root.u.def.section->output_section->vma + sec->output_section->vma);
+ sdata2->sym_hash->root.u.def.section->output_offset); }
break; 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_SDA21:
case (int)R_PPC_EMB_RELSDA: case (int)R_PPC_EMB_RELSDA:
{ {
const char *name = bfd_get_section_name (abfd, sec); const char *name;
int reg; int reg;
BFD_ASSERT (sec != (asection *)0); BFD_ASSERT (sec != (asection *)0);
name = bfd_get_section_name (abfd, sec->output_section);
if (strcmp (name, ".sdata") == 0 || strcmp (name, ".sbss") == 0) if (strcmp (name, ".sdata") == 0 || strcmp (name, ".sbss") == 0)
{ {
reg = 13; reg = 13;
addend -= (sdata->sym_hash->root.u.def.value addend -= (sdata->sym_hash->root.u.def.value
+ sdata->sym_hash->root.u.def.section->output_section->vma + sec->output_section->vma);
+ sdata->sym_hash->root.u.def.section->output_offset);
} }
else if (strcmp (name, ".sdata2") == 0 || strcmp (name, ".sbss2") == 0) else if (strcmp (name, ".sdata2") == 0 || strcmp (name, ".sbss2") == 0)
{ {
reg = 2; reg = 2;
addend -= (sdata2->sym_hash->root.u.def.value addend -= (sdata2->sym_hash->root.u.def.value
+ sdata2->sym_hash->root.u.def.section->output_section->vma + sec->output_section->vma);
+ sdata2->sym_hash->root.u.def.section->output_offset);
} }
else if (strcmp (name, ".PPC.EMB.sdata0") == 0 || strcmp (name, ".PPC.EMB.sbss0") == 0) 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 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), bfd_get_filename (input_bfd),
sym_name, sym_name,
ppc_elf_howto_table[ (int)r_type ]->name, ppc_elf_howto_table[ (int)r_type ]->name,
bfd_get_section_name (abfd, sec)); name);
bfd_set_error (bfd_error_bad_value); bfd_set_error (bfd_error_bad_value);
ret = false; ret = false;