summaryrefslogtreecommitdiffstats
path: root/x/binutils/ld/emultempl
diff options
context:
space:
mode:
Diffstat (limited to 'x/binutils/ld/emultempl')
-rw-r--r--x/binutils/ld/emultempl/README3
-rw-r--r--x/binutils/ld/emultempl/alphaelf.em80
-rw-r--r--x/binutils/ld/emultempl/armcoff.em277
-rw-r--r--x/binutils/ld/emultempl/armelf.em220
-rw-r--r--x/binutils/ld/emultempl/armelf_oabi.em176
-rw-r--r--x/binutils/ld/emultempl/astring.sed13
-rw-r--r--x/binutils/ld/emultempl/elf32.em1780
-rw-r--r--x/binutils/ld/emultempl/generic.em148
-rw-r--r--x/binutils/ld/emultempl/ia64elf.em62
-rw-r--r--x/binutils/ld/emultempl/linux.em207
-rw-r--r--x/binutils/ld/emultempl/mipsecoff.em248
-rw-r--r--x/binutils/ld/emultempl/mipself.em177
-rw-r--r--x/binutils/ld/emultempl/needrelax.em38
-rw-r--r--x/binutils/ld/emultempl/netbsd.em13
-rw-r--r--x/binutils/ld/emultempl/ostring.sed4
-rw-r--r--x/binutils/ld/emultempl/pe.em1952
-rw-r--r--x/binutils/ld/emultempl/ppc32elf.em80
-rw-r--r--x/binutils/ld/emultempl/ppc64elf.em529
-rw-r--r--x/binutils/ld/emultempl/stringify.sed4
-rw-r--r--x/binutils/ld/emultempl/sunos.em1031
-rw-r--r--x/binutils/ld/emultempl/ticoff.em182
-rw-r--r--x/binutils/ld/emultempl/vanilla.em85
22 files changed, 7309 insertions, 0 deletions
diff --git a/x/binutils/ld/emultempl/README b/x/binutils/ld/emultempl/README
new file mode 100644
index 0000000..30ec0ab
--- /dev/null
+++ b/x/binutils/ld/emultempl/README
@@ -0,0 +1,3 @@
+The files in this directory are sourced by genscripts.sh, after
+setting some variables to substitute in, to produce
+C source files that contain jump tables for each emulation.
diff --git a/x/binutils/ld/emultempl/alphaelf.em b/x/binutils/ld/emultempl/alphaelf.em
new file mode 100644
index 0000000..7e64323
--- /dev/null
+++ b/x/binutils/ld/emultempl/alphaelf.em
@@ -0,0 +1,80 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2003 Free Software Foundation, Inc.
+#
+# This file is part of GLD, the Gnu Linker.
+#
+# 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 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.
+#
+
+# This file is sourced from elf32.em, and defines extra alpha
+# specific routines.
+#
+cat >>e${EMULATION_NAME}.c <<EOF
+
+#include "elf/internal.h"
+#include "elf/alpha.h"
+#include "elf-bfd.h"
+
+static int elf64alpha_32bit = 0;
+
+/* Set the start address as in the Tru64 ld. */
+#define ALPHA_TEXT_START_32BIT 0x12000000
+
+static void
+alpha_after_parse (void)
+{
+ if (elf64alpha_32bit && !link_info.shared && !link_info.relocatable)
+ lang_section_start (".interp",
+ exp_binop ('+',
+ exp_intop (ALPHA_TEXT_START_32BIT),
+ exp_nameop (SIZEOF_HEADERS, NULL)));
+}
+
+static void
+alpha_finish (void)
+{
+ if (elf64alpha_32bit)
+ elf_elfheader (output_bfd)->e_flags |= EF_ALPHA_32BIT;
+
+ gld${EMULATION_NAME}_finish ();
+}
+EOF
+
+# Define some shell vars to insert bits of code into the standard elf
+# parse_args and list_options functions.
+#
+PARSE_AND_LIST_PROLOGUE='
+#define OPTION_TASO 300
+'
+
+PARSE_AND_LIST_LONGOPTS='
+ {"taso", no_argument, NULL, OPTION_TASO},
+'
+
+PARSE_AND_LIST_OPTIONS='
+ fprintf (file, _(" -taso\t\t\tLoad executable in the lower 31-bit addressable\n"));
+ fprintf (file, _("\t\t\t virtual address range\n"));
+'
+
+PARSE_AND_LIST_ARGS_CASES='
+ case OPTION_TASO:
+ elf64alpha_32bit = 1;
+ break;
+'
+
+# Put these extra alpha routines in ld_${EMULATION_NAME}_emulation
+#
+LDEMUL_AFTER_PARSE=alpha_after_parse
+LDEMUL_FINISH=alpha_finish
diff --git a/x/binutils/ld/emultempl/armcoff.em b/x/binutils/ld/emultempl/armcoff.em
new file mode 100644
index 0000000..468c3b0
--- /dev/null
+++ b/x/binutils/ld/emultempl/armcoff.em
@@ -0,0 +1,277 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+cat >e${EMULATION_NAME}.c <<EOF
+/* This file is is generated by a shell script. DO NOT EDIT! */
+
+/* emulate the original gld for the given ${EMULATION_NAME}
+ Copyright 1991, 1993, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+ 2004 Free Software Foundation, Inc.
+ Written by Steve Chamberlain steve@cygnus.com
+
+This file is part of GLD, the Gnu Linker.
+
+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 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. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "getopt.h"
+
+#include "ld.h"
+#include "ldmain.h"
+#include "ldmisc.h"
+
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldfile.h"
+#include "ldemul.h"
+
+/* If TRUE, then interworking stubs which support calls to old,
+ non-interworking aware ARM code should be generated. */
+
+static int support_old_code = 0;
+static char * thumb_entry_symbol = NULL;
+
+#define OPTION_SUPPORT_OLD_CODE 300
+#define OPTION_THUMB_ENTRY 301
+
+static void
+gld${EMULATION_NAME}_add_options
+ (int ns ATTRIBUTE_UNUSED, char **shortopts ATTRIBUTE_UNUSED, int nl,
+ struct option **longopts, int nrl ATTRIBUTE_UNUSED,
+ struct option **really_longopts ATTRIBUTE_UNUSED)
+{
+ static const struct option xtra_long[] = {
+ {"support-old-code", no_argument, NULL, OPTION_SUPPORT_OLD_CODE},
+ {"thumb-entry", required_argument, NULL, OPTION_THUMB_ENTRY},
+ {NULL, no_argument, NULL, 0}
+ };
+
+ *longopts = xrealloc (*longopts,
+ nl * sizeof (struct option) + sizeof (xtra_long));
+ memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
+}
+
+static void
+gld${EMULATION_NAME}_list_options (FILE *file)
+{
+ fprintf (file, _(" --support-old-code Support interworking with old code\n"));
+ fprintf (file, _(" --thumb-entry=<sym> Set the entry point to be Thumb symbol <sym>\n"));
+}
+
+static bfd_boolean
+gld${EMULATION_NAME}_handle_option (int optc)
+{
+ switch (optc)
+ {
+ default:
+ return FALSE;
+
+ case OPTION_SUPPORT_OLD_CODE:
+ support_old_code = 1;
+ break;
+
+ case OPTION_THUMB_ENTRY:
+ thumb_entry_symbol = optarg;
+ break;
+ }
+
+ return TRUE;
+}
+
+static void
+gld${EMULATION_NAME}_before_parse (void)
+{
+#ifndef TARGET_ /* I.e., if not generic. */
+ ldfile_set_output_arch ("`echo ${ARCH}`", bfd_arch_unknown);
+#endif /* not TARGET_ */
+}
+
+/* This is called after the sections have been attached to output
+ sections, but before any sizes or addresses have been set. */
+
+static void
+gld${EMULATION_NAME}_before_allocation (void)
+{
+ /* we should be able to set the size of the interworking stub section */
+
+ /* Here we rummage through the found bfds to collect glue information */
+ /* FIXME: should this be based on a command line option? krk@cygnus.com */
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (is)
+ {
+ if (! bfd_arm_process_before_allocation
+ (is->the_bfd, & link_info, support_old_code))
+ {
+ /* xgettext:c-format */
+ einfo (_("Errors encountered processing file %s"), is->filename);
+ }
+ }
+ }
+
+ /* We have seen it all. Allocate it, and carry on */
+ bfd_arm_allocate_interworking_sections (& link_info);
+}
+
+static void
+gld${EMULATION_NAME}_after_open (void)
+{
+ if (strstr (bfd_get_target (output_bfd), "arm") == NULL)
+ {
+ /* The arm backend needs special fields in the output hash structure.
+ These will only be created if the output format is an arm format,
+ hence we do not support linking and changing output formats at the
+ same time. Use a link followed by objcopy to change output formats. */
+ einfo ("%F%X%P: error: cannot change output format whilst linking ARM binaries\n");
+ return;
+ }
+
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (is)
+ {
+ if (bfd_arm_get_bfd_for_interworking (is->the_bfd, & link_info))
+ break;
+ }
+ }
+}
+
+static void
+gld${EMULATION_NAME}_finish (void)
+{
+ struct bfd_link_hash_entry * h;
+
+ if (thumb_entry_symbol == NULL)
+ return;
+
+ h = bfd_link_hash_lookup (link_info.hash, thumb_entry_symbol,
+ FALSE, FALSE, TRUE);
+
+ if (h != (struct bfd_link_hash_entry *) NULL
+ && (h->type == bfd_link_hash_defined
+ || h->type == bfd_link_hash_defweak)
+ && h->u.def.section->output_section != NULL)
+ {
+ static char buffer[32];
+ bfd_vma val;
+
+ /* Special procesing is required for a Thumb entry symbol. The
+ bottom bit of its address must be set. */
+ val = (h->u.def.value
+ + bfd_get_section_vma (output_bfd,
+ h->u.def.section->output_section)
+ + h->u.def.section->output_offset);
+
+ val |= 1;
+
+ /* Now convert this value into a string and store it in entry_symbol
+ where the lang_finish() function will pick it up. */
+ buffer[0] = '0';
+ buffer[1] = 'x';
+
+ sprintf_vma (buffer + 2, val);
+
+ if (entry_symbol.name != NULL && entry_from_cmdline)
+ einfo (_("%P: warning: '--thumb-entry %s' is overriding '-e %s'\n"),
+ thumb_entry_symbol, entry_symbol.name);
+ entry_symbol.name = buffer;
+ }
+ else
+ einfo (_("%P: warning: connot find thumb start symbol %s\n"), thumb_entry_symbol);
+}
+
+static char *
+gld${EMULATION_NAME}_get_script (int *isfile)
+EOF
+
+if test -n "$COMPILE_IN"
+then
+# Scripts compiled in.
+
+# sed commands to quote an ld script as a C string.
+sc="-f stringify.sed"
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 0;
+
+ if (link_info.relocatable && config.build_constructors)
+ return
+EOF
+sed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c
+echo ' ; else if (link_info.relocatable) 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
+{
+ *isfile = 1;
+
+ if (link_info.relocatable && config.build_constructors)
+ return "ldscripts/${EMULATION_NAME}.xu";
+ else if (link_info.relocatable)
+ return "ldscripts/${EMULATION_NAME}.xr";
+ else if (!config.text_read_only)
+ return "ldscripts/${EMULATION_NAME}.xbn";
+ else if (!config.magic_demand_paged)
+ return "ldscripts/${EMULATION_NAME}.xn";
+ else
+ return "ldscripts/${EMULATION_NAME}.x";
+}
+EOF
+
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+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_allocation_default,
+ set_output_arch_default,
+ ldemul_default_target,
+ gld${EMULATION_NAME}_before_allocation,
+ gld${EMULATION_NAME}_get_script,
+ "${EMULATION_NAME}",
+ "${OUTPUT_FORMAT}",
+ gld${EMULATION_NAME}_finish,
+ NULL, /* create output section statements */
+ NULL, /* open dynamic archive */
+ NULL, /* place orphan */
+ NULL, /* set symbols */
+ NULL, /* parse_args */
+ gld${EMULATION_NAME}_add_options,
+ gld${EMULATION_NAME}_handle_option,
+ NULL, /* unrecognised file */
+ gld${EMULATION_NAME}_list_options,
+ NULL, /* recognized file */
+ NULL, /* find_potential_libraries */
+ NULL /* new_vers_pattern */
+};
+EOF
diff --git a/x/binutils/ld/emultempl/armelf.em b/x/binutils/ld/emultempl/armelf.em
new file mode 100644
index 0000000..0c051ad
--- /dev/null
+++ b/x/binutils/ld/emultempl/armelf.em
@@ -0,0 +1,220 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 1991, 1993, 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004
+# Free Software Foundation, Inc.
+#
+# This file is part of GLD, the Gnu Linker.
+#
+# 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 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.
+#
+
+# This file is sourced from elf32.em, and defines extra arm-elf
+# specific routines.
+#
+cat >>e${EMULATION_NAME}.c <<EOF
+
+static int no_pipeline_knowledge = 0;
+static char *thumb_entry_symbol = NULL;
+static bfd *bfd_for_interwork;
+
+static void
+gld${EMULATION_NAME}_before_parse (void)
+{
+#ifndef TARGET_ /* I.e., if not generic. */
+ ldfile_set_output_arch ("`echo ${ARCH}`", bfd_arch_unknown);
+#endif /* not TARGET_ */
+ config.dynamic_link = ${DYNAMIC_LINK-TRUE};
+ config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`;
+}
+
+static void
+arm_elf_after_open (void)
+{
+ if (strstr (bfd_get_target (output_bfd), "arm") == NULL)
+ {
+ /* The arm backend needs special fields in the output hash structure.
+ These will only be created if the output format is an arm format,
+ hence we do not support linking and changing output formats at the
+ same time. Use a link followed by objcopy to change output formats. */
+ einfo ("%F%X%P: error: cannot change output format whilst linking ARM binaries\n");
+ return;
+ }
+
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (is)
+ {
+ bfd_elf32_arm_add_glue_sections_to_bfd (is->the_bfd, & link_info);
+ }
+ }
+
+ /* Call the standard elf routine. */
+ gld${EMULATION_NAME}_after_open ();
+}
+
+static void
+arm_elf_set_bfd_for_interworking (lang_statement_union_type *statement)
+{
+ if (statement->header.type == lang_input_section_enum
+ && !statement->input_section.ifile->just_syms_flag)
+ {
+ asection *i = statement->input_section.section;
+ asection *output_section = i->output_section;
+
+ ASSERT (output_section->owner == output_bfd);
+
+ if ((output_section->flags & SEC_HAS_CONTENTS) != 0
+ && (i->flags & SEC_NEVER_LOAD) == 0
+ && ! i->owner->output_has_begun)
+ {
+ bfd_for_interwork = i->owner;
+ bfd_for_interwork->output_has_begun = TRUE;
+ }
+ }
+}
+
+static void
+arm_elf_before_allocation (void)
+{
+ bfd *tem;
+
+ /* Call the standard elf routine. */
+ gld${EMULATION_NAME}_before_allocation ();
+
+ if (link_info.input_bfds != NULL)
+ {
+ /* The interworking bfd must be the last one in the link. */
+ bfd_for_interwork = NULL;
+ for (tem = link_info.input_bfds; tem != NULL; tem = tem->link_next)
+ tem->output_has_begun = FALSE;
+
+ lang_for_each_statement (arm_elf_set_bfd_for_interworking);
+ for (tem = link_info.input_bfds; tem != NULL; tem = tem->link_next)
+ tem->output_has_begun = FALSE;
+
+ /* If bfd_for_interwork is NULL, then there are no loadable sections
+ with real contents to be linked, so we are not going to have to
+ create any interworking stubs, so it is OK not to call
+ bfd_elf32_arm_get_bfd_for_interworking. */
+ if (bfd_for_interwork != NULL)
+ bfd_elf32_arm_get_bfd_for_interworking (bfd_for_interwork, &link_info);
+ }
+ /* We should be able to set the size of the interworking stub section. */
+
+ /* Here we rummage through the found bfds to collect glue information. */
+ /* FIXME: should this be based on a command line option? krk@cygnus.com */
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (is)
+ {
+ if (!bfd_elf32_arm_process_before_allocation (is->the_bfd, & link_info,
+ no_pipeline_knowledge))
+ {
+ /* xgettext:c-format */
+ einfo (_("Errors encountered processing file %s"), is->filename);
+ }
+ }
+ }
+
+ /* We have seen it all. Allocate it, and carry on. */
+ bfd_elf32_arm_allocate_interworking_sections (& link_info);
+}
+
+static void
+arm_elf_finish (void)
+{
+ struct bfd_link_hash_entry * h;
+
+ /* Call the elf32.em routine. */
+ gld${EMULATION_NAME}_finish ();
+
+ if (thumb_entry_symbol == NULL)
+ return;
+
+ h = bfd_link_hash_lookup (link_info.hash, thumb_entry_symbol,
+ FALSE, FALSE, TRUE);
+
+ if (h != (struct bfd_link_hash_entry *) NULL
+ && (h->type == bfd_link_hash_defined
+ || h->type == bfd_link_hash_defweak)
+ && h->u.def.section->output_section != NULL)
+ {
+ static char buffer[32];
+ bfd_vma val;
+
+ /* Special procesing is required for a Thumb entry symbol. The
+ bottom bit of its address must be set. */
+ val = (h->u.def.value
+ + bfd_get_section_vma (output_bfd,
+ h->u.def.section->output_section)
+ + h->u.def.section->output_offset);
+
+ val |= 1;
+
+ /* Now convert this value into a string and store it in entry_symbol
+ where the lang_finish() function will pick it up. */
+ buffer[0] = '0';
+ buffer[1] = 'x';
+
+ sprintf_vma (buffer + 2, val);
+
+ if (entry_symbol.name != NULL && entry_from_cmdline)
+ einfo (_("%P: warning: '--thumb-entry %s' is overriding '-e %s'\n"),
+ thumb_entry_symbol, entry_symbol.name);
+ entry_symbol.name = buffer;
+ }
+ else
+ einfo (_("%P: warning: connot find thumb start symbol %s\n"),
+ thumb_entry_symbol);
+}
+
+EOF
+
+# Define some shell vars to insert bits of code into the standard elf
+# parse_args and list_options functions.
+#
+PARSE_AND_LIST_PROLOGUE='
+#define OPTION_THUMB_ENTRY 301
+'
+
+PARSE_AND_LIST_SHORTOPTS=p
+
+PARSE_AND_LIST_LONGOPTS='
+ { "no-pipeline-knowledge", no_argument, NULL, '\'p\''},
+ { "thumb-entry", required_argument, NULL, OPTION_THUMB_ENTRY},
+'
+
+PARSE_AND_LIST_OPTIONS='
+ fprintf (file, _(" -p --no-pipeline-knowledge Stop the linker knowing about the pipeline length\n"));
+ fprintf (file, _(" --thumb-entry=<sym> Set the entry point to be Thumb symbol <sym>\n"));
+'
+
+PARSE_AND_LIST_ARGS_CASES='
+ case '\'p\'':
+ no_pipeline_knowledge = 1;
+ break;
+
+ case OPTION_THUMB_ENTRY:
+ thumb_entry_symbol = optarg;
+ break;
+'
+
+# We have our own after_open and before_allocation functions, but they call
+# the standard routines, so give them a different name.
+LDEMUL_AFTER_OPEN=arm_elf_after_open
+LDEMUL_BEFORE_ALLOCATION=arm_elf_before_allocation
+
+# Replace the elf before_parse function with our own.
+LDEMUL_BEFORE_PARSE=gld"${EMULATION_NAME}"_before_parse
+
+# Call the extra arm-elf function
+LDEMUL_FINISH=arm_elf_finish
diff --git a/x/binutils/ld/emultempl/armelf_oabi.em b/x/binutils/ld/emultempl/armelf_oabi.em
new file mode 100644
index 0000000..d75c658
--- /dev/null
+++ b/x/binutils/ld/emultempl/armelf_oabi.em
@@ -0,0 +1,176 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+cat >e${EMULATION_NAME}.c <<EOF
+/* This file is is generated by a shell script. DO NOT EDIT! */
+
+/* emulate the original gld for the given ${EMULATION_NAME}
+ Copyright 1991, 1993, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+ 2004 Free Software Foundation, Inc.
+ Written by Steve Chamberlain steve@cygnus.com
+
+This file is part of GLD, the Gnu Linker.
+
+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 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. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#define bfd_elf32_arm_allocate_interworking_sections \
+ bfd_elf32_arm_oabi_allocate_interworking_sections
+#define bfd_elf32_arm_get_bfd_for_interworking \
+ bfd_elf32_arm_oabi_get_bfd_for_interworking
+#define bfd_elf32_arm_process_before_allocation \
+ bfd_elf32_arm_oabi_process_before_allocation
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "getopt.h"
+
+#include "ld.h"
+#include "ldmain.h"
+#include "ldmisc.h"
+
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldfile.h"
+#include "ldemul.h"
+
+static void
+gld${EMULATION_NAME}_before_parse (void)
+{
+#ifndef TARGET_ /* I.e., if not generic. */
+ ldfile_set_output_arch ("`echo ${ARCH}`", bfd_arch_unknown);
+#endif /* not TARGET_ */
+}
+
+/* This is called after the sections have been attached to output
+ sections, but before any sizes or addresses have been set. */
+
+static void
+gld${EMULATION_NAME}_before_allocation (void)
+{
+ /* we should be able to set the size of the interworking stub section */
+
+ /* Here we rummage through the found bfds to collect glue information */
+ /* FIXME: should this be based on a command line option? krk@cygnus.com */
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (is)
+ {
+ if (!bfd_elf32_arm_process_before_allocation (is->the_bfd, &link_info, 0))
+ {
+ /* xgettext:c-format */
+ einfo (_("Errors encountered processing file %s"), is->filename);
+ }
+ }
+ }
+
+ /* We have seen it all. Allocate it, and carry on */
+ bfd_elf32_arm_allocate_interworking_sections (& link_info);
+}
+
+static void
+gld${EMULATION_NAME}_after_open (void)
+{
+
+ LANG_FOR_EACH_INPUT_STATEMENT (is)
+ {
+ /* The interworking bfd must be the last one to be processed */
+ if (!is->next)
+ bfd_elf32_arm_get_bfd_for_interworking (is->the_bfd, & link_info);
+ }
+}
+
+static char *
+gld${EMULATION_NAME}_get_script (int *isfile)
+EOF
+
+if test -n "$COMPILE_IN"
+then
+# Scripts compiled in.
+
+# sed commands to quote an ld script as a C string.
+sc="-f stringify.sed"
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 0;
+
+ if (link_info.relocatable && config.build_constructors)
+ return
+EOF
+sed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c
+echo ' ; else if (link_info.relocatable) 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
+{
+ *isfile = 1;
+
+ if (link_info.relocatable && config.build_constructors)
+ return "ldscripts/${EMULATION_NAME}.xu";
+ else if (link_info.relocatable)
+ return "ldscripts/${EMULATION_NAME}.xr";
+ else if (!config.text_read_only)
+ return "ldscripts/${EMULATION_NAME}.xbn";
+ else if (!config.magic_demand_paged)
+ return "ldscripts/${EMULATION_NAME}.xn";
+ else
+ return "ldscripts/${EMULATION_NAME}.x";
+}
+EOF
+
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+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_allocation_default,
+ set_output_arch_default,
+ ldemul_default_target,
+ gld${EMULATION_NAME}_before_allocation,
+ gld${EMULATION_NAME}_get_script,
+ "${EMULATION_NAME}",
+ "${OUTPUT_FORMAT}",
+ NULL, /* finish */
+ NULL, /* create output section statements */
+ NULL, /* open dynamic archive */
+ NULL, /* place orphan */
+ NULL, /* set symbols */
+ NULL, /* parse args */
+ NULL, /* add_options */
+ NULL, /* handle_option */
+ NULL, /* unrecognized file */
+ NULL, /* list options */
+ NULL, /* recognized file */
+ NULL, /* find_potential_libraries */
+ NULL /* new_vers_pattern */
+};
+EOF
diff --git a/x/binutils/ld/emultempl/astring.sed b/x/binutils/ld/emultempl/astring.sed
new file mode 100644
index 0000000..08bd8a6
--- /dev/null
+++ b/x/binutils/ld/emultempl/astring.sed
@@ -0,0 +1,13 @@
+s/["\\]/\\&/g
+s/$/\\n\\/
+1 s/^/"/
+25s/\\$/"/
+26s/^/"/
+50s/\\$/"/
+51s/^/"/
+75s/\\$/"/
+76s/^/"/
+100s/\\$/"/
+101s/^/"/
+$ s/$/n"/
+$ s/\\n"n"$/\\n"/
diff --git a/x/binutils/ld/emultempl/elf32.em b/x/binutils/ld/emultempl/elf32.em
new file mode 100644
index 0000000..92f502d
--- /dev/null
+++ b/x/binutils/ld/emultempl/elf32.em
@@ -0,0 +1,1780 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+# This file is now misnamed, because it supports both 32 bit and 64 bit
+# ELF emulations.
+test -z "${ELFSIZE}" && ELFSIZE=32
+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! */
+
+/* ${ELFSIZE} bit ELF emulation code for ${EMULATION_NAME}
+ Copyright 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+ 2002, 2003, 2004 Free Software Foundation, Inc.
+ Written by Steve Chamberlain <sac@cygnus.com>
+ ELF support by Ian Lance Taylor <ian@cygnus.com>
+
+This file is part of GLD, the Gnu Linker.
+
+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 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. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libiberty.h"
+#include "safe-ctype.h"
+#include "getopt.h"
+
+#include "bfdlink.h"
+
+#include "ld.h"
+#include "ldmain.h"
+#include "ldmisc.h"
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldfile.h"
+#include "ldemul.h"
+#include <ldgram.h>
+#include "elf/common.h"
+
+/* Declare functions used by various EXTRA_EM_FILEs. */
+static void gld${EMULATION_NAME}_before_parse (void);
+static void gld${EMULATION_NAME}_after_open (void);
+static void gld${EMULATION_NAME}_before_allocation (void);
+static bfd_boolean gld${EMULATION_NAME}_place_orphan
+ (lang_input_statement_type *file, asection *s);
+static void gld${EMULATION_NAME}_finish (void);
+
+EOF
+
+# Import any needed special functions and/or overrides.
+#
+if test -n "$EXTRA_EM_FILE" ; then
+. ${srcdir}/emultempl/${EXTRA_EM_FILE}.em
+fi
+
+# Functions in this file can be overridden by setting the LDEMUL_* shell
+# variables. If the name of the overriding function is the same as is
+# defined in this file, then don't output this file's version.
+# If a different overriding name is given then output the standard function
+# as presumably it is called from the overriding function.
+#
+if test x"$LDEMUL_BEFORE_PARSE" != xgld"$EMULATION_NAME"_before_parse; then
+cat >>e${EMULATION_NAME}.c <<EOF
+
+static void
+gld${EMULATION_NAME}_before_parse (void)
+{
+ ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`);
+ config.dynamic_link = ${DYNAMIC_LINK-TRUE};
+ config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`;
+}
+
+EOF
+fi
+
+if test x"$LDEMUL_RECOGNIZED_FILE" != xgld"${EMULATION_NAME}"_load_symbols; then
+cat >>e${EMULATION_NAME}.c <<EOF
+/* Handle as_needed DT_NEEDED. */
+
+static bfd_boolean
+gld${EMULATION_NAME}_load_symbols (lang_input_statement_type *entry)
+{
+ if (!entry->as_needed
+ || (bfd_get_file_flags (entry->the_bfd) & DYNAMIC) == 0)
+ return FALSE;
+
+ /* Tell the ELF linker that we don't want the output file to have a
+ DT_NEEDED entry for this file, unless it is used to resolve
+ references in a regular object. */
+ bfd_elf_set_dyn_lib_class (entry->the_bfd, DYN_AS_NEEDED);
+
+ /* Continue on with normal load_symbols processing. */
+ return FALSE;
+}
+EOF
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+/* These variables are required to pass information back and forth
+ between after_open and check_needed and stat_needed and vercheck. */
+
+static struct bfd_link_needed_list *global_needed;
+static struct stat global_stat;
+static bfd_boolean global_found;
+static struct bfd_link_needed_list *global_vercheck_needed;
+static bfd_boolean global_vercheck_failed;
+
+
+/* On Linux, it's possible to have different versions of the same
+ shared library linked against different versions of libc. The
+ dynamic linker somehow tags which libc version to use in
+ /etc/ld.so.cache, and, based on the libc that it sees in the
+ executable, chooses which version of the shared library to use.
+
+ We try to do a similar check here by checking whether this shared
+ library needs any other shared libraries which may conflict with
+ libraries we have already included in the link. If it does, we
+ skip it, and try to find another shared library farther on down the
+ link path.
+
+ This is called via lang_for_each_input_file.
+ GLOBAL_VERCHECK_NEEDED is the list of objects needed by the object
+ which we are checking. This sets GLOBAL_VERCHECK_FAILED if we find
+ a conflicting version. */
+
+static void
+gld${EMULATION_NAME}_vercheck (lang_input_statement_type *s)
+{
+ const char *soname;
+ struct bfd_link_needed_list *l;
+
+ if (global_vercheck_failed)
+ return;
+ if (s->the_bfd == NULL
+ || (bfd_get_file_flags (s->the_bfd) & DYNAMIC) == 0)
+ return;
+
+ soname = bfd_elf_get_dt_soname (s->the_bfd);
+ if (soname == NULL)
+ soname = lbasename (bfd_get_filename (s->the_bfd));
+
+ for (l = global_vercheck_needed; l != NULL; l = l->next)
+ {
+ const char *suffix;
+
+ if (strcmp (soname, l->name) == 0)
+ {
+ /* Probably can't happen, but it's an easy check. */
+ continue;
+ }
+
+ if (strchr (l->name, '/') != NULL)
+ continue;
+
+ suffix = strstr (l->name, ".so.");
+ if (suffix == NULL)
+ continue;
+
+ suffix += sizeof ".so." - 1;
+
+ if (strncmp (soname, l->name, suffix - l->name) == 0)
+ {
+ /* Here we know that S is a dynamic object FOO.SO.VER1, and
+ the object we are considering needs a dynamic object
+ FOO.SO.VER2, and VER1 and VER2 are different. This
+ appears to be a version mismatch, so we tell the caller
+ to try a different version of this library. */
+ global_vercheck_failed = TRUE;
+ return;
+ }
+ }
+}
+
+
+/* See if an input file matches a DT_NEEDED entry by running stat on
+ the file. */
+
+static void
+gld${EMULATION_NAME}_stat_needed (lang_input_statement_type *s)
+{
+ struct stat st;
+ const char *suffix;
+ const char *soname;
+
+ if (global_found)
+ return;
+ if (s->the_bfd == NULL)
+ return;
+
+ if (bfd_stat (s->the_bfd, &st) != 0)
+ {
+ einfo ("%P:%B: bfd_stat failed: %E\n", s->the_bfd);
+ return;
+ }
+
+ if (st.st_dev == global_stat.st_dev
+ && st.st_ino == global_stat.st_ino)
+ {
+ global_found = TRUE;
+ return;
+ }
+
+ /* We issue a warning if it looks like we are including two
+ different versions of the same shared library. For example,
+ there may be a problem if -lc picks up libc.so.6 but some other
+ shared library has a DT_NEEDED entry of libc.so.5. This is a
+ heuristic test, and it will only work if the name looks like
+ NAME.so.VERSION. FIXME: Depending on file names is error-prone.
+ If we really want to issue warnings about mixing version numbers
+ of shared libraries, we need to find a better way. */
+
+ if (strchr (global_needed->name, '/') != NULL)
+ return;
+ suffix = strstr (global_needed->name, ".so.");
+ if (suffix == NULL)
+ return;
+ suffix += sizeof ".so." - 1;
+
+ soname = bfd_elf_get_dt_soname (s->the_bfd);
+ if (soname == NULL)
+ soname = lbasename (s->filename);
+
+ if (strncmp (soname, global_needed->name, suffix - global_needed->name) == 0)
+ einfo ("%P: warning: %s, needed by %B, may conflict with %s\n",
+ global_needed->name, global_needed->by, soname);
+}
+
+
+/* This function is called for each possible name for a dynamic object
+ named by a DT_NEEDED entry. The FORCE parameter indicates whether
+ to skip the check for a conflicting version. */
+
+static bfd_boolean
+gld${EMULATION_NAME}_try_needed (const char *name, int force)
+{
+ bfd *abfd;
+ const char *soname;
+
+ abfd = bfd_openr (name, bfd_get_target (output_bfd));
+ if (abfd == NULL)
+ return FALSE;
+ if (! bfd_check_format (abfd, bfd_object))
+ {
+ bfd_close (abfd);
+ return FALSE;
+ }
+ if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0)
+ {
+ bfd_close (abfd);
+ return FALSE;
+ }
+
+ /* For DT_NEEDED, they have to match. */
+ if (abfd->xvec != output_bfd->xvec)
+ {
+ bfd_close (abfd);
+ return FALSE;
+ }
+
+ /* Check whether this object would include any conflicting library
+ versions. If FORCE is set, then we skip this check; we use this
+ the second time around, if we couldn't find any compatible
+ instance of the shared library. */
+
+ if (! force)
+ {
+ struct bfd_link_needed_list *needed;
+
+ if (! bfd_elf_get_bfd_needed_list (abfd, &needed))
+ einfo ("%F%P:%B: bfd_elf_get_bfd_needed_list failed: %E\n", abfd);
+
+ if (needed != NULL)
+ {
+ global_vercheck_needed = needed;
+ global_vercheck_failed = FALSE;
+ lang_for_each_input_file (gld${EMULATION_NAME}_vercheck);
+ if (global_vercheck_failed)
+ {
+ bfd_close (abfd);
+ /* Return FALSE to force the caller to move on to try
+ another file on the search path. */
+ return FALSE;
+ }
+
+ /* But wait! It gets much worse. On Linux, if a shared
+ library does not use libc at all, we are supposed to skip
+ it the first time around in case we encounter a shared
+ library later on with the same name which does use the
+ version of libc that we want. This is much too horrible
+ to use on any system other than Linux. */
+
+EOF
+case ${target} in
+ *-*-linux-gnu*)
+ cat >>e${EMULATION_NAME}.c <<EOF
+ {
+ struct bfd_link_needed_list *l;
+
+ for (l = needed; l != NULL; l = l->next)
+ if (strncmp (l->name, "libc.so", 7) == 0)
+ break;
+ if (l == NULL)
+ {
+ bfd_close (abfd);
+ return FALSE;
+ }
+ }
+
+EOF
+ ;;
+esac
+cat >>e${EMULATION_NAME}.c <<EOF
+ }
+ }
+
+ /* We've found a dynamic object matching the DT_NEEDED entry. */
+
+ /* We have already checked that there is no other input file of the
+ same name. We must now check again that we are not including the
+ same file twice. We need to do this because on many systems
+ libc.so is a symlink to, e.g., libc.so.1. The SONAME entry will
+ reference libc.so.1. If we have already included libc.so, we
+ don't want to include libc.so.1 if they are the same file, and we
+ can only check that using stat. */
+
+ if (bfd_stat (abfd, &global_stat) != 0)
+ einfo ("%F%P:%B: bfd_stat failed: %E\n", abfd);
+
+ /* First strip off everything before the last '/'. */
+ soname = lbasename (abfd->filename);
+
+ if (trace_file_tries)
+ info_msg (_("found %s at %s\n"), soname, name);
+
+ global_found = FALSE;
+ lang_for_each_input_file (gld${EMULATION_NAME}_stat_needed);
+ if (global_found)
+ {
+ /* Return TRUE to indicate that we found the file, even though
+ we aren't going to do anything with it. */
+ return TRUE;
+ }
+
+ /* Specify the soname to use. */
+ bfd_elf_set_dt_needed_name (abfd, soname);
+
+ /* Tell the ELF linker that we don't want the output file to have a
+ DT_NEEDED entry for this file, unless it is used to resolve
+ references in a regular object. */
+ bfd_elf_set_dyn_lib_class (abfd, DYN_DT_NEEDED);
+
+ /* Add this file into the symbol table. */
+ if (! bfd_link_add_symbols (abfd, &link_info))
+ einfo ("%F%B: could not read symbols: %E\n", abfd);
+
+ return TRUE;
+}
+
+
+/* Search for a needed file in a path. */
+
+static bfd_boolean
+gld${EMULATION_NAME}_search_needed (const char *path, const char *name, int force)
+{
+ const char *s;
+ size_t len;
+
+ if (name[0] == '/')
+ return gld${EMULATION_NAME}_try_needed (name, force);
+
+ if (path == NULL || *path == '\0')
+ return FALSE;
+ len = strlen (name);
+ while (1)
+ {
+ char *filename, *sset;
+
+ s = strchr (path, ':');
+ if (s == NULL)
+ s = path + strlen (path);
+
+ filename = (char *) xmalloc (s - path + len + 2);
+ if (s == path)
+ sset = filename;
+ else
+ {
+ memcpy (filename, path, s - path);
+ filename[s - path] = '/';
+ sset = filename + (s - path) + 1;
+ }
+ strcpy (sset, name);
+
+ if (gld${EMULATION_NAME}_try_needed (filename, force))
+ return TRUE;
+
+ free (filename);
+
+ if (*s == '\0')
+ break;
+ path = s + 1;
+ }
+
+ return FALSE;
+}
+
+EOF
+if [ "x${USE_LIBPATH}" = xyes ] ; then
+ cat >>e${EMULATION_NAME}.c <<EOF
+
+/* Add the sysroot to every entry in a colon-separated path. */
+
+static char *
+gld${EMULATION_NAME}_add_sysroot (const char *path)
+{
+ int len, colons, i;
+ char *ret, *p;
+
+ len = strlen (path);
+ colons = 0;
+ i = 0;
+ while (path[i])
+ if (path[i++] == ':')
+ colons++;
+
+ if (path[i])
+ colons++;
+
+ len = len + (colons + 1) * strlen (ld_sysroot);
+ ret = xmalloc (len + 1);
+ strcpy (ret, ld_sysroot);
+ p = ret + strlen (ret);
+ i = 0;
+ while (path[i])
+ if (path[i] == ':')
+ {
+ *p++ = path[i++];
+ strcpy (p, ld_sysroot);
+ p = p + strlen (p);
+ }
+ else
+ *p++ = path[i++];
+
+ *p = 0;
+ return ret;
+}
+
+EOF
+ case ${target} in
+ *-*-linux-gnu*)
+ cat >>e${EMULATION_NAME}.c <<EOF
+/* For a native linker, check the file /etc/ld.so.conf for directories
+ in which we may find shared libraries. /etc/ld.so.conf is really
+ only meaningful on Linux. */
+
+static bfd_boolean
+gld${EMULATION_NAME}_check_ld_so_conf (const char *name, int force)
+{
+ static bfd_boolean initialized;
+ static char *ld_so_conf;
+
+ if (! initialized)
+ {
+ FILE *f;
+ char *tmppath;
+
+ tmppath = concat (ld_sysroot, "/etc/ld.so.conf", NULL);
+ f = fopen (tmppath, FOPEN_RT);
+ free (tmppath);
+ if (f != NULL)
+ {
+ char *b;
+ size_t len, alloc;
+ int c;
+
+ len = 0;
+ alloc = 100;
+ b = (char *) xmalloc (alloc);
+
+ while ((c = getc (f)) != EOF)
+ {
+ if (len + 1 >= alloc)
+ {
+ alloc *= 2;
+ b = (char *) xrealloc (b, alloc);
+ }
+ if (c != ':'
+ && c != ' '
+ && c != '\t'
+ && c != '\n'
+ && c != ',')
+ {
+ b[len] = c;
+ ++len;
+ }
+ else
+ {
+ if (len > 0 && b[len - 1] != ':')
+ {
+ b[len] = ':';
+ ++len;
+ }
+ }
+ }
+
+ if (len > 0 && b[len - 1] == ':')
+ --len;
+
+ if (len > 0)
+ b[len] = '\0';
+ else
+ {
+ free (b);
+ b = NULL;
+ }
+
+ fclose (f);
+
+ if (b)
+ {
+ char *d = gld${EMULATION_NAME}_add_sysroot (b);
+ free (b);
+ b = d;
+ }
+
+ ld_so_conf = b;
+ }
+
+ initialized = TRUE;
+ }
+
+ if (ld_so_conf == NULL)
+ return FALSE;
+
+ return gld${EMULATION_NAME}_search_needed (ld_so_conf, name, force);
+}
+
+EOF
+ # Linux
+ ;;
+ esac
+fi
+cat >>e${EMULATION_NAME}.c <<EOF
+
+/* See if an input file matches a DT_NEEDED entry by name. */
+
+static void
+gld${EMULATION_NAME}_check_needed (lang_input_statement_type *s)
+{
+ if (global_found)
+ return;
+
+ if (s->filename != NULL)
+ {
+ const char *f;
+
+ if (strcmp (s->filename, global_needed->name) == 0)
+ {
+ global_found = TRUE;
+ return;
+ }
+
+ if (s->search_dirs_flag)
+ {
+ f = strrchr (s->filename, '/');
+ if (f != NULL
+ && strcmp (f + 1, global_needed->name) == 0)
+ {
+ global_found = TRUE;
+ return;
+ }
+ }
+ }
+
+ if (s->the_bfd != NULL)
+ {
+ const char *soname;
+
+ soname = bfd_elf_get_dt_soname (s->the_bfd);
+ if (soname != NULL
+ && strcmp (soname, global_needed->name) == 0)
+ {
+ global_found = TRUE;
+ return;
+ }
+ }
+}
+
+EOF
+
+if test x"$LDEMUL_AFTER_OPEN" != xgld"$EMULATION_NAME"_after_open; then
+cat >>e${EMULATION_NAME}.c <<EOF
+
+/* This is called after all the input files have been opened. */
+
+static void
+gld${EMULATION_NAME}_after_open (void)
+{
+ struct bfd_link_needed_list *needed, *l;
+
+ /* We only need to worry about this when doing a final link. */
+ if (link_info.relocatable || !link_info.executable)
+ return;
+
+ /* Get the list of files which appear in DT_NEEDED entries in
+ dynamic objects included in the link (often there will be none).
+ For each such file, we want to track down the corresponding
+ library, and include the symbol table in the link. This is what
+ the runtime dynamic linker will do. Tracking the files down here
+ permits one dynamic object to include another without requiring
+ special action by the person doing the link. Note that the
+ needed list can actually grow while we are stepping through this
+ loop. */
+ needed = bfd_elf_get_needed_list (output_bfd, &link_info);
+ for (l = needed; l != NULL; l = l->next)
+ {
+ struct bfd_link_needed_list *ll;
+ int force;
+
+ /* If we've already seen this file, skip it. */
+ for (ll = needed; ll != l; ll = ll->next)
+ if (strcmp (ll->name, l->name) == 0)
+ break;
+ if (ll != l)
+ continue;
+
+ /* See if this file was included in the link explicitly. */
+ global_needed = l;
+ global_found = FALSE;
+ lang_for_each_input_file (gld${EMULATION_NAME}_check_needed);
+ if (global_found)
+ continue;
+
+ if (trace_file_tries)
+ info_msg (_("%s needed by %B\n"), l->name, l->by);
+
+ /* We need to find this file and include the symbol table. We
+ want to search for the file in the same way that the dynamic
+ linker will search. That means that we want to use
+ rpath_link, rpath, then the environment variable
+ LD_LIBRARY_PATH (native only), then the DT_RPATH/DT_RUNPATH
+ entries (native only), then the linker script LIB_SEARCH_DIRS.
+ We do not search using the -L arguments.
+
+ We search twice. The first time, we skip objects which may
+ introduce version mismatches. The second time, we force
+ their use. See gld${EMULATION_NAME}_vercheck comment. */
+ for (force = 0; force < 2; force++)
+ {
+ size_t len;
+ search_dirs_type *search;
+EOF
+if [ "x${USE_LIBPATH}" = xyes ] ; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ const char *lib_path;
+ struct bfd_link_needed_list *rp;
+ int found;
+EOF
+fi
+cat >>e${EMULATION_NAME}.c <<EOF
+
+ if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link,
+ l->name, force))
+ break;
+EOF
+if [ "x${USE_LIBPATH}" = xyes ] ; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ if (gld${EMULATION_NAME}_search_needed (command_line.rpath,
+ l->name, force))
+ break;
+EOF
+fi
+if [ "x${NATIVE}" = xyes ] ; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ if (command_line.rpath_link == NULL
+ && command_line.rpath == NULL)
+ {
+ lib_path = (const char *) getenv ("LD_RUN_PATH");
+ if (gld${EMULATION_NAME}_search_needed (lib_path, l->name,
+ force))
+ break;
+ }
+ lib_path = (const char *) getenv ("LD_LIBRARY_PATH");
+ if (gld${EMULATION_NAME}_search_needed (lib_path, l->name, force))
+ break;
+EOF
+fi
+if [ "x${USE_LIBPATH}" = xyes ] ; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ found = 0;
+ rp = bfd_elf_get_runpath_list (output_bfd, &link_info);
+ for (; !found && rp != NULL; rp = rp->next)
+ {
+ char *tmpname = gld${EMULATION_NAME}_add_sysroot (rp->name);
+ found = (rp->by == l->by
+ && gld${EMULATION_NAME}_search_needed (tmpname,
+ l->name,
+ force));
+ free (tmpname);
+ }
+ if (found)
+ break;
+
+EOF
+fi
+cat >>e${EMULATION_NAME}.c <<EOF
+ len = strlen (l->name);
+ for (search = search_head; search != NULL; search = search->next)
+ {
+ char *filename;
+
+ if (search->cmdline)
+ continue;
+ filename = (char *) xmalloc (strlen (search->name) + len + 2);
+ sprintf (filename, "%s/%s", search->name, l->name);
+ if (gld${EMULATION_NAME}_try_needed (filename, force))
+ break;
+ free (filename);
+ }
+ if (search != NULL)
+ break;
+EOF
+if [ "x${USE_LIBPATH}" = xyes ] ; then
+ case ${target} in
+ *-*-linux-gnu*)
+ cat >>e${EMULATION_NAME}.c <<EOF
+ if (gld${EMULATION_NAME}_check_ld_so_conf (l->name, force))
+ break;
+EOF
+ # Linux
+ ;;
+ esac
+fi
+cat >>e${EMULATION_NAME}.c <<EOF
+ }
+
+ if (force < 2)
+ continue;
+
+ einfo ("%P: warning: %s, needed by %B, not found (try using -rpath or -rpath-link)\n",
+ l->name, l->by);
+ }
+}
+
+EOF
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+/* Look through an expression for an assignment statement. */
+
+static void
+gld${EMULATION_NAME}_find_exp_assignment (etree_type *exp)
+{
+ struct bfd_link_hash_entry *h;
+
+ switch (exp->type.node_class)
+ {
+ case etree_provide:
+ h = bfd_link_hash_lookup (link_info.hash, exp->assign.dst,
+ FALSE, FALSE, FALSE);
+ if (h == NULL)
+ break;
+
+ /* We call record_link_assignment even if the symbol is defined.
+ This is because if it is defined by a dynamic object, we
+ actually want to use the value defined by the linker script,
+ not the value from the dynamic object (because we are setting
+ symbols like etext). If the symbol is defined by a regular
+ object, then, as it happens, calling record_link_assignment
+ will do no harm. */
+
+ /* Fall through. */
+ case etree_assign:
+ if (strcmp (exp->assign.dst, ".") != 0)
+ {
+ if (! (bfd_elf_record_link_assignment
+ (output_bfd, &link_info, exp->assign.dst,
+ exp->type.node_class == etree_provide ? TRUE : FALSE)))
+ einfo ("%P%F: failed to record assignment to %s: %E\n",
+ exp->assign.dst);
+ }
+ gld${EMULATION_NAME}_find_exp_assignment (exp->assign.src);
+ break;
+
+ case etree_binary:
+ gld${EMULATION_NAME}_find_exp_assignment (exp->binary.lhs);
+ gld${EMULATION_NAME}_find_exp_assignment (exp->binary.rhs);
+ break;
+
+ case etree_trinary:
+ gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.cond);
+ gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs);
+ gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.rhs);
+ break;
+
+ case etree_unary:
+ gld${EMULATION_NAME}_find_exp_assignment (exp->unary.child);
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+/* This is called by the before_allocation routine via
+ lang_for_each_statement. It locates any assignment statements, and
+ tells the ELF backend about them, in case they are assignments to
+ symbols which are referred to by dynamic objects. */
+
+static void
+gld${EMULATION_NAME}_find_statement_assignment (lang_statement_union_type *s)
+{
+ if (s->header.type == lang_assignment_statement_enum)
+ gld${EMULATION_NAME}_find_exp_assignment (s->assignment_statement.exp);
+}
+
+EOF
+
+if test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation; then
+ if test x"${ELF_INTERPRETER_NAME+set}" = xset; then
+ ELF_INTERPRETER_SET_DEFAULT="
+ if (sinterp != NULL)
+ {
+ sinterp->contents = ${ELF_INTERPRETER_NAME};
+ sinterp->_raw_size = strlen (sinterp->contents) + 1;
+ }
+
+"
+ else
+ ELF_INTERPRETER_SET_DEFAULT=
+ fi
+cat >>e${EMULATION_NAME}.c <<EOF
+
+/* This is called after the sections have been attached to output
+ sections, but before any sizes or addresses have been set. */
+
+static void
+gld${EMULATION_NAME}_before_allocation (void)
+{
+ const char *rpath;
+ asection *sinterp;
+
+ if (link_info.hash->type == bfd_link_elf_hash_table)
+ _bfd_elf_tls_setup (output_bfd, &link_info);
+
+ /* If we are going to make any variable assignments, we need to let
+ the ELF backend know about them in case the variables are
+ referred to by dynamic objects. */
+ lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment);
+
+ /* Let the ELF backend work out the sizes of any sections required
+ by dynamic linking. */
+ rpath = command_line.rpath;
+ if (rpath == NULL)
+ rpath = (const char *) getenv ("LD_RUN_PATH");
+ if (! (bfd_elf_size_dynamic_sections
+ (output_bfd, command_line.soname, rpath,
+ command_line.filter_shlib,
+ (const char * const *) command_line.auxiliary_filters,
+ &link_info, &sinterp, lang_elf_version_info)))
+ einfo ("%P%F: failed to set dynamic section sizes: %E\n");
+${ELF_INTERPRETER_SET_DEFAULT}
+ /* Let the user override the dynamic linker we are using. */
+ if (command_line.interpreter != NULL
+ && sinterp != NULL)
+ {
+ sinterp->contents = (bfd_byte *) command_line.interpreter;
+ sinterp->_raw_size = strlen (command_line.interpreter) + 1;
+ }
+
+ /* Look for any sections named .gnu.warning. As a GNU extensions,
+ we treat such sections as containing warning messages. We print
+ out the warning message, and then zero out the section size so
+ that it does not get copied into the output file. */
+
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (is)
+ {
+ asection *s;
+ bfd_size_type sz;
+ bfd_size_type prefix_len;
+ char *msg;
+ bfd_boolean ret;
+ const char * gnu_warning_prefix = _("warning: ");
+
+ if (is->just_syms_flag)
+ continue;
+
+ s = bfd_get_section_by_name (is->the_bfd, ".gnu.warning");
+ if (s == NULL)
+ continue;
+
+ sz = bfd_section_size (is->the_bfd, s);
+ prefix_len = strlen (gnu_warning_prefix);
+ msg = xmalloc ((size_t) (prefix_len + sz + 1));
+ strcpy (msg, gnu_warning_prefix);
+ if (! bfd_get_section_contents (is->the_bfd, s, msg + prefix_len,
+ (file_ptr) 0, sz))
+ einfo ("%F%B: Can't read contents of section .gnu.warning: %E\n",
+ is->the_bfd);
+ msg[prefix_len + sz] = '\0';
+ ret = link_info.callbacks->warning (&link_info, msg,
+ (const char *) NULL,
+ is->the_bfd, (asection *) NULL,
+ (bfd_vma) 0);
+ ASSERT (ret);
+ free (msg);
+
+ /* Clobber the section size, so that we don't waste copying the
+ warning into the output file. */
+ s->_raw_size = 0;
+ }
+ }
+}
+
+EOF
+fi
+
+if test x"$LDEMUL_OPEN_DYNAMIC_ARCHIVE" != xgld"$EMULATION_NAME"_open_dynamic_archive; then
+cat >>e${EMULATION_NAME}.c <<EOF
+
+/* Try to open a dynamic archive. This is where we know that ELF
+ dynamic libraries have an extension of .so (or .sl on oddball systems
+ like hpux). */
+
+static bfd_boolean
+gld${EMULATION_NAME}_open_dynamic_archive
+ (const char *arch, search_dirs_type *search, lang_input_statement_type *entry)
+{
+ const char *filename;
+ char *string;
+
+ if (! entry->is_archive)
+ return FALSE;
+
+ filename = entry->filename;
+
+ /* This allocates a few bytes too many when EXTRA_SHLIB_EXTENSION
+ is defined, but it does not seem worth the headache to optimize
+ away those two bytes of space. */
+ string = (char *) xmalloc (strlen (search->name)
+ + strlen (filename)
+ + strlen (arch)
+#ifdef EXTRA_SHLIB_EXTENSION
+ + strlen (EXTRA_SHLIB_EXTENSION)
+#endif
+ + sizeof "/lib.so");
+
+ sprintf (string, "%s/lib%s%s.so", search->name, filename, arch);
+
+#ifdef EXTRA_SHLIB_EXTENSION
+ /* Try the .so extension first. If that fails build a new filename
+ using EXTRA_SHLIB_EXTENSION. */
+ if (! ldfile_try_open_bfd (string, entry))
+ sprintf (string, "%s/lib%s%s%s", search->name,
+ filename, arch, EXTRA_SHLIB_EXTENSION);
+#endif
+
+ if (! ldfile_try_open_bfd (string, entry))
+ {
+ free (string);
+ return FALSE;
+ }
+
+ entry->filename = string;
+
+ /* We have found a dynamic object to include in the link. The ELF
+ backend linker will create a DT_NEEDED entry in the .dynamic
+ section naming this file. If this file includes a DT_SONAME
+ entry, it will be used. Otherwise, the ELF linker will just use
+ the name of the file. For an archive found by searching, like
+ this one, the DT_NEEDED entry should consist of just the name of
+ the file, without the path information used to find it. Note
+ that we only need to do this if we have a dynamic object; an
+ archive will never be referenced by a DT_NEEDED entry.
+
+ FIXME: This approach--using bfd_elf_set_dt_needed_name--is not
+ very pretty. I haven't been able to think of anything that is
+ pretty, though. */
+ if (bfd_check_format (entry->the_bfd, bfd_object)
+ && (entry->the_bfd->flags & DYNAMIC) != 0)
+ {
+ ASSERT (entry->is_archive && entry->search_dirs_flag);
+
+ /* Rather than duplicating the logic above. Just use the
+ filename we recorded earlier. */
+
+ filename = lbasename (entry->filename);
+ bfd_elf_set_dt_needed_name (entry->the_bfd, filename);
+ }
+
+ return TRUE;
+}
+
+EOF
+fi
+
+if test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then
+cat >>e${EMULATION_NAME}.c <<EOF
+
+/* A variant of lang_output_section_find. Used by place_orphan. */
+
+static lang_output_section_statement_type *
+output_rel_find (asection *sec, int isdyn)
+{
+ lang_statement_union_type *u;
+ lang_output_section_statement_type *lookup;
+ lang_output_section_statement_type *last = NULL;
+ lang_output_section_statement_type *last_alloc = NULL;
+ lang_output_section_statement_type *last_rel = NULL;
+ lang_output_section_statement_type *last_rel_alloc = NULL;
+ int rela = sec->name[4] == 'a';
+
+ for (u = lang_output_section_statement.head; u; u = lookup->next)
+ {
+ lookup = &u->output_section_statement;
+ if (strncmp (".rel", lookup->name, 4) == 0)
+ {
+ int lookrela = lookup->name[4] == 'a';
+
+ /* .rel.dyn must come before all other reloc sections, to suit
+ GNU ld.so. */
+ if (isdyn)
+ break;
+
+ /* Don't place after .rel.plt as doing so results in wrong
+ dynamic tags. */
+ if (strcmp (".plt", lookup->name + 4 + lookrela) == 0)
+ break;
+
+ if (rela == lookrela || last_rel == NULL)
+ last_rel = lookup;
+ if ((rela == lookrela || last_rel_alloc == NULL)
+ && lookup->bfd_section != NULL
+ && (lookup->bfd_section->flags & SEC_ALLOC) != 0)
+ last_rel_alloc = lookup;
+ }
+
+ last = lookup;
+ if (lookup->bfd_section != NULL
+ && (lookup->bfd_section->flags & SEC_ALLOC) != 0)
+ last_alloc = lookup;
+ }
+
+ if (last_rel_alloc)
+ return last_rel_alloc;
+
+ if (last_rel)
+ return last_rel;
+
+ if (last_alloc)
+ return last_alloc;
+
+ return last;
+}
+
+/* Find the last output section before given output statement.
+ Used by place_orphan. */
+
+static asection *
+output_prev_sec_find (lang_output_section_statement_type *os)
+{
+ asection *s = (asection *) NULL;
+ lang_statement_union_type *u;
+ lang_output_section_statement_type *lookup;
+
+ for (u = lang_output_section_statement.head;
+ u != (lang_statement_union_type *) NULL;
+ u = lookup->next)
+ {
+ lookup = &u->output_section_statement;
+ if (lookup == os)
+ return s;
+
+ if (lookup->bfd_section != NULL && lookup->bfd_section->owner != NULL)
+ s = lookup->bfd_section;
+ }
+
+ return NULL;
+}
+
+/* Place an orphan section. We use this to put random SHF_ALLOC
+ sections in the right segment. */
+
+struct orphan_save {
+ lang_output_section_statement_type *os;
+ asection **section;
+ lang_statement_union_type **stmt;
+ lang_statement_union_type **os_tail;
+};
+
+static bfd_boolean
+gld${EMULATION_NAME}_place_orphan (lang_input_statement_type *file, asection *s)
+{
+ static struct orphan_save hold_text;
+ static struct orphan_save hold_rodata;
+ static struct orphan_save hold_data;
+ static struct orphan_save hold_bss;
+ static struct orphan_save hold_rel;
+ static struct orphan_save hold_interp;
+ static struct orphan_save hold_sdata;
+ static int count = 1;
+ struct orphan_save *place;
+ lang_statement_list_type *old;
+ lang_statement_list_type add;
+ etree_type *address;
+ const char *secname;
+ const char *ps = NULL;
+ lang_output_section_statement_type *os;
+ lang_statement_union_type **os_tail;
+ etree_type *load_base;
+ int isdyn = 0;
+
+ secname = bfd_get_section_name (s->owner, s);
+ if (! link_info.relocatable
+ && link_info.combreloc
+ && (s->flags & SEC_ALLOC)
+ && strncmp (secname, ".rel", 4) == 0)
+ {
+ if (secname[4] == 'a')
+ secname = ".rela.dyn";
+ else
+ secname = ".rel.dyn";
+ isdyn = 1;
+ }
+
+ if (isdyn || (!config.unique_orphan_sections && !unique_section_p (secname)))
+ {
+ /* Look through the script to see where to place this section. */
+ os = lang_output_section_find (secname);
+
+ if (os != NULL
+ && (os->bfd_section == NULL
+ || ((s->flags ^ os->bfd_section->flags)
+ & (SEC_LOAD | SEC_ALLOC)) == 0))
+ {
+ /* We already have an output section statement with this
+ name, and its bfd section, if any, has compatible flags. */
+ lang_add_section (&os->children, s, os, file);
+ return TRUE;
+ }
+ }
+
+ if (hold_text.os == NULL)
+ hold_text.os = lang_output_section_find (".text");
+
+ /* If this is a final link, then always put .gnu.warning.SYMBOL
+ sections into the .text section to get them out of the way. */
+ if (link_info.executable
+ && ! link_info.relocatable
+ && strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0
+ && hold_text.os != NULL)
+ {
+ lang_add_section (&hold_text.os->children, s, hold_text.os, file);
+ return TRUE;
+ }
+
+ /* Decide which segment the section should go in based on the
+ section name and section flags. We put loadable .note sections
+ right after the .interp section, so that the PT_NOTE segment is
+ stored right after the program headers where the OS can read it
+ in the first page. */
+#define HAVE_SECTION(hold, name) \
+(hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL)
+
+ if ((s->flags & SEC_EXCLUDE) != 0 && !link_info.relocatable)
+ {
+ if (s->output_section == NULL)
+ s->output_section = bfd_abs_section_ptr;
+ return TRUE;
+ }
+
+ place = NULL;
+ if ((s->flags & SEC_ALLOC) == 0)
+ ;
+ else if ((s->flags & SEC_LOAD) != 0
+ && strncmp (secname, ".note", 5) == 0
+ && HAVE_SECTION (hold_interp, ".interp"))
+ place = &hold_interp;
+ else if ((s->flags & SEC_HAS_CONTENTS) == 0
+ && HAVE_SECTION (hold_bss, ".bss"))
+ place = &hold_bss;
+ else if ((s->flags & SEC_SMALL_DATA) != 0
+ && HAVE_SECTION (hold_sdata, ".sdata"))
+ place = &hold_sdata;
+ else if ((s->flags & SEC_READONLY) == 0
+ && HAVE_SECTION (hold_data, ".data"))
+ place = &hold_data;
+ else if (strncmp (secname, ".rel", 4) == 0
+ && (s->flags & SEC_LOAD) != 0
+ && (hold_rel.os != NULL
+ || (hold_rel.os = output_rel_find (s, isdyn)) != NULL))
+ place = &hold_rel;
+ else if ((s->flags & (SEC_CODE | SEC_READONLY)) == SEC_READONLY
+ && HAVE_SECTION (hold_rodata, ".rodata"))
+ place = &hold_rodata;
+ else if ((s->flags & (SEC_CODE | SEC_READONLY)) == (SEC_CODE | SEC_READONLY)
+ && hold_text.os != NULL)
+ place = &hold_text;
+
+#undef HAVE_SECTION
+
+ /* Choose a unique name for the section. This will be needed if the
+ same section name appears in the input file with different
+ loadable or allocatable characteristics. */
+ if (bfd_get_section_by_name (output_bfd, secname) != NULL)
+ {
+ secname = bfd_get_unique_section_name (output_bfd, secname, &count);
+ if (secname == NULL)
+ einfo ("%F%P: place_orphan failed: %E\n");
+ }
+
+ /* Start building a list of statements for this section.
+ First save the current statement pointer. */
+ old = stat_ptr;
+
+ /* If we have found an appropriate place for the output section
+ statements for this orphan, add them to our own private list,
+ inserting them later into the global statement list. */
+ if (place != NULL)
+ {
+ stat_ptr = &add;
+ lang_list_init (stat_ptr);
+ }
+
+ if (config.build_constructors)
+ {
+ /* If the name of the section is representable in C, then create
+ symbols to mark the start and the end of the section. */
+ for (ps = secname; *ps != '\0'; ps++)
+ if (! ISALNUM (*ps) && *ps != '_')
+ break;
+ if (*ps == '\0')
+ {
+ char *symname;
+ etree_type *e_align;
+
+ symname = (char *) xmalloc (ps - secname + sizeof "__start_");
+ sprintf (symname, "__start_%s", secname);
+ e_align = exp_unop (ALIGN_K,
+ exp_intop ((bfd_vma) 1 << s->alignment_power));
+ lang_add_assignment (exp_assop ('=', symname, e_align));
+ }
+ }
+
+ address = NULL;
+ if (link_info.relocatable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
+ address = exp_intop ((bfd_vma) 0);
+
+ load_base = NULL;
+ if (place != NULL && place->os->load_base != NULL)
+ {
+ etree_type *lma_from_vma;
+ lma_from_vma = exp_binop ('-', place->os->load_base,
+ exp_nameop (ADDR, place->os->name));
+ load_base = exp_binop ('+', lma_from_vma,
+ exp_nameop (ADDR, secname));
+ }
+
+ os_tail = lang_output_section_statement.tail;
+ os = lang_enter_output_section_statement (secname, address, 0,
+ (etree_type *) NULL,
+ (etree_type *) NULL,
+ load_base);
+
+ lang_add_section (&os->children, s, os, file);
+
+ lang_leave_output_section_statement
+ ((bfd_vma) 0, "*default*",
+ (struct lang_output_section_phdr_list *) NULL, NULL);
+
+ if (config.build_constructors && *ps == '\0')
+ {
+ char *symname;
+
+ /* lang_leave_ouput_section_statement resets stat_ptr. Put
+ stat_ptr back where we want it. */
+ if (place != NULL)
+ stat_ptr = &add;
+
+ symname = (char *) xmalloc (ps - secname + sizeof "__stop_");
+ sprintf (symname, "__stop_%s", secname);
+ lang_add_assignment (exp_assop ('=', symname,
+ exp_nameop (NAME, ".")));
+ }
+
+ /* Restore the global list pointer. */
+ stat_ptr = old;
+
+ if (place != NULL && os->bfd_section != NULL)
+ {
+ asection *snew, **pps;
+
+ snew = os->bfd_section;
+
+ /* Shuffle the bfd section list to make the output file look
+ neater. This is really only cosmetic. */
+ if (place->section == NULL)
+ {
+ asection *bfd_section = place->os->bfd_section;
+
+ /* If the output statement hasn't been used to place
+ any input sections (and thus doesn't have an output
+ bfd_section), look for the closest prior output statement
+ having an output section. */
+ if (bfd_section == NULL)
+ bfd_section = output_prev_sec_find (place->os);
+
+ if (bfd_section != NULL && bfd_section != snew)
+ place->section = &bfd_section->next;
+ }
+
+ if (place->section != NULL)
+ {
+ /* Unlink the section. */
+ for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next)
+ ;
+ bfd_section_list_remove (output_bfd, pps);
+
+ /* Now tack it on to the "place->os" section list. */
+ bfd_section_list_insert (output_bfd, place->section, snew);
+ }
+
+ /* Save the end of this list. Further ophans of this type will
+ follow the one we've just added. */
+ place->section = &snew->next;
+
+ /* The following is non-cosmetic. We try to put the output
+ statements in some sort of reasonable order here, because
+ they determine the final load addresses of the orphan
+ sections. In addition, placing output statements in the
+ wrong order may require extra segments. For instance,
+ given a typical situation of all read-only sections placed
+ in one segment and following that a segment containing all
+ the read-write sections, we wouldn't want to place an orphan
+ read/write section before or amongst the read-only ones. */
+ if (add.head != NULL)
+ {
+ lang_statement_union_type *newly_added_os;
+
+ if (place->stmt == NULL)
+ {
+ /* Put the new statement list right at the head. */
+ *add.tail = place->os->header.next;
+ place->os->header.next = add.head;
+
+ place->os_tail = &place->os->next;
+ }
+ else
+ {
+ /* Put it after the last orphan statement we added. */
+ *add.tail = *place->stmt;
+ *place->stmt = add.head;
+ }
+
+ /* Fix the global list pointer if we happened to tack our
+ new list at the tail. */
+ if (*old->tail == add.head)
+ old->tail = add.tail;
+
+ /* Save the end of this list. */
+ place->stmt = add.tail;
+
+ /* Do the same for the list of output section statements. */
+ newly_added_os = *os_tail;
+ *os_tail = NULL;
+ newly_added_os->output_section_statement.next = *place->os_tail;
+ *place->os_tail = newly_added_os;
+ place->os_tail = &newly_added_os->output_section_statement.next;
+
+ /* Fixing the global list pointer here is a little different.
+ We added to the list in lang_enter_output_section_statement,
+ trimmed off the new output_section_statment above when
+ assigning *os_tail = NULL, but possibly added it back in
+ the same place when assigning *place->os_tail. */
+ if (*os_tail == NULL)
+ lang_output_section_statement.tail = os_tail;
+ }
+ }
+
+ return TRUE;
+}
+EOF
+fi
+
+if test x"$LDEMUL_FINISH" != xgld"$EMULATION_NAME"_finish; then
+cat >>e${EMULATION_NAME}.c <<EOF
+
+static void
+gld${EMULATION_NAME}_finish (void)
+{
+ if (bfd_elf_discard_info (output_bfd, &link_info))
+ {
+ lang_reset_memory_regions ();
+
+ /* Resize the sections. */
+ lang_size_sections (stat_ptr->head, abs_output_section,
+ &stat_ptr->head, 0, (bfd_vma) 0, NULL, TRUE);
+
+ /* Redo special stuff. */
+ ldemul_after_allocation ();
+
+ /* Do the assignments again. */
+ lang_do_assignments (stat_ptr->head, abs_output_section,
+ (fill_type *) 0, (bfd_vma) 0);
+ }
+}
+EOF
+fi
+
+if test x"$LDEMUL_GET_SCRIPT" != xgld"$EMULATION_NAME"_get_script; then
+cat >>e${EMULATION_NAME}.c <<EOF
+
+static char *
+gld${EMULATION_NAME}_get_script (int *isfile)
+EOF
+
+if test -n "$COMPILE_IN"
+then
+# Scripts compiled in.
+
+# sed commands to quote an ld script as a C string.
+sc="-f stringify.sed"
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 0;
+
+ if (link_info.relocatable && config.build_constructors)
+ return
+EOF
+sed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c
+echo ' ; else if (link_info.relocatable) 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
+if cmp -s ldscripts/${EMULATION_NAME}.x ldscripts/${EMULATION_NAME}.xn; then : ; else
+echo ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c
+fi
+if test -n "$GENERATE_PIE_SCRIPT" ; then
+if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
+echo ' ; else if (link_info.pie && link_info.combreloc) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xdc >> e${EMULATION_NAME}.c
+fi
+echo ' ; else if (link_info.pie) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xd >> e${EMULATION_NAME}.c
+fi
+if test -n "$GENERATE_SHLIB_SCRIPT" ; then
+if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
+echo ' ; else if (link_info.shared && link_info.combreloc) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xsc >> e${EMULATION_NAME}.c
+fi
+echo ' ; else if (link_info.shared) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xs >> e${EMULATION_NAME}.c
+fi
+if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
+echo ' ; else if (link_info.combreloc) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xc >> e${EMULATION_NAME}.c
+fi
+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
+{
+ *isfile = 1;
+
+ if (link_info.relocatable && config.build_constructors)
+ return "ldscripts/${EMULATION_NAME}.xu";
+ else if (link_info.relocatable)
+ return "ldscripts/${EMULATION_NAME}.xr";
+ else if (!config.text_read_only)
+ return "ldscripts/${EMULATION_NAME}.xbn";
+EOF
+if cmp -s ldscripts/${EMULATION_NAME}.x ldscripts/${EMULATION_NAME}.xn; then :
+else
+cat >>e${EMULATION_NAME}.c <<EOF
+ else if (!config.magic_demand_paged)
+ return "ldscripts/${EMULATION_NAME}.xn";
+EOF
+fi
+if test -n "$GENERATE_PIE_SCRIPT" ; then
+if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ else if (link_info.pie && link_info.combreloc)
+ return "ldscripts/${EMULATION_NAME}.xdc";
+EOF
+fi
+cat >>e${EMULATION_NAME}.c <<EOF
+ else if (link_info.pie)
+ return "ldscripts/${EMULATION_NAME}.xd";
+EOF
+fi
+if test -n "$GENERATE_SHLIB_SCRIPT" ; then
+if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ else if (link_info.shared && link_info.combreloc)
+ return "ldscripts/${EMULATION_NAME}.xsc";
+EOF
+fi
+cat >>e${EMULATION_NAME}.c <<EOF
+ else if (link_info.shared)
+ return "ldscripts/${EMULATION_NAME}.xs";
+EOF
+fi
+if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ else if (link_info.combreloc)
+ return "ldscripts/${EMULATION_NAME}.xc";
+EOF
+fi
+cat >>e${EMULATION_NAME}.c <<EOF
+ else
+ return "ldscripts/${EMULATION_NAME}.x";
+}
+
+EOF
+fi
+fi
+
+if test -n "$PARSE_AND_LIST_ARGS_CASES" -o x"$GENERATE_SHLIB_SCRIPT" = xyes; then
+
+if test -n "$PARSE_AND_LIST_PROLOGUE" ; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ $PARSE_AND_LIST_PROLOGUE
+EOF
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+#define OPTION_DISABLE_NEW_DTAGS (400)
+#define OPTION_ENABLE_NEW_DTAGS (OPTION_DISABLE_NEW_DTAGS + 1)
+#define OPTION_GROUP (OPTION_ENABLE_NEW_DTAGS + 1)
+#define OPTION_EH_FRAME_HDR (OPTION_GROUP + 1)
+
+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[] = "${PARSE_AND_LIST_SHORTOPTS}z:";
+ static const struct option xtra_long[] = {
+EOF
+
+if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS},
+ {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS},
+ {"eh-frame-hdr", no_argument, NULL, OPTION_EH_FRAME_HDR},
+ {"Bgroup", no_argument, NULL, OPTION_GROUP},
+EOF
+fi
+
+if test -n "$PARSE_AND_LIST_LONGOPTS" ; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ $PARSE_AND_LIST_LONGOPTS
+EOF
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+ {NULL, no_argument, NULL, 0}
+ };
+
+ *shortopts = (char *) xrealloc (*shortopts, ns + sizeof (xtra_short));
+ memcpy (*shortopts + ns, &xtra_short, sizeof (xtra_short));
+ *longopts = (struct option *)
+ xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long));
+ memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
+}
+
+static bfd_boolean
+gld${EMULATION_NAME}_handle_option (int optc)
+{
+ switch (optc)
+ {
+ default:
+ return FALSE;
+
+EOF
+
+if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ case OPTION_DISABLE_NEW_DTAGS:
+ link_info.new_dtags = FALSE;
+ break;
+
+ case OPTION_ENABLE_NEW_DTAGS:
+ link_info.new_dtags = TRUE;
+ break;
+
+ case OPTION_EH_FRAME_HDR:
+ link_info.eh_frame_hdr = TRUE;
+ break;
+
+ case OPTION_GROUP:
+ link_info.flags_1 |= (bfd_vma) DF_1_GROUP;
+ /* Groups must be self-contained. */
+ link_info.unresolved_syms_in_objects = RM_GENERATE_ERROR;
+ link_info.unresolved_syms_in_shared_libs = RM_GENERATE_ERROR;
+ break;
+
+ case 'z':
+ if (strcmp (optarg, "initfirst") == 0)
+ link_info.flags_1 |= (bfd_vma) DF_1_INITFIRST;
+ else if (strcmp (optarg, "interpose") == 0)
+ link_info.flags_1 |= (bfd_vma) DF_1_INTERPOSE;
+ else if (strcmp (optarg, "loadfltr") == 0)
+ link_info.flags_1 |= (bfd_vma) DF_1_LOADFLTR;
+ else if (strcmp (optarg, "nodefaultlib") == 0)
+ link_info.flags_1 |= (bfd_vma) DF_1_NODEFLIB;
+ else if (strcmp (optarg, "nodelete") == 0)
+ link_info.flags_1 |= (bfd_vma) DF_1_NODELETE;
+ else if (strcmp (optarg, "nodlopen") == 0)
+ link_info.flags_1 |= (bfd_vma) DF_1_NOOPEN;
+ else if (strcmp (optarg, "nodump") == 0)
+ link_info.flags_1 |= (bfd_vma) DF_1_NODUMP;
+ else if (strcmp (optarg, "now") == 0)
+ {
+ link_info.flags |= (bfd_vma) DF_BIND_NOW;
+ link_info.flags_1 |= (bfd_vma) DF_1_NOW;
+ }
+ else if (strcmp (optarg, "origin") == 0)
+ {
+ link_info.flags |= (bfd_vma) DF_ORIGIN;
+ link_info.flags_1 |= (bfd_vma) DF_1_ORIGIN;
+ }
+ else if (strcmp (optarg, "defs") == 0)
+ link_info.unresolved_syms_in_objects = RM_GENERATE_ERROR;
+ else if (strcmp (optarg, "muldefs") == 0)
+ link_info.allow_multiple_definition = TRUE;
+ else if (strcmp (optarg, "combreloc") == 0)
+ link_info.combreloc = TRUE;
+ else if (strcmp (optarg, "nocombreloc") == 0)
+ link_info.combreloc = FALSE;
+ else if (strcmp (optarg, "nocopyreloc") == 0)
+ link_info.nocopyreloc = TRUE;
+ else if (strcmp (optarg, "execstack") == 0)
+ {
+ link_info.execstack = TRUE;
+ link_info.noexecstack = FALSE;
+ }
+ else if (strcmp (optarg, "noexecstack") == 0)
+ {
+ link_info.noexecstack = TRUE;
+ link_info.execstack = FALSE;
+ }
+ /* What about the other Solaris -z options? FIXME. */
+ break;
+EOF
+fi
+
+if test -n "$PARSE_AND_LIST_ARGS_CASES" ; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ $PARSE_AND_LIST_ARGS_CASES
+EOF
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+ }
+
+ return TRUE;
+}
+
+EOF
+
+if test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
+cat >>e${EMULATION_NAME}.c <<EOF
+
+static void
+gld${EMULATION_NAME}_list_options (FILE * file)
+{
+EOF
+
+if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ fprintf (file, _(" -Bgroup\t\tSelects group name lookup rules for DSO\n"));
+ fprintf (file, _(" --disable-new-dtags\tDisable new dynamic tags\n"));
+ fprintf (file, _(" --enable-new-dtags\tEnable new dynamic tags\n"));
+ fprintf (file, _(" --eh-frame-hdr\tCreate .eh_frame_hdr section\n"));
+ fprintf (file, _(" -z combreloc\t\tMerge dynamic relocs into one section and sort\n"));
+ fprintf (file, _(" -z defs\t\tReport unresolved symbols in object files.\n"));
+ fprintf (file, _(" -z execstack\t\tMark executable as requiring executable stack\n"));
+ fprintf (file, _(" -z initfirst\t\tMark DSO to be initialized first at runtime\n"));
+ fprintf (file, _(" -z interpose\t\tMark object to interpose all DSOs but executable\n"));
+ fprintf (file, _(" -z loadfltr\t\tMark object requiring immediate process\n"));
+ fprintf (file, _(" -z muldefs\t\tAllow multiple definitions\n"));
+ fprintf (file, _(" -z nocombreloc\tDon't merge dynamic relocs into one section\n"));
+ fprintf (file, _(" -z nocopyreloc\tDon't create copy relocs\n"));
+ fprintf (file, _(" -z nodefaultlib\tMark object not to use default search paths\n"));
+ fprintf (file, _(" -z nodelete\t\tMark DSO non-deletable at runtime\n"));
+ fprintf (file, _(" -z nodlopen\t\tMark DSO not available to dlopen\n"));
+ fprintf (file, _(" -z nodump\t\tMark DSO not available to dldump\n"));
+ fprintf (file, _(" -z noexecstack\tMark executable as not requiring executable stack\n"));
+ fprintf (file, _(" -z now\t\tMark object non-lazy runtime binding\n"));
+ fprintf (file, _(" -z origin\t\tMark object requiring immediate \$ORIGIN processing\n\t\t\t at runtime\n"));
+ fprintf (file, _(" -z KEYWORD\t\tIgnored for Solaris compatibility\n"));
+EOF
+fi
+
+if test -n "$PARSE_AND_LIST_OPTIONS" ; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ $PARSE_AND_LIST_OPTIONS
+EOF
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+}
+EOF
+
+if test -n "$PARSE_AND_LIST_EPILOGUE" ; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ $PARSE_AND_LIST_EPILOGUE
+EOF
+fi
+fi
+else
+cat >>e${EMULATION_NAME}.c <<EOF
+#define gld${EMULATION_NAME}_add_options NULL
+#define gld${EMULATION_NAME}_handle_option NULL
+EOF
+if test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
+cat >>e${EMULATION_NAME}.c <<EOF
+#define gld${EMULATION_NAME}_list_options NULL
+EOF
+fi
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
+{
+ ${LDEMUL_BEFORE_PARSE-gld${EMULATION_NAME}_before_parse},
+ ${LDEMUL_SYSLIB-syslib_default},
+ ${LDEMUL_HLL-hll_default},
+ ${LDEMUL_AFTER_PARSE-after_parse_default},
+ ${LDEMUL_AFTER_OPEN-gld${EMULATION_NAME}_after_open},
+ ${LDEMUL_AFTER_ALLOCATION-after_allocation_default},
+ ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default},
+ ${LDEMUL_CHOOSE_TARGET-ldemul_default_target},
+ ${LDEMUL_BEFORE_ALLOCATION-gld${EMULATION_NAME}_before_allocation},
+ ${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script},
+ "${EMULATION_NAME}",
+ "${OUTPUT_FORMAT}",
+ ${LDEMUL_FINISH-gld${EMULATION_NAME}_finish},
+ ${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-NULL},
+ ${LDEMUL_OPEN_DYNAMIC_ARCHIVE-gld${EMULATION_NAME}_open_dynamic_archive},
+ ${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan},
+ ${LDEMUL_SET_SYMBOLS-NULL},
+ ${LDEMUL_PARSE_ARGS-NULL},
+ gld${EMULATION_NAME}_add_options,
+ gld${EMULATION_NAME}_handle_option,
+ ${LDEMUL_UNRECOGNIZED_FILE-NULL},
+ ${LDEMUL_LIST_OPTIONS-gld${EMULATION_NAME}_list_options},
+ ${LDEMUL_RECOGNIZED_FILE-gld${EMULATION_NAME}_load_symbols},
+ ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL},
+ ${LDEMUL_NEW_VERS_PATTERN-NULL}
+};
+EOF
diff --git a/x/binutils/ld/emultempl/generic.em b/x/binutils/ld/emultempl/generic.em
new file mode 100644
index 0000000..4d17ca2
--- /dev/null
+++ b/x/binutils/ld/emultempl/generic.em
@@ -0,0 +1,148 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+cat >e${EMULATION_NAME}.c <<EOF
+/* This file is is generated by a shell script. DO NOT EDIT! */
+
+/* emulate the original gld for the given ${EMULATION_NAME}
+ Copyright 1991, 1992, 1994, 1996, 2000, 2001, 2002, 2003, 2004
+ Free Software Foundation, Inc.
+ Written by Steve Chamberlain steve@cygnus.com
+
+This file is part of GLD, the Gnu Linker.
+
+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 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. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+
+#include "ld.h"
+#include "ldmain.h"
+#include "ldmisc.h"
+
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldfile.h"
+#include "ldemul.h"
+
+EOF
+
+# Import any needed special functions and/or overrides.
+#
+if test -n "$EXTRA_EM_FILE" ; then
+. ${srcdir}/emultempl/${EXTRA_EM_FILE}.em
+fi
+
+if test x"$LDEMUL_BEFORE_PARSE" != xgld"$EMULATION_NAME"_before_parse; then
+cat >>e${EMULATION_NAME}.c <<EOF
+
+static void
+gld${EMULATION_NAME}_before_parse (void)
+{
+#ifndef TARGET_ /* I.e., if not generic. */
+ ldfile_set_output_arch ("`echo ${ARCH}`", bfd_arch_unknown);
+#endif /* not TARGET_ */
+}
+
+EOF
+fi
+
+if test x"$LDEMUL_GET_SCRIPT" != xgld"$EMULATION_NAME"_get_script; then
+cat >>e${EMULATION_NAME}.c <<EOF
+
+static char *
+gld${EMULATION_NAME}_get_script (int *isfile)
+EOF
+
+if test -n "$COMPILE_IN"
+then
+# Scripts compiled in.
+
+# sed commands to quote an ld script as a C string.
+sc="-f stringify.sed"
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 0;
+
+ if (link_info.relocatable && config.build_constructors)
+ return
+EOF
+sed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c
+echo ' ; else if (link_info.relocatable) 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
+{
+ *isfile = 1;
+
+ if (link_info.relocatable && config.build_constructors)
+ return "ldscripts/${EMULATION_NAME}.xu";
+ else if (link_info.relocatable)
+ return "ldscripts/${EMULATION_NAME}.xr";
+ else if (!config.text_read_only)
+ return "ldscripts/${EMULATION_NAME}.xbn";
+ else if (!config.magic_demand_paged)
+ return "ldscripts/${EMULATION_NAME}.xn";
+ else
+ return "ldscripts/${EMULATION_NAME}.x";
+}
+EOF
+fi
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
+{
+ ${LDEMUL_BEFORE_PARSE-gld${EMULATION_NAME}_before_parse},
+ ${LDEMUL_SYSLIB-syslib_default},
+ ${LDEMUL_HLL-hll_default},
+ ${LDEMUL_AFTER_PARSE-after_parse_default},
+ ${LDEMUL_AFTER_OPEN-after_open_default},
+ ${LDEMUL_AFTER_ALLOCATION-after_allocation_default},
+ ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default},
+ ${LDEMUL_CHOOSE_TARGET-ldemul_default_target},
+ ${LDEMUL_BEFORE_ALLOCATION-before_allocation_default},
+ ${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script},
+ "${EMULATION_NAME}",
+ "${OUTPUT_FORMAT}",
+ ${LDEMUL_FINISH-NULL},
+ ${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-NULL},
+ ${LDEMUL_OPEN_DYNAMIC_ARCHIVE-NULL},
+ ${LDEMUL_PLACE_ORPHAN-NULL},
+ ${LDEMUL_SET_SYMBOLS-NULL},
+ ${LDEMUL_PARSE_ARGS-NULL},
+ NULL, /* add_options */
+ NULL, /* handle_option */
+ ${LDEMUL_UNRECOGNIZED_FILE-NULL},
+ ${LDEMUL_LIST_OPTIONS-NULL},
+ ${LDEMUL_RECOGNIZED_FILE-NULL},
+ ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL},
+ ${LDEMUL_NEW_VERS_PATTERN-NULL}
+};
+EOF
diff --git a/x/binutils/ld/emultempl/ia64elf.em b/x/binutils/ld/emultempl/ia64elf.em
new file mode 100644
index 0000000..eee467b
--- /dev/null
+++ b/x/binutils/ld/emultempl/ia64elf.em
@@ -0,0 +1,62 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2003 Free Software Foundation, Inc.
+#
+# This file is part of GLD, the Gnu Linker.
+#
+# 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 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.
+#
+
+# This file is sourced from elf32.em, and defines extra ia64-elf
+# specific routines.
+#
+# Define some shell vars to insert bits of code into the standard elf
+# parse_args and list_options functions.
+#
+cat >>e${EMULATION_NAME}.c <<EOF
+
+/* None zero if generating binary for Intel Itanium processor. */
+static int itanium = 0;
+
+static void
+gld${EMULATION_NAME}_after_parse (void)
+{
+ link_info.need_relax_finalize = TRUE;
+ bfd_elf${ELFSIZE}_ia64_after_parse (itanium);
+}
+
+EOF
+
+PARSE_AND_LIST_PROLOGUE='
+#define OPTION_ITANIUM 300
+'
+
+PARSE_AND_LIST_LONGOPTS='
+ { "itanium", no_argument, NULL, OPTION_ITANIUM},
+'
+
+PARSE_AND_LIST_OPTIONS='
+ fprintf (file, _("\
+ --itanium Generate code for Intel Itanium processor\n"
+ ));
+'
+
+PARSE_AND_LIST_ARGS_CASES='
+ case OPTION_ITANIUM:
+ itanium = 1;
+ break;
+'
+
+LDEMUL_AFTER_PARSE=gld${EMULATION_NAME}_after_parse
+. ${srcdir}/emultempl/needrelax.em
diff --git a/x/binutils/ld/emultempl/linux.em b/x/binutils/ld/emultempl/linux.em
new file mode 100644
index 0000000..d041b68
--- /dev/null
+++ b/x/binutils/ld/emultempl/linux.em
@@ -0,0 +1,207 @@
+# 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! */
+
+/* Linux a.out emulation code for ${EMULATION_NAME}
+ Copyright 1991, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2002, 2003, 2004
+ Free Software Foundation, Inc.
+ Written by Steve Chamberlain <sac@cygnus.com>
+ Linux support by Eric Youngdale <ericy@cais.cais.com>
+
+This file is part of GLD, the Gnu Linker.
+
+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 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. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+
+#include "ld.h"
+#include "ldmain.h"
+#include "ldmisc.h"
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldfile.h"
+#include "ldemul.h"
+
+static void
+gld${EMULATION_NAME}_before_parse (void)
+{
+ ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`);
+ config.dynamic_link = TRUE;
+ config.has_shared = TRUE;
+}
+
+/* Try to open a dynamic archive. This is where we know that Linux
+ dynamic libraries have an extension of .sa. */
+
+static bfd_boolean
+gld${EMULATION_NAME}_open_dynamic_archive
+ (const char *arch, search_dirs_type *search, lang_input_statement_type *entry)
+{
+ char *string;
+
+ if (! entry->is_archive)
+ return FALSE;
+
+ string = (char *) xmalloc (strlen (search->name)
+ + strlen (entry->filename)
+ + strlen (arch)
+ + sizeof "/lib.sa");
+
+ sprintf (string, "%s/lib%s%s.sa", search->name, entry->filename, arch);
+
+ if (! ldfile_try_open_bfd (string, entry))
+ {
+ free (string);
+ return FALSE;
+ }
+
+ entry->filename = string;
+
+ return TRUE;
+}
+
+/* This is called by the create_output_section_statements routine via
+ lang_for_each_statement. It locates any address assignment to
+ .text, and modifies it to include the size of the headers. This
+ causes -Ttext to mean the starting address of the header, rather
+ than the starting address of .text, which is compatible with other
+ Linux tools. */
+
+static void
+gld${EMULATION_NAME}_find_address_statement (lang_statement_union_type *s)
+{
+ if (s->header.type == lang_address_statement_enum
+ && strcmp (s->address_statement.section_name, ".text") == 0)
+ {
+ ASSERT (s->address_statement.address->type.node_class == etree_value);
+ s->address_statement.address->value.value += 0x20;
+ }
+}
+
+/* This is called before opening the input BFD's. */
+
+static void
+gld${EMULATION_NAME}_create_output_section_statements (void)
+{
+ lang_for_each_statement (gld${EMULATION_NAME}_find_address_statement);
+}
+
+/* This is called after the sections have been attached to output
+ sections, but before any sizes or addresses have been set. */
+
+static void
+gld${EMULATION_NAME}_before_allocation (void)
+{
+ if (link_info.relocatable)
+ return;
+
+ /* Let the backend work out the sizes of any sections required by
+ dynamic linking. */
+ if (! bfd_${EMULATION_NAME}_size_dynamic_sections (output_bfd, &link_info))
+ einfo ("%P%F: failed to set dynamic section sizes: %E\n");
+}
+
+static char *
+gld${EMULATION_NAME}_get_script (int *isfile)
+EOF
+
+if test -n "$COMPILE_IN"
+then
+# Scripts compiled in.
+
+# sed commands to quote an ld script as a C string.
+sc="-f stringify.sed"
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 0;
+
+ if (link_info.relocatable && config.build_constructors)
+ return
+EOF
+sed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c
+echo ' ; else if (link_info.relocatable) 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
+{
+ *isfile = 1;
+
+ if (link_info.relocatable && config.build_constructors)
+ return "ldscripts/${EMULATION_NAME}.xu";
+ else if (link_info.relocatable)
+ return "ldscripts/${EMULATION_NAME}.xr";
+ else if (!config.text_read_only)
+ return "ldscripts/${EMULATION_NAME}.xbn";
+ else if (!config.magic_demand_paged)
+ return "ldscripts/${EMULATION_NAME}.xn";
+ else
+ return "ldscripts/${EMULATION_NAME}.x";
+}
+EOF
+
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
+{
+ gld${EMULATION_NAME}_before_parse,
+ syslib_default,
+ hll_default,
+ after_parse_default,
+ after_open_default,
+ after_allocation_default,
+ set_output_arch_default,
+ ldemul_default_target,
+ gld${EMULATION_NAME}_before_allocation,
+ gld${EMULATION_NAME}_get_script,
+ "${EMULATION_NAME}",
+ "${OUTPUT_FORMAT}",
+ NULL, /* finish */
+ gld${EMULATION_NAME}_create_output_section_statements,
+ gld${EMULATION_NAME}_open_dynamic_archive,
+ NULL, /* place orphan */
+ NULL, /* set symbols */
+ NULL, /* parse args */
+ NULL, /* add_options */
+ NULL, /* handle_option */
+ NULL, /* unrecognized file */
+ NULL, /* list options */
+ NULL, /* recognized file */
+ NULL, /* find_potential_libraries */
+ NULL /* new_vers_pattern */
+};
+EOF
diff --git a/x/binutils/ld/emultempl/mipsecoff.em b/x/binutils/ld/emultempl/mipsecoff.em
new file mode 100644
index 0000000..dde33c2
--- /dev/null
+++ b/x/binutils/ld/emultempl/mipsecoff.em
@@ -0,0 +1,248 @@
+# 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! */
+
+/* Handle embedded relocs for MIPS.
+ Copyright 1994, 1995, 1997, 2000, 2002, 2003, 2004
+ Free Software Foundation, Inc.
+ Written by Ian Lance Taylor <ian@cygnus.com> based on generic.em.
+
+This file is part of GLD, the Gnu Linker.
+
+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 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. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+
+#include "ld.h"
+#include "ldmain.h"
+#include "ldmisc.h"
+
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldfile.h"
+#include "ldemul.h"
+
+static void check_sections (bfd *, asection *, void *);
+
+static void
+gld${EMULATION_NAME}_before_parse (void)
+{
+#ifndef TARGET_ /* I.e., if not generic. */
+ ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`);
+#endif /* not TARGET_ */
+}
+
+/* This function is run after all the input files have been opened.
+ We create a .rel.sdata section for each input file with a non zero
+ .sdata section. The BFD backend will fill in these sections with
+ magic numbers which can be used to relocate the data section at run
+ time. This will only do the right thing if all the input files
+ have been compiled using -membedded-pic. */
+
+static void
+gld${EMULATION_NAME}_after_open (void)
+{
+ bfd *abfd;
+
+ if (! command_line.embedded_relocs
+ || link_info.relocatable)
+ return;
+
+ for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link_next)
+ {
+ asection *datasec;
+
+ /* As first-order business, make sure that each input BFD is ECOFF. It
+ better be, as we are directly calling an ECOFF backend function. */
+ if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour)
+ einfo ("%F%B: all input objects must be ECOFF for --embedded-relocs\n");
+
+ datasec = bfd_get_section_by_name (abfd, ".sdata");
+
+ /* Note that we assume that the reloc_count field has already
+ been set up. We could call bfd_get_reloc_upper_bound, but
+ that returns the size of a memory buffer rather than a reloc
+ count. We do not want to call bfd_canonicalize_reloc,
+ because although it would always work it would force us to
+ read in the relocs into BFD canonical form, which would waste
+ a significant amount of time and memory. */
+ if (datasec != NULL && datasec->reloc_count > 0)
+ {
+ asection *relsec;
+
+ relsec = bfd_make_section (abfd, ".rel.sdata");
+ if (relsec == NULL
+ || ! bfd_set_section_flags (abfd, relsec,
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY))
+ || ! bfd_set_section_alignment (abfd, relsec, 2)
+ || ! bfd_set_section_size (abfd, relsec,
+ datasec->reloc_count * 4))
+ einfo ("%F%B: can not create .rel.sdata section: %E\n");
+ }
+
+ /* Double check that all other data sections are empty, as is
+ required for embedded PIC code. */
+ bfd_map_over_sections (abfd, check_sections, datasec);
+ }
+}
+
+/* Check that of the data sections, only the .sdata section has
+ relocs. This is called via bfd_map_over_sections. */
+
+static void
+check_sections (bfd *abfd, asection *sec, void *sdatasec)
+{
+ if ((bfd_get_section_flags (abfd, sec) & SEC_CODE) == 0
+ && sec != sdatasec
+ && sec->reloc_count != 0)
+ einfo ("%B%X: section %s has relocs; can not use --embedded-relocs\n",
+ abfd, bfd_get_section_name (abfd, sec));
+}
+
+/* This function is called after the section sizes and offsets have
+ been set. If we are generating embedded relocs, it calls a special
+ BFD backend routine to do the work. */
+
+static void
+gld${EMULATION_NAME}_after_allocation (void)
+{
+ bfd *abfd;
+
+ if (! command_line.embedded_relocs
+ || link_info.relocatable)
+ return;
+
+ for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link_next)
+ {
+ asection *datasec, *relsec;
+ char *errmsg;
+
+ datasec = bfd_get_section_by_name (abfd, ".sdata");
+
+ if (datasec == NULL || datasec->reloc_count == 0)
+ continue;
+
+ relsec = bfd_get_section_by_name (abfd, ".rel.sdata");
+ ASSERT (relsec != NULL);
+
+ if (! bfd_mips_ecoff_create_embedded_relocs (abfd, &link_info,
+ datasec, relsec,
+ &errmsg))
+ {
+ if (errmsg == NULL)
+ einfo ("%B%X: can not create runtime reloc information: %E\n",
+ abfd);
+ else
+ einfo ("%X%B: can not create runtime reloc information: %s\n",
+ abfd, errmsg);
+ }
+ }
+}
+
+static char *
+gld${EMULATION_NAME}_get_script (int *isfile)
+EOF
+
+if test -n "$COMPILE_IN"
+then
+# Scripts compiled in.
+
+# sed commands to quote an ld script as a C string.
+sc="-f stringify.sed"
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 0;
+
+ if (link_info.relocatable && config.build_constructors)
+ return
+EOF
+sed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c
+echo ' ; else if (link_info.relocatable) 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
+{
+ *isfile = 1;
+
+ if (link_info.relocatable && config.build_constructors)
+ return "ldscripts/${EMULATION_NAME}.xu";
+ else if (link_info.relocatable)
+ return "ldscripts/${EMULATION_NAME}.xr";
+ else if (!config.text_read_only)
+ return "ldscripts/${EMULATION_NAME}.xbn";
+ else if (!config.magic_demand_paged)
+ return "ldscripts/${EMULATION_NAME}.xn";
+ else
+ return "ldscripts/${EMULATION_NAME}.x";
+}
+EOF
+
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+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,
+ gld${EMULATION_NAME}_after_allocation,
+ set_output_arch_default,
+ ldemul_default_target,
+ before_allocation_default,
+ gld${EMULATION_NAME}_get_script,
+ "${EMULATION_NAME}",
+ "${OUTPUT_FORMAT}",
+ NULL, /* finish */
+ NULL, /* create output section statements */
+ NULL, /* open dynamic archive */
+ NULL, /* place orphan */
+ NULL, /* set symbols */
+ NULL, /* parse args */
+ NULL, /* add_options */
+ NULL, /* handle_option */
+ NULL, /* unrecognized file */
+ NULL, /* list options */
+ NULL, /* recognized file */
+ NULL, /* find_potential_libraries */
+ NULL /* new_vers_pattern */
+};
+EOF
diff --git a/x/binutils/ld/emultempl/mipself.em b/x/binutils/ld/emultempl/mipself.em
new file mode 100644
index 0000000..a950fb1
--- /dev/null
+++ b/x/binutils/ld/emultempl/mipself.em
@@ -0,0 +1,177 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2002, 2003 Free Software Foundation, Inc.
+# Written by Mitch Lichtenberg <mpl@broadcom.com> and
+# Chris Demetriou <cgd@broadcom.com> based on m68kelf.em and mipsecoff.em.
+#
+# This file is part of GLD, the Gnu Linker.
+#
+# 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 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.
+
+
+# This file is sourced from elf32.em, and defines some extra routines for m68k
+# embedded systems using ELF and for some other systems using m68k ELF. While
+# it is sourced from elf32.em for all m68k ELF configurations, here we include
+# only the features we want depending on the configuration.
+
+case ${target} in
+ mips*-*-elf)
+ echo "#define SUPPORT_EMBEDDED_RELOCS" >>e${EMULATION_NAME}.c
+ ;;
+esac
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+#ifdef SUPPORT_EMBEDDED_RELOCS
+static void mips_elf${ELFSIZE}_check_sections (bfd *, asection *, void *);
+#endif
+
+/* This function is run after all the input files have been opened. */
+
+static void
+mips_elf${ELFSIZE}_after_open (void)
+{
+ /* Call the standard elf routine. */
+ gld${EMULATION_NAME}_after_open ();
+
+#ifdef SUPPORT_EMBEDDED_RELOCS
+ if (command_line.embedded_relocs && (! link_info.relocatable))
+ {
+ bfd *abfd;
+
+ /* In the embedded relocs mode we create a .rel.sdata section for
+ each input file with a .sdata section which has has
+ relocations. The BFD backend will fill in these sections
+ with magic numbers which can be used to relocate the data
+ section at run time. */
+ for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link_next)
+ {
+ asection *datasec;
+
+ /* As first-order business, make sure that each input BFD is
+ ELF. We need to call a special BFD backend function to
+ generate the embedded relocs, and we have that function
+ only for ELF */
+
+ if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
+ einfo ("%F%B: all input objects must be ELF for --embedded-relocs\n");
+
+ if (bfd_get_arch_size (abfd) != ${ELFSIZE})
+ einfo ("%F%B: all input objects must be ${ELFSIZE}-bit ELF for --embedded-relocs\n");
+
+ datasec = bfd_get_section_by_name (abfd, ".sdata");
+
+ /* Note that we assume that the reloc_count field has already
+ been set up. We could call bfd_get_reloc_upper_bound, but
+ that returns the size of a memory buffer rather than a reloc
+ count. We do not want to call bfd_canonicalize_reloc,
+ because although it would always work it would force us to
+ read in the relocs into BFD canonical form, which would waste
+ a significant amount of time and memory. */
+
+ if (datasec != NULL && datasec->reloc_count > 0)
+ {
+ asection *relsec;
+
+ relsec = bfd_make_section (abfd, ".rel.sdata");
+ if (relsec == NULL
+ || ! bfd_set_section_flags (abfd, relsec,
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY))
+ || ! bfd_set_section_alignment (abfd, relsec,
+ (${ELFSIZE} == 32) ? 2 : 3)
+ || ! bfd_set_section_size (abfd, relsec,
+ datasec->reloc_count
+ * ((${ELFSIZE} / 8) + 8)))
+ einfo ("%F%B: cannot create .rel.sdata section: %E\n");
+ }
+
+ /* Double check that all other data sections have no relocs,
+ as is required for embedded PIC code. */
+ bfd_map_over_sections (abfd, mips_elf${ELFSIZE}_check_sections,
+ datasec);
+ }
+ }
+#endif /* SUPPORT_EMBEDDED_RELOCS */
+}
+
+#ifdef SUPPORT_EMBEDDED_RELOCS
+/* Check that of the data sections, only the .sdata section has
+ relocs. This is called via bfd_map_over_sections. */
+
+static void
+mips_elf${ELFSIZE}_check_sections (bfd *abfd, asection *sec, void *sdatasec)
+{
+ if ((bfd_get_section_flags (abfd, sec) & SEC_DATA)
+ && sec != sdatasec
+ && sec->reloc_count != 0)
+ einfo ("%B%X: section %s has relocs; cannot use --embedded-relocs\n",
+ abfd, bfd_get_section_name (abfd, sec));
+}
+#endif /* SUPPORT_EMBEDDED_RELOCS */
+
+/* This function is called after the section sizes and offsets have
+ been set. If we are generating embedded relocs, it calls a special
+ BFD backend routine to do the work. */
+
+static void
+mips_elf${ELFSIZE}_after_allocation (void)
+{
+ /* Call the standard elf routine. */
+ after_allocation_default ();
+
+#ifdef SUPPORT_EMBEDDED_RELOCS
+ if (command_line.embedded_relocs && (! link_info.relocatable))
+ {
+ bfd *abfd;
+
+ for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link_next)
+ {
+ asection *datasec, *relsec;
+ char *errmsg;
+
+ datasec = bfd_get_section_by_name (abfd, ".sdata");
+
+ if (datasec == NULL || datasec->reloc_count == 0)
+ continue;
+
+ relsec = bfd_get_section_by_name (abfd, ".rel.sdata");
+ ASSERT (relsec != NULL);
+
+ if (! bfd_mips_elf${ELFSIZE}_create_embedded_relocs (abfd,
+ &link_info,
+ datasec,
+ relsec,
+ &errmsg))
+ {
+ if (errmsg == NULL)
+ einfo ("%B%X: can not create runtime reloc information: %E\n",
+ abfd);
+ else
+ einfo ("%X%B: can not create runtime reloc information: %s\n",
+ abfd, errmsg);
+ }
+ }
+ }
+#endif /* SUPPORT_EMBEDDED_RELOCS */
+}
+
+EOF
+
+# We have our own after_open and after_allocation functions, but they call
+# the standard routines, so give them a different name.
+LDEMUL_AFTER_OPEN=mips_elf${ELFSIZE}_after_open
+LDEMUL_AFTER_ALLOCATION=mips_elf${ELFSIZE}_after_allocation
diff --git a/x/binutils/ld/emultempl/needrelax.em b/x/binutils/ld/emultempl/needrelax.em
new file mode 100644
index 0000000..65e622b
--- /dev/null
+++ b/x/binutils/ld/emultempl/needrelax.em
@@ -0,0 +1,38 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+#
+# This file is part of GLD, the Gnu Linker.
+#
+# 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 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.
+#
+
+# This file is sourced from elf32.em. It is used by targets for
+# which relaxation is not just an optimization, but for correctness.
+
+LDEMUL_BEFORE_ALLOCATION=need_relax_${EMULATION_NAME}_before_allocation
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+static void
+need_relax_${EMULATION_NAME}_before_allocation (void)
+{
+ /* Call main function; we're just extending it. */
+ gld${EMULATION_NAME}_before_allocation ();
+
+ /* Force -relax on if not doing a relocatable link. */
+ if (! link_info.relocatable)
+ command_line.relax = TRUE;
+}
+EOF
diff --git a/x/binutils/ld/emultempl/netbsd.em b/x/binutils/ld/emultempl/netbsd.em
new file mode 100644
index 0000000..43715e4
--- /dev/null
+++ b/x/binutils/ld/emultempl/netbsd.em
@@ -0,0 +1,13 @@
+LDEMUL_BEFORE_PARSE=gldnetbsd_before_parse
+
+cat >>e${EMULATION_NAME}.c <<EOF
+static void
+gld${EMULATION_NAME}_before_parse (void);
+
+static void
+gldnetbsd_before_parse (void)
+{
+ gld${EMULATION_NAME}_before_parse ();
+ link_info.common_skip_ar_aymbols = bfd_link_common_skip_text;
+}
+EOF
diff --git a/x/binutils/ld/emultempl/ostring.sed b/x/binutils/ld/emultempl/ostring.sed
new file mode 100644
index 0000000..a526d3f
--- /dev/null
+++ b/x/binutils/ld/emultempl/ostring.sed
@@ -0,0 +1,4 @@
+s/["\\]/\\&/g
+s/$/\\n\\/
+1 s/^/"/
+$ s/$/n"/
diff --git a/x/binutils/ld/emultempl/pe.em b/x/binutils/ld/emultempl/pe.em
new file mode 100644
index 0000000..7d6c2e8
--- /dev/null
+++ b/x/binutils/ld/emultempl/pe.em
@@ -0,0 +1,1952 @@
+# 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
+rm -f e${EMULATION_NAME}.c
+(echo;echo;echo;echo;echo)>e${EMULATION_NAME}.c # there, now line numbers match ;-)
+cat >>e${EMULATION_NAME}.c <<EOF
+/* This file is part of GLD, the Gnu Linker.
+ Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+ Free Software Foundation, Inc.
+
+ 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 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. */
+
+/* For WINDOWS_NT */
+/* The original file generated returned different default scripts depending
+ on whether certain switches were set, but these switches pertain to the
+ Linux system and that particular version of coff. In the NT case, we
+ only determine if the subsystem is console or windows in order to select
+ the correct entry point by default. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+/* Do this before including bfd.h, so we prototype the right functions. */
+#ifdef TARGET_IS_arm_epoc_pe
+#define bfd_arm_pe_allocate_interworking_sections \
+ bfd_arm_epoc_pe_allocate_interworking_sections
+#define bfd_arm_pe_get_bfd_for_interworking \
+ bfd_arm_epoc_pe_get_bfd_for_interworking
+#define bfd_arm_pe_process_before_allocation \
+ bfd_arm_epoc_pe_process_before_allocation
+#endif
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "getopt.h"
+#include "libiberty.h"
+#include "ld.h"
+#include "ldmain.h"
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldfile.h"
+#include "ldemul.h"
+#include <ldgram.h>
+#include "ldlex.h"
+#include "ldmisc.h"
+#include "ldctor.h"
+#include "coff/internal.h"
+
+/* FIXME: This is a BFD internal header file, and we should not be
+ using it here. */
+#include "../bfd/libcoff.h"
+
+#include "deffile.h"
+#include "pe-dll.h"
+#include "safe-ctype.h"
+
+/* Permit the emulation parameters to override the default section
+ alignment by setting OVERRIDE_SECTION_ALIGNMENT. FIXME: This makes
+ it seem that include/coff/internal.h should not define
+ PE_DEF_SECTION_ALIGNMENT. */
+#if PE_DEF_SECTION_ALIGNMENT != ${OVERRIDE_SECTION_ALIGNMENT:-PE_DEF_SECTION_ALIGNMENT}
+#undef PE_DEF_SECTION_ALIGNMENT
+#define PE_DEF_SECTION_ALIGNMENT ${OVERRIDE_SECTION_ALIGNMENT}
+#endif
+
+#if defined(TARGET_IS_i386pe)
+#define DLL_SUPPORT
+#endif
+#if defined(TARGET_IS_shpe) || defined(TARGET_IS_mipspe) || defined(TARGET_IS_armpe)
+#define DLL_SUPPORT
+#endif
+
+#if defined(TARGET_IS_i386pe) || ! defined(DLL_SUPPORT)
+#define PE_DEF_SUBSYSTEM 3
+#else
+#undef NT_EXE_IMAGE_BASE
+#undef PE_DEF_SECTION_ALIGNMENT
+#undef PE_DEF_FILE_ALIGNMENT
+#define NT_EXE_IMAGE_BASE 0x00010000
+#ifdef TARGET_IS_armpe
+#define PE_DEF_SECTION_ALIGNMENT 0x00001000
+#define PE_DEF_SUBSYSTEM 9
+#else
+#define PE_DEF_SECTION_ALIGNMENT 0x00000400
+#define PE_DEF_SUBSYSTEM 2
+#endif
+#define PE_DEF_FILE_ALIGNMENT 0x00000200
+#endif
+
+
+static struct internal_extra_pe_aouthdr pe;
+static int dll;
+static int support_old_code = 0;
+static char * thumb_entry_symbol = NULL;
+static lang_assignment_statement_type *image_base_statement = 0;
+
+#ifdef DLL_SUPPORT
+static int pe_enable_stdcall_fixup = -1; /* 0=disable 1=enable. */
+static char *pe_out_def_filename = NULL;
+static char *pe_implib_filename = NULL;
+static int pe_enable_auto_image_base = 0;
+static char *pe_dll_search_prefix = NULL;
+#endif
+
+extern const char *output_filename;
+
+static void
+gld_${EMULATION_NAME}_before_parse (void)
+{
+ ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`);
+ output_filename = "${EXECUTABLE_NAME:-a.exe}";
+#ifdef DLL_SUPPORT
+ config.dynamic_link = TRUE;
+ config.has_shared = 1;
+ link_info.pei386_auto_import = -1;
+ link_info.pei386_runtime_pseudo_reloc = FALSE;
+
+#if (PE_DEF_SUBSYSTEM == 9) || (PE_DEF_SUBSYSTEM == 2)
+#if defined TARGET_IS_mipspe || defined TARGET_IS_armpe
+ lang_add_entry ("WinMainCRTStartup", FALSE);
+#else
+ lang_add_entry ("_WinMainCRTStartup", FALSE);
+#endif
+#endif
+#endif
+}
+
+/* PE format extra command line options. */
+
+/* Used for setting flags in the PE header. */
+#define OPTION_BASE_FILE (300 + 1)
+#define OPTION_DLL (OPTION_BASE_FILE + 1)
+#define OPTION_FILE_ALIGNMENT (OPTION_DLL + 1)
+#define OPTION_IMAGE_BASE (OPTION_FILE_ALIGNMENT + 1)
+#define OPTION_MAJOR_IMAGE_VERSION (OPTION_IMAGE_BASE + 1)
+#define OPTION_MAJOR_OS_VERSION (OPTION_MAJOR_IMAGE_VERSION + 1)
+#define OPTION_MAJOR_SUBSYSTEM_VERSION (OPTION_MAJOR_OS_VERSION + 1)
+#define OPTION_MINOR_IMAGE_VERSION (OPTION_MAJOR_SUBSYSTEM_VERSION + 1)
+#define OPTION_MINOR_OS_VERSION (OPTION_MINOR_IMAGE_VERSION + 1)
+#define OPTION_MINOR_SUBSYSTEM_VERSION (OPTION_MINOR_OS_VERSION + 1)
+#define OPTION_SECTION_ALIGNMENT (OPTION_MINOR_SUBSYSTEM_VERSION + 1)
+#define OPTION_STACK (OPTION_SECTION_ALIGNMENT + 1)
+#define OPTION_SUBSYSTEM (OPTION_STACK + 1)
+#define OPTION_HEAP (OPTION_SUBSYSTEM + 1)
+#define OPTION_SUPPORT_OLD_CODE (OPTION_HEAP + 1)
+#define OPTION_OUT_DEF (OPTION_SUPPORT_OLD_CODE + 1)
+#define OPTION_EXPORT_ALL (OPTION_OUT_DEF + 1)
+#define OPTION_EXCLUDE_SYMBOLS (OPTION_EXPORT_ALL + 1)
+#define OPTION_KILL_ATS (OPTION_EXCLUDE_SYMBOLS + 1)
+#define OPTION_STDCALL_ALIASES (OPTION_KILL_ATS + 1)
+#define OPTION_ENABLE_STDCALL_FIXUP (OPTION_STDCALL_ALIASES + 1)
+#define OPTION_DISABLE_STDCALL_FIXUP (OPTION_ENABLE_STDCALL_FIXUP + 1)
+#define OPTION_IMPLIB_FILENAME (OPTION_DISABLE_STDCALL_FIXUP + 1)
+#define OPTION_THUMB_ENTRY (OPTION_IMPLIB_FILENAME + 1)
+#define OPTION_WARN_DUPLICATE_EXPORTS (OPTION_THUMB_ENTRY + 1)
+#define OPTION_IMP_COMPAT (OPTION_WARN_DUPLICATE_EXPORTS + 1)
+#define OPTION_ENABLE_AUTO_IMAGE_BASE (OPTION_IMP_COMPAT + 1)
+#define OPTION_DISABLE_AUTO_IMAGE_BASE (OPTION_ENABLE_AUTO_IMAGE_BASE + 1)
+#define OPTION_DLL_SEARCH_PREFIX (OPTION_DISABLE_AUTO_IMAGE_BASE + 1)
+#define OPTION_NO_DEFAULT_EXCLUDES (OPTION_DLL_SEARCH_PREFIX + 1)
+#define OPTION_DLL_ENABLE_AUTO_IMPORT (OPTION_NO_DEFAULT_EXCLUDES + 1)
+#define OPTION_DLL_DISABLE_AUTO_IMPORT (OPTION_DLL_ENABLE_AUTO_IMPORT + 1)
+#define OPTION_ENABLE_EXTRA_PE_DEBUG (OPTION_DLL_DISABLE_AUTO_IMPORT + 1)
+#define OPTION_EXCLUDE_LIBS (OPTION_ENABLE_EXTRA_PE_DEBUG + 1)
+#define OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC \
+ (OPTION_EXCLUDE_LIBS + 1)
+#define OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC \
+ (OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC + 1)
+
+static void
+gld${EMULATION_NAME}_add_options
+ (int ns ATTRIBUTE_UNUSED, char **shortopts ATTRIBUTE_UNUSED, int nl,
+ struct option **longopts, int nrl ATTRIBUTE_UNUSED,
+ struct option **really_longopts ATTRIBUTE_UNUSED)
+{
+ static const struct option xtra_long[] = {
+ /* PE options */
+ {"base-file", required_argument, NULL, OPTION_BASE_FILE},
+ {"dll", no_argument, NULL, OPTION_DLL},
+ {"file-alignment", required_argument, NULL, OPTION_FILE_ALIGNMENT},
+ {"heap", required_argument, NULL, OPTION_HEAP},
+ {"image-base", required_argument, NULL, OPTION_IMAGE_BASE},
+ {"major-image-version", required_argument, NULL, OPTION_MAJOR_IMAGE_VERSION},
+ {"major-os-version", required_argument, NULL, OPTION_MAJOR_OS_VERSION},
+ {"major-subsystem-version", required_argument, NULL, OPTION_MAJOR_SUBSYSTEM_VERSION},
+ {"minor-image-version", required_argument, NULL, OPTION_MINOR_IMAGE_VERSION},
+ {"minor-os-version", required_argument, NULL, OPTION_MINOR_OS_VERSION},
+ {"minor-subsystem-version", required_argument, NULL, OPTION_MINOR_SUBSYSTEM_VERSION},
+ {"section-alignment", required_argument, NULL, OPTION_SECTION_ALIGNMENT},
+ {"stack", required_argument, NULL, OPTION_STACK},
+ {"subsystem", required_argument, NULL, OPTION_SUBSYSTEM},
+ {"support-old-code", no_argument, NULL, OPTION_SUPPORT_OLD_CODE},
+ {"thumb-entry", required_argument, NULL, OPTION_THUMB_ENTRY},
+#ifdef DLL_SUPPORT
+ /* getopt allows abbreviations, so we do this to stop it from treating -o
+ as an abbreviation for this option */
+ {"output-def", required_argument, NULL, OPTION_OUT_DEF},
+ {"output-def", required_argument, NULL, OPTION_OUT_DEF},
+ {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL},
+ {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMBOLS},
+ {"exclude-libs", required_argument, NULL, OPTION_EXCLUDE_LIBS},
+ {"kill-at", no_argument, NULL, OPTION_KILL_ATS},
+ {"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES},
+ {"enable-stdcall-fixup", no_argument, NULL, OPTION_ENABLE_STDCALL_FIXUP},
+ {"disable-stdcall-fixup", no_argument, NULL, OPTION_DISABLE_STDCALL_FIXUP},
+ {"out-implib", required_argument, NULL, OPTION_IMPLIB_FILENAME},
+ {"warn-duplicate-exports", no_argument, NULL, OPTION_WARN_DUPLICATE_EXPORTS},
+ /* getopt() allows abbreviations, so we do this to stop it from
+ treating -c as an abbreviation for these --compat-implib. */
+ {"compat-implib", no_argument, NULL, OPTION_IMP_COMPAT},
+ {"compat-implib", no_argument, NULL, OPTION_IMP_COMPAT},
+ {"enable-auto-image-base", no_argument, NULL, OPTION_ENABLE_AUTO_IMAGE_BASE},
+ {"disable-auto-image-base", no_argument, NULL, OPTION_DISABLE_AUTO_IMAGE_BASE},
+ {"dll-search-prefix", required_argument, NULL, OPTION_DLL_SEARCH_PREFIX},
+ {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
+ {"enable-auto-import", no_argument, NULL, OPTION_DLL_ENABLE_AUTO_IMPORT},
+ {"disable-auto-import", no_argument, NULL, OPTION_DLL_DISABLE_AUTO_IMPORT},
+ {"enable-extra-pe-debug", no_argument, NULL, OPTION_ENABLE_EXTRA_PE_DEBUG},
+ {"enable-runtime-pseudo-reloc", no_argument, NULL, OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC},
+ {"disable-runtime-pseudo-reloc", no_argument, NULL, OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC},
+#endif
+ {NULL, no_argument, NULL, 0}
+ };
+
+ *longopts = (struct option *)
+ xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long));
+ memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
+}
+
+/* PE/WIN32; added routines to get the subsystem type, heap and/or stack
+ parameters which may be input from the command line. */
+
+typedef struct
+{
+ void *ptr;
+ int size;
+ int value;
+ char *symbol;
+ int inited;
+} definfo;
+
+#define D(field,symbol,def) {&pe.field,sizeof(pe.field), def, symbol,0}
+
+static definfo init[] =
+{
+ /* imagebase must be first */
+#define IMAGEBASEOFF 0
+ D(ImageBase,"__image_base__", NT_EXE_IMAGE_BASE),
+#define DLLOFF 1
+ {&dll, sizeof(dll), 0, "__dll__", 0},
+ D(SectionAlignment,"__section_alignment__", PE_DEF_SECTION_ALIGNMENT),
+ D(FileAlignment,"__file_alignment__", PE_DEF_FILE_ALIGNMENT),
+ D(MajorOperatingSystemVersion,"__major_os_version__", 4),
+ D(MinorOperatingSystemVersion,"__minor_os_version__", 0),
+ D(MajorImageVersion,"__major_image_version__", 1),
+ D(MinorImageVersion,"__minor_image_version__", 0),
+#ifdef TARGET_IS_armpe
+ D(MajorSubsystemVersion,"__major_subsystem_version__", 2),
+#else
+ D(MajorSubsystemVersion,"__major_subsystem_version__", 4),
+#endif
+ D(MinorSubsystemVersion,"__minor_subsystem_version__", 0),
+ D(Subsystem,"__subsystem__", ${SUBSYSTEM}),
+ D(SizeOfStackReserve,"__size_of_stack_reserve__", 0x200000),
+ D(SizeOfStackCommit,"__size_of_stack_commit__", 0x1000),
+ D(SizeOfHeapReserve,"__size_of_heap_reserve__", 0x100000),
+ D(SizeOfHeapCommit,"__size_of_heap_commit__", 0x1000),
+ D(LoaderFlags,"__loader_flags__", 0x0),
+ { NULL, 0, 0, NULL, 0 }
+};
+
+
+static void
+gld_${EMULATION_NAME}_list_options (FILE *file)
+{
+ fprintf (file, _(" --base_file <basefile> Generate a base file for relocatable DLLs\n"));
+ fprintf (file, _(" --dll Set image base to the default for DLLs\n"));
+ fprintf (file, _(" --file-alignment <size> Set file alignment\n"));
+ fprintf (file, _(" --heap <size> Set initial size of the heap\n"));
+ fprintf (file, _(" --image-base <address> Set start address of the executable\n"));
+ fprintf (file, _(" --major-image-version <number> Set version number of the executable\n"));
+ fprintf (file, _(" --major-os-version <number> Set minimum required OS version\n"));
+ fprintf (file, _(" --major-subsystem-version <number> Set minimum required OS subsystem version\n"));
+ fprintf (file, _(" --minor-image-version <number> Set revision number of the executable\n"));
+ fprintf (file, _(" --minor-os-version <number> Set minimum required OS revision\n"));
+ fprintf (file, _(" --minor-subsystem-version <number> Set minimum required OS subsystem revision\n"));
+ fprintf (file, _(" --section-alignment <size> Set section alignment\n"));
+ fprintf (file, _(" --stack <size> Set size of the initial stack\n"));
+ fprintf (file, _(" --subsystem <name>[:<version>] Set required OS subsystem [& version]\n"));
+ fprintf (file, _(" --support-old-code Support interworking with old code\n"));
+ fprintf (file, _(" --thumb-entry=<symbol> Set the entry point to be Thumb <symbol>\n"));
+#ifdef DLL_SUPPORT
+ fprintf (file, _(" --add-stdcall-alias Export symbols with and without @nn\n"));
+ fprintf (file, _(" --disable-stdcall-fixup Don't link _sym to _sym@nn\n"));
+ fprintf (file, _(" --enable-stdcall-fixup Link _sym to _sym@nn without warnings\n"));
+ fprintf (file, _(" --exclude-symbols sym,sym,... Exclude symbols from automatic export\n"));
+ fprintf (file, _(" --exclude-libs lib,lib,... Exclude libraries from automatic export\n"));
+ fprintf (file, _(" --export-all-symbols Automatically export all globals to DLL\n"));
+ fprintf (file, _(" --kill-at Remove @nn from exported symbols\n"));
+ fprintf (file, _(" --out-implib <file> Generate import library\n"));
+ fprintf (file, _(" --output-def <file> Generate a .DEF file for the built DLL\n"));
+ fprintf (file, _(" --warn-duplicate-exports Warn about duplicate exports.\n"));
+ fprintf (file, _(" --compat-implib Create backward compatible import libs;\n\
+ create __imp_<SYMBOL> as well.\n"));
+ fprintf (file, _(" --enable-auto-image-base Automatically choose image base for DLLs\n\
+ unless user specifies one\n"));
+ fprintf (file, _(" --disable-auto-image-base Do not auto-choose image base. (default)\n"));
+ fprintf (file, _(" --dll-search-prefix=<string> When linking dynamically to a dll without\n\
+ an importlib, use <string><basename>.dll\n\
+ in preference to lib<basename>.dll \n"));
+ fprintf (file, _(" --enable-auto-import Do sophistcated linking of _sym to\n\
+ __imp_sym for DATA references\n"));
+ fprintf (file, _(" --disable-auto-import Do not auto-import DATA items from DLLs\n"));
+ fprintf (file, _(" --enable-runtime-pseudo-reloc Work around auto-import limitations by\n\
+ adding pseudo-relocations resolved at\n\
+ runtime.\n"));
+ fprintf (file, _(" --disable-runtime-pseudo-reloc Do not add runtime pseudo-relocations for\n\
+ auto-imported DATA.\n"));
+ fprintf (file, _(" --enable-extra-pe-debug Enable verbose debug output when building\n\
+ or linking to DLLs (esp. auto-import)\n"));
+#endif
+}
+
+
+static void
+set_pe_name (char *name, long val)
+{
+ int i;
+
+ /* Find the name and set it. */
+ for (i = 0; init[i].ptr; i++)
+ {
+ if (strcmp (name, init[i].symbol) == 0)
+ {
+ init[i].value = val;
+ init[i].inited = 1;
+ return;
+ }
+ }
+ abort ();
+}
+
+
+static void
+set_pe_subsystem (void)
+{
+ const char *sver;
+ int len;
+ int i;
+ static const struct
+ {
+ const char *name;
+ const int value;
+ const char *entry;
+ }
+ v[] =
+ {
+ { "native", 1, "NtProcessStartup" },
+#if defined TARGET_IS_mipspe || defined TARGET_IS_armpe
+ { "windows", 2, "WinMainCRTStartup" },
+#else
+ { "windows", 2, "WinMainCRTStartup" },
+#endif
+ { "console", 3, "mainCRTStartup" },
+#if 0
+ /* The Microsoft linker does not recognize this. */
+ { "os2", 5, "" },
+#endif
+ { "posix", 7, "__PosixProcessStartup"},
+ { "wince", 9, "_WinMainCRTStartup" },
+ { 0, 0, 0 }
+ };
+
+ sver = strchr (optarg, ':');
+ if (sver == NULL)
+ len = strlen (optarg);
+ else
+ {
+ char *end;
+
+ len = sver - optarg;
+ set_pe_name ("__major_subsystem_version__",
+ strtoul (sver + 1, &end, 0));
+ if (*end == '.')
+ set_pe_name ("__minor_subsystem_version__",
+ strtoul (end + 1, &end, 0));
+ if (*end != '\0')
+ einfo (_("%P: warning: bad version number in -subsystem option\n"));
+ }
+
+ for (i = 0; v[i].name; i++)
+ {
+ if (strncmp (optarg, v[i].name, len) == 0
+ && v[i].name[len] == '\0')
+ {
+ const char *initial_symbol_char;
+ const char *entry;
+
+ set_pe_name ("__subsystem__", v[i].value);
+
+ initial_symbol_char = ${INITIAL_SYMBOL_CHAR};
+ if (*initial_symbol_char == '\0')
+ entry = v[i].entry;
+ else
+ {
+ char *alc_entry;
+
+ /* lang_add_entry expects its argument to be permanently
+ allocated, so we don't free this string. */
+ alc_entry = xmalloc (strlen (initial_symbol_char)
+ + strlen (v[i].entry)
+ + 1);
+ strcpy (alc_entry, initial_symbol_char);
+ strcat (alc_entry, v[i].entry);
+ entry = alc_entry;
+ }
+
+ lang_add_entry (entry, TRUE);
+
+ return;
+ }
+ }
+
+ einfo (_("%P%F: invalid subsystem type %s\n"), optarg);
+}
+
+
+static void
+set_pe_value (char *name)
+{
+ char *end;
+
+ set_pe_name (name, strtoul (optarg, &end, 0));
+
+ if (end == optarg)
+ einfo (_("%P%F: invalid hex number for PE parameter '%s'\n"), optarg);
+
+ optarg = end;
+}
+
+
+static void
+set_pe_stack_heap (char *resname, char *comname)
+{
+ set_pe_value (resname);
+
+ if (*optarg == ',')
+ {
+ optarg++;
+ set_pe_value (comname);
+ }
+ else if (*optarg)
+ einfo (_("%P%F: strange hex info for PE parameter '%s'\n"), optarg);
+}
+
+
+static bfd_boolean
+gld${EMULATION_NAME}_handle_option (int optc)
+{
+ switch (optc)
+ {
+ default:
+ return FALSE;
+
+ case OPTION_BASE_FILE:
+ link_info.base_file = fopen (optarg, FOPEN_WB);
+ if (link_info.base_file == NULL)
+ {
+ /* xgettext:c-format */
+ fprintf (stderr, _("%s: Can't open base file %s\n"),
+ program_name, optarg);
+ xexit (1);
+ }
+ break;
+
+ /* PE options. */
+ case OPTION_HEAP:
+ set_pe_stack_heap ("__size_of_heap_reserve__", "__size_of_heap_commit__");
+ break;
+ case OPTION_STACK:
+ set_pe_stack_heap ("__size_of_stack_reserve__", "__size_of_stack_commit__");
+ break;
+ case OPTION_SUBSYSTEM:
+ set_pe_subsystem ();
+ break;
+ case OPTION_MAJOR_OS_VERSION:
+ set_pe_value ("__major_os_version__");
+ break;
+ case OPTION_MINOR_OS_VERSION:
+ set_pe_value ("__minor_os_version__");
+ break;
+ case OPTION_MAJOR_SUBSYSTEM_VERSION:
+ set_pe_value ("__major_subsystem_version__");
+ break;
+ case OPTION_MINOR_SUBSYSTEM_VERSION:
+ set_pe_value ("__minor_subsystem_version__");
+ break;
+ case OPTION_MAJOR_IMAGE_VERSION:
+ set_pe_value ("__major_image_version__");
+ break;
+ case OPTION_MINOR_IMAGE_VERSION:
+ set_pe_value ("__minor_image_version__");
+ break;
+ case OPTION_FILE_ALIGNMENT:
+ set_pe_value ("__file_alignment__");
+ break;
+ case OPTION_SECTION_ALIGNMENT:
+ set_pe_value ("__section_alignment__");
+ break;
+ case OPTION_DLL:
+ set_pe_name ("__dll__", 1);
+ break;
+ case OPTION_IMAGE_BASE:
+ set_pe_value ("__image_base__");
+ break;
+ case OPTION_SUPPORT_OLD_CODE:
+ support_old_code = 1;
+ break;
+ case OPTION_THUMB_ENTRY:
+ thumb_entry_symbol = optarg;
+ break;
+#ifdef DLL_SUPPORT
+ case OPTION_OUT_DEF:
+ pe_out_def_filename = xstrdup (optarg);
+ break;
+ case OPTION_EXPORT_ALL:
+ pe_dll_export_everything = 1;
+ break;
+ case OPTION_EXCLUDE_SYMBOLS:
+ pe_dll_add_excludes (optarg, 0);
+ break;
+ case OPTION_EXCLUDE_LIBS:
+ pe_dll_add_excludes (optarg, 1);
+ break;
+ case OPTION_KILL_ATS:
+ pe_dll_kill_ats = 1;
+ break;
+ case OPTION_STDCALL_ALIASES:
+ pe_dll_stdcall_aliases = 1;
+ break;
+ case OPTION_ENABLE_STDCALL_FIXUP:
+ pe_enable_stdcall_fixup = 1;
+ break;
+ case OPTION_DISABLE_STDCALL_FIXUP:
+ pe_enable_stdcall_fixup = 0;
+ break;
+ case OPTION_IMPLIB_FILENAME:
+ pe_implib_filename = xstrdup (optarg);
+ break;
+ case OPTION_WARN_DUPLICATE_EXPORTS:
+ pe_dll_warn_dup_exports = 1;
+ break;
+ case OPTION_IMP_COMPAT:
+ pe_dll_compat_implib = 1;
+ break;
+ case OPTION_ENABLE_AUTO_IMAGE_BASE:
+ pe_enable_auto_image_base = 1;
+ break;
+ case OPTION_DISABLE_AUTO_IMAGE_BASE:
+ pe_enable_auto_image_base = 0;
+ break;
+ case OPTION_DLL_SEARCH_PREFIX:
+ pe_dll_search_prefix = xstrdup (optarg);
+ break;
+ case OPTION_NO_DEFAULT_EXCLUDES:
+ pe_dll_do_default_excludes = 0;
+ break;
+ case OPTION_DLL_ENABLE_AUTO_IMPORT:
+ link_info.pei386_auto_import = 1;
+ break;
+ case OPTION_DLL_DISABLE_AUTO_IMPORT:
+ link_info.pei386_auto_import = 0;
+ break;
+ case OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC:
+ link_info.pei386_runtime_pseudo_reloc = 1;
+ break;
+ case OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC:
+ link_info.pei386_runtime_pseudo_reloc = 0;
+ break;
+ case OPTION_ENABLE_EXTRA_PE_DEBUG:
+ pe_dll_extra_pe_debug = 1;
+ break;
+#endif
+ }
+ return TRUE;
+}
+
+
+#ifdef DLL_SUPPORT
+static unsigned long
+strhash (const char *str)
+{
+ const unsigned char *s;
+ unsigned long hash;
+ unsigned int c;
+ unsigned int len;
+
+ hash = 0;
+ len = 0;
+ s = (const unsigned char *) str;
+ while ((c = *s++) != '\0')
+ {
+ hash += c + (c << 17);
+ hash ^= hash >> 2;
+ ++len;
+ }
+ hash += len + (len << 17);
+ hash ^= hash >> 2;
+
+ return hash;
+}
+
+/* Use the output file to create a image base for relocatable DLLs. */
+
+static unsigned long
+compute_dll_image_base (const char *ofile)
+{
+ unsigned long hash = strhash (ofile);
+ return 0x60000000 | ((hash << 16) & 0x0FFC0000);
+}
+#endif
+
+/* Assign values to the special symbols before the linker script is
+ read. */
+
+static void
+gld_${EMULATION_NAME}_set_symbols (void)
+{
+ /* Run through and invent symbols for all the
+ names and insert the defaults. */
+ int j;
+ lang_statement_list_type *save;
+
+ if (!init[IMAGEBASEOFF].inited)
+ {
+ if (link_info.relocatable)
+ init[IMAGEBASEOFF].value = 0;
+ else if (init[DLLOFF].value || link_info.shared)
+#ifdef DLL_SUPPORT
+ init[IMAGEBASEOFF].value = (pe_enable_auto_image_base) ?
+ compute_dll_image_base (output_filename) : NT_DLL_IMAGE_BASE;
+#else
+ init[IMAGEBASEOFF].value = NT_DLL_IMAGE_BASE;
+#endif
+ else
+ init[IMAGEBASEOFF].value = NT_EXE_IMAGE_BASE;
+ }
+
+ /* Don't do any symbol assignments if this is a relocatable link. */
+ if (link_info.relocatable)
+ return;
+
+ /* Glue the assignments into the abs section. */
+ save = stat_ptr;
+
+ stat_ptr = &(abs_output_section->children);
+
+ for (j = 0; init[j].ptr; j++)
+ {
+ long val = init[j].value;
+ lang_assignment_statement_type *rv;
+ rv = lang_add_assignment (exp_assop ('=', init[j].symbol,
+ exp_intop (val)));
+ if (init[j].size == sizeof (short))
+ *(short *) init[j].ptr = val;
+ else if (init[j].size == sizeof (int))
+ *(int *) init[j].ptr = val;
+ else if (init[j].size == sizeof (long))
+ *(long *) init[j].ptr = val;
+ /* This might be a long long or other special type. */
+ else if (init[j].size == sizeof (bfd_vma))
+ *(bfd_vma *) init[j].ptr = val;
+ else abort ();
+ if (j == IMAGEBASEOFF)
+ image_base_statement = rv;
+ }
+ /* Restore the pointer. */
+ stat_ptr = save;
+
+ if (pe.FileAlignment >
+ pe.SectionAlignment)
+ {
+ einfo (_("%P: warning, file alignment > section alignment.\n"));
+ }
+}
+
+/* This is called after the linker script and the command line options
+ have been read. */
+
+static void
+gld_${EMULATION_NAME}_after_parse (void)
+{
+ /* The Windows libraries are designed for the linker to treat the
+ entry point as an undefined symbol. Otherwise, the .obj that
+ defines mainCRTStartup is brought in because it is the first
+ encountered in libc.lib and it has other symbols in it which will
+ be pulled in by the link process. To avoid this, we act as
+ though the user specified -u with the entry point symbol.
+
+ This function is called after the linker script and command line
+ options have been read, so at this point we know the right entry
+ point. This function is called before the input files are
+ opened, so registering the symbol as undefined will make a
+ difference. */
+
+ if (! link_info.relocatable && entry_symbol.name != NULL)
+ ldlang_add_undef (entry_symbol.name);
+}
+
+/* pe-dll.c directly accesses pe_data_import_dll,
+ so it must be defined outside of #ifdef DLL_SUPPORT.
+ Note - this variable is deliberately not initialised.
+ This allows it to be treated as a common varaible, and only
+ exist in one incarnation in a multiple target enabled linker. */
+char * pe_data_import_dll;
+
+#ifdef DLL_SUPPORT
+static struct bfd_link_hash_entry *pe_undef_found_sym;
+
+static bfd_boolean
+pe_undef_cdecl_match (struct bfd_link_hash_entry *h, void *inf)
+{
+ int sl;
+ char *string = inf;
+
+ sl = strlen (string);
+ if (h->type == bfd_link_hash_defined
+ && strncmp (h->root.string, string, sl) == 0
+ && h->root.string[sl] == '@')
+ {
+ pe_undef_found_sym = h;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+pe_fixup_stdcalls (void)
+{
+ static int gave_warning_message = 0;
+ struct bfd_link_hash_entry *undef, *sym;
+
+ if (pe_dll_extra_pe_debug)
+ printf ("%s\n", __FUNCTION__);
+
+ for (undef = link_info.hash->undefs; undef; undef=undef->und_next)
+ if (undef->type == bfd_link_hash_undefined)
+ {
+ char* at = strchr (undef->root.string, '@');
+ int lead_at = (*undef->root.string == '@');
+ /* For now, don't try to fixup fastcall symbols. */
+
+ if (at && !lead_at)
+ {
+ /* The symbol is a stdcall symbol, so let's look for a
+ cdecl symbol with the same name and resolve to that. */
+ char *cname = xstrdup (undef->root.string /* + lead_at */);
+ at = strchr (cname, '@');
+ *at = 0;
+ sym = bfd_link_hash_lookup (link_info.hash, cname, 0, 0, 1);
+
+ if (sym && sym->type == bfd_link_hash_defined)
+ {
+ undef->type = bfd_link_hash_defined;
+ undef->u.def.value = sym->u.def.value;
+ undef->u.def.section = sym->u.def.section;
+
+ if (pe_enable_stdcall_fixup == -1)
+ {
+ einfo (_("Warning: resolving %s by linking to %s\n"),
+ undef->root.string, cname);
+ if (! gave_warning_message)
+ {
+ gave_warning_message = 1;
+ einfo (_("Use --enable-stdcall-fixup to disable these warnings\n"));
+ einfo (_("Use --disable-stdcall-fixup to disable these fixups\n"));
+ }
+ }
+ }
+ }
+ else
+ {
+ /* The symbol is a cdecl symbol, so we look for stdcall
+ symbols - which means scanning the whole symbol table. */
+ pe_undef_found_sym = 0;
+ bfd_link_hash_traverse (link_info.hash, pe_undef_cdecl_match,
+ (char *) undef->root.string);
+ sym = pe_undef_found_sym;
+ if (sym)
+ {
+ undef->type = bfd_link_hash_defined;
+ undef->u.def.value = sym->u.def.value;
+ undef->u.def.section = sym->u.def.section;
+
+ if (pe_enable_stdcall_fixup == -1)
+ {
+ einfo (_("Warning: resolving %s by linking to %s\n"),
+ undef->root.string, sym->root.string);
+ if (! gave_warning_message)
+ {
+ gave_warning_message = 1;
+ einfo (_("Use --enable-stdcall-fixup to disable these warnings\n"));
+ einfo (_("Use --disable-stdcall-fixup to disable these fixups\n"));
+ }
+ }
+ }
+ }
+ }
+}
+
+static int
+make_import_fixup (arelent *rel, asection *s)
+{
+ struct bfd_symbol *sym = *rel->sym_ptr_ptr;
+ int addend = 0;
+
+ if (pe_dll_extra_pe_debug)
+ printf ("arelent: %s@%#lx: add=%li\n", sym->name,
+ (long) rel->address, (long) rel->addend);
+
+ if (! bfd_get_section_contents (s->owner, s, &addend, rel->address, sizeof (addend)))
+ einfo (_("%C: Cannot get section contents - auto-import exception\n"),
+ s->owner, s, rel->address);
+
+ pe_create_import_fixup (rel, s, addend);
+
+ return 1;
+}
+
+static void
+pe_find_data_imports (void)
+{
+ struct bfd_link_hash_entry *undef, *sym;
+
+ if (link_info.pei386_auto_import == 0)
+ return;
+
+ for (undef = link_info.hash->undefs; undef; undef=undef->und_next)
+ {
+ if (undef->type == bfd_link_hash_undefined)
+ {
+ /* C++ symbols are *long*. */
+ char buf[4096];
+
+ if (pe_dll_extra_pe_debug)
+ printf ("%s:%s\n", __FUNCTION__, undef->root.string);
+
+ sprintf (buf, "__imp_%s", undef->root.string);
+
+ sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1);
+
+ if (sym && sym->type == bfd_link_hash_defined)
+ {
+ bfd *b = sym->u.def.section->owner;
+ asymbol **symbols;
+ int nsyms, symsize, i;
+
+ if (link_info.pei386_auto_import == -1)
+ info_msg (_("Info: resolving %s by linking to %s (auto-import)\n"),
+ undef->root.string, buf);
+
+ symsize = bfd_get_symtab_upper_bound (b);
+ symbols = (asymbol **) xmalloc (symsize);
+ nsyms = bfd_canonicalize_symtab (b, symbols);
+
+ for (i = 0; i < nsyms; i++)
+ {
+ if (memcmp (symbols[i]->name, "__head_",
+ sizeof ("__head_") - 1))
+ continue;
+
+ if (pe_dll_extra_pe_debug)
+ printf ("->%s\n", symbols[i]->name);
+
+ pe_data_import_dll = (char*) (symbols[i]->name +
+ sizeof ("__head_") - 1);
+ break;
+ }
+
+ pe_walk_relocs_of_symbol (&link_info, undef->root.string,
+ make_import_fixup);
+
+ /* Let's differentiate it somehow from defined. */
+ undef->type = bfd_link_hash_defweak;
+ /* We replace original name with __imp_ prefixed, this
+ 1) may trash memory 2) leads to duplicate symbol generation.
+ Still, IMHO it's better than having name poluted. */
+ undef->root.string = sym->root.string;
+ undef->u.def.value = sym->u.def.value;
+ undef->u.def.section = sym->u.def.section;
+ }
+ }
+ }
+}
+
+static bfd_boolean
+pr_sym (struct bfd_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
+{
+ if (pe_dll_extra_pe_debug)
+ printf ("+%s\n", h->string);
+
+ return TRUE;
+}
+#endif /* DLL_SUPPORT */
+
+
+static void
+gld_${EMULATION_NAME}_after_open (void)
+{
+#ifdef DLL_SUPPORT
+ if (pe_dll_extra_pe_debug)
+ {
+ bfd *a;
+ struct bfd_link_hash_entry *sym;
+
+ printf ("%s()\n", __FUNCTION__);
+
+ for (sym = link_info.hash->undefs; sym; sym=sym->und_next)
+ printf ("-%s\n", sym->root.string);
+ bfd_hash_traverse (&link_info.hash->table, pr_sym, NULL);
+
+ for (a = link_info.input_bfds; a; a = a->link_next)
+ printf ("*%s\n",a->filename);
+ }
+#endif
+
+ /* Pass the wacky PE command line options into the output bfd.
+ FIXME: This should be done via a function, rather than by
+ including an internal BFD header. */
+
+ if (coff_data (output_bfd) == NULL || coff_data (output_bfd)->pe == 0)
+ einfo (_("%F%P: PE operations on non PE file.\n"));
+
+ pe_data (output_bfd)->pe_opthdr = pe;
+ pe_data (output_bfd)->dll = init[DLLOFF].value;
+
+#ifdef DLL_SUPPORT
+ if (pe_enable_stdcall_fixup) /* -1=warn or 1=disable */
+ pe_fixup_stdcalls ();
+
+ pe_process_import_defs (output_bfd, & link_info);
+
+ pe_find_data_imports ();
+
+#if ! (defined (TARGET_IS_i386pe) || defined (TARGET_IS_armpe))
+ if (link_info.shared)
+#else
+ if (!link_info.relocatable)
+#endif
+ pe_dll_build_sections (output_bfd, &link_info);
+
+#ifndef TARGET_IS_i386pe
+#ifndef TARGET_IS_armpe
+ else
+ pe_exe_build_sections (output_bfd, &link_info);
+#endif
+#endif
+#endif
+
+#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe)
+ if (strstr (bfd_get_target (output_bfd), "arm") == NULL)
+ {
+ /* The arm backend needs special fields in the output hash structure.
+ These will only be created if the output format is an arm format,
+ hence we do not support linking and changing output formats at the
+ same time. Use a link followed by objcopy to change output formats. */
+ einfo ("%F%X%P: error: cannot change output format whilst linking ARM binaries\n");
+ return;
+ }
+ {
+ /* Find a BFD that can hold the interworking stubs. */
+ LANG_FOR_EACH_INPUT_STATEMENT (is)
+ {
+ if (bfd_arm_pe_get_bfd_for_interworking (is->the_bfd, & link_info))
+ break;
+ }
+ }
+#endif
+
+ {
+ /* This next chunk of code tries to detect the case where you have
+ two import libraries for the same DLL (specifically,
+ symbolically linking libm.a and libc.a in cygwin to
+ libcygwin.a). In those cases, it's possible for function
+ thunks from the second implib to be used but without the
+ head/tail objects, causing an improper import table. We detect
+ those cases and rename the "other" import libraries to match
+ the one the head/tail come from, so that the linker will sort
+ things nicely and produce a valid import table. */
+
+ LANG_FOR_EACH_INPUT_STATEMENT (is)
+ {
+ if (is->the_bfd->my_archive)
+ {
+ int idata2 = 0, reloc_count=0, is_imp = 0;
+ asection *sec;
+
+ /* See if this is an import library thunk. */
+ for (sec = is->the_bfd->sections; sec; sec = sec->next)
+ {
+ if (strcmp (sec->name, ".idata\$2") == 0)
+ idata2 = 1;
+ if (strncmp (sec->name, ".idata\$", 7) == 0)
+ is_imp = 1;
+ reloc_count += sec->reloc_count;
+ }
+
+ if (is_imp && !idata2 && reloc_count)
+ {
+ /* It is, look for the reference to head and see if it's
+ from our own library. */
+ for (sec = is->the_bfd->sections; sec; sec = sec->next)
+ {
+ int i;
+ long symsize;
+ long relsize;
+ asymbol **symbols;
+ arelent **relocs;
+ int nrelocs;
+
+ symsize = bfd_get_symtab_upper_bound (is->the_bfd);
+ if (symsize < 1)
+ break;
+ relsize = bfd_get_reloc_upper_bound (is->the_bfd, sec);
+ if (relsize < 1)
+ break;
+
+ symbols = (asymbol **) xmalloc (symsize);
+ symsize = bfd_canonicalize_symtab (is->the_bfd, symbols);
+ if (symsize < 0)
+ {
+ einfo ("%X%P: unable to process symbols: %E");
+ return;
+ }
+
+ relocs = (arelent **) xmalloc ((size_t) relsize);
+ nrelocs = bfd_canonicalize_reloc (is->the_bfd, sec,
+ relocs, symbols);
+ if (nrelocs < 0)
+ {
+ free (relocs);
+ einfo ("%X%P: unable to process relocs: %E");
+ return;
+ }
+
+ for (i = 0; i < nrelocs; i++)
+ {
+ struct bfd_symbol *s;
+ struct bfd_link_hash_entry * blhe;
+ bfd *other_bfd;
+ char *n;
+
+ s = (relocs[i]->sym_ptr_ptr)[0];
+
+ if (s->flags & BSF_LOCAL)
+ continue;
+
+ /* Thunk section with reloc to another bfd. */
+ blhe = bfd_link_hash_lookup (link_info.hash,
+ s->name,
+ FALSE, FALSE, TRUE);
+
+ if (blhe == NULL
+ || blhe->type != bfd_link_hash_defined)
+ continue;
+
+ other_bfd = blhe->u.def.section->owner;
+
+ if (strcmp (is->the_bfd->my_archive->filename,
+ other_bfd->my_archive->filename) == 0)
+ continue;
+
+ /* Rename this implib to match the other. */
+ n = (char *) xmalloc (strlen (other_bfd->my_archive->filename) + 1);
+
+ strcpy (n, other_bfd->my_archive->filename);
+
+ is->the_bfd->my_archive->filename = n;
+ }
+
+ free (relocs);
+ /* Note - we do not free the symbols,
+ they are now cached in the BFD. */
+ }
+ }
+ }
+ }
+ }
+
+ {
+ int is_ms_arch = 0;
+ bfd *cur_arch = 0;
+ lang_input_statement_type *is2;
+ lang_input_statement_type *is3;
+
+ /* Careful - this is a shell script. Watch those dollar signs! */
+ /* Microsoft import libraries have every member named the same,
+ and not in the right order for us to link them correctly. We
+ must detect these and rename the members so that they'll link
+ correctly. There are three types of objects: the head, the
+ thunks, and the sentinel(s). The head is easy; it's the one
+ with idata2. We assume that the sentinels won't have relocs,
+ and the thunks will. It's easier than checking the symbol
+ table for external references. */
+ LANG_FOR_EACH_INPUT_STATEMENT (is)
+ {
+ if (is->the_bfd->my_archive)
+ {
+ char *pnt;
+ bfd *arch = is->the_bfd->my_archive;
+
+ if (cur_arch != arch)
+ {
+ cur_arch = arch;
+ is_ms_arch = 1;
+
+ for (is3 = is;
+ is3 && is3->the_bfd->my_archive == arch;
+ is3 = (lang_input_statement_type *) is3->next)
+ {
+ /* A MS dynamic import library can also contain static
+ members, so look for the first element with a .dll
+ extension, and use that for the remainder of the
+ comparisons. */
+ pnt = strrchr (is3->the_bfd->filename, '.');
+ if (pnt != NULL && strcmp (pnt, ".dll") == 0)
+ break;
+ }
+
+ if (is3 == NULL)
+ is_ms_arch = 0;
+ else
+ {
+ /* OK, found one. Now look to see if the remaining
+ (dynamic import) members use the same name. */
+ for (is2 = is;
+ is2 && is2->the_bfd->my_archive == arch;
+ is2 = (lang_input_statement_type *) is2->next)
+ {
+ /* Skip static members, ie anything with a .obj
+ extension. */
+ pnt = strrchr (is2->the_bfd->filename, '.');
+ if (pnt != NULL && strcmp (pnt, ".obj") == 0)
+ continue;
+
+ if (strcmp (is3->the_bfd->filename,
+ is2->the_bfd->filename))
+ {
+ is_ms_arch = 0;
+ break;
+ }
+ }
+ }
+ }
+
+ /* This fragment might have come from an .obj file in a Microsoft
+ import, and not an actual import record. If this is the case,
+ then leave the filename alone. */
+ pnt = strrchr (is->the_bfd->filename, '.');
+
+ if (is_ms_arch && (strcmp (pnt, ".dll") == 0))
+ {
+ int idata2 = 0, reloc_count=0;
+ asection *sec;
+ char *new_name, seq;
+
+ for (sec = is->the_bfd->sections; sec; sec = sec->next)
+ {
+ if (strcmp (sec->name, ".idata\$2") == 0)
+ idata2 = 1;
+ reloc_count += sec->reloc_count;
+ }
+
+ if (idata2) /* .idata2 is the TOC */
+ seq = 'a';
+ else if (reloc_count > 0) /* thunks */
+ seq = 'b';
+ else /* sentinel */
+ seq = 'c';
+
+ new_name = xmalloc (strlen (is->the_bfd->filename) + 3);
+ sprintf (new_name, "%s.%c", is->the_bfd->filename, seq);
+ is->the_bfd->filename = new_name;
+
+ new_name = xmalloc (strlen (is->filename) + 3);
+ sprintf (new_name, "%s.%c", is->filename, seq);
+ is->filename = new_name;
+ }
+ }
+ }
+ }
+}
+
+static void
+gld_${EMULATION_NAME}_before_allocation (void)
+{
+#ifdef TARGET_IS_ppcpe
+ /* Here we rummage through the found bfds to collect toc information. */
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (is)
+ {
+ if (!ppc_process_before_allocation (is->the_bfd, &link_info))
+ {
+ /* xgettext:c-format */
+ einfo (_("Errors encountered processing file %s\n"), is->filename);
+ }
+ }
+ }
+
+ /* We have seen it all. Allocate it, and carry on. */
+ ppc_allocate_toc_section (&link_info);
+#endif /* TARGET_IS_ppcpe */
+
+#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe)
+ /* FIXME: we should be able to set the size of the interworking stub
+ section.
+
+ Here we rummage through the found bfds to collect glue
+ information. FIXME: should this be based on a command line
+ option? krk@cygnus.com. */
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (is)
+ {
+ if (! bfd_arm_pe_process_before_allocation
+ (is->the_bfd, & link_info, support_old_code))
+ {
+ /* xgettext:c-format */
+ einfo (_("Errors encountered processing file %s for interworking"),
+ is->filename);
+ }
+ }
+ }
+
+ /* We have seen it all. Allocate it, and carry on. */
+ bfd_arm_pe_allocate_interworking_sections (& link_info);
+#endif /* TARGET_IS_armpe */
+}
+
+#ifdef DLL_SUPPORT
+/* This is called when an input file isn't recognized as a BFD. We
+ check here for .DEF files and pull them in automatically. */
+
+static int
+saw_option (char *option)
+{
+ int i;
+
+ for (i = 0; init[i].ptr; i++)
+ if (strcmp (init[i].symbol, option) == 0)
+ return init[i].inited;
+ return 0;
+}
+#endif /* DLL_SUPPORT */
+
+static bfd_boolean
+gld_${EMULATION_NAME}_unrecognized_file (lang_input_statement_type *entry ATTRIBUTE_UNUSED)
+{
+#ifdef DLL_SUPPORT
+ const char *ext = entry->filename + strlen (entry->filename) - 4;
+
+ if (strcmp (ext, ".def") == 0 || strcmp (ext, ".DEF") == 0)
+ {
+ if (pe_def_file == 0)
+ pe_def_file = def_file_empty ();
+
+ def_file_parse (entry->filename, pe_def_file);
+
+ if (pe_def_file)
+ {
+ int i, buflen=0, len;
+ char *buf;
+
+ for (i = 0; i < pe_def_file->num_exports; i++)
+ {
+ len = strlen (pe_def_file->exports[i].internal_name);
+ if (buflen < len + 2)
+ buflen = len + 2;
+ }
+
+ buf = (char *) xmalloc (buflen);
+
+ for (i = 0; i < pe_def_file->num_exports; i++)
+ {
+ struct bfd_link_hash_entry *h;
+
+ sprintf (buf, "_%s", pe_def_file->exports[i].internal_name);
+
+ h = bfd_link_hash_lookup (link_info.hash, buf, TRUE, TRUE, TRUE);
+ if (h == (struct bfd_link_hash_entry *) NULL)
+ einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
+ if (h->type == bfd_link_hash_new)
+ {
+ h->type = bfd_link_hash_undefined;
+ h->u.undef.abfd = NULL;
+ bfd_link_add_undef (link_info.hash, h);
+ }
+ }
+ free (buf);
+
+ /* def_file_print (stdout, pe_def_file); */
+ if (pe_def_file->is_dll == 1)
+ link_info.shared = 1;
+
+ if (pe_def_file->base_address != (bfd_vma)(-1))
+ {
+ pe.ImageBase =
+ pe_data (output_bfd)->pe_opthdr.ImageBase =
+ init[IMAGEBASEOFF].value = pe_def_file->base_address;
+ init[IMAGEBASEOFF].inited = 1;
+ if (image_base_statement)
+ image_base_statement->exp =
+ exp_assop ('=', "__image_base__", exp_intop (pe.ImageBase));
+ }
+
+#if 0
+ /* Not sure if these *should* be set. */
+ if (pe_def_file->version_major != -1)
+ {
+ pe.MajorImageVersion = pe_def_file->version_major;
+ pe.MinorImageVersion = pe_def_file->version_minor;
+ }
+#endif
+ if (pe_def_file->stack_reserve != -1
+ && ! saw_option ("__size_of_stack_reserve__"))
+ {
+ pe.SizeOfStackReserve = pe_def_file->stack_reserve;
+ if (pe_def_file->stack_commit != -1)
+ pe.SizeOfStackCommit = pe_def_file->stack_commit;
+ }
+ if (pe_def_file->heap_reserve != -1
+ && ! saw_option ("__size_of_heap_reserve__"))
+ {
+ pe.SizeOfHeapReserve = pe_def_file->heap_reserve;
+ if (pe_def_file->heap_commit != -1)
+ pe.SizeOfHeapCommit = pe_def_file->heap_commit;
+ }
+ return TRUE;
+ }
+ }
+#endif
+ return FALSE;
+}
+
+static bfd_boolean
+gld_${EMULATION_NAME}_recognized_file (lang_input_statement_type *entry ATTRIBUTE_UNUSED)
+{
+#ifdef DLL_SUPPORT
+#ifdef TARGET_IS_i386pe
+ pe_dll_id_target ("pei-i386");
+#endif
+#ifdef TARGET_IS_shpe
+ pe_dll_id_target ("pei-shl");
+#endif
+#ifdef TARGET_IS_mipspe
+ pe_dll_id_target ("pei-mips");
+#endif
+#ifdef TARGET_IS_armpe
+ pe_dll_id_target ("pei-arm-little");
+#endif
+ if (bfd_get_format (entry->the_bfd) == bfd_object)
+ {
+ char fbuf[LD_PATHMAX + 1];
+ const char *ext;
+
+ if (REALPATH (entry->filename, fbuf) == NULL)
+ strncpy (fbuf, entry->filename, sizeof (fbuf));
+
+ ext = fbuf + strlen (fbuf) - 4;
+
+ if (strcmp (ext, ".dll") == 0 || strcmp (ext, ".DLL") == 0)
+ return pe_implied_import_dll (fbuf);
+ }
+#endif
+ return FALSE;
+}
+
+static void
+gld_${EMULATION_NAME}_finish (void)
+{
+#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe)
+ struct bfd_link_hash_entry * h;
+
+ if (thumb_entry_symbol != NULL)
+ {
+ h = bfd_link_hash_lookup (link_info.hash, thumb_entry_symbol,
+ FALSE, FALSE, TRUE);
+
+ if (h != (struct bfd_link_hash_entry *) NULL
+ && (h->type == bfd_link_hash_defined
+ || h->type == bfd_link_hash_defweak)
+ && h->u.def.section->output_section != NULL)
+ {
+ static char buffer[32];
+ bfd_vma val;
+
+ /* Special procesing is required for a Thumb entry symbol. The
+ bottom bit of its address must be set. */
+ val = (h->u.def.value
+ + bfd_get_section_vma (output_bfd,
+ h->u.def.section->output_section)
+ + h->u.def.section->output_offset);
+
+ val |= 1;
+
+ /* Now convert this value into a string and store it in entry_symbol
+ where the lang_finish() function will pick it up. */
+ buffer[0] = '0';
+ buffer[1] = 'x';
+
+ sprintf_vma (buffer + 2, val);
+
+ if (entry_symbol.name != NULL && entry_from_cmdline)
+ einfo (_("%P: warning: '--thumb-entry %s' is overriding '-e %s'\n"),
+ thumb_entry_symbol, entry_symbol.name);
+ entry_symbol.name = buffer;
+ }
+ else
+ einfo (_("%P: warning: connot find thumb start symbol %s\n"), thumb_entry_symbol);
+ }
+#endif /* defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) */
+
+#ifdef DLL_SUPPORT
+ if (link_info.shared
+#if !defined(TARGET_IS_shpe) && !defined(TARGET_IS_mipspe)
+ || (!link_info.relocatable && pe_def_file->num_exports != 0)
+#endif
+ )
+ {
+ pe_dll_fill_sections (output_bfd, &link_info);
+ if (pe_implib_filename)
+ pe_dll_generate_implib (pe_def_file, pe_implib_filename);
+ }
+#if defined(TARGET_IS_shpe) || defined(TARGET_IS_mipspe)
+ /* ARM doesn't need relocs. */
+ else
+ {
+ pe_exe_fill_sections (output_bfd, &link_info);
+ }
+#endif
+
+ if (pe_out_def_filename)
+ pe_dll_generate_def_file (pe_out_def_filename);
+#endif /* DLL_SUPPORT */
+
+ /* I don't know where .idata gets set as code, but it shouldn't be. */
+ {
+ asection *asec = bfd_get_section_by_name (output_bfd, ".idata");
+
+ if (asec)
+ {
+ asec->flags &= ~SEC_CODE;
+ asec->flags |= SEC_DATA;
+ }
+ }
+}
+
+
+/* Find the last output section before given output statement.
+ Used by place_orphan. */
+
+static asection *
+output_prev_sec_find (lang_output_section_statement_type *os)
+{
+ asection *s = (asection *) NULL;
+ lang_statement_union_type *u;
+ lang_output_section_statement_type *lookup;
+
+ for (u = lang_output_section_statement.head;
+ u != (lang_statement_union_type *) NULL;
+ u = lookup->next)
+ {
+ lookup = &u->output_section_statement;
+ if (lookup == os)
+ return s;
+
+ if (lookup->bfd_section != NULL && lookup->bfd_section->owner != NULL)
+ s = lookup->bfd_section;
+ }
+
+ return NULL;
+}
+
+/* Place an orphan section.
+
+ We use this to put sections in a reasonable place in the file, and
+ to ensure that they are aligned as required.
+
+ We handle grouped sections here as well. A section named .foo$nn
+ goes into the output section .foo. All grouped sections are sorted
+ by name.
+
+ Grouped sections for the default sections are handled by the
+ default linker script using wildcards, and are sorted by
+ sort_sections. */
+
+struct orphan_save
+{
+ lang_output_section_statement_type *os;
+ asection **section;
+ lang_statement_union_type **stmt;
+};
+
+static bfd_boolean
+gld_${EMULATION_NAME}_place_orphan (lang_input_statement_type *file, asection *s)
+{
+ const char *secname;
+ char *hold_section_name;
+ char *dollar = NULL;
+ const char *ps = NULL;
+ lang_output_section_statement_type *os;
+ lang_statement_list_type add_child;
+
+ secname = bfd_get_section_name (s->owner, s);
+
+ /* Look through the script to see where to place this section. */
+ hold_section_name = xstrdup (secname);
+ if (!link_info.relocatable)
+ {
+ dollar = strchr (hold_section_name, '$');
+ if (dollar != NULL)
+ *dollar = '\0';
+ }
+
+ os = lang_output_section_find (hold_section_name);
+
+ lang_list_init (&add_child);
+
+ if (os != NULL
+ && (os->bfd_section == NULL
+ || ((s->flags ^ os->bfd_section->flags)
+ & (SEC_LOAD | SEC_ALLOC)) == 0))
+ {
+ /* We already have an output section statement with this
+ name, and its bfd section, if any, has compatible flags. */
+ lang_add_section (&add_child, s, os, file);
+ }
+ else
+ {
+ struct orphan_save *place;
+ static struct orphan_save hold_text;
+ static struct orphan_save hold_rdata;
+ static struct orphan_save hold_data;
+ static struct orphan_save hold_bss;
+ char *outsecname;
+ lang_statement_list_type *old;
+ lang_statement_list_type add;
+ etree_type *address;
+
+ /* Try to put the new output section in a reasonable place based
+ on the section name and section flags. */
+#define HAVE_SECTION(hold, name) \
+(hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL)
+
+ place = NULL;
+ if ((s->flags & SEC_ALLOC) == 0)
+ ;
+ else if ((s->flags & SEC_HAS_CONTENTS) == 0
+ && HAVE_SECTION (hold_bss, ".bss"))
+ place = &hold_bss;
+ else if ((s->flags & SEC_READONLY) == 0
+ && HAVE_SECTION (hold_data, ".data"))
+ place = &hold_data;
+ else if ((s->flags & SEC_CODE) == 0
+ && (s->flags & SEC_READONLY) != 0
+ && HAVE_SECTION (hold_rdata, ".rdata"))
+ place = &hold_rdata;
+ else if ((s->flags & SEC_READONLY) != 0
+ && HAVE_SECTION (hold_text, ".text"))
+ place = &hold_text;
+
+#undef HAVE_SECTION
+
+ /* Choose a unique name for the section. This will be needed if
+ the same section name appears in the input file with
+ different loadable or allocatable characteristics. */
+ outsecname = xstrdup (hold_section_name);
+ if (bfd_get_section_by_name (output_bfd, outsecname) != NULL)
+ {
+ unsigned int len;
+ char *newname;
+ unsigned int i;
+
+ len = strlen (outsecname);
+ newname = xmalloc (len + 5);
+ strcpy (newname, outsecname);
+ i = 0;
+ do
+ {
+ sprintf (newname + len, "%d", i);
+ ++i;
+ }
+ while (bfd_get_section_by_name (output_bfd, newname) != NULL);
+
+ free (outsecname);
+ outsecname = newname;
+ }
+
+ /* Start building a list of statements for this section. */
+ old = stat_ptr;
+ stat_ptr = &add;
+ lang_list_init (stat_ptr);
+
+ if (config.build_constructors)
+ {
+ /* If the name of the section is representable in C, then create
+ symbols to mark the start and the end of the section. */
+ for (ps = outsecname; *ps != '\0'; ps++)
+ if (! ISALNUM ((unsigned char) *ps) && *ps != '_')
+ break;
+ if (*ps == '\0')
+ {
+ char *symname;
+ etree_type *e_align;
+
+ symname = (char *) xmalloc (ps - outsecname + sizeof "___start_");
+ sprintf (symname, "___start_%s", outsecname);
+ e_align = exp_unop (ALIGN_K,
+ exp_intop ((bfd_vma) 1 << s->alignment_power));
+ lang_add_assignment (exp_assop ('=', symname, e_align));
+ }
+ }
+
+ if (link_info.relocatable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
+ address = exp_intop ((bfd_vma) 0);
+ else
+ {
+ /* All sections in an executable must be aligned to a page
+ boundary. */
+ address = exp_unop (ALIGN_K,
+ exp_nameop (NAME, "__section_alignment__"));
+ }
+
+ os = lang_enter_output_section_statement (outsecname, address, 0,
+ (etree_type *) NULL,
+ (etree_type *) NULL,
+ (etree_type *) NULL);
+
+ lang_add_section (&add_child, s, os, file);
+
+ lang_leave_output_section_statement
+ ((bfd_vma) 0, "*default*",
+ (struct lang_output_section_phdr_list *) NULL, NULL);
+
+ if (config.build_constructors && *ps == '\0')
+ {
+ char *symname;
+
+ /* lang_leave_ouput_section_statement resets stat_ptr.
+ Put stat_ptr back where we want it. */
+ if (place != NULL)
+ stat_ptr = &add;
+
+ symname = (char *) xmalloc (ps - outsecname + sizeof "___stop_");
+ sprintf (symname, "___stop_%s", outsecname);
+ lang_add_assignment (exp_assop ('=', symname,
+ exp_nameop (NAME, ".")));
+ }
+
+ stat_ptr = old;
+
+ if (place != NULL && os->bfd_section != NULL)
+ {
+ asection *snew, **pps;
+
+ snew = os->bfd_section;
+
+ /* Shuffle the bfd section list to make the output file look
+ neater. This is really only cosmetic. */
+ if (place->section == NULL)
+ {
+ asection *bfd_section = place->os->bfd_section;
+
+ /* If the output statement hasn't been used to place
+ any input sections (and thus doesn't have an output
+ bfd_section), look for the closest prior output statement
+ having an output section. */
+ if (bfd_section == NULL)
+ bfd_section = output_prev_sec_find (place->os);
+
+ if (bfd_section != NULL && bfd_section != snew)
+ place->section = &bfd_section->next;
+ }
+
+ if (place->section != NULL)
+ {
+ /* Unlink the section. */
+ for (pps = &output_bfd->sections;
+ *pps != snew;
+ pps = &(*pps)->next)
+ ;
+ bfd_section_list_remove (output_bfd, pps);
+
+ /* Now tack it on to the "place->os" section list. */
+ bfd_section_list_insert (output_bfd, place->section, snew);
+ }
+
+ /* Save the end of this list. Further ophans of this type will
+ follow the one we've just added. */
+ place->section = &snew->next;
+
+ /* The following is non-cosmetic. We try to put the output
+ statements in some sort of reasonable order here, because
+ they determine the final load addresses of the orphan
+ sections. In addition, placing output statements in the
+ wrong order may require extra segments. For instance,
+ given a typical situation of all read-only sections placed
+ in one segment and following that a segment containing all
+ the read-write sections, we wouldn't want to place an orphan
+ read/write section before or amongst the read-only ones. */
+ if (add.head != NULL)
+ {
+ if (place->stmt == NULL)
+ {
+ /* Put the new statement list right at the head. */
+ *add.tail = place->os->header.next;
+ place->os->header.next = add.head;
+ }
+ else
+ {
+ /* Put it after the last orphan statement we added. */
+ *add.tail = *place->stmt;
+ *place->stmt = add.head;
+ }
+
+ /* Fix the global list pointer if we happened to tack our
+ new list at the tail. */
+ if (*old->tail == add.head)
+ old->tail = add.tail;
+
+ /* Save the end of this list. */
+ place->stmt = add.tail;
+ }
+ }
+ }
+
+ {
+ lang_statement_union_type **pl = &os->children.head;
+
+ if (dollar != NULL)
+ {
+ bfd_boolean found_dollar;
+
+ /* The section name has a '$'. Sort it with the other '$'
+ sections. */
+ found_dollar = FALSE;
+ for ( ; *pl != NULL; pl = &(*pl)->header.next)
+ {
+ lang_input_section_type *ls;
+ const char *lname;
+
+ if ((*pl)->header.type != lang_input_section_enum)
+ continue;
+
+ ls = &(*pl)->input_section;
+
+ lname = bfd_get_section_name (ls->ifile->the_bfd, ls->section);
+ if (strchr (lname, '$') == NULL)
+ {
+ if (found_dollar)
+ break;
+ }
+ else
+ {
+ found_dollar = TRUE;
+ if (strcmp (secname, lname) < 0)
+ break;
+ }
+ }
+ }
+
+ if (add_child.head != NULL)
+ {
+ add_child.head->header.next = *pl;
+ *pl = add_child.head;
+ }
+ }
+
+ free (hold_section_name);
+
+ return TRUE;
+}
+
+static bfd_boolean
+gld_${EMULATION_NAME}_open_dynamic_archive
+ (const char *arch ATTRIBUTE_UNUSED, search_dirs_type *search,
+ lang_input_statement_type *entry)
+{
+ const char * filename;
+ char * string;
+
+ if (! entry->is_archive)
+ return FALSE;
+
+ filename = entry->filename;
+
+ string = (char *) xmalloc (strlen (search->name)
+ + strlen (filename)
+ + sizeof "/lib.a.dll"
+#ifdef DLL_SUPPORT
+ + (pe_dll_search_prefix ? strlen (pe_dll_search_prefix) : 0)
+#endif
+ + 1);
+
+ /* Try "libfoo.dll.a" first (preferred explicit import library for dll's. */
+ sprintf (string, "%s/lib%s.dll.a", search->name, filename);
+
+ if (! ldfile_try_open_bfd (string, entry))
+ {
+ /* Try "foo.dll.a" next (alternate explicit import library for dll's. */
+ sprintf (string, "%s/%s.dll.a", search->name, filename);
+ if (! ldfile_try_open_bfd (string, entry))
+ {
+ /* Try libfoo.a next. Normally, this would be interpreted as a static
+ library, but it *could* be an import library. For backwards compatibility,
+ libfoo.a needs to ==precede== libfoo.dll and foo.dll in the search,
+ or sometimes errors occur when building legacy packages.
+
+ Putting libfoo.a here means that in a failure case (i.e. the library
+ -lfoo is not found) we will search for libfoo.a twice before
+ giving up -- once here, and once when searching for a "static" lib.
+ for a "static" lib. */
+ /* Try "libfoo.a" (import lib, or static lib, but must
+ take precedence over dll's). */
+ sprintf (string, "%s/lib%s.a", search->name, filename);
+ if (! ldfile_try_open_bfd (string, entry))
+ {
+#ifdef DLL_SUPPORT
+ if (pe_dll_search_prefix)
+ {
+ /* Try "<prefix>foo.dll" (preferred dll name, if specified). */
+ sprintf (string, "%s/%s%s.dll", search->name, pe_dll_search_prefix, filename);
+ if (! ldfile_try_open_bfd (string, entry))
+ {
+ /* Try "libfoo.dll" (default preferred dll name). */
+ sprintf (string, "%s/lib%s.dll", search->name, filename);
+ if (! ldfile_try_open_bfd (string, entry))
+ {
+ /* Finally, try "foo.dll" (alternate dll name). */
+ sprintf (string, "%s/%s.dll", search->name, filename);
+ if (! ldfile_try_open_bfd (string, entry))
+ {
+ free (string);
+ return FALSE;
+ }
+ }
+ }
+ }
+ else /* pe_dll_search_prefix not specified. */
+#endif
+ {
+ /* Try "libfoo.dll" (preferred dll name). */
+ sprintf (string, "%s/lib%s.dll", search->name, filename);
+ if (! ldfile_try_open_bfd (string, entry))
+ {
+ /* Finally, try "foo.dll" (alternate dll name). */
+ sprintf (string, "%s/%s.dll", search->name, filename);
+ if (! ldfile_try_open_bfd (string, entry))
+ {
+ free (string);
+ return FALSE;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ entry->filename = string;
+
+ return TRUE;
+}
+
+static int
+gld_${EMULATION_NAME}_find_potential_libraries
+ (char *name, lang_input_statement_type *entry)
+{
+ return ldfile_open_file_search (name, entry, "", ".lib");
+}
+
+static char *
+gld_${EMULATION_NAME}_get_script (int *isfile)
+EOF
+# Scripts compiled in.
+# sed commands to quote an ld script as a C string.
+sc="-f stringify.sed"
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 0;
+
+ if (link_info.relocatable && config.build_constructors)
+ return
+EOF
+sed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c
+echo ' ; else if (link_info.relocatable) 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
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+
+struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
+{
+ gld_${EMULATION_NAME}_before_parse,
+ syslib_default,
+ hll_default,
+ gld_${EMULATION_NAME}_after_parse,
+ gld_${EMULATION_NAME}_after_open,
+ after_allocation_default,
+ set_output_arch_default,
+ ldemul_default_target,
+ gld_${EMULATION_NAME}_before_allocation,
+ gld_${EMULATION_NAME}_get_script,
+ "${EMULATION_NAME}",
+ "${OUTPUT_FORMAT}",
+ gld_${EMULATION_NAME}_finish,
+ NULL, /* Create output section statements. */
+ gld_${EMULATION_NAME}_open_dynamic_archive,
+ gld_${EMULATION_NAME}_place_orphan,
+ gld_${EMULATION_NAME}_set_symbols,
+ NULL, /* parse_args */
+ gld${EMULATION_NAME}_add_options,
+ gld${EMULATION_NAME}_handle_option,
+ gld_${EMULATION_NAME}_unrecognized_file,
+ gld_${EMULATION_NAME}_list_options,
+ gld_${EMULATION_NAME}_recognized_file,
+ gld_${EMULATION_NAME}_find_potential_libraries,
+ NULL /* new_vers_pattern. */
+};
+EOF
diff --git a/x/binutils/ld/emultempl/ppc32elf.em b/x/binutils/ld/emultempl/ppc32elf.em
new file mode 100644
index 0000000..4614593
--- /dev/null
+++ b/x/binutils/ld/emultempl/ppc32elf.em
@@ -0,0 +1,80 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2003 Free Software Foundation, Inc.
+#
+# This file is part of GLD, the Gnu Linker.
+#
+# 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 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.
+#
+
+# This file is sourced from elf32.em, and defines extra powerpc64-elf
+# specific routines.
+#
+cat >>e${EMULATION_NAME}.c <<EOF
+
+#include "libbfd.h"
+#include "elf32-ppc.h"
+
+/* Whether to run tls optimization. */
+static int notlsopt = 0;
+
+static void
+ppc_before_allocation (void)
+{
+ extern const bfd_target bfd_elf32_powerpc_vec;
+ extern const bfd_target bfd_elf32_powerpcle_vec;
+
+ if (link_info.hash->creator == &bfd_elf32_powerpc_vec
+ || link_info.hash->creator == &bfd_elf32_powerpcle_vec)
+ {
+ if (ppc_elf_tls_setup (output_bfd, &link_info) && !notlsopt)
+ {
+ if (!ppc_elf_tls_optimize (output_bfd, &link_info))
+ {
+ einfo ("%X%P: TLS problem %E\n");
+ return;
+ }
+ }
+ }
+ gld${EMULATION_NAME}_before_allocation ();
+}
+
+EOF
+
+# Define some shell vars to insert bits of code into the standard elf
+# parse_args and list_options functions.
+#
+PARSE_AND_LIST_PROLOGUE='
+#define OPTION_NO_TLS_OPT 301
+'
+
+PARSE_AND_LIST_LONGOPTS='
+ { "no-tls-optimize", no_argument, NULL, OPTION_NO_TLS_OPT },
+'
+
+PARSE_AND_LIST_OPTIONS='
+ fprintf (file, _("\
+ --no-tls-optimize Don'\''t try to optimize TLS accesses.\n"
+ ));
+'
+
+PARSE_AND_LIST_ARGS_CASES='
+ case OPTION_NO_TLS_OPT:
+ notlsopt = 1;
+ break;
+'
+
+# Put these extra ppc64elf routines in ld_${EMULATION_NAME}_emulation
+#
+LDEMUL_BEFORE_ALLOCATION=ppc_before_allocation
diff --git a/x/binutils/ld/emultempl/ppc64elf.em b/x/binutils/ld/emultempl/ppc64elf.em
new file mode 100644
index 0000000..4f408a9
--- /dev/null
+++ b/x/binutils/ld/emultempl/ppc64elf.em
@@ -0,0 +1,529 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2002, 2003, 2004 Free Software Foundation, Inc.
+#
+# This file is part of GLD, the Gnu Linker.
+#
+# 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 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.
+#
+
+# This file is sourced from elf32.em, and defines extra powerpc64-elf
+# specific routines.
+#
+cat >>e${EMULATION_NAME}.c <<EOF
+
+#include "ldctor.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+#include "elf64-ppc.h"
+
+/* Fake input file for stubs. */
+static lang_input_statement_type *stub_file;
+static int stub_added = 0;
+
+/* Whether we need to call ppc_layout_sections_again. */
+static int need_laying_out = 0;
+
+/* Maximum size of a group of input sections that can be handled by
+ one stub section. A value of +/-1 indicates the bfd back-end
+ should use a suitable default size. */
+static bfd_signed_vma group_size = 1;
+
+/* Whether to add ".foo" entries for each "foo" in a version script. */
+static int dotsyms = 1;
+
+/* Whether to run tls optimization. */
+static int notlsopt = 0;
+
+/* Whether to emit symbols for stubs. */
+static int emit_stub_syms = 0;
+
+static asection *toc_section = 0;
+
+
+/* This is called before the input files are opened. We create a new
+ fake input file to hold the stub sections. */
+
+static void
+ppc_create_output_section_statements (void)
+{
+ extern const bfd_target bfd_elf64_powerpc_vec;
+ extern const bfd_target bfd_elf64_powerpcle_vec;
+
+ if (link_info.hash->creator != &bfd_elf64_powerpc_vec
+ && link_info.hash->creator != &bfd_elf64_powerpcle_vec)
+ return;
+
+ link_info.wrap_char = '.';
+
+ stub_file = lang_add_input_file ("linker stubs",
+ lang_input_file_is_fake_enum,
+ NULL);
+ stub_file->the_bfd = bfd_create ("linker stubs", output_bfd);
+ if (stub_file->the_bfd == NULL
+ || !bfd_set_arch_mach (stub_file->the_bfd,
+ bfd_get_arch (output_bfd),
+ bfd_get_mach (output_bfd)))
+ {
+ einfo ("%X%P: can not create BFD %E\n");
+ return;
+ }
+
+ ldlang_add_file (stub_file);
+ ppc64_elf_init_stub_bfd (stub_file->the_bfd, &link_info);
+}
+
+static void
+ppc_after_open (void)
+{
+ if (!ppc64_elf_mark_entry_syms (&link_info))
+ {
+ einfo ("%X%P: can not mark entry symbols %E\n");
+ return;
+ }
+
+ gld${EMULATION_NAME}_after_open ();
+}
+
+static void
+ppc_before_allocation (void)
+{
+ if (stub_file != NULL)
+ {
+ if (!ppc64_elf_edit_opd (output_bfd, &link_info))
+ {
+ einfo ("%X%P: can not edit opd %E\n");
+ return;
+ }
+
+ if (ppc64_elf_tls_setup (output_bfd, &link_info) && !notlsopt)
+ {
+ /* Size the sections. This is premature, but we want to know the
+ TLS segment layout so that certain optimizations can be done. */
+ lang_size_sections (stat_ptr->head, abs_output_section,
+ &stat_ptr->head, 0, 0, NULL, TRUE);
+
+ if (!ppc64_elf_tls_optimize (output_bfd, &link_info))
+ {
+ einfo ("%X%P: TLS problem %E\n");
+ return;
+ }
+
+ /* We must not cache anything from the preliminary sizing. */
+ elf_tdata (output_bfd)->program_header_size = 0;
+ lang_reset_memory_regions ();
+ }
+ }
+
+ gld${EMULATION_NAME}_before_allocation ();
+}
+
+struct hook_stub_info
+{
+ lang_statement_list_type add;
+ asection *input_section;
+};
+
+/* Traverse the linker tree to find the spot where the stub goes. */
+
+static bfd_boolean
+hook_in_stub (struct hook_stub_info *info, lang_statement_union_type **lp)
+{
+ lang_statement_union_type *l;
+ bfd_boolean ret;
+
+ for (; (l = *lp) != NULL; lp = &l->header.next)
+ {
+ switch (l->header.type)
+ {
+ case lang_constructors_statement_enum:
+ ret = hook_in_stub (info, &constructor_list.head);
+ if (ret)
+ return ret;
+ break;
+
+ case lang_output_section_statement_enum:
+ ret = hook_in_stub (info,
+ &l->output_section_statement.children.head);
+ if (ret)
+ return ret;
+ break;
+
+ case lang_wild_statement_enum:
+ ret = hook_in_stub (info, &l->wild_statement.children.head);
+ if (ret)
+ return ret;
+ break;
+
+ case lang_group_statement_enum:
+ ret = hook_in_stub (info, &l->group_statement.children.head);
+ if (ret)
+ return ret;
+ break;
+
+ case lang_input_section_enum:
+ if (l->input_section.section == info->input_section)
+ {
+ /* We've found our section. Insert the stub immediately
+ before its associated input section. */
+ *lp = info->add.head;
+ *(info->add.tail) = l;
+ return TRUE;
+ }
+ break;
+
+ case lang_data_statement_enum:
+ case lang_reloc_statement_enum:
+ case lang_object_symbols_statement_enum:
+ case lang_output_statement_enum:
+ case lang_target_statement_enum:
+ case lang_input_statement_enum:
+ case lang_assignment_statement_enum:
+ case lang_padding_statement_enum:
+ case lang_address_statement_enum:
+ case lang_fill_statement_enum:
+ break;
+
+ default:
+ FAIL ();
+ break;
+ }
+ }
+ return FALSE;
+}
+
+
+/* Call-back for ppc64_elf_size_stubs. */
+
+/* Create a new stub section, and arrange for it to be linked
+ immediately before INPUT_SECTION. */
+
+static asection *
+ppc_add_stub_section (const char *stub_sec_name, asection *input_section)
+{
+ asection *stub_sec;
+ flagword flags;
+ asection *output_section;
+ const char *secname;
+ lang_output_section_statement_type *os;
+ struct hook_stub_info info;
+
+ stub_sec = bfd_make_section_anyway (stub_file->the_bfd, stub_sec_name);
+ if (stub_sec == NULL)
+ goto err_ret;
+
+ flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
+ | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP);
+ if (!bfd_set_section_flags (stub_file->the_bfd, stub_sec, flags))
+ goto err_ret;
+
+ output_section = input_section->output_section;
+ secname = bfd_get_section_name (output_section->owner, output_section);
+ os = lang_output_section_find (secname);
+
+ info.input_section = input_section;
+ lang_list_init (&info.add);
+ lang_add_section (&info.add, stub_sec, os, stub_file);
+
+ if (info.add.head == NULL)
+ goto err_ret;
+
+ stub_added = 1;
+ if (hook_in_stub (&info, &os->children.head))
+ return stub_sec;
+
+ err_ret:
+ einfo ("%X%P: can not make stub section: %E\n");
+ return NULL;
+}
+
+
+/* Another call-back for ppc64_elf_size_stubs. */
+
+static void
+ppc_layout_sections_again (void)
+{
+ /* If we have changed sizes of the stub sections, then we need
+ to recalculate all the section offsets. This may mean we need to
+ add even more stubs. */
+ need_laying_out = 0;
+
+ lang_reset_memory_regions ();
+
+ /* Resize the sections. */
+ lang_size_sections (stat_ptr->head, abs_output_section,
+ &stat_ptr->head, 0, 0, NULL, TRUE);
+
+ /* Recalculate TOC base. */
+ ldemul_after_allocation ();
+
+ /* Do the assignments again. */
+ lang_do_assignments (stat_ptr->head, abs_output_section, NULL, 0);
+}
+
+
+/* Call the back-end function to set TOC base after we have placed all
+ the sections. */
+static void
+gld${EMULATION_NAME}_after_allocation (void)
+{
+ if (!link_info.relocatable)
+ _bfd_set_gp_value (output_bfd, ppc64_elf_toc (output_bfd));
+}
+
+
+static void
+build_toc_list (lang_statement_union_type *statement)
+{
+ if (statement->header.type == lang_input_section_enum
+ && !statement->input_section.ifile->just_syms_flag
+ && statement->input_section.section->output_section == toc_section)
+ ppc64_elf_next_toc_section (&link_info, statement->input_section.section);
+}
+
+
+static void
+build_section_lists (lang_statement_union_type *statement)
+{
+ if (statement->header.type == lang_input_section_enum
+ && !statement->input_section.ifile->just_syms_flag
+ && statement->input_section.section->output_section != NULL
+ && statement->input_section.section->output_section->owner == output_bfd)
+ {
+ if (!ppc64_elf_next_input_section (&link_info,
+ statement->input_section.section))
+ einfo ("%X%P: can not size stub section: %E\n");
+ }
+}
+
+
+/* Final emulation specific call. */
+
+static void
+gld${EMULATION_NAME}_finish (void)
+{
+ /* e_entry on PowerPC64 points to the function descriptor for
+ _start. If _start is missing, default to the first function
+ descriptor in the .opd section. */
+ entry_section = ".opd";
+
+ /* bfd_elf_discard_info just plays with debugging sections,
+ ie. doesn't affect any code, so we can delay resizing the
+ sections. It's likely we'll resize everything in the process of
+ adding stubs. */
+ if (bfd_elf_discard_info (output_bfd, &link_info))
+ need_laying_out = 1;
+
+ /* If generating a relocatable output file, then we don't have any
+ stubs. */
+ if (stub_file != NULL && !link_info.relocatable)
+ {
+ int ret = ppc64_elf_setup_section_lists (output_bfd, &link_info);
+ if (ret != 0)
+ {
+ if (ret < 0)
+ {
+ einfo ("%X%P: can not size stub section: %E\n");
+ return;
+ }
+
+ toc_section = bfd_get_section_by_name (output_bfd, ".got");
+ if (toc_section != NULL)
+ lang_for_each_statement (build_toc_list);
+
+ ppc64_elf_reinit_toc (output_bfd, &link_info);
+
+ lang_for_each_statement (build_section_lists);
+
+ /* Call into the BFD backend to do the real work. */
+ if (!ppc64_elf_size_stubs (output_bfd,
+ &link_info,
+ group_size,
+ &ppc_add_stub_section,
+ &ppc_layout_sections_again))
+ {
+ einfo ("%X%P: can not size stub section: %E\n");
+ return;
+ }
+ }
+ }
+
+ if (need_laying_out)
+ ppc_layout_sections_again ();
+
+ if (stub_added)
+ {
+ char *msg = NULL;
+ char *line, *endline;
+
+ if (!ppc64_elf_build_stubs (emit_stub_syms, &link_info,
+ config.stats ? &msg : NULL))
+ einfo ("%X%P: can not build stubs: %E\n");
+
+ for (line = msg; line != NULL; line = endline)
+ {
+ endline = strchr (line, '\n');
+ if (endline != NULL)
+ *endline++ = '\0';
+ fprintf (stderr, "%s: %s\n", program_name, line);
+ }
+ if (msg != NULL)
+ free (msg);
+ }
+}
+
+
+/* Add a pattern matching ".foo" for every "foo" in a version script.
+
+ The reason for doing this is that many shared library version
+ scripts export a selected set of functions or data symbols, forcing
+ others local. eg.
+
+ . VERS_1 {
+ . global:
+ . this; that; some; thing;
+ . local:
+ . *;
+ . };
+
+ To make the above work for PowerPC64, we need to export ".this",
+ ".that" and so on, otherwise only the function descriptor syms are
+ exported. Lack of an exported function code sym may cause a
+ definition to be pulled in from a static library. */
+
+static struct bfd_elf_version_expr *
+gld${EMULATION_NAME}_new_vers_pattern (struct bfd_elf_version_expr *entry)
+{
+ struct bfd_elf_version_expr *dot_entry;
+ unsigned int len;
+ char *dot_pat;
+
+ if (!dotsyms || entry->pattern[0] == '*' || entry->pattern[0] == '.')
+ return entry;
+
+ dot_entry = xmalloc (sizeof *dot_entry);
+ *dot_entry = *entry;
+ dot_entry->next = entry;
+ len = strlen (entry->pattern) + 2;
+ dot_pat = xmalloc (len);
+ dot_pat[0] = '.';
+ memcpy (dot_pat + 1, entry->pattern, len - 1);
+ dot_entry->pattern = dot_pat;
+ return dot_entry;
+}
+
+
+/* Avoid processing the fake stub_file in vercheck, stat_needed and
+ check_needed routines. */
+
+static void (*real_func) (lang_input_statement_type *);
+
+static void ppc_for_each_input_file_wrapper (lang_input_statement_type *l)
+{
+ if (l != stub_file)
+ (*real_func) (l);
+}
+
+static void
+ppc_lang_for_each_input_file (void (*func) (lang_input_statement_type *))
+{
+ real_func = func;
+ lang_for_each_input_file (&ppc_for_each_input_file_wrapper);
+}
+
+#define lang_for_each_input_file ppc_lang_for_each_input_file
+
+EOF
+
+# Define some shell vars to insert bits of code into the standard elf
+# parse_args and list_options functions.
+#
+PARSE_AND_LIST_PROLOGUE='
+#define OPTION_STUBGROUP_SIZE 301
+#define OPTION_STUBSYMS (OPTION_STUBGROUP_SIZE + 1)
+#define OPTION_DOTSYMS (OPTION_STUBSYMS + 1)
+#define OPTION_NO_DOTSYMS (OPTION_DOTSYMS + 1)
+#define OPTION_NO_TLS_OPT (OPTION_NO_DOTSYMS + 1)
+'
+
+PARSE_AND_LIST_LONGOPTS='
+ { "stub-group-size", required_argument, NULL, OPTION_STUBGROUP_SIZE },
+ { "emit-stub-syms", no_argument, NULL, OPTION_STUBSYMS },
+ { "dotsyms", no_argument, NULL, OPTION_DOTSYMS },
+ { "no-dotsyms", no_argument, NULL, OPTION_NO_DOTSYMS },
+ { "no-tls-optimize", no_argument, NULL, OPTION_NO_TLS_OPT },
+'
+
+PARSE_AND_LIST_OPTIONS='
+ fprintf (file, _("\
+ --stub-group-size=N Maximum size of a group of input sections that can be\n\
+ handled by one stub section. A negative value\n\
+ locates all stubs before their branches (with a\n\
+ group size of -N), while a positive value allows\n\
+ two groups of input sections, one before, and one\n\
+ after each stub section. Values of +/-1 indicate\n\
+ the linker should choose suitable defaults.\n"
+ ));
+ fprintf (file, _("\
+ --emit-stub-syms Label linker stubs with a symbol.\n"
+ ));
+ fprintf (file, _("\
+ --dotsyms For every version pattern \"foo\" in a version script,\n\
+ add \".foo\" so that function code symbols are\n\
+ treated the same as function descriptor symbols.\n\
+ Defaults to on.\n"
+ ));
+ fprintf (file, _("\
+ --no-dotsyms Don'\''t do anything special in version scripts.\n"
+ ));
+ fprintf (file, _("\
+ --no-tls-optimize Don'\''t try to optimize TLS accesses.\n"
+ ));
+'
+
+PARSE_AND_LIST_ARGS_CASES='
+ case OPTION_STUBGROUP_SIZE:
+ {
+ const char *end;
+ group_size = bfd_scan_vma (optarg, &end, 0);
+ if (*end)
+ einfo (_("%P%F: invalid number `%s'\''\n"), optarg);
+ }
+ break;
+
+ case OPTION_STUBSYMS:
+ emit_stub_syms = 1;
+ break;
+
+ case OPTION_DOTSYMS:
+ dotsyms = 1;
+ break;
+
+ case OPTION_NO_DOTSYMS:
+ dotsyms = 0;
+ break;
+
+ case OPTION_NO_TLS_OPT:
+ notlsopt = 1;
+ break;
+'
+
+# Put these extra ppc64elf routines in ld_${EMULATION_NAME}_emulation
+#
+LDEMUL_AFTER_OPEN=ppc_after_open
+LDEMUL_BEFORE_ALLOCATION=ppc_before_allocation
+LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation
+LDEMUL_FINISH=gld${EMULATION_NAME}_finish
+LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=ppc_create_output_section_statements
+LDEMUL_NEW_VERS_PATTERN=gld${EMULATION_NAME}_new_vers_pattern
diff --git a/x/binutils/ld/emultempl/stringify.sed b/x/binutils/ld/emultempl/stringify.sed
new file mode 100644
index 0000000..a526d3f
--- /dev/null
+++ b/x/binutils/ld/emultempl/stringify.sed
@@ -0,0 +1,4 @@
+s/["\\]/\\&/g
+s/$/\\n\\/
+1 s/^/"/
+$ s/$/n"/
diff --git a/x/binutils/ld/emultempl/sunos.em b/x/binutils/ld/emultempl/sunos.em
new file mode 100644
index 0000000..358bc9a
--- /dev/null
+++ b/x/binutils/ld/emultempl/sunos.em
@@ -0,0 +1,1031 @@
+# 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! */
+
+/* SunOS emulation code for ${EMULATION_NAME}
+ Copyright 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002,
+ 2003, 2004 Free Software Foundation, Inc.
+ Written by Steve Chamberlain <sac@cygnus.com>
+ SunOS shared library support by Ian Lance Taylor <ian@cygnus.com>
+
+This file is part of GLD, the Gnu Linker.
+
+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 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. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "libiberty.h"
+#include "safe-ctype.h"
+
+#include "ld.h"
+#include "ldmain.h"
+#include "ldmisc.h"
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldfile.h"
+#include "ldemul.h"
+
+#ifdef HAVE_DIRENT_H
+# include <dirent.h>
+#else
+# define dirent direct
+# ifdef HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif
+# ifdef HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif
+# ifdef HAVE_NDIR_H
+# include <ndir.h>
+# endif
+#endif
+
+static void gld${EMULATION_NAME}_find_so
+ (lang_input_statement_type *);
+static char *gld${EMULATION_NAME}_search_dir
+ (const char *, const char *, bfd_boolean *);
+static void gld${EMULATION_NAME}_check_needed
+ (lang_input_statement_type *);
+static bfd_boolean gld${EMULATION_NAME}_search_needed
+ (const char *, const char *);
+static bfd_boolean gld${EMULATION_NAME}_try_needed
+ (const char *, const char *);
+static void gld${EMULATION_NAME}_find_assignment
+ (lang_statement_union_type *);
+static void gld${EMULATION_NAME}_find_exp_assignment
+ (etree_type *);
+static void gld${EMULATION_NAME}_count_need
+ (lang_input_statement_type *);
+static void gld${EMULATION_NAME}_set_need
+ (lang_input_statement_type *);
+
+static void
+gld${EMULATION_NAME}_before_parse (void)
+{
+ ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`);
+ config.dynamic_link = TRUE;
+ config.has_shared = TRUE;
+}
+
+/* This is called after the command line arguments have been parsed,
+ but before the linker script has been read. If this is a native
+ linker, we add the directories in LD_LIBRARY_PATH to the search
+ list. */
+
+static void
+gld${EMULATION_NAME}_set_symbols (void)
+{
+EOF
+if [ "x${host}" = "x${target}" ] ; then
+ case " ${EMULATION_LIBPATH} " in
+ *" ${EMULATION_NAME} "*)
+cat >>e${EMULATION_NAME}.c <<EOF
+ const char *env;
+
+ env = (const char *) getenv ("LD_LIBRARY_PATH");
+ if (env != NULL)
+ {
+ char *l;
+
+ l = xstrdup (env);
+ while (1)
+ {
+ char *c;
+
+ c = strchr (l, ':');
+ if (c != NULL)
+ *c++ = '\0';
+ if (*l != '\0')
+ ldfile_add_library_path (l, FALSE);
+ if (c == NULL)
+ break;
+ l = c;
+ }
+ }
+EOF
+ ;;
+ esac
+fi
+cat >>e${EMULATION_NAME}.c <<EOF
+}
+
+/* Despite the name, we use this routine to search for dynamic
+ libraries. On SunOS this requires a directory search. We need to
+ find the .so file with the highest version number. The user may
+ restrict the major version by saying, e.g., -lc.1. Also, if we
+ find a .so file, we need to look for a the same file after
+ replacing .so with .sa; if it exists, it will be an archive which
+ provide some initializations for data symbols, and we need to
+ search it after including the .so file. */
+
+static void
+gld${EMULATION_NAME}_create_output_section_statements (void)
+{
+ lang_for_each_input_file (gld${EMULATION_NAME}_find_so);
+}
+
+/* Search the directory for a .so file for each library search. */
+
+static void
+gld${EMULATION_NAME}_find_so (lang_input_statement_type *inp)
+{
+ search_dirs_type *search;
+ char *found = NULL;
+ char *alc;
+ struct stat st;
+
+ if (! inp->search_dirs_flag
+ || ! inp->is_archive
+ || ! inp->dynamic)
+ return;
+
+ ASSERT (strncmp (inp->local_sym_name, "-l", 2) == 0);
+
+ for (search = search_head; search != NULL; search = search->next)
+ {
+ bfd_boolean found_static;
+
+ found = gld${EMULATION_NAME}_search_dir (search->name, inp->filename,
+ &found_static);
+ if (found != NULL || found_static)
+ break;
+ }
+
+ if (found == NULL)
+ {
+ /* We did not find a matching .so file. This isn't an error,
+ since there might still be a matching .a file, which will be
+ found by the usual search. */
+ return;
+ }
+
+ /* Replace the filename with the one we have found. */
+ alc = (char *) xmalloc (strlen (search->name) + strlen (found) + 2);
+ sprintf (alc, "%s/%s", search->name, found);
+ inp->filename = alc;
+
+ /* Turn off the search_dirs_flag to prevent ldfile_open_file from
+ searching for this file again. */
+ inp->search_dirs_flag = FALSE;
+
+ free (found);
+
+ /* Now look for the same file name, but with .sa instead of .so. If
+ found, add it to the list of input files. */
+ alc = (char *) xmalloc (strlen (inp->filename) + 1);
+ strcpy (alc, inp->filename);
+ strstr (alc + strlen (search->name), ".so")[2] = 'a';
+ if (stat (alc, &st) != 0)
+ free (alc);
+ else
+ {
+ lang_input_statement_type *sa;
+
+ /* Add the .sa file to the statement list just before the .so
+ file. This is really a hack. */
+ sa = ((lang_input_statement_type *)
+ xmalloc (sizeof (lang_input_statement_type)));
+ *sa = *inp;
+
+ inp->filename = alc;
+ inp->local_sym_name = alc;
+
+ inp->header.next = (lang_statement_union_type *) sa;
+ inp->next_real_file = (lang_statement_union_type *) sa;
+ }
+}
+
+/* Search a directory for a .so file. */
+
+static char *
+gld${EMULATION_NAME}_search_dir
+ (const char *dirname, const char *filename, bfd_boolean *found_static)
+{
+ int force_maj, force_min;
+ const char *dot;
+ unsigned int len;
+ char *alc;
+ char *found;
+ int max_maj, max_min;
+ DIR *dir;
+ struct dirent *entry;
+ unsigned int dirnamelen;
+ char *full_path;
+ int statval;
+ struct stat st;
+
+ *found_static = FALSE;
+
+ force_maj = -1;
+ force_min = -1;
+ dot = strchr (filename, '.');
+ if (dot == NULL)
+ {
+ len = strlen (filename);
+ alc = NULL;
+ }
+ else
+ {
+ force_maj = atoi (dot + 1);
+
+ len = dot - filename;
+ alc = (char *) xmalloc (len + 1);
+ strncpy (alc, filename, len);
+ alc[len] = '\0';
+ filename = alc;
+
+ dot = strchr (dot + 1, '.');
+ if (dot != NULL)
+ force_min = atoi (dot + 1);
+ }
+
+ found = NULL;
+ max_maj = max_min = 0;
+
+ dir = opendir (dirname);
+ if (dir == NULL)
+ return NULL;
+ dirnamelen = strlen (dirname);
+
+ while ((entry = readdir (dir)) != NULL)
+ {
+ const char *s;
+ int found_maj, found_min;
+
+ if (strncmp (entry->d_name, "lib", 3) != 0
+ || strncmp (entry->d_name + 3, filename, len) != 0)
+ continue;
+
+ if (dot == NULL
+ && strcmp (entry->d_name + 3 + len, ".a") == 0)
+ {
+ *found_static = TRUE;
+ continue;
+ }
+
+ /* We accept libfoo.so without a version number, even though the
+ native linker does not. This is more convenient for packages
+ which just generate .so files for shared libraries, as on ELF
+ systems. */
+ if (strncmp (entry->d_name + 3 + len, ".so", 3) != 0)
+ continue;
+ if (entry->d_name[6 + len] == '\0')
+ ;
+ else if (entry->d_name[6 + len] == '.'
+ && ISDIGIT (entry->d_name[7 + len]))
+ ;
+ else
+ continue;
+
+ for (s = entry->d_name + 6 + len; *s != '\0'; s++)
+ if (*s != '.' && ! ISDIGIT (*s))
+ break;
+ if (*s != '\0')
+ continue;
+
+ /* We've found a .so file. Work out the major and minor
+ version numbers. */
+ found_maj = 0;
+ found_min = 0;
+ sscanf (entry->d_name + 3 + len, ".so.%d.%d",
+ &found_maj, &found_min);
+
+ if ((force_maj != -1 && force_maj != found_maj)
+ || (force_min != -1 && force_min != found_min))
+ continue;
+
+ /* Make sure the file really exists (ignore broken symlinks). */
+ full_path = xmalloc (dirnamelen + 1 + strlen (entry->d_name) + 1);
+ sprintf (full_path, "%s/%s", dirname, entry->d_name);
+ statval = stat (full_path, &st);
+ free (full_path);
+ if (statval != 0)
+ continue;
+
+ /* We've found a match for the name we are searching for. See
+ if this is the version we should use. If the major and minor
+ versions match, we use the last entry in alphabetical order;
+ I don't know if this is how SunOS distinguishes libc.so.1.8
+ from libc.so.1.8.1, but it ought to suffice. */
+ if (found == NULL
+ || (found_maj > max_maj)
+ || (found_maj == max_maj
+ && (found_min > max_min
+ || (found_min == max_min
+ && strcmp (entry->d_name, found) > 0))))
+ {
+ if (found != NULL)
+ free (found);
+ found = (char *) xmalloc (strlen (entry->d_name) + 1);
+ strcpy (found, entry->d_name);
+ max_maj = found_maj;
+ max_min = found_min;
+ }
+ }
+
+ closedir (dir);
+
+ if (alc != NULL)
+ free (alc);
+
+ return found;
+}
+
+/* These variables are required to pass information back and forth
+ between after_open and check_needed. */
+
+static struct bfd_link_needed_list *global_needed;
+static bfd_boolean global_found;
+
+/* This is called after all the input files have been opened. */
+
+static void
+gld${EMULATION_NAME}_after_open (void)
+{
+ struct bfd_link_needed_list *needed, *l;
+
+ /* We only need to worry about this when doing a final link. */
+ if (link_info.relocatable || link_info.shared)
+ return;
+
+ /* Get the list of files which appear in ld_need entries in dynamic
+ objects included in the link. For each such file, we want to
+ track down the corresponding library, and include the symbol
+ table in the link. This is what the runtime dynamic linker will
+ do. Tracking the files down here permits one dynamic object to
+ include another without requiring special action by the person
+ doing the link. Note that the needed list can actually grow
+ while we are stepping through this loop. */
+ needed = bfd_sunos_get_needed_list (output_bfd, &link_info);
+ for (l = needed; l != NULL; l = l->next)
+ {
+ struct bfd_link_needed_list *ll;
+ const char *lname;
+ search_dirs_type *search;
+
+ lname = l->name;
+
+ /* If we've already seen this file, skip it. */
+ for (ll = needed; ll != l; ll = ll->next)
+ if (strcmp (ll->name, lname) == 0)
+ break;
+ if (ll != l)
+ continue;
+
+ /* See if this file was included in the link explicitly. */
+ global_needed = l;
+ global_found = FALSE;
+ lang_for_each_input_file (gld${EMULATION_NAME}_check_needed);
+ if (global_found)
+ continue;
+
+ if (strncmp (lname, "-l", 2) != 0)
+ {
+ bfd *abfd;
+
+ abfd = bfd_openr (lname, bfd_get_target (output_bfd));
+ if (abfd != NULL)
+ {
+ if (! bfd_check_format (abfd, bfd_object))
+ {
+ (void) bfd_close (abfd);
+ abfd = NULL;
+ }
+ }
+ if (abfd != NULL)
+ {
+ if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0)
+ {
+ (void) bfd_close (abfd);
+ abfd = NULL;
+ }
+ }
+ if (abfd != NULL)
+ {
+ /* We've found the needed dynamic object. */
+ if (! bfd_link_add_symbols (abfd, &link_info))
+ einfo ("%F%B: could not read symbols: %E\n", abfd);
+ }
+ else
+ {
+ einfo ("%P: warning: %s, needed by %B, not found\n",
+ lname, l->by);
+ }
+
+ continue;
+ }
+
+ lname += 2;
+
+ /* We want to search for the file in the same way that the
+ dynamic linker will search. That means that we want to use
+ rpath_link, rpath or -L, then the environment variable
+ LD_LIBRARY_PATH (native only), then (if rpath was used) the
+ linker script LIB_SEARCH_DIRS. */
+ if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link,
+ lname))
+ continue;
+ if (command_line.rpath != NULL)
+ {
+ if (gld${EMULATION_NAME}_search_needed (command_line.rpath, lname))
+ continue;
+ }
+ else
+ {
+ for (search = search_head; search != NULL; search = search->next)
+ if (gld${EMULATION_NAME}_try_needed (search->name, lname))
+ break;
+ if (search != NULL)
+ continue;
+ }
+EOF
+if [ "x${host}" = "x${target}" ] ; then
+ case " ${EMULATION_LIBPATH} " in
+ *" ${EMULATION_NAME} "*)
+cat >>e${EMULATION_NAME}.c <<EOF
+ {
+ const char *lib_path;
+
+ lib_path = (const char *) getenv ("LD_LIBRARY_PATH");
+ if (gld${EMULATION_NAME}_search_needed (lib_path, lname))
+ continue;
+ }
+EOF
+ ;;
+ esac
+fi
+cat >>e${EMULATION_NAME}.c <<EOF
+ if (command_line.rpath != NULL)
+ {
+ for (search = search_head; search != NULL; search = search->next)
+ {
+ if (search->cmdline)
+ continue;
+ if (gld${EMULATION_NAME}_try_needed (search->name, lname))
+ break;
+ }
+ if (search != NULL)
+ continue;
+ }
+
+ einfo ("%P: warning: %s, needed by %B, not found\n",
+ l->name, l->by);
+ }
+}
+
+/* Search for a needed file in a path. */
+
+static bfd_boolean
+gld${EMULATION_NAME}_search_needed (const char *path, const char *name)
+{
+ const char *s;
+
+ if (path == NULL || *path == '\0')
+ return FALSE;
+ while (1)
+ {
+ const char *dir;
+ char *dircopy;
+
+ s = strchr (path, ':');
+ if (s == NULL)
+ {
+ dircopy = NULL;
+ dir = path;
+ }
+ else
+ {
+ dircopy = (char *) xmalloc (s - path + 1);
+ memcpy (dircopy, path, s - path);
+ dircopy[s - path] = '\0';
+ dir = dircopy;
+ }
+
+ if (gld${EMULATION_NAME}_try_needed (dir, name))
+ return TRUE;
+
+ if (dircopy != NULL)
+ free (dircopy);
+
+ if (s == NULL)
+ break;
+ path = s + 1;
+ }
+
+ return FALSE;
+}
+
+/* This function is called for each possible directory for a needed
+ dynamic object. */
+
+static bfd_boolean
+gld${EMULATION_NAME}_try_needed (const char *dir, const char *name)
+{
+ char *file;
+ char *alc;
+ bfd_boolean ignore;
+ bfd *abfd;
+
+ file = gld${EMULATION_NAME}_search_dir (dir, name, &ignore);
+ if (file == NULL)
+ return FALSE;
+
+ alc = (char *) xmalloc (strlen (dir) + strlen (file) + 2);
+ sprintf (alc, "%s/%s", dir, file);
+ free (file);
+ abfd = bfd_openr (alc, bfd_get_target (output_bfd));
+ if (abfd == NULL)
+ return FALSE;
+ if (! bfd_check_format (abfd, bfd_object))
+ {
+ (void) bfd_close (abfd);
+ return FALSE;
+ }
+ if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0)
+ {
+ (void) bfd_close (abfd);
+ return FALSE;
+ }
+
+ /* We've found the needed dynamic object. */
+
+ /* Add this file into the symbol table. */
+ if (! bfd_link_add_symbols (abfd, &link_info))
+ einfo ("%F%B: could not read symbols: %E\n", abfd);
+
+ return TRUE;
+}
+
+/* See if we have already included a needed object in the link. This
+ does not have to be precise, as it does no harm to include a
+ dynamic object more than once. */
+
+static void
+gld${EMULATION_NAME}_check_needed (lang_input_statement_type *s)
+{
+ if (s->filename == NULL)
+ return;
+ if (strncmp (global_needed->name, "-l", 2) != 0)
+ {
+ if (strcmp (s->filename, global_needed->name) == 0)
+ global_found = TRUE;
+ }
+ else
+ {
+ const char *sname, *lname;
+ const char *sdot, *ldot;
+ int lmaj, lmin, smaj, smin;
+
+ lname = global_needed->name + 2;
+
+ sname = strrchr (s->filename, '/');
+ if (sname == NULL)
+ sname = s->filename;
+ else
+ ++sname;
+
+ if (strncmp (sname, "lib", 3) != 0)
+ return;
+ sname += 3;
+
+ ldot = strchr (lname, '.');
+ if (ldot == NULL)
+ ldot = lname + strlen (lname);
+
+ sdot = strstr (sname, ".so.");
+ if (sdot == NULL)
+ return;
+
+ if (sdot - sname != ldot - lname
+ || strncmp (lname, sname, sdot - sname) != 0)
+ return;
+
+ lmaj = lmin = -1;
+ sscanf (ldot, ".%d.%d", &lmaj, &lmin);
+ smaj = smin = -1;
+ sscanf (sdot, ".so.%d.%d", &smaj, &smin);
+ if ((smaj != lmaj && smaj != -1 && lmaj != -1)
+ || (smin != lmin && smin != -1 && lmin != -1))
+ return;
+
+ global_found = TRUE;
+ }
+}
+
+/* We need to use static variables to pass information around the call
+ to lang_for_each_statement. Ick. */
+
+static const char *find_assign;
+static bfd_boolean found_assign;
+
+/* We need to use static variables to pass information around the call
+ to lang_for_each_input_file. Ick. */
+
+static bfd_size_type need_size;
+static bfd_size_type need_entries;
+static bfd_byte *need_contents;
+static bfd_byte *need_pinfo;
+static bfd_byte *need_pnames;
+
+/* The size of one entry in the .need section, not including the file
+ name. */
+
+#define NEED_ENTRY_SIZE (16)
+
+/* This is called after the sections have been attached to output
+ sections, but before any sizes or addresses have been set. */
+
+static void
+gld${EMULATION_NAME}_before_allocation (void)
+{
+ struct bfd_link_hash_entry *hdyn = NULL;
+ asection *sneed;
+ asection *srules;
+ asection *sdyn;
+
+ /* The SunOS native linker creates a shared library whenever there
+ are any undefined symbols in a link, unless -e is used. This is
+ pretty weird, but we are compatible. */
+ if (! link_info.shared && ! link_info.relocatable && ! entry_from_cmdline)
+ {
+ struct bfd_link_hash_entry *h;
+
+ for (h = link_info.hash->undefs; h != NULL; h = h->und_next)
+ {
+ if (h->type == bfd_link_hash_undefined
+ && h->u.undef.abfd != NULL
+ && (h->u.undef.abfd->flags & DYNAMIC) == 0
+ && strcmp (h->root.string, "__DYNAMIC") != 0
+ && strcmp (h->root.string, "__GLOBAL_OFFSET_TABLE_") != 0)
+ {
+ find_assign = h->root.string;
+ found_assign = FALSE;
+ lang_for_each_statement (gld${EMULATION_NAME}_find_assignment);
+ if (! found_assign)
+ {
+ link_info.shared = TRUE;
+ break;
+ }
+ }
+ }
+ }
+
+ if (link_info.shared)
+ {
+ lang_output_section_statement_type *os;
+
+ /* Set the .text section to start at 0x20, not 0x2020. FIXME:
+ This is too magical. */
+ os = lang_output_section_statement_lookup (".text");
+ if (os->addr_tree == NULL)
+ os->addr_tree = exp_intop (0x20);
+ }
+
+ /* We need to create a __DYNAMIC symbol. We don't do this in the
+ linker script because we want to set the value to the start of
+ the dynamic section if there is one, or to zero if there isn't
+ one. We need to create the symbol before calling
+ size_dynamic_sections, although we can't set the value until
+ afterward. */
+ if (! link_info.relocatable)
+ {
+ hdyn = bfd_link_hash_lookup (link_info.hash, "__DYNAMIC", TRUE, FALSE,
+ FALSE);
+ if (hdyn == NULL)
+ einfo ("%P%F: bfd_link_hash_lookup: %E\n");
+ if (! bfd_sunos_record_link_assignment (output_bfd, &link_info,
+ "__DYNAMIC"))
+ einfo ("%P%F: failed to record assignment to __DYNAMIC: %E\n");
+ }
+
+ /* If we are going to make any variable assignments, we need to let
+ the backend linker know about them in case the variables are
+ referred to by dynamic objects. */
+ lang_for_each_statement (gld${EMULATION_NAME}_find_assignment);
+
+ /* Let the backend linker work out the sizes of any sections
+ required by dynamic linking. */
+ if (! bfd_sunos_size_dynamic_sections (output_bfd, &link_info, &sdyn,
+ &sneed, &srules))
+ einfo ("%P%F: failed to set dynamic section sizes: %E\n");
+
+ if (sneed != NULL)
+ {
+ /* Set up the .need section. See the description of the ld_need
+ field in include/aout/sun4.h. */
+
+ need_entries = 0;
+ need_size = 0;
+
+ lang_for_each_input_file (gld${EMULATION_NAME}_count_need);
+
+ /* We should only have a .need section if we have at least one
+ dynamic object. */
+ ASSERT (need_entries != 0);
+
+ sneed->_raw_size = need_size;
+ sneed->contents = (bfd_byte *) xmalloc (need_size);
+
+ need_contents = sneed->contents;
+ need_pinfo = sneed->contents;
+ need_pnames = sneed->contents + need_entries * 16;
+
+ lang_for_each_input_file (gld${EMULATION_NAME}_set_need);
+
+ ASSERT ((bfd_size_type) (need_pnames - sneed->contents) == need_size);
+ }
+
+ if (srules != NULL)
+ {
+ /* Set up the .rules section. This is just a PATH like string
+ of the -L arguments given on the command line. We permit the
+ user to specify the directories using the -rpath command line
+ option. */
+ if (command_line.rpath)
+ {
+ srules->_raw_size = strlen (command_line.rpath);
+ srules->contents = (bfd_byte *) command_line.rpath;
+ }
+ else
+ {
+ unsigned int size;
+ search_dirs_type *search;
+
+ size = 0;
+ for (search = search_head; search != NULL; search = search->next)
+ if (search->cmdline)
+ size += strlen (search->name) + 1;
+ srules->_raw_size = size;
+ if (size > 0)
+ {
+ char *p;
+
+ srules->contents = (bfd_byte *) xmalloc (size);
+ p = (char *) srules->contents;
+ *p = '\0';
+ for (search = search_head; search != NULL; search = search->next)
+ {
+ if (search->cmdline)
+ {
+ if (p != (char *) srules->contents)
+ *p++ = ':';
+ strcpy (p, search->name);
+ p += strlen (p);
+ }
+ }
+ }
+ }
+ }
+
+ /* We must assign a value to __DYNAMIC. It should be zero if we are
+ not doing a dynamic link, or the start of the .dynamic section if
+ we are doing one. */
+ if (! link_info.relocatable)
+ {
+ hdyn->type = bfd_link_hash_defined;
+ hdyn->u.def.value = 0;
+ if (sdyn != NULL)
+ hdyn->u.def.section = sdyn;
+ else
+ hdyn->u.def.section = bfd_abs_section_ptr;
+ }
+}
+
+/* This is called by the before_allocation routine via
+ lang_for_each_statement. It does one of two things: if the
+ variable find_assign is set, it sets found_assign if it finds an
+ assignment to that variable; otherwise it tells the backend linker
+ about all assignment statements, in case they are assignments to
+ symbols which are referred to by dynamic objects. */
+
+static void
+gld${EMULATION_NAME}_find_assignment (lang_statement_union_type *s)
+{
+ if (s->header.type == lang_assignment_statement_enum
+ && (find_assign == NULL || ! found_assign))
+ gld${EMULATION_NAME}_find_exp_assignment (s->assignment_statement.exp);
+}
+
+/* Look through an expression for an assignment statement. */
+
+static void
+gld${EMULATION_NAME}_find_exp_assignment (etree_type *exp)
+{
+ switch (exp->type.node_class)
+ {
+ case etree_assign:
+ if (find_assign != NULL)
+ {
+ if (strcmp (find_assign, exp->assign.dst) == 0)
+ found_assign = TRUE;
+ return;
+ }
+
+ if (strcmp (exp->assign.dst, ".") != 0)
+ {
+ if (! bfd_sunos_record_link_assignment (output_bfd, &link_info,
+ exp->assign.dst))
+ einfo ("%P%F: failed to record assignment to %s: %E\n",
+ exp->assign.dst);
+ }
+ gld${EMULATION_NAME}_find_exp_assignment (exp->assign.src);
+ break;
+
+ case etree_binary:
+ gld${EMULATION_NAME}_find_exp_assignment (exp->binary.lhs);
+ gld${EMULATION_NAME}_find_exp_assignment (exp->binary.rhs);
+ break;
+
+ case etree_trinary:
+ gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.cond);
+ gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs);
+ gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.rhs);
+ break;
+
+ case etree_unary:
+ gld${EMULATION_NAME}_find_exp_assignment (exp->unary.child);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/* Work out the size of the .need section, and the number of entries.
+ The backend will set the ld_need field of the dynamic linking
+ information to point to the .need section. See include/aout/sun4.h
+ for more information. */
+
+static void
+gld${EMULATION_NAME}_count_need (lang_input_statement_type *inp)
+{
+ if (inp->the_bfd != NULL
+ && (inp->the_bfd->flags & DYNAMIC) != 0)
+ {
+ ++need_entries;
+ need_size += NEED_ENTRY_SIZE;
+ if (! inp->is_archive)
+ need_size += strlen (inp->filename) + 1;
+ else
+ {
+ ASSERT (inp->local_sym_name[0] == '-'
+ && inp->local_sym_name[1] == 'l');
+ need_size += strlen (inp->local_sym_name + 2) + 1;
+ }
+ }
+}
+
+/* Fill in the contents of the .need section. */
+
+static void
+gld${EMULATION_NAME}_set_need (lang_input_statement_type *inp)
+{
+ if (inp->the_bfd != NULL
+ && (inp->the_bfd->flags & DYNAMIC) != 0)
+ {
+ bfd_size_type c;
+
+ /* To really fill in the .need section contents, we need to know
+ the final file position of the section, but we don't.
+ Instead, we use offsets, and rely on the BFD backend to
+ finish the section up correctly. FIXME: Talk about lack of
+ referential locality. */
+ bfd_put_32 (output_bfd, need_pnames - need_contents, need_pinfo);
+ if (! inp->is_archive)
+ {
+ bfd_put_32 (output_bfd, (bfd_vma) 0, need_pinfo + 4);
+ bfd_put_16 (output_bfd, (bfd_vma) 0, need_pinfo + 8);
+ bfd_put_16 (output_bfd, (bfd_vma) 0, need_pinfo + 10);
+ strcpy (need_pnames, inp->filename);
+ }
+ else
+ {
+ char *verstr;
+ int maj, min;
+
+ bfd_put_32 (output_bfd, (bfd_vma) 0x80000000, need_pinfo + 4);
+ maj = 0;
+ min = 0;
+ verstr = strstr (inp->filename, ".so.");
+ if (verstr != NULL)
+ sscanf (verstr, ".so.%d.%d", &maj, &min);
+ bfd_put_16 (output_bfd, (bfd_vma) maj, need_pinfo + 8);
+ bfd_put_16 (output_bfd, (bfd_vma) min, need_pinfo + 10);
+ strcpy (need_pnames, inp->local_sym_name + 2);
+ }
+
+ c = (need_pinfo - need_contents) / NEED_ENTRY_SIZE;
+ if (c + 1 >= need_entries)
+ bfd_put_32 (output_bfd, (bfd_vma) 0, need_pinfo + 12);
+ else
+ bfd_put_32 (output_bfd, (bfd_vma) (c + 1) * NEED_ENTRY_SIZE,
+ need_pinfo + 12);
+
+ need_pinfo += NEED_ENTRY_SIZE;
+ need_pnames += strlen (need_pnames) + 1;
+ }
+}
+
+static char *
+gld${EMULATION_NAME}_get_script (int *isfile)
+EOF
+
+if test -n "$COMPILE_IN"
+then
+# Scripts compiled in.
+
+# sed commands to quote an ld script as a C string.
+sc="-f stringify.sed"
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 0;
+
+ if (link_info.relocatable && config.build_constructors)
+ return
+EOF
+sed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c
+echo ' ; else if (link_info.relocatable) 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
+{
+ *isfile = 1;
+
+ if (link_info.relocatable && config.build_constructors)
+ return "ldscripts/${EMULATION_NAME}.xu";
+ else if (link_info.relocatable)
+ return "ldscripts/${EMULATION_NAME}.xr";
+ else if (!config.text_read_only)
+ return "ldscripts/${EMULATION_NAME}.xbn";
+ else if (!config.magic_demand_paged)
+ return "ldscripts/${EMULATION_NAME}.xn";
+ else
+ return "ldscripts/${EMULATION_NAME}.x";
+}
+EOF
+
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+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_allocation_default,
+ set_output_arch_default,
+ ldemul_default_target,
+ gld${EMULATION_NAME}_before_allocation,
+ gld${EMULATION_NAME}_get_script,
+ "${EMULATION_NAME}",
+ "${OUTPUT_FORMAT}",
+ NULL, /* finish */
+ gld${EMULATION_NAME}_create_output_section_statements,
+ NULL, /* open dynamic archive */
+ NULL, /* place orphan */
+ gld${EMULATION_NAME}_set_symbols,
+ NULL, /* parse args */
+ NULL, /* add_options */
+ NULL, /* handle_option */
+ NULL, /* unrecognized file */
+ NULL, /* list options */
+ NULL, /* recognized file */
+ NULL, /* find_potential_libraries */
+ NULL /* new_vers_pattern */
+};
+EOF
diff --git a/x/binutils/ld/emultempl/ticoff.em b/x/binutils/ld/emultempl/ticoff.em
new file mode 100644
index 0000000..8f86b04
--- /dev/null
+++ b/x/binutils/ld/emultempl/ticoff.em
@@ -0,0 +1,182 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+(echo;echo;echo;echo)>e${EMULATION_NAME}.c # there, now line numbers match ;-)
+cat >>e${EMULATION_NAME}.c <<EOF
+/* This file is part of GLD, the Gnu Linker.
+ Copyright 1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+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 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. */
+
+/* For TI COFF */
+/* Need to determine load and run pages for output sections */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "getopt.h"
+
+#include "ld.h"
+#include "ldmain.h"
+#include "ldmisc.h"
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldfile.h"
+#include "ldemul.h"
+
+static int coff_version;
+
+/* TI COFF extra command line options */
+#define OPTION_COFF_FORMAT (300 + 1)
+
+static void
+gld${EMULATION_NAME}_add_options
+ (int ns ATTRIBUTE_UNUSED, char **shortopts ATTRIBUTE_UNUSED, int nl,
+ struct option **longopts, int nrl ATTRIBUTE_UNUSED,
+ struct option **really_longopts ATTRIBUTE_UNUSED)
+{
+ static const struct option xtra_long[] = {
+ /* TI COFF options */
+ {"format", required_argument, NULL, OPTION_COFF_FORMAT },
+ {NULL, no_argument, NULL, 0}
+ };
+
+ *longopts = (struct option *)
+ xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long));
+ memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
+}
+
+static void
+gld_${EMULATION_NAME}_list_options (FILE * file)
+{
+ fprintf (file, _(" --format 0|1|2 Specify which COFF version to use\n"));
+}
+
+static bfd_boolean
+gld${EMULATION_NAME}_handle_option (int optc)
+{
+ switch (optc)
+ {
+ default:
+ return FALSE;
+
+ case OPTION_COFF_FORMAT:
+ if ((*optarg == '0' || *optarg == '1' || *optarg == '2')
+ && optarg[1] == '\0')
+ {
+ static char buf[] = "coffX-${OUTPUT_FORMAT_TEMPLATE}";
+ coff_version = *optarg - '0';
+ buf[4] = *optarg;
+ lang_add_output_format (buf, NULL, NULL, 0);
+ }
+ else
+ {
+ einfo (_("%P%F: invalid COFF format version %s\n"), optarg);
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static void
+gld_${EMULATION_NAME}_before_parse(void)
+{
+#ifndef TARGET_ /* I.e., if not generic. */
+ ldfile_set_output_arch ("`echo ${ARCH}`", bfd_arch_unknown);
+#endif /* not TARGET_ */
+}
+
+static char *
+gld_${EMULATION_NAME}_get_script (int *isfile)
+EOF
+if test -n "$COMPILE_IN"
+then
+# Scripts compiled in.
+
+# sed commands to quote an ld script as a C string.
+sc='s/["\\]/\\&/g
+s/$/\\n\\/
+1s/^/"/
+$s/$/n"/
+'
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 0;
+ if (link_info.relocatable && config.build_constructors)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xu`;
+ else if (link_info.relocatable)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xr`;
+ else if (!config.text_read_only)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xbn`;
+ else if (!config.magic_demand_paged)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xn`;
+ else
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.x`;
+}
+EOF
+
+else
+# Scripts read from the filesystem.
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 1;
+
+ if (link_info.relocatable && config.build_constructors)
+ return "ldscripts/${EMULATION_NAME}.xu";
+ else if (link_info.relocatable)
+ return "ldscripts/${EMULATION_NAME}.xr";
+ else if (!config.text_read_only)
+ return "ldscripts/${EMULATION_NAME}.xbn";
+ else if (!config.magic_demand_paged)
+ return "ldscripts/${EMULATION_NAME}.xn";
+ else
+ return "ldscripts/${EMULATION_NAME}.x";
+}
+EOF
+
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
+{
+ gld_${EMULATION_NAME}_before_parse,
+ syslib_default,
+ hll_default,
+ after_parse_default,
+ after_open_default,
+ after_allocation_default,
+ set_output_arch_default,
+ ldemul_default_target,
+ before_allocation_default,
+ gld_${EMULATION_NAME}_get_script,
+ "${EMULATION_NAME}",
+ "${OUTPUT_FORMAT}",
+ NULL, /* finish */
+ NULL, /* create output section statements */
+ NULL, /* open dynamic archive */
+ NULL, /* place orphan */
+ NULL, /* set_symbols */
+ NULL, /* parse_args */
+ gld${EMULATION_NAME}_add_options,
+ gld${EMULATION_NAME}_handle_option,
+ NULL, /* unrecognized_file */
+ gld_${EMULATION_NAME}_list_options,
+ NULL, /* recognized file */
+ NULL, /* find_potential_libraries */
+ NULL /* new_vers_pattern */
+};
+EOF
diff --git a/x/binutils/ld/emultempl/vanilla.em b/x/binutils/ld/emultempl/vanilla.em
new file mode 100644
index 0000000..2141083
--- /dev/null
+++ b/x/binutils/ld/emultempl/vanilla.em
@@ -0,0 +1,85 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+cat >e${EMULATION_NAME}.c <<EOF
+/* A vanilla emulation with no defaults
+ Copyright 1991, 1992, 1994, 2000, 2001, 2002, 2003
+ Free Software Foundation, Inc.
+ Written by Steve Chamberlain steve@cygnus.com
+
+This file is part of GLD, the Gnu Linker.
+
+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 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. */
+
+#include "bfd.h"
+#include "sysdep.h"
+
+
+#include "ld.h"
+#include "ldmisc.h"
+#include "ldmain.h"
+
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldfile.h"
+#include "ldemul.h"
+
+static void vanilla_before_parse (void)
+{
+}
+
+static void
+vanilla_set_output_arch (void)
+{
+ /* Set the output architecture and machine if possible */
+ unsigned long machine = 0;
+ bfd_set_arch_mach(output_bfd, ldfile_output_architecture, machine);
+}
+
+static char *
+vanilla_get_script (int *isfile)
+{
+ *isfile = 0;
+ return "";
+}
+
+struct ld_emulation_xfer_struct ld_vanilla_emulation =
+{
+ vanilla_before_parse,
+ syslib_default,
+ hll_default,
+ after_parse_default,
+ after_open_default,
+ after_allocation_default,
+ vanilla_set_output_arch,
+ ldemul_default_target,
+ before_allocation_default,
+ vanilla_get_script,
+ "vanilla",
+ "a.out-sunos-big",
+ NULL, /* finish */
+ NULL, /* create output section statements */
+ NULL, /* open dynamic archive */
+ NULL, /* place orphan */
+ NULL, /* set symbols */
+ NULL, /* parse args */
+ NULL, /* add_options */
+ NULL, /* handle_option */
+ NULL, /* unrecognized file */
+ NULL, /* list options */
+ NULL, /* recognized file */
+ NULL, /* find_potential_libraries */
+ NULL /* new_vers_pattern */
+};
+EOF
OpenPOWER on IntegriCloud