bfd/
[deliverable/binutils-gdb.git] / bfd / coff64-rs6000.c
index 678ba9380b3affdae90363f9193d8c049e2e2860..71a02c237beb012098d6c478b46f07c7baa94a70 100644 (file)
@@ -1,5 +1,5 @@
 /* BFD back-end for IBM RS/6000 "XCOFF64" files.
-   Copyright 2000, 2001, 2002, 2003, 2004
+   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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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"
@@ -127,7 +128,7 @@ extern bfd_boolean _bfd_xcoff_write_armap
 extern bfd_boolean _bfd_xcoff_write_archive_contents
   PARAMS ((bfd *));
 extern int _bfd_xcoff_sizeof_headers
-  PARAMS ((bfd *, bfd_boolean));
+  PARAMS ((bfd *, struct bfd_link_info *));
 extern void _bfd_xcoff_swap_sym_in
   PARAMS ((bfd *, PTR, PTR));
 extern unsigned int _bfd_xcoff_swap_sym_out
@@ -161,7 +162,7 @@ static const bfd_target *xcoff64_archive_p
 static bfd *xcoff64_openr_next_archived_file
   PARAMS ((bfd *, bfd *));
 static int xcoff64_sizeof_headers
-  PARAMS ((bfd *, bfd_boolean));
+  PARAMS ((bfd *, struct bfd_link_info *));
 static asection *xcoff64_create_csect_from_smclas
   PARAMS ((bfd *, union internal_auxent *, const char *));
 static bfd_boolean xcoff64_is_lineno_count_overflow
@@ -237,6 +238,7 @@ bfd_boolean (*xcoff64_calculate_relocation[XCOFF_MAX_CALCULATE_RELOCATION])
 #define coff_bfd_copy_private_bfd_data _bfd_xcoff_copy_private_bfd_data
 #define coff_bfd_is_local_label_name _bfd_xcoff_is_local_label_name
 #define coff_bfd_reloc_type_lookup xcoff64_reloc_type_lookup
+#define coff_bfd_reloc_name_lookup xcoff64_reloc_name_lookup
 #ifdef AIX_CORE
 extern const bfd_target * rs6000coff_core_p
   PARAMS ((bfd *abfd));
@@ -270,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
@@ -564,7 +570,7 @@ _bfd_xcoff64_put_ldsymbol_name (abfd, ldinfo, ldsym, name)
   if (ldinfo->string_size + len + 3 > ldinfo->string_alc)
     {
       bfd_size_type newalc;
-      bfd_byte *newstrings;
+      char *newstrings;
 
       newalc = ldinfo->string_alc * 2;
       if (newalc == 0)
@@ -572,8 +578,7 @@ _bfd_xcoff64_put_ldsymbol_name (abfd, ldinfo, ldsym, name)
       while (ldinfo->string_size + len + 3 > newalc)
        newalc *= 2;
 
-      newstrings = ((bfd_byte *)
-                   bfd_realloc ((PTR) ldinfo->strings, newalc));
+      newstrings = bfd_realloc (ldinfo->strings, newalc);
       if (newstrings == NULL)
        {
          ldinfo->failed = TRUE;
@@ -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;
@@ -845,11 +848,11 @@ xcoff64_write_object_contents (abfd)
 
       section.s_vaddr = current->vma;
       section.s_paddr = current->lma;
-      section.s_size =  current->_raw_size;
+      section.s_size =  current->size;
 
       /* If this section has no size or is unloadable then the scnptr
         will be 0 too.  */
