Support for xcoff64
authorTom Rix <trix@redhat.com>
Thu, 24 May 2001 20:59:23 +0000 (20:59 +0000)
committerTom Rix <trix@redhat.com>
Thu, 24 May 2001 20:59:23 +0000 (20:59 +0000)
ld/ChangeLog
ld/Makefile.am
ld/Makefile.in
ld/configure.tgt
ld/emulparams/aixppc.sh
ld/emulparams/aixppc64.sh [new file with mode: 0644]
ld/emultempl/aix.em
ld/emultempl/stringify.sed [new file with mode: 0644]
ld/scripttempl/aix.sc

index 80be489005d21700c333658f8b2b9959b42022bb..7a9025e025e56ef60aac01d46d9f0067795fe57c 100644 (file)
@@ -1,3 +1,34 @@
+2001-05-24 Tom Rix <trix@redhat.com>
+
+       * emultempl/aix.em : (gld${EMULATION_NAME}_read_file) 
+       udate import file format.
+       (change_symbol_mode) New, same
+       (is_syscall) New, same
+       * emulparams/aixppc.sh : add SYSCALL_MASK and SYMBOL_MODE_MASK
+       * emulparams/aixppc64.sh : same
+       * emulparams/aixrs6.sh : same
+       * emulparams/ppcmacos.sh : same
+       * emultempl/aix.em : use strtoull to parse options
+       * Makefile.am : add eaixppc64 emulation for xcoff64
+       * Makefile.in : same
+       * configure.tgt : same
+
+       * scripttempl/aix.sc : default text section offset to 0x10000000
+        default data section offset to 0x20000000
+       add .sv3264 and .sv64 pseudo sections
+       loader and debug sections use the currect section offset. 
+
+       * emultempl/aix.em : Add xcoff64 support
+       Add -binitfini support
+       (gld${EMULATION_NAME}_before_parse) -binitfini 
+       (gld${EMULATION_NAME}_parse_args) same
+       (gld${EMULATION_NAME}_before_allocation) format change for special 
+       sections
+
+       * emulparams/aixppc64.sh : New file for xcoff64 support
+       
+2000-01-18  H.J. Lu  <hjl@gnu.org>
+
 2001-05-23  Alexandre Oliva  <aoliva@redhat.com>
 
        * emultempl/elf32.em (ELF_INTERPRETER_SET_DEFAULT): Use this new
index 75755dff7a8a910aedad44ec03c41ddf70a791cb..ef08348867a710522844421ba721dae41ab2eeb8 100644 (file)
@@ -261,7 +261,8 @@ ALL_64_EMULATIONS = \
        eelf64bmip.o \
        eelf64btsmip.o \
        eelf64ltsmip.o \
-       eelf64hppa.o
+       eelf64hppa.o \
+       eaixppc64.o
 
 ALL_EMUL_EXTRA_OFILES = \
        deffilep.o \
@@ -324,6 +325,9 @@ GEN_DEPENDS = $(srcdir)/genscripts.sh stringify.sed
 ea29k.c: $(srcdir)/emulparams/a29k.sh \
   $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/a29k.sc ${GEN_DEPENDS}
        ${GENSCRIPTS} a29k "$(tdir_a29k)"
+eaixppc64.c: $(srcdir)/emulparams/aixppc64.sh \
+  $(srcdir)/emultempl/aix.em $(srcdir)/scripttempl/aix.sc ${GEN_DEPENDS}
+       ${GENSCRIPTS} aixppc64 "$(tdir_aixppc64)"
 eaixppc.c: $(srcdir)/emulparams/aixppc.sh \
   $(srcdir)/emultempl/aix.em $(srcdir)/scripttempl/aix.sc ${GEN_DEPENDS}
        ${GENSCRIPTS} aixppc "$(tdir_aixppc)"
