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>
|
2014-04-11 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
PR ld/16821
|
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_3_12_2 0x7c6c1214
|
||||||
#define ADD_11_0_11 0x7d605a14
|
#define ADD_11_0_11 0x7d605a14
|
||||||
#define B 0x48000000
|
#define B 0x48000000
|
||||||
|
#define BA 0x48000002
|
||||||
#define BCL_20_31 0x429f0005
|
#define BCL_20_31 0x429f0005
|
||||||
#define BCTR 0x4e800420
|
#define BCTR 0x4e800420
|
||||||
#define BEQLR 0x4d820020
|
#define BEQLR 0x4d820020
|
||||||
|
@ -3249,7 +3250,7 @@ static struct bfd_link_hash_table *
|
||||||
ppc_elf_link_hash_table_create (bfd *abfd)
|
ppc_elf_link_hash_table_create (bfd *abfd)
|
||||||
{
|
{
|
||||||
struct ppc_elf_link_hash_table *ret;
|
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));
|
ret = bfd_zmalloc (sizeof (struct ppc_elf_link_hash_table));
|
||||||
if (ret == NULL)
|
if (ret == NULL)
|
||||||
|
@ -7336,7 +7337,7 @@ write_glink_stub (struct plt_entry *ent, asection *plt_sec, unsigned char *p,
|
||||||
p += 4;
|
p += 4;
|
||||||
bfd_put_32 (output_bfd, BCTR, p);
|
bfd_put_32 (output_bfd, BCTR, p);
|
||||||
p += 4;
|
p += 4;
|
||||||
bfd_put_32 (output_bfd, NOP, p);
|
bfd_put_32 (output_bfd, htab->params->ppc476_workaround ? BA : NOP, p);
|
||||||
p += 4;
|
p += 4;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -10115,7 +10116,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
|
||||||
p += htab->glink_pltresolve;
|
p += htab->glink_pltresolve;
|
||||||
endp = htab->glink->contents;
|
endp = htab->glink->contents;
|
||||||
endp += htab->glink->size - GLINK_PLTRESOLVE;
|
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);
|
bfd_put_32 (output_bfd, B + endp - p, p);
|
||||||
p += 4;
|
p += 4;
|
||||||
|
@ -10130,6 +10131,39 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
|
||||||
+ htab->glink->output_section->vma
|
+ htab->glink->output_section->vma
|
||||||
+ htab->glink->output_offset);
|
+ 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. */
|
/* Last comes the PLTresolve stub. */
|
||||||
if (info->shared)
|
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++)
|
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;
|
||||||
}
|
}
|
||||||
p -= 4 * ARRAY_SIZE (pic_plt_resolve);
|
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++)
|
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;
|
||||||
}
|
}
|
||||||
p -= 4 * ARRAY_SIZE (plt_resolve);
|
p -= 4 * ARRAY_SIZE (plt_resolve);
|
||||||
|
|
Loading…
Reference in New Issue