* elf64-ppc.c: Remove stale part of ABI comment.
(NO_OPD_RELOCS): Define. (ppc64_elf_check_relocs): Use it. (ppc64_elf_relocate_section): Here too. (build_one_stub): Don't point function syms at the stub. Instead, hijack plt.offset. (ppc64_elf_relocate_section): Check whether REL24 relocs should really go to the stub. Make all dynamic relocs in opd against locals. (ppc64_elf_finish_dynamic_symbol): Allow for non-standard use of plt.offset.
This commit is contained in:
parent
13fc0c2f38
commit
41bd81abfa
|
@ -1,3 +1,17 @@
|
||||||
|
2002-01-23 Alan Modra <amodra@bigpond.net.au>
|
||||||
|
|
||||||
|
* elf64-ppc.c: Remove stale part of ABI comment.
|
||||||
|
(NO_OPD_RELOCS): Define.
|
||||||
|
(ppc64_elf_check_relocs): Use it.
|
||||||
|
(ppc64_elf_relocate_section): Here too.
|
||||||
|
(build_one_stub): Don't point function syms at the stub. Instead,
|
||||||
|
hijack plt.offset.
|
||||||
|
(ppc64_elf_relocate_section): Check whether REL24 relocs should
|
||||||
|
really go to the stub. Make all dynamic relocs in opd against
|
||||||
|
locals.
|
||||||
|
(ppc64_elf_finish_dynamic_symbol): Allow for non-standard use of
|
||||||
|
plt.offset.
|
||||||
|
|
||||||
2002-01-22 Richard Henderson <rth@redhat.com>
|
2002-01-22 Richard Henderson <rth@redhat.com>
|
||||||
|
|
||||||
* elf64-alpha.c (INSN_UNOP): Encode with RB as $sp.
|
* elf64-alpha.c (INSN_UNOP): Encode with RB as $sp.
|
||||||
|
|
103
bfd/elf64-ppc.c
103
bfd/elf64-ppc.c
|
@ -152,6 +152,18 @@ static boolean ppc64_elf_finish_dynamic_sections
|
||||||
a branch. */
|
a branch. */
|
||||||
#define LIS_R0_0 0x3c000000 /* lis %r0,0 */
|
#define LIS_R0_0 0x3c000000 /* lis %r0,0 */
|
||||||
#define ORI_R0_R0_0 0x60000000 /* ori %r0,%r0,0 */
|
#define ORI_R0_R0_0 0x60000000 /* ori %r0,%r0,0 */
|
||||||
|
|
||||||
|
/* Since .opd is an array of descriptors and each entry will end up
|
||||||
|
with identical R_PPC64_RELATIVE relocs, there is really no need to
|
||||||
|
propagate .opd relocs; The dynamic linker should be taught to
|
||||||
|
relocate .opd without reloc entries. FIXME: the dynamic linker
|
||||||
|
will need to know where and how large .opd is via a couple of new
|
||||||
|
DT_PPC64_* tags, or perhaps just with one reloc that specifies the
|
||||||
|
start of .opd via its offset and the size via its addend. Also,
|
||||||
|
.opd should be trimmed of unused values. */
|
||||||
|
#ifndef NO_OPD_RELOCS
|
||||||
|
#define NO_OPD_RELOCS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Relocation HOWTO's. */
|
/* Relocation HOWTO's. */
|
||||||
static reloc_howto_type *ppc64_elf_howto_table[(int) R_PPC_max];
|
static reloc_howto_type *ppc64_elf_howto_table[(int) R_PPC_max];
|
||||||
|
@ -1648,10 +1660,7 @@ ppc64_elf_section_from_shdr (abfd, hdr, name)
|
||||||
creating a shared library containing foo, we need to have both symbols
|
creating a shared library containing foo, we need to have both symbols
|
||||||
dynamic so that references to .foo are satisfied during the early
|
dynamic so that references to .foo are satisfied during the early
|
||||||
stages of linking. Otherwise the linker might decide to pull in a
|
stages of linking. Otherwise the linker might decide to pull in a
|
||||||
definition from some other object, eg. a static library. Thirdly, we'd
|
definition from some other object, eg. a static library. */
|
||||||
like to use .foo as the stub symbol to avoid creating another symbol.
|
|
||||||
We need to make sure that when .foo labels a stub in a shared library,
|
|
||||||
it isn't exported. */
|
|
||||||
|
|
||||||
/* The linker needs to keep track of the number of relocs that it
|
/* The linker needs to keep track of the number of relocs that it
|
||||||
decides to copy as dynamic relocs in check_relocs for each symbol.
|
decides to copy as dynamic relocs in check_relocs for each symbol.
|
||||||
|
@ -2123,11 +2132,9 @@ ppc64_elf_check_relocs (abfd, info, sec, relocs)
|
||||||
case R_PPC64_UADDR32:
|
case R_PPC64_UADDR32:
|
||||||
case R_PPC64_UADDR64:
|
case R_PPC64_UADDR64:
|
||||||
case R_PPC64_TOC:
|
case R_PPC64_TOC:
|
||||||
#if 0
|
/* Don't propagate .opd relocs. */
|
||||||
/* Don't propagate .opd relocs. */
|
if (NO_OPD_RELOCS && is_opd)
|
||||||
if (is_opd)
|
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
|
|
||||||
/* If we are creating a shared library, and this is a reloc
|
/* If we are creating a shared library, and this is a reloc
|
||||||
against a global symbol, or a non PC relative reloc
|
against a global symbol, or a non PC relative reloc
|
||||||
|
@ -3313,7 +3320,8 @@ build_one_stub (h, inf)
|
||||||
htab = ppc_hash_table (info);
|
htab = ppc_hash_table (info);
|
||||||
|
|
||||||
if (htab->elf.dynamic_sections_created
|
if (htab->elf.dynamic_sections_created
|
||||||
&& h->plt.offset != (bfd_vma) -1)
|
&& h->plt.offset != (bfd_vma) -1
|
||||||
|
&& ((struct ppc_link_hash_entry *) h)->is_func_descriptor)
|
||||||
{
|
{
|
||||||
struct elf_link_hash_entry *fh;
|
struct elf_link_hash_entry *fh;
|
||||||
asection *s;
|
asection *s;
|
||||||
|
@ -3321,8 +3329,6 @@ build_one_stub (h, inf)
|
||||||
bfd_byte *p;
|
bfd_byte *p;
|
||||||
unsigned int indx;
|
unsigned int indx;
|
||||||
|
|
||||||
BFD_ASSERT (((struct ppc_link_hash_entry *) h)->is_func_descriptor);
|
|
||||||
|
|
||||||
fh = elf_link_hash_lookup (&htab->elf, h->root.root.string - 1,
|
fh = elf_link_hash_lookup (&htab->elf, h->root.root.string - 1,
|
||||||
false, false, true);
|
false, false, true);
|
||||||
|
|
||||||
|
@ -3331,14 +3337,6 @@ build_one_stub (h, inf)
|
||||||
|
|
||||||
BFD_ASSERT (((struct ppc_link_hash_entry *) fh)->is_func);
|
BFD_ASSERT (((struct ppc_link_hash_entry *) fh)->is_func);
|
||||||
|
|
||||||
/* Point the function at the linkage stub. This works because
|
|
||||||
the only references to the function code sym are calls.
|
|
||||||
Function pointer comparisons use the function descriptor. */
|
|
||||||
s = htab->sstub;
|
|
||||||
fh->root.type = bfd_link_hash_defined;
|
|
||||||
fh->root.u.def.section = s;
|
|
||||||
fh->root.u.def.value = s->_cooked_size;
|
|
||||||
|
|
||||||
/* Build the .plt call stub. */
|
/* Build the .plt call stub. */
|
||||||
plt_r2 = (htab->splt->output_section->vma
|
plt_r2 = (htab->splt->output_section->vma
|
||||||
+ htab->splt->output_offset
|
+ htab->splt->output_offset
|
||||||
|
@ -3356,6 +3354,10 @@ build_one_stub (h, inf)
|
||||||
htab->plt_overflow = true;
|
htab->plt_overflow = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s = htab->sstub;
|
||||||
|
/* Steal plt.offset to store the stub offset. */
|
||||||
|
fh->plt.offset = s->_cooked_size;
|
||||||
p = s->contents + s->_cooked_size;
|
p = s->contents + s->_cooked_size;
|
||||||
p = build_plt_stub (s->owner, p, (int) plt_r2, 0);
|
p = build_plt_stub (s->owner, p, (int) plt_r2, 0);
|
||||||
s->_cooked_size = p - s->contents;
|
s->_cooked_size = p - s->contents;
|
||||||
|
@ -3501,6 +3503,7 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||||
bfd_vma *local_got_offsets;
|
bfd_vma *local_got_offsets;
|
||||||
bfd_vma TOCstart;
|
bfd_vma TOCstart;
|
||||||
boolean ret = true;
|
boolean ret = true;
|
||||||
|
boolean is_opd;
|
||||||
|
|
||||||
/* Initialize howto table if needed. */
|
/* Initialize howto table if needed. */
|
||||||
if (!ppc64_elf_howto_table[R_PPC64_ADDR32])
|
if (!ppc64_elf_howto_table[R_PPC64_ADDR32])
|
||||||
|
@ -3511,6 +3514,7 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||||
TOCstart = elf_gp (output_bfd);
|
TOCstart = elf_gp (output_bfd);
|
||||||
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
|
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
|
||||||
sym_hashes = elf_sym_hashes (input_bfd);
|
sym_hashes = elf_sym_hashes (input_bfd);
|
||||||
|
is_opd = strcmp (bfd_get_section_name (abfd, input_section), ".opd") == 0;
|
||||||
|
|
||||||
rel = relocs;
|
rel = relocs;
|
||||||
relend = relocs + input_section->reloc_count;
|
relend = relocs + input_section->reloc_count;
|
||||||
|
@ -3616,7 +3620,6 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||||
|| info->no_undefined
|
|| info->no_undefined
|
||||||
|| ELF_ST_VISIBILITY (h->other)))))
|
|| ELF_ST_VISIBILITY (h->other)))))
|
||||||
return false;
|
return false;
|
||||||
relocation = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3659,24 +3662,33 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||||
recognized by their need for a PLT entry. */
|
recognized by their need for a PLT entry. */
|
||||||
has_nop = 0;
|
has_nop = 0;
|
||||||
if (h != NULL
|
if (h != NULL
|
||||||
&& (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0
|
&& h->plt.offset != (bfd_vma) -1
|
||||||
|
&& htab->sstub != NULL)
|
||||||
|
{
|
||||||
|
/* plt.offset here is the offset into the stub section. */
|
||||||
|
relocation = (htab->sstub->output_section->vma
|
||||||
|
+ htab->sstub->output_offset
|
||||||
|
+ h->plt.offset);
|
||||||
|
unresolved_reloc = false;
|
||||||
|
|
||||||
/* Make sure that there really is an instruction after
|
/* Make sure that there really is an instruction after
|
||||||
the branch that we can decode. */
|
the branch that we can decode. */
|
||||||
&& offset + 8 <= input_section->_cooked_size)
|
if (offset + 8 <= input_section->_cooked_size)
|
||||||
{
|
|
||||||
bfd_byte *pnext;
|
|
||||||
|
|
||||||
pnext = contents + offset + 4;
|
|
||||||
insn = bfd_get_32 (input_bfd, pnext);
|
|
||||||
|
|
||||||
if (insn == 0x60000000 /* nop (ori r0,r0,0) */
|
|
||||||
|| insn == 0x4def7b82 /* cror 15,15,15 */
|
|
||||||
|| insn == 0x4ffffb82) /* cror 31,31,31 */
|
|
||||||
{
|
{
|
||||||
bfd_put_32 (input_bfd,
|
bfd_byte *pnext;
|
||||||
(bfd_vma) 0xe8410028, /* ld r2,40(r1) */
|
|
||||||
pnext);
|
pnext = contents + offset + 4;
|
||||||
has_nop = 1;
|
insn = bfd_get_32 (input_bfd, pnext);
|
||||||
|
|
||||||
|
if (insn == 0x60000000 /* nop (ori r0,r0,0) */
|
||||||
|
|| insn == 0x4def7b82 /* cror 15,15,15 */
|
||||||
|
|| insn == 0x4ffffb82) /* cror 31,31,31 */
|
||||||
|
{
|
||||||
|
bfd_put_32 (input_bfd,
|
||||||
|
(bfd_vma) 0xe8410028, /* ld r2,40(r1) */
|
||||||
|
pnext);
|
||||||
|
has_nop = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3912,6 +3924,9 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||||
if ((input_section->flags & SEC_ALLOC) == 0)
|
if ((input_section->flags & SEC_ALLOC) == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (NO_OPD_RELOCS && is_opd)
|
||||||
|
break;
|
||||||
|
|
||||||
if ((info->shared
|
if ((info->shared
|
||||||
&& (IS_ABSOLUTE_RELOC (r_type)
|
&& (IS_ABSOLUTE_RELOC (r_type)
|
||||||
|| (h != NULL
|
|| (h != NULL
|
||||||
|
@ -3935,12 +3950,6 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||||
asection *sreloc;
|
asection *sreloc;
|
||||||
Elf64_External_Rela *loc;
|
Elf64_External_Rela *loc;
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (strcmp (bfd_get_section_name (output_bfd, input_section),
|
|
||||||
".opd") == 0)
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* When generating a dynamic object, these relocations
|
/* When generating a dynamic object, these relocations
|
||||||
are copied into the output file to be resolved at run
|
are copied into the output file to be resolved at run
|
||||||
time. */
|
time. */
|
||||||
|
@ -3964,6 +3973,7 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||||
}
|
}
|
||||||
else if (h != NULL
|
else if (h != NULL
|
||||||
&& h->dynindx != -1
|
&& h->dynindx != -1
|
||||||
|
&& !is_opd
|
||||||
&& (!IS_ABSOLUTE_RELOC (r_type)
|
&& (!IS_ABSOLUTE_RELOC (r_type)
|
||||||
|| !info->shared
|
|| !info->shared
|
||||||
|| !info->symbolic
|
|| !info->symbolic
|
||||||
|
@ -3975,7 +3985,9 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* This symbol is local, or marked to become local. */
|
/* This symbol is local, or marked to become local,
|
||||||
|
or this is an opd section reloc which must point
|
||||||
|
at a local function. */
|
||||||
outrel.r_addend += relocation;
|
outrel.r_addend += relocation;
|
||||||
relocate = true;
|
relocate = true;
|
||||||
if (r_type == R_PPC64_ADDR64 || r_type == R_PPC64_TOC)
|
if (r_type == R_PPC64_ADDR64 || r_type == R_PPC64_TOC)
|
||||||
|
@ -3986,7 +3998,7 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||||
{
|
{
|
||||||
long indx = 0;
|
long indx = 0;
|
||||||
|
|
||||||
if (r_type == R_PPC64_TOC || bfd_is_abs_section (sec))
|
if (bfd_is_abs_section (sec))
|
||||||
;
|
;
|
||||||
else if (sec == NULL || sec->owner == NULL)
|
else if (sec == NULL || sec->owner == NULL)
|
||||||
{
|
{
|
||||||
|
@ -4185,7 +4197,8 @@ ppc64_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
|
||||||
htab = ppc_hash_table (info);
|
htab = ppc_hash_table (info);
|
||||||
dynobj = htab->elf.dynobj;
|
dynobj = htab->elf.dynobj;
|
||||||
|
|
||||||
if (h->plt.offset != (bfd_vma) -1)
|
if (h->plt.offset != (bfd_vma) -1
|
||||||
|
&& ((struct ppc_link_hash_entry *) h)->is_func_descriptor)
|
||||||
{
|
{
|
||||||
Elf_Internal_Rela rela;
|
Elf_Internal_Rela rela;
|
||||||
Elf64_External_Rela *loc;
|
Elf64_External_Rela *loc;
|
||||||
|
@ -4198,8 +4211,6 @@ ppc64_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
|
||||||
|| htab->sglink == NULL)
|
|| htab->sglink == NULL)
|
||||||
abort ();
|
abort ();
|
||||||
|
|
||||||
BFD_ASSERT (((struct ppc_link_hash_entry *) h)->is_func_descriptor);
|
|
||||||
|
|
||||||
/* Create a JMP_SLOT reloc to inform the dynamic linker to
|
/* Create a JMP_SLOT reloc to inform the dynamic linker to
|
||||||
fill in the PLT entry. */
|
fill in the PLT entry. */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue