* ldlang.c (record_bfd_errors): Remove.
[binutils-gdb.git] / ld / emultempl / aix.em
index dd81b5f744ca2279a5b1cd2c9f5f08423801590d..9b037a0d63215b8f79530f61af92f74c995cb121 100644 (file)
@@ -1,12 +1,19 @@
 # This shell script emits a C file. -*- C -*-
 # It does some substitutions.
+if [ -z "$MACHINE" ]; then
+  OUTPUT_ARCH=${ARCH}
+else
+  OUTPUT_ARCH=${ARCH}:${MACHINE}
+fi
 cat >e${EMULATION_NAME}.c <<EOF
 /* This file is is generated by a shell script.  DO NOT EDIT! */
 
 /* AIX emulation code for ${EMULATION_NAME}
-   Copyright (C) 1991, 93, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
+   Copyright 1991, 1993, 1995, 1996, 1997, 1998, 2000, 2001
+   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.
 
@@ -45,6 +52,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "ldctor.h"
 #include "ldgram.h"
 
+#include "coff/internal.h"
+#include "coff/xcoff.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));
@@ -101,15 +111,35 @@ struct export_symbol_list
 
 static struct export_symbol_list *export_symbols;
 
+/* Maintains the 32 or 64 bit mode state of import file */
+static unsigned int symbol_mode = 0x04;
+
 /* This routine is called before anything else is done.  */
 
 static void
 gld${EMULATION_NAME}_before_parse()
 {
 #ifndef TARGET_                        /* I.e., if not generic.  */
-  ldfile_output_architecture = bfd_arch_${ARCH};
+  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.
+   */ 
+  link_info.init_function = NULL;
+  link_info.fini_function = NULL;
+
 }
 
 /* Handle AIX specific options.  */
@@ -124,27 +154,81 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
   int indx;
   int longind;
   int optc;
-  long val;
+  bfd_signed_vma val;
   char *end;
 
