* coff-rs6000.c (xcoff_reloc_type_br): Make the branch absolute
	if the target is absolute.  Fix comment typo.
	(xcoff_ppc_relocate_section): Remove FIXME.
	* coff64-rs6000.c (xcoff64_reloc_type_br): Make the branch absolute
	if the target is absolute.

ld/testsuite/
	* ld-powerpc/aix-abs-branch-1.im, ld-powerpc/aix-abs-branch-1.ex,
	ld-powerpc/aix-abs-branch-1.s,
	ld-powerpc/aix-abs-branch-1.dd: New test.
	* ld-powerpc/aix52.exp: Run it.
This commit is contained in:
Richard Sandiford
2009-03-14 09:16:01 +00:00
parent 0e3212aded
commit 12b2cce914
9 changed files with 124 additions and 21 deletions

View File

@@ -2947,11 +2947,13 @@ xcoff_reloc_type_br (input_bfd, input_section, output_bfd, rel, sym, howto,
bfd_byte *contents;
{
struct xcoff_link_hash_entry *h;
bfd_vma section_offset;
if (0 > rel->r_symndx)
return FALSE;
h = obj_xcoff_sym_hashes (input_bfd)[rel->r_symndx];
section_offset = rel->r_vaddr - input_section->vma;
/* If we see an R_BR or R_RBR reloc which is jumping to global
linkage code, and it is followed by an appropriate cror nop
@@ -2962,12 +2964,12 @@ xcoff_reloc_type_br (input_bfd, input_section, output_bfd, rel, sym, howto,
cror. */
if (NULL != h
&& bfd_link_hash_defined == h->root.type
&& rel->r_vaddr - input_section->vma + 8 <= input_section->size)
&& section_offset + 8 <= input_section->size)
{
bfd_byte *pnext;
unsigned long next;
pnext = contents + (rel->r_vaddr - input_section->vma) + 4;
pnext = contents + section_offset + 4;
next = bfd_get_32 (input_bfd, pnext);
/* The _ptrgl function is magic. It is used by the AIX
@@ -2977,12 +2979,12 @@ xcoff_reloc_type_br (input_bfd, input_section, output_bfd, rel, sym, howto,
if (next == 0x4def7b82 /* cror 15,15,15 */
|| next == 0x4ffffb82 /* cror 31,31,31 */
|| next == 0x60000000) /* ori r0,r0,0 */
bfd_put_32 (input_bfd, 0x80410014, pnext); /* lwz r1,20(r1) */
bfd_put_32 (input_bfd, 0x80410014, pnext); /* lwz r2,20(r1) */
}
else
{
if (next == 0x80410014) /* lwz r1,20(r1) */
if (next == 0x80410014) /* lwz r2,20(r1) */
bfd_put_32 (input_bfd, 0x60000000, pnext); /* ori r0,r0,0 */
}
}
@@ -2998,16 +3000,41 @@ xcoff_reloc_type_br (input_bfd, input_section, output_bfd, rel, sym, howto,
howto->complain_on_overflow = complain_overflow_dont;
}
howto->pc_relative = TRUE;
/* The original PC-relative relocation is biased by -r_vaddr, so adding
the value below will give the absolute target address. */
*relocation = val + addend + rel->r_vaddr;
howto->src_mask &= ~3;
howto->dst_mask = howto->src_mask;
/* A PC relative reloc includes the section address. */
addend += input_section->vma;
if (h != NULL
&& h->root.type == bfd_link_hash_defined
&& bfd_is_abs_section (h->root.u.def.section)
&& section_offset + 4 <= input_section->size)
{
bfd_byte *ptr;
bfd_vma insn;
*relocation = val + addend;
*relocation -= (input_section->output_section->vma
+ input_section->output_offset);
/* Turn the relative branch into an absolute one by setting the
AA bit. */
ptr = contents + section_offset;
insn = bfd_get_32 (input_bfd, ptr);
insn |= 2;
bfd_put_32 (input_bfd, insn, ptr);
/* Make the howto absolute too. */
howto->pc_relative = FALSE;
howto->complain_on_overflow = complain_overflow_bitfield;
}
else
{
/* Use a PC-relative howto and subtract the instruction's address
from the target address we calculated above. */
howto->pc_relative = TRUE;
*relocation -= (input_section->output_section->vma
+ input_section->output_offset
+ section_offset);
}
return TRUE;
}
@@ -3323,9 +3350,7 @@ xcoff_complain_overflow_unsigned_func (input_bfd, val, relocation, howto)
R_RBR:
A relative branch which may be modified to become an
absolute branch. FIXME: We don't implement this,
although we should for symbols of storage mapping class
XMC_XO.
absolute branch.
R_RL:
The PowerPC AIX ABI describes this as a load which may be