X-Git-Url: http://drtracing.org/?a=blobdiff_plain;ds=sidebyside;f=ld%2Fldmain.c;h=52a4b04830a59196eb259c4d2713a8fc5d47984e;hb=9e2278f567e4ddeb7180ef4e0b3b24e4b087d703;hp=7cb4fc9e99c6a6d3fab2dc3a1608494d19704de9;hpb=7d24f02c67bc8efdcfc1806e1f39e045342ae90f;p=deliverable%2Fbinutils-gdb.git diff --git a/ld/ldmain.c b/ld/ldmain.c index 7cb4fc9e99..52a4b04830 100644 --- a/ld/ldmain.c +++ b/ld/ldmain.c @@ -1,6 +1,6 @@ /* Main program of GNU linker. Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2005, 2006, 2007, 2008 + 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Written by Steve Chamberlain steve@cygnus.com @@ -40,6 +40,11 @@ #include "ldfile.h" #include "ldemul.h" #include "ldctor.h" +#ifdef ENABLE_PLUGINS +#include "plugin.h" +#include "plugin-api.h" +#include "libbfd.h" +#endif /* ENABLE_PLUGINS */ /* Somewhere above, sys/stat.h got included. */ #if !defined(S_ISDIR) && defined(S_IFDIR) @@ -93,13 +98,14 @@ bfd_boolean version_printed; /* Nonzero means link in every member of an archive. */ bfd_boolean whole_archive; -/* Nonzero means create DT_NEEDED entries only if a dynamic library - actually satisfies some reference in a regular object. */ -bfd_boolean as_needed; +/* True means only create DT_NEEDED entries for dynamic libraries + if they actually satisfy some reference in a regular object. */ +bfd_boolean add_DT_NEEDED_for_regular; -/* Nonzero means never create DT_NEEDED entries for dynamic libraries - in DT_NEEDED tags. */ -bfd_boolean add_needed = TRUE; +/* True means create DT_NEEDED entries for dynamic libraries that + are DT_NEEDED by dynamic libraries specifically mentioned on + the command line. */ +bfd_boolean add_DT_NEEDED_for_dynamic = TRUE; /* TRUE if we should demangle symbol names. */ bfd_boolean demangling; @@ -115,7 +121,7 @@ static const char *get_sysroot static char *get_emulation (int, char **); static bfd_boolean add_archive_element - (struct bfd_link_info *, bfd *, const char *); + (struct bfd_link_info *, bfd *, const char *, bfd **); static bfd_boolean multiple_definition (struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma, bfd *, asection *, bfd_vma); @@ -168,15 +174,14 @@ static struct bfd_link_callbacks link_callbacks = struct bfd_link_info link_info; static void -remove_output (void) +ld_cleanup (void) { - if (output_filename) - { - if (link_info.output_bfd) - bfd_cache_close (link_info.output_bfd); - if (delete_output_file_on_failure) - unlink_if_ordinary (output_filename); - } + bfd_cache_close_all (); +#ifdef ENABLE_PLUGINS + plugin_call_cleanup (); +#endif + if (output_filename && delete_output_file_on_failure) + unlink_if_ordinary (output_filename); } int @@ -205,7 +210,7 @@ main (int argc, char **argv) bfd_set_error_program_name (program_name); - xatexit (remove_output); + xatexit (ld_cleanup); /* Set up the sysroot directory. */ ld_sysroot = get_sysroot (argc, argv); @@ -252,6 +257,7 @@ main (int argc, char **argv) command_line.warn_mismatch = TRUE; command_line.warn_search_mismatch = TRUE; command_line.check_section_addresses = -1; + command_line.disable_target_specific_optimizations = -1; /* We initialize DEMANGLING based on the environment variable COLLECT_NO_DEMANGLE. The gcc collect2 program will demangle the @@ -280,6 +286,8 @@ main (int argc, char **argv) emulation = get_emulation (argc, argv); ldemul_choose_mode (emulation); default_target = ldemul_choose_target (argc, argv); + config.maxpagesize = bfd_emul_get_maxpagesize (default_target); + config.commonpagesize = bfd_emul_get_commonpagesize (default_target); lang_init (); ldemul_before_parse (); lang_has_input_file = FALSE; @@ -294,8 +302,6 @@ main (int argc, char **argv) { if (command_line.check_section_addresses < 0) command_line.check_section_addresses = 0; - if (command_line.relax) - einfo (_("%P%F: --relax and -r may not be used together\n")); if (link_info.shared) einfo (_("%P%F: -r and -shared may not be used together\n")); } @@ -399,7 +405,7 @@ main (int argc, char **argv) { static const int ld_bufsz = 8193; size_t n; - char *buf = xmalloc (ld_bufsz); + char *buf = (char *) xmalloc (ld_bufsz); rewind (saved_script_handle); while ((n = fread (buf, 1, ld_bufsz - 1, saved_script_handle)) > 0) @@ -503,9 +509,9 @@ main (int argc, char **argv) FILE *src; FILE *dst; const int bsize = 4096; - char *buf = xmalloc (bsize); + char *buf = (char *) xmalloc (bsize); int l; - char *dst_name = xmalloc (len + 5); + char *dst_name = (char *) xmalloc (len + 5); strcpy (dst_name, output_filename); strcat (dst_name, ".exe"); @@ -540,16 +546,18 @@ main (int argc, char **argv) if (config.stats) { #ifdef HAVE_SBRK - char *lim = sbrk (0); + char *lim = (char *) sbrk (0); #endif long run_time = get_run_time () - start_time; + fflush (stdout); fprintf (stderr, _("%s: total time in link: %ld.%06ld\n"), program_name, run_time / 1000000, run_time % 1000000); #ifdef HAVE_SBRK fprintf (stderr, _("%s: data size %ld\n"), program_name, (long) (lim - (char *) &environ)); #endif + fflush (stderr); } /* Prevent remove_output from doing anything, after a successful link. */ @@ -672,7 +680,8 @@ add_ysym (const char *name) { if (link_info.notice_hash == NULL) { - link_info.notice_hash = xmalloc (sizeof (struct bfd_hash_table)); + link_info.notice_hash = + (struct bfd_hash_table *) xmalloc (sizeof (struct bfd_hash_table)); if (!bfd_hash_table_init_n (link_info.notice_hash, bfd_hash_newfunc, sizeof (struct bfd_hash_entry), @@ -691,7 +700,8 @@ add_wrap (const char *name) { if (link_info.wrap_hash == NULL) { - link_info.wrap_hash = xmalloc (sizeof (struct bfd_hash_table)); + link_info.wrap_hash = + (struct bfd_hash_table *) xmalloc (sizeof (struct bfd_hash_table)); if (!bfd_hash_table_init_n (link_info.wrap_hash, bfd_hash_newfunc, sizeof (struct bfd_hash_entry), @@ -724,13 +734,14 @@ add_keepsyms_file (const char *filename) return; } - link_info.keep_hash = xmalloc (sizeof (struct bfd_hash_table)); + link_info.keep_hash = (struct bfd_hash_table *) + xmalloc (sizeof (struct bfd_hash_table)); if (!bfd_hash_table_init (link_info.keep_hash, bfd_hash_newfunc, sizeof (struct bfd_hash_entry))) einfo (_("%P%F: bfd_hash_table_init failed: %E\n")); bufsize = 100; - buf = xmalloc (bufsize); + buf = (char *) xmalloc (bufsize); c = getc (file); while (c != EOF) @@ -749,7 +760,7 @@ add_keepsyms_file (const char *filename) if (len >= bufsize) { bufsize *= 2; - buf = xrealloc (buf, bufsize); + buf = (char *) xrealloc (buf, bufsize); } c = getc (file); } @@ -776,15 +787,68 @@ add_keepsyms_file (const char *filename) static bfd_boolean add_archive_element (struct bfd_link_info *info, bfd *abfd, - const char *name) + const char *name, + bfd **subsbfd ATTRIBUTE_UNUSED) { lang_input_statement_type *input; + lang_input_statement_type orig_input; - input = xcalloc (1, sizeof (lang_input_statement_type)); + input = (lang_input_statement_type *) + xcalloc (1, sizeof (lang_input_statement_type)); input->filename = abfd->filename; input->local_sym_name = abfd->filename; input->the_bfd = abfd; + /* Save the original data for trace files/tries below, as plugins + (if enabled) may possibly alter it to point to a replacement + BFD, but we still want to output the original BFD filename. */ + orig_input = *input; +#ifdef ENABLE_PLUGINS + if (bfd_my_archive (abfd) != NULL + && plugin_active_plugins_p () + && !no_more_claiming) + { + /* We must offer this archive member to the plugins to claim. */ + int fd = open (bfd_my_archive (abfd)->filename, O_RDONLY | O_BINARY); + if (fd >= 0) + { + struct ld_plugin_input_file file; + int claimed = 0; + /* Offset and filesize must refer to the individual archive + member, not the whole file, and must exclude the header. + Fortunately for us, that is how the data is stored in the + origin field of the bfd and in the arelt_data. */ + file.name = bfd_my_archive (abfd)->filename; + file.offset = abfd->origin; + file.filesize = arelt_size (abfd); + file.fd = fd; + /* We create a dummy BFD, initially empty, to house + whatever symbols the plugin may want to add. */ + file.handle = plugin_get_ir_dummy_bfd (abfd->filename, abfd); + if (plugin_call_claim_file (&file, &claimed)) + einfo (_("%P%F: %s: plugin reported error claiming file\n"), + plugin_error_plugin ()); + /* fd belongs to us, not the plugin; but we don't need it. */ + close (fd); + if (claimed) + { + /* Substitute the dummy BFD. */ + input->the_bfd = file.handle; + input->claimed = TRUE; + input->claim_archive = TRUE; + bfd_make_readable (input->the_bfd); + *subsbfd = input->the_bfd; + } + else + { + /* Abandon the dummy BFD. */ + bfd_close_all_done (file.handle); + input->claimed = FALSE; + } + } + } +#endif /* ENABLE_PLUGINS */ + ldlang_add_file (input); if (config.map_file != NULL) @@ -865,8 +929,7 @@ add_archive_element (struct bfd_link_info *info, } if (trace_files || trace_file_tries) - info_msg ("%I\n", input); - + info_msg ("%I\n", &orig_input); return TRUE; } @@ -901,10 +964,10 @@ multiple_definition (struct bfd_link_info *info ATTRIBUTE_UNUSED, if (obfd != NULL) einfo (_("%D: first defined here\n"), obfd, osec, oval); - if (command_line.relax) + if (RELAXATION_ENABLED) { einfo (_("%P: Disabling relaxation: it will not work with multiple definitions\n")); - command_line.relax = 0; + command_line.disable_target_specific_optimizations = -1; } return TRUE; @@ -1098,7 +1161,7 @@ warning_callback (struct bfd_link_info *info ATTRIBUTE_UNUSED, einfo ("%B: %s%s\n", abfd, _("warning: "), warning); else { - struct warning_callback_info info; + struct warning_callback_info cinfo; /* Look through the relocs to see if we can find a plausible address. */ @@ -1106,13 +1169,13 @@ warning_callback (struct bfd_link_info *info ATTRIBUTE_UNUSED, if (!bfd_generic_link_read_symbols (abfd)) einfo (_("%B%F: could not read symbols: %E\n"), abfd); - info.found = FALSE; - info.warning = warning; - info.symbol = symbol; - info.asymbols = bfd_get_outsymbols (abfd); - bfd_map_over_sections (abfd, warning_find_reloc, &info); + cinfo.found = FALSE; + cinfo.warning = warning; + cinfo.symbol = symbol; + cinfo.asymbols = bfd_get_outsymbols (abfd); + bfd_map_over_sections (abfd, warning_find_reloc, &cinfo); - if (! info.found) + if (! cinfo.found) einfo ("%B: %s%s\n", abfd, _("warning: "), warning); } @@ -1127,7 +1190,7 @@ warning_callback (struct bfd_link_info *info ATTRIBUTE_UNUSED, static void warning_find_reloc (bfd *abfd, asection *sec, void *iarg) { - struct warning_callback_info *info = iarg; + struct warning_callback_info *info = (struct warning_callback_info *) iarg; long relsize; arelent **relpp; long relcount; @@ -1142,7 +1205,7 @@ warning_find_reloc (bfd *abfd, asection *sec, void *iarg) if (relsize == 0) return; - relpp = xmalloc (relsize); + relpp = (arelent **) xmalloc (relsize); relcount = bfd_canonicalize_reloc (abfd, sec, relpp, info->asymbols); if (relcount < 0) einfo (_("%B%F: could not read relocs: %E\n"), abfd); @@ -1190,7 +1253,8 @@ undefined_symbol (struct bfd_link_info *info ATTRIBUTE_UNUSED, /* Only warn once about a particular undefined symbol. */ if (hash == NULL) { - hash = xmalloc (sizeof (struct bfd_hash_table)); + hash = (struct bfd_hash_table *) + xmalloc (sizeof (struct bfd_hash_table)); if (!bfd_hash_table_init (hash, bfd_hash_newfunc, sizeof (struct bfd_hash_entry))) einfo (_("%F%P: bfd_hash_table_init failed: %E\n")); @@ -1364,7 +1428,10 @@ unattached_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED, /* This is called if link_info.notice_all is set, or when a symbol in link_info.notice_hash is found. Symbols are put in notice_hash - using the -y option. */ + using the -y option, while notice_all is set if the --cref option + has been supplied, or if there are any NOCROSSREFS sections in the + linker script; and if plugins are active, since they need to monitor + all references from non-IR files. */ static bfd_boolean notice (struct bfd_link_info *info, @@ -1376,13 +1443,12 @@ notice (struct bfd_link_info *info, if (name == NULL) { if (command_line.cref || nocrossref_list != NULL) - return handle_asneeded_cref (abfd, value); + return handle_asneeded_cref (abfd, (enum notice_asneeded_action) value); return TRUE; } - if (! info->notice_all - || (info->notice_hash != NULL - && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL)) + if (info->notice_hash != NULL + && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL) { if (bfd_is_und_section (section)) einfo ("%B: reference to %s\n", abfd, name);