-#define OPTION_IGNORE (300)
-#define OPTION_AUTOIMP (OPTION_IGNORE + 1)
-#define OPTION_ERNOTOK (OPTION_AUTOIMP + 1)
-#define OPTION_EROK (OPTION_ERNOTOK + 1)
-#define OPTION_EXPORT (OPTION_EROK + 1)
-#define OPTION_IMPORT (OPTION_EXPORT + 1)
-#define OPTION_LOADMAP (OPTION_IMPORT + 1)
-#define OPTION_MAXDATA (OPTION_LOADMAP + 1)
-#define OPTION_MAXSTACK (OPTION_MAXDATA + 1)
-#define OPTION_MODTYPE (OPTION_MAXSTACK + 1)
-#define OPTION_NOAUTOIMP (OPTION_MODTYPE + 1)
-#define OPTION_NOSTRCMPCT (OPTION_NOAUTOIMP + 1)
-#define OPTION_PD (OPTION_NOSTRCMPCT + 1)
-#define OPTION_PT (OPTION_PD + 1)
-#define OPTION_STRCMPCT (OPTION_PT + 1)
-#define OPTION_UNIX (OPTION_STRCMPCT + 1)
-
-  static struct option longopts[] = {
+  enum {
+    OPTION_IGNORE = 300,
+    OPTION_AUTOIMP, 
+    OPTION_ERNOTOK, 
+    OPTION_EROK, 
+    OPTION_EXPORT, 
+    OPTION_IMPORT, 
+    OPTION_INITFINI, 
+    OPTION_LOADMAP, 
+    OPTION_MAXDATA, 
+    OPTION_MAXSTACK, 
+    OPTION_MODTYPE, 
+    OPTION_NOAUTOIMP, 
+    OPTION_NOSTRCMPCT, 
+    OPTION_PD, 
+    OPTION_PT, 
+    OPTION_STRCMPCT, 
+    OPTION_UNIX
+  };
+
+  /*
+    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[] = {
     {"basis", no_argument, NULL, OPTION_IGNORE},
     {"bautoimp", no_argument, NULL, OPTION_AUTOIMP},
     {"bcomprld", no_argument, NULL, OPTION_IGNORE},
@@ -162,6 +246,7 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
     {"bhalt", required_argument, NULL, OPTION_IGNORE},
     {"bI", required_argument, NULL, OPTION_IMPORT},
     {"bimport", required_argument, NULL, OPTION_IMPORT},
+    {"binitfini", required_argument, NULL, OPTION_INITFINI},
     {"bl", required_argument, NULL, OPTION_LOADMAP},
     {"bloadmap", required_argument, NULL, OPTION_LOADMAP},
     {"bmaxdata", required_argument, NULL, OPTION_MAXDATA},
@@ -183,6 +268,7 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
     {"bso", no_argument, NULL, OPTION_AUTOIMP},
     {"bstrcmpct", no_argument, NULL, OPTION_STRCMPCT},
     {"btextro", no_argument, &textro, 1},
+    {"b64", no_argument, NULL, 0},
     {"static", no_argument, NULL, OPTION_NOAUTOIMP},
     {"unix", no_argument, NULL, OPTION_UNIX},
     {NULL, no_argument, NULL, 0}
@@ -201,21 +287,21 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
      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)
+  if (indx == 0) {
     indx = 1;
-  if (indx < argc && strncmp (argv[indx], "-b", 2) == 0)
-    {
-      char *s;
-
-      for (s = argv[indx]; *s != '\0'; s++)
-       {
-         if (*s == ':')
-           {
-             *s = '=';
-             break;
-           }
-       }
+  }
+
+  if (indx < argc && strncmp (argv[indx], "-b", 2) == 0) {
+    char *s;
+    
+    for (s = argv[indx]; *s != '\0'; s++) {
+      if (*s == ':') {
+       *s = '=';
+       break;
+      }
     }
+  }
+
 
   /* 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.  */
@@ -237,7 +323,7 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
       break;
 
     case 'D':
-      val = strtol (optarg, &end, 0);
+      val = strtoll (optarg, &end, 0);
       if (*end != '\0')
        einfo ("%P: warning: ignoring invalid -D number %s\n", optarg);
       else if (val != -1)
@@ -264,7 +350,7 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
          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 = strtoul (optarg, &end, 0);
+      val = strtoull (optarg, &end, 0);
       if (*end != '\0')
        {
          optind = prevoptind;
@@ -276,6 +362,41 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
     case OPTION_IGNORE:
       break;
 
+    case OPTION_INITFINI: {
+      /* 
+       * The aix linker init fini has the format :
+       *
+       * -binitfini:[ Initial][:Termination][:Priority]
+       *
+       * it allows the Termination and Priority to be optional.
+       *
+       * Since we support only one init/fini pair, we ignore the Priority.
+       * 
+       * Define the special symbol __rtinit.
+       *
+       * strtok does not correctly handle the case of -binitfini::fini: so
+       * do it by hand
+       */
+      char *t, *i, *f;
+
+      i = t = optarg;
+      while (*t && ':' != *t) t++;
+      if (*t) *t++ = 0;
+
+      if (0 != strlen(i)) {
+       link_info.init_function = i;
+      }
+
+      f = t;
+      while (*t && ':' != *t) t++;
+      *t = 0;
+
+      if (0 != strlen(f)) {
+       link_info.fini_function = f;
+      }
+    }
+    break;
+
     case OPTION_AUTOIMP:
       link_info.static_link = false;
       break;
@@ -312,7 +433,7 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
       break;
 
     case OPTION_MAXDATA:
-      val = strtoul (optarg, &end, 0);
+      val = strtoull (optarg, &end, 0);
       if (*end != '\0')
        einfo ("%P: warning: ignoring invalid -bmaxdata number %s\n",
               optarg);
@@ -321,7 +442,7 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
       break;
 
     case OPTION_MAXSTACK:
-      val = strtoul (optarg, &end, 0);
+      val = strtoull (optarg, &end, 0);
       if (*end != '\0')
        einfo ("%P: warning: ignoring invalid -bmaxstack number %s\n",
               optarg);
@@ -354,7 +475,7 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
          start on.  The offset within the page should still be the
          offset within the file, so we need to build an appropriate
          expression.  */
-      val = strtoul (optarg, &end, 0);
+      val = strtoull (optarg, &end, 0);
       if (*end != '\0')
        einfo ("%P: warning: ignoring invalid -pD number %s\n", optarg);
       else
@@ -377,7 +498,7 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
       /* 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 = strtoul (optarg, &end, 0);
+      val = strtoull (optarg, &end, 0);
       if (*end != '\0')
        einfo ("%P: warning: ignoring invalid -pT number %s\n", optarg);
       else
@@ -498,22 +619,21 @@ gld${EMULATION_NAME}_before_allocation ()
   struct filelist *fl;
   struct export_symbol_list *el;
   char *libpath;
-  asection *special_sections[6];
+  asection *special_sections[XCOFF_NUMBER_OF_SPECIAL_SECTIONS];
   int i;
 
   /* 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);
-  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);
-      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");
-    }
+  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);
+    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");
+  }
 
   /* Track down all relocations called for by the linker script (these
      are typically constructor/destructor entries created by
@@ -561,109 +681,186 @@ gld${EMULATION_NAME}_before_allocation ()
 
   /* Look through the special sections, and put them in the right
      place in the link ordering.  This is especially magic.  */
-  for (i = 0; i < 6; i++)
-    {
-      asection *sec;
-      lang_output_section_statement_type *os;
-      lang_statement_union_type **pls;
-      lang_input_section_type *is;
-      const char *oname;
-      boolean start;
-
-      sec = special_sections[i];
-      if (sec == NULL)
-       continue;
+  for (i = 0; i < XCOFF_NUMBER_OF_SPECIAL_SECTIONS; i++) {
+    asection *sec;
+    lang_output_section_statement_type *os;
+    lang_statement_union_type **pls;
+    lang_input_section_type *is;
+    const char *oname;
+    boolean start;
+
+    sec = special_sections[i];
+    if (sec == NULL)
+      continue;
+
+    /* 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",
+            sec->output_section->name);
+    }
 
-      /* 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",
-              sec->output_section->name);
-      for (pls = &os->children.head; *pls != NULL; pls = &(*pls)->next)
-       {
-         if ((*pls)->header.type == lang_input_section_enum
-             && (*pls)->input_section.section == sec)
-           {
-             is = (lang_input_section_type *) *pls;
-             *pls = (*pls)->next;
+    for (pls = &os->children.head; *pls != NULL; pls = &(*pls)->next) {
+
+      if ((*pls)->header.type == lang_input_section_enum && 
+         (*pls)->input_section.section == sec) {
+       is = (lang_input_section_type *) *pls;
+       *pls = (*pls)->next;
+       break;
+      }
+       
+      if ((*pls)->header.type == lang_wild_statement_enum) {
+       lang_statement_union_type **pwls;
+       
+       for (pwls = &(*pls)->wild_statement.children.head;
+            *pwls != NULL;
+            pwls = &(*pwls)->next) {
+
+         if ((*pwls)->header.type == lang_input_section_enum && 
+             (*pwls)->input_section.section == sec) {
+
+             is = (lang_input_section_type *) *pwls;
+             *pwls = (*pwls)->next;
              break;
-           }
-         if ((*pls)->header.type == lang_wild_statement_enum)
-           {
-             lang_statement_union_type **pwls;
+         }
+       }
+       
+       if (is != NULL)
+         break;
+      }
+    }  
 
-             for (pwls = &(*pls)->wild_statement.children.head;
-                  *pwls != NULL;
-                  pwls = &(*pwls)->next)
-               {
-                 if ((*pwls)->header.type == lang_input_section_enum
-                     && (*pwls)->input_section.section == sec)
-                   {
-                     is = (lang_input_section_type *) *pwls;
-                     *pwls = (*pwls)->next;
-                     break;
-                   }
-               }
-             if (is != NULL)
-               break;
-           }
-       }       
+    if (is == NULL) {
+      einfo ("%P%F: can't find %s in output section\n",
+            bfd_get_section_name (sec->owner, sec));
+    }
+     
+    /* Now figure out where the section should go.  */
+    switch (i) {
+
+    default: /* to avoid warnings */
+    case XCOFF_SPECIAL_SECTION_TEXT:
+      /* _text */
+      oname = ".text";
+      start = true;
+      break;
+    
+    case XCOFF_SPECIAL_SECTION_ETEXT:
+      /* _etext */
+      oname = ".text";
+      start = false;
+      break;
 
-      if (is == NULL)
-       einfo ("%P%F: can't find %s in output section\n",
-              bfd_get_section_name (sec->owner, sec));
+    case XCOFF_SPECIAL_SECTION_DATA:
+      /* _data */
+      oname = ".data";
+      start = true;
+      break;
+    
+    case XCOFF_SPECIAL_SECTION_EDATA:
+      /* _edata */
+      oname = ".data";
+      start = false;
+      break;
 
-      /* Now figure out where the section should go.  */
-      switch (i)
-       {
-       default: /* to avoid warnings */
-       case 0:
-         /* _text */
-         oname = ".text";
-         start = true;
-         break;
-       case 1:
-         /* _etext */
-         oname = ".text";
-         start = false;
-         break;
-       case 2:
-         /* _data */
-         oname = ".data";
-         start = true;
-         break;
-       case 3:
-         /* _edata */
-         oname = ".data";
-         start = false;
-         break;
-       case 4:
-       case 5:
-         /* _end and end */
-         oname = ".bss";
-         start = false;
-         break;
-       }
+    case XCOFF_SPECIAL_SECTION_END:
+    case XCOFF_SPECIAL_SECTION_END2:
+      /* _end and end */
+      oname = ".bss";
+      start = false;
+      break;
+    }
 
-      os = lang_output_section_find (oname);
+    os = lang_output_section_find (oname);
 
-      if (start)
-       {
-         is->header.next = os->children.head;
-         os->children.head = (lang_statement_union_type *) is;
-       }
-      else
-       {
-         is->header.next = NULL;
-         lang_statement_append (&os->children,
-                                (lang_statement_union_type *) is,
-                                &is->header.next);
-       }
+    if (start) {
+      is->header.next = os->children.head;
+      os->children.head = (lang_statement_union_type *) is;
+    } else {
+      is->header.next = NULL;
+      lang_statement_append (&os->children,
+                            (lang_statement_union_type *) is,
+                            &is->header.next);
+    }
+  }
+}
+
+static int change_symbol_mode (char *input) 
+{
+  /*
+   * 1 : state changed
+   * 0 : no change
+   */
+
+  char *symbol_mode_string[] = {
+    "# 32",   /* 0x01 */
+    "# 64",   /* 0x02 */
+    "# no32", /* 0x04 */
+    "# no64", /* 0x08 */
+    NULL,
+  };
+  unsigned int bit;
+  char *string;
+
+  for (bit = 0; ; bit++) {
+    string = symbol_mode_string[bit];
+    if (NULL == string)
+      return 0;
+    
+    if (0 == strcmp(input, string)) {
+      symbol_mode = (1 << bit);
+      return 1;
+    }
+  }
+  /* should not be here */
+  return 0;
+}
+
+
+static int is_syscall(char *input)
+{
+  /*
+   * 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
+  };
+
+  for (bit = 0; ;bit++) {
+    
+    string = syscall_string[bit];
+    if (NULL == string) {
+      return -1;
     }
+
+    if (0 == strcmp(input, string)) {
+      if (1 << bit & ${SYSCALL_MASK}) {
+       return 1;
+      } else {
+       return 0;
+      }
+    }
+  }
+  /* should not be here */
+  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.  */
@@ -699,6 +896,15 @@ gld${EMULATION_NAME}_read_file (filename, import)
   impmember = NULL;
 
   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.
+   */
+  symbol_mode = 0x04;
+
   while ((c = getc (f)) != EOF)
     {
       char *s;
@@ -719,10 +925,11 @@ gld${EMULATION_NAME}_read_file (filename, import)
       s = (char *) obstack_base (o);
       while (isspace ((unsigned char) *s))
        ++s;
-      if (*s == '\0'
-         || *s == '*'
-         || (*s == '#' && s[1] == ' ')
-         || (! import && *s == '#' && s[1] == '!'))
+      if (*s == '\0'  || 
+         *s == '*' ||
+         change_symbol_mode (s) ||
+         (*s == '#' && s[1] == ' ') ||
+         (! import && *s == '#' && s[1] == '!'))
        {
          obstack_free (o, obstack_base (o));
          continue;
@@ -801,100 +1008,111 @@ gld${EMULATION_NAME}_read_file (filename, import)
          continue;
        }
 
-      /* This is a symbol to be imported or exported.  */
-      symname = s;
-      syscall = false;
-      address = (bfd_vma) -1;
-
-      while (! isspace ((unsigned char) *s) && *s != '\0')
-       ++s;
-      if (*s != '\0')
-       {
-         char *se;
-
-         *s++ = '\0';
-
-         while (isspace ((unsigned char) *s))
-           ++s;
-
-         se = s;
-         while (! isspace ((unsigned char) *se) && *se != '\0')
-           ++se;
-         if (*se != '\0')
-           {
-             *se++ = '\0';
-             while (isspace ((unsigned char) *se))
-               ++se;
-             if (*se != '\0')
-               einfo ("%s%d: warning: syntax error in import/export file\n",
-                      filename, lineno);
-           }
-
-         if (s == se)
-           {
-             /* There was no address after all.  */
-           }
-         else if (strcasecmp (s, "svc") == 0
-                  || strcasecmp (s, "syscall") == 0)
-           syscall = true;
-         else
-           {
+      if (symbol_mode & ${SYMBOL_MODE_MASK}) { 
+
+       /* This is a symbol to be imported or exported.  */
+       symname = s;
+       syscall = false;
+       address = (bfd_vma) -1;
+
+       while (! isspace ((unsigned char) *s) && *s != '\0')
+         ++s;
+       if (*s != '\0')
+         {
+           char *se;
+           
+           *s++ = '\0';
+
+           while (isspace ((unsigned char) *s))
+             ++s;
+
+           se = s;
+           while (! isspace ((unsigned char) *se) && *se != '\0')
+             ++se;
+           if (*se != '\0')
+             {
+               *se++ = '\0';
+               while (isspace ((unsigned char) *se))
+                 ++se;
+               if (*se != '\0')
+                 einfo ("%s%d: warning: syntax error in import/export file\n",
+                        filename, lineno);
+             }
+
+           if (s != se) {
+             int status;
              char *end;
-
-             address = strtoul (s, &end, 0);
-             if (*end != '\0')
-               einfo ("%s:%d: warning: syntax error in import/export file\n",
-                      filename, lineno);
-           }
-       }
-
-      if (! import)
-       {
-         struct export_symbol_list *n;
-
-         ldlang_add_undef (symname);
-         n = ((struct export_symbol_list *)
-              xmalloc (sizeof (struct export_symbol_list)));
-         n->next = export_symbols;
-         n->name = buystring (symname);
-         n->syscall = syscall;
-         export_symbols = n;
-       }
-      else
-       {
-         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
-                symbol.  */
-           }
-         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",
-                      filename, lineno, symname);
+                         
+             status = is_syscall(s);
+                         
+             switch (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);
+               if (*end != '\0') {
+                 einfo ("%s:%d: warning: syntax error in import/export file\n", filename, lineno);
+                        
+               }
+             }
            }
-       }
-
+         }
+
+       if (! import)
+         {
+           struct export_symbol_list *n;
+
+           ldlang_add_undef (symname);
+           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);
+           if (h == NULL || h->type == bfd_link_hash_new)
+             {
+               /* We can just ignore attempts to import an unreferenced
+                  symbol.  */
+             }
+           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",
+                        filename, lineno, symname);
+             }
+         }
+      }
       obstack_free (o, obstack_base (o));
     }
