Commit | Line | Data |
---|---|---|
252b5132 | 1 | /* messages.c - error reporter - |
82704155 | 2 | Copyright (C) 1987-2019 Free Software Foundation, Inc. |
252b5132 RH |
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 | |
ec2655a6 | 7 | the Free Software Foundation; either version 3, or (at your option) |
252b5132 RH |
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 | |
4b4da160 NC |
17 | Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA |
18 | 02110-1301, USA. */ | |
252b5132 RH |
19 | |
20 | #include "as.h" | |
1ec4b9f2 NS |
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 | |
252b5132 | 28 | |
3b4dbbbf | 29 | static void identify (const char *); |
254d758c | 30 | static void as_show_where (void); |
3b4dbbbf TS |
31 | static void as_warn_internal (const char *, unsigned int, char *); |
32 | static void as_bad_internal (const char *, unsigned int, char *); | |
1ec4b9f2 | 33 | static void signal_crash (int) ATTRIBUTE_NORETURN; |
252b5132 | 34 | |
ef99799a | 35 | /* Despite the rest of the comments in this file, (FIXME-SOON), |
5a1964ec NC |
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 | |
1ec4b9f2 NS |
69 | continues as though no error occurred. |
70 | ||
71 | as_abort () is used for logic failure (assert or abort, signal). | |
72 | */ | |
252b5132 RH |
73 | |
74 | static void | |
3b4dbbbf | 75 | identify (const char *file) |
252b5132 RH |
76 | { |
77 | static int identified; | |
5a1964ec | 78 | |
252b5132 RH |
79 | if (identified) |
80 | return; | |
81 | identified++; | |
82 | ||
83 | if (!file) | |
84 | { | |
85 | unsigned int x; | |
3b4dbbbf | 86 | file = as_where (&x); |
252b5132 RH |
87 | } |
88 | ||
89 | if (file) | |
90 | fprintf (stderr, "%s: ", file); | |
91 | fprintf (stderr, _("Assembler messages:\n")); | |
92 | } | |
93 | ||
ef99799a KH |
94 | /* The number of warnings issued. */ |
95 | static int warning_count; | |
252b5132 | 96 | |
c488923f | 97 | int |
254d758c | 98 | had_warnings (void) |
252b5132 | 99 | { |
5a1964ec | 100 | return warning_count; |
252b5132 RH |
101 | } |
102 | ||
103 | /* Nonzero if we've hit a 'bad error', and should not write an obj file, | |
ef99799a | 104 | and exit with a nonzero error code. */ |
252b5132 RH |
105 | |
106 | static int error_count; | |
107 | ||
c488923f | 108 | int |
254d758c | 109 | had_errors (void) |
252b5132 | 110 | { |
5a1964ec | 111 | return error_count; |
252b5132 RH |
112 | } |
113 | ||
252b5132 RH |
114 | /* Print the current location to stderr. */ |
115 | ||
116 | static void | |
254d758c | 117 | as_show_where (void) |
252b5132 | 118 | { |
3b4dbbbf | 119 | const char *file; |
252b5132 RH |
120 | unsigned int line; |
121 | ||
3b4dbbbf | 122 | file = as_where (&line); |
252b5132 RH |
123 | identify (file); |
124 | if (file) | |
144886fa AM |
125 | { |
126 | if (line != 0) | |
127 | fprintf (stderr, "%s:%u: ", file, line); | |
128 | else | |
129 | fprintf (stderr, "%s: ", file); | |
130 | } | |
252b5132 RH |
131 | } |
132 | ||
ef99799a KH |
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. */ | |
252b5132 | 138 | |
c488923f | 139 | void |
ef99799a | 140 | as_tsktsk (const char *format, ...) |
252b5132 RH |
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); | |
ef99799a | 149 | } |
252b5132 RH |
150 | |
151 | /* The common portion of as_warn and as_warn_where. */ | |
152 | ||
153 | static void | |
3b4dbbbf | 154 | as_warn_internal (const char *file, unsigned int line, char *buffer) |
252b5132 RH |
155 | { |
156 | ++warning_count; | |
157 | ||
158 | if (file == NULL) | |
3b4dbbbf | 159 | file = as_where (&line); |
252b5132 RH |
160 | |
161 | identify (file); | |
162 | if (file) | |
144886fa AM |
163 | { |
164 | if (line != 0) | |
b52855e7 | 165 | fprintf (stderr, "%s:%u: %s%s\n", file, line, _("Warning: "), buffer); |
144886fa | 166 | else |
b52855e7 | 167 | fprintf (stderr, "%s: %s%s\n", file, _("Warning: "), buffer); |
144886fa | 168 | } |
39128ec0 | 169 | else |
b52855e7 | 170 | fprintf (stderr, "%s%s\n", _("Warning: "), buffer); |
252b5132 RH |
171 | #ifndef NO_LISTING |
172 | listing_warning (buffer); | |
173 | #endif | |
174 | } | |
175 | ||
ef99799a KH |
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. */ | |
252b5132 | 181 | |
c488923f | 182 | void |
ef99799a | 183 | as_warn (const char *format, ...) |
252b5132 RH |
184 | { |
185 | va_list args; | |
186 | char buffer[2000]; | |
187 | ||
188 | if (!flag_no_warnings) | |
189 | { | |
190 | va_start (args, format); | |
a9bfff94 | 191 | vsnprintf (buffer, sizeof (buffer), format, args); |
252b5132 RH |
192 | va_end (args); |
193 | as_warn_internal ((char *) NULL, 0, buffer); | |
194 | } | |
ef99799a | 195 | } |
252b5132 | 196 | |
ef99799a KH |
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. */ | |
252b5132 | 200 | |
c488923f | 201 | void |
3b4dbbbf | 202 | as_warn_where (const char *file, unsigned int line, const char *format, ...) |
252b5132 RH |
203 | { |
204 | va_list args; | |
205 | char buffer[2000]; | |
206 | ||
207 | if (!flag_no_warnings) | |
208 | { | |
209 | va_start (args, format); | |
a9bfff94 | 210 | vsnprintf (buffer, sizeof (buffer), format, args); |
252b5132 RH |
211 | va_end (args); |
212 | as_warn_internal (file, line, buffer); | |
213 | } | |
ef99799a | 214 | } |
252b5132 RH |
215 | |
216 | /* The common portion of as_bad and as_bad_where. */ | |
217 | ||
218 | static void | |
3b4dbbbf | 219 | as_bad_internal (const char *file, unsigned int line, char *buffer) |
252b5132 RH |
220 | { |
221 | ++error_count; | |
222 | ||
223 | if (file == NULL) | |
3b4dbbbf | 224 | file = as_where (&line); |
252b5132 RH |
225 | |
226 | identify (file); | |
227 | if (file) | |
144886fa AM |
228 | { |
229 | if (line != 0) | |
b52855e7 | 230 | fprintf (stderr, "%s:%u: %s%s\n", file, line, _("Error: "), buffer); |
144886fa | 231 | else |
b52855e7 | 232 | fprintf (stderr, "%s: %s%s\n", file, _("Error: "), buffer); |
144886fa | 233 | } |
39128ec0 | 234 | else |
b52855e7 | 235 | fprintf (stderr, "%s%s\n", _("Error: "), buffer); |
252b5132 RH |
236 | #ifndef NO_LISTING |
237 | listing_error (buffer); | |
238 | #endif | |
239 | } | |
240 | ||
ef99799a | 241 | /* Send to stderr a string as a warning, and locate warning in input |
08918cc8 | 242 | file(s). Please use when there is no recovery, but we want to |
ef99799a KH |
243 | continue processing but not produce an object file. |
244 | Please explain in string (which may have '\n's) what recovery was | |
43ad3147 | 245 | done. */ |
252b5132 | 246 | |
c488923f | 247 | void |
ef99799a | 248 | as_bad (const char *format, ...) |
252b5132 RH |
249 | { |
250 | va_list args; | |
251 | char buffer[2000]; | |
252 | ||
253 | va_start (args, format); | |
a9bfff94 | 254 | vsnprintf (buffer, sizeof (buffer), format, args); |
252b5132 RH |
255 | va_end (args); |
256 | ||
257 | as_bad_internal ((char *) NULL, 0, buffer); | |
258 | } | |
259 | ||
ef99799a KH |
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. */ | |
252b5132 | 263 | |
c488923f | 264 | void |
3b4dbbbf | 265 | as_bad_where (const char *file, unsigned int line, const char *format, ...) |
252b5132 RH |
266 | { |
267 | va_list args; | |
268 | char buffer[2000]; | |
269 | ||
270 | va_start (args, format); | |
a9bfff94 | 271 | vsnprintf (buffer, sizeof (buffer), format, args); |
252b5132 RH |
272 | va_end (args); |
273 | ||
274 | as_bad_internal (file, line, buffer); | |
275 | } | |
276 | ||
ef99799a KH |
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. */ | |
252b5132 | 281 | |
c488923f | 282 | void |
ef99799a | 283 | as_fatal (const char *format, ...) |
252b5132 RH |
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); | |
d4887adc NC |
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) | |
bb14f524 | 296 | unlink_if_ordinary (out_file_name); |
252b5132 | 297 | xexit (EXIT_FAILURE); |
ef99799a | 298 | } |
252b5132 | 299 | |
1ec4b9f2 NS |
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. */ | |
252b5132 RH |
303 | |
304 | void | |
1ec4b9f2 | 305 | as_abort (const char *file, int line, const char *fn) |
252b5132 RH |
306 | { |
307 | as_show_where (); | |
1ec4b9f2 NS |
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); | |
252b5132 | 313 | else |
1ec4b9f2 NS |
314 | fprintf (stderr, _("Internal error at %s:%d.\n"), file, line); |
315 | ||
252b5132 | 316 | fprintf (stderr, _("Please report this bug.\n")); |
1ec4b9f2 | 317 | |
252b5132 RH |
318 | xexit (EXIT_FAILURE); |
319 | } | |
320 | ||
1ec4b9f2 NS |
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. */ | |
ef99799a | 333 | |
252b5132 | 334 | void |
1ec4b9f2 | 335 | signal_init (void) |
252b5132 | 336 | { |
1ec4b9f2 NS |
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 | |
252b5132 RH |
355 | } |
356 | ||
357 | /* Support routines. */ | |
358 | ||
252b5132 | 359 | void |
254d758c | 360 | sprint_value (char *buf, valueT val) |
252b5132 RH |
361 | { |
362 | if (sizeof (val) <= sizeof (long)) | |
363 | { | |
364 | sprintf (buf, "%ld", (long) val); | |
365 | return; | |
366 | } | |
252b5132 RH |
367 | if (sizeof (val) <= sizeof (bfd_vma)) |
368 | { | |
369 | sprintf_vma (buf, val); | |
370 | return; | |
371 | } | |
252b5132 RH |
372 | abort (); |
373 | } | |
e5976317 NC |
374 | |
375 | #define HEX_MAX_THRESHOLD 1024 | |
376 | #define HEX_MIN_THRESHOLD -(HEX_MAX_THRESHOLD) | |
377 | ||
378 | static void | |
6d4af3c2 AM |
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) | |
e5976317 NC |
386 | { |
387 | const char * err; | |
388 | ||
389 | if (prefix == NULL) | |
390 | prefix = ""; | |
391 | ||
b84bf58a AM |
392 | if (val >= min && val <= max) |
393 | { | |
394 | addressT right = max & -max; | |
395 | ||
396 | if (max <= 1) | |
397 | abort (); | |
398 | ||
399 | /* xgettext:c-format */ | |
8acf1435 PB |
400 | err = _("%s out of domain (%" BFD_VMA_FMT "d is not a multiple of %" \ |
401 | BFD_VMA_FMT "d)"); | |
b84bf58a | 402 | if (bad) |
8acf1435 | 403 | as_bad_where (file, line, err, prefix, val, right); |
b84bf58a | 404 | else |
8acf1435 | 405 | as_warn_where (file, line, err, prefix, val, right); |
931774a9 | 406 | return; |
b84bf58a AM |
407 | } |
408 | ||
e5976317 NC |
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) | |
e5976317 NC |
415 | { |
416 | /* xgettext:c-format */ | |
8acf1435 PB |
417 | err = _("%s out of range (%" BFD_VMA_FMT "d is not between %" \ |
418 | BFD_VMA_FMT "d and %" BFD_VMA_FMT "d)"); | |
e5976317 NC |
419 | |
420 | if (bad) | |
8acf1435 | 421 | as_bad_where (file, line, err, prefix, val, min, max); |
e5976317 | 422 | else |
8acf1435 | 423 | as_warn_where (file, line, err, prefix, val, min, max); |
e5976317 | 424 | } |
e5976317 NC |
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 | ||
0af1713e AM |
434 | sprintf_vma (val_buf, (bfd_vma) val); |
435 | sprintf_vma (min_buf, (bfd_vma) min); | |
436 | sprintf_vma (max_buf, (bfd_vma) max); | |
e5976317 NC |
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 | } | |
e5976317 NC |
446 | } |
447 | ||
448 | void | |
6d4af3c2 AM |
449 | as_warn_value_out_of_range (const char *prefix, |
450 | offsetT value, | |
451 | offsetT min, | |
452 | offsetT max, | |
453 | const char *file, | |
e5976317 NC |
454 | unsigned line) |
455 | { | |
456 | as_internal_value_out_of_range (prefix, value, min, max, file, line, 0); | |
457 | } | |
458 | ||
459 | void | |
6d4af3c2 AM |
460 | as_bad_value_out_of_range (const char *prefix, |
461 | offsetT value, | |
462 | offsetT min, | |
463 | offsetT max, | |
464 | const char *file, | |
e5976317 NC |
465 | unsigned line) |
466 | { | |
467 | as_internal_value_out_of_range (prefix, value, min, max, file, line, 1); | |
468 | } |