bfd/
[deliverable/binutils-gdb.git] / bfd / coff64-rs6000.c
index ce8f1661754c7267d0a4ec74dc0b4d9a9cba602c..71a02c237beb012098d6c478b46f07c7baa94a70 100644 (file)
@@ -1,5 +1,5 @@
 /* BFD back-end for IBM RS/6000 "XCOFF64" files.
-   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
    Written Clinton Popetz.
    Contributed by Cygnus Support.
@@ -8,7 +8,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
-#include "bfd.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "bfdlink.h"
 #include "libbfd.h"
 #include "coff/internal.h"
@@ -271,6 +272,10 @@ extern int rs6000coff_core_file_failing_signal
 #define coff_swap_reloc_out xcoff64_swap_reloc_out
 #define NO_COFF_RELOCS
 
+#ifndef bfd_pe_print_pdata
+#define bfd_pe_print_pdata     NULL
+#endif
+
 #include "coffcode.h"
 
 /* For XCOFF64, the effective width of symndx changes depending on
@@ -762,7 +767,6 @@ xcoff64_write_object_contents (abfd)
   file_ptr sym_base;
   unsigned long reloc_size = 0;
   unsigned long lnno_size = 0;
-  bfd_boolean long_section_names;
   asection *text_sec = ((void *) 0);
   asection *data_sec = ((void *) 0);
   asection *bss_sec = ((void *) 0);
@@ -832,7 +836,6 @@ xcoff64_write_object_contents (abfd)
   if (bfd_seek (abfd, scn_base, SEEK_SET) != 0)
     return FALSE;
 
-  long_section_names = FALSE;
   for (current = abfd->sections; current != NULL; current = current->next)
     {
       struct internal_scnhdr section;
@@ -1045,6 +1048,8 @@ xcoff64_write_object_contents (abfd)
            case bfd_arch_powerpc:
              if (bfd_get_mach (abfd) == bfd_mach_ppc)
                internal_a.o_cputype = 3;
+             else if (bfd_get_mach (abfd) == bfd_mach_ppc_620)
+               internal_a.o_cputype = 2;
              else
                internal_a.o_cputype = 1;
              break;
@@ -1112,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
@@ -1127,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
@@ -1161,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;
 }
 
@@ -2556,7 +2588,7 @@ static const struct xcoff_backend_data_rec bfd_xcoff_backend_data =
       LINESZ,
       FILNMLEN,
       TRUE,                    /* _bfd_coff_long_filenames */
-      FALSE,                   /* _bfd_coff_long_section_names */
+      XCOFF_NO_LONG_SECTION_NAMES,  /* _bfd_coff_long_section_names */
       3,                       /* _bfd_coff_default_section_alignment_power */
       TRUE,                    /* _bfd_coff_force_symnames_in_strings */
       4,                       /* _bfd_coff_debug_string_prefix_length */
@@ -2575,7 +2607,7 @@ static const struct xcoff_backend_data_rec bfd_xcoff_backend_data =
       coff_print_aux,
       dummy_reloc16_extra_cases,
       dummy_reloc16_estimate,
-      NULL,                    /* bfd_coff_sym_is_global */
+      NULL,                    /* bfd_coff_symbol_classification */
       coff_compute_section_file_positions,
       NULL,                    /* _bfd_coff_start_final_link */
       xcoff64_ppc_relocate_section,
@@ -2583,7 +2615,8 @@ static const struct xcoff_backend_data_rec bfd_xcoff_backend_data =
       NULL,                    /* _bfd_coff_adjust_symndx */
       _bfd_generic_link_add_one_symbol,
       coff_link_output_has_begun,
-      coff_final_link_postscript
+      coff_final_link_postscript,
+      NULL                     /* print_pdata.  */
     },
 
     0x01EF,                    /* magic number */
@@ -2809,7 +2842,7 @@ static const struct xcoff_backend_data_rec bfd_xcoff_aix5_backend_data =
       LINESZ,
       FILNMLEN,
       TRUE,                    /* _bfd_coff_long_filenames */
-      FALSE,                   /* _bfd_coff_long_section_names */
+      XCOFF_NO_LONG_SECTION_NAMES,  /* _bfd_coff_long_section_names */
       3,                       /* _bfd_coff_default_section_alignment_power */
       TRUE,                    /* _bfd_coff_force_symnames_in_strings */
       4,                       /* _bfd_coff_debug_string_prefix_length */
@@ -2836,7 +2869,8 @@ static const struct xcoff_backend_data_rec bfd_xcoff_aix5_backend_data =
       NULL,                    /* _bfd_coff_adjust_symndx */
       _bfd_generic_link_add_one_symbol,
       coff_link_output_has_begun,
-      coff_final_link_postscript
+      coff_final_link_postscript,
+      NULL                     /* print_pdata.  */
     },
 
     U64_TOCMAGIC,              /* magic number */
This page took 0.040782 seconds and 4 git commands to generate.