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 <stdio.h>
#include "libiberty.h"
+#include "progress.h"
#include "bfdlink.h"
#include "config.h"
#include <string.h>
+/* 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));
instead of complaining if no input files are given. */
boolean version_printed;
+/* Nonzero means link in every member of an archive. */
+boolean whole_archive;
+
args_type command_line;
ld_config_type config;
program_name = argv[0];
xmalloc_set_program_name (program_name);
+ START_PROGRESS (program_name, 0);
+
bfd_init ();
xatexit (remove_output);
/* Initialize the data about options. */
trace_files = trace_file_tries = version_printed = 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.symbolic = false;
link_info.strip = strip_none;
link_info.discard = discard_none;
link_info.lprefix_len = 1;
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 ("");
{
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.strip == strip_all)
- einfo ("%P%F: -r and -s 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
if (isfile)
ldfile_open_command_file (s);
else
- lex_redirect (s);
+ {
+ if (trace_file_tries)
+ {
+ info_msg ("using internal linker script:\n");
+ info_msg ("==================================================\n");
+ info_msg (s);
+ info_msg ("\n==================================================\n");
+ }
+ lex_redirect (s);
+ }
parser_input = input_script;
yyparse ();
}
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);
}
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: %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. */
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 */
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;
}
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;
}
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
{
{
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);
}
}
#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
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;
}
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;
}