/* ldmisc.c
- Copyright (C) 1991, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000, 2002
+ Free Software Foundation, Inc.
Written by Steve Chamberlain of Cygnus Support.
This file is part of GLD, the Gnu Linker.
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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+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. */
#include "bfd.h"
#include "sysdep.h"
-#include <demangle.h>
+#include "libiberty.h"
+#include "demangle.h"
#ifdef ANSI_PROTOTYPES
#include <stdarg.h>
-#define USE_STDARG 1
#else
#include <varargs.h>
-#define USE_STDARG 0
#endif
#include "ld.h"
#include "ldmain.h"
#include "ldfile.h"
-
-#if USE_STDARG
-static void finfo PARAMS ((FILE *, const char *, ...));
-#else
-/* VARARGS*/
-static void finfo ();
-#endif
-static const char *demangle PARAMS ((const char *string,
- int remove_underscore));
+static void vfinfo PARAMS ((FILE *, const char *, va_list));
/*
%% literal %
%X no object output, fail return
%V hex bfd_vma
%v hex bfd_vma, no leading zeros
+ %W hex bfd_vma with 0x with no leading zeros taking up 8 spaces
%C clever filename:linenumber with function
%D like %C, but no function name
+ %G like %D, but only function name
%R info about a relent
%s arbitrary string, like printf
%d integer, like printf
%u integer, like printf
*/
-static const char *
-demangle (string, remove_underscore)
+char *
+demangle (string)
const char *string;
- int remove_underscore;
{
- const char *res;
+ char *res;
+ const char *p;
- if (remove_underscore
- && output_bfd != NULL
+ if (output_bfd != NULL
&& bfd_get_symbol_leading_char (output_bfd) == string[0])
++string;
- /* This is a hack for better error reporting on XCOFF. */
- if (remove_underscore && string[0] == '.')
- ++string;
+ /* This is a hack for better error reporting on XCOFF, PowerPC64-ELF
+ or the MS PE format. These formats have a number of leading '.'s
+ on at least some symbols, so we remove all dots. */
+ p = string;
+ while (*p == '.')
+ ++p;
- /* Note that there's a memory leak here, we keep buying memory for
- demangled names, and never free. But if you have so many errors
- that you run out of VM with the error messages, then there's
- something up. */
- res = cplus_demangle (string, DMGL_ANSI | DMGL_PARAMS);
- return res ? res : string;
+ res = cplus_demangle (p, DMGL_ANSI | DMGL_PARAMS);
+ return res ? res : xstrdup (string);
}
static void
while (*fmt != '\0')
{
- while (*fmt != '%' && *fmt != '\0')
+ while (*fmt != '%' && *fmt != '\0')
{
putc (*fmt, fp);
fmt++;
}
- if (*fmt == '%')
+ if (*fmt == '%')
{
- fmt ++;
- switch (*fmt++)
+ fmt++;
+ switch (*fmt++)
{
default:
- fprintf (fp,"%%%c", fmt[-1]);
+ fprintf (fp, "%%%c", fmt[-1]);
break;
case '%':
}
break;
+ case 'W':
+ /* hex bfd_vma with 0x with no leading zeroes taking up
+ 8 spaces. */
+ {
+ char buf[100];
+ bfd_vma value;
+ char *p;
+ int len;
+
+ value = va_arg (arg, bfd_vma);
+ sprintf_vma (buf, value);
+ for (p = buf; *p == '0'; ++p)
+ ;
+ if (*p == '\0')
+ --p;
+ len = strlen (p);
+ while (len < 8)
+ {
+ putc (' ', fp);
+ ++len;
+ }
+ fprintf (fp, "0x%s", p);
+ }
+ break;
+
case 'T':
/* Symbol name. */
{
const char *name = va_arg (arg, const char *);
- if (name != (const char *) NULL)
- fprintf (fp, "%s", demangle (name, 1));
+ if (name == (const char *) NULL || *name == 0)
+ fprintf (fp, _("no symbol"));
+ else if (! demangling)
+ fprintf (fp, "%s", name);
else
- fprintf (fp, "no symbol");
+ {
+ char *demangled;
+
+ demangled = demangle (name);
+ fprintf (fp, "%s", demangled);
+ free (demangled);
+ }
}
break;
case 'B':
/* filename from a bfd */
- {
+ {
bfd *abfd = va_arg (arg, bfd *);
if (abfd->my_archive)
fprintf (fp, "%s(%s)", abfd->my_archive->filename,
break;
case 'F':
- /* error is fatal */
+ /* Error is fatal. */
fatal = true;
break;
case 'P':
- /* print program name */
+ /* Print program name. */
fprintf (fp, "%s", program_name);
break;
case 'E':
/* current bfd error or errno */
- fprintf (fp, bfd_errmsg (bfd_get_error ()));
+ fprintf (fp, "%s", bfd_errmsg (bfd_get_error ()));
break;
case 'I':
break;
case 'S':
- /* print script file and linenumber */
+ /* Print script file and linenumber. */
if (parsing_defsym)
fprintf (fp, "--defsym %s", lex_string);
else if (ldfile_input_filename != NULL)
fprintf (fp, "%s:%u", ldfile_input_filename, lineno);
else
- fprintf (fp, "built in linker script:%u", lineno);
+ fprintf (fp, _("built in linker script:%u"), lineno);
break;
case 'R':
- /* Print all that's interesting about a relent */
+ /* Print all that's interesting about a relent. */
{
arelent *relent = va_arg (arg, arelent *);
-
- finfo (fp, "%s+0x%v (type %s)",
- (*(relent->sym_ptr_ptr))->name,
- relent->addend,
- relent->howto->name);
+
+ lfinfo (fp, "%s+0x%v (type %s)",
+ (*(relent->sym_ptr_ptr))->name,
+ relent->addend,
+ relent->howto->name);
}
break;
-
+
case 'C':
case 'D':
+ case 'G':
/* Clever filename:linenumber with function name if possible,
or section name as a last resort. The arguments are a BFD,
a section, and an offset. */
symsize = bfd_get_symtab_upper_bound (abfd);
if (symsize < 0)
- einfo ("%B%F: could not read symbols\n", abfd);
+ einfo (_("%B%F: could not read symbols\n"), abfd);
asymbols = (asymbol **) xmalloc (symsize);
symbol_count = bfd_canonicalize_symtab (abfd, asymbols);
if (symbol_count < 0)
- einfo ("%B%F: could not read symbols\n", abfd);
+ einfo (_("%B%F: could not read symbols\n"), abfd);
if (entry != (lang_input_statement_type *) NULL)
{
entry->asymbols = asymbols;
&filename, &functionname,
&linenumber))
{
- if (functionname != NULL && fmt[-1] == 'C')
+ if (functionname != NULL && fmt[-1] == 'G')
+ {
+ lfinfo (fp, "%B:", abfd);
+ if (filename != NULL
+ && strcmp (filename, bfd_get_filename (abfd)) != 0)
+ fprintf (fp, "%s:", filename);
+ lfinfo (fp, "%T", functionname);
+ }
+ else if (functionname != NULL && fmt[-1] == 'C')
{
if (filename == (char *) NULL)
filename = abfd->filename;
/* We use abfd->filename in this initial line,
in case filename is a .h file or something
similarly unhelpful. */
- finfo (fp, "%B: In function `%s':\n",
- abfd, demangle (functionname, 1));
+ lfinfo (fp, _("%B: In function `%T':\n"),
+ abfd, functionname);
last_bfd = abfd;
if (last_file != NULL)
free (last_file);
- last_file = buystring (filename);
+ last_file = xstrdup (filename);
if (last_function != NULL)
free (last_function);
- last_function = buystring (functionname);
+ last_function = xstrdup (functionname);
}
discard_last = false;
if (linenumber != 0)
fprintf (fp, "%s:%u", filename, linenumber);
else
- finfo (fp, "%s(%s+0x%v)", filename, section->name,
- offset);
+ lfinfo (fp, "%s(%s+0x%v)", filename, section->name,
+ offset);
}
else if (filename == NULL
|| strcmp (filename, abfd->filename) == 0)
{
- finfo (fp, "%B(%s+0x%v)", abfd, section->name, offset);
+ lfinfo (fp, "%B(%s+0x%v)", abfd, section->name,
+ offset);
if (linenumber != 0)
- finfo (fp, "%u", linenumber);
+ lfinfo (fp, ":%u", linenumber);
}
- else if (linenumber != 0)
- finfo (fp, "%B:%s:%u", abfd, filename, linenumber);
+ else if (linenumber != 0)
+ lfinfo (fp, "%B:%s:%u", abfd, filename, linenumber);
else
- finfo (fp, "%B(%s+0x%v):%s", abfd, section->name, offset,
- filename);
+ lfinfo (fp, "%B(%s+0x%v):%s", abfd, section->name,
+ offset, filename);
}
else
- finfo (fp, "%B(%s+0x%v)", abfd, section->name, offset);
+ lfinfo (fp, "%B(%s+0x%v)", abfd, section->name, offset);
if (discard_last)
{
}
}
break;
-
+
case 's':
/* arbitrary string, like printf */
fprintf (fp, "%s", va_arg (arg, char *));
case 'u':
/* unsigned integer, like printf */
- fprintf (fp,"%u", va_arg (arg, unsigned int));
+ fprintf (fp, "%u", va_arg (arg, unsigned int));
break;
}
}
}
- if (fatal == true)
- xexit(1);
+ if (config.fatal_warnings)
+ config.make_executable = false;
+
+ if (fatal == true)
+ xexit (1);
}
-/* Format info message and print on stdout. */
+/* Format info message and print on stdout. */
/* (You would think this should be called just "info", but then you
would hosed by LynxOS, which defines that name in its libc.) */
void
-#if USE_STDARG
-info_msg (const char *fmt, ...)
-#else
-info_msg (va_alist)
- va_dcl
-#endif
+info_msg VPARAMS ((const char *fmt, ...))
{
- va_list arg;
-
-#if ! USE_STDARG
- const char *fmt;
-
- va_start (arg);
- fmt = va_arg (arg, const char *);
-#else
- va_start (arg, fmt);
-#endif
+ VA_OPEN (arg, fmt);
+ VA_FIXEDARG (arg, const char *, fmt);
vfinfo (stdout, fmt, arg);
- va_end (arg);
+ VA_CLOSE (arg);
}
-/* ('e' for error.) Format info message and print on stderr. */
+/* ('e' for error.) Format info message and print on stderr. */
void
-#if USE_STDARG
-einfo (const char *fmt, ...)
-#else
-einfo (va_alist)
- va_dcl
-#endif
+einfo VPARAMS ((const char *fmt, ...))
{
- va_list arg;
-
-#if ! USE_STDARG
- const char *fmt;
-
- va_start (arg);
- fmt = va_arg (arg, const char *);
-#else
- va_start (arg, fmt);
-#endif
+ VA_OPEN (arg, fmt);
+ VA_FIXEDARG (arg, const char *, fmt);
vfinfo (stderr, fmt, arg);
- va_end (arg);
+ VA_CLOSE (arg);
}
-void
+void
info_assert (file, line)
const char *file;
unsigned int line;
{
- einfo ("%F%P: internal error %s %d\n", file, line);
+ einfo (_("%F%P: internal error %s %d\n"), file, line);
}
-char *
-buystring (x)
- CONST char *CONST x;
-{
- size_t l = strlen(x)+1;
- char *r = xmalloc(l);
- memcpy(r, x,l);
- return r;
-}
-
-/* ('m' for map) Format info message and print on map. */
+/* ('m' for map) Format info message and print on map. */
void
-#if USE_STDARG
-minfo (const char *fmt, ...)
-#else
-minfo (va_alist)
- va_dcl
-#endif
+minfo VPARAMS ((const char *fmt, ...))
{
- va_list arg;
-
-#if ! USE_STDARG
- const char *fmt;
- va_start (arg);
- fmt = va_arg (arg, const char *);
-#else
- va_start (arg, fmt);
-#endif
+ VA_OPEN (arg, fmt);
+ VA_FIXEDARG (arg, const char *, fmt);
vfinfo (config.map_file, fmt, arg);
- va_end (arg);
+ VA_CLOSE (arg);
}
-static void
-#if USE_STDARG
-finfo (FILE *file, const char *fmt, ...)
-#else
-finfo (va_alist)
- va_dcl
-#endif
+void
+lfinfo VPARAMS ((FILE *file, const char *fmt, ...))
{
- va_list arg;
-
-#if ! USE_STDARG
- FILE *file;
- const char *fmt;
-
- va_start (arg);
- file = va_arg (arg, FILE *);
- fmt = va_arg (arg, const char *);
-#else
- va_start (arg, fmt);
-#endif
+ VA_OPEN (arg, fmt);
+ VA_FIXEDARG (arg, FILE *, file);
+ VA_FIXEDARG (arg, const char *, fmt);
vfinfo (file, fmt, arg);
- va_end (arg);
+ VA_CLOSE (arg);
}
\f
/* Functions to print the link map. */
-void
+void
print_space ()
{
fprintf (config.map_file, " ");
}
-void
+void
print_nl ()
{
fprintf (config.map_file, "\n");
}
-void
-print_address (value)
- bfd_vma value;
+/* A more or less friendly abort message. In ld.h abort is defined to
+ call this function. */
+
+void
+ld_abort (file, line, fn)
+ const char *file;
+ int line;
+ const char *fn;
{
- fprintf_vma (config.map_file, value);
+ if (fn != NULL)
+ einfo (_("%P: internal error: aborting at %s line %d in %s\n"),
+ file, line, fn);
+ else
+ einfo (_("%P: internal error: aborting at %s line %d\n"),
+ file, line);
+ einfo (_("%P%F: please report this bug\n"));
+ xexit (1);
}