-      if (current->_raw_size == 0
+      if (current->size == 0
          || (current->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
        {
          section.s_scnptr = 0;
@@ -965,19 +968,19 @@ xcoff64_write_object_contents (abfd)
 
   if (text_sec)
     {
-      internal_a.tsize = bfd_get_section_size_before_reloc (text_sec);
+      internal_a.tsize = text_sec->size;
       internal_a.text_start = internal_a.tsize ? text_sec->vma : 0;
     }
 
   if (data_sec)
     {
-      internal_a.dsize = bfd_get_section_size_before_reloc (data_sec);
+      internal_a.dsize = data_sec->size;
       internal_a.data_start = internal_a.dsize ? data_sec->vma : 0;
     }
 
   if (bss_sec)
     {
-      internal_a.bsize = bfd_get_section_size_before_reloc (bss_sec);
+      internal_a.bsize = bss_sec->size;
       if (internal_a.bsize && bss_sec->vma < internal_a.data_start)
        internal_a.data_start = bss_sec->vma;
     }
@@ -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,13 +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->_cooked_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
@@ -1162,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;
 }
 
@@ -1301,7 +1332,7 @@ xcoff64_ppc_relocate_section (output_bfd, info, input_bfd,
       address = rel->r_vaddr - input_section->vma;
       location = contents + address;
 
-      if (address > input_section->_raw_size)
+      if (address > input_section->size)
        abort ();
 
       /* Get the value we are going to relocate.  */
@@ -1336,7 +1367,7 @@ xcoff64_ppc_relocate_section (output_bfd, info, input_bfd,
            }
          else if (h != NULL)
            {
-             name = h->root.root.string;
+             name = NULL;
            }
          else
            {
@@ -1347,8 +1378,9 @@ xcoff64_ppc_relocate_section (output_bfd, info, input_bfd,
          sprintf (reloc_type_name, "0x%02x", rel->r_type);
 
          if (! ((*info->callbacks->reloc_overflow)
-                (info, name, reloc_type_name, (bfd_vma) 0, input_bfd,
-                 input_section, rel->r_vaddr - input_section->vma)))
+                (info, (h ? &h->root : NULL), name, reloc_type_name,
+                 (bfd_vma) 0, input_bfd, input_section,
+                 rel->r_vaddr - input_section->vma)))
            return FALSE;
        }
 
@@ -1844,6 +1876,22 @@ xcoff64_reloc_type_lookup (abfd, code)
     }
 }
 
+static reloc_howto_type *
+xcoff64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+                          const char *r_name)
+{
+  unsigned int i;
+
+  for (i = 0;
+       i < sizeof (xcoff64_howto_table) / sizeof (xcoff64_howto_table[0]);
+       i++)
+    if (xcoff64_howto_table[i].name != NULL
+       && strcasecmp (xcoff64_howto_table[i].name, r_name) == 0)
+      return &xcoff64_howto_table[i];
+
+  return NULL;
+}
+
 /* Read in the armap of an XCOFF archive.  */
 
 static bfd_boolean
@@ -1984,10 +2032,12 @@ xcoff64_archive_p (abfd)
   if (bfd_ardata (abfd) == (struct artdata *) NULL)
     goto error_ret_restore;
 
-  bfd_ardata (abfd)->cache = NULL;
-  bfd_ardata (abfd)->archive_head = NULL;
-  bfd_ardata (abfd)->symdefs = NULL;
-  bfd_ardata (abfd)->extended_names = NULL;
+  /* Already cleared by bfd_zalloc above.
+     bfd_ardata (abfd)->cache = NULL;
+     bfd_ardata (abfd)->archive_head = NULL;
+     bfd_ardata (abfd)->symdefs = NULL;
+     bfd_ardata (abfd)->extended_names = NULL;
+     bfd_ardata (abfd)->extended_names_size = 0;  */
   bfd_ardata (abfd)->first_file_filepos = bfd_scan_vma (hdr.firstmemoff,
                                                        (const char **) NULL,
                                                        10);
@@ -2055,9 +2105,8 @@ xcoff64_openr_next_archived_file (archive, last_file)
    always uses an a.out header.  */
 
 static int
