X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=ld%2Fldmain.c;h=a0f5eb5c157d5702b1955231c5af33ccf08909a2;hb=943fbd5bd520934ca3a26abb2d5cfbdd2a7659ec;hp=f153ceb01b60f01c4c713197fc0ac5de7c101cd5;hpb=52a8ebfe04a89a747b014ab2eaa96968bc346360;p=deliverable%2Fbinutils-gdb.git diff --git a/ld/ldmain.c b/ld/ldmain.c index f153ceb01b..a0f5eb5c15 100644 --- a/ld/ldmain.c +++ b/ld/ldmain.c @@ -16,12 +16,14 @@ 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ +the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "bfd.h" #include "sysdep.h" #include +#include "libiberty.h" +#include "progress.h" #include "bfdlink.h" #include "config.h" @@ -44,6 +46,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include +/* Use sbrk() except on specific OS types */ +#if !defined(__amigados__) && !defined(WINDOWS_NT) +#define HAVE_SBRK +#endif + static char *get_emulation PARAMS ((int, char **)); static void set_scripts_dir PARAMS ((void)); @@ -71,8 +78,8 @@ boolean trace_file_tries; instead of complaining if no input files are given. */ boolean version_printed; -/* 1 => write load map. */ -boolean write_map; +/* Nonzero means link in every member of an archive. */ +boolean whole_archive; args_type command_line; @@ -92,11 +99,10 @@ static boolean multiple_common PARAMS ((struct bfd_link_info *, bfd_vma)); static boolean add_to_set PARAMS ((struct bfd_link_info *, struct bfd_link_hash_entry *, - unsigned int bitsize, + bfd_reloc_code_real_type, bfd *, asection *, bfd_vma)); static boolean constructor_callback PARAMS ((struct bfd_link_info *, boolean constructor, - unsigned int bitsize, const char *name, bfd *, asection *, bfd_vma)); static boolean warning_callback PARAMS ((struct bfd_link_info *, @@ -153,19 +159,27 @@ main (argc, argv) long start_time = get_run_time (); program_name = argv[0]; + xmalloc_set_program_name (program_name); + + START_PROGRESS (program_name, 0); bfd_init (); - atexit (remove_output); + xatexit (remove_output); /* Initialize the data about options. */ trace_files = trace_file_tries = version_printed = false; - write_map = false; + whole_archive = false; + config.traditional_format = false; config.build_constructors = true; + config.dynamic_link = false; command_line.force_common_definition = false; + command_line.interpreter = NULL; + command_line.rpath = NULL; link_info.callbacks = &link_callbacks; link_info.relocateable = false; + link_info.shared = false; link_info.strip = strip_none; link_info.discard = discard_none; link_info.lprefix_len = 1; @@ -176,6 +190,14 @@ main (argc, argv) link_info.hash = NULL; link_info.keep_hash = NULL; link_info.notice_hash = NULL; + link_info.subsystem = console; + link_info.stack_heap_parameters.stack_defined = false; + link_info.stack_heap_parameters.heap_defined = false; + link_info.stack_heap_parameters.stack_reserve = 0; + link_info.stack_heap_parameters.stack_commit = 0; + link_info.stack_heap_parameters.heap_reserve = 0; + link_info.stack_heap_parameters.heap_commit = 0; + ldfile_add_arch (""); @@ -193,6 +215,26 @@ main (argc, argv) lang_has_input_file = false; parse_args (argc, argv); + if (link_info.relocateable) + { + if (command_line.relax) + einfo ("%P%F: -relax and -r may not be used together\n"); + if (config.dynamic_link) + einfo ("%P%F: -r and -call_shared may not be used together\n"); + if (link_info.shared) + einfo ("%P%F: -r and -shared may not be used together\n"); + } + + /* Treat ld -r -s as ld -r -S -x (i.e., strip all local symbols). I + don't see how else this can be handled, since in this case we + must preserve all externally visible symbols. */ + if (link_info.relocateable && link_info.strip == strip_all) + { + link_info.strip = strip_debugger; + if (link_info.discard == discard_none) + link_info.discard = discard_all; + } + /* This essentially adds another -L directory so this must be done after the -L's in argv have been processed. */ set_scripts_dir (); @@ -204,22 +246,22 @@ main (argc, argv) char *s = ldemul_get_script (&isfile); if (isfile) + ldfile_open_command_file (s); + else { - /* sizeof counts the terminating NUL. */ - size_t size = strlen (s) + sizeof ("-T "); - char *buf = (char *) xmalloc(size); - sprintf (buf, "-T %s", s); - parse_line (buf, 0); - free (buf); + if (trace_file_tries) + { + info_msg ("using internal linker script:\n"); + info_msg ("==================================================\n"); + info_msg (s); + info_msg ("\n==================================================\n"); + } + lex_redirect (s); } - else - parse_line (s, 1); + parser_input = input_script; + yyparse (); } - if (link_info.relocateable && command_line.relax) - { - einfo ("%P%F: -relax and -r may not be used together\n"); - } lang_final (); if (lang_has_input_file == false) @@ -248,6 +290,7 @@ main (argc, argv) config.map_file = fopen (config.map_filename, FOPEN_WT); if (config.map_file == (FILE *) NULL) { + bfd_set_error (bfd_error_system_call); einfo ("%P%F: cannot open map file %s: %E\n", config.map_filename); } @@ -299,19 +342,26 @@ main (argc, argv) } else { - bfd_close (output_bfd); + if (! bfd_close (output_bfd)) + einfo ("%F%B: final close failed: %E\n", output_bfd); } + END_PROGRESS (program_name); + if (config.stats) { extern char **environ; +#ifdef HAVE_SBRK char *lim = (char *) sbrk (0); +#endif long run_time = get_run_time () - start_time; - fprintf (stderr, "%s: total time in link: %d.%06d\n", + 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 } /* Prevent remove_output from doing anything, after a successful link. */ @@ -365,6 +415,12 @@ get_emulation (argc, argv) the arguments and hope that nobody ever creates emulations named ips1, ips2 or ips3. */ } + else if (strcmp (argv[i], "-m486") == 0) + { + /* FIXME: The argument -m486 is passed to the linker on + some Linux systems. Hope that nobody creates an + emulation named 486. */ + } else { /* -mEMUL */ @@ -397,7 +453,7 @@ check_for_scripts_dir (dir) res = stat (buf, &s) == 0 && S_ISDIR (s.st_mode); free (buf); if (res) - ldfile_add_library_path (dir); + ldfile_add_library_path (dir, false); return res; } @@ -483,7 +539,7 @@ add_keepsyms_file (filename) file = fopen (filename, "r"); if (file == (FILE *) NULL) { - bfd_error = system_call_error; + bfd_set_error (bfd_error_system_call); einfo ("%X%P: %s: %E", filename); return; } @@ -552,27 +608,22 @@ add_archive_element (info, abfd, name) input->local_sym_name = abfd->filename; input->the_bfd = abfd; input->asymbols = NULL; - input->subfiles = NULL; input->next = NULL; input->just_syms_flag = false; input->loaded = false; - input->chain = NULL; - - /* FIXME: This is wrong. It should point to an entry for the - archive itself. However, it doesn't seem to matter. */ - input->superfile = NULL; + input->search_dirs_flag = false; /* FIXME: The following fields are not set: header.next, - header.type, closed, passive_position, symbol_count, total_size, - next_real_file, is_archive, search_dirs_flag, target, real, - common_section, common_output_section, complained. This bit of - code is from the old decode_library_subfile function. I don't - know whether any of those fields matters. */ + header.type, closed, passive_position, symbol_count, + next_real_file, is_archive, target, real, common_section, + common_output_section, complained. This bit of code is from the + old decode_library_subfile function. I don't know whether any of + those fields matters. */ ldlang_add_file (input); - if (write_map) - info_msg ("%s needed due to %T\n", abfd->filename, name); + if (config.map_file != (FILE *) NULL) + minfo ("%s needed due to %T\n", abfd->filename, name); if (trace_files || trace_file_tries) info_msg ("%I\n", input); @@ -598,7 +649,7 @@ multiple_definition (info, name, obfd, osec, oval, nbfd, nsec, nval) einfo ("%X%C: multiple definition of `%T'\n", nbfd, nsec, nval, name); if (obfd != (bfd *) NULL) - einfo ("%C: first defined here\n", obfd, osec, oval); + einfo ("%D: first defined here\n", obfd, osec, oval); return true; } @@ -622,19 +673,25 @@ multiple_common (info, name, obfd, otype, osize, nbfd, ntype, nsize) if (! config.warn_common) return true; - if (ntype == bfd_link_hash_defined) + if (ntype == bfd_link_hash_defined + || ntype == bfd_link_hash_defweak + || ntype == bfd_link_hash_indirect) { ASSERT (otype == bfd_link_hash_common); einfo ("%B: warning: definition of `%T' overriding common\n", nbfd, name); - einfo ("%B: warning: common is here\n", obfd); + if (obfd != NULL) + einfo ("%B: warning: common is here\n", obfd); } - else if (otype == bfd_link_hash_defined) + else if (otype == bfd_link_hash_defined + || otype == bfd_link_hash_defweak + || otype == bfd_link_hash_indirect) { ASSERT (ntype == bfd_link_hash_common); einfo ("%B: warning: common of `%T' overridden by definition\n", nbfd, name); - einfo ("%B: warning: defined here\n", obfd); + if (obfd != NULL) + einfo ("%B: warning: defined here\n", obfd); } else { @@ -643,18 +700,21 @@ multiple_common (info, name, obfd, otype, osize, nbfd, ntype, nsize) { einfo ("%B: warning: common of `%T' overridden by larger common\n", nbfd, name); - einfo ("%B: warning: larger common is here\n", obfd); + if (obfd != NULL) + einfo ("%B: warning: larger common is here\n", obfd); } else if (nsize > osize) { einfo ("%B: warning: common of `%T' overriding smaller common\n", nbfd, name); - einfo ("%B: warning: smaller common is here\n", obfd); + if (obfd != NULL) + einfo ("%B: warning: smaller common is here\n", obfd); } else { einfo ("%B: warning: multiple common of `%T'\n", nbfd, name); - einfo ("%B: warning: previous common is here\n", obfd); + if (obfd != NULL) + einfo ("%B: warning: previous common is here\n", obfd); } } @@ -667,15 +727,28 @@ multiple_common (info, name, obfd, otype, osize, nbfd, ntype, nsize) /*ARGSUSED*/ static boolean -add_to_set (info, h, bitsize, abfd, section, value) +add_to_set (info, h, reloc, abfd, section, value) struct bfd_link_info *info; struct bfd_link_hash_entry *h; - unsigned int bitsize; + bfd_reloc_code_real_type reloc; bfd *abfd; asection *section; bfd_vma value; { - ldctor_add_set_entry (h, bitsize, section, value); + if (! config.build_constructors) + return true; + + ldctor_add_set_entry (h, reloc, section, value); + + if (h->type == bfd_link_hash_new) + { + h->type = bfd_link_hash_undefined; + h->u.undef.abfd = abfd; + /* We don't call bfd_link_add_undef to add this to the list of + undefined symbols because we are going to define it + ourselves. */ + } + return true; } @@ -685,10 +758,9 @@ add_to_set (info, h, bitsize, abfd, section, value) adding an element to a set, but less general. */ static boolean -constructor_callback (info, constructor, bitsize, name, abfd, section, value) +constructor_callback (info, constructor, name, abfd, section, value) struct bfd_link_info *info; boolean constructor; - unsigned int bitsize; const char *name; bfd *abfd; asection *section; @@ -701,6 +773,11 @@ constructor_callback (info, constructor, bitsize, name, abfd, section, value) if (! config.build_constructors) return true; + /* Ensure that BFD_RELOC_CTOR exists now, so that we can give a + useful error message. */ + if (bfd_reloc_type_lookup (output_bfd, BFD_RELOC_CTOR) == NULL) + einfo ("%P%F: BFD backend error: BFD_RELOC_CTOR unsupported"); + set_name = (char *) alloca (1 + sizeof "__CTOR_LIST__"); s = set_name; if (bfd_get_symbol_leading_char (abfd) != '\0') @@ -710,8 +787,9 @@ constructor_callback (info, constructor, bitsize, name, abfd, section, value) else strcpy (s, "__DTOR_LIST__"); - if (write_map) - info_msg ("Adding %s to constructor/destructor set %s\n", name, set_name); + if (config.map_file != (FILE *) NULL) + fprintf (config.map_file, + "Adding %s to constructor/destructor set %s\n", name, set_name); h = bfd_link_hash_lookup (info->hash, set_name, true, true, true); if (h == (struct bfd_link_hash_entry *) NULL) @@ -725,7 +803,7 @@ constructor_callback (info, constructor, bitsize, name, abfd, section, value) ourselves. */ } - ldctor_add_set_entry (h, bitsize, section, value); + ldctor_add_set_entry (h, BFD_RELOC_CTOR, section, value); return true; } @@ -757,6 +835,27 @@ undefined_symbol (info, name, abfd, section, address) #define MAX_ERRORS_IN_A_ROW 5 + if (config.warn_once) + { + static struct bfd_hash_table *hash; + + /* Only warn once about a particular undefined symbol. */ + + if (hash == NULL) + { + hash = ((struct bfd_hash_table *) + xmalloc (sizeof (struct bfd_hash_table))); + if (! bfd_hash_table_init (hash, bfd_hash_newfunc)) + einfo ("%F%P: bfd_hash_table_init failed: %E\n"); + } + + if (bfd_hash_lookup (hash, name, false, false) != NULL) + return true; + + if (bfd_hash_lookup (hash, name, true, true) == NULL) + einfo ("%F%P: bfd_hash_lookup failed: %E\n"); + } + /* We never print more than a reasonable number of errors in a row for a single symbol. */ if (error_name != (char *) NULL @@ -770,12 +869,24 @@ undefined_symbol (info, name, abfd, section, address) error_name = buystring (name); } - if (error_count < MAX_ERRORS_IN_A_ROW) - einfo ("%X%C: undefined reference to `%T'\n", - abfd, section, address, name); - else if (error_count == MAX_ERRORS_IN_A_ROW) - einfo ("%C: more undefined references to `%T' follow\n", - abfd, section, address, name); + if (section != NULL) + { + if (error_count < MAX_ERRORS_IN_A_ROW) + einfo ("%X%C: undefined reference to `%T'\n", + abfd, section, address, name); + else if (error_count == MAX_ERRORS_IN_A_ROW) + einfo ("%D: more undefined references to `%T' follow\n", + abfd, section, address, name); + } + else + { + if (error_count < MAX_ERRORS_IN_A_ROW) + einfo ("%X%B: undefined reference to `%T'\n", + abfd, name); + else if (error_count == MAX_ERRORS_IN_A_ROW) + einfo ("%B: more undefined references to `%T' follow\n", + abfd, name); + } return true; } @@ -793,8 +904,11 @@ reloc_overflow (info, name, reloc_name, addend, abfd, section, address) asection *section; bfd_vma address; { - einfo ("%X%C: relocation truncated to fit: %s %T", abfd, section, - address, reloc_name, name); + if (abfd == (bfd *) NULL) + einfo ("%P%X: generated"); + else + einfo ("%X%C:", abfd, section, address); + einfo (" relocation truncated to fit: %s %T", reloc_name, name); if (addend != 0) einfo ("+%v", addend); einfo ("\n"); @@ -812,7 +926,11 @@ reloc_dangerous (info, message, abfd, section, address) asection *section; bfd_vma address; { - einfo ("%X%C: dangerous relocation: %s\n", abfd, section, address, message); + if (abfd == (bfd *) NULL) + einfo ("%P%X: generated"); + else + einfo ("%X%C:", abfd, section, address); + einfo ("dangerous relocation: %s\n", message); return true; } @@ -828,8 +946,11 @@ unattached_reloc (info, name, abfd, section, address) asection *section; bfd_vma address; { - einfo ("%X%C: reloc refers to symbol `%T' which is not being output\n", - abfd, section, address, name); + if (abfd == (bfd *) NULL) + einfo ("%P%X: generated"); + else + einfo ("%X%C:", abfd, section, address); + einfo (" reloc refers to symbol `%T' which is not being output\n", name); return true; } @@ -846,7 +967,7 @@ notice_ysym (info, name, abfd, section, value) bfd_vma value; { einfo ("%B: %s %s\n", abfd, - section != &bfd_und_section ? "definition of" : "reference to", + bfd_is_und_section (section) ? "reference to" : "definition of", name); return true; }