XCOFF64 fixes. For setting arch/mach and for R_BR relocations.
authorTom Rix <trix@redhat.com>
Fri, 10 May 2002 21:20:16 +0000 (21:20 +0000)
committerTom Rix <trix@redhat.com>
Fri, 10 May 2002 21:20:16 +0000 (21:20 +0000)
bfd/ChangeLog
bfd/coff-rs6000.c
bfd/coff64-rs6000.c
bfd/libxcoff.h
ld/ChangeLog
ld/emultempl/aix.em
ld/ldfile.c
ld/ldfile.h

index ed2814779f0c91dfb85d6776748533e29c54de16..a837ebec983cb3af32c139ad16a919ad9f4b3949 100644 (file)
@@ -1,3 +1,10 @@
+2002-05-10  Tom Rix  <trix@redhat.com>
+
+       * coff64-rs6000.c (xcoff64_reloc_type_br): New function for 
+       xcoff64_ppc_relocate_section.
+       * coff-rs6000.c : Extern common xcoff_reloc_type functions.
+       * libxcoff.h: Common xcoff_reloc_type function declaration.
+
 2002-05-10  Alan Modra  <amodra@bigpond.net.au>
 
        * elf32-i386.c (elf_i386_relocate_section): Remove overflow checks
index b1db78fe25c8a91f06548647ad303d005dc2d68b..10ef5dfd777877d724c40ef534010679e4dfb2ad 100644 (file)
@@ -155,15 +155,7 @@ static boolean do_copy PARAMS((bfd *, bfd *));
 static boolean do_shared_object_padding PARAMS ((bfd *, bfd *, ufile_ptr *, int));
 
 /* Relocation functions */
-static boolean xcoff_reloc_type_noop PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
-static boolean xcoff_reloc_type_fail PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
-static boolean xcoff_reloc_type_pos PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
-static boolean xcoff_reloc_type_neg PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
-static boolean xcoff_reloc_type_rel PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
-static boolean xcoff_reloc_type_toc PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
-static boolean xcoff_reloc_type_ba PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
 static boolean xcoff_reloc_type_br PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
-static boolean xcoff_reloc_type_crel PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
 
 static boolean xcoff_complain_overflow_dont_func 
   PARAMS ((XCOFF_COMPLAIN_FUNCTION_ARGS));
@@ -2726,7 +2718,7 @@ xcoff_swap_ldrel_out (abfd, src, d)
 }
 \f
 
-static boolean 
+boolean 
 xcoff_reloc_type_noop (input_bfd, input_section, output_bfd, rel, sym, howto, 
                       val, addend, relocation, contents)
      bfd *input_bfd ATTRIBUTE_UNUSED;
@@ -2743,7 +2735,7 @@ xcoff_reloc_type_noop (input_bfd, input_section, output_bfd, rel, sym, howto,
   return true;
 }
 
-static boolean 
+boolean 
 xcoff_reloc_type_fail (input_bfd, input_section, output_bfd, rel, sym, howto, 
                       val, addend, relocation, contents)
      bfd *input_bfd;
@@ -2764,7 +2756,7 @@ xcoff_reloc_type_fail (input_bfd, input_section, output_bfd, rel, sym, howto,
   return false;
 }
 
-static boolean 
+boolean 
 xcoff_reloc_type_pos (input_bfd, input_section, output_bfd, rel, sym, howto, 
                      val, addend, relocation, contents)
      bfd *input_bfd ATTRIBUTE_UNUSED;
@@ -2782,7 +2774,7 @@ xcoff_reloc_type_pos (input_bfd, input_section, output_bfd, rel, sym, howto,
   return true;
 }
 
-static boolean 
+boolean 
 xcoff_reloc_type_neg (input_bfd, input_section, output_bfd, rel, sym, howto, 
                      val, addend, relocation, contents)
      bfd *input_bfd ATTRIBUTE_UNUSED;
@@ -2800,7 +2792,7 @@ xcoff_reloc_type_neg (input_bfd, input_section, output_bfd, rel, sym, howto,
   return true;
 }
 
