summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/binutils/ld/emultempl
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>1996-01-08 11:10:27 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>1996-01-08 11:10:27 +0000
commit8b46c09925a80623c289e346c12921bc09fd1678 (patch)
tree01507d0da339cc7e5e6f5d16dfa625f94910b091 /gnu/usr.bin/binutils/ld/emultempl
parent5d56227f9458a53138642c1b4488b4a30f85f334 (diff)
Initial GNU binutils 2.6 import
Diffstat (limited to 'gnu/usr.bin/binutils/ld/emultempl')
-rw-r--r--gnu/usr.bin/binutils/ld/emultempl/README3
-rw-r--r--gnu/usr.bin/binutils/ld/emultempl/aix.em990
-rw-r--r--gnu/usr.bin/binutils/ld/emultempl/elf32.em799
-rw-r--r--gnu/usr.bin/binutils/ld/emultempl/generic.em118
-rw-r--r--gnu/usr.bin/binutils/ld/emultempl/gld960.em176
-rw-r--r--gnu/usr.bin/binutils/ld/emultempl/gld960c.em177
-rw-r--r--gnu/usr.bin/binutils/ld/emultempl/hppaelf.em286
-rw-r--r--gnu/usr.bin/binutils/ld/emultempl/linux.em207
-rw-r--r--gnu/usr.bin/binutils/ld/emultempl/lnk960.em323
-rw-r--r--gnu/usr.bin/binutils/ld/emultempl/m88kbcs.em119
-rw-r--r--gnu/usr.bin/binutils/ld/emultempl/mipsecoff.em229
-rw-r--r--gnu/usr.bin/binutils/ld/emultempl/pe.em518
-rw-r--r--gnu/usr.bin/binutils/ld/emultempl/stringify.sed4
-rw-r--r--gnu/usr.bin/binutils/ld/emultempl/sunos.em969
-rw-r--r--gnu/usr.bin/binutils/ld/emultempl/vanilla.em69
15 files changed, 4987 insertions, 0 deletions
diff --git a/gnu/usr.bin/binutils/ld/emultempl/README b/gnu/usr.bin/binutils/ld/emultempl/README
new file mode 100644
index 00000000000..30ec0abf379
--- /dev/null
+++ b/gnu/usr.bin/binutils/ld/emultempl/README
@@ -0,0 +1,3 @@
+The files in this directory are sourced by genscripts.sh, after
+setting some variables to substitute in, to produce
+C source files that contain jump tables for each emulation.
diff --git a/gnu/usr.bin/binutils/ld/emultempl/aix.em b/gnu/usr.bin/binutils/ld/emultempl/aix.em
new file mode 100644
index 00000000000..c40b86c2953
--- /dev/null
+++ b/gnu/usr.bin/binutils/ld/emultempl/aix.em
@@ -0,0 +1,990 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+cat >e${EMULATION_NAME}.c <<EOF
+/* This file is is generated by a shell script. DO NOT EDIT! */
+
+/* AIX emulation code for ${EMULATION_NAME}
+ Copyright (C) 1991, 1993, 1995 Free Software Foundation, Inc.
+ Written by Steve Chamberlain <sac@cygnus.com>
+ AIX support by Ian Lance Taylor <ian@cygnus.com>
+
+This file is part of GLD, the Gnu Linker.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libiberty.h"
+#include "getopt.h"
+#include "bfdlink.h"
+
+#include <ctype.h>
+
+#include "ld.h"
+#include "ldmain.h"
+#include "ldemul.h"
+#include "ldfile.h"
+#include "ldmisc.h"
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldctor.h"
+#include "ldgram.h"
+
+static void gld${EMULATION_NAME}_before_parse PARAMS ((void));
+static int gld${EMULATION_NAME}_parse_args PARAMS ((int, char **));
+static void gld${EMULATION_NAME}_after_open PARAMS ((void));
+static void gld${EMULATION_NAME}_before_allocation PARAMS ((void));
+static void gld${EMULATION_NAME}_read_file PARAMS ((const char *, boolean));
+static void gld${EMULATION_NAME}_free PARAMS ((PTR));
+static void gld${EMULATION_NAME}_find_relocs
+ PARAMS ((lang_statement_union_type *));
+static void gld${EMULATION_NAME}_find_exp_assignment PARAMS ((etree_type *));
+static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
+
+/* 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;
+
+/* 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;
+ boolean syscall;
+};
+
+static struct export_symbol_list *export_symbols;
+
+/* This routine is called before anything else is done. */
+
+static void
+gld${EMULATION_NAME}_before_parse()
+{
+#ifndef TARGET_ /* I.e., if not generic. */
+ ldfile_output_architecture = bfd_arch_${ARCH};
+#endif /* not TARGET_ */
+}
+
+/* Handle AIX specific options. */
+
+static int
+gld${EMULATION_NAME}_parse_args (argc, argv)
+ int argc;
+ char **argv;
+{
+ int prevoptind = optind;
+ int prevopterr = opterr;
+ int indx;
+ int longind;
+ int optc;
+ long val;
+ char *end;
+
+#define OPTION_IGNORE (300)
+#define OPTION_AUTOIMP (OPTION_IGNORE + 1)
+#define OPTION_ERNOTOK (OPTION_AUTOIMP + 1)
+#define OPTION_EROK (OPTION_ERNOTOK + 1)
+#define OPTION_EXPORT (OPTION_EROK + 1)
+#define OPTION_IMPORT (OPTION_EXPORT + 1)
+#define OPTION_LOADMAP (OPTION_IMPORT + 1)
+#define OPTION_MAXDATA (OPTION_LOADMAP + 1)
+#define OPTION_MAXSTACK (OPTION_MAXDATA + 1)
+#define OPTION_MODTYPE (OPTION_MAXSTACK + 1)
+#define OPTION_NOAUTOIMP (OPTION_MODTYPE + 1)
+#define OPTION_NOSTRCMPCT (OPTION_NOAUTOIMP + 1)
+#define OPTION_PD (OPTION_NOSTRCMPCT + 1)
+#define OPTION_PT (OPTION_PD + 1)
+#define OPTION_STRCMPCT (OPTION_PT + 1)
+
+ static struct option longopts[] = {
+ {"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},
+ {"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},
+ {"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},
+ {"bnodelcsect", 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},
+ {"bS", required_argument, NULL, OPTION_MAXSTACK},
+ {"bso", no_argument, NULL, OPTION_AUTOIMP},
+ {"bstrcmpct", no_argument, NULL, OPTION_STRCMPCT},
+ {"btextro", no_argument, &textro, 1},
+ {"static", no_argument, NULL, OPTION_NOAUTOIMP},
+ {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. */
+
+ /* 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 && strncmp (argv[indx], "-b", 2) == 0)
+ {
+ char *s;
+
+ for (s = argv[indx]; *s != '\0'; s++)
+ {
+ if (*s == ':')
+ {
+ *s = '=';
+ break;
+ }
+ }
+ }
+
+ opterr = 0;
+ optc = getopt_long_only (argc, argv, "-D:H:KT:z", longopts, &longind);
+ opterr = prevopterr;
+
+ switch (optc)
+ {
+ default:
+ optind = prevoptind;
+ return 0;
+
+ case 0:
+ /* Long option which just sets a flag. */
+ break;
+
+ case 'D':
+ val = strtol (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));
+ break;
+
+ case 'H':
+ val = strtoul (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 = strtoul (optarg, &end, 0);
+ if (*end != '\0')
+ {
+ optind = prevoptind;
+ return 0;
+ }
+ lang_section_start (".text", exp_intop (val));
+ break;
+
+ case OPTION_IGNORE:
+ break;
+
+ case OPTION_AUTOIMP:
+ link_info.static_link = false;
+ break;
+
+ case OPTION_ERNOTOK:
+ force_make_executable = false;
+ break;
+
+ case OPTION_EROK:
+ force_make_executable = true;
+ 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 = strtoul (optarg, &end, 0);
+ if (*end != '\0')
+ einfo ("%P: warning: ignoring invalid -bmaxdata number %s\n",
+ optarg);
+ else
+ maxdata = val;
+ break;
+
+ case OPTION_MAXSTACK:
+ val = strtoul (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_NOSTRCMPCT:
+ config.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 = strtoul (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 (7)),
+ exp_intop (~ (bfd_vma) 7));
+ lang_section_start (".data", t);
+ }
+ 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 = strtoul (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 (7)),
+ exp_intop (~ (bfd_vma) 7));
+ lang_section_start (".text", t);
+ }
+ break;
+
+ case OPTION_STRCMPCT:
+ config.traditional_format = false;
+ break;
+ }
+
+ return 1;
+}
+
+/* This is called after the input files have been opened. */
+
+static void
+gld${EMULATION_NAME}_after_open ()
+{
+ boolean r;
+ struct set_info *p;
+
+ /* Call ldctor_build_sets, after pretending that this is a
+ relocateable link. We do this because AIX requires relocation
+ entries for all references to symbols, even in a final
+ executable. */
+ r = link_info.relocateable;
+ link_info.relocateable = true;
+ ldctor_build_sets ();
+ link_info.relocateable = 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 (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 ()
+{
+ struct filelist *fl;
+ struct export_symbol_list *el;
+ char *libpath;
+ asection *special_sections[6];
+ int i;
+
+ /* Handle the import and export files, if any. */
+ for (fl = import_files; fl != NULL; fl = fl->next)
+ gld${EMULATION_NAME}_read_file (fl->name, true);
+ for (el = export_symbols; el != NULL; el = el->next)
+ {
+ struct bfd_link_hash_entry *h;
+
+ h = bfd_link_hash_lookup (link_info.hash, el->name, false, false, false);
+ if (h == NULL)
+ einfo ("%P%F: bfd_link_hash_lookup of export symbol failed: %E\n");
+ if (! bfd_xcoff_export_symbol (output_bfd, &link_info, h, el->syscall))
+ einfo ("%P%F: bfd_xcoff_export_symbol failed: %E\n");
+ }
+
+ /* Track down all relocations called for by the linker script (these
+ are typically constructor/destructor entries created by
+ CONSTRUCTORS) and let the backend know it will need to create
+ .loader relocs for them. */
+ lang_for_each_statement (gld${EMULATION_NAME}_find_relocs);
+
+ /* We need to build LIBPATH from the -L arguments. If any -rpath
+ arguments were used, though, we use -rpath instead, as a GNU
+ extension. */
+ if (command_line.rpath != NULL)
+ libpath = command_line.rpath;
+ else if (search_head == NULL)
+ libpath = (char *) "";
+ else
+ {
+ size_t len;
+ search_dirs_type *search;
+
+ 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;
+ }
+ }
+
+ /* Let the XCOFF backend set up the .loader section. */
+ if (! bfd_xcoff_size_dynamic_sections (output_bfd, &link_info, libpath,
+ entry_symbol, file_align,
+ maxstack, maxdata,
+ gc ? true : false,
+ modtype,
+ textro ? true : false,
+ special_sections))
+ 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 < 6; i++)
+ {
+ asection *sec;
+ lang_output_section_statement_type *os;
+ lang_statement_union_type **pls;
+ lang_input_section_type *is;
+ const char *oname;
+ boolean start;
+
+ sec = special_sections[i];
+ if (sec == NULL)
+ continue;
+
+ /* Remove this section from the list of the output section.
+ This assumes we know what the script looks like. */
+ is = NULL;
+ os = lang_output_section_find (sec->output_section->name);
+ if (os == NULL)
+ einfo ("%P%F: can't find output section %s\n",
+ sec->output_section->name);
+ for (pls = &os->children.head; *pls != NULL; pls = &(*pls)->next)
+ {
+ if ((*pls)->header.type == lang_input_section_enum
+ && (*pls)->input_section.section == sec)
+ {
+ is = (lang_input_section_type *) *pls;
+ *pls = (*pls)->next;
+ break;
+ }
+ if ((*pls)->header.type == lang_wild_statement_enum)
+ {
+ lang_statement_union_type **pwls;
+
+ for (pwls = &(*pls)->wild_statement.children.head;
+ *pwls != NULL;
+ pwls = &(*pwls)->next)
+ {
+ if ((*pwls)->header.type == lang_input_section_enum
+ && (*pwls)->input_section.section == sec)
+ {
+ is = (lang_input_section_type *) *pwls;
+ *pwls = (*pwls)->next;
+ break;
+ }
+ }
+ if (is != NULL)
+ break;
+ }
+ }
+
+ if (is == NULL)
+ einfo ("%P%F: can't find %s in output section\n",
+ bfd_get_section_name (sec->owner, sec));
+
+ /* Now figure out where the section should go. */
+ switch (i)
+ {
+ default: /* to avoid warnings */
+ case 0:
+ /* _text */
+ oname = ".text";
+ start = true;
+ break;
+ case 1:
+ /* _etext */
+ oname = ".text";
+ start = false;
+ break;
+ case 2:
+ /* _data */
+ oname = ".data";
+ start = true;
+ break;
+ case 3:
+ /* _edata */
+ oname = ".data";
+ start = false;
+ break;
+ case 4:
+ case 5:
+ /* _end and end */
+ oname = ".bss";
+ start = false;
+ break;
+ }
+
+ os = lang_output_section_find (oname);
+
+ if (start)
+ {
+ is->header.next = os->children.head;
+ os->children.head = (lang_statement_union_type *) is;
+ }
+ else
+ {
+ is->header.next = NULL;
+ lang_statement_append (&os->children,
+ (lang_statement_union_type *) is,
+ &is->header.next);
+ }
+ }
+}
+
+/* Read an import or export file. For an import file, this is called
+ by the before_allocation emulation routine. For an export file,
+ this is called by the parse_args emulation routine. */
+
+static void
+gld${EMULATION_NAME}_read_file (filename, import)
+ const char *filename;
+ boolean import;
+{
+ struct obstack *o;
+ FILE *f;
+ int lineno;
+ int c;
+ 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, "r");
+ 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;
+ while ((c = getc (f)) != EOF)
+ {
+ char *s;
+ char *symname;
+ boolean syscall;
+ 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 ((unsigned char) *s))
+ ++s;
+ if (*s == '\0'
+ || *s == '*'
+ || (*s == '#' && s[1] == ' ')
+ || (! import && *s == '#' && s[1] == '!'))
+ {
+ obstack_free (o, obstack_base (o));
+ continue;
+ }
+
+ if (*s == '#' && s[1] == '!')
+ {
+ s += 2;
+ while (isspace ((unsigned char) *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",
+ filename, lineno);
+ else
+ {
+ char cs;
+ char *file;
+
+ (void) obstack_finish (o);
+ keep = true;
+ imppath = s;
+ impfile = NULL;
+ while (! isspace ((unsigned char) *s) && *s != '(' && *s != '\0')
+ {
+ if (*s == '/')
+ file = s + 1;
+ ++s;
+ }
+ if (file != NULL)
+ {
+ file[-1] = '\0';
+ impfile = file;
+ if (imppath == file - 1)
+ imppath = "/";
+ }
+ else
+ {
+ impfile = imppath;
+ imppath = "";
+ }
+ cs = *s;
+ *s = '\0';
+ while (isspace ((unsigned char) 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;
+ }
+
+ /* This is a symbol to be imported or exported. */
+ symname = s;
+ syscall = false;
+ address = (bfd_vma) -1;
+
+ while (! isspace ((unsigned char) *s) && *s != '\0')
+ ++s;
+ if (*s != '\0')
+ {
+ char *se;
+
+ *s++ = '\0';
+
+ while (isspace ((unsigned char) *s))
+ ++s;
+
+ se = s;
+ while (! isspace ((unsigned char) *se) && *se != '\0')
+ ++se;
+ if (*se != '\0')
+ {
+ *se++ = '\0';
+ while (isspace ((unsigned char) *se))
+ ++se;
+ if (*se != '\0')
+ einfo ("%s%d: warning: syntax error in import/export file\n",
+ filename, lineno);
+ }
+
+ if (strcasecmp (s, "svc") == 0
+ || strcasecmp (s, "syscall") == 0)
+ syscall = true;
+ else
+ {
+ char *end;
+
+ address = strtoul (s, &end, 0);
+ if (*end != '\0')
+ einfo ("%s:%d: warning: syntax error in import/export file\n",
+ filename, lineno);
+ }
+ }
+
+ if (! import)
+ {
+ struct export_symbol_list *n;
+
+ ldlang_add_undef (symname);
+ n = ((struct export_symbol_list *)
+ xmalloc (sizeof (struct export_symbol_list)));
+ n->next = export_symbols;
+ n->name = buystring (symname);
+ n->syscall = syscall;
+ export_symbols = n;
+ }
+ else
+ {
+ h = bfd_link_hash_lookup (link_info.hash, symname, false, false,
+ true);
+ if (h == NULL || h->type == bfd_link_hash_new)
+ {
+ /* We can just ignore attempts to import an unreferenced
+ symbol. */
+ }
+ else
+ {
+ if (! bfd_xcoff_import_symbol (output_bfd, &link_info, h,
+ address, imppath, impfile,
+ impmember))
+ einfo ("%X%s:%d: failed to import symbol %s: %E\n",
+ filename, lineno, symname);
+ }
+ }
+
+ obstack_free (o, obstack_base (o));
+ }
+
+ if (obstack_object_size (o) > 0)
+ {
+ einfo ("%s:%d: warning: ignoring unterminated last line\n",
+ filename, lineno);
+ obstack_free (o, obstack_base (o));
+ }
+
+ if (! keep)
+ {
+ obstack_free (o, NULL);
+ free (o);
+ }
+}
+
+/* This routine saves us from worrying about declaring free. */
+
+static void
+gld${EMULATION_NAME}_free (p)
+ PTR 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 (s)
+ 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 (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 (exp)
+ 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 (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(isfile)
+ 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/stringify.sed"
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 0;
+
+ if (link_info.relocateable == true && config.build_constructors == true)
+ return
+EOF
+sed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c
+echo ' ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.c
+echo ' ; else if (!config.text_read_only) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c
+echo ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c
+echo ' ; else return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c
+echo '; }' >> e${EMULATION_NAME}.c
+
+else
+# Scripts read from the filesystem.
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 1;
+
+ if (link_info.relocateable == true && config.build_constructors == true)
+ return "ldscripts/${EMULATION_NAME}.xu";
+ else if (link_info.relocateable == true)
+ return "ldscripts/${EMULATION_NAME}.xr";
+ else if (!config.text_read_only)
+ return "ldscripts/${EMULATION_NAME}.xbn";
+ else if (!config.magic_demand_paged)
+ return "ldscripts/${EMULATION_NAME}.xn";
+ else
+ return "ldscripts/${EMULATION_NAME}.x";
+}
+EOF
+
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
+{
+ gld${EMULATION_NAME}_before_parse,
+ syslib_default,
+ hll_default,
+ after_parse_default,
+ gld${EMULATION_NAME}_after_open,
+ after_allocation_default,
+ set_output_arch_default,
+ ldemul_default_target,
+ gld${EMULATION_NAME}_before_allocation,
+ gld${EMULATION_NAME}_get_script,
+ "${EMULATION_NAME}",
+ "${OUTPUT_FORMAT}",
+ 0, /* finish */
+ 0, /* create_output_section_statements */
+ 0, /* open_dynamic_archive */
+ 0, /* place_orphan */
+ 0, /* set_symbols */
+ gld${EMULATION_NAME}_parse_args,
+};
+EOF
diff --git a/gnu/usr.bin/binutils/ld/emultempl/elf32.em b/gnu/usr.bin/binutils/ld/emultempl/elf32.em
new file mode 100644
index 00000000000..8b2f6259748
--- /dev/null
+++ b/gnu/usr.bin/binutils/ld/emultempl/elf32.em
@@ -0,0 +1,799 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+cat >e${EMULATION_NAME}.c <<EOF
+/* This file is is generated by a shell script. DO NOT EDIT! */
+
+/* 32 bit ELF emulation code for ${EMULATION_NAME}
+ Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Written by Steve Chamberlain <sac@cygnus.com>
+ ELF support by Ian Lance Taylor <ian@cygnus.com>
+
+This file is part of GLD, the Gnu Linker.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include "bfd.h"
+#include "sysdep.h"
+
+#include <ctype.h>
+
+#include "bfdlink.h"
+
+#include "ld.h"
+#include "ldmain.h"
+#include "ldemul.h"
+#include "ldfile.h"
+#include "ldmisc.h"
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldgram.h"
+
+static void gld${EMULATION_NAME}_before_parse PARAMS ((void));
+static boolean gld${EMULATION_NAME}_open_dynamic_archive
+ PARAMS ((const char *, search_dirs_type *, lang_input_statement_type *));
+static void gld${EMULATION_NAME}_after_open PARAMS ((void));
+static void gld${EMULATION_NAME}_check_needed
+ PARAMS ((lang_input_statement_type *));
+static void gld${EMULATION_NAME}_stat_needed
+ PARAMS ((lang_input_statement_type *));
+static boolean gld${EMULATION_NAME}_search_needed
+ PARAMS ((const char *, const char *));
+static boolean gld${EMULATION_NAME}_try_needed PARAMS ((const char *));
+static void gld${EMULATION_NAME}_before_allocation PARAMS ((void));
+static void gld${EMULATION_NAME}_find_statement_assignment
+ PARAMS ((lang_statement_union_type *));
+static void gld${EMULATION_NAME}_find_exp_assignment PARAMS ((etree_type *));
+static boolean gld${EMULATION_NAME}_place_orphan
+ PARAMS ((lang_input_statement_type *, asection *));
+static void gld${EMULATION_NAME}_place_section
+ PARAMS ((lang_statement_union_type *));
+static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
+
+static void
+gld${EMULATION_NAME}_before_parse()
+{
+ ldfile_output_architecture = bfd_arch_${ARCH};
+ config.dynamic_link = ${DYNAMIC_LINK-true};
+}
+
+/* Try to open a dynamic archive. This is where we know that ELF
+ dynamic libraries have an extension of .so. */
+
+static boolean
+gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry)
+ 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;
+
+ string = (char *) xmalloc (strlen (search->name)
+ + strlen (filename)
+ + strlen (arch)
+ + sizeof "/lib.so");
+
+ sprintf (string, "%s/lib%s%s.so", search->name, filename, arch);
+
+ if (! ldfile_try_open_bfd (string, entry))
+ {
+ free (string);
+ return false;
+ }
+
+ entry->filename = string;
+
+ /* We have found a dynamic object to include in the link. The ELF
+ backend linker will create a DT_NEEDED entry in the .dynamic
+ section naming this file. If this file includes a DT_SONAME
+ entry, it will be used. Otherwise, the ELF linker will just use
+ the name of the file. For an archive found by searching, like
+ this one, the DT_NEEDED entry should consist of just the name of
+ the file, without the path information used to find it. Note
+ that we only need to do this if we have a dynamic object; an
+ archive will never be referenced by a DT_NEEDED entry.
+
+ FIXME: This approach--using bfd_elf_set_dt_needed_name--is not
+ very pretty. I haven't been able to think of anything that is
+ pretty, though. */
+ if (bfd_check_format (entry->the_bfd, bfd_object)
+ && (entry->the_bfd->flags & DYNAMIC) != 0)
+ {
+ char *needed_name;
+
+ ASSERT (entry->is_archive && entry->search_dirs_flag);
+ needed_name = (char *) xmalloc (strlen (filename)
+ + strlen (arch)
+ + sizeof "lib.so");
+ sprintf (needed_name, "lib%s%s.so", filename, arch);
+ bfd_elf_set_dt_needed_name (entry->the_bfd, needed_name);
+ }
+
+ return true;
+}
+
+/* These variables are required to pass information back and forth
+ between after_open and check_needed and stat_needed. */
+
+static struct bfd_link_needed_list *global_needed;
+static struct stat global_stat;
+static boolean global_found;
+
+/* This is called after all the input files have been opened. */
+
+static void
+gld${EMULATION_NAME}_after_open ()
+{
+ struct bfd_link_needed_list *needed, *l;
+
+ /* We only need to worry about this when doing a final link. */
+ if (link_info.relocateable || link_info.shared)
+ return;
+
+ /* Get the list of files which appear in DT_NEEDED entries in
+ dynamic objects included in the link (often there will be none).
+ For each such file, we want to track down the corresponding
+ library, and include the symbol table in the link. This is what
+ the runtime dynamic linker will do. Tracking the files down here
+ permits one dynamic object to include another without requiring
+ special action by the person doing the link. Note that the
+ needed list can actually grow while we are stepping through this
+ loop. */
+ needed = bfd_elf_get_needed_list (output_bfd, &link_info);
+ for (l = needed; l != NULL; l = l->next)
+ {
+ struct bfd_link_needed_list *ll;
+ const char *lib_path;
+ size_t len;
+ search_dirs_type *search;
+
+ /* If we've already seen this file, skip it. */
+ for (ll = needed; ll != l; ll = ll->next)
+ if (strcmp (ll->name, l->name) == 0)
+ break;
+ if (ll != l)
+ continue;
+
+ /* See if this file was included in the link explicitly. */
+ global_needed = l;
+ global_found = false;
+ lang_for_each_input_file (gld${EMULATION_NAME}_check_needed);
+ if (global_found)
+ continue;
+
+ /* 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 linker script
+ LIB_SEARCH_DIRS. We do not search using the -L arguments. */
+ if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link,
+ l->name))
+ continue;
+ if (gld${EMULATION_NAME}_search_needed (command_line.rpath, l->name))
+ continue;
+ if (command_line.rpath_link == NULL
+ && command_line.rpath == NULL)
+ {
+ lib_path = (const char *) getenv ("LD_RUN_PATH");
+ if (gld${EMULATION_NAME}_search_needed (lib_path, l->name))
+ continue;
+ }
+EOF
+if [ "x${host_alias}" = "x${target_alias}" ] ; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ lib_path = (const char *) getenv ("LD_LIBRARY_PATH");
+ if (gld${EMULATION_NAME}_search_needed (lib_path, l->name))
+ continue;
+EOF
+fi
+cat >>e${EMULATION_NAME}.c <<EOF
+ len = strlen (l->name);
+ for (search = search_head; search != NULL; search = search->next)
+ {
+ char *filename;
+
+ if (search->cmdline)
+ continue;
+ filename = (char *) xmalloc (strlen (search->name) + len + 2);
+ sprintf (filename, "%s/%s", search->name, l->name);
+ if (gld${EMULATION_NAME}_try_needed (filename))
+ break;
+ free (filename);
+ }
+ 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 boolean
+gld${EMULATION_NAME}_search_needed (path, name)
+ const char *path;
+ const char *name;
+{
+ const char *s;
+ size_t len;
+
+ if (path == NULL || *path == '\0')
+ return false;
+ len = strlen (name);
+ while (1)
+ {
+ char *filename, *sset;
+
+ s = strchr (path, ':');
+ if (s == NULL)
+ s = path + strlen (path);
+
+ filename = (char *) xmalloc (s - path + len + 2);
+ if (s == path)
+ sset = filename;
+ else
+ {
+ memcpy (filename, path, s - path);
+ filename[s - path] = '/';
+ sset = filename + (s - path) + 1;
+ }
+ strcpy (sset, name);
+
+ if (gld${EMULATION_NAME}_try_needed (filename))
+ return true;
+
+ free (filename);
+
+ if (*s == '\0')
+ break;
+ path = s + 1;
+ }
+
+ return false;
+}
+
+/* This function is called for each possible name for a dynamic object
+ named by a DT_NEEDED entry. */
+
+static boolean
+gld${EMULATION_NAME}_try_needed (name)
+ const char *name;
+{
+ bfd *abfd;
+
+ abfd = bfd_openr (name, bfd_get_target (output_bfd));
+ if (abfd == NULL)
+ return false;
+ if (! bfd_check_format (abfd, bfd_object))
+ {
+ (void) bfd_close (abfd);
+ return false;
+ }
+ if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0)
+ {
+ (void) bfd_close (abfd);
+ return false;
+ }
+
+ /* We've found 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);
+ global_found = false;
+ lang_for_each_input_file (gld${EMULATION_NAME}_stat_needed);
+ if (global_found)
+ {
+ /* Return true to indicate that we found the file, even though
+ we aren't going to do anything with it. */
+ return true;
+ }
+
+ /* Tell the ELF backend that don't want the output file to have a
+ DT_NEEDED entry for this file. */
+ bfd_elf_set_dt_needed_name (abfd, "");
+
+ /* 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 an input file matches a DT_NEEDED entry by name. */
+
+static void
+gld${EMULATION_NAME}_check_needed (s)
+ lang_input_statement_type *s;
+{
+ if (s->filename != NULL
+ && strcmp (s->filename, global_needed->name) == 0)
+ global_found = true;
+ else if (s->search_dirs_flag
+ && s->filename != NULL
+ && strchr (global_needed->name, '/') == NULL)
+ {
+ const char *f;
+
+ f = strrchr (s->filename, '/');
+ if (f != NULL
+ && strcmp (f + 1, global_needed->name) == 0)
+ global_found = true;
+ }
+}
+
+/* See if an input file matches a DT_NEEDED entry by running stat on
+ the file. */
+
+static void
+gld${EMULATION_NAME}_stat_needed (s)
+ lang_input_statement_type *s;
+{
+ if (global_found)
+ return;
+ if (s->the_bfd != NULL)
+ {
+ struct stat st;
+
+ if (bfd_stat (s->the_bfd, &st) != 0)
+ einfo ("%P:%B: bfd_stat failed: %E\n", s->the_bfd);
+ else
+ {
+ if (st.st_dev == global_stat.st_dev
+ && st.st_ino == global_stat.st_ino)
+ global_found = true;
+ }
+ }
+}
+
+/* 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 ()
+{
+ const char *rpath;
+ asection *sinterp;
+
+ /* 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_elf32_size_dynamic_sections (output_bfd,
+ command_line.soname,
+ rpath,
+ command_line.export_dynamic,
+ &link_info,
+ &sinterp))
+ einfo ("%P%F: failed to set dynamic section sizes: %E\n");
+
+ /* Let the user override the dynamic linker we are using. */
+ if (command_line.interpreter != NULL
+ && sinterp != NULL)
+ {
+ sinterp->contents = (bfd_byte *) command_line.interpreter;
+ sinterp->_raw_size = strlen (command_line.interpreter) + 1;
+ }
+
+ /* Look for any sections named .gnu.warning. As a GNU extensions,
+ we treat such sections as containing warning messages. We print
+ out the warning message, and then zero out the section size so
+ that it does not get copied into the output file. */
+
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (is)
+ {
+ asection *s;
+ bfd_size_type sz;
+ char *msg;
+ boolean ret;
+
+ if (is->just_syms_flag)
+ continue;
+
+ s = bfd_get_section_by_name (is->the_bfd, ".gnu.warning");
+ if (s == NULL)
+ continue;
+
+ sz = bfd_section_size (is->the_bfd, s);
+ msg = 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 copying the
+ warning into the output file. */
+ s->_raw_size = 0;
+ }
+ }
+
+#if defined (TARGET_IS_elf32bmip) || defined (TARGET_IS_elf32lmip)
+ /* For MIPS ELF the .reginfo section requires special handling.
+ Each input section is 24 bytes, and the final output section must
+ also be 24 bytes. We handle this by clobbering all but the first
+ input section size to 0. The .reginfo section is handled
+ specially by the backend code anyhow. */
+ {
+ boolean found = false;
+ LANG_FOR_EACH_INPUT_STATEMENT (is)
+ {
+ asection *s;
+
+ if (is->just_syms_flag)
+ continue;
+
+ s = bfd_get_section_by_name (is->the_bfd, ".reginfo");
+ if (s == NULL)
+ continue;
+
+ if (! found)
+ {
+ found = true;
+ continue;
+ }
+
+ s->_raw_size = 0;
+ s->_cooked_size = 0;
+ }
+ }
+#endif
+}
+
+/* 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 (s)
+ lang_statement_union_type *s;
+{
+ 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 (exp)
+ etree_type *exp;
+{
+ struct bfd_link_hash_entry *h;
+
+ switch (exp->type.node_class)
+ {
+ case etree_provide:
+ h = bfd_link_hash_lookup (link_info.hash, exp->assign.dst,
+ false, false, false);
+ if (h == NULL)
+ break;
+
+ /* We call record_link_assignment even if the symbol is defined.
+ This is because if it is defined by a dynamic object, we
+ actually want to use the value defined by the linker script,
+ not the value from the dynamic object (because we are setting
+ symbols like etext). If the symbol is defined by a regular
+ object, then, as it happens, calling record_link_assignment
+ will do no harm. */
+
+ /* Fall through. */
+ case etree_assign:
+ if (strcmp (exp->assign.dst, ".") != 0)
+ {
+ if (! (bfd_elf32_record_link_assignment
+ (output_bfd, &link_info, exp->assign.dst,
+ exp->type.node_class == etree_provide ? true : false)))
+ einfo ("%P%F: failed to record assignment to %s: %E\n",
+ exp->assign.dst);
+ }
+ gld${EMULATION_NAME}_find_exp_assignment (exp->assign.src);
+ break;
+
+ case etree_binary:
+ gld${EMULATION_NAME}_find_exp_assignment (exp->binary.lhs);
+ gld${EMULATION_NAME}_find_exp_assignment (exp->binary.rhs);
+ break;
+
+ case etree_trinary:
+ gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs);
+ 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;
+ }
+}
+
+/* Place an orphan section. We use this to put random SHF_ALLOC
+ sections in the right segment. */
+
+static asection *hold_section;
+static lang_output_section_statement_type *hold_use;
+static lang_output_section_statement_type *hold_text;
+static lang_output_section_statement_type *hold_data;
+static lang_output_section_statement_type *hold_bss;
+static lang_output_section_statement_type *hold_rel;
+
+/*ARGSUSED*/
+static boolean
+gld${EMULATION_NAME}_place_orphan (file, s)
+ lang_input_statement_type *file;
+ asection *s;
+{
+ lang_output_section_statement_type *place;
+ asection *snew, **pps;
+ lang_statement_list_type *old;
+ lang_statement_list_type add;
+ etree_type *address;
+ const char *secname, *ps;
+ lang_output_section_statement_type *os;
+
+ if ((s->flags & SEC_ALLOC) == 0)
+ return false;
+
+ /* Look through the script to see where to place this section. */
+ hold_section = s;
+ hold_use = NULL;
+ lang_for_each_statement (gld${EMULATION_NAME}_place_section);
+
+ if (hold_use != NULL)
+ {
+ /* We have already placed a section with this name. */
+ wild_doit (&hold_use->children, s, hold_use, file);
+ return true;
+ }
+
+ secname = bfd_get_section_name (s->owner, s);
+
+ /* 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.shared
+ && ! link_info.relocateable
+ && strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0
+ && hold_text != NULL)
+ {
+ wild_doit (&hold_text->children, s, hold_text, file);
+ return true;
+ }
+
+ /* Decide which segment the section should go in based on the
+ section name and section flags. */
+ place = NULL;
+ if ((s->flags & SEC_HAS_CONTENTS) == 0
+ && hold_bss != NULL)
+ place = hold_bss;
+ else if ((s->flags & SEC_READONLY) == 0
+ && hold_data != NULL)
+ place = hold_data;
+ else if (strncmp (secname, ".rel", 4) == 0
+ && hold_rel != NULL)
+ place = hold_rel;
+ else if ((s->flags & SEC_READONLY) != 0
+ && hold_text != NULL)
+ place = hold_text;
+ if (place == NULL)
+ return false;
+
+ /* Create the section in the output file, and put it in the right
+ place. This shuffling is to make the output file look neater. */
+ snew = bfd_make_section (output_bfd, secname);
+ if (snew == NULL)
+ einfo ("%P%F: output format %s cannot represent section called %s\n",
+ output_bfd->xvec->name, secname);
+ if (place->bfd_section != NULL)
+ {
+ for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next)
+ ;
+ *pps = snew->next;
+ snew->next = place->bfd_section->next;
+ place->bfd_section->next = snew;
+ }
+
+ /* Start building a list of statements for this section. */
+ old = stat_ptr;
+ stat_ptr = &add;
+ lang_list_init (stat_ptr);
+
+ /* If the name of the section is representable in C, then create
+ symbols to mark the start and the end of the section. */
+ for (ps = secname; *ps != '\0'; ps++)
+ if (! isalnum (*ps) && *ps != '_')
+ break;
+ if (*ps == '\0' && config.build_constructors)
+ {
+ char *symname;
+
+ symname = (char *) xmalloc (ps - secname + sizeof "__start_");
+ sprintf (symname, "__start_%s", secname);
+ lang_add_assignment (exp_assop ('=', symname,
+ exp_nameop (NAME, ".")));
+ }
+
+ if (! link_info.relocateable)
+ address = NULL;
+ else
+ address = exp_intop ((bfd_vma) 0);
+
+ lang_enter_output_section_statement (secname, address, 0,
+ (bfd_vma) 0,
+ (etree_type *) NULL,
+ (etree_type *) NULL,
+ (etree_type *) NULL);
+
+ os = lang_output_section_statement_lookup (secname);
+ wild_doit (&os->children, s, os, file);
+
+ lang_leave_output_section_statement ((bfd_vma) 0, "*default*");
+ stat_ptr = &add;
+
+ if (*ps == '\0' && config.build_constructors)
+ {
+ char *symname;
+
+ symname = (char *) xmalloc (ps - secname + sizeof "__stop_");
+ sprintf (symname, "__stop_%s", secname);
+ lang_add_assignment (exp_assop ('=', symname,
+ exp_nameop (NAME, ".")));
+ }
+
+ /* Now stick the new statement list right after PLACE. */
+ *add.tail = place->header.next;
+ place->header.next = add.head;
+
+ stat_ptr = old;
+
+ return true;
+}
+
+static void
+gld${EMULATION_NAME}_place_section (s)
+ lang_statement_union_type *s;
+{
+ lang_output_section_statement_type *os;
+
+ if (s->header.type != lang_output_section_statement_enum)
+ return;
+
+ os = &s->output_section_statement;
+
+ if (strcmp (os->name, hold_section->name) == 0)
+ hold_use = os;
+
+ if (strcmp (os->name, ".text") == 0)
+ hold_text = os;
+ else if (strcmp (os->name, ".data") == 0)
+ hold_data = os;
+ else if (strcmp (os->name, ".bss") == 0)
+ hold_bss = os;
+ else if (hold_rel == NULL
+ && strncmp (os->name, ".rel", 4) == 0)
+ hold_rel = os;
+}
+
+static char *
+gld${EMULATION_NAME}_get_script(isfile)
+ int *isfile;
+EOF
+
+if test -n "$COMPILE_IN"
+then
+# Scripts compiled in.
+
+# sed commands to quote an ld script as a C string.
+sc='s/["\\]/\\&/g
+s/$/\\n\\/
+1s/^/"/
+$s/$/n"/
+'
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 0;
+
+ if (link_info.relocateable == true && config.build_constructors == true)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xu`;
+ else if (link_info.relocateable == true)
+ 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 if (link_info.shared)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xs`;
+ else
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.x`;
+}
+EOF
+
+else
+# Scripts read from the filesystem.
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 1;
+
+ if (link_info.relocateable == true && config.build_constructors == true)
+ return "ldscripts/${EMULATION_NAME}.xu";
+ else if (link_info.relocateable == true)
+ 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 if (link_info.shared)
+ return "ldscripts/${EMULATION_NAME}.xs";
+ else
+ return "ldscripts/${EMULATION_NAME}.x";
+}
+EOF
+
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
+{
+ gld${EMULATION_NAME}_before_parse,
+ syslib_default,
+ hll_default,
+ after_parse_default,
+ gld${EMULATION_NAME}_after_open,
+ after_allocation_default,
+ set_output_arch_default,
+ ldemul_default_target,
+ gld${EMULATION_NAME}_before_allocation,
+ gld${EMULATION_NAME}_get_script,
+ "${EMULATION_NAME}",
+ "${OUTPUT_FORMAT}",
+ NULL,
+ NULL,
+ gld${EMULATION_NAME}_open_dynamic_archive,
+ gld${EMULATION_NAME}_place_orphan
+};
+EOF
diff --git a/gnu/usr.bin/binutils/ld/emultempl/generic.em b/gnu/usr.bin/binutils/ld/emultempl/generic.em
new file mode 100644
index 00000000000..6b8e6758e31
--- /dev/null
+++ b/gnu/usr.bin/binutils/ld/emultempl/generic.em
@@ -0,0 +1,118 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+cat >e${EMULATION_NAME}.c <<EOF
+/* This file is is generated by a shell script. DO NOT EDIT! */
+
+/* emulate the original gld for the given ${EMULATION_NAME}
+ Copyright (C) 1991, 1993 Free Software Foundation, Inc.
+ Written by Steve Chamberlain steve@cygnus.com
+
+This file is part of GLD, the Gnu Linker.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+
+#include "ld.h"
+#include "ldmain.h"
+#include "ldemul.h"
+#include "ldfile.h"
+#include "ldmisc.h"
+
+static void gld${EMULATION_NAME}_before_parse PARAMS ((void));
+static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
+
+static void
+gld${EMULATION_NAME}_before_parse()
+{
+#ifndef TARGET_ /* I.e., if not generic. */
+ ldfile_output_architecture = bfd_arch_${ARCH};
+#endif /* not TARGET_ */
+}
+
+static char *
+gld${EMULATION_NAME}_get_script(isfile)
+ 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/stringify.sed"
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 0;
+
+ if (link_info.relocateable == true && config.build_constructors == true)
+ return
+EOF
+sed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c
+echo ' ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.c
+echo ' ; else if (!config.text_read_only) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c
+echo ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c
+echo ' ; else return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c
+echo '; }' >> e${EMULATION_NAME}.c
+
+else
+# Scripts read from the filesystem.
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 1;
+
+ if (link_info.relocateable == true && config.build_constructors == true)
+ return "ldscripts/${EMULATION_NAME}.xu";
+ else if (link_info.relocateable == true)
+ return "ldscripts/${EMULATION_NAME}.xr";
+ else if (!config.text_read_only)
+ return "ldscripts/${EMULATION_NAME}.xbn";
+ else if (!config.magic_demand_paged)
+ return "ldscripts/${EMULATION_NAME}.xn";
+ else
+ return "ldscripts/${EMULATION_NAME}.x";
+}
+EOF
+
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
+{
+ gld${EMULATION_NAME}_before_parse,
+ syslib_default,
+ hll_default,
+ after_parse_default,
+ after_open_default,
+ after_allocation_default,
+ set_output_arch_default,
+ ldemul_default_target,
+ before_allocation_default,
+ gld${EMULATION_NAME}_get_script,
+ "${EMULATION_NAME}",
+ "${OUTPUT_FORMAT}"
+};
+EOF
diff --git a/gnu/usr.bin/binutils/ld/emultempl/gld960.em b/gnu/usr.bin/binutils/ld/emultempl/gld960.em
new file mode 100644
index 00000000000..df998fb74a8
--- /dev/null
+++ b/gnu/usr.bin/binutils/ld/emultempl/gld960.em
@@ -0,0 +1,176 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+cat >e${EMULATION_NAME}.c <<EOF
+/* Copyright (C) 1991, 1993 Free Software Foundation, Inc.
+
+This file is part of GLD, the Gnu Linker.
+
+GLD 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 1, or (at your option)
+any later version.
+
+GLD 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 GLD; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * emulate the Intels port of gld
+ */
+
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libiberty.h"
+#include "bfdlink.h"
+
+#include "ld.h"
+#include "ldemul.h"
+#include "ldfile.h"
+#include "ldmisc.h"
+#include "ldmain.h"
+
+#ifdef GNU960
+
+static void
+gld960_before_parse()
+{
+ static char *env_variables[] = { "G960LIB", "G960BASE", 0 };
+ char **p;
+ char *env ;
+
+ for ( p = env_variables; *p; p++ ){
+ env = (char *) getenv(*p);
+ if (env) {
+ ldfile_add_library_path (concat (env,
+ "/lib/libbout",
+ (const char *) NULL),
+ false);
+ }
+ }
+ ldfile_output_architecture = bfd_arch_i960;
+}
+
+#else /* not GNU960 */
+
+static void gld960_before_parse()
+{
+ 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;
+}
+
+#endif /* GNU960 */
+
+
+static void
+gld960_set_output_arch()
+{
+ bfd_set_arch_mach(output_bfd, ldfile_output_architecture, bfd_mach_i960_core);
+}
+
+static char *
+gld960_choose_target()
+{
+#ifdef GNU960
+
+ output_filename = "b.out";
+ return bfd_make_targ_name(BFD_BOUT_FORMAT, 0);
+
+#else
+
+ char *from_outside = getenv(TARGET_ENVIRON);
+ output_filename = "b.out";
+
+ if (from_outside != (char *)NULL)
+ return from_outside;
+
+ return "b.out.little";
+
+#endif
+}
+
+static char *
+gld960_get_script(isfile)
+ int *isfile;
+EOF
+
+if test -n "$COMPILE_IN"
+then
+# Scripts compiled in.
+
+# sed commands to quote an ld script as a C string.
+sc='s/["\\]/\\&/g
+s/$/\\n\\/
+1s/^/"/
+$s/$/n"/
+'
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 0;
+
+ if (link_info.relocateable == true && config.build_constructors == true)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xu`;
+ else if (link_info.relocateable == true)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xr`;
+ else if (!config.text_read_only)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xbn`;
+ else if (!config.magic_demand_paged)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xn`;
+ else
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.x`;
+}
+EOF
+
+else
+# Scripts read from the filesystem.
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 1;
+
+ if (link_info.relocateable == true && config.build_constructors == true)
+ return "ldscripts/${EMULATION_NAME}.xu";
+ else if (link_info.relocateable == true)
+ return "ldscripts/${EMULATION_NAME}.xr";
+ else if (!config.text_read_only)
+ return "ldscripts/${EMULATION_NAME}.xbn";
+ else if (!config.magic_demand_paged)
+ return "ldscripts/${EMULATION_NAME}.xn";
+ else
+ return "ldscripts/${EMULATION_NAME}.x";
+}
+EOF
+
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+struct ld_emulation_xfer_struct ld_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",
+ ""
+};
+EOF
diff --git a/gnu/usr.bin/binutils/ld/emultempl/gld960c.em b/gnu/usr.bin/binutils/ld/emultempl/gld960c.em
new file mode 100644
index 00000000000..492d5d3d6ae
--- /dev/null
+++ b/gnu/usr.bin/binutils/ld/emultempl/gld960c.em
@@ -0,0 +1,177 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+cat >e${EMULATION_NAME}.c <<EOF
+/* Copyright (C) 1991, 1993 Free Software Foundation, Inc.
+
+This file is part of GLD, the Gnu Linker.
+
+GLD 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 1, or (at your option)
+any later version.
+
+GLD 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 GLD; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * emulate the Intels port of gld
+ */
+
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libiberty.h"
+#include "bfdlink.h"
+
+#include "ld.h"
+#include "ldemul.h"
+#include "ldfile.h"
+#include "ldmisc.h"
+#include "ldmain.h"
+
+#ifdef GNU960
+
+static void
+gld960_before_parse()
+{
+ static char *env_variables[] = { "G960LIB", "G960BASE", 0 };
+ char **p;
+ char *env ;
+
+ for ( p = env_variables; *p; p++ ){
+ env = (char *) getenv(*p);
+ if (env) {
+ ldfile_add_library_path (concat (env,
+ "/lib/libcoff",
+ (const char *) NULL),
+ false);
+ }
+ }
+ ldfile_output_architecture = bfd_arch_i960;
+}
+
+#else /* not GNU960 */
+
+static void gld960_before_parse()
+{
+ 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;
+}
+
+#endif /* GNU960 */
+
+
+static void
+gld960_set_output_arch()
+{
+ bfd_set_arch_mach(output_bfd, ldfile_output_architecture, bfd_mach_i960_core);
+}
+
+static char *
+gld960_choose_target()
+{
+#ifdef GNU960
+
+ output_filename = "b.out";
+ return bfd_make_targ_name(BFD_BOUT_FORMAT, 0);
+
+#else
+
+ char *from_outside = getenv(TARGET_ENVIRON);
+ output_filename = "b.out";
+
+ if (from_outside != (char *)NULL)
+ return from_outside;
+
+ return "coff-Intel-little";
+
+#endif
+}
+
+static char *
+gld960_get_script(isfile)
+ int *isfile;
+EOF
+
+if test -n "$COMPILE_IN"
+then
+# Scripts compiled in.
+
+# sed commands to quote an ld script as a C string.
+sc='s/["\\]/\\&/g
+s/$/\\n\\/
+1s/^/"/
+$s/$/n"/
+'
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 0;
+
+ if (link_info.relocateable == true && config.build_constructors == true)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xu`;
+ else if (link_info.relocateable == true)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xr`;
+ else if (!config.text_read_only)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xbn`;
+ else if (!config.magic_demand_paged)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xn`;
+ else
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.x`;
+}
+EOF
+
+else
+# Scripts read from the filesystem.
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 1;
+
+ if (link_info.relocateable == true && config.build_constructors == true)
+ return "ldscripts/${EMULATION_NAME}.xu";
+ else if (link_info.relocateable == true)
+ return "ldscripts/${EMULATION_NAME}.xr";
+ else if (!config.text_read_only)
+ return "ldscripts/${EMULATION_NAME}.xbn";
+ else if (!config.magic_demand_paged)
+ return "ldscripts/${EMULATION_NAME}.xn";
+ else
+ return "ldscripts/${EMULATION_NAME}.x";
+}
+EOF
+
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+struct ld_emulation_xfer_struct ld_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",
+ ""
+};
+EOF
diff --git a/gnu/usr.bin/binutils/ld/emultempl/hppaelf.em b/gnu/usr.bin/binutils/ld/emultempl/hppaelf.em
new file mode 100644
index 00000000000..57920174a8a
--- /dev/null
+++ b/gnu/usr.bin/binutils/ld/emultempl/hppaelf.em
@@ -0,0 +1,286 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+cat >e${EMULATION_NAME}.c <<EOF
+/* An emulation for HP PA-RISC ELF linkers.
+ Copyright (C) 1991, 1993 Free Software Foundation, Inc.
+ Written by Steve Chamberlain steve@cygnus.com
+
+This file is part of GLD, the Gnu Linker.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+
+#include "ld.h"
+#include "ldemul.h"
+#include "ldfile.h"
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldmisc.h"
+#include "ldmain.h"
+#include "ldctor.h"
+
+/* Section in which we build stubs. */
+static asection *stub_sec;
+static lang_input_statement_type *stub_file;
+
+
+/* FIXME. This doesn't belong here. */
+extern lang_statement_list_type file_chain;
+
+/* Perform some emulation specific initialization. For PA ELF we set
+ up the local label prefix and the output architecture. */
+
+static void
+hppaelf_before_parse ()
+{
+ link_info.lprefix = "L$";
+ link_info.lprefix_len = 2;
+
+ ldfile_output_architecture = bfd_arch_hppa;
+}
+
+/* Set the output architecture and machine. */
+
+static void
+hppaelf_set_output_arch()
+{
+ unsigned long machine = 0;
+
+ bfd_set_arch_mach (output_bfd, ldfile_output_architecture, machine);
+}
+
+/* This is called before the input files are opened. We create a new
+ fake input file to hold the stub section. */
+
+static void
+hppaelf_create_output_section_statements ()
+{
+ stub_file = lang_add_input_file ("linker stubs",
+ lang_input_file_is_fake_enum,
+ NULL);
+ stub_file->the_bfd = bfd_create ("linker stubs", output_bfd);
+ if (stub_file->the_bfd == NULL
+ || ! bfd_set_arch_mach (stub_file->the_bfd,
+ bfd_get_arch (output_bfd),
+ bfd_get_mach (output_bfd)))
+ {
+ einfo ("%X%P: can not create BFD %E\n");
+ return;
+ }
+
+ stub_sec = bfd_make_section_old_way (stub_file->the_bfd, ".text");
+ /* Don't set SEC_RELOC until we actually have relocations in this
+ section. */
+ if (stub_sec == NULL
+ || ! bfd_set_section_flags (stub_file->the_bfd, stub_sec,
+ (SEC_HAS_CONTENTS
+ | SEC_ALLOC
+ | SEC_LOAD
+ | SEC_CODE
+ | SEC_IN_MEMORY)))
+ {
+ einfo ("%X%P: can not create stub section: %E\n");
+ return;
+ }
+
+ ldlang_add_file (stub_file);
+}
+
+/* Walk all the lang statements splicing out any padding statements from
+ the list. */
+
+static void
+hppaelf_delete_padding_statements (s, prev)
+ lang_statement_union_type *s;
+ lang_statement_union_type **prev;
+{
+ lang_statement_union_type *sprev = NULL;
+ for (; s != NULL; s = s->next)
+ {
+ switch (s->header.type)
+ {
+
+ /* We want recursively walk these sections. */
+ case lang_constructors_statement_enum:
+ hppaelf_delete_padding_statements (constructor_list.head,
+ &constructor_list.head);
+ break;
+
+ case lang_output_section_statement_enum:
+ hppaelf_delete_padding_statements (s->output_section_statement.
+ children.head,
+ &s->output_section_statement.
+ children.head);
+ break;
+
+ /* Huh? What is a lang_wild_statement? */
+ case lang_wild_statement_enum:
+ hppaelf_delete_padding_statements (s->wild_statement.
+ children.head,
+ &s->wild_statement.
+ children.head);
+ break;
+
+ /* Here's what we are really looking for. Splice these out of
+ the list. */
+ case lang_padding_statement_enum:
+ if (sprev)
+ sprev->header.next = s->header.next;
+ else
+ **prev = *s;
+ break;
+
+ /* We don't care about these cases. */
+ case lang_data_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_address_statement_enum:
+ break;
+
+ default:
+ abort ();
+ break;
+ }
+ sprev = s;
+ }
+}
+
+/* Final emulation specific call. For the PA we use this opportunity
+ to build linker stubs. */
+
+static void
+hppaelf_finish ()
+{
+ /* Call into the BFD backend to do the real work. */
+ if (elf32_hppa_size_stubs (stub_file->the_bfd, output_bfd, &link_info)
+ == false)
+ {
+ einfo ("%X%P: can not size stub section: %E\n");
+ return;
+ }
+
+ /* If the size of the stub section is nonzero, then we need
+ to resize the sections, recompute the assignments, and finally
+ build the stubs. */
+ if (bfd_section_size (stub_file->the_bfd, stub_file->the_bfd->sections) != 0)
+ {
+ /* Delete all the padding statements, they're no longer valid. */
+ hppaelf_delete_padding_statements (stat_ptr->head, &stat_ptr->head);
+
+ /* Resize the sections. */
+ lang_size_sections (stat_ptr->head, abs_output_section,
+ &stat_ptr->head, 0, (bfd_vma) 0, false);
+
+ /* Redo special stuff. */
+ ldemul_after_allocation ();
+
+ /* Do the assignments again. */
+ lang_do_assignments (stat_ptr->head,
+ abs_output_section,
+ (fill_type) 0, (bfd_vma) 0);
+
+ /* Now build the linker stubs. */
+ if (elf32_hppa_build_stubs (stub_file->the_bfd, &link_info) == false)
+ {
+ einfo ("%X%P: can not build stubs: %E\n");
+ return;
+ }
+ }
+}
+
+/* The script itself gets inserted here. */
+
+static char *
+hppaelf_get_script(isfile)
+ int *isfile;
+EOF
+
+if test -n "$COMPILE_IN"
+then
+# Scripts compiled in.
+
+# sed commands to quote an ld script as a C string.
+sc='s/["\\]/\\&/g
+s/$/\\n\\/
+1s/^/"/
+$s/$/n"/
+'
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 0;
+
+ if (link_info.relocateable == true && config.build_constructors == true)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xu`;
+ else if (link_info.relocateable == true)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xr`;
+ else if (!config.text_read_only)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xbn`;
+ else if (!config.magic_demand_paged)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xn`;
+ else
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.x`;
+}
+EOF
+
+else
+# Scripts read from the filesystem.
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 1;
+
+ if (link_info.relocateable == true && config.build_constructors == true)
+ return "ldscripts/${EMULATION_NAME}.xu";
+ else if (link_info.relocateable == true)
+ return "ldscripts/${EMULATION_NAME}.xr";
+ else if (!config.text_read_only)
+ return "ldscripts/${EMULATION_NAME}.xbn";
+ else if (!config.magic_demand_paged)
+ return "ldscripts/${EMULATION_NAME}.xn";
+ else
+ return "ldscripts/${EMULATION_NAME}.x";
+}
+EOF
+
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+struct ld_emulation_xfer_struct ld_hppaelf_emulation =
+{
+ hppaelf_before_parse,
+ syslib_default,
+ hll_default,
+ after_parse_default,
+ after_open_default,
+ after_allocation_default,
+ hppaelf_set_output_arch,
+ ldemul_default_target,
+ before_allocation_default,
+ hppaelf_get_script,
+ "hppaelf",
+ "elf32-hppa",
+ hppaelf_finish,
+ hppaelf_create_output_section_statements,
+};
+EOF
diff --git a/gnu/usr.bin/binutils/ld/emultempl/linux.em b/gnu/usr.bin/binutils/ld/emultempl/linux.em
new file mode 100644
index 00000000000..1f9d37eec2b
--- /dev/null
+++ b/gnu/usr.bin/binutils/ld/emultempl/linux.em
@@ -0,0 +1,207 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+cat >e${EMULATION_NAME}.c <<EOF
+/* This file is is generated by a shell script. DO NOT EDIT! */
+
+/* Linux a.out emulation code for ${EMULATION_NAME}
+ Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc.
+ Written by Steve Chamberlain <sac@cygnus.com>
+ Linux support by Eric Youngdale <ericy@cais.cais.com>
+
+This file is part of GLD, the Gnu Linker.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+
+#include "ld.h"
+#include "ldmain.h"
+#include "ldemul.h"
+#include "ldfile.h"
+#include "ldmisc.h"
+#include "ldexp.h"
+#include "ldlang.h"
+
+static void gld${EMULATION_NAME}_before_parse PARAMS ((void));
+static boolean gld${EMULATION_NAME}_open_dynamic_archive
+ PARAMS ((const char *, search_dirs_type *, lang_input_statement_type *));
+static void gld${EMULATION_NAME}_find_address_statement
+ PARAMS ((lang_statement_union_type *));
+static void gld${EMULATION_NAME}_create_output_section_statements
+ PARAMS ((void));
+static void gld${EMULATION_NAME}_before_allocation PARAMS ((void));
+static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
+
+static void
+gld${EMULATION_NAME}_before_parse()
+{
+ ldfile_output_architecture = bfd_arch_${ARCH};
+ config.dynamic_link = true;
+}
+
+/* Try to open a dynamic archive. This is where we know that Linux
+ dynamic libraries have an extension of .sa. */
+
+static boolean
+gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry)
+ 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 (s)
+ 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 ()
+{
+ 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 ()
+{
+ if (link_info.relocateable)
+ return;
+
+ /* Let the backend work out the sizes of any sections required by
+ dynamic linking. */
+ if (! bfd_linux_size_dynamic_sections (output_bfd, &link_info))
+ einfo ("%P%F: failed to set dynamic section sizes: %E\n");
+}
+
+static char *
+gld${EMULATION_NAME}_get_script(isfile)
+ int *isfile;
+EOF
+
+if test -n "$COMPILE_IN"
+then
+# Scripts compiled in.
+
+# sed commands to quote an ld script as a C string.
+sc='s/["\\]/\\&/g
+s/$/\\n\\/
+1s/^/"/
+$s/$/n"/
+'
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 0;
+
+ if (link_info.relocateable == true && config.build_constructors == true)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xu`;
+ else if (link_info.relocateable == true)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xr`;
+ else if (!config.text_read_only)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xbn`;
+ else if (!config.magic_demand_paged)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xn`;
+ else
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.x`;
+}
+EOF
+
+else
+# Scripts read from the filesystem.
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 1;
+
+ if (link_info.relocateable == true && config.build_constructors == true)
+ return "ldscripts/${EMULATION_NAME}.xu";
+ else if (link_info.relocateable == true)
+ return "ldscripts/${EMULATION_NAME}.xr";
+ else if (!config.text_read_only)
+ return "ldscripts/${EMULATION_NAME}.xbn";
+ else if (!config.magic_demand_paged)
+ return "ldscripts/${EMULATION_NAME}.xn";
+ else
+ return "ldscripts/${EMULATION_NAME}.x";
+}
+EOF
+
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
+{
+ gld${EMULATION_NAME}_before_parse,
+ syslib_default,
+ hll_default,
+ after_parse_default,
+ after_open_default,
+ after_allocation_default,
+ set_output_arch_default,
+ ldemul_default_target,
+ gld${EMULATION_NAME}_before_allocation,
+ gld${EMULATION_NAME}_get_script,
+ "${EMULATION_NAME}",
+ "${OUTPUT_FORMAT}",
+ NULL,
+ gld${EMULATION_NAME}_create_output_section_statements,
+ gld${EMULATION_NAME}_open_dynamic_archive
+};
+EOF
diff --git a/gnu/usr.bin/binutils/ld/emultempl/lnk960.em b/gnu/usr.bin/binutils/ld/emultempl/lnk960.em
new file mode 100644
index 00000000000..8f6ad40c6c9
--- /dev/null
+++ b/gnu/usr.bin/binutils/ld/emultempl/lnk960.em
@@ -0,0 +1,323 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+cat >e${EMULATION_NAME}.c <<EOF
+/* intel coff loader emulation specific stuff
+ Copyright (C) 1991, 1993 Free Software Foundation, Inc.
+ Written by Steve Chamberlain steve@cygnus.com
+
+This file is part of GLD, the Gnu Linker.
+
+GLD is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GLD 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 GLD; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "libiberty.h"
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+
+/*#include "archures.h"*/
+#include "ld.h"
+#include "ldemul.h"
+#include "ldmisc.h"
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldfile.h"
+#include "ldmain.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(list, name)
+ 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 boolean had_hll = false;
+static boolean had_hll_name = false;
+
+static void
+lnk960_hll(name)
+ char *name;
+{
+ had_hll = true;
+ if (name != (char *)NULL) {
+ had_hll_name = true;
+ append(&hll_list_tail, name);
+ }
+}
+
+static void
+lnk960_syslib(name)
+ char *name;
+{
+ append(&syslib_list_tail,name);
+}
+
+
+#ifdef GNU960
+
+static void
+lnk960_before_parse()
+{
+ static char *env_variables[] = { "G960LIB", "G960BASE", 0 };
+ char **p;
+ char *env ;
+
+ for ( p = env_variables; *p; p++ ){
+ env = (char *) getenv(*p);
+ if (env) {
+ ldfile_add_library_path(concat(env,"/lib/libcoff",""), false);
+ }
+ }
+
+ env= (char *) getenv("I960BASE");
+ if ( env ) {
+ ldfile_add_library_path(concat(env,"/lib",""), false);
+ }
+
+ ldfile_output_architecture = bfd_arch_i960;
+ ldfile_output_machine = bfd_mach_i960_core;
+}
+
+#else /* not GNU960 */
+
+static void
+lnk960_before_parse()
+{
+ 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",""), false);
+ ldfile_output_architecture = bfd_arch_i960;
+ ldfile_output_machine = bfd_mach_i960_core;
+}
+
+#endif /* GNU960 */
+
+
+static void
+add_on(list, search)
+ 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()
+{
+ /* 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_before_allocation()
+{
+}
+
+static void
+lnk960_after_allocation()
+{
+ if (link_info.relocateable == false) {
+ 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_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" },
+
+ { 0, (char *) NULL }
+};
+
+static void
+lnk960_set_output_arch()
+{
+ /* 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(output_bfd, ldfile_output_architecture, ldfile_output_machine);
+}
+
+static char *
+lnk960_choose_target()
+{
+#ifdef GNU960
+
+ return bfd_make_targ_name(BFD_COFF_FORMAT, 0);
+
+#else
+
+ 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
+#endif
+
+}
+
+static char *
+lnk960_get_script(isfile)
+ int *isfile;
+EOF
+
+if test -n "$COMPILE_IN"
+then
+# Scripts compiled in.
+
+# sed commands to quote an ld script as a C string.
+sc='s/["\\]/\\&/g
+s/$/\\n\\/
+1s/^/"/
+$s/$/n"/
+'
+
+cat >>e${EMULATION_NAME}.c <<EOF
+ *isfile = 0;
+
+ if (link_info.relocateable == true && config.build_constructors == true)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xu`;
+ else if (link_info.relocateable == true)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xr`;
+ else if (!config.text_read_only)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xbn`;
+ else if (!config.magic_demand_paged)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xn`;
+ else
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.x`;
+}
+EOF
+
+else
+# Scripts read from the filesystem.
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 1;
+
+ if (link_info.relocateable == true && config.build_constructors == true)
+ return "ldscripts/${EMULATION_NAME}.xu";
+ else if (link_info.relocateable == true)
+ return "ldscripts/${EMULATION_NAME}.xr";
+ else if (!config.text_read_only)
+ return "ldscripts/${EMULATION_NAME}.xbn";
+ else if (!config.magic_demand_paged)
+ return "ldscripts/${EMULATION_NAME}.xn";
+ else
+ return "ldscripts/${EMULATION_NAME}.x";
+}
+EOF
+
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+struct ld_emulation_xfer_struct ld_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,
+ lnk960_before_allocation,
+ lnk960_get_script,
+ "lnk960",
+ ""
+};
+EOF
diff --git a/gnu/usr.bin/binutils/ld/emultempl/m88kbcs.em b/gnu/usr.bin/binutils/ld/emultempl/m88kbcs.em
new file mode 100644
index 00000000000..ebf58bec380
--- /dev/null
+++ b/gnu/usr.bin/binutils/ld/emultempl/m88kbcs.em
@@ -0,0 +1,119 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+cat >e${EMULATION_NAME}.c <<EOF
+/* This file is is generated by a shell script. DO NOT EDIT! */
+
+/* emulate the original gld for the given ${EMULATION_NAME}
+ Copyright (C) 1991, 1993 Free Software Foundation, Inc.
+ Written by Steve Chamberlain steve@cygnus.com
+
+This file is part of GLD, the Gnu Linker.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+
+#include "ld.h"
+#include "ldemul.h"
+#include "ldfile.h"
+#include "ldmisc.h"
+#include "ldmain.h"
+
+static void
+gld${EMULATION_NAME}_before_parse()
+{
+ link_info.lprefix = "@";
+ link_info.lprefix_len = 1;
+
+ ldfile_output_architecture = bfd_arch_${ARCH};
+}
+
+static char *
+gld${EMULATION_NAME}_get_script(isfile)
+ int *isfile;
+EOF
+
+if test -n "$COMPILE_IN"
+then
+# Scripts compiled in.
+
+# sed commands to quote an ld script as a C string.
+sc='s/["\\]/\\&/g
+s/$/\\n\\/
+1s/^/"/
+$s/$/n"/
+'
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 0;
+
+ if (link_info.relocateable == true && config.build_constructors == true)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xu`;
+ else if (link_info.relocateable == true)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xr`;
+ else if (!config.text_read_only)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xbn`;
+ else if (!config.magic_demand_paged)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xn`;
+ else
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.x`;
+}
+EOF
+
+else
+# Scripts read from the filesystem.
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 1;
+
+ if (link_info.relocateable == true && config.build_constructors == true)
+ return "ldscripts/${EMULATION_NAME}.xu";
+ else if (link_info.relocateable == true)
+ return "ldscripts/${EMULATION_NAME}.xr";
+ else if (!config.text_read_only)
+ return "ldscripts/${EMULATION_NAME}.xbn";
+ else if (!config.magic_demand_paged)
+ return "ldscripts/${EMULATION_NAME}.xn";
+ else
+ return "ldscripts/${EMULATION_NAME}.x";
+}
+EOF
+
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
+{
+ gld${EMULATION_NAME}_before_parse,
+ syslib_default,
+ hll_default,
+ after_parse_default,
+ after_open_default,
+ after_allocation_default,
+ set_output_arch_default,
+ ldemul_default_target,
+ before_allocation_default,
+ gld${EMULATION_NAME}_get_script,
+ "${EMULATION_NAME}",
+ "${OUTPUT_FORMAT}"
+};
+EOF
diff --git a/gnu/usr.bin/binutils/ld/emultempl/mipsecoff.em b/gnu/usr.bin/binutils/ld/emultempl/mipsecoff.em
new file mode 100644
index 00000000000..7ceb6e07b8a
--- /dev/null
+++ b/gnu/usr.bin/binutils/ld/emultempl/mipsecoff.em
@@ -0,0 +1,229 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+cat >e${EMULATION_NAME}.c <<EOF
+/* This file is is generated by a shell script. DO NOT EDIT! */
+
+/* Handle embedded relocs for MIPS.
+ Copyright 1994 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor <ian@cygnus.com> based on generic.em.
+
+This file is part of GLD, the Gnu Linker.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+
+#include "ld.h"
+#include "ldmain.h"
+#include "ldemul.h"
+#include "ldfile.h"
+#include "ldmisc.h"
+
+static void gld${EMULATION_NAME}_before_parse PARAMS ((void));
+static void gld${EMULATION_NAME}_after_open PARAMS ((void));
+static void check_sections PARAMS ((bfd *, asection *, PTR));
+static void gld${EMULATION_NAME}_after_allocation PARAMS ((void));
+static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
+
+static void
+gld${EMULATION_NAME}_before_parse()
+{
+#ifndef TARGET_ /* I.e., if not generic. */
+ ldfile_output_architecture = bfd_arch_${ARCH};
+#endif /* not TARGET_ */
+}
+
+/* This function is run after all the input files have been opened.
+ We create a .rel.sdata section for each input file with a non zero
+ .sdata section. The BFD backend will fill in these sections with
+ magic numbers which can be used to relocate the data section at run
+ time. This will only do the right thing if all the input files
+ have been compiled using -membedded-pic. */
+
+static void
+gld${EMULATION_NAME}_after_open ()
+{
+ bfd *abfd;
+
+ if (! command_line.embedded_relocs
+ || link_info.relocateable)
+ return;
+
+ for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link_next)
+ {
+ asection *datasec;
+
+ datasec = bfd_get_section_by_name (abfd, ".sdata");
+
+ /* Note that we assume that the reloc_count field has already
+ been set up. We could call bfd_get_reloc_upper_bound, but
+ that returns the size of a memory buffer rather than a reloc
+ count. We do not want to call bfd_canonicalize_reloc,
+ because although it would always work it would force us to
+ read in the relocs into BFD canonical form, which would waste
+ a significant amount of time and memory. */
+ if (datasec != NULL && datasec->reloc_count > 0)
+ {
+ asection *relsec;
+
+ relsec = bfd_make_section (abfd, ".rel.sdata");
+ if (relsec == NULL
+ || ! bfd_set_section_flags (abfd, relsec,
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY))
+ || ! bfd_set_section_alignment (abfd, relsec, 2)
+ || ! bfd_set_section_size (abfd, relsec,
+ datasec->reloc_count * 4))
+ einfo ("%F%B: can not create .rel.sdata section: %E");
+ }
+
+ /* Double check that all other data sections are empty, as is
+ required for embedded PIC code. */
+ bfd_map_over_sections (abfd, check_sections, (PTR) datasec);
+ }
+}
+
+/* Check that of the data sections, only the .sdata section has
+ relocs. This is called via bfd_map_over_sections. */
+
+static void
+check_sections (abfd, sec, sdatasec)
+ bfd *abfd;
+ asection *sec;
+ PTR sdatasec;
+{
+ if ((bfd_get_section_flags (abfd, sec) & SEC_CODE) == 0
+ && sec != (asection *) sdatasec
+ && sec->reloc_count != 0)
+ einfo ("%P%X: section %s has relocs; can not use --embedded-relocs",
+ 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 ()
+{
+ bfd *abfd;
+
+ if (! command_line.embedded_relocs
+ || link_info.relocateable)
+ return;
+
+ for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link_next)
+ {
+ asection *datasec, *relsec;
+ char *errmsg;
+
+ datasec = bfd_get_section_by_name (abfd, ".sdata");
+
+ if (datasec == NULL || datasec->reloc_count == 0)
+ continue;
+
+ relsec = bfd_get_section_by_name (abfd, ".rel.sdata");
+ ASSERT (relsec != NULL);
+
+ if (! bfd_mips_ecoff_create_embedded_relocs (abfd, &link_info,
+ datasec, relsec,
+ &errmsg))
+ {
+ if (errmsg == NULL)
+ einfo ("%B%X: can not create runtime reloc information: %E",
+ abfd);
+ else
+ einfo ("%X%B: can not create runtime reloc information: %s",
+ abfd, errmsg);
+ }
+ }
+}
+
+static char *
+gld${EMULATION_NAME}_get_script(isfile)
+ 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/stringify.sed"
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 0;
+
+ if (link_info.relocateable == true && config.build_constructors == true)
+ return
+EOF
+sed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c
+echo ' ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.c
+echo ' ; else if (!config.text_read_only) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c
+echo ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c
+echo ' ; else return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c
+echo '; }' >> e${EMULATION_NAME}.c
+
+else
+# Scripts read from the filesystem.
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 1;
+
+ if (link_info.relocateable == true && config.build_constructors == true)
+ return "ldscripts/${EMULATION_NAME}.xu";
+ else if (link_info.relocateable == true)
+ return "ldscripts/${EMULATION_NAME}.xr";
+ else if (!config.text_read_only)
+ return "ldscripts/${EMULATION_NAME}.xbn";
+ else if (!config.magic_demand_paged)
+ return "ldscripts/${EMULATION_NAME}.xn";
+ else
+ return "ldscripts/${EMULATION_NAME}.x";
+}
+EOF
+
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
+{
+ gld${EMULATION_NAME}_before_parse,
+ syslib_default,
+ hll_default,
+ after_parse_default,
+ gld${EMULATION_NAME}_after_open,
+ gld${EMULATION_NAME}_after_allocation,
+ set_output_arch_default,
+ ldemul_default_target,
+ before_allocation_default,
+ gld${EMULATION_NAME}_get_script,
+ "${EMULATION_NAME}",
+ "${OUTPUT_FORMAT}"
+};
+EOF
diff --git a/gnu/usr.bin/binutils/ld/emultempl/pe.em b/gnu/usr.bin/binutils/ld/emultempl/pe.em
new file mode 100644
index 00000000000..3e40d78ddb0
--- /dev/null
+++ b/gnu/usr.bin/binutils/ld/emultempl/pe.em
@@ -0,0 +1,518 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+cat >e${EMULATION_NAME}.c <<EOF
+/* 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. */
+
+
+/* This file is part of GLD, the Gnu Linker.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "getopt.h"
+#include "ld.h"
+#include "ld.h"
+#include "ldmain.h"
+#include "ldgram.h"
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldemul.h"
+#include "ldlex.h"
+#include "ldmisc.h"
+#include "ldctor.h"
+#include "ldfile.h"
+#include "coff/internal.h"
+#include "../bfd/libcoff.h"
+
+#define TARGET_IS_${EMULATION_NAME}
+
+static void gld_${EMULATION_NAME}_before_parse PARAMS ((void));
+static char *gld_${EMULATION_NAME}_get_script PARAMS ((int *isfile));
+
+
+static struct internal_extra_pe_aouthdr pe;
+static int dll;
+
+static void
+gld_${EMULATION_NAME}_before_parse()
+{
+ ldfile_output_architecture = bfd_arch_${ARCH};
+}
+
+
+/* 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 struct option longopts[] = {
+ /* 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}
+ };
+
+
+/* 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__"},
+ 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__", 0x100000),
+ 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),
+ 0
+};
+
+
+static void
+set_pe_name (name, val)
+ 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 ()
+{
+ int i;
+ static struct
+ {
+ char *name ;
+ int value;
+ }
+ v[] =
+ {
+ {"native", 1},
+ {"windows",2},
+ {"console",3},
+ {"os2",5},
+ {"posix", 7},
+ {0,0}
+ };
+
+ for (i = 0; v[i].name; i++)
+ {
+ if (!strcmp (optarg, v[i].name))
+ {
+ set_pe_name ("__subsystem__", v[i].value);
+ return;
+ }
+ }
+ einfo ("%P%F: invalid subsystem type %s\n", optarg);
+}
+
+
+
+static void
+set_pe_value (name)
+ char *name;
+
+{
+ char *end;
+ set_pe_name (name, strtoul (optarg, &end, 16));
+ if (end == optarg)
+ {
+ einfo ("%P%F: invalid hex number for PE parameter '%s'\n", optarg);
+ }
+
+ optarg = end;
+}
+
+static void
+set_pe_stack_heap (resname, comname)
+ char *resname;
+ char *comname;
+{
+ char *begin_commit;
+ char *end;
+
+ 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 int
+gld_${EMULATION_NAME}_parse_args(argc, argv)
+ int argc;
+ char **argv;
+{
+ int longind;
+ int optc;
+ int prevoptind = optind;
+ int prevopterr = opterr;
+ int wanterror;
+ static int lastoptind = -1;
+
+ if (lastoptind != optind)
+ opterr = 0;
+ wanterror = opterr;
+
+ lastoptind = optind;
+
+ optc = getopt_long_only (argc, argv, "-", longopts, &longind);
+ opterr = prevopterr;
+
+ switch (optc)
+ {
+ default:
+ if (wanterror)
+ xexit (1);
+ optind = prevoptind;
+ return 0;
+
+ case OPTION_BASE_FILE:
+ link_info.base_file = (PTR) 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 ("__heap_reserve__", "__heap_commit__");
+ break;
+ case OPTION_STACK:
+ set_pe_stack_heap ("__stack_reserve__", "__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 1;
+}
+
+static void
+gld_${EMULATION_NAME}_set_symbols()
+{
+ /* Run through and invent symbols for all the
+ names and insert the defaults. */
+ int j;
+ lang_statement_list_type *save;
+
+ if (!init[IMAGEBASEOFF].inited)
+ init[IMAGEBASEOFF].value = init[DLLOFF].value
+ ? NT_DLL_IMAGE_BASE : NT_EXE_IMAGE_BASE;
+
+ /* Glue the assignments into the abs section */
+ save=stat_ptr;
+
+ stat_ptr = &(abs_output_section->children);
+ for (j = 0; init[j].ptr; j++)
+ {
+ long val = init[j].value;
+ lang_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;
+ else abort();
+ }
+ /* Restore the pointer. */
+ stat_ptr = save;
+
+ if (pe.FileAlignment >
+ pe.SectionAlignment)
+ {
+ einfo ("%P: warning, file alignment > section alignment.\n");
+ }
+}
+
+static void
+gld_${EMULATION_NAME}_after_open()
+{
+ /* Pass the wacky PE command line options into the output bfd */
+ struct internal_extra_pe_aouthdr *i;
+ if (!coff_data(output_bfd)->pe)
+ {
+ einfo ("%F%P: PE operations on non PE file.\n");
+ }
+
+ pe_data(output_bfd)->pe_opthdr = pe;
+ pe_data(output_bfd)->dll = init[DLLOFF].value;
+
+}
+
+/* Callback function for qsort in sort_sections. */
+
+static int sfunc (a, b)
+void *a;
+void *b;
+{
+ lang_statement_union_type **ra = a;
+ lang_statement_union_type **rb = b;
+ return strcmp ((*ra)->input_section.ifile->filename,
+ (*rb)->input_section.ifile->filename);
+}
+
+/* Sort the input sections of archives into filename order. */
+
+static void
+sort_sections (s)
+ lang_statement_union_type *s;
+{
+ for (; s ; s = s->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;
+
+ /* Sort any children in the same archive. Run through all
+ the children of this wild statement, when an
+ input_section in an archive is found, scan forward to
+ find all input_sections which are in the same archive.
+ Sort them by their filename and then re-thread the
+ pointer chain. */
+
+ while (*p)
+ {
+ lang_statement_union_type *start = *p;
+ if (start->header.type != lang_input_section_enum
+ || !start->input_section.ifile->the_bfd->my_archive)
+ p = &(start->header.next);
+ else
+ {
+ lang_statement_union_type **vec;
+ lang_statement_union_type *end;
+ lang_statement_union_type *np;
+ int count;
+ int i;
+
+ for (end = start, count = 0;
+ end && end->header.type == lang_input_section_enum
+ && (end->input_section.ifile->the_bfd->my_archive
+ == start->input_section.ifile->the_bfd->my_archive);
+ end = end->next)
+ count++;
+
+ np = end;
+
+ vec = (lang_statement_union_type **)
+ alloca (count * sizeof (lang_statement_union_type *));
+
+ for (end = start, i = 0; i < count; i++, end = end->next)
+ vec[i] = end;
+
+ qsort (vec, count, sizeof (vec[0]), sfunc);
+
+ /* Fill in the next pointers again. */
+ *p = vec[0];
+ for (i = 0; i < count - 1; i++)
+ vec[i]->header.next = vec[i + 1];
+ vec[i]->header.next = np;
+ p = &(vec[i]->header.next);
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+gld_${EMULATION_NAME}_before_allocation()
+{
+ extern lang_statement_list_type *stat_ptr;
+
+#ifdef TARGET_IS_ppcpe
+ /* Here we rummage through the found bfds to collect toc information */
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (is)
+ {
+ ppc_process_before_allocation(is->the_bfd, &link_info);
+ }
+ }
+
+ /* We have seen it all. Allocate it, and carry on */
+ ppc_allocate_toc_section (&link_info);
+#endif
+
+ sort_sections (*stat_ptr);
+}
+
+static char *
+gld_${EMULATION_NAME}_get_script(isfile)
+ int *isfile;
+EOF
+# Scripts compiled in.
+# sed commands to quote an ld script as a C string.
+sc="-f ${srcdir}/emultempl/stringify.sed"
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 0;
+
+ if (link_info.relocateable == true && config.build_constructors == true)
+ return
+EOF
+sed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c
+echo ' ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.c
+echo ' ; else if (!config.text_read_only) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c
+echo ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c
+echo ' ; else return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c
+echo '; }' >> e${EMULATION_NAME}.c
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+
+
+struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
+{
+ gld_${EMULATION_NAME}_before_parse,
+ syslib_default,
+ hll_default,
+ after_parse_default,
+ gld_${EMULATION_NAME}_after_open,
+ after_allocation_default,
+ set_output_arch_default,
+ ldemul_default_target,
+ gld_${EMULATION_NAME}_before_allocation,
+ gld_${EMULATION_NAME}_get_script,
+ "${EMULATION_NAME}",
+ "${OUTPUT_FORMAT}",
+ NULL, /* finish */
+ NULL, /* create output section statements */
+ NULL, /* open dynamic archive */
+ NULL, /* place orphan */
+ gld_${EMULATION_NAME}_set_symbols,
+ gld_${EMULATION_NAME}_parse_args
+};
+EOF
+
diff --git a/gnu/usr.bin/binutils/ld/emultempl/stringify.sed b/gnu/usr.bin/binutils/ld/emultempl/stringify.sed
new file mode 100644
index 00000000000..a526d3ffc4c
--- /dev/null
+++ b/gnu/usr.bin/binutils/ld/emultempl/stringify.sed
@@ -0,0 +1,4 @@
+s/["\\]/\\&/g
+s/$/\\n\\/
+1 s/^/"/
+$ s/$/n"/
diff --git a/gnu/usr.bin/binutils/ld/emultempl/sunos.em b/gnu/usr.bin/binutils/ld/emultempl/sunos.em
new file mode 100644
index 00000000000..abcc9739279
--- /dev/null
+++ b/gnu/usr.bin/binutils/ld/emultempl/sunos.em
@@ -0,0 +1,969 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+cat >e${EMULATION_NAME}.c <<EOF
+/* This file is is generated by a shell script. DO NOT EDIT! */
+
+/* SunOS emulation code for ${EMULATION_NAME}
+ Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc.
+ Written by Steve Chamberlain <sac@cygnus.com>
+ SunOS shared library support by Ian Lance Taylor <ian@cygnus.com>
+
+This file is part of GLD, the Gnu Linker.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+
+#include "ld.h"
+#include "ldmain.h"
+#include "ldemul.h"
+#include "ldfile.h"
+#include "ldmisc.h"
+#include "ldexp.h"
+#include "ldlang.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}_before_parse PARAMS ((void));
+static void gld${EMULATION_NAME}_create_output_section_statements
+ PARAMS ((void));
+static void gld${EMULATION_NAME}_find_so
+ PARAMS ((lang_input_statement_type *));
+static char *gld${EMULATION_NAME}_search_dir
+ PARAMS ((const char *, const char *, boolean *));
+static void gld${EMULATION_NAME}_after_open PARAMS ((void));
+static void gld${EMULATION_NAME}_check_needed
+ PARAMS ((lang_input_statement_type *));
+static boolean gld${EMULATION_NAME}_search_needed
+ PARAMS ((const char *, const char *));
+static boolean gld${EMULATION_NAME}_try_needed
+ PARAMS ((const char *, const char *));
+static void gld${EMULATION_NAME}_before_allocation PARAMS ((void));
+static void gld${EMULATION_NAME}_find_assignment
+ PARAMS ((lang_statement_union_type *));
+static void gld${EMULATION_NAME}_find_exp_assignment PARAMS ((etree_type *));
+static void gld${EMULATION_NAME}_count_need
+ PARAMS ((lang_input_statement_type *));
+static void gld${EMULATION_NAME}_set_need
+ PARAMS ((lang_input_statement_type *));
+static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
+
+static void
+gld${EMULATION_NAME}_before_parse()
+{
+ ldfile_output_architecture = bfd_arch_${ARCH};
+ config.dynamic_link = true;
+}
+
+/* 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 ()
+{
+ 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 (inp)
+ lang_input_statement_type *inp;
+{
+ search_dirs_type *search;
+ char *found;
+ char *alc;
+ struct stat st;
+
+ if (! inp->search_dirs_flag
+ || ! inp->is_archive
+ || ! inp->dynamic)
+ return;
+
+ ASSERT (strncmp (inp->local_sym_name, "-l", 2) == 0);
+
+ for (search = search_head; search != NULL; search = search->next)
+ {
+ 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, ".so.")[2] = 'a';
+ if (stat (alc, &st) == 0)
+ {
+ lang_input_statement_type *sa;
+ char *a;
+
+ /* Add the .sa file to the statement list just after the .so
+ file. This is really a hack. */
+ sa = ((lang_input_statement_type *)
+ xmalloc (sizeof (lang_input_statement_type)));
+ sa->header.next = inp->header.next;
+ sa->header.type = lang_input_statement_enum;
+ a = (char *) xmalloc (strlen (alc) + 1);
+ strcpy (a, alc);
+ sa->filename = a;
+ sa->local_sym_name = a;
+ sa->the_bfd = NULL;
+ sa->asymbols = NULL;
+ sa->symbol_count = 0;
+ sa->next = NULL;
+ sa->next_real_file = inp->next_real_file;
+ sa->is_archive = false;
+ sa->search_dirs_flag = false;
+ sa->just_syms_flag = false;
+ sa->loaded = false;
+ sa->real = true;
+ sa->complained = false;
+
+ /* Put the new statement next on the list of statements and next
+ on the list of input files. */
+ 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 (dirname, filename, found_static)
+ const char *dirname;
+ const char *filename;
+ 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;
+
+ *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;
+
+ while ((entry = readdir (dir)) != NULL)
+ {
+ int found_maj, found_min;
+
+ if (strncmp (entry->d_name, "lib", 3) != 0
+ || strncmp (entry->d_name + 3, filename, len) != 0)
+ continue;
+
+ if (dot == NULL
+ && strcmp (entry->d_name + 3 + len, ".a") == 0)
+ {
+ *found_static = true;
+ continue;
+ }
+
+ if (strncmp (entry->d_name + 3 + len, ".so", 3) != 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;
+
+ /* 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 boolean global_found;
+
+/* This is called after all the input files have been opened. */
+
+static void
+gld${EMULATION_NAME}_after_open ()
+{
+ struct bfd_link_needed_list *needed, *l;
+
+ /* We only need to worry about this when doing a final link. */
+ if (link_info.relocateable || link_info.shared)
+ return;
+
+ /* Get the list of files which appear in ld_need entries in dynamic
+ objects included in the link. For each such file, we want to
+ track down the corresponding library, and include the symbol
+ table in the link. This is what the runtime dynamic linker will
+ do. Tracking the files down here permits one dynamic object to
+ include another without requiring special action by the person
+ doing the link. Note that the needed list can actually grow
+ while we are stepping through this loop. */
+ needed = bfd_sunos_get_needed_list (output_bfd, &link_info);
+ for (l = needed; l != NULL; l = l->next)
+ {
+ struct bfd_link_needed_list *ll;
+ const char *lname;
+ const char *lib_path;
+ search_dirs_type *search;
+
+ lname = l->name;
+
+ /* If we've already seen this file, skip it. */
+ for (ll = needed; ll != l; ll = ll->next)
+ if (strcmp (ll->name, lname) == 0)
+ break;
+ if (ll != l)
+ continue;
+
+ /* See if this file was included in the link explicitly. */
+ global_needed = l;
+ global_found = false;
+ lang_for_each_input_file (gld${EMULATION_NAME}_check_needed);
+ if (global_found)
+ continue;
+
+ if (strncmp (lname, "-l", 2) != 0)
+ {
+ bfd *abfd;
+
+ abfd = bfd_openr (lname, bfd_get_target (output_bfd));
+ if (abfd != NULL)
+ {
+ if (! bfd_check_format (abfd, bfd_object))
+ {
+ (void) bfd_close (abfd);
+ abfd = NULL;
+ }
+ }
+ if (abfd != NULL)
+ {
+ if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0)
+ {
+ (void) bfd_close (abfd);
+ abfd = NULL;
+ }
+ }
+ if (abfd != NULL)
+ {
+ /* We've found the needed dynamic object. */
+ if (! bfd_link_add_symbols (abfd, &link_info))
+ einfo ("%F%B: could not read symbols: %E\n", abfd);
+ }
+ else
+ {
+ einfo ("%P: warning: %s, needed by %B, not found\n",
+ lname, l->by);
+ }
+
+ continue;
+ }
+
+ lname += 2;
+
+ /* We want to search for the file in the same way that the
+ dynamic linker will search. That means that we want to use
+ rpath_link, rpath or -L, then the environment variable
+ LD_LIBRARY_PATH (native only), then (if rpath was used) the
+ linker script LIB_SEARCH_DIRS. */
+ if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link,
+ lname))
+ continue;
+ if (command_line.rpath != NULL)
+ {
+ if (gld${EMULATION_NAME}_search_needed (command_line.rpath, lname))
+ continue;
+ }
+ else
+ {
+ for (search = search_head; search != NULL; search = search->next)
+ if (gld${EMULATION_NAME}_try_needed (search->name, lname))
+ break;
+ if (search != NULL)
+ continue;
+ }
+EOF
+if [ "x${host_alias}" = "x${target_alias}" ] ; then
+cat >>e${EMULATION_NAME}.c <<EOF
+ lib_path = (const char *) getenv ("LD_LIBRARY_PATH");
+ if (gld${EMULATION_NAME}_search_needed (lib_path, lname))
+ continue;
+EOF
+fi
+cat >>e${EMULATION_NAME}.c <<EOF
+ if (command_line.rpath != NULL)
+ {
+ for (search = search_head; search != NULL; search = search->next)
+ {
+ if (search->cmdline)
+ continue;
+ if (gld${EMULATION_NAME}_try_needed (search->name, lname))
+ break;
+ }
+ if (search != NULL)
+ continue;
+ }
+
+ einfo ("%P: warning: %s, needed by %B, not found\n",
+ l->name, l->by);
+ }
+}
+
+/* Search for a needed file in a path. */
+
+static boolean
+gld${EMULATION_NAME}_search_needed (path, name)
+ 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 boolean
+gld${EMULATION_NAME}_try_needed (dir, name)
+ const char *dir;
+ const char *name;
+{
+ char *file;
+ char *alc;
+ boolean ignore;
+ bfd *abfd;
+
+ file = gld${EMULATION_NAME}_search_dir (dir, name, &ignore);
+ if (file == NULL)
+ return false;
+
+ alc = (char *) xmalloc (strlen (dir) + strlen (file) + 2);
+ sprintf (alc, "%s/%s", dir, file);
+ free (file);
+ abfd = bfd_openr (alc, bfd_get_target (output_bfd));
+ if (abfd == NULL)
+ return false;
+ if (! bfd_check_format (abfd, bfd_object))
+ {
+ (void) bfd_close (abfd);
+ return false;
+ }
+ if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0)
+ {
+ (void) bfd_close (abfd);
+ return false;
+ }
+
+ /* We've found the needed dynamic object. */
+
+ /* Add this file into the symbol table. */
+ if (! bfd_link_add_symbols (abfd, &link_info))
+ einfo ("%F%B: could not read symbols: %E\n", abfd);
+
+ return true;
+}
+
+/* See if we have already included a needed object in the link. This
+ does not have to be precise, as it does no harm to include a
+ dynamic object more than once. */
+
+static void
+gld${EMULATION_NAME}_check_needed (s)
+ lang_input_statement_type *s;
+{
+ if (s->filename == NULL)
+ return;
+ if (strncmp (global_needed->name, "-l", 2) != 0)
+ {
+ if (strcmp (s->filename, global_needed->name) == 0)
+ global_found = true;
+ }
+ else
+ {
+ const char *sname, *lname;
+ const char *sdot, *ldot;
+ int lmaj, lmin, smaj, smin;
+
+ lname = global_needed->name + 2;
+
+ sname = strrchr (s->filename, '/');
+ if (sname == NULL)
+ sname = s->filename;
+ else
+ ++sname;
+
+ if (strncmp (sname, "lib", 3) != 0)
+ return;
+ sname += 3;
+
+ ldot = strchr (lname, '.');
+ if (ldot == NULL)
+ ldot = lname + strlen (lname);
+
+ sdot = strstr (sname, ".so.");
+ if (sdot == NULL)
+ return;
+
+ if (sdot - sname != ldot - lname
+ || strncmp (lname, sname, sdot - sname) != 0)
+ return;
+
+ lmaj = lmin = -1;
+ sscanf (ldot, ".%d.%d", &lmaj, &lmin);
+ smaj = smin = -1;
+ sscanf (sdot, ".so.%d.%d", &smaj, &smin);
+ if ((smaj != lmaj && smaj != -1 && lmaj != -1)
+ || (smin != lmin && smin != -1 && lmin != -1))
+ return;
+
+ global_found = true;
+ }
+}
+
+/* We need to use static variables to pass information around the call
+ to lang_for_each_statement. Ick. */
+
+static const char *find_assign;
+static 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 ()
+{
+ 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.relocateable && ! entry_from_cmdline)
+ {
+ struct bfd_link_hash_entry *h;
+
+ for (h = link_info.hash->undefs; h != NULL; h = h->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)
+ {
+ find_assign = h->root.string;
+ found_assign = false;
+ lang_for_each_statement (gld${EMULATION_NAME}_find_assignment);
+ if (! found_assign)
+ {
+ link_info.shared = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (link_info.shared)
+ {
+ lang_output_section_statement_type *os;
+
+ /* Set the .text section to start at 0x20, not 0x2020. FIXME:
+ This is too magical. */
+ os = lang_output_section_statement_lookup (".text");
+ if (os->addr_tree == NULL)
+ os->addr_tree = exp_intop (0x20);
+ }
+
+ /* We need to create a __DYNAMIC symbol. We don't do this in the
+ linker script because we want to set the value to the start of
+ the dynamic section if there is one, or to zero if there isn't
+ one. We need to create the symbol before calling
+ size_dynamic_sections, although we can't set the value until
+ afterward. */
+ if (! link_info.relocateable)
+ {
+ hdyn = bfd_link_hash_lookup (link_info.hash, "__DYNAMIC", true, false,
+ false);
+ if (hdyn == NULL)
+ einfo ("%P%F: bfd_link_hash_lookup: %E\n");
+ if (! bfd_sunos_record_link_assignment (output_bfd, &link_info,
+ "__DYNAMIC"))
+ einfo ("%P%F: failed to record assignment to __DYNAMIC: %E\n");
+ }
+
+ /* If we are going to make any variable assignments, we need to let
+ the backend linker know about them in case the variables are
+ referred to by dynamic objects. */
+ lang_for_each_statement (gld${EMULATION_NAME}_find_assignment);
+
+ /* Let the backend linker work out the sizes of any sections
+ required by dynamic linking. */
+ if (! bfd_sunos_size_dynamic_sections (output_bfd, &link_info, &sdyn,
+ &sneed, &srules))
+ einfo ("%P%F: failed to set dynamic section sizes: %E\n");
+
+ if (sneed != NULL)
+ {
+ /* Set up the .need section. See the description of the ld_need
+ field in include/aout/sun4.h. */
+
+ need_entries = 0;
+ need_size = 0;
+
+ lang_for_each_input_file (gld${EMULATION_NAME}_count_need);
+
+ /* We should only have a .need section if we have at least one
+ dynamic object. */
+ ASSERT (need_entries != 0);
+
+ sneed->_raw_size = need_size;
+ sneed->contents = (bfd_byte *) xmalloc (need_size);
+
+ need_contents = sneed->contents;
+ need_pinfo = sneed->contents;
+ need_pnames = sneed->contents + need_entries * 16;
+
+ lang_for_each_input_file (gld${EMULATION_NAME}_set_need);
+
+ ASSERT ((bfd_size_type) (need_pnames - sneed->contents) == need_size);
+ }
+
+ if (srules != NULL)
+ {
+ /* Set up the .rules section. This is just a PATH like string
+ of the -L arguments given on the command line. We permit the
+ user to specify the directories using the -rpath command line
+ option. */
+ if (command_line.rpath)
+ {
+ srules->_raw_size = strlen (command_line.rpath);
+ srules->contents = (bfd_byte *) command_line.rpath;
+ }
+ else
+ {
+ unsigned int size;
+ search_dirs_type *search;
+
+ size = 0;
+ for (search = search_head; search != NULL; search = search->next)
+ if (search->cmdline)
+ size += strlen (search->name) + 1;
+ srules->_raw_size = size;
+ if (size > 0)
+ {
+ char *p;
+
+ srules->contents = (bfd_byte *) xmalloc (size);
+ p = (char *) srules->contents;
+ *p = '\0';
+ for (search = search_head; search != NULL; search = search->next)
+ {
+ if (search->cmdline)
+ {
+ if (p != (char *) srules->contents)
+ *p++ = ':';
+ strcpy (p, search->name);
+ p += strlen (p);
+ }
+ }
+ }
+ }
+ }
+
+ /* We must assign a value to __DYNAMIC. It should be zero if we are
+ not doing a dynamic link, or the start of the .dynamic section if
+ we are doing one. */
+ if (! link_info.relocateable)
+ {
+ hdyn->type = bfd_link_hash_defined;
+ hdyn->u.def.value = 0;
+ if (sdyn != NULL)
+ hdyn->u.def.section = sdyn;
+ else
+ hdyn->u.def.section = bfd_abs_section_ptr;
+ }
+}
+
+/* This is called by the before_allocation routine via
+ lang_for_each_statement. It does one of two things: if the
+ variable find_assign is set, it sets found_assign if it finds an
+ assignment to that variable; otherwise it tells the backend linker
+ about all assignment statements, in case they are assignments to
+ symbols which are referred to by dynamic objects. */
+
+static void
+gld${EMULATION_NAME}_find_assignment (s)
+ 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 (exp)
+ etree_type *exp;
+{
+ switch (exp->type.node_class)
+ {
+ case etree_assign:
+ if (find_assign != NULL)
+ {
+ if (strcmp (find_assign, exp->assign.dst) == 0)
+ found_assign = true;
+ return;
+ }
+
+ if (strcmp (exp->assign.dst, ".") != 0)
+ {
+ if (! bfd_sunos_record_link_assignment (output_bfd, &link_info,
+ exp->assign.dst))
+ einfo ("%P%F: failed to record assignment to %s: %E\n",
+ exp->assign.dst);
+ }
+ gld${EMULATION_NAME}_find_exp_assignment (exp->assign.src);
+ break;
+
+ case etree_binary:
+ gld${EMULATION_NAME}_find_exp_assignment (exp->binary.lhs);
+ gld${EMULATION_NAME}_find_exp_assignment (exp->binary.rhs);
+ break;
+
+ case etree_trinary:
+ gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.cond);
+ gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs);
+ gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.rhs);
+ break;
+
+ case etree_unary:
+ gld${EMULATION_NAME}_find_exp_assignment (exp->unary.child);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/* Work out the size of the .need section, and the number of entries.
+ The backend will set the ld_need field of the dynamic linking
+ information to point to the .need section. See include/aout/sun4.h
+ for more information. */
+
+static void
+gld${EMULATION_NAME}_count_need (inp)
+ 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 (inp)
+ lang_input_statement_type *inp;
+{
+ if (inp->the_bfd != NULL
+ && (inp->the_bfd->flags & DYNAMIC) != 0)
+ {
+ bfd_size_type c;
+
+ /* To really fill in the .need section contents, we need to know
+ the final file position of the section, but we don't.
+ Instead, we use offsets, and rely on the BFD backend to
+ finish the section up correctly. FIXME: Talk about lack of
+ referential locality. */
+ bfd_put_32 (output_bfd, need_pnames - need_contents, need_pinfo);
+ if (! inp->is_archive)
+ {
+ bfd_put_32 (output_bfd, (bfd_vma) 0, need_pinfo + 4);
+ bfd_put_16 (output_bfd, (bfd_vma) 0, need_pinfo + 8);
+ bfd_put_16 (output_bfd, (bfd_vma) 0, need_pinfo + 10);
+ strcpy (need_pnames, inp->filename);
+ }
+ else
+ {
+ char *verstr;
+ int maj, min;
+
+ bfd_put_32 (output_bfd, (bfd_vma) 0x80000000, need_pinfo + 4);
+ maj = 0;
+ min = 0;
+ verstr = strstr (inp->filename, ".so.");
+ if (verstr != NULL)
+ sscanf (verstr, ".so.%d.%d", &maj, &min);
+ bfd_put_16 (output_bfd, (bfd_vma) maj, need_pinfo + 8);
+ bfd_put_16 (output_bfd, (bfd_vma) min, need_pinfo + 10);
+ strcpy (need_pnames, inp->local_sym_name + 2);
+ }
+
+ c = (need_pinfo - need_contents) / NEED_ENTRY_SIZE;
+ if (c + 1 >= need_entries)
+ bfd_put_32 (output_bfd, (bfd_vma) 0, need_pinfo + 12);
+ else
+ bfd_put_32 (output_bfd, (bfd_vma) (c + 1) * NEED_ENTRY_SIZE,
+ need_pinfo + 12);
+
+ need_pinfo += NEED_ENTRY_SIZE;
+ need_pnames += strlen (need_pnames) + 1;
+ }
+}
+
+static char *
+gld${EMULATION_NAME}_get_script(isfile)
+ int *isfile;
+EOF
+
+if test -n "$COMPILE_IN"
+then
+# Scripts compiled in.
+
+# sed commands to quote an ld script as a C string.
+sc='s/["\\]/\\&/g
+s/$/\\n\\/
+1s/^/"/
+$s/$/n"/
+'
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 0;
+
+ if (link_info.relocateable == true && config.build_constructors == true)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xu`;
+ else if (link_info.relocateable == true)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xr`;
+ else if (!config.text_read_only)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xbn`;
+ else if (!config.magic_demand_paged)
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.xn`;
+ else
+ return `sed "$sc" ldscripts/${EMULATION_NAME}.x`;
+}
+EOF
+
+else
+# Scripts read from the filesystem.
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+ *isfile = 1;
+
+ if (link_info.relocateable == true && config.build_constructors == true)
+ return "ldscripts/${EMULATION_NAME}.xu";
+ else if (link_info.relocateable == true)
+ return "ldscripts/${EMULATION_NAME}.xr";
+ else if (!config.text_read_only)
+ return "ldscripts/${EMULATION_NAME}.xbn";
+ else if (!config.magic_demand_paged)
+ return "ldscripts/${EMULATION_NAME}.xn";
+ else
+ return "ldscripts/${EMULATION_NAME}.x";
+}
+EOF
+
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
+{
+ gld${EMULATION_NAME}_before_parse,
+ syslib_default,
+ hll_default,
+ after_parse_default,
+ gld${EMULATION_NAME}_after_open,
+ after_allocation_default,
+ set_output_arch_default,
+ ldemul_default_target,
+ gld${EMULATION_NAME}_before_allocation,
+ gld${EMULATION_NAME}_get_script,
+ "${EMULATION_NAME}",
+ "${OUTPUT_FORMAT}",
+ NULL, /* finish */
+ gld${EMULATION_NAME}_create_output_section_statements,
+ NULL /* open_dynamic_library */
+};
+EOF
diff --git a/gnu/usr.bin/binutils/ld/emultempl/vanilla.em b/gnu/usr.bin/binutils/ld/emultempl/vanilla.em
new file mode 100644
index 00000000000..04e36fbc947
--- /dev/null
+++ b/gnu/usr.bin/binutils/ld/emultempl/vanilla.em
@@ -0,0 +1,69 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+cat >e${EMULATION_NAME}.c <<EOF
+/* A vanilla emulation with no defaults
+ Copyright (C) 1991, 1993 Free Software Foundation, Inc.
+ Written by Steve Chamberlain steve@cygnus.com
+
+This file is part of GLD, the Gnu Linker.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+
+
+#include "ld.h"
+#include "ldemul.h"
+#include "ldfile.h"
+#include "ldmisc.h"
+#include "ldmain.h"
+
+static void vanilla_before_parse()
+{
+}
+
+static void
+vanilla_set_output_arch()
+{
+ /* Set the output architecture and machine if possible */
+ unsigned long machine = 0;
+ bfd_set_arch_mach(output_bfd, ldfile_output_architecture, machine);
+}
+
+static char *
+vanilla_get_script(isfile)
+ 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"
+};
+EOF