bfd_boolean ldfile_try_open_bfd (const char *attempt, lang_input_statement_type *entry) { entry->the_bfd = bfd_openr (attempt, entry->target); if (verbose) { if (entry->the_bfd == NULL) info_msg (_("attempt to open %s failed\n"), attempt); else info_msg (_("attempt to open %s succeeded\n"), attempt); } 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; } /* 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; }
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 (entry->the_bfd == NULL) info_msg (_("attempt to open %s failed\n"), attempt); else info_msg (_("attempt to open %s succeeded\n"), attempt); } 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; } /* 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. */ if (entry->search_dirs_flag || !entry->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->search_dirs_flag && 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; } } return TRUE; } if (!entry->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->search_dirs_flag && !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; } } } return TRUE; }