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