index b71ed5bbf259d2f60e5da7640e188164622a2946..a8a215b7364a5991ee90ef72dbfadcd6aa0f1d1c 100644 (file)
@@ -387,6 +387,7 @@ HFILES = ld.h ldctor.h ldemul.h ldexp.h ldfile.h \
        ldlang.h ldlex.h ldmain.h ldmisc.h ldver.h \
        ldwrite.h mri.h deffile.h pe-dll.h
 
+ALL_64_EMULATIONS =    eaixppc64.o     eelf64_aix.o    eelf64_ia64.o   eelf_x86_64.o   eelf64_s390.o   eelf64_sparc.o  eelf64alpha.o   eelf64bmip.o    eelf64btsmip.o  eelf64ltsmip.o  eelf64hppa.o
 
 GENERATED_CFILES = ldgram.c ldlex.c deffilep.c
 GENERATED_HFILES = ldgram.h ldemul-list.h deffilep.h
@@ -1038,6 +1039,9 @@ stringify.sed: ${srcdir}/emultempl/$(STRINGIFY)
 ea29k.c: $(srcdir)/emulparams/a29k.sh \
   $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/a29k.sc ${GEN_DEPENDS}
        ${GENSCRIPTS} a29k "$(tdir_a29k)"
+eaixppc64.c: $(srcdir)/emulparams/aixppc64.sh \
+  $(srcdir)/emultempl/aix.em $(srcdir)/scripttempl/aix.sc ${GEN_DEPENDS}
+       ${GENSCRIPTS} aixppc64 "$(tdir_aixppc64)"
 eaixppc.c: $(srcdir)/emulparams/aixppc.sh \
   $(srcdir)/emultempl/aix.em $(srcdir)/scripttempl/aix.sc ${GEN_DEPENDS}
        ${GENSCRIPTS} aixppc "$(tdir_aixppc)"
index f2736858bb8b248bcb40f270040e3edf49d54911..120f83234e6b656bfba339942b043c12406b6bcd 100644 (file)
@@ -332,8 +332,12 @@ powerpc-*-macos*)  targ_emul=ppcmacos ;;
 powerpc-*-netware*)    targ_emul=ppcnw ;;
 powerpcle-*-pe)         targ_emul=ppcpe ;;
 powerpcle-*-winnt*)     targ_emul=ppcpe ;;
-powerpcle-*-cygwin*)   targ_emul=ppcpe ;;
-powerpc-*-aix*)                targ_emul=aixppc ;;
+powerpcle-*-cygwin*)    targ_emul=ppcpe ;;
+
+powerpc-*-aix*)                targ_emul=aixppc 
+                       targ_extra_emuls="aixppc64"     
+                       tdir_aixppc64=${targ_alias}
+                       ;;
 powerpc-*-beos*)       targ_emul=aixppc ;;
 rs6000-*-aix*)         targ_emul=aixrs6 ;;
 tic30-*-*aout*)                targ_emul=tic30aout ;;
index f92e686dd6d9a7bf7ab488d9ee73dc0917746a35..b8abe2b2c0d18bdcabfaf7e12dd2a592a107efe8 100644 (file)
@@ -2,3 +2,5 @@ TEMPLATE_NAME=aix
 SCRIPT_NAME=aix
 OUTPUT_FORMAT="aixcoff-rs6000"
 ARCH=powerpc
