From 12b2cce9148e4cfdc9f135cfa1a21485be51dc5b Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Sat, 14 Mar 2009 09:16:01 +0000 Subject: [PATCH] bfd/ * 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. --- bfd/ChangeLog | 8 ++++ bfd/coff-rs6000.c | 53 +++++++++++++++------ bfd/coff64-rs6000.c | 45 +++++++++++++---- ld/testsuite/ChangeLog | 7 +++ ld/testsuite/ld-powerpc/aix-abs-branch-1.dd | 14 ++++++ ld/testsuite/ld-powerpc/aix-abs-branch-1.ex | 1 + ld/testsuite/ld-powerpc/aix-abs-branch-1.im | 1 + ld/testsuite/ld-powerpc/aix-abs-branch-1.s | 14 ++++++ ld/testsuite/ld-powerpc/aix52.exp | 6 +++ 9 files changed, 126 insertions(+), 23 deletions(-) create mode 100644 ld/testsuite/ld-powerpc/aix-abs-branch-1.dd create mode 100644 ld/testsuite/ld-powerpc/aix-abs-branch-1.ex create mode 100644 ld/testsuite/ld-powerpc/aix-abs-branch-1.im create mode 100644 ld/testsuite/ld-powerpc/aix-abs-branch-1.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 9182ef27e3d..818054cf0a0 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,11 @@ +2009-03-14 Richard Sandiford + + * 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. + 2009-03-14 Richard Sandiford * xcofflink.c (xcoff_mark, xcoff_link_input_bfd): Don't copy diff --git a/bfd/coff-rs6000.c b/bfd/coff-rs6000.c index 1db66e77d61..0a849d1f75a 100644 --- a/bfd/coff-rs6000.c +++ b/bfd/coff-rs6000.c @@ -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; - - *relocation = val + addend; - *relocation -= (input_section->output_section->vma - + input_section->output_offset); + 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; + + /* 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 diff --git a/bfd/coff64-rs6000.c b/bfd/coff64-rs6000.c index 14489176e6c..71a02c237be 100644 --- a/bfd/coff64-rs6000.c +++ b/bfd/coff64-rs6000.c @@ -1117,11 +1117,13 @@ xcoff64_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 @@ -1132,12 +1134,12 @@ xcoff64_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 compiler to call @@ -1166,16 +1168,41 @@ xcoff64_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; - - *relocation = val + addend; - *relocation -= (input_section->output_section->vma - + input_section->output_offset); + 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; + + /* 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; } diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index b02892bf636..55e3a9237c1 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2009-03-14 Richard Sandiford + + * 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. + 2009-03-14 Richard Sandiford * ld-powerpc/aix-abs-reloc-1.ex, ld-powerpc/aix-abs-reloc-1.im, diff --git a/ld/testsuite/ld-powerpc/aix-abs-branch-1.dd b/ld/testsuite/ld-powerpc/aix-abs-branch-1.dd new file mode 100644 index 00000000000..6bfd13680fa --- /dev/null +++ b/ld/testsuite/ld-powerpc/aix-abs-branch-1.dd @@ -0,0 +1,14 @@ + +.* + + +Disassembly of section \.text: + +0*10000000 : + *10000000:.* bla * 144d000 <.*> + *10000004:.* l(wz|) * r1,80\(r1\) + *10000008:.* bla * 1451000 <.*> + *1000000c:.* (oril * r0,r0,0|nop) + *10000010:.* bla * 1452800 <.*> + *10000014:.* (oril * r0,r0,0|nop) + *10000018:.* bla * 1450000 <.*> diff --git a/ld/testsuite/ld-powerpc/aix-abs-branch-1.ex b/ld/testsuite/ld-powerpc/aix-abs-branch-1.ex new file mode 100644 index 00000000000..257cc5642cb --- /dev/null +++ b/ld/testsuite/ld-powerpc/aix-abs-branch-1.ex @@ -0,0 +1 @@ +foo diff --git a/ld/testsuite/ld-powerpc/aix-abs-branch-1.im b/ld/testsuite/ld-powerpc/aix-abs-branch-1.im new file mode 100644 index 00000000000..0efbfc960a7 --- /dev/null +++ b/ld/testsuite/ld-powerpc/aix-abs-branch-1.im @@ -0,0 +1 @@ +bar 0x1450000 diff --git a/ld/testsuite/ld-powerpc/aix-abs-branch-1.s b/ld/testsuite/ld-powerpc/aix-abs-branch-1.s new file mode 100644 index 00000000000..82c322fae51 --- /dev/null +++ b/ld/testsuite/ld-powerpc/aix-abs-branch-1.s @@ -0,0 +1,14 @@ + .globl foo + .csect foo[PR] +foo: + bl bar - 0x3000 + lwz 1,80(1) + bl bar + 0x1000 + .ifeq size - 32 + lwz 2,20(1) + .else + ld 2,40(1) + .endif + bl bar + 0x2800 + nop + bl bar diff --git a/ld/testsuite/ld-powerpc/aix52.exp b/ld/testsuite/ld-powerpc/aix52.exp index 1263796b720..632d0b9cd19 100644 --- a/ld/testsuite/ld-powerpc/aix52.exp +++ b/ld/testsuite/ld-powerpc/aix52.exp @@ -65,6 +65,12 @@ proc run_aix_test { size name ldopts asopts sources tools output } { } set aix52tests { + {"Absolute branch test 1" + "-shared -bI:aix-abs-branch-1.im -bE:aix-abs-branch-1.ex" + "" {aix-abs-branch-1.s} + {{objdump {-dR} aix-abs-branch-1.dd}} + "aix-abs-branch-1.so"} + {"Relocations against absolute symbols 1" "-shared -bI:aix-abs-reloc-1.im -bE:aix-abs-reloc-1.ex" {} {aix-abs-reloc-1.s} -- 2.30.2