-xcoff64_sizeof_headers (abfd, reloc)
-     bfd *abfd;
-     bfd_boolean reloc ATTRIBUTE_UNUSED;
+xcoff64_sizeof_headers (bfd *abfd,
+                       struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
   int size;
 
@@ -2105,8 +2154,8 @@ xcoff64_create_csect_from_smclas (abfd, aux, symbol_name)
   else
     {
       (*_bfd_error_handler)
-       (_("%s: symbol `%s' has unrecognized smclas %d"),
-        bfd_archive_filename (abfd), symbol_name, aux->x_csect.x_smclas);
+       (_("%B: symbol `%s' has unrecognized smclas %d"),
+        abfd, symbol_name, aux->x_csect.x_smclas);
       bfd_set_error (bfd_error_bad_value);
     }
 
@@ -2539,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 */
@@ -2558,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,
@@ -2566,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 */
@@ -2681,6 +2731,7 @@ const bfd_target rs6000coff64_vec =
     /* Copy */
     _bfd_xcoff_copy_private_bfd_data,
     ((bfd_boolean (*) (bfd *, bfd *)) bfd_true),
+    _bfd_generic_init_private_section_data,
     ((bfd_boolean (*) (bfd *, asection *, bfd *, asection *)) bfd_true),
     ((bfd_boolean (*) (bfd *, asymbol *, bfd *, asymbol *)) bfd_true),
     ((bfd_boolean (*) (bfd *, bfd *)) bfd_true),
@@ -2711,8 +2762,11 @@ const bfd_target rs6000coff64_vec =
     coff_print_symbol,
     coff_get_symbol_info,
     _bfd_xcoff_is_local_label_name,
+    coff_bfd_is_target_special_symbol,
     coff_get_lineno,
     coff_find_nearest_line,
+    _bfd_generic_find_line,
+    coff_find_inliner_info,
     coff_bfd_make_debug_symbol,
     _bfd_generic_read_minisymbols,
     _bfd_generic_minisymbol_to_symbol,
@@ -2721,6 +2775,7 @@ const bfd_target rs6000coff64_vec =
     coff_get_reloc_upper_bound,
     coff_canonicalize_reloc,
     xcoff64_reloc_type_lookup,
+    xcoff64_reloc_name_lookup,
 
     /* Write */
     coff_set_arch_mach,
@@ -2740,6 +2795,7 @@ const bfd_target rs6000coff64_vec =
     bfd_generic_merge_sections,
     bfd_generic_is_group_section,
     bfd_generic_discard_group,
+    _bfd_generic_section_already_linked,
 
     /* Dynamic */
     _bfd_xcoff_get_dynamic_symtab_upper_bound,
@@ -2786,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 */
@@ -2813,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 */
@@ -2927,6 +2984,7 @@ const bfd_target aix5coff64_vec =
     /* Copy */
     _bfd_xcoff_copy_private_bfd_data,
     ((bfd_boolean (*) (bfd *, bfd *)) bfd_true),
+    _bfd_generic_init_private_section_data,
     ((bfd_boolean (*) (bfd *, asection *, bfd *, asection *)) bfd_true),
     ((bfd_boolean (*) (bfd *, asymbol *, bfd *, asymbol *)) bfd_true),
     ((bfd_boolean (*) (bfd *, bfd *)) bfd_true),
@@ -2957,8 +3015,11 @@ const bfd_target aix5coff64_vec =
     coff_print_symbol,
     coff_get_symbol_info,
     _bfd_xcoff_is_local_label_name,
+    coff_bfd_is_target_special_symbol,
     coff_get_lineno,
     coff_find_nearest_line,
+    _bfd_generic_find_line,
+    coff_find_inliner_info,
     coff_bfd_make_debug_symbol,
     _bfd_generic_read_minisymbols,
     _bfd_generic_minisymbol_to_symbol,
@@ -2967,6 +3028,7 @@ const bfd_target aix5coff64_vec =
     coff_get_reloc_upper_bound,
     coff_canonicalize_reloc,
     xcoff64_reloc_type_lookup,
+    xcoff64_reloc_name_lookup,
 
     /* Write */
     coff_set_arch_mach,
@@ -2986,6 +3048,7 @@ const bfd_target aix5coff64_vec =
     bfd_generic_merge_sections,
     bfd_generic_is_group_section,
     bfd_generic_discard_group,
+    _bfd_generic_section_already_linked,
 
     /* Dynamic */
     _bfd_xcoff_get_dynamic_symtab_upper_bound,
This page took 0.036609 seconds and 4 git commands to generate.