diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1996-01-08 11:10:27 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1996-01-08 11:10:27 +0000 |
commit | 8b46c09925a80623c289e346c12921bc09fd1678 (patch) | |
tree | 01507d0da339cc7e5e6f5d16dfa625f94910b091 /gnu/usr.bin/binutils/ld/emultempl | |
parent | 5d56227f9458a53138642c1b4488b4a30f85f334 (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/README | 3 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/aix.em | 990 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/elf32.em | 799 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/generic.em | 118 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/gld960.em | 176 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/gld960c.em | 177 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/hppaelf.em | 286 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/linux.em | 207 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/lnk960.em | 323 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/m88kbcs.em | 119 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/mipsecoff.em | 229 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/pe.em | 518 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/stringify.sed | 4 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/sunos.em | 969 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/vanilla.em | 69 |
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 |