+SYSCALL_MASK=0x77
+SYMBOL_MODE_MASK=0x0d
diff --git a/ld/emulparams/aixppc64.sh b/ld/emulparams/aixppc64.sh
new file mode 100644 (file)
index 0000000..2246e3e
--- /dev/null
@@ -0,0 +1,14 @@
+TEMPLATE_NAME=aix
+SCRIPT_NAME=aix
+OUTPUT_FORMAT="aixcoff64-rs6000"
+ARCH=powerpc
+SYSCALL_MASK=0xcc
+SYMBOL_MODE_MASK=0x0e
+#
+# This script is called by genscripts.sh.  genscripts does not produce the
+# the correct lib search path for the aixppc64 because the default emulation
+# is aixppc. Aix libs can have 32 bit and 64 bit objects in them so it is 
+# ok for both the aixppc and aixppc64 linkers to look at the same place.
+# $libdir is defined in genscripts.sh before aixppc64.sh is sourced in
+# so it will be valid.
+LIB_PATH="/lib:/usr/lib:$libdir:/usr/local/lib"
index 0dc332b22eaf23e0440b562aa68d5a06d4987c49..88d13b29c7f65523129c3c8af325070f56632df4 100644 (file)
@@ -4,10 +4,10 @@ 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 1991, 1993, 1995, 1996, 1997, 1998, 2000
-   Free Software Foundation, Inc.
+   Copyright (C) 1991, 93, 95, 96, 97, 1998 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.
 
@@ -38,14 +38,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "ld.h"
 #include "ldmain.h"
+#include "ldemul.h"
+#include "ldfile.h"
 #include "ldmisc.h"
 #include "ldexp.h"
 #include "ldlang.h"
-#include "ldfile.h"
-#include "ldemul.h"
 #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));
@@ -102,6 +105,9 @@ 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
@@ -111,6 +117,15 @@ gld${EMULATION_NAME}_before_parse()
   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.  */
@@ -125,27 +140,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},
@@ -163,6 +232,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},
@@ -184,6 +254,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}
@@ -202,21 +273,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.  */
@@ -238,7 +309,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)
@@ -265,7 +336,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;
@@ -277,6 +348,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;
@@ -313,7 +419,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);
@@ -322,7 +428,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);
@@ -355,7 +461,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
@@ -378,7 +484,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
@@ -499,22 +605,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
@@ -562,109 +667,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.  */
@@ -700,6 +882,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;
@@ -720,10 +911,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;
@@ -802,100 +994,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 = 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);
+                         
+             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.  */
 
@@ -986,7 +1189,7 @@ then
 # Scripts compiled in.
 
 # sed commands to quote an ld script as a C string.
-sc="-f stringify.sed"
+sc="-f ${srcdir}/emultempl/stringify.sed"
 
 cat >>e${EMULATION_NAME}.c <<EOF
 {                           
@@ -1051,6 +1254,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
diff --git a/ld/emultempl/stringify.sed b/ld/emultempl/stringify.sed
new file mode 100644 (file)
index 0000000..a526d3f
--- /dev/null
@@ -0,0 +1,4 @@
+s/["\\]/\\&/g
+s/$/\\n\\/
+1 s/^/"/
+$ s/$/n"/
index 3f4b61759068b23f33ddb765286d6ec3ac4ff40a..207decdd47f96d7f0d6f282934dd82bfb14d2216 100644 (file)
@@ -10,6 +10,8 @@ ENTRY(__start)
 SECTIONS
 {
   .pad 0 : { *(.pad) }
+
+  . = 0x10000000;
   .text ${RELOCATING-0} : {
     ${RELOCATING+PROVIDE (_text = .);}
     *(.text)
@@ -22,11 +24,14 @@ SECTIONS
     *(.tb)
     ${RELOCATING+PROVIDE (_etext = .);}
   }
-  .data 0 : {
+  . = 0x20000000;
+  .data . : {
     ${RELOCATING+PROVIDE (_data = .);}
     *(.data)
     *(.rw)
     *(.sv)
+    *(.sv64)
+    *(.sv3264)
     *(.ua)
     . = ALIGN(4);
     ${CONSTRUCTING+CONSTRUCTORS}
@@ -45,10 +50,12 @@ SECTIONS
     ${RELOCATING+PROVIDE (_end = .);}
     ${RELOCATING+PROVIDE (end = .);}
   }
-  .loader 0 : {
+
+  .loader : {
     *(.loader)
   }
-  .debug 0 : {
+  
+  .debug : {
     *(.debug)
   }
 }