]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - ld/emultempl/aix.em
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / ld / emultempl / aix.em
index 3d1c018658060b04dc3078947a79cf3d1965f257..d578b6eae7974f066232a3ea280c64d2e04d173f 100644 (file)
@@ -5,42 +5,42 @@ if [ -z "$MACHINE" ]; then
 else
   OUTPUT_ARCH=${ARCH}:${MACHINE}
 fi
-cat >e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
 /* This file is is generated by a shell script.  DO NOT EDIT! */
 
 /* AIX emulation code for ${EMULATION_NAME}
-   Copyright 1991, 1993, 1995, 1996, 1997, 1998, 2000, 2001
-   Free Software Foundation, Inc.
+   Copyright (C) 1991-2021 Free Software Foundation, Inc.
    Written by Steve Chamberlain <sac@cygnus.com>
    AIX support by Ian Lance Taylor <ian@cygnus.com>
    AIX 64 bit support by Tom Rix <trix@redhat.com>
 
-This file is part of GLD, the Gnu Linker.
+   This file is part of the GNU Binutils.
 
-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
-(at your option) any later version.
+   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 3 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-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.  */
+   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.  */
 
 #define TARGET_IS_${EMULATION_NAME}
 
-#include "bfd.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "libiberty.h"
+#include "safe-ctype.h"
 #include "getopt.h"
 #include "obstack.h"
 #include "bfdlink.h"
-
-#include <ctype.h>
+#include "ctf-api.h"
 
 #include "ld.h"
 #include "ldmain.h"
@@ -50,23 +50,19 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "ldfile.h"
 #include "ldemul.h"
 #include "ldctor.h"
-#include "ldgram.h"
+#include <ldgram.h>
 
 #include "coff/internal.h"
 #include "coff/xcoff.h"
+#include "libcoff.h"
+#include "libxcoff.h"
+#include "xcofflink.h"
+
+static void gld${EMULATION_NAME}_read_file (const char *, bfd_boolean);
+static void gld${EMULATION_NAME}_free (void *);
+static void gld${EMULATION_NAME}_find_relocs (lang_statement_union_type *);
+static void gld${EMULATION_NAME}_find_exp_assignment (etree_type *);
 
-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 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));
-static void gld${EMULATION_NAME}_find_relocs
-  PARAMS ((lang_statement_union_type *));
-static void gld${EMULATION_NAME}_find_exp_assignment PARAMS ((etree_type *));
-static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
-static boolean gld${EMULATION_NAME}_unrecognized_file
-  PARAMS ((lang_input_statement_type *));
 
 /* The file alignment required for each section.  */
 static unsigned long file_align;
@@ -88,6 +84,14 @@ static unsigned short modtype = ('1' << 8) | 'L';
    permitted).  */
 static int textro;
 
+/* A mask of XCOFF_EXPALL and XCOFF_EXPFULL flags, as set by their
+   associated -b and -bno options.  */
+static unsigned int auto_export_flags;
+
+/* A mask of auto_export_flags bits that were explicitly set on the
+   command line.  */
+static unsigned int explicit_auto_export_flags;
+
 /* Whether to implement Unix like linker semantics.  */
 static int unix_ld;
 
@@ -108,7 +112,6 @@ struct export_symbol_list
 {
   struct export_symbol_list *next;
   const char *name;
-  boolean syscall;
 };
 
 static struct export_symbol_list *export_symbols;
@@ -116,54 +119,53 @@ static struct export_symbol_list *export_symbols;
 /* Maintains the 32 or 64 bit mode state of import file */
 static unsigned int symbol_mode = 0x04;
 
+/* Which symbol modes are valid */
+static unsigned int symbol_mode_mask = 0x0d;
+
+/* Whether this is a 64 bit link */
+static int is_64bit = 0;
+
+/* Which syscalls from import file are valid */
+static unsigned int syscall_mask = 0x77;
+
+/* fake file for -binitfini support */
+static lang_input_statement_type *initfini_file;
+
+/* Whether to do run time linking
+   -brtl enables, -bnortl and -bnortllib disable. */
+static int rtld;
+
+/* Explicit command line library path, -blibpath */
+static char *command_line_blibpath = NULL;
+
 /* This routine is called before anything else is done.  */
 
 static void
