mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-26 05:20:30 +00:00
Mon Jun 16 18:56:27 1997 Geoff Keating <geoffk@ozemail.com.au>
* elf32-ppc.c (ppc_elf_relocate_section): Don't emit R_PPC_REL* relocs in shared libraries which refer to local symbols. Cope with addend when processing a GOT relocation. * elf32-ppc.c (ppc_elf_size_dynamic_sections): Only create symbols for sections that the linker didn't create. (ppc_elf_finish_dynamic_sections): Only try to write out a section symbol if it was created in ppc_elf_size_dynamic_sections. (ppc_elf_relocate_section): Complain if we have to generate a reloc relative to a section for which we didn't output a symbol. * elf32-ppc.c (ppc_elf_size_dynamic_sections): Clean up. PLT relocs are 'rela' relocs, like everything else. .rela.plt is not a read-only section, so we don't have to special-case it. * elf32-ppc.c (ppc_elf_adjust_dynamic_symbol): Entries in the .rela.bss section are (of course) 'rela' relocs not 'rel' relocs. * elf32-ppc.c (ppc_elf_check_relocs): Initialise srelgot. (ppc_elf_relocate_section): @got offsets are 4 from start of the actual .got section. * elflink.c (_bfd_elf_create_got_section): The three reserved words start from the symbol '_GLOBAL_OFFSET_TABLE_'. * elf32-ppc.c (ppc_elf_size_dynamic_sections): '.rela' is 5 characters, not 4. * elf32-ppc.c (ppc_elf_check_relocs): Use _bfd_elf_create_got_section to create the GOT rather than ppc_elf_create_linker_section. Create the '.rela.got' section ourselves. (ppc_elf_finish_dynamic_symbol): Set up GOT relocations when a symbol has a GOT entry. (ppc_elf_relocate_section): Record when a symbol is used through the GOT, and allocate space in the GOT for each such symbol. (ppc_elf_adjust_dynamic_symbol): Delete unused .got.plt stuff. (ppc_elf_create_linker_section): Delete unused LINKER_SECTION_GOT stuff. * elf32-ppc.c (ppc_elf_howto_raw): GOT16_HA relocs should be treated in a similar way to ADDR16_HA relocs. (ppc_elf_relocate_section): PLTREL24 relocs do not get copied into shared objects; the linker must deal with them. (ppc_elf_create_linker_section): Stop setting _GLOBAL_OFFSET_TABLE_ to the wrong value; delete unused LINKER_SECTION_PLT stuff. (ppc_elf_check_relocs): Delete unused LINKER_SECTION_PLT stuff. (ppc_elf_finish_dynamic_sections): Use BFD calls to get GOT section, not ELF-specific calls. (elf_backend_plt_not_loaded): Set to 1. (elf_backend_got_symbol_offset): Set to 4. * elf-bfd.h (elf_backend_data): Add 'plt_not_loaded' member for when ld.so fills in the PLT; and 'got_symbol_offset' member. * elflink.c (_bfd_elf_create_dynamic_sections): Apply plt_not_loaded member. (_bfd_elf_create_got_section): Apply got_symbol_offset. * elfxx-target.h (elf_backend_plt_not_loaded): Set default to 'loaded'. (elf_backend_G_O_T_offset): Set default to 0. (elfNN_bed): Set added fields. * elf32-ppc.c (ppc_elf_size_dynamic_sections): Was setting DT_RELENT in shared objects; should be DT_RELAENT. * elf32-ppc.c (ppc_elf_relocate_section): Propagate R_PPC_ADDR16_HA relocs to shared objects. Cope with case where such a reloc (in a non-shared object) refers to a symbol that's not defined.
This commit is contained in:
parent
3a0358617e
commit
b6eb341bf8
@ -1,3 +1,74 @@
|
||||
Mon Jun 16 18:56:27 1997 Geoff Keating <geoffk@ozemail.com.au>
|
||||
|
||||
* elf32-ppc.c (ppc_elf_relocate_section): Don't emit R_PPC_REL*
|
||||
relocs in shared libraries which refer to local symbols. Cope
|
||||
with addend when processing a GOT relocation.
|
||||
|
||||
* elf32-ppc.c (ppc_elf_size_dynamic_sections): Only create symbols
|
||||
for sections that the linker didn't create.
|
||||
(ppc_elf_finish_dynamic_sections): Only try to write out a section
|
||||
symbol if it was created in ppc_elf_size_dynamic_sections.
|
||||
(ppc_elf_relocate_section): Complain if we have to generate a reloc
|
||||
relative to a section for which we didn't output a symbol.
|
||||
|
||||
* elf32-ppc.c (ppc_elf_size_dynamic_sections): Clean up. PLT
|
||||
relocs are 'rela' relocs, like everything else. .rela.plt is not
|
||||
a read-only section, so we don't have to special-case it.
|
||||
|
||||
* elf32-ppc.c (ppc_elf_adjust_dynamic_symbol): Entries in the
|
||||
.rela.bss section are (of course) 'rela' relocs not 'rel' relocs.
|
||||
|
||||
* elf32-ppc.c (ppc_elf_check_relocs): Initialise srelgot.
|
||||
(ppc_elf_relocate_section): @got offsets are 4 from start of the
|
||||
actual .got section.
|
||||
* elflink.c (_bfd_elf_create_got_section): The three reserved
|
||||
words start from the symbol '_GLOBAL_OFFSET_TABLE_'.
|
||||
|
||||
* elf32-ppc.c (ppc_elf_size_dynamic_sections): '.rela' is 5
|
||||
characters, not 4.
|
||||
|
||||
* elf32-ppc.c (ppc_elf_check_relocs): Use
|
||||
_bfd_elf_create_got_section to create the GOT rather than
|
||||
ppc_elf_create_linker_section. Create the '.rela.got' section
|
||||
ourselves.
|
||||
(ppc_elf_finish_dynamic_symbol): Set up GOT relocations when a
|
||||
symbol has a GOT entry.
|
||||
(ppc_elf_relocate_section): Record when a symbol is used through
|
||||
the GOT, and allocate space in the GOT for each such symbol.
|
||||
(ppc_elf_adjust_dynamic_symbol): Delete unused .got.plt stuff.
|
||||
(ppc_elf_create_linker_section): Delete unused LINKER_SECTION_GOT
|
||||
stuff.
|
||||
|
||||
* elf32-ppc.c (ppc_elf_howto_raw): GOT16_HA relocs should be
|
||||
treated in a similar way to ADDR16_HA relocs.
|
||||
(ppc_elf_relocate_section): PLTREL24 relocs do not get copied into
|
||||
shared objects; the linker must deal with them.
|
||||
(ppc_elf_create_linker_section): Stop setting
|
||||
_GLOBAL_OFFSET_TABLE_ to the wrong value; delete unused
|
||||
LINKER_SECTION_PLT stuff.
|
||||
(ppc_elf_check_relocs): Delete unused LINKER_SECTION_PLT stuff.
|
||||
(ppc_elf_finish_dynamic_sections): Use BFD calls to get GOT
|
||||
section, not ELF-specific calls.
|
||||
(elf_backend_plt_not_loaded): Set to 1.
|
||||
(elf_backend_got_symbol_offset): Set to 4.
|
||||
* elf-bfd.h (elf_backend_data): Add 'plt_not_loaded' member
|
||||
for when ld.so fills in the PLT; and 'got_symbol_offset' member.
|
||||
* elflink.c (_bfd_elf_create_dynamic_sections): Apply
|
||||
plt_not_loaded member.
|
||||
(_bfd_elf_create_got_section): Apply got_symbol_offset.
|
||||
* elfxx-target.h (elf_backend_plt_not_loaded): Set default to
|
||||
'loaded'.
|
||||
(elf_backend_G_O_T_offset): Set default to 0.
|
||||
(elfNN_bed): Set added fields.
|
||||
|
||||
* elf32-ppc.c (ppc_elf_size_dynamic_sections): Was setting
|
||||
DT_RELENT in shared objects; should be DT_RELAENT.
|
||||
|
||||
* elf32-ppc.c (ppc_elf_relocate_section): Propagate
|
||||
R_PPC_ADDR16_HA relocs to shared objects. Cope with case where
|
||||
such a reloc (in a non-shared object) refers to a symbol that's
|
||||
not defined.
|
||||
|
||||
Mon Jun 16 14:42:14 1997 H.J. Lu <hjl@gnu.ai.mit.edu>
|
||||
|
||||
* elfcode.h (put_signed_word): Define.
|
||||
|
517
bfd/elf32-ppc.c
517
bfd/elf32-ppc.c
@ -452,13 +452,13 @@ static reloc_howto_type ppc_elf_howto_raw[] =
|
||||
/* Like R_PPC_ADDR16_HA, but referring to the GOT table entry for
|
||||
the symbol. */
|
||||
HOWTO (R_PPC_GOT16_HA, /* type */
|
||||
0, /* rightshift */
|
||||
16, /* rightshift */
|
||||
1, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
16, /* bitsize */
|
||||
false, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_bitfield, /* complain_on_overflow */
|
||||
bfd_elf_generic_reloc, /* special_function */
|
||||
ppc_elf_addr16_ha_reloc, /* special_function */
|
||||
"R_PPC_GOT16_HA", /* name */
|
||||
false, /* partial_inplace */
|
||||
0, /* src_mask */
|
||||
@ -1305,25 +1305,6 @@ ppc_elf_create_linker_section (abfd, info, which)
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return (elf_linker_section_t *)0;
|
||||
|
||||
case LINKER_SECTION_GOT: /* .got section */
|
||||
defaults.name = ".got";
|
||||
defaults.rel_name = ".rela.got";
|
||||
defaults.sym_name = "_GLOBAL_OFFSET_TABLE_";
|
||||
defaults.max_hole_offset = 32764;
|
||||
defaults.hole_size = 16;
|
||||
defaults.sym_offset = 4;
|
||||
break;
|
||||
|
||||
case LINKER_SECTION_PLT: /* .plt section */
|
||||
defaults.name = ".plt";
|
||||
defaults.rel_name = ".rela.plt";
|
||||
defaults.sym_name = (char *)0;
|
||||
defaults.max_hole_offset = 0;
|
||||
defaults.hole_size = 0;
|
||||
defaults.sym_offset = 0;
|
||||
defaults.flags &= ~SEC_LOAD;
|
||||
break;
|
||||
|
||||
case LINKER_SECTION_SDATA: /* .sdata/.sbss section */
|
||||
defaults.name = ".sdata";
|
||||
defaults.rel_name = ".rela.sdata";
|
||||
@ -1474,17 +1455,7 @@ ppc_elf_adjust_dynamic_symbol (info, h)
|
||||
/* Make room for this entry. */
|
||||
s->_raw_size += PLT_ENTRY_SIZE;
|
||||
|
||||
#if 0
|
||||
/* We also need to make an entry in the .got.plt section, which
|
||||
will be placed in the .got section by the linker script. */
|
||||
|
||||
s = bfd_get_section_by_name (dynobj, ".got.plt");
|
||||
BFD_ASSERT (s != NULL);
|
||||
s->_raw_size += 4;
|
||||
#endif
|
||||
|
||||
/* We also need to make an entry in the .rela.plt section. */
|
||||
|
||||
s = bfd_get_section_by_name (dynobj, ".rela.plt");
|
||||
BFD_ASSERT (s != NULL);
|
||||
s->_raw_size += sizeof (Elf32_External_Rela);
|
||||
@ -1537,7 +1508,7 @@ ppc_elf_adjust_dynamic_symbol (info, h)
|
||||
|
||||
srel = bfd_get_section_by_name (dynobj, ".rela.bss");
|
||||
BFD_ASSERT (srel != NULL);
|
||||
srel->_raw_size += sizeof (Elf32_External_Rel);
|
||||
srel->_raw_size += sizeof (Elf32_External_Rela);
|
||||
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY;
|
||||
}
|
||||
|
||||
@ -1689,27 +1660,19 @@ ppc_elf_size_dynamic_sections (output_bfd, info)
|
||||
else
|
||||
{
|
||||
asection *target;
|
||||
const char *outname;
|
||||
|
||||
/* Remember whether there are any reloc sections other
|
||||
than .rel.plt. */
|
||||
if (strcmp (name, ".rela.plt") != 0)
|
||||
{
|
||||
const char *outname;
|
||||
/* Remember whether there are any relocation sections. */
|
||||
relocs = true;
|
||||
|
||||
relocs = true;
|
||||
|
||||
/* If this relocation section applies to a read only
|
||||
section, then we probably need a DT_TEXTREL
|
||||
entry. The entries in the .rel.plt section
|
||||
really apply to the .got section, which we
|
||||
created ourselves and so know is not readonly. */
|
||||
outname = bfd_get_section_name (output_bfd,
|
||||
s->output_section);
|
||||
target = bfd_get_section_by_name (output_bfd, outname + 4);
|
||||
if (target != NULL
|
||||
&& (target->flags & SEC_READONLY) != 0)
|
||||
reltext = true;
|
||||
}
|
||||
/* If this relocation section applies to a read only
|
||||
section, then we probably need a DT_TEXTREL entry. */
|
||||
outname = bfd_get_section_name (output_bfd,
|
||||
s->output_section);
|
||||
target = bfd_get_section_by_name (output_bfd, outname + 5);
|
||||
if (target != NULL
|
||||
&& (target->flags & SEC_READONLY) != 0)
|
||||
reltext = true;
|
||||
|
||||
/* We use the reloc_count field as a counter if we need
|
||||
to copy relocs into the output file. */
|
||||
@ -1761,7 +1724,7 @@ ppc_elf_size_dynamic_sections (output_bfd, info)
|
||||
{
|
||||
if (! bfd_elf32_add_dynamic_entry (info, DT_PLTGOT, 0)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_PLTRELSZ, 0)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_PLTREL, DT_REL)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_PLTREL, DT_RELA)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_JMPREL, 0))
|
||||
return false;
|
||||
}
|
||||
@ -1769,8 +1732,8 @@ ppc_elf_size_dynamic_sections (output_bfd, info)
|
||||
if (relocs)
|
||||
{
|
||||
if (! bfd_elf32_add_dynamic_entry (info, DT_RELA, 0)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_RELASZ, DT_RELA)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_RELENT,
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_RELASZ, 0)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_RELAENT,
|
||||
sizeof (Elf32_External_Rela)))
|
||||
return false;
|
||||
}
|
||||
@ -1786,23 +1749,42 @@ ppc_elf_size_dynamic_sections (output_bfd, info)
|
||||
symbol for each output section. These are local symbols, which
|
||||
means that they must come first in the dynamic symbol table.
|
||||
That means we must increment the dynamic symbol index of every
|
||||
other dynamic symbol. */
|
||||
other dynamic symbol.
|
||||
|
||||
FIXME: We assume that there will never be relocations to
|
||||
locations in linker-created sections that do not have
|
||||
externally-visible names. Instead, we should work out precisely
|
||||
which sections relocations are targetted at. */
|
||||
if (info->shared)
|
||||
{
|
||||
int c, i;
|
||||
|
||||
c = bfd_count_sections (output_bfd);
|
||||
for (c = 0, s = output_bfd->sections; s != NULL; s = s->next)
|
||||
{
|
||||
if ((s->flags & SEC_LINKER_CREATED) != 0)
|
||||
continue;
|
||||
c++;
|
||||
}
|
||||
|
||||
elf_link_hash_traverse (elf_hash_table (info),
|
||||
ppc_elf_adjust_dynindx,
|
||||
(PTR) &c);
|
||||
elf_hash_table (info)->dynsymcount += c;
|
||||
|
||||
for (i = 1, s = output_bfd->sections; s != NULL; s = s->next, i++)
|
||||
for (i = 1, s = output_bfd->sections; s != NULL; s = s->next)
|
||||
{
|
||||
elf_section_data (s)->dynindx = i;
|
||||
/* These symbols will have no names, so we don't need to
|
||||
fiddle with dynstr_index. */
|
||||
if ((s->flags & SEC_LINKER_CREATED) != 0)
|
||||
elf_section_data (s)->dynindx = -1;
|
||||
else
|
||||
{
|
||||
elf_section_data (s)->dynindx = i;
|
||||
/* These symbols will have no names, so we don't need to
|
||||
fiddle with dynstr_index. */
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
BFD_ASSERT(i == c + 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -1827,10 +1809,11 @@ ppc_elf_check_relocs (abfd, info, sec, relocs)
|
||||
const Elf_Internal_Rela *rel;
|
||||
const Elf_Internal_Rela *rel_end;
|
||||
bfd_vma *local_got_offsets;
|
||||
elf_linker_section_t *got;
|
||||
elf_linker_section_t *sdata;
|
||||
elf_linker_section_t *sdata2;
|
||||
asection *sreloc;
|
||||
asection *sgot;
|
||||
asection *srelgot = NULL;
|
||||
|
||||
if (info->relocateable)
|
||||
return true;
|
||||
@ -1842,17 +1825,7 @@ ppc_elf_check_relocs (abfd, info, sec, relocs)
|
||||
#endif
|
||||
|
||||
/* Create the linker generated sections all the time so that the
|
||||
special symbols are created. The .got section is an exception,
|
||||
so that we don't waste space allocating it when it is not needed. */
|
||||
|
||||
#if 0
|
||||
if ((plt = elf_linker_section (abfd, LINKER_SECTION_PLT)) == NULL)
|
||||
{
|
||||
plt = ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_PLT);
|
||||
if (!plt)
|
||||
ret = false;
|
||||
}
|
||||
#endif
|
||||
special symbols are created. */
|
||||
|
||||
if ((sdata = elf_linker_section (abfd, LINKER_SECTION_SDATA)) == NULL)
|
||||
{
|
||||
@ -1869,18 +1842,19 @@ ppc_elf_check_relocs (abfd, info, sec, relocs)
|
||||
ret = false;
|
||||
}
|
||||
|
||||
if ((got = elf_linker_section (abfd, LINKER_SECTION_GOT)) == NULL)
|
||||
{
|
||||
got = ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_GOT);
|
||||
if (!got)
|
||||
ret = false;
|
||||
}
|
||||
|
||||
dynobj = elf_hash_table (info)->dynobj;
|
||||
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
|
||||
sym_hashes = elf_sym_hashes (abfd);
|
||||
local_got_offsets = elf_local_got_offsets (abfd);
|
||||
|
||||
/* FIXME: We should only create the .got section if we need it.
|
||||
Otherwise we waste space in a statically linked executable. */
|
||||
|
||||
if (! _bfd_elf_create_got_section (dynobj, info))
|
||||
return false;
|
||||
sgot = bfd_get_section_by_name (dynobj, ".got");
|
||||
BFD_ASSERT (sgot != NULL);
|
||||
|
||||
sreloc = NULL;
|
||||
|
||||
rel_end = relocs + sec->reloc_count;
|
||||
@ -1902,16 +1876,78 @@ ppc_elf_check_relocs (abfd, info, sec, relocs)
|
||||
case R_PPC_GOT16_LO:
|
||||
case R_PPC_GOT16_HI:
|
||||
case R_PPC_GOT16_HA:
|
||||
if (got->rel_section == NULL
|
||||
&& (h != NULL || info->shared)
|
||||
&& !_bfd_elf_make_linker_section_rela (dynobj, got, 2))
|
||||
if (srelgot == NULL
|
||||
&& (h != NULL || info->shared))
|
||||
{
|
||||
ret = false;
|
||||
break;
|
||||
srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
|
||||
if (srelgot == NULL)
|
||||
{
|
||||
srelgot = bfd_make_section (dynobj, ".rela.got");
|
||||
if (srelgot == NULL
|
||||
|| ! bfd_set_section_flags (dynobj, srelgot,
|
||||
(SEC_ALLOC
|
||||
| SEC_LOAD
|
||||
| SEC_HAS_CONTENTS
|
||||
| SEC_IN_MEMORY
|
||||
| SEC_LINKER_CREATED
|
||||
| SEC_READONLY))
|
||||
|| ! bfd_set_section_alignment (dynobj, srelgot, 2))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bfd_elf32_create_pointer_linker_section (abfd, info, got, h, rel))
|
||||
ret = false;
|
||||
if (h != NULL)
|
||||
{
|
||||
if (h->got_offset != (bfd_vma) -1)
|
||||
{
|
||||
/* We have already allocated space in the .got. */
|
||||
break;
|
||||
}
|
||||
h->got_offset = sgot->_raw_size;
|
||||
|
||||
/* Make sure this symbol is output as a dynamic symbol. */
|
||||
if (h->dynindx == -1)
|
||||
{
|
||||
if (! bfd_elf32_link_record_dynamic_symbol (info, h))
|
||||
return false;
|
||||
}
|
||||
|
||||
srelgot->_raw_size += sizeof (Elf32_External_Rela);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is a global offset table entry for a local
|
||||
symbol. */
|
||||
if (local_got_offsets == NULL)
|
||||
{
|
||||
size_t size;
|
||||
register unsigned int i;
|
||||
|
||||
size = symtab_hdr->sh_info * sizeof (bfd_vma);
|
||||
local_got_offsets = (bfd_vma *) bfd_alloc (abfd, size);
|
||||
if (local_got_offsets == NULL)
|
||||
return false;
|
||||
elf_local_got_offsets (abfd) = local_got_offsets;
|
||||
for (i = 0; i < symtab_hdr->sh_info; i++)
|
||||
local_got_offsets[i] = (bfd_vma) -1;
|
||||
}
|
||||
if (local_got_offsets[r_symndx] != (bfd_vma) -1)
|
||||
{
|
||||
/* We have already allocated space in the .got. */
|
||||
break;
|
||||
}
|
||||
local_got_offsets[r_symndx] = sgot->_raw_size;
|
||||
|
||||
if (info->shared)
|
||||
{
|
||||
/* If we are generating a shared object, we need to
|
||||
output a R_PPC_RELATIVE reloc so that the
|
||||
dynamic linker can adjust this GOT entry. */
|
||||
srelgot->_raw_size += sizeof (Elf32_External_Rela);
|
||||
}
|
||||
}
|
||||
|
||||
sgot->_raw_size += 4;
|
||||
|
||||
break;
|
||||
|
||||
@ -1926,26 +1962,26 @@ ppc_elf_check_relocs (abfd, info, sec, relocs)
|
||||
break;
|
||||
}
|
||||
|
||||
if (got == NULL
|
||||
&& (got = elf_linker_section (abfd, LINKER_SECTION_GOT)) == NULL)
|
||||
if (srelgot == NULL
|
||||
&& (h != NULL || info->shared))
|
||||
{
|
||||
got = ppc_elf_create_linker_section (abfd, info,
|
||||
LINKER_SECTION_GOT);
|
||||
if (!got)
|
||||
srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
|
||||
if (srelgot == NULL)
|
||||
{
|
||||
ret = false;
|
||||
break;
|
||||
srelgot = bfd_make_section (dynobj, ".rela.got");
|
||||
if (srelgot == NULL
|
||||
|| ! bfd_set_section_flags (dynobj, srelgot,
|
||||
(SEC_ALLOC
|
||||
| SEC_LOAD
|
||||
| SEC_HAS_CONTENTS
|
||||
| SEC_IN_MEMORY
|
||||
| SEC_LINKER_CREATED
|
||||
| SEC_READONLY))
|
||||
|| ! bfd_set_section_alignment (dynobj, srelgot, 2))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (got->rel_section == NULL
|
||||
&& (h != NULL || info->shared)
|
||||
&& !_bfd_elf_make_linker_section_rela (dynobj, got, 2))
|
||||
{
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!bfd_elf32_create_pointer_linker_section (abfd, info, sdata, h, rel))
|
||||
ret = false;
|
||||
|
||||
@ -1962,23 +1998,26 @@ ppc_elf_check_relocs (abfd, info, sec, relocs)
|
||||
break;
|
||||
}
|
||||
|
||||
if (got == NULL
|
||||
&& (got = elf_linker_section (abfd, LINKER_SECTION_GOT)) == NULL)
|
||||
if (srelgot == NULL
|
||||
&& (h != NULL || info->shared))
|
||||
{
|
||||
got = ppc_elf_create_linker_section (abfd, info,
|
||||
LINKER_SECTION_GOT);
|
||||
if (!got)
|
||||
srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
|
||||
if (srelgot == NULL)
|
||||
{
|
||||
ret = false;
|
||||
break;
|
||||
srelgot = bfd_make_section (dynobj, ".rela.got");
|
||||
if (srelgot == NULL
|
||||
|| ! bfd_set_section_flags (dynobj, srelgot,
|
||||
(SEC_ALLOC
|
||||
| SEC_LOAD
|
||||
| SEC_HAS_CONTENTS
|
||||
| SEC_IN_MEMORY
|
||||
| SEC_LINKER_CREATED
|
||||
| SEC_READONLY))
|
||||
|| ! bfd_set_section_alignment (dynobj, srelgot, 2))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (got->rel_section == NULL
|
||||
&& (h != NULL || info->shared)
|
||||
&& !_bfd_elf_make_linker_section_rela (dynobj, got, 2))
|
||||
return false;
|
||||
|
||||
if (!bfd_elf32_create_pointer_linker_section (abfd, info, sdata2, h, rel))
|
||||
return false;
|
||||
|
||||
@ -2032,8 +2071,9 @@ ppc_elf_check_relocs (abfd, info, sec, relocs)
|
||||
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
|
||||
break;
|
||||
|
||||
/* the following relocations don't need to propigate the relocation if
|
||||
linking a shared object since they are section relative. */
|
||||
/* The following relocations don't need to propagate the
|
||||
relocation if linking a shared object since they are
|
||||
section relative. */
|
||||
case R_PPC_SECTOFF:
|
||||
case R_PPC_SECTOFF_LO:
|
||||
case R_PPC_SECTOFF_HI:
|
||||
@ -2061,8 +2101,7 @@ ppc_elf_check_relocs (abfd, info, sec, relocs)
|
||||
/* fall through */
|
||||
|
||||
default:
|
||||
if (info->shared
|
||||
&& (sec->flags & SEC_ALLOC) != 0)
|
||||
if (info->shared)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "ppc_elf_check_relocs need to create relocation for %s\n",
|
||||
@ -2208,8 +2247,8 @@ ppc_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
|
||||
srela = bfd_get_section_by_name (dynobj, ".rela.plt");
|
||||
BFD_ASSERT (splt != NULL && srela != NULL);
|
||||
|
||||
/* We don't need to fill in the .plt. The solaris dynamic linker will
|
||||
fill it in. */
|
||||
/* We don't need to fill in the .plt. The ppc dynamic linker
|
||||
will fill it in. */
|
||||
|
||||
/* Fill in the entry in the .rela.plt section. */
|
||||
rela.r_offset = (splt->output_section->vma
|
||||
@ -2229,6 +2268,46 @@ ppc_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
|
||||
}
|
||||
}
|
||||
|
||||
if (h->got_offset != (bfd_vma) -1)
|
||||
{
|
||||
asection *sgot;
|
||||
asection *srela;
|
||||
Elf_Internal_Rela rela;
|
||||
|
||||
/* This symbol has an entry in the global offset table. Set it
|
||||
up. */
|
||||
|
||||
BFD_ASSERT (h->dynindx != -1);
|
||||
|
||||
sgot = bfd_get_section_by_name (dynobj, ".got");
|
||||
srela = bfd_get_section_by_name (dynobj, ".rela.got");
|
||||
BFD_ASSERT (sgot != NULL && srela != NULL);
|
||||
|
||||
rela.r_offset = (sgot->output_section->vma
|
||||
+ sgot->output_offset
|
||||
+ (h->got_offset &~ 1));
|
||||
|
||||
/* If this is a -Bsymbolic link, and the symbol is defined
|
||||
locally, we just want to emit a RELATIVE reloc. The entry in
|
||||
the global offset table will already have been initialized in
|
||||
the relocate_section function. */
|
||||
if (info->shared
|
||||
&& info->symbolic
|
||||
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
|
||||
rela.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE);
|
||||
else
|
||||
{
|
||||
bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got_offset);
|
||||
rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_GLOB_DAT);
|
||||
}
|
||||
|
||||
rela.r_addend = 0;
|
||||
bfd_elf32_swap_reloca_out (output_bfd, &rela,
|
||||
((Elf32_External_Rela *) srela->contents
|
||||
+ srela->reloc_count));
|
||||
++srela->reloc_count;
|
||||
}
|
||||
|
||||
if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0)
|
||||
{
|
||||
asection *s;
|
||||
@ -2280,7 +2359,7 @@ ppc_elf_finish_dynamic_sections (output_bfd, info)
|
||||
{
|
||||
asection *sdyn;
|
||||
bfd *dynobj = elf_hash_table (info)->dynobj;
|
||||
elf_linker_section_t *got = elf_linker_section (dynobj, LINKER_SECTION_GOT);
|
||||
asection *sgot = bfd_get_section_by_name (dynobj, ".got");
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "ppc_elf_finish_dynamic_sections called\n");
|
||||
@ -2340,9 +2419,9 @@ ppc_elf_finish_dynamic_sections (output_bfd, info)
|
||||
|
||||
/* Add a blrl instruction at _GLOBAL_OFFSET_TABLE_-4 so that a function can
|
||||
easily find the address of the _GLOBAL_OFFSET_TABLE_. */
|
||||
if (got)
|
||||
if (sgot)
|
||||
{
|
||||
unsigned char *contents = got->section->contents + got->hole_offset;
|
||||
unsigned char *contents = sgot->contents;
|
||||
bfd_put_32 (output_bfd, 0x4e800021 /* blrl */, contents);
|
||||
|
||||
if (sdyn == NULL)
|
||||
@ -2352,7 +2431,7 @@ ppc_elf_finish_dynamic_sections (output_bfd, info)
|
||||
sdyn->output_section->vma + sdyn->output_offset,
|
||||
contents+4);
|
||||
|
||||
elf_section_data (got->section->output_section)->this_hdr.sh_entsize = 4;
|
||||
elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
|
||||
}
|
||||
|
||||
if (info->shared)
|
||||
@ -2360,6 +2439,7 @@ ppc_elf_finish_dynamic_sections (output_bfd, info)
|
||||
asection *sdynsym;
|
||||
asection *s;
|
||||
Elf_Internal_Sym sym;
|
||||
int maxdindx = 0;
|
||||
|
||||
/* Set up the section symbols for the output sections. */
|
||||
|
||||
@ -2373,24 +2453,33 @@ ppc_elf_finish_dynamic_sections (output_bfd, info)
|
||||
|
||||
for (s = output_bfd->sections; s != NULL; s = s->next)
|
||||
{
|
||||
int indx;
|
||||
int indx, dindx;
|
||||
|
||||
sym.st_value = s->vma;
|
||||
|
||||
indx = elf_section_data (s)->this_idx;
|
||||
BFD_ASSERT (indx > 0);
|
||||
sym.st_shndx = indx;
|
||||
dindx = elf_section_data (s)->dynindx;
|
||||
if (dindx != -1)
|
||||
{
|
||||
BFD_ASSERT(indx > 0);
|
||||
BFD_ASSERT(dindx > 0);
|
||||
|
||||
if (dindx > maxdindx)
|
||||
maxdindx = dindx;
|
||||
|
||||
bfd_elf32_swap_symbol_out (output_bfd, &sym,
|
||||
(PTR) (((Elf32_External_Sym *)
|
||||
sdynsym->contents)
|
||||
+ elf_section_data (s)->dynindx));
|
||||
sym.st_shndx = indx;
|
||||
|
||||
bfd_elf32_swap_symbol_out (output_bfd, &sym,
|
||||
(PTR) (((Elf32_External_Sym *)
|
||||
sdynsym->contents)
|
||||
+ dindx));
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the sh_info field of the output .dynsym section to the
|
||||
index of the first global symbol. */
|
||||
elf_section_data (sdynsym->output_section)->this_hdr.sh_info =
|
||||
bfd_count_sections (output_bfd) + 1;
|
||||
maxdindx + 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -2441,12 +2530,14 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
Elf_Internal_Shdr *symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
|
||||
struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
|
||||
bfd *dynobj = elf_hash_table (info)->dynobj;
|
||||
elf_linker_section_t *got = (dynobj) ? elf_linker_section (dynobj, LINKER_SECTION_GOT) : NULL;
|
||||
elf_linker_section_t *sdata = (dynobj) ? elf_linker_section (dynobj, LINKER_SECTION_SDATA) : NULL;
|
||||
elf_linker_section_t *sdata2 = (dynobj) ? elf_linker_section (dynobj, LINKER_SECTION_SDATA2) : NULL;
|
||||
Elf_Internal_Rela *rel = relocs;
|
||||
Elf_Internal_Rela *relend = relocs + input_section->reloc_count;
|
||||
asection *sreloc = NULL;
|
||||
asection *splt = NULL;
|
||||
asection *sgot = NULL;
|
||||
bfd_vma *local_got_offsets;
|
||||
boolean ret = true;
|
||||
long insn;
|
||||
|
||||
@ -2461,6 +2552,8 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
if (!ppc_elf_howto_table[ R_PPC_ADDR32 ]) /* Initialize howto table if needed */
|
||||
ppc_elf_howto_init ();
|
||||
|
||||
local_got_offsets = elf_local_got_offsets (input_bfd);
|
||||
|
||||
for (; rel < relend; rel++)
|
||||
{
|
||||
enum ppc_reloc_type r_type = (enum ppc_reloc_type)ELF32_R_TYPE (rel->r_info);
|
||||
@ -2635,25 +2728,25 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
|
||||
case (int)R_PPC_REL24:
|
||||
case (int)R_PPC_REL14:
|
||||
if (h != NULL
|
||||
&& strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
|
||||
if (h == NULL
|
||||
|| strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
|
||||
break;
|
||||
/* fall through */
|
||||
|
||||
/* Relocations that need to be propigated if this is a shared object */
|
||||
/* Relocations that need to be propagated if this is a shared
|
||||
object. */
|
||||
case (int)R_PPC_NONE:
|
||||
case (int)R_PPC_ADDR32:
|
||||
case (int)R_PPC_ADDR24:
|
||||
case (int)R_PPC_ADDR16:
|
||||
case (int)R_PPC_ADDR16_LO:
|
||||
case (int)R_PPC_ADDR16_HI:
|
||||
case (int)R_PPC_ADDR16_HA:
|
||||
case (int)R_PPC_ADDR14:
|
||||
case (int)R_PPC_UADDR32:
|
||||
case (int)R_PPC_UADDR16:
|
||||
case (int)R_PPC_REL32:
|
||||
case (int)R_PPC_PLTREL24:
|
||||
if (info->shared
|
||||
&& (input_section->flags & SEC_ALLOC) != 0)
|
||||
if (info->shared)
|
||||
{
|
||||
Elf_Internal_Rela outrel;
|
||||
boolean skip;
|
||||
@ -2754,8 +2847,7 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
|
||||
osec = sec->output_section;
|
||||
indx = elf_section_data (osec)->dynindx;
|
||||
if (indx == 0)
|
||||
abort ();
|
||||
BFD_ASSERT(indx > 0);
|
||||
}
|
||||
|
||||
outrel.r_info = ELF32_R_INFO (indx, r_type);
|
||||
@ -2770,8 +2862,24 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
++sreloc->reloc_count;
|
||||
|
||||
/* This reloc will be computed at runtime, so there's no
|
||||
need to do anything now. */
|
||||
continue;
|
||||
need to do anything now, unless this is a RELATIVE
|
||||
reloc in an unallocated section. */
|
||||
if (skip
|
||||
|| (input_section->flags & SEC_ALLOC) != 0
|
||||
|| ELF32_R_TYPE (outrel.r_info) != R_PPC_RELATIVE)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Arithmetic adjust relocations that aren't going into a
|
||||
shared object. */
|
||||
if (r_type == R_PPC_ADDR16_HA
|
||||
/* It's just possible that this symbol is a weak symbol
|
||||
that's not actually defined anywhere. In that case,
|
||||
'sec' would be NULL, and we should leave the symbol
|
||||
alone (it will be set to zero elsewhere in the link). */
|
||||
&& sec != NULL)
|
||||
{
|
||||
addend += ((relocation + addend) & 0x8000) << 1;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -2802,9 +2910,97 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
case (int)R_PPC_GOT16_LO:
|
||||
case (int)R_PPC_GOT16_HI:
|
||||
case (int)R_PPC_GOT16_HA:
|
||||
relocation = bfd_elf32_finish_pointer_linker_section (output_bfd, input_bfd, info,
|
||||
got, h, relocation, rel,
|
||||
R_PPC_RELATIVE);
|
||||
/* 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);
|
||||
}
|
||||
|
||||
if (h != NULL)
|
||||
{
|
||||
bfd_vma off;
|
||||
|
||||
off = h->got_offset;
|
||||
BFD_ASSERT (off != (bfd_vma) -1);
|
||||
|
||||
if (! elf_hash_table (info)->dynamic_sections_created
|
||||
|| (info->shared
|
||||
&& info->symbolic
|
||||
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
|
||||
{
|
||||
/* This is actually a static link, or it is a
|
||||
-Bsymbolic link and the symbol is defined
|
||||
locally. We must initialize this entry in the
|
||||
global offset table. Since the offset must
|
||||
always be a multiple of 4, we use the least
|
||||
significant bit to record whether we have
|
||||
initialized it already.
|
||||
|
||||
When doing a dynamic link, we create a .rela.got
|
||||
relocation entry to initialize the value. This
|
||||
is done in the finish_dynamic_symbol routine. */
|
||||
if ((off & 1) != 0)
|
||||
off &= ~1;
|
||||
else
|
||||
{
|
||||
bfd_put_32 (output_bfd, relocation + addend,
|
||||
sgot->contents + off);
|
||||
h->got_offset |= 1;
|
||||
}
|
||||
}
|
||||
|
||||
relocation = sgot->output_offset + off - 4;
|
||||
addend = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
bfd_vma off;
|
||||
|
||||
BFD_ASSERT (local_got_offsets != NULL
|
||||
&& local_got_offsets[r_symndx] != (bfd_vma) -1);
|
||||
|
||||
off = local_got_offsets[r_symndx];
|
||||
|
||||
/* The offset must always be a multiple of 4. We use
|
||||
the least significant bit to record whether we have
|
||||
already processed this entry. */
|
||||
if ((off & 1) != 0)
|
||||
off &= ~1;
|
||||
else
|
||||
{
|
||||
bfd_put_32 (output_bfd, relocation, sgot->contents + off);
|
||||
|
||||
if (info->shared)
|
||||
{
|
||||
asection *srelgot;
|
||||
Elf_Internal_Rela outrel;
|
||||
|
||||
/* We need to generate a R_PPC_RELATIVE reloc
|
||||
for the dynamic linker. */
|
||||
srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
|
||||
BFD_ASSERT (srelgot != NULL);
|
||||
|
||||
outrel.r_offset = (sgot->output_section->vma
|
||||
+ sgot->output_offset
|
||||
+ off);
|
||||
outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE);
|
||||
outrel.r_addend = relocation + addend;
|
||||
bfd_elf32_swap_reloca_out (output_bfd, &outrel,
|
||||
(((Elf32_External_Rela *)
|
||||
srelgot->contents)
|
||||
+ srelgot->reloc_count));
|
||||
++srelgot->reloc_count;
|
||||
}
|
||||
|
||||
local_got_offsets[r_symndx] |= 1;
|
||||
}
|
||||
|
||||
relocation = sgot->output_offset + off - 4;
|
||||
addend = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
/* Indirect .sdata relocation */
|
||||
@ -2836,12 +3032,30 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
addend -= sec->output_section->vma + sec->output_offset + 0x8000;
|
||||
break;
|
||||
|
||||
/* arithmetic adjust relocations */
|
||||
case (int)R_PPC_ADDR16_HA:
|
||||
BFD_ASSERT (sec != (asection *)0);
|
||||
addend += ((relocation + addend) & 0x8000) << 1;
|
||||
break;
|
||||
case (int)R_PPC_PLTREL24:
|
||||
/* Relocation is to the entry for this symbol in the
|
||||
procedure linkage table. */
|
||||
BFD_ASSERT (h != NULL);
|
||||
|
||||
if (h->plt_offset == (bfd_vma) -1)
|
||||
{
|
||||
/* We didn't make a PLT entry for this symbol. This
|
||||
happens when statically linking PIC code, or when
|
||||
using -Bsymbolic. */
|
||||
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);
|
||||
break;
|
||||
|
||||
/* relocate against _SDA_BASE_ */
|
||||
case (int)R_PPC_SDAREL16:
|
||||
BFD_ASSERT (sec != (asection *)0);
|
||||
@ -3078,6 +3292,9 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
#define ELF_MACHINE_ALT2 EM_PPC_OLD
|
||||
#endif
|
||||
|
||||
#define elf_backend_plt_not_loaded 1
|
||||
#define elf_backend_got_symbol_offset 4
|
||||
|
||||
#define bfd_elf32_bfd_copy_private_bfd_data ppc_elf_copy_private_bfd_data
|
||||
#define bfd_elf32_bfd_merge_private_bfd_data ppc_elf_merge_private_bfd_data
|
||||
#define bfd_elf32_bfd_set_private_flags ppc_elf_set_private_flags
|
||||
|
Loading…
Reference in New Issue
Block a user