-static boolean 
+boolean 
 xcoff_reloc_type_rel (input_bfd, input_section, output_bfd, rel, sym, howto, 
                      val, addend, relocation, contents)
      bfd *input_bfd ATTRIBUTE_UNUSED;
@@ -2824,7 +2816,8 @@ xcoff_reloc_type_rel (input_bfd, input_section, output_bfd, rel, sym, howto,
                  input_section->output_offset);
   return true;
 }
-static boolean 
+
+boolean 
 xcoff_reloc_type_toc (input_bfd, input_section, output_bfd, rel, sym, howto, 
                      val, addend, relocation, contents)
      bfd *input_bfd;
@@ -2866,7 +2859,8 @@ xcoff_reloc_type_toc (input_bfd, input_section, output_bfd, rel, sym, howto,
                 (sym->n_value - xcoff_data (input_bfd)->toc));
   return true;
 }
-static boolean 
+
+boolean 
 xcoff_reloc_type_ba (input_bfd, input_section, output_bfd, rel, sym, howto, 
                     val, addend, relocation, contents)
      bfd *input_bfd ATTRIBUTE_UNUSED;
@@ -2967,7 +2961,7 @@ xcoff_reloc_type_br (input_bfd, input_section, output_bfd, rel, sym, howto,
   return true;
 }
 
-static boolean 
+boolean 
 xcoff_reloc_type_crel (input_bfd, input_section, output_bfd, rel, sym, howto, 
                       val, addend, relocation, contents)
      bfd *input_bfd ATTRIBUTE_UNUSED;
index b1bc2f58af91146419bb7516e1e09fe920f324a4..931a914cbf622bbb738e465788a86e50674102b4 100644 (file)
@@ -152,6 +152,42 @@ static boolean xcoff64_generate_rtinit
   PARAMS ((bfd *, const char *, const char *, boolean));
 static boolean xcoff64_bad_format_hook PARAMS ((bfd *, PTR ));
 
+/* Relocation functions */
+static boolean xcoff64_reloc_type_br PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
+
+boolean (*xcoff64_calculate_relocation[XCOFF_MAX_CALCULATE_RELOCATION])
+     (XCOFF_RELOC_FUNCTION_ARGS) =
+{
+  xcoff_reloc_type_pos,  /* R_POS   (0x00) */
+  xcoff_reloc_type_neg,  /* R_NEG   (0x01) */
+  xcoff_reloc_type_rel,  /* R_REL   (0x02) */
+  xcoff_reloc_type_toc,  /* R_TOC   (0x03) */
+  xcoff_reloc_type_fail, /* R_RTB   (0x04) */
+  xcoff_reloc_type_toc,  /* R_GL    (0x05) */
+  xcoff_reloc_type_toc,  /* R_TCL   (0x06) */
+  xcoff_reloc_type_fail, /*         (0x07) */
+  xcoff_reloc_type_ba,   /* R_BA    (0x08) */
+  xcoff_reloc_type_fail, /*         (0x09) */
+  xcoff64_reloc_type_br, /* R_BR    (0x0a) */
+  xcoff_reloc_type_fail, /*         (0x0b) */
+  xcoff_reloc_type_pos,  /* R_RL    (0x0c) */
+  xcoff_reloc_type_pos,  /* R_RLA   (0x0d) */
+  xcoff_reloc_type_fail, /*         (0x0e) */
+  xcoff_reloc_type_noop, /* R_REF   (0x0f) */
+  xcoff_reloc_type_fail, /*         (0x10) */
+  xcoff_reloc_type_fail, /*         (0x11) */
+  xcoff_reloc_type_toc,  /* R_TRL   (0x12) */
+  xcoff_reloc_type_toc,  /* R_TRLA  (0x13) */
+  xcoff_reloc_type_fail, /* R_RRTBI (0x14) */
+  xcoff_reloc_type_fail, /* R_RRTBA (0x15) */
+  xcoff_reloc_type_ba,   /* R_CAI   (0x16) */
+  xcoff_reloc_type_crel, /* R_CREL  (0x17) */
+  xcoff_reloc_type_ba,   /* R_RBA   (0x18) */
+  xcoff_reloc_type_ba,   /* R_RBAC  (0x19) */
+  xcoff64_reloc_type_br, /* R_RBR   (0x1a) */
+  xcoff_reloc_type_ba,   /* R_RBRC  (0x1b) */
+};
+
 /* coffcode.h needs these to be defined.  */
 /* Internalcoff.h and coffcode.h modify themselves based on these flags.  */
 #define XCOFF64