-gld${EMULATION_NAME}_before_parse ()
+gld${EMULATION_NAME}_before_parse (void)
 {
-#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.
-   * Override them here so we can use the link_info.init_function as a
-   * state flag that lets the backend know that -binitfini has been done.
-   */
+  ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`);
+
+  input_flags.dynamic = TRUE;
+  config.has_shared = TRUE;
+
+  /* The link_info.[init|fini]_functions are initialized in ld/lexsup.c.
+     Override them here so we can use the link_info.init_function as a
+     state flag that lets the backend know that -binitfini has been done.  */
+
   link_info.init_function = NULL;
   link_info.fini_function = NULL;
-
 }
 
 /* Handle AIX specific options.  */
 
-static int
-gld${EMULATION_NAME}_parse_args (argc, argv)
-     int argc;
-     char **argv;
-{
-  int prevoptind = optind;
-  int prevopterr = opterr;
-  int indx;
-  int longind;
-  int optc;
-  bfd_signed_vma val;
-  char *end;
-
-  enum {
+enum
+  {
     OPTION_IGNORE = 300,
     OPTION_AUTOIMP,
     OPTION_ERNOTOK,
     OPTION_EROK,
+    OPTION_EXPALL,
+    OPTION_EXPFULL,
     OPTION_EXPORT,
     OPTION_IMPORT,
     OPTION_INITFINI,
@@ -172,65 +174,35 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
     OPTION_MAXSTACK,
     OPTION_MODTYPE,
     OPTION_NOAUTOIMP,
+    OPTION_NOEXPALL,
+    OPTION_NOEXPFULL,
     OPTION_NOSTRCMPCT,
     OPTION_PD,
     OPTION_PT,
     OPTION_STRCMPCT,
-    OPTION_UNIX
+    OPTION_UNIX,
+    OPTION_32,
+    OPTION_64,
+    OPTION_LIBPATH,
+    OPTION_NOLIBPATH,
   };
 
-  /*
-    b64 is an empty option.  The native linker uses -b64 for xcoff64 support
-    Our linker uses -m aixppc64 for xcoff64 support. The choice for the
-    correct emulation is done in collect2.c via the environmental varible
-    LDEMULATION.
-
-    binitfini has special handling in the linker backend.  The native linker
-    uses the arguemnts to generate a table of init and fini functions for
-    the executable.  The important use for this option is to support aix 4.2+
-    c++ constructors and destructors.  This is tied into gcc via collect2.c.
-    The function table is accessed by the runtime linker/loader by checking if
-    the first symbol in the loader symbol table is "__rtinit".  The native
-    linker generates this table and the loader symbol.  The gnu linker looks
-    for the symbol "__rtinit" and makes it the first loader symbol.  It is the
-    responsiblity of the user to define the __rtinit symbol.  The format for
-    __rtinit is given by the aix system file /usr/include/rtinit.h.  You can
-    look at collect2.c to see an example of how this is done for 32 and 64 bit.
-    Below is an exmaple of a 32 bit assembly file that defines __rtinit.
-
-    .file   "my_rtinit.s"
-
-    .csect .data[RW],3
-    .globl __rtinit
-    .extern init_function
-    .extern fini_function
-
-    __rtinit:
-            .long 0
-            .long f1i - __rtinit
-            .long f1f - __rtinit
-            .long f2i - f1i
-            .align 3
-    f1i:    .long init_function
-            .long s1i - __rtinit
-            .long 0
-    f2i:    .long 0
-            .long 0
-            .long 0
-    f1f:    .long fini_function
-            .long s1f - __rtinit
-            .long 0
-    f2f:    .long 0
-            .long 0
-            .long 0
-            .align 3
-    s1i:    .string "init_function"
-            .align 3
-    s1f:    .string "fini_function"
-
-   */
-
-  static const struct option longopts[] = {
+static void
+gld${EMULATION_NAME}_add_options
+  (int ns, char **shortopts, int nl, struct option **longopts,
+   int nrl ATTRIBUTE_UNUSED, struct option **really_longopts ATTRIBUTE_UNUSED)
+{
+  static const char xtra_short[] = "D:H:KT:z";
+  static const struct option xtra_long[] = {
+  /* -binitfini has special handling in the linker backend.  The native linker
+     uses the arguemnts to generate a table of init and fini functions for
+     the executable.  The important use for this option is to support aix 4.2+
+     c++ constructors and destructors.  This is tied into gcc via collect2.c.
+
+     The function table is accessed by the runtime linker/loader by checking if
+     the first symbol in the loader symbol table is __rtinit.  The gnu linker
+     generates this symbol and makes it the first loader symbol.  */
+
     {"basis", no_argument, NULL, OPTION_IGNORE},
     {"bautoimp", no_argument, NULL, OPTION_AUTOIMP},
     {"bcomprld", no_argument, NULL, OPTION_IGNORE},
@@ -241,7 +213,10 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
     {"bernotok", no_argument, NULL, OPTION_ERNOTOK},
     {"berok", no_argument, NULL, OPTION_EROK},
     {"berrmsg", no_argument, NULL, OPTION_IGNORE},
+    {"bexpall", no_argument, NULL, OPTION_EXPALL},
+    {"bexpfull", no_argument, NULL, OPTION_EXPFULL},
     {"bexport", required_argument, NULL, OPTION_EXPORT},
+    {"bbigtoc", no_argument, NULL, OPTION_IGNORE},
     {"bf", no_argument, NULL, OPTION_ERNOTOK},
     {"bgc", no_argument, &gc, 1},
     {"bh", required_argument, NULL, OPTION_IGNORE},
@@ -256,6 +231,8 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
     {"bM", required_argument, NULL, OPTION_MODTYPE},
     {"bmodtype", required_argument, NULL, OPTION_MODTYPE},
     {"bnoautoimp", no_argument, NULL, OPTION_NOAUTOIMP},
+    {"bnoexpall", no_argument, NULL, OPTION_NOEXPALL},
+    {"bnoexpfull", no_argument, NULL, OPTION_NOEXPFULL},
     {"bnodelcsect", no_argument, NULL, OPTION_IGNORE},
     {"bnoentry", no_argument, NULL, OPTION_IGNORE},
     {"bnogc", no_argument, &gc, 0},
@@ -266,17 +243,23 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
     {"bpD", required_argument, NULL, OPTION_PD},
     {"bpT", required_argument, NULL, OPTION_PT},
     {"bro", no_argument, &textro, 1},
+    {"brtl", no_argument, &rtld, 1},
+    {"bnortl", no_argument, &rtld, 0},
+    {"bnortllib", no_argument, &rtld, 0},
     {"bS", required_argument, NULL, OPTION_MAXSTACK},
     {"bso", no_argument, NULL, OPTION_AUTOIMP},
     {"bstrcmpct", no_argument, NULL, OPTION_STRCMPCT},
     {"btextro", no_argument, &textro, 1},
-    {"b64", no_argument, NULL, 0},
+    {"b32", no_argument, NULL, OPTION_32},
+    {"b64", no_argument, NULL, OPTION_64},
     {"static", no_argument, NULL, OPTION_NOAUTOIMP},
     {"unix", no_argument, NULL, OPTION_UNIX},
+    {"blibpath", required_argument, NULL, OPTION_LIBPATH},
+    {"bnolibpath", required_argument, NULL, OPTION_NOLIBPATH},
     {NULL, no_argument, NULL, 0}
   };
 
-  /* Options supported by the AIX linker which we do not support: -f,
+  /* Options supported by the AIX linker which we do not support:
      -S, -v, -Z, -bbindcmds, -bbinder, -bbindopts, -bcalls, -bcaps,
      -bcror15, -bdebugopt, -bdbg, -bdelcsect, -bex?, -bfilelist, -bfl,
      -bgcbypass, -bglink, -binsert, -bi, -bloadmap, -bl, -bmap, -bnl,
@@ -285,16 +268,26 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
      -bnotypchk, -bnox, -bquiet, -bR, -brename, -breorder, -btypchk,
      -bx, -bX, -bxref.  */
 
+  *shortopts = (char *) xrealloc (*shortopts, ns + sizeof (xtra_short));
+  memcpy (*shortopts + ns, &xtra_short, sizeof (xtra_short));
+  *longopts = xrealloc (*longopts,
+                       nl * sizeof (struct option) + sizeof (xtra_long));
+  memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
+}
+
+static bfd_boolean
+gld${EMULATION_NAME}_parse_args (int argc, char **argv)
+{
+  int indx;
+
   /* If the current option starts with -b, change the first : to an =.
      The AIX linker uses : to separate the option from the argument;
      changing it to = lets us treat it as a getopt option.  */
   indx = optind;
   if (indx == 0)
-    {
-      indx = 1;
-    }
+    indx = 1;
 
-  if (indx < argc && strncmp (argv[indx], "-b", 2) == 0)
+  if (indx < argc && CONST_STRNEQ (argv[indx], "-b"))
     {
       char *s;
 
@@ -307,40 +300,112 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
            }
        }
     }
+  return FALSE;
+}
 
+/* Helper for option '-f', which specify a list of input files.
+   Contrary to the native linker, we don't support shell patterns
+   (simply because glob isn't always available).  */
 
-  /* We add s and u so to the short options list so that -s and -u on
-     the command line do not match -static and -unix.  */
+static void
+read_file_list (const char *filename)
+{
+  FILE *f;
+  /* An upper bound on the number of characters in the file.  */
+  long pos;
+  /* File in memory.  */
+  char *buffer;
+  size_t len;
+  char *b;
+  char *e;
 
-  opterr = 0;
-  optc = getopt_long_only (argc, argv, "-D:H:KT:zsu", longopts, &longind);
-  opterr = prevopterr;
+  f = fopen (filename, FOPEN_RT);
+  if (f == NULL)
+    {
+      einfo (_("%F%P: cannot open %s\n"), filename);
+      return;
+    }
+  if (fseek (f, 0L, SEEK_END) == -1)
+    goto error;
+  pos = ftell (f);
+  if (pos == -1)
+    goto error;
+  if (fseek (f, 0L, SEEK_SET) == -1)
+    goto error;
+
+  buffer = (char *) xmalloc (pos + 1);
+  len = fread (buffer, sizeof (char), pos, f);
+  if (len != (size_t) pos && ferror (f))
+    goto error;
+  /* Add a NUL terminator.  */
+  buffer[len] = '\0';
+  fclose (f);
+
+  /* Parse files.  */
+  b = buffer;
+  while (1)
+    {
+      /* Skip empty lines.  */
+      while (*b == '\n' || *b == '\r')
+       b++;
+
+      /* Stop if end of buffer.  */
+      if (b == buffer + len)
+       break;
+
+      /* Eat any byte until end of line.  */
+      for (e = b; *e != '\0'; e++)
+       if (*e == '\n' || *e == '\r')
+         break;
+
+      /* Replace end of line by nul.  */
+      if (*e != '\0')
+       *e++ = '\0';
+
+      if (b != e)
+       lang_add_input_file (b, lang_input_file_is_search_file_enum, NULL);
+      b = e;
+    }
+  return;
+
+ error:
+  einfo (_("%F%P: cannot read %s\n"), optarg);
+  fclose (f);
+}
+
+static bfd_boolean
+gld${EMULATION_NAME}_handle_option (int optc)
+{
+  bfd_signed_vma val;
+  const char *end;
 
   switch (optc)
     {
-    case 's':
-    case 'u':
     default:
-      optind = prevoptind;
-      return 0;
+      return FALSE;
 
     case 0:
       /* Long option which just sets a flag.  */
       break;
 
+    case 'f':
+      /* This overrides --auxiliary.  This option specifies a file containing
+        a list of input files.  */
+      read_file_list (optarg);
+      break;
+
     case 'D':
-      val = strtoll (optarg, &end, 0);
+      val = bfd_scan_vma (optarg, &end, 0);
       if (*end != '\0')
-       einfo ("%P: warning: ignoring invalid -D number %s\n", optarg);
+       einfo (_("%P: warning: ignoring invalid -D number %s\n"), optarg);
       else if (val != -1)
-       lang_section_start (".data", exp_intop (val));
+       lang_section_start (".data", exp_intop (val), NULL);
       break;
 
     case 'H':
-      val = strtoul (optarg, &end, 0);
-      if (*end != '\0'
-         || (val & (val - 1)) != 0)
-       einfo ("%P: warning: ignoring invalid -H number %s\n", optarg);
+      val = bfd_scan_vma (optarg, &end, 0);
+      if (*end != '\0' || (val & (val - 1)) != 0)
+       einfo (_("%P: warning: ignoring invalid -H number %s\n"), optarg);
       else
        file_align = val;
       break;
@@ -353,16 +418,13 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
 
     case 'T':
       /* On AIX this is the same as GNU ld -Ttext.  When we see -T
-         number, we assume the AIX option is intended.  Otherwise, we
-         assume the usual GNU ld -T option is intended.  We can't just
-         ignore the AIX option, because gcc passes it to the linker.  */
-      val = strtoull (optarg, &end, 0);
+        number, we assume the AIX option is intended.  Otherwise, we
+        assume the usual GNU ld -T option is intended.  We can't just
+        ignore the AIX option, because gcc passes it to the linker.  */
+      val = bfd_scan_vma (optarg, &end, 0);
       if (*end != '\0')
-       {
-         optind = prevoptind;
-         return 0;
-       }
-      lang_section_start (".text", exp_intop (val));
+       return FALSE;
+      lang_section_start (".text", exp_intop (val), NULL);
       break;
 
     case OPTION_IGNORE:
@@ -393,9 +455,7 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
          *t++ = 0;
 
        if (0 != strlen (i))
-         {
-           link_info.init_function = i;
-         }
+         link_info.init_function = i;
 
        f = t;
        while (*t && ':' != *t)
@@ -403,26 +463,36 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
        *t = 0;
 
        if (0 != strlen (f))
-         {
-           link_info.fini_function = f;
-         }
+         link_info.fini_function = f;
       }
-    break;
+      break;
 
     case OPTION_AUTOIMP:
-      link_info.static_link = false;
+      link_info.static_link = FALSE;
       break;
 
     case OPTION_ERNOTOK:
-      force_make_executable = false;
+      link_info.unresolved_syms_in_objects = RM_DIAGNOSE;
+      link_info.unresolved_syms_in_shared_libs = RM_DIAGNOSE;
       break;
 
     case OPTION_EROK:
-      force_make_executable = true;
+      link_info.unresolved_syms_in_objects = RM_IGNORE;
+      link_info.unresolved_syms_in_shared_libs = RM_IGNORE;
+      break;
+
+    case OPTION_EXPALL:
+      auto_export_flags |= XCOFF_EXPALL;
+      explicit_auto_export_flags |= XCOFF_EXPALL;
+      break;
+
+    case OPTION_EXPFULL:
+      auto_export_flags |= XCOFF_EXPFULL;
+      explicit_auto_export_flags |= XCOFF_EXPFULL;
       break;
 
     case OPTION_EXPORT:
-      gld${EMULATION_NAME}_read_file (optarg, false);
+      gld${EMULATION_NAME}_read_file (optarg, FALSE);
       break;
 
     case OPTION_IMPORT:
@@ -445,17 +515,19 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
       break;
 
     case OPTION_MAXDATA:
-      val = strtoull (optarg, &end, 0);
+      val = bfd_scan_vma (optarg, &end, 0);
       if (*end != '\0')
-       einfo ("%P: warning: ignoring invalid -bmaxdata number %s\n", optarg);
+       einfo (_("%P: warning: ignoring invalid -bmaxdata number %s\n"),
+              optarg);
       else
        maxdata = val;
       break;
 
     case OPTION_MAXSTACK:
-      val = strtoull (optarg, &end, 0);
+      val = bfd_scan_vma (optarg, &end, 0);
       if (*end != '\0')
-       einfo ("%P: warning: ignoring invalid -bmaxstack number %s\n", optarg);
+       einfo (_("%P: warning: ignoring invalid -bmaxstack number %s\n"),
+              optarg);
       else
        maxstack = val;
       break;
@@ -463,31 +535,41 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
     case OPTION_MODTYPE:
       if (*optarg == 'S')
        {
-         link_info.shared = true;
+         link_info.type = type_dll;
          ++optarg;
        }
       if (*optarg == '\0' || optarg[1] == '\0')
-       einfo ("%P: warning: ignoring invalid module type %s\n", optarg);
+       einfo (_("%P: warning: ignoring invalid module type %s\n"), optarg);
       else
        modtype = (*optarg << 8) | optarg[1];
       break;
 
     case OPTION_NOAUTOIMP:
-      link_info.static_link = true;
+      link_info.static_link = TRUE;
+      break;
+
+    case OPTION_NOEXPALL:
+      auto_export_flags &= ~XCOFF_EXPALL;
+      explicit_auto_export_flags |= XCOFF_EXPALL;
+      break;
+
+    case OPTION_NOEXPFULL:
+      auto_export_flags &= ~XCOFF_EXPFULL;
+      explicit_auto_export_flags |= XCOFF_EXPFULL;
       break;
 
     case OPTION_NOSTRCMPCT:
-      link_info.traditional_format = true;
+      link_info.traditional_format = TRUE;
       break;
 
     case OPTION_PD:
       /* This sets the page that the .data section is supposed to
-         start on.  The offset within the page should still be the
-         offset within the file, so we need to build an appropriate
-         expression.  */
-      val = strtoull (optarg, &end, 0);
+        start on.  The offset within the page should still be the
+        offset within the file, so we need to build an appropriate
+        expression.  */
+      val = bfd_scan_vma (optarg, &end, 0);
       if (*end != '\0')
-       einfo ("%P: warning: ignoring invalid -pD number %s\n", optarg);
+       einfo (_("%P: warning: ignoring invalid -pD number %s\n"), optarg);
       else
        {
          etree_type *t;
@@ -499,18 +581,18 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
                                    exp_intop (0xfff)));
          t = exp_binop ('&',
                         exp_binop ('+', t, exp_intop (31)),
-                        exp_intop (~ (bfd_vma) 31));
-         lang_section_start (".data", t);
+                        exp_intop (~(bfd_vma) 31));
+         lang_section_start (".data", t, NULL);
        }
       break;
 
     case OPTION_PT:
       /* This set the page that the .text section is supposed to start
-         on.  The offset within the page should still be the offset
-         within the file.  */
-      val = strtoull (optarg, &end, 0);
+        on.  The offset within the page should still be the offset
+        within the file.  */
+      val = bfd_scan_vma (optarg, &end, 0);
       if (*end != '\0')
-       einfo ("%P: warning: ignoring invalid -pT number %s\n", optarg);
+       einfo (_("%P: warning: ignoring invalid -pT number %s\n"), optarg);
       else
        {
          etree_type *t;
@@ -520,39 +602,59 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
                         exp_nameop (SIZEOF_HEADERS, NULL));
          t = exp_binop ('&',
                         exp_binop ('+', t, exp_intop (31)),
-                        exp_intop (~ (bfd_vma) 31));
-         lang_section_start (".text", t);
+                        exp_intop (~(bfd_vma) 31));
+         lang_section_start (".text", t, NULL);
        }
       break;
 
     case OPTION_STRCMPCT:
-      link_info.traditional_format = false;
+      link_info.traditional_format = FALSE;
       break;
 
     case OPTION_UNIX:
-      unix_ld = true;
+      unix_ld = TRUE;
+      break;
+
+    case OPTION_32:
+      is_64bit = 0;
+      syscall_mask = 0x77;
+      symbol_mode_mask = 0x0d;
+      break;
+
+    case OPTION_64:
+      is_64bit = 1;
+      syscall_mask = 0xcc;
+      symbol_mode_mask = 0x0e;
+      break;
+
+    case OPTION_LIBPATH:
+      command_line_blibpath = optarg;
       break;
+
+    case OPTION_NOLIBPATH:
+      command_line_blibpath = NULL;
+      break;
+
     }
 
-  return 1;
+  return TRUE;
 }
 
 /* This is called when an input file can not be recognized as a BFD
    object or an archive.  If the file starts with #!, we must treat it
    as an import file.  This is for AIX compatibility.  */
 
-static boolean
-gld${EMULATION_NAME}_unrecognized_file (entry)
-     lang_input_statement_type *entry;
+static bfd_boolean
+gld${EMULATION_NAME}_unrecognized_file (lang_input_statement_type *entry)
 {
   FILE *e;
-  boolean ret;
+  bfd_boolean ret;
 
   e = fopen (entry->filename, FOPEN_RT);
   if (e == NULL)
-    return false;
+    return FALSE;
 
-  ret = false;
+  ret = FALSE;
 
   if (getc (e) == '#' && getc (e) == '!')
     {
@@ -567,8 +669,8 @@ gld${EMULATION_NAME}_unrecognized_file (entry)
        flpp = &(*flpp)->next;
       *flpp = n;
 
-      ret = true;
-      entry->loaded = true;
+      ret = TRUE;
+      entry->flags.loaded = TRUE;
     }
 
   fclose (e);
@@ -579,21 +681,23 @@ gld${EMULATION_NAME}_unrecognized_file (entry)
 /* This is called after the input files have been opened.  */
 
 static void
-gld${EMULATION_NAME}_after_open ()
+gld${EMULATION_NAME}_after_open (void)
 {
-  boolean r;
+  enum output_type t;
   struct set_info *p;
 
+  after_open_default ();
+
   /* Call ldctor_build_sets, after pretending that this is a
-     relocateable link.  We do this because AIX requires relocation
+     relocatable link.  We do this because AIX requires relocation
      entries for all references to symbols, even in a final
      executable.  Of course, we only want to do this if we are
      producing an XCOFF output file.  */
-  r = link_info.relocateable;
-  if (strstr (bfd_get_target (output_bfd), "xcoff") != NULL)
-    link_info.relocateable = true;
+  t = link_info.type;
+  if (strstr (bfd_get_target (link_info.output_bfd), "xcoff") != NULL)
+    link_info.type = type_relocatable;
   ldctor_build_sets ();
-  link_info.relocateable = r;
+  link_info.type = t;
 
   /* For each set, record the size, so that the XCOFF backend can
      output the correct csect length.  */
@@ -615,8 +719,9 @@ gld${EMULATION_NAME}_after_open ()
        }
 
       size = (p->count + 2) * 4;
-      if (! bfd_xcoff_link_record_set (output_bfd, &link_info, p->h, size))
-       einfo ("%F%P: bfd_xcoff_link_record_set failed: %E\n");
+      if (!bfd_xcoff_link_record_set (link_info.output_bfd, &link_info,
+                                     p->h, size))
+       einfo (_("%F%P: bfd_xcoff_link_record_set failed: %E\n"));
     }
 }
 
@@ -624,26 +729,31 @@ gld${EMULATION_NAME}_after_open ()
    sections, but before any sizes or addresses have been set.  */
 
 static void
-gld${EMULATION_NAME}_before_allocation ()
+gld${EMULATION_NAME}_before_allocation (void)
 {
   struct filelist *fl;
   struct export_symbol_list *el;
   char *libpath;
   asection *special_sections[XCOFF_NUMBER_OF_SPECIAL_SECTIONS];
-  int i;
+  static const char *const must_keep_sections[] = {
+    ".text",
+    ".data",
+    ".bss"
+  };
+  unsigned int i, flags;
 
   /* Handle the import and export files, if any.  */
   for (fl = import_files; fl != NULL; fl = fl->next)
-    gld${EMULATION_NAME}_read_file (fl->name, true);
+    gld${EMULATION_NAME}_read_file (fl->name, TRUE);
   for (el = export_symbols; el != NULL; el = el->next)
     {
       struct bfd_link_hash_entry *h;
 
-      h = bfd_link_hash_lookup (link_info.hash, el->name, false, false, false);
+      h = bfd_link_hash_lookup (link_info.hash, el->name, FALSE, FALSE, FALSE);
       if (h == NULL)
-       einfo ("%P%F: bfd_link_hash_lookup of export symbol failed: %E\n");
-      if (! bfd_xcoff_export_symbol (output_bfd, &link_info, h, el->syscall))
-       einfo ("%P%F: bfd_xcoff_export_symbol failed: %E\n");
+       einfo (_("%F%P: bfd_link_hash_lookup of export symbol failed: %E\n"));
+      if (!bfd_xcoff_export_symbol (link_info.output_bfd, &link_info, h))
+       einfo (_("%F%P: bfd_xcoff_export_symbol failed: %E\n"));
     }
 
   /* Track down all relocations called for by the linker script (these
@@ -652,10 +762,13 @@ gld${EMULATION_NAME}_before_allocation ()
      .loader relocs for them.  */
   lang_for_each_statement (gld${EMULATION_NAME}_find_relocs);
 
-  /* We need to build LIBPATH from the -L arguments.  If any -rpath
-     arguments were used, though, we use -rpath instead, as a GNU
-     extension.  */
-  if (command_line.rpath != NULL)
+  /* Precedence of LIBPATH
+     -blibpath:         native support always first
+     -rpath:    gnu extension
+     -L                 build from command line -L's */
+  if (command_line_blibpath != NULL)
+    libpath = command_line_blibpath;
+  else if (command_line.rpath != NULL)
     libpath = command_line.rpath;
   else if (search_head == NULL)
     libpath = (char *) "";
@@ -664,31 +777,67 @@ gld${EMULATION_NAME}_before_allocation ()
       size_t len;
       search_dirs_type *search;
 
-      len = strlen (search_head->name);
-      libpath = xmalloc (len + 1);
-      strcpy (libpath, search_head->name);
-      for (search = search_head->next; search != NULL; search = search->next)
+      /* PR ld/4023: Strip sysroot prefix from any paths
+        being inserted into the output binary's DT_RPATH.  */
+      if (ld_sysroot != NULL
+         && * ld_sysroot != 0)
        {
-         size_t nlen;
+         const char * name = search_head->name;
+         size_t ld_sysroot_len = strlen (ld_sysroot);
+
+         if (strncmp (name, ld_sysroot, ld_sysroot_len) == 0)
+           name += ld_sysroot_len;
+
+         len = strlen (name);
+         libpath = xmalloc (len + 1);
+         strcpy (libpath, name);
+
+         for (search = search_head->next; search != NULL; search = search->next)
+           {
+             size_t nlen;
+
+             name = search->name;
+             if (strncmp (name, ld_sysroot, ld_sysroot_len) == 0)
+               name += ld_sysroot_len;
 
-         nlen = strlen (search->name);
-         libpath = xrealloc (libpath, len + nlen + 2);
-         libpath[len] = ':';
-         strcpy (libpath + len + 1, search->name);
-         len += nlen + 1;
+             nlen = strlen (name);
+             libpath = xrealloc (libpath, len + nlen + 2);
+             libpath[len] = ':';
+             strcpy (libpath + len + 1, name);
+             len += nlen + 1;
+           }
+       }
+      else
+       {
+         len = strlen (search_head->name);
+         libpath = xmalloc (len + 1);
+         strcpy (libpath, search_head->name);
+
+         for (search = search_head->next; search != NULL; search = search->next)
+           {
+             size_t nlen;
+
+             nlen = strlen (search->name);
+             libpath = xrealloc (libpath, len + nlen + 2);
+             libpath[len] = ':';
+             strcpy (libpath + len + 1, search->name);
+             len += nlen + 1;
+           }
        }
     }
 
+  /* Default to -bexpfull for SVR4-like semantics.  */
+  flags = (unix_ld ? XCOFF_EXPFULL : 0);
+  flags &= ~explicit_auto_export_flags;
+  flags |= auto_export_flags;
+
   /* Let the XCOFF backend set up the .loader section.  */
-  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))
-    einfo ("%P%F: failed to set dynamic section sizes: %E\n");
+  if (!bfd_xcoff_size_dynamic_sections
+      (link_info.output_bfd, &link_info, libpath, entry_symbol.name, file_align,
+       maxstack, maxdata, gc && !unix_ld ? TRUE : FALSE,
+       modtype, textro ? TRUE : FALSE, flags, special_sections,
+       rtld ? TRUE : FALSE))
+    einfo (_("%F%P: failed to set dynamic section sizes: %E\n"));
 
   /* Look through the special sections, and put them in the right
      place in the link ordering.  This is especially magic.  */
@@ -699,7 +848,7 @@ gld${EMULATION_NAME}_before_allocation ()
       lang_statement_union_type **pls;
       lang_input_section_type *is;
       const char *oname;
-      boolean start;
+      bfd_boolean start;
 
       sec = special_sections[i];
       if (sec == NULL)
@@ -708,19 +857,17 @@ gld${EMULATION_NAME}_before_allocation ()
       /* Remove this section from the list of the output section.
         This assumes we know what the script looks like.  */
       is = NULL;
-      os = lang_output_section_find (sec->output_section->name);
-      if (os == NULL) {
-       einfo ("%P%F: can't find output section %s\n",
+      os = lang_output_section_get (sec->output_section);
+      if (os == NULL)
+       einfo (_("%F%P: can't find output section %s\n"),
               sec->output_section->name);
-      }
 
       for (pls = &os->children.head; *pls != NULL; pls = &(*pls)->header.next)
        {
-
-         if ((*pls)->header.type == lang_input_section_enum &&
-             (*pls)->input_section.section == sec)
+         if ((*pls)->header.type == lang_input_section_enum
+             && (*pls)->input_section.section == sec)
            {
-             is = (lang_input_section_type *) *pls;
+             is = (lang_input_section_type *) * pls;
              *pls = (*pls)->header.next;
              break;
            }
@@ -730,15 +877,13 @@ gld${EMULATION_NAME}_before_allocation ()
              lang_statement_union_type **pwls;
 
              for (pwls = &(*pls)->wild_statement.children.head;
-                  *pwls != NULL;
-                  pwls = &(*pwls)->header.next)
+                  *pwls != NULL; pwls = &(*pwls)->header.next)
                {
 
-                 if ((*pwls)->header.type == lang_input_section_enum &&
-                     (*pwls)->input_section.section == sec)
+                 if ((*pwls)->header.type == lang_input_section_enum
+                     && (*pwls)->input_section.section == sec)
                    {
-
-                     is = (lang_input_section_type *) *pwls;
+                     is = (lang_input_section_type *) * pwls;
                      *pwls = (*pwls)->header.next;
                      break;
                    }
@@ -751,44 +896,44 @@ gld${EMULATION_NAME}_before_allocation ()
 
       if (is == NULL)
        {
-         einfo ("%P%F: can't find %s in output section\n",
-                bfd_get_section_name (sec->owner, sec));
+         einfo (_("%F%P: can't find %s in output section\n"),
+                bfd_section_name (sec));
        }
 
       /* Now figure out where the section should go.  */
       switch (i)
        {
 
-       default: /* to avoid warnings */
+       default:                /* to avoid warnings */
        case XCOFF_SPECIAL_SECTION_TEXT:
          /* _text */
          oname = ".text";
-         start = true;
+         start = TRUE;
          break;
 
        case XCOFF_SPECIAL_SECTION_ETEXT:
          /* _etext */
          oname = ".text";
-         start = false;
+         start = FALSE;
          break;
 
        case XCOFF_SPECIAL_SECTION_DATA:
          /* _data */
          oname = ".data";
-         start = true;
+         start = TRUE;
          break;
 
        case XCOFF_SPECIAL_SECTION_EDATA:
          /* _edata */
          oname = ".data";
-         start = false;
+         start = FALSE;
          break;
 
        case XCOFF_SPECIAL_SECTION_END:
        case XCOFF_SPECIAL_SECTION_END2:
          /* _end and end */
          oname = ".bss";
-         start = false;
+         start = FALSE;
          break;
        }
 
@@ -802,34 +947,84 @@ gld${EMULATION_NAME}_before_allocation ()
       else
        {
          is->header.next = NULL;
-         lang_statement_append (&os->children,
-                                (lang_statement_union_type *) is,
-                                &is->header.next);
+         *os->children.tail = (lang_statement_union_type *) is;
+         os->children.tail = &is->header.next;
        }
     }
+
+  /* Executables and shared objects must always have .text, .data
+     and .bss output sections, so that the header can refer to them.
+     The kernel refuses to load objects that have missing sections.  */
+  if (!bfd_link_relocatable (&link_info))
+    for (i = 0; i < ARRAY_SIZE (must_keep_sections); i++)
+      {
+       asection *sec;
+
+       sec = bfd_get_section_by_name (link_info.output_bfd,
+                                      must_keep_sections[i]);
+       if (sec == NULL)
+         einfo (_("%P: can't find required output section %s\n"),
+                must_keep_sections[i]);
+       else
+         sec->flags |= SEC_KEEP;
+      }
+
+  before_allocation_default ();
 }
 
-static int change_symbol_mode (char *input)
+static char *
+gld${EMULATION_NAME}_choose_target (int argc, char **argv)
 {
-  /*
-   * 1 : state changed
-   * 0 : no change
-   */
+  int i, j, jmax;
+  static char *from_outside;
+  static char *from_inside;
+  static char *argv_to_target[][2] = {
+    {NULL,   "${OUTPUT_FORMAT}"},
+    {"-b32", "${OUTPUT_FORMAT_32BIT}"},
+    {"-b64", "${OUTPUT_FORMAT_64BIT}"},
+  };
+
+  jmax = 3;
+
+  from_outside = getenv (TARGET_ENVIRON);
+  if (from_outside != (char *) NULL)
+    return from_outside;
+
+  /* Set to default. */
+  from_inside = argv_to_target[0][1];
+  for (i = 1; i < argc; i++)
+    {
+      for (j = 1; j < jmax; j++)
+       {
+         if (0 == strcmp (argv[i], argv_to_target[j][0]))
+           from_inside = argv_to_target[j][1];
+       }
+    }
+
+  return from_inside;
+}
 
+/* Returns
+   1 : state changed
+   0 : no change */
+static int
+change_symbol_mode (char *input)
+{
   char *symbol_mode_string[] = {
-    "# 32",   /* 0x01 */
-    "# 64",   /* 0x02 */
-    "# no32", /* 0x04 */
-    "# no64", /* 0x08 */
+    "# 32",                    /* 0x01 */
+    "# 64",                    /* 0x02 */
+    "# no32",                  /* 0x04 */
+    "# no64",                  /* 0x08 */
     NULL,
   };
+
   unsigned int bit;
   char *string;
 
-  for (bit = 0; ; bit++)
+  for (bit = 0;; bit++)
     {
       string = symbol_mode_string[bit];
-      if (NULL == string)
+      if (string == NULL)
        return 0;
 
       if (0 == strcmp (input, string))
@@ -842,42 +1037,44 @@ static int change_symbol_mode (char *input)
   return 0;
 }
 
-
-static int is_syscall (char *input)
+/* Returns
+   1 : yes
+   0 : ignore
+   -1 : error, try something else */
+static int
+is_syscall (char *input, unsigned int *flag)
 {
-  /*
-   * 1 : yes
-   * 0 : ignore
-   * -1 : error, try something else
-   */
   unsigned int bit;
   char *string;
 
-  char *syscall_string[] = {
-    "svc",          /* 0x01 */
-    "svc32",        /* 0x02 */
-    "svc3264",      /* 0x04 */
-    "svc64",        /* 0x08 */
-    "syscall",      /* 0x10 */
-    "syscall32",     /* 0x20 */
-    "syscall3264",   /* 0x40 */
-    "syscall64",     /* 0x80 */
-    NULL
+  struct sc {
+    char *syscall_string;
+    unsigned int flag;
+  } s [] = {
+    { "svc"        /* 0x01 */, XCOFF_SYSCALL32 },
+    { "svc32"      /* 0x02 */, XCOFF_SYSCALL32 },
+    { "svc3264"     /* 0x04 */, XCOFF_SYSCALL32 | XCOFF_SYSCALL64 },
+    { "svc64"      /* 0x08 */, XCOFF_SYSCALL64 },
+    { "syscall"     /* 0x10 */, XCOFF_SYSCALL32 },
+    { "syscall32"   /* 0x20 */, XCOFF_SYSCALL32 },
+    { "syscall3264" /* 0x40 */, XCOFF_SYSCALL32 | XCOFF_SYSCALL64 },
+    { "syscall64"   /* 0x80 */, XCOFF_SYSCALL64 },
+    { NULL, 0 },
   };
 
-  for (bit = 0; ;bit++)
-    {
+  *flag = 0;
 
-      string = syscall_string[bit];
-      if (NULL == string)
-       {
-         return -1;
-       }
+  for (bit = 0;; bit++)
+    {
+      string = s[bit].syscall_string;
+      if (string == NULL)
+       return -1;
 
       if (0 == strcmp (input, string))
        {
-         if (1 << bit & ${SYSCALL_MASK})
+         if (1 << bit & syscall_mask)
            {
+             *flag = s[bit].flag;
              return 1;
            }
          else
@@ -890,21 +1087,18 @@ static int is_syscall (char *input)
   return -1;
 }
 
-
 /* Read an import or export file.  For an import file, this is called
    by the before_allocation emulation routine.  For an export file,
-   this is called by the parse_args emulation routine.  */
+   this is called by the handle_option emulation routine.  */
 
 static void
-gld${EMULATION_NAME}_read_file (filename, import)
-     const char *filename;
-     boolean import;
+gld${EMULATION_NAME}_read_file (const char *filename, bfd_boolean import)
 {
   struct obstack *o;
   FILE *f;
   int lineno;
   int c;
-  boolean keep;
+  bfd_boolean keep;
   const char *imppath;
   const char *impfile;
   const char *impmember;
@@ -916,10 +1110,11 @@ gld${EMULATION_NAME}_read_file (filename, import)
   if (f == NULL)
     {
       bfd_set_error (bfd_error_system_call);
-      einfo ("%F%s: %E\n", filename);
+      einfo ("%F%P: %s: %E\n", filename);
+      return;
     }
 
-  keep = false;
+  keep = FALSE;
 
   imppath = NULL;
   impfile = NULL;
@@ -927,19 +1122,18 @@ gld${EMULATION_NAME}_read_file (filename, import)
 
   lineno = 0;
 
-  /*
-   * default to 32 and 64 bit mode
-   * symbols at top of /lib/syscalls.exp do not have a mode modifier and they
-   * are not repeated, assume 64 bit routines also want to use them.
-   * See the routine change_symbol_mode for more information.
-   */
+  /* Default to 32 and 64 bit mode
+     symbols at top of /lib/syscalls.exp do not have a mode modifier and they
+     are not repeated, assume 64 bit routines also want to use them.
+     See the routine change_symbol_mode for more information.  */
+
   symbol_mode = 0x04;
 
   while ((c = getc (f)) != EOF)
     {
       char *s;
       char *symname;
-      boolean syscall;
+      unsigned int syscall_flag = 0;
       bfd_vma address;
       struct bfd_link_hash_entry *h;
 
@@ -953,13 +1147,13 @@ gld${EMULATION_NAME}_read_file (filename, import)
       ++lineno;
 
       s = (char *) obstack_base (o);
-      while (isspace ((unsigned char) *s))
+      while (ISSPACE (*s))
        ++s;
       if (*s == '\0'
          || *s == '*'
          || change_symbol_mode (s)
          || (*s == '#' && s[1] == ' ')
-         || (! import && *s == '#' && s[1] == '!'))
+         || (!import && *s == '#' && s[1] == '!'))
        {
          obstack_free (o, obstack_base (o));
          continue;
@@ -968,7 +1162,7 @@ gld${EMULATION_NAME}_read_file (filename, import)
       if (*s == '#' && s[1] == '!')
        {
          s += 2;
-         while (isspace ((unsigned char) *s))
+         while (ISSPACE (*s))
            ++s;
          if (*s == '\0')
            {
@@ -978,38 +1172,25 @@ gld${EMULATION_NAME}_read_file (filename, import)
              obstack_free (o, obstack_base (o));
            }
          else if (*s == '(')
-           einfo ("%F%s%d: #! ([member]) is not supported in import files\n",
+           einfo (_("%F%P:%s:%d: #! ([member]) is not supported "
+                    "in import files\n"),
                   filename, lineno);
          else
            {
              char cs;
-             char *file;
+             char *start;
 
              (void) obstack_finish (o);
-             keep = true;
-             imppath = s;
-             file = NULL;
-             while (! isspace ((unsigned char) *s) && *s != '(' && *s != '\0')
-               {
-                 if (*s == '/')
-                   file = s + 1;
-                 ++s;
-               }
-             if (file != NULL)
-               {
-                 file[-1] = '\0';
-                 impfile = file;
-                 if (imppath == file - 1)
-                   imppath = "/";
-               }
-             else
-               {
-                 impfile = imppath;
-                 imppath = "";
-               }
+             keep = TRUE;
+             start = s;
+             while (!ISSPACE (*s) && *s != '(' && *s != '\0')
+               ++s;
              cs = *s;
              *s = '\0';
-             while (isspace ((unsigned char) cs))
+             if (!bfd_xcoff_split_import_path (link_info.output_bfd,
+                                               start, &imppath, &impfile))
+               einfo (_("%F%P: could not parse import path: %E\n"));
+             while (ISSPACE (cs))
                {
                  ++s;
                  cs = *s;
@@ -1018,7 +1199,7 @@ gld${EMULATION_NAME}_read_file (filename, import)
                {
                  impmember = "";
                  if (cs != '\0')
-                   einfo ("%s:%d: warning: syntax error in import file\n",
+                   einfo (_("%P:%s:%d: warning: syntax error in import file\n"),
                           filename, lineno);
                }
              else
@@ -1030,7 +1211,7 @@ gld${EMULATION_NAME}_read_file (filename, import)
                  if (*s == ')')
                    *s = '\0';
                  else
-                   einfo ("%s:%d: warning: syntax error in import file\n",
+                   einfo (_("%P:%s:%d: warning: syntax error in import file\n"),
                           filename, lineno);
                }
            }
@@ -1038,14 +1219,14 @@ gld${EMULATION_NAME}_read_file (filename, import)
          continue;
        }
 
-      if (symbol_mode & ${SYMBOL_MODE_MASK})
+      if (symbol_mode & symbol_mode_mask)
        {
          /* This is a symbol to be imported or exported.  */
          symname = s;
-         syscall = false;
+         syscall_flag = 0;
          address = (bfd_vma) -1;
 
-         while (! isspace ((unsigned char) *s) && *s != '\0')
+         while (!ISSPACE (*s) && *s != '\0')
            ++s;
          if (*s != '\0')
            {
@@ -1053,46 +1234,38 @@ gld${EMULATION_NAME}_read_file (filename, import)
 
              *s++ = '\0';
 
-             while (isspace ((unsigned char) *s))
+             while (ISSPACE (*s))
                ++s;
 
              se = s;
-             while (! isspace ((unsigned char) *se) && *se != '\0')
+             while (!ISSPACE (*se) && *se != '\0')
                ++se;
              if (*se != '\0')
                {
                  *se++ = '\0';
-                 while (isspace ((unsigned char) *se))
+                 while (ISSPACE (*se))
                    ++se;
                  if (*se != '\0')
-                   einfo ("%s%d: warning: syntax error in import/export file\n",
+                   einfo (_("%P:%s%d: warning: syntax error in "
+                            "import/export file\n"),
                           filename, lineno);
                }
 
              if (s != se)
                {
                  int status;
-                 char *end;
+                 const char *end;
 
-                 status = is_syscall (s);
+                 status = is_syscall (s, &syscall_flag);
 
-                 switch (status)
+                 if (0 > status)
                    {
-                   case 1:
-                     /* this is a system call */
-                     syscall = true;
-                     break;
-
-                   case 0:
-                     /* ignore this system call */
-                     break;
-
-                   default:
                      /* not a system call, check for address */
-                     address = strtoul (s, &end, 0);
+                     address = bfd_scan_vma (s, &end, 0);
                      if (*end != '\0')
                        {
-                         einfo ("%s:%d: warning: syntax error in import/export file\n",
+                         einfo (_("%P:%s:%d: warning: syntax error in "
+                                  "import/export file\n"),
                                 filename, lineno);
 
                        }
@@ -1100,22 +1273,21 @@ gld${EMULATION_NAME}_read_file (filename, import)
                }
            }
 
-         if (! import)
+         if (!import)
            {
              struct export_symbol_list *n;
 
-             ldlang_add_undef (symname);
+             ldlang_add_undef (symname, TRUE);
              n = ((struct export_symbol_list *)
                   xmalloc (sizeof (struct export_symbol_list)));
              n->next = export_symbols;
              n->name = xstrdup (symname);
-             n->syscall = syscall;
              export_symbols = n;
            }
          else
            {
-             h = bfd_link_hash_lookup (link_info.hash, symname, false, false,
-                                       true);
+             h = bfd_link_hash_lookup (link_info.hash, symname, FALSE, FALSE,
+                                       TRUE);
              if (h == NULL || h->type == bfd_link_hash_new)
                {
                  /* We can just ignore attempts to import an unreferenced
@@ -1123,10 +1295,11 @@ gld${EMULATION_NAME}_read_file (filename, import)
                }
              else
                {
-                 if (! bfd_xcoff_import_symbol (output_bfd, &link_info, h,
-                                                address, imppath, impfile,
-                                                impmember))
-                   einfo ("%X%s:%d: failed to import symbol %s: %E\n",
+                 if (!bfd_xcoff_import_symbol (link_info.output_bfd,
+                                               &link_info, h,
+                                               address, imppath, impfile,
+                                               impmember, syscall_flag))
+                   einfo (_("%X%P:%s:%d: failed to import symbol %s: %E\n"),
                           filename, lineno, symname);
                }
            }
@@ -1136,23 +1309,24 @@ gld${EMULATION_NAME}_read_file (filename, import)
 
   if (obstack_object_size (o) > 0)
     {
-      einfo ("%s:%d: warning: ignoring unterminated last line\n",
+      einfo (_("%P:%s:%d: warning: ignoring unterminated last line\n"),
             filename, lineno);
       obstack_free (o, obstack_base (o));
     }
 
-  if (! keep)
+  if (!keep)
     {
       obstack_free (o, NULL);
       free (o);
     }
+
+  fclose (f);
 }
 
 /* This routine saves us from worrying about declaring free.  */
 
 static void
-gld${EMULATION_NAME}_free (p)
-     PTR p;
+gld${EMULATION_NAME}_free (void *p)
 {
   free (p);
 }
@@ -1162,8 +1336,7 @@ gld${EMULATION_NAME}_free (p)
    to symbols.  */
 
 static void
-gld${EMULATION_NAME}_find_relocs (s)
-     lang_statement_union_type *s;
+gld${EMULATION_NAME}_find_relocs (lang_statement_union_type *s)
 {
   if (s->header.type == lang_reloc_statement_enum)
     {
@@ -1171,9 +1344,10 @@ gld${EMULATION_NAME}_find_relocs (s)
 
       rs = &s->reloc_statement;
       if (rs->name == NULL)
-       einfo ("%F%P: only relocations against symbols are permitted\n");
-      if (! bfd_xcoff_link_count_reloc (output_bfd, &link_info, rs->name))
-       einfo ("%F%P: bfd_xcoff_link_count_reloc failed: %E\n");
+       einfo (_("%F%P: only relocations against symbols are permitted\n"));
+      if (!bfd_xcoff_link_count_reloc (link_info.output_bfd, &link_info,
+                                      rs->name))
+       einfo (_("%F%P: bfd_xcoff_link_count_reloc failed: %E\n"));
     }
 
   if (s->header.type == lang_assignment_statement_enum)
@@ -1183,25 +1357,26 @@ gld${EMULATION_NAME}_find_relocs (s)
 /* Look through an expression for an assignment statement.  */
 
 static void
-gld${EMULATION_NAME}_find_exp_assignment (exp)
-     etree_type *exp;
+gld${EMULATION_NAME}_find_exp_assignment (etree_type *exp)
 {
   struct bfd_link_hash_entry *h;
 
   switch (exp->type.node_class)
     {
     case etree_provide:
+    case etree_provided:
       h = bfd_link_hash_lookup (link_info.hash, exp->assign.dst,
-                               false, false, false);
+                               FALSE, FALSE, FALSE);
       if (h == NULL)
        break;
       /* Fall through.  */
     case etree_assign:
       if (strcmp (exp->assign.dst, ".") != 0)
        {
-         if (! bfd_xcoff_record_link_assignment (output_bfd, &link_info,
-                                                 exp->assign.dst))
-           einfo ("%P%F: failed to record assignment to %s: %E\n",
+         if (!bfd_xcoff_record_link_assignment (link_info.output_bfd,
+                                                &link_info,
+                                                exp->assign.dst))
+           einfo (_("%F%P: failed to record assignment to %s: %E\n"),
                   exp->assign.dst);
        }
       gld${EMULATION_NAME}_find_exp_assignment (exp->assign.src);
@@ -1228,45 +1403,44 @@ gld${EMULATION_NAME}_find_exp_assignment (exp)
 }
 
 static char *
-gld${EMULATION_NAME}_get_script (isfile)
-     int *isfile;
+gld${EMULATION_NAME}_get_script (int *isfile)
 EOF
 
-if test -n "$COMPILE_IN"
+if test x"$COMPILE_IN" = xyes
 then
 # Scripts compiled in.
 
 # sed commands to quote an ld script as a C string.
 sc="-f ${srcdir}/emultempl/ostring.sed"
 
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
 {
   *isfile = 0;
 
-  if (link_info.relocateable == true && config.build_constructors == true)
+  if (bfd_link_relocatable (&link_info) && config.build_constructors)
     return
 EOF
-sed $sc ldscripts/${EMULATION_NAME}.xu                     >> e${EMULATION_NAME}.c
-echo '  ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}.c
-sed $sc ldscripts/${EMULATION_NAME}.xr                     >> e${EMULATION_NAME}.c
-echo '  ; else if (!config.text_read_only) return'         >> e${EMULATION_NAME}.c
-sed $sc ldscripts/${EMULATION_NAME}.xbn                    >> e${EMULATION_NAME}.c
-echo '  ; else if (!config.magic_demand_paged) return'     >> e${EMULATION_NAME}.c
-sed $sc ldscripts/${EMULATION_NAME}.xn                     >> e${EMULATION_NAME}.c
-echo '  ; else return'                                     >> e${EMULATION_NAME}.c
-sed $sc ldscripts/${EMULATION_NAME}.x                      >> e${EMULATION_NAME}.c
-echo '; }'                                                 >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xu                >> e${EMULATION_NAME}.c
+echo '  ; else if (bfd_link_relocatable (&link_info)) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xr                >> e${EMULATION_NAME}.c
+echo '  ; else if (!config.text_read_only) return'     >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xbn                       >> e${EMULATION_NAME}.c
+echo '  ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xn                >> e${EMULATION_NAME}.c
+echo '  ; else return'                                >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.x                 >> e${EMULATION_NAME}.c
+echo '; }'                                            >> e${EMULATION_NAME}.c
 
 else
 # Scripts read from the filesystem.
 
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
 {
   *isfile = 1;
 
-  if (link_info.relocateable == true && config.build_constructors == true)
+  if (bfd_link_relocatable (&link_info) && config.build_constructors)
     return "ldscripts/${EMULATION_NAME}.xu";
-  else if (link_info.relocateable == true)
+  else if (bfd_link_relocatable (&link_info))
     return "ldscripts/${EMULATION_NAME}.xr";
   else if (!config.text_read_only)
     return "ldscripts/${EMULATION_NAME}.xbn";
@@ -1279,31 +1453,150 @@ EOF
 
 fi
 
-cat >>e${EMULATION_NAME}.c <<EOF
+fragment <<EOF
+
+static void
+gld${EMULATION_NAME}_create_output_section_statements (void)
+{
+  /* __rtinit */
+  if ((bfd_get_flavour (link_info.output_bfd) == bfd_target_xcoff_flavour)
+      && (link_info.init_function != NULL
+         || link_info.fini_function != NULL
+         || rtld))
+    {
+      initfini_file = lang_add_input_file ("initfini",
+                                          lang_input_file_is_file_enum,
+                                          NULL);
+
+      initfini_file->the_bfd = bfd_create ("initfini", link_info.output_bfd);
+      if (initfini_file->the_bfd == NULL
+         || ! bfd_set_arch_mach (initfini_file->the_bfd,
+                                 bfd_get_arch (link_info.output_bfd),
+                                 bfd_get_mach (link_info.output_bfd)))
+       {
+         einfo (_("%F%P: can not create BFD: %E\n"));
+         return;
+       }
+
+      /* Call backend to fill in the rest */
+      if (! bfd_xcoff_link_generate_rtinit (initfini_file->the_bfd,
+                                           link_info.init_function,
+                                           link_info.fini_function,
+                                           rtld))
+       {
+         einfo (_("%F%P: can not create BFD: %E\n"));
+         return;
+       }
+
+      /* __rtld defined in /lib/librtl.a */
+      if (rtld)
+       lang_add_input_file ("rtl", lang_input_file_is_l_enum, NULL);
+    }
+}
+
+static void
+gld${EMULATION_NAME}_set_output_arch (void)
+{
+  bfd_set_arch_mach (link_info.output_bfd,
+                    bfd_xcoff_architecture (link_info.output_bfd),
+                    bfd_xcoff_machine (link_info.output_bfd));
+
+  ldfile_output_architecture = bfd_get_arch (link_info.output_bfd);
+  ldfile_output_machine = bfd_get_mach (link_info.output_bfd);
+  ldfile_output_machine_name = bfd_printable_name (link_info.output_bfd);
+}
 
-struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
+static bfd_boolean
+gld${EMULATION_NAME}_open_dynamic_archive (const char *arch,
+                                          search_dirs_type *search,
+                                          lang_input_statement_type *entry)
 {
+  char *path;
+
+  if (!entry->flags.maybe_archive)
+    return FALSE;
+
+  if (entry->flags.full_name_provided)
+    path = concat (search->name, "/", entry->filename,
+                  (const char *) NULL);
+  else
+    path = concat (search->name, "/lib", entry->filename, arch, ".a",
+                  (const char *) NULL);
+
+  if (!ldfile_try_open_bfd (path, entry))
+    {
+      free (path);
+      return FALSE;
+    }
+  /* Don't include the searched directory in the import path.  */
+  bfd_xcoff_set_archive_import_path (&link_info, entry->the_bfd,
+                                    path + strlen (search->name) + 1);
+  entry->filename = path;
+  return TRUE;
+}
+
+static bfd_boolean
+gld${EMULATION_NAME}_print_symbol (struct bfd_link_hash_entry *hash_entry,
+                                  void *ptr)
+{
+  asection *sec = (asection *) ptr;
+
+  if ((hash_entry->type == bfd_link_hash_defined
+       || hash_entry->type == bfd_link_hash_defweak)
+      && sec == hash_entry->u.def.section)
+    {
+      int i;
+      struct xcoff_link_hash_entry *h;
+
+      for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++)
+       print_space ();
+      minfo ("0x%V   ",
+            (hash_entry->u.def.value
+             + hash_entry->u.def.section->output_offset
+             + hash_entry->u.def.section->output_section->vma));
+
+      /* Flag symbol if it has been garbage collected.  */
+      h = (struct xcoff_link_hash_entry *) hash_entry;
+      if ((h != NULL) && !(h->flags & XCOFF_MARK))
+       minfo (" -->gc");
+      minfo ("             %pT\n", hash_entry->root.string);
+    }
+
+  return TRUE;
+}
+
+struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = {
   gld${EMULATION_NAME}_before_parse,
   syslib_default,
   hll_default,
   after_parse_default,
   gld${EMULATION_NAME}_after_open,
+  after_check_relocs_default,
+  before_place_orphans_default,
   after_allocation_default,
-  set_output_arch_default,
-  ldemul_default_target,
+  gld${EMULATION_NAME}_set_output_arch,
+  gld${EMULATION_NAME}_choose_target,
   gld${EMULATION_NAME}_before_allocation,
   gld${EMULATION_NAME}_get_script,
   "${EMULATION_NAME}",
   "${OUTPUT_FORMAT}",
-  0,   /* finish */
-  0,   /* create_output_section_statements */
-  0,   /* open_dynamic_archive */
-  0,   /* place_orphan */
-  0,   /* set_symbols */
+  finish_default,
+  gld${EMULATION_NAME}_create_output_section_statements,
+  gld${EMULATION_NAME}_open_dynamic_archive,
+  0,                           /* place_orphan */
+  0,                           /* set_symbols */
   gld${EMULATION_NAME}_parse_args,
+  gld${EMULATION_NAME}_add_options,
+  gld${EMULATION_NAME}_handle_option,
   gld${EMULATION_NAME}_unrecognized_file,
-  NULL, /* list_options */
-  NULL, /* recognized_file */
-  NULL, /* find potential_libraries */
+  NULL,                                /* list_options */
+  NULL,                                /* recognized_file */
+  NULL,                                /* find potential_libraries */
+  NULL,                                /* new_vers_pattern */
+  NULL,                                /* extra_map_file_text */
+  ${LDEMUL_EMIT_CTF_EARLY-NULL},
+  ${LDEMUL_ACQUIRE_STRINGS_FOR_CTF-NULL},
+  ${LDEMUL_NEW_DYNSYM_FOR_CTF-NULL},
+  gld${EMULATION_NAME}_print_symbol
 };
 EOF