/* Main program of GNU linker.
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005, 2006
+ 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
Written by Steve Chamberlain steve@cygnus.com
- 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
+ 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 2, or (at your option)
- any later version.
+ 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,
+ 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, 51 Franklin Street - Fifth Floor, Boston, MA
- 02110-1301, USA. */
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 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"
/* EXPORTS */
+FILE *saved_script_handle = NULL;
+FILE *previous_script_handle = NULL;
+bfd_boolean force_make_executable = FALSE;
+
char *default_target;
const char *output_filename = "a.out";
char * ld_canon_sysroot;
int ld_canon_sysroot_len;
-/* The file that we're creating. */
-bfd *output_bfd = 0;
-
/* Set by -G argument, for MIPS ECOFF target. */
int g_switch_value = 8;
/* 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;
(int, char **);
static char *get_emulation
(int, char **);
-static void set_scripts_dir
- (void);
static bfd_boolean add_archive_element
(struct bfd_link_info *, bfd *, const char *);
static bfd_boolean multiple_definition
reloc_dangerous,
unattached_reloc,
notice,
- einfo
+ einfo,
+ info_msg,
+ minfo,
+ ldlang_override_segment_assignment
};
struct bfd_link_info link_info;
{
if (output_filename)
{
- if (output_bfd)
- bfd_cache_close (output_bfd);
+ if (link_info.output_bfd)
+ bfd_cache_close (link_info.output_bfd);
if (delete_output_file_on_failure)
unlink_if_ordinary (output_filename);
}
}
#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;
- config.hash_table_size = 0;
- command_line.force_common_definition = FALSE;
- command_line.inhibit_common_definition = FALSE;
- command_line.interpreter = NULL;
- command_line.rpath = NULL;
- command_line.warn_mismatch = TRUE;
- command_line.check_section_addresses = TRUE;
- command_line.accept_unknown_input_arch = FALSE;
+ config.make_executable = TRUE;
+ config.magic_demand_paged = TRUE;
+ config.text_read_only = TRUE;
- sort_section = none;
+ 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
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.create_default_symver = FALSE;
- link_info.default_imported_symver = FALSE;
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.relro = 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.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.emit_hash = TRUE;
- link_info.emit_gnu_hash = FALSE;
+ link_info.callbacks = &link_callbacks;
+ 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.relax_pass = 1;
- link_info.warn_shared_textrel = FALSE;
- link_info.gc_sections = FALSE;
- link_info.print_gc_sections = FALSE;
- link_info.dynamic = NULL;
- link_info.reduce_memory_overheads = FALSE;
-
- config.maxpagesize = 0;
- config.commonpagesize = 0;
+ link_info.path_separator = ':';
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);
+ 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;
if (config.hash_table_size != 0)
bfd_hash_set_default_size (config.hash_table_size);
- if (config.maxpagesize != 0)
- bfd_emul_set_maxpagesize (default_target, config.maxpagesize);
-
- if (config.commonpagesize != 0)
- bfd_emul_set_commonpagesize (default_target,
- config.commonpagesize);
-
ldemul_set_symbols ();
if (link_info.relocatable)
{
- 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"));
+ if (command_line.check_section_addresses < 0)
+ command_line.check_section_addresses = 0;
if (link_info.shared)
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)
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 ();
+ /* 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. */
char *s = ldemul_get_script (&isfile);
if (isfile)
- ldfile_open_command_file (s);
+ ldfile_open_default_command_file (s);
else
{
lex_string = s;
{
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)
/* Print error messages for any missing symbols, for any warning
symbols, and possibly multiple definitions. */
if (link_info.relocatable)
- output_bfd->flags &= ~EXEC_P;
+ link_info.output_bfd->flags &= ~EXEC_P;
else
- output_bfd->flags |= EXEC_P;
+ link_info.output_bfd->flags |= EXEC_P;
ldwrite ();
}
else
{
- if (! bfd_close (output_bfd))
- einfo (_("%F%B: final close failed: %E\n"), output_bfd);
+ if (! bfd_close (link_info.output_bfd))
+ einfo (_("%F%B: final close failed: %E\n"), link_info.output_bfd);
/* If the --force-exe-suffix is enabled, and we're making an
executable file and it doesn't end in .exe, copy it to one
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");
if (config.stats)
{
#ifdef HAVE_SBRK
- char *lim = sbrk (0);
+ char *lim = (char *) sbrk (0);
#endif
long run_time = get_run_time () - start_time;
return emulation;
}
-/* If directory DIR contains an "ldscripts" subdirectory,
- add DIR to the library search path and return TRUE,
- else return FALSE. */
-
-static bfd_boolean
-check_for_scripts_dir (char *dir)
-{
- size_t dirlen;
- char *buf;
- struct stat s;
- bfd_boolean res;
-
- dirlen = strlen (dir);
- /* sizeof counts the terminating NUL. */
- buf = xmalloc (dirlen + sizeof ("/ldscripts"));
- sprintf (buf, "%s/ldscripts", dir);
-
- res = stat (buf, &s) == 0 && S_ISDIR (s.st_mode);
- free (buf);
- if (res)
- ldfile_add_library_path (dir, FALSE);
- return res;
-}
-
-/* Set the default directory for finding script files.
- Libraries will be searched for here too, but that's ok.
- We look for the "ldscripts" directory in:
-
- SCRIPTDIR (passed from Makefile)
- (adjusted according to the current location of the binary)
- SCRIPTDIR (passed from Makefile)
- the dir where this program is (for using it from the build tree)
- the dir where this program is/../lib
- (for installing the tool suite elsewhere). */
-
-static void
-set_scripts_dir (void)
-{
- char *end, *dir;
- size_t dirlen;
- bfd_boolean found;
-
- dir = make_relative_prefix (program_name, BINDIR, SCRIPTDIR);
- if (dir)
- {
- found = check_for_scripts_dir (dir);
- free (dir);
- if (found)
- return;
- }
-
- dir = make_relative_prefix (program_name, TOOLBINDIR, SCRIPTDIR);
- if (dir)
- {
- found = check_for_scripts_dir (dir);
- free (dir);
- if (found)
- return;
- }
-
- if (check_for_scripts_dir (SCRIPTDIR))
- /* We've been installed normally. */
- return;
-
- /* Look for "ldscripts" in the dir where our binary is. */
- end = strrchr (program_name, '/');
-#ifdef HAVE_DOS_BASED_FILE_SYSTEM
- {
- /* We could have \foo\bar, or /foo\bar. */
- char *bslash = strrchr (program_name, '\\');
-
- if (end == NULL || (bslash != NULL && bslash > end))
- end = bslash;
- }
-#endif
-
- if (end == NULL)
- /* Don't look for ldscripts in the current directory. There is
- too much potential for confusion. */
- return;
-
- dirlen = end - program_name;
- /* Make a copy of program_name in dir.
- Leave room for later "/../lib". */
- dir = xmalloc (dirlen + 8);
- strncpy (dir, program_name, dirlen);
- dir[dirlen] = '\0';
-
- if (check_for_scripts_dir (dir))
- {
- free (dir);
- return;
- }
-
- /* Look for "ldscripts" in <the dir where our binary is>/../lib. */
- strcpy (dir + dirlen, "/../lib");
- check_for_scripts_dir (dir);
- free (dir);
-}
-
void
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),
{
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),
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)
if (len >= bufsize)
{
bufsize *= 2;
- buf = xrealloc (buf, bufsize);
+ buf = (char *) xrealloc (buf, bufsize);
}
c = getc (file);
}
{
lang_input_statement_type *input;
- input = xmalloc (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;
- input->asymbols = NULL;
- input->next = NULL;
- input->just_syms_flag = FALSE;
- input->loaded = FALSE;
- input->search_dirs_flag = FALSE;
-
- /* FIXME: The following fields are not set: header.next,
- header.type, closed, passive_position, symbol_count,
- next_real_file, is_archive, target, real. 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 (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;
/* 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
+ if (bfd_reloc_type_lookup (link_info.output_bfd, BFD_RELOC_CTOR) == NULL
&& (info->relocatable
|| bfd_reloc_type_lookup (abfd, BFD_RELOC_CTOR) == NULL))
einfo (_("%P%F: BFD backend error: BFD_RELOC_CTOR unsupported\n"));
einfo ("%B: %s%s\n", abfd, _("warning: "), warning);
else
{
- lang_input_statement_type *entry;
- asymbol **asymbols;
- struct warning_callback_info info;
+ struct warning_callback_info cinfo;
/* Look through the relocs to see if we can find a plausible
address. */
- entry = (lang_input_statement_type *) abfd->usrdata;
- if (entry != NULL && entry->asymbols != NULL)
- asymbols = entry->asymbols;
- else
- {
- long symsize;
- long symbol_count;
-
- symsize = bfd_get_symtab_upper_bound (abfd);
- if (symsize < 0)
- einfo (_("%B%F: could not read symbols: %E\n"), abfd);
- asymbols = xmalloc (symsize);
- symbol_count = bfd_canonicalize_symtab (abfd, asymbols);
- if (symbol_count < 0)
- einfo (_("%B%F: could not read symbols: %E\n"), abfd);
- if (entry != NULL)
- {
- entry->asymbols = asymbols;
- entry->symbol_count = symbol_count;
- }
- }
- info.found = FALSE;
- info.warning = warning;
- info.symbol = symbol;
- info.asymbols = asymbols;
- bfd_map_over_sections (abfd, warning_find_reloc, &info);
+ if (!bfd_generic_link_read_symbols (abfd))
+ einfo (_("%B%F: could not read symbols: %E\n"), abfd);
- if (! info.found)
- einfo ("%B: %s%s\n", abfd, _("warning: "), warning);
+ 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 (entry == NULL)
- free (asymbols);
+ if (! cinfo.found)
+ einfo ("%B: %s%s\n", abfd, _("warning: "), warning);
}
return TRUE;
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;
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);
/* 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"));
reloc_name, entry->root.string,
entry->u.def.section,
entry->u.def.section == bfd_abs_section_ptr
- ? output_bfd : entry->u.def.section->owner);
+ ? link_info.output_bfd : entry->u.def.section->owner);
break;
default:
abort ();
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;
}