@@ -1030,6 +1066,84 @@ xcoff64_write_object_contents (abfd)
   return true;
 }
 
+static boolean 
+xcoff64_reloc_type_br (input_bfd, input_section, output_bfd, rel, sym, howto, 
+                      val, addend, relocation, contents)
+     bfd *input_bfd;
+     asection *input_section;
+     bfd *output_bfd ATTRIBUTE_UNUSED;
+     struct internal_reloc *rel;
+     struct internal_syment *sym ATTRIBUTE_UNUSED;
+     struct reloc_howto_struct *howto;
+     bfd_vma val;
+     bfd_vma addend;
+     bfd_vma *relocation;
+     bfd_byte *contents;
+{
+  struct xcoff_link_hash_entry *h;
+
+  if (0 > rel->r_symndx) 
+    return false;
+
+  h = obj_xcoff_sym_hashes (input_bfd)[rel->r_symndx];
+
+  /* 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
+     instruction, we replace the cror with ld r2,40(r1).  This
+     restores the TOC after the glink code.  Contrariwise, if the
+     call is followed by a ld r2,40(r1), but the call is not
+     going to global linkage code, we can replace the load with a
+     cror.  */
+  if (NULL != h 
+      && bfd_link_hash_defined == h->root.type 
+      && (rel->r_vaddr - input_section->vma + 8 <= 
+         input_section->_cooked_size)) 
+    {
+      bfd_byte *pnext;
+      unsigned long next;
+      
+      pnext = contents + (rel->r_vaddr - input_section->vma) + 4;
+      next = bfd_get_32 (input_bfd, pnext);
+      
+      /* The _ptrgl function is magic.  It is used by the AIX compiler to call 
+        a function through a pointer.  */
+      if (h->smclas == XMC_GL || strcmp (h->root.root.string, "._ptrgl") == 0) 
+       {
+         if (next == 0x4def7b82                       /* cror 15,15,15  */
+             || next == 0x4ffffb82                    /* cror 31,31,31  */
+             || next == 0x60000000)                   /* ori  r0,r0,0   */
+           bfd_put_32 (input_bfd, 0xe8410028, pnext); /* ld   r2,40(r1) */
+       } 
+      else 
+       {
+         if (next == 0xe8410028)                      /* ld r2,40(r1)   */
+           bfd_put_32 (input_bfd, 0x60000000, pnext); /* ori r0,r0,0    */
+       }
+    } 
+  else if (NULL != h && bfd_link_hash_undefined == h->root.type) 
+    {
+      /* Normally, this relocation is against a defined symbol.  In the
+        case where this is a partial link and the output section offset
+        is greater than 2^25, the linker will return an invalid error 
+        message that the relocation has been truncated.  Yes it has been
+        truncated but no it not important.  For this case, disable the 
+        overflow checking. */
+      howto->complain_on_overflow = complain_overflow_dont;
+    }
+  
+  howto->pc_relative = true;
+  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);
+  return true;
+}
+
 /* This is the relocation function for the PowerPC64.
    See xcoff_ppc_relocation_section for more information. */
 
