ppc476 plt call stubs
Fuss over bctr in call stubs. * elf32-ppc.c (BA): Define (ppc_elf_link_hash_table_create): Correct default_params. (write_glink_stub): Pad small plt call stub with "ba 0" rather than "nop" for ppc476_workaround. (ppc_elf_finish_dynamic_sections): Likewise for branch table and __glink_PLTresolve. Ensure plt call stub at end of page doesn't allow fall-thru prefetch.
This commit is contained in:
parent
f871211585
commit
da3a208854
@ -1,3 +1,13 @@
|
||||
2014-04-14 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* elf32-ppc.c (BA): Define
|
||||
(ppc_elf_link_hash_table_create): Correct default_params.
|
||||
(write_glink_stub): Pad small plt call stub with "ba 0" rather
|
||||
than "nop" for ppc476_workaround.
|
||||
(ppc_elf_finish_dynamic_sections): Likewise for branch table
|
||||
and __glink_PLTresolve. Ensure plt call stub at end of page
|
||||
doesn't allow fall-thru prefetch.
|
||||
|
||||
2014-04-11 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
PR ld/16821
|
||||
|
@ -147,6 +147,7 @@ static const bfd_vma ppc_elf_vxworks_pic_plt0_entry
|
||||
#define ADD_3_12_2 0x7c6c1214
|
||||
#define ADD_11_0_11 0x7d605a14
|
||||
#define B 0x48000000
|
||||
#define BA 0x48000002
|
||||
#define BCL_20_31 0x429f0005
|
||||
#define BCTR 0x4e800420
|
||||
#define BEQLR 0x4d820020
|
||||
@ -3249,7 +3250,7 @@ static struct bfd_link_hash_table *
|
||||
ppc_elf_link_hash_table_create (bfd *abfd)
|
||||
{
|
||||
struct ppc_elf_link_hash_table *ret;
|
||||
static struct ppc_elf_params default_params = { PLT_OLD, 0, 1, 0, 0, 4096 };
|
||||
static struct ppc_elf_params default_params = { PLT_OLD, 0, 1, 0, 0, 12 };
|
||||
|
||||
ret = bfd_zmalloc (sizeof (struct ppc_elf_link_hash_table));
|
||||
if (ret == NULL)
|
||||
@ -7336,7 +7337,7 @@ write_glink_stub (struct plt_entry *ent, asection *plt_sec, unsigned char *p,
|
||||
p += 4;
|
||||
bfd_put_32 (output_bfd, BCTR, p);
|
||||
p += 4;
|
||||
bfd_put_32 (output_bfd, NOP, p);
|
||||
bfd_put_32 (output_bfd, htab->params->ppc476_workaround ? BA : NOP, p);
|
||||
p += 4;
|
||||
}
|
||||
else
|
||||
@ -10115,7 +10116,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
|
||||
p += htab->glink_pltresolve;
|
||||
endp = htab->glink->contents;
|
||||
endp += htab->glink->size - GLINK_PLTRESOLVE;
|
||||
while (p < endp - 8 * 4)
|
||||
while (p < endp - (htab->params->ppc476_workaround ? 0 : 8 * 4))
|
||||
{
|
||||
bfd_put_32 (output_bfd, B + endp - p, p);
|
||||
p += 4;
|
||||
@ -10130,6 +10131,39 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
|
||||
+ htab->glink->output_section->vma
|
||||
+ htab->glink->output_offset);
|
||||
|
||||
if (htab->params->ppc476_workaround)
|
||||
{
|
||||
/* Ensure that a call stub at the end of a page doesn't
|
||||
result in prefetch over the end of the page into the
|
||||
glink branch table. */
|
||||
bfd_vma pagesize = (bfd_vma) 1 << htab->params->pagesize_p2;
|
||||
bfd_vma page_addr;
|
||||
bfd_vma glink_start = (htab->glink->output_section->vma
|
||||
+ htab->glink->output_offset);
|
||||
|
||||
for (page_addr = res0 & -pagesize;
|
||||
page_addr > glink_start;
|
||||
page_addr -= pagesize)
|
||||
{
|
||||
/* We have a plt call stub that may need fixing. */
|
||||
bfd_byte *loc;
|
||||
unsigned int insn;
|
||||
|
||||
loc = htab->glink->contents + page_addr - 4 - glink_start;
|
||||
insn = bfd_get_32 (output_bfd, loc);
|
||||
if (insn == BCTR)
|
||||
{
|
||||
/* By alignment, we know that there must be at least
|
||||
one other call stub before this one. */
|
||||
insn = bfd_get_32 (output_bfd, loc - 16);
|
||||
if (insn == BCTR)
|
||||
bfd_put_32 (output_bfd, B | (-16 & 0x3fffffc), loc);
|
||||
else
|
||||
bfd_put_32 (output_bfd, B | (-20 & 0x3fffffc), loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Last comes the PLTresolve stub. */
|
||||
if (info->shared)
|
||||
{
|
||||
@ -10137,7 +10171,11 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE (pic_plt_resolve); i++)
|
||||
{
|
||||
bfd_put_32 (output_bfd, pic_plt_resolve[i], p);
|
||||
unsigned int insn = pic_plt_resolve[i];
|
||||
|
||||
if (htab->params->ppc476_workaround && insn == NOP)
|
||||
insn = BA + 0;
|
||||
bfd_put_32 (output_bfd, insn, p);
|
||||
p += 4;
|
||||
}
|
||||
p -= 4 * ARRAY_SIZE (pic_plt_resolve);
|
||||
@ -10171,7 +10209,11 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
|
||||
{
|
||||
for (i = 0; i < ARRAY_SIZE (plt_resolve); i++)
|
||||
{
|
||||
bfd_put_32 (output_bfd, plt_resolve[i], p);
|
||||
unsigned int insn = plt_resolve[i];
|
||||
|
||||
if (htab->params->ppc476_workaround && insn == NOP)
|
||||
insn = BA + 0;
|
||||
bfd_put_32 (output_bfd, insn, p);
|
||||
p += 4;
|
||||
}
|
||||
p -= 4 * ARRAY_SIZE (plt_resolve);
|
||||
|
Loading…
Reference in New Issue
Block a user