xref: /netbsd-src/external/gpl3/binutils.old/dist/binutils/bucomm.c (revision ccd9df534e375a4366c5b55f23782053c7a98d82)
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 
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 
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 /* Like xmalloc except that ABFD's objalloc memory is returned.
146    Use objalloc_free_block to free this memory and all more recently
147    allocated, or more usually, leave it to bfd_close to free.  */
148 
149 void *
150 bfd_xalloc (bfd *abfd, size_t size)
151 {
152   void *ret = bfd_alloc (abfd, size);
153   if (ret == NULL)
154     bfd_fatal (NULL);
155   return ret;
156 }
157 
158 /* Set the default BFD target based on the configured target.  Doing
159    this permits the binutils to be configured for a particular target,
160    and linked against a shared BFD library which was configured for a
161    different target.  */
162 
163 void
164 set_default_bfd_target (void)
165 {
166   /* The macro TARGET is defined by Makefile.  */
167   const char *target = TARGET;
168 
169   if (! bfd_set_default_target (target))
170     fatal (_("can't set BFD default target to `%s': %s"),
171 	   target, bfd_errmsg (bfd_get_error ()));
172 }
173 
174 /* After a FALSE return from bfd_check_format_matches with
175    bfd_get_error () == bfd_error_file_ambiguously_recognized, print
176    the possible matching targets and free the list of targets.  */
177 
178 void
179 list_matching_formats (char **matching)
180 {
181   fflush (stdout);
182   fprintf (stderr, _("%s: Matching formats:"), program_name);
183   char **p = matching;
184   while (*p)
185     fprintf (stderr, " %s", *p++);
186   free (matching);
187   fputc ('\n', stderr);
188 }
189 
190 /* List the supported targets.  */
191 
192 void
193 list_supported_targets (const char *name, FILE *f)
194 {
195   int t;
196   const char **targ_names;
197 
198   if (name == NULL)
199     fprintf (f, _("Supported targets:"));
200   else
201     fprintf (f, _("%s: supported targets:"), name);
202 
203   targ_names = bfd_target_list ();
204   for (t = 0; targ_names[t] != NULL; t++)
205     fprintf (f, " %s", targ_names[t]);
206   fprintf (f, "\n");
207   free (targ_names);
208 }
209 
210 /* List the supported architectures.  */
211 
212 void
213 list_supported_architectures (const char *name, FILE *f)
214 {
215   const char ** arch;
216   const char ** arches;
217 
218   if (name == NULL)
219     fprintf (f, _("Supported architectures:"));
220   else
221     fprintf (f, _("%s: supported architectures:"), name);
222 
223   for (arch = arches = bfd_arch_list (); *arch; arch++)
224     fprintf (f, " %s", *arch);
225   fprintf (f, "\n");
226   free (arches);
227 }
228 
229 static const char *
230 endian_string (enum bfd_endian endian)
231 {
232   switch (endian)
233     {
234     case BFD_ENDIAN_BIG: return _("big endian");
235     case BFD_ENDIAN_LITTLE: return _("little endian");
236     default: return _("endianness unknown");
237     }
238 }
239 
240 /* Data passed to do_display_target and other target iterators.  */
241 
242 struct display_target {
243   /* Temp file.  */
244   char *filename;
245   /* Return status.  */
246   int error;
247   /* Number of targets.  */
248   int count;
249   /* Size of info in bytes.  */
250   size_t alloc;
251   /* Per-target info.  */
252   struct {
253     /* Target name.  */
254     const char *name;
255     /* Non-zero if target/arch combination supported.  */
256     unsigned char arch[bfd_arch_last - bfd_arch_obscure - 1];
257   } *info;
258 };
259 
260 /* List the targets that BFD is configured to support, each followed
261    by its endianness and the architectures it supports.  Also build
262    info about target/archs.  */
263 
264 static int
265 do_display_target (const bfd_target *targ, void *data)
266 {
267   struct display_target *param = (struct display_target *) data;
268   bfd *abfd;
269   size_t amt;
270 
271   param->count += 1;
272   amt = param->count * sizeof (*param->info);
273   if (param->alloc < amt)
274     {
275       size_t size = ((param->count < 64 ? 64 : param->count)
276 		     * sizeof (*param->info) * 2);
277       param->info = xrealloc (param->info, size);
278       memset ((char *) param->info + param->alloc, 0, size - param->alloc);
279       param->alloc = size;
280     }
281   param->info[param->count - 1].name = targ->name;
282 
283   printf (_("%s\n (header %s, data %s)\n"), targ->name,
284 	  endian_string (targ->header_byteorder),
285 	  endian_string (targ->byteorder));
286 
287   abfd = bfd_openw (param->filename, targ->name);
288   if (abfd == NULL)
289     {
290       bfd_nonfatal (param->filename);
291       param->error = 1;
292     }
293   else if (!bfd_set_format (abfd, bfd_object))
294     {
295       if (bfd_get_error () != bfd_error_invalid_operation)
296 	{
297 	  bfd_nonfatal (targ->name);
298 	  param->error = 1;
299 	}
300     }
301   else
302     {
303       enum bfd_architecture a;
304 
305       for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++)
306 	if (bfd_set_arch_mach (abfd, a, 0))
307 	  {
308 	    printf ("  %s\n", bfd_printable_arch_mach (a, 0));
309 	    param->info[param->count - 1].arch[a - bfd_arch_obscure - 1] = 1;
310 	  }
311     }
312   if (abfd != NULL)
313     bfd_close_all_done (abfd);
314 
315   return param->error;
316 }
317 
318 static void
319 display_target_list (struct display_target *arg)
320 {
321   arg->filename = make_temp_file (NULL);
322   arg->error = 0;
323   arg->count = 0;
324   arg->alloc = 0;
325   arg->info = NULL;
326 
327   bfd_iterate_over_targets (do_display_target, arg);
328 
329   unlink (arg->filename);
330   free (arg->filename);
331 }
332 
333 /* Calculate how many targets we can print across the page.  */
334 
335 static int
336 do_info_size (int targ, int width, const struct display_target *arg)
337 {
338   while (targ < arg->count)
339     {
340       width -= strlen (arg->info[targ].name) + 1;
341       if (width < 0)
342 	return targ;
343       ++targ;
344     }
345   return targ;
346 }
347 
348 /* Print header of target names.  */
349 
350 static void
351 do_info_header (int targ, int stop_targ, const struct display_target *arg)
352 {
353   while (targ != stop_targ)
354     printf ("%s ", arg->info[targ++].name);
355 }
356 
357 /* Print a table row.  */
358 
359 static void
360 do_info_row (int targ, int stop_targ, enum bfd_architecture a,
361 	     const struct display_target *arg)
362 {
363   while (targ != stop_targ)
364     {
365       if (arg->info[targ].arch[a - bfd_arch_obscure - 1])
366 	fputs (arg->info[targ].name, stdout);
367       else
368 	{
369 	  int l = strlen (arg->info[targ].name);
370 	  while (l--)
371 	    putchar ('-');
372 	}
373       ++targ;
374       if (targ != stop_targ)
375 	putchar (' ');
376     }
377 }
378 
379 /* Print tables of all the target-architecture combinations that
380    BFD has been configured to support.  */
381 
382 static void
383 display_target_tables (const struct display_target *arg)
384 {
385   const char *columns;
386   int width, start_targ, stop_targ;
387   enum bfd_architecture arch;
388   int longest_arch = 0;
389 
390   for (arch = bfd_arch_obscure + 1; arch < bfd_arch_last; arch++)
391     {
392       const char *s = bfd_printable_arch_mach (arch, 0);
393       int len = strlen (s);
394       if (len > longest_arch)
395 	longest_arch = len;
396     }
397 
398   width = 0;
399   columns = getenv ("COLUMNS");
400   if (columns != NULL)
401     width = atoi (columns);
402   if (width == 0)
403     width = 80;
404 
405   for (start_targ = 0; start_targ < arg->count; start_targ = stop_targ)
406     {
407       stop_targ = do_info_size (start_targ, width - longest_arch - 1, arg);
408 
409       printf ("\n%*s", longest_arch + 1, " ");
410       do_info_header (start_targ, stop_targ, arg);
411       putchar ('\n');
412 
413       for (arch = bfd_arch_obscure + 1; arch < bfd_arch_last; arch++)
414 	{
415 	  if (strcmp (bfd_printable_arch_mach (arch, 0), "UNKNOWN!") != 0)
416 	    {
417 	      printf ("%*s ", longest_arch,
418 		      bfd_printable_arch_mach (arch, 0));
419 
420 	      do_info_row (start_targ, stop_targ, arch, arg);
421 	      putchar ('\n');
422 	    }
423 	}
424     }
425 }
426 
427 int
428 display_info (void)
429 {
430   struct display_target arg;
431 
432   printf (_("BFD header file version %s\n"), BFD_VERSION_STRING);
433 
434   display_target_list (&arg);
435   if (!arg.error)
436     display_target_tables (&arg);
437 
438   return arg.error;
439 }
440 
441 /* Display the archive header for an element as if it were an ls -l listing:
442 
443    Mode       User\tGroup\tSize\tDate               Name */
444 
445 void
446 print_arelt_descr (FILE *file, bfd *abfd, bool verbose, bool offsets)
447 {
448   struct stat buf;
449 
450   if (verbose)
451     {
452       if (bfd_stat_arch_elt (abfd, &buf) == 0)
453 	{
454 	  char modebuf[11];
455 	  char timebuf[40];
456 	  time_t when = buf.st_mtime;
457 	  const char *ctime_result = (const char *) ctime (&when);
458 	  bfd_size_type size;
459 
460 	  /* PR binutils/17605: Check for corrupt time values.  */
461 	  if (ctime_result == NULL)
462 	    sprintf (timebuf, _("<time data corrupt>"));
463 	  else
464 	    /* POSIX format:  skip weekday and seconds from ctime output.  */
465 	    sprintf (timebuf, "%.12s %.4s", ctime_result + 4, ctime_result + 20);
466 
467 	  mode_string (buf.st_mode, modebuf);
468 	  modebuf[10] = '\0';
469 	  size = buf.st_size;
470 	  /* POSIX 1003.2/D11 says to skip first character (entry type).  */
471 	  fprintf (file, "%s %ld/%ld %6" BFD_VMA_FMT "u %s ", modebuf + 1,
472 		   (long) buf.st_uid, (long) buf.st_gid,
473 		   size, timebuf);
474 	}
475     }
476 
477   fprintf (file, "%s", bfd_get_filename (abfd));
478 
479   if (offsets)
480     {
481       if (bfd_is_thin_archive (abfd) && abfd->proxy_origin)
482         fprintf (file, " 0x%lx", (unsigned long) abfd->proxy_origin);
483       else if (!bfd_is_thin_archive (abfd) && abfd->origin)
484         fprintf (file, " 0x%lx", (unsigned long) abfd->origin);
485     }
486 
487   fprintf (file, "\n");
488 }
489 
490 /* Return a path for a new temporary file in the same directory
491    as file PATH.  */
492 
493 static char *
494 template_in_dir (const char *path)
495 {
496 #define template "stXXXXXX"
497   const char *slash = strrchr (path, '/');
498   char *tmpname;
499   size_t len;
500 
501 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
502   {
503     /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
504     char *bslash = strrchr (path, '\\');
505 
506     if (slash == NULL || (bslash != NULL && bslash > slash))
507       slash = bslash;
508     if (slash == NULL && path[0] != '\0' && path[1] == ':')
509       slash = path + 1;
510   }
511 #endif
512 
513   if (slash != (char *) NULL)
514     {
515       len = slash - path;
516       tmpname = (char *) xmalloc (len + sizeof (template) + 2);
517       memcpy (tmpname, path, len);
518 
519 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
520       /* If tmpname is "X:", appending a slash will make it a root
521 	 directory on drive X, which is NOT the same as the current
522 	 directory on drive X.  */
523       if (len == 2 && tmpname[1] == ':')
524 	tmpname[len++] = '.';
525 #endif
526       tmpname[len++] = '/';
527     }
528   else
529     {
530       tmpname = (char *) xmalloc (sizeof (template));
531       len = 0;
532     }
533 
534   memcpy (tmpname + len, template, sizeof (template));
535   return tmpname;
536 #undef template
537 }
538 
539 /* Return the name of a created temporary file in the same directory
540    as FILENAME.  */
541 
542 char *
543 make_tempname (const char *filename, int *ofd)
544 {
545   char *tmpname = template_in_dir (filename);
546   int fd;
547 
548 #ifdef HAVE_MKSTEMP
549   fd = mkstemp (tmpname);
550 #else
551   tmpname = mktemp (tmpname);
552   if (tmpname == NULL)
553     fd = -1;
554   else
555     fd = open (tmpname, O_RDWR | O_CREAT | O_EXCL, 0600);
556 #endif
557   if (fd == -1)
558     {
559       free (tmpname);
560       return NULL;
561     }
562   *ofd = fd;
563   return tmpname;
564 }
565 
566 /* Return the name of a created temporary directory inside the
567    directory containing FILENAME.  */
568 
569 char *
570 make_tempdir (const char *filename)
571 {
572   char *tmpname = template_in_dir (filename);
573   char *ret;
574 
575 #ifdef HAVE_MKDTEMP
576   ret = mkdtemp (tmpname);
577 #else
578   ret = mktemp (tmpname);
579 #if defined (_WIN32) && !defined (__CYGWIN32__)
580   if (mkdir (tmpname) != 0)
581     ret = NULL;
582 #else
583   if (mkdir (tmpname, 0700) != 0)
584     ret = NULL;
585 #endif
586 #endif
587   if (ret == NULL)
588     free (tmpname);
589   return ret;
590 }
591 
592 /* Parse a string into a VMA, with a fatal error if it can't be
593    parsed.  */
594 
595 bfd_vma
596 parse_vma (const char *s, const char *arg)
597 {
598   bfd_vma ret;
599   const char *end;
600 
601   ret = bfd_scan_vma (s, &end, 0);
602 
603   if (*end != '\0')
604     fatal (_("%s: bad number: %s"), arg, s);
605 
606   return ret;
607 }
608 
609 /* Returns the size of the named file.  If the file does not
610    exist, or if it is not a real file, then a suitable non-fatal
611    error message is printed and (off_t) -1 is returned.  */
612 
613 off_t
614 get_file_size (const char * file_name)
615 {
616   struct stat statbuf;
617 
618   if (file_name == NULL)
619     return (off_t) -1;
620 
621   if (stat (file_name, &statbuf) < 0)
622     {
623       if (errno == ENOENT)
624 	non_fatal (_("'%s': No such file"), file_name);
625       else
626 	non_fatal (_("Warning: could not locate '%s'.  reason: %s"),
627 		   file_name, strerror (errno));
628     }
629   else if (S_ISDIR (statbuf.st_mode))
630     non_fatal (_("Warning: '%s' is a directory"), file_name);
631   else if (! S_ISREG (statbuf.st_mode))
632     {
633       if (!S_ISCHR(statbuf.st_mode))
634 	{
635 	  non_fatal (_("Warning: '%s' is not an ordinary file"), file_name);
636 	  return 0;
637 	}
638       return statbuf.st_size ? statbuf.st_size : 1;
639     }
640   else if (statbuf.st_size < 0)
641     non_fatal (_("Warning: '%s' has negative size, probably it is too large"),
642                file_name);
643 #if defined (_WIN32) && !defined (__CYGWIN__)
644   else if (statbuf.st_size == 0)
645     {
646       /* MS-Windows 'stat' reports the null device as a regular file;
647 	 fix that.  */
648       int fd = open (file_name, O_RDONLY | O_BINARY);
649       if (isatty (fd))
650 	{
651 	  close (fd);
652 	  non_fatal (_("Warning: '%s' is not an ordinary file"),
653 		     /* libtool wants to see /dev/null in the output.  */
654 		     strcasecmp (file_name, "nul") ? file_name : "/dev/null");
655 	}
656     }
657 #endif
658   else
659     return statbuf.st_size;
660 
661   return (off_t) -1;
662 }
663 
664 /* Return the filename in a static buffer.  */
665 
666 const char *
667 bfd_get_archive_filename (const bfd *abfd)
668 {
669   static size_t curr = 0;
670   static char *buf;
671   size_t needed;
672 
673   assert (abfd != NULL);
674 
675   if (abfd->my_archive == NULL
676       || bfd_is_thin_archive (abfd->my_archive))
677     return bfd_get_filename (abfd);
678 
679   needed = (strlen (bfd_get_filename (abfd->my_archive))
680 	    + strlen (bfd_get_filename (abfd)) + 3);
681   if (needed > curr)
682     {
683       if (curr)
684 	free (buf);
685       curr = needed + (needed >> 1);
686       buf = (char *) xmalloc (curr);
687     }
688   sprintf (buf, "%s(%s)", bfd_get_filename (abfd->my_archive),
689 	   bfd_get_filename (abfd));
690   return buf;
691 }
692 
693 /* Returns TRUE iff PATHNAME, a filename of an archive member,
694    is valid for writing.  For security reasons absolute paths
695    and paths containing /../ are not allowed.  See PR 17533.  */
696 
697 bool
698 is_valid_archive_path (char const * pathname)
699 {
700   const char * n = pathname;
701 
702   if (IS_ABSOLUTE_PATH (n))
703     return false;
704 
705   while (*n)
706     {
707       if (*n == '.' && *++n == '.' && ( ! *++n || IS_DIR_SEPARATOR (*n)))
708 	return false;
709 
710       while (*n && ! IS_DIR_SEPARATOR (*n))
711 	n++;
712       while (IS_DIR_SEPARATOR (*n))
713 	n++;
714     }
715 
716   return true;
717 }
718