diff options
Diffstat (limited to 'contrib/binutils/ld/ldmain.c')
-rw-r--r-- | contrib/binutils/ld/ldmain.c | 331 |
1 files changed, 201 insertions, 130 deletions
diff --git a/contrib/binutils/ld/ldmain.c b/contrib/binutils/ld/ldmain.c index d0e0b12..354c41a 100644 --- a/contrib/binutils/ld/ldmain.c +++ b/contrib/binutils/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 + 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. Written by Steve Chamberlain steve@cygnus.com @@ -18,12 +18,11 @@ 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. */ + Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ -#include "bfd.h" #include "sysdep.h" -#include <stdio.h> +#include "bfd.h" #include "safe-ctype.h" #include "libiberty.h" #include "progress.h" @@ -50,7 +49,7 @@ #include <string.h> #ifdef HAVE_SBRK -#ifdef NEED_DECLARATION_SBRK +#if !HAVE_DECL_SBRK extern void *sbrk (); #endif #endif @@ -68,7 +67,7 @@ const char *output_filename = "a.out"; char *program_name; /* The prefix for system library directories. */ -char *ld_sysroot; +const char *ld_sysroot; /* The canonical representation of ld_sysroot. */ char * ld_canon_sysroot; @@ -97,6 +96,10 @@ bfd_boolean whole_archive; actually satisfies some reference in a regular object. */ bfd_boolean as_needed; +/* Nonzero means never create DT_NEEDED entries for dynamic libraries + in DT_NEEDED tags. */ +bfd_boolean add_needed = TRUE; + /* TRUE if we should demangle symbol names. */ bfd_boolean demangling; @@ -104,6 +107,10 @@ args_type command_line; ld_config_type config; +sort_type sort_section; + +static const char *get_sysroot + (int, char **); static char *get_emulation (int, char **); static void set_scripts_dir @@ -131,8 +138,8 @@ static bfd_boolean undefined_symbol (struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma, bfd_boolean); static bfd_boolean reloc_overflow - (struct bfd_link_info *, const char *, const char *, bfd_vma, - bfd *, asection *, bfd_vma); + (struct bfd_link_info *, struct bfd_link_hash_entry *, const char *, + const char *, bfd_vma, bfd *, asection *, bfd_vma); static bfd_boolean reloc_dangerous (struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma); static bfd_boolean unattached_reloc @@ -153,7 +160,10 @@ static struct bfd_link_callbacks link_callbacks = reloc_dangerous, unattached_reloc, notice, - error_handler + einfo, + info_msg, + minfo, + ldlang_override_segment_assignment }; struct bfd_link_info link_info; @@ -166,7 +176,7 @@ remove_output (void) if (output_bfd) bfd_cache_close (output_bfd); if (delete_output_file_on_failure) - unlink (output_filename); + unlink_if_ordinary (output_filename); } } @@ -190,53 +200,26 @@ main (int argc, char **argv) START_PROGRESS (program_name, 0); + expandargv (&argc, &argv); + bfd_init (); bfd_set_error_program_name (program_name); xatexit (remove_output); -#ifdef TARGET_SYSTEM_ROOT_RELOCATABLE - ld_sysroot = make_relative_prefix (program_name, BINDIR, - TARGET_SYSTEM_ROOT); - - if (ld_sysroot) - { - struct stat s; - int res = stat (ld_sysroot, &s) == 0 && S_ISDIR (s.st_mode); - - if (!res) - { - free (ld_sysroot); - ld_sysroot = NULL; - } - } - - if (! ld_sysroot) + /* Set up the sysroot directory. */ + ld_sysroot = get_sysroot (argc, argv); + if (*ld_sysroot) { - ld_sysroot = make_relative_prefix (program_name, TOOLBINDIR, - TARGET_SYSTEM_ROOT); - - if (ld_sysroot) + if (*TARGET_SYSTEM_ROOT == 0) { - struct stat s; - int res = stat (ld_sysroot, &s) == 0 && S_ISDIR (s.st_mode); - - if (!res) - { - free (ld_sysroot); - ld_sysroot = NULL; - } + einfo ("%P%F: this linker was not configured to use sysroots\n"); + ld_sysroot = ""; } + else + ld_canon_sysroot = lrealpath (ld_sysroot); } - - if (! ld_sysroot) -#endif - ld_sysroot = TARGET_SYSTEM_ROOT; - - if (ld_sysroot && *ld_sysroot) - ld_canon_sysroot = lrealpath (ld_sysroot); - if (ld_canon_sysroot) ld_canon_sysroot_len = strlen (ld_canon_sysroot); else @@ -259,21 +242,17 @@ main (int argc, char **argv) } #endif - /* Initialize the data about options. */ - trace_files = trace_file_tries = version_printed = FALSE; - whole_archive = FALSE; config.build_constructors = TRUE; - config.dynamic_link = FALSE; - config.has_shared = FALSE; + config.rpath_separator = ':'; config.split_by_reloc = (unsigned) -1; config.split_by_file = (bfd_size_type) -1; - command_line.force_common_definition = FALSE; - command_line.inhibit_common_definition = FALSE; - command_line.interpreter = NULL; - command_line.rpath = NULL; + config.make_executable = TRUE; + config.magic_demand_paged = TRUE; + config.text_read_only = TRUE; + command_line.warn_mismatch = TRUE; + command_line.warn_search_mismatch = TRUE; command_line.check_section_addresses = TRUE; - command_line.accept_unknown_input_arch = FALSE; /* We initialize DEMANGLING based on the environment variable COLLECT_NO_DEMANGLE. The gcc collect2 program will demangle the @@ -282,58 +261,22 @@ main (int argc, char **argv) interface by default. */ demangling = getenv ("COLLECT_NO_DEMANGLE") == NULL; - link_info.relocatable = FALSE; - link_info.emitrelocations = FALSE; - link_info.task_link = FALSE; - link_info.shared = FALSE; - link_info.pie = FALSE; - link_info.executable = FALSE; - link_info.symbolic = FALSE; - link_info.export_dynamic = FALSE; - link_info.static_link = FALSE; - link_info.traditional_format = FALSE; - link_info.optimize = FALSE; - link_info.unresolved_syms_in_objects = RM_NOT_YET_SET; - link_info.unresolved_syms_in_shared_libs = RM_NOT_YET_SET; - link_info.allow_multiple_definition = FALSE; link_info.allow_undefined_version = TRUE; link_info.keep_memory = TRUE; - link_info.notice_all = FALSE; - link_info.nocopyreloc = FALSE; - link_info.new_dtags = FALSE; link_info.combreloc = TRUE; - link_info.eh_frame_hdr = FALSE; link_info.strip_discarded = TRUE; - link_info.strip = strip_none; - link_info.discard = discard_sec_merge; - link_info.common_skip_ar_aymbols = bfd_link_common_skip_none; + link_info.emit_hash = TRUE; link_info.callbacks = &link_callbacks; - link_info.hash = NULL; - link_info.keep_hash = NULL; - link_info.notice_hash = NULL; - link_info.wrap_hash = NULL; - link_info.input_bfds = NULL; - link_info.create_object_symbols_section = NULL; - link_info.gc_sym_list = NULL; - link_info.base_file = NULL; + link_info.input_bfds_tail = &link_info.input_bfds; /* SVR4 linkers seem to set DT_INIT and DT_FINI based on magic _init and _fini symbols. We are compatible. */ link_info.init_function = "_init"; link_info.fini_function = "_fini"; + link_info.relax_pass = 1; link_info.pei386_auto_import = -1; - link_info.pei386_runtime_pseudo_reloc = FALSE; link_info.spare_dynamic_tags = 5; - link_info.flags = 0; - link_info.flags_1 = 0; - link_info.need_relax_finalize = FALSE; ldfile_add_arch (""); - - config.make_executable = TRUE; - force_make_executable = FALSE; - config.magic_demand_paged = TRUE; - config.text_read_only = TRUE; - emulation = get_emulation (argc, argv); ldemul_choose_mode (emulation); default_target = ldemul_choose_target (argc, argv); @@ -342,11 +285,14 @@ main (int argc, char **argv) lang_has_input_file = FALSE; parse_args (argc, argv); + if (config.hash_table_size != 0) + bfd_hash_set_default_size (config.hash_table_size); + ldemul_set_symbols (); if (link_info.relocatable) { - if (command_line.gc_sections) + if (link_info.gc_sections) einfo ("%P%F: --gc-sections and -r may not be used together\n"); else if (command_line.relax) einfo (_("%P%F: --relax and -r may not be used together\n")); @@ -354,6 +300,43 @@ main (int argc, char **argv) einfo (_("%P%F: -r and -shared may not be used together\n")); } + /* We may have -Bsymbolic, -Bsymbolic-functions, --dynamic-list-data, + --dynamic-list-cpp-new, --dynamic-list-cpp-typeinfo and + --dynamic-list FILE. -Bsymbolic and -Bsymbolic-functions are + for shared libraries. -Bsymbolic overrides all others and vice + versa. */ + switch (command_line.symbolic) + { + case symbolic_unset: + break; + case symbolic: + /* -Bsymbolic is for shared library only. */ + if (link_info.shared) + { + link_info.symbolic = TRUE; + /* Should we free the unused memory? */ + link_info.dynamic_list = NULL; + command_line.dynamic_list = dynamic_list_unset; + } + break; + case symbolic_functions: + /* -Bsymbolic-functions is for shared library only. */ + if (link_info.shared) + command_line.dynamic_list = dynamic_list_data; + break; + } + + switch (command_line.dynamic_list) + { + case dynamic_list_unset: + break; + case dynamic_list_data: + link_info.dynamic_data = TRUE; + case dynamic_list: + link_info.dynamic = TRUE; + break; + } + if (! link_info.shared) { if (command_line.filter_shlib) @@ -379,6 +362,16 @@ main (int argc, char **argv) the -L's in argv have been processed. */ set_scripts_dir (); + /* If we have not already opened and parsed a linker script, + try the default script from command line first. */ + if (saved_script_handle == NULL + && command_line.default_script != NULL) + { + ldfile_open_command_file (command_line.default_script); + parser_input = input_script; + yyparse (); + } + /* If we have not already opened and parsed a linker script read the emulation's appropriate default script. */ if (saved_script_handle == NULL) @@ -481,6 +474,8 @@ main (int argc, char **argv) if (nocrossref_list != NULL) check_nocrossrefs (); + lang_finish (); + /* Even if we're producing relocatable output, some non-fatal errors should be reported in the exit status. (What non-fatal errors, if any, do we want to ignore for relocatable output?) */ @@ -568,6 +563,51 @@ main (int argc, char **argv) return 0; } +/* If the configured sysroot is relocatable, try relocating it based on + default prefix FROM. Return the relocated directory if it exists, + otherwise return null. */ + +static char * +get_relative_sysroot (const char *from ATTRIBUTE_UNUSED) +{ +#ifdef TARGET_SYSTEM_ROOT_RELOCATABLE + char *path; + struct stat s; + + path = make_relative_prefix (program_name, from, TARGET_SYSTEM_ROOT); + if (path) + { + if (stat (path, &s) == 0 && S_ISDIR (s.st_mode)) + return path; + free (path); + } +#endif + return 0; +} + +/* Return the sysroot directory. Return "" if no sysroot is being used. */ + +static const char * +get_sysroot (int argc, char **argv) +{ + int i; + const char *path; + + for (i = 1; i < argc; i++) + if (CONST_STRNEQ (argv[i], "--sysroot=")) + return argv[i] + strlen ("--sysroot="); + + path = get_relative_sysroot (BINDIR); + if (path) + return path; + + path = get_relative_sysroot (TOOLBINDIR); + if (path) + return path; + + return TARGET_SYSTEM_ROOT; +} + /* We need to find any explicitly given emulation in order to initialize the state that's needed by the lex&yacc argument parser (parse_args). */ @@ -583,7 +623,7 @@ get_emulation (int argc, char **argv) for (i = 1; i < argc; i++) { - if (!strncmp (argv[i], "-m", 2)) + if (CONST_STRNEQ (argv[i], "-m")) { if (argv[i][2] == '\0') { @@ -737,9 +777,10 @@ add_ysym (const char *name) if (link_info.notice_hash == NULL) { link_info.notice_hash = xmalloc (sizeof (struct bfd_hash_table)); - if (! bfd_hash_table_init_n (link_info.notice_hash, - bfd_hash_newfunc, - 61)) + if (!bfd_hash_table_init_n (link_info.notice_hash, + bfd_hash_newfunc, + sizeof (struct bfd_hash_entry), + 61)) einfo (_("%P%F: bfd_hash_table_init failed: %E\n")); } @@ -755,9 +796,10 @@ add_wrap (const char *name) if (link_info.wrap_hash == NULL) { link_info.wrap_hash = xmalloc (sizeof (struct bfd_hash_table)); - if (! bfd_hash_table_init_n (link_info.wrap_hash, - bfd_hash_newfunc, - 61)) + if (!bfd_hash_table_init_n (link_info.wrap_hash, + bfd_hash_newfunc, + sizeof (struct bfd_hash_entry), + 61)) einfo (_("%P%F: bfd_hash_table_init failed: %E\n")); } @@ -787,7 +829,8 @@ add_keepsyms_file (const char *filename) } link_info.keep_hash = xmalloc (sizeof (struct bfd_hash_table)); - if (! bfd_hash_table_init (link_info.keep_hash, bfd_hash_newfunc)) + 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; @@ -835,7 +878,7 @@ add_keepsyms_file (const char *filename) a link. */ static bfd_boolean -add_archive_element (struct bfd_link_info *info ATTRIBUTE_UNUSED, +add_archive_element (struct bfd_link_info *info, bfd *abfd, const char *name) { @@ -866,7 +909,7 @@ add_archive_element (struct bfd_link_info *info ATTRIBUTE_UNUSED, bfd *from; int len; - h = bfd_link_hash_lookup (link_info.hash, name, FALSE, FALSE, TRUE); + h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE); if (h == NULL) from = NULL; @@ -1107,7 +1150,7 @@ constructor_callback (struct bfd_link_info *info, /* 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 - && (link_info.relocatable + && (info->relocatable || bfd_reloc_type_lookup (abfd, BFD_RELOC_CTOR) == NULL)) einfo (_("%P%F: BFD backend error: BFD_RELOC_CTOR unsupported\n")); @@ -1163,11 +1206,11 @@ warning_callback (struct bfd_link_info *info ATTRIBUTE_UNUSED, return TRUE; if (section != NULL) - einfo ("%C: %s\n", abfd, section, address, warning); + einfo ("%C: %s%s\n", abfd, section, address, _("warning: "), warning); else if (abfd == NULL) - einfo ("%P: %s\n", warning); + einfo ("%P: %s%s\n", _("warning: "), warning); else if (symbol == NULL) - einfo ("%B: %s\n", abfd, warning); + einfo ("%B: %s%s\n", abfd, _("warning: "), warning); else { lang_input_statement_type *entry; @@ -1205,7 +1248,7 @@ warning_callback (struct bfd_link_info *info ATTRIBUTE_UNUSED, bfd_map_over_sections (abfd, warning_find_reloc, &info); if (! info.found) - einfo ("%B: %s\n", abfd, warning); + einfo ("%B: %s%s\n", abfd, _("warning: "), warning); if (entry == NULL) free (asymbols); @@ -1253,7 +1296,8 @@ warning_find_reloc (bfd *abfd, asection *sec, void *iarg) && strcmp (bfd_asymbol_name (*q->sym_ptr_ptr), info->symbol) == 0) { /* We found a reloc for the symbol we are looking for. */ - einfo ("%C: %s\n", abfd, sec, q->address, info->warning); + einfo ("%C: %s%s\n", abfd, sec, q->address, _("warning: "), + info->warning); info->found = TRUE; break; } @@ -1285,7 +1329,8 @@ undefined_symbol (struct bfd_link_info *info ATTRIBUTE_UNUSED, if (hash == NULL) { hash = xmalloc (sizeof (struct bfd_hash_table)); - if (! bfd_hash_table_init (hash, bfd_hash_newfunc)) + if (!bfd_hash_table_init (hash, bfd_hash_newfunc, + sizeof (struct bfd_hash_entry))) einfo (_("%F%P: bfd_hash_table_init failed: %E\n")); } @@ -1372,6 +1417,7 @@ int overflow_cutoff_limit = 10; static bfd_boolean reloc_overflow (struct bfd_link_info *info ATTRIBUTE_UNUSED, + struct bfd_link_hash_entry *entry, const char *name, const char *reloc_name, bfd_vma addend, @@ -1382,10 +1428,7 @@ reloc_overflow (struct bfd_link_info *info ATTRIBUTE_UNUSED, if (overflow_cutoff_limit == -1) return TRUE; - if (abfd == NULL) - einfo (_("%P%X: generated")); - else - einfo ("%X%C:", abfd, section, address); + einfo ("%X%C:", abfd, section, address); if (overflow_cutoff_limit >= 0 && overflow_cutoff_limit-- == 0) @@ -1394,7 +1437,34 @@ reloc_overflow (struct bfd_link_info *info ATTRIBUTE_UNUSED, return TRUE; } - einfo (_(" relocation truncated to fit: %s %T"), reloc_name, name); + if (entry) + { + while (entry->type == bfd_link_hash_indirect + || entry->type == bfd_link_hash_warning) + entry = entry->u.i.link; + switch (entry->type) + { + case bfd_link_hash_undefined: + case bfd_link_hash_undefweak: + einfo (_(" relocation truncated to fit: %s against undefined symbol `%T'"), + reloc_name, entry->root.string); + break; + case bfd_link_hash_defined: + case bfd_link_hash_defweak: + einfo (_(" relocation truncated to fit: %s against symbol `%T' defined in %A section in %B"), + reloc_name, entry->root.string, + entry->u.def.section, + entry->u.def.section == bfd_abs_section_ptr + ? output_bfd : entry->u.def.section->owner); + break; + default: + abort (); + break; + } + } + else + einfo (_(" relocation truncated to fit: %s against `%T'"), + reloc_name, name); if (addend != 0) einfo ("+%v", addend); einfo ("\n"); @@ -1410,11 +1480,8 @@ reloc_dangerous (struct bfd_link_info *info ATTRIBUTE_UNUSED, asection *section, bfd_vma address) { - if (abfd == NULL) - einfo (_("%P%X: generated")); - else - einfo ("%X%C:", abfd, section, address); - einfo (_("dangerous relocation: %s\n"), message); + einfo (_("%X%C: dangerous relocation: %s\n"), + abfd, section, address, message); return TRUE; } @@ -1428,11 +1495,8 @@ unattached_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED, asection *section, bfd_vma address) { - if (abfd == 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); + einfo (_("%X%C: reloc refers to symbol `%T' which is not being output\n"), + abfd, section, address, name); return TRUE; } @@ -1447,6 +1511,13 @@ notice (struct bfd_link_info *info, asection *section, bfd_vma value) { + if (name == NULL) + { + if (command_line.cref || nocrossref_list != NULL) + return handle_asneeded_cref (abfd, value); + return TRUE; + } + if (! info->notice_all || (info->notice_hash != NULL && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL)) |