[PATCH] allow empty string as argument to -Map
[deliverable/binutils-gdb.git] / ld / ldmisc.c
index e8c6b302ebfeb7a3da606f824b69987c62909b3d..418e8d5c6eda8a3a570b90e39ce60eacd94939d4 100644 (file)
@@ -1,7 +1,5 @@
 /* ldmisc.c
 /* ldmisc.c
-   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007
-   Free Software Foundation, Inc.
+   Copyright (C) 1991-2020 Free Software Foundation, Inc.
    Written by Steve Chamberlain of Cygnus Support.
 
    This file is part of the GNU Binutils.
    Written by Steve Chamberlain of Cygnus Support.
 
    This file is part of the GNU Binutils.
@@ -25,6 +23,9 @@
 #include "bfd.h"
 #include "bfdlink.h"
 #include "libiberty.h"
 #include "bfd.h"
 #include "bfdlink.h"
 #include "libiberty.h"
+#include "ctf-api.h"
+#include "safe-ctype.h"
+#include "filenames.h"
 #include "demangle.h"
 #include <stdarg.h>
 #include "ld.h"
 #include "demangle.h"
 #include <stdarg.h>
 #include "ld.h"
 #include "ldlex.h"
 #include "ldmain.h"
 #include "ldfile.h"
 #include "ldlex.h"
 #include "ldmain.h"
 #include "ldfile.h"
-#include "elf-bfd.h"
 
 /*
  %% literal %
 
 /*
  %% literal %
- %A section name from a section
- %B filename from a bfd
  %C clever filename:linenumber with function
  %D like %C, but no function name
  %E current bfd error or errno
  %F error is fatal
  %G like %D, but only function name
  %C clever filename:linenumber with function
  %D like %C, but no function name
  %E current bfd error or errno
  %F error is fatal
  %G like %D, but only function name
- %I filename from a lang_input_statement_type
+ %H like %C but in addition emit section+offset
  %P print program name
  %P print program name
- %R info about a relent
- %S print script file and linenumber
- %T symbol name
  %V hex bfd_vma
  %W hex bfd_vma with 0x with no leading zeros taking up 8 spaces
  %X no object output, fail return
  %d integer, like printf
  %ld long, like printf
  %lu unsigned long, like printf
  %V hex bfd_vma
  %W hex bfd_vma with 0x with no leading zeros taking up 8 spaces
  %X no object output, fail return
  %d integer, like printf
  %ld long, like printf
  %lu unsigned long, like printf
+ %p native (host) void* pointer, like printf
+ %pA section name from a section
+ %pB filename from a bfd
+ %pI filename from a lang_input_statement_type
+ %pR info about a relent
+ %pS print script file and linenumber from etree_type.
+ %pT symbol name
  %s arbitrary string, like printf
  %u integer, like printf
  %v hex bfd_vma, no leading zeros
 */
 
  %s arbitrary string, like printf
  %u integer, like printf
  %v hex bfd_vma, no leading zeros
 */
 
