summaryrefslogtreecommitdiffstats
path: root/binutils-2.20.1/ld/emultempl
diff options
context:
space:
mode:
authorJing Yu <jingyu@google.com>2011-01-30 22:09:54 -0800
committerJing Yu <jingyu@google.com>2011-01-30 22:09:54 -0800
commita9a8b9e7e4aee6a3846ba62703283d10849bc0a6 (patch)
treebfd550c5e600ab0c227d3615fb5183127604870d /binutils-2.20.1/ld/emultempl
parent8a5a8339de3149b7f99caf08e9cb72467d60cd01 (diff)
downloadtoolchain_binutils-a9a8b9e7e4aee6a3846ba62703283d10849bc0a6.tar.gz
toolchain_binutils-a9a8b9e7e4aee6a3846ba62703283d10849bc0a6.tar.bz2
toolchain_binutils-a9a8b9e7e4aee6a3846ba62703283d10849bc0a6.zip
Upgrade binutils and gold.
upgrade binutils-2.19 to binutils-2.20.1 upgrade gold to a relatively new version binutils-20100303 Before, both binutils and gold were built from binutils-2.19. Now binutils will be built from binutils-2.20.1 and gold will be built from binutils-20100303. Change-Id: Ibd0130756723337d2b4783d5b1d5e5b02a1adc83
Diffstat (limited to 'binutils-2.20.1/ld/emultempl')
-rw-r--r--binutils-2.20.1/ld/emultempl/README3
-rw-r--r--binutils-2.20.1/ld/emultempl/aix.em1474
-rw-r--r--binutils-2.20.1/ld/emultempl/alphaelf.em155
-rw-r--r--binutils-2.20.1/ld/emultempl/armcoff.em283
-rw-r--r--binutils-2.20.1/ld/emultempl/armelf.em674
-rw-r--r--binutils-2.20.1/ld/emultempl/astring.sed13
-rw-r--r--binutils-2.20.1/ld/emultempl/avrelf.em265
-rw-r--r--binutils-2.20.1/ld/emultempl/beos.em783
-rw-r--r--binutils-2.20.1/ld/emultempl/cr16elf.em208
-rw-r--r--binutils-2.20.1/ld/emultempl/crxelf.em96
-rw-r--r--binutils-2.20.1/ld/emultempl/elf-generic.em73
-rw-r--r--binutils-2.20.1/ld/emultempl/elf32.em2357
-rw-r--r--binutils-2.20.1/ld/emultempl/genelf.em59
-rw-r--r--binutils-2.20.1/ld/emultempl/generic.em149
-rw-r--r--binutils-2.20.1/ld/emultempl/gld960.em154
-rw-r--r--binutils-2.20.1/ld/emultempl/gld960c.em167
-rw-r--r--binutils-2.20.1/ld/emultempl/hppaelf.em379
-rw-r--r--binutils-2.20.1/ld/emultempl/ia64elf.em65
-rw-r--r--binutils-2.20.1/ld/emultempl/irix.em44
-rw-r--r--binutils-2.20.1/ld/emultempl/linux.em211
-rw-r--r--binutils-2.20.1/ld/emultempl/lnk960.em290
-rw-r--r--binutils-2.20.1/ld/emultempl/m68hc1xelf.em373
-rw-r--r--binutils-2.20.1/ld/emultempl/m68kcoff.em243
-rw-r--r--binutils-2.20.1/ld/emultempl/m68kelf.em250
-rw-r--r--binutils-2.20.1/ld/emultempl/mipsecoff.em38
-rw-r--r--binutils-2.20.1/ld/emultempl/mipself.em241
-rw-r--r--binutils-2.20.1/ld/emultempl/mmix-elfnmmo.em116
-rw-r--r--binutils-2.20.1/ld/emultempl/mmixelf.em44
-rw-r--r--binutils-2.20.1/ld/emultempl/mmo.em158
-rw-r--r--binutils-2.20.1/ld/emultempl/needrelax.em39
-rw-r--r--binutils-2.20.1/ld/emultempl/netbsd.em34
-rw-r--r--binutils-2.20.1/ld/emultempl/ostring.sed4
-rw-r--r--binutils-2.20.1/ld/emultempl/pe.em2080
-rw-r--r--binutils-2.20.1/ld/emultempl/pep.em1855
-rw-r--r--binutils-2.20.1/ld/emultempl/ppc32elf.em244
-rw-r--r--binutils-2.20.1/ld/emultempl/ppc64elf.em620
-rw-r--r--binutils-2.20.1/ld/emultempl/scoreelf.em77
-rw-r--r--binutils-2.20.1/ld/emultempl/sh64elf.em557
-rw-r--r--binutils-2.20.1/ld/emultempl/spu_icache.S7
-rw-r--r--binutils-2.20.1/ld/emultempl/spu_icache.o_c33
-rw-r--r--binutils-2.20.1/ld/emultempl/spu_ovl.S471
-rw-r--r--binutils-2.20.1/ld/emultempl/spu_ovl.o_c101
-rw-r--r--binutils-2.20.1/ld/emultempl/spuelf.em824
-rw-r--r--binutils-2.20.1/ld/emultempl/sunos.em1037
-rw-r--r--binutils-2.20.1/ld/emultempl/ticoff.em186
-rw-r--r--binutils-2.20.1/ld/emultempl/vanilla.em87
-rw-r--r--binutils-2.20.1/ld/emultempl/vxworks.em102
-rw-r--r--binutils-2.20.1/ld/emultempl/xtensaelf.em2028
-rw-r--r--binutils-2.20.1/ld/emultempl/z80.em102
49 files changed, 19853 insertions, 0 deletions
diff --git a/binutils-2.20.1/ld/emultempl/README b/binutils-2.20.1/ld/emultempl/README
new file mode 100644
index 00000000..30ec0abf
--- /dev/null
+++ b/binutils-2.20.1/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/binutils-2.20.1/ld/emultempl/aix.em b/binutils-2.20.1/ld/emultempl/aix.em
new file mode 100644
index 00000000..27903244
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/aix.em
@@ -0,0 +1,1474 @@
+# 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
+fragment <<EOF
+/* This file is is generated by a shell script. DO NOT EDIT! */
+
+/* AIX emulation code for ${EMULATION_NAME}
+ Copyright 1991, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+ 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ Free Software Foundation, Inc.
+ Written by Steve Chamberlain <sac@cygnus.com>
+ AIX support by Ian Lance Taylor <ian@cygnus.com>
+ AIX 64 bit support by Tom Rix <trix@redhat.com>
+
+ This file is part of the GNU Binutils.
+
+ 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libiberty.h"
+#include "safe-ctype.h"
+#include "getopt.h"
+#include "obstack.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 "ldctor.h"
+#include <ldgram.h>
+
+#include "coff/internal.h"
+#include "coff/xcoff.h"
+#include "libcoff.h"
+#include "libxcoff.h"
+
+static void gld${EMULATION_NAME}_read_file (const char *, bfd_boolean);
+static void gld${EMULATION_NAME}_free (void *);
+static void gld${EMULATION_NAME}_find_relocs (lang_statement_union_type *);
+static void gld${EMULATION_NAME}_find_exp_assignment (etree_type *);
+
+
+/* The file alignment required for each section. */
+static unsigned long file_align;
+
+/* The maximum size the stack is permitted to grow. This is stored in
+ the a.out header. */
+static unsigned long maxstack;
+
+/* The maximum data size. This is stored in the a.out header. */
+static unsigned long maxdata;
+
+/* Whether to perform garbage collection. */
+static int gc = 1;
+
+/* The module type to use. */
+static unsigned short modtype = ('1' << 8) | 'L';
+
+/* Whether the .text section must be read-only (i.e., no relocs
+ permitted). */
+static int textro;
+
+/* A mask of XCOFF_EXPALL and XCOFF_EXPFULL flags, as set by their
+ associated -b and -bno options. */
+static unsigned int auto_export_flags;
+
+/* A mask of auto_export_flags bits that were explicitly set on the
+ command line. */
+static unsigned int explicit_auto_export_flags;
+
+/* Whether to implement Unix like linker semantics. */
+static int unix_ld;
+
+/* Structure used to hold import file list. */
+
+struct filelist
+{
+ struct filelist *next;
+ const char *name;
+};
+
+/* List of import files. */
+static struct filelist *import_files;
+
+/* List of export symbols read from the export files. */
+
+struct export_symbol_list
+{
+ struct export_symbol_list *next;
+ const char *name;
+};
+
+static struct export_symbol_list *export_symbols;
+
+/* Maintains the 32 or 64 bit mode state of import file */
+static unsigned int symbol_mode = 0x04;
+
+/* Which symbol modes are valid */
+static unsigned int symbol_mode_mask = 0x0d;
+
+/* Whether this is a 64 bit link */
+static int is_64bit = 0;
+
+/* Which syscalls from import file are valid */
+static unsigned int syscall_mask = 0x77;
+
+/* fake file for -binitfini support */
+static lang_input_statement_type *initfini_file;
+
+/* Whether to do run time linking
+ -brtl enables, -bnortl and -bnortllib disable. */
+static int rtld;
+
+/* Explicit command line library path, -blibpath */
+static char *command_line_blibpath = NULL;
+
+/* This routine is called before anything else is done. */
+
+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;
+
+ /* The link_info.[init|fini]_functions are initialized in ld/lexsup.c.
+ Override them here so we can use the link_info.init_function as a
+ state flag that lets the backend know that -binitfini has been done. */
+
+ link_info.init_function = NULL;
+ link_info.fini_function = NULL;
+}
+
+/* Handle AIX specific options. */
+
+enum
+ {
+ OPTION_IGNORE = 300,
+ OPTION_AUTOIMP,
+ OPTION_ERNOTOK,
+ OPTION_EROK,
+ OPTION_EXPALL,
+ OPTION_EXPFULL,
+ OPTION_EXPORT,
+ OPTION_IMPORT,
+ OPTION_INITFINI,
+ OPTION_LOADMAP,
+ OPTION_MAXDATA,
+ OPTION_MAXSTACK,
+ OPTION_MODTYPE,
+ OPTION_NOAUTOIMP,
+ OPTION_NOEXPALL,
+ OPTION_NOEXPFULL,
+ OPTION_NOSTRCMPCT,
+ OPTION_PD,
+ OPTION_PT,
+ OPTION_STRCMPCT,
+ OPTION_UNIX,
+ OPTION_32,
+ OPTION_64,
+ OPTION_LIBPATH,
+ OPTION_NOLIBPATH,
+ };
+
+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[] = "D:H:KT:z";
+ static const struct option xtra_long[] = {
+ /* -binitfini has special handling in the linker backend. The native linker
+ uses the arguemnts to generate a table of init and fini functions for
+ the executable. The important use for this option is to support aix 4.2+
+ c++ constructors and destructors. This is tied into gcc via collect2.c.
+
+ The function table is accessed by the runtime linker/loader by checking if
+ the first symbol in the loader symbol table is __rtinit. The gnu linker
+ generates this symbol and makes it the first loader symbol. */
+
+ {"basis", no_argument, NULL, OPTION_IGNORE},
+ {"bautoimp", no_argument, NULL, OPTION_AUTOIMP},
+ {"bcomprld", no_argument, NULL, OPTION_IGNORE},
+ {"bcrld", no_argument, NULL, OPTION_IGNORE},
+ {"bcror31", no_argument, NULL, OPTION_IGNORE},
+ {"bD", required_argument, NULL, OPTION_MAXDATA},
+ {"bE", required_argument, NULL, OPTION_EXPORT},
+ {"bernotok", no_argument, NULL, OPTION_ERNOTOK},
+ {"berok", no_argument, NULL, OPTION_EROK},
+ {"berrmsg", no_argument, NULL, OPTION_IGNORE},
+ {"bexpall", no_argument, NULL, OPTION_EXPALL},
+ {"bexpfull", no_argument, NULL, OPTION_EXPFULL},
+ {"bexport", required_argument, NULL, OPTION_EXPORT},
+ {"bf", no_argument, NULL, OPTION_ERNOTOK},
+ {"bgc", no_argument, &gc, 1},
+ {"bh", required_argument, NULL, OPTION_IGNORE},
+ {"bhalt", required_argument, NULL, OPTION_IGNORE},
+ {"bI", required_argument, NULL, OPTION_IMPORT},
+ {"bimport", required_argument, NULL, OPTION_IMPORT},
+ {"binitfini", required_argument, NULL, OPTION_INITFINI},
+ {"bl", required_argument, NULL, OPTION_LOADMAP},
+ {"bloadmap", required_argument, NULL, OPTION_LOADMAP},
+ {"bmaxdata", required_argument, NULL, OPTION_MAXDATA},
+ {"bmaxstack", required_argument, NULL, OPTION_MAXSTACK},
+ {"bM", required_argument, NULL, OPTION_MODTYPE},
+ {"bmodtype", required_argument, NULL, OPTION_MODTYPE},
+ {"bnoautoimp", no_argument, NULL, OPTION_NOAUTOIMP},
+ {"bnoexpall", no_argument, NULL, OPTION_NOEXPALL},
+ {"bnoexpfull", no_argument, NULL, OPTION_NOEXPFULL},
+ {"bnodelcsect", no_argument, NULL, OPTION_IGNORE},
+ {"bnoentry", no_argument, NULL, OPTION_IGNORE},
+ {"bnogc", no_argument, &gc, 0},
+ {"bnso", no_argument, NULL, OPTION_NOAUTOIMP},
+ {"bnostrcmpct", no_argument, NULL, OPTION_NOSTRCMPCT},
+ {"bnotextro", no_argument, &textro, 0},
+ {"bnro", no_argument, &textro, 0},
+ {"bpD", required_argument, NULL, OPTION_PD},
+ {"bpT", required_argument, NULL, OPTION_PT},
+ {"bro", no_argument, &textro, 1},
+ {"brtl", no_argument, &rtld, 1},
+ {"bnortl", no_argument, &rtld, 0},
+ {"bnortllib", no_argument, &rtld, 0},
+ {"bS", required_argument, NULL, OPTION_MAXSTACK},
+ {"bso", no_argument, NULL, OPTION_AUTOIMP},
+ {"bstrcmpct", no_argument, NULL, OPTION_STRCMPCT},
+ {"btextro", no_argument, &textro, 1},
+ {"b32", no_argument, NULL, OPTION_32},
+ {"b64", no_argument, NULL, OPTION_64},
+ {"static", no_argument, NULL, OPTION_NOAUTOIMP},
+ {"unix", no_argument, NULL, OPTION_UNIX},
+ {"blibpath", required_argument, NULL, OPTION_LIBPATH},
+ {"bnolibpath", required_argument, NULL, OPTION_NOLIBPATH},
+ {NULL, no_argument, NULL, 0}
+ };
+
+ /* Options supported by the AIX linker which we do not support: -f,
+ -S, -v, -Z, -bbindcmds, -bbinder, -bbindopts, -bcalls, -bcaps,
+ -bcror15, -bdebugopt, -bdbg, -bdelcsect, -bex?, -bfilelist, -bfl,
+ -bgcbypass, -bglink, -binsert, -bi, -bloadmap, -bl, -bmap, -bnl,
+ -bnobind, -bnocomprld, -bnocrld, -bnoerrmsg, -bnoglink,
+ -bnoloadmap, -bnl, -bnoobjreorder, -bnoquiet, -bnoreorder,
+ -bnotypchk, -bnox, -bquiet, -bR, -brename, -breorder, -btypchk,
+ -bx, -bX, -bxref. */
+
+ *shortopts = (char *) xrealloc (*shortopts, ns + sizeof (xtra_short));
+ memcpy (*shortopts + ns, &xtra_short, sizeof (xtra_short));
+ *longopts = xrealloc (*longopts,
+ nl * sizeof (struct option) + sizeof (xtra_long));
+ memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
+}
+
+static bfd_boolean
+gld${EMULATION_NAME}_parse_args (int argc, char **argv)
+{
+ int indx;
+
+ /* If the current option starts with -b, change the first : to an =.
+ The AIX linker uses : to separate the option from the argument;
+ changing it to = lets us treat it as a getopt option. */
+ indx = optind;
+ if (indx == 0)
+ indx = 1;
+
+ if (indx < argc && CONST_STRNEQ (argv[indx], "-b"))
+ {
+ char *s;
+
+ for (s = argv[indx]; *s != '\0'; s++)
+ {
+ if (*s == ':')
+ {
+ *s = '=';
+ break;
+ }
+ }
+ }
+ return FALSE;
+}
+
+static bfd_boolean
+gld${EMULATION_NAME}_handle_option (int optc)
+{
+ bfd_signed_vma val;
+ const char *end;
+
+ switch (optc)
+ {
+ default:
+ return FALSE;
+
+ case 0:
+ /* Long option which just sets a flag. */
+ break;
+
+ case 'D':
+ val = bfd_scan_vma (optarg, &end, 0);
+ if (*end != '\0')
+ einfo ("%P: warning: ignoring invalid -D number %s\n", optarg);
+ else if (val != -1)
+ lang_section_start (".data", exp_intop (val), NULL);
+ break;
+
+ case 'H':
+ val = bfd_scan_vma (optarg, &end, 0);
+ if (*end != '\0' || (val & (val - 1)) != 0)
+ einfo ("%P: warning: ignoring invalid -H number %s\n", optarg);
+ else
+ file_align = val;
+ break;
+
+ case 'K':
+ case 'z':
+ /* FIXME: This should use the page size for the target system. */
+ file_align = 4096;
+ break;
+
+ case 'T':
+ /* On AIX this is the same as GNU ld -Ttext. When we see -T
+ number, we assume the AIX option is intended. Otherwise, we
+ assume the usual GNU ld -T option is intended. We can't just
+ ignore the AIX option, because gcc passes it to the linker. */
+ val = bfd_scan_vma (optarg, &end, 0);
+ if (*end != '\0')
+ return FALSE;
+ lang_section_start (".text", exp_intop (val), NULL);
+ break;
+
+ case OPTION_IGNORE:
+ break;
+
+ case OPTION_INITFINI:
+ {
+ /*
+ * The aix linker init fini has the format :
+ *
+ * -binitfini:[ Initial][:Termination][:Priority]
+ *
+ * it allows the Termination and Priority to be optional.
+ *
+ * Since we support only one init/fini pair, we ignore the Priority.
+ *
+ * Define the special symbol __rtinit.
+ *
+ * strtok does not correctly handle the case of -binitfini::fini: so
+ * do it by hand
+ */
+ char *t, *i, *f;
+
+ i = t = optarg;
+ while (*t && ':' != *t)
+ t++;
+ if (*t)
+ *t++ = 0;
+
+ if (0 != strlen (i))
+ link_info.init_function = i;
+
+ f = t;
+ while (*t && ':' != *t)
+ t++;
+ *t = 0;
+
+ if (0 != strlen (f))
+ link_info.fini_function = f;
+ }
+ break;
+
+ case OPTION_AUTOIMP:
+ link_info.static_link = FALSE;
+ break;
+
+ case OPTION_ERNOTOK:
+ link_info.unresolved_syms_in_objects = RM_GENERATE_ERROR;
+ link_info.unresolved_syms_in_shared_libs = RM_GENERATE_ERROR;
+ break;
+
+ case OPTION_EROK:
+ link_info.unresolved_syms_in_objects = RM_IGNORE;
+ link_info.unresolved_syms_in_shared_libs = RM_IGNORE;
+ break;
+
+ case OPTION_EXPALL:
+ auto_export_flags |= XCOFF_EXPALL;
+ explicit_auto_export_flags |= XCOFF_EXPALL;
+ break;
+
+ case OPTION_EXPFULL:
+ auto_export_flags |= XCOFF_EXPFULL;
+ explicit_auto_export_flags |= XCOFF_EXPFULL;
+ break;
+
+ case OPTION_EXPORT:
+ gld${EMULATION_NAME}_read_file (optarg, FALSE);
+ break;
+
+ case OPTION_IMPORT:
+ {
+ struct filelist *n;
+ struct filelist **flpp;
+
+ n = (struct filelist *) xmalloc (sizeof (struct filelist));
+ n->next = NULL;
+ n->name = optarg;
+ flpp = &import_files;
+ while (*flpp != NULL)
+ flpp = &(*flpp)->next;
+ *flpp = n;
+ }
+ break;
+
+ case OPTION_LOADMAP:
+ config.map_filename = optarg;
+ break;
+
+ case OPTION_MAXDATA:
+ val = bfd_scan_vma (optarg, &end, 0);
+ if (*end != '\0')
+ einfo ("%P: warning: ignoring invalid -bmaxdata number %s\n", optarg);
+ else
+ maxdata = val;
+ break;
+
+ case OPTION_MAXSTACK:
+ val = bfd_scan_vma (optarg, &end, 0);
+ if (*end != '\0')
+ einfo ("%P: warning: ignoring invalid -bmaxstack number %s\n",
+ optarg);
+ else
+ maxstack = val;
+ break;
+
+ case OPTION_MODTYPE:
+ if (*optarg == 'S')
+ {
+ link_info.shared = TRUE;
+ ++optarg;
+ }
+ if (*optarg == '\0' || optarg[1] == '\0')
+ einfo ("%P: warning: ignoring invalid module type %s\n", optarg);
+ else
+ modtype = (*optarg << 8) | optarg[1];
+ break;
+
+ case OPTION_NOAUTOIMP:
+ link_info.static_link = TRUE;
+ break;
+
+ case OPTION_NOEXPALL:
+ auto_export_flags &= ~XCOFF_EXPALL;
+ explicit_auto_export_flags |= XCOFF_EXPALL;
+ break;
+
+ case OPTION_NOEXPFULL:
+ auto_export_flags &= ~XCOFF_EXPFULL;
+ explicit_auto_export_flags |= XCOFF_EXPFULL;
+ break;
+
+ case OPTION_NOSTRCMPCT:
+ link_info.traditional_format = TRUE;
+ break;
+
+ case OPTION_PD:
+ /* This sets the page that the .data section is supposed to
+ start on. The offset within the page should still be the
+ offset within the file, so we need to build an appropriate
+ expression. */
+ val = bfd_scan_vma (optarg, &end, 0);
+ if (*end != '\0')
+ einfo ("%P: warning: ignoring invalid -pD number %s\n", optarg);
+ else
+ {
+ etree_type *t;
+
+ t = exp_binop ('+',
+ exp_intop (val),
+ exp_binop ('&',
+ exp_nameop (NAME, "."),
+ exp_intop (0xfff)));
+ t = exp_binop ('&',
+ exp_binop ('+', t, exp_intop (31)),
+ exp_intop (~(bfd_vma) 31));
+ lang_section_start (".data", t, NULL);
+ }
+ break;
+
+ case OPTION_PT:
+ /* This set the page that the .text section is supposed to start
+ on. The offset within the page should still be the offset
+ within the file. */
+ val = bfd_scan_vma (optarg, &end, 0);
+ if (*end != '\0')
+ einfo ("%P: warning: ignoring invalid -pT number %s\n", optarg);
+ else
+ {
+ etree_type *t;
+
+ t = exp_binop ('+',
+ exp_intop (val),
+ exp_nameop (SIZEOF_HEADERS, NULL));
+ t = exp_binop ('&',
+ exp_binop ('+', t, exp_intop (31)),
+ exp_intop (~(bfd_vma) 31));
+ lang_section_start (".text", t, NULL);
+ }
+ break;
+
+ case OPTION_STRCMPCT:
+ link_info.traditional_format = FALSE;
+ break;
+
+ case OPTION_UNIX:
+ unix_ld = TRUE;
+ break;
+
+ case OPTION_32:
+ is_64bit = 0;
+ syscall_mask = 0x77;
+ symbol_mode_mask = 0x0d;
+ break;
+
+ case OPTION_64:
+ is_64bit = 1;
+ syscall_mask = 0xcc;
+ symbol_mode_mask = 0x0e;
+ break;
+
+ case OPTION_LIBPATH:
+ command_line_blibpath = optarg;
+ break;
+
+ case OPTION_NOLIBPATH:
+ command_line_blibpath = NULL;
+ break;
+
+ }
+
+ return TRUE;
+}
+
+/* This is called when an input file can not be recognized as a BFD
+ object or an archive. If the file starts with #!, we must treat it
+ as an import file. This is for AIX compatibility. */
+
+static bfd_boolean
+gld${EMULATION_NAME}_unrecognized_file (lang_input_statement_type *entry)
+{
+ FILE *e;
+ bfd_boolean ret;
+
+ e = fopen (entry->filename, FOPEN_RT);
+ if (e == NULL)
+ return FALSE;
+
+ ret = FALSE;
+
+ if (getc (e) == '#' && getc (e) == '!')
+ {
+ struct filelist *n;
+ struct filelist **flpp;
+
+ n = (struct filelist *) xmalloc (sizeof (struct filelist));
+ n->next = NULL;
+ n->name = entry->filename;
+ flpp = &import_files;
+ while (*flpp != NULL)
+ flpp = &(*flpp)->next;
+ *flpp = n;
+
+ ret = TRUE;
+ entry->loaded = TRUE;
+ }
+
+ fclose (e);
+
+ return ret;
+}
+
+/* This is called after the input files have been opened. */
+
+static void
+gld${EMULATION_NAME}_after_open (void)
+{
+ bfd_boolean r;
+ struct set_info *p;
+
+ /* Call ldctor_build_sets, after pretending that this is a
+ relocatable link. We do this because AIX requires relocation
+ entries for all references to symbols, even in a final
+ executable. Of course, we only want to do this if we are
+ producing an XCOFF output file. */
+ r = link_info.relocatable;
+ if (strstr (bfd_get_target (link_info.output_bfd), "xcoff") != NULL)
+ link_info.relocatable = TRUE;
+ ldctor_build_sets ();
+ link_info.relocatable = r;
+
+ /* For each set, record the size, so that the XCOFF backend can
+ output the correct csect length. */
+ for (p = sets; p != (struct set_info *) NULL; p = p->next)
+ {
+ bfd_size_type size;
+
+ /* If the symbol is defined, we may have been invoked from
+ collect, and the sets may already have been built, so we do
+ not do anything. */
+ if (p->h->type == bfd_link_hash_defined
+ || p->h->type == bfd_link_hash_defweak)
+ continue;
+
+ if (p->reloc != BFD_RELOC_CTOR)
+ {
+ /* Handle this if we need to. */
+ abort ();
+ }
+
+ size = (p->count + 2) * 4;
+ if (!bfd_xcoff_link_record_set (link_info.output_bfd, &link_info,
+ p->h, size))
+ einfo ("%F%P: bfd_xcoff_link_record_set failed: %E\n");
+ }
+}
+
+/* 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 filelist *fl;
+ struct export_symbol_list *el;
+ char *libpath;
+ asection *special_sections[XCOFF_NUMBER_OF_SPECIAL_SECTIONS];
+ static const char *const must_keep_sections[] = {
+ ".text",
+ ".data",
+ ".bss"
+ };
+ unsigned int i, flags;
+
+ /* Handle the import and export files, if any. */
+ for (fl = import_files; fl != NULL; fl = fl->next)
+ gld${EMULATION_NAME}_read_file (fl->name, TRUE);
+ for (el = export_symbols; el != NULL; el = el->next)
+ {
+ struct bfd_link_hash_entry *h;
+
+ h = bfd_link_hash_lookup (link_info.hash, el->name, FALSE, FALSE, FALSE);
+ if (h == NULL)
+ einfo ("%P%F: bfd_link_hash_lookup of export symbol failed: %E\n");
+ if (!bfd_xcoff_export_symbol (link_info.output_bfd, &link_info, h))
+ einfo ("%P%F: bfd_xcoff_export_symbol failed: %E\n");
+ }
+
+ /* Track down all relocations called for by the linker script (these
+ are typically constructor/destructor entries created by
+ CONSTRUCTORS) and let the backend know it will need to create
+ .loader relocs for them. */
+ lang_for_each_statement (gld${EMULATION_NAME}_find_relocs);
+
+ /* Precedence of LIBPATH
+ -blibpath: native support always first
+ -rpath: gnu extension
+ -L build from command line -L's */
+ if (command_line_blibpath != NULL)
+ libpath = command_line_blibpath;
+ else if (command_line.rpath != NULL)
+ libpath = command_line.rpath;
+ else if (search_head == NULL)
+ libpath = (char *) "";
+ else
+ {
+ size_t len;
+ search_dirs_type *search;
+
+ /* PR ld/4023: Strip sysroot prefix from any paths
+ being inserted into the output binary's DT_RPATH. */
+ if (ld_sysroot != NULL
+ && * ld_sysroot != 0)
+ {
+ const char * name = search_head->name;
+ size_t ld_sysroot_len = strlen (ld_sysroot);
+
+ if (strncmp (name, ld_sysroot, ld_sysroot_len) == 0)
+ name += ld_sysroot_len;
+
+ len = strlen (name);
+ libpath = xmalloc (len + 1);
+ strcpy (libpath, name);
+
+ for (search = search_head->next; search != NULL; search = search->next)
+ {
+ size_t nlen;
+
+ name = search->name;
+ if (strncmp (name, ld_sysroot, ld_sysroot_len) == 0)
+ name += ld_sysroot_len;
+
+ nlen = strlen (name);
+ libpath = xrealloc (libpath, len + nlen + 2);
+ libpath[len] = ':';
+ strcpy (libpath + len + 1, name);
+ len += nlen + 1;
+ }
+ }
+ else
+ {
+ len = strlen (search_head->name);
+ libpath = xmalloc (len + 1);
+ strcpy (libpath, search_head->name);
+
+ for (search = search_head->next; search != NULL; search = search->next)
+ {
+ size_t nlen;
+
+ nlen = strlen (search->name);
+ libpath = xrealloc (libpath, len + nlen + 2);
+ libpath[len] = ':';
+ strcpy (libpath + len + 1, search->name);
+ len += nlen + 1;
+ }
+ }
+ }
+
+ /* Default to -bexpfull for SVR4-like semantics. */
+ flags = (unix_ld ? XCOFF_EXPFULL : 0);
+ flags &= ~explicit_auto_export_flags;
+ flags |= auto_export_flags;
+
+ /* Let the XCOFF backend set up the .loader section. */
+ if (!bfd_xcoff_size_dynamic_sections
+ (link_info.output_bfd, &link_info, libpath, entry_symbol.name, file_align,
+ maxstack, maxdata, gc && !unix_ld ? TRUE : FALSE,
+ modtype, textro ? TRUE : FALSE, flags, special_sections,
+ rtld ? TRUE : FALSE))
+ einfo ("%P%F: failed to set dynamic section sizes: %E\n");
+
+ /* Look through the special sections, and put them in the right
+ place in the link ordering. This is especially magic. */
+ for (i = 0; i < XCOFF_NUMBER_OF_SPECIAL_SECTIONS; i++)
+ {
+ asection *sec;
+ lang_output_section_statement_type *os;
+ lang_statement_union_type **pls;
+ lang_input_section_type *is;
+ const char *oname;
+ bfd_boolean start;
+
+ sec = special_sections[i];
+ if (sec == NULL)
+ continue;
+
+ /* Remove this section from the list of the output section.
+ This assumes we know what the script looks like. */
+ is = NULL;
+ os = lang_output_section_find (sec->output_section->name);
+ if (os == NULL)
+ einfo ("%P%F: can't find output section %s\n",
+ sec->output_section->name);
+
+ for (pls = &os->children.head; *pls != NULL; pls = &(*pls)->header.next)
+ {
+ if ((*pls)->header.type == lang_input_section_enum
+ && (*pls)->input_section.section == sec)
+ {
+ is = (lang_input_section_type *) * pls;
+ *pls = (*pls)->header.next;
+ break;
+ }
+
+ if ((*pls)->header.type == lang_wild_statement_enum)
+ {
+ lang_statement_union_type **pwls;
+
+ for (pwls = &(*pls)->wild_statement.children.head;
+ *pwls != NULL; pwls = &(*pwls)->header.next)
+ {
+
+ if ((*pwls)->header.type == lang_input_section_enum
+ && (*pwls)->input_section.section == sec)
+ {
+ is = (lang_input_section_type *) * pwls;
+ *pwls = (*pwls)->header.next;
+ break;
+ }
+ }
+
+ if (is != NULL)
+ break;
+ }
+ }
+
+ if (is == NULL)
+ {
+ einfo ("%P%F: can't find %s in output section\n",
+ bfd_get_section_name (sec->owner, sec));
+ }
+
+ /* Now figure out where the section should go. */
+ switch (i)
+ {
+
+ default: /* to avoid warnings */
+ case XCOFF_SPECIAL_SECTION_TEXT:
+ /* _text */
+ oname = ".text";
+ start = TRUE;
+ break;
+
+ case XCOFF_SPECIAL_SECTION_ETEXT:
+ /* _etext */
+ oname = ".text";
+ start = FALSE;
+ break;
+
+ case XCOFF_SPECIAL_SECTION_DATA:
+ /* _data */
+ oname = ".data";
+ start = TRUE;
+ break;
+
+ case XCOFF_SPECIAL_SECTION_EDATA:
+ /* _edata */
+ oname = ".data";
+ start = FALSE;
+ break;
+
+ case XCOFF_SPECIAL_SECTION_END:
+ case XCOFF_SPECIAL_SECTION_END2:
+ /* _end and end */
+ oname = ".bss";
+ start = FALSE;
+ break;
+ }
+
+ os = lang_output_section_find (oname);
+
+ if (start)
+ {
+ is->header.next = os->children.head;
+ os->children.head = (lang_statement_union_type *) is;
+ }
+ else
+ {
+ is->header.next = NULL;
+ lang_statement_append (&os->children,
+ (lang_statement_union_type *) is,
+ &is->header.next);
+ }
+ }
+
+ /* Executables and shared objects must always have .text, .data
+ and .bss output sections, so that the header can refer to them.
+ The kernel refuses to load objects that have missing sections. */
+ if (!link_info.relocatable)
+ for (i = 0; i < ARRAY_SIZE (must_keep_sections); i++)
+ {
+ asection *sec;
+
+ sec = bfd_get_section_by_name (link_info.output_bfd,
+ must_keep_sections[i]);
+ if (sec == NULL)
+ einfo ("%P: can't find required output section %s\n", must_keep_sections[i]);
+ else
+ sec->flags |= SEC_KEEP;
+ }
+
+ before_allocation_default ();
+}
+
+static char *
+gld${EMULATION_NAME}_choose_target (int argc, char **argv)
+{
+ int i, j, jmax;
+ static char *from_outside;
+ static char *from_inside;
+ static char *argv_to_target[][2] = {
+ {NULL, "${OUTPUT_FORMAT}"},
+ {"-b32", "${OUTPUT_FORMAT_32BIT}"},
+ {"-b64", "${OUTPUT_FORMAT_64BIT}"},
+ };
+
+ jmax = 3;
+
+ from_outside = getenv (TARGET_ENVIRON);
+ if (from_outside != (char *) NULL)
+ return from_outside;
+
+ /* Set to default. */
+ from_inside = argv_to_target[0][1];
+ for (i = 1; i < argc; i++)
+ {
+ for (j = 1; j < jmax; j++)
+ {
+ if (0 == strcmp (argv[i], argv_to_target[j][0]))
+ from_inside = argv_to_target[j][1];
+ }
+ }
+
+ return from_inside;
+}
+
+/* Returns
+ 1 : state changed
+ 0 : no change */
+static int
+change_symbol_mode (char *input)
+{
+ char *symbol_mode_string[] = {
+ "# 32", /* 0x01 */
+ "# 64", /* 0x02 */
+ "# no32", /* 0x04 */
+ "# no64", /* 0x08 */
+ NULL,
+ };
+
+ unsigned int bit;
+ char *string;
+
+ for (bit = 0;; bit++)
+ {
+ string = symbol_mode_string[bit];
+ if (string == NULL)
+ return 0;
+
+ if (0 == strcmp (input, string))
+ {
+ symbol_mode = (1 << bit);
+ return 1;
+ }
+ }
+ /* should not be here */
+ return 0;
+}
+
+/* Returns
+ 1 : yes
+ 0 : ignore
+ -1 : error, try something else */
+static int
+is_syscall (char *input, unsigned int *flag)
+{
+ unsigned int bit;
+ char *string;
+
+ struct sc {
+ char *syscall_string;
+ unsigned int flag;
+ } s [] = {
+ { "svc" /* 0x01 */, XCOFF_SYSCALL32 },
+ { "svc32" /* 0x02 */, XCOFF_SYSCALL32 },
+ { "svc3264" /* 0x04 */, XCOFF_SYSCALL32 | XCOFF_SYSCALL64 },
+ { "svc64" /* 0x08 */, XCOFF_SYSCALL64 },
+ { "syscall" /* 0x10 */, XCOFF_SYSCALL32 },
+ { "syscall32" /* 0x20 */, XCOFF_SYSCALL32 },
+ { "syscall3264" /* 0x40 */, XCOFF_SYSCALL32 | XCOFF_SYSCALL64 },
+ { "syscall64" /* 0x80 */, XCOFF_SYSCALL64 },
+ { NULL, 0 },
+ };
+
+ *flag = 0;
+
+ for (bit = 0;; bit++)
+ {
+ string = s[bit].syscall_string;
+ if (string == NULL)
+ return -1;
+
+ if (0 == strcmp (input, string))
+ {
+ if (1 << bit & syscall_mask)
+ {
+ *flag = s[bit].flag;
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ }
+ /* should not be here */
+ return -1;
+}
+
+/* Read an import or export file. For an import file, this is called
+ by the before_allocation emulation routine. For an export file,
+ this is called by the handle_option emulation routine. */
+
+static void
+gld${EMULATION_NAME}_read_file (const char *filename, bfd_boolean import)
+{
+ struct obstack *o;
+ FILE *f;
+ int lineno;
+ int c;
+ bfd_boolean keep;
+ const char *imppath;
+ const char *impfile;
+ const char *impmember;
+
+ o = (struct obstack *) xmalloc (sizeof (struct obstack));
+ obstack_specify_allocation (o, 0, 0, xmalloc, gld${EMULATION_NAME}_free);
+
+ f = fopen (filename, FOPEN_RT);
+ if (f == NULL)
+ {
+ bfd_set_error (bfd_error_system_call);
+ einfo ("%F%s: %E\n", filename);
+ }
+
+ keep = FALSE;
+
+ imppath = NULL;
+ impfile = NULL;
+ impmember = NULL;
+
+ lineno = 0;
+
+ /* Default to 32 and 64 bit mode
+ symbols at top of /lib/syscalls.exp do not have a mode modifier and they
+ are not repeated, assume 64 bit routines also want to use them.
+ See the routine change_symbol_mode for more information. */
+
+ symbol_mode = 0x04;
+
+ while ((c = getc (f)) != EOF)
+ {
+ char *s;
+ char *symname;
+ unsigned int syscall_flag = 0;
+ bfd_vma address;
+ struct bfd_link_hash_entry *h;
+
+ if (c != '\n')
+ {
+ obstack_1grow (o, c);
+ continue;
+ }
+
+ obstack_1grow (o, '\0');
+ ++lineno;
+
+ s = (char *) obstack_base (o);
+ while (ISSPACE (*s))
+ ++s;
+ if (*s == '\0'
+ || *s == '*'
+ || change_symbol_mode (s)
+ || (*s == '#' && s[1] == ' ')
+ || (!import && *s == '#' && s[1] == '!'))
+ {
+ obstack_free (o, obstack_base (o));
+ continue;
+ }
+
+ if (*s == '#' && s[1] == '!')
+ {
+ s += 2;
+ while (ISSPACE (*s))
+ ++s;
+ if (*s == '\0')
+ {
+ imppath = NULL;
+ impfile = NULL;
+ impmember = NULL;
+ obstack_free (o, obstack_base (o));
+ }
+ else if (*s == '(')
+ einfo ("%F%s%d: #! ([member]) is not supported in import files\n",
+ filename, lineno);
+ else
+ {
+ char cs;
+ char *start;
+
+ (void) obstack_finish (o);
+ keep = TRUE;
+ start = s;
+ while (!ISSPACE (*s) && *s != '(' && *s != '\0')
+ ++s;
+ cs = *s;
+ *s = '\0';
+ if (!bfd_xcoff_split_import_path (link_info.output_bfd,
+ start, &imppath, &impfile))
+ einfo ("%F%P: Could not parse import path: %E\n");
+ while (ISSPACE (cs))
+ {
+ ++s;
+ cs = *s;
+ }
+ if (cs != '(')
+ {
+ impmember = "";
+ if (cs != '\0')
+ einfo ("%s:%d: warning: syntax error in import file\n",
+ filename, lineno);
+ }
+ else
+ {
+ ++s;
+ impmember = s;
+ while (*s != ')' && *s != '\0')
+ ++s;
+ if (*s == ')')
+ *s = '\0';
+ else
+ einfo ("%s:%d: warning: syntax error in import file\n",
+ filename, lineno);
+ }
+ }
+
+ continue;
+ }
+
+ if (symbol_mode & symbol_mode_mask)
+ {
+ /* This is a symbol to be imported or exported. */
+ symname = s;
+ syscall_flag = 0;
+ address = (bfd_vma) -1;
+
+ while (!ISSPACE (*s) && *s != '\0')
+ ++s;
+ if (*s != '\0')
+ {
+ char *se;
+
+ *s++ = '\0';
+
+ while (ISSPACE (*s))
+ ++s;
+
+ se = s;
+ while (!ISSPACE (*se) && *se != '\0')
+ ++se;
+ if (*se != '\0')
+ {
+ *se++ = '\0';
+ while (ISSPACE (*se))
+ ++se;
+ if (*se != '\0')
+ einfo ("%s%d: warning: syntax error in import/export file\n",
+ filename, lineno);
+ }
+
+ if (s != se)
+ {
+ int status;
+ const char *end;
+
+ status = is_syscall (s, &syscall_flag);
+
+ if (0 > status)
+ {
+ /* not a system call, check for address */
+ address = bfd_scan_vma (s, &end, 0);
+ if (*end != '\0')
+ {
+ einfo ("%s:%d: warning: syntax error in import/export file\n",
+ filename, lineno);
+
+ }
+ }
+ }
+ }
+
+ if (!import)
+ {
+ struct export_symbol_list *n;
+
+ ldlang_add_undef (symname);
+ n = ((struct export_symbol_list *)
+ xmalloc (sizeof (struct export_symbol_list)));
+ n->next = export_symbols;
+ n->name = xstrdup (symname);
+ export_symbols = n;
+ }
+ else
+ {
+ h = bfd_link_hash_lookup (link_info.hash, symname, FALSE, FALSE,
+ TRUE);
+ if (h == NULL || h->type == bfd_link_hash_new)
+ {
+ /* We can just ignore attempts to import an unreferenced
+ symbol. */
+ }
+ else
+ {
+ if (!bfd_xcoff_import_symbol (link_info.output_bfd,
+ &link_info, h,
+ address, imppath, impfile,
+ impmember, syscall_flag))
+ einfo ("%X%s:%d: failed to import symbol %s: %E\n",
+ filename, lineno, symname);
+ }
+ }
+ }
+ obstack_free (o, obstack_base (o));
+ }
+
+ if (obstack_object_size (o) > 0)
+ {
+ einfo ("%s:%d: warning: ignoring unterminated last line\n",
+ filename, lineno);
+ obstack_free (o, obstack_base (o));
+ }
+
+ if (!keep)
+ {
+ obstack_free (o, NULL);
+ free (o);
+ }
+}
+
+/* This routine saves us from worrying about declaring free. */
+
+static void
+gld${EMULATION_NAME}_free (void *p)
+{
+ free (p);
+}
+
+/* This is called by the before_allocation routine via
+ lang_for_each_statement. It looks for relocations and assignments
+ to symbols. */
+
+static void
+gld${EMULATION_NAME}_find_relocs (lang_statement_union_type *s)
+{
+ if (s->header.type == lang_reloc_statement_enum)
+ {
+ lang_reloc_statement_type *rs;
+
+ rs = &s->reloc_statement;
+ if (rs->name == NULL)
+ einfo ("%F%P: only relocations against symbols are permitted\n");
+ if (!bfd_xcoff_link_count_reloc (link_info.output_bfd, &link_info,
+ rs->name))
+ einfo ("%F%P: bfd_xcoff_link_count_reloc failed: %E\n");
+ }
+
+ if (s->header.type == lang_assignment_statement_enum)
+ 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)
+{
+ 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;
+ /* Fall through. */
+ case etree_assign:
+ if (strcmp (exp->assign.dst, ".") != 0)
+ {
+ if (!bfd_xcoff_record_link_assignment (link_info.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;
+ }
+}
+
+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 ${srcdir}/emultempl/ostring.sed"
+
+fragment <<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.
+
+fragment <<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
+
+fragment <<EOF
+
+static void
+gld${EMULATION_NAME}_create_output_section_statements (void)
+{
+ /* __rtinit */
+ if ((bfd_get_flavour (link_info.output_bfd) == bfd_target_xcoff_flavour)
+ && (link_info.init_function != NULL
+ || link_info.fini_function != NULL
+ || rtld))
+ {
+ initfini_file = lang_add_input_file ("initfini",
+ lang_input_file_is_file_enum,
+ NULL);
+
+ initfini_file->the_bfd = bfd_create ("initfini", link_info.output_bfd);
+ if (initfini_file->the_bfd == NULL
+ || ! bfd_set_arch_mach (initfini_file->the_bfd,
+ bfd_get_arch (link_info.output_bfd),
+ bfd_get_mach (link_info.output_bfd)))
+ {
+ einfo ("%X%P: can not create BFD %E\n");
+ return;
+ }
+
+ /* Call backend to fill in the rest */
+ if (! bfd_xcoff_link_generate_rtinit (initfini_file->the_bfd,
+ link_info.init_function,
+ link_info.fini_function,
+ rtld))
+ {
+ einfo ("%X%P: can not create BFD %E\n");
+ return;
+ }
+
+ /* __rtld defined in /lib/librtl.a */
+ if (rtld)
+ lang_add_input_file ("rtl", lang_input_file_is_l_enum, NULL);
+ }
+}
+
+static void
+gld${EMULATION_NAME}_set_output_arch (void)
+{
+ bfd_set_arch_mach (link_info.output_bfd,
+ bfd_xcoff_architecture (link_info.output_bfd),
+ bfd_xcoff_machine (link_info.output_bfd));
+
+ ldfile_output_architecture = bfd_get_arch (link_info.output_bfd);
+ ldfile_output_machine = bfd_get_mach (link_info.output_bfd);
+ ldfile_output_machine_name = bfd_printable_name (link_info.output_bfd);
+}
+
+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 *path;
+
+ if (!entry->is_archive)
+ return FALSE;
+
+ filename = entry->filename;
+ path = concat (search->name, "/lib", entry->filename, arch, ".a", NULL);
+ if (!ldfile_try_open_bfd (path, entry))
+ {
+ free (path);
+ return FALSE;
+ }
+ /* Don't include the searched directory in the import path. */
+ bfd_xcoff_set_archive_import_path (&link_info, entry->the_bfd,
+ path + strlen (search->name) + 1);
+ entry->filename = path;
+ return TRUE;
+}
+
+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,
+ gld${EMULATION_NAME}_set_output_arch,
+ gld${EMULATION_NAME}_choose_target,
+ gld${EMULATION_NAME}_before_allocation,
+ gld${EMULATION_NAME}_get_script,
+ "${EMULATION_NAME}",
+ "${OUTPUT_FORMAT}",
+ finish_default,
+ gld${EMULATION_NAME}_create_output_section_statements,
+ gld${EMULATION_NAME}_open_dynamic_archive,
+ 0, /* place_orphan */
+ 0, /* set_symbols */
+ gld${EMULATION_NAME}_parse_args,
+ gld${EMULATION_NAME}_add_options,
+ gld${EMULATION_NAME}_handle_option,
+ gld${EMULATION_NAME}_unrecognized_file,
+ NULL, /* list_options */
+ NULL, /* recognized_file */
+ NULL, /* find potential_libraries */
+ NULL /* new_vers_pattern */
+};
+EOF
diff --git a/binutils-2.20.1/ld/emultempl/alphaelf.em b/binutils-2.20.1/ld/emultempl/alphaelf.em
new file mode 100644
index 00000000..864e6998
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/alphaelf.em
@@ -0,0 +1,155 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2003, 2004, 2005, 2007, 2008, 2009
+# Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+# This file is sourced from elf32.em, and defines extra alpha
+# specific routines.
+#
+fragment <<EOF
+
+#include "elf/internal.h"
+#include "elf/alpha.h"
+#include "elf-bfd.h"
+
+static bfd_boolean limit_32bit;
+static bfd_boolean disable_relaxation;
+
+extern bfd_boolean elf64_alpha_use_secureplt;
+
+
+/* Set the start address as in the Tru64 ld. */
+#define ALPHA_TEXT_START_32BIT 0x12000000
+
+static void
+alpha_after_open (void)
+{
+ if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour
+ && elf_object_id (link_info.output_bfd) == ALPHA_ELF_TDATA)
+ {
+ unsigned int num_plt;
+ lang_output_section_statement_type *os;
+ lang_output_section_statement_type *plt_os[2];
+
+ num_plt = 0;
+ for (os = &lang_output_section_statement.head->output_section_statement;
+ os != NULL;
+ os = os->next)
+ {
+ if (os->constraint == SPECIAL && strcmp (os->name, ".plt") == 0)
+ {
+ if (num_plt < 2)
+ plt_os[num_plt] = os;
+ ++num_plt;
+ }
+ }
+
+ if (num_plt == 2)
+ {
+ plt_os[0]->constraint = elf64_alpha_use_secureplt ? 0 : -1;
+ plt_os[1]->constraint = elf64_alpha_use_secureplt ? -1 : 0;
+ }
+ }
+
+ gld${EMULATION_NAME}_after_open ();
+}
+
+static void
+alpha_after_parse (void)
+{
+ if (limit_32bit && !link_info.shared && !link_info.relocatable)
+ lang_section_start (".interp",
+ exp_binop ('+',
+ exp_intop (ALPHA_TEXT_START_32BIT),
+ exp_nameop (SIZEOF_HEADERS, NULL)),
+ NULL);
+
+ after_parse_default ();
+}
+
+static void
+alpha_before_allocation (void)
+{
+ /* Call main function; we're just extending it. */
+ gld${EMULATION_NAME}_before_allocation ();
+
+ /* Add -relax if -O, not -r, and not explicitly disabled. */
+ if (link_info.optimize && !link_info.relocatable && !disable_relaxation)
+ command_line.relax = TRUE;
+}
+
+static void
+alpha_finish (void)
+{
+ if (limit_32bit)
+ elf_elfheader (link_info.output_bfd)->e_flags |= EF_ALPHA_32BIT;
+
+ finish_default ();
+}
+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
+#define OPTION_NO_RELAX (OPTION_TASO + 1)
+#define OPTION_SECUREPLT (OPTION_NO_RELAX + 1)
+#define OPTION_NO_SECUREPLT (OPTION_SECUREPLT + 1)
+'
+
+PARSE_AND_LIST_LONGOPTS='
+ { "taso", no_argument, NULL, OPTION_TASO },
+ { "no-relax", no_argument, NULL, OPTION_NO_RELAX },
+ { "secureplt", no_argument, NULL, OPTION_SECUREPLT },
+ { "no-secureplt", no_argument, NULL, OPTION_NO_SECUREPLT },
+'
+
+PARSE_AND_LIST_OPTIONS='
+ fprintf (file, _("\
+ --taso Load executable in the lower 31-bit addressable\n\
+ virtual address range.\n\
+ --no-relax Do not relax call and gp sequences.\n\
+ --secureplt Force PLT in text segment.\n\
+ --no-secureplt Force PLT in data segment.\n\
+"));
+'
+
+PARSE_AND_LIST_ARGS_CASES='
+ case OPTION_TASO:
+ limit_32bit = 1;
+ break;
+ case OPTION_NO_RELAX:
+ disable_relaxation = TRUE;
+ break;
+ case OPTION_SECUREPLT:
+ elf64_alpha_use_secureplt = TRUE;
+ break;
+ case OPTION_NO_SECUREPLT:
+ elf64_alpha_use_secureplt = FALSE;
+ break;
+'
+
+# Put these extra alpha routines in ld_${EMULATION_NAME}_emulation
+#
+LDEMUL_AFTER_OPEN=alpha_after_open
+LDEMUL_AFTER_PARSE=alpha_after_parse
+LDEMUL_BEFORE_ALLOCATION=alpha_before_allocation
+LDEMUL_FINISH=alpha_finish
diff --git a/binutils-2.20.1/ld/emultempl/armcoff.em b/binutils-2.20.1/ld/emultempl/armcoff.em
new file mode 100644
index 00000000..b3cdde90
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/armcoff.em
@@ -0,0 +1,283 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+fragment <<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, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ Written by Steve Chamberlain steve@cygnus.com
+
+ This file is part of the GNU Binutils.
+
+ 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include "sysdep.h"
+#include "bfd.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);
+
+ before_allocation_default ();
+}
+
+static void
+gld${EMULATION_NAME}_after_open (void)
+{
+ if (strstr (bfd_get_target (link_info.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)
+{
+ if (thumb_entry_symbol != NULL)
+ {
+ struct bfd_link_hash_entry * h;
+
+ 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 (link_info.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: cannot find thumb start symbol %s\n"),
+ thumb_entry_symbol);
+ }
+
+ finish_default ();
+}
+
+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"
+
+fragment <<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.
+
+fragment <<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
+
+fragment <<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/binutils-2.20.1/ld/emultempl/armelf.em b/binutils-2.20.1/ld/emultempl/armelf.em
new file mode 100644
index 00000000..ef1a3c75
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/armelf.em
@@ -0,0 +1,674 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 1991, 1993, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+# 2004, 2005, 2006, 2007, 2008, 2009
+# Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+# This file is sourced from elf32.em, and defines extra arm-elf
+# specific routines.
+#
+test -z "$TARGET2_TYPE" && TARGET2_TYPE="rel"
+fragment <<EOF
+
+#include "ldctor.h"
+#include "elf/arm.h"
+
+static char *thumb_entry_symbol = NULL;
+static int byteswap_code = 0;
+static int target1_is_rel = 0${TARGET1_IS_REL};
+static char *target2_type = "${TARGET2_TYPE}";
+static int fix_v4bx = 0;
+static int use_blx = 0;
+static bfd_arm_vfp11_fix vfp11_denorm_fix = BFD_ARM_VFP11_FIX_DEFAULT;
+static int fix_cortex_a8 = -1;
+static int no_enum_size_warning = 0;
+static int no_wchar_size_warning = 0;
+static int pic_veneer = 0;
+
+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_before_allocation (void)
+{
+ bfd_elf32_arm_set_byteswap_code (&link_info, byteswap_code);
+
+ /* Choose type of VFP11 erratum fix, or warn if specified fix is unnecessary
+ due to architecture version. */
+ bfd_elf32_arm_set_vfp11_fix (link_info.output_bfd, &link_info);
+
+ /* Auto-select Cortex-A8 erratum fix if it wasn't explicitly specified. */
+ bfd_elf32_arm_set_cortex_a8_fix (link_info.output_bfd, &link_info);
+
+ /* We should be able to set the size of the interworking stub section. We
+ can't do it until later if we have dynamic sections, though. */
+ if (! elf_hash_table (&link_info)->dynamic_sections_created)
+ {
+ /* Here we rummage through the found bfds to collect glue information. */
+ LANG_FOR_EACH_INPUT_STATEMENT (is)
+ {
+ /* Initialise mapping tables for code/data. */
+ bfd_elf32_arm_init_maps (is->the_bfd);
+
+ if (!bfd_elf32_arm_process_before_allocation (is->the_bfd,
+ &link_info)
+ || !bfd_elf32_arm_vfp11_erratum_scan (is->the_bfd, &link_info))
+ /* 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);
+ }
+
+ /* Call the standard elf routine. */
+ gld${EMULATION_NAME}_before_allocation ();
+}
+
+/* Fake input file for stubs. */
+static lang_input_statement_type *stub_file;
+
+/* Whether we need to call gldarm_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;
+
+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
+ after its associated input section. */
+ *(info->add.tail) = l->header.next;
+ l->header.next = info->add.head;
+ 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 elf32_arm_size_stubs. */
+
+/* Create a new stub section, and arrange for it to be linked
+ immediately after INPUT_SECTION. */
+
+static asection *
+elf32_arm_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;
+
+ flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
+ | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP);
+ stub_sec = bfd_make_section_anyway_with_flags (stub_file->the_bfd,
+ stub_sec_name, flags);
+ if (stub_sec == NULL)
+ goto err_ret;
+
+ bfd_set_section_alignment (stub_file->the_bfd, stub_sec, 3);
+
+ 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);
+
+ if (info.add.head == NULL)
+ goto err_ret;
+
+ 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 elf_arm_size_stubs. */
+
+static void
+gldarm_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. */
+ gld${EMULATION_NAME}_map_segments (TRUE);
+ need_laying_out = -1;
+}
+
+static void
+build_section_lists (lang_statement_union_type *statement)
+{
+ if (statement->header.type == lang_input_section_enum)
+ {
+ asection *i = statement->input_section.section;
+
+ if (!((lang_input_statement_type *) i->owner->usrdata)->just_syms_flag
+ && (i->flags & SEC_EXCLUDE) == 0
+ && i->output_section != NULL
+ && i->output_section->owner == link_info.output_bfd)
+ elf32_arm_next_input_section (& link_info, i);
+ }
+}
+
+static int
+compare_output_sec_vma (const void *a, const void *b)
+{
+ asection *asec = *(asection **) a, *bsec = *(asection **) b;
+ asection *aout = asec->output_section, *bout = bsec->output_section;
+ bfd_vma avma, bvma;
+
+ /* If there's no output section for some reason, compare equal. */
+ if (!aout || !bout)
+ return 0;
+
+ avma = aout->vma + asec->output_offset;
+ bvma = bout->vma + bsec->output_offset;
+
+ if (avma > bvma)
+ return 1;
+ else if (avma < bvma)
+ return -1;
+
+ return 0;
+}
+
+static void
+gld${EMULATION_NAME}_after_allocation (void)
+{
+ if (!link_info.relocatable)
+ {
+ /* Build a sorted list of input text sections, then use that to process
+ the unwind table index. */
+ unsigned int list_size = 10;
+ asection **sec_list = xmalloc (list_size * sizeof (asection *));
+ unsigned int sec_count = 0;
+
+ LANG_FOR_EACH_INPUT_STATEMENT (is)
+ {
+ bfd *abfd = is->the_bfd;
+ asection *sec;
+
+ if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
+ continue;
+
+ for (sec = abfd->sections; sec != NULL; sec = sec->next)
+ {
+ asection *out_sec = sec->output_section;
+
+ if (out_sec
+ && elf_section_data (sec)
+ && elf_section_type (sec) == SHT_PROGBITS
+ && (elf_section_flags (sec) & SHF_EXECINSTR) != 0
+ && (sec->flags & SEC_EXCLUDE) == 0
+ && sec->sec_info_type != ELF_INFO_TYPE_JUST_SYMS
+ && out_sec != bfd_abs_section_ptr)
+ {
+ if (sec_count == list_size)
+ {
+ list_size *= 2;
+ sec_list = xrealloc (sec_list,
+ list_size * sizeof (asection *));
+ }
+
+ sec_list[sec_count++] = sec;
+ }
+ }
+ }
+
+ qsort (sec_list, sec_count, sizeof (asection *), &compare_output_sec_vma);
+
+ if (elf32_arm_fix_exidx_coverage (sec_list, sec_count, &link_info))
+ need_laying_out = 1;
+
+ free (sec_list);
+ }
+
+ /* bfd_elf32_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 (link_info.output_bfd, & link_info))
+ need_laying_out = 1;
+
+ /* If generating a relocatable output file, then we don't
+ have to examine the relocs. */
+ if (stub_file != NULL && !link_info.relocatable)
+ {
+ int ret = elf32_arm_setup_section_lists (link_info.output_bfd, & link_info);
+
+ if (ret != 0)
+ {
+ if (ret < 0)
+ {
+ einfo ("%X%P: could not compute sections lists for stub generation: %E\n");
+ return;
+ }
+
+ lang_for_each_statement (build_section_lists);
+
+ /* Call into the BFD backend to do the real work. */
+ if (! elf32_arm_size_stubs (link_info.output_bfd,
+ stub_file->the_bfd,
+ & link_info,
+ group_size,
+ & elf32_arm_add_stub_section,
+ & gldarm_layout_sections_again))
+ {
+ einfo ("%X%P: cannot size stub section: %E\n");
+ return;
+ }
+ }
+ }
+
+ if (need_laying_out != -1)
+ gld${EMULATION_NAME}_map_segments (need_laying_out);
+}
+
+static void
+gld${EMULATION_NAME}_finish (void)
+{
+ struct bfd_link_hash_entry * h;
+
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (is)
+ {
+ /* Figure out where VFP11 erratum veneers (and the labels returning
+ from same) have been placed. */
+ bfd_elf32_arm_vfp11_fix_veneer_locations (is->the_bfd, &link_info);
+ }
+ }
+
+ if (! link_info.relocatable)
+ {
+ /* Now build the linker stubs. */
+ if (stub_file->the_bfd->sections != NULL)
+ {
+ if (! elf32_arm_build_stubs (& link_info))
+ einfo ("%X%P: can not build stubs: %E\n");
+ }
+ }
+
+ finish_default ();
+
+ if (thumb_entry_symbol)
+ {
+ h = bfd_link_hash_lookup (link_info.hash, thumb_entry_symbol,
+ FALSE, FALSE, TRUE);
+ }
+ else
+ {
+ struct elf_link_hash_entry * eh;
+
+ if (!entry_symbol.name)
+ return;
+
+ h = bfd_link_hash_lookup (link_info.hash, entry_symbol.name,
+ FALSE, FALSE, TRUE);
+ eh = (struct elf_link_hash_entry *)h;
+ if (!h || ELF_ST_TYPE(eh->type) != STT_ARM_TFUNC)
+ return;
+ }
+
+
+ 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 (link_info.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 (thumb_entry_symbol != NULL && 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: cannot find thumb start symbol %s\n"),
+ thumb_entry_symbol);
+}
+
+/* This is a convenient point to tell BFD about target specific flags.
+ After the output has been created, but before inputs are read. */
+static void
+arm_elf_create_output_section_statements (void)
+{
+ if (strstr (bfd_get_target (link_info.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;
+ }
+
+ bfd_elf32_arm_set_target_relocs (link_info.output_bfd, &link_info,
+ target1_is_rel,
+ target2_type, fix_v4bx, use_blx,
+ vfp11_denorm_fix, no_enum_size_warning,
+ no_wchar_size_warning,
+ pic_veneer, fix_cortex_a8);
+
+ stub_file = lang_add_input_file ("linker stubs",
+ lang_input_file_is_fake_enum,
+ NULL);
+ stub_file->the_bfd = bfd_create ("linker stubs", link_info.output_bfd);
+ if (stub_file->the_bfd == NULL
+ || ! bfd_set_arch_mach (stub_file->the_bfd,
+ bfd_get_arch (link_info.output_bfd),
+ bfd_get_mach (link_info.output_bfd)))
+ {
+ einfo ("%X%P: can not create BFD %E\n");
+ return;
+ }
+
+ stub_file->the_bfd->flags |= BFD_LINKER_CREATED;
+ ldlang_add_file (stub_file);
+
+ /* Also use the stub file for stubs placed in a single output section. */
+ bfd_elf32_arm_add_glue_sections_to_bfd (stub_file->the_bfd, &link_info);
+ bfd_elf32_arm_get_bfd_for_interworking (stub_file->the_bfd, &link_info);
+}
+
+/* Avoid processing the fake stub_file in vercheck, stat_needed and
+ check_needed routines. */
+
+static void (*real_func) (lang_input_statement_type *);
+
+static void arm_for_each_input_file_wrapper (lang_input_statement_type *l)
+{
+ if (l != stub_file)
+ (*real_func) (l);
+}
+
+static void
+arm_lang_for_each_input_file (void (*func) (lang_input_statement_type *))
+{
+ real_func = func;
+ lang_for_each_input_file (&arm_for_each_input_file_wrapper);
+}
+
+#define lang_for_each_input_file arm_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_THUMB_ENTRY 301
+#define OPTION_BE8 302
+#define OPTION_TARGET1_REL 303
+#define OPTION_TARGET1_ABS 304
+#define OPTION_TARGET2 305
+#define OPTION_FIX_V4BX 306
+#define OPTION_USE_BLX 307
+#define OPTION_VFP11_DENORM_FIX 308
+#define OPTION_NO_ENUM_SIZE_WARNING 309
+#define OPTION_PIC_VENEER 310
+#define OPTION_FIX_V4BX_INTERWORKING 311
+#define OPTION_STUBGROUP_SIZE 312
+#define OPTION_NO_WCHAR_SIZE_WARNING 313
+#define OPTION_FIX_CORTEX_A8 314
+#define OPTION_NO_FIX_CORTEX_A8 315
+#define OPTION_ICF 399
+'
+
+PARSE_AND_LIST_SHORTOPTS=p
+
+PARSE_AND_LIST_LONGOPTS='
+ { "no-pipeline-knowledge", no_argument, NULL, '\'p\''},
+ { "thumb-entry", required_argument, NULL, OPTION_THUMB_ENTRY},
+ { "be8", no_argument, NULL, OPTION_BE8},
+ { "target1-rel", no_argument, NULL, OPTION_TARGET1_REL},
+ { "target1-abs", no_argument, NULL, OPTION_TARGET1_ABS},
+ { "target2", required_argument, NULL, OPTION_TARGET2},
+ { "fix-v4bx", no_argument, NULL, OPTION_FIX_V4BX},
+ { "fix-v4bx-interworking", no_argument, NULL, OPTION_FIX_V4BX_INTERWORKING},
+ { "use-blx", no_argument, NULL, OPTION_USE_BLX},
+ { "vfp11-denorm-fix", required_argument, NULL, OPTION_VFP11_DENORM_FIX},
+ { "no-enum-size-warning", no_argument, NULL, OPTION_NO_ENUM_SIZE_WARNING},
+ { "pic-veneer", no_argument, NULL, OPTION_PIC_VENEER},
+ { "stub-group-size", required_argument, NULL, OPTION_STUBGROUP_SIZE },
+ { "no-wchar-size-warning", no_argument, NULL, OPTION_NO_WCHAR_SIZE_WARNING},
+ { "fix-cortex-a8", no_argument, NULL, OPTION_FIX_CORTEX_A8 },
+ { "no-fix-cortex-a8", no_argument, NULL, OPTION_NO_FIX_CORTEX_A8 },
+ { "icf", required_argument, NULL, OPTION_ICF },
+'
+
+PARSE_AND_LIST_OPTIONS='
+ fprintf (file, _(" --thumb-entry=<sym> Set the entry point to be Thumb symbol <sym>\n"));
+ fprintf (file, _(" --be8 Output BE8 format image\n"));
+ fprintf (file, _(" --target1=rel Interpret R_ARM_TARGET1 as R_ARM_REL32\n"));
+ fprintf (file, _(" --target1=abs Interpret R_ARM_TARGET1 as R_ARM_ABS32\n"));
+ fprintf (file, _(" --target2=<type> Specify definition of R_ARM_TARGET2\n"));
+ fprintf (file, _(" --fix-v4bx Rewrite BX rn as MOV pc, rn for ARMv4\n"));
+ fprintf (file, _(" --fix-v4bx-interworking Rewrite BX rn branch to ARMv4 interworking veneer\n"));
+ fprintf (file, _(" --use-blx Enable use of BLX instructions\n"));
+ fprintf (file, _(" --vfp11-denorm-fix Specify how to fix VFP11 denorm erratum\n"));
+ fprintf (file, _(" --no-enum-size-warning Don'\''t warn about objects with incompatible\n"
+ " enum sizes\n"));
+ fprintf (file, _(" --no-wchar-size-warning Don'\''t warn about objects with incompatible"
+ " wchar_t sizes\n"));
+ fprintf (file, _(" --pic-veneer Always generate PIC interworking veneers\n"));
+ 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 after 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, _(" --[no-]fix-cortex-a8 Disable/enable Cortex-A8 Thumb-2 branch erratum fix\n"));
+ fprintf (file, _(" --icf=<value> Ignored for compatibility with gold.\n"));
+'
+
+PARSE_AND_LIST_ARGS_CASES='
+ case '\'p\'':
+ /* Only here for backwards compatibility. */
+ break;
+
+ case OPTION_THUMB_ENTRY:
+ thumb_entry_symbol = optarg;
+ break;
+
+ case OPTION_BE8:
+ byteswap_code = 1;
+ break;
+
+ case OPTION_TARGET1_REL:
+ target1_is_rel = 1;
+ break;
+
+ case OPTION_TARGET1_ABS:
+ target1_is_rel = 0;
+ break;
+
+ case OPTION_TARGET2:
+ target2_type = optarg;
+ break;
+
+ case OPTION_FIX_V4BX:
+ fix_v4bx = 1;
+ break;
+
+ case OPTION_FIX_V4BX_INTERWORKING:
+ fix_v4bx = 2;
+ break;
+
+ case OPTION_USE_BLX:
+ use_blx = 1;
+ break;
+
+ case OPTION_VFP11_DENORM_FIX:
+ if (strcmp (optarg, "none") == 0)
+ vfp11_denorm_fix = BFD_ARM_VFP11_FIX_NONE;
+ else if (strcmp (optarg, "scalar") == 0)
+ vfp11_denorm_fix = BFD_ARM_VFP11_FIX_SCALAR;
+ else if (strcmp (optarg, "vector") == 0)
+ vfp11_denorm_fix = BFD_ARM_VFP11_FIX_VECTOR;
+ else
+ einfo (_("Unrecognized VFP11 fix type '\''%s'\''.\n"), optarg);
+ break;
+
+ case OPTION_NO_ENUM_SIZE_WARNING:
+ no_enum_size_warning = 1;
+ break;
+
+ case OPTION_NO_WCHAR_SIZE_WARNING:
+ no_wchar_size_warning = 1;
+ break;
+
+ case OPTION_PIC_VENEER:
+ pic_veneer = 1;
+ break;
+
+ 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_FIX_CORTEX_A8:
+ fix_cortex_a8 = 1;
+ break;
+
+ case OPTION_NO_FIX_CORTEX_A8:
+ fix_cortex_a8 = 0;
+ break;
+
+ case OPTION_ICF:
+ /* For compatibility with gold. */
+ break;
+'
+
+# We have our own before_allocation etc. functions, but they call
+# the standard routines, so give them a different name.
+LDEMUL_BEFORE_ALLOCATION=arm_elf_before_allocation
+LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation
+LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=arm_elf_create_output_section_statements
+
+# 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=gld${EMULATION_NAME}_finish
diff --git a/binutils-2.20.1/ld/emultempl/astring.sed b/binutils-2.20.1/ld/emultempl/astring.sed
new file mode 100644
index 00000000..08bd8a64
--- /dev/null
+++ b/binutils-2.20.1/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/binutils-2.20.1/ld/emultempl/avrelf.em b/binutils-2.20.1/ld/emultempl/avrelf.em
new file mode 100644
index 00000000..f0807dde
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/avrelf.em
@@ -0,0 +1,265 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2006, 2007, 2008, 2009
+# Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+
+# This file is sourced from elf32.em, and defines extra avr-elf specific
+# routines. It is used to generate the trampolines for the avr6 family
+# of devices where one needs to address the issue that it is not possible
+# to reach the whole program memory by using 16 bit pointers.
+
+fragment <<EOF
+
+#include "elf32-avr.h"
+#include "ldctor.h"
+
+/* The fake file and it's corresponding section meant to hold
+ the linker stubs if needed. */
+
+static lang_input_statement_type *stub_file;
+static asection *avr_stub_section;
+
+/* Variables set by the command-line parameters and transfered
+ to the bfd without use of global shared variables. */
+
+static bfd_boolean avr_no_stubs = FALSE;
+static bfd_boolean avr_debug_relax = FALSE;
+static bfd_boolean avr_debug_stubs = FALSE;
+static bfd_boolean avr_replace_call_ret_sequences = TRUE;
+static bfd_vma avr_pc_wrap_around = 0x10000000;
+
+/* Transfers information to the bfd frontend. */
+
+static void
+avr_elf_set_global_bfd_parameters (void)
+{
+ elf32_avr_setup_params (& link_info,
+ stub_file->the_bfd,
+ avr_stub_section,
+ avr_no_stubs,
+ avr_debug_stubs,
+ avr_debug_relax,
+ avr_pc_wrap_around,
+ avr_replace_call_ret_sequences);
+}
+
+
+/* Makes a conservative estimate of the trampoline section size that could
+ be corrected later on. */
+
+static void
+avr_elf_${EMULATION_NAME}_before_allocation (void)
+{
+ int ret;
+
+ gld${EMULATION_NAME}_before_allocation ();
+
+ /* We only need stubs for the avr6 family. */
+ if (strcmp ("${EMULATION_NAME}","avr6"))
+ avr_no_stubs = TRUE;
+
+ avr_elf_set_global_bfd_parameters ();
+
+ /* If generating a relocatable output file, then
+ we don't have to generate the trampolines. */
+ if (link_info.relocatable)
+ avr_no_stubs = TRUE;
+
+ if (avr_no_stubs)
+ return;
+
+ ret = elf32_avr_setup_section_lists (link_info.output_bfd, &link_info);
+
+ if (ret < 0)
+ einfo ("%X%P: can not setup the input section list: %E\n");
+
+ if (ret <= 0)
+ return;
+
+ /* Call into the BFD backend to do the real "stub"-work. */
+ if (! elf32_avr_size_stubs (link_info.output_bfd, &link_info, TRUE))
+ einfo ("%X%P: can not size stub section: %E\n");
+}
+
+/* This is called before the input files are opened. We create a new
+ fake input file to hold the stub section and generate the section itself. */
+
+static void
+avr_elf_create_output_section_statements (void)
+{
+ flagword flags;
+
+ stub_file = lang_add_input_file ("linker stubs",
+ lang_input_file_is_fake_enum,
+ NULL);
+
+ stub_file->the_bfd = bfd_create ("linker stubs", link_info.output_bfd);
+ if (stub_file->the_bfd == NULL
+ || !bfd_set_arch_mach (stub_file->the_bfd,
+ bfd_get_arch (link_info.output_bfd),
+ bfd_get_mach (link_info.output_bfd)))
+ {
+ einfo ("%X%P: can not create stub BFD %E\n");
+ return;
+ }
+
+ /* Now we add the stub section. */
+
+ flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
+ | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP);
+ avr_stub_section = bfd_make_section_anyway_with_flags (stub_file->the_bfd,
+ ".trampolines",
+ flags);
+ if (avr_stub_section == NULL)
+ goto err_ret;
+
+ avr_stub_section->alignment_power = 1;
+
+ ldlang_add_file (stub_file);
+
+ return;
+
+ err_ret:
+ einfo ("%X%P: can not make stub section: %E\n");
+ return;
+}
+
+/* Re-calculates the size of the stubs so that we won't waste space. */
+
+static void
+avr_elf_after_allocation (void)
+{
+ if (!avr_no_stubs && !command_line.relax)
+ {
+ /* If relaxing, elf32_avr_size_stubs will be called from
+ elf32_avr_relax_section. */
+ if (!elf32_avr_size_stubs (link_info.output_bfd, &link_info, FALSE))
+ einfo ("%X%P: can not size stub section: %E\n");
+ }
+
+ gld${EMULATION_NAME}_after_allocation ();
+
+ /* Now build the linker stubs. */
+ if (!avr_no_stubs)
+ {
+ if (!elf32_avr_build_stubs (&link_info))
+ einfo ("%X%P: can not build stubs: %E\n");
+ }
+}
+
+
+EOF
+
+
+PARSE_AND_LIST_PROLOGUE='
+
+#define OPTION_NO_CALL_RET_REPLACEMENT 301
+#define OPTION_PMEM_WRAP_AROUND 302
+#define OPTION_NO_STUBS 303
+#define OPTION_DEBUG_STUBS 304
+#define OPTION_DEBUG_RELAX 305
+'
+
+PARSE_AND_LIST_LONGOPTS='
+ { "no-call-ret-replacement", no_argument,
+ NULL, OPTION_NO_CALL_RET_REPLACEMENT},
+ { "pmem-wrap-around", required_argument,
+ NULL, OPTION_PMEM_WRAP_AROUND},
+ { "no-stubs", no_argument,
+ NULL, OPTION_NO_STUBS},
+ { "debug-stubs", no_argument,
+ NULL, OPTION_DEBUG_STUBS},
+ { "debug-relax", no_argument,
+ NULL, OPTION_DEBUG_RELAX},
+'
+
+PARSE_AND_LIST_OPTIONS='
+ fprintf (file, _(" --pmem-wrap-around=<val> "
+ "Make the linker relaxation machine assume that a\n"
+ " "
+ " program counter wrap-around occures at address\n"
+ " "
+ " <val>. Supported values: 8k, 16k, 32k and 64k.\n"));
+ fprintf (file, _(" --no-call-ret-replacement "
+ "The relaxation machine normally will\n"
+ " "
+ " substitute two immediately following call/ret\n"
+ " "
+ " instructions by a single jump instruction.\n"
+ " "
+ " This option disables this optimization.\n"));
+ fprintf (file, _(" --no-stubs "
+ "If the linker detects to attempt to access\n"
+ " "
+ " an instruction beyond 128k by a reloc that\n"
+ " "
+ " is limited to 128k max, it inserts a jump\n"
+ " "
+ " stub. You can de-active this with this switch.\n"));
+ fprintf (file, _(" --debug-stubs "
+ "Used for debugging avr-ld.\n"));
+ fprintf (file, _(" --debug-relax "
+ "Used for debugging avr-ld.\n"));
+'
+
+PARSE_AND_LIST_ARGS_CASES='
+
+ case OPTION_PMEM_WRAP_AROUND:
+ {
+ /* This variable is defined in the bfd library. */
+ if ((!strcmp (optarg,"32k")) || (!strcmp (optarg,"32K")))
+ avr_pc_wrap_around = 32768;
+ else if ((!strcmp (optarg,"8k")) || (!strcmp (optarg,"8K")))
+ avr_pc_wrap_around = 8192;
+ else if ((!strcmp (optarg,"16k")) || (!strcmp (optarg,"16K")))
+ avr_pc_wrap_around = 16384;
+ else if ((!strcmp (optarg,"64k")) || (!strcmp (optarg,"64K")))
+ avr_pc_wrap_around = 0x10000;
+ else
+ return FALSE;
+ }
+ break;
+
+ case OPTION_DEBUG_STUBS:
+ avr_debug_stubs = TRUE;
+ break;
+
+ case OPTION_DEBUG_RELAX:
+ avr_debug_relax = TRUE;
+ break;
+
+ case OPTION_NO_STUBS:
+ avr_no_stubs = TRUE;
+ break;
+
+ case OPTION_NO_CALL_RET_REPLACEMENT:
+ {
+ /* This variable is defined in the bfd library. */
+ avr_replace_call_ret_sequences = FALSE;
+ }
+ break;
+'
+
+#
+# Put these extra avr-elf routines in ld_${EMULATION_NAME}_emulation
+#
+LDEMUL_BEFORE_ALLOCATION=avr_elf_${EMULATION_NAME}_before_allocation
+LDEMUL_AFTER_ALLOCATION=avr_elf_after_allocation
+LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=avr_elf_create_output_section_statements
diff --git a/binutils-2.20.1/ld/emultempl/beos.em b/binutils-2.20.1/ld/emultempl/beos.em
new file mode 100644
index 00000000..370dbacd
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/beos.em
@@ -0,0 +1,783 @@
+# 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
+fragment <<EOF
+/* This file is part of GLD, the Gnu Linker.
+ Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+
+ This file is part of the GNU Binutils.
+
+ 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, 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. */
+
+#include "sysdep.h"
+#include "bfd.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"
+#include "../bfd/libcoff.h"
+
+#define TARGET_IS_${EMULATION_NAME}
+
+static struct internal_extra_pe_aouthdr pe;
+static int dll;
+
+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 = "a.exe";
+}
+
+/* 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)
+
+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},
+ {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__", BEOS_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),
+ D(MajorSubsystemVersion,"__major_subsystem_version__", 4),
+ D(MinorSubsystemVersion,"__minor_subsystem_version__", 0),
+ D(Subsystem,"__subsystem__", 3),
+ D(SizeOfStackReserve,"__size_of_stack_reserve__", 0x2000000),
+ 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
+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" },
+ { "windows", 2, "_WinMainCRTStartup" },
+ { "wwindows", 2, "_wWinMainCRTStartup" },
+ { "console", 3, "_mainCRTStartup" },
+ { "wconsole", 3, "_wmainCRTStartup" },
+ { "posix", 7, "___PosixProcessStartup"},
+ { 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')
+ {
+ set_pe_name ("__subsystem__", v[i].value);
+
+ /* If the subsystem is windows, we use a different entry
+ point. */
+ lang_default_entry (v[i].entry);
+
+ 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)
+ {
+ 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;
+ }
+ return TRUE;
+}
+
+/* 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;
+
+ if (!init[IMAGEBASEOFF].inited)
+ {
+ if (link_info.relocatable)
+ init[IMAGEBASEOFF].value = 0;
+ else if (init[DLLOFF].value)
+ init[IMAGEBASEOFF].value = BEOS_DLL_IMAGE_BASE;
+ else
+ init[IMAGEBASEOFF].value = BEOS_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 */
+ push_stat_ptr (&abs_output_section->children);
+
+ for (j = 0; init[j].ptr; j++)
+ {
+ long val = init[j].value;
+ 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();
+ }
+ /* Restore the pointer. */
+ pop_stat_ptr ();
+
+ if (pe.FileAlignment >
+ pe.SectionAlignment)
+ {
+ einfo ("%P: warning, file alignment > section alignment.\n");
+ }
+}
+
+static void
+gld_${EMULATION_NAME}_after_open (void)
+{
+ /* 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(link_info.output_bfd)->pe)
+ {
+ einfo ("%F%P: PE operations on non PE file.\n");
+ }
+
+ pe_data(link_info.output_bfd)->pe_opthdr = pe;
+ pe_data(link_info.output_bfd)->dll = init[DLLOFF].value;
+
+}
+
+/* Callback functions for qsort in sort_sections. */
+
+static int
+sort_by_file_name (const void *a, const void *b)
+{
+ const lang_statement_union_type *const *ra = a;
+ const lang_statement_union_type *const *rb = b;
+ int i, a_sec, b_sec;
+
+ i = strcmp ((*ra)->input_section.section->owner->my_archive->filename,
+ (*rb)->input_section.section->owner->my_archive->filename);
+ if (i != 0)
+ return i;
+
+ i = strcmp ((*ra)->input_section.section->owner->filename,
+ (*rb)->input_section.section->owner->filename);
+ if (i != 0)
+ return i;
+ /* the tail idata4/5 are the only ones without relocs to an
+ idata$6 section unless we are importing by ordinal,
+ so sort them to last to terminate the IAT
+ and HNT properly. if no reloc this one is import by ordinal
+ so we have to sort by section contents */
+
+ if ( ((*ra)->input_section.section->reloc_count + (*rb)->input_section.section->reloc_count) )
+ {
+ i = (((*ra)->input_section.section->reloc_count >
+ (*rb)->input_section.section->reloc_count) ? -1 : 0);
+ if ( i != 0)
+ return i;
+
+ return (((*ra)->input_section.section->reloc_count >
+ (*rb)->input_section.section->reloc_count) ? 0 : 1);
+ }
+ else
+ {
+ if ( (strcmp( (*ra)->input_section.section->name, ".idata$6") == 0) )
+ return 0; /* don't sort .idata$6 or .idata$7 FIXME dlltool eliminate .idata$7 */
+
+ if (! bfd_get_section_contents ((*ra)->input_section.section->owner,
+ (*ra)->input_section.section, &a_sec, (file_ptr) 0, (bfd_size_type)sizeof(a_sec)))
+ einfo ("%F%B: Can't read contents of section .idata: %E\n",
+ (*ra)->input_section.section->owner);
+
+ if (! bfd_get_section_contents ((*rb)->input_section.section->owner,
+ (*rb)->input_section.section, &b_sec, (file_ptr) 0, (bfd_size_type)sizeof(b_sec) ))
+ einfo ("%F%B: Can't read contents of section .idata: %E\n",
+ (*rb)->input_section.section->owner);
+
+ i = ((a_sec < b_sec) ? -1 : 0);
+ if ( i != 0)
+ return i;
+ return ((a_sec < b_sec) ? 0 : 1);
+ }
+return 0;
+}
+
+static int
+sort_by_section_name (const void *a, const void *b)
+{
+ const lang_statement_union_type *const *ra = a;
+ const lang_statement_union_type *const *rb = b;
+ int i;
+ i = strcmp ((*ra)->input_section.section->name,
+ (*rb)->input_section.section->name);
+ /* This is a hack to make .stab and .stabstr last, so we don't have
+ to fix strip/objcopy for .reloc sections.
+ FIXME stripping images with a .rsrc section still needs to be fixed. */
+ if (i != 0)
+ {
+ if ((CONST_STRNEQ ((*ra)->input_section.section->name, ".stab"))
+ && (! CONST_STRNEQ ((*rb)->input_section.section->name, ".stab")))
+ return 1;
+ }
+ return i;
+}
+
+/* Subroutine of sort_sections to a contiguous subset of a list of sections.
+ NEXT_AFTER is the element after the last one to sort.
+ The result is a pointer to the last element's "next" pointer. */
+
+static lang_statement_union_type **
+sort_sections_1 (lang_statement_union_type **startptr,
+ lang_statement_union_type *next_after,
+ int count,
+ int (*sort_func) (const void *, const void *))
+{
+ lang_statement_union_type **vec;
+ lang_statement_union_type *p;
+ int i;
+ lang_statement_union_type **ret;
+
+ if (count == 0)
+ return startptr;
+
+ vec = ((lang_statement_union_type **)
+ xmalloc (count * sizeof (lang_statement_union_type *)));
+
+ for (p = *startptr, i = 0; i < count; i++, p = p->header.next)
+ vec[i] = p;
+
+ qsort (vec, count, sizeof (vec[0]), sort_func);
+
+ /* Fill in the next pointers again. */
+ *startptr = vec[0];
+ for (i = 0; i < count - 1; i++)
+ vec[i]->header.next = vec[i + 1];
+ vec[i]->header.next = next_after;
+ ret = &vec[i]->header.next;
+ free (vec);
+ return ret;
+}
+
+/* Sort the .idata\$foo input sections of archives into filename order.
+ The reason is so dlltool can arrange to have the pe dll import information
+ generated correctly - the head of the list goes into dh.o, the tail into
+ dt.o, and the guts into ds[nnnn].o. Note that this is only needed for the
+ .idata section.
+ FIXME: This may no longer be necessary with grouped sections. Instead of
+ sorting on dh.o, ds[nnnn].o, dt.o, one could, for example, have dh.o use
+ .idata\$4h, have ds[nnnn].o use .idata\$4s[nnnn], and have dt.o use .idata\$4t.
+ This would have to be elaborated upon to handle multiple dll's
+ [assuming such an eloboration is possible of course].
+
+ We also sort sections in '\$' wild statements. These are created by the
+ place_orphans routine to implement grouped sections. */
+
+static void
+sort_sections (lang_statement_union_type *s)
+{
+ for (; s ; s = s->header.next)
+ switch (s->header.type)
+ {
+ case lang_output_section_statement_enum:
+ sort_sections (s->output_section_statement.children.head);
+ break;
+ case lang_wild_statement_enum:
+ {
+ lang_statement_union_type **p = &s->wild_statement.children.head;
+ struct wildcard_list *sec;
+
+ for (sec = s->wild_statement.section_list; sec; sec = sec->next)
+ {
+ /* Is this the .idata section? */
+ if (sec->spec.name != NULL
+ && CONST_STRNEQ (sec->spec.name, ".idata"))
+ {
+ /* Sort the children. We want to sort any objects in
+ the same archive. In order to handle the case of
+ including a single archive multiple times, we sort
+ all the children by archive name and then by object
+ name. After sorting them, we re-thread the pointer
+ chain. */
+
+ while (*p)
+ {
+ lang_statement_union_type *start = *p;
+ if (start->header.type != lang_input_section_enum
+ || !start->input_section.section->owner->my_archive)
+ p = &(start->header.next);
+ else
+ {
+ lang_statement_union_type *end;
+ int count;
+
+ for (end = start, count = 0;
+ end && (end->header.type
+ == lang_input_section_enum);
+ end = end->header.next)
+ count++;
+
+ p = sort_sections_1 (p, end, count,
+ sort_by_file_name);
+ }
+ }
+ break;
+ }
+
+ /* If this is a collection of grouped sections, sort them.
+ The linker script must explicitly mention "*(.foo\$)" or
+ "*(.foo\$*)". Don't sort them if \$ is not the last
+ character (not sure if this is really useful, but it
+ allows explicitly mentioning some \$ sections and letting
+ the linker handle the rest). */
+ if (sec->spec.name != NULL)
+ {
+ char *q = strchr (sec->spec.name, '\$');
+
+ if (q != NULL
+ && (q[1] == '\0'
+ || (q[1] == '*' && q[2] == '\0')))
+ {
+ lang_statement_union_type *end;
+ int count;
+
+ for (end = *p, count = 0; end; end = end->header.next)
+ {
+ if (end->header.type != lang_input_section_enum)
+ abort ();
+ count++;
+ }
+ (void) sort_sections_1 (p, end, count,
+ sort_by_section_name);
+ }
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+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))
+ {
+ 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);
+#else
+#ifdef TARGET_IS_armpe
+ /* 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 (!arm_process_before_allocation (is->the_bfd, & link_info))
+ {
+ einfo ("Errors encountered processing file %s", is->filename);
+ }
+ }
+ }
+
+ /* We have seen it all. Allocate it, and carry on */
+ arm_allocate_interworking_sections (& link_info);
+#endif /* TARGET_IS_armpe */
+#endif /* TARGET_IS_ppcpe */
+
+ sort_sections (stat_ptr->head);
+
+ before_allocation_default ();
+}
+
+/* Place an orphan section. We use this to put sections with a '\$' in them
+ into the right place. Any section with a '\$' in them (e.g. .text\$foo)
+ gets mapped to the output section with everything from the '\$' on stripped
+ (e.g. .text).
+ See the Microsoft Portable Executable and Common Object File Format
+ Specification 4.1, section 4.2, Grouped Sections.
+
+ FIXME: This is now handled by the linker script using wildcards,
+ but I'm leaving this here in case we want to enable it for sections
+ which are not mentioned in the linker script. */
+
+static lang_output_section_statement_type *
+gld${EMULATION_NAME}_place_orphan (asection *s,
+ const char *secname,
+ int constraint)
+{
+ char *output_secname, *ps;
+ lang_output_section_statement_type *os;
+ lang_statement_union_type *l;
+
+ if ((s->flags & SEC_ALLOC) == 0)
+ return NULL;
+
+ /* Don't process grouped sections unless doing a final link.
+ If they're marked as COMDAT sections, we don't want .text\$foo to
+ end up in .text and then have .text disappear because it's marked
+ link-once-discard. */
+ if (link_info.relocatable)
+ return NULL;
+
+ /* Everything from the '\$' on gets deleted so don't allow '\$' as the
+ first character. */
+ if (*secname == '\$')
+ einfo ("%P%F: section %s has '\$' as first character\n", secname);
+ if (strchr (secname + 1, '\$') == NULL)
+ return NULL;
+
+ /* Look up the output section. The Microsoft specs say sections names in
+ image files never contain a '\$'. Fortunately, lang_..._lookup creates
+ the section if it doesn't exist. */
+ output_secname = xstrdup (secname);
+ ps = strchr (output_secname + 1, '\$');
+ *ps = 0;
+ os = lang_output_section_statement_lookup (output_secname, constraint, TRUE);
+
+ /* Find the '\$' wild statement for this section. We currently require the
+ linker script to explicitly mention "*(.foo\$)".
+ FIXME: ppcpe.sc has .CRT\$foo in the .rdata section. According to the
+ Microsoft docs this isn't correct so it's not (currently) handled. */
+
+ ps[0] = '\$';
+ ps[1] = 0;
+ for (l = os->children.head; l; l = l->header.next)
+ if (l->header.type == lang_wild_statement_enum)
+ {
+ struct wildcard_list *sec;
+
+ for (sec = l->wild_statement.section_list; sec; sec = sec->next)
+ if (sec->spec.name && strcmp (sec->spec.name, output_secname) == 0)
+ break;
+ if (sec)
+ break;
+ }
+ ps[0] = 0;
+ if (l == NULL)
+ einfo ("%P%F: *(%s\$) missing from linker script\n", output_secname);
+
+ /* Link the input section in and we're done for now.
+ The sections still have to be sorted, but that has to wait until
+ all such sections have been processed by us. The sorting is done by
+ sort_sections. */
+ lang_add_section (&l->wild_statement.children, s, os);
+
+ return os;
+}
+
+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"
+
+fragment <<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
+
+fragment <<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}",
+ finish_default,
+ NULL, /* create output section statements */
+ NULL, /* 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,
+ NULL, /* unrecognized file */
+ NULL, /* list options */
+ NULL, /* recognized file */
+ NULL, /* find_potential_libraries */
+ NULL /* new_vers_pattern */
+};
+EOF
diff --git a/binutils-2.20.1/ld/emultempl/cr16elf.em b/binutils-2.20.1/ld/emultempl/cr16elf.em
new file mode 100644
index 00000000..83f07834
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/cr16elf.em
@@ -0,0 +1,208 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
+# Contributed by M R Swami Reddy <MR.Swami.Reddy@nsc.com>
+#
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+# This file is sourced from elf32.em, and defines extra cr16-elf
+# specific routines.
+#
+fragment <<EOF
+
+#include "ldctor.h"
+
+/* Flag for the emulation-specific "--no-relax" option. */
+static bfd_boolean disable_relaxation = FALSE;
+
+static void check_sections (bfd *, asection *, void *);
+
+
+/* This function is run after all the input files have been opened. */
+
+static void
+cr16_elf_after_open (void)
+{
+ /* Call the standard elf routine. */
+ gld${EMULATION_NAME}_after_open ();
+
+ if (command_line.embedded_relocs
+ && (! link_info.relocatable))
+ {
+ bfd *abfd;
+
+ /* In the embedded relocs mode we create a .emreloc section for each
+ input file with a nonzero .data section. 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 either
+ COFF or ELF. We need to call a special BFD backend function to
+ generate the embedded relocs, and we have such functions only for
+ COFF and ELF. */
+ if (bfd_get_flavour (abfd) != bfd_target_coff_flavour
+ && bfd_get_flavour (abfd) != bfd_target_elf_flavour)
+ einfo ("%F%B: all input objects must be COFF or ELF for --embedded-relocs\n");
+
+ datasec = bfd_get_section_by_name (abfd, ".data.rel");
+
+ /* 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, ".emreloc");
+ 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 * 8))
+ einfo ("%F%B: can not create .emreloc 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 .data section has
+ relocs. This is called via bfd_map_over_sections. */
+
+static void
+check_sections (bfd *abfd, asection *sec, void *datasec)
+{
+ if ((strncmp (bfd_get_section_name (abfd, sec), ".data.rel", 9) == 0)
+ && sec != datasec
+ && sec->reloc_count == 0 )
+ einfo ("%B%X: section %s has relocs; can not use --embedded-relocs\n",
+ abfd, bfd_get_section_name (abfd, sec));
+}
+
+static void
+cr16elf_after_parse (void)
+{
+ /* Always behave as if called with --sort-common command line
+ option.
+ This is to emulate the CRTools' method of keeping variables
+ of different alignment in separate sections. */
+ config.sort_common = TRUE;
+
+ /* Don't create a demand-paged executable, since this feature isn't
+ meaninful in CR16 embedded systems. Moreover, when magic_demand_paged
+ is true the link sometimes fails. */
+ config.magic_demand_paged = FALSE;
+
+ after_parse_default ();
+}
+
+/* This is called after the sections have been attached to output
+ sections, but before any sizes or addresses have been set. */
+
+static void
+cr16elf_before_allocation (void)
+{
+ /* Call the default first. */
+ gld${EMULATION_NAME}_before_allocation ();
+
+ if (command_line.embedded_relocs
+ && (! link_info.relocatable))
+ {
+
+ bfd *abfd;
+
+ /* If we are generating embedded relocs, call a special BFD backend
+ routine to do the work. */
+ for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link_next)
+ {
+ asection *datasec, *relsec;
+ char *errmsg;
+
+ datasec = bfd_get_section_by_name (abfd, ".data.rel");
+
+ if (datasec == NULL || datasec->reloc_count == 0)
+ continue;
+
+ relsec = bfd_get_section_by_name (abfd, ".emreloc");
+ ASSERT (relsec != NULL);
+
+ if (! bfd_cr16_elf32_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);
+ }
+ }
+ }
+
+ /* Enable relaxation by default if the "--no-relax" option was not
+ specified. This is done here instead of in the before_parse hook
+ because there is a check in main() to prohibit use of --relax and
+ -r together. */
+
+ if (!disable_relaxation)
+ command_line.relax = TRUE;
+}
+
+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_RELAX 301
+'
+
+PARSE_AND_LIST_LONGOPTS='
+ { "no-relax", no_argument, NULL, OPTION_NO_RELAX},
+'
+
+PARSE_AND_LIST_OPTIONS='
+ fprintf (file, _(" --no-relax Do not relax branches\n"));
+'
+
+PARSE_AND_LIST_ARGS_CASES='
+ case OPTION_NO_RELAX:
+ disable_relaxation = TRUE;
+ break;
+'
+
+# Put these extra cr16-elf routines in ld_${EMULATION_NAME}_emulation
+#
+LDEMUL_AFTER_OPEN=cr16_elf_after_open
+LDEMUL_AFTER_PARSE=cr16elf_after_parse
+LDEMUL_BEFORE_ALLOCATION=cr16elf_before_allocation
diff --git a/binutils-2.20.1/ld/emultempl/crxelf.em b/binutils-2.20.1/ld/emultempl/crxelf.em
new file mode 100644
index 00000000..a257c06d
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/crxelf.em
@@ -0,0 +1,96 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2004, 2005, 2007, 2009
+# Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+# This file is sourced from elf32.em, and defines extra crx-elf
+# specific routines.
+#
+fragment <<EOF
+
+#include "ldctor.h"
+
+/* Flag for the emulation-specific "--no-relax" option. */
+static bfd_boolean disable_relaxation = FALSE;
+
+static void crxelf_after_parse (void);
+
+static void
+crxelf_after_parse (void)
+{
+ /* Always behave as if called with --sort-common command line
+ option.
+ This is to emulate the CRTools' method of keeping variables
+ of different alignment in separate sections. */
+ config.sort_common = TRUE;
+
+ /* Don't create a demand-paged executable, since this feature isn't
+ meaninful in CRX embedded systems. Moreover, when magic_demand_paged
+ is true the link sometimes fails. */
+ config.magic_demand_paged = FALSE;
+
+ after_parse_default ();
+}
+
+/* This is called after the sections have been attached to output
+ sections, but before any sizes or addresses have been set. */
+
+static void
+crxelf_before_allocation (void)
+{
+ /* Call the default first. */
+ gld${EMULATION_NAME}_before_allocation ();
+
+ /* Enable relaxation by default if the "--no-relax" option was not
+ specified. This is done here instead of in the before_parse hook
+ because there is a check in main() to prohibit use of --relax and
+ -r together. */
+
+ if (!disable_relaxation)
+ command_line.relax = TRUE;
+}
+
+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_RELAX 301
+'
+
+PARSE_AND_LIST_LONGOPTS='
+ { "no-relax", no_argument, NULL, OPTION_NO_RELAX},
+'
+
+PARSE_AND_LIST_OPTIONS='
+ fprintf (file, _(" --no-relax Do not relax branches\n"));
+'
+
+PARSE_AND_LIST_ARGS_CASES='
+ case OPTION_NO_RELAX:
+ disable_relaxation = TRUE;
+ break;
+'
+
+# Put these extra crx-elf routines in ld_${EMULATION_NAME}_emulation
+#
+LDEMUL_AFTER_PARSE=crxelf_after_parse
+LDEMUL_BEFORE_ALLOCATION=crxelf_before_allocation
diff --git a/binutils-2.20.1/ld/emultempl/elf-generic.em b/binutils-2.20.1/ld/emultempl/elf-generic.em
new file mode 100644
index 00000000..cf4c2c82
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/elf-generic.em
@@ -0,0 +1,73 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+# This file is sourced from elf32.em and from ELF targets that use
+# generic.em.
+#
+fragment <<EOF
+
+static void
+gld${EMULATION_NAME}_map_segments (bfd_boolean need_layout)
+{
+ int tries = 10;
+
+ do
+ {
+ lang_relax_sections (need_layout);
+ need_layout = FALSE;
+
+ if (link_info.output_bfd->xvec->flavour == bfd_target_elf_flavour
+ && !link_info.relocatable)
+ {
+ bfd_size_type phdr_size;
+
+ phdr_size = elf_tdata (link_info.output_bfd)->program_header_size;
+ /* If we don't have user supplied phdrs, throw away any
+ previous linker generated program headers. */
+ if (lang_phdr_list == NULL)
+ elf_tdata (link_info.output_bfd)->segment_map = NULL;
+ if (!_bfd_elf_map_sections_to_segments (link_info.output_bfd,
+ &link_info))
+ einfo ("%F%P: map sections to segments failed: %E\n");
+
+ if (phdr_size
+ != elf_tdata (link_info.output_bfd)->program_header_size)
+ {
+ if (tries > 6)
+ /* The first few times we allow any change to
+ phdr_size . */
+ need_layout = TRUE;
+ else if (phdr_size
+ < elf_tdata (link_info.output_bfd)->program_header_size)
+ /* After that we only allow the size to grow. */
+ need_layout = TRUE;
+ else
+ elf_tdata (link_info.output_bfd)->program_header_size
+ = phdr_size;
+ }
+ }
+ }
+ while (need_layout && --tries);
+
+ if (tries == 0)
+ einfo (_("%P%F: looping in map_segments"));
+}
+EOF
diff --git a/binutils-2.20.1/ld/emultempl/elf32.em b/binutils-2.20.1/ld/emultempl/elf32.em
new file mode 100644
index 00000000..9518714e
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/elf32.em
@@ -0,0 +1,2357 @@
+# 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
+fragment <<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, 2005, 2006, 2007, 2008, 2009
+ 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 the GNU Binutils.
+
+ 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libiberty.h"
+#include "safe-ctype.h"
+#include "getopt.h"
+#include "md5.h"
+#include "sha1.h"
+#include <fcntl.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"
+#include "elf-bfd.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 void gld${EMULATION_NAME}_after_allocation (void);
+static lang_output_section_statement_type *gld${EMULATION_NAME}_place_orphan
+ (asection *, const char *, int);
+EOF
+
+if [ "x${USE_LIBPATH}" = xyes ] ; then
+ case ${target} in
+ *-*-linux-* | *-*-k*bsd*-*)
+ fragment <<EOF
+#ifdef HAVE_GLOB
+#include <glob.h>
+#endif
+EOF
+ ;;
+ esac
+fi
+
+# Import any needed special functions and/or overrides.
+#
+source_em ${srcdir}/emultempl/elf-generic.em
+if test -n "$EXTRA_EM_FILE" ; then
+ source_em ${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
+fragment <<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
+fragment <<EOF
+/* Handle as_needed DT_NEEDED. */
+
+static bfd_boolean
+gld${EMULATION_NAME}_load_symbols (lang_input_statement_type *entry)
+{
+ int link_class = 0;
+
+ /* 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. */
+ if (entry->as_needed)
+ link_class = DYN_AS_NEEDED;
+
+ /* Tell the ELF linker that we don't want the output file to have a
+ DT_NEEDED entry for any dynamic library in DT_NEEDED tags from
+ this file at all. */
+ if (!entry->add_needed)
+ link_class |= DYN_NO_ADD_NEEDED;
+
+ if (entry->just_syms_flag
+ && (bfd_get_file_flags (entry->the_bfd) & DYNAMIC) != 0)
+ einfo (_("%P%F: --just-symbols may not be used on DSO: %B\n"),
+ entry->the_bfd);
+
+ if (!link_class
+ || (bfd_get_file_flags (entry->the_bfd) & DYNAMIC) == 0)
+ return FALSE;
+
+ bfd_elf_set_dyn_lib_class (entry->the_bfd,
+ (enum dynamic_lib_link_class) link_class);
+
+ /* Continue on with normal load_symbols processing. */
+ return FALSE;
+}
+EOF
+fi
+
+fragment <<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 lang_input_statement_type *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 != NULL)
+ return;
+ if (s->the_bfd == NULL)
+ return;
+
+ /* If this input file was an as-needed entry, and wasn't found to be
+ needed at the stage it was linked, then don't say we have loaded it. */
+ if ((bfd_elf_get_dyn_lib_class (s->the_bfd) & DYN_AS_NEEDED) != 0)
+ return;
+
+ if (bfd_stat (s->the_bfd, &st) != 0)
+ {
+ einfo ("%P:%B: bfd_stat failed: %E\n", s->the_bfd);
+ return;
+ }
+
+ /* Some operating systems, e.g. Windows, do not provide a meaningful
+ st_ino; they always set it to zero. (Windows does provide a
+ meaningful st_dev.) Do not indicate a duplicate library in that
+ case. While there is no guarantee that a system that provides
+ meaningful inode numbers will never set st_ino to zero, this is
+ merely an optimization, so we do not need to worry about false
+ negatives. */
+ if (st.st_dev == global_stat.st_dev
+ && st.st_ino == global_stat.st_ino
+ && st.st_ino != 0)
+ {
+ global_found = s;
+ 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);
+}
+
+struct dt_needed
+{
+ bfd *by;
+ const char *name;
+};
+
+/* 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 (struct dt_needed *needed,
+ int force)
+{
+ bfd *abfd;
+ const char *name = needed->name;
+ const char *soname;
+ int link_class;
+
+ abfd = bfd_openr (name, bfd_get_target (link_info.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 != link_info.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-* | *-*-k*bsd*-*)
+ fragment <<EOF
+ {
+ struct bfd_link_needed_list *l;
+
+ for (l = needed; l != NULL; l = l->next)
+ if (CONST_STRNEQ (l->name, "libc.so"))
+ break;
+ if (l == NULL)
+ {
+ bfd_close (abfd);
+ return FALSE;
+ }
+ }
+
+EOF
+ ;;
+esac
+fragment <<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 = NULL;
+ lang_for_each_input_file (gld${EMULATION_NAME}_stat_needed);
+ if (global_found != NULL)
+ {
+ /* 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. */
+ link_class = DYN_DT_NEEDED;
+
+ /* Tell the ELF linker that we don't want the output file to have a
+ DT_NEEDED entry for this file at all if the entry is from a file
+ with DYN_NO_ADD_NEEDED. */
+ if (needed->by != NULL
+ && (bfd_elf_get_dyn_lib_class (needed->by) & DYN_NO_ADD_NEEDED) != 0)
+ link_class |= DYN_NO_NEEDED | DYN_NO_ADD_NEEDED;
+
+ bfd_elf_set_dyn_lib_class (abfd, (enum dynamic_lib_link_class) link_class);
+
+ /* 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,
+ struct dt_needed *n, int force)
+{
+ const char *s;
+ const char *name = n->name;
+ size_t len;
+ struct dt_needed needed;
+
+ if (name[0] == '/')
+ return gld${EMULATION_NAME}_try_needed (n, force);
+
+ if (path == NULL || *path == '\0')
+ return FALSE;
+
+ needed.by = n->by;
+ needed.name = n->name;
+
+ len = strlen (name);
+ while (1)
+ {
+ char *filename, *sset;
+
+ s = strchr (path, config.rpath_separator);
+ 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);
+
+ needed.name = filename;
+ if (gld${EMULATION_NAME}_try_needed (&needed, force))
+ return TRUE;
+
+ free (filename);
+
+ if (*s == '\0')
+ break;
+ path = s + 1;
+ }
+
+ return FALSE;
+}
+
+EOF
+if [ "x${USE_LIBPATH}" = xyes ] ; then
+ fragment <<EOF
+
+/* Add the sysroot to every entry in a path separated by
+ config.rpath_separator. */
+
+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++] == config.rpath_separator)
+ 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] == config.rpath_separator)
+ {
+ *p++ = path[i++];
+ strcpy (p, ld_sysroot);
+ p = p + strlen (p);
+ }
+ else
+ *p++ = path[i++];
+
+ *p = 0;
+ return ret;
+}
+
+EOF
+ case ${target} in
+ *-*-freebsd* | *-*-dragonfly*)
+ fragment <<EOF
+/* Read the system search path the FreeBSD way rather than the Linux way. */
+#ifdef HAVE_ELF_HINTS_H
+#include <elf-hints.h>
+#else
+#include "elf-hints-local.h"
+#endif
+
+static bfd_boolean
+gld${EMULATION_NAME}_check_ld_elf_hints (const char *name, int force)
+{
+ static bfd_boolean initialized;
+ static char *ld_elf_hints;
+ struct dt_needed needed;
+
+ if (!initialized)
+ {
+ FILE *f;
+ char *tmppath;
+
+ tmppath = concat (ld_sysroot, _PATH_ELF_HINTS, (const char *) NULL);
+ f = fopen (tmppath, FOPEN_RB);
+ free (tmppath);
+ if (f != NULL)
+ {
+ struct elfhints_hdr hdr;
+
+ if (fread (&hdr, 1, sizeof (hdr), f) == sizeof (hdr)
+ && hdr.magic == ELFHINTS_MAGIC
+ && hdr.version == 1)
+ {
+ if (fseek (f, hdr.strtab + hdr.dirlist, SEEK_SET) != -1)
+ {
+ char *b;
+
+ b = xmalloc (hdr.dirlistlen + 1);
+ if (fread (b, 1, hdr.dirlistlen + 1, f) ==
+ hdr.dirlistlen + 1)
+ ld_elf_hints = gld${EMULATION_NAME}_add_sysroot (b);
+
+ free (b);
+ }
+ }
+ fclose (f);
+ }
+
+ initialized = TRUE;
+ }
+
+ if (ld_elf_hints == NULL)
+ return FALSE;
+
+ needed.by = NULL;
+ needed.name = name;
+ return gld${EMULATION_NAME}_search_needed (ld_elf_hints, & needed,
+ force);
+}
+EOF
+ # FreeBSD
+ ;;
+
+ *-*-linux-* | *-*-k*bsd*-*)
+ fragment <<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. */
+
+struct gld${EMULATION_NAME}_ld_so_conf
+{
+ char *path;
+ size_t len, alloc;
+};
+
+static bfd_boolean
+gld${EMULATION_NAME}_parse_ld_so_conf
+ (struct gld${EMULATION_NAME}_ld_so_conf *info, const char *filename);
+
+static void
+gld${EMULATION_NAME}_parse_ld_so_conf_include
+ (struct gld${EMULATION_NAME}_ld_so_conf *info, const char *filename,
+ const char *pattern)
+{
+ char *newp = NULL;
+#ifdef HAVE_GLOB
+ glob_t gl;
+#endif
+
+ if (pattern[0] != '/')
+ {
+ char *p = strrchr (filename, '/');
+ size_t patlen = strlen (pattern) + 1;
+
+ newp = xmalloc (p - filename + 1 + patlen);
+ memcpy (newp, filename, p - filename + 1);
+ memcpy (newp + (p - filename + 1), pattern, patlen);
+ pattern = newp;
+ }
+
+#ifdef HAVE_GLOB
+ if (glob (pattern, 0, NULL, &gl) == 0)
+ {
+ size_t i;
+
+ for (i = 0; i < gl.gl_pathc; ++i)
+ gld${EMULATION_NAME}_parse_ld_so_conf (info, gl.gl_pathv[i]);
+ globfree (&gl);
+ }
+#else
+ /* If we do not have glob, treat the pattern as a literal filename. */
+ gld${EMULATION_NAME}_parse_ld_so_conf (info, pattern);
+#endif
+
+ if (newp)
+ free (newp);
+}
+
+static bfd_boolean
+gld${EMULATION_NAME}_parse_ld_so_conf
+ (struct gld${EMULATION_NAME}_ld_so_conf *info, const char *filename)
+{
+ FILE *f = fopen (filename, FOPEN_RT);
+ char *line;
+ size_t linelen;
+
+ if (f == NULL)
+ return FALSE;
+
+ linelen = 256;
+ line = xmalloc (linelen);
+ do
+ {
+ char *p = line, *q;
+
+ /* Normally this would use getline(3), but we need to be portable. */
+ while ((q = fgets (p, linelen - (p - line), f)) != NULL
+ && strlen (q) == linelen - (p - line) - 1
+ && line[linelen - 2] != '\n')
+ {
+ line = xrealloc (line, 2 * linelen);
+ p = line + linelen - 1;
+ linelen += linelen;
+ }
+
+ if (q == NULL && p == line)
+ break;
+
+ p = strchr (line, '\n');
+ if (p)
+ *p = '\0';
+
+ /* Because the file format does not know any form of quoting we
+ can search forward for the next '#' character and if found
+ make it terminating the line. */
+ p = strchr (line, '#');
+ if (p)
+ *p = '\0';
+
+ /* Remove leading whitespace. NUL is no whitespace character. */
+ p = line;
+ while (*p == ' ' || *p == '\f' || *p == '\r' || *p == '\t' || *p == '\v')
+ ++p;
+
+ /* If the line is blank it is ignored. */
+ if (p[0] == '\0')
+ continue;
+
+ if (CONST_STRNEQ (p, "include") && (p[7] == ' ' || p[7] == '\t'))
+ {
+ char *dir, c;
+ p += 8;
+ do
+ {
+ while (*p == ' ' || *p == '\t')
+ ++p;
+
+ if (*p == '\0')
+ break;
+
+ dir = p;
+
+ while (*p != ' ' && *p != '\t' && *p)
+ ++p;
+
+ c = *p;
+ *p++ = '\0';
+ if (dir[0] != '\0')
+ gld${EMULATION_NAME}_parse_ld_so_conf_include (info, filename,
+ dir);
+ }
+ while (c != '\0');
+ }
+ else
+ {
+ char *dir = p;
+ while (*p && *p != '=' && *p != ' ' && *p != '\t' && *p != '\f'
+ && *p != '\r' && *p != '\v')
+ ++p;
+
+ while (p != dir && p[-1] == '/')
+ --p;
+ if (info->path == NULL)
+ {
+ info->alloc = p - dir + 1 + 256;
+ info->path = xmalloc (info->alloc);
+ info->len = 0;
+ }
+ else
+ {
+ if (info->len + 1 + (p - dir) >= info->alloc)
+ {
+ info->alloc += p - dir + 256;
+ info->path = xrealloc (info->path, info->alloc);
+ }
+ info->path[info->len++] = config.rpath_separator;
+ }
+ memcpy (info->path + info->len, dir, p - dir);
+ info->len += p - dir;
+ info->path[info->len] = '\0';
+ }
+ }
+ while (! feof (f));
+ free (line);
+ fclose (f);
+ return TRUE;
+}
+
+static bfd_boolean
+gld${EMULATION_NAME}_check_ld_so_conf (const char *name, int force)
+{
+ static bfd_boolean initialized;
+ static char *ld_so_conf;
+ struct dt_needed needed;
+
+ if (! initialized)
+ {
+ char *tmppath;
+ struct gld${EMULATION_NAME}_ld_so_conf info;
+
+ info.path = NULL;
+ info.len = info.alloc = 0;
+ tmppath = concat (ld_sysroot, "${prefix}/etc/ld.so.conf",
+ (const char *) NULL);
+ if (!gld${EMULATION_NAME}_parse_ld_so_conf (&info, tmppath))
+ {
+ free (tmppath);
+ tmppath = concat (ld_sysroot, "/etc/ld.so.conf",
+ (const char *) NULL);
+ gld${EMULATION_NAME}_parse_ld_so_conf (&info, tmppath);
+ }
+ free (tmppath);
+
+ if (info.path)
+ {
+ char *d = gld${EMULATION_NAME}_add_sysroot (info.path);
+ free (info.path);
+ ld_so_conf = d;
+ }
+ initialized = TRUE;
+ }
+
+ if (ld_so_conf == NULL)
+ return FALSE;
+
+
+ needed.by = NULL;
+ needed.name = name;
+ return gld${EMULATION_NAME}_search_needed (ld_so_conf, &needed, force);
+}
+
+EOF
+ # Linux
+ ;;
+ esac
+fi
+fragment <<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)
+{
+ const char *soname;
+
+ /* Stop looking if we've found a loaded lib. */
+ if (global_found != NULL
+ && (bfd_elf_get_dyn_lib_class (global_found->the_bfd)
+ & DYN_AS_NEEDED) == 0)
+ return;
+
+ if (s->filename == NULL || s->the_bfd == NULL)
+ return;
+
+ /* Don't look for a second non-loaded as-needed lib. */
+ if (global_found != NULL
+ && (bfd_elf_get_dyn_lib_class (s->the_bfd) & DYN_AS_NEEDED) != 0)
+ return;
+
+ if (strcmp (s->filename, global_needed->name) == 0)
+ {
+ global_found = s;
+ return;
+ }
+
+ if (s->search_dirs_flag)
+ {
+ const char *f = strrchr (s->filename, '/');
+ if (f != NULL
+ && strcmp (f + 1, global_needed->name) == 0)
+ {
+ global_found = s;
+ return;
+ }
+ }
+
+ soname = bfd_elf_get_dt_soname (s->the_bfd);
+ if (soname != NULL
+ && strcmp (soname, global_needed->name) == 0)
+ {
+ global_found = s;
+ return;
+ }
+}
+
+EOF
+
+if test x"$LDEMUL_AFTER_OPEN" != xgld"$EMULATION_NAME"_after_open; then
+fragment <<EOF
+
+static bfd_size_type
+gld${EMULATION_NAME}_id_note_section_size (bfd *abfd,
+ struct bfd_link_info *link_info)
+{
+ const char *style = link_info->emit_note_gnu_build_id;
+ bfd_size_type size;
+
+ abfd = abfd;
+
+ size = offsetof (Elf_External_Note, name[sizeof "GNU"]);
+ size = (size + 3) & -(bfd_size_type) 4;
+
+ if (!strcmp (style, "md5") || !strcmp (style, "uuid"))
+ size += 128 / 8;
+ else if (!strcmp (style, "sha1"))
+ size += 160 / 8;
+ else if (!strncmp (style, "0x", 2))
+ {
+ /* ID is in string form (hex). Convert to bits. */
+ const char *id = style + 2;
+ do
+ {
+ if (ISXDIGIT (id[0]) && ISXDIGIT (id[1]))
+ {
+ ++size;
+ id += 2;
+ }
+ else if (*id == '-' || *id == ':')
+ ++id;
+ else
+ {
+ size = 0;
+ break;
+ }
+ } while (*id != '\0');
+ }
+ else
+ size = 0;
+
+ return size;
+}
+
+static unsigned char
+read_hex (const char xdigit)
+{
+ if (ISDIGIT (xdigit))
+ return xdigit - '0';
+ if (ISUPPER (xdigit))
+ return xdigit - 'A' + 0xa;
+ if (ISLOWER (xdigit))
+ return xdigit - 'a' + 0xa;
+ abort ();
+ return 0;
+}
+
+struct build_id_info
+{
+ const char *style;
+ asection *sec;
+};
+
+static bfd_boolean
+gld${EMULATION_NAME}_write_build_id_section (bfd *abfd)
+{
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ struct build_id_info *info = (struct build_id_info *)
+ elf_tdata (abfd)->after_write_object_contents_info;
+ asection *asec;
+ Elf_Internal_Shdr *i_shdr;
+ unsigned char *contents, *id_bits;
+ bfd_size_type size;
+ Elf_External_Note *e_note;
+
+ asec = info->sec;
+ if (bfd_is_abs_section (asec->output_section))
+ {
+ einfo (_("%P: warning: .note.gnu.build-id section discarded,"
+ " --build-id ignored.\n"));
+ return TRUE;
+ }
+ i_shdr = &elf_section_data (asec->output_section)->this_hdr;
+
+ if (i_shdr->contents == NULL)
+ {
+ if (asec->contents == NULL)
+ asec->contents = (unsigned char *) xmalloc (asec->size);
+ contents = asec->contents;
+ }
+ else
+ contents = i_shdr->contents + asec->output_offset;
+
+ e_note = (Elf_External_Note *) contents;
+ size = offsetof (Elf_External_Note, name[sizeof "GNU"]);
+ size = (size + 3) & -(bfd_size_type) 4;
+ id_bits = contents + size;
+ size = asec->size - size;
+
+ bfd_h_put_32 (abfd, sizeof "GNU", &e_note->namesz);
+ bfd_h_put_32 (abfd, size, &e_note->descsz);
+ bfd_h_put_32 (abfd, NT_GNU_BUILD_ID, &e_note->type);
+ memcpy (e_note->name, "GNU", sizeof "GNU");
+
+ if (!strcmp (info->style, "md5"))
+ {
+ struct md5_ctx ctx;
+ md5_init_ctx (&ctx);
+ if (bed->s->checksum_contents (abfd,
+ (void (*) (const void *, size_t, void *))
+ &md5_process_bytes,
+ &ctx))
+ md5_finish_ctx (&ctx, id_bits);
+ else
+ return FALSE;
+ }
+ else if (!strcmp (info->style, "sha1"))
+ {
+ struct sha1_ctx ctx;
+ sha1_init_ctx (&ctx);
+ if (bed->s->checksum_contents (abfd,
+ (void (*) (const void *, size_t, void *))
+ &sha1_process_bytes,
+ &ctx))
+ sha1_finish_ctx (&ctx, id_bits);
+ else
+ return FALSE;
+ }
+ else if (!strcmp (info->style, "uuid"))
+ {
+ int n;
+ int fd = open ("/dev/urandom", O_RDONLY);
+ if (fd < 0)
+ return FALSE;
+ n = read (fd, id_bits, size);
+ close (fd);
+ if (n < (int) size)
+ return FALSE;
+ }
+ else if (!strncmp (info->style, "0x", 2))
+ {
+ /* ID is in string form (hex). Convert to bits. */
+ const char *id = info->style + 2;
+ size_t n = 0;
+ do
+ {
+ if (ISXDIGIT (id[0]) && ISXDIGIT (id[1]))
+ {
+ id_bits[n] = read_hex (*id++) << 4;
+ id_bits[n++] |= read_hex (*id++);
+ }
+ else if (*id == '-' || *id == ':')
+ ++id;
+ else
+ abort (); /* Should have been validated earlier. */
+ } while (*id != '\0');
+ }
+ else
+ abort (); /* Should have been validated earlier. */
+
+ size = asec->size;
+ return (bfd_seek (abfd,
+ i_shdr->sh_offset + asec->output_offset, SEEK_SET) == 0
+ && bfd_bwrite (contents, size, abfd) == size);
+}
+
+
+/* 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;
+ struct elf_link_hash_table *htab;
+
+ htab = elf_hash_table (&link_info);
+ if (!is_elf_hash_table (htab))
+ return;
+
+ if (link_info.emit_note_gnu_build_id)
+ {
+ bfd *abfd;
+ asection *s;
+ bfd_size_type size;
+
+ abfd = link_info.input_bfds;
+
+ if (abfd == NULL)
+ {
+ /* PR 10555: If there are no input files do not
+ try to create a .note.gnu-build-id section. */
+ free (link_info.emit_note_gnu_build_id);
+ link_info.emit_note_gnu_build_id = NULL;
+ }
+ else
+ {
+ size = gld${EMULATION_NAME}_id_note_section_size (abfd, &link_info);
+ if (size == 0)
+ {
+ einfo ("%P: warning: unrecognized --build-id style ignored.\n");
+ free (link_info.emit_note_gnu_build_id);
+ link_info.emit_note_gnu_build_id = NULL;
+ }
+ else
+ {
+ s = bfd_make_section_with_flags (abfd, ".note.gnu.build-id",
+ SEC_ALLOC | SEC_LOAD
+ | SEC_IN_MEMORY | SEC_LINKER_CREATED
+ | SEC_READONLY | SEC_DATA);
+ if (s != NULL && bfd_set_section_alignment (abfd, s, 2))
+ {
+ struct elf_obj_tdata *t = elf_tdata (link_info.output_bfd);
+ struct build_id_info *b =
+ (struct build_id_info *) xmalloc (sizeof *b);
+
+ b->style = link_info.emit_note_gnu_build_id;
+ b->sec = s;
+ elf_section_type (s) = SHT_NOTE;
+ s->size = size;
+ t->after_write_object_contents
+ = &gld${EMULATION_NAME}_write_build_id_section;
+ t->after_write_object_contents_info = b;
+ }
+ else
+ {
+ einfo ("%P: warning: Cannot create .note.gnu.build-id section,"
+ " --build-id ignored.\n");
+ free (link_info.emit_note_gnu_build_id);
+ link_info.emit_note_gnu_build_id = NULL;
+ }
+ }
+ }
+ }
+
+ if (link_info.relocatable)
+ return;
+
+ if (link_info.eh_frame_hdr
+ && !link_info.traditional_format)
+ {
+ bfd *abfd;
+ asection *s;
+
+ for (abfd = link_info.input_bfds; abfd; abfd = abfd->link_next)
+ {
+ s = bfd_get_section_by_name (abfd, ".eh_frame");
+ if (s && s->size > 8 && !bfd_is_abs_section (s->output_section))
+ break;
+ }
+ if (abfd)
+ {
+ const struct elf_backend_data *bed;
+
+ bed = get_elf_backend_data (abfd);
+ s = bfd_make_section_with_flags (abfd, ".eh_frame_hdr",
+ bed->dynamic_sec_flags
+ | SEC_READONLY);
+ if (s != NULL
+ && bfd_set_section_alignment (abfd, s, 2))
+ htab->eh_info.hdr_sec = s;
+ else
+ einfo ("%P: warning: Cannot create .eh_frame_hdr section,"
+ " --eh-frame-hdr ignored.\n");
+ }
+ }
+
+ /* 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. */
+ if (!link_info.executable)
+ return;
+ needed = bfd_elf_get_needed_list (link_info.output_bfd, &link_info);
+ for (l = needed; l != NULL; l = l->next)
+ {
+ struct bfd_link_needed_list *ll;
+ struct dt_needed n, nn;
+ int force;
+
+ /* If the lib that needs this one was --as-needed and wasn't
+ found to be needed, then this lib isn't needed either. */
+ if (l->by != NULL
+ && (bfd_elf_get_dyn_lib_class (l->by) & DYN_AS_NEEDED) != 0)
+ continue;
+
+ /* If we've already seen this file, skip it. */
+ for (ll = needed; ll != l; ll = ll->next)
+ if ((ll->by == NULL
+ || (bfd_elf_get_dyn_lib_class (ll->by) & DYN_AS_NEEDED) == 0)
+ && 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 = NULL;
+ lang_for_each_input_file (gld${EMULATION_NAME}_check_needed);
+ if (global_found != NULL
+ && (bfd_elf_get_dyn_lib_class (global_found->the_bfd)
+ & DYN_AS_NEEDED) == 0)
+ continue;
+
+ n.by = l->by;
+ n.name = l->name;
+ nn.by = l->by;
+ if (trace_file_tries)
+ info_msg (_("%s needed by %B\n"), l->name, l->by);
+
+ /* As-needed libs specified on the command line (or linker script)
+ take priority over libs found in search dirs. */
+ if (global_found != NULL)
+ {
+ nn.name = global_found->filename;
+ if (gld${EMULATION_NAME}_try_needed (&nn, TRUE))
+ continue;
+ }
+
+ /* 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${NATIVE}" = xyes ] ; then
+fragment <<EOF
+ const char *lib_path;
+EOF
+fi
+if [ "x${USE_LIBPATH}" = xyes ] ; then
+fragment <<EOF
+ struct bfd_link_needed_list *rp;
+ int found;
+EOF
+fi
+fragment <<EOF
+
+ if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link,
+ &n, force))
+ break;
+EOF
+if [ "x${USE_LIBPATH}" = xyes ] ; then
+fragment <<EOF
+ if (gld${EMULATION_NAME}_search_needed (command_line.rpath,
+ &n, force))
+ break;
+EOF
+fi
+if [ "x${NATIVE}" = xyes ] ; then
+fragment <<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, &n,
+ force))
+ break;
+ }
+ lib_path = (const char *) getenv ("LD_LIBRARY_PATH");
+ if (gld${EMULATION_NAME}_search_needed (lib_path, &n, force))
+ break;
+EOF
+fi
+if [ "x${USE_LIBPATH}" = xyes ] ; then
+fragment <<EOF
+ found = 0;
+ rp = bfd_elf_get_runpath_list (link_info.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,
+ &n,
+ force));
+ free (tmpname);
+ }
+ if (found)
+ break;
+
+EOF
+fi
+if [ "x${USE_LIBPATH}" = xyes ] ; then
+ case ${target} in
+ *-*-freebsd* | *-*-dragonfly*)
+ fragment <<EOF
+ if (gld${EMULATION_NAME}_check_ld_elf_hints (l->name, force))
+ break;
+EOF
+ # FreeBSD
+ ;;
+
+ *-*-linux-* | *-*-k*bsd*-*)
+ # Linux
+ fragment <<EOF
+ if (gld${EMULATION_NAME}_check_ld_so_conf (l->name, force))
+ break;
+
+EOF
+ ;;
+ esac
+fi
+fragment <<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);
+ nn.name = filename;
+ if (gld${EMULATION_NAME}_try_needed (&nn, force))
+ break;
+ free (filename);
+ }
+ if (search != NULL)
+ break;
+EOF
+fragment <<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
+
+fragment <<EOF
+
+/* Look through an expression for an assignment statement. */
+
+static void
+gld${EMULATION_NAME}_find_exp_assignment (etree_type *exp)
+{
+ bfd_boolean provide = FALSE;
+
+ switch (exp->type.node_class)
+ {
+ case etree_provide:
+ provide = TRUE;
+ /* Fall thru */
+ case etree_assign:
+ /* 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. */
+ if (strcmp (exp->assign.dst, ".") != 0)
+ {
+ if (!bfd_elf_record_link_assignment (link_info.output_bfd,
+ &link_info,
+ exp->assign.dst, provide,
+ exp->assign.hidden))
+ 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 = (unsigned char *) ${ELF_INTERPRETER_NAME};
+ sinterp->size = strlen ((char *) sinterp->contents) + 1;
+ }
+
+"
+ else
+ ELF_INTERPRETER_SET_DEFAULT=
+ fi
+fragment <<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 (link_info.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
+ (link_info.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->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;
+ char *msg;
+ bfd_boolean ret;
+
+ if (is->just_syms_flag)
+ continue;
+
+ s = bfd_get_section_by_name (is->the_bfd, ".gnu.warning");
+ if (s == NULL)
+ continue;
+
+ sz = s->size;
+ msg = (char *) xmalloc ((size_t) (sz + 1));
+ if (! bfd_get_section_contents (is->the_bfd, s, msg,
+ (file_ptr) 0, sz))
+ einfo ("%F%B: Can't read contents of section .gnu.warning: %E\n",
+ is->the_bfd);
+ msg[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 space
+ copying the warning into the output file. If we've already
+ sized the output section, adjust its size. The adjustment
+ is on rawsize because targets that size sections early will
+ have called lang_reset_memory_regions after sizing. */
+ if (s->output_section != NULL
+ && s->output_section->rawsize >= s->size)
+ s->output_section->rawsize -= s->size;
+
+ s->size = 0;
+
+ /* Also set SEC_EXCLUDE, so that local symbols defined in the
+ warning section don't get copied to the output. */
+ s->flags |= SEC_EXCLUDE | SEC_KEEP;
+ }
+ }
+
+ before_allocation_default ();
+
+ if (!bfd_elf_size_dynsym_hash_dynstr (link_info.output_bfd, &link_info))
+ einfo ("%P%F: failed to set dynamic section sizes: %E\n");
+}
+
+EOF
+fi
+
+if test x"$LDEMUL_OPEN_DYNAMIC_ARCHIVE" != xgld"$EMULATION_NAME"_open_dynamic_archive; then
+fragment <<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;
+ }
+#ifdef EXTRA_SHLIB_EXTENSION
+ }
+#endif
+
+ 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
+fragment <<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_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_ro_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 (lookup = &lang_output_section_statement.head->output_section_statement;
+ lookup != NULL;
+ lookup = lookup->next)
+ {
+ if (lookup->constraint >= 0
+ && CONST_STRNEQ (lookup->name, ".rel"))
+ {
+ 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 ((lookup->bfd_section->flags & SEC_READONLY) != 0)
+ last_ro_alloc = lookup;
+ }
+ }
+
+ if (last_rel_alloc)
+ return last_rel_alloc;
+
+ if (last_rel)
+ return last_rel;
+
+ if (last_ro_alloc)
+ return last_ro_alloc;
+
+ if (last_alloc)
+ return last_alloc;
+
+ return last;
+}
+
+/* Place an orphan section. We use this to put random SHF_ALLOC
+ sections in the right segment. */
+
+static lang_output_section_statement_type *
+gld${EMULATION_NAME}_place_orphan (asection *s,
+ const char *secname,
+ int constraint)
+{
+ static struct orphan_save hold[] =
+ {
+ { ".text",
+ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE,
+ 0, 0, 0, 0 },
+ { ".rodata",
+ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
+ 0, 0, 0, 0 },
+ { ".data",
+ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA,
+ 0, 0, 0, 0 },
+ { ".bss",
+ SEC_ALLOC,
+ 0, 0, 0, 0 },
+ { 0,
+ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
+ 0, 0, 0, 0 },
+ { ".interp",
+ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
+ 0, 0, 0, 0 },
+ { ".sdata",
+ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_SMALL_DATA,
+ 0, 0, 0, 0 },
+ { 0,
+ SEC_HAS_CONTENTS,
+ 0, 0, 0, 0 },
+ };
+ enum orphan_save_index
+ {
+ orphan_text = 0,
+ orphan_rodata,
+ orphan_data,
+ orphan_bss,
+ orphan_rel,
+ orphan_interp,
+ orphan_sdata,
+ orphan_nonalloc
+ };
+ static int orphan_init_done = 0;
+ struct orphan_save *place;
+ lang_output_section_statement_type *after;
+ lang_output_section_statement_type *os;
+ int isdyn = 0;
+ int iself = s->owner->xvec->flavour == bfd_target_elf_flavour;
+ unsigned int sh_type = iself ? elf_section_type (s) : SHT_NULL;
+
+ if (! link_info.relocatable
+ && link_info.combreloc
+ && (s->flags & SEC_ALLOC))
+ {
+ if (iself)
+ switch (sh_type)
+ {
+ case SHT_RELA:
+ secname = ".rela.dyn";
+ isdyn = 1;
+ break;
+ case SHT_REL:
+ secname = ".rel.dyn";
+ isdyn = 1;
+ break;
+ default:
+ break;
+ }
+ else if (CONST_STRNEQ (secname, ".rel"))
+ {
+ secname = secname[4] == 'a' ? ".rela.dyn" : ".rel.dyn";
+ isdyn = 1;
+ }
+ }
+
+ /* Look through the script to see where to place this section. */
+ if (constraint == 0)
+ for (os = lang_output_section_find (secname);
+ os != NULL;
+ os = next_matching_output_section_statement (os, 0))
+ {
+ /* If we don't match an existing output section, tell
+ lang_insert_orphan to create a new output section. */
+ constraint = SPECIAL;
+
+ if (os->bfd_section != NULL
+ && (os->bfd_section->flags == 0
+ || (_bfd_elf_match_sections_by_type (link_info.output_bfd,
+ os->bfd_section,
+ s->owner, s)
+ && ((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 has compatible flags.
+ If the section already exists but does not have any flags
+ set, then it has been created by the linker, probably as a
+ result of a --section-start command line switch. */
+ lang_add_section (&os->children, s, os);
+ return os;
+ }
+ }
+
+ if (!orphan_init_done)
+ {
+ lang_output_section_statement_type *lookup;
+ struct orphan_save *ho;
+
+ for (ho = hold; ho < hold + sizeof (hold) / sizeof (hold[0]); ++ho)
+ if (ho->name != NULL)
+ {
+ ho->os = lang_output_section_find (ho->name);
+ if (ho->os != NULL && ho->os->flags == 0)
+ ho->os->flags = ho->flags;
+ }
+ lookup = hold[orphan_bss].os;
+ if (lookup == NULL)
+ lookup = &lang_output_section_statement.head->output_section_statement;
+ for (; lookup != NULL; lookup = lookup->next)
+ if ((lookup->bfd_section != NULL
+ && (lookup->bfd_section->flags & SEC_DEBUGGING) != 0)
+ || strcmp (lookup->name, ".comment") == 0)
+ break;
+ hold[orphan_nonalloc].os = lookup ? lookup->prev : NULL;
+ hold[orphan_nonalloc].name = ".comment";
+ orphan_init_done = 1;
+ }
+
+ /* 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
+ && CONST_STRNEQ (s->name, ".gnu.warning.")
+ && hold[orphan_text].os != NULL)
+ {
+ os = hold[orphan_text].os;
+ lang_add_section (&os->children, s, os);
+ return os;
+ }
+
+ /* 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. */
+
+ place = NULL;
+ if ((s->flags & (SEC_ALLOC | SEC_DEBUGGING)) == 0)
+ place = &hold[orphan_nonalloc];
+ else if ((s->flags & SEC_ALLOC) == 0)
+ ;
+ else if ((s->flags & SEC_LOAD) != 0
+ && ((iself && sh_type == SHT_NOTE)
+ || (!iself && CONST_STRNEQ (secname, ".note"))))
+ place = &hold[orphan_interp];
+ else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
+ place = &hold[orphan_bss];
+ else if ((s->flags & SEC_SMALL_DATA) != 0)
+ place = &hold[orphan_sdata];
+ else if ((s->flags & SEC_READONLY) == 0)
+ place = &hold[orphan_data];
+ else if (((iself && (sh_type == SHT_RELA || sh_type == SHT_REL))
+ || (!iself && CONST_STRNEQ (secname, ".rel")))
+ && (s->flags & SEC_LOAD) != 0)
+ place = &hold[orphan_rel];
+ else if ((s->flags & SEC_CODE) == 0)
+ place = &hold[orphan_rodata];
+ else
+ place = &hold[orphan_text];
+
+ after = NULL;
+ if (place != NULL)
+ {
+ if (place->os == NULL)
+ {
+ if (place->name != NULL)
+ place->os = lang_output_section_find (place->name);
+ else
+ place->os = output_rel_find (s, isdyn);
+ }
+ after = place->os;
+ if (after == NULL)
+ after = lang_output_section_find_by_flags
+ (s, &place->os, _bfd_elf_match_sections_by_type);
+ if (after == NULL)
+ /* *ABS* is always the first output section statement. */
+ after = &lang_output_section_statement.head->output_section_statement;
+ }
+
+ return lang_insert_orphan (s, secname, constraint, after, place, NULL, NULL);
+}
+EOF
+fi
+
+if test x"$LDEMUL_AFTER_ALLOCATION" != xgld"$EMULATION_NAME"_after_allocation; then
+fragment <<EOF
+
+static void
+gld${EMULATION_NAME}_after_allocation (void)
+{
+ bfd_boolean need_layout = bfd_elf_discard_info (link_info.output_bfd,
+ &link_info);
+ gld${EMULATION_NAME}_map_segments (need_layout);
+}
+EOF
+fi
+
+if test x"$LDEMUL_GET_SCRIPT" != xgld"$EMULATION_NAME"_get_script; then
+fragment <<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"
+
+fragment <<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' >> e${EMULATION_NAME}.c
+echo ' && link_info.relro' >> e${EMULATION_NAME}.c
+echo ' && (link_info.flags & DF_BIND_NOW)) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xdw >> e${EMULATION_NAME}.c
+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' >> e${EMULATION_NAME}.c
+echo ' && link_info.relro' >> e${EMULATION_NAME}.c
+echo ' && (link_info.flags & DF_BIND_NOW)) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xsw >> e${EMULATION_NAME}.c
+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 && link_info.relro' >> e${EMULATION_NAME}.c
+echo ' && (link_info.flags & DF_BIND_NOW)) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xw >> e${EMULATION_NAME}.c
+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.
+
+fragment <<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
+fragment <<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
+fragment <<EOF
+ else if (link_info.pie && link_info.combreloc
+ && link_info.relro && (link_info.flags & DF_BIND_NOW))
+ return "ldscripts/${EMULATION_NAME}.xdw";
+ else if (link_info.pie && link_info.combreloc)
+ return "ldscripts/${EMULATION_NAME}.xdc";
+EOF
+fi
+fragment <<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
+fragment <<EOF
+ else if (link_info.shared && link_info.combreloc
+ && link_info.relro && (link_info.flags & DF_BIND_NOW))
+ return "ldscripts/${EMULATION_NAME}.xsw";
+ else if (link_info.shared && link_info.combreloc)
+ return "ldscripts/${EMULATION_NAME}.xsc";
+EOF
+fi
+fragment <<EOF
+ else if (link_info.shared)
+ return "ldscripts/${EMULATION_NAME}.xs";
+EOF
+fi
+if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
+fragment <<EOF
+ else if (link_info.combreloc && link_info.relro
+ && (link_info.flags & DF_BIND_NOW))
+ return "ldscripts/${EMULATION_NAME}.xw";
+ else if (link_info.combreloc)
+ return "ldscripts/${EMULATION_NAME}.xc";
+EOF
+fi
+fragment <<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
+fragment <<EOF
+ $PARSE_AND_LIST_PROLOGUE
+EOF
+fi
+
+fragment <<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)
+#define OPTION_EXCLUDE_LIBS (OPTION_EH_FRAME_HDR + 1)
+#define OPTION_HASH_STYLE (OPTION_EXCLUDE_LIBS + 1)
+#define OPTION_BUILD_ID (OPTION_HASH_STYLE + 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[] = {
+ {"build-id", optional_argument, NULL, OPTION_BUILD_ID},
+EOF
+
+if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
+fragment <<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},
+ {"exclude-libs", required_argument, NULL, OPTION_EXCLUDE_LIBS},
+ {"hash-style", required_argument, NULL, OPTION_HASH_STYLE},
+ {"Bgroup", no_argument, NULL, OPTION_GROUP},
+EOF
+fi
+
+if test -n "$PARSE_AND_LIST_LONGOPTS" ; then
+fragment <<EOF
+ $PARSE_AND_LIST_LONGOPTS
+EOF
+fi
+
+fragment <<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));
+}
+
+#define DEFAULT_BUILD_ID_STYLE "sha1"
+
+static bfd_boolean
+gld${EMULATION_NAME}_handle_option (int optc)
+{
+ switch (optc)
+ {
+ default:
+ return FALSE;
+
+ case OPTION_BUILD_ID:
+ if (link_info.emit_note_gnu_build_id != NULL)
+ {
+ free (link_info.emit_note_gnu_build_id);
+ link_info.emit_note_gnu_build_id = NULL;
+ }
+ if (optarg == NULL)
+ optarg = DEFAULT_BUILD_ID_STYLE;
+ if (strcmp (optarg, "none"))
+ link_info.emit_note_gnu_build_id = xstrdup (optarg);
+ break;
+
+EOF
+
+if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
+fragment <<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 OPTION_EXCLUDE_LIBS:
+ add_excluded_libs (optarg);
+ break;
+
+ case OPTION_HASH_STYLE:
+ link_info.emit_hash = FALSE;
+ link_info.emit_gnu_hash = FALSE;
+ if (strcmp (optarg, "sysv") == 0)
+ link_info.emit_hash = TRUE;
+ else if (strcmp (optarg, "gnu") == 0)
+ link_info.emit_gnu_hash = TRUE;
+ else if (strcmp (optarg, "both") == 0)
+ {
+ link_info.emit_hash = TRUE;
+ link_info.emit_gnu_hash = TRUE;
+ }
+ else
+ einfo (_("%P%F: invalid hash style \`%s'\n"), optarg);
+ 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, "lazy") == 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;
+ }
+EOF
+
+ if test -n "$COMMONPAGESIZE"; then
+fragment <<EOF
+ else if (strcmp (optarg, "relro") == 0)
+ link_info.relro = TRUE;
+ else if (strcmp (optarg, "norelro") == 0)
+ link_info.relro = FALSE;
+EOF
+ fi
+
+fragment <<EOF
+ else if (CONST_STRNEQ (optarg, "max-page-size="))
+ {
+ char *end;
+
+ config.maxpagesize = strtoul (optarg + 14, &end, 0);
+ if (*end || (config.maxpagesize & (config.maxpagesize - 1)) != 0)
+ einfo (_("%P%F: invalid maxium page size \`%s'\n"),
+ optarg + 14);
+ }
+ else if (CONST_STRNEQ (optarg, "common-page-size="))
+ {
+ char *end;
+ config.commonpagesize = strtoul (optarg + 17, &end, 0);
+ if (*end
+ || (config.commonpagesize & (config.commonpagesize - 1)) != 0)
+ einfo (_("%P%F: invalid common page size \`%s'\n"),
+ optarg + 17);
+ }
+ /* What about the other Solaris -z options? FIXME. */
+ break;
+EOF
+fi
+
+if test -n "$PARSE_AND_LIST_ARGS_CASES" ; then
+fragment <<EOF
+ $PARSE_AND_LIST_ARGS_CASES
+EOF
+fi
+
+fragment <<EOF
+ }
+
+ return TRUE;
+}
+
+EOF
+
+if test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
+fragment <<EOF
+
+static void
+gld${EMULATION_NAME}_list_options (FILE * file)
+{
+ fprintf (file, _("\
+ --build-id[=STYLE] Generate build ID note\n"));
+EOF
+
+if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
+fragment <<EOF
+ fprintf (file, _("\
+ -Bgroup Selects group name lookup rules for DSO\n"));
+ fprintf (file, _("\
+ --disable-new-dtags Disable new dynamic tags\n"));
+ fprintf (file, _("\
+ --enable-new-dtags Enable new dynamic tags\n"));
+ fprintf (file, _("\
+ --eh-frame-hdr Create .eh_frame_hdr section\n"));
+ fprintf (file, _("\
+ --hash-style=STYLE Set hash style to sysv, gnu or both\n"));
+ fprintf (file, _("\
+ -z combreloc Merge dynamic relocs into one section and sort\n"));
+ fprintf (file, _("\
+ -z defs Report unresolved symbols in object files.\n"));
+ fprintf (file, _("\
+ -z execstack Mark executable as requiring executable stack\n"));
+ fprintf (file, _("\
+ -z initfirst Mark DSO to be initialized first at runtime\n"));
+ fprintf (file, _("\
+ -z interpose Mark object to interpose all DSOs but executable\n"));
+ fprintf (file, _("\
+ -z lazy Mark object lazy runtime binding (default)\n"));
+ fprintf (file, _("\
+ -z loadfltr Mark object requiring immediate process\n"));
+ fprintf (file, _("\
+ -z muldefs Allow multiple definitions\n"));
+ fprintf (file, _("\
+ -z nocombreloc Don't merge dynamic relocs into one section\n"));
+ fprintf (file, _("\
+ -z nocopyreloc Don't create copy relocs\n"));
+ fprintf (file, _("\
+ -z nodefaultlib Mark object not to use default search paths\n"));
+ fprintf (file, _("\
+ -z nodelete Mark DSO non-deletable at runtime\n"));
+ fprintf (file, _("\
+ -z nodlopen Mark DSO not available to dlopen\n"));
+ fprintf (file, _("\
+ -z nodump Mark DSO not available to dldump\n"));
+ fprintf (file, _("\
+ -z noexecstack Mark executable as not requiring executable stack\n"));
+EOF
+
+ if test -n "$COMMONPAGESIZE"; then
+fragment <<EOF
+ fprintf (file, _("\
+ -z norelro Don't create RELRO program header\n"));
+EOF
+ fi
+
+fragment <<EOF
+ fprintf (file, _("\
+ -z now Mark object non-lazy runtime binding\n"));
+ fprintf (file, _("\
+ -z origin Mark object requiring immediate \$ORIGIN\n\
+ processing at runtime\n"));
+EOF
+
+ if test -n "$COMMONPAGESIZE"; then
+fragment <<EOF
+ fprintf (file, _("\
+ -z relro Create RELRO program header\n"));
+EOF
+ fi
+
+fragment <<EOF
+ fprintf (file, _("\
+ -z max-page-size=SIZE Set maximum page size to SIZE\n"));
+ fprintf (file, _("\
+ -z common-page-size=SIZE Set common page size to SIZE\n"));
+ fprintf (file, _("\
+ -z KEYWORD Ignored for Solaris compatibility\n"));
+EOF
+fi
+
+if test -n "$PARSE_AND_LIST_OPTIONS" ; then
+fragment <<EOF
+ $PARSE_AND_LIST_OPTIONS
+EOF
+fi
+
+fragment <<EOF
+}
+EOF
+
+if test -n "$PARSE_AND_LIST_EPILOGUE" ; then
+fragment <<EOF
+ $PARSE_AND_LIST_EPILOGUE
+EOF
+fi
+fi
+else
+fragment <<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
+fragment <<EOF
+#define gld${EMULATION_NAME}_list_options NULL
+EOF
+fi
+fi
+
+fragment <<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-gld${EMULATION_NAME}_after_allocation},
+ ${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-finish_default},
+ ${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/binutils-2.20.1/ld/emultempl/genelf.em b/binutils-2.20.1/ld/emultempl/genelf.em
new file mode 100644
index 00000000..1a6c539b
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/genelf.em
@@ -0,0 +1,59 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+# This file is sourced from generic.em
+#
+fragment <<EOF
+#include "elf-bfd.h"
+
+EOF
+source_em ${srcdir}/emultempl/elf-generic.em
+fragment <<EOF
+
+static void
+gld${EMULATION_NAME}_after_open (void)
+{
+ bfd *ibfd;
+ asection *sec;
+ asymbol **syms;
+
+ if (link_info.relocatable)
+ for (ibfd = link_info.input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+ if ((syms = bfd_get_outsymbols (ibfd)) != NULL
+ && bfd_get_flavour (ibfd) == bfd_target_elf_flavour)
+ for (sec = ibfd->sections; sec != NULL; sec = sec->next)
+ if ((sec->flags & (SEC_GROUP | SEC_LINKER_CREATED)) == SEC_GROUP)
+ {
+ struct bfd_elf_section_data *sec_data = elf_section_data (sec);
+ elf_group_id (sec) = syms[sec_data->this_hdr.sh_info - 1];
+ }
+}
+
+static void
+gld${EMULATION_NAME}_after_allocation (void)
+{
+ gld${EMULATION_NAME}_map_segments (FALSE);
+}
+EOF
+# Put these extra routines in ld_${EMULATION_NAME}_emulation
+#
+LDEMUL_AFTER_OPEN=gld${EMULATION_NAME}_after_open
+LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation
diff --git a/binutils-2.20.1/ld/emultempl/generic.em b/binutils-2.20.1/ld/emultempl/generic.em
new file mode 100644
index 00000000..4a846802
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/generic.em
@@ -0,0 +1,149 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+fragment <<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, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+ 2007 Free Software Foundation, Inc.
+ Written by Steve Chamberlain steve@cygnus.com
+
+ This file is part of the GNU Binutils.
+
+ 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include "sysdep.h"
+#include "bfd.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
+ source_em ${srcdir}/emultempl/${EXTRA_EM_FILE}.em
+fi
+
+if test x"$LDEMUL_BEFORE_PARSE" != xgld"$EMULATION_NAME"_before_parse; then
+fragment <<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
+fragment <<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"
+
+fragment <<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.
+
+fragment <<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
+
+fragment <<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-finish_default},
+ ${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/binutils-2.20.1/ld/emultempl/gld960.em b/binutils-2.20.1/ld/emultempl/gld960.em
new file mode 100644
index 00000000..4ba3eeca
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/gld960.em
@@ -0,0 +1,154 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+fragment <<EOF
+/* Copyright 1991, 1992, 1994, 1999, 2000, 2001, 2002, 2003, 2005, 2007, 2008
+ Free Software Foundation, Inc.
+
+ This file is part of the GNU Binutils.
+
+ 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+
+/* Emulate the Intel's port of gld. */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libiberty.h"
+#include "bfdlink.h"
+
+#include "ld.h"
+#include "ldmisc.h"
+#include "ldmain.h"
+
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldfile.h"
+#include "ldemul.h"
+
+static void gld960_before_parse (void)
+{
+ char *env ;
+ env = getenv("G960LIB");
+ if (env) {
+ ldfile_add_library_path(env, FALSE);
+ }
+ env = getenv("G960BASE");
+ if (env)
+ ldfile_add_library_path (concat (env, "/lib", (const char *) NULL), FALSE);
+ ldfile_output_architecture = bfd_arch_i960;
+}
+
+static void
+gld960_set_output_arch (void)
+{
+ bfd_set_arch_mach (link_info.output_bfd,
+ ldfile_output_architecture, bfd_mach_i960_core);
+}
+
+static char *
+gld960_choose_target (int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
+{
+ char *from_outside = getenv(TARGET_ENVIRON);
+ output_filename = "b.out";
+
+ if (from_outside != (char *)NULL)
+ return from_outside;
+
+ return "b.out.little";
+}
+
+static char *
+gld960_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"
+
+fragment <<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.
+
+fragment <<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
+
+fragment <<EOF
+
+struct ld_emulation_xfer_struct ld_gld960_emulation =
+{
+ gld960_before_parse,
+ syslib_default,
+ hll_default,
+ after_parse_default,
+ after_open_default,
+ after_allocation_default,
+ gld960_set_output_arch,
+ gld960_choose_target,
+ before_allocation_default,
+ gld960_get_script,
+ "960",
+ "",
+ finish_default,
+ 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/binutils-2.20.1/ld/emultempl/gld960c.em b/binutils-2.20.1/ld/emultempl/gld960c.em
new file mode 100644
index 00000000..1999ea89
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/gld960c.em
@@ -0,0 +1,167 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+fragment <<EOF
+/* Copyright 1991, 1993, 1994, 1996, 1999, 2000, 2001, 2002, 2003, 2004,
+ 2005, 2007 Free Software Foundation, Inc.
+
+ This file is part of the GNU Binutils.
+
+ 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+
+/* Emulate the Intel's port of gld. */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libiberty.h"
+#include "safe-ctype.h"
+#include "bfdlink.h"
+
+#include "ld.h"
+#include "ldmisc.h"
+#include "ldmain.h"
+
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldfile.h"
+#include "ldemul.h"
+
+static void gld960_before_parse (void)
+{
+ char *env ;
+ env = getenv("G960LIB");
+ if (env) {
+ ldfile_add_library_path(env, FALSE);
+ }
+ env = getenv("G960BASE");
+ if (env)
+ ldfile_add_library_path (concat (env, "/lib", (const char *) NULL),
+ FALSE);
+ ldfile_output_architecture = bfd_arch_i960;
+}
+
+static void
+gld960_set_output_arch (void)
+{
+ if (ldfile_output_machine_name != NULL
+ && *ldfile_output_machine_name != '\0')
+ {
+ char *s, *s1;
+
+ s = concat ("i960:", ldfile_output_machine_name, (char *) NULL);
+ for (s1 = s; *s1 != '\0'; s1++)
+ *s1 = TOLOWER (*s1);
+ ldfile_set_output_arch (s, bfd_arch_unknown);
+ free (s);
+ }
+
+ set_output_arch_default ();
+}
+
+static char *
+gld960_choose_target (int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
+{
+ char *from_outside = getenv(TARGET_ENVIRON);
+ output_filename = "b.out";
+
+ if (from_outside != (char *)NULL)
+ return from_outside;
+
+ return "coff-Intel-little";
+}
+
+static char *
+gld960_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"
+
+fragment <<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.
+
+fragment <<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
+
+fragment <<EOF
+
+struct ld_emulation_xfer_struct ld_gld960coff_emulation =
+{
+ gld960_before_parse,
+ syslib_default,
+ hll_default,
+ after_parse_default,
+ after_open_default,
+ after_allocation_default,
+ gld960_set_output_arch,
+ gld960_choose_target,
+ before_allocation_default,
+ gld960_get_script,
+ "960coff",
+ "",
+ finish_default,
+ 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/binutils-2.20.1/ld/emultempl/hppaelf.em b/binutils-2.20.1/ld/emultempl/hppaelf.em
new file mode 100644
index 00000000..3ce5d54a
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/hppaelf.em
@@ -0,0 +1,379 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 1991, 1993, 1994, 1997, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+# This file is sourced from elf32.em, and defines extra hppa-elf
+# specific routines.
+#
+fragment <<EOF
+
+#include "ldctor.h"
+#include "elf32-hppa.h"
+
+
+/* Fake input file for stubs. */
+static lang_input_statement_type *stub_file;
+
+/* Type of import/export stubs to build. For a single sub-space model,
+ we can build smaller import stubs and there is no need for export
+ stubs. */
+static int multi_subspace = 0;
+
+/* Whether we need to call hppa_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;
+
+/* Stops the linker merging .text sections on a relocatable link,
+ and adds millicode library to the list of input files. */
+
+static void
+hppaelf_after_parse (void)
+{
+ if (link_info.relocatable)
+ lang_add_unique (".text");
+
+ /* Enable this once we split millicode stuff from libgcc:
+ lang_add_input_file ("milli",
+ lang_input_file_is_l_enum,
+ NULL);
+ */
+
+ after_parse_default ();
+}
+
+/* This is called before the input files are opened. We create a new
+ fake input file to hold the stub sections. */
+
+static void
+hppaelf_create_output_section_statements (void)
+{
+ if (!(bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour
+ && elf_object_id (link_info.output_bfd) == HPPA_ELF_TDATA))
+ return;
+
+ stub_file = lang_add_input_file ("linker stubs",
+ lang_input_file_is_fake_enum,
+ NULL);
+ stub_file->the_bfd = bfd_create ("linker stubs", link_info.output_bfd);
+ if (stub_file->the_bfd == NULL
+ || ! bfd_set_arch_mach (stub_file->the_bfd,
+ bfd_get_arch (link_info.output_bfd),
+ bfd_get_mach (link_info.output_bfd)))
+ {
+ einfo ("%X%P: can not create BFD %E\n");
+ return;
+ }
+
+ stub_file->the_bfd->flags |= BFD_LINKER_CREATED;
+ ldlang_add_file (stub_file);
+}
+
+
+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 elf32_hppa_size_stubs. */
+
+/* Create a new stub section, and arrange for it to be linked
+ immediately before INPUT_SECTION. */
+
+static asection *
+hppaelf_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;
+
+ flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
+ | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP);
+ stub_sec = bfd_make_section_anyway_with_flags (stub_file->the_bfd,
+ stub_sec_name, flags);
+ if (stub_sec == NULL)
+ 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);
+
+ if (info.add.head == NULL)
+ goto err_ret;
+
+ 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 elf32_hppa_size_stubs. */
+
+static void
+hppaelf_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. */
+ gld${EMULATION_NAME}_map_segments (TRUE);
+ need_laying_out = -1;
+}
+
+
+static void
+build_section_lists (lang_statement_union_type *statement)
+{
+ if (statement->header.type == lang_input_section_enum)
+ {
+ asection *i = statement->input_section.section;
+
+ if (!((lang_input_statement_type *) i->owner->usrdata)->just_syms_flag
+ && (i->flags & SEC_EXCLUDE) == 0
+ && i->output_section != NULL
+ && i->output_section->owner == link_info.output_bfd)
+ {
+ elf32_hppa_next_input_section (&link_info, i);
+ }
+ }
+}
+
+
+/* For the PA we use this opportunity to size and build linker stubs. */
+
+static void
+gld${EMULATION_NAME}_after_allocation (void)
+{
+ /* bfd_elf_discard_info just plays with data and debugging sections,
+ ie. doesn't affect code size, 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 (link_info.output_bfd, &link_info))
+ need_laying_out = 1;
+
+ /* If generating a relocatable output file, then we don't
+ have to examine the relocs. */
+ if (stub_file != NULL && !link_info.relocatable)
+ {
+ int ret = elf32_hppa_setup_section_lists (link_info.output_bfd,
+ &link_info);
+
+ if (ret != 0)
+ {
+ if (ret < 0)
+ {
+ einfo ("%X%P: can not size stub section: %E\n");
+ return;
+ }
+
+ lang_for_each_statement (build_section_lists);
+
+ /* Call into the BFD backend to do the real work. */
+ if (! elf32_hppa_size_stubs (link_info.output_bfd,
+ stub_file->the_bfd,
+ &link_info,
+ multi_subspace,
+ group_size,
+ &hppaelf_add_stub_section,
+ &hppaelf_layout_sections_again))
+ {
+ einfo ("%X%P: can not size stub section: %E\n");
+ return;
+ }
+ }
+ }
+
+ if (need_laying_out != -1)
+ gld${EMULATION_NAME}_map_segments (need_laying_out);
+
+ if (! link_info.relocatable)
+ {
+ /* Set the global data pointer. */
+ if (! elf32_hppa_set_gp (link_info.output_bfd, &link_info))
+ {
+ einfo ("%X%P: can not set gp\n");
+ return;
+ }
+
+ /* Now build the linker stubs. */
+ if (stub_file != NULL && stub_file->the_bfd->sections != NULL)
+ {
+ if (! elf32_hppa_build_stubs (&link_info))
+ einfo ("%X%P: can not build stubs: %E\n");
+ }
+ }
+}
+
+
+/* Avoid processing the fake stub_file in vercheck, stat_needed and
+ check_needed routines. */
+
+static void (*real_func) (lang_input_statement_type *);
+
+static void hppa_for_each_input_file_wrapper (lang_input_statement_type *l)
+{
+ if (l != stub_file)
+ (*real_func) (l);
+}
+
+static void
+hppa_lang_for_each_input_file (void (*func) (lang_input_statement_type *))
+{
+ real_func = func;
+ lang_for_each_input_file (&hppa_for_each_input_file_wrapper);
+}
+
+#define lang_for_each_input_file hppa_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_MULTI_SUBSPACE 301
+#define OPTION_STUBGROUP_SIZE (OPTION_MULTI_SUBSPACE + 1)
+'
+
+PARSE_AND_LIST_LONGOPTS='
+ { "multi-subspace", no_argument, NULL, OPTION_MULTI_SUBSPACE },
+ { "stub-group-size", required_argument, NULL, OPTION_STUBGROUP_SIZE },
+'
+
+PARSE_AND_LIST_OPTIONS='
+ fprintf (file, _("\
+ --multi-subspace Generate import and export stubs to support\n\
+ multiple sub-space shared libraries\n"
+ ));
+ fprintf (file, _("\
+ --stub-group-size=N Maximum size of a group of input sections that\n\
+ can be handled by one stub section. A negative\n\
+ value locates all stubs before their branches\n\
+ (with a group size of -N), while a positive\n\
+ value allows two groups of input sections, one\n\
+ before, and one after each stub section.\n\
+ Values of +/-1 indicate the linker should\n\
+ choose suitable defaults.\n"
+ ));
+'
+
+PARSE_AND_LIST_ARGS_CASES='
+ case OPTION_MULTI_SUBSPACE:
+ multi_subspace = 1;
+ break;
+
+ 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;
+'
+
+# Put these extra hppaelf routines in ld_${EMULATION_NAME}_emulation
+#
+LDEMUL_AFTER_PARSE=hppaelf_after_parse
+LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation
+LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=hppaelf_create_output_section_statements
diff --git a/binutils-2.20.1/ld/emultempl/ia64elf.em b/binutils-2.20.1/ld/emultempl/ia64elf.em
new file mode 100644
index 00000000..88d57480
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/ia64elf.em
@@ -0,0 +1,65 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2003, 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, 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.
+#
+fragment <<EOF
+
+/* None zero if generating binary for Intel Itanium processor. */
+static int itanium = 0;
+
+static void
+gld${EMULATION_NAME}_after_parse (void)
+{
+ link_info.relax_pass = 2;
+ bfd_elf${ELFSIZE}_ia64_after_parse (itanium);
+
+ after_parse_default ();
+}
+
+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
+source_em ${srcdir}/emultempl/needrelax.em
diff --git a/binutils-2.20.1/ld/emultempl/irix.em b/binutils-2.20.1/ld/emultempl/irix.em
new file mode 100644
index 00000000..41b8ce42
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/irix.em
@@ -0,0 +1,44 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+fragment <<EOF
+
+#include "ld.h"
+#include "ldmain.h"
+#include "libiberty.h"
+
+/* The native IRIX linker will always create a DT_SONAME for shared objects.
+ While this shouldn't really be necessary for ABI conformance, some versions
+ of the native linker will segfault if the tag is missing. */
+
+static void
+irix_after_open (void)
+{
+ if (link_info.shared && command_line.soname == 0)
+ command_line.soname
+ = (char *) lbasename (bfd_get_filename (link_info.output_bfd));
+
+ gld${EMULATION_NAME}_after_open ();
+}
+EOF
+
+LDEMUL_AFTER_OPEN=irix_after_open
+source_em "${srcdir}/emultempl/mipself.em"
diff --git a/binutils-2.20.1/ld/emultempl/linux.em b/binutils-2.20.1/ld/emultempl/linux.em
new file mode 100644
index 00000000..2a2a960a
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/linux.em
@@ -0,0 +1,211 @@
+# 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
+fragment <<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, 2001, 2002,
+ 2003, 2004, 2005, 2007, 2008 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 the GNU Binutils.
+
+ 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include "sysdep.h"
+#include "bfd.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 (link_info.output_bfd,
+ &link_info))
+ einfo ("%P%F: failed to set dynamic section sizes: %E\n");
+
+ before_allocation_default ();
+}
+
+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"
+
+fragment <<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.
+
+fragment <<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
+
+fragment <<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}",
+ finish_default,
+ 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/binutils-2.20.1/ld/emultempl/lnk960.em b/binutils-2.20.1/ld/emultempl/lnk960.em
new file mode 100644
index 00000000..e13233c7
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/lnk960.em
@@ -0,0 +1,290 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+fragment <<EOF
+/* intel coff loader emulation specific stuff
+ Copyright 1991, 1992, 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2003,
+ 2005, 2007, 2008 Free Software Foundation, Inc.
+ Written by Steve Chamberlain steve@cygnus.com
+
+ This file is part of the GNU Binutils.
+
+ 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "sysdep.h"
+#include "libiberty.h"
+#include "bfd.h"
+#include "bfdlink.h"
+
+/*#include "archures.h"*/
+#include "ld.h"
+#include "ldmain.h"
+#include "ldmisc.h"
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldfile.h"
+#include "ldemul.h"
+
+typedef struct lib_list {
+ char *name;
+ struct lib_list *next;
+} lib_list_type;
+
+static lib_list_type *hll_list;
+static lib_list_type **hll_list_tail = &hll_list;
+
+static lib_list_type *syslib_list;
+static lib_list_type **syslib_list_tail = &syslib_list;
+
+
+static void
+append (lib_list_type ***list, char *name)
+{
+ lib_list_type *element = (lib_list_type *) xmalloc (sizeof (lib_list_type));
+
+ element->name = name;
+ element->next = (lib_list_type *) NULL;
+ **list = element;
+ *list = &element->next;
+
+}
+
+static bfd_boolean had_hll = FALSE;
+static bfd_boolean had_hll_name = FALSE;
+
+static void
+lnk960_hll (char *name)
+{
+ had_hll = TRUE;
+ if (name != (char *) NULL)
+ {
+ had_hll_name = TRUE;
+ append (&hll_list_tail, name);
+ }
+}
+
+static void
+lnk960_syslib (char *name)
+{
+ append (&syslib_list_tail, name);
+}
+
+
+static void
+lnk960_before_parse (void)
+{
+ char *name = getenv ("I960BASE");
+
+ if (name == (char *) NULL)
+ {
+ name = getenv("G960BASE");
+ if (name == (char *) NULL)
+ einfo ("%P%F I960BASE and G960BASE not set\n");
+ }
+
+ ldfile_add_library_path (concat (name, "/lib", (const char *) NULL), FALSE);
+ ldfile_output_architecture = bfd_arch_i960;
+ ldfile_output_machine = bfd_mach_i960_core;
+}
+
+static void
+add_on (lib_list_type *list, lang_input_file_enum_type search)
+{
+ while (list)
+ {
+ lang_add_input_file (list->name, search, (char *) NULL);
+ list = list->next;
+ }
+}
+
+static void
+lnk960_after_parse (void)
+{
+ /* If there has been no arch, default to -KB */
+ if (ldfile_output_machine_name[0] == 0)
+ ldfile_add_arch ("KB");
+
+ /* if there has been no hll list then add our own */
+
+ if (had_hll && !had_hll_name)
+ {
+ append (&hll_list_tail, "cg");
+ if (ldfile_output_machine == bfd_mach_i960_ka_sa
+ || ldfile_output_machine == bfd_mach_i960_ca)
+ append (&hll_list_tail, "fpg");
+ }
+
+ add_on (hll_list, lang_input_file_is_l_enum);
+ add_on (syslib_list, lang_input_file_is_search_file_enum);
+}
+
+static void
+lnk960_after_allocation (void)
+{
+ if (!link_info.relocatable)
+ {
+ lang_abs_symbol_at_end_of (".text", "_etext");
+ lang_abs_symbol_at_end_of (".data", "_edata");
+ lang_abs_symbol_at_beginning_of (".bss", "_bss_start");
+ lang_abs_symbol_at_end_of (".bss", "_end");
+ }
+}
+
+
+static struct
+ {
+ unsigned long number;
+ char *name;
+ }
+machine_table[] =
+{
+ { bfd_mach_i960_core ,"CORE" },
+ { bfd_mach_i960_kb_sb ,"KB" },
+ { bfd_mach_i960_kb_sb ,"SB" },
+ { bfd_mach_i960_mc ,"MC" },
+ { bfd_mach_i960_xa ,"XA" },
+ { bfd_mach_i960_ca ,"CA" },
+ { bfd_mach_i960_ka_sa ,"KA" },
+ { bfd_mach_i960_ka_sa ,"SA" },
+ { bfd_mach_i960_jx ,"JX" },
+ { bfd_mach_i960_hx ,"HX" },
+
+ { bfd_mach_i960_core ,"core" },
+ { bfd_mach_i960_kb_sb ,"kb" },
+ { bfd_mach_i960_kb_sb ,"sb" },
+ { bfd_mach_i960_mc ,"mc" },
+ { bfd_mach_i960_xa ,"xa" },
+ { bfd_mach_i960_ca ,"ca" },
+ { bfd_mach_i960_ka_sa ,"ka" },
+ { bfd_mach_i960_ka_sa ,"sa" },
+ { bfd_mach_i960_jx ,"jx" },
+ { bfd_mach_i960_hx ,"hx" },
+
+ { 0, (char *) NULL }
+};
+
+static void
+lnk960_set_output_arch (void)
+{
+ /* Set the output architecture and machine if possible */
+ unsigned int i;
+ ldfile_output_machine = bfd_mach_i960_core;
+ for (i= 0; machine_table[i].name != (char*) NULL; i++)
+ {
+ if (strcmp (ldfile_output_machine_name, machine_table[i].name) == 0)
+ {
+ ldfile_output_machine = machine_table[i].number;
+ break;
+ }
+ }
+ bfd_set_arch_mach (link_info.output_bfd, ldfile_output_architecture,
+ ldfile_output_machine);
+}
+
+static char *
+lnk960_choose_target (int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
+{
+ char *from_outside = getenv (TARGET_ENVIRON);
+ if (from_outside != (char *) NULL)
+ return from_outside;
+#ifdef LNK960_LITTLE
+ return "coff-Intel-little";
+#else
+ return "coff-Intel-big";
+#endif
+}
+
+static char *
+lnk960_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"
+
+fragment <<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.
+
+fragment <<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
+
+fragment <<EOF
+
+struct ld_emulation_xfer_struct ld_lnk960_emulation =
+{
+ lnk960_before_parse,
+ lnk960_syslib,
+ lnk960_hll,
+ lnk960_after_parse,
+ NULL, /* after_open */
+ lnk960_after_allocation,
+ lnk960_set_output_arch,
+ lnk960_choose_target,
+ before_allocation_default,
+ lnk960_get_script,
+ "lnk960",
+ "",
+ finish_default,
+ 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/binutils-2.20.1/ld/emultempl/m68hc1xelf.em b/binutils-2.20.1/ld/emultempl/m68hc1xelf.em
new file mode 100644
index 00000000..4751346b
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/m68hc1xelf.em
@@ -0,0 +1,373 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 1991, 1993, 1994, 1997, 1999, 2000, 2001, 2002, 2003, 2005, 2007,
+# 2008, 2009 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+# This file is sourced from elf32.em, and defines extra m68hc12-elf
+# and m68hc11-elf specific routines. It is used to generate the
+# HC11/HC12 trampolines to call a far function by using a normal 'jsr/bsr'.
+#
+# - The HC11/HC12 relocations are checked to see if there is a
+# R_M68HC11_16 relocation to a symbol marked with STO_M68HC12_FAR.
+# This relocation cannot be made on the symbol but must be made on
+# its trampoline
+# The trampolines to generate are collected during this pass
+# (See elf32_m68hc11_size_stubs)
+#
+# - The trampolines are generated in a ".tramp" section. The generation
+# takes care of HC11 and HC12 specificities.
+# (See elf32_m68hc11_build_stubs)
+#
+# - During relocation the R_M68HC11_16 relocation to the far symbols
+# are redirected to the trampoline that was generated.
+#
+# Copied from hppaelf and adapted for M68HC11/M68HC12 specific needs.
+#
+fragment <<EOF
+
+#include "ldctor.h"
+#include "elf32-m68hc1x.h"
+
+static asection *m68hc11elf_add_stub_section (const char *, asection *);
+
+/* Fake input file for stubs. */
+static lang_input_statement_type *stub_file;
+
+/* By default the HC11/HC12 trampolines to call a far function using
+ a normal 'bsr' and 'jsr' convention are generated during the link.
+ The --no-trampoline option prevents that. */
+static int no_trampoline = 0;
+
+/* Name of memory bank window in the MEMORY description.
+ This is set by --bank-window option. */
+static const char* bank_window_name = 0;
+
+static void
+m68hc11_elf_${EMULATION_NAME}_before_allocation (void)
+{
+ lang_memory_region_type* region;
+ int ret;
+
+ gld${EMULATION_NAME}_before_allocation ();
+
+ /* If generating a relocatable output file, then we don't
+ have to generate the trampolines. */
+ if (link_info.relocatable)
+ return;
+
+ ret = elf32_m68hc11_setup_section_lists (link_info.output_bfd, &link_info);
+ if (ret != 0 && no_trampoline == 0)
+ {
+ if (ret < 0)
+ {
+ einfo ("%X%P: can not size stub section: %E\n");
+ return;
+ }
+
+ /* Call into the BFD backend to do the real work. */
+ if (!elf32_m68hc11_size_stubs (link_info.output_bfd,
+ stub_file->the_bfd,
+ &link_info,
+ &m68hc11elf_add_stub_section))
+ {
+ einfo ("%X%P: can not size stub section: %E\n");
+ return;
+ }
+ }
+
+ if (bank_window_name == 0)
+ return;
+
+ /* The 'bank_window_name' memory region is a special region that describes
+ the memory bank window to access to paged memory. For 68HC12
+ this is fixed and should be:
+
+ window (rx) : ORIGIN = 0x8000, LENGTH = 16K
+
+ But for 68HC11 this is board specific. The definition of such
+ memory region allows to control how this paged memory is accessed. */
+ region = lang_memory_region_lookup (bank_window_name, FALSE);
+
+ /* Check the length to see if it was defined in the script. */
+ if (region->length != 0)
+ {
+ struct m68hc11_page_info *pinfo;
+ unsigned i;
+
+ /* Get default values */
+ m68hc11_elf_get_bank_parameters (&link_info);
+ pinfo = &m68hc11_elf_hash_table (&link_info)->pinfo;
+
+ /* And override them with the region definition. */
+ pinfo->bank_size = region->length;
+ pinfo->bank_shift = 0;
+ for (i = pinfo->bank_size; i != 0; i >>= 1)
+ pinfo->bank_shift++;
+ pinfo->bank_shift--;
+ pinfo->bank_size = 1L << pinfo->bank_shift;
+ pinfo->bank_mask = (1 << pinfo->bank_shift) - 1;
+ pinfo->bank_physical = region->origin;
+ pinfo->bank_physical_end = region->origin + pinfo->bank_size;
+
+ if (pinfo->bank_size != region->length)
+ {
+ einfo (_("warning: the size of the 'window' memory region "
+ "is not a power of 2\n"));
+ einfo (_("warning: its size %d is truncated to %d\n"),
+ region->length, pinfo->bank_size);
+ }
+ }
+}
+
+/* This is called before the input files are opened. We create a new
+ fake input file to hold the stub sections. */
+
+static void
+m68hc11elf_create_output_section_statements (void)
+{
+ stub_file = lang_add_input_file ("linker stubs",
+ lang_input_file_is_fake_enum,
+ NULL);
+ stub_file->the_bfd = bfd_create ("linker stubs", link_info.output_bfd);
+ if (stub_file->the_bfd == NULL
+ || !bfd_set_arch_mach (stub_file->the_bfd,
+ bfd_get_arch (link_info.output_bfd),
+ bfd_get_mach (link_info.output_bfd)))
+ {
+ einfo ("%X%P: can not create BFD %E\n");
+ return;
+ }
+
+ ldlang_add_file (stub_file);
+}
+
+
+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
+ || strcmp (bfd_get_section_name (output_section,
+ l->input_section.section),
+ bfd_get_section_name (output_section,
+ info->input_section)) == 0)
+ {
+ /* 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 elf32_m68hc11_size_stubs. */
+
+/* Create a new stub section, and arrange for it to be linked
+ immediately before INPUT_SECTION. */
+
+static asection *
+m68hc11elf_add_stub_section (const char *stub_sec_name,
+ asection *tramp_section)
+{
+ asection *stub_sec;
+ flagword flags;
+ asection *output_section;
+ const char *secname;
+ lang_output_section_statement_type *os;
+ struct hook_stub_info info;
+
+ flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
+ | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP);
+ stub_sec = bfd_make_section_anyway_with_flags (stub_file->the_bfd,
+ stub_sec_name, flags);
+ if (stub_sec == NULL)
+ goto err_ret;
+
+ output_section = tramp_section->output_section;
+ secname = bfd_get_section_name (output_section->owner, output_section);
+ os = lang_output_section_find (secname);
+
+ /* Try to put the new section at the same place as an existing
+ .tramp section. Such .tramp section exists in most cases and
+ contains the trampoline code. This way we put the generated trampoline
+ at the correct place. */
+ info.input_section = tramp_section;
+ lang_list_init (&info.add);
+ lang_add_section (&info.add, stub_sec, os);
+
+ if (info.add.head == NULL)
+ goto err_ret;
+
+ 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;
+}
+
+/* For the 68HC12 we use this opportunity to build linker stubs. */
+
+static void
+m68hc11elf_after_allocation (void)
+{
+ /* Now build the linker stubs. */
+ if (stub_file->the_bfd->sections != NULL)
+ {
+ /* Call again the trampoline analyzer to initialize the trampoline
+ stubs with the correct symbol addresses. Since there could have
+ been relaxation, the symbol addresses that were found during
+ first call may no longer be correct. */
+ if (!elf32_m68hc11_size_stubs (link_info.output_bfd,
+ stub_file->the_bfd,
+ &link_info, 0))
+ {
+ einfo ("%X%P: can not size stub section: %E\n");
+ return;
+ }
+ if (!elf32_m68hc11_build_stubs (link_info.output_bfd, &link_info))
+ einfo ("%X%P: can not build stubs: %E\n");
+ }
+
+ gld${EMULATION_NAME}_after_allocation ();
+}
+
+
+/* Avoid processing the fake stub_file in vercheck, stat_needed and
+ check_needed routines. */
+
+static void (*real_func) (lang_input_statement_type *);
+
+static void m68hc11_for_each_input_file_wrapper (lang_input_statement_type *l)
+{
+ if (l != stub_file)
+ (*real_func) (l);
+}
+
+static void
+m68hc11_lang_for_each_input_file (void (*func) (lang_input_statement_type *))
+{
+ real_func = func;
+ lang_for_each_input_file (&m68hc11_for_each_input_file_wrapper);
+}
+
+#define lang_for_each_input_file m68hc11_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_NO_TRAMPOLINE 300
+#define OPTION_BANK_WINDOW 301
+'
+
+# The options are repeated below so that no abbreviations are allowed.
+# Otherwise -s matches stub-group-size
+PARSE_AND_LIST_LONGOPTS='
+ { "no-trampoline", no_argument, NULL, OPTION_NO_TRAMPOLINE },
+ { "bank-window", required_argument, NULL, OPTION_BANK_WINDOW },
+'
+
+PARSE_AND_LIST_OPTIONS='
+ fprintf (file, _(
+" --no-trampoline Do not generate the far trampolines used to call\n"
+" a far function using 'jsr' or 'bsr'.\n"
+" --bank-window NAME Specify the name of the memory region describing\n"
+" the layout of the memory bank window.\n"
+ ));
+'
+
+PARSE_AND_LIST_ARGS_CASES='
+ case OPTION_NO_TRAMPOLINE:
+ no_trampoline = 1;
+ break;
+ case OPTION_BANK_WINDOW:
+ bank_window_name = optarg;
+ break;
+'
+
+# Put these extra m68hc11elf routines in ld_${EMULATION_NAME}_emulation
+#
+LDEMUL_BEFORE_ALLOCATION=m68hc11_elf_${EMULATION_NAME}_before_allocation
+LDEMUL_AFTER_ALLOCATION=m68hc11elf_after_allocation
+LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=m68hc11elf_create_output_section_statements
diff --git a/binutils-2.20.1/ld/emultempl/m68kcoff.em b/binutils-2.20.1/ld/emultempl/m68kcoff.em
new file mode 100644
index 00000000..276c3b25
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/m68kcoff.em
@@ -0,0 +1,243 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+fragment <<EOF
+/* This file is is generated by a shell script. DO NOT EDIT! */
+
+/* Handle embedded relocs for m68k.
+ Copyright 2000, 2002, 2003, 2004, 2005, 2007, 2008
+ Free Software Foundation, Inc.
+ Written by Michael Sokolov <msokolov@ivan.Harhan.ORG>, based on generic.em
+ by Steve Chamberlain <steve@cygnus.com>, embedded relocs code based on
+ mipsecoff.em by Ian Lance Taylor <ian@cygnus.com>.
+
+ This file is part of the GNU Binutils.
+
+ 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "bfdlink.h"
+
+#include "ld.h"
+#include "ldmain.h"
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldfile.h"
+#include "ldemul.h"
+#include "ldmisc.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 ("`echo ${ARCH}`", bfd_arch_unknown);
+#endif /* not TARGET_ */
+}
+
+/* This function is run after all the input files have been opened.
+ We create a .emreloc section for each input file with a non zero
+ .data section. The BFD backend will fill in these sections with
+ magic numbers which can be used to relocate the data section at run
+ time. */
+
+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 COFF. It
+ better be, as we are directly calling a COFF backend function. */
+ if (bfd_get_flavour (abfd) != bfd_target_coff_flavour)
+ einfo ("%F%B: all input objects must be COFF for --embedded-relocs\n");
+
+ datasec = bfd_get_section_by_name (abfd, ".data");
+
+ /* 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_with_flags (abfd, ".emreloc",
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY));
+ if (relsec == NULL
+ || ! bfd_set_section_alignment (abfd, relsec, 2)
+ || ! bfd_set_section_size (abfd, relsec,
+ datasec->reloc_count * 12))
+ einfo ("%F%B: can not create .emreloc 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 .data section has
+ relocs. This is called via bfd_map_over_sections. */
+
+static void
+check_sections (bfd *abfd, asection *sec, void *datasec)
+{
+ if ((bfd_get_section_flags (abfd, sec) & SEC_DATA)
+ && sec != datasec
+ && 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, ".data");
+
+ if (datasec == NULL || datasec->reloc_count == 0)
+ continue;
+
+ relsec = bfd_get_section_by_name (abfd, ".emreloc");
+ ASSERT (relsec != NULL);
+
+ if (! bfd_m68k_coff_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"
+
+fragment <<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.
+
+fragment <<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
+
+fragment <<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}",
+ finish_default,
+ 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/binutils-2.20.1/ld/emultempl/m68kelf.em b/binutils-2.20.1/ld/emultempl/m68kelf.em
new file mode 100644
index 00000000..48a50bcf
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/m68kelf.em
@@ -0,0 +1,250 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2000, 2001, 2003, 2005, 2007, 2008, 2009
+# Free Software Foundation, Inc.
+# Written by Michael Sokolov <msokolov@ivan.Harhan.ORG>, based on armelf.em
+#
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, 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
+ m68*-*-elf)
+ echo "#define SUPPORT_EMBEDDED_RELOCS" >>e${EMULATION_NAME}.c
+ ;;
+esac
+
+case ${target} in
+ *-linux*)
+# Don't use multi-GOT by default due to glibc linker's assumption
+# that GOT pointer points to GOT[0].
+# got_handling_target_default=GOT_HANDLING_MULTIGOT
+ got_handling_target_default=GOT_HANDLING_SINGLE
+ ;;
+ *)
+ got_handling_target_default=GOT_HANDLING_SINGLE
+ ;;
+esac
+
+fragment <<EOF
+
+#define GOT_HANDLING_SINGLE (0)
+#define GOT_HANDLING_NEGATIVE (1)
+#define GOT_HANDLING_MULTIGOT (2)
+#define GOT_HANDLING_TARGET_DEFAULT ${got_handling_target_default}
+
+/* How to generate GOT. */
+static int got_handling = GOT_HANDLING_DEFAULT;
+
+#ifdef SUPPORT_EMBEDDED_RELOCS
+static void check_sections (bfd *, asection *, void *);
+#endif
+
+/* This function is run after all the input files have been opened. */
+
+static void
+m68k_elf_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 .emreloc section for each
+ input file with a nonzero .data section. 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 either
+ COFF or ELF. We need to call a special BFD backend function to
+ generate the embedded relocs, and we have such functions only for
+ COFF and ELF. */
+ if (bfd_get_flavour (abfd) != bfd_target_coff_flavour
+ && bfd_get_flavour (abfd) != bfd_target_elf_flavour)
+ einfo ("%F%B: all input objects must be COFF or ELF for --embedded-relocs\n");
+
+ datasec = bfd_get_section_by_name (abfd, ".data");
+
+ /* 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_with_flags (abfd, ".emreloc",
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY));
+ if (relsec == NULL
+ || ! bfd_set_section_alignment (abfd, relsec, 2)
+ || ! bfd_set_section_size (abfd, relsec,
+ datasec->reloc_count * 12))
+ einfo ("%F%B: can not create .emreloc 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);
+ }
+ }
+#endif /* SUPPORT_EMBEDDED_RELOCS */
+}
+
+#ifdef SUPPORT_EMBEDDED_RELOCS
+/* Check that of the data sections, only the .data section has
+ relocs. This is called via bfd_map_over_sections. */
+
+static void
+check_sections (bfd *abfd, asection *sec, void *datasec)
+{
+ if ((bfd_get_section_flags (abfd, sec) & SEC_DATA)
+ && sec != datasec
+ && sec->reloc_count != 0)
+ einfo ("%B%X: section %s has relocs; can not 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. */
+
+static void
+m68k_elf_after_allocation (void)
+{
+ /* Call the standard elf routine. */
+ gld${EMULATION_NAME}_after_allocation ();
+
+#ifdef SUPPORT_EMBEDDED_RELOCS
+ if (command_line.embedded_relocs
+ && (! link_info.relocatable))
+ {
+ bfd *abfd;
+
+ /* If we are generating embedded relocs, call a special BFD backend
+ routine to do the work. */
+ for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link_next)
+ {
+ asection *datasec, *relsec;
+ char *errmsg;
+
+ datasec = bfd_get_section_by_name (abfd, ".data");
+
+ if (datasec == NULL || datasec->reloc_count == 0)
+ continue;
+
+ relsec = bfd_get_section_by_name (abfd, ".emreloc");
+ ASSERT (relsec != NULL);
+
+ if (bfd_get_flavour (abfd) == bfd_target_coff_flavour)
+ {
+ if (! bfd_m68k_coff_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);
+ }
+ }
+ else if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
+ {
+ if (! bfd_m68k_elf32_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);
+ }
+ }
+ else
+ abort ();
+ }
+ }
+#endif /* SUPPORT_EMBEDDED_RELOCS */
+}
+
+/* This is a convenient point to tell BFD about target specific flags.
+ After the output has been created, but before inputs are read. */
+
+static void
+elf_m68k_create_output_section_statements (void)
+{
+ bfd_elf_m68k_set_target_options (&link_info, got_handling);
+}
+
+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_GOT 301
+'
+
+PARSE_AND_LIST_LONGOPTS='
+ { "got", required_argument, NULL, OPTION_GOT},
+'
+
+PARSE_AND_LIST_OPTIONS='
+ fprintf (file, _(" --got=<type> Specify GOT handling scheme\n"));
+'
+
+PARSE_AND_LIST_ARGS_CASES='
+ case OPTION_GOT:
+ if (strcmp (optarg, "target") == 0)
+ got_handling = GOT_HANDLING_TARGET_DEFAULT;
+ else if (strcmp (optarg, "single") == 0)
+ got_handling = 0;
+ else if (strcmp (optarg, "negative") == 0)
+ got_handling = 1;
+ else if (strcmp (optarg, "multigot") == 0)
+ got_handling = 2;
+ else
+ einfo (_("Unrecognized --got argument '\''%s'\''.\n"), optarg);
+ break;
+'
+
+# 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=m68k_elf_after_open
+LDEMUL_AFTER_ALLOCATION=m68k_elf_after_allocation
+LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=elf_m68k_create_output_section_statements
diff --git a/binutils-2.20.1/ld/emultempl/mipsecoff.em b/binutils-2.20.1/ld/emultempl/mipsecoff.em
new file mode 100644
index 00000000..809229fd
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/mipsecoff.em
@@ -0,0 +1,38 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 1994, 1995, 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
+# Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+if [ -z "$MACHINE" ]; then
+ OUTPUT_ARCH=${ARCH}
+else
+ OUTPUT_ARCH=${ARCH}:${MACHINE}
+fi
+fragment <<EOF
+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_ */
+}
+EOF
+
+LDEMUL_BEFORE_PARSE=gld${EMULATION_NAME}_before_parse
diff --git a/binutils-2.20.1/ld/emultempl/mipself.em b/binutils-2.20.1/ld/emultempl/mipself.em
new file mode 100644
index 00000000..65cb0731
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/mipself.em
@@ -0,0 +1,241 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2004, 2006, 2007, 2008 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+fragment <<EOF
+
+#include "ldctor.h"
+#include "elf/mips.h"
+#include "elfxx-mips.h"
+
+#define is_mips_elf(bfd) \
+ (bfd_get_flavour (bfd) == bfd_target_elf_flavour \
+ && elf_tdata (bfd) != NULL \
+ && elf_object_id (bfd) == MIPS_ELF_TDATA)
+
+/* Fake input file for stubs. */
+static lang_input_statement_type *stub_file;
+static bfd *stub_bfd;
+
+static void
+mips_after_parse (void)
+{
+ /* .gnu.hash and the MIPS ABI require .dynsym to be sorted in different
+ ways. .gnu.hash needs symbols to be grouped by hash code whereas the
+ MIPS ABI requires a mapping between the GOT and the symbol table. */
+ if (link_info.emit_gnu_hash)
+ {
+ einfo ("%X%P: .gnu.hash is incompatible with the MIPS ABI\n");
+ link_info.emit_hash = TRUE;
+ link_info.emit_gnu_hash = FALSE;
+ }
+ after_parse_default ();
+}
+
+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 (info->input_section == NULL
+ || 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;
+}
+
+/* Create a new stub section called STUB_SEC_NAME and arrange for it to
+ be linked in OUTPUT_SECTION. The section should go at the beginning of
+ OUTPUT_SECTION if INPUT_SECTION is null, otherwise it must go immediately
+ before INPUT_SECTION. */
+
+static asection *
+mips_add_stub_section (const char *stub_sec_name, asection *input_section,
+ asection *output_section)
+{
+ asection *stub_sec;
+ flagword flags;
+ const char *secname;
+ lang_output_section_statement_type *os;
+ struct hook_stub_info info;
+
+ /* Create the stub file, if we haven't already. */
+ if (stub_file == NULL)
+ {
+ stub_file = lang_add_input_file ("linker stubs",
+ lang_input_file_is_fake_enum,
+ NULL);
+ stub_bfd = bfd_create ("linker stubs", link_info.output_bfd);
+ if (stub_bfd == NULL
+ || !bfd_set_arch_mach (stub_bfd,
+ bfd_get_arch (link_info.output_bfd),
+ bfd_get_mach (link_info.output_bfd)))
+ {
+ einfo ("%F%P: can not create BFD %E\n");
+ return NULL;
+ }
+ stub_bfd->flags |= BFD_LINKER_CREATED;
+ stub_file->the_bfd = stub_bfd;
+ ldlang_add_file (stub_file);
+ }
+
+ /* Create the section. */
+ stub_sec = bfd_make_section_anyway (stub_bfd, stub_sec_name);
+ if (stub_sec == NULL)
+ goto err_ret;
+
+ /* Set the flags. */
+ flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
+ | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_KEEP);
+ if (!bfd_set_section_flags (stub_bfd, stub_sec, flags))
+ goto err_ret;
+
+ /* Create an output section statement. */
+ secname = bfd_get_section_name (output_section->owner, output_section);
+ os = lang_output_section_find (secname);
+
+ /* Initialize a statement list that contains only the new statement. */
+ lang_list_init (&info.add);
+ lang_add_section (&info.add, stub_sec, os);
+ if (info.add.head == NULL)
+ goto err_ret;
+
+ /* Insert the new statement in the appropriate place. */
+ info.input_section = input_section;
+ 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;
+}
+
+/* This is called before the input files are opened. */
+
+static void
+mips_create_output_section_statements (void)
+{
+ if (is_mips_elf (link_info.output_bfd))
+ _bfd_mips_elf_init_stubs (&link_info, mips_add_stub_section);
+}
+
+/* This is called after we have merged the private data of the input bfds. */
+
+static void
+mips_before_allocation (void)
+{
+ flagword flags;
+
+ flags = elf_elfheader (link_info.output_bfd)->e_flags;
+ if (!link_info.shared
+ && !link_info.nocopyreloc
+ && (flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) == EF_MIPS_CPIC)
+ _bfd_mips_elf_use_plts_and_copy_relocs (&link_info);
+
+ gld${EMULATION_NAME}_before_allocation ();
+}
+
+/* Avoid processing the fake stub_file in vercheck, stat_needed and
+ check_needed routines. */
+
+static void (*real_func) (lang_input_statement_type *);
+
+static void mips_for_each_input_file_wrapper (lang_input_statement_type *l)
+{
+ if (l != stub_file)
+ (*real_func) (l);
+}
+
+static void
+mips_lang_for_each_input_file (void (*func) (lang_input_statement_type *))
+{
+ real_func = func;
+ lang_for_each_input_file (&mips_for_each_input_file_wrapper);
+}
+
+#define lang_for_each_input_file mips_lang_for_each_input_file
+
+EOF
+
+LDEMUL_AFTER_PARSE=mips_after_parse
+LDEMUL_BEFORE_ALLOCATION=mips_before_allocation
+LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=mips_create_output_section_statements
diff --git a/binutils-2.20.1/ld/emultempl/mmix-elfnmmo.em b/binutils-2.20.1/ld/emultempl/mmix-elfnmmo.em
new file mode 100644
index 00000000..6a7b2954
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/mmix-elfnmmo.em
@@ -0,0 +1,116 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
+# Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+# This file is sourced from elf32.em and mmo.em, used to define
+# MMIX-specific things common to ELF and MMO.
+
+fragment <<EOF
+#include "elf/mmix.h"
+
+/* Set up handling of linker-allocated global registers. */
+
+static void
+mmix_before_allocation (void)
+{
+ /* Call the default first. */
+ gld${EMULATION_NAME}_before_allocation ();
+
+ /* There's a needrelax.em which uses this ..._before_allocation-hook and
+ just has the statement below as payload. It's more of a hassle to
+ use that than to just include these two lines and take the
+ maintenance burden to keep them in sync. (Of course we lose the
+ maintenance burden of checking that it still does what we need.) */
+
+ /* Force -relax on (regardless of whether we're doing a relocatable
+ link). */
+ command_line.relax = TRUE;
+
+ if (!_bfd_mmix_before_linker_allocation (link_info.output_bfd, &link_info))
+ einfo ("%X%P: Internal problems setting up section %s",
+ MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME);
+}
+
+/* We need to set the VMA of the .MMIX.reg_contents section when it has
+ been allocated, and produce the final settings for the linker-generated
+ GREGs. */
+
+static void
+mmix_after_allocation (void)
+{
+ asection *sec;
+ bfd_signed_vma regvma;
+
+ gld${EMULATION_NAME}_after_allocation ();
+
+ /* If there's no register section, we don't need to do anything. On the
+ other hand, if there's a non-standard linker-script without a mapping
+ from MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME when that section is
+ present (as in the ld test "NOCROSSREFS 2"), that section (1) will be
+ orphaned; not inserted in MMIX_REG_CONTENTS_SECTION_NAME and (2) we
+ will not do the necessary preparations for those relocations that
+ caused it to be created. We'll SEGV from the latter error. The
+ former error in separation will result in a non-working binary, but
+ that's expected when you play tricks with linker scripts. The
+ "NOCROSSREFS 2" test does not run the output so it does not matter
+ there. */
+ sec = bfd_get_section_by_name (link_info.output_bfd,
+ MMIX_REG_CONTENTS_SECTION_NAME);
+ if (sec == NULL)
+ sec
+ = bfd_get_section_by_name (link_info.output_bfd,
+ MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME);
+ if (sec == NULL)
+ return;
+
+ regvma = 256 * 8 - sec->size - 8;
+
+ /* If we start on a local register, we have too many global registers.
+ We treat this error as nonfatal (meaning processing will continue in
+ search for other errors), because it's a link error in the same way
+ as an undefined symbol. */
+ if (regvma < 32 * 8)
+ {
+ einfo ("%X%P: Too many global registers: %u, max 223\n",
+ (unsigned) sec->size / 8);
+ regvma = 32 * 8;
+ }
+
+ /* Set vma to correspond to first such register number * 8. */
+ bfd_set_section_vma (link_info.output_bfd, sec, (bfd_vma) regvma);
+
+ /* Simplify symbol output for the register section (without contents;
+ created for register symbols) by setting the output offset to 0.
+ This section is only present when there are register symbols. */
+ sec = bfd_get_section_by_name (link_info.output_bfd, MMIX_REG_SECTION_NAME);
+ if (sec != NULL)
+ bfd_set_section_vma (abfd, sec, 0);
+
+ if (!_bfd_mmix_after_linker_allocation (link_info.output_bfd, &link_info))
+ {
+ /* This is a fatal error; make einfo call not return. */
+ einfo ("%F%P: Can't finalize linker-allocated global registers\n");
+ }
+}
+EOF
+
+LDEMUL_AFTER_ALLOCATION=mmix_after_allocation
+LDEMUL_BEFORE_ALLOCATION=mmix_before_allocation
diff --git a/binutils-2.20.1/ld/emultempl/mmixelf.em b/binutils-2.20.1/ld/emultempl/mmixelf.em
new file mode 100644
index 00000000..a875a5c1
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/mmixelf.em
@@ -0,0 +1,44 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2001, 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+# This file is sourced from elf32.em and used to define MMIX and ELF
+# specific things. First include what we have in common with mmo.
+
+source_em ${srcdir}/emultempl/mmix-elfnmmo.em
+
+fragment <<EOF
+
+static void
+elfmmix_before_parse (void)
+{
+ gld${EMULATION_NAME}_before_parse ();
+
+ /* Make sure we don't create a demand-paged executable. Unfortunately
+ this isn't changeable with a command-line option. It makes no
+ difference to mmo, but the sections in elf64mmix will be aligned to a
+ page in the linked file, which is non-intuitive. If there's ever a
+ full system with shared libraries and demand paging, you will want to
+ exclude this file. */
+ config.magic_demand_paged = FALSE;
+}
+EOF
+
+LDEMUL_BEFORE_PARSE=elfmmix_before_parse
diff --git a/binutils-2.20.1/ld/emultempl/mmo.em b/binutils-2.20.1/ld/emultempl/mmo.em
new file mode 100644
index 00000000..d1a6f146
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/mmo.em
@@ -0,0 +1,158 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+# Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+# This file is sourced from generic.em.
+
+fragment <<EOF
+/* Need to have this macro defined before mmix-elfnmmo, which uses the
+ name for the before_allocation function, defined in ldemul.c (for
+ the mmo "emulation") or in elf32.em (for the elf64mmix
+ "emulation"). */
+#define gldmmo_before_allocation before_allocation_default
+
+/* We include this header *not* because we expect to handle ELF here
+ but because we re-use the map_segments function in elf-generic.em,
+ a file which is rightly somewhat ELF-centric. But this is only to
+ get a weird testcase right; ld-mmix/bpo-22, forcing ELF to be
+ output from the mmo emulation: -m mmo --oformat elf64-mmix! */
+#include "elf-bfd.h"
+
+static void gld${EMULATION_NAME}_after_allocation (void);
+EOF
+
+source_em ${srcdir}/emultempl/elf-generic.em
+source_em ${srcdir}/emultempl/mmix-elfnmmo.em
+
+fragment <<EOF
+
+/* Place an orphan section. We use this to put random SEC_CODE or
+ SEC_READONLY sections right after MMO_TEXT_SECTION_NAME. Much borrowed
+ from elf32.em. */
+
+static lang_output_section_statement_type *
+mmo_place_orphan (asection *s,
+ const char *secname,
+ int constraint ATTRIBUTE_UNUSED)
+{
+ static struct orphan_save hold_text =
+ {
+ MMO_TEXT_SECTION_NAME,
+ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE,
+ 0, 0, 0, 0
+ };
+ struct orphan_save *place;
+ lang_output_section_statement_type *after;
+ lang_output_section_statement_type *os;
+
+ /* We have nothing to say for anything other than a final link. */
+ if (link_info.relocatable
+ || (s->flags & (SEC_EXCLUDE | SEC_LOAD)) != SEC_LOAD)
+ return NULL;
+
+ /* Only care for sections we're going to load. */
+ os = lang_output_section_find (secname);
+
+ /* We have an output section by this name. Place the section inside it
+ (regardless of whether the linker script lists it as input). */
+ if (os != NULL)
+ {
+ lang_add_section (&os->children, s, os);
+ return os;
+ }
+
+ /* If this section does not have .text-type section flags or there's no
+ MMO_TEXT_SECTION_NAME, we don't have anything to say. */
+ if ((s->flags & (SEC_CODE | SEC_READONLY)) == 0)
+ return NULL;
+
+ if (hold_text.os == NULL)
+ hold_text.os = lang_output_section_find (hold_text.name);
+
+ place = &hold_text;
+ if (hold_text.os != NULL)
+ after = hold_text.os;
+ else
+ after = &lang_output_section_statement.head->output_section_statement;
+
+ /* If there's an output section by this name, we'll use it, regardless
+ of section flags, in contrast to what's done in elf32.em. */
+ os = lang_insert_orphan (s, secname, 0, after, place, NULL, NULL);
+
+ /* We need an output section for .text as a root, so if there was none
+ (might happen with a peculiar linker script such as in "map
+ addresses", map-address.exp), we grab the output section created
+ above. */
+ if (hold_text.os == NULL)
+ hold_text.os = os;
+
+ return os;
+}
+
+/* Remove the spurious settings of SEC_RELOC that make it to the output at
+ link time. We are as confused as elflink.h:elf_bfd_final_link, and
+ paper over the bug similarly. */
+
+static void
+mmo_wipe_sec_reloc_flag (bfd *abfd, asection *sec, void *ptr ATTRIBUTE_UNUSED)
+{
+ bfd_set_section_flags (abfd, sec,
+ bfd_get_section_flags (abfd, sec) & ~SEC_RELOC);
+}
+
+/* Iterate with bfd_map_over_sections over mmo_wipe_sec_reloc_flag... */
+
+static void
+gld${EMULATION_NAME}_after_allocation (void)
+{
+ bfd_map_over_sections (link_info.output_bfd, mmo_wipe_sec_reloc_flag, NULL);
+ gld${EMULATION_NAME}_map_segments (FALSE);
+}
+
+/* To get on-demand global register allocation right, we need to parse the
+ relocs, like what happens when linking to ELF. It needs to be done
+ before all input sections are supposed to be present. When linking to
+ ELF, it's done when reading symbols. When linking to mmo, we do it
+ when all input files are seen, which is equivalent. */
+
+static void
+mmo_after_open (void)
+{
+ /* When there's a mismatch between the output format and the emulation
+ (using weird combinations like "-m mmo --oformat elf64-mmix" for
+ example), we'd count relocs twice because they'd also be counted
+ along the usual route for ELF-only linking, which would lead to an
+ internal accounting error. */
+ if (bfd_get_flavour (link_info.output_bfd) != bfd_target_elf_flavour)
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (is)
+ {
+ if (bfd_get_flavour (is->the_bfd) == bfd_target_elf_flavour
+ && !_bfd_mmix_check_all_relocs (is->the_bfd, &link_info))
+ einfo ("%X%P: Internal problems scanning %B after opening it",
+ is->the_bfd);
+ }
+ }
+}
+EOF
+
+LDEMUL_PLACE_ORPHAN=mmo_place_orphan
+LDEMUL_AFTER_OPEN=mmo_after_open
diff --git a/binutils-2.20.1/ld/emultempl/needrelax.em b/binutils-2.20.1/ld/emultempl/needrelax.em
new file mode 100644
index 00000000..4c475db7
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/needrelax.em
@@ -0,0 +1,39 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2001, 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, 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
+
+fragment <<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/binutils-2.20.1/ld/emultempl/netbsd.em b/binutils-2.20.1/ld/emultempl/netbsd.em
new file mode 100644
index 00000000..6e25486a
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/netbsd.em
@@ -0,0 +1,34 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2007 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+LDEMUL_BEFORE_PARSE=gldnetbsd_before_parse
+
+fragment <<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/binutils-2.20.1/ld/emultempl/ostring.sed b/binutils-2.20.1/ld/emultempl/ostring.sed
new file mode 100644
index 00000000..a526d3ff
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/ostring.sed
@@ -0,0 +1,4 @@
+s/["\\]/\\&/g
+s/$/\\n\\/
+1 s/^/"/
+$ s/$/n"/
diff --git a/binutils-2.20.1/ld/emultempl/pe.em b/binutils-2.20.1/ld/emultempl/pe.em
new file mode 100644
index 00000000..788818d6
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/pe.em
@@ -0,0 +1,2080 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+test -z "${ENTRY}" && ENTRY="_mainCRTStartup"
+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 ;-)
+fragment <<EOF
+/* Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+
+ This file is part of the GNU Binutils.
+
+ 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, 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. */
+
+#if defined(TARGET_IS_armpe) \
+ || defined(TARGET_IS_arm_epoc_pe) \
+ || defined(TARGET_IS_arm_wince_pe)
+#define bfd_arm_allocate_interworking_sections \
+ bfd_${EMULATION_NAME}_allocate_interworking_sections
+#define bfd_arm_get_bfd_for_interworking \
+ bfd_${EMULATION_NAME}_get_bfd_for_interworking
+#define bfd_arm_process_before_allocation \
+ bfd_${EMULATION_NAME}_process_before_allocation
+#endif
+
+#include "sysdep.h"
+#include "bfd.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: See bfd/peXXigen.c for why we include an architecture specific
+ header in generic PE code. */
+#include "coff/i386.h"
+#include "coff/pe.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) \
+ || defined(TARGET_IS_shpe) \
+ || defined(TARGET_IS_mipspe) \
+ || defined(TARGET_IS_armpe) \
+ || defined(TARGET_IS_arm_epoc_pe) \
+ || defined(TARGET_IS_arm_wince_pe)
+#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
+
+#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_wince_pe)
+#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
+
+#define U(S) ${INITIAL_SYMBOL_CHAR} S
+
+static struct internal_extra_pe_aouthdr pe;
+static int dll;
+static flagword real_flags = 0;
+static int support_old_code = 0;
+static char * thumb_entry_symbol = NULL;
+static lang_assignment_statement_type *image_base_statement = 0;
+static unsigned short pe_dll_characteristics = 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;
+EOF
+
+# Cygwin no longer wants these noisy warnings. Other PE
+# targets might like to consider adding themselves here.
+case ${target} in
+ *-*-cygwin*)
+ default_auto_import=1
+ ;;
+ *)
+ default_auto_import=-1
+ ;;
+esac
+
+fragment <<EOF
+ link_info.pei386_auto_import = ${default_auto_import};
+ link_info.pei386_runtime_pseudo_reloc = 1; /* Use by default version 1. */
+
+#if (PE_DEF_SUBSYSTEM == 9) || (PE_DEF_SUBSYSTEM == 2)
+#if defined TARGET_IS_mipspe || defined TARGET_IS_armpe || defined TARGET_IS_arm_wince_pe
+ lang_default_entry ("WinMainCRTStartup");
+#else
+ lang_default_entry ("_WinMainCRTStartup");
+#endif
+#else
+ lang_default_entry ("${ENTRY}");
+#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)
+#define OPTION_LARGE_ADDRESS_AWARE \
+ (OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC + 1)
+#define OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V1 \
+ (OPTION_LARGE_ADDRESS_AWARE + 1)
+#define OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2 \
+ (OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V1 + 1)
+#define OPTION_EXCLUDE_MODULES_FOR_IMPLIB \
+ (OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2 + 1)
+#define OPTION_USE_NUL_PREFIXED_IMPORT_TABLES \
+ (OPTION_EXCLUDE_MODULES_FOR_IMPLIB + 1)
+#define OPTION_ENABLE_LONG_SECTION_NAMES \
+ (OPTION_USE_NUL_PREFIXED_IMPORT_TABLES + 1)
+#define OPTION_DISABLE_LONG_SECTION_NAMES \
+ (OPTION_ENABLE_LONG_SECTION_NAMES + 1)
+/* DLLCharacteristics flags */
+#define OPTION_DYNAMIC_BASE (OPTION_DISABLE_LONG_SECTION_NAMES + 1)
+#define OPTION_FORCE_INTEGRITY (OPTION_DYNAMIC_BASE + 1)
+#define OPTION_NX_COMPAT (OPTION_FORCE_INTEGRITY + 1)
+#define OPTION_NO_ISOLATION (OPTION_NX_COMPAT + 1)
+#define OPTION_NO_SEH (OPTION_NO_ISOLATION + 1)
+#define OPTION_NO_BIND (OPTION_NO_SEH + 1)
+#define OPTION_WDM_DRIVER (OPTION_NO_BIND + 1)
+#define OPTION_TERMINAL_SERVER_AWARE (OPTION_WDM_DRIVER + 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},
+ {"use-nul-prefixed-import-tables", no_argument, NULL,
+ OPTION_USE_NUL_PREFIXED_IMPORT_TABLES},
+#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},
+ {"exclude-modules-for-implib", required_argument, NULL, OPTION_EXCLUDE_MODULES_FOR_IMPLIB},
+ {"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},
+ {"enable-runtime-pseudo-reloc-v1", no_argument, NULL, OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V1},
+ {"enable-runtime-pseudo-reloc-v2", no_argument, NULL, OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2},
+#endif
+ {"large-address-aware", no_argument, NULL, OPTION_LARGE_ADDRESS_AWARE},
+ {"enable-long-section-names", no_argument, NULL, OPTION_ENABLE_LONG_SECTION_NAMES},
+ {"disable-long-section-names", no_argument, NULL, OPTION_DISABLE_LONG_SECTION_NAMES},
+ {"dynamicbase",no_argument, NULL, OPTION_DYNAMIC_BASE},
+ {"forceinteg", no_argument, NULL, OPTION_FORCE_INTEGRITY},
+ {"nxcompat", no_argument, NULL, OPTION_NX_COMPAT},
+ {"no-isolation", no_argument, NULL, OPTION_NO_ISOLATION},
+ {"no-seh", no_argument, NULL, OPTION_NO_SEH},
+ {"no-bind", no_argument, NULL, OPTION_NO_BIND},
+ {"wdmdriver", no_argument, NULL, OPTION_WDM_DRIVER},
+ {"tsaware", no_argument, NULL, OPTION_TERMINAL_SERVER_AWARE},
+ {NULL, no_argument, NULL, 0}
+ };
+
+ *longopts
+ = 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},
+#define MSIMAGEBASEOFF 2
+ D(ImageBase, U ("__ImageBase"), NT_EXE_IMAGE_BASE),
+ 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),
+#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_wince_pe)
+ D(MajorSubsystemVersion,"__major_subsystem_version__", 3),
+#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),
+ D(DllCharacteristics, "__dll_characteristics__", 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, _(" --exclude-modules-for-implib mod,mod,...\n"));
+ fprintf (file, _(" Exclude objects, archive members from auto\n"));
+ fprintf (file, _(" export, place into import library instead.\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
+ fprintf (file, _(" --large-address-aware Executable supports virtual addresses\n\
+ greater than 2 gigabytes\n"));
+ fprintf (file, _(" --enable-long-section-names Use long COFF section names even in\n\
+ executable image files\n"));
+ fprintf (file, _(" --disable-long-section-names Never use long COFF section names, even\n\
+ in object files\n"));
+ fprintf (file, _(" --dynamicbase Image base address may be relocated using\n\
+ address space layout randomization (ASLR)\n"));
+ fprintf (file, _(" --forceinteg Code integrity checks are enforced\n"));
+ fprintf (file, _(" --nxcompat Image is compatible with data execution prevention\n"));
+ fprintf (file, _(" --no-isolation Image understands isolation but do not isolate the image\n"));
+ fprintf (file, _(" --no-seh Image does not use SEH. No SE handler may\n\
+ be called in this image\n"));
+ fprintf (file, _(" --no-bind Do not bind this image\n"));
+ fprintf (file, _(" --wdmdriver Driver uses the WDM model\n"));
+ fprintf (file, _(" --tsaware Image is Terminal Server aware\n"));
+}
+
+
+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;
+ if (strcmp (name,"__image_base__") == 0)
+ set_pe_name (U ("__ImageBase"), val);
+ return;
+ }
+ }
+ abort ();
+}
+
+
+static void
+set_pe_subsystem (void)
+{
+ const char *sver;
+ const char *entry;
+ const char *initial_symbol_char;
+ char *end;
+ int len;
+ int i;
+ int subsystem;
+ unsigned long temp_subsystem;
+ static const struct
+ {
+ const char *name;
+ const int value;
+ const char *entry;
+ }
+ v[] =
+ {
+ { "native", 1, "NtProcessStartup" },
+ { "windows", 2, "WinMainCRTStartup" },
+ { "console", 3, "mainCRTStartup" },
+ { "posix", 7, "__PosixProcessStartup"},
+ { "wince", 9, "WinMainCRTStartup" },
+ { "xbox", 14, "mainCRTStartup" },
+ { NULL, 0, NULL }
+ };
+ /* Entry point name for arbitrary subsystem numbers. */
+ static const char default_entry[] = "mainCRTStartup";
+
+ /* Check for the presence of a version number. */
+ sver = strchr (optarg, ':');
+ if (sver == NULL)
+ len = strlen (optarg);
+ else
+ {
+ 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"));
+ }
+
+ /* Check for numeric subsystem. */
+ temp_subsystem = strtoul (optarg, & end, 0);
+ if ((*end == ':' || *end == '\0') && (temp_subsystem < 65536))
+ {
+ /* Search list for a numeric match to use its entry point. */
+ for (i = 0; v[i].name; i++)
+ if (v[i].value == (int) temp_subsystem)
+ break;
+
+ /* If no match, use the default. */
+ if (v[i].name != NULL)
+ entry = v[i].entry;
+ else
+ entry = default_entry;
+
+ /* Use this subsystem. */
+ subsystem = (int) temp_subsystem;
+ }
+ else
+ {
+ /* Search for subsystem by name. */
+ for (i = 0; v[i].name; i++)
+ if (strncmp (optarg, v[i].name, len) == 0
+ && v[i].name[len] == '\0')
+ break;
+
+ if (v[i].name == NULL)
+ {
+ einfo (_("%P%F: invalid subsystem type %s\n"), optarg);
+ return;
+ }
+
+ entry = v[i].entry;
+ subsystem = v[i].value;
+ }
+
+ set_pe_name ("__subsystem__", subsystem);
+
+ initial_symbol_char = ${INITIAL_SYMBOL_CHAR};
+ if (*initial_symbol_char != '\0')
+ {
+ char *alc_entry;
+
+ /* lang_default_entry expects its argument to be permanently
+ allocated, so we don't free this string. */
+ alc_entry = xmalloc (strlen (initial_symbol_char)
+ + strlen (entry)
+ + 1);
+ strcpy (alc_entry, initial_symbol_char);
+ strcat (alc_entry, entry);
+ entry = alc_entry;
+ }
+
+ lang_default_entry (entry);
+
+ return;
+}
+
+
+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;
+ case OPTION_USE_NUL_PREFIXED_IMPORT_TABLES:
+ pe_use_nul_prefixed_import_tables = TRUE;
+ 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, EXCLUDESYMS);
+ break;
+ case OPTION_EXCLUDE_LIBS:
+ pe_dll_add_excludes (optarg, EXCLUDELIBS);
+ break;
+ case OPTION_EXCLUDE_MODULES_FOR_IMPLIB:
+ pe_dll_add_excludes (optarg, EXCLUDEFORIMPLIB);
+ 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_ENABLE_RUNTIME_PSEUDO_RELOC_V1:
+ link_info.pei386_runtime_pseudo_reloc = 1;
+ break;
+ case OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2:
+ link_info.pei386_runtime_pseudo_reloc = 2;
+ 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
+ case OPTION_LARGE_ADDRESS_AWARE:
+ real_flags |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
+ break;
+ case OPTION_ENABLE_LONG_SECTION_NAMES:
+ pe_use_coff_long_section_names = 1;
+ break;
+ case OPTION_DISABLE_LONG_SECTION_NAMES:
+ pe_use_coff_long_section_names = 0;
+ break;
+/* Get DLLCharacteristics bits */
+ case OPTION_DYNAMIC_BASE:
+ pe_dll_characteristics |= IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE;
+ break;
+ case OPTION_FORCE_INTEGRITY:
+ pe_dll_characteristics |= IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY;
+ break;
+ case OPTION_NX_COMPAT:
+ pe_dll_characteristics |= IMAGE_DLL_CHARACTERISTICS_NX_COMPAT;
+ break;
+ case OPTION_NO_ISOLATION:
+ pe_dll_characteristics |= IMAGE_DLLCHARACTERISTICS_NO_ISOLATION;
+ break;
+ case OPTION_NO_SEH:
+ pe_dll_characteristics |= IMAGE_DLLCHARACTERISTICS_NO_SEH;
+ break;
+ case OPTION_NO_BIND:
+ pe_dll_characteristics |= IMAGE_DLLCHARACTERISTICS_NO_BIND;
+ break;
+ case OPTION_WDM_DRIVER:
+ pe_dll_characteristics |= IMAGE_DLLCHARACTERISTICS_WDM_DRIVER;
+ break;
+ case OPTION_TERMINAL_SERVER_AWARE:
+ pe_dll_characteristics |= IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE;
+ break;
+ }
+
+ /* Set DLLCharacteristics bits */
+ set_pe_name ("__dll_characteristics__", pe_dll_characteristics);
+
+ 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 0x61300000 + ((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;
+
+ if (!init[IMAGEBASEOFF].inited)
+ {
+ if (link_info.relocatable)
+ init[IMAGEBASEOFF].value = 0;
+ else if (init[DLLOFF].value || (link_info.shared && !link_info.pie))
+ {
+#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;
+ init[MSIMAGEBASEOFF].value = init[IMAGEBASEOFF].value;
+ }
+
+ /* Don't do any symbol assignments if this is a relocatable link. */
+ if (link_info.relocatable)
+ return;
+
+ /* Glue the assignments into the abs section. */
+ push_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. */
+ pop_stat_ptr ();
+
+ 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)
+{
+ /* PR ld/6744: Warn the user if they have used an ELF-only
+ option hoping it will work on PE. */
+ if (link_info.export_dynamic)
+ einfo (_("%P: warning: --export-dynamic is not supported for PE "
+ "targets, did you mean --export-all-symbols?\n"));
+
+ after_parse_default ();
+}
+
+/* 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->u.undef.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;
+ char addend[4];
+
+ if (pe_dll_extra_pe_debug)
+ printf ("arelent: %s@%#lx: add=%li\n", sym->name,
+ (unsigned 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, bfd_get_32 (s->owner, 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->u.undef.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, i;
+
+ if (link_info.pei386_auto_import == -1)
+ {
+ static bfd_boolean warned = FALSE;
+
+ info_msg (_("Info: resolving %s by linking to %s (auto-import)\n"),
+ undef->root.string, buf);
+
+ /* PR linker/4844. */
+ if (! warned)
+ {
+ warned = TRUE;
+ einfo (_("%P: warning: auto-importing has been activated without --enable-auto-import specified on the command line.\n\
+This should work unless it involves constant data structures referencing symbols from auto-imported DLLs.\n"));
+ }
+ }
+
+ if (!bfd_generic_link_read_symbols (b))
+ {
+ einfo (_("%B%F: could not read symbols: %E\n"), b);
+ return;
+ }
+
+ symbols = bfd_get_outsymbols (b);
+ nsyms = bfd_get_symcount (b);
+
+ for (i = 0; i < nsyms; i++)
+ {
+ if (! CONST_STRNEQ (symbols[i]->name, U ("_head_")))
+ continue;
+
+ if (pe_dll_extra_pe_debug)
+ printf ("->%s\n", symbols[i]->name);
+
+ pe_data_import_dll = (char*) (symbols[i]->name +
+ sizeof (U ("_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
+debug_section_p (bfd *abfd ATTRIBUTE_UNUSED, asection *sect, void *obj)
+{
+ int *found = (int *) obj;
+ if (strncmp (".debug_", sect->name, sizeof (".debug_") - 1) == 0)
+ *found = 1;
+}
+
+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->u.undef.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 (link_info.output_bfd) == NULL
+ || coff_data (link_info.output_bfd)->pe == 0)
+ einfo (_("%F%P: cannot perform PE operations on non PE output file '%B'.\n"),
+ link_info.output_bfd);
+
+ pe_data (link_info.output_bfd)->pe_opthdr = pe;
+ pe_data (link_info.output_bfd)->dll = init[DLLOFF].value;
+ pe_data (link_info.output_bfd)->real_flags |= real_flags;
+
+ /* At this point we must decide whether to use long section names
+ in the output or not. If the user hasn't explicitly specified
+ on the command line, we leave it to the default for the format
+ (object files yes, image files no), except if there is debug
+ information present; GDB relies on the long section names to
+ find it, so enable it in that case. */
+ if (pe_use_coff_long_section_names < 0 && link_info.strip == strip_none)
+ {
+ /* Iterate over all sections of all input BFDs, checking
+ for any that begin 'debug_' and are long names. */
+ LANG_FOR_EACH_INPUT_STATEMENT (is)
+ {
+ int found_debug = 0;
+ bfd_map_over_sections (is->the_bfd, debug_section_p, &found_debug);
+ if (found_debug)
+ {
+ pe_use_coff_long_section_names = 1;
+ break;
+ }
+ }
+ }
+
+ pe_output_file_set_long_section_names (link_info.output_bfd);
+
+#ifdef DLL_SUPPORT
+ if (pe_enable_stdcall_fixup) /* -1=warn or 1=disable */
+ pe_fixup_stdcalls ();
+
+ pe_process_import_defs (link_info.output_bfd, &link_info);
+
+ pe_find_data_imports ();
+
+#if defined (TARGET_IS_i386pe) \
+ || defined (TARGET_IS_armpe) \
+ || defined (TARGET_IS_arm_epoc_pe) \
+ || defined (TARGET_IS_arm_wince_pe)
+ if (!link_info.relocatable)
+ pe_dll_build_sections (link_info.output_bfd, &link_info);
+#else
+ if (link_info.shared)
+ pe_dll_build_sections (link_info.output_bfd, &link_info);
+ else
+ pe_exe_build_sections (link_info.output_bfd, &link_info);
+#endif
+#endif /* DLL_SUPPORT */
+
+#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) || defined(TARGET_IS_arm_wince_pe)
+ if (strstr (bfd_get_target (link_info.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_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 (CONST_STRNEQ (sec->name, ".idata\$"))
+ 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 relsize;
+ asymbol **symbols;
+ arelent **relocs;
+ int nrelocs;
+
+ relsize = bfd_get_reloc_upper_bound (is->the_bfd, sec);
+ if (relsize < 1)
+ break;
+
+ if (!bfd_generic_link_read_symbols (is->the_bfd))
+ {
+ einfo (_("%B%F: could not read symbols: %E\n"),
+ is->the_bfd);
+ return;
+ }
+ symbols = bfd_get_outsymbols (is->the_bfd);
+
+ relocs = 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\n");
+ return;
+ }
+
+ for (i = 0; i < nrelocs; i++)
+ {
+ struct bfd_symbol *s;
+ struct bfd_link_hash_entry * blhe;
+ char *other_bfd_filename;
+ 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_filename
+ = blhe->u.def.section->owner->my_archive
+ ? bfd_get_filename (blhe->u.def.section->owner->my_archive)
+ : bfd_get_filename (blhe->u.def.section->owner);
+
+ if (strcmp (bfd_get_filename (is->the_bfd->my_archive),
+ other_bfd_filename) == 0)
+ continue;
+
+ /* Rename this implib to match the other one. */
+ n = xmalloc (strlen (other_bfd_filename) + 1);
+ strcpy (n, other_bfd_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;
+ }
+ }
+ }
+ }
+
+ {
+ /* The following chunk of code tries to identify jump stubs in
+ import libraries which are dead code and eliminates them
+ from the final link. For each exported symbol <sym>, there
+ is a object file in the import library with a .text section
+ and several .idata\$* sections. The .text section contains the
+ symbol definition for <sym> which is a jump stub of the form
+ jmp *__imp_<sym>. The .idata\$5 contains the symbol definition
+ for __imp_<sym> which is the address of the slot for <sym> in
+ the import address table. When a symbol is imported explicitly
+ using __declspec(dllimport) declaration, the compiler generates
+ a reference to __imp_<sym> which directly resolves to the
+ symbol in .idata\$5, in which case the jump stub code is not
+ needed. The following code tries to identify jump stub sections
+ in import libraries which are not referred to by anyone and
+ marks them for exclusion from the final link. */
+ LANG_FOR_EACH_INPUT_STATEMENT (is)
+ {
+ if (is->the_bfd->my_archive)
+ {
+ int is_imp = 0;
+ asection *sec, *stub_sec = NULL;
+
+ /* See if this is an import library thunk. */
+ for (sec = is->the_bfd->sections; sec; sec = sec->next)
+ {
+ if (strncmp (sec->name, ".idata\$", 7) == 0)
+ is_imp = 1;
+ /* The section containing the jmp stub has code
+ and has a reloc. */
+ if ((sec->flags & SEC_CODE) && sec->reloc_count)
+ stub_sec = sec;
+ }
+
+ if (is_imp && stub_sec)
+ {
+ asymbol **symbols;
+ long nsyms, src_count;
+ struct bfd_link_hash_entry * blhe;
+
+ if (!bfd_generic_link_read_symbols (is->the_bfd))
+ {
+ einfo (_("%B%F: could not read symbols: %E\n"),
+ is->the_bfd);
+ return;
+ }
+ symbols = bfd_get_outsymbols (is->the_bfd);
+ nsyms = bfd_get_symcount (is->the_bfd);
+
+ for (src_count = 0; src_count < nsyms; src_count++)
+ {
+ if (symbols[src_count]->section->id == stub_sec->id)
+ {
+ /* This symbol belongs to the section containing
+ the stub. */
+ blhe = bfd_link_hash_lookup (link_info.hash,
+ symbols[src_count]->name,
+ FALSE, FALSE, TRUE);
+ /* If the symbol in the stub section has no other
+ undefined references, exclude the stub section
+ from the final link. */
+ if (blhe && (blhe->type == bfd_link_hash_defined)
+ && (blhe->u.undef.next == NULL))
+ stub_sec->flags |= SEC_EXCLUDE;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+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) || defined(TARGET_IS_arm_wince_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_process_before_allocation
+ (is->the_bfd, & link_info, support_old_code))
+ {
+ /* xgettext:c-format */
+ einfo (_("Errors encountered processing file %s for interworking\n"),
+ is->filename);
+ }
+ }
+ }
+
+ /* We have seen it all. Allocate it, and carry on. */
+ bfd_arm_allocate_interworking_sections (& link_info);
+#endif /* TARGET_IS_armpe || TARGET_IS_arm_epoc_pe || TARGET_IS_arm_wince_pe */
+
+ before_allocation_default ();
+}
+
+#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)
+ {
+ pe_def_file = 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 = xmalloc (buflen);
+
+ for (i = 0; i < pe_def_file->num_exports; i++)
+ {
+ struct bfd_link_hash_entry *h;
+
+ sprintf (buf, "%s%s", U (""), 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 (link_info.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 (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
+#ifdef TARGET_IS_arm_epoc_pe
+ pe_dll_id_target ("epoc-pei-arm-little");
+#endif
+#ifdef TARGET_IS_arm_wince_pe
+ pe_dll_id_target ("pei-arm-wince-little");
+#endif
+ if (pe_bfd_is_dll (entry->the_bfd))
+ return pe_implied_import_dll (entry->filename);
+#endif
+ return FALSE;
+}
+
+static void
+gld_${EMULATION_NAME}_finish (void)
+{
+#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) || defined(TARGET_IS_arm_wince_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 (link_info.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: cannot find thumb start symbol %s\n"), thumb_entry_symbol);
+ }
+#endif /* defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) || defined(TARGET_IS_arm_wince_pe) */
+
+ finish_default ();
+
+#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 (link_info.output_bfd, &link_info);
+ if (pe_implib_filename)
+ pe_dll_generate_implib (pe_def_file, pe_implib_filename, &link_info);
+ }
+#if defined(TARGET_IS_shpe) || defined(TARGET_IS_mipspe)
+ /* ARM doesn't need relocs. */
+ else
+ {
+ pe_exe_fill_sections (link_info.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 (link_info.output_bfd, ".idata");
+
+ if (asec)
+ {
+ asec->flags &= ~SEC_CODE;
+ asec->flags |= SEC_DATA;
+ }
+ }
+}
+
+
+/* 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. */
+
+static lang_output_section_statement_type *
+gld_${EMULATION_NAME}_place_orphan (asection *s,
+ const char *secname,
+ int constraint)
+{
+ const char *orig_secname = secname;
+ char *dollar = NULL;
+ lang_output_section_statement_type *os;
+ lang_statement_list_type add_child;
+ lang_statement_union_type **pl;
+
+ /* Look through the script to see where to place this section. */
+ if (!link_info.relocatable
+ && (dollar = strchr (secname, '\$')) != NULL)
+ {
+ size_t len = dollar - secname;
+ char *newname = xmalloc (len + 1);
+ memcpy (newname, secname, len);
+ newname[len] = '\0';
+ secname = newname;
+ }
+
+ lang_list_init (&add_child);
+
+ os = NULL;
+ if (constraint == 0)
+ for (os = lang_output_section_find (secname);
+ os != NULL;
+ os = next_matching_output_section_statement (os, 0))
+ {
+ /* If we don't match an existing output section, tell
+ lang_insert_orphan to create a new output section. */
+ constraint = SPECIAL;
+
+ if (os->bfd_section != NULL
+ && (os->bfd_section->flags == 0
+ || ((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 has compatible flags.
+ If the section already exists but does not have any flags set,
+ then it has been created by the linker, probably as a result of
+ a --section-start command line switch. */
+ lang_add_section (&add_child, s, os);
+ break;
+ }
+ }
+
+ if (os == NULL)
+ {
+ static struct orphan_save hold[] =
+ {
+ { ".text",
+ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE,
+ 0, 0, 0, 0 },
+ { ".rdata",
+ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
+ 0, 0, 0, 0 },
+ { ".data",
+ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA,
+ 0, 0, 0, 0 },
+ { ".bss",
+ SEC_ALLOC,
+ 0, 0, 0, 0 }
+ };
+ enum orphan_save_index
+ {
+ orphan_text = 0,
+ orphan_rodata,
+ orphan_data,
+ orphan_bss
+ };
+ static int orphan_init_done = 0;
+ struct orphan_save *place;
+ lang_output_section_statement_type *after;
+ etree_type *address;
+
+ if (!orphan_init_done)
+ {
+ struct orphan_save *ho;
+ for (ho = hold; ho < hold + sizeof (hold) / sizeof (hold[0]); ++ho)
+ if (ho->name != NULL)
+ {
+ ho->os = lang_output_section_find (ho->name);
+ if (ho->os != NULL && ho->os->flags == 0)
+ ho->os->flags = ho->flags;
+ }
+ orphan_init_done = 1;
+ }
+
+ /* Try to put the new output section in a reasonable place based
+ on the section name and section flags. */
+
+ place = NULL;
+ if ((s->flags & SEC_ALLOC) == 0)
+ ;
+ else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
+ place = &hold[orphan_bss];
+ else if ((s->flags & SEC_READONLY) == 0)
+ place = &hold[orphan_data];
+ else if ((s->flags & SEC_CODE) == 0)
+ place = &hold[orphan_rodata];
+ else
+ place = &hold[orphan_text];
+
+ after = NULL;
+ if (place != NULL)
+ {
+ if (place->os == NULL)
+ place->os = lang_output_section_find (place->name);
+ after = place->os;
+ if (after == NULL)
+ after = lang_output_section_find_by_flags (s, &place->os, NULL);
+ if (after == NULL)
+ /* *ABS* is always the first output section statement. */
+ after = (&lang_output_section_statement.head
+ ->output_section_statement);
+ }
+
+ /* All sections in an executable must be aligned to a page boundary. */
+ address = exp_unop (ALIGN_K, exp_nameop (NAME, "__section_alignment__"));
+ os = lang_insert_orphan (s, secname, constraint, after, place, address,
+ &add_child);
+ }
+
+ /* If the section name has a '\$', sort it with the other '\$'
+ sections. */
+ for (pl = &os->children.head; *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->section->owner, ls->section);
+ if (strchr (lname, '\$') != NULL
+ && (dollar == NULL || strcmp (orig_secname, lname) < 0))
+ break;
+ }
+
+ if (add_child.head != NULL)
+ {
+ *add_child.tail = *pl;
+ *pl = add_child.head;
+ }
+
+ return os;
+}
+
+static bfd_boolean
+gld_${EMULATION_NAME}_open_dynamic_archive
+ (const char *arch ATTRIBUTE_UNUSED,
+ search_dirs_type *search,
+ lang_input_statement_type *entry)
+{
+ static const struct
+ {
+ const char * format;
+ bfd_boolean use_prefix;
+ }
+ libname_fmt [] =
+ {
+ /* Preferred explicit import library for dll's. */
+ { "lib%s.dll.a", FALSE },
+ /* Alternate explicit import library for dll's. */
+ { "%s.dll.a", FALSE },
+ /* "libfoo.a" could be either an import lib or a static lib.
+ For backwards compatibility, libfoo.a needs to precede
+ libfoo.dll and foo.dll in the search. */
+ { "lib%s.a", FALSE },
+ /* The 'native' spelling of an import lib name is "foo.lib". */
+ { "%s.lib", FALSE },
+#ifdef DLL_SUPPORT
+ /* Try "<prefix>foo.dll" (preferred dll name, if specified). */
+ { "%s%s.dll", TRUE },
+#endif
+ /* Try "libfoo.dll" (default preferred dll name). */
+ { "lib%s.dll", FALSE },
+ /* Finally try 'native' dll name "foo.dll". */
+ { "%s.dll", FALSE },
+ /* Note: If adding more formats to this table, make sure to check to
+ see if their length is longer than libname_fmt[0].format, and if
+ so, update the call to xmalloc() below. */
+ { NULL, FALSE }
+ };
+ static unsigned int format_max_len = 0;
+ const char * filename;
+ char * full_string;
+ char * base_string;
+ unsigned int i;
+
+
+ if (! entry->is_archive)
+ return FALSE;
+
+ filename = entry->filename;
+
+ if (format_max_len == 0)
+ /* We need to allow space in the memory that we are going to allocate
+ for the characters in the format string. Since the format array is
+ static we only need to calculate this information once. In theory
+ this value could also be computed statically, but this introduces
+ the possibility for a discrepancy and hence a possible memory
+ corruption. The lengths we compute here will be too long because
+ they will include any formating characters (%s) in the strings, but
+ this will not matter. */
+ for (i = 0; libname_fmt[i].format; i++)
+ if (format_max_len < strlen (libname_fmt[i].format))
+ format_max_len = strlen (libname_fmt[i].format);
+
+ full_string = xmalloc (strlen (search->name)
+ + strlen (filename)
+ + format_max_len
+#ifdef DLL_SUPPORT
+ + (pe_dll_search_prefix
+ ? strlen (pe_dll_search_prefix) : 0)
+#endif
+ /* Allow for the terminating NUL and for the path
+ separator character that is inserted between
+ search->name and the start of the format string. */
+ + 2);
+
+ sprintf (full_string, "%s/", search->name);
+ base_string = full_string + strlen (full_string);
+
+ for (i = 0; libname_fmt[i].format; i++)
+ {
+#ifdef DLL_SUPPORT
+ if (libname_fmt[i].use_prefix)
+ {
+ if (!pe_dll_search_prefix)
+ continue;
+ sprintf (base_string, libname_fmt[i].format, pe_dll_search_prefix, filename);
+ }
+ else
+#endif
+ sprintf (base_string, libname_fmt[i].format, filename);
+
+ if (ldfile_try_open_bfd (full_string, entry))
+ break;
+ }
+
+ if (!libname_fmt[i].format)
+ {
+ free (full_string);
+ return FALSE;
+ }
+
+ entry->filename = full_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"
+
+fragment <<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
+if test -n "$GENERATE_AUTO_IMPORT_SCRIPT" ; then
+echo ' ; else if (link_info.pei386_auto_import == 1) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xa >> 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
+
+fragment <<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/binutils-2.20.1/ld/emultempl/pep.em b/binutils-2.20.1/ld/emultempl/pep.em
new file mode 100644
index 00000000..90af0205
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/pep.em
@@ -0,0 +1,1855 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+test -z "${ENTRY}" && ENTRY="_mainCRTStartup"
+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 ;-)
+fragment <<EOF
+/* Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+ Written by Kai Tietz, OneVision Software GmbH&CoKg.
+
+ This file is part of the GNU Binutils.
+
+ 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+
+/* For WINDOWS_XP64 and higher */
+/* Based on pe.em, but modified for 64 bit support. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#define COFF_IMAGE_WITH_PE
+#define COFF_WITH_PE
+#define COFF_WITH_pex64
+
+#include "sysdep.h"
+#include "bfd.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: See bfd/peXXigen.c for why we include an architecture specific
+ header in generic PE code. */
+#include "coff/x86_64.h"
+#include "coff/pe.h"
+
+/* FIXME: This is a BFD internal header file, and we should not be
+ using it here. */
+#include "../bfd/libcoff.h"
+
+#undef AOUTSZ
+#define AOUTSZ PEPAOUTSZ
+#define PEAOUTHDR PEPAOUTHDR
+
+#include "deffile.h"
+#include "pep-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
+
+#ifdef TARGET_IS_i386pep
+#define DLL_SUPPORT
+#endif
+
+#if defined(TARGET_IS_i386pep) || ! defined(DLL_SUPPORT)
+#define PE_DEF_SUBSYSTEM 3
+#else
+#undef NT_EXE_IMAGE_BASE
+#define NT_EXE_IMAGE_BASE 0x00010000
+#undef PE_DEF_SECTION_ALIGNMENT
+#define PE_DEF_SUBSYSTEM 2
+#undef PE_DEF_FILE_ALIGNMENT
+#define PE_DEF_FILE_ALIGNMENT 0x00000200
+#define PE_DEF_SECTION_ALIGNMENT 0x00000400
+#endif
+
+
+static struct internal_extra_pe_aouthdr pep;
+static int dll;
+static flagword real_flags = IMAGE_FILE_LARGE_ADDRESS_AWARE;
+static int support_old_code = 0;
+static lang_assignment_statement_type *image_base_statement = 0;
+static unsigned short pe_dll_characteristics = 0;
+
+#ifdef DLL_SUPPORT
+static int pep_enable_stdcall_fixup = 1; /* 0=disable 1=enable (default). */
+static char * pep_out_def_filename = NULL;
+static char * pep_implib_filename = NULL;
+static int pep_enable_auto_image_base = 0;
+static char * pep_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 = 2; /* Use by default version 2. */
+
+#if (PE_DEF_SUBSYSTEM == 9) || (PE_DEF_SUBSYSTEM == 2)
+ lang_default_entry ("_WinMainCRTStartup");
+#else
+ lang_default_entry ("${ENTRY}");
+#endif
+#endif
+}
+
+/* PE format extra command line options. */
+
+/* Used for setting flags in the PE header. */
+enum options
+{
+ OPTION_BASE_FILE = 300 + 1,
+ OPTION_DLL,
+ OPTION_FILE_ALIGNMENT,
+ OPTION_IMAGE_BASE,
+ OPTION_MAJOR_IMAGE_VERSION,
+ OPTION_MAJOR_OS_VERSION,
+ OPTION_MAJOR_SUBSYSTEM_VERSION,
+ OPTION_MINOR_IMAGE_VERSION,
+ OPTION_MINOR_OS_VERSION,
+ OPTION_MINOR_SUBSYSTEM_VERSION,
+ OPTION_SECTION_ALIGNMENT,
+ OPTION_STACK,
+ OPTION_SUBSYSTEM,
+ OPTION_HEAP,
+ OPTION_SUPPORT_OLD_CODE,
+ OPTION_OUT_DEF,
+ OPTION_EXPORT_ALL,
+ OPTION_EXCLUDE_SYMBOLS,
+ OPTION_KILL_ATS,
+ OPTION_STDCALL_ALIASES,
+ OPTION_ENABLE_STDCALL_FIXUP,
+ OPTION_DISABLE_STDCALL_FIXUP,
+ OPTION_IMPLIB_FILENAME,
+ OPTION_WARN_DUPLICATE_EXPORTS,
+ OPTION_IMP_COMPAT,
+ OPTION_ENABLE_AUTO_IMAGE_BASE,
+ OPTION_DISABLE_AUTO_IMAGE_BASE,
+ OPTION_DLL_SEARCH_PREFIX,
+ OPTION_NO_DEFAULT_EXCLUDES,
+ OPTION_DLL_ENABLE_AUTO_IMPORT,
+ OPTION_DLL_DISABLE_AUTO_IMPORT,
+ OPTION_ENABLE_EXTRA_PE_DEBUG,
+ OPTION_EXCLUDE_LIBS,
+ OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC,
+ OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC,
+ OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V1,
+ OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2,
+ OPTION_EXCLUDE_MODULES_FOR_IMPLIB,
+ OPTION_USE_NUL_PREFIXED_IMPORT_TABLES,
+ OPTION_ENABLE_LONG_SECTION_NAMES,
+ OPTION_DISABLE_LONG_SECTION_NAMES,
+ OPTION_DYNAMIC_BASE,
+ OPTION_FORCE_INTEGRITY,
+ OPTION_NX_COMPAT,
+ OPTION_NO_ISOLATION,
+ OPTION_NO_SEH,
+ OPTION_NO_BIND,
+ OPTION_WDM_DRIVER,
+ OPTION_TERMINAL_SERVER_AWARE
+};
+
+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},
+ {"use-nul-prefixed-import-tables", no_argument, NULL,
+ OPTION_USE_NUL_PREFIXED_IMPORT_TABLES},
+#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},
+ {"exclude-modules-for-implib", required_argument, NULL, OPTION_EXCLUDE_MODULES_FOR_IMPLIB},
+ {"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-pep-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},
+ {"enable-runtime-pseudo-reloc-v1", no_argument, NULL, OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V1},
+ {"enable-runtime-pseudo-reloc-v2", no_argument, NULL, OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2},
+#endif
+ {"enable-long-section-names", no_argument, NULL, OPTION_ENABLE_LONG_SECTION_NAMES},
+ {"disable-long-section-names", no_argument, NULL, OPTION_DISABLE_LONG_SECTION_NAMES},
+ {"dynamicbase",no_argument, NULL, OPTION_DYNAMIC_BASE},
+ {"forceinteg", no_argument, NULL, OPTION_FORCE_INTEGRITY},
+ {"nxcompat", no_argument, NULL, OPTION_NX_COMPAT},
+ {"no-isolation", no_argument, NULL, OPTION_NO_ISOLATION},
+ {"no-seh", no_argument, NULL, OPTION_NO_SEH},
+ {"no-bind", no_argument, NULL, OPTION_NO_BIND},
+ {"wdmdriver", no_argument, NULL, OPTION_WDM_DRIVER},
+ {"tsaware", no_argument, NULL, OPTION_TERMINAL_SERVER_AWARE},
+ {NULL, no_argument, NULL, 0}
+ };
+
+ *longopts
+ = 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;
+ bfd_vma value;
+ char *symbol;
+ int inited;
+} definfo;
+
+#define D(field,symbol,def) {&pep.field,sizeof(pep.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},
+#define MSIMAGEBASEOFF 2
+ D(ImageBase,"___ImageBase", NT_EXE_IMAGE_BASE),
+ 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__", 0),
+ D(MinorImageVersion,"__minor_image_version__", 0),
+ D(MajorSubsystemVersion,"__major_subsystem_version__", 5),
+ D(MinorSubsystemVersion,"__minor_subsystem_version__", 2),
+ 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),
+ D(DllCharacteristics, "__dll_characteristics__", 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"));
+#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, _(" --exclude-modules-for-implib mod,mod,...\n"));
+ fprintf (file, _(" Exclude objects, archive members from auto\n"));
+ fprintf (file, _(" export, place into import library instead.\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-pep-debug Enable verbose debug output when building\n\
+ or linking to DLLs (esp. auto-import)\n"));
+ fprintf (file, _(" --enable-long-section-names Use long COFF section names even in\n\
+ executable image files\n"));
+ fprintf (file, _(" --disable-long-section-names Never use long COFF section names, even\n\
+ in object files\n"));
+ fprintf (file, _(" --dynamicbase Image base address may be relocated using\n\
+ address space layout randomization (ASLR)\n"));
+ fprintf (file, _(" --forceinteg Code integrity checks are enforced\n"));
+ fprintf (file, _(" --nxcompat Image is compatible with data execution prevention\n"));
+ fprintf (file, _(" --no-isolation Image understands isolation but do not isolate the image\n"));
+ fprintf (file, _(" --no-seh Image does not use SEH. No SE handler may\n\
+ be called in this image\n"));
+ fprintf (file, _(" --no-bind Do not bind this image\n"));
+ fprintf (file, _(" --wdmdriver Driver uses the WDM model\n"));
+ fprintf (file, _(" --tsaware Image is Terminal Server aware\n"));
+#endif
+}
+
+
+static void
+set_pep_name (char *name, bfd_vma 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;
+ if (strcmp (name,"__image_base__") == 0)
+ set_pep_name ("___ImageBase", val);
+ return;
+ }
+ }
+ abort ();
+}
+
+
+static void
+set_pep_subsystem (void)
+{
+ const char *sver;
+ const char *entry;
+ const char *initial_symbol_char;
+ char *end;
+ int len;
+ int i;
+ int subsystem;
+ unsigned long temp_subsystem;
+ static const struct
+ {
+ const char *name;
+ const int value;
+ const char *entry;
+ }
+ v[] =
+ {
+ { "native", 1, "NtProcessStartup" },
+ { "windows", 2, "WinMainCRTStartup" },
+ { "console", 3, "mainCRTStartup" },
+ { "posix", 7, "__PosixProcessStartup"},
+ { "wince", 9, "_WinMainCRTStartup" },
+ { "xbox", 14, "mainCRTStartup" },
+ { NULL, 0, NULL }
+ };
+ /* Entry point name for arbitrary subsystem numbers. */
+ static const char default_entry[] = "mainCRTStartup";
+
+ /* Check for the presence of a version number. */
+ sver = strchr (optarg, ':');
+ if (sver == NULL)
+ len = strlen (optarg);
+ else
+ {
+ len = sver - optarg;
+ set_pep_name ("__major_subsystem_version__",
+ strtoul (sver + 1, &end, 0));
+ if (*end == '.')
+ set_pep_name ("__minor_subsystem_version__",
+ strtoul (end + 1, &end, 0));
+ if (*end != '\0')
+ einfo (_("%P: warning: bad version number in -subsystem option\n"));
+ }
+
+ /* Check for numeric subsystem. */
+ temp_subsystem = strtoul (optarg, & end, 0);
+ if ((*end == ':' || *end == '\0') && (temp_subsystem < 65536))
+ {
+ /* Search list for a numeric match to use its entry point. */
+ for (i = 0; v[i].name; i++)
+ if (v[i].value == (int) temp_subsystem)
+ break;
+
+ /* If no match, use the default. */
+ if (v[i].name != NULL)
+ entry = v[i].entry;
+ else
+ entry = default_entry;
+
+ /* Use this subsystem. */
+ subsystem = (int) temp_subsystem;
+ }
+ else
+ {
+ /* Search for subsystem by name. */
+ for (i = 0; v[i].name; i++)
+ if (strncmp (optarg, v[i].name, len) == 0
+ && v[i].name[len] == '\0')
+ break;
+
+ if (v[i].name == NULL)
+ {
+ einfo (_("%P%F: invalid subsystem type %s\n"), optarg);
+ return;
+ }
+
+ entry = v[i].entry;
+ subsystem = v[i].value;
+ }
+
+ set_pep_name ("__subsystem__", subsystem);
+
+ initial_symbol_char = ${INITIAL_SYMBOL_CHAR};
+ if (*initial_symbol_char != '\0')
+ {
+ char *alc_entry;
+
+ /* lang_default_entry expects its argument to be permanently
+ allocated, so we don't free this string. */
+ alc_entry = xmalloc (strlen (initial_symbol_char)
+ + strlen (entry)
+ + 1);
+ strcpy (alc_entry, initial_symbol_char);
+ strcat (alc_entry, entry);
+ entry = alc_entry;
+ }
+
+ lang_default_entry (entry);
+
+ return;
+}
+
+
+static void
+set_pep_value (char *name)
+{
+ char *end;
+
+ set_pep_name (name, (bfd_vma) strtoull (optarg, &end, 0));
+
+ if (end == optarg)
+ einfo (_("%P%F: invalid hex number for PE parameter '%s'\n"), optarg);
+
+ optarg = end;
+}
+
+
+static void
+set_pep_stack_heap (char *resname, char *comname)
+{
+ set_pep_value (resname);
+
+ if (*optarg == ',')
+ {
+ optarg++;
+ set_pep_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_pep_stack_heap ("__size_of_heap_reserve__", "__size_of_heap_commit__");
+ break;
+ case OPTION_STACK:
+ set_pep_stack_heap ("__size_of_stack_reserve__", "__size_of_stack_commit__");
+ break;
+ case OPTION_SUBSYSTEM:
+ set_pep_subsystem ();
+ break;
+ case OPTION_MAJOR_OS_VERSION:
+ set_pep_value ("__major_os_version__");
+ break;
+ case OPTION_MINOR_OS_VERSION:
+ set_pep_value ("__minor_os_version__");
+ break;
+ case OPTION_MAJOR_SUBSYSTEM_VERSION:
+ set_pep_value ("__major_subsystem_version__");
+ break;
+ case OPTION_MINOR_SUBSYSTEM_VERSION:
+ set_pep_value ("__minor_subsystem_version__");
+ break;
+ case OPTION_MAJOR_IMAGE_VERSION:
+ set_pep_value ("__major_image_version__");
+ break;
+ case OPTION_MINOR_IMAGE_VERSION:
+ set_pep_value ("__minor_image_version__");
+ break;
+ case OPTION_FILE_ALIGNMENT:
+ set_pep_value ("__file_alignment__");
+ break;
+ case OPTION_SECTION_ALIGNMENT:
+ set_pep_value ("__section_alignment__");
+ break;
+ case OPTION_DLL:
+ set_pep_name ("__dll__", 1);
+ break;
+ case OPTION_IMAGE_BASE:
+ set_pep_value ("__image_base__");
+ break;
+ case OPTION_SUPPORT_OLD_CODE:
+ support_old_code = 1;
+ break;
+ case OPTION_USE_NUL_PREFIXED_IMPORT_TABLES:
+ pep_use_nul_prefixed_import_tables = TRUE;
+ break;
+#ifdef DLL_SUPPORT
+ case OPTION_OUT_DEF:
+ pep_out_def_filename = xstrdup (optarg);
+ break;
+ case OPTION_EXPORT_ALL:
+ pep_dll_export_everything = 1;
+ break;
+ case OPTION_EXCLUDE_SYMBOLS:
+ pep_dll_add_excludes (optarg, EXCLUDESYMS);
+ break;
+ case OPTION_EXCLUDE_LIBS:
+ pep_dll_add_excludes (optarg, EXCLUDELIBS);
+ break;
+ case OPTION_EXCLUDE_MODULES_FOR_IMPLIB:
+ pep_dll_add_excludes (optarg, EXCLUDEFORIMPLIB);
+ break;
+ case OPTION_KILL_ATS:
+ pep_dll_kill_ats = 1;
+ break;
+ case OPTION_STDCALL_ALIASES:
+ pep_dll_stdcall_aliases = 1;
+ break;
+ case OPTION_ENABLE_STDCALL_FIXUP:
+ pep_enable_stdcall_fixup = 1;
+ break;
+ case OPTION_DISABLE_STDCALL_FIXUP:
+ pep_enable_stdcall_fixup = 0;
+ break;
+ case OPTION_IMPLIB_FILENAME:
+ pep_implib_filename = xstrdup (optarg);
+ break;
+ case OPTION_WARN_DUPLICATE_EXPORTS:
+ pep_dll_warn_dup_exports = 1;
+ break;
+ case OPTION_IMP_COMPAT:
+ pep_dll_compat_implib = 1;
+ break;
+ case OPTION_ENABLE_AUTO_IMAGE_BASE:
+ pep_enable_auto_image_base = 1;
+ break;
+ case OPTION_DISABLE_AUTO_IMAGE_BASE:
+ pep_enable_auto_image_base = 0;
+ break;
+ case OPTION_DLL_SEARCH_PREFIX:
+ pep_dll_search_prefix = xstrdup (optarg);
+ break;
+ case OPTION_NO_DEFAULT_EXCLUDES:
+ pep_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 = 2;
+ break;
+ case OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC:
+ link_info.pei386_runtime_pseudo_reloc = 0;
+ break;
+ case OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V1:
+ link_info.pei386_runtime_pseudo_reloc = 1;
+ break;
+ case OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2:
+ link_info.pei386_runtime_pseudo_reloc = 2;
+ break;
+ case OPTION_ENABLE_EXTRA_PE_DEBUG:
+ pep_dll_extra_pe_debug = 1;
+ break;
+#endif
+ case OPTION_ENABLE_LONG_SECTION_NAMES:
+ pep_use_coff_long_section_names = 1;
+ break;
+ case OPTION_DISABLE_LONG_SECTION_NAMES:
+ pep_use_coff_long_section_names = 0;
+ break;
+ /* Get DLLCharacteristics bits */
+ case OPTION_DYNAMIC_BASE:
+ pe_dll_characteristics |= IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE;
+ break;
+ case OPTION_FORCE_INTEGRITY:
+ pe_dll_characteristics |= IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY;
+ break;
+ case OPTION_NX_COMPAT:
+ pe_dll_characteristics |= IMAGE_DLL_CHARACTERISTICS_NX_COMPAT;
+ break;
+ case OPTION_NO_ISOLATION:
+ pe_dll_characteristics |= IMAGE_DLLCHARACTERISTICS_NO_ISOLATION;
+ break;
+ case OPTION_NO_SEH:
+ pe_dll_characteristics |= IMAGE_DLLCHARACTERISTICS_NO_SEH;
+ break;
+ case OPTION_NO_BIND:
+ pe_dll_characteristics |= IMAGE_DLLCHARACTERISTICS_NO_BIND;
+ break;
+ case OPTION_WDM_DRIVER:
+ pe_dll_characteristics |= IMAGE_DLLCHARACTERISTICS_WDM_DRIVER;
+ break;
+ case OPTION_TERMINAL_SERVER_AWARE:
+ pe_dll_characteristics |= IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE;
+ break;
+ }
+
+ /* Set DLLCharacteristics bits */
+ set_pep_name ("__dll_characteristics__", pe_dll_characteristics);
+
+ 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 bfd_vma
+compute_dll_image_base (const char *ofile)
+{
+ bfd_vma hash = (bfd_vma) strhash (ofile);
+ return 0x61300000 + ((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;
+
+ if (!init[IMAGEBASEOFF].inited)
+ {
+ if (link_info.relocatable)
+ init[IMAGEBASEOFF].value = 0;
+ else if (init[DLLOFF].value || (link_info.shared && !link_info.pie))
+ {
+#ifdef DLL_SUPPORT
+ init[IMAGEBASEOFF].value = (pep_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;
+ init[MSIMAGEBASEOFF].value = init[IMAGEBASEOFF].value;
+ }
+
+ /* Don't do any symbol assignments if this is a relocatable link. */
+ if (link_info.relocatable)
+ return;
+
+ /* Glue the assignments into the abs section. */
+ push_stat_ptr (&abs_output_section->children);
+
+ for (j = 0; init[j].ptr; j++)
+ {
+ bfd_vma 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 = (short) val;
+ else if (init[j].size == sizeof (int))
+ *(int *) init[j].ptr = (int) val;
+ else if (init[j].size == sizeof (long))
+ *(long *) init[j].ptr = (long) 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. */
+ pop_stat_ptr ();
+
+ if (pep.FileAlignment > pep.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)
+{
+ /* PR ld/6744: Warn the user if they have used an ELF-only
+ option hoping it will work on PE+. */
+ if (link_info.export_dynamic)
+ einfo (_("%P: warning: --export-dynamic is not supported for PE+ "
+ "targets, did you mean --export-all-symbols?\n"));
+
+ after_parse_default ();
+}
+
+/* pep-dll.c directly accesses pep_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 * pep_data_import_dll;
+
+#ifdef DLL_SUPPORT
+static struct bfd_link_hash_entry *pep_undef_found_sym;
+
+static bfd_boolean
+pep_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] == '@')
+ {
+ pep_undef_found_sym = h;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+pep_fixup_stdcalls (void)
+{
+ static int gave_warning_message = 0;
+ struct bfd_link_hash_entry *undef, *sym;
+
+ if (pep_dll_extra_pe_debug)
+ printf ("%s\n", __FUNCTION__);
+
+ for (undef = link_info.hash->undefs; undef; undef=undef->u.undef.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 (pep_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. */
+ pep_undef_found_sym = 0;
+ bfd_link_hash_traverse (link_info.hash, pep_undef_cdecl_match,
+ (char *) undef->root.string);
+ sym = pep_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 (pep_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;
+ char addend[8];
+ bfd_vma _addend = 0;
+ int suc = 0;
+
+ if (pep_dll_extra_pe_debug)
+ printf ("arelent: %s@%#lx: add=%li\n", sym->name,
+ (unsigned long) rel->address, (long) rel->addend);
+
+ memset (addend, 0, sizeof (addend));
+ switch ((rel->howto->bitsize))
+ {
+ case 8:
+ suc = bfd_get_section_contents (s->owner, s, addend, rel->address, 1);
+ if (suc && rel->howto->pc_relative)
+ _addend = (bfd_vma) ((bfd_signed_vma) ((char) bfd_get_8 (s->owner, addend)));
+ else if (suc)
+ _addend = ((bfd_vma) bfd_get_8 (s->owner, addend)) & 0xff;
+ break;
+ case 16:
+ suc = bfd_get_section_contents (s->owner, s, addend, rel->address, 2);
+ if (suc && rel->howto->pc_relative)
+ _addend = (bfd_vma) ((bfd_signed_vma) ((short) bfd_get_16 (s->owner, addend)));
+ else if (suc)
+ _addend = ((bfd_vma) bfd_get_16 (s->owner, addend)) & 0xffff;
+ break;
+ case 32:
+ suc = bfd_get_section_contents (s->owner, s, addend, rel->address, 4);
+ if (suc && rel->howto->pc_relative)
+ _addend = (bfd_vma) ((bfd_signed_vma) ((int) bfd_get_32 (s->owner, addend)));
+ else if (suc)
+ _addend = ((bfd_vma) bfd_get_32 (s->owner, addend)) & 0xffffffff;
+ break;
+ case 64:
+ suc = bfd_get_section_contents (s->owner, s, addend, rel->address, 8);
+ if (suc)
+ _addend = ((bfd_vma) bfd_get_64 (s->owner, addend));
+ break;
+ }
+ if (! suc)
+ einfo (_("%C: Cannot get section contents - auto-import exception\n"),
+ s->owner, s, rel->address);
+
+ if (pep_dll_extra_pe_debug)
+ {
+ printf ("import of 0x%lx(0x%lx) sec_addr=0x%lx", (long) _addend, (long) rel->addend, (long) rel->address);
+ if (rel->howto->pc_relative) printf (" pcrel");
+ printf (" %d bit rel.\n",(int) rel->howto->bitsize);
+ }
+ pep_create_import_fixup (rel, s, _addend);
+
+ return 1;
+}
+
+static void
+pep_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->u.undef.next)
+ {
+ if (undef->type == bfd_link_hash_undefined)
+ {
+ /* C++ symbols are *long*. */
+ char buf[4096];
+
+ if (pep_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, i;
+
+ if (link_info.pei386_auto_import == -1)
+ {
+ static bfd_boolean warned = FALSE;
+
+ info_msg (_("Info: resolving %s by linking to %s (auto-import)\n"),
+ undef->root.string, buf);
+
+ /* PR linker/4844. */
+ if (! warned)
+ {
+ warned = TRUE;
+ einfo (_("%P: warning: auto-importing has been activated without --enable-auto-import specified on the command line.\n\
+This should work unless it involves constant data structures referencing symbols from auto-imported DLLs.\n"));
+ }
+ }
+
+ if (!bfd_generic_link_read_symbols (b))
+ {
+ einfo (_("%B%F: could not read symbols: %E\n"), b);
+ return;
+ }
+
+ symbols = bfd_get_outsymbols (b);
+ nsyms = bfd_get_symcount (b);
+
+ for (i = 0; i < nsyms; i++)
+ {
+ if (! CONST_STRNEQ (symbols[i]->name, "__head_"))
+ continue;
+
+ if (pep_dll_extra_pe_debug)
+ printf ("->%s\n", symbols[i]->name);
+
+ pep_data_import_dll = (char*) (symbols[i]->name +
+ sizeof ("__head_") - 1);
+ break;
+ }
+
+ pep_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 (pep_dll_extra_pe_debug)
+ printf ("+%s\n", h->string);
+
+ return TRUE;
+}
+#endif /* DLL_SUPPORT */
+
+static void
+debug_section_p (bfd *abfd ATTRIBUTE_UNUSED, asection *sect, void *obj)
+{
+ int *found = (int *) obj;
+ if (strncmp (".debug_", sect->name, sizeof (".debug_") - 1) == 0)
+ *found = 1;
+}
+
+static void
+gld_${EMULATION_NAME}_after_open (void)
+{
+#ifdef DLL_SUPPORT
+ if (pep_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->u.undef.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 (link_info.output_bfd) == NULL
+ || coff_data (link_info.output_bfd)->pe == 0)
+ einfo (_("%F%P: cannot perform PE operations on non PE output file '%B'.\n"),
+ link_info.output_bfd);
+
+ pe_data (link_info.output_bfd)->pe_opthdr = pep;
+ pe_data (link_info.output_bfd)->dll = init[DLLOFF].value;
+ pe_data (link_info.output_bfd)->real_flags |= real_flags;
+
+ /* At this point we must decide whether to use long section names
+ in the output or not. If the user hasn't explicitly specified
+ on the command line, we leave it to the default for the format
+ (object files yes, image files no), except if there is debug
+ information present; GDB relies on the long section names to
+ find it, so enable it in that case. */
+ if (pep_use_coff_long_section_names < 0 && link_info.strip == strip_none)
+ {
+ /* Iterate over all sections of all input BFDs, checking
+ for any that begin 'debug_' and are long names. */
+ LANG_FOR_EACH_INPUT_STATEMENT (is)
+ {
+ int found_debug = 0;
+ bfd_map_over_sections (is->the_bfd, debug_section_p, &found_debug);
+ if (found_debug)
+ {
+ pep_use_coff_long_section_names = 1;
+ break;
+ }
+ }
+ }
+
+ pep_output_file_set_long_section_names (link_info.output_bfd);
+
+#ifdef DLL_SUPPORT
+ if (pep_enable_stdcall_fixup) /* -1=warn or 1=disable */
+ pep_fixup_stdcalls ();
+
+ pep_process_import_defs (link_info.output_bfd, &link_info);
+
+ pep_find_data_imports ();
+
+#ifndef TARGET_IS_i386pep
+ if (link_info.shared)
+#else
+ if (!link_info.relocatable)
+#endif
+ pep_dll_build_sections (link_info.output_bfd, &link_info);
+
+#ifndef TARGET_IS_i386pep
+ else
+ pep_exe_build_sections (link_info.output_bfd, &link_info);
+#endif
+#endif /* DLL_SUPPORT */
+
+ {
+ /* 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 (CONST_STRNEQ (sec->name, ".idata\$"))
+ 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 relsize;
+ asymbol **symbols;
+ arelent **relocs;
+ int nrelocs;
+
+ relsize = bfd_get_reloc_upper_bound (is->the_bfd, sec);
+ if (relsize < 1)
+ break;
+
+ if (!bfd_generic_link_read_symbols (is->the_bfd))
+ {
+ einfo (_("%B%F: could not read symbols: %E\n"),
+ is->the_bfd);
+ return;
+ }
+ symbols = bfd_get_outsymbols (is->the_bfd);
+
+ relocs = 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\n");
+ return;
+ }
+
+ for (i = 0; i < nrelocs; i++)
+ {
+ struct bfd_symbol *s;
+ struct bfd_link_hash_entry * blhe;
+ char *other_bfd_filename;
+ 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_filename
+ = blhe->u.def.section->owner->my_archive
+ ? bfd_get_filename (blhe->u.def.section->owner->my_archive)
+ : bfd_get_filename (blhe->u.def.section->owner);
+
+ if (strcmp (bfd_get_filename (is->the_bfd->my_archive),
+ other_bfd_filename) == 0)
+ continue;
+
+ /* Rename this implib to match the other one. */
+ n = xmalloc (strlen (other_bfd_filename) + 1);
+ strcpy (n, other_bfd_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)
+{
+ before_allocation_default ();
+}
+
+#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)
+ {
+ pep_def_file = def_file_parse (entry->filename, pep_def_file);
+
+ if (pep_def_file)
+ {
+ int i, buflen=0, len;
+ char *buf;
+
+ for (i = 0; i < pep_def_file->num_exports; i++)
+ {
+ len = strlen (pep_def_file->exports[i].internal_name);
+ if (buflen < len + 2)
+ buflen = len + 2;
+ }
+
+ buf = xmalloc (buflen);
+
+ for (i = 0; i < pep_def_file->num_exports; i++)
+ {
+ struct bfd_link_hash_entry *h;
+
+ sprintf (buf, "_%s", pep_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, pep_def_file); */
+ if (pep_def_file->is_dll == 1)
+ link_info.shared = 1;
+
+ if (pep_def_file->base_address != (bfd_vma)(-1))
+ {
+ pep.ImageBase
+ = pe_data (link_info.output_bfd)->pe_opthdr.ImageBase
+ = init[IMAGEBASEOFF].value
+ = pep_def_file->base_address;
+ init[IMAGEBASEOFF].inited = 1;
+ if (image_base_statement)
+ image_base_statement->exp = exp_assop ('=', "__image_base__",
+ exp_intop (pep.ImageBase));
+ }
+
+ if (pep_def_file->stack_reserve != -1
+ && ! saw_option ("__size_of_stack_reserve__"))
+ {
+ pep.SizeOfStackReserve = pep_def_file->stack_reserve;
+ if (pep_def_file->stack_commit != -1)
+ pep.SizeOfStackCommit = pep_def_file->stack_commit;
+ }
+ if (pep_def_file->heap_reserve != -1
+ && ! saw_option ("__size_of_heap_reserve__"))
+ {
+ pep.SizeOfHeapReserve = pep_def_file->heap_reserve;
+ if (pep_def_file->heap_commit != -1)
+ pep.SizeOfHeapCommit = pep_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_i386pep
+ pep_dll_id_target ("pei-x86-64");
+#endif
+ if (pep_bfd_is_dll (entry->the_bfd))
+ return pep_implied_import_dll (entry->filename);
+#endif
+ return FALSE;
+}
+
+static void
+gld_${EMULATION_NAME}_finish (void)
+{
+ finish_default ();
+
+#ifdef DLL_SUPPORT
+ if (link_info.shared
+ || (!link_info.relocatable && pep_def_file->num_exports != 0))
+ {
+ pep_dll_fill_sections (link_info.output_bfd, &link_info);
+ if (pep_implib_filename)
+ pep_dll_generate_implib (pep_def_file, pep_implib_filename, &link_info);
+ }
+
+ if (pep_out_def_filename)
+ pep_dll_generate_def_file (pep_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 (link_info.output_bfd, ".idata");
+
+ if (asec)
+ {
+ asec->flags &= ~SEC_CODE;
+ asec->flags |= SEC_DATA;
+ }
+ }
+}
+
+
+/* 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. */
+
+static lang_output_section_statement_type *
+gld_${EMULATION_NAME}_place_orphan (asection *s,
+ const char *secname,
+ int constraint)
+{
+ const char *orig_secname = secname;
+ char *dollar = NULL;
+ lang_output_section_statement_type *os;
+ lang_statement_list_type add_child;
+ lang_statement_union_type **pl;
+
+ /* Look through the script to see where to place this section. */
+ if (!link_info.relocatable
+ && (dollar = strchr (secname, '\$')) != NULL)
+ {
+ size_t len = dollar - secname;
+ char *newname = xmalloc (len + 1);
+ memcpy (newname, secname, len);
+ newname[len] = '\0';
+ secname = newname;
+ }
+
+ lang_list_init (&add_child);
+
+ os = NULL;
+ if (constraint == 0)
+ for (os = lang_output_section_find (secname);
+ os != NULL;
+ os = next_matching_output_section_statement (os, 0))
+ {
+ /* If we don't match an existing output section, tell
+ lang_insert_orphan to create a new output section. */
+ constraint = SPECIAL;
+
+ if (os->bfd_section != NULL
+ && (os->bfd_section->flags == 0
+ || ((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 has compatible flags.
+ If the section already exists but does not have any flags set,
+ then it has been created by the linker, probably as a result of
+ a --section-start command line switch. */
+ lang_add_section (&add_child, s, os);
+ break;
+ }
+ }
+
+ if (os == NULL)
+ {
+ static struct orphan_save hold[] =
+ {
+ { ".text",
+ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE,
+ 0, 0, 0, 0 },
+ { ".rdata",
+ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
+ 0, 0, 0, 0 },
+ { ".data",
+ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA,
+ 0, 0, 0, 0 },
+ { ".bss",
+ SEC_ALLOC,
+ 0, 0, 0, 0 }
+ };
+ enum orphan_save_index
+ {
+ orphan_text = 0,
+ orphan_rodata,
+ orphan_data,
+ orphan_bss
+ };
+ static int orphan_init_done = 0;
+ struct orphan_save *place;
+ lang_output_section_statement_type *after;
+ etree_type *address;
+
+ if (!orphan_init_done)
+ {
+ struct orphan_save *ho;
+ for (ho = hold; ho < hold + sizeof (hold) / sizeof (hold[0]); ++ho)
+ if (ho->name != NULL)
+ {
+ ho->os = lang_output_section_find (ho->name);
+ if (ho->os != NULL && ho->os->flags == 0)
+ ho->os->flags = ho->flags;
+ }
+ orphan_init_done = 1;
+ }
+
+ /* Try to put the new output section in a reasonable place based
+ on the section name and section flags. */
+
+ place = NULL;
+ if ((s->flags & SEC_ALLOC) == 0)
+ ;
+ else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
+ place = &hold[orphan_bss];
+ else if ((s->flags & SEC_READONLY) == 0)
+ place = &hold[orphan_data];
+ else if ((s->flags & SEC_CODE) == 0)
+ place = &hold[orphan_rodata];
+ else
+ place = &hold[orphan_text];
+
+ after = NULL;
+ if (place != NULL)
+ {
+ if (place->os == NULL)
+ place->os = lang_output_section_find (place->name);
+ after = place->os;
+ if (after == NULL)
+ after = lang_output_section_find_by_flags (s, &place->os, NULL);
+ if (after == NULL)
+ /* *ABS* is always the first output section statement. */
+ after = (&lang_output_section_statement.head
+ ->output_section_statement);
+ }
+
+ /* All sections in an executable must be aligned to a page boundary. */
+ address = exp_unop (ALIGN_K, exp_nameop (NAME, "__section_alignment__"));
+ os = lang_insert_orphan (s, secname, constraint, after, place, address,
+ &add_child);
+ }
+
+ /* If the section name has a '\$', sort it with the other '\$'
+ sections. */
+ for (pl = &os->children.head; *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->section->owner, ls->section);
+ if (strchr (lname, '\$') != NULL
+ && (dollar == NULL || strcmp (orig_secname, lname) < 0))
+ break;
+ }
+
+ if (add_child.head != NULL)
+ {
+ *add_child.tail = *pl;
+ *pl = add_child.head;
+ }
+
+ return os;
+}
+
+static bfd_boolean
+gld_${EMULATION_NAME}_open_dynamic_archive
+ (const char *arch ATTRIBUTE_UNUSED,
+ search_dirs_type *search,
+ lang_input_statement_type *entry)
+{
+ static const struct
+ {
+ const char * format;
+ bfd_boolean use_prefix;
+ }
+ libname_fmt [] =
+ {
+ /* Preferred explicit import library for dll's. */
+ { "lib%s.dll.a", FALSE },
+ /* Alternate explicit import library for dll's. */
+ { "%s.dll.a", FALSE },
+ /* "libfoo.a" could be either an import lib or a static lib.
+ For backwards compatibility, libfoo.a needs to precede
+ libfoo.dll and foo.dll in the search. */
+ { "lib%s.a", FALSE },
+ /* The 'native' spelling of an import lib name is "foo.lib". */
+ { "%s.lib", FALSE },
+#ifdef DLL_SUPPORT
+ /* Try "<prefix>foo.dll" (preferred dll name, if specified). */
+ { "%s%s.dll", TRUE },
+#endif
+ /* Try "libfoo.dll" (default preferred dll name). */
+ { "lib%s.dll", FALSE },
+ /* Finally try 'native' dll name "foo.dll". */
+ { "%s.dll", FALSE },
+ /* Note: If adding more formats to this table, make sure to check to
+ see if their length is longer than libname_fmt[0].format, and if
+ so, update the call to xmalloc() below. */
+ { NULL, FALSE }
+ };
+ static unsigned int format_max_len = 0;
+ const char * filename;
+ char * full_string;
+ char * base_string;
+ unsigned int i;
+
+
+ if (! entry->is_archive)
+ return FALSE;
+
+ filename = entry->filename;
+
+ if (format_max_len == 0)
+ /* We need to allow space in the memory that we are going to allocate
+ for the characters in the format string. Since the format array is
+ static we only need to calculate this information once. In theory
+ this value could also be computed statically, but this introduces
+ the possibility for a discrepancy and hence a possible memory
+ corruption. The lengths we compute here will be too long because
+ they will include any formating characters (%s) in the strings, but
+ this will not matter. */
+ for (i = 0; libname_fmt[i].format; i++)
+ if (format_max_len < strlen (libname_fmt[i].format))
+ format_max_len = strlen (libname_fmt[i].format);
+
+ full_string = xmalloc (strlen (search->name)
+ + strlen (filename)
+ + format_max_len
+#ifdef DLL_SUPPORT
+ + (pep_dll_search_prefix
+ ? strlen (pep_dll_search_prefix) : 0)
+#endif
+ /* Allow for the terminating NUL and for the path
+ separator character that is inserted between
+ search->name and the start of the format string. */
+ + 2);
+
+ sprintf (full_string, "%s/", search->name);
+ base_string = full_string + strlen (full_string);
+
+ for (i = 0; libname_fmt[i].format; i++)
+ {
+#ifdef DLL_SUPPORT
+ if (libname_fmt[i].use_prefix)
+ {
+ if (!pep_dll_search_prefix)
+ continue;
+ sprintf (base_string, libname_fmt[i].format, pep_dll_search_prefix, filename);
+ }
+ else
+#endif
+ sprintf (base_string, libname_fmt[i].format, filename);
+
+ if (ldfile_try_open_bfd (full_string, entry))
+ break;
+ }
+
+ if (!libname_fmt[i].format)
+ {
+ free (full_string);
+ return FALSE;
+ }
+
+ entry->filename = full_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"
+
+fragment <<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
+if test -n "$GENERATE_AUTO_IMPORT_SCRIPT" ; then
+echo ' ; else if (link_info.pei386_auto_import == 1) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xa >> 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
+
+fragment <<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/binutils-2.20.1/ld/emultempl/ppc32elf.em b/binutils-2.20.1/ld/emultempl/ppc32elf.em
new file mode 100644
index 00000000..3befe750
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/ppc32elf.em
@@ -0,0 +1,244 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2003, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+# This file is sourced from elf32.em, and defines extra powerpc32-elf
+# specific routines.
+#
+fragment <<EOF
+
+#include "libbfd.h"
+#include "elf32-ppc.h"
+
+#define is_ppc_elf(bfd) \
+ (bfd_get_flavour (bfd) == bfd_target_elf_flavour \
+ && elf_object_id (bfd) == PPC32_ELF_TDATA)
+
+/* Whether to run tls optimization. */
+static int notlsopt = 0;
+static int no_tls_get_addr_opt = 0;
+
+/* Whether to emit symbols for stubs. */
+static int emit_stub_syms = -1;
+
+/* Chooses the correct place for .plt and .got. */
+static enum ppc_elf_plt_type plt_style = PLT_UNSET;
+static int old_got = 0;
+
+static void
+ppc_after_open (void)
+{
+ if (is_ppc_elf (link_info.output_bfd))
+ {
+ int new_plt;
+ int keep_new;
+ unsigned int num_plt;
+ unsigned int num_got;
+ lang_output_section_statement_type *os;
+ lang_output_section_statement_type *plt_os[2];
+ lang_output_section_statement_type *got_os[2];
+
+ if (emit_stub_syms < 0)
+ emit_stub_syms = link_info.emitrelocations || link_info.shared;
+ new_plt = ppc_elf_select_plt_layout (link_info.output_bfd, &link_info,
+ plt_style, emit_stub_syms);
+ if (new_plt < 0)
+ einfo ("%X%P: select_plt_layout problem %E\n");
+
+ num_got = 0;
+ num_plt = 0;
+ for (os = &lang_output_section_statement.head->output_section_statement;
+ os != NULL;
+ os = os->next)
+ {
+ if (os->constraint == SPECIAL && strcmp (os->name, ".plt") == 0)
+ {
+ if (num_plt < 2)
+ plt_os[num_plt] = os;
+ ++num_plt;
+ }
+ if (os->constraint == SPECIAL && strcmp (os->name, ".got") == 0)
+ {
+ if (num_got < 2)
+ got_os[num_got] = os;
+ ++num_got;
+ }
+ }
+
+ keep_new = new_plt == 1 ? 0 : -1;
+ if (num_plt == 2)
+ {
+ plt_os[0]->constraint = keep_new;
+ plt_os[1]->constraint = ~keep_new;
+ }
+ if (num_got == 2)
+ {
+ if (old_got)
+ keep_new = -1;
+ got_os[0]->constraint = keep_new;
+ got_os[1]->constraint = ~keep_new;
+ }
+ }
+
+ gld${EMULATION_NAME}_after_open ();
+}
+
+static void
+ppc_before_allocation (void)
+{
+ if (is_ppc_elf (link_info.output_bfd))
+ {
+ if (ppc_elf_tls_setup (link_info.output_bfd, &link_info,
+ no_tls_get_addr_opt)
+ && !notlsopt)
+ {
+ if (!ppc_elf_tls_optimize (link_info.output_bfd, &link_info))
+ {
+ einfo ("%X%P: TLS problem %E\n");
+ return;
+ }
+ }
+ }
+
+ gld${EMULATION_NAME}_before_allocation ();
+
+ /* Turn on relaxation if executable sections have addresses that
+ might make branches overflow. */
+ if (!command_line.relax)
+ {
+ bfd_vma low = (bfd_vma) -1;
+ bfd_vma high = 0;
+ asection *o;
+
+ /* Run lang_size_sections (if not already done). */
+ if (expld.phase != lang_mark_phase_enum)
+ {
+ expld.phase = lang_mark_phase_enum;
+ expld.dataseg.phase = exp_dataseg_none;
+ one_lang_size_sections_pass (NULL, FALSE);
+ lang_reset_memory_regions ();
+ }
+
+ for (o = link_info.output_bfd->sections; o != NULL; o = o->next)
+ {
+ if ((o->flags & (SEC_ALLOC | SEC_CODE)) != (SEC_ALLOC | SEC_CODE))
+ continue;
+ if (o->rawsize == 0)
+ continue;
+ if (low > o->vma)
+ low = o->vma;
+ if (high < o->vma + o->rawsize - 1)
+ high = o->vma + o->rawsize - 1;
+ }
+ if (high > low && high - low > (1 << 25) - 1)
+ command_line.relax = TRUE;
+ }
+}
+
+EOF
+
+if grep -q 'ld_elf32_spu_emulation' ldemul-list.h; then
+ fragment <<EOF
+/* Special handling for embedded SPU executables. */
+extern bfd_boolean embedded_spu_file (lang_input_statement_type *, const char *);
+static bfd_boolean gld${EMULATION_NAME}_load_symbols (lang_input_statement_type *);
+
+static bfd_boolean
+ppc_recognized_file (lang_input_statement_type *entry)
+{
+ if (embedded_spu_file (entry, "-m32"))
+ return TRUE;
+
+ return gld${EMULATION_NAME}_load_symbols (entry);
+}
+
+EOF
+LDEMUL_RECOGNIZED_FILE=ppc_recognized_file
+fi
+
+# 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
+#define OPTION_NO_TLS_GET_ADDR_OPT (OPTION_NO_TLS_OPT + 1)
+#define OPTION_NEW_PLT (OPTION_NO_TLS_GET_ADDR_OPT + 1)
+#define OPTION_OLD_PLT (OPTION_NEW_PLT + 1)
+#define OPTION_OLD_GOT (OPTION_OLD_PLT + 1)
+#define OPTION_STUBSYMS (OPTION_OLD_GOT + 1)
+#define OPTION_NO_STUBSYMS (OPTION_STUBSYMS + 1)
+'
+
+PARSE_AND_LIST_LONGOPTS='
+ { "emit-stub-syms", no_argument, NULL, OPTION_STUBSYMS },
+ { "no-emit-stub-syms", no_argument, NULL, OPTION_NO_STUBSYMS },
+ { "no-tls-optimize", no_argument, NULL, OPTION_NO_TLS_OPT },
+ { "no-tls-get-addr-optimize", no_argument, NULL, OPTION_NO_TLS_GET_ADDR_OPT },
+ { "secure-plt", no_argument, NULL, OPTION_NEW_PLT },
+ { "bss-plt", no_argument, NULL, OPTION_OLD_PLT },
+ { "sdata-got", no_argument, NULL, OPTION_OLD_GOT },
+'
+
+PARSE_AND_LIST_OPTIONS='
+ fprintf (file, _("\
+ --emit-stub-syms Label linker stubs with a symbol.\n\
+ --no-emit-stub-syms Don'\''t label linker stubs with a symbol.\n\
+ --no-tls-optimize Don'\''t try to optimize TLS accesses.\n\
+ --no-tls-get-addr-optimize Don'\''t use a special __tls_get_addr call.\n\
+ --secure-plt Use new-style PLT if possible.\n\
+ --bss-plt Force old-style BSS PLT.\n\
+ --sdata-got Force GOT location just before .sdata.\n"
+ ));
+'
+
+PARSE_AND_LIST_ARGS_CASES='
+ case OPTION_STUBSYMS:
+ emit_stub_syms = 1;
+ break;
+
+ case OPTION_NO_STUBSYMS:
+ emit_stub_syms = 0;
+ break;
+
+ case OPTION_NO_TLS_OPT:
+ notlsopt = 1;
+ break;
+
+ case OPTION_NO_TLS_GET_ADDR_OPT:
+ no_tls_get_addr_opt = 1;
+ break;
+
+ case OPTION_NEW_PLT:
+ plt_style = PLT_NEW;
+ break;
+
+ case OPTION_OLD_PLT:
+ plt_style = PLT_OLD;
+ break;
+
+ case OPTION_OLD_GOT:
+ old_got = 1;
+ break;
+'
+
+# Put these extra ppc32elf routines in ld_${EMULATION_NAME}_emulation
+#
+LDEMUL_AFTER_OPEN=ppc_after_open
+LDEMUL_BEFORE_ALLOCATION=ppc_before_allocation
diff --git a/binutils-2.20.1/ld/emultempl/ppc64elf.em b/binutils-2.20.1/ld/emultempl/ppc64elf.em
new file mode 100644
index 00000000..88971d7c
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/ppc64elf.em
@@ -0,0 +1,620 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+# Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+# This file is sourced from elf32.em, and defines extra powerpc64-elf
+# specific routines.
+#
+fragment <<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 no_tls_opt = 0;
+static int no_tls_get_addr_opt = 0;
+
+/* Whether to run opd optimization. */
+static int no_opd_opt = 0;
+
+/* Whether to run toc optimization. */
+static int no_toc_opt = 0;
+
+/* Whether to allow multiple toc sections. */
+static int no_multi_toc = 0;
+
+/* Whether to emit symbols for stubs. */
+static int emit_stub_syms = -1;
+
+static asection *toc_section = 0;
+
+/* Whether to canonicalize .opd so that there are no overlapping
+ .opd entries. */
+static int non_overlapping_opd = 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)
+{
+ if (!(bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour
+ && elf_object_id (link_info.output_bfd) == PPC64_ELF_TDATA))
+ 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", link_info.output_bfd);
+ if (stub_file->the_bfd == NULL
+ || !bfd_set_arch_mach (stub_file->the_bfd,
+ bfd_get_arch (link_info.output_bfd),
+ bfd_get_mach (link_info.output_bfd)))
+ {
+ einfo ("%F%P: can not create BFD %E\n");
+ return;
+ }
+
+ stub_file->the_bfd->flags |= BFD_LINKER_CREATED;
+ ldlang_add_file (stub_file);
+ ppc64_elf_init_stub_bfd (stub_file->the_bfd, &link_info);
+}
+
+static void
+ppc_before_allocation (void)
+{
+ if (stub_file != NULL)
+ {
+ if (!no_opd_opt
+ && !ppc64_elf_edit_opd (link_info.output_bfd, &link_info,
+ non_overlapping_opd))
+ einfo ("%X%P: can not edit %s %E\n", "opd");
+
+ if (ppc64_elf_tls_setup (link_info.output_bfd, &link_info,
+ no_tls_get_addr_opt)
+ && !no_tls_opt)
+ {
+ /* Size the sections. This is premature, but we want to know the
+ TLS segment layout so that certain optimizations can be done. */
+ expld.phase = lang_mark_phase_enum;
+ expld.dataseg.phase = exp_dataseg_none;
+ one_lang_size_sections_pass (NULL, TRUE);
+
+ if (!ppc64_elf_tls_optimize (link_info.output_bfd, &link_info))
+ einfo ("%X%P: TLS problem %E\n");
+
+ /* We must not cache anything from the preliminary sizing. */
+ lang_reset_memory_regions ();
+ }
+
+ if (!no_toc_opt
+ && !link_info.relocatable
+ && !ppc64_elf_edit_toc (link_info.output_bfd, &link_info))
+ einfo ("%X%P: can not edit %s %E\n", "toc");
+ }
+
+ 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;
+
+ flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
+ | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_KEEP);
+ stub_sec = bfd_make_section_anyway_with_flags (stub_file->the_bfd,
+ stub_sec_name, flags);
+ if (stub_sec == NULL)
+ 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);
+
+ 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. */
+ gld${EMULATION_NAME}_map_segments (TRUE);
+
+ if (!link_info.relocatable)
+ _bfd_set_gp_value (link_info.output_bfd,
+ ppc64_elf_toc (link_info.output_bfd));
+
+ need_laying_out = -1;
+}
+
+
+static void
+build_toc_list (lang_statement_union_type *statement)
+{
+ if (statement->header.type == lang_input_section_enum)
+ {
+ asection *i = statement->input_section.section;
+
+ if (!((lang_input_statement_type *) i->owner->usrdata)->just_syms_flag
+ && (i->flags & SEC_EXCLUDE) == 0
+ && i->output_section == toc_section)
+ ppc64_elf_next_toc_section (&link_info, i);
+ }
+}
+
+
+static void
+build_section_lists (lang_statement_union_type *statement)
+{
+ if (statement->header.type == lang_input_section_enum)
+ {
+ asection *i = statement->input_section.section;
+
+ if (!((lang_input_statement_type *) i->owner->usrdata)->just_syms_flag
+ && (i->flags & SEC_EXCLUDE) == 0
+ && i->output_section != NULL
+ && i->output_section->owner == link_info.output_bfd)
+ {
+ if (!ppc64_elf_next_input_section (&link_info, i))
+ einfo ("%X%P: can not size stub section: %E\n");
+ }
+ }
+}
+
+
+/* Call the back-end function to set TOC base after we have placed all
+ the sections. */
+static void
+gld${EMULATION_NAME}_after_allocation (void)
+{
+ /* bfd_elf_discard_info just plays with data and debugging sections,
+ ie. doesn't affect code size, 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 (link_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 (link_info.output_bfd,
+ &link_info,
+ no_multi_toc);
+ if (ret < 0)
+ einfo ("%X%P: can not size stub section: %E\n");
+ else if (ret > 0)
+ {
+ toc_section = bfd_get_section_by_name (link_info.output_bfd, ".got");
+ if (toc_section != NULL)
+ lang_for_each_statement (build_toc_list);
+
+ ppc64_elf_reinit_toc (link_info.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 (link_info.output_bfd,
+ &link_info,
+ group_size,
+ &ppc_add_stub_section,
+ &ppc_layout_sections_again))
+ einfo ("%X%P: can not size stub section: %E\n");
+ }
+ }
+
+ if (need_laying_out != -1)
+ {
+ gld${EMULATION_NAME}_map_segments (need_laying_out);
+
+ if (!link_info.relocatable)
+ _bfd_set_gp_value (link_info.output_bfd,
+ ppc64_elf_toc (link_info.output_bfd));
+ }
+}
+
+
+/* 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";
+
+ if (link_info.relocatable)
+ {
+ asection *toc = bfd_get_section_by_name (link_info.output_bfd, ".toc");
+ if (toc != NULL
+ && bfd_section_size (link_info.output_bfd, toc) > 0x10000)
+ einfo ("%X%P: TOC section size exceeds 64k\n");
+ }
+
+ if (stub_added)
+ {
+ char *msg = NULL;
+ char *line, *endline;
+
+ if (emit_stub_syms < 0)
+ emit_stub_syms = 1;
+ 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);
+ }
+
+ ppc64_elf_restore_symbols (&link_info);
+ finish_default ();
+}
+
+
+/* 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->literal && 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
+
+if grep -q 'ld_elf32_spu_emulation' ldemul-list.h; then
+ fragment <<EOF
+/* Special handling for embedded SPU executables. */
+extern bfd_boolean embedded_spu_file (lang_input_statement_type *, const char *);
+static bfd_boolean gld${EMULATION_NAME}_load_symbols (lang_input_statement_type *);
+
+static bfd_boolean
+ppc64_recognized_file (lang_input_statement_type *entry)
+{
+ if (embedded_spu_file (entry, "-m64"))
+ return TRUE;
+
+ return gld${EMULATION_NAME}_load_symbols (entry);
+}
+EOF
+LDEMUL_RECOGNIZED_FILE=ppc64_recognized_file
+fi
+
+# 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_NO_STUBSYMS (OPTION_STUBSYMS + 1)
+#define OPTION_DOTSYMS (OPTION_NO_STUBSYMS + 1)
+#define OPTION_NO_DOTSYMS (OPTION_DOTSYMS + 1)
+#define OPTION_NO_TLS_OPT (OPTION_NO_DOTSYMS + 1)
+#define OPTION_NO_TLS_GET_ADDR_OPT (OPTION_NO_TLS_OPT + 1)
+#define OPTION_NO_OPD_OPT (OPTION_NO_TLS_GET_ADDR_OPT + 1)
+#define OPTION_NO_TOC_OPT (OPTION_NO_OPD_OPT + 1)
+#define OPTION_NO_MULTI_TOC (OPTION_NO_TOC_OPT + 1)
+#define OPTION_NON_OVERLAPPING_OPD (OPTION_NO_MULTI_TOC + 1)
+'
+
+PARSE_AND_LIST_LONGOPTS='
+ { "stub-group-size", required_argument, NULL, OPTION_STUBGROUP_SIZE },
+ { "emit-stub-syms", no_argument, NULL, OPTION_STUBSYMS },
+ { "no-emit-stub-syms", no_argument, NULL, OPTION_NO_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 },
+ { "no-tls-get-addr-optimize", no_argument, NULL, OPTION_NO_TLS_GET_ADDR_OPT },
+ { "no-opd-optimize", no_argument, NULL, OPTION_NO_OPD_OPT },
+ { "no-toc-optimize", no_argument, NULL, OPTION_NO_TOC_OPT },
+ { "no-multi-toc", no_argument, NULL, OPTION_NO_MULTI_TOC },
+ { "non-overlapping-opd", no_argument, NULL, OPTION_NON_OVERLAPPING_OPD },
+'
+
+PARSE_AND_LIST_OPTIONS='
+ fprintf (file, _("\
+ --stub-group-size=N Maximum size of a group of input sections that\n\
+ can be handled by one stub section. A negative\n\
+ value locates all stubs before their branches\n\
+ (with a group size of -N), while a positive\n\
+ value allows two groups of input sections, one\n\
+ before, and one after each stub section.\n\
+ Values of +/-1 indicate the linker should\n\
+ choose suitable defaults.\n"
+ ));
+ fprintf (file, _("\
+ --emit-stub-syms Label linker stubs with a symbol.\n"
+ ));
+ fprintf (file, _("\
+ --no-emit-stub-syms Don'\''t label linker stubs with a symbol.\n"
+ ));
+ fprintf (file, _("\
+ --dotsyms For every version pattern \"foo\" in a version\n\
+ script, add \".foo\" so that function code\n\
+ symbols are treated the same as function\n\
+ descriptor symbols. 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"
+ ));
+ fprintf (file, _("\
+ --no-tls-get-addr-optimize Don'\''t use a special __tls_get_addr call.\n"
+ ));
+ fprintf (file, _("\
+ --no-opd-optimize Don'\''t optimize the OPD section.\n"
+ ));
+ fprintf (file, _("\
+ --no-toc-optimize Don'\''t optimize the TOC section.\n"
+ ));
+ fprintf (file, _("\
+ --no-multi-toc Disallow automatic multiple toc sections.\n"
+ ));
+ fprintf (file, _("\
+ --non-overlapping-opd Canonicalize .opd, so that there are no\n\
+ overlapping .opd entries.\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_NO_STUBSYMS:
+ emit_stub_syms = 0;
+ break;
+
+ case OPTION_DOTSYMS:
+ dotsyms = 1;
+ break;
+
+ case OPTION_NO_DOTSYMS:
+ dotsyms = 0;
+ break;
+
+ case OPTION_NO_TLS_OPT:
+ no_tls_opt = 1;
+ break;
+
+ case OPTION_NO_TLS_GET_ADDR_OPT:
+ no_tls_get_addr_opt = 1;
+ break;
+
+ case OPTION_NO_OPD_OPT:
+ no_opd_opt = 1;
+ break;
+
+ case OPTION_NO_TOC_OPT:
+ no_toc_opt = 1;
+ break;
+
+ case OPTION_NO_MULTI_TOC:
+ no_multi_toc = 1;
+ break;
+
+ case OPTION_NON_OVERLAPPING_OPD:
+ non_overlapping_opd = 1;
+ break;
+'
+
+# Put these extra ppc64elf routines in ld_${EMULATION_NAME}_emulation
+#
+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/binutils-2.20.1/ld/emultempl/scoreelf.em b/binutils-2.20.1/ld/emultempl/scoreelf.em
new file mode 100644
index 00000000..897147e9
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/scoreelf.em
@@ -0,0 +1,77 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+# Contributed by:
+# Brain.lin (brain.lin@sunplusct.com)
+# Mei Ligang (ligang@sunnorth.com.cn)
+# Pei-Lin Tsai (pltsai@sunplus.com)
+
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+# This file is sourced from elf32.em, and defines extra score-elf
+# specific routines.
+#
+fragment <<EOF
+
+#include "elf32-score.h"
+
+static void
+gld${EMULATION_NAME}_before_parse ()
+{
+#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
+score_elf_after_open (void)
+{
+ if (strstr (bfd_get_target (link_info.output_bfd), "score") == NULL)
+ {
+ /* The score backend needs special fields in the output hash structure.
+ These will only be created if the output format is an score 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 S+core binaries\n");
+ return;
+ }
+
+ /* Call the standard elf routine. */
+ gld${EMULATION_NAME}_after_open ();
+}
+
+EOF
+
+# Define some shell vars to insert bits of code into the standard elf
+# parse_args and list_options functions.
+#
+PARSE_AND_LIST_PROLOGUE=''
+PARSE_AND_LIST_SHORTOPTS=
+PARSE_AND_LIST_LONGOPTS=''
+PARSE_AND_LIST_OPTIONS=''
+PARSE_AND_LIST_ARGS_CASES=''
+
+# 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=score_elf_after_open
+
+# Replace the elf before_parse function with our own.
+LDEMUL_BEFORE_PARSE=gld"${EMULATION_NAME}"_before_parse
+
diff --git a/binutils-2.20.1/ld/emultempl/sh64elf.em b/binutils-2.20.1/ld/emultempl/sh64elf.em
new file mode 100644
index 00000000..0c5dc4e9
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/sh64elf.em
@@ -0,0 +1,557 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
+# Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+# This file is sourced from elf32.em, and defines extra sh64
+# specific routines.
+#
+
+LDEMUL_AFTER_ALLOCATION=sh64_elf_${EMULATION_NAME}_after_allocation
+LDEMUL_BEFORE_ALLOCATION=sh64_elf_${EMULATION_NAME}_before_allocation
+
+fragment <<EOF
+
+#include "libiberty.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+#include "elf/sh.h"
+#include "elf32-sh64.h"
+
+/* Check if we need a .cranges section and create it if it's not in any
+ input file. It might seem better to always create it and if unneeded,
+ discard it, but I don't find a simple way to discard it totally from
+ the output.
+
+ Putting it here instead of as a elf_backend_always_size_sections hook
+ in elf32-sh64.c, means that we have access to linker command line
+ options here, and we can access input sections in the order in which
+ they will be linked. */
+
+static void
+sh64_elf_${EMULATION_NAME}_before_allocation (void)
+{
+ asection *cranges;
+ asection *osec;
+
+ /* Call main function; we're just extending it. */
+ gld${EMULATION_NAME}_before_allocation ();
+
+ cranges = bfd_get_section_by_name (link_info.output_bfd,
+ SH64_CRANGES_SECTION_NAME);
+
+ if (cranges != NULL)
+ {
+ if (command_line.relax)
+ {
+ /* FIXME: Look through incoming sections with .cranges
+ descriptors, build up some kind of descriptors that the
+ relaxing function will pick up and adjust, or perhaps make it
+ find and adjust an associated .cranges descriptor. We could
+ also look through incoming relocs and kill the ones marking
+ relaxation areas, but that wouldn't be TRT. */
+ einfo
+ (_("%P: Sorry, turning off relaxing: .cranges section in input.\n"));
+ einfo (_(" A .cranges section is present in:\n"));
+
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (f)
+ {
+ asection *input_cranges
+ = bfd_get_section_by_name (f->the_bfd,
+ SH64_CRANGES_SECTION_NAME);
+ if (input_cranges != NULL)
+ einfo (" %I\n", f);
+ }
+ }
+
+ command_line.relax = FALSE;
+ }
+
+ /* We wouldn't need to do anything when there's already a .cranges
+ section (and have a return here), except that we need to set the
+ section flags right for output sections that *don't* need a
+ .cranges section. */
+ }
+
+ if (command_line.relax)
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (f)
+ {
+ if (bfd_get_flavour (f->the_bfd) == bfd_target_elf_flavour)
+ {
+ asection *isec;
+ for (isec = f->the_bfd->sections;
+ isec != NULL;
+ isec = isec->next)
+ {
+ if (elf_section_data (isec)->this_hdr.sh_flags
+ & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED))
+ {
+ einfo (_("%P: Sorry, turning off relaxing: SHmedia sections present.\n"));
+ einfo (" %I\n", f);
+ command_line.relax = FALSE;
+ goto done_scanning_shmedia_sections;
+ }
+ }
+ }
+ }
+ }
+ done_scanning_shmedia_sections:
+
+ /* For each non-empty input section in each output section, check if it
+ has the same SH64-specific flags. If some input section differs, we
+ need a .cranges section. */
+ for (osec = link_info.output_bfd->sections;
+ osec != NULL;
+ osec = osec->next)
+ {
+ struct sh64_section_data *sh64_sec_data;
+ bfd_vma oflags_isa = 0;
+ bfd_vma iflags_isa = 0;
+
+ if (bfd_get_flavour (link_info.output_bfd) != bfd_target_elf_flavour)
+ einfo (_("%FError: non-ELF output formats are not supported by this target's linker.\n"));
+
+ sh64_sec_data = sh64_elf_section_data (osec)->sh64_info;
+
+ /* Omit excluded or garbage-collected sections. */
+ if (bfd_get_section_flags (link_info.output_bfd, osec) & SEC_EXCLUDE)
+ continue;
+
+ /* Make sure we have the target section data initialized. */
+ if (sh64_sec_data == NULL)
+ {
+ sh64_sec_data = xcalloc (1, sizeof (struct sh64_section_data));
+ sh64_elf_section_data (osec)->sh64_info = sh64_sec_data;
+ }
+
+ /* First find an input section so we have flags to compare with; the
+ flags in the output section are not valid. */
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (f)
+ {
+ asection *isec;
+
+ for (isec = f->the_bfd->sections;
+ isec != NULL;
+ isec = isec->next)
+ {
+ if (isec->output_section == osec
+ && isec->size != 0
+ && (bfd_get_section_flags (isec->owner, isec)
+ & SEC_EXCLUDE) == 0)
+ {
+ oflags_isa
+ = (elf_section_data (isec)->this_hdr.sh_flags
+ & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED));
+ goto break_1;
+ }
+ }
+ }
+ }
+
+ break_1:
+
+ /* Check that all input sections have the same contents-type flags
+ as the first input section. */
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (f)
+ {
+ asection *isec;
+
+ for (isec = f->the_bfd->sections;
+ isec != NULL;
+ isec = isec->next)
+ {
+ if (isec->output_section == osec
+ && isec->size != 0
+ && (bfd_get_section_flags (isec->owner, isec)
+ & SEC_EXCLUDE) == 0)
+ {
+ iflags_isa
+ = (elf_section_data (isec)->this_hdr.sh_flags
+ & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED));
+
+ /* If flags don't agree, we need a .cranges section.
+ Create it here if it did not exist through input
+ sections. */
+ if (iflags_isa != oflags_isa)
+ {
+ if (cranges == NULL)
+ {
+ /* This section will be *appended* to
+ sections, so the outer iteration will reach
+ it in due time and set
+ sh64_elf_section_data; no need to set it
+ specifically here. */
+ cranges
+ = bfd_make_section_with_flags (link_info.output_bfd,
+ SH64_CRANGES_SECTION_NAME,
+ SEC_LINKER_CREATED
+ | SEC_KEEP
+ | SEC_HAS_CONTENTS
+ | SEC_DEBUGGING);
+ if (cranges == NULL)
+ einfo
+ (_("%P%E%F: Can't make .cranges section\n"));
+ }
+
+ /* We don't need to look at more input sections,
+ and we know this section will have mixed
+ contents. */
+ goto break_2;
+ }
+ }
+ }
+ }
+ }
+
+ /* If we got here, then all input sections in this output section
+ have the same contents flag. Put that where we expect to see
+ contents flags. We don't need to do this for sections that will
+ need additional, linker-generated .cranges entries. */
+ sh64_sec_data->contents_flags = iflags_isa;
+
+ break_2:
+ ;
+ }
+}
+
+/* Size up and extend the .cranges section, merging generated entries. */
+
+static void
+sh64_elf_${EMULATION_NAME}_after_allocation (void)
+{
+ bfd_vma new_cranges = 0;
+ bfd_vma cranges_growth = 0;
+ asection *osec;
+ bfd_byte *crangesp;
+ asection *cranges;
+
+ gld${EMULATION_NAME}_after_allocation ();
+
+ cranges = bfd_get_section_by_name (link_info.output_bfd,
+ SH64_CRANGES_SECTION_NAME);
+
+ /* If there is no .cranges section, it is because it was seen earlier on
+ that none was needed. Otherwise it must have been created then, or
+ be present in input. */
+ if (cranges == NULL)
+ return;
+
+ /* First, we set the ISA flags for each output section according to the
+ first non-discarded section. For each input section in osec, we
+ check if it has the same flags. If it does not, we set flags to mark
+ a mixed section (and exit the loop early). */
+ for (osec = link_info.output_bfd->sections;
+ osec != NULL;
+ osec = osec->next)
+ {
+ bfd_vma oflags_isa = 0;
+ bfd_boolean need_check_cranges = FALSE;
+
+ /* Omit excluded or garbage-collected sections. */
+ if (bfd_get_section_flags (link_info.output_bfd, osec) & SEC_EXCLUDE)
+ continue;
+
+ /* First find an input section so we have flags to compare with; the
+ flags in the output section are not valid. */
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (f)
+ {
+ asection *isec;
+
+ for (isec = f->the_bfd->sections;
+ isec != NULL;
+ isec = isec->next)
+ {
+ if (isec->output_section == osec
+ && isec->size != 0
+ && (bfd_get_section_flags (isec->owner, isec)
+ & SEC_EXCLUDE) == 0)
+ {
+ oflags_isa
+ = (elf_section_data (isec)->this_hdr.sh_flags
+ & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED));
+ goto break_1;
+ }
+ }
+ }
+ }
+
+ break_1:
+
+ /* Check that all input sections have the same contents-type flags
+ as the first input section. */
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (f)
+ {
+ asection *isec;
+
+ for (isec = f->the_bfd->sections;
+ isec != NULL;
+ isec = isec->next)
+ {
+ if (isec->output_section == osec
+ && isec->size != 0
+ && (bfd_get_section_flags (isec->owner, isec)
+ & SEC_EXCLUDE) == 0)
+ {
+ bfd_vma iflags_isa
+ = (elf_section_data (isec)->this_hdr.sh_flags
+ & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED));
+
+ /* If flags don't agree, set the target-specific data
+ of the section to mark that this section needs to
+ be have .cranges section entries added. Don't
+ bother setting ELF section flags in output section;
+ they will be cleared later and will have to be
+ re-initialized before the linked file is written. */
+ if (iflags_isa != oflags_isa)
+ {
+ oflags_isa = SHF_SH5_ISA32_MIXED;
+
+ BFD_ASSERT (sh64_elf_section_data (osec)->sh64_info);
+
+ sh64_elf_section_data (osec)->sh64_info->contents_flags
+ = SHF_SH5_ISA32_MIXED;
+ need_check_cranges = TRUE;
+ goto break_2;
+ }
+ }
+ }
+ }
+ }
+
+ break_2:
+
+ /* If there were no new ranges for this output section, we don't
+ need to iterate over the input sections to check how many are
+ needed. */
+ if (! need_check_cranges)
+ continue;
+
+ /* If we found a section with differing contents type, we need more
+ ranges to mark the sections that are not mixed (and already have
+ .cranges descriptors). Calculate the maximum number of new
+ entries here. We may merge some of them, so that number is not
+ final; it can shrink. */
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (f)
+ {
+ asection *isec;
+
+ for (isec = f->the_bfd->sections;
+ isec != NULL;
+ isec = isec->next)
+ {
+ if (isec->output_section == osec
+ && isec->size != 0
+ && (bfd_get_section_flags (isec->owner, isec)
+ & SEC_EXCLUDE) == 0
+ && ((elf_section_data (isec)->this_hdr.sh_flags
+ & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED))
+ != SHF_SH5_ISA32_MIXED))
+ new_cranges++;
+ }
+ }
+ }
+ }
+
+ if (cranges->contents != NULL)
+ free (cranges->contents);
+
+ BFD_ASSERT (sh64_elf_section_data (cranges)->sh64_info != NULL);
+
+ /* Make sure we have .cranges in memory even if there were only
+ assembler-generated .cranges. */
+ cranges_growth = new_cranges * SH64_CRANGE_SIZE;
+ cranges->contents = xcalloc (cranges->size + cranges_growth, 1);
+ bfd_set_section_flags (cranges->owner, cranges,
+ bfd_get_section_flags (cranges->owner, cranges)
+ | SEC_IN_MEMORY);
+
+ /* If we don't need to grow the .cranges section beyond what was in the
+ input sections, we have nothing more to do here. We then only got
+ here because there was a .cranges section coming from input. Zero
+ out the number of generated .cranges. */
+ if (new_cranges == 0)
+ {
+ sh64_elf_section_data (cranges)->sh64_info->cranges_growth = 0;
+ return;
+ }
+
+ crangesp = cranges->contents + cranges->size;
+
+ /* Now pass over the sections again, and make reloc orders for the new
+ .cranges entries. Constants are set as we go. */
+ for (osec = link_info.output_bfd->sections;
+ osec != NULL;
+ osec = osec->next)
+ {
+ struct bfd_link_order *cr_addr_order = NULL;
+ enum sh64_elf_cr_type last_cr_type = CRT_NONE;
+ bfd_vma last_cr_size = 0;
+ bfd_vma continuation_vma = 0;
+
+ /* Omit excluded or garbage-collected sections, and output sections
+ which were not marked as needing further processing. */
+ if ((bfd_get_section_flags (link_info.output_bfd, osec) & SEC_EXCLUDE) != 0
+ || (sh64_elf_section_data (osec)->sh64_info->contents_flags
+ != SHF_SH5_ISA32_MIXED))
+ continue;
+
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (f)
+ {
+ asection *isec;
+
+ for (isec = f->the_bfd->sections;
+ isec != NULL;
+ isec = isec->next)
+ {
+ /* Allow only sections that have (at least initially) a
+ non-zero size, and are not excluded, and are not marked
+ as containing mixed data, thus already having .cranges
+ entries. */
+ if (isec->output_section == osec
+ && isec->size != 0
+ && (bfd_get_section_flags (isec->owner, isec)
+ & SEC_EXCLUDE) == 0
+ && ((elf_section_data (isec)->this_hdr.sh_flags
+ & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED))
+ != SHF_SH5_ISA32_MIXED))
+ {
+ enum sh64_elf_cr_type cr_type;
+ bfd_vma cr_size;
+ bfd_vma isa_flags
+ = (elf_section_data (isec)->this_hdr.sh_flags
+ & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED));
+
+ if (isa_flags == SHF_SH5_ISA32)
+ cr_type = CRT_SH5_ISA32;
+ else if ((bfd_get_section_flags (isec->owner, isec)
+ & SEC_CODE) == 0)
+ cr_type = CRT_DATA;
+ else
+ cr_type = CRT_SH5_ISA16;
+
+ cr_size = isec->size;
+
+ /* Sections can be empty, like .text in a file that
+ only contains other sections. Ranges shouldn't be
+ emitted for them. This can presumably happen after
+ relaxing and is not be caught at the "raw size"
+ test above. */
+ if (cr_size == 0)
+ continue;
+
+ /* See if this is a continuation of the previous range
+ for the same output section. If so, just change
+ the size of the last range and continue. */
+ if (cr_type == last_cr_type
+ && (continuation_vma
+ == osec->vma + isec->output_offset))
+ {
+ last_cr_size += cr_size;
+ bfd_put_32 (link_info.output_bfd, last_cr_size,
+ crangesp - SH64_CRANGE_SIZE
+ + SH64_CRANGE_CR_SIZE_OFFSET);
+
+ continuation_vma += cr_size;
+ continue;
+ }
+
+ /* If we emit relocatable contents, we need a
+ relocation for the start address. */
+ if (link_info.relocatable || link_info.emitrelocations)
+ {
+ /* FIXME: We could perhaps use lang_add_reloc and
+ friends here, but I'm not really sure that
+ would leave us free to do some optimizations
+ later. */
+ cr_addr_order
+ = bfd_new_link_order (link_info.output_bfd, cranges);
+
+ if (cr_addr_order == NULL)
+ {
+ einfo (_("%P%F: bfd_new_link_order failed\n"));
+ return;
+ }
+
+ cr_addr_order->type = bfd_section_reloc_link_order;
+ cr_addr_order->offset
+ = (cranges->output_offset
+ + crangesp + SH64_CRANGE_CR_ADDR_OFFSET
+ - cranges->contents);
+ cr_addr_order->size = 4;
+ cr_addr_order->u.reloc.p
+ = xmalloc (sizeof (struct bfd_link_order_reloc));
+
+ cr_addr_order->u.reloc.p->reloc = BFD_RELOC_32;
+ cr_addr_order->u.reloc.p->u.section = osec;
+
+ /* Since SH, unlike normal RELA-targets, uses a
+ "partial inplace" REL-like relocation for this,
+ we put the addend in the contents and specify 0
+ for the reloc. */
+ bfd_put_32 (link_info.output_bfd, isec->output_offset,
+ crangesp + SH64_CRANGE_CR_ADDR_OFFSET);
+ cr_addr_order->u.reloc.p->addend = 0;
+ }
+ else
+ bfd_put_32 (link_info.output_bfd,
+ osec->vma + isec->output_offset,
+ crangesp + SH64_CRANGE_CR_ADDR_OFFSET);
+
+ /* If we could make a reloc for cr_size we would do
+ it, but we would have to have a symbol for the size
+ of the _input_ section and there's no way to
+ generate that. */
+ bfd_put_32 (link_info.output_bfd, cr_size,
+ crangesp + SH64_CRANGE_CR_SIZE_OFFSET);
+
+ bfd_put_16 (link_info.output_bfd, cr_type,
+ crangesp + SH64_CRANGE_CR_TYPE_OFFSET);
+
+ last_cr_type = cr_type;
+ last_cr_size = cr_size;
+ continuation_vma
+ = osec->vma + isec->output_offset + cr_size;
+ crangesp += SH64_CRANGE_SIZE;
+ }
+ }
+ }
+ }
+ }
+
+ /* The .cranges section will have this size, no larger or smaller.
+ Since relocs (if relocatable linking) will be emitted into the
+ "extended" size, we must set the raw size to the total. We have to
+ keep track of the number of new .cranges entries.
+
+ Sorting before writing is done by sh64_elf_final_write_processing. */
+
+ sh64_elf_section_data (cranges)->sh64_info->cranges_growth
+ = crangesp - cranges->contents - cranges->size;
+ cranges->size = crangesp - cranges->contents;
+ cranges->rawsize = cranges->size;
+}
diff --git a/binutils-2.20.1/ld/emultempl/spu_icache.S b/binutils-2.20.1/ld/emultempl/spu_icache.S
new file mode 100644
index 00000000..12eb7f14
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/spu_icache.S
@@ -0,0 +1,7 @@
+ .text
+ .global __icache_br_handler
+__icache_br_handler:
+ stop
+ .global __icache_call_handler
+__icache_call_handler:
+ stop
diff --git a/binutils-2.20.1/ld/emultempl/spu_icache.o_c b/binutils-2.20.1/ld/emultempl/spu_icache.o_c
new file mode 100644
index 00000000..2006fe25
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/spu_icache.o_c
@@ -0,0 +1,33 @@
+0x7f,0x45,0x4c,0x46,0x01,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x01,0x00,0x17,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x68,0x00,0x00,0x00,0x00,0x00,0x34,0x00,0x00,0x00,0x00,0x00,0x28,
+0x00,0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2e,0x73,0x79,
+0x6d,0x74,0x61,0x62,0x00,0x2e,0x73,0x74,0x72,0x74,0x61,0x62,0x00,0x2e,0x73,0x68,
+0x73,0x74,0x72,0x74,0x61,0x62,0x00,0x2e,0x74,0x65,0x78,0x74,0x00,0x2e,0x64,0x61,
+0x74,0x61,0x00,0x2e,0x62,0x73,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x1b,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x34,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x01,
+0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x27,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x03,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x2c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x01,0x80,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x04,
+0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x03,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xe0,0x00,0x00,0x00,0x2b,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x01,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x02,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x03,
+0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x01,
+0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x01,
+0x00,0x5f,0x5f,0x69,0x63,0x61,0x63,0x68,0x65,0x5f,0x62,0x72,0x5f,0x68,0x61,0x6e,
+0x64,0x6c,0x65,0x72,0x00,0x5f,0x5f,0x69,0x63,0x61,0x63,0x68,0x65,0x5f,0x63,0x61,
+0x6c,0x6c,0x5f,0x68,0x61,0x6e,0x64,0x6c,0x65,0x72,0x00,
diff --git a/binutils-2.20.1/ld/emultempl/spu_ovl.S b/binutils-2.20.1/ld/emultempl/spu_ovl.S
new file mode 100644
index 00000000..509397a6
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/spu_ovl.S
@@ -0,0 +1,471 @@
+/* Overlay manager for SPU.
+
+ Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
+
+ This file is part of the GNU Binutils.
+
+ 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* MFC DMA defn's. */
+#define MFC_GET_CMD 0x40
+#define MFC_MAX_DMA_SIZE 0x4000
+#define MFC_TAG_UPDATE_ALL 2
+#define MFC_TAG_ID 0
+
+/* Register usage. */
+#define reserved1 $75
+#define parm $75
+#define tab1 reserved1
+#define tab2 reserved1
+#define vma reserved1
+#define oldvma reserved1
+#define newmask reserved1
+#define map reserved1
+
+#define reserved2 $76
+#define off1 reserved2
+#define off2 reserved2
+#define present1 reserved2
+#define present2 reserved2
+#define sz reserved2
+#define cmp reserved2
+#define add64 reserved2
+#define cgbits reserved2
+#define off3 reserved2
+#define off4 reserved2
+#define addr4 reserved2
+#define off5 reserved2
+#define tagstat reserved2
+
+#define reserved3 $77
+#define size1 reserved3
+#define size2 reserved3
+#define rv3 reserved3
+#define ealo reserved3
+#define cmd reserved3
+#define off64 reserved3
+#define tab3 reserved3
+#define tab4 reserved3
+#define tab5 reserved3
+
+#define reserved4 $78
+#define ovl reserved4
+#define rv2 reserved4
+#define rv5 reserved4
+#define cgshuf reserved4
+#define newovl reserved4
+#define irqtmp1 reserved4
+#define irqtmp2 reserved4
+
+#define reserved5 $79
+#define target reserved5
+
+#define save1 $74
+#define rv4 save1
+#define rv7 save1
+#define tagid save1
+#define maxsize save1
+#define pbyte save1
+#define pbit save1
+
+#define save2 $73
+#define cur save2
+#define rv6 save2
+#define osize save2
+#define zovl save2
+#define oldovl save2
+#define newvma save2
+
+#define save3 $72
+#define rv1 save3
+#define ea64 save3
+#define buf3 save3
+#define genwi save3
+#define newmap save3
+#define oldmask save3
+
+#define save4 $71
+#define irq_stat save4
+
+ .text
+ .align 4
+ .type __rv_pattern, @object
+ .size __rv_pattern, 16
+__rv_pattern:
+ .word 0x00010203, 0x10111213, 0x80808080, 0x80808080
+
+ .type __cg_pattern, @object
+ .size __cg_pattern, 16
+__cg_pattern:
+ .word 0x04050607, 0x80808080, 0x80808080, 0x80808080
+
+ .type __ovly_current, @object
+ .size __ovly_current, 16
+__ovly_current:
+ .space 16
+
+/*
+ * __ovly_return - stub for returning from overlay functions.
+ *
+ * On entry the four slots of $lr are:
+ * __ovly_return, prev ovl index, caller return addr, undefined.
+ *
+ * Load the previous overlay and jump to the caller return address.
+ * Updates __ovly_current.
+ */
+ .align 4
+ .global __ovly_return
+ .type __ovly_return, @function
+__ovly_return:
+ ila tab1, _ovly_table - 16 # 0,2 0
+ shlqbyi ovl, $lr, 4 # 1,4 0
+#nop
+ shlqbyi target, $lr, 8 # 1,4 1
+#nop; lnop
+#nop; lnop
+ shli off1, ovl, 4 # 0,4 4
+#lnop
+#nop
+ hbr ovly_ret9, target # 1,15 5
+#nop; lnop
+#nop; lnop
+#nop
+ lqx vma, tab1, off1 # 1,6 8
+#ifdef OVLY_IRQ_SAVE
+ nop
+ stqd save4, -64($sp) # 1,6 9
+#else
+#nop; lnop
+#endif
+#nop; lnop
+#nop; lnop
+#nop; lnop
+#nop; lnop
+#nop
+ rotqbyi size1, vma, 4 # 1,4 14
+#nop
+ stqd save3, -48($sp) # 1,6 15
+#nop
+ stqd save2, -32($sp) # 1,6 16
+#nop
+ stqd save1, -16($sp) # 1,6 17
+ andi present1, size1, 1 # 0,2 18
+ stqr ovl, __ovly_current # 1,6 18
+#nop; lnop
+#nop
+ brz present1, do_load # 1,4 20
+ovly_ret9:
+#nop
+ bi target # 1,4 21
+
+/*
+ * __ovly_load - copy an overlay partion to local store.
+ *
+ * On entry $75 points to a word consisting of the overlay index in
+ * the top 14 bits, and the target address in the bottom 18 bits.
+ *
+ * Sets up $lr to return via __ovly_return. If $lr is already set
+ * to return via __ovly_return, don't change it. In that case we
+ * have a tail call from one overlay function to another.
+ * Updates __ovly_current.
+ */
+ .align 3
+ .global __ovly_load
+ .type __ovly_load, @function
+__ovly_load:
+#if OVL_STUB_SIZE == 8
+########
+#nop
+ lqd target, 0(parm) # 1,6 -11
+#nop; lnop
+#nop; lnop
+#nop; lnop
+#nop; lnop
+#nop; lnop
+#nop
+ rotqby target, target, parm # 1,4 -5
+ ila tab2, _ovly_table - 16 # 0,2 -4
+ stqd save3, -48($sp) # 1,6 -4
+#nop
+ stqd save2, -32($sp) # 1,6 -3
+#nop
+ stqd save1, -16($sp) # 1,6 -2
+ rotmi ovl, target, -18 # 0,4 -1
+ hbr ovly_load9, target # 1,15 -1
+ ila rv1, __ovly_return # 0,2 0
+#lnop
+#nop; lnop
+#nop
+ lqr cur, __ovly_current # 1,6 2
+ shli off2, ovl, 4 # 0,4 3
+ stqr ovl, __ovly_current # 1,6 3
+ ceq rv2, $lr, rv1 # 0,2 4
+ lqr rv3, __rv_pattern # 1,6 4
+#nop; lnop
+#nop; lnop
+#nop
+ lqx vma, tab2, off2 # 1,6 7
+########
+#else /* OVL_STUB_SIZE == 16 */
+########
+ ila tab2, _ovly_table - 16 # 0,2 0
+ stqd save3, -48($sp) # 1,6 0
+ ila rv1, __ovly_return # 0,2 1
+ stqd save2, -32($sp) # 1,6 1
+ shli off2, ovl, 4 # 0,4 2
+ lqr cur, __ovly_current # 1,6 2
+ nop
+ stqr ovl, __ovly_current # 1,6 3
+ ceq rv2, $lr, rv1 # 0,2 4
+ lqr rv3, __rv_pattern # 1,6 4
+#nop
+ hbr ovly_load9, target # 1,15 5
+#nop
+ lqx vma, tab2, off2 # 1,6 6
+#nop
+ stqd save1, -16($sp) # 1,6 7
+########
+#endif
+
+#nop; lnop
+#nop; lnop
+#nop
+ shufb rv4, rv1, cur, rv3 # 1,4 10
+#nop
+ fsmb rv5, rv2 # 1,4 11
+#nop
+ rotqmbyi rv6, $lr, -8 # 1,4 12
+#nop
+ rotqbyi size2, vma, 4 # 1,4 13
+#nop
+ lqd save3, -48($sp) # 1,6 14
+#nop; lnop
+ or rv7, rv4, rv6 # 0,2 16
+ lqd save2, -32($sp) # 1,6 16
+ andi present2, size2, 1 # 0,2 17
+#ifdef OVLY_IRQ_SAVE
+ stqd save4, -64($sp) # 1,6 17
+#else
+ lnop # 1,0 17
+#endif
+ selb $lr, rv7, $lr, rv5 # 0,2 18
+ lqd save1, -16($sp) # 1,6 18
+#nop
+ brz present2, do_load # 1,4 19
+ovly_load9:
+#nop
+ bi target # 1,4 20
+
+/* If we get here, we are about to load a new overlay.
+ * "vma" contains the relevant entry from _ovly_table[].
+ * extern struct {
+ * u32 vma;
+ * u32 size;
+ * u32 file_offset;
+ * u32 buf;
+ * } _ovly_table[];
+ */
+ .align 3
+ .global __ovly_load_event
+ .type __ovly_load_event, @function
+__ovly_load_event:
+do_load:
+#ifdef OVLY_IRQ_SAVE
+ ila irqtmp1, do_load10 # 0,2 -5
+ rotqbyi sz, vma, 8 # 1,4 -5
+#nop
+ rdch irq_stat, $SPU_RdMachStat # 1,6 -4
+#nop
+ bid irqtmp1 # 1,4 -3
+do_load10:
+ nop
+#else
+#nop
+ rotqbyi sz, vma, 8 # 1,4 0
+#endif
+ rotqbyi osize, vma, 4 # 1,4 1
+#nop
+ lqa ea64, _EAR_ # 1,6 2
+#nop
+ lqr cgshuf, __cg_pattern # 1,6 3
+
+/* We could predict the branch at the end of this loop by adding a few
+ instructions, and there are plenty of free cycles to do so without
+ impacting loop execution time. However, it doesn't make a great
+ deal of sense since we need to wait for the dma to complete anyway. */
+__ovly_xfer_loop:
+#nop
+ rotqmbyi off64, sz, -4 # 1,4 4
+#nop; lnop
+#nop; lnop
+#nop; lnop
+ cg cgbits, ea64, off64 # 0,2 8
+#lnop
+#nop; lnop
+#nop
+ shufb add64, cgbits, cgbits, cgshuf # 1,4 10
+#nop; lnop
+#nop; lnop
+#nop; lnop
+ addx add64, ea64, off64 # 0,2 14
+#lnop
+ ila maxsize, MFC_MAX_DMA_SIZE # 0,2 15
+ lnop
+ ori ea64, add64, 0 # 0,2 16
+ rotqbyi ealo, add64, 4 # 1,4 16
+ cgt cmp, osize, maxsize # 0,2 17
+ wrch $MFC_LSA, vma # 1,6 17
+#nop; lnop
+ selb sz, osize, maxsize, cmp # 0,2 19
+ wrch $MFC_EAH, ea64 # 1,6 19
+ ila tagid, MFC_TAG_ID # 0,2 20
+ wrch $MFC_EAL, ealo # 1,6 20
+ ila cmd, MFC_GET_CMD # 0,2 21
+ wrch $MFC_Size, sz # 1,6 21
+ sf osize, sz, osize # 0,2 22
+ wrch $MFC_TagId, tagid # 1,6 22
+ a vma, vma, sz # 0,2 23
+ wrch $MFC_Cmd, cmd # 1,6 23
+#nop
+ brnz osize, __ovly_xfer_loop # 1,4 24
+
+/* Now update our data structions while waiting for DMA to complete.
+ Low bit of .size needs to be cleared on the _ovly_table entry
+ corresponding to the evicted overlay, and set on the entry for the
+ newly loaded overlay. Note that no overlay may in fact be evicted
+ as _ovly_buf_table[] starts with all zeros. Don't zap .size entry
+ for zero index! Also of course update the _ovly_buf_table entry. */
+#nop
+ lqr newovl, __ovly_current # 1,6 25
+#nop; lnop
+#nop; lnop
+#nop; lnop
+#nop; lnop
+#nop; lnop
+ shli off3, newovl, 4 # 0,4 31
+#lnop
+ ila tab3, _ovly_table - 16 # 0,2 32
+#lnop
+#nop
+ fsmbi pbyte, 0x100 # 1,4 33
+#nop; lnop
+#nop
+ lqx vma, tab3, off3 # 1,6 35
+#nop; lnop
+ andi pbit, pbyte, 1 # 0,2 37
+ lnop
+#nop; lnop
+#nop; lnop
+#nop; lnop
+ or newvma, vma, pbit # 0,2 41
+ rotqbyi buf3, vma, 12 # 1,4 41
+#nop; lnop
+#nop
+ stqx newvma, tab3, off3 # 1,6 43
+#nop; lnop
+ shli off4, buf3, 2 # 1,4 45
+#lnop
+ ila tab4, _ovly_buf_table - 4 # 0,2 46
+#lnop
+#nop; lnop
+#nop; lnop
+#nop
+ lqx map, tab4, off4 # 1,6 49
+#nop
+ cwx genwi, tab4, off4 # 1,4 50
+ a addr4, tab4, off4 # 0,2 51
+#lnop
+#nop; lnop
+#nop; lnop
+#nop; lnop
+#nop
+ rotqby oldovl, map, addr4 # 1,4 55
+#nop
+ shufb newmap, newovl, map, genwi # 0,4 56
+#if MFC_TAG_ID < 16
+ ila newmask, 1 << MFC_TAG_ID # 0,2 57
+#else
+ ilhu newmask, 1 << (MFC_TAG_ID - 16) # 0,2 57
+#endif
+#lnop
+#nop; lnop
+#nop; lnop
+ stqd newmap, 0(addr4) # 1,6 60
+
+/* Save app's tagmask, wait for DMA complete, restore mask. */
+ ila tagstat, MFC_TAG_UPDATE_ALL # 0,2 61
+ rdch oldmask, $MFC_RdTagMask # 1,6 61
+#nop
+ wrch $MFC_WrTagMask, newmask # 1,6 62
+#nop
+ wrch $MFC_WrTagUpdate, tagstat # 1,6 63
+#nop
+ rdch tagstat, $MFC_RdTagStat # 1,6 64
+#nop
+ sync # 1,4 65
+/* Any hint prior to the sync is lost. A hint here allows the branch
+ to complete 15 cycles after the hint. With no hint the branch will
+ take 18 or 19 cycles. */
+ ila tab5, _ovly_table - 16 # 0,2 66
+ hbr do_load99, target # 1,15 66
+ shli off5, oldovl, 4 # 0,4 67
+ wrch $MFC_WrTagMask, oldmask # 1,6 67
+ ceqi zovl, oldovl, 0 # 0,2 68
+#lnop
+#nop; lnop
+#nop
+ fsm zovl, zovl # 1,4 70
+#nop
+ lqx oldvma, tab5, off5 # 1,6 71
+#nop
+ lqd save3, -48($sp) # 1,6 72
+#nop; lnop
+ andc pbit, pbit, zovl # 0,2 74
+ lqd save2, -32($sp) # 1,6 74
+#ifdef OVLY_IRQ_SAVE
+ ila irqtmp2, do_load90 # 0,2 75
+#lnop
+ andi irq_stat, irq_stat, 1 # 0,2 76
+#lnop
+#else
+#nop; lnop
+#nop; lnop
+#endif
+ andc oldvma, oldvma, pbit # 0,2 77
+ lqd save1, -16($sp) # 1,6 77
+ nop # 0,0 78
+#lnop
+#nop
+ stqx oldvma, tab5, off5 # 1,6 79
+#nop
+#ifdef OVLY_IRQ_SAVE
+ binze irq_stat, irqtmp2 # 1,4 80
+do_load90:
+#nop
+ lqd save4, -64($sp) # 1,6 84
+#else
+#nop; lnop
+#endif
+
+ .global _ovly_debug_event
+ .type _ovly_debug_event, @function
+_ovly_debug_event:
+ nop
+/* Branch to target address. */
+do_load99:
+ bi target # 1,4 81/85
+
+ .size __ovly_load, . - __ovly_load
diff --git a/binutils-2.20.1/ld/emultempl/spu_ovl.o_c b/binutils-2.20.1/ld/emultempl/spu_ovl.o_c
new file mode 100644
index 00000000..c9eff93f
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/spu_ovl.o_c
@@ -0,0 +1,101 @@
+0x7f,0x45,0x4c,0x46,0x01,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x01,0x00,0x17,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x02,0x74,0x00,0x00,0x00,0x00,0x00,0x34,0x00,0x00,0x00,0x00,0x00,0x28,
+0x00,0x08,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x01,0x02,0x03,0x10,0x11,0x12,0x13,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+0x04,0x05,0x06,0x07,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x42,0x00,0x00,0x4b,0x3f,0xe1,0x00,0x4e,0x3f,0xe2,0x00,0x4f,0x0f,0x61,0x27,0x4c,
+0x35,0x80,0x27,0x8b,0x38,0x93,0x25,0xcb,0x40,0x20,0x00,0x00,0x24,0xff,0x00,0xc7,
+0x3f,0x81,0x25,0xcd,0x24,0xff,0x40,0xc8,0x24,0xff,0x80,0xc9,0x24,0xff,0xc0,0xca,
+0x14,0x00,0x66,0xcc,0x23,0xff,0xf7,0xce,0x20,0x00,0x0e,0x4c,0x35,0x00,0x27,0x80,
+0x42,0x00,0x00,0x4b,0x24,0xff,0x40,0xc8,0x42,0x00,0x00,0x48,0x24,0xff,0x80,0xc9,
+0x0f,0x61,0x27,0x4c,0x33,0xff,0xf3,0xc9,0x40,0x20,0x00,0x00,0x23,0xff,0xf2,0xce,
+0x78,0x12,0x00,0x4e,0x33,0xff,0xed,0xcd,0x35,0x80,0x27,0x8f,0x38,0x93,0x25,0xcb,
+0x24,0xff,0xc0,0xca,0xb9,0x52,0x64,0x4d,0x36,0xc0,0x27,0x4e,0x3f,0xbe,0x00,0x49,
+0x3f,0x81,0x25,0xcd,0x34,0xff,0x40,0xc8,0x08,0x32,0x65,0x4a,0x34,0xff,0x80,0xc9,
+0x14,0x00,0x66,0xcc,0x24,0xff,0x00,0xc7,0x80,0x00,0x25,0x4e,0x34,0xff,0xc0,0xca,
+0x20,0x00,0x01,0x4c,0x35,0x00,0x27,0x80,0x42,0x00,0x00,0x4e,0x3f,0x82,0x25,0xcc,
+0x01,0xa0,0x06,0xc7,0x35,0x08,0x27,0x00,0x40,0x20,0x00,0x00,0x3f,0x81,0x25,0xc9,
+0x30,0x80,0x00,0x48,0x33,0xff,0xe3,0xce,0x3f,0xbf,0x26,0x4d,0x18,0x53,0x64,0x4c,
+0xb9,0x93,0x26,0x4e,0x68,0x13,0x64,0x4c,0x42,0x20,0x00,0x4a,0x00,0x20,0x00,0x00,
+0x04,0x00,0x26,0x48,0x3f,0x81,0x26,0x4d,0x48,0x12,0xa4,0xcc,0x21,0xa0,0x08,0x4b,
+0x89,0x92,0xa4,0xcc,0x21,0xa0,0x08,0xc8,0x42,0x00,0x00,0x4a,0x21,0xa0,0x09,0x4d,
+0x42,0x00,0x20,0x4d,0x21,0xa0,0x09,0xcc,0x08,0x12,0x66,0x49,0x21,0xa0,0x0a,0x4a,
+0x18,0x13,0x25,0xcb,0x21,0xa0,0x0a,0xcd,0x21,0x7f,0xf6,0x49,0x33,0xff,0xda,0xce,
+0x0f,0x61,0x27,0x4c,0x42,0x00,0x00,0x4d,0x32,0x80,0x80,0x4a,0x38,0x93,0x26,0xcb,
+0x14,0x00,0x65,0x4a,0x00,0x20,0x00,0x00,0x08,0x32,0xa5,0xc9,0x3f,0x83,0x25,0xc8,
+0x28,0x93,0x26,0xc9,0x0f,0x60,0xa4,0x4c,0x42,0x00,0x00,0x4d,0x38,0x93,0x26,0xcb,
+0x3a,0xd3,0x26,0xc8,0x18,0x13,0x26,0xcc,0x3b,0x93,0x25,0xc9,0xb9,0x12,0xe7,0x48,
+0x42,0x00,0x00,0xcb,0x24,0x00,0x26,0x48,0x42,0x00,0x01,0x4c,0x01,0xa0,0x06,0x48,
+0x21,0xa0,0x0b,0x4b,0x21,0xa0,0x0b,0xcc,0x01,0xa0,0x0c,0x4c,0x00,0x40,0x00,0x00,
+0x42,0x00,0x00,0x4d,0x35,0x80,0x27,0x92,0x0f,0x61,0x24,0xcc,0x21,0xa0,0x0b,0x48,
+0x7c,0x00,0x24,0xc9,0x36,0x80,0x24,0xc9,0x38,0x93,0x26,0xcb,0x34,0xff,0x40,0xc8,
+0x58,0x32,0x65,0x4a,0x34,0xff,0x80,0xc9,0x42,0x00,0x00,0x4e,0x14,0x00,0x63,0xc7,
+0x58,0x32,0xa5,0xcb,0x34,0xff,0xc0,0xca,0x40,0x20,0x00,0x00,0x28,0x93,0x26,0xcb,
+0x25,0x24,0x27,0x47,0x34,0xff,0x00,0xc7,0x40,0x20,0x00,0x00,0x35,0x00,0x27,0x80,
+0x00,0x2e,0x73,0x79,0x6d,0x74,0x61,0x62,0x00,0x2e,0x73,0x74,0x72,0x74,0x61,0x62,
+0x00,0x2e,0x73,0x68,0x73,0x74,0x72,0x74,0x61,0x62,0x00,0x2e,0x72,0x65,0x6c,0x61,
+0x2e,0x74,0x65,0x78,0x74,0x00,0x2e,0x64,0x61,0x74,0x61,0x00,0x2e,0x62,0x73,0x73,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,
+0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,
+0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xdc,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x06,
+0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x26,
+0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x40,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x03,
+0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,
+0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x40,
+0x00,0x00,0x00,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xb4,0x00,0x00,0x01,0x50,0x00,0x00,0x00,0x07,
+0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x09,
+0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x04,
+0x00,0x00,0x00,0xd6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x03,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x03,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x03,0x00,0x00,0x04,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,
+0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10,
+0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x1b,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x10,
+0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x34,0x00,0x00,0x00,0xd8,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0xd4,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x47,0x00,0x00,0x00,0xe8,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x62,0x00,0x00,0x01,0xfc,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x6c,0x00,0x00,0x01,0xf4,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x76,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,
+0x12,0x00,0x00,0x01,0x00,0x00,0x00,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0x00,0x00,0x70,0x00,0x00,0x01,0x90,
+0x12,0x00,0x00,0x01,0x00,0x00,0x00,0x9c,0x00,0x00,0x00,0xd8,0x00,0x00,0x00,0x00,
+0x12,0x00,0x00,0x01,0x00,0x00,0x00,0xae,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x10,0x00,0x00,0x00,0x00,0x00,0x00,0xb4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x10,0x00,0x00,0x00,0x00,0x00,0x00,0xc4,0x00,0x00,0x01,0xf8,0x00,0x00,0x00,0x00,
+0x12,0x00,0x00,0x01,0x00,0x5f,0x5f,0x72,0x76,0x5f,0x70,0x61,0x74,0x74,0x65,0x72,
+0x6e,0x00,0x5f,0x5f,0x63,0x67,0x5f,0x70,0x61,0x74,0x74,0x65,0x72,0x6e,0x00,0x5f,
+0x5f,0x6f,0x76,0x6c,0x79,0x5f,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x00,0x6f,0x76,
+0x6c,0x79,0x5f,0x72,0x65,0x74,0x39,0x00,0x64,0x6f,0x5f,0x6c,0x6f,0x61,0x64,0x00,
+0x6f,0x76,0x6c,0x79,0x5f,0x6c,0x6f,0x61,0x64,0x39,0x00,0x64,0x6f,0x5f,0x6c,0x6f,
+0x61,0x64,0x31,0x30,0x00,0x5f,0x5f,0x6f,0x76,0x6c,0x79,0x5f,0x78,0x66,0x65,0x72,
+0x5f,0x6c,0x6f,0x6f,0x70,0x00,0x64,0x6f,0x5f,0x6c,0x6f,0x61,0x64,0x39,0x39,0x00,
+0x64,0x6f,0x5f,0x6c,0x6f,0x61,0x64,0x39,0x30,0x00,0x5f,0x5f,0x6f,0x76,0x6c,0x79,
+0x5f,0x72,0x65,0x74,0x75,0x72,0x6e,0x00,0x5f,0x6f,0x76,0x6c,0x79,0x5f,0x74,0x61,
+0x62,0x6c,0x65,0x00,0x5f,0x5f,0x6f,0x76,0x6c,0x79,0x5f,0x6c,0x6f,0x61,0x64,0x00,
+0x5f,0x5f,0x6f,0x76,0x6c,0x79,0x5f,0x6c,0x6f,0x61,0x64,0x5f,0x65,0x76,0x65,0x6e,
+0x74,0x00,0x5f,0x45,0x41,0x52,0x5f,0x00,0x5f,0x6f,0x76,0x6c,0x79,0x5f,0x62,0x75,
+0x66,0x5f,0x74,0x61,0x62,0x6c,0x65,0x00,0x5f,0x6f,0x76,0x6c,0x79,0x5f,0x64,0x65,
+0x62,0x75,0x67,0x5f,0x65,0x76,0x65,0x6e,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x30,
+0x00,0x00,0x0f,0x05,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x70,0x00,0x00,0x0f,0x05,
+0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x78,0x00,0x00,0x0e,0x05,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0xd8,0x00,0x00,0x01,0x05,0x00,0x00,0x00,0xe8,0x00,0x00,0x00,0xf0,
+0x00,0x00,0x12,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x54,0x00,0x00,0x0f,0x05,
+0xff,0xff,0xff,0xf0,0x00,0x00,0x01,0x78,0x00,0x00,0x13,0x05,0xff,0xff,0xff,0xfc,
+0x00,0x00,0x01,0xb0,0x00,0x00,0x0f,0x05,0xff,0xff,0xff,0xf0,0x00,0x00,0x01,0xd8,
+0x00,0x00,0x01,0x05,0x00,0x00,0x01,0xf4,
diff --git a/binutils-2.20.1/ld/emultempl/spuelf.em b/binutils-2.20.1/ld/emultempl/spuelf.em
new file mode 100644
index 00000000..2ea760a7
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/spuelf.em
@@ -0,0 +1,824 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+# This file is sourced from elf32.em, and defines extra spu specific
+# features.
+#
+fragment <<EOF
+#include "ldctor.h"
+#include "elf32-spu.h"
+
+static void spu_place_special_section (asection *, asection *, const char *);
+static bfd_size_type spu_elf_load_ovl_mgr (void);
+static FILE *spu_elf_open_overlay_script (void);
+static void spu_elf_relink (void);
+
+static struct spu_elf_params params =
+{
+ &spu_place_special_section,
+ &spu_elf_load_ovl_mgr,
+ &spu_elf_open_overlay_script,
+ &spu_elf_relink,
+ 0, ovly_normal, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0x3ffff,
+ 1, 0, 16, 0, 0, 2000
+};
+
+static unsigned int no_overlays = 0;
+static unsigned int num_lines_set = 0;
+static unsigned int line_size_set = 0;
+static char *auto_overlay_file = 0;
+int my_argc;
+char **my_argv;
+
+static const char ovl_mgr[] = {
+EOF
+
+if ! cat ${srcdir}/emultempl/spu_ovl.o_c >> e${EMULATION_NAME}.c
+then
+ echo >&2 "Missing ${srcdir}/emultempl/spu_ovl.o_c"
+ echo >&2 "You must build gas/as-new with --target=spu"
+ exit 1
+fi
+
+fragment <<EOF
+};
+
+static const char icache_mgr[] = {
+EOF
+
+if ! cat ${srcdir}/emultempl/spu_icache.o_c >> e${EMULATION_NAME}.c
+then
+ echo >&2 "Missing ${srcdir}/emultempl/spu_icache.o_c"
+ echo >&2 "You must build gas/as-new with --target=spu"
+ exit 1
+fi
+
+fragment <<EOF
+};
+
+static const struct _ovl_stream ovl_mgr_stream = {
+ ovl_mgr,
+ ovl_mgr + sizeof (ovl_mgr)
+};
+
+static const struct _ovl_stream icache_mgr_stream = {
+ icache_mgr,
+ icache_mgr + sizeof (icache_mgr)
+};
+
+
+static int
+is_spu_target (void)
+{
+ extern const bfd_target bfd_elf32_spu_vec;
+
+ return link_info.output_bfd->xvec == &bfd_elf32_spu_vec;
+}
+
+/* Create our note section. */
+
+static void
+spu_after_open (void)
+{
+ if (is_spu_target ())
+ {
+ /* Pass params to backend. */
+ if ((params.auto_overlay & AUTO_OVERLAY) == 0)
+ params.auto_overlay = 0;
+ params.emit_stub_syms |= link_info.emitrelocations;
+ spu_elf_setup (&link_info, &params);
+
+ if (link_info.relocatable)
+ lang_add_unique (".text.ia.*");
+
+ if (!link_info.relocatable
+ && link_info.input_bfds != NULL
+ && !spu_elf_create_sections (&link_info))
+ einfo ("%X%P: can not create note section: %E\n");
+ }
+
+ gld${EMULATION_NAME}_after_open ();
+}
+
+/* If O is NULL, add section S at the end of output section OUTPUT_NAME.
+ If O is not NULL, add section S at the beginning of output section O,
+ except for soft-icache which adds to the end.
+
+ Really, we should be duplicating ldlang.c map_input_to_output_sections
+ logic here, ie. using the linker script to find where the section
+ goes. That's rather a lot of code, and we don't want to run
+ map_input_to_output_sections again because most sections are already
+ mapped. So cheat, and put the section in a fixed place, ignoring any
+ attempt via a linker script to put .stub, .ovtab, and built-in
+ overlay manager code somewhere else. */
+
+static void
+spu_place_special_section (asection *s, asection *o, const char *output_name)
+{
+ lang_output_section_statement_type *os;
+
+ if (o != NULL)
+ output_name = o->name;
+ os = lang_output_section_find (output_name);
+ if (os == NULL)
+ {
+ os = gld${EMULATION_NAME}_place_orphan (s, output_name, 0);
+ os->addr_tree = NULL;
+ }
+ else if (params.ovly_flavour != ovly_soft_icache
+ && o != NULL && os->children.head != NULL)
+ {
+ lang_statement_list_type add;
+
+ lang_list_init (&add);
+ lang_add_section (&add, s, os);
+ *add.tail = os->children.head;
+ os->children.head = add.head;
+ }
+ else
+ {
+ if (params.ovly_flavour == ovly_soft_icache && o != NULL)
+ {
+ /* Pad this stub section so that it finishes at the
+ end of the icache line. */
+ etree_type *e_size;
+
+ push_stat_ptr (&os->children);
+ e_size = exp_intop (params.line_size - s->size);
+ lang_add_assignment (exp_assop ('=', ".", e_size));
+ pop_stat_ptr ();
+ }
+ lang_add_section (&os->children, s, os);
+ }
+
+ s->output_section->size += s->size;
+}
+
+/* Load built-in overlay manager. */
+
+static bfd_size_type
+spu_elf_load_ovl_mgr (void)
+{
+ struct elf_link_hash_entry *h;
+ const char *ovly_mgr_entry;
+ const struct _ovl_stream *mgr_stream;
+ bfd_size_type total = 0;
+
+ ovly_mgr_entry = "__ovly_load";
+ mgr_stream = &ovl_mgr_stream;
+ if (params.ovly_flavour == ovly_soft_icache)
+ {
+ ovly_mgr_entry = "__icache_br_handler";
+ mgr_stream = &icache_mgr_stream;
+ }
+ h = elf_link_hash_lookup (elf_hash_table (&link_info),
+ ovly_mgr_entry, FALSE, FALSE, FALSE);
+
+ if (h != NULL
+ && (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && h->def_regular)
+ {
+ /* User supplied __ovly_load. */
+ }
+ else if (mgr_stream->start == mgr_stream->end)
+ einfo ("%F%P: no built-in overlay manager\n");
+ else
+ {
+ lang_input_statement_type *ovl_is;
+
+ ovl_is = lang_add_input_file ("builtin ovl_mgr",
+ lang_input_file_is_file_enum,
+ NULL);
+
+ if (!spu_elf_open_builtin_lib (&ovl_is->the_bfd, mgr_stream))
+ einfo ("%X%P: can not open built-in overlay manager: %E\n");
+ else
+ {
+ asection *in;
+
+ if (!load_symbols (ovl_is, NULL))
+ einfo ("%X%P: can not load built-in overlay manager: %E\n");
+
+ /* Map overlay manager sections to output sections.
+ First try for a matching output section name, if that
+ fails then try mapping .abc.xyz to .abc, otherwise map
+ to .text. */
+ for (in = ovl_is->the_bfd->sections; in != NULL; in = in->next)
+ if ((in->flags & (SEC_ALLOC | SEC_LOAD))
+ == (SEC_ALLOC | SEC_LOAD))
+ {
+ const char *oname = in->name;
+ if (strncmp (in->name, ".ovl.init", 9) != 0)
+ {
+ total += in->size;
+ if (!lang_output_section_find (oname))
+ {
+ lang_output_section_statement_type *os = NULL;
+ char *p = strchr (oname + 1, '.');
+ if (p != NULL)
+ {
+ size_t len = p - oname;
+ p = memcpy (xmalloc (len + 1), oname, len);
+ p[len] = '\0';
+ os = lang_output_section_find (p);
+ free (p);
+ }
+ if (os != NULL)
+ oname = os->name;
+ else
+ oname = ".text";
+ }
+ }
+
+ spu_place_special_section (in, NULL, oname);
+ }
+ }
+ }
+ return total;
+}
+
+/* Go find if we need to do anything special for overlays. */
+
+static void
+spu_before_allocation (void)
+{
+ if (is_spu_target ()
+ && !link_info.relocatable
+ && !no_overlays)
+ {
+ int ret;
+
+ /* Size the sections. This is premature, but we need to know the
+ rough layout so that overlays can be found. */
+ expld.phase = lang_mark_phase_enum;
+ expld.dataseg.phase = exp_dataseg_none;
+ one_lang_size_sections_pass (NULL, TRUE);
+
+ /* Find overlays by inspecting section vmas. */
+ ret = spu_elf_find_overlays (&link_info);
+ if (ret == 0)
+ einfo ("%X%P: can not find overlays: %E\n");
+ else if (ret == 2)
+ {
+ lang_output_section_statement_type *os;
+
+ if (params.auto_overlay != 0)
+ {
+ einfo ("%P: --auto-overlay ignored with user overlay script\n");
+ params.auto_overlay = 0;
+ }
+
+ /* Ensure alignment of overlay sections is sufficient. */
+ for (os = &lang_output_section_statement.head->output_section_statement;
+ os != NULL;
+ os = os->next)
+ if (os->bfd_section != NULL
+ && spu_elf_section_data (os->bfd_section) != NULL
+ && spu_elf_section_data (os->bfd_section)->u.o.ovl_index != 0)
+ {
+ if (os->bfd_section->alignment_power < 4)
+ os->bfd_section->alignment_power = 4;
+
+ /* Also ensure size rounds up. */
+ os->block_value = 16;
+ }
+
+ ret = spu_elf_size_stubs (&link_info);
+ if (ret == 0)
+ einfo ("%X%P: can not size overlay stubs: %E\n");
+ else if (ret == 2)
+ spu_elf_load_ovl_mgr ();
+
+ spu_elf_place_overlay_data (&link_info);
+ }
+
+ /* We must not cache anything from the preliminary sizing. */
+ lang_reset_memory_regions ();
+ }
+
+ if (is_spu_target ()
+ && !link_info.relocatable)
+ spu_elf_size_sections (link_info.output_bfd, &link_info);
+
+ gld${EMULATION_NAME}_before_allocation ();
+}
+
+struct tflist {
+ struct tflist *next;
+ char name[9];
+};
+
+static struct tflist *tmp_file_list;
+
+static void clean_tmp (void)
+{
+ for (; tmp_file_list != NULL; tmp_file_list = tmp_file_list->next)
+ unlink (tmp_file_list->name);
+}
+
+static int
+new_tmp_file (char **fname)
+{
+ struct tflist *tf;
+ int fd;
+
+ if (tmp_file_list == NULL)
+ atexit (clean_tmp);
+ tf = xmalloc (sizeof (*tf));
+ tf->next = tmp_file_list;
+ tmp_file_list = tf;
+ memcpy (tf->name, "ldXXXXXX", sizeof (tf->name));
+ *fname = tf->name;
+#ifdef HAVE_MKSTEMP
+ fd = mkstemp (*fname);
+#else
+ *fname = mktemp (*fname);
+ if (*fname == NULL)
+ return -1;
+ fd = open (fname, O_RDWR | O_CREAT | O_EXCL, 0600);
+#endif
+ return fd;
+}
+
+static FILE *
+spu_elf_open_overlay_script (void)
+{
+ FILE *script = NULL;
+
+ if (auto_overlay_file == NULL)
+ {
+ int fd = new_tmp_file (&auto_overlay_file);
+ if (fd == -1)
+ goto file_err;
+ script = fdopen (fd, "w");
+ }
+ else
+ script = fopen (auto_overlay_file, "w");
+
+ if (script == NULL)
+ {
+ file_err:
+ einfo ("%F%P: can not open script: %E\n");
+ }
+ return script;
+}
+
+static void
+spu_elf_relink (void)
+{
+ char **argv = xmalloc ((my_argc + 4) * sizeof (*argv));
+
+ memcpy (argv, my_argv, my_argc * sizeof (*argv));
+ argv[my_argc++] = "--no-auto-overlay";
+ if (tmp_file_list->name == auto_overlay_file)
+ argv[my_argc - 1] = concat (argv[my_argc - 1], "=",
+ auto_overlay_file, (const char *) NULL);
+ argv[my_argc++] = "-T";
+ argv[my_argc++] = auto_overlay_file;
+ argv[my_argc] = 0;
+ execvp (argv[0], (char *const *) argv);
+ perror (argv[0]);
+ _exit (127);
+}
+
+/* Final emulation specific call. */
+
+static void
+gld${EMULATION_NAME}_finish (void)
+{
+ if (is_spu_target ())
+ {
+ if (params.local_store_lo < params.local_store_hi)
+ {
+ asection *s;
+
+ s = spu_elf_check_vma (&link_info);
+ if (s != NULL && !params.auto_overlay)
+ einfo ("%X%P: %A exceeds local store range\n", s);
+ }
+ else if (params.auto_overlay)
+ einfo ("%P: --auto-overlay ignored with zero local store range\n");
+ }
+
+ finish_default ();
+}
+
+static char *
+gld${EMULATION_NAME}_choose_target (int argc, char *argv[])
+{
+ my_argc = argc;
+ my_argv = argv;
+ return ldemul_default_target (argc, argv);
+}
+
+EOF
+
+if grep -q 'ld_elf.*ppc.*_emulation' ldemul-list.h; then
+ fragment <<EOF
+#include <errno.h>
+#include "filenames.h"
+#include "libiberty.h"
+
+static const char *
+base_name (const char *path)
+{
+ const char *file = strrchr (path, '/');
+#ifdef HAVE_DOS_BASED_FILE_SYSTEM
+ {
+ char *bslash = strrchr (path, '\\\\');
+
+ if (file == NULL || (bslash != NULL && bslash > file))
+ file = bslash;
+ if (file == NULL
+ && path[0] != '\0'
+ && path[1] == ':')
+ file = path + 1;
+ }
+#endif
+ if (file == NULL)
+ file = path;
+ else
+ ++file;
+ return file;
+}
+
+/* This function is called when building a ppc32 or ppc64 executable
+ to handle embedded spu images. */
+extern bfd_boolean embedded_spu_file (lang_input_statement_type *, const char *);
+
+bfd_boolean
+embedded_spu_file (lang_input_statement_type *entry, const char *flags)
+{
+ const char *cmd[6];
+ const char *pex_return;
+ const char *sym;
+ char *handle, *p;
+ char *oname;
+ int fd;
+ int status;
+ union lang_statement_union **old_stat_tail;
+ union lang_statement_union **old_file_tail;
+ union lang_statement_union *new_ent;
+ lang_input_statement_type *search;
+
+ if (entry->the_bfd->format != bfd_object
+ || strcmp (entry->the_bfd->xvec->name, "elf32-spu") != 0
+ || (entry->the_bfd->tdata.elf_obj_data->elf_header->e_type != ET_EXEC
+ && entry->the_bfd->tdata.elf_obj_data->elf_header->e_type != ET_DYN))
+ return FALSE;
+
+ /* Use the filename as the symbol marking the program handle struct. */
+ sym = base_name (entry->the_bfd->filename);
+
+ handle = xstrdup (sym);
+ for (p = handle; *p; ++p)
+ if (!(ISALNUM (*p) || *p == '$' || *p == '.'))
+ *p = '_';
+
+ fd = new_tmp_file (&oname);
+ if (fd == -1)
+ return FALSE;
+ close (fd);
+
+ for (search = (lang_input_statement_type *) input_file_chain.head;
+ search != NULL;
+ search = (lang_input_statement_type *) search->next_real_file)
+ if (search->filename != NULL)
+ {
+ const char *infile = base_name (search->filename);
+
+ if (strncmp (infile, "crtbegin", 8) == 0)
+ {
+ if (infile[8] == 'S')
+ flags = concat (flags, " -fPIC", (const char *) NULL);
+ else if (infile[8] == 'T')
+ flags = concat (flags, " -fpie", (const char *) NULL);
+ break;
+ }
+ }
+
+ cmd[0] = EMBEDSPU;
+ cmd[1] = flags;
+ cmd[2] = handle;
+ cmd[3] = entry->the_bfd->filename;
+ cmd[4] = oname;
+ cmd[5] = NULL;
+ if (trace_file_tries)
+ {
+ info_msg (_("running: %s \"%s\" \"%s\" \"%s\" \"%s\"\n"),
+ cmd[0], cmd[1], cmd[2], cmd[3], cmd[4]);
+ fflush (stdout);
+ }
+
+ pex_return = pex_one (PEX_SEARCH | PEX_LAST, cmd[0], (char *const *) cmd,
+ cmd[0], NULL, NULL, &status, &errno);
+ if (NULL != pex_return) {
+ if (strcmp ("embedspu", EMBEDSPU) != 0)
+ {
+ cmd[0] = "embedspu";
+ pex_return = pex_one (PEX_SEARCH | PEX_LAST, cmd[0], (char *const *) cmd,
+ cmd[0], NULL, NULL, &status, &errno);
+ }
+ if (NULL != pex_return) {
+ perror (pex_return);
+ _exit (127);
+ }
+ }
+ if (status)
+ return FALSE;
+
+
+ old_stat_tail = stat_ptr->tail;
+ old_file_tail = input_file_chain.tail;
+ if (lang_add_input_file (oname, lang_input_file_is_file_enum, NULL) == NULL)
+ return FALSE;
+
+ /* lang_add_input_file puts the new list entry at the end of the statement
+ and input file lists. Move it to just after the current entry. */
+ new_ent = *old_stat_tail;
+ *old_stat_tail = NULL;
+ stat_ptr->tail = old_stat_tail;
+ *old_file_tail = NULL;
+ input_file_chain.tail = old_file_tail;
+ new_ent->header.next = entry->header.next;
+ entry->header.next = new_ent;
+ new_ent->input_statement.next_real_file = entry->next_real_file;
+ entry->next_real_file = new_ent;
+
+ /* Ensure bfd sections are excluded from the output. */
+ bfd_section_list_clear (entry->the_bfd);
+ entry->loaded = TRUE;
+ return TRUE;
+}
+
+EOF
+fi
+
+# 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_SPU_PLUGIN 301
+#define OPTION_SPU_NO_OVERLAYS (OPTION_SPU_PLUGIN + 1)
+#define OPTION_SPU_COMPACT_STUBS (OPTION_SPU_NO_OVERLAYS + 1)
+#define OPTION_SPU_STUB_SYMS (OPTION_SPU_COMPACT_STUBS + 1)
+#define OPTION_SPU_NON_OVERLAY_STUBS (OPTION_SPU_STUB_SYMS + 1)
+#define OPTION_SPU_LOCAL_STORE (OPTION_SPU_NON_OVERLAY_STUBS + 1)
+#define OPTION_SPU_STACK_ANALYSIS (OPTION_SPU_LOCAL_STORE + 1)
+#define OPTION_SPU_STACK_SYMS (OPTION_SPU_STACK_ANALYSIS + 1)
+#define OPTION_SPU_AUTO_OVERLAY (OPTION_SPU_STACK_SYMS + 1)
+#define OPTION_SPU_AUTO_RELINK (OPTION_SPU_AUTO_OVERLAY + 1)
+#define OPTION_SPU_OVERLAY_RODATA (OPTION_SPU_AUTO_RELINK + 1)
+#define OPTION_SPU_SOFT_ICACHE (OPTION_SPU_OVERLAY_RODATA + 1)
+#define OPTION_SPU_LINE_SIZE (OPTION_SPU_SOFT_ICACHE + 1)
+#define OPTION_SPU_NUM_LINES (OPTION_SPU_LINE_SIZE + 1)
+#define OPTION_SPU_LRLIVE (OPTION_SPU_NUM_LINES + 1)
+#define OPTION_SPU_NON_IA_TEXT (OPTION_SPU_LRLIVE + 1)
+#define OPTION_SPU_FIXED_SPACE (OPTION_SPU_NON_IA_TEXT + 1)
+#define OPTION_SPU_RESERVED_SPACE (OPTION_SPU_FIXED_SPACE + 1)
+#define OPTION_SPU_EXTRA_STACK (OPTION_SPU_RESERVED_SPACE + 1)
+#define OPTION_SPU_NO_AUTO_OVERLAY (OPTION_SPU_EXTRA_STACK + 1)
+#define OPTION_SPU_EMIT_FIXUPS (OPTION_SPU_NO_AUTO_OVERLAY + 1)
+'
+
+PARSE_AND_LIST_LONGOPTS='
+ { "plugin", no_argument, NULL, OPTION_SPU_PLUGIN },
+ { "soft-icache", no_argument, NULL, OPTION_SPU_SOFT_ICACHE },
+ { "lrlive-analysis", no_argument, NULL, OPTION_SPU_LRLIVE },
+ { "num-lines", required_argument, NULL, OPTION_SPU_NUM_LINES },
+ { "line-size", required_argument, NULL, OPTION_SPU_LINE_SIZE },
+ { "non-ia-text", no_argument, NULL, OPTION_SPU_NON_IA_TEXT },
+ { "no-overlays", no_argument, NULL, OPTION_SPU_NO_OVERLAYS },
+ { "compact-stubs", no_argument, NULL, OPTION_SPU_COMPACT_STUBS },
+ { "emit-stub-syms", no_argument, NULL, OPTION_SPU_STUB_SYMS },
+ { "extra-overlay-stubs", no_argument, NULL, OPTION_SPU_NON_OVERLAY_STUBS },
+ { "local-store", required_argument, NULL, OPTION_SPU_LOCAL_STORE },
+ { "stack-analysis", no_argument, NULL, OPTION_SPU_STACK_ANALYSIS },
+ { "emit-stack-syms", no_argument, NULL, OPTION_SPU_STACK_SYMS },
+ { "auto-overlay", optional_argument, NULL, OPTION_SPU_AUTO_OVERLAY },
+ { "auto-relink", no_argument, NULL, OPTION_SPU_AUTO_RELINK },
+ { "overlay-rodata", no_argument, NULL, OPTION_SPU_OVERLAY_RODATA },
+ { "num-regions", required_argument, NULL, OPTION_SPU_NUM_LINES },
+ { "region-size", required_argument, NULL, OPTION_SPU_LINE_SIZE },
+ { "fixed-space", required_argument, NULL, OPTION_SPU_FIXED_SPACE },
+ { "reserved-space", required_argument, NULL, OPTION_SPU_RESERVED_SPACE },
+ { "extra-stack-space", required_argument, NULL, OPTION_SPU_EXTRA_STACK },
+ { "no-auto-overlay", optional_argument, NULL, OPTION_SPU_NO_AUTO_OVERLAY },
+ { "emit-fixups", optional_argument, NULL, OPTION_SPU_EMIT_FIXUPS },
+'
+
+PARSE_AND_LIST_OPTIONS='
+ fprintf (file, _("\
+ --plugin Make SPU plugin.\n\
+ --no-overlays No overlay handling.\n\
+ --compact-stubs Use smaller and possibly slower call stubs.\n\
+ --emit-stub-syms Add symbols on overlay call stubs.\n\
+ --extra-overlay-stubs Add stubs on all calls out of overlay regions.\n\
+ --local-store=lo:hi Valid address range.\n\
+ --stack-analysis Estimate maximum stack requirement.\n\
+ --emit-stack-syms Add sym giving stack needed for each func.\n\
+ --auto-overlay [=filename] Create an overlay script in filename if\n\
+ executable does not fit in local store.\n\
+ --auto-relink Rerun linker using auto-overlay script.\n\
+ --overlay-rodata Place read-only data with associated function\n\
+ code in overlays.\n\
+ --num-regions Number of overlay buffers (default 1).\n\
+ --region-size Size of overlay buffers (default 0, auto).\n\
+ --fixed-space=bytes Local store for non-overlay code and data.\n\
+ --reserved-space=bytes Local store for stack and heap. If not specified\n\
+ ld will estimate stack size and assume no heap.\n\
+ --extra-stack-space=bytes Space for negative sp access (default 2000) if\n\
+ --reserved-space not given.\n\
+ --soft-icache Generate software icache overlays.\n\
+ --num-lines Number of soft-icache lines (default 32).\n\
+ --line-size Size of soft-icache lines (default 1k).\n\
+ --non-ia-text Allow non-icache code in icache lines.\n\
+ --lrlive-analysis Scan function prologue for lr liveness.\n"
+ ));
+'
+
+PARSE_AND_LIST_ARGS_CASES='
+ case OPTION_SPU_PLUGIN:
+ spu_elf_plugin (1);
+ break;
+
+ case OPTION_SPU_NO_OVERLAYS:
+ no_overlays = 1;
+ break;
+
+ case OPTION_SPU_COMPACT_STUBS:
+ params.compact_stub = 1;
+ break;
+
+ case OPTION_SPU_STUB_SYMS:
+ params.emit_stub_syms = 1;
+ break;
+
+ case OPTION_SPU_NON_OVERLAY_STUBS:
+ params.non_overlay_stubs = 1;
+ break;
+
+ case OPTION_SPU_LOCAL_STORE:
+ {
+ char *end;
+ params.local_store_lo = strtoul (optarg, &end, 0);
+ if (*end == '\'':'\'')
+ {
+ params.local_store_hi = strtoul (end + 1, &end, 0);
+ if (*end == 0)
+ break;
+ }
+ einfo (_("%P%F: invalid --local-store address range `%s'\''\n"), optarg);
+ }
+ break;
+
+ case OPTION_SPU_STACK_ANALYSIS:
+ params.stack_analysis = 1;
+ break;
+
+ case OPTION_SPU_STACK_SYMS:
+ params.emit_stack_syms = 1;
+ break;
+
+ case OPTION_SPU_AUTO_OVERLAY:
+ params.auto_overlay |= 1;
+ if (optarg != NULL)
+ {
+ auto_overlay_file = optarg;
+ break;
+ }
+ /* Fall thru */
+
+ case OPTION_SPU_AUTO_RELINK:
+ params.auto_overlay |= 2;
+ break;
+
+ case OPTION_SPU_OVERLAY_RODATA:
+ params.auto_overlay |= 4;
+ break;
+
+ case OPTION_SPU_SOFT_ICACHE:
+ params.ovly_flavour = ovly_soft_icache;
+ /* Software i-cache stubs are always "compact". */
+ params.compact_stub = 1;
+ if (!num_lines_set)
+ params.num_lines = 32;
+ else if ((params.num_lines & -params.num_lines) != params.num_lines)
+ einfo (_("%P%F: invalid --num-lines/--num-regions `%u'\''\n"),
+ params.num_lines);
+ if (!line_size_set)
+ params.line_size = 1024;
+ else if ((params.line_size & -params.line_size) != params.line_size)
+ einfo (_("%P%F: invalid --line-size/--region-size `%u'\''\n"),
+ params.line_size);
+ break;
+
+ case OPTION_SPU_LRLIVE:
+ params.lrlive_analysis = 1;
+ break;
+
+ case OPTION_SPU_NON_IA_TEXT:
+ params.non_ia_text = 1;
+ break;
+
+ case OPTION_SPU_NUM_LINES:
+ {
+ char *end;
+ params.num_lines = strtoul (optarg, &end, 0);
+ num_lines_set = 1;
+ if (*end == 0
+ && (params.ovly_flavour != ovly_soft_icache
+ || (params.num_lines & -params.num_lines) == params.num_lines))
+ break;
+ einfo (_("%P%F: invalid --num-lines/--num-regions `%s'\''\n"), optarg);
+ }
+ break;
+
+ case OPTION_SPU_LINE_SIZE:
+ {
+ char *end;
+ params.line_size = strtoul (optarg, &end, 0);
+ line_size_set = 1;
+ if (*end == 0
+ && (params.ovly_flavour != ovly_soft_icache
+ || (params.line_size & -params.line_size) == params.line_size))
+ break;
+ einfo (_("%P%F: invalid --line-size/--region-size `%s'\''\n"), optarg);
+ }
+ break;
+
+ case OPTION_SPU_FIXED_SPACE:
+ {
+ char *end;
+ params.auto_overlay_fixed = strtoul (optarg, &end, 0);
+ if (*end != 0)
+ einfo (_("%P%F: invalid --fixed-space value `%s'\''\n"), optarg);
+ }
+ break;
+
+ case OPTION_SPU_RESERVED_SPACE:
+ {
+ char *end;
+ params.auto_overlay_reserved = strtoul (optarg, &end, 0);
+ if (*end != 0)
+ einfo (_("%P%F: invalid --reserved-space value `%s'\''\n"), optarg);
+ }
+ break;
+
+ case OPTION_SPU_EXTRA_STACK:
+ {
+ char *end;
+ params.extra_stack_space = strtol (optarg, &end, 0);
+ if (*end != 0)
+ einfo (_("%P%F: invalid --extra-stack-space value `%s'\''\n"), optarg);
+ }
+ break;
+
+ case OPTION_SPU_NO_AUTO_OVERLAY:
+ params.auto_overlay = 0;
+ if (optarg != NULL)
+ {
+ struct tflist *tf;
+ size_t len;
+
+ if (tmp_file_list == NULL)
+ atexit (clean_tmp);
+
+ len = strlen (optarg) + 1;
+ tf = xmalloc (sizeof (*tf) - sizeof (tf->name) + len);
+ memcpy (tf->name, optarg, len);
+ tf->next = tmp_file_list;
+ tmp_file_list = tf;
+ break;
+ }
+ break;
+
+ case OPTION_SPU_EMIT_FIXUPS:
+ params.emit_fixups = 1;
+ break;
+'
+
+LDEMUL_AFTER_OPEN=spu_after_open
+LDEMUL_BEFORE_ALLOCATION=spu_before_allocation
+LDEMUL_FINISH=gld${EMULATION_NAME}_finish
+LDEMUL_CHOOSE_TARGET=gld${EMULATION_NAME}_choose_target
diff --git a/binutils-2.20.1/ld/emultempl/sunos.em b/binutils-2.20.1/ld/emultempl/sunos.em
new file mode 100644
index 00000000..bbd60751
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/sunos.em
@@ -0,0 +1,1037 @@
+# 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
+fragment <<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, 2001,
+ 2002, 2003, 2004, 2005, 2006, 2007, 2008 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 the GNU Binutils.
+
+ 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include "sysdep.h"
+#include "bfd.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} "*)
+fragment <<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
+fragment <<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 (CONST_STRNEQ (inp->local_sym_name, "-l"));
+
+ 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 (! CONST_STRNEQ (entry->d_name, "lib")
+ || 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 (! CONST_STRNEQ (entry->d_name + 3 + len, ".so"))
+ 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 (link_info.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 (! CONST_STRNEQ (lname, "-l"))
+ {
+ bfd *abfd;
+
+ abfd = bfd_openr (lname, bfd_get_target (link_info.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} "*)
+fragment <<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
+fragment <<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 (link_info.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 (! CONST_STRNEQ (global_needed->name, "-l"))
+ {
+ 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 (! CONST_STRNEQ (sname, "lib"))
+ 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->u.undef.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", 0, TRUE);
+ 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 (link_info.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 (link_info.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->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->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->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;
+ }
+
+ before_allocation_default ();
+}
+
+/* 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 (link_info.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 (link_info.output_bfd, need_pnames - need_contents,
+ need_pinfo);
+ if (! inp->is_archive)
+ {
+ bfd_put_32 (link_info.output_bfd, (bfd_vma) 0, need_pinfo + 4);
+ bfd_put_16 (link_info.output_bfd, (bfd_vma) 0, need_pinfo + 8);
+ bfd_put_16 (link_info.output_bfd, (bfd_vma) 0, need_pinfo + 10);
+ strcpy ((char *) need_pnames, inp->filename);
+ }
+ else
+ {
+ char *verstr;
+ int maj, min;
+
+ bfd_put_32 (link_info.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 (link_info.output_bfd, (bfd_vma) maj, need_pinfo + 8);
+ bfd_put_16 (link_info.output_bfd, (bfd_vma) min, need_pinfo + 10);
+ strcpy ((char *) need_pnames, inp->local_sym_name + 2);
+ }
+
+ c = (need_pinfo - need_contents) / NEED_ENTRY_SIZE;
+ if (c + 1 >= need_entries)
+ bfd_put_32 (link_info.output_bfd, (bfd_vma) 0, need_pinfo + 12);
+ else
+ bfd_put_32 (link_info.output_bfd, (bfd_vma) (c + 1) * NEED_ENTRY_SIZE,
+ need_pinfo + 12);
+
+ need_pinfo += NEED_ENTRY_SIZE;
+ need_pnames += strlen ((char *) 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"
+
+fragment <<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.
+
+fragment <<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
+
+fragment <<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}",
+ finish_default,
+ 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/binutils-2.20.1/ld/emultempl/ticoff.em b/binutils-2.20.1/ld/emultempl/ticoff.em
new file mode 100644
index 00000000..dff1d701
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/ticoff.em
@@ -0,0 +1,186 @@
+# 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 ;-)
+fragment <<EOF
+/* This file is part of GLD, the Gnu Linker.
+ Copyright 1999, 2000, 2002, 2003, 2004, 2005, 2007
+ Free Software Foundation, Inc.
+
+ This file is part of the GNU Binutils.
+
+ 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* For TI COFF */
+/* Need to determine load and run pages for output sections */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include "sysdep.h"
+#include "bfd.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"/
+'
+fragment <<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.
+
+fragment <<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
+
+fragment <<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}",
+ finish_default,
+ 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/binutils-2.20.1/ld/emultempl/vanilla.em b/binutils-2.20.1/ld/emultempl/vanilla.em
new file mode 100644
index 00000000..4a83dfd2
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/vanilla.em
@@ -0,0 +1,87 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+fragment <<EOF
+/* A vanilla emulation with no defaults
+ Copyright 1991, 1992, 1994, 2000, 2001, 2002, 2003, 2005, 2007, 2008
+ Free Software Foundation, Inc.
+ Written by Steve Chamberlain steve@cygnus.com
+
+ This file is part of the GNU Binutils.
+
+ 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "bfdlink.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 (link_info.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",
+ finish_default,
+ 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/binutils-2.20.1/ld/emultempl/vxworks.em b/binutils-2.20.1/ld/emultempl/vxworks.em
new file mode 100644
index 00000000..7a21ac3f
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/vxworks.em
@@ -0,0 +1,102 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2006, 2007, 2008, 2010 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+if test -n "$VXWORKS_BASE_EM_FILE" ; then
+ source_em "${srcdir}/emultempl/${VXWORKS_BASE_EM_FILE}.em"
+fi
+
+fragment <<EOF
+
+static int force_dynamic;
+
+static void
+vxworks_before_parse (void)
+{
+ ${LDEMUL_BEFORE_PARSE-gld${EMULATION_NAME}_before_parse} ();
+ config.rpath_separator = ';';
+}
+
+static void
+vxworks_after_open (void)
+{
+ ${LDEMUL_AFTER_OPEN-gld${EMULATION_NAME}_after_open} ();
+
+ if (force_dynamic
+ && link_info.input_bfds
+ && bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour
+ && !_bfd_elf_link_create_dynamic_sections (link_info.input_bfds,
+ &link_info))
+ einfo ("%X%P: Cannot create dynamic sections %E\n");
+
+ if (!force_dynamic
+ && !link_info.shared
+ && bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour
+ && elf_hash_table (&link_info)->dynamic_sections_created)
+ einfo ("%X%P: Dynamic sections created in non-dynamic link\n");
+}
+
+EOF
+
+PARSE_AND_LIST_PROLOGUE=$PARSE_AND_LIST_PROLOGUE'
+enum {
+ OPTION_FORCE_DYNAMIC = 501
+};
+'
+
+PARSE_AND_LIST_LONGOPTS=$PARSE_AND_LIST_LONGOPTS'
+ {"force-dynamic", no_argument, NULL, OPTION_FORCE_DYNAMIC},
+'
+
+PARSE_AND_LIST_OPTIONS=$PARSE_AND_LIST_OPTIONS'
+ fprintf (file, _("\
+ --force-dynamic Always create dynamic sections\n"));
+'
+
+PARSE_AND_LIST_ARGS_CASES=$PARSE_AND_LIST_ARGS_CASES'
+ case OPTION_FORCE_DYNAMIC:
+ force_dynamic = 1;
+ break;
+'
+
+# Hook in our routines above. There are three possibilities:
+#
+# (1) VXWORKS_BASE_EM_FILE did not set the hook's LDEMUL_FOO variable.
+# We want to define LDEMUL_FOO to vxworks_foo in that case,
+#
+# (2) VXWORKS_BASE_EM_FILE set the hook's LDEMUL_FOO variable to
+# gld${EMULATION_NAME}_foo. This means that the file has
+# replaced elf32.em's default definition, so we simply #define
+# the current value of LDEMUL_FOO to vxworks_foo.
+#
+# (3) VXWORKS_BASE_EM_FILE set the hook's LDEMUL_FOO variable to
+# something other than gld${EMULATION_NAME}_foo. We handle
+# this case in the same way as (1).
+for override in before_parse after_open; do
+ var="LDEMUL_`echo ${override} | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`"
+ eval value=\$${var}
+ if test "${value}" = "gld${EMULATION_NAME}_${override}"; then
+ fragment <<EOF
+#define ${value} vxworks_${override}
+EOF
+ else
+ eval $var=vxworks_${override}
+ fi
+done
diff --git a/binutils-2.20.1/ld/emultempl/xtensaelf.em b/binutils-2.20.1/ld/emultempl/xtensaelf.em
new file mode 100644
index 00000000..acc32909
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/xtensaelf.em
@@ -0,0 +1,2028 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009
+# Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+# This file is sourced from elf32.em, and defines extra xtensa-elf
+# specific routines.
+#
+fragment <<EOF
+
+#include <xtensa-config.h>
+#include "../bfd/elf-bfd.h"
+#include "../bfd/libbfd.h"
+#include "elf/xtensa.h"
+#include "bfd.h"
+
+/* Provide default values for new configuration settings. */
+#ifndef XSHAL_ABI
+#define XSHAL_ABI 0
+#endif
+
+static void xtensa_wild_group_interleave (lang_statement_union_type *);
+static void xtensa_colocate_output_literals (lang_statement_union_type *);
+static void xtensa_strip_inconsistent_linkonce_sections
+ (lang_statement_list_type *);
+
+
+/* Flag for the emulation-specific "--no-relax" option. */
+static bfd_boolean disable_relaxation = FALSE;
+
+/* This number is irrelevant until we turn on use_literal_pages */
+static bfd_vma xtensa_page_power = 12; /* 4K pages. */
+
+/* To force a page break between literals and text, change
+ xtensa_use_literal_pages to "TRUE". */
+static bfd_boolean xtensa_use_literal_pages = FALSE;
+
+#define EXTRA_VALIDATION 0
+
+
+static char *
+elf_xtensa_choose_target (int argc ATTRIBUTE_UNUSED,
+ char **argv ATTRIBUTE_UNUSED)
+{
+ if (XCHAL_HAVE_BE)
+ return "${BIG_OUTPUT_FORMAT}";
+ else
+ return "${LITTLE_OUTPUT_FORMAT}";
+}
+
+
+static void
+elf_xtensa_before_parse (void)
+{
+ /* Just call the default hook.... Tensilica's version of this function
+ does some other work that isn't relevant here. */
+ gld${EMULATION_NAME}_before_parse ();
+}
+
+
+static void
+remove_section (bfd *abfd, asection *os)
+{
+ asection **spp;
+ for (spp = &abfd->sections; *spp; spp = &(*spp)->next)
+ if (*spp == os)
+ {
+ *spp = os->next;
+ os->owner->section_count--;
+ break;
+ }
+}
+
+
+static bfd_boolean
+replace_insn_sec_with_prop_sec (bfd *abfd,
+ const char *insn_sec_name,
+ const char *prop_sec_name,
+ char **error_message)
+{
+ asection *insn_sec;
+ asection *prop_sec;
+ bfd_byte *prop_contents = NULL;
+ bfd_byte *insn_contents = NULL;
+ unsigned entry_count;
+ unsigned entry;
+ Elf_Internal_Shdr *symtab_hdr;
+ Elf_Internal_Rela *internal_relocs = NULL;
+ unsigned reloc_count;
+
+ *error_message = "";
+ insn_sec = bfd_get_section_by_name (abfd, insn_sec_name);
+ if (insn_sec == NULL)
+ return TRUE;
+ entry_count = insn_sec->size / 8;
+
+ prop_sec = bfd_get_section_by_name (abfd, prop_sec_name);
+ if (prop_sec != NULL && insn_sec != NULL)
+ {
+ *error_message = _("file already has property tables");
+ return FALSE;
+ }
+
+ if (insn_sec->size != 0)
+ {
+ insn_contents = (bfd_byte *) bfd_malloc (insn_sec->size);
+ if (insn_contents == NULL)
+ {
+ *error_message = _("out of memory");
+ goto cleanup;
+ }
+ if (! bfd_get_section_contents (abfd, insn_sec, insn_contents,
+ (file_ptr) 0, insn_sec->size))
+ {
+ *error_message = _("failed to read section contents");
+ goto cleanup;
+ }
+ }
+
+ /* Create a property table section for it. */
+ prop_sec_name = strdup (prop_sec_name);
+ prop_sec = bfd_make_section_with_flags
+ (abfd, prop_sec_name, bfd_get_section_flags (abfd, insn_sec));
+ if (prop_sec == NULL
+ || ! bfd_set_section_alignment (abfd, prop_sec, 2))
+ {
+ *error_message = _("could not create new section");
+ goto cleanup;
+ }
+
+ prop_sec->size = entry_count * 12;
+ prop_contents = (bfd_byte *) bfd_zalloc (abfd, prop_sec->size);
+ elf_section_data (prop_sec)->this_hdr.contents = prop_contents;
+
+ /* The entry size and size must be set to allow the linker to compute
+ the number of relocations since it does not use reloc_count. */
+ elf_section_data (prop_sec)->rel_hdr.sh_entsize =
+ sizeof (Elf32_External_Rela);
+ elf_section_data (prop_sec)->rel_hdr.sh_size =
+ elf_section_data (insn_sec)->rel_hdr.sh_size;
+
+ if (prop_contents == NULL && prop_sec->size != 0)
+ {
+ *error_message = _("could not allocate section contents");
+ goto cleanup;
+ }
+
+ /* Read the relocations. */
+ reloc_count = insn_sec->reloc_count;
+ if (reloc_count != 0)
+ {
+ /* If there is already an internal_reloc, then save it so that the
+ read_relocs function freshly allocates a copy. */
+ Elf_Internal_Rela *saved_relocs = elf_section_data (insn_sec)->relocs;
+
+ elf_section_data (insn_sec)->relocs = NULL;
+ internal_relocs =
+ _bfd_elf_link_read_relocs (abfd, insn_sec, NULL, NULL, FALSE);
+ elf_section_data (insn_sec)->relocs = saved_relocs;
+
+ if (internal_relocs == NULL)
+ {
+ *error_message = _("out of memory");
+ goto cleanup;
+ }
+ }
+
+ /* Create a relocation section for the property section. */
+ if (internal_relocs != NULL)
+ {
+ elf_section_data (prop_sec)->relocs = internal_relocs;
+ prop_sec->reloc_count = reloc_count;
+ }
+
+ /* Now copy each insn table entry to the prop table entry with
+ appropriate flags. */
+ for (entry = 0; entry < entry_count; ++entry)
+ {
+ unsigned value;
+ unsigned flags = (XTENSA_PROP_INSN | XTENSA_PROP_NO_TRANSFORM
+ | XTENSA_PROP_INSN_NO_REORDER);
+ value = bfd_get_32 (abfd, insn_contents + entry * 8 + 0);
+ bfd_put_32 (abfd, value, prop_contents + entry * 12 + 0);
+ value = bfd_get_32 (abfd, insn_contents + entry * 8 + 4);
+ bfd_put_32 (abfd, value, prop_contents + entry * 12 + 4);
+ bfd_put_32 (abfd, flags, prop_contents + entry * 12 + 8);
+ }
+
+ /* Now copy all of the relocations. Change offsets for the
+ instruction table section to offsets in the property table
+ section. */
+ if (internal_relocs)
+ {
+ unsigned i;
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+
+ for (i = 0; i < reloc_count; i++)
+ {
+ Elf_Internal_Rela *rela;
+ unsigned r_offset;
+
+ rela = &internal_relocs[i];
+
+ /* If this relocation is to the .xt.insn section,
+ change the section number and the offset. */
+ r_offset = rela->r_offset;
+ r_offset += 4 * (r_offset / 8);
+ rela->r_offset = r_offset;
+ }
+ }
+
+ remove_section (abfd, insn_sec);
+
+ if (insn_contents)
+ free (insn_contents);
+
+ return TRUE;
+
+ cleanup:
+ if (prop_sec && prop_sec->owner)
+ remove_section (abfd, prop_sec);
+ if (insn_contents)
+ free (insn_contents);
+ if (internal_relocs)
+ free (internal_relocs);
+
+ return FALSE;
+}
+
+
+#define PROP_SEC_BASE_NAME ".xt.prop"
+#define INSN_SEC_BASE_NAME ".xt.insn"
+#define LINKONCE_SEC_OLD_TEXT_BASE_NAME ".gnu.linkonce.x."
+
+
+static void
+replace_instruction_table_sections (bfd *abfd, asection *sec)
+{
+ char *message = "";
+ const char *insn_sec_name = NULL;
+ char *prop_sec_name = NULL;
+ char *owned_prop_sec_name = NULL;
+ const char *sec_name;
+
+ sec_name = bfd_get_section_name (abfd, sec);
+ if (strcmp (sec_name, INSN_SEC_BASE_NAME) == 0)
+ {
+ insn_sec_name = INSN_SEC_BASE_NAME;
+ prop_sec_name = PROP_SEC_BASE_NAME;
+ }
+ else if (CONST_STRNEQ (sec_name, LINKONCE_SEC_OLD_TEXT_BASE_NAME))
+ {
+ insn_sec_name = sec_name;
+ owned_prop_sec_name = (char *) xmalloc (strlen (sec_name) + 20);
+ prop_sec_name = owned_prop_sec_name;
+ strcpy (prop_sec_name, ".gnu.linkonce.prop.t.");
+ strcat (prop_sec_name,
+ sec_name + strlen (LINKONCE_SEC_OLD_TEXT_BASE_NAME));
+ }
+ if (insn_sec_name != NULL)
+ {
+ if (! replace_insn_sec_with_prop_sec (abfd, insn_sec_name, prop_sec_name,
+ &message))
+ {
+ einfo (_("%P: warning: failed to convert %s table in %B (%s); subsequent disassembly may be incomplete\n"),
+ insn_sec_name, abfd, message);
+ }
+ }
+ if (owned_prop_sec_name)
+ free (owned_prop_sec_name);
+}
+
+
+/* This is called after all input sections have been opened to convert
+ instruction tables (.xt.insn, gnu.linkonce.x.*) tables into property
+ tables (.xt.prop) before any section placement. */
+
+static void
+elf_xtensa_after_open (void)
+{
+ /* First call the ELF version. */
+ gld${EMULATION_NAME}_after_open ();
+
+ /* Now search the input files looking for instruction table sections. */
+ LANG_FOR_EACH_INPUT_STATEMENT (f)
+ {
+ asection *sec = f->the_bfd->sections;
+ asection *next_sec;
+
+ /* Do not use bfd_map_over_sections here since we are removing
+ sections as we iterate. */
+ while (sec != NULL)
+ {
+ next_sec = sec->next;
+ replace_instruction_table_sections (f->the_bfd, sec);
+ sec = next_sec;
+ }
+ }
+}
+
+
+static bfd_boolean
+xt_config_info_unpack_and_check (char *data,
+ bfd_boolean *pmismatch,
+ char **pmsg)
+{
+ char *d, *key;
+ unsigned num;
+
+ *pmismatch = FALSE;
+
+ d = data;
+ while (*d)
+ {
+ key = d;
+ d = strchr (d, '=');
+ if (! d)
+ goto error;
+
+ /* Overwrite the equal sign. */
+ *d++ = 0;
+
+ /* Check if this is a quoted string or a number. */
+ if (*d == '"')
+ {
+ /* No string values are currently checked by LD;
+ just skip over the quotes. */
+ d++;
+ d = strchr (d, '"');
+ if (! d)
+ goto error;
+ /* Overwrite the trailing quote. */
+ *d++ = 0;
+ }
+ else
+ {
+ if (*d == 0)
+ goto error;
+ num = strtoul (d, &d, 0);
+
+ if (! strcmp (key, "ABI"))
+ {
+ if (num != XSHAL_ABI)
+ {
+ *pmismatch = TRUE;
+ *pmsg = "ABI does not match";
+ }
+ }
+ else if (! strcmp (key, "USE_ABSOLUTE_LITERALS"))
+ {
+ if (num != XSHAL_USE_ABSOLUTE_LITERALS)
+ {
+ *pmismatch = TRUE;
+ *pmsg = "incompatible use of the Extended L32R option";
+ }
+ }
+ }
+
+ if (*d++ != '\n')
+ goto error;
+ }
+
+ return TRUE;
+
+ error:
+ return FALSE;
+}
+
+
+#define XTINFO_NAME "Xtensa_Info"
+#define XTINFO_NAMESZ 12
+#define XTINFO_TYPE 1
+
+static void
+check_xtensa_info (bfd *abfd, asection *info_sec)
+{
+ char *data, *errmsg = "";
+ bfd_boolean mismatch;
+
+ data = xmalloc (info_sec->size);
+ if (! bfd_get_section_contents (abfd, info_sec, data, 0, info_sec->size))
+ einfo (_("%F%P:%B: cannot read contents of section %A\n"), abfd, info_sec);
+
+ if (info_sec->size > 24
+ && info_sec->size >= 24 + bfd_get_32 (abfd, data + 4)
+ && bfd_get_32 (abfd, data + 0) == XTINFO_NAMESZ
+ && bfd_get_32 (abfd, data + 8) == XTINFO_TYPE
+ && strcmp (data + 12, XTINFO_NAME) == 0
+ && xt_config_info_unpack_and_check (data + 12 + XTINFO_NAMESZ,
+ &mismatch, &errmsg))
+ {
+ if (mismatch)
+ einfo (_("%P:%B: warning: incompatible Xtensa configuration (%s)\n"),
+ abfd, errmsg);
+ }
+ else
+ einfo (_("%P:%B: warning: cannot parse .xtensa.info section\n"), abfd);
+
+ free (data);
+}
+
+
+/* This is called after the sections have been attached to output
+ sections, but before any sizes or addresses have been set. */
+
+static void
+elf_xtensa_before_allocation (void)
+{
+ asection *info_sec, *first_info_sec;
+ bfd *first_bfd;
+ bfd_boolean is_big_endian = XCHAL_HAVE_BE;
+
+ /* Check that the output endianness matches the Xtensa
+ configuration. The BFD library always includes both big and
+ little endian target vectors for Xtensa, but it only supports the
+ detailed instruction encode/decode operations (such as are
+ required to process relocations) for the selected Xtensa
+ configuration. */
+
+ if (is_big_endian
+ && link_info.output_bfd->xvec->byteorder == BFD_ENDIAN_LITTLE)
+ {
+ einfo (_("%F%P: little endian output does not match "
+ "Xtensa configuration\n"));
+ }
+ if (!is_big_endian
+ && link_info.output_bfd->xvec->byteorder == BFD_ENDIAN_BIG)
+ {
+ einfo (_("%F%P: big endian output does not match "
+ "Xtensa configuration\n"));
+ }
+
+ /* Keep track of the first input .xtensa.info section, and as a fallback,
+ the first input bfd where a .xtensa.info section could be created.
+ After the input .xtensa.info has been checked, the contents of the
+ first one will be replaced with the output .xtensa.info table. */
+ first_info_sec = 0;
+ first_bfd = 0;
+
+ LANG_FOR_EACH_INPUT_STATEMENT (f)
+ {
+ /* Check that the endianness for each input file matches the output.
+ The merge_private_bfd_data hook has already reported any mismatches
+ as errors, but those errors are not fatal. At this point, we
+ cannot go any further if there are any mismatches. */
+ if ((is_big_endian && f->the_bfd->xvec->byteorder == BFD_ENDIAN_LITTLE)
+ || (!is_big_endian && f->the_bfd->xvec->byteorder == BFD_ENDIAN_BIG))
+ einfo (_("%F%P: cross-endian linking for %B not supported\n"),
+ f->the_bfd);
+
+ if (! first_bfd)
+ first_bfd = f->the_bfd;
+
+ info_sec = bfd_get_section_by_name (f->the_bfd, ".xtensa.info");
+ if (! info_sec)
+ continue;
+
+ if (! first_info_sec)
+ first_info_sec = info_sec;
+
+ /* Unpack the .xtensa.info section and check it against the current
+ Xtensa configuration. */
+ check_xtensa_info (f->the_bfd, info_sec);
+
+ /* Do not include this copy of .xtensa.info in the output. */
+ info_sec->size = 0;
+ info_sec->flags |= SEC_EXCLUDE;
+ }
+
+ /* Reuse the first .xtensa.info input section to hold the output
+ .xtensa.info; or, if none were found, create a new section in the
+ first input bfd (assuming there is one). */
+ info_sec = first_info_sec;
+ if (! info_sec && first_bfd)
+ {
+ info_sec = bfd_make_section_with_flags (first_bfd, ".xtensa.info",
+ SEC_HAS_CONTENTS | SEC_READONLY);
+ if (! info_sec)
+ einfo (_("%F%P: failed to create .xtensa.info section\n"));
+ }
+ if (info_sec)
+ {
+ int xtensa_info_size;
+ char *data;
+
+ info_sec->flags &= ~SEC_EXCLUDE;
+ info_sec->flags |= SEC_IN_MEMORY;
+
+ data = xmalloc (100);
+ sprintf (data, "USE_ABSOLUTE_LITERALS=%d\nABI=%d\n",
+ XSHAL_USE_ABSOLUTE_LITERALS, XSHAL_ABI);
+ xtensa_info_size = strlen (data) + 1;
+
+ /* Add enough null terminators to pad to a word boundary. */
+ do
+ data[xtensa_info_size++] = 0;
+ while ((xtensa_info_size & 3) != 0);
+
+ info_sec->size = 12 + XTINFO_NAMESZ + xtensa_info_size;
+ info_sec->contents = xmalloc (info_sec->size);
+ bfd_put_32 (info_sec->owner, XTINFO_NAMESZ, info_sec->contents + 0);
+ bfd_put_32 (info_sec->owner, xtensa_info_size, info_sec->contents + 4);
+ bfd_put_32 (info_sec->owner, XTINFO_TYPE, info_sec->contents + 8);
+ memcpy (info_sec->contents + 12, XTINFO_NAME, XTINFO_NAMESZ);
+ memcpy (info_sec->contents + 12 + XTINFO_NAMESZ, data, xtensa_info_size);
+ free (data);
+ }
+
+ /* Enable relaxation by default if the "--no-relax" option was not
+ specified. This is done here instead of in the before_parse hook
+ because there is a check in main() to prohibit use of --relax and
+ -r together and that combination should be allowed for Xtensa. */
+
+ if (!disable_relaxation)
+ command_line.relax = TRUE;
+
+ xtensa_strip_inconsistent_linkonce_sections (stat_ptr);
+
+ gld${EMULATION_NAME}_before_allocation ();
+
+ xtensa_wild_group_interleave (stat_ptr->head);
+ if (command_line.relax)
+ xtensa_colocate_output_literals (stat_ptr->head);
+
+ /* TBD: We need to force the page alignments to here and only do
+ them as needed for the entire output section. Finally, if this
+ is a relocatable link then we need to add alignment notes so
+ that the literals can be separated later. */
+}
+
+
+typedef struct wildcard_list section_name_list;
+
+typedef struct reloc_deps_e_t reloc_deps_e;
+typedef struct reloc_deps_section_t reloc_deps_section;
+typedef struct reloc_deps_graph_t reloc_deps_graph;
+
+
+struct reloc_deps_e_t
+{
+ asection *src; /* Contains l32rs. */
+ asection *tgt; /* Contains literals. */
+ reloc_deps_e *next;
+};
+
+/* Place these in the userdata field. */
+struct reloc_deps_section_t
+{
+ reloc_deps_e *preds;
+ reloc_deps_e *succs;
+ bfd_boolean is_only_literal;
+};
+
+
+struct reloc_deps_graph_t
+{
+ size_t count;
+ size_t size;
+ asection **sections;
+};
+
+static void xtensa_layout_wild
+ (const reloc_deps_graph *, lang_wild_statement_type *);
+
+typedef void (*deps_callback_t) (asection *, /* src_sec */
+ bfd_vma, /* src_offset */
+ asection *, /* target_sec */
+ bfd_vma, /* target_offset */
+ void *); /* closure */
+
+extern bfd_boolean xtensa_callback_required_dependence
+ (bfd *, asection *, struct bfd_link_info *, deps_callback_t, void *);
+static void xtensa_ldlang_clear_addresses (lang_statement_union_type *);
+static bfd_boolean ld_local_file_relocations_fit
+ (lang_statement_union_type *, const reloc_deps_graph *);
+static bfd_vma ld_assign_relative_paged_dot
+ (bfd_vma, lang_statement_union_type *, const reloc_deps_graph *,
+ bfd_boolean);
+static bfd_vma ld_xtensa_insert_page_offsets
+ (bfd_vma, lang_statement_union_type *, reloc_deps_graph *, bfd_boolean);
+#if EXTRA_VALIDATION
+static size_t ld_count_children (lang_statement_union_type *);
+#endif
+
+extern lang_statement_list_type constructor_list;
+
+/* Begin verbatim code from ldlang.c:
+ the following are copied from ldlang.c because they are defined
+ there statically. */
+
+static void
+lang_for_each_statement_worker (void (*func) (lang_statement_union_type *),
+ lang_statement_union_type *s)
+{
+ for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
+ {
+ func (s);
+
+ switch (s->header.type)
+ {
+ case lang_constructors_statement_enum:
+ lang_for_each_statement_worker (func, constructor_list.head);
+ break;
+ case lang_output_section_statement_enum:
+ lang_for_each_statement_worker
+ (func,
+ s->output_section_statement.children.head);
+ break;
+ case lang_wild_statement_enum:
+ lang_for_each_statement_worker
+ (func,
+ s->wild_statement.children.head);
+ break;
+ case lang_group_statement_enum:
+ lang_for_each_statement_worker (func,
+ s->group_statement.children.head);
+ 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_section_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;
+ }
+ }
+}
+
+/* End of verbatim code from ldlang.c. */
+
+
+static reloc_deps_section *
+xtensa_get_section_deps (const reloc_deps_graph *deps ATTRIBUTE_UNUSED,
+ asection *sec)
+{
+ /* We have a separate function for this so that
+ we could in the future keep a completely independent
+ structure that maps a section to its dependence edges.
+ For now, we place these in the sec->userdata field. */
+ reloc_deps_section *sec_deps = sec->userdata;
+ return sec_deps;
+}
+
+static void
+xtensa_set_section_deps (const reloc_deps_graph *deps ATTRIBUTE_UNUSED,
+ asection *sec,
+ reloc_deps_section *deps_section)
+{
+ sec->userdata = deps_section;
+}
+
+
+/* This is used to keep a list of all of the sections participating in
+ the graph so we can clean them up quickly. */
+
+static void
+xtensa_append_section_deps (reloc_deps_graph *deps, asection *sec)
+{
+ if (deps->size <= deps->count)
+ {
+ asection **new_sections;
+ size_t i;
+ size_t new_size;
+
+ new_size = deps->size * 2;
+ if (new_size == 0)
+ new_size = 20;
+
+ new_sections = xmalloc (sizeof (asection *) * new_size);
+ memset (new_sections, 0, sizeof (asection *) * new_size);
+ for (i = 0; i < deps->count; i++)
+ {
+ new_sections[i] = deps->sections[i];
+ }
+ if (deps->sections != NULL)
+ free (deps->sections);
+ deps->sections = new_sections;
+ deps->size = new_size;
+ }
+ deps->sections[deps->count] = sec;
+ deps->count++;
+}
+
+
+static void
+free_reloc_deps_graph (reloc_deps_graph *deps)
+{
+ size_t i;
+ for (i = 0; i < deps->count; i++)
+ {
+ asection *sec = deps->sections[i];
+ reloc_deps_section *sec_deps;
+ sec_deps = xtensa_get_section_deps (deps, sec);
+ if (sec_deps)
+ {
+ reloc_deps_e *next;
+ while (sec_deps->succs != NULL)
+ {
+ next = sec_deps->succs->next;
+ free (sec_deps->succs);
+ sec_deps->succs = next;
+ }
+
+ while (sec_deps->preds != NULL)
+ {
+ next = sec_deps->preds->next;
+ free (sec_deps->preds);
+ sec_deps->preds = next;
+ }
+ free (sec_deps);
+ }
+ xtensa_set_section_deps (deps, sec, NULL);
+ }
+ if (deps->sections)
+ free (deps->sections);
+
+ free (deps);
+}
+
+
+static bfd_boolean
+section_is_source (const reloc_deps_graph *deps ATTRIBUTE_UNUSED,
+ lang_statement_union_type *s)
+{
+ asection *sec;
+ const reloc_deps_section *sec_deps;
+
+ if (s->header.type != lang_input_section_enum)
+ return FALSE;
+ sec = s->input_section.section;
+
+ sec_deps = xtensa_get_section_deps (deps, sec);
+ return sec_deps && sec_deps->succs != NULL;
+}
+
+
+static bfd_boolean
+section_is_target (const reloc_deps_graph *deps ATTRIBUTE_UNUSED,
+ lang_statement_union_type *s)
+{
+ asection *sec;
+ const reloc_deps_section *sec_deps;
+
+ if (s->header.type != lang_input_section_enum)
+ return FALSE;
+ sec = s->input_section.section;
+
+ sec_deps = xtensa_get_section_deps (deps, sec);
+ return sec_deps && sec_deps->preds != NULL;
+}
+
+
+static bfd_boolean
+section_is_source_or_target (const reloc_deps_graph *deps ATTRIBUTE_UNUSED,
+ lang_statement_union_type *s)
+{
+ return (section_is_source (deps, s)
+ || section_is_target (deps, s));
+}
+
+
+typedef struct xtensa_ld_iter_stack_t xtensa_ld_iter_stack;
+typedef struct xtensa_ld_iter_t xtensa_ld_iter;
+
+struct xtensa_ld_iter_t
+{
+ lang_statement_union_type *parent; /* Parent of the list. */
+ lang_statement_list_type *l; /* List that holds it. */
+ lang_statement_union_type **loc; /* Place in the list. */
+};
+
+struct xtensa_ld_iter_stack_t
+{
+ xtensa_ld_iter iterloc; /* List that hold it. */
+
+ xtensa_ld_iter_stack *next; /* Next in the stack. */
+ xtensa_ld_iter_stack *prev; /* Back pointer for stack. */
+};
+
+
+static void
+ld_xtensa_move_section_after (xtensa_ld_iter *to, xtensa_ld_iter *current)
+{
+ lang_statement_union_type *to_next;
+ lang_statement_union_type *current_next;
+ lang_statement_union_type **e;
+
+#if EXTRA_VALIDATION
+ size_t old_to_count, new_to_count;
+ size_t old_current_count, new_current_count;
+#endif
+
+ if (to == current)
+ return;
+
+#if EXTRA_VALIDATION
+ old_to_count = ld_count_children (to->parent);
+ old_current_count = ld_count_children (current->parent);
+#endif
+
+ to_next = *(to->loc);
+ current_next = (*current->loc)->header.next;
+
+ *(to->loc) = *(current->loc);
+
+ *(current->loc) = current_next;
+ (*(to->loc))->header.next = to_next;
+
+ /* reset "to" list tail */
+ for (e = &to->l->head; *e != NULL; e = &(*e)->header.next)
+ ;
+ to->l->tail = e;
+
+ /* reset "current" list tail */
+ for (e = &current->l->head; *e != NULL; e = &(*e)->header.next)
+ ;
+ current->l->tail = e;
+
+#if EXTRA_VALIDATION
+ new_to_count = ld_count_children (to->parent);
+ new_current_count = ld_count_children (current->parent);
+
+ ASSERT ((old_to_count + old_current_count)
+ == (new_to_count + new_current_count));
+#endif
+}
+
+
+/* Can only be called with lang_statements that have lists. Returns
+ FALSE if the list is empty. */
+
+static bfd_boolean
+iter_stack_empty (xtensa_ld_iter_stack **stack_p)
+{
+ return *stack_p == NULL;
+}
+
+
+static bfd_boolean
+iter_stack_push (xtensa_ld_iter_stack **stack_p,
+ lang_statement_union_type *parent)
+{
+ xtensa_ld_iter_stack *stack;
+ lang_statement_list_type *l = NULL;
+
+ switch (parent->header.type)
+ {
+ case lang_output_section_statement_enum:
+ l = &parent->output_section_statement.children;
+ break;
+ case lang_wild_statement_enum:
+ l = &parent->wild_statement.children;
+ break;
+ case lang_group_statement_enum:
+ l = &parent->group_statement.children;
+ break;
+ default:
+ ASSERT (0);
+ return FALSE;
+ }
+
+ /* Empty. do not push. */
+ if (l->tail == &l->head)
+ return FALSE;
+
+ stack = xmalloc (sizeof (xtensa_ld_iter_stack));
+ memset (stack, 0, sizeof (xtensa_ld_iter_stack));
+ stack->iterloc.parent = parent;
+ stack->iterloc.l = l;
+ stack->iterloc.loc = &l->head;
+
+ stack->next = *stack_p;
+ stack->prev = NULL;
+ if (*stack_p != NULL)
+ (*stack_p)->prev = stack;
+ *stack_p = stack;
+ return TRUE;
+}
+
+
+static void
+iter_stack_pop (xtensa_ld_iter_stack **stack_p)
+{
+ xtensa_ld_iter_stack *stack;
+
+ stack = *stack_p;
+
+ if (stack == NULL)
+ {
+ ASSERT (stack != NULL);
+ return;
+ }
+
+ if (stack->next != NULL)
+ stack->next->prev = NULL;
+
+ *stack_p = stack->next;
+ free (stack);
+}
+
+
+/* This MUST be called if, during iteration, the user changes the
+ underlying structure. It will check for a NULL current and advance
+ accordingly. */
+
+static void
+iter_stack_update (xtensa_ld_iter_stack **stack_p)
+{
+ if (!iter_stack_empty (stack_p)
+ && (*(*stack_p)->iterloc.loc) == NULL)
+ {
+ iter_stack_pop (stack_p);
+
+ while (!iter_stack_empty (stack_p)
+ && ((*(*stack_p)->iterloc.loc)->header.next == NULL))
+ {
+ iter_stack_pop (stack_p);
+ }
+ if (!iter_stack_empty (stack_p))
+ (*stack_p)->iterloc.loc = &(*(*stack_p)->iterloc.loc)->header.next;
+ }
+}
+
+
+static void
+iter_stack_next (xtensa_ld_iter_stack **stack_p)
+{
+ xtensa_ld_iter_stack *stack;
+ lang_statement_union_type *current;
+ stack = *stack_p;
+
+ current = *stack->iterloc.loc;
+ /* If we are on the first element. */
+ if (current != NULL)
+ {
+ switch (current->header.type)
+ {
+ case lang_output_section_statement_enum:
+ case lang_wild_statement_enum:
+ case lang_group_statement_enum:
+ /* If the list if not empty, we are done. */
+ if (iter_stack_push (stack_p, *stack->iterloc.loc))
+ return;
+ /* Otherwise increment the pointer as normal. */
+ break;
+ default:
+ break;
+ }
+ }
+
+ while (!iter_stack_empty (stack_p)
+ && ((*(*stack_p)->iterloc.loc)->header.next == NULL))
+ {
+ iter_stack_pop (stack_p);
+ }
+ if (!iter_stack_empty (stack_p))
+ (*stack_p)->iterloc.loc = &(*(*stack_p)->iterloc.loc)->header.next;
+}
+
+
+static lang_statement_union_type *
+iter_stack_current (xtensa_ld_iter_stack **stack_p)
+{
+ return *((*stack_p)->iterloc.loc);
+}
+
+
+/* The iter stack is a preorder. */
+
+static void
+iter_stack_create (xtensa_ld_iter_stack **stack_p,
+ lang_statement_union_type *parent)
+{
+ iter_stack_push (stack_p, parent);
+}
+
+
+static void
+iter_stack_copy_current (xtensa_ld_iter_stack **stack_p, xtensa_ld_iter *front)
+{
+ *front = (*stack_p)->iterloc;
+}
+
+
+static void
+xtensa_colocate_literals (reloc_deps_graph *deps,
+ lang_statement_union_type *statement)
+{
+ /* Keep a stack of pointers to control iteration through the contours. */
+ xtensa_ld_iter_stack *stack = NULL;
+ xtensa_ld_iter_stack **stack_p = &stack;
+
+ xtensa_ld_iter front; /* Location where new insertion should occur. */
+ xtensa_ld_iter *front_p = NULL;
+
+ xtensa_ld_iter current; /* Location we are checking. */
+ xtensa_ld_iter *current_p = NULL;
+ bfd_boolean in_literals = FALSE;
+
+ if (deps->count == 0)
+ return;
+
+ iter_stack_create (stack_p, statement);
+
+ while (!iter_stack_empty (stack_p))
+ {
+ bfd_boolean skip_increment = FALSE;
+ lang_statement_union_type *l = iter_stack_current (stack_p);
+
+ switch (l->header.type)
+ {
+ case lang_assignment_statement_enum:
+ /* Any assignment statement should block reordering across it. */
+ front_p = NULL;
+ in_literals = FALSE;
+ break;
+
+ case lang_input_section_enum:
+ if (front_p == NULL)
+ {
+ in_literals = (section_is_target (deps, l)
+ && !section_is_source (deps, l));
+ if (in_literals)
+ {
+ front_p = &front;
+ iter_stack_copy_current (stack_p, front_p);
+ }
+ }
+ else
+ {
+ bfd_boolean is_target;
+ current_p = &current;
+ iter_stack_copy_current (stack_p, current_p);
+ is_target = (section_is_target (deps, l)
+ && !section_is_source (deps, l));
+
+ if (in_literals)
+ {
+ iter_stack_copy_current (stack_p, front_p);
+ if (!is_target)
+ in_literals = FALSE;
+ }
+ else
+ {
+ if (is_target)
+ {
+ /* Try to insert in place. */
+ ld_xtensa_move_section_after (front_p, current_p);
+ ld_assign_relative_paged_dot (0x100000,
+ statement,
+ deps,
+ xtensa_use_literal_pages);
+
+ /* We use this code because it's already written. */
+ if (!ld_local_file_relocations_fit (statement, deps))
+ {
+ /* Move it back. */
+ ld_xtensa_move_section_after (current_p, front_p);
+ /* Reset the literal placement. */
+ iter_stack_copy_current (stack_p, front_p);
+ }
+ else
+ {
+ /* Move front pointer up by one. */
+ front_p->loc = &(*front_p->loc)->header.next;
+
+ /* Do not increment the current pointer. */
+ skip_increment = TRUE;
+ }
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!skip_increment)
+ iter_stack_next (stack_p);
+ else
+ /* Be careful to update the stack_p if it now is a null. */
+ iter_stack_update (stack_p);
+ }
+
+ lang_for_each_statement_worker (xtensa_ldlang_clear_addresses, statement);
+}
+
+
+static void
+xtensa_move_dependencies_to_front (reloc_deps_graph *deps,
+ lang_wild_statement_type *w)
+{
+ /* Keep a front pointer and a current pointer. */
+ lang_statement_union_type **front;
+ lang_statement_union_type **current;
+
+ /* Walk to the end of the targets. */
+ for (front = &w->children.head;
+ (*front != NULL) && section_is_source_or_target (deps, *front);
+ front = &(*front)->header.next)
+ ;
+
+ if (*front == NULL)
+ return;
+
+ current = &(*front)->header.next;
+ while (*current != NULL)
+ {
+ if (section_is_source_or_target (deps, *current))
+ {
+ /* Insert in place. */
+ xtensa_ld_iter front_iter;
+ xtensa_ld_iter current_iter;
+
+ front_iter.parent = (lang_statement_union_type *) w;
+ front_iter.l = &w->children;
+ front_iter.loc = front;
+
+ current_iter.parent = (lang_statement_union_type *) w;
+ current_iter.l = &w->children;
+ current_iter.loc = current;
+
+ ld_xtensa_move_section_after (&front_iter, &current_iter);
+ front = &(*front)->header.next;
+ }
+ else
+ {
+ current = &(*current)->header.next;
+ }
+ }
+}
+
+
+static bfd_boolean
+deps_has_sec_edge (const reloc_deps_graph *deps, asection *src, asection *tgt)
+{
+ const reloc_deps_section *sec_deps;
+ const reloc_deps_e *sec_deps_e;
+
+ sec_deps = xtensa_get_section_deps (deps, src);
+ if (sec_deps == NULL)
+ return FALSE;
+
+ for (sec_deps_e = sec_deps->succs;
+ sec_deps_e != NULL;
+ sec_deps_e = sec_deps_e->next)
+ {
+ ASSERT (sec_deps_e->src == src);
+ if (sec_deps_e->tgt == tgt)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+static bfd_boolean
+deps_has_edge (const reloc_deps_graph *deps,
+ lang_statement_union_type *src,
+ lang_statement_union_type *tgt)
+{
+ if (!section_is_source (deps, src))
+ return FALSE;
+ if (!section_is_target (deps, tgt))
+ return FALSE;
+
+ if (src->header.type != lang_input_section_enum)
+ return FALSE;
+ if (tgt->header.type != lang_input_section_enum)
+ return FALSE;
+
+ return deps_has_sec_edge (deps, src->input_section.section,
+ tgt->input_section.section);
+}
+
+
+static void
+add_deps_edge (reloc_deps_graph *deps, asection *src_sec, asection *tgt_sec)
+{
+ reloc_deps_section *src_sec_deps;
+ reloc_deps_section *tgt_sec_deps;
+
+ reloc_deps_e *src_edge;
+ reloc_deps_e *tgt_edge;
+
+ if (deps_has_sec_edge (deps, src_sec, tgt_sec))
+ return;
+
+ src_sec_deps = xtensa_get_section_deps (deps, src_sec);
+ if (src_sec_deps == NULL)
+ {
+ /* Add a section. */
+ src_sec_deps = xmalloc (sizeof (reloc_deps_section));
+ memset (src_sec_deps, 0, sizeof (reloc_deps_section));
+ src_sec_deps->is_only_literal = 0;
+ src_sec_deps->preds = NULL;
+ src_sec_deps->succs = NULL;
+ xtensa_set_section_deps (deps, src_sec, src_sec_deps);
+ xtensa_append_section_deps (deps, src_sec);
+ }
+
+ tgt_sec_deps = xtensa_get_section_deps (deps, tgt_sec);
+ if (tgt_sec_deps == NULL)
+ {
+ /* Add a section. */
+ tgt_sec_deps = xmalloc (sizeof (reloc_deps_section));
+ memset (tgt_sec_deps, 0, sizeof (reloc_deps_section));
+ tgt_sec_deps->is_only_literal = 0;
+ tgt_sec_deps->preds = NULL;
+ tgt_sec_deps->succs = NULL;
+ xtensa_set_section_deps (deps, tgt_sec, tgt_sec_deps);
+ xtensa_append_section_deps (deps, tgt_sec);
+ }
+
+ /* Add the edges. */
+ src_edge = xmalloc (sizeof (reloc_deps_e));
+ memset (src_edge, 0, sizeof (reloc_deps_e));
+ src_edge->src = src_sec;
+ src_edge->tgt = tgt_sec;
+ src_edge->next = src_sec_deps->succs;
+ src_sec_deps->succs = src_edge;
+
+ tgt_edge = xmalloc (sizeof (reloc_deps_e));
+ memset (tgt_edge, 0, sizeof (reloc_deps_e));
+ tgt_edge->src = src_sec;
+ tgt_edge->tgt = tgt_sec;
+ tgt_edge->next = tgt_sec_deps->preds;
+ tgt_sec_deps->preds = tgt_edge;
+}
+
+
+static void
+build_deps_graph_callback (asection *src_sec,
+ bfd_vma src_offset ATTRIBUTE_UNUSED,
+ asection *target_sec,
+ bfd_vma target_offset ATTRIBUTE_UNUSED,
+ void *closure)
+{
+ reloc_deps_graph *deps = closure;
+
+ /* If the target is defined. */
+ if (target_sec != NULL)
+ add_deps_edge (deps, src_sec, target_sec);
+}
+
+
+static reloc_deps_graph *
+ld_build_required_section_dependence (lang_statement_union_type *s)
+{
+ reloc_deps_graph *deps;
+ xtensa_ld_iter_stack *stack = NULL;
+
+ deps = xmalloc (sizeof (reloc_deps_graph));
+ deps->sections = NULL;
+ deps->count = 0;
+ deps->size = 0;
+
+ for (iter_stack_create (&stack, s);
+ !iter_stack_empty (&stack);
+ iter_stack_next (&stack))
+ {
+ lang_statement_union_type *l = iter_stack_current (&stack);
+
+ if (l->header.type == lang_input_section_enum)
+ {
+ lang_input_section_type *input;
+ input = &l->input_section;
+ xtensa_callback_required_dependence (input->section->owner,
+ input->section,
+ &link_info,
+ /* Use the same closure. */
+ build_deps_graph_callback,
+ deps);
+ }
+ }
+ return deps;
+}
+
+
+#if EXTRA_VALIDATION
+static size_t
+ld_count_children (lang_statement_union_type *s)
+{
+ size_t count = 0;
+ xtensa_ld_iter_stack *stack = NULL;
+ for (iter_stack_create (&stack, s);
+ !iter_stack_empty (&stack);
+ iter_stack_next (&stack))
+ {
+ lang_statement_union_type *l = iter_stack_current (&stack);
+ ASSERT (l != NULL);
+ count++;
+ }
+ return count;
+}
+#endif /* EXTRA_VALIDATION */
+
+
+/* Check if a particular section is included in the link. This will only
+ be true for one instance of a particular linkonce section. */
+
+static bfd_boolean input_section_found = FALSE;
+static asection *input_section_target = NULL;
+
+static void
+input_section_linked_worker (lang_statement_union_type *statement)
+{
+ if ((statement->header.type == lang_input_section_enum
+ && (statement->input_section.section == input_section_target)))
+ input_section_found = TRUE;
+}
+
+static bfd_boolean
+input_section_linked (asection *sec)
+{
+ input_section_found = FALSE;
+ input_section_target = sec;
+ lang_for_each_statement_worker (input_section_linked_worker, stat_ptr->head);
+ return input_section_found;
+}
+
+
+/* Strip out any linkonce property tables or XCC exception tables where the
+ associated linkonce text is from a different object file. Normally,
+ a matching set of linkonce sections is taken from the same object file,
+ but sometimes the files are compiled differently so that some of the
+ linkonce sections are not present in all files. Stripping the
+ inconsistent sections like this is not completely robust -- a much
+ better solution is to use comdat groups. */
+
+static int linkonce_len = sizeof (".gnu.linkonce.") - 1;
+
+static bfd_boolean
+is_inconsistent_linkonce_section (asection *sec)
+{
+ bfd *abfd = sec->owner;
+ const char *sec_name = bfd_get_section_name (abfd, sec);
+ const char *name;
+
+ if ((bfd_get_section_flags (abfd, sec) & SEC_LINK_ONCE) == 0
+ || strncmp (sec_name, ".gnu.linkonce.", linkonce_len) != 0)
+ return FALSE;
+
+ /* Check if this is an Xtensa property section or an exception table
+ for Tensilica's XCC compiler. */
+ name = sec_name + linkonce_len;
+ if (CONST_STRNEQ (name, "prop."))
+ name = strchr (name + 5, '.') + 1;
+ else if (name[1] == '.'
+ && (name[0] == 'p' || name[0] == 'e' || name[0] == 'h'))
+ name += 2;
+ else
+ name = 0;
+
+ if (name)
+ {
+ char *dep_sec_name = xmalloc (strlen (sec_name) + 1);
+ asection *dep_sec;
+
+ /* Get the associated linkonce text section and check if it is
+ included in the link. If not, this section is inconsistent
+ and should be stripped. */
+ strcpy (dep_sec_name, ".gnu.linkonce.t.");
+ strcat (dep_sec_name, name);
+ dep_sec = bfd_get_section_by_name (abfd, dep_sec_name);
+ if (dep_sec == NULL || ! input_section_linked (dep_sec))
+ {
+ free (dep_sec_name);
+ return TRUE;
+ }
+ free (dep_sec_name);
+ }
+
+ return FALSE;
+}
+
+
+static void
+xtensa_strip_inconsistent_linkonce_sections (lang_statement_list_type *slist)
+{
+ lang_statement_union_type **s_p = &slist->head;
+ while (*s_p)
+ {
+ lang_statement_union_type *s = *s_p;
+ lang_statement_union_type *s_next = (*s_p)->header.next;
+
+ switch (s->header.type)
+ {
+ case lang_input_section_enum:
+ if (is_inconsistent_linkonce_section (s->input_section.section))
+ {
+ s->input_section.section->output_section = bfd_abs_section_ptr;
+ *s_p = s_next;
+ continue;
+ }
+ break;
+
+ case lang_constructors_statement_enum:
+ xtensa_strip_inconsistent_linkonce_sections (&constructor_list);
+ break;
+
+ case lang_output_section_statement_enum:
+ if (s->output_section_statement.children.head)
+ xtensa_strip_inconsistent_linkonce_sections
+ (&s->output_section_statement.children);
+ break;
+
+ case lang_wild_statement_enum:
+ xtensa_strip_inconsistent_linkonce_sections
+ (&s->wild_statement.children);
+ break;
+
+ case lang_group_statement_enum:
+ xtensa_strip_inconsistent_linkonce_sections
+ (&s->group_statement.children);
+ 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;
+ }
+
+ s_p = &(*s_p)->header.next;
+ }
+
+ /* Reset the tail of the list, in case the last entry was removed. */
+ if (s_p != slist->tail)
+ slist->tail = s_p;
+}
+
+
+static void
+xtensa_wild_group_interleave_callback (lang_statement_union_type *statement)
+{
+ lang_wild_statement_type *w;
+ reloc_deps_graph *deps;
+ if (statement->header.type == lang_wild_statement_enum)
+ {
+#if EXTRA_VALIDATION
+ size_t old_child_count;
+ size_t new_child_count;
+#endif
+ bfd_boolean no_reorder;
+
+ w = &statement->wild_statement;
+
+ no_reorder = FALSE;
+
+ /* If it has 0 or 1 section bound, then do not reorder. */
+ if (w->children.head == NULL
+ || (w->children.head->header.type == lang_input_section_enum
+ && w->children.head->header.next == NULL))
+ no_reorder = TRUE;
+
+ if (w->filenames_sorted)
+ no_reorder = TRUE;
+
+ /* Check for sorting in a section list wildcard spec as well. */
+ if (!no_reorder)
+ {
+ struct wildcard_list *l;
+ for (l = w->section_list; l != NULL; l = l->next)
+ {
+ if (l->spec.sorted == TRUE)
+ {
+ no_reorder = TRUE;
+ break;
+ }
+ }
+ }
+
+ /* Special case until the NOREORDER linker directive is supported:
+ *(.init) output sections and *(.fini) specs may NOT be reordered. */
+
+ /* Check for sorting in a section list wildcard spec as well. */
+ if (!no_reorder)
+ {
+ struct wildcard_list *l;
+ for (l = w->section_list; l != NULL; l = l->next)
+ {
+ if (l->spec.name
+ && ((strcmp (".init", l->spec.name) == 0)
+ || (strcmp (".fini", l->spec.name) == 0)))
+ {
+ no_reorder = TRUE;
+ break;
+ }
+ }
+ }
+
+#if EXTRA_VALIDATION
+ old_child_count = ld_count_children (statement);
+#endif
+
+ /* It is now officially a target. Build the graph of source
+ section -> target section (kept as a list of edges). */
+ deps = ld_build_required_section_dependence (statement);
+
+ /* If this wildcard does not reorder.... */
+ if (!no_reorder && deps->count != 0)
+ {
+ /* First check for reverse dependences. Fix if possible. */
+ xtensa_layout_wild (deps, w);
+
+ xtensa_move_dependencies_to_front (deps, w);
+#if EXTRA_VALIDATION
+ new_child_count = ld_count_children (statement);
+ ASSERT (new_child_count == old_child_count);
+#endif
+
+ xtensa_colocate_literals (deps, statement);
+
+#if EXTRA_VALIDATION
+ new_child_count = ld_count_children (statement);
+ ASSERT (new_child_count == old_child_count);
+#endif
+ }
+
+ /* Clean up. */
+ free_reloc_deps_graph (deps);
+ }
+}
+
+
+static void
+xtensa_wild_group_interleave (lang_statement_union_type *s)
+{
+ lang_for_each_statement_worker (xtensa_wild_group_interleave_callback, s);
+}
+
+
+static void
+xtensa_layout_wild (const reloc_deps_graph *deps, lang_wild_statement_type *w)
+{
+ /* If it does not fit initially, we need to do this step. Move all
+ of the wild literal sections to a new list, then move each of
+ them back in just before the first section they depend on. */
+ lang_statement_union_type **s_p;
+#if EXTRA_VALIDATION
+ size_t old_count, new_count;
+ size_t ct1, ct2;
+#endif
+
+ lang_wild_statement_type literal_wild;
+ literal_wild.header.next = NULL;
+ literal_wild.header.type = lang_wild_statement_enum;
+ literal_wild.filename = NULL;
+ literal_wild.filenames_sorted = FALSE;
+ literal_wild.section_list = NULL;
+ literal_wild.keep_sections = FALSE;
+ literal_wild.children.head = NULL;
+ literal_wild.children.tail = &literal_wild.children.head;
+
+#if EXTRA_VALIDATION
+ old_count = ld_count_children ((lang_statement_union_type*) w);
+#endif
+
+ s_p = &w->children.head;
+ while (*s_p != NULL)
+ {
+ lang_statement_union_type *l = *s_p;
+ if (l->header.type == lang_input_section_enum)
+ {
+ if (section_is_target (deps, l)
+ && ! section_is_source (deps, l))
+ {
+ /* Detach. */
+ *s_p = l->header.next;
+ if (*s_p == NULL)
+ w->children.tail = s_p;
+ l->header.next = NULL;
+
+ /* Append. */
+ *literal_wild.children.tail = l;
+ literal_wild.children.tail = &l->header.next;
+ continue;
+ }
+ }
+ s_p = &(*s_p)->header.next;
+ }
+
+#if EXTRA_VALIDATION
+ ct1 = ld_count_children ((lang_statement_union_type*) w);
+ ct2 = ld_count_children ((lang_statement_union_type*) &literal_wild);
+
+ ASSERT (old_count == (ct1 + ct2));
+#endif
+
+ /* Now place them back in front of their dependent sections. */
+
+ while (literal_wild.children.head != NULL)
+ {
+ lang_statement_union_type *lit = literal_wild.children.head;
+ bfd_boolean placed = FALSE;
+
+#if EXTRA_VALIDATION
+ ASSERT (ct2 > 0);
+ ct2--;
+#endif
+
+ /* Detach. */
+ literal_wild.children.head = lit->header.next;
+ if (literal_wild.children.head == NULL)
+ literal_wild.children.tail = &literal_wild.children.head;
+ lit->header.next = NULL;
+
+ /* Find a spot to place it. */
+ for (s_p = &w->children.head; *s_p != NULL; s_p = &(*s_p)->header.next)
+ {
+ lang_statement_union_type *src = *s_p;
+ if (deps_has_edge (deps, src, lit))
+ {
+ /* Place it here. */
+ lit->header.next = *s_p;
+ *s_p = lit;
+ placed = TRUE;
+ break;
+ }
+ }
+
+ if (!placed)
+ {
+ /* Put it at the end. */
+ *w->children.tail = lit;
+ w->children.tail = &lit->header.next;
+ }
+ }
+
+#if EXTRA_VALIDATION
+ new_count = ld_count_children ((lang_statement_union_type*) w);
+ ASSERT (new_count == old_count);
+#endif
+}
+
+
+static void
+xtensa_colocate_output_literals_callback (lang_statement_union_type *statement)
+{
+ lang_output_section_statement_type *os;
+ reloc_deps_graph *deps;
+ if (statement->header.type == lang_output_section_statement_enum)
+ {
+ /* Now, we walk over the contours of the output section statement.
+
+ First we build the literal section dependences as before.
+
+ At the first uniquely_literal section, we mark it as a good
+ spot to place other literals. Continue walking (and counting
+ sizes) until we find the next literal section. If this
+ section can be moved to the first one, then we move it. If
+ we every find a modification of ".", start over. If we find
+ a labeling of the current location, start over. Finally, at
+ the end, if we require page alignment, add page alignments. */
+
+#if EXTRA_VALIDATION
+ size_t old_child_count;
+ size_t new_child_count;
+#endif
+ bfd_boolean no_reorder = FALSE;
+
+ os = &statement->output_section_statement;
+
+#if EXTRA_VALIDATION
+ old_child_count = ld_count_children (statement);
+#endif
+
+ /* It is now officially a target. Build the graph of source
+ section -> target section (kept as a list of edges). */
+
+ deps = ld_build_required_section_dependence (statement);
+
+ /* If this wildcard does not reorder.... */
+ if (!no_reorder)
+ {
+ /* First check for reverse dependences. Fix if possible. */
+ xtensa_colocate_literals (deps, statement);
+
+#if EXTRA_VALIDATION
+ new_child_count = ld_count_children (statement);
+ ASSERT (new_child_count == old_child_count);
+#endif
+ }
+
+ /* Insert align/offset assignment statement. */
+ if (xtensa_use_literal_pages)
+ {
+ ld_xtensa_insert_page_offsets (0, statement, deps,
+ xtensa_use_literal_pages);
+ lang_for_each_statement_worker (xtensa_ldlang_clear_addresses,
+ statement);
+ }
+
+ /* Clean up. */
+ free_reloc_deps_graph (deps);
+ }
+}
+
+
+static void
+xtensa_colocate_output_literals (lang_statement_union_type *s)
+{
+ lang_for_each_statement_worker (xtensa_colocate_output_literals_callback, s);
+}
+
+
+static void
+xtensa_ldlang_clear_addresses (lang_statement_union_type *statement)
+{
+ switch (statement->header.type)
+ {
+ case lang_input_section_enum:
+ {
+ asection *bfd_section = statement->input_section.section;
+ bfd_section->output_offset = 0;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+
+static bfd_vma
+ld_assign_relative_paged_dot (bfd_vma dot,
+ lang_statement_union_type *s,
+ const reloc_deps_graph *deps ATTRIBUTE_UNUSED,
+ bfd_boolean lit_align)
+{
+ /* Walk through all of the input statements in this wild statement
+ assign dot to all of them. */
+
+ xtensa_ld_iter_stack *stack = NULL;
+ xtensa_ld_iter_stack **stack_p = &stack;
+
+ bfd_boolean first_section = FALSE;
+ bfd_boolean in_literals = FALSE;
+
+ for (iter_stack_create (stack_p, s);
+ !iter_stack_empty (stack_p);
+ iter_stack_next (stack_p))
+ {
+ lang_statement_union_type *l = iter_stack_current (stack_p);
+
+ switch (l->header.type)
+ {
+ case lang_input_section_enum:
+ {
+ asection *section = l->input_section.section;
+ size_t align_pow = section->alignment_power;
+ bfd_boolean do_xtensa_alignment = FALSE;
+
+ if (lit_align)
+ {
+ bfd_boolean sec_is_target = section_is_target (deps, l);
+ bfd_boolean sec_is_source = section_is_source (deps, l);
+
+ if (section->size != 0
+ && (first_section
+ || (in_literals && !sec_is_target)
+ || (!in_literals && sec_is_target)))
+ {
+ do_xtensa_alignment = TRUE;
+ }
+ first_section = FALSE;
+ if (section->size != 0)
+ in_literals = (sec_is_target && !sec_is_source);
+ }
+
+ if (do_xtensa_alignment && xtensa_page_power != 0)
+ dot += (1 << xtensa_page_power);
+
+ dot = align_power (dot, align_pow);
+ section->output_offset = dot;
+ dot += section->size;
+ }
+ break;
+ case lang_fill_statement_enum:
+ dot += l->fill_statement.size;
+ break;
+ case lang_padding_statement_enum:
+ dot += l->padding_statement.size;
+ break;
+ default:
+ break;
+ }
+ }
+ return dot;
+}
+
+
+static bfd_boolean
+ld_local_file_relocations_fit (lang_statement_union_type *statement,
+ const reloc_deps_graph *deps ATTRIBUTE_UNUSED)
+{
+ /* Walk over all of the dependencies that we identified and make
+ sure that IF the source and target are here (addr != 0):
+ 1) target addr < source addr
+ 2) (roundup(source + source_size, 4) - rounddown(target, 4))
+ < (256K - (1 << bad align))
+ Need a worst-case proof.... */
+
+ xtensa_ld_iter_stack *stack = NULL;
+ xtensa_ld_iter_stack **stack_p = &stack;
+ size_t max_align_power = 0;
+ size_t align_penalty = 256;
+ reloc_deps_e *e;
+ size_t i;
+
+ /* Find the worst-case alignment requirement for this set of statements. */
+ for (iter_stack_create (stack_p, statement);
+ !iter_stack_empty (stack_p);
+ iter_stack_next (stack_p))
+ {
+ lang_statement_union_type *l = iter_stack_current (stack_p);
+ if (l->header.type == lang_input_section_enum)
+ {
+ lang_input_section_type *input = &l->input_section;
+ asection *section = input->section;
+ if (section->alignment_power > max_align_power)
+ max_align_power = section->alignment_power;
+ }
+ }
+
+ /* Now check that everything fits. */
+ for (i = 0; i < deps->count; i++)
+ {
+ asection *sec = deps->sections[i];
+ const reloc_deps_section *deps_section =
+ xtensa_get_section_deps (deps, sec);
+ if (deps_section)
+ {
+ /* We choose to walk through the successors. */
+ for (e = deps_section->succs; e != NULL; e = e->next)
+ {
+ if (e->src != e->tgt
+ && e->src->output_section == e->tgt->output_section
+ && e->src->output_offset != 0
+ && e->tgt->output_offset != 0)
+ {
+ bfd_vma l32r_addr =
+ align_power (e->src->output_offset + e->src->size, 2);
+ bfd_vma target_addr = e->tgt->output_offset & ~3;
+ if (l32r_addr < target_addr)
+ {
+ fprintf (stderr, "Warning: "
+ "l32r target section before l32r\n");
+ return FALSE;
+ }
+
+ if (l32r_addr - target_addr > 256 * 1024 - align_penalty)
+ return FALSE;
+ }
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+
+static bfd_vma
+ld_xtensa_insert_page_offsets (bfd_vma dot,
+ lang_statement_union_type *s,
+ reloc_deps_graph *deps,
+ bfd_boolean lit_align)
+{
+ xtensa_ld_iter_stack *stack = NULL;
+ xtensa_ld_iter_stack **stack_p = &stack;
+
+ bfd_boolean first_section = FALSE;
+ bfd_boolean in_literals = FALSE;
+
+ if (!lit_align)
+ return FALSE;
+
+ for (iter_stack_create (stack_p, s);
+ !iter_stack_empty (stack_p);
+ iter_stack_next (stack_p))
+ {
+ lang_statement_union_type *l = iter_stack_current (stack_p);
+
+ switch (l->header.type)
+ {
+ case lang_input_section_enum:
+ {
+ asection *section = l->input_section.section;
+ bfd_boolean do_xtensa_alignment = FALSE;
+
+ if (lit_align)
+ {
+ if (section->size != 0
+ && (first_section
+ || (in_literals && !section_is_target (deps, l))
+ || (!in_literals && section_is_target (deps, l))))
+ {
+ do_xtensa_alignment = TRUE;
+ }
+ first_section = FALSE;
+ if (section->size != 0)
+ {
+ in_literals = (section_is_target (deps, l)
+ && !section_is_source (deps, l));
+ }
+ }
+
+ if (do_xtensa_alignment && xtensa_page_power != 0)
+ {
+ /* Create an expression that increments the current address,
+ i.e., "dot", by (1 << xtensa_align_power). */
+ etree_type *name_op = exp_nameop (NAME, ".");
+ etree_type *addend_op = exp_intop (1 << xtensa_page_power);
+ etree_type *add_op = exp_binop ('+', name_op, addend_op);
+ etree_type *assign_op = exp_assop ('=', ".", add_op);
+
+ lang_assignment_statement_type *assign_stmt;
+ lang_statement_union_type *assign_union;
+ lang_statement_list_type tmplist;
+
+ /* There is hidden state in "lang_add_assignment". It
+ appends the new assignment statement to the stat_ptr
+ list. Thus, we swap it before and after the call. */
+
+ lang_list_init (&tmplist);
+ push_stat_ptr (&tmplist);
+ /* Warning: side effect; statement appended to stat_ptr. */
+ assign_stmt = lang_add_assignment (assign_op);
+ assign_union = (lang_statement_union_type *) assign_stmt;
+ pop_stat_ptr ();
+
+ assign_union->header.next = l;
+ *(*stack_p)->iterloc.loc = assign_union;
+ iter_stack_next (stack_p);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return dot;
+}
+
+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_OPT_SIZEOPT (300)
+#define OPTION_NO_RELAX (OPTION_OPT_SIZEOPT + 1)
+#define OPTION_LITERAL_MOVEMENT (OPTION_NO_RELAX + 1)
+#define OPTION_NO_LITERAL_MOVEMENT (OPTION_LITERAL_MOVEMENT + 1)
+extern int elf32xtensa_size_opt;
+extern int elf32xtensa_no_literal_movement;
+'
+
+PARSE_AND_LIST_LONGOPTS='
+ { "size-opt", no_argument, NULL, OPTION_OPT_SIZEOPT},
+ { "no-relax", no_argument, NULL, OPTION_NO_RELAX},
+ { "literal-movement", no_argument, NULL, OPTION_LITERAL_MOVEMENT},
+ { "no-literal-movement", no_argument, NULL, OPTION_NO_LITERAL_MOVEMENT},
+'
+
+PARSE_AND_LIST_OPTIONS='
+ fprintf (file, _("\
+ --size-opt When relaxing longcalls, prefer size\n\
+ optimization over branch target alignment\n"));
+ fprintf (file, _("\
+ --no-relax Do not relax branches or coalesce literals\n"));
+'
+
+PARSE_AND_LIST_ARGS_CASES='
+ case OPTION_OPT_SIZEOPT:
+ elf32xtensa_size_opt = 1;
+ break;
+ case OPTION_NO_RELAX:
+ disable_relaxation = TRUE;
+ break;
+ case OPTION_LITERAL_MOVEMENT:
+ elf32xtensa_no_literal_movement = 0;
+ break;
+ case OPTION_NO_LITERAL_MOVEMENT:
+ elf32xtensa_no_literal_movement = 1;
+ break;
+'
+
+# Replace some of the standard ELF functions with our own versions.
+#
+LDEMUL_BEFORE_PARSE=elf_xtensa_before_parse
+LDEMUL_AFTER_OPEN=elf_xtensa_after_open
+LDEMUL_CHOOSE_TARGET=elf_xtensa_choose_target
+LDEMUL_BEFORE_ALLOCATION=elf_xtensa_before_allocation
diff --git a/binutils-2.20.1/ld/emultempl/z80.em b/binutils-2.20.1/ld/emultempl/z80.em
new file mode 100644
index 00000000..100ebd0e
--- /dev/null
+++ b/binutils-2.20.1/ld/emultempl/z80.em
@@ -0,0 +1,102 @@
+# This shell script emits C code -*- C -*-
+# to keep track of the machine type of Z80 object files
+# It does some substitutions.
+# Copyright 2005, 2007, 2008 Free Software Foundation, Inc.
+# This file is part of the GNU Binutils.
+#
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+LDEMUL_BEFORE_PARSE=gldz80_before_parse
+LDEMUL_RECOGNIZED_FILE=gldz80_recognized_file
+LDEMUL_AFTER_OPEN=gldz80_after_open
+
+fragment <<EOF
+/* --- \begin{z80.em} */
+/* Codes for machine types, bitwise or gives the code to use for the
+ output. */
+#define M_Z80STRICT 1
+#define M_Z80 3
+#define M_Z80FULL 7
+#define M_R800 11
+#define M_Z80ANY 15
+
+/* Bitwise or of the machine types seen so far. */
+static int result_mach_type;
+
+static void
+${LDEMUL_BEFORE_PARSE} (void)
+{
+#ifndef TARGET_ /* I.e., if not generic. */
+ ldfile_set_output_arch ("`echo ${ARCH}`", bfd_arch_unknown);
+#endif /* not TARGET_ */
+ result_mach_type = M_Z80STRICT;
+}
+
+
+/* Update result_mach_type. */
+static bfd_boolean
+${LDEMUL_RECOGNIZED_FILE} (lang_input_statement_type *entry)
+{
+ unsigned long mach_type;
+
+ mach_type = bfd_get_mach (entry->the_bfd);
+ switch (mach_type)
+ {
+ case bfd_mach_z80strict:
+ result_mach_type |= M_Z80STRICT;
+ break;
+ case bfd_mach_z80:
+ result_mach_type |= M_Z80;
+ break;
+ case bfd_mach_z80full:
+ result_mach_type |= M_Z80FULL;
+ break;
+ case bfd_mach_r800:
+ result_mach_type |= M_R800;
+ break;
+ default:
+ result_mach_type |= M_Z80ANY;
+ }
+ return FALSE;
+}
+
+/* Set the machine type of the output file based on result_mach_type. */
+static void
+gldz80_after_open (void)
+{
+ unsigned long mach_type;
+
+ switch (result_mach_type)
+ {
+ case M_Z80STRICT:
+ mach_type = bfd_mach_z80strict;
+ break;
+ case M_Z80:
+ mach_type = bfd_mach_z80;
+ break;
+ case M_Z80FULL:
+ mach_type = bfd_mach_z80full;
+ break;
+ case M_R800:
+ mach_type = bfd_mach_r800;
+ break;
+ default:
+ mach_type = 0;
+ }
+ bfd_set_arch_mach (link_info.output_bfd, bfd_arch_z80, mach_type);
+}
+/* --- \end{z80.em} */
+EOF