mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-25 04:49:54 +08:00
* elf64-ppc.c (ppc64_elf_relocate_section): Combine handling of
long branch stubs with code handling plt and r2off branch stubs.
This commit is contained in:
@ -1,3 +1,8 @@
|
|||||||
|
2004-08-09 Alan Modra <amodra@bigpond.net.au>
|
||||||
|
|
||||||
|
* elf64-ppc.c (ppc64_elf_relocate_section): Combine handling of
|
||||||
|
long branch stubs with code handling plt and r2off branch stubs.
|
||||||
|
|
||||||
2004-08-09 Alan Modra <amodra@bigpond.net.au>
|
2004-08-09 Alan Modra <amodra@bigpond.net.au>
|
||||||
|
|
||||||
* elf-bfd.h (_bfd_elf_gc_mark): Declare.
|
* elf-bfd.h (_bfd_elf_gc_mark): Declare.
|
||||||
@ -10,6 +15,7 @@
|
|||||||
(ppc64_elf_mark_entry_syms): Delete.
|
(ppc64_elf_mark_entry_syms): Delete.
|
||||||
(ppc64_elf_gc_mark_hook): Mark entry syms here. Also mark opd
|
(ppc64_elf_gc_mark_hook): Mark entry syms here. Also mark opd
|
||||||
sections. Use get_opd_info.
|
sections. Use get_opd_info.
|
||||||
|
|
||||||
* elf64-ppc.h (ppc64_elf_mark_entry_syms): Delete.
|
* elf64-ppc.h (ppc64_elf_mark_entry_syms): Delete.
|
||||||
|
|
||||||
2004-08-09 Alan Modra <amodra@bigpond.net.au>
|
2004-08-09 Alan Modra <amodra@bigpond.net.au>
|
||||||
|
150
bfd/elf64-ppc.c
150
bfd/elf64-ppc.c
@ -7863,6 +7863,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
|
|
||||||
/* Handle other relocations that tweak non-addend part of insn. */
|
/* Handle other relocations that tweak non-addend part of insn. */
|
||||||
insn = 0;
|
insn = 0;
|
||||||
|
max_br_offset = 1 << 25;
|
||||||
|
addend = rel->r_addend;
|
||||||
switch (r_type)
|
switch (r_type)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
@ -7879,31 +7881,11 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
case R_PPC64_REL14_BRNTAKEN:
|
case R_PPC64_REL14_BRNTAKEN:
|
||||||
insn |= bfd_get_32 (output_bfd,
|
insn |= bfd_get_32 (output_bfd,
|
||||||
contents + rel->r_offset) & ~(0x01 << 21);
|
contents + rel->r_offset) & ~(0x01 << 21);
|
||||||
if (is_power4)
|
/* Fall thru. */
|
||||||
{
|
|
||||||
/* Set 'a' bit. This is 0b00010 in BO field for branch
|
|
||||||
on CR(BI) insns (BO == 001at or 011at), and 0b01000
|
|
||||||
for branch on CTR insns (BO == 1a00t or 1a01t). */
|
|
||||||
if ((insn & (0x14 << 21)) == (0x04 << 21))
|
|
||||||
insn |= 0x02 << 21;
|
|
||||||
else if ((insn & (0x14 << 21)) == (0x10 << 21))
|
|
||||||
insn |= 0x08 << 21;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
from = (rel->r_offset
|
|
||||||
+ input_section->output_offset
|
|
||||||
+ input_section->output_section->vma);
|
|
||||||
|
|
||||||
/* Invert 'y' bit if not the default. */
|
case R_PPC64_REL14:
|
||||||
if ((bfd_signed_vma) (relocation + rel->r_addend - from) < 0)
|
max_br_offset = 1 << 15;
|
||||||
insn ^= 0x01 << 21;
|
/* Fall thru. */
|
||||||
}
|
|
||||||
|
|
||||||
bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_PPC64_REL24:
|
case R_PPC64_REL24:
|
||||||
/* Calls to functions with a different TOC, such as calls to
|
/* Calls to functions with a different TOC, such as calls to
|
||||||
@ -7912,11 +7894,13 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
linkage stubs needs to be followed by a nop, as the nop
|
linkage stubs needs to be followed by a nop, as the nop
|
||||||
will be replaced with an instruction to restore the TOC
|
will be replaced with an instruction to restore the TOC
|
||||||
base pointer. */
|
base pointer. */
|
||||||
|
stub_entry = NULL;
|
||||||
if (((h != NULL
|
if (((h != NULL
|
||||||
&& (fdh = &((struct ppc_link_hash_entry *) h)->oh->elf) != NULL
|
&& (fdh = &((struct ppc_link_hash_entry *) h)->oh->elf) != NULL
|
||||||
&& fdh->plt.plist != NULL)
|
&& fdh->plt.plist != NULL)
|
||||||
|| ((fdh = h, sec) != NULL
|
|| ((fdh = h, sec) != NULL
|
||||||
&& sec->output_section != NULL
|
&& sec->output_section != NULL
|
||||||
|
&& sec->id <= htab->top_id
|
||||||
&& (htab->stub_group[sec->id].toc_off
|
&& (htab->stub_group[sec->id].toc_off
|
||||||
!= htab->stub_group[input_section->id].toc_off)))
|
!= htab->stub_group[input_section->id].toc_off)))
|
||||||
&& (stub_entry = ppc_get_stub_entry (input_section, sec, fdh,
|
&& (stub_entry = ppc_get_stub_entry (input_section, sec, fdh,
|
||||||
@ -7925,17 +7909,18 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
|| stub_entry->stub_type == ppc_stub_plt_branch_r2off
|
|| stub_entry->stub_type == ppc_stub_plt_branch_r2off
|
||||||
|| stub_entry->stub_type == ppc_stub_long_branch_r2off))
|
|| stub_entry->stub_type == ppc_stub_long_branch_r2off))
|
||||||
{
|
{
|
||||||
bfd_boolean can_plt_call = 0;
|
bfd_boolean can_plt_call = FALSE;
|
||||||
|
|
||||||
if (rel->r_offset + 8 <= input_section->size)
|
if (rel->r_offset + 8 <= input_section->size)
|
||||||
{
|
{
|
||||||
insn = bfd_get_32 (input_bfd, contents + rel->r_offset + 4);
|
unsigned long nop;
|
||||||
if (insn == NOP
|
nop = bfd_get_32 (input_bfd, contents + rel->r_offset + 4);
|
||||||
|| insn == CROR_151515 || insn == CROR_313131)
|
if (nop == NOP
|
||||||
|
|| nop == CROR_151515 || nop == CROR_313131)
|
||||||
{
|
{
|
||||||
bfd_put_32 (input_bfd, LD_R2_40R1,
|
bfd_put_32 (input_bfd, LD_R2_40R1,
|
||||||
contents + rel->r_offset + 4);
|
contents + rel->r_offset + 4);
|
||||||
can_plt_call = 1;
|
can_plt_call = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7945,16 +7930,17 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
{
|
{
|
||||||
/* If this is a plain branch rather than a branch
|
/* If this is a plain branch rather than a branch
|
||||||
and link, don't require a nop. */
|
and link, don't require a nop. */
|
||||||
insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
|
unsigned long br;
|
||||||
if ((insn & 1) == 0)
|
br = bfd_get_32 (input_bfd, contents + rel->r_offset);
|
||||||
can_plt_call = 1;
|
if ((br & 1) == 0)
|
||||||
|
can_plt_call = TRUE;
|
||||||
}
|
}
|
||||||
else if (h != NULL
|
else if (h != NULL
|
||||||
&& strcmp (h->root.root.string,
|
&& strcmp (h->root.root.string,
|
||||||
".__libc_start_main") == 0)
|
".__libc_start_main") == 0)
|
||||||
{
|
{
|
||||||
/* Allow crt1 branch to go via a toc adjusting stub. */
|
/* Allow crt1 branch to go via a toc adjusting stub. */
|
||||||
can_plt_call = 1;
|
can_plt_call = TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -7986,23 +7972,66 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (can_plt_call)
|
if (can_plt_call
|
||||||
|
&& stub_entry->stub_type == ppc_stub_plt_call)
|
||||||
|
unresolved_reloc = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the branch is out of reach we ought to have a long
|
||||||
|
branch stub. */
|
||||||
|
from = (rel->r_offset
|
||||||
|
+ input_section->output_offset
|
||||||
|
+ input_section->output_section->vma);
|
||||||
|
|
||||||
|
if (stub_entry == NULL
|
||||||
|
&& (relocation + rel->r_addend - from + max_br_offset
|
||||||
|
>= 2 * max_br_offset)
|
||||||
|
&& r_type != R_PPC64_ADDR14_BRTAKEN
|
||||||
|
&& r_type != R_PPC64_ADDR14_BRNTAKEN)
|
||||||
|
stub_entry = ppc_get_stub_entry (input_section, sec, h, rel, htab);
|
||||||
|
|
||||||
|
if (stub_entry != NULL)
|
||||||
|
{
|
||||||
|
/* Munge up the value and addend so that we call the stub
|
||||||
|
rather than the procedure directly. */
|
||||||
|
relocation = (stub_entry->stub_offset
|
||||||
|
+ stub_entry->stub_sec->output_offset
|
||||||
|
+ stub_entry->stub_sec->output_section->vma);
|
||||||
|
addend = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (insn != 0)
|
||||||
|
{
|
||||||
|
if (is_power4)
|
||||||
{
|
{
|
||||||
relocation = (stub_entry->stub_offset
|
/* Set 'a' bit. This is 0b00010 in BO field for branch
|
||||||
+ stub_entry->stub_sec->output_offset
|
on CR(BI) insns (BO == 001at or 011at), and 0b01000
|
||||||
+ stub_entry->stub_sec->output_section->vma);
|
for branch on CTR insns (BO == 1a00t or 1a01t). */
|
||||||
if (stub_entry->stub_type == ppc_stub_plt_call)
|
if ((insn & (0x14 << 21)) == (0x04 << 21))
|
||||||
unresolved_reloc = FALSE;
|
insn |= 0x02 << 21;
|
||||||
|
else if ((insn & (0x14 << 21)) == (0x10 << 21))
|
||||||
|
insn |= 0x08 << 21;
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Invert 'y' bit if not the default. */
|
||||||
|
if ((bfd_signed_vma) (relocation + rel->r_addend - from) < 0)
|
||||||
|
insn ^= 0x01 << 21;
|
||||||
|
}
|
||||||
|
|
||||||
|
bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NOP out calls to undefined weak functions.
|
/* NOP out calls to undefined weak functions.
|
||||||
We can thus call a weak function without first
|
We can thus call a weak function without first
|
||||||
checking whether the function is defined. */
|
checking whether the function is defined. */
|
||||||
if (h != NULL
|
else if (h != NULL
|
||||||
&& h->root.type == bfd_link_hash_undefweak
|
&& h->root.type == bfd_link_hash_undefweak
|
||||||
&& relocation == 0
|
&& r_type == R_PPC64_REL24
|
||||||
&& rel->r_addend == 0)
|
&& relocation == 0
|
||||||
|
&& rel->r_addend == 0)
|
||||||
{
|
{
|
||||||
bfd_put_32 (output_bfd, NOP, contents + rel->r_offset);
|
bfd_put_32 (output_bfd, NOP, contents + rel->r_offset);
|
||||||
continue;
|
continue;
|
||||||
@ -8012,7 +8041,6 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
|
|
||||||
/* Set `addend'. */
|
/* Set `addend'. */
|
||||||
tls_type = 0;
|
tls_type = 0;
|
||||||
addend = rel->r_addend;
|
|
||||||
switch (r_type)
|
switch (r_type)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
@ -8645,40 +8673,6 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_PPC64_REL14:
|
|
||||||
case R_PPC64_REL14_BRNTAKEN:
|
|
||||||
case R_PPC64_REL14_BRTAKEN:
|
|
||||||
max_br_offset = 1 << 15;
|
|
||||||
goto branch_check;
|
|
||||||
|
|
||||||
case R_PPC64_REL24:
|
|
||||||
max_br_offset = 1 << 25;
|
|
||||||
|
|
||||||
branch_check:
|
|
||||||
/* If the branch is out of reach or the TOC register needs
|
|
||||||
adjusting, then redirect the call to the local stub for
|
|
||||||
this function. */
|
|
||||||
from = (rel->r_offset
|
|
||||||
+ input_section->output_offset
|
|
||||||
+ input_section->output_section->vma);
|
|
||||||
if ((relocation + addend - from + max_br_offset >= 2 * max_br_offset
|
|
||||||
|| (sec != NULL
|
|
||||||
&& sec->output_section != NULL
|
|
||||||
&& sec->id <= htab->top_id
|
|
||||||
&& (htab->stub_group[sec->id].toc_off
|
|
||||||
!= htab->stub_group[input_section->id].toc_off)))
|
|
||||||
&& (stub_entry = ppc_get_stub_entry (input_section, sec, h,
|
|
||||||
rel, htab)) != NULL)
|
|
||||||
{
|
|
||||||
/* Munge up the value and addend so that we call the stub
|
|
||||||
rather than the procedure directly. */
|
|
||||||
relocation = (stub_entry->stub_offset
|
|
||||||
+ stub_entry->stub_sec->output_offset
|
|
||||||
+ stub_entry->stub_sec->output_section->vma);
|
|
||||||
addend = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dynamic relocs are not propagated for SEC_DEBUGGING sections
|
/* Dynamic relocs are not propagated for SEC_DEBUGGING sections
|
||||||
|
Reference in New Issue
Block a user