X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=ld%2Femultempl%2Faix.em;h=56985cfa753efe2e695d886924c1bcb7ba58b38c;hb=74fffc39827629fb48c9e24a7d12ebbd5693df4b;hp=c77857f822d64d3169e6c062c04b061e22de48d8;hpb=30727aa6d12fb866494020c0b62ab265a2bdcdfe;p=deliverable%2Fbinutils-gdb.git diff --git a/ld/emultempl/aix.em b/ld/emultempl/aix.em index c77857f822..56985cfa75 100644 --- a/ld/emultempl/aix.em +++ b/ld/emultempl/aix.em @@ -1,60 +1,66 @@ # This shell script emits a C file. -*- C -*- # It does some substitutions. -cat >e${EMULATION_NAME}.c < AIX support by Ian Lance Taylor + AIX 64 bit support by Tom Rix -This file is part of GLD, the Gnu Linker. + This file is part of the GNU Binutils. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + 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. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ #define TARGET_IS_${EMULATION_NAME} -#include "bfd.h" #include "sysdep.h" +#include "bfd.h" #include "libiberty.h" +#include "safe-ctype.h" #include "getopt.h" #include "obstack.h" #include "bfdlink.h" -#include - #include "ld.h" #include "ldmain.h" -#include "ldemul.h" -#include "ldfile.h" #include "ldmisc.h" #include "ldexp.h" #include "ldlang.h" +#include "ldfile.h" +#include "ldemul.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)); +#include + +#include "coff/internal.h" +#include "coff/xcoff.h" +#include "libcoff.h" +#include "libxcoff.h" + +static void gld${EMULATION_NAME}_read_file (const char *, bfd_boolean); +static void gld${EMULATION_NAME}_free (void *); +static void gld${EMULATION_NAME}_find_relocs (lang_statement_union_type *); +static void gld${EMULATION_NAME}_find_exp_assignment (etree_type *); + /* The file alignment required for each section. */ static unsigned long file_align; @@ -76,6 +82,14 @@ static unsigned short modtype = ('1' << 8) | 'L'; permitted). */ static int textro; +/* A mask of XCOFF_EXPALL and XCOFF_EXPFULL flags, as set by their + associated -b and -bno options. */ +static unsigned int auto_export_flags; + +/* A mask of auto_export_flags bits that were explicitly set on the + command line. */ +static unsigned int explicit_auto_export_flags; + /* Whether to implement Unix like linker semantics. */ static int unix_ld; @@ -96,55 +110,97 @@ struct export_symbol_list { struct export_symbol_list *next; const char *name; - boolean syscall; }; static struct export_symbol_list *export_symbols; +/* Maintains the 32 or 64 bit mode state of import file */ +static unsigned int symbol_mode = 0x04; + +/* Which symbol modes are valid */ +static unsigned int symbol_mode_mask = 0x0d; + +/* Whether this is a 64 bit link */ +static int is_64bit = 0; + +/* Which syscalls from import file are valid */ +static unsigned int syscall_mask = 0x77; + +/* fake file for -binitfini support */ +static lang_input_statement_type *initfini_file; + +/* Whether to do run time linking + -brtl enables, -bnortl and -bnortllib disable. */ +static int rtld; + +/* Explicit command line library path, -blibpath */ +static char *command_line_blibpath = NULL; + /* This routine is called before anything else is done. */ static void -gld${EMULATION_NAME}_before_parse() +gld${EMULATION_NAME}_before_parse (void) { -#ifndef TARGET_ /* I.e., if not generic. */ - ldfile_output_architecture = bfd_arch_${ARCH}; -#endif /* not TARGET_ */ - config.has_shared = true; + ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`); + + input_flags.dynamic = TRUE; + config.has_shared = TRUE; + + /* The link_info.[init|fini]_functions are initialized in ld/lexsup.c. + Override them here so we can use the link_info.init_function as a + state flag that lets the backend know that -binitfini has been done. */ + + link_info.init_function = NULL; + link_info.fini_function = NULL; } /* Handle AIX specific options. */ -static int -gld${EMULATION_NAME}_parse_args (argc, argv) - int argc; - char **argv; +enum + { + OPTION_IGNORE = 300, + OPTION_AUTOIMP, + OPTION_ERNOTOK, + OPTION_EROK, + OPTION_EXPALL, + OPTION_EXPFULL, + OPTION_EXPORT, + OPTION_IMPORT, + OPTION_INITFINI, + OPTION_LOADMAP, + OPTION_MAXDATA, + OPTION_MAXSTACK, + OPTION_MODTYPE, + OPTION_NOAUTOIMP, + OPTION_NOEXPALL, + OPTION_NOEXPFULL, + OPTION_NOSTRCMPCT, + OPTION_PD, + OPTION_PT, + OPTION_STRCMPCT, + OPTION_UNIX, + OPTION_32, + OPTION_64, + OPTION_LIBPATH, + OPTION_NOLIBPATH, + }; + +static void +gld${EMULATION_NAME}_add_options + (int ns, char **shortopts, int nl, struct option **longopts, + int nrl ATTRIBUTE_UNUSED, struct option **really_longopts ATTRIBUTE_UNUSED) { - 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) -#define OPTION_UNIX (OPTION_STRCMPCT + 1) - - static struct option longopts[] = { + static const char xtra_short[] = "D:H:KT:z"; + static const struct option xtra_long[] = { + /* -binitfini has special handling in the linker backend. The native linker + uses the arguemnts to generate a table of init and fini functions for + the executable. The important use for this option is to support aix 4.2+ + c++ constructors and destructors. This is tied into gcc via collect2.c. + + The function table is accessed by the runtime linker/loader by checking if + the first symbol in the loader symbol table is __rtinit. The gnu linker + generates this symbol and makes it the first loader symbol. */ + {"basis", no_argument, NULL, OPTION_IGNORE}, {"bautoimp", no_argument, NULL, OPTION_AUTOIMP}, {"bcomprld", no_argument, NULL, OPTION_IGNORE}, @@ -155,13 +211,17 @@ gld${EMULATION_NAME}_parse_args (argc, argv) {"bernotok", no_argument, NULL, OPTION_ERNOTOK}, {"berok", no_argument, NULL, OPTION_EROK}, {"berrmsg", no_argument, NULL, OPTION_IGNORE}, + {"bexpall", no_argument, NULL, OPTION_EXPALL}, + {"bexpfull", no_argument, NULL, OPTION_EXPFULL}, {"bexport", required_argument, NULL, OPTION_EXPORT}, + {"bbigtoc", no_argument, NULL, OPTION_IGNORE}, {"bf", no_argument, NULL, OPTION_ERNOTOK}, {"bgc", no_argument, &gc, 1}, {"bh", required_argument, NULL, OPTION_IGNORE}, {"bhalt", required_argument, NULL, OPTION_IGNORE}, {"bI", required_argument, NULL, OPTION_IMPORT}, {"bimport", required_argument, NULL, OPTION_IMPORT}, + {"binitfini", required_argument, NULL, OPTION_INITFINI}, {"bl", required_argument, NULL, OPTION_LOADMAP}, {"bloadmap", required_argument, NULL, OPTION_LOADMAP}, {"bmaxdata", required_argument, NULL, OPTION_MAXDATA}, @@ -169,6 +229,8 @@ gld${EMULATION_NAME}_parse_args (argc, argv) {"bM", required_argument, NULL, OPTION_MODTYPE}, {"bmodtype", required_argument, NULL, OPTION_MODTYPE}, {"bnoautoimp", no_argument, NULL, OPTION_NOAUTOIMP}, + {"bnoexpall", no_argument, NULL, OPTION_NOEXPALL}, + {"bnoexpfull", no_argument, NULL, OPTION_NOEXPFULL}, {"bnodelcsect", no_argument, NULL, OPTION_IGNORE}, {"bnoentry", no_argument, NULL, OPTION_IGNORE}, {"bnogc", no_argument, &gc, 0}, @@ -179,16 +241,23 @@ gld${EMULATION_NAME}_parse_args (argc, argv) {"bpD", required_argument, NULL, OPTION_PD}, {"bpT", required_argument, NULL, OPTION_PT}, {"bro", no_argument, &textro, 1}, + {"brtl", no_argument, &rtld, 1}, + {"bnortl", no_argument, &rtld, 0}, + {"bnortllib", no_argument, &rtld, 0}, {"bS", required_argument, NULL, OPTION_MAXSTACK}, {"bso", no_argument, NULL, OPTION_AUTOIMP}, {"bstrcmpct", no_argument, NULL, OPTION_STRCMPCT}, {"btextro", no_argument, &textro, 1}, + {"b32", no_argument, NULL, OPTION_32}, + {"b64", no_argument, NULL, OPTION_64}, {"static", no_argument, NULL, OPTION_NOAUTOIMP}, {"unix", no_argument, NULL, OPTION_UNIX}, + {"blibpath", required_argument, NULL, OPTION_LIBPATH}, + {"bnolibpath", required_argument, NULL, OPTION_NOLIBPATH}, {NULL, no_argument, NULL, 0} }; - /* Options supported by the AIX linker which we do not support: -f, + /* Options supported by the AIX linker which we do not support: -S, -v, -Z, -bbindcmds, -bbinder, -bbindopts, -bcalls, -bcaps, -bcror15, -bdebugopt, -bdbg, -bdelcsect, -bex?, -bfilelist, -bfl, -bgcbypass, -bglink, -binsert, -bi, -bloadmap, -bl, -bmap, -bnl, @@ -197,13 +266,26 @@ gld${EMULATION_NAME}_parse_args (argc, argv) -bnotypchk, -bnox, -bquiet, -bR, -brename, -breorder, -btypchk, -bx, -bX, -bxref. */ + *shortopts = (char *) xrealloc (*shortopts, ns + sizeof (xtra_short)); + memcpy (*shortopts + ns, &xtra_short, sizeof (xtra_short)); + *longopts = xrealloc (*longopts, + nl * sizeof (struct option) + sizeof (xtra_long)); + memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long)); +} + +static bfd_boolean +gld${EMULATION_NAME}_parse_args (int argc, char **argv) +{ + int indx; + /* If the current option starts with -b, change the first : to an =. The AIX linker uses : to separate the option from the argument; changing it to = lets us treat it as a getopt option. */ indx = optind; if (indx == 0) indx = 1; - if (indx < argc && strncmp (argv[indx], "-b", 2) == 0) + + if (indx < argc && CONST_STRNEQ (argv[indx], "-b")) { char *s; @@ -216,38 +298,111 @@ gld${EMULATION_NAME}_parse_args (argc, argv) } } } + return FALSE; +} + +/* Helper for option '-f', which specify a list of input files. + Contrary to the native linker, we don't support shell patterns + (simply because glob isn't always available). */ + +static void +read_file_list (const char *filename) +{ + FILE *f; + /* An upper bound on the number of characters in the file. */ + long pos; + /* File in memory. */ + char *buffer; + size_t len; + char *b; + char *e; + + f = fopen (filename, FOPEN_RT); + if (f == NULL) + { + einfo ("%F%P: cannot open %s\n", filename); + return; + } + if (fseek (f, 0L, SEEK_END) == -1) + goto error; + pos = ftell (f); + if (pos == -1) + goto error; + if (fseek (f, 0L, SEEK_SET) == -1) + goto error; + + buffer = (char *) xmalloc (pos + 1); + len = fread (buffer, sizeof (char), pos, f); + if (len != (size_t) pos && ferror (f)) + goto error; + /* Add a NUL terminator. */ + buffer[len] = '\0'; + fclose (f); + + /* Parse files. */ + b = buffer; + while (1) + { + /* Skip empty lines. */ + while (*b == '\n' || *b == '\r') + b++; + + /* Stop if end of buffer. */ + if (b == buffer + len) + break; + + /* Eat any byte until end of line. */ + for (e = b; *e != '\0'; e++) + if (*e == '\n' || *e == '\r') + break; + + /* Replace end of line by nul. */ + if (*e != '\0') + *e++ = '\0'; + + if (b != e) + lang_add_input_file (b, lang_input_file_is_search_file_enum, NULL); + b = e; + } + return; - /* We add s and u so to the short options list so that -s and -u on - the command line do not match -static and -unix. */ + error: + einfo ("%F%P: cannot read %s\n", optarg); + fclose (f); +} - opterr = 0; - optc = getopt_long_only (argc, argv, "-D:H:KT:zsu", longopts, &longind); - opterr = prevopterr; +static bfd_boolean +gld${EMULATION_NAME}_handle_option (int optc) +{ + bfd_signed_vma val; + const char *end; switch (optc) { - case 's': - case 'u': default: - optind = prevoptind; - return 0; + return FALSE; case 0: /* Long option which just sets a flag. */ break; + case 'f': + /* This overrides --auxiliary. This option specifies a file containing + a list of input files. */ + read_file_list (optarg); + break; + case 'D': - val = strtol (optarg, &end, 0); + val = bfd_scan_vma (optarg, &end, 0); if (*end != '\0') einfo ("%P: warning: ignoring invalid -D number %s\n", optarg); else if (val != -1) - lang_section_start (".data", exp_intop (val)); + lang_section_start (".data", exp_intop (val), NULL); break; case 'H': - val = strtoul (optarg, &end, 0); - if (*end != '\0' - || (val & (val - 1)) != 0) + val = bfd_scan_vma (optarg, &end, 0); + if (*end != '\0' || (val & (val - 1)) != 0) einfo ("%P: warning: ignoring invalid -H number %s\n", optarg); else file_align = val; @@ -261,35 +416,81 @@ gld${EMULATION_NAME}_parse_args (argc, argv) 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); + number, we assume the AIX option is intended. Otherwise, we + assume the usual GNU ld -T option is intended. We can't just + ignore the AIX option, because gcc passes it to the linker. */ + val = bfd_scan_vma (optarg, &end, 0); if (*end != '\0') - { - optind = prevoptind; - return 0; - } - lang_section_start (".text", exp_intop (val)); + return FALSE; + lang_section_start (".text", exp_intop (val), NULL); break; case OPTION_IGNORE: break; + case OPTION_INITFINI: + { + /* + * The aix linker init fini has the format : + * + * -binitfini:[ Initial][:Termination][:Priority] + * + * it allows the Termination and Priority to be optional. + * + * Since we support only one init/fini pair, we ignore the Priority. + * + * Define the special symbol __rtinit. + * + * strtok does not correctly handle the case of -binitfini::fini: so + * do it by hand + */ + char *t, *i, *f; + + i = t = optarg; + while (*t && ':' != *t) + t++; + if (*t) + *t++ = 0; + + if (0 != strlen (i)) + link_info.init_function = i; + + f = t; + while (*t && ':' != *t) + t++; + *t = 0; + + if (0 != strlen (f)) + link_info.fini_function = f; + } + break; + case OPTION_AUTOIMP: - link_info.static_link = false; + link_info.static_link = FALSE; break; case OPTION_ERNOTOK: - force_make_executable = false; + link_info.unresolved_syms_in_objects = RM_GENERATE_ERROR; + link_info.unresolved_syms_in_shared_libs = RM_GENERATE_ERROR; break; case OPTION_EROK: - force_make_executable = true; + link_info.unresolved_syms_in_objects = RM_IGNORE; + link_info.unresolved_syms_in_shared_libs = RM_IGNORE; + break; + + case OPTION_EXPALL: + auto_export_flags |= XCOFF_EXPALL; + explicit_auto_export_flags |= XCOFF_EXPALL; + break; + + case OPTION_EXPFULL: + auto_export_flags |= XCOFF_EXPFULL; + explicit_auto_export_flags |= XCOFF_EXPFULL; break; case OPTION_EXPORT: - gld${EMULATION_NAME}_read_file (optarg, false); + gld${EMULATION_NAME}_read_file (optarg, FALSE); break; case OPTION_IMPORT: @@ -312,16 +513,15 @@ gld${EMULATION_NAME}_parse_args (argc, argv) break; case OPTION_MAXDATA: - val = strtoul (optarg, &end, 0); + val = bfd_scan_vma (optarg, &end, 0); if (*end != '\0') - einfo ("%P: warning: ignoring invalid -bmaxdata number %s\n", - optarg); + einfo ("%P: warning: ignoring invalid -bmaxdata number %s\n", optarg); else maxdata = val; break; case OPTION_MAXSTACK: - val = strtoul (optarg, &end, 0); + val = bfd_scan_vma (optarg, &end, 0); if (*end != '\0') einfo ("%P: warning: ignoring invalid -bmaxstack number %s\n", optarg); @@ -332,7 +532,7 @@ gld${EMULATION_NAME}_parse_args (argc, argv) case OPTION_MODTYPE: if (*optarg == 'S') { - link_info.shared = true; + link_info.shared = TRUE; ++optarg; } if (*optarg == '\0' || optarg[1] == '\0') @@ -342,19 +542,29 @@ gld${EMULATION_NAME}_parse_args (argc, argv) break; case OPTION_NOAUTOIMP: - link_info.static_link = true; + link_info.static_link = TRUE; + break; + + case OPTION_NOEXPALL: + auto_export_flags &= ~XCOFF_EXPALL; + explicit_auto_export_flags |= XCOFF_EXPALL; + break; + + case OPTION_NOEXPFULL: + auto_export_flags &= ~XCOFF_EXPFULL; + explicit_auto_export_flags |= XCOFF_EXPFULL; break; case OPTION_NOSTRCMPCT: - link_info.traditional_format = true; + link_info.traditional_format = TRUE; break; case OPTION_PD: /* This sets the page that the .data section is supposed to - start on. The offset within the page should still be the - offset within the file, so we need to build an appropriate - expression. */ - val = strtoul (optarg, &end, 0); + start on. The offset within the page should still be the + offset within the file, so we need to build an appropriate + expression. */ + val = bfd_scan_vma (optarg, &end, 0); if (*end != '\0') einfo ("%P: warning: ignoring invalid -pD number %s\n", optarg); else @@ -368,16 +578,16 @@ gld${EMULATION_NAME}_parse_args (argc, argv) exp_intop (0xfff))); t = exp_binop ('&', exp_binop ('+', t, exp_intop (31)), - exp_intop (~ (bfd_vma) 31)); - lang_section_start (".data", t); + exp_intop (~(bfd_vma) 31)); + lang_section_start (".data", t, NULL); } break; case OPTION_PT: /* This set the page that the .text section is supposed to start - on. The offset within the page should still be the offset - within the file. */ - val = strtoul (optarg, &end, 0); + on. The offset within the page should still be the offset + within the file. */ + val = bfd_scan_vma (optarg, &end, 0); if (*end != '\0') einfo ("%P: warning: ignoring invalid -pT number %s\n", optarg); else @@ -389,39 +599,59 @@ gld${EMULATION_NAME}_parse_args (argc, argv) exp_nameop (SIZEOF_HEADERS, NULL)); t = exp_binop ('&', exp_binop ('+', t, exp_intop (31)), - exp_intop (~ (bfd_vma) 31)); - lang_section_start (".text", t); + exp_intop (~(bfd_vma) 31)); + lang_section_start (".text", t, NULL); } break; case OPTION_STRCMPCT: - link_info.traditional_format = false; + link_info.traditional_format = FALSE; break; case OPTION_UNIX: - unix_ld = true; + unix_ld = TRUE; + break; + + case OPTION_32: + is_64bit = 0; + syscall_mask = 0x77; + symbol_mode_mask = 0x0d; + break; + + case OPTION_64: + is_64bit = 1; + syscall_mask = 0xcc; + symbol_mode_mask = 0x0e; + break; + + case OPTION_LIBPATH: + command_line_blibpath = optarg; + break; + + case OPTION_NOLIBPATH: + command_line_blibpath = NULL; break; + } - return 1; + return TRUE; } /* This is called when an input file can not be recognized as a BFD object or an archive. If the file starts with #!, we must treat it as an import file. This is for AIX compatibility. */ -static boolean -gld${EMULATION_NAME}_unrecognized_file (entry) - lang_input_statement_type *entry; +static bfd_boolean +gld${EMULATION_NAME}_unrecognized_file (lang_input_statement_type *entry) { FILE *e; - boolean ret; + bfd_boolean ret; e = fopen (entry->filename, FOPEN_RT); if (e == NULL) - return false; + return FALSE; - ret = false; + ret = FALSE; if (getc (e) == '#' && getc (e) == '!') { @@ -436,8 +666,8 @@ gld${EMULATION_NAME}_unrecognized_file (entry) flpp = &(*flpp)->next; *flpp = n; - ret = true; - entry->loaded = true; + ret = TRUE; + entry->flags.loaded = TRUE; } fclose (e); @@ -448,21 +678,23 @@ gld${EMULATION_NAME}_unrecognized_file (entry) /* This is called after the input files have been opened. */ static void -gld${EMULATION_NAME}_after_open () +gld${EMULATION_NAME}_after_open (void) { - boolean r; + bfd_boolean r; struct set_info *p; + after_open_default (); + /* Call ldctor_build_sets, after pretending that this is a - relocateable link. We do this because AIX requires relocation + relocatable link. We do this because AIX requires relocation entries for all references to symbols, even in a final executable. Of course, we only want to do this if we are producing an XCOFF output file. */ - r = link_info.relocateable; - if (strstr (bfd_get_target (output_bfd), "xcoff") != NULL) - link_info.relocateable = true; + r = link_info.relocatable; + if (strstr (bfd_get_target (link_info.output_bfd), "xcoff") != NULL) + link_info.relocatable = TRUE; ldctor_build_sets (); - link_info.relocateable = r; + link_info.relocatable = r; /* For each set, record the size, so that the XCOFF backend can output the correct csect length. */ @@ -484,7 +716,8 @@ gld${EMULATION_NAME}_after_open () } size = (p->count + 2) * 4; - if (! bfd_xcoff_link_record_set (output_bfd, &link_info, p->h, size)) + if (!bfd_xcoff_link_record_set (link_info.output_bfd, &link_info, + p->h, size)) einfo ("%F%P: bfd_xcoff_link_record_set failed: %E\n"); } } @@ -493,25 +726,30 @@ gld${EMULATION_NAME}_after_open () sections, but before any sizes or addresses have been set. */ static void -gld${EMULATION_NAME}_before_allocation () +gld${EMULATION_NAME}_before_allocation (void) { struct filelist *fl; struct export_symbol_list *el; char *libpath; - asection *special_sections[6]; - int i; + asection *special_sections[XCOFF_NUMBER_OF_SPECIAL_SECTIONS]; + static const char *const must_keep_sections[] = { + ".text", + ".data", + ".bss" + }; + unsigned int i, flags; /* Handle the import and export files, if any. */ for (fl = import_files; fl != NULL; fl = fl->next) - gld${EMULATION_NAME}_read_file (fl->name, true); + 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); + 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)) + if (!bfd_xcoff_export_symbol (link_info.output_bfd, &link_info, h)) einfo ("%P%F: bfd_xcoff_export_symbol failed: %E\n"); } @@ -521,10 +759,13 @@ gld${EMULATION_NAME}_before_allocation () .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) + /* Precedence of LIBPATH + -blibpath: native support always first + -rpath: gnu extension + -L build from command line -L's */ + if (command_line_blibpath != NULL) + libpath = command_line_blibpath; + else if (command_line.rpath != NULL) libpath = command_line.rpath; else if (search_head == NULL) libpath = (char *) ""; @@ -533,117 +774,163 @@ gld${EMULATION_NAME}_before_allocation () 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) + /* PR ld/4023: Strip sysroot prefix from any paths + being inserted into the output binary's DT_RPATH. */ + if (ld_sysroot != NULL + && * ld_sysroot != 0) { - size_t nlen; + const char * name = search_head->name; + size_t ld_sysroot_len = strlen (ld_sysroot); + + if (strncmp (name, ld_sysroot, ld_sysroot_len) == 0) + name += ld_sysroot_len; + + len = strlen (name); + libpath = xmalloc (len + 1); + strcpy (libpath, name); + + for (search = search_head->next; search != NULL; search = search->next) + { + size_t nlen; - nlen = strlen (search->name); - libpath = xrealloc (libpath, len + nlen + 2); - libpath[len] = ':'; - strcpy (libpath + len + 1, search->name); - len += nlen + 1; + name = search->name; + if (strncmp (name, ld_sysroot, ld_sysroot_len) == 0) + name += ld_sysroot_len; + + nlen = strlen (name); + libpath = xrealloc (libpath, len + nlen + 2); + libpath[len] = ':'; + strcpy (libpath + len + 1, name); + len += nlen + 1; + } + } + else + { + len = strlen (search_head->name); + libpath = xmalloc (len + 1); + strcpy (libpath, search_head->name); + + for (search = search_head->next; search != NULL; search = search->next) + { + size_t nlen; + + nlen = strlen (search->name); + libpath = xrealloc (libpath, len + nlen + 2); + libpath[len] = ':'; + strcpy (libpath + len + 1, search->name); + len += nlen + 1; + } } } + /* Default to -bexpfull for SVR4-like semantics. */ + flags = (unix_ld ? XCOFF_EXPFULL : 0); + flags &= ~explicit_auto_export_flags; + flags |= auto_export_flags; + /* Let the XCOFF backend set up the .loader section. */ - if (! bfd_xcoff_size_dynamic_sections (output_bfd, &link_info, libpath, - entry_symbol, file_align, - maxstack, maxdata, - gc && ! unix_ld ? true : false, - modtype, - textro ? true : false, - unix_ld, - special_sections)) + if (!bfd_xcoff_size_dynamic_sections + (link_info.output_bfd, &link_info, libpath, entry_symbol.name, file_align, + maxstack, maxdata, gc && !unix_ld ? TRUE : FALSE, + modtype, textro ? TRUE : FALSE, flags, special_sections, + rtld ? TRUE : FALSE)) einfo ("%P%F: failed to set dynamic section sizes: %E\n"); /* Look through the special sections, and put them in the right place in the link ordering. This is especially magic. */ - for (i = 0; i < 6; i++) + for (i = 0; i < XCOFF_NUMBER_OF_SPECIAL_SECTIONS; i++) { asection *sec; lang_output_section_statement_type *os; lang_statement_union_type **pls; lang_input_section_type *is; const char *oname; - boolean start; + bfd_boolean start; sec = special_sections[i]; if (sec == NULL) continue; /* Remove this section from the list of the output section. - This assumes we know what the script looks like. */ + This assumes we know what the script looks like. */ is = NULL; - os = lang_output_section_find (sec->output_section->name); + os = lang_output_section_get (sec->output_section); 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) + + for (pls = &os->children.head; *pls != NULL; pls = &(*pls)->header.next) { if ((*pls)->header.type == lang_input_section_enum && (*pls)->input_section.section == sec) { - is = (lang_input_section_type *) *pls; - *pls = (*pls)->next; + is = (lang_input_section_type *) * pls; + *pls = (*pls)->header.next; break; } + if ((*pls)->header.type == lang_wild_statement_enum) { lang_statement_union_type **pwls; for (pwls = &(*pls)->wild_statement.children.head; - *pwls != NULL; - pwls = &(*pwls)->next) + *pwls != NULL; pwls = &(*pwls)->header.next) { + if ((*pwls)->header.type == lang_input_section_enum && (*pwls)->input_section.section == sec) { - is = (lang_input_section_type *) *pwls; - *pwls = (*pwls)->next; + is = (lang_input_section_type *) * pwls; + *pwls = (*pwls)->header.next; break; } } + if (is != NULL) break; } - } + } if (is == NULL) - einfo ("%P%F: can't find %s in output section\n", - bfd_get_section_name (sec->owner, sec)); + { + 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: + + default: /* to avoid warnings */ + case XCOFF_SPECIAL_SECTION_TEXT: /* _text */ oname = ".text"; - start = true; + start = TRUE; break; - case 1: + + case XCOFF_SPECIAL_SECTION_ETEXT: /* _etext */ oname = ".text"; - start = false; + start = FALSE; break; - case 2: + + case XCOFF_SPECIAL_SECTION_DATA: /* _data */ oname = ".data"; - start = true; + start = TRUE; break; - case 3: + + case XCOFF_SPECIAL_SECTION_EDATA: /* _edata */ oname = ".data"; - start = false; + start = FALSE; break; - case 4: - case 5: + + case XCOFF_SPECIAL_SECTION_END: + case XCOFF_SPECIAL_SECTION_END2: /* _end and end */ oname = ".bss"; - start = false; + start = FALSE; break; } @@ -662,22 +949,153 @@ gld${EMULATION_NAME}_before_allocation () &is->header.next); } } + + /* Executables and shared objects must always have .text, .data + and .bss output sections, so that the header can refer to them. + The kernel refuses to load objects that have missing sections. */ + if (!link_info.relocatable) + for (i = 0; i < ARRAY_SIZE (must_keep_sections); i++) + { + asection *sec; + + sec = bfd_get_section_by_name (link_info.output_bfd, + must_keep_sections[i]); + if (sec == NULL) + einfo ("%P: can't find required output section %s\n", must_keep_sections[i]); + else + sec->flags |= SEC_KEEP; + } + + before_allocation_default (); +} + +static char * +gld${EMULATION_NAME}_choose_target (int argc, char **argv) +{ + int i, j, jmax; + static char *from_outside; + static char *from_inside; + static char *argv_to_target[][2] = { + {NULL, "${OUTPUT_FORMAT}"}, + {"-b32", "${OUTPUT_FORMAT_32BIT}"}, + {"-b64", "${OUTPUT_FORMAT_64BIT}"}, + }; + + jmax = 3; + + from_outside = getenv (TARGET_ENVIRON); + if (from_outside != (char *) NULL) + return from_outside; + + /* Set to default. */ + from_inside = argv_to_target[0][1]; + for (i = 1; i < argc; i++) + { + for (j = 1; j < jmax; j++) + { + if (0 == strcmp (argv[i], argv_to_target[j][0])) + from_inside = argv_to_target[j][1]; + } + } + + return from_inside; +} + +/* Returns + 1 : state changed + 0 : no change */ +static int +change_symbol_mode (char *input) +{ + char *symbol_mode_string[] = { + "# 32", /* 0x01 */ + "# 64", /* 0x02 */ + "# no32", /* 0x04 */ + "# no64", /* 0x08 */ + NULL, + }; + + unsigned int bit; + char *string; + + for (bit = 0;; bit++) + { + string = symbol_mode_string[bit]; + if (string == NULL) + return 0; + + if (0 == strcmp (input, string)) + { + symbol_mode = (1 << bit); + return 1; + } + } + /* should not be here */ + return 0; +} + +/* Returns + 1 : yes + 0 : ignore + -1 : error, try something else */ +static int +is_syscall (char *input, unsigned int *flag) +{ + unsigned int bit; + char *string; + + struct sc { + char *syscall_string; + unsigned int flag; + } s [] = { + { "svc" /* 0x01 */, XCOFF_SYSCALL32 }, + { "svc32" /* 0x02 */, XCOFF_SYSCALL32 }, + { "svc3264" /* 0x04 */, XCOFF_SYSCALL32 | XCOFF_SYSCALL64 }, + { "svc64" /* 0x08 */, XCOFF_SYSCALL64 }, + { "syscall" /* 0x10 */, XCOFF_SYSCALL32 }, + { "syscall32" /* 0x20 */, XCOFF_SYSCALL32 }, + { "syscall3264" /* 0x40 */, XCOFF_SYSCALL32 | XCOFF_SYSCALL64 }, + { "syscall64" /* 0x80 */, XCOFF_SYSCALL64 }, + { NULL, 0 }, + }; + + *flag = 0; + + for (bit = 0;; bit++) + { + string = s[bit].syscall_string; + if (string == NULL) + return -1; + + if (0 == strcmp (input, string)) + { + if (1 << bit & syscall_mask) + { + *flag = s[bit].flag; + return 1; + } + else + { + return 0; + } + } + } + /* should not be here */ + return -1; } /* Read an import or export file. For an import file, this is called by the before_allocation emulation routine. For an export file, - this is called by the parse_args emulation routine. */ + this is called by the handle_option emulation routine. */ static void -gld${EMULATION_NAME}_read_file (filename, import) - const char *filename; - boolean import; +gld${EMULATION_NAME}_read_file (const char *filename, bfd_boolean import) { struct obstack *o; FILE *f; int lineno; int c; - boolean keep; + bfd_boolean keep; const char *imppath; const char *impfile; const char *impmember; @@ -690,20 +1108,29 @@ gld${EMULATION_NAME}_read_file (filename, import) { bfd_set_error (bfd_error_system_call); einfo ("%F%s: %E\n", filename); + return; } - keep = false; + keep = FALSE; imppath = NULL; impfile = NULL; impmember = NULL; lineno = 0; + + /* Default to 32 and 64 bit mode + symbols at top of /lib/syscalls.exp do not have a mode modifier and they + are not repeated, assume 64 bit routines also want to use them. + See the routine change_symbol_mode for more information. */ + + symbol_mode = 0x04; + while ((c = getc (f)) != EOF) { char *s; char *symname; - boolean syscall; + unsigned int syscall_flag = 0; bfd_vma address; struct bfd_link_hash_entry *h; @@ -717,12 +1144,13 @@ gld${EMULATION_NAME}_read_file (filename, import) ++lineno; s = (char *) obstack_base (o); - while (isspace ((unsigned char) *s)) + while (ISSPACE (*s)) ++s; if (*s == '\0' || *s == '*' + || change_symbol_mode (s) || (*s == '#' && s[1] == ' ') - || (! import && *s == '#' && s[1] == '!')) + || (!import && *s == '#' && s[1] == '!')) { obstack_free (o, obstack_base (o)); continue; @@ -731,7 +1159,7 @@ gld${EMULATION_NAME}_read_file (filename, import) if (*s == '#' && s[1] == '!') { s += 2; - while (isspace ((unsigned char) *s)) + while (ISSPACE (*s)) ++s; if (*s == '\0') { @@ -746,33 +1174,19 @@ gld${EMULATION_NAME}_read_file (filename, import) else { char cs; - char *file; + char *start; (void) obstack_finish (o); - keep = true; - imppath = s; - file = 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 = ""; - } + keep = TRUE; + start = s; + while (!ISSPACE (*s) && *s != '(' && *s != '\0') + ++s; cs = *s; *s = '\0'; - while (isspace ((unsigned char) cs)) + if (!bfd_xcoff_split_import_path (link_info.output_bfd, + start, &imppath, &impfile)) + einfo ("%F%P: Could not parse import path: %E\n"); + while (ISSPACE (cs)) { ++s; cs = *s; @@ -801,84 +1215,89 @@ gld${EMULATION_NAME}_read_file (filename, import) 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') + if (symbol_mode & symbol_mode_mask) { - char *se; - - *s++ = '\0'; + /* This is a symbol to be imported or exported. */ + symname = s; + syscall_flag = 0; + address = (bfd_vma) -1; - while (isspace ((unsigned char) *s)) + while (!ISSPACE (*s) && *s != '\0') ++s; - - se = s; - while (! isspace ((unsigned char) *se) && *se != '\0') - ++se; - if (*se != '\0') + if (*s != '\0') { - *se++ = '\0'; - while (isspace ((unsigned char) *se)) + char *se; + + *s++ = '\0'; + + while (ISSPACE (*s)) + ++s; + + se = s; + while (!ISSPACE (*se) && *se != '\0') ++se; if (*se != '\0') - einfo ("%s%d: warning: syntax error in import/export file\n", - filename, lineno); - } + { + *se++ = '\0'; + while (ISSPACE (*se)) + ++se; + if (*se != '\0') + einfo ("%s%d: warning: syntax error in import/export file\n", + filename, lineno); + } - if (s == se) - { - /* There was no address after all. */ - } - else if (strcasecmp (s, "svc") == 0 - || strcasecmp (s, "syscall") == 0) - syscall = true; - else - { - char *end; + if (s != se) + { + int status; + const char *end; + + status = is_syscall (s, &syscall_flag); - address = strtoul (s, &end, 0); - if (*end != '\0') - einfo ("%s:%d: warning: syntax error in import/export file\n", - filename, lineno); + if (0 > status) + { + /* not a system call, check for address */ + address = bfd_scan_vma (s, &end, 0); + if (*end != '\0') + { + einfo ("%s:%d: warning: syntax error in import/export file\n", + filename, lineno); + + } + } + } } - } - if (! import) - { - struct export_symbol_list *n; - - ldlang_add_undef (symname); - n = ((struct export_symbol_list *) - xmalloc (sizeof (struct export_symbol_list))); - n->next = export_symbols; - n->name = 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) + if (!import) { - /* We can just ignore attempts to import an unreferenced - symbol. */ + struct export_symbol_list *n; + + ldlang_add_undef (symname, TRUE); + n = ((struct export_symbol_list *) + xmalloc (sizeof (struct export_symbol_list))); + n->next = export_symbols; + n->name = xstrdup (symname); + export_symbols = n; } 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); + h = bfd_link_hash_lookup (link_info.hash, symname, FALSE, FALSE, + TRUE); + if (h == NULL || h->type == bfd_link_hash_new) + { + /* We can just ignore attempts to import an unreferenced + symbol. */ + } + else + { + if (!bfd_xcoff_import_symbol (link_info.output_bfd, + &link_info, h, + address, imppath, impfile, + impmember, syscall_flag)) + einfo ("%X%s:%d: failed to import symbol %s: %E\n", + filename, lineno, symname); + } } } - obstack_free (o, obstack_base (o)); } @@ -889,18 +1308,19 @@ gld${EMULATION_NAME}_read_file (filename, import) obstack_free (o, obstack_base (o)); } - if (! keep) + if (!keep) { obstack_free (o, NULL); free (o); } + + fclose (f); } /* This routine saves us from worrying about declaring free. */ static void -gld${EMULATION_NAME}_free (p) - PTR p; +gld${EMULATION_NAME}_free (void *p) { free (p); } @@ -910,8 +1330,7 @@ gld${EMULATION_NAME}_free (p) to symbols. */ static void -gld${EMULATION_NAME}_find_relocs (s) - lang_statement_union_type *s; +gld${EMULATION_NAME}_find_relocs (lang_statement_union_type *s) { if (s->header.type == lang_reloc_statement_enum) { @@ -920,7 +1339,8 @@ gld${EMULATION_NAME}_find_relocs (s) 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)) + if (!bfd_xcoff_link_count_reloc (link_info.output_bfd, &link_info, + rs->name)) einfo ("%F%P: bfd_xcoff_link_count_reloc failed: %E\n"); } @@ -931,8 +1351,7 @@ gld${EMULATION_NAME}_find_relocs (s) /* Look through an expression for an assignment statement. */ static void -gld${EMULATION_NAME}_find_exp_assignment (exp) - etree_type *exp; +gld${EMULATION_NAME}_find_exp_assignment (etree_type *exp) { struct bfd_link_hash_entry *h; @@ -940,15 +1359,16 @@ gld${EMULATION_NAME}_find_exp_assignment (exp) { case etree_provide: h = bfd_link_hash_lookup (link_info.hash, exp->assign.dst, - false, false, false); + 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)) + if (!bfd_xcoff_record_link_assignment (link_info.output_bfd, + &link_info, + exp->assign.dst)) einfo ("%P%F: failed to record assignment to %s: %E\n", exp->assign.dst); } @@ -976,45 +1396,44 @@ gld${EMULATION_NAME}_find_exp_assignment (exp) } static char * -gld${EMULATION_NAME}_get_script(isfile) - int *isfile; +gld${EMULATION_NAME}_get_script (int *isfile) EOF -if test -n "$COMPILE_IN" +if test x"$COMPILE_IN" = xyes then # Scripts compiled in. # sed commands to quote an ld script as a C string. -sc="-f ${srcdir}/emultempl/stringify.sed" +sc="-f ${srcdir}/emultempl/ostring.sed" -cat >>e${EMULATION_NAME}.c <> 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 +sed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c +echo ' ; else if (link_info.relocatable) return' >> e${EMULATION_NAME}.c +sed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.c +echo ' ; else if (!config.text_read_only) return' >> e${EMULATION_NAME}.c +sed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c +echo ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c +sed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c +echo ' ; else return' >> e${EMULATION_NAME}.c +sed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c +echo '; }' >> e${EMULATION_NAME}.c else # Scripts read from the filesystem. -cat >>e${EMULATION_NAME}.c <>e${EMULATION_NAME}.c <the_bfd = bfd_create ("initfini", link_info.output_bfd); + if (initfini_file->the_bfd == NULL + || ! bfd_set_arch_mach (initfini_file->the_bfd, + bfd_get_arch (link_info.output_bfd), + bfd_get_mach (link_info.output_bfd))) + { + einfo ("%X%P: can not create BFD %E\n"); + return; + } + + /* Call backend to fill in the rest */ + if (! bfd_xcoff_link_generate_rtinit (initfini_file->the_bfd, + link_info.init_function, + link_info.fini_function, + rtld)) + { + einfo ("%X%P: can not create BFD %E\n"); + return; + } + + /* __rtld defined in /lib/librtl.a */ + if (rtld) + lang_add_input_file ("rtl", lang_input_file_is_l_enum, NULL); + } +} + +static void +gld${EMULATION_NAME}_set_output_arch (void) +{ + bfd_set_arch_mach (link_info.output_bfd, + bfd_xcoff_architecture (link_info.output_bfd), + bfd_xcoff_machine (link_info.output_bfd)); + + ldfile_output_architecture = bfd_get_arch (link_info.output_bfd); + ldfile_output_machine = bfd_get_mach (link_info.output_bfd); + ldfile_output_machine_name = bfd_printable_name (link_info.output_bfd); +} + +static bfd_boolean +gld${EMULATION_NAME}_open_dynamic_archive (const char *arch, + search_dirs_type *search, + lang_input_statement_type *entry) +{ + char *path; + + if (!entry->flags.maybe_archive) + return FALSE; + + if (entry->flags.full_name_provided) + path = concat (search->name, "/", entry->filename, + (const char *) NULL); + else + path = concat (search->name, "/lib", entry->filename, arch, ".a", + (const char *) NULL); + + if (!ldfile_try_open_bfd (path, entry)) + { + free (path); + return FALSE; + } + /* Don't include the searched directory in the import path. */ + bfd_xcoff_set_archive_import_path (&link_info, entry->the_bfd, + path + strlen (search->name) + 1); + entry->filename = path; + return TRUE; +} + +struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = { gld${EMULATION_NAME}_before_parse, syslib_default, hll_default, after_parse_default, gld${EMULATION_NAME}_after_open, after_allocation_default, - set_output_arch_default, - ldemul_default_target, + gld${EMULATION_NAME}_set_output_arch, + gld${EMULATION_NAME}_choose_target, gld${EMULATION_NAME}_before_allocation, gld${EMULATION_NAME}_get_script, "${EMULATION_NAME}", "${OUTPUT_FORMAT}", - 0, /* finish */ - 0, /* create_output_section_statements */ - 0, /* open_dynamic_archive */ - 0, /* place_orphan */ - 0, /* set_symbols */ + finish_default, + gld${EMULATION_NAME}_create_output_section_statements, + gld${EMULATION_NAME}_open_dynamic_archive, + 0, /* place_orphan */ + 0, /* set_symbols */ gld${EMULATION_NAME}_parse_args, - gld${EMULATION_NAME}_unrecognized_file + gld${EMULATION_NAME}_add_options, + gld${EMULATION_NAME}_handle_option, + gld${EMULATION_NAME}_unrecognized_file, + NULL, /* list_options */ + NULL, /* recognized_file */ + NULL, /* find potential_libraries */ + NULL, /* new_vers_pattern */ + NULL /* extra_map_file_text */ }; EOF