bfd/
authorRichard Sandiford <rdsandiford@googlemail.com>
Sat, 14 Mar 2009 09:16:01 +0000 (09:16 +0000)
committerRichard Sandiford <rdsandiford@googlemail.com>
Sat, 14 Mar 2009 09:16:01 +0000 (09:16 +0000)
* 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
bfd/coff-rs6000.c
bfd/coff64-rs6000.c
ld/testsuite/ChangeLog
ld/testsuite/ld-powerpc/aix-abs-branch-1.dd [new file with mode: 0644]
ld/testsuite/ld-powerpc/aix-abs-branch-1.ex [new file with mode: 0644]
ld/testsuite/ld-powerpc/aix-abs-branch-1.im [new file with mode: 0644]
ld/testsuite/ld-powerpc/aix-abs-branch-1.s [new file with mode: 0644]
ld/testsuite/ld-powerpc/aix52.exp

index 9182ef2..818054c 100644 (file)
@@ -1,5 +1,13 @@
 2009-03-14  Richard Sandiford  <r.sandiford@uk.ibm.com>
 
+       * 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  <r.sandiford@uk.ibm.com>
+
        * xcofflink.c (xcoff_mark, xcoff_link_input_bfd): Don't copy
        R_POS and R_NEG relocations against absolute symbols to the
        .loader section.
index 1db66e7..0a849d1 100644 (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;
-
-  *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
index 1448917..71a02c2 100644 (file)
@@ -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;
 }
 
index b02892b..55e3a92 100644 (file)
@@ -1,5 +1,12 @@
 2009-03-14  Richard Sandiford  <r.sandiford@uk.ibm.com>
 
+       * 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  <r.sandiford@uk.ibm.com>
+
        * ld-powerpc/aix-abs-reloc-1.ex, ld-powerpc/aix-abs-reloc-1.im,
        ld-powerpc/aix-abs-reloc-1.od, ld-powerpc/aix-abs-reloc-1.s: New test.
        * ld-powerpc/aix52.exp: Run it.
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 (file)
index 0000000..6bfd136
--- /dev/null
@@ -0,0 +1,14 @@
+
+.*
+
+
+Disassembly of section \.text:
+
+0*10000000 <foo>:
+ *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 (file)
index 0000000..257cc56
--- /dev/null
@@ -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 (file)
index 0000000..0efbfc9
--- /dev/null
@@ -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 (file)
index 0000000..82c322f
--- /dev/null
@@ -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
index 1263796..632d0b9 100644 (file)
@@ -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}