@@ -1146,7 +1260,7 @@ xcoff64_ppc_relocate_section (output_bfd, info, input_bfd,
        }
       
       if (rel->r_type >= XCOFF_MAX_CALCULATE_RELOCATION 
-         || (false == xcoff_calculate_relocation[rel->r_type]
+         || (false == xcoff64_calculate_relocation[rel->r_type]
              (input_bfd, input_section, output_bfd, rel, sym, &howto, val, 
               addend, &relocation, contents))) 
        return false;
index 5e16fb2b6012dc3d55d1cd283f3cb51fb20e17b9..7463eeffecfbbc98a236e93ebe9a73b1efb738c2 100644 (file)
@@ -222,4 +222,14 @@ extern boolean (*xcoff_calculate_relocation[XCOFF_MAX_CALCULATE_RELOCATION])
 extern boolean (*xcoff_complain_overflow[XCOFF_MAX_COMPLAIN_OVERFLOW])
      (XCOFF_COMPLAIN_FUNCTION_ARGS);
 
+/* Relocation functions */
+boolean xcoff_reloc_type_noop PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
+boolean xcoff_reloc_type_fail PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
+boolean xcoff_reloc_type_pos PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
+boolean xcoff_reloc_type_neg PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
+boolean xcoff_reloc_type_rel PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
+boolean xcoff_reloc_type_toc PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
+boolean xcoff_reloc_type_ba PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
+boolean xcoff_reloc_type_crel PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
+
 #endif /* LIBXCOFF_H */
index 7aea9e92b25b255eec1e34e4e7f302c7860a3ab2..a38bd69d8452da3d40df5e25e1fb72421c271893 100644 (file)
@@ -1,3 +1,14 @@
+2002-05-10  Tom Rix  <trix@redhat.com>
+
+       * emultempl/aix.em: (gld*_set_output_arch): New function. Use 
+       architecture and machine information in the output bfd.
+       (gld*_before_parse): Remove old arch and machine code.
+       (choose_target): Rename to gld*_choose_target.
+       (rtld): Change type to int. 
+       * ldfile.c (ldfile_try_open_bfd): Disable compatiblity check for 
+       objects in XCOFF archives.
+       * ldfile.h: Update copyright date.
+
 2002-05-10  Jakub Jelinek  <jakub@redhat.com>
 
        * ldmain.c (main): Enable -z combreloc by default.
index 28f45c4ee358545be69fee8f208f4acb953df1da..90e104a0d30b7c6cb859893962031eb396c18a07 100644 (file)
@@ -53,11 +53,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "coff/internal.h"
 #include "coff/xcoff.h"
+#include "libcoff.h"
+#include "libxcoff.h"
 
 static void gld${EMULATION_NAME}_before_parse PARAMS ((void));
 static int gld${EMULATION_NAME}_parse_args PARAMS ((int, char **));
 static void gld${EMULATION_NAME}_after_open PARAMS ((void));
-static char *choose_target PARAMS ((int, char **));
+static char *gld${EMULATION_NAME}_choose_target PARAMS ((int, char **));
 static void gld${EMULATION_NAME}_before_allocation PARAMS ((void));
 static void gld${EMULATION_NAME}_read_file PARAMS ((const char *, boolean));
 static void gld${EMULATION_NAME}_free PARAMS ((PTR));
@@ -68,7 +70,9 @@ static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
 static boolean gld${EMULATION_NAME}_unrecognized_file
   PARAMS ((lang_input_statement_type *));
 static void gld${EMULATION_NAME}_create_output_section_statements 
-  PARAMS((void));
+  PARAMS ((void));
+static void gld${EMULATION_NAME}_set_output_arch PARAMS ((void));
+
 static int is_syscall PARAMS ((char *, unsigned int *));
 static int change_symbol_mode PARAMS ((char *));
 
@@ -132,7 +136,7 @@ static unsigned int syscall_mask = 0x77;
 static lang_input_statement_type *initfini_file;
 
 /* Whether to do run time linking */
-static boolean rtld;
+static int rtld;
 
 /* Explicit command line library path, -blibpath */
 static char *command_line_blibpath = NULL;
@@ -142,17 +146,7 @@ static char *command_line_blibpath = NULL;
 static void
 gld${EMULATION_NAME}_before_parse ()
 {
-#ifndef TARGET_                        /* I.e., if not generic.  */
-  const bfd_arch_info_type *arch = bfd_scan_arch ("${OUTPUT_ARCH}");
-  if (arch)
-    {
-      ldfile_output_architecture = arch->arch;
-      ldfile_output_machine = arch->mach;
-      ldfile_output_machine_name = arch->printable_name;
-    }
-  else
-    ldfile_output_architecture = bfd_arch_${ARCH};
-#endif /* not TARGET_ */
+
   config.has_shared = true;
 
   /* The link_info.[init|fini]_functions are initialized in ld/lexsup.c.
@@ -687,7 +681,8 @@ gld${EMULATION_NAME}_before_allocation ()
   if (!bfd_xcoff_size_dynamic_sections 
       (output_bfd, &link_info, libpath,        entry_symbol, file_align,
        maxstack, maxdata, gc && !unix_ld ? true : false,
-       modtype,        textro ? true : false, unix_ld, special_sections, rtld))
+       modtype,        textro ? true : false, unix_ld, special_sections, 
+       rtld ? true : false))
     einfo ("%P%F: failed to set dynamic section sizes: %E\n");
 
   /* Look through the special sections, and put them in the right
@@ -806,7 +801,7 @@ gld${EMULATION_NAME}_before_allocation ()
 }
 
 static char *
-choose_target (argc, argv)
+gld${EMULATION_NAME}_choose_target (argc, argv)
      int argc;
      char **argv;
 {
@@ -1304,7 +1299,7 @@ fi
 cat >>e${EMULATION_NAME}.c <<EOF
 
 static void 
-gld${EMULATION_NAME}_create_output_section_statements()
+gld${EMULATION_NAME}_create_output_section_statements ()
 {
   /* __rtinit */
   if ((bfd_get_flavour (output_bfd) == bfd_target_xcoff_flavour) 
@@ -1342,6 +1337,18 @@ gld${EMULATION_NAME}_create_output_section_statements()
     }
 }
 
+static void
+gld${EMULATION_NAME}_set_output_arch ()
+{
+  bfd_set_arch_mach (output_bfd,
+                    bfd_xcoff_architecture (output_bfd),
+                    bfd_xcoff_machine (output_bfd));
+
+  ldfile_output_architecture = bfd_get_arch (output_bfd);
+  ldfile_output_machine = bfd_get_mach (output_bfd);
+  ldfile_output_machine_name = bfd_printable_name (output_bfd);
+}
+
 struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = {
   gld${EMULATION_NAME}_before_parse,
   syslib_default,
@@ -1349,8 +1356,8 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = {
   after_parse_default,
   gld${EMULATION_NAME}_after_open,
   after_allocation_default,
-  set_output_arch_default,
-  choose_target,
+  gld${EMULATION_NAME}_set_output_arch,
+  gld${EMULATION_NAME}_choose_target,
   gld${EMULATION_NAME}_before_allocation,
   gld${EMULATION_NAME}_get_script,
   "${EMULATION_NAME}",
index 8d8310aa1081d6a84b1b0e024126611eaea96e15..7258bb1c4dab5f0bd8fca56d83d0846e25d41f69 100644 (file)
@@ -132,7 +132,13 @@ ldfile_try_open_bfd (attempt, entry)
        {
          if (! bfd_check_format (check, bfd_object))
            return true;
-         if (bfd_arch_get_compatible (check, output_bfd) == NULL)
+
+         if ((bfd_arch_get_compatible (check, output_bfd) == NULL)
+             /* XCOFF archives can have 32 and 64 bit objects */
+             && ! (bfd_get_flavour (check) == bfd_target_xcoff_flavour
+                   && bfd_get_flavour (output_bfd) == 
+                   bfd_target_xcoff_flavour
+                   && bfd_check_format (entry->the_bfd, bfd_archive)))
            {
              einfo (_("%P: skipping incompatible %s when searching for %s\n"),
                     attempt, entry->local_sym_name);
index ce822e7dee7b76e39285e81602fae7b3e24dced1..777932591a40c1283921d33a8b9566163236ec9d 100644 (file)
@@ -1,5 +1,5 @@
 /* ldfile.h -
-   Copyright 1991, 1992, 1993, 1994, 1995, 2000
+   Copyright 1991, 1992, 1993, 1994, 1995, 2000, 2002
    Free Software Foundation, Inc.
 
    This file is part of GLD, the Gnu Linker.