(root)/
binutils-2.41/
gas/
messages.c
       1  /* messages.c - error reporter -
       2     Copyright (C) 1987-2023 Free Software Foundation, Inc.
       3     This file is part of GAS, the GNU Assembler.
       4  
       5     GAS is free software; you can redistribute it and/or modify
       6     it under the terms of the GNU General Public License as published by
       7     the Free Software Foundation; either version 3, or (at your option)
       8     any later version.
       9  
      10     GAS is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13     GNU General Public License for more details.
      14  
      15     You should have received a copy of the GNU General Public License
      16     along with GAS; see the file COPYING.  If not, write to the Free
      17     Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
      18     02110-1301, USA.  */
      19  
      20  #include "as.h"
      21  #include <limits.h>
      22  #include <signal.h>
      23  
      24  /* If the system doesn't provide strsignal, we get it defined in
      25     libiberty but no declaration is supplied.  Because, reasons. */
      26  #if !defined (HAVE_STRSIGNAL) && !defined (strsignal)
      27  extern const char *strsignal (int);
      28  #endif
      29  
      30  static void identify (const char *);
      31  static void as_show_where (void);
      32  static void as_warn_internal (const char *, unsigned int, char *);
      33  static void as_bad_internal (const char *, unsigned int, char *);
      34  static void signal_crash (int) ATTRIBUTE_NORETURN;
      35  
      36  /* Despite the rest of the comments in this file, (FIXME-SOON),
      37     here is the current scheme for error messages etc:
      38  
      39     as_fatal() is used when gas is quite confused and
      40     continuing the assembly is pointless.  In this case we
      41     exit immediately with error status.
      42  
      43     as_bad() is used to mark errors that result in what we
      44     presume to be a useless object file.  Say, we ignored
      45     something that might have been vital.  If we see any of
      46     these, assembly will continue to the end of the source,
      47     no object file will be produced, and we will terminate
      48     with error status.  The new option, -Z, tells us to
      49     produce an object file anyway but we still exit with
      50     error status.  The assumption here is that you don't want
      51     this object file but we could be wrong.
      52  
      53     as_warn() is used when we have an error from which we
      54     have a plausible error recovery.  eg, masking the top
      55     bits of a constant that is longer than will fit in the
      56     destination.  In this case we will continue to assemble
      57     the source, although we may have made a bad assumption,
      58     and we will produce an object file and return normal exit
      59     status (ie, no error).  The new option -X tells us to
      60     treat all as_warn() errors as as_bad() errors.  That is,
      61     no object file will be produced and we will exit with
      62     error status.  The idea here is that we don't kill an
      63     entire make because of an error that we knew how to
      64     correct.  On the other hand, sometimes you might want to
      65     stop the make at these points.
      66  
      67     as_tsktsk() is used when we see a minor error for which
      68     our error recovery action is almost certainly correct.
      69     In this case, we print a message and then assembly
      70     continues as though no error occurred.
      71  
      72     as_abort () is used for logic failure (assert or abort, signal).
      73  */
      74  
      75  static void
      76  identify (const char *file)
      77  {
      78    static int identified;
      79  
      80    if (identified)
      81      return;
      82    identified++;
      83  
      84    if (!file)
      85      {
      86        unsigned int x;
      87        file = as_where (&x);
      88      }
      89  
      90    if (file)
      91      fprintf (stderr, "%s: ", file);
      92    fprintf (stderr, _("Assembler messages:\n"));
      93  }
      94  
      95  /* The number of warnings issued.  */
      96  static int warning_count;
      97  
      98  int
      99  had_warnings (void)
     100  {
     101    return warning_count;
     102  }
     103  
     104  /* Nonzero if we've hit a 'bad error', and should not write an obj file,
     105     and exit with a nonzero error code.  */
     106  
     107  static int error_count;
     108  
     109  int
     110  had_errors (void)
     111  {
     112    return error_count;
     113  }
     114  
     115  /* Print the current location to stderr.  */
     116  
     117  static void
     118  as_show_where (void)
     119  {
     120    const char *file;
     121    unsigned int line;
     122  
     123    file = as_where_top (&line);
     124    identify (file);
     125    if (file)
     126      {
     127        if (line != 0)
     128  	fprintf (stderr, "%s:%u: ", file, line);
     129        else
     130  	fprintf (stderr, "%s: ", file);
     131      }
     132  }
     133  
     134  /* Send to stderr a string as information, with location data passed in.
     135     Note that for now this is not intended for general use.  */
     136  
     137  void
     138  as_info_where (const char *file, unsigned int line, unsigned int indent,
     139  	       const char *format, ...)
     140  {
     141    va_list args;
     142    char buffer[2000];
     143  
     144    va_start (args, format);
     145    vsnprintf (buffer, sizeof (buffer), format, args);
     146    va_end (args);
     147    fprintf (stderr, "%s:%u: %*s%s%s\n",
     148  	   file, line, (int)indent, "", _("Info: "), buffer);
     149  }
     150  
     151  /* Send to stderr a string as a warning, and locate warning
     152     in input file(s).
     153     Please only use this for when we have some recovery action.
     154     Please explain in string (which may have '\n's) what recovery was
     155     done.  */
     156  
     157  void
     158  as_tsktsk (const char *format, ...)
     159  {
     160    va_list args;
     161  
     162    as_show_where ();
     163    va_start (args, format);
     164    vfprintf (stderr, format, args);
     165    va_end (args);
     166    (void) putc ('\n', stderr);
     167    as_report_context ();
     168  }
     169  
     170  /* The common portion of as_warn and as_warn_where.  */
     171  
     172  static void
     173  as_warn_internal (const char *file, unsigned int line, char *buffer)
     174  {
     175    bool context = false;
     176  
     177    ++warning_count;
     178  
     179    if (file == NULL)
     180      {
     181        file = as_where_top (&line);
     182        context = true;
     183      }
     184  
     185    identify (file);
     186    if (file)
     187      {
     188        if (line != 0)
     189  	fprintf (stderr, "%s:%u: %s%s\n", file, line, _("Warning: "), buffer);
     190        else
     191  	fprintf (stderr, "%s: %s%s\n", file, _("Warning: "), buffer);
     192      }
     193    else
     194      fprintf (stderr, "%s%s\n", _("Warning: "), buffer);
     195  
     196    if (context)
     197      as_report_context ();
     198  
     199  #ifndef NO_LISTING
     200    listing_warning (buffer);
     201  #endif
     202  }
     203  
     204  /* Send to stderr a string as a warning, and locate warning
     205     in input file(s).
     206     Please only use this for when we have some recovery action.
     207     Please explain in string (which may have '\n's) what recovery was
     208     done.  */
     209  
     210  void
     211  as_warn (const char *format, ...)
     212  {
     213    va_list args;
     214    char buffer[2000];
     215  
     216    if (!flag_no_warnings)
     217      {
     218        va_start (args, format);
     219        vsnprintf (buffer, sizeof (buffer), format, args);
     220        va_end (args);
     221        as_warn_internal ((char *) NULL, 0, buffer);
     222      }
     223  }
     224  
     225  /* Like as_warn but the file name and line number are passed in.
     226     Unfortunately, we have to repeat the function in order to handle
     227     the varargs correctly and portably.  */
     228  
     229  void
     230  as_warn_where (const char *file, unsigned int line, const char *format, ...)
     231  {
     232    va_list args;
     233    char buffer[2000];
     234  
     235    if (!flag_no_warnings)
     236      {
     237        va_start (args, format);
     238        vsnprintf (buffer, sizeof (buffer), format, args);
     239        va_end (args);
     240        as_warn_internal (file, line, buffer);
     241      }
     242  }
     243  
     244  /* The common portion of as_bad and as_bad_where.  */
     245  
     246  static void
     247  as_bad_internal (const char *file, unsigned int line, char *buffer)
     248  {
     249    bool context = false;
     250  
     251    ++error_count;
     252  
     253    if (file == NULL)
     254      {
     255        file = as_where_top (&line);
     256        context = true;
     257      }
     258  
     259    identify (file);
     260    if (file)
     261      {
     262        if (line != 0)
     263  	fprintf (stderr, "%s:%u: %s%s\n", file, line, _("Error: "), buffer);
     264        else
     265  	fprintf (stderr, "%s: %s%s\n", file, _("Error: "), buffer);
     266      }
     267    else
     268      fprintf (stderr, "%s%s\n", _("Error: "), buffer);
     269  
     270    if (context)
     271      as_report_context ();
     272  
     273  #ifndef NO_LISTING
     274    listing_error (buffer);
     275  #endif
     276  }
     277  
     278  /* Send to stderr a string as a warning, and locate warning in input
     279     file(s).  Please use when there is no recovery, but we want to
     280     continue processing but not produce an object file.
     281     Please explain in string (which may have '\n's) what recovery was
     282     done.  */
     283  
     284  void
     285  as_bad (const char *format, ...)
     286  {
     287    va_list args;
     288    char buffer[2000];
     289  
     290    va_start (args, format);
     291    vsnprintf (buffer, sizeof (buffer), format, args);
     292    va_end (args);
     293  
     294    as_bad_internal ((char *) NULL, 0, buffer);
     295  }
     296  
     297  /* Like as_bad but the file name and line number are passed in.
     298     Unfortunately, we have to repeat the function in order to handle
     299     the varargs correctly and portably.  */
     300  
     301  void
     302  as_bad_where (const char *file, unsigned int line, const char *format, ...)
     303  {
     304    va_list args;
     305    char buffer[2000];
     306  
     307    va_start (args, format);
     308    vsnprintf (buffer, sizeof (buffer), format, args);
     309    va_end (args);
     310  
     311    as_bad_internal (file, line, buffer);
     312  }
     313  
     314  /* Send to stderr a string as a fatal message, and print location of
     315     error in input file(s).
     316     Please only use this for when we DON'T have some recovery action.
     317     It xexit()s with a warning status.  */
     318  
     319  void
     320  as_fatal (const char *format, ...)
     321  {
     322    va_list args;
     323  
     324    as_show_where ();
     325    va_start (args, format);
     326    fprintf (stderr, _("Fatal error: "));
     327    vfprintf (stderr, format, args);
     328    (void) putc ('\n', stderr);
     329    va_end (args);
     330    as_report_context ();
     331    /* Delete the output file, if it exists.  This will prevent make from
     332       thinking that a file was created and hence does not need rebuilding.  */
     333    if (out_file_name != NULL)
     334      unlink_if_ordinary (out_file_name);
     335    xexit (EXIT_FAILURE);
     336  }
     337  
     338  /* Indicate internal constency error.
     339     Arguments: Filename, line number, optional function name.
     340     FILENAME may be NULL, which we use for crash-via-signal.  */
     341  
     342  void
     343  as_abort (const char *file, int line, const char *fn)
     344  {
     345    as_show_where ();
     346  
     347    if (!file)
     348      fprintf (stderr, _("Internal error (%s).\n"), fn ? fn : "unknown");
     349    else if (fn)
     350      fprintf (stderr, _("Internal error in %s at %s:%d.\n"), fn, file, line);
     351    else
     352      fprintf (stderr, _("Internal error at %s:%d.\n"), file, line);
     353    as_report_context ();
     354  
     355    fprintf (stderr, _("Please report this bug.\n"));
     356  
     357    xexit (EXIT_FAILURE);
     358  }
     359  
     360  /* Handler for fatal signals, such as SIGSEGV. */
     361  
     362  static void
     363  signal_crash (int signo)
     364  {
     365    /* Reset, to prevent unbounded recursion.  */
     366    signal (signo, SIG_DFL);
     367  
     368    as_abort (NULL, 0, strsignal (signo));
     369  }
     370  
     371  /* Register signal handlers, for less abrubt crashes.  */
     372  
     373  void
     374  signal_init (void)
     375  {
     376  #ifdef SIGSEGV
     377    signal (SIGSEGV, signal_crash);
     378  #endif
     379  #ifdef SIGILL
     380    signal (SIGILL, signal_crash);
     381  #endif
     382  #ifdef SIGBUS
     383    signal (SIGBUS, signal_crash);
     384  #endif
     385  #ifdef SIGABRT
     386    signal (SIGABRT, signal_crash);
     387  #endif
     388  #if defined SIGIOT && (!defined SIGABRT || SIGABRT != SIGIOT)
     389    signal (SIGIOT, signal_crash);
     390  #endif
     391  #ifdef SIGFPE
     392    signal (SIGFPE, signal_crash);
     393  #endif
     394  }
     395  
     396  /* Support routines.  */
     397  
     398  #define HEX_MAX_THRESHOLD	1024
     399  #define HEX_MIN_THRESHOLD	-(HEX_MAX_THRESHOLD)
     400  
     401  static void
     402  as_internal_value_out_of_range (const char *prefix,
     403  				offsetT val,
     404  				offsetT min,
     405  				offsetT max,
     406  				const char *file,
     407  				unsigned line,
     408  				bool bad)
     409  {
     410    const char * err;
     411  
     412    if (prefix == NULL)
     413      prefix = "";
     414  
     415    if (val >= min && val <= max)
     416      {
     417        addressT right = max & -max;
     418  
     419        if (max <= 1)
     420  	abort ();
     421  
     422        /* xgettext:c-format  */
     423        err = _("%s out of domain (%" PRId64
     424  	      " is not a multiple of %" PRId64 ")");
     425  
     426        if (bad)
     427  	as_bad_where (file, line, err, prefix, (int64_t) val, (int64_t) right);
     428        else
     429  	as_warn_where (file, line, err, prefix, (int64_t) val, (int64_t) right);
     430      }
     431    else if (   val < HEX_MAX_THRESHOLD
     432  	   && min < HEX_MAX_THRESHOLD
     433  	   && max < HEX_MAX_THRESHOLD
     434  	   && val > HEX_MIN_THRESHOLD
     435  	   && min > HEX_MIN_THRESHOLD
     436  	   && max > HEX_MIN_THRESHOLD)
     437      {
     438        /* xgettext:c-format.  */
     439        err = _("%s out of range (%" PRId64
     440  	      " is not between %" PRId64 " and %" PRId64 ")");
     441  
     442        if (bad)
     443  	as_bad_where (file, line, err, prefix,
     444  		      (int64_t) val, (int64_t) min, (int64_t) max);
     445        else
     446  	as_warn_where (file, line, err, prefix,
     447  		       (int64_t) val, (int64_t) min, (int64_t) max);
     448      }
     449    else
     450      {
     451        /* xgettext:c-format.  */
     452        err = _("%s out of range (0x%" PRIx64
     453  	      " is not between 0x%" PRIx64 " and 0x%" PRIx64 ")");
     454  
     455        if (bad)
     456  	as_bad_where (file, line, err, prefix,
     457  		      (int64_t) val, (int64_t) min, (int64_t) max);
     458        else
     459  	as_warn_where (file, line, err, prefix,
     460  		       (int64_t) val, (int64_t) min, (int64_t) max);
     461      }
     462  }
     463  
     464  void
     465  as_warn_value_out_of_range (const char *prefix,
     466  			   offsetT value,
     467  			   offsetT min,
     468  			   offsetT max,
     469  			   const char *file,
     470  			   unsigned line)
     471  {
     472    as_internal_value_out_of_range (prefix, value, min, max, file, line, false);
     473  }
     474  
     475  void
     476  as_bad_value_out_of_range (const char *prefix,
     477  			   offsetT value,
     478  			   offsetT min,
     479  			   offsetT max,
     480  			   const char *file,
     481  			   unsigned line)
     482  {
     483    as_internal_value_out_of_range (prefix, value, min, max, file, line, true);
     484  }