Fix skip.exp test failure observed with gcc-9.2.0
[deliverable/binutils-gdb.git] / ld / ldmisc.c
index 904a23d37d0641e7a5fa8f8cf562823a783bd6c3..2e53d645985d7d4775c53f10361671fffcbecb00 100644 (file)
@@ -1,5 +1,5 @@
 /* ldmisc.c
 /* ldmisc.c
-   Copyright (C) 1991-2017 Free Software Foundation, Inc.
+   Copyright (C) 1991-2019 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.
@@ -23,6 +23,8 @@
 #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 "filenames.h"
 #include "demangle.h"
 #include <stdarg.h>
 #include "ldlex.h"
 #include "ldmain.h"
 #include "ldfile.h"
 #include "ldlex.h"
 #include "ldmain.h"
 #include "ldfile.h"
-#include "elf-bfd.h"
-#include "coff-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
  %H like %C but in addition emit section+offset
  %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
  %H like %C but in addition emit section+offset
- %I filename from a lang_input_statement_type
  %P print program name
  %P print program name
- %R info about a relent
- %S print script file and linenumber from etree_type.
- %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
  %V hex bfd_vma
  %W hex bfd_vma with 0x with no leading zeros taking up 8 spaces
  %X no object output, fail return
  %ld long, like printf
  %lu unsigned long, like printf
  %p native (host) void* pointer, 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
 */
 
 void
  %s arbitrary string, like printf
  %u integer, like printf
  %v hex bfd_vma, no leading zeros
 */
 
 void
-vfinfo (FILE *fp, const char *fmt, va_list arg, bfd_boolean is_warning)
+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++;
+
+      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++)
+    {
+      switch (args[arg_no].type)
+       {
+       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 != '\0')
     {
       const char *str = fmt;
@@ -83,8 +213,20 @@ vfinfo (FILE *fp, const char *fmt, va_list arg, bfd_boolean is_warning)
       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);
@@ -98,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;
@@ -108,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++;
@@ -127,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)
                  ;
@@ -143,73 +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 (link_info.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 != NULL
-                        && !bfd_is_thin_archive (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;
@@ -225,53 +303,6 @@ 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 (i->the_bfd->my_archive != NULL
-                   && !bfd_is_thin_archive (i->the_bfd->my_archive))
-                 fprintf (fp, "(%s)",
-                          bfd_get_filename (i->the_bfd->my_archive));
-               fprintf (fp, "%s", i->local_sym_name);
-               if ((i->the_bfd->my_archive == NULL
-                    || bfd_is_thin_archive (i->the_bfd->my_archive))
-                   && filename_cmp (i->local_sym_name, i->filename) != 0)
-                 fprintf (fp, " (%s)", i->filename);
-             }
-             break;
-
-           case 'S':
-             /* Print script file and linenumber.  */
-             {
-               etree_type node;
-               etree_type *tp = va_arg (arg, etree_type *);
-
-               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);
-             }
-             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':
@@ -280,8 +311,8 @@ vfinfo (FILE *fp, const char *fmt, va_list arg, bfd_boolean is_warning)
                 The arguments are a BFD, a section, and an offset.  */
              {
                static bfd *last_bfd;
                 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;
@@ -291,15 +322,17 @@ vfinfo (FILE *fp, const char *fmt, va_list arg, bfd_boolean is_warning)
                unsigned int linenumber;
                bfd_boolean discard_last;
                bfd_boolean done;
                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)
                  {
                    if (!bfd_generic_link_read_symbols (abfd))
 
                if (abfd != NULL)
                  {
                    if (!bfd_generic_link_read_symbols (abfd))
-                     einfo (_("%B%F: could not read symbols: %E\n"), abfd);
+                     einfo (_("%F%P: %pB: could not read symbols: %E\n"), abfd);
 
                    asymbols = bfd_get_outsymbols (abfd);
                  }
 
                    asymbols = bfd_get_outsymbols (abfd);
                  }
@@ -331,14 +364,14 @@ 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_cmp (last_file, filename) != 0)
                            || strcmp (last_function, functionname) != 0)
                          {
                            || (filename != NULL
                                && filename_cmp (last_file, filename) != 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;
@@ -354,14 +387,14 @@ vfinfo (FILE *fp, const char *fmt, va_list arg, bfd_boolean is_warning)
                        discard_last = FALSE;
                      }
                    else
                        discard_last = FALSE;
                      }
                    else
-                     lfinfo (fp, "%B:", abfd);
+                     lfinfo (fp, "%pB:", abfd);
 
                    if (filename != NULL)
                      fprintf (fp, "%s:", filename);
 
                    done = fmt[-1] != 'H';
                    if (functionname != NULL && fmt[-1] == 'G')
 
                    if (filename != NULL)
                      fprintf (fp, "%s:", filename);
 
                    done = fmt[-1] != 'H';
                    if (functionname != NULL && fmt[-1] == 'G')
-                     lfinfo (fp, "%T", functionname);
+                     lfinfo (fp, "%pT", functionname);
                    else if (filename != NULL && linenumber != 0)
                      fprintf (fp, "%u%s", linenumber, done ? "" : ":");
                    else
                    else if (filename != NULL && linenumber != 0)
                      fprintf (fp, "%u%s", linenumber, done ? "" : ":");
                    else
@@ -369,11 +402,12 @@ vfinfo (FILE *fp, const char *fmt, va_list arg, bfd_boolean is_warning)
                  }
                else
                  {
                  }
                else
                  {
-                   lfinfo (fp, "%B:", abfd);
+                   lfinfo (fp, "%pB:", abfd);
                    done = FALSE;
                  }
                if (!done)
                    done = FALSE;
                  }
                if (!done)
-                 lfinfo (fp, "(%A+0x%v)", section, offset);
+                 lfinfo (fp, "(%pA+0x%v)", section, offset);
+               bfd_set_error (last_bfd_error);
 
                if (discard_last)
                  {
 
                if (discard_last)
                  {
@@ -393,35 +427,150 @@ vfinfo (FILE *fp, const char *fmt, va_list arg, bfd_boolean is_warning)
              break;
 
            case 'p':
              break;
 
            case 'p':
-             /* native (host) void* pointer, like printf */
-             fprintf (fp, "%p", va_arg (arg, void *));
+             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)", abfd->my_archive->filename,
+                            abfd->filename);
+                 else
+                   fprintf (fp, "%s", abfd->filename);
+               }
+             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", i->the_bfd->my_archive->filename,
+                            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 */
              break;
 
            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;
                }
@@ -542,6 +691,6 @@ ld_abort (const char *file, int line, const char *fn)
   else
     einfo (_("%P: internal error: aborting at %s:%d\n"),
           file, line);
   else
     einfo (_("%P: internal error: aborting at %s:%d\n"),
           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.045479 seconds and 4 git commands to generate.