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