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