This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

xcoff64 ld-emultempl-aix.em.patch



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

----------------------------------------------------------------------------
--

diff -rcp sources-original/src/ld/emultempl/aix.em
sources/src/ld/emultempl/aix.em
*** sources-original/src/ld/emultempl/aix.em	Sat Jan 20 00:28:59 2001
--- sources/src/ld/emultempl/aix.em	Tue Jan 23 15:21:37 2001
*************** cat >e${EMULATION_NAME}.c <<EOF
*** 8,13 ****
--- 8,14 ----
     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@rehat.com>

  This file is part of GLD, the Gnu Linker.

*************** Foundation, Inc., 59 Temple Place - Suit
*** 35,41 ****
  #include "bfdlink.h"

  #include <ctype.h>
-
  #include "ld.h"
  #include "ldmain.h"
  #include "ldmisc.h"
--- 36,41 ----
*************** Foundation, Inc., 59 Temple Place - Suit
*** 46,51 ****
--- 46,58 ----
  #include "ldctor.h"
  #include "ldgram.h"

+ #include "coff/internal.h"
+ #include "coff/xcoff.h"
+ #include "libcoff.h"
+ #include "libxcoff.h"
+ #include "string.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));
*************** gld${EMULATION_NAME}_before_parse()
*** 111,116 ****
--- 118,132 ----
    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.  */
*************** gld${EMULATION_NAME}_parse_args (argc, a
*** 128,151 ****
    long 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[] = {
      {"basis", no_argument, NULL, OPTION_IGNORE},
      {"bautoimp", no_argument, NULL, OPTION_AUTOIMP},
      {"bcomprld", no_argument, NULL, OPTION_IGNORE},
--- 144,221 ----
    long val;
    char *end;

!   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},
*************** gld${EMULATION_NAME}_parse_args (argc, a
*** 163,168 ****
--- 233,239 ----
      {"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},
*************** gld${EMULATION_NAME}_parse_args (argc, a
*** 184,189 ****
--- 255,261 ----
      {"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}
*************** gld${EMULATION_NAME}_parse_args (argc, a
*** 202,222 ****
       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;
!   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.  */
--- 274,294 ----
       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;
!   }

!   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.  */
*************** gld${EMULATION_NAME}_parse_args (argc, a
*** 277,282 ****
--- 349,389 ----
      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;
*************** gld${EMULATION_NAME}_before_allocation (
*** 499,520 ****
    struct filelist *fl;
    struct export_symbol_list *el;
    char *libpath;
!   asection *special_sections[6];
    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");
!     }

    /* Track down all relocations called for by the linker script (these
       are typically constructor/destructor entries created by
--- 606,626 ----
    struct filelist *fl;
    struct export_symbol_list *el;
    char *libpath;
!   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");
!   }

    /* Track down all relocations called for by the linker script (these
       are typically constructor/destructor entries created by
*************** gld${EMULATION_NAME}_before_allocation (
*** 562,668 ****

    /* 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;

!       /* 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;
! 	      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 (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 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;
  	}

!       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);
! 	}
      }
  }

  /* Read an import or export file.  For an import file, this is called
--- 668,777 ----

    /* Look through the special sections, and put them in the right
       place in the link ordering.  This is especially magic.  */
!   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);
!     }

!     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 (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;
+
+     case XCOFF_SPECIAL_SECTION_DATA:
+       /* _data */
+       oname = ".data";
+       start = true;
+       break;
+
+     case XCOFF_SPECIAL_SECTION_EDATA:
+       /* _edata */
+       oname = ".data";
+       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);

!     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);
      }
+   }
  }

  /* Read an import or export file.  For an import file, this is called


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]