-
+  
   if (obstack_object_size (o) > 0)
     {
-      einfo ("%s:%d: warning: ignoring unterminated last line\n",
-            filename, lineno);
-      obstack_free (o, obstack_base (o));
-    }
+         einfo ("%s:%d: warning: ignoring unterminated last line\n",
+                filename, lineno);
+         obstack_free (o, obstack_base (o));
+       }
 
-  if (! keep)
-    {
-      obstack_free (o, NULL);
-      free (o);
+      if (! keep)
+       {
+         obstack_free (o, NULL);
+         free (o);
+       }
     }
-}
 
 /* This routine saves us from worrying about declaring free.  */
 
@@ -985,7 +1203,7 @@ then
 # Scripts compiled in.
 
 # sed commands to quote an ld script as a C string.
-sc="-f stringify.sed"
+sc="-f ${srcdir}/emultempl/ostring.sed"
 
 cat >>e${EMULATION_NAME}.c <<EOF
 {                           
@@ -1050,6 +1268,8 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   0,   /* set_symbols */
   gld${EMULATION_NAME}_parse_args,
   gld${EMULATION_NAME}_unrecognized_file,
-  NULL         /* find_potential_libraries */
+  NULL, /* list_options */
+  NULL, /* recognized_file */
+  NULL, /* find potential_libraries */
 };
 EOF