This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
xcoff64 ld-emultempl-aix.em.patch
- To: "binutils" <binutils at sources dot redhat dot com>
- Subject: xcoff64 ld-emultempl-aix.em.patch
- From: "Tom Rix" <trix at redhat dot com>
- Date: Mon, 29 Jan 2001 13:40:01 -0600
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