]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - binutils/bucomm.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / binutils / bucomm.c
1 /* bucomm.c -- Bin Utils COMmon code.
2 Copyright (C) 1991-2022 Free Software Foundation, Inc.
3
4 This file is part of GNU Binutils.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
19 02110-1301, USA. */
20 \f
21 /* We might put this in a library someday so it could be dynamically
22 loaded, but for now it's not necessary. */
23
24 #include "sysdep.h"
25 #include "bfd.h"
26 #include "libiberty.h"
27 #include "filenames.h"
28 #include <time.h>
29 #include <assert.h>
30 #include "bucomm.h"
31 \f
32 /* Error reporting. */
33
34 char *program_name;
35
36 void
37 bfd_nonfatal (const char *string)
38 {
39 const char *errmsg;
40 enum bfd_error err = bfd_get_error ();
41
42 if (err == bfd_error_no_error)
43 errmsg = _("cause of error unknown");
44 else
45 errmsg = bfd_errmsg (err);
46 fflush (stdout);
47 if (string)
48 fprintf (stderr, "%s: %s: %s\n", program_name, string, errmsg);
49 else
50 fprintf (stderr, "%s: %s\n", program_name, errmsg);
51 }
52
53 /* Issue a non fatal error message. FILENAME, or if NULL then BFD,
54 are used to indicate the problematic file. SECTION, if non NULL,
55 is used to provide a section name. If FORMAT is non-null, then it
56 is used to print additional information via vfprintf. Finally the
57 bfd error message is printed. In summary, error messages are of
58 one of the following forms:
59
60 PROGRAM: file: bfd-error-message
61 PROGRAM: file[section]: bfd-error-message
62 PROGRAM: file: printf-message: bfd-error-message
63 PROGRAM: file[section]: printf-message: bfd-error-message. */
64
65 void
66 bfd_nonfatal_message (const char *filename,
67 const bfd *abfd,
68 const asection *section,
69 const char *format, ...)
70 {
71 const char *errmsg;
72 const char *section_name;
73 enum bfd_error err = bfd_get_error ();
74
75 if (err == bfd_error_no_error)
76 errmsg = _("cause of error unknown");
77 else
78 errmsg = bfd_errmsg (err);
79 fflush (stdout);
80 section_name = NULL;
81 fprintf (stderr, "%s", program_name);
82
83 if (abfd)
84 {
85 if (!filename)
86 filename = bfd_get_archive_filename (abfd);
87 if (section)
88 section_name = bfd_section_name (section);
89 }
90 if (section_name)
91 fprintf (stderr, ": %s[%s]", filename, section_name);
92 else
93 fprintf (stderr, ": %s", filename);
94
95 if (format)
96 {
97 va_list args;
98 va_start (args, format);
99 fprintf (stderr, ": ");
100 vfprintf (stderr, format, args);
101 va_end (args);
102 }
103 fprintf (stderr, ": %s\n", errmsg);
104 }
105
106 void
107 bfd_fatal (const char *string)
108 {
109 bfd_nonfatal (string);
110 xexit (1);
111 }
112
113 void
114 report (const char * format, va_list args)
115 {
116 fflush (stdout);
117 fprintf (stderr, "%s: ", program_name);
118 vfprintf (stderr, format, args);
119 putc ('\n', stderr);
120 }
121
122 void
123 fatal (const char *format, ...)
124 {
125 va_list args;
126
127 va_start (args, format);
128
129 report (format, args);
130 va_end (args);
131 xexit (1);
132 }
133
134 void
135 non_fatal (const char *format, ...)
136 {
137 va_list args;
138
139 va_start (args, format);
140
141 report (format, args);
142 va_end (args);
143 }
144
145 /* Set the default BFD target based on the configured target. Doing
146 this permits the binutils to be configured for a particular target,
147 and linked against a shared BFD library which was configured for a
148 different target. */
149
150 void
151 set_default_bfd_target (void)
152 {
153 /* The macro TARGET is defined by Makefile. */
154 const char *target = TARGET;
155
156 if (! bfd_set_default_target (target))
157 fatal (_("can't set BFD default target to `%s': %s"),
158 target, bfd_errmsg (bfd_get_error ()));
159 }
160
161 /* After a FALSE return from bfd_check_format_matches with
162 bfd_get_error () == bfd_error_file_ambiguously_recognized, print
163 the possible matching targets. */
164
165 void
166 list_matching_formats (char **p)
167 {
168 fflush (stdout);
169 fprintf (stderr, _("%s: Matching formats:"), program_name);
170 while (*p)
171 fprintf (stderr, " %s", *p++);
172 fputc ('\n', stderr);
173 }
174
175 /* List the supported targets. */
176
177 void
178 list_supported_targets (const char *name, FILE *f)
179 {
180 int t;
181 const char **targ_names;
182
183 if (name == NULL)
184 fprintf (f, _("Supported targets:"));
185 else
186 fprintf (f, _("%s: supported targets:"), name);
187
188 targ_names = bfd_target_list ();
189 for (t = 0; targ_names[t] != NULL; t++)
190 fprintf (f, " %s", targ_names[t]);
191 fprintf (f, "\n");
192 free (targ_names);
193 }
194
195 /* List the supported architectures. */
196
197 void
198 list_supported_architectures (const char *name, FILE *f)
199 {
200 const char ** arch;
201 const char ** arches;
202
203 if (name == NULL)
204 fprintf (f, _("Supported architectures:"));
205 else
206 fprintf (f, _("%s: supported architectures:"), name);
207
208 for (arch = arches = bfd_arch_list (); *arch; arch++)
209 fprintf (f, " %s", *arch);
210 fprintf (f, "\n");
211 free (arches);
212 }
213 \f
214 static const char *
215 endian_string (enum bfd_endian endian)
216 {
217 switch (endian)
218 {
219 case BFD_ENDIAN_BIG: return _("big endian");
220 case BFD_ENDIAN_LITTLE: return _("little endian");
221 default: return _("endianness unknown");
222 }
223 }
224
225 /* Data passed to do_display_target and other target iterators. */
226
227 struct display_target {
228 /* Temp file. */
229 char *filename;
230 /* Return status. */
231 int error;
232 /* Number of targets. */
233 int count;
234 /* Size of info in bytes. */
235 size_t alloc;
236 /* Per-target info. */
237 struct {
238 /* Target name. */
239 const char *name;
240 /* Non-zero if target/arch combination supported. */
241 unsigned char arch[bfd_arch_last - bfd_arch_obscure - 1];
242 } *info;
243 };
244
245 /* List the targets that BFD is configured to support, each followed
246 by its endianness and the architectures it supports. Also build
247 info about target/archs. */
248
249 static int
250 do_display_target (const bfd_target *targ, void *data)
251 {
252 struct display_target *param = (struct display_target *) data;
253 bfd *abfd;
254 size_t amt;
255
256 param->count += 1;
257 amt = param->count * sizeof (*param->info);
258 if (param->alloc < amt)
259 {
260 size_t size = ((param->count < 64 ? 64 : param->count)
261 * sizeof (*param->info) * 2);
262 param->info = xrealloc (param->info, size);
263 memset ((char *) param->info + param->alloc, 0, size - param->alloc);
264 param->alloc = size;
265 }
266 param->info[param->count - 1].name = targ->name;
267
268 printf (_("%s\n (header %s, data %s)\n"), targ->name,
269 endian_string (targ->header_byteorder),
270 endian_string (targ->byteorder));
271
272 abfd = bfd_openw (param->filename, targ->name);
273 if (abfd == NULL)
274 {
275 bfd_nonfatal (param->filename);
276 param->error = 1;
277 }
278 else if (!bfd_set_format (abfd, bfd_object))
279 {
280 if (bfd_get_error () != bfd_error_invalid_operation)
281 {
282 bfd_nonfatal (targ->name);
283 param->error = 1;
284 }
285 }
286 else
287 {
288 enum bfd_architecture a;
289
290 for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++)
291 if (bfd_set_arch_mach (abfd, a, 0))
292 {
293 printf (" %s\n", bfd_printable_arch_mach (a, 0));
294 param->info[param->count - 1].arch[a - bfd_arch_obscure - 1] = 1;
295 }
296 }
297 if (abfd != NULL)
298 bfd_close_all_done (abfd);
299
300 return param->error;
301 }
302
303 static void
304 display_target_list (struct display_target *arg)
305 {
306 arg->filename = make_temp_file (NULL);
307 arg->error = 0;
308 arg->count = 0;
309 arg->alloc = 0;
310 arg->info = NULL;
311
312 bfd_iterate_over_targets (do_display_target, arg);
313
314 unlink (arg->filename);
315 free (arg->filename);
316 }
317
318 /* Calculate how many targets we can print across the page. */
319
320 static int
321 do_info_size (int targ, int width, const struct display_target *arg)
322 {
323 while (targ < arg->count)
324 {
325 width -= strlen (arg->info[targ].name) + 1;
326 if (width < 0)
327 return targ;
328 ++targ;
329 }
330 return targ;
331 }
332
333 /* Print header of target names. */
334
335 static void
336 do_info_header (int targ, int stop_targ, const struct display_target *arg)
337 {
338 while (targ != stop_targ)
339 printf ("%s ", arg->info[targ++].name);
340 }
341
342 /* Print a table row. */
343
344 static void
345 do_info_row (int targ, int stop_targ, enum bfd_architecture a,
346 const struct display_target *arg)
347 {
348 while (targ != stop_targ)
349 {
350 if (arg->info[targ].arch[a - bfd_arch_obscure - 1])
351 fputs (arg->info[targ].name, stdout);
352 else
353 {
354 int l = strlen (arg->info[targ].name);
355 while (l--)
356 putchar ('-');
357 }
358 ++targ;
359 if (targ != stop_targ)
360 putchar (' ');
361 }
362 }
363
364 /* Print tables of all the target-architecture combinations that
365 BFD has been configured to support. */
366
367 static void
368 display_target_tables (const struct display_target *arg)
369 {
370 const char *columns;
371 int width, start_targ, stop_targ;
372 enum bfd_architecture arch;
373 int longest_arch = 0;
374
375 for (arch = bfd_arch_obscure + 1; arch < bfd_arch_last; arch++)
376 {
377 const char *s = bfd_printable_arch_mach (arch, 0);
378 int len = strlen (s);
379 if (len > longest_arch)
380 longest_arch = len;
381 }
382
383 width = 0;
384 columns = getenv ("COLUMNS");
385 if (columns != NULL)
386 width = atoi (columns);
387 if (width == 0)
388 width = 80;
389
390 for (start_targ = 0; start_targ < arg->count; start_targ = stop_targ)
391 {
392 stop_targ = do_info_size (start_targ, width - longest_arch - 1, arg);
393
394 printf ("\n%*s", longest_arch + 1, " ");
395 do_info_header (start_targ, stop_targ, arg);
396 putchar ('\n');
397
398 for (arch = bfd_arch_obscure + 1; arch < bfd_arch_last; arch++)
399 {
400 if (strcmp (bfd_printable_arch_mach (arch, 0), "UNKNOWN!") != 0)
401 {
402 printf ("%*s ", longest_arch,
403 bfd_printable_arch_mach (arch, 0));
404
405 do_info_row (start_targ, stop_targ, arch, arg);
406 putchar ('\n');
407 }
408 }
409 }
410 }
411
412 int
413 display_info (void)
414 {
415 struct display_target arg;
416
417 printf (_("BFD header file version %s\n"), BFD_VERSION_STRING);
418
419 display_target_list (&arg);
420 if (!arg.error)
421 display_target_tables (&arg);
422
423 return arg.error;
424 }
425 \f
426 /* Display the archive header for an element as if it were an ls -l listing:
427
428 Mode User\tGroup\tSize\tDate Name */
429
430 void
431 print_arelt_descr (FILE *file, bfd *abfd, bool verbose, bool offsets)
432 {
433 struct stat buf;
434
435 if (verbose)
436 {
437 if (bfd_stat_arch_elt (abfd, &buf) == 0)
438 {
439 char modebuf[11];
440 char timebuf[40];
441 time_t when = buf.st_mtime;
442 const char *ctime_result = (const char *) ctime (&when);
443 bfd_size_type size;
444
445 /* PR binutils/17605: Check for corrupt time values. */
446 if (ctime_result == NULL)
447 sprintf (timebuf, _("<time data corrupt>"));
448 else
449 /* POSIX format: skip weekday and seconds from ctime output. */
450 sprintf (timebuf, "%.12s %.4s", ctime_result + 4, ctime_result + 20);
451
452 mode_string (buf.st_mode, modebuf);
453 modebuf[10] = '\0';
454 size = buf.st_size;
455 /* POSIX 1003.2/D11 says to skip first character (entry type). */
456 fprintf (file, "%s %ld/%ld %6" BFD_VMA_FMT "u %s ", modebuf + 1,
457 (long) buf.st_uid, (long) buf.st_gid,
458 size, timebuf);
459 }
460 }
461
462 fprintf (file, "%s", bfd_get_filename (abfd));
463
464 if (offsets)
465 {
466 if (bfd_is_thin_archive (abfd) && abfd->proxy_origin)
467 fprintf (file, " 0x%lx", (unsigned long) abfd->proxy_origin);
468 else if (!bfd_is_thin_archive (abfd) && abfd->origin)
469 fprintf (file, " 0x%lx", (unsigned long) abfd->origin);
470 }
471
472 fprintf (file, "\n");
473 }
474
475 /* Return a path for a new temporary file in the same directory
476 as file PATH. */
477
478 static char *
479 template_in_dir (const char *path)
480 {
481 #define template "stXXXXXX"
482 const char *slash = strrchr (path, '/');
483 char *tmpname;
484 size_t len;
485
486 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
487 {
488 /* We could have foo/bar\\baz, or foo\\bar, or d:bar. */
489 char *bslash = strrchr (path, '\\');
490
491 if (slash == NULL || (bslash != NULL && bslash > slash))
492 slash = bslash;
493 if (slash == NULL && path[0] != '\0' && path[1] == ':')
494 slash = path + 1;
495 }
496 #endif
497
498 if (slash != (char *) NULL)
499 {
500 len = slash - path;
501 tmpname = (char *) xmalloc (len + sizeof (template) + 2);
502 memcpy (tmpname, path, len);
503
504 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
505 /* If tmpname is "X:", appending a slash will make it a root
506 directory on drive X, which is NOT the same as the current
507 directory on drive X. */
508 if (len == 2 && tmpname[1] == ':')
509 tmpname[len++] = '.';
510 #endif
511 tmpname[len++] = '/';
512 }
513 else
514 {
515 tmpname = (char *) xmalloc (sizeof (template));
516 len = 0;
517 }
518
519 memcpy (tmpname + len, template, sizeof (template));
520 return tmpname;
521 #undef template
522 }
523
524 /* Return the name of a created temporary file in the same directory
525 as FILENAME. */
526
527 char *
528 make_tempname (const char *filename, int *ofd)
529 {
530 char *tmpname = template_in_dir (filename);
531 int fd;
532
533 #ifdef HAVE_MKSTEMP
534 fd = mkstemp (tmpname);
535 #else
536 tmpname = mktemp (tmpname);
537 if (tmpname == NULL)
538 return NULL;
539 fd = open (tmpname, O_RDWR | O_CREAT | O_EXCL, 0600);
540 #endif
541 if (fd == -1)
542 {
543 free (tmpname);
544 return NULL;
545 }
546 *ofd = fd;
547 return tmpname;
548 }
549
550 /* Return the name of a created temporary directory inside the
551 directory containing FILENAME. */
552
553 char *
554 make_tempdir (const char *filename)
555 {
556 char *tmpname = template_in_dir (filename);
557
558 #ifdef HAVE_MKDTEMP
559 return mkdtemp (tmpname);
560 #else
561 tmpname = mktemp (tmpname);
562 if (tmpname == NULL)
563 return NULL;
564 #if defined (_WIN32) && !defined (__CYGWIN32__)
565 if (mkdir (tmpname) != 0)
566 return NULL;
567 #else
568 if (mkdir (tmpname, 0700) != 0)
569 return NULL;
570 #endif
571 return tmpname;
572 #endif
573 }
574
575 /* Parse a string into a VMA, with a fatal error if it can't be
576 parsed. */
577
578 bfd_vma
579 parse_vma (const char *s, const char *arg)
580 {
581 bfd_vma ret;
582 const char *end;
583
584 ret = bfd_scan_vma (s, &end, 0);
585
586 if (*end != '\0')
587 fatal (_("%s: bad number: %s"), arg, s);
588
589 return ret;
590 }
591
592 /* Returns the size of the named file. If the file does not
593 exist, or if it is not a real file, then a suitable non-fatal
594 error message is printed and (off_t) -1 is returned. */
595
596 off_t
597 get_file_size (const char * file_name)
598 {
599 struct stat statbuf;
600
601 if (file_name == NULL)
602 return (off_t) -1;
603
604 if (stat (file_name, &statbuf) < 0)
605 {
606 if (errno == ENOENT)
607 non_fatal (_("'%s': No such file"), file_name);
608 else
609 non_fatal (_("Warning: could not locate '%s'. reason: %s"),
610 file_name, strerror (errno));
611 }
612 else if (S_ISDIR (statbuf.st_mode))
613 non_fatal (_("Warning: '%s' is a directory"), file_name);
614 else if (! S_ISREG (statbuf.st_mode))
615 non_fatal (_("Warning: '%s' is not an ordinary file"), file_name);
616 else if (statbuf.st_size < 0)
617 non_fatal (_("Warning: '%s' has negative size, probably it is too large"),
618 file_name);
619 #if defined (_WIN32) && !defined (__CYGWIN__)
620 else if (statbuf.st_size == 0)
621 {
622 /* MS-Windows 'stat' reports the null device as a regular file;
623 fix that. */
624 int fd = open (file_name, O_RDONLY | O_BINARY);
625 if (isatty (fd))
626 {
627 close (fd);
628 non_fatal (_("Warning: '%s' is not an ordinary file"),
629 /* libtool wants to see /dev/null in the output. */
630 strcasecmp (file_name, "nul") ? file_name : "/dev/null");
631 }
632 }
633 #endif
634 else
635 return statbuf.st_size;
636
637 return (off_t) -1;
638 }
639
640 /* Return the filename in a static buffer. */
641
642 const char *
643 bfd_get_archive_filename (const bfd *abfd)
644 {
645 static size_t curr = 0;
646 static char *buf;
647 size_t needed;
648
649 assert (abfd != NULL);
650
651 if (abfd->my_archive == NULL
652 || bfd_is_thin_archive (abfd->my_archive))
653 return bfd_get_filename (abfd);
654
655 needed = (strlen (bfd_get_filename (abfd->my_archive))
656 + strlen (bfd_get_filename (abfd)) + 3);
657 if (needed > curr)
658 {
659 if (curr)
660 free (buf);
661 curr = needed + (needed >> 1);
662 buf = (char *) xmalloc (curr);
663 }
664 sprintf (buf, "%s(%s)", bfd_get_filename (abfd->my_archive),
665 bfd_get_filename (abfd));
666 return buf;
667 }
668
669 /* Returns TRUE iff PATHNAME, a filename of an archive member,
670 is valid for writing. For security reasons absolute paths
671 and paths containing /../ are not allowed. See PR 17533. */
672
673 bool
674 is_valid_archive_path (char const * pathname)
675 {
676 const char * n = pathname;
677
678 if (IS_ABSOLUTE_PATH (n))
679 return false;
680
681 while (*n)
682 {
683 if (*n == '.' && *++n == '.' && ( ! *++n || IS_DIR_SEPARATOR (*n)))
684 return false;
685
686 while (*n && ! IS_DIR_SEPARATOR (*n))
687 n++;
688 while (IS_DIR_SEPARATOR (*n))
689 n++;
690 }
691
692 return true;
693 }