X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=ld%2Fldfile.c;h=411f7ddf971a28676564b50f6083c35798dc6436;hb=db2d40f7d0b8477ca5ad9e305b8137a085434c97;hp=7946dda818a243d3c98b24a71c5764700f35222f;hpb=99f8f232c6b14a5842615b9ef0e824eb58f6f717;p=deliverable%2Fbinutils-gdb.git diff --git a/ld/ldfile.c b/ld/ldfile.c index 7946dda818..411f7ddf97 100644 --- a/ld/ldfile.c +++ b/ld/ldfile.c @@ -1,109 +1,133 @@ -/* Copyright (C) 1991, 92, 93, 94, 95, 98, 1999 Free Software Foundation, Inc. +/* Linker file opening and searching. + Copyright (C) 1991-2020 Free Software Foundation, Inc. -This file is part of GLD, the Gnu Linker. + This file is part of the GNU Binutils. -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. + 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. -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. + 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 GLD; see the file COPYING. If not, write to the Free -Software Foundation, 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. */ -/* - ldfile.c - - look after all the file stuff - - */ - -#include "bfd.h" #include "sysdep.h" +#include "bfd.h" #include "bfdlink.h" +#include "ctf-api.h" +#include "safe-ctype.h" #include "ld.h" #include "ldmisc.h" #include "ldexp.h" #include "ldlang.h" #include "ldfile.h" #include "ldmain.h" -#include "ldgram.h" +#include #include "ldlex.h" #include "ldemul.h" - -#include - -const char *ldfile_input_filename; -boolean ldfile_assumed_script = false; +#include "libiberty.h" +#include "filenames.h" +#ifdef ENABLE_PLUGINS +#include "plugin-api.h" +#include "plugin.h" +#endif /* ENABLE_PLUGINS */ + +bfd_boolean ldfile_assumed_script = FALSE; const char *ldfile_output_machine_name = ""; unsigned long ldfile_output_machine; enum bfd_architecture ldfile_output_architecture; search_dirs_type *search_head; -#ifndef MPW #ifdef VMS -char *slash = ""; +static char *slash = ""; #else -#if defined (_WIN32) && ! defined (__CYGWIN32__) -char *slash = "\\"; +#if defined (_WIN32) && !defined (__CYGWIN32__) +static char *slash = "\\"; #else -char *slash = "/"; +static char *slash = "/"; #endif #endif -#else /* MPW */ -/* The MPW path char is a colon. */ -char *slash = ":"; -#endif /* MPW */ - -/* LOCAL */ - -static search_dirs_type **search_tail_ptr = &search_head; -typedef struct search_arch +typedef struct search_arch { - char *name; + char *name; struct search_arch *next; } search_arch_type; +static search_dirs_type **search_tail_ptr = &search_head; static search_arch_type *search_arch_head; static search_arch_type **search_arch_tail_ptr = &search_arch_head; - -static boolean ldfile_open_file_search - PARAMS ((const char *arch, lang_input_statement_type *, - const char *lib, const char *suffix)); -static FILE *try_open PARAMS ((const char *name, const char *exten)); + +/* Test whether a pathname, after canonicalization, is the same or a + sub-directory of the sysroot directory. */ + +static bfd_boolean +is_sysrooted_pathname (const char *name) +{ + char *realname; + int len; + bfd_boolean result; + + if (ld_canon_sysroot == NULL) + return FALSE; + + realname = lrealpath (name); + len = strlen (realname); + result = FALSE; + if (len > ld_canon_sysroot_len + && IS_DIR_SEPARATOR (realname[ld_canon_sysroot_len])) + { + realname[ld_canon_sysroot_len] = '\0'; + result = FILENAME_CMP (ld_canon_sysroot, realname) == 0; + } + + free (realname); + return result; +} + +/* Adds NAME to the library search path. + Makes a copy of NAME using xmalloc(). */ void -ldfile_add_library_path (name, cmdline) - const char *name; - boolean cmdline; +ldfile_add_library_path (const char *name, bfd_boolean cmdline) { - search_dirs_type *new; - - new = (search_dirs_type *) xmalloc (sizeof (search_dirs_type)); - new->next = NULL; - new->name = name; - new->cmdline = cmdline; - *search_tail_ptr = new; - search_tail_ptr = &new->next; + search_dirs_type *new_dirs; + + if (!cmdline && config.only_cmd_line_lib_dirs) + return; + + new_dirs = (search_dirs_type *) xmalloc (sizeof (search_dirs_type)); + new_dirs->next = NULL; + new_dirs->cmdline = cmdline; + *search_tail_ptr = new_dirs; + search_tail_ptr = &new_dirs->next; + + /* If a directory is marked as honoring sysroot, prepend the sysroot path + now. */ + if (name[0] == '=') + new_dirs->name = concat (ld_sysroot, name + 1, (const char *) NULL); + else if (CONST_STRNEQ (name, "$SYSROOT")) + new_dirs->name = concat (ld_sysroot, name + strlen ("$SYSROOT"), (const char *) NULL); + else + new_dirs->name = xstrdup (name); } /* Try to open a BFD for a lang_input_statement. */ -boolean -ldfile_try_open_bfd (attempt, entry) - const char *attempt; - lang_input_statement_type *entry; +bfd_boolean +ldfile_try_open_bfd (const char *attempt, + lang_input_statement_type *entry) { entry->the_bfd = bfd_openr (attempt, entry->target); - if (trace_file_tries) + if (verbose) { if (entry->the_bfd == NULL) info_msg (_("attempt to open %s failed\n"), attempt); @@ -111,160 +135,335 @@ ldfile_try_open_bfd (attempt, entry) info_msg (_("attempt to open %s succeeded\n"), attempt); } - if (entry->the_bfd != NULL) - return true; - else + if (entry->the_bfd == NULL) { if (bfd_get_error () == bfd_error_invalid_target) einfo (_("%F%P: invalid BFD target `%s'\n"), entry->target); - return false; + return FALSE; } + + /* Linker needs to decompress sections. */ + entry->the_bfd->flags |= BFD_DECOMPRESS; + + /* This is a linker input BFD. */ + entry->the_bfd->is_linker_input = 1; + +#ifdef ENABLE_PLUGINS + if (entry->flags.lto_output) + entry->the_bfd->lto_output = 1; +#endif + + /* If we are searching for this file, see if the architecture is + compatible with the output file. If it isn't, keep searching. + If we can't open the file as an object file, stop the search + here. If we are statically linking, ensure that we don't link + a dynamic object. + + In the code below, it's OK to exit early if the check fails, + closing the checked BFD and returning FALSE, but if the BFD + checks out compatible, do not exit early returning TRUE, or + the plugins will not get a chance to claim the file. */ + + if (entry->flags.search_dirs || !entry->flags.dynamic) + { + bfd *check; + + if (bfd_check_format (entry->the_bfd, bfd_archive)) + check = bfd_openr_next_archived_file (entry->the_bfd, NULL); + else + check = entry->the_bfd; + + if (check != NULL) + { + if (!bfd_check_format (check, bfd_object)) + { + if (check == entry->the_bfd + && entry->flags.search_dirs + && bfd_get_error () == bfd_error_file_not_recognized + && !ldemul_unrecognized_file (entry)) + { + int token, skip = 0; + char *arg, *arg1, *arg2, *arg3; + extern FILE *yyin; + + /* Try to interpret the file as a linker script. */ + ldfile_open_command_file (attempt); + + ldfile_assumed_script = TRUE; + parser_input = input_selected; + ldlex_both (); + token = INPUT_SCRIPT; + while (token != 0) + { + switch (token) + { + case OUTPUT_FORMAT: + if ((token = yylex ()) != '(') + continue; + if ((token = yylex ()) != NAME) + continue; + arg1 = yylval.name; + arg2 = NULL; + arg3 = NULL; + token = yylex (); + if (token == ',') + { + if ((token = yylex ()) != NAME) + { + free (arg1); + continue; + } + arg2 = yylval.name; + if ((token = yylex ()) != ',' + || (token = yylex ()) != NAME) + { + free (arg1); + free (arg2); + continue; + } + arg3 = yylval.name; + token = yylex (); + } + if (token == ')') + { + switch (command_line.endian) + { + default: + case ENDIAN_UNSET: + arg = arg1; break; + case ENDIAN_BIG: + arg = arg2 ? arg2 : arg1; break; + case ENDIAN_LITTLE: + arg = arg3 ? arg3 : arg1; break; + } + if (strcmp (arg, lang_get_output_target ()) != 0) + skip = 1; + } + free (arg1); + if (arg2) free (arg2); + if (arg3) free (arg3); + break; + case NAME: + case LNAME: + case VERS_IDENTIFIER: + case VERS_TAG: + free (yylval.name); + break; + case INT: + if (yylval.bigint.str) + free (yylval.bigint.str); + break; + } + token = yylex (); + } + ldlex_popstate (); + ldfile_assumed_script = FALSE; + fclose (yyin); + yyin = NULL; + if (skip) + { + if (command_line.warn_search_mismatch) + einfo (_("%P: skipping incompatible %s " + "when searching for %s\n"), + attempt, entry->local_sym_name); + bfd_close (entry->the_bfd); + entry->the_bfd = NULL; + return FALSE; + } + } + goto success; + } + + if (!entry->flags.dynamic && (entry->the_bfd->flags & DYNAMIC) != 0) + { + einfo (_("%F%P: attempted static link of dynamic object `%s'\n"), + attempt); + bfd_close (entry->the_bfd); + entry->the_bfd = NULL; + return FALSE; + } + + if (entry->flags.search_dirs + && !bfd_arch_get_compatible (check, link_info.output_bfd, + command_line.accept_unknown_input_arch) + /* XCOFF archives can have 32 and 64 bit objects. */ + && !(bfd_get_flavour (check) == bfd_target_xcoff_flavour + && (bfd_get_flavour (link_info.output_bfd) + == bfd_target_xcoff_flavour) + && bfd_check_format (entry->the_bfd, bfd_archive))) + { + if (command_line.warn_search_mismatch) + einfo (_("%P: skipping incompatible %s " + "when searching for %s\n"), + attempt, entry->local_sym_name); + bfd_close (entry->the_bfd); + entry->the_bfd = NULL; + return FALSE; + } + } + } +success: +#ifdef ENABLE_PLUGINS + /* If plugins are active, they get first chance to claim + any successfully-opened input file. We skip archives + here; the plugin wants us to offer it the individual + members when we enumerate them, not the whole file. We + also ignore corefiles, because that's just weird. It is + a needed side-effect of calling bfd_check_format with + bfd_object that it sets the bfd's arch and mach, which + will be needed when and if we want to bfd_create a new + one using this one as a template. */ + if (link_info.lto_plugin_active + && !no_more_claiming + && bfd_check_format (entry->the_bfd, bfd_object)) + plugin_maybe_claim (entry); +#endif /* ENABLE_PLUGINS */ + + /* It opened OK, the format checked out, and the plugins have had + their chance to claim it, so this is success. */ + return TRUE; } /* Search for and open the file specified by ENTRY. If it is an archive, use ARCH, LIB and SUFFIX to modify the file name. */ -static boolean -ldfile_open_file_search (arch, entry, lib, suffix) - const char *arch; - lang_input_statement_type *entry; - const char *lib; - const char *suffix; +bfd_boolean +ldfile_open_file_search (const char *arch, + lang_input_statement_type *entry, + const char *lib, + const char *suffix) { search_dirs_type *search; /* If this is not an archive, try to open it in the current directory first. */ - if (! entry->is_archive) + if (!entry->flags.maybe_archive) { - if (ldfile_try_open_bfd (entry->filename, entry)) - return true; + if (entry->flags.sysrooted && IS_ABSOLUTE_PATH (entry->filename)) + { + char *name = concat (ld_sysroot, entry->filename, + (const char *) NULL); + if (ldfile_try_open_bfd (name, entry)) + { + entry->filename = name; + return TRUE; + } + free (name); + } + else if (ldfile_try_open_bfd (entry->filename, entry)) + return TRUE; + + if (IS_ABSOLUTE_PATH (entry->filename)) + return FALSE; } - for (search = search_head; - search != (search_dirs_type *)NULL; - search = search->next) + for (search = search_head; search != NULL; search = search->next) { char *string; - if (entry->dynamic && ! link_info.relocateable) + if (entry->flags.dynamic && !bfd_link_relocatable (&link_info)) { if (ldemul_open_dynamic_archive (arch, search, entry)) - return true; + return TRUE; } - string = (char *) xmalloc (strlen (search->name) - + strlen (slash) - + strlen (lib) - + strlen (entry->filename) - + strlen (arch) - + strlen (suffix) - + 1); - - if (entry->is_archive) - sprintf (string, "%s%s%s%s%s%s", search->name, slash, - lib, entry->filename, arch, suffix); - else if (entry->filename[0] == '/' || entry->filename[0] == '.' -#if defined (__MSDOS__) || defined (_WIN32) - || entry->filename[0] == '\\' - || (isalpha (entry->filename[0]) - && entry->filename[1] == ':') -#endif - ) - strcpy (string, entry->filename); + if (entry->flags.maybe_archive && !entry->flags.full_name_provided) + string = concat (search->name, slash, lib, entry->filename, + arch, suffix, (const char *) NULL); else - sprintf (string, "%s%s%s", search->name, slash, entry->filename); + string = concat (search->name, slash, entry->filename, + (const char *) 0); if (ldfile_try_open_bfd (string, entry)) { - bfd * arfile = NULL; - - if (bfd_check_format (entry->the_bfd, bfd_archive)) - { - /* We treat an archive as compatible if it empty - or has at least one compatible object. */ - arfile = bfd_openr_next_archived_file (entry->the_bfd, NULL); - - if (!arfile) - arfile = output_bfd; - else - while (arfile - && !(bfd_check_format (arfile, bfd_object) - && bfd_arch_get_compatible (arfile, output_bfd))) - arfile = bfd_openr_next_archived_file (entry->the_bfd, arfile); - } - else if (bfd_arch_get_compatible (entry->the_bfd, output_bfd)) - arfile = output_bfd; - - if (arfile) - { - entry->filename = string; - return true; - } - - info_msg (_("%s is for an incompatible architecture -- skipped\n"), - string); - bfd_close(entry->the_bfd); - entry->the_bfd = NULL; + entry->filename = string; + return TRUE; } free (string); } - return false; + return FALSE; } -/* Open the input file specified by ENTRY. */ +/* Open the input file specified by ENTRY. + PR 4437: Do not stop on the first missing file, but + continue processing other input files in case there + are more errors to report. */ void -ldfile_open_file (entry) - lang_input_statement_type *entry; +ldfile_open_file (lang_input_statement_type *entry) { if (entry->the_bfd != NULL) return; - if (! entry->search_dirs_flag) + if (!entry->flags.search_dirs) { if (ldfile_try_open_bfd (entry->filename, entry)) return; - if (strcmp (entry->filename, entry->local_sym_name) != 0) - einfo (_("%F%P: cannot open %s for %s: %E\n"), + + if (filename_cmp (entry->filename, entry->local_sym_name) != 0) + einfo (_("%P: cannot find %s (%s): %E\n"), entry->filename, entry->local_sym_name); else - einfo(_("%F%P: cannot open %s: %E\n"), entry->local_sym_name); + einfo (_("%P: cannot find %s: %E\n"), entry->local_sym_name); + + entry->flags.missing_file = TRUE; + input_flags.missing_file = TRUE; } else { search_arch_type *arch; + bfd_boolean found = FALSE; /* Try to open or lib.a */ - for (arch = search_arch_head; - arch != (search_arch_type *) NULL; - arch = arch->next) + for (arch = search_arch_head; arch != NULL; arch = arch->next) { - if (ldfile_open_file_search (arch->name, entry, "lib", ".a")) - return; + found = ldfile_open_file_search (arch->name, entry, "lib", ".a"); + if (found) + break; #ifdef VMS - if (ldfile_open_file_search (arch->name, entry, ":lib", ".a")) - return; + found = ldfile_open_file_search (arch->name, entry, ":lib", ".a"); + if (found) + break; #endif + found = ldemul_find_potential_libraries (arch->name, entry); + if (found) + break; + } + + /* If we have found the file, we don't need to search directories + again. */ + if (found) + entry->flags.search_dirs = FALSE; + else + { + if (entry->flags.sysrooted + && ld_sysroot + && IS_ABSOLUTE_PATH (entry->local_sym_name)) + einfo (_("%P: cannot find %s inside %s\n"), + entry->local_sym_name, ld_sysroot); + else + einfo (_("%P: cannot find %s\n"), entry->local_sym_name); + entry->flags.missing_file = TRUE; + input_flags.missing_file = TRUE; } - einfo (_("%F%P: cannot find %s\n"), entry->local_sym_name); } } -/* Try to open NAME; if that fails, try NAME with EXTEN appended to it. */ +/* Try to open NAME. */ static FILE * -try_open (name, exten) - const char *name; - const char *exten; +try_open (const char *name, bfd_boolean *sysrooted) { FILE *result; - char buff[1000]; result = fopen (name, "r"); - if (trace_file_tries) + + if (result != NULL) + *sysrooted = is_sysrooted_pathname (name); + + if (verbose) { if (result == NULL) info_msg (_("cannot find script file %s\n"), name); @@ -272,172 +471,244 @@ try_open (name, exten) info_msg (_("opened script file %s\n"), name); } - if (result != NULL) - return result; - - if (*exten) - { - sprintf (buff, "%s%s", name, exten); - result = fopen (buff, "r"); - if (trace_file_tries) - { - if (result == NULL) - info_msg (_("cannot find script file %s\n"), buff); - else - info_msg (_("opened script file %s\n"), buff); - } - } - return result; } -/* Try to open NAME; if that fails, look for it in any directories - specified with -L, without and with EXTEND apppended. */ +/* Return TRUE iff directory DIR contains an "ldscripts" subdirectory. */ -FILE * -ldfile_find_command_file (name, extend) - const char *name; - const char *extend; +static bfd_boolean +check_for_scripts_dir (char *dir) { - search_dirs_type *search; - FILE *result; - char buffer[1000]; - - /* First try raw name */ - result = try_open(name,""); - if (result == (FILE *)NULL) { - /* Try now prefixes */ - for (search = search_head; - search != (search_dirs_type *)NULL; - search = search->next) { - sprintf(buffer,"%s%s%s", search->name, slash, name); - result = try_open(buffer, extend); - if (result)break; - } - } - return result; + char *buf; + struct stat s; + bfd_boolean res; + + buf = concat (dir, "/ldscripts", (const char *) NULL); + res = stat (buf, &s) == 0 && S_ISDIR (s.st_mode); + free (buf); + return res; } -void -ldfile_open_command_file (name) - const char *name; +/* Return the default directory for finding script files. + We look for the "ldscripts" directory in: + + SCRIPTDIR (passed from Makefile) + (adjusted according to the current location of the binary) + the dir where this program is (for using it from the build tree). */ + +static char * +find_scripts_dir (void) { - FILE *ldlex_input_stack; - ldlex_input_stack = ldfile_find_command_file(name, ""); - - if (ldlex_input_stack == (FILE *)NULL) { - bfd_set_error (bfd_error_system_call); - einfo(_("%P%F: cannot open linker script file %s: %E\n"),name); - } - lex_push_file(ldlex_input_stack, name); - - ldfile_input_filename = name; - lineno = 1; - had_script = true; -} + char *dir; + dir = make_relative_prefix (program_name, BINDIR, SCRIPTDIR); + if (dir) + { + if (check_for_scripts_dir (dir)) + return dir; + free (dir); + } + dir = make_relative_prefix (program_name, TOOLBINDIR, SCRIPTDIR); + if (dir) + { + if (check_for_scripts_dir (dir)) + return dir; + free (dir); + } + /* Look for "ldscripts" in the dir where our binary is. */ + dir = make_relative_prefix (program_name, ".", "."); + if (dir) + { + if (check_for_scripts_dir (dir)) + return dir; + free (dir); + } + + return NULL; +} +/* If DEFAULT_ONLY is false, try to open NAME; if that fails, look for + it in directories specified with -L, then in the default script + directory. If DEFAULT_ONLY is true, the search is restricted to + the default script location. */ -#ifdef GNU960 -static -char * -gnu960_map_archname( name ) -char *name; +static FILE * +ldfile_find_command_file (const char *name, + bfd_boolean default_only, + bfd_boolean *sysrooted) { - struct tabentry { char *cmd_switch; char *arch; }; - static struct tabentry arch_tab[] = { - "", "", - "KA", "ka", - "KB", "kb", - "KC", "mc", /* Synonym for MC */ - "MC", "mc", - "CA", "ca", - "SA", "ka", /* Functionally equivalent to KA */ - "SB", "kb", /* Functionally equivalent to KB */ - NULL, "" - }; - struct tabentry *tp; - - - for ( tp = arch_tab; tp->cmd_switch != NULL; tp++ ){ - if ( !strcmp(name,tp->cmd_switch) ){ - break; + search_dirs_type *search; + FILE *result = NULL; + char *path; + static search_dirs_type *script_search; + + if (!default_only) + { + /* First try raw name. */ + result = try_open (name, sysrooted); + if (result != NULL) + return result; } - } - if ( tp->cmd_switch == NULL ){ - einfo(_("%P%F: unknown architecture: %s\n"),name); - } - return tp->arch; -} + if (!script_search) + { + char *script_dir = find_scripts_dir (); + if (script_dir) + { + search_dirs_type **save_tail_ptr = search_tail_ptr; + search_tail_ptr = &script_search; + ldfile_add_library_path (script_dir, TRUE); + search_tail_ptr = save_tail_ptr; + } + } + /* Temporarily append script_search to the path list so that the + paths specified with -L will be searched first. */ + *search_tail_ptr = script_search; + /* Try now prefixes. */ + for (search = default_only ? script_search : search_head; + search != NULL; + search = search->next) + { + path = concat (search->name, slash, name, (const char *) NULL); + result = try_open (path, sysrooted); + free (path); + if (result) + break; + } -void -ldfile_add_arch(name) -char *name; + /* Restore the original path list. */ + *search_tail_ptr = NULL; + + return result; +} + +enum script_open_style { + script_nonT, + script_T, + script_defaultT +}; + +struct script_name_list { - search_arch_type *new = - (search_arch_type *)xmalloc((bfd_size_type)(sizeof(search_arch_type))); + struct script_name_list *next; + enum script_open_style open_how; + char name[1]; +}; +/* Open command file NAME. */ + +static void +ldfile_open_command_file_1 (const char *name, enum script_open_style open_how) +{ + FILE *ldlex_input_stack; + bfd_boolean sysrooted; + static struct script_name_list *processed_scripts = NULL; + struct script_name_list *script; + size_t len; + + /* PR 24576: Catch the case where the user has accidentally included + the same linker script twice. */ + for (script = processed_scripts; script != NULL; script = script->next) + { + if ((open_how != script_nonT || script->open_how != script_nonT) + && strcmp (name, script->name) == 0) + { + einfo (_("%F%P: error: linker script file '%s'" + " appears multiple times\n"), name); + return; + } + } - if (*name != '\0') { - if (ldfile_output_machine_name[0] != '\0') { - einfo(_("%P%F: target architecture respecified\n")); + /* FIXME: This memory is never freed, but that should not really matter. + It will be released when the linker exits, and it is unlikely to ever + be more than a few tens of bytes. */ + len = strlen (name); + script = xmalloc (sizeof (*script) + len); + script->next = processed_scripts; + script->open_how = open_how; + memcpy (script->name, name, len + 1); + processed_scripts = script; + + ldlex_input_stack = ldfile_find_command_file (name, + open_how == script_defaultT, + &sysrooted); + if (ldlex_input_stack == NULL) + { + bfd_set_error (bfd_error_system_call); + einfo (_("%F%P: cannot open linker script file %s: %E\n"), name); return; } - ldfile_output_machine_name = name; - } - new->next = (search_arch_type*)NULL; - new->name = gnu960_map_archname( name ); - *search_arch_tail_ptr = new; - search_arch_tail_ptr = &new->next; + lex_push_file (ldlex_input_stack, name, sysrooted); + + lineno = 1; + saved_script_handle = ldlex_input_stack; } -#else /* not GNU960 */ +/* Open command file NAME in the current directory, -L directories, + the default script location, in that order. */ +void +ldfile_open_command_file (const char *name) +{ + ldfile_open_command_file_1 (name, script_nonT); +} void -ldfile_add_arch (in_name) - CONST char * in_name; +ldfile_open_script_file (const char *name) { - char *name = buystring(in_name); - search_arch_type *new = - (search_arch_type *) xmalloc (sizeof (search_arch_type)); + ldfile_open_command_file_1 (name, script_T); +} + +/* Open command file NAME at the default script location. */ + +void +ldfile_open_default_command_file (const char *name) +{ + ldfile_open_command_file_1 (name, script_defaultT); +} + +void +ldfile_add_arch (const char *in_name) +{ + char *name = xstrdup (in_name); + search_arch_type *new_arch + = (search_arch_type *) xmalloc (sizeof (search_arch_type)); ldfile_output_machine_name = in_name; - new->name = name; - new->next = (search_arch_type*)NULL; + new_arch->name = name; + new_arch->next = NULL; while (*name) { - if (isupper ((unsigned char) *name)) - *name = tolower ((unsigned char) *name); + *name = TOLOWER (*name); name++; } - *search_arch_tail_ptr = new; - search_arch_tail_ptr = &new->next; + *search_arch_tail_ptr = new_arch; + search_arch_tail_ptr = &new_arch->next; } -#endif -/* Set the output architecture */ +/* Set the output architecture. */ + void -ldfile_set_output_arch (string) - CONST char *string; +ldfile_set_output_arch (const char *string, enum bfd_architecture defarch) { - const bfd_arch_info_type *arch = bfd_scan_arch(string); - - if (arch) { - ldfile_output_architecture = arch->arch; - ldfile_output_machine = arch->mach; - ldfile_output_machine_name = arch->printable_name; - } - else { - einfo(_("%P%F: cannot represent machine `%s'\n"), string); - } + const bfd_arch_info_type *arch = bfd_scan_arch (string); + + if (arch) + { + ldfile_output_architecture = arch->arch; + ldfile_output_machine = arch->mach; + ldfile_output_machine_name = arch->printable_name; + } + else if (defarch != bfd_arch_unknown) + ldfile_output_architecture = defarch; + else + einfo (_("%F%P: cannot represent machine `%s'\n"), string); }