-static void
-vfinfo (FILE *fp, const char *fmt, va_list arg, bfd_boolean is_warning)
+void
+vfinfo (FILE *fp, const char *fmt, va_list ap, bfd_boolean is_warning)
 {
   bfd_boolean fatal = FALSE;
 {
   bfd_boolean fatal = FALSE;
+  const char *scan;
+  int arg_type;
+  unsigned int arg_count = 0;
+  unsigned int arg_no;
+  union vfinfo_args
+  {
+    int i;
+    long l;
+    void *p;
+    bfd_vma v;
+    struct {
+      bfd *abfd;
+      asection *sec;
+      bfd_vma off;
+    } reladdr;
+    enum
+      {
+       Bad,
+       Int,
+       Long,
+       Ptr,
+       Vma,
+       RelAddr
+      } type;
+  } args[9];
+
+  for (arg_no = 0; arg_no < sizeof (args) / sizeof (args[0]); arg_no++)
+    args[arg_no].type = Bad;
+
+  arg_count = 0;
+  scan = fmt;
+  while (*scan != '\0')
+    {
+      while (*scan != '%' && *scan != '\0')
+       scan++;
 
 
-  while (*fmt != '\0')
+      if (*scan == '%')
+       {
+         scan++;
+
+         arg_no = arg_count;
+         if (*scan != '0' && ISDIGIT (*scan) && scan[1] == '$')
+           {
+             arg_no = *scan - '1';
+             scan += 2;
+           }
+
+         arg_type = Bad;
+         switch (*scan++)
+           {
+           case '\0':
+             --scan;
+             break;
+
+           case 'V':
+           case 'v':
+           case 'W':
+             arg_type = Vma;
+             break;
+
+           case 's':
+             arg_type = Ptr;
+             break;
+
+           case 'p':
+             if (*scan == 'A' || *scan == 'B' || *scan == 'I'
+                 || *scan == 'R' || *scan == 'S' || *scan ==  'T')
+               scan++;
+             arg_type = Ptr;
+             break;
+
+           case 'C':
+           case 'D':
+           case 'G':
+           case 'H':
+             arg_type = RelAddr;
+             break;
+
+           case 'd':
+           case 'u':
+             arg_type = Int;
+             break;
+
+           case 'l':
+             if (*scan == 'd' || *scan == 'u')
+               {
+                 ++scan;
+                 arg_type = Long;
+               }
+             break;
+
+           default:
+             break;
+           }
+         if (arg_type != Bad)
+           {
+             if (arg_no >= sizeof (args) / sizeof (args[0]))
+               abort ();
+             args[arg_no].type = arg_type;
+             ++arg_count;
+           }
+       }
+    }
+
+  for (arg_no = 0; arg_no < arg_count; arg_no++)
     {
     {
-      while (*fmt != '%' && *fmt != '\0')
+      switch (args[arg_no].type)
        {
        {
-         putc (*fmt, fp);
-         fmt++;
+       case Int:
+         args[arg_no].i = va_arg (ap, int);
+         break;
+       case Long:
+         args[arg_no].l = va_arg (ap, long);
+         break;
+       case Ptr:
+         args[arg_no].p = va_arg (ap, void *);
+         break;
+       case Vma:
+         args[arg_no].v = va_arg (ap, bfd_vma);
+         break;
+       case RelAddr:
+         args[arg_no].reladdr.abfd = va_arg (ap, bfd *);
+         args[arg_no].reladdr.sec = va_arg (ap, asection *);
+         args[arg_no].reladdr.off = va_arg (ap, bfd_vma);
+         break;
+       default:
+         abort ();
        }
        }
+    }
+
+  arg_count = 0;
+  while (*fmt != '\0')
+    {
+      const char *str = fmt;
+      while (*fmt != '%' && *fmt != '\0')
+       fmt++;
+      if (fmt != str)
+       if (fwrite (str, 1, fmt - str, fp))
+         {
+           /* Ignore.  */
+         }
 
       if (*fmt == '%')
        {
          fmt++;
 
       if (*fmt == '%')
        {
          fmt++;
+
+         arg_no = arg_count;
+         if (*fmt != '0' && ISDIGIT (*fmt) && fmt[1] == '$')
+           {
+             arg_no = *fmt - '1';
+             fmt += 2;
+           }
+
          switch (*fmt++)
            {
          switch (*fmt++)
            {
+           case '\0':
+             --fmt;
+             /* Fall through.  */
+
            case '%':
              /* literal % */
              putc ('%', fp);
            case '%':
              /* literal % */
              putc ('%', fp);
@@ -93,7 +240,8 @@ vfinfo (FILE *fp, const char *fmt, va_list arg, bfd_boolean is_warning)
            case 'V':
              /* hex bfd_vma */
              {
            case 'V':
              /* hex bfd_vma */
              {
-               bfd_vma value = va_arg (arg, bfd_vma);
+               bfd_vma value = args[arg_no].v;
+               ++arg_count;
                fprintf_vma (fp, value);
              }
              break;
                fprintf_vma (fp, value);
              }
              break;
@@ -103,7 +251,8 @@ vfinfo (FILE *fp, const char *fmt, va_list arg, bfd_boolean is_warning)
              {
                char buf[100];
                char *p = buf;
              {
                char buf[100];
                char *p = buf;
-               bfd_vma value = va_arg (arg, bfd_vma);
+               bfd_vma value = args[arg_no].v;
+               ++arg_count;
                sprintf_vma (p, value);
                while (*p == '0')
                  p++;
                sprintf_vma (p, value);
                while (*p == '0')
                  p++;
@@ -122,7 +271,8 @@ vfinfo (FILE *fp, const char *fmt, va_list arg, bfd_boolean is_warning)
                char *p;
                int len;
 
                char *p;
                int len;
 
-               value = va_arg (arg, bfd_vma);
+               value = args[arg_no].v;
+               ++arg_count;
                sprintf_vma (buf, value);
                for (p = buf; *p == '0'; ++p)
                  ;
                sprintf_vma (buf, value);
                for (p = buf; *p == '0'; ++p)
                  ;
@@ -138,72 +288,6 @@ vfinfo (FILE *fp, const char *fmt, va_list arg, bfd_boolean is_warning)
              }
              break;
 
              }
              break;
 
-           case 'T':
-             /* Symbol name.  */
-             {
-               const char *name = va_arg (arg, const char *);
-
-               if (name == NULL || *name == 0)
-                 {
-                   fprintf (fp, _("no symbol"));
-                   break;
-                 }
-               else if (demangling)
-                 {
-                   char *demangled;
-
-                   demangled = bfd_demangle (output_bfd, name,
-                                             DMGL_ANSI | DMGL_PARAMS);
-                   if (demangled != NULL)
-                     {
-                       fprintf (fp, "%s", demangled);
-                       free (demangled);
-                       break;
-                     }
-                 }
-               fprintf (fp, "%s", name);
-             }
-             break;
-
-           case 'A':
-             /* section name from a section */
-             {
-               asection *sec = va_arg (arg, asection *);
-               bfd *abfd = sec->owner;
-               const char *group = NULL;
-               struct coff_comdat_info *ci;
-
-               fprintf (fp, "%s", sec->name);
-               if (abfd != NULL
-                   && bfd_get_flavour (abfd) == bfd_target_elf_flavour
-                   && elf_next_in_group (sec) != NULL
-                   && (sec->flags & SEC_GROUP) == 0)
-                 group = elf_group_name (sec);
-               else if (abfd != NULL
-                        && bfd_get_flavour (abfd) == bfd_target_coff_flavour
-                        && (ci = bfd_coff_get_comdat_section (sec->owner,
-                                                              sec)) != NULL)
-                 group = ci->name;
-               if (group != NULL)
-                 fprintf (fp, "[%s]", group);
-             }
-             break;
-
-           case 'B':
-             /* filename from a bfd */
-             {
-               bfd *abfd = va_arg (arg, bfd *);
-
-               if (abfd == NULL)
-                 fprintf (fp, "%s generated", program_name);
-               else if (abfd->my_archive)
-                 fprintf (fp, "%s(%s)", abfd->my_archive->filename,
-                          abfd->filename);
-               else
-                 fprintf (fp, "%s", abfd->filename);
-             }
-             break;
-
            case 'F':
              /* Error is fatal.  */
              fatal = TRUE;
            case 'F':
              /* Error is fatal.  */
              fatal = TRUE;
@@ -219,113 +303,56 @@ vfinfo (FILE *fp, const char *fmt, va_list arg, bfd_boolean is_warning)
              fprintf (fp, "%s", bfd_errmsg (bfd_get_error ()));
              break;
 
              fprintf (fp, "%s", bfd_errmsg (bfd_get_error ()));
              break;
 
-           case 'I':
-             /* filename from a lang_input_statement_type */
-             {
-               lang_input_statement_type *i;
-
-               i = va_arg (arg, lang_input_statement_type *);
-               if (bfd_my_archive (i->the_bfd) != NULL)
-                 fprintf (fp, "(%s)",
-                          bfd_get_filename (bfd_my_archive (i->the_bfd)));
-               fprintf (fp, "%s", i->local_sym_name);
-               if (bfd_my_archive (i->the_bfd) == NULL
-                   && strcmp (i->local_sym_name, i->filename) != 0)
-                 fprintf (fp, " (%s)", i->filename);
-             }
-             break;
-
-           case 'S':
-             /* 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);
-             break;
-
-           case 'R':
-             /* Print all that's interesting about a relent.  */
-             {
-               arelent *relent = va_arg (arg, arelent *);
-
-               lfinfo (fp, "%s+0x%v (type %s)",
-                       (*(relent->sym_ptr_ptr))->name,
-                       relent->addend,
-                       relent->howto->name);
-             }
-             break;
-
            case 'C':
            case 'D':
            case 'G':
            case 'C':
            case 'D':
            case 'G':
+           case 'H':
              /* Clever filename:linenumber with function name if possible.
                 The arguments are a BFD, a section, and an offset.  */
              {
                static bfd *last_bfd;
              /* Clever filename:linenumber with function name if possible.
                 The arguments are a BFD, a section, and an offset.  */
              {
                static bfd *last_bfd;
-               static char *last_file = NULL;
-               static char *last_function = NULL;
+               static char *last_file;
+               static char *last_function;
                bfd *abfd;
                asection *section;
                bfd_vma offset;
                bfd *abfd;
                asection *section;
                bfd_vma offset;
-               lang_input_statement_type *entry;
-               asymbol **asymbols;
+               asymbol **asymbols = NULL;
                const char *filename;
                const char *functionname;
                unsigned int linenumber;
                bfd_boolean discard_last;
                const char *filename;
                const char *functionname;
                unsigned int linenumber;
                bfd_boolean discard_last;
+               bfd_boolean done;
+               bfd_error_type last_bfd_error = bfd_get_error ();
 
 
-               abfd = va_arg (arg, bfd *);
-               section = va_arg (arg, asection *);
-               offset = va_arg (arg, bfd_vma);
+               abfd = args[arg_no].reladdr.abfd;
+               section = args[arg_no].reladdr.sec;
+               offset = args[arg_no].reladdr.off;
+               ++arg_count;
 
 
-               if (abfd == NULL)
-                 {
-                   entry = NULL;
-                   asymbols = NULL;
-                 }
-               else
+               if (abfd != NULL)
                  {
                  {
-                   entry = (lang_input_statement_type *) abfd->usrdata;
-                   if (entry != (lang_input_statement_type *) NULL
-                       && entry->asymbols != (asymbol **) NULL)
-                     asymbols = entry->asymbols;
-                   else
-                     {
-                       long symsize;
-                       long sym_count;
-
-                       symsize = bfd_get_symtab_upper_bound (abfd);
-                       if (symsize < 0)
-                         einfo (_("%B%F: could not read symbols\n"), abfd);
-                       asymbols = xmalloc (symsize);
-                       sym_count = bfd_canonicalize_symtab (abfd, asymbols);
-                       if (sym_count < 0)
-                         einfo (_("%B%F: could not read symbols\n"), abfd);
-                       if (entry != (lang_input_statement_type *) NULL)
-                         {
-                           entry->asymbols = asymbols;
-                           entry->symbol_count = sym_count;
-                         }
-                     }
+                   if (!bfd_generic_link_read_symbols (abfd))
+                     einfo (_("%F%P: %pB: could not read symbols: %E\n"), abfd);
+
+                   asymbols = bfd_get_outsymbols (abfd);
                  }
 
                /* The GNU Coding Standard requires that error messages
                   be of the form:
                  }
 
                /* The GNU Coding Standard requires that error messages
                   be of the form:
-                  
+
                     source-file-name:lineno: message
 
                   We do not always have a line number available so if
                   we cannot find them we print out the section name and
                     source-file-name:lineno: message
 
                   We do not always have a line number available so if
                   we cannot find them we print out the section name and
-                  offset instread.  */
+                  offset instead.  */
                discard_last = TRUE;
                if (abfd != NULL
                    && bfd_find_nearest_line (abfd, section, asymbols, offset,
                                              &filename, &functionname,
                                              &linenumber))
                  {
                discard_last = TRUE;
                if (abfd != NULL
                    && bfd_find_nearest_line (abfd, section, asymbols, offset,
                                              &filename, &functionname,
                                              &linenumber))
                  {
-                   if (functionname != NULL && fmt[-1] == 'C')
+                   if (functionname != NULL
+                       && (fmt[-1] == 'C' || fmt[-1] == 'H'))
                      {
                        /* Detect the case where we are printing out a
                           message for the same function as the last
                      {
                        /* Detect the case where we are printing out a
                           message for the same function as the last
@@ -337,93 +364,211 @@ vfinfo (FILE *fp, const char *fmt, va_list arg, bfd_boolean is_warning)
                           (eg emacs) to correctly locate multiple
                           errors in the same source file.  */
                        if (last_bfd == NULL
                           (eg emacs) to correctly locate multiple
                           errors in the same source file.  */
                        if (last_bfd == NULL
-                           || last_file == NULL
                            || last_function == NULL
                            || last_bfd != abfd
                            || last_function == NULL
                            || last_bfd != abfd
+                           || (last_file == NULL) != (filename == NULL)
                            || (filename != NULL
                            || (filename != NULL
-                               && strcmp (last_file, filename) != 0)
+                               && filename_cmp (last_file, filename) != 0)
                            || strcmp (last_function, functionname) != 0)
                          {
                            || strcmp (last_function, functionname) != 0)
                          {
-                           lfinfo (fp, _("%B: In function `%T':\n"),
+                           lfinfo (fp, _("%pB: in function `%pT':\n"),
                                    abfd, functionname);
 
                            last_bfd = abfd;
                                    abfd, functionname);
 
                            last_bfd = abfd;
-                           if (last_file != NULL)
-                             free (last_file);
+                           free (last_file);
                            last_file = NULL;
                            if (filename)
                              last_file = xstrdup (filename);
                            last_file = NULL;
                            if (filename)
                              last_file = xstrdup (filename);
-                           if (last_function != NULL)
-                             free (last_function);
+                           free (last_function);
                            last_function = xstrdup (functionname);
                          }
                        discard_last = FALSE;
                      }
                    else
                            last_function = xstrdup (functionname);
                          }
                        discard_last = FALSE;
                      }
                    else
-                     lfinfo (fp, "%B:", abfd);
+                     lfinfo (fp, "%pB:", abfd);
 
                    if (filename != NULL)
                      fprintf (fp, "%s:", filename);
 
 
                    if (filename != NULL)
                      fprintf (fp, "%s:", filename);
 
+                   done = fmt[-1] != 'H';
                    if (functionname != NULL && fmt[-1] == 'G')
                    if (functionname != NULL && fmt[-1] == 'G')
-                     lfinfo (fp, "%T", functionname);
+                     lfinfo (fp, "%pT", functionname);
                    else if (filename != NULL && linenumber != 0)
                    else if (filename != NULL && linenumber != 0)
-                     fprintf (fp, "%u", linenumber);
+                     fprintf (fp, "%u%s", linenumber, done ? "" : ":");
                    else
                    else
-                     lfinfo (fp, "(%A+0x%v)", section, offset);
+                     done = FALSE;
                  }
                else
                  }
                else
-                 lfinfo (fp, "%B:(%A+0x%v)", abfd, section, offset);
-
-               if (asymbols != NULL && entry == NULL)
-                 free (asymbols);
+                 {
+                   lfinfo (fp, "%pB:", abfd);
+                   done = FALSE;
+                 }
+               if (!done)
+                 lfinfo (fp, "(%pA+0x%v)", section, offset);
+               bfd_set_error (last_bfd_error);
 
                if (discard_last)
                  {
                    last_bfd = NULL;
 
                if (discard_last)
                  {
                    last_bfd = NULL;
-                   if (last_file != NULL)
-                     {
-                       free (last_file);
-                       last_file = NULL;
-                     }
-                   if (last_function != NULL)
-                     {
-                       free (last_function);
-                       last_function = NULL;
-                     }
+                   free (last_file);
+                   last_file = NULL;
+                   free (last_function);
+                   last_function = NULL;
                  }
              }
              break;
 
                  }
              }
              break;
 
+           case 'p':
+             if (*fmt == 'A')
+               {
+                 /* section name from a section */
+                 asection *sec;
+                 bfd *abfd;
+
+                 fmt++;
+                 sec = (asection *) args[arg_no].p;
+                 ++arg_count;
+                 fprintf (fp, "%s", sec->name);
+                 abfd = sec->owner;
+                 if (abfd != NULL)
+                   {
+                     const char *group = bfd_group_name (abfd, sec);
+                     if (group != NULL)
+                       fprintf (fp, "[%s]", group);
+                   }
+               }
+             else if (*fmt == 'B')
+               {
+                 /* filename from a bfd */
+                 bfd *abfd = (bfd *) args[arg_no].p;
+
+                 fmt++;
+                 ++arg_count;
+                 if (abfd == NULL)
+                   fprintf (fp, "%s generated", program_name);
+                 else if (abfd->my_archive != NULL
+                          && !bfd_is_thin_archive (abfd->my_archive))
+                   fprintf (fp, "%s(%s)",
+                            bfd_get_filename (abfd->my_archive),
+                            bfd_get_filename (abfd));
+                 else
+                   fprintf (fp, "%s", bfd_get_filename (abfd));
+               }
+             else if (*fmt == 'I')
+               {
+                 /* filename from a lang_input_statement_type */
+                 lang_input_statement_type *i;
+
+                 fmt++;
+                 i = (lang_input_statement_type *) args[arg_no].p;
+                 ++arg_count;
+                 if (i->the_bfd != NULL
+                     && i->the_bfd->my_archive != NULL
+                     && !bfd_is_thin_archive (i->the_bfd->my_archive))
+                   fprintf (fp, "(%s)%s",
+                            bfd_get_filename (i->the_bfd->my_archive),
+                            i->local_sym_name);
+                 else
+                   fprintf (fp, "%s", i->filename);
+               }
+             else if (*fmt == 'R')
+               {
+                 /* Print all that's interesting about a relent.  */
+                 arelent *relent = (arelent *) args[arg_no].p;
+
+                 fmt++;
+                 ++arg_count;
+                 lfinfo (fp, "%s+0x%v (type %s)",
+                         (*(relent->sym_ptr_ptr))->name,
+                         relent->addend,
+                         relent->howto->name);
+               }
+             else if (*fmt == 'S')
+               {
+                 /* Print script file and linenumber.  */
+                 etree_type node;
+                 etree_type *tp = (etree_type *) args[arg_no].p;
+
+                 fmt++;
+                 ++arg_count;
+                 if (tp == NULL)
+                   {
+                     tp = &node;
+                     tp->type.filename = ldlex_filename ();
+                     tp->type.lineno = lineno;
+                   }
+                 if (tp->type.filename != NULL)
+                   fprintf (fp, "%s:%u", tp->type.filename, tp->type.lineno);
+               }
+             else if (*fmt == 'T')
+               {
+                 /* Symbol name.  */
+                 const char *name = (const char *) args[arg_no].p;
+
+                 fmt++;
+                 ++arg_count;
+                 if (name == NULL || *name == 0)
+                   {
+                     fprintf (fp, _("no symbol"));
+                     break;
+                   }
+                 else if (demangling)
+                   {
+                     char *demangled;
+
+                     demangled = bfd_demangle (link_info.output_bfd, name,
+                                               DMGL_ANSI | DMGL_PARAMS);
+                     if (demangled != NULL)
+                       {
+                         fprintf (fp, "%s", demangled);
+                         free (demangled);
+                         break;
+                       }
+                   }
+                 fprintf (fp, "%s", name);
+               }
+             else
+               {
+                 /* native (host) void* pointer, like printf */
+                 fprintf (fp, "%p", args[arg_no].p);
+                 ++arg_count;
+               }
+             break;
+
            case 's':
              /* arbitrary string, like printf */
            case 's':
              /* arbitrary string, like printf */
-             fprintf (fp, "%s", va_arg (arg, char *));
+             fprintf (fp, "%s", (char *) args[arg_no].p);
+             ++arg_count;
              break;
 
            case 'd':
              /* integer, like printf */
              break;
 
            case 'd':
              /* integer, like printf */
-             fprintf (fp, "%d", va_arg (arg, int));
+             fprintf (fp, "%d", args[arg_no].i);
+             ++arg_count;
              break;
 
            case 'u':
              /* unsigned integer, like printf */
              break;
 
            case 'u':
              /* unsigned integer, like printf */
-             fprintf (fp, "%u", va_arg (arg, unsigned int));
+             fprintf (fp, "%u", args[arg_no].i);
+             ++arg_count;
              break;
 
            case 'l':
              if (*fmt == 'd')
                {
              break;
 
            case 'l':
              if (*fmt == 'd')
                {
-                 fprintf (fp, "%ld", va_arg (arg, long));
+                 fprintf (fp, "%ld", args[arg_no].l);
+                 ++arg_count;
                  ++fmt;
                  break;
                }
              else if (*fmt == 'u')
                {
                  ++fmt;
                  break;
                }
              else if (*fmt == 'u')
                {
-                 fprintf (fp, "%lu", va_arg (arg, unsigned long));
+                 fprintf (fp, "%lu", args[arg_no].l);
+                 ++arg_count;
                  ++fmt;
                  break;
                }
                  ++fmt;
                  break;
                }
-             /* Fall thru */
+             /* Fallthru */
 
            default:
              fprintf (fp, "%%%c", fmt[-1]);
 
            default:
              fprintf (fp, "%%%c", fmt[-1]);
@@ -461,9 +606,11 @@ einfo (const char *fmt, ...)
 {
   va_list arg;
 
 {
   va_list arg;
 
+  fflush (stdout);
   va_start (arg, fmt);
   vfinfo (stderr, fmt, arg, TRUE);
   va_end (arg);
   va_start (arg, fmt);
   vfinfo (stderr, fmt, arg, TRUE);
   va_end (arg);
+  fflush (stderr);
 }
 
 void
 }
 
 void
@@ -482,7 +629,22 @@ minfo (const char *fmt, ...)
       va_list arg;
 
       va_start (arg, fmt);
       va_list arg;
 
       va_start (arg, fmt);
-      vfinfo (config.map_file, fmt, arg, FALSE);
+      if (fmt[0] == '%' && fmt[1] == '!' && fmt[2] == 0)
+       {
+         /* Stash info about --as-needed shared libraries.  Print
+            later so they don't appear intermingled with archive
+            library info.  */
+         struct asneeded_minfo *m = xmalloc (sizeof *m);
+
+         m->next = NULL;
+         m->soname = va_arg (arg, const char *);
+         m->ref = va_arg (arg, bfd *);
+         m->name = va_arg (arg, const char *);
+         *asneeded_list_tail = m;
+         asneeded_list_tail = &m->next;
+       }
+      else
+       vfinfo (config.map_file, fmt, arg, FALSE);
       va_end (arg);
     }
 }
       va_end (arg);
     }
 }
@@ -518,11 +680,11 @@ void
 ld_abort (const char *file, int line, const char *fn)
 {
   if (fn != NULL)
 ld_abort (const char *file, int line, const char *fn)
 {
   if (fn != NULL)
-    einfo (_("%P: internal error: aborting at %s line %d in %s\n"),
+    einfo (_("%P: internal error: aborting at %s:%d in %s\n"),
           file, line, fn);
   else
           file, line, fn);
   else
-    einfo (_("%P: internal error: aborting at %s line %d\n"),
+    einfo (_("%P: internal error: aborting at %s:%d\n"),
           file, line);
           file, line);
-  einfo (_("%P%F: please report this bug\n"));
+  einfo (_("%F%P: please report this bug\n"));
   xexit (1);
 }
   xexit (1);
 }
This page took 0.033087 seconds and 4 git commands to generate.