Back to index

cell-binutils  2.17cvs20070401
bucomm.c
Go to the documentation of this file.
00001 /* bucomm.c -- Bin Utils COMmon code.
00002    Copyright 1991, 1992, 1993, 1994, 1995, 1997, 1998, 2000, 2001, 2002,
00003    2003, 2006
00004    Free Software Foundation, Inc.
00005 
00006    This file is part of GNU Binutils.
00007 
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2 of the License, or
00011    (at your option) any later version.
00012 
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with this program; if not, write to the Free Software
00020    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
00021    02110-1301, USA.  */
00022 
00023 /* We might put this in a library someday so it could be dynamically
00024    loaded, but for now it's not necessary.  */
00025 
00026 #include "bfd.h"
00027 #include "libiberty.h"
00028 #include "bucomm.h"
00029 #include "filenames.h"
00030 #include "libbfd.h"
00031 
00032 #include <sys/stat.h>
00033 #include <time.h>           /* ctime, maybe time_t */
00034 #include <assert.h>
00035 
00036 #ifndef HAVE_TIME_T_IN_TIME_H
00037 #ifndef HAVE_TIME_T_IN_TYPES_H
00038 typedef long time_t;
00039 #endif
00040 #endif
00041 
00042 static const char * endian_string (enum bfd_endian);
00043 static int display_target_list (void);
00044 static int display_info_table (int, int);
00045 static int display_target_tables (void);
00046 
00047 /* Error reporting.  */
00048 
00049 char *program_name;
00050 
00051 void
00052 bfd_nonfatal (const char *string)
00053 {
00054   const char *errmsg = bfd_errmsg (bfd_get_error ());
00055 
00056   if (string)
00057     fprintf (stderr, "%s: %s: %s\n", program_name, string, errmsg);
00058   else
00059     fprintf (stderr, "%s: %s\n", program_name, errmsg);
00060 }
00061 
00062 void
00063 bfd_fatal (const char *string)
00064 {
00065   bfd_nonfatal (string);
00066   xexit (1);
00067 }
00068 
00069 void
00070 report (const char * format, va_list args)
00071 {
00072   fprintf (stderr, "%s: ", program_name);
00073   vfprintf (stderr, format, args);
00074   putc ('\n', stderr);
00075 }
00076 
00077 void
00078 fatal VPARAMS ((const char *format, ...))
00079 {
00080   VA_OPEN (args, format);
00081   VA_FIXEDARG (args, const char *, format);
00082 
00083   report (format, args);
00084   VA_CLOSE (args);
00085   xexit (1);
00086 }
00087 
00088 void
00089 non_fatal VPARAMS ((const char *format, ...))
00090 {
00091   VA_OPEN (args, format);
00092   VA_FIXEDARG (args, const char *, format);
00093 
00094   report (format, args);
00095   VA_CLOSE (args);
00096 }
00097 
00098 /* Set the default BFD target based on the configured target.  Doing
00099    this permits the binutils to be configured for a particular target,
00100    and linked against a shared BFD library which was configured for a
00101    different target.  */
00102 
00103 void
00104 set_default_bfd_target (void)
00105 {
00106   /* The macro TARGET is defined by Makefile.  */
00107   const char *target = TARGET;
00108 
00109   if (! bfd_set_default_target (target))
00110     fatal (_("can't set BFD default target to `%s': %s"),
00111           target, bfd_errmsg (bfd_get_error ()));
00112 }
00113 
00114 /* After a FALSE return from bfd_check_format_matches with
00115    bfd_get_error () == bfd_error_file_ambiguously_recognized, print
00116    the possible matching targets.  */
00117 
00118 void
00119 list_matching_formats (char **p)
00120 {
00121   fprintf (stderr, _("%s: Matching formats:"), program_name);
00122   while (*p)
00123     fprintf (stderr, " %s", *p++);
00124   fputc ('\n', stderr);
00125 }
00126 
00127 /* List the supported targets.  */
00128 
00129 void
00130 list_supported_targets (const char *name, FILE *f)
00131 {
00132   int t;
00133   const char **targ_names = bfd_target_list ();
00134 
00135   if (name == NULL)
00136     fprintf (f, _("Supported targets:"));
00137   else
00138     fprintf (f, _("%s: supported targets:"), name);
00139 
00140   for (t = 0; targ_names[t] != NULL; t++)
00141     fprintf (f, " %s", targ_names[t]);
00142   fprintf (f, "\n");
00143   free (targ_names);
00144 }
00145 
00146 /* List the supported architectures.  */
00147 
00148 void
00149 list_supported_architectures (const char *name, FILE *f)
00150 {
00151   const char **arch;
00152 
00153   if (name == NULL)
00154     fprintf (f, _("Supported architectures:"));
00155   else
00156     fprintf (f, _("%s: supported architectures:"), name);
00157 
00158   for (arch = bfd_arch_list (); *arch; arch++)
00159     fprintf (f, " %s", *arch);
00160   fprintf (f, "\n");
00161 }
00162 
00163 /* The length of the longest architecture name + 1.  */
00164 #define LONGEST_ARCH sizeof ("powerpc:common")
00165 
00166 static const char *
00167 endian_string (enum bfd_endian endian)
00168 {
00169   switch (endian)
00170     {
00171     case BFD_ENDIAN_BIG: return "big endian";
00172     case BFD_ENDIAN_LITTLE: return "little endian";
00173     default: return "endianness unknown";
00174     }
00175 }
00176 
00177 /* List the targets that BFD is configured to support, each followed
00178    by its endianness and the architectures it supports.  */
00179 
00180 static int
00181 display_target_list (void)
00182 {
00183   char *dummy_name;
00184   int t;
00185   int ret = 1;
00186 
00187   dummy_name = make_temp_file (NULL);
00188   for (t = 0; bfd_target_vector[t]; t++)
00189     {
00190       const bfd_target *p = bfd_target_vector[t];
00191       bfd *abfd = bfd_openw (dummy_name, p->name);
00192       enum bfd_architecture a;
00193 
00194       printf ("%s\n (header %s, data %s)\n", p->name,
00195              endian_string (p->header_byteorder),
00196              endian_string (p->byteorder));
00197 
00198       if (abfd == NULL)
00199        {
00200           bfd_nonfatal (dummy_name);
00201           ret = 0;
00202          continue;
00203        }
00204 
00205       if (! bfd_set_format (abfd, bfd_object))
00206        {
00207          if (bfd_get_error () != bfd_error_invalid_operation)
00208             {
00209              bfd_nonfatal (p->name);
00210               ret = 0;
00211             }
00212          bfd_close_all_done (abfd);
00213          continue;
00214        }
00215 
00216       for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++)
00217        if (bfd_set_arch_mach (abfd, (enum bfd_architecture) a, 0))
00218          printf ("  %s\n",
00219                 bfd_printable_arch_mach ((enum bfd_architecture) a, 0));
00220       bfd_close_all_done (abfd);
00221     }
00222   unlink (dummy_name);
00223   free (dummy_name);
00224 
00225   return ret;
00226 }
00227 
00228 /* Print a table showing which architectures are supported for entries
00229    FIRST through LAST-1 of bfd_target_vector (targets across,
00230    architectures down).  */
00231 
00232 static int
00233 display_info_table (int first, int last)
00234 {
00235   int t;
00236   int ret = 1;
00237   char *dummy_name;
00238   enum bfd_architecture a;
00239 
00240   /* Print heading of target names.  */
00241   printf ("\n%*s", (int) LONGEST_ARCH, " ");
00242   for (t = first; t < last && bfd_target_vector[t]; t++)
00243     printf ("%s ", bfd_target_vector[t]->name);
00244   putchar ('\n');
00245 
00246   dummy_name = make_temp_file (NULL);
00247   for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++)
00248     if (strcmp (bfd_printable_arch_mach (a, 0), "UNKNOWN!") != 0)
00249       {
00250        printf ("%*s ", (int) LONGEST_ARCH - 1,
00251               bfd_printable_arch_mach (a, 0));
00252        for (t = first; t < last && bfd_target_vector[t]; t++)
00253          {
00254            const bfd_target *p = bfd_target_vector[t];
00255            bfd_boolean ok = TRUE;
00256            bfd *abfd = bfd_openw (dummy_name, p->name);
00257 
00258            if (abfd == NULL)
00259              {
00260               bfd_nonfatal (p->name);
00261                 ret = 0;
00262               ok = FALSE;
00263              }
00264 
00265            if (ok)
00266              {
00267               if (! bfd_set_format (abfd, bfd_object))
00268                 {
00269                   if (bfd_get_error () != bfd_error_invalid_operation)
00270                       {
00271                       bfd_nonfatal (p->name);
00272                         ret = 0;
00273                       }
00274                   ok = FALSE;
00275                 }
00276              }
00277 
00278            if (ok)
00279              {
00280               if (! bfd_set_arch_mach (abfd, a, 0))
00281                 ok = FALSE;
00282              }
00283 
00284            if (ok)
00285              printf ("%s ", p->name);
00286            else
00287              {
00288               int l = strlen (p->name);
00289               while (l--)
00290                 putchar ('-');
00291               putchar (' ');
00292              }
00293            if (abfd != NULL)
00294              bfd_close_all_done (abfd);
00295          }
00296        putchar ('\n');
00297       }
00298   unlink (dummy_name);
00299   free (dummy_name);
00300 
00301   return ret;
00302 }
00303 
00304 /* Print tables of all the target-architecture combinations that
00305    BFD has been configured to support.  */
00306 
00307 static int
00308 display_target_tables (void)
00309 {
00310   int t;
00311   int columns;
00312   int ret = 1;
00313   char *colum;
00314 
00315   columns = 0;
00316   colum = getenv ("COLUMNS");
00317   if (colum != NULL)
00318     columns = atoi (colum);
00319   if (columns == 0)
00320     columns = 80;
00321 
00322   t = 0;
00323   while (bfd_target_vector[t] != NULL)
00324     {
00325       int oldt = t, wid;
00326 
00327       wid = LONGEST_ARCH + strlen (bfd_target_vector[t]->name) + 1;
00328       ++t;
00329       while (wid < columns && bfd_target_vector[t] != NULL)
00330        {
00331          int newwid;
00332 
00333          newwid = wid + strlen (bfd_target_vector[t]->name) + 1;
00334          if (newwid >= columns)
00335            break;
00336          wid = newwid;
00337          ++t;
00338        }
00339       if (! display_info_table (oldt, t))
00340         ret = 0;
00341     }
00342 
00343   return ret;
00344 }
00345 
00346 int
00347 display_info (void)
00348 {
00349   printf (_("BFD header file version %s\n"), BFD_VERSION_STRING);
00350   if (! display_target_list () || ! display_target_tables ())
00351     return 1;
00352   else
00353     return 0;
00354 }
00355 
00356 /* Display the archive header for an element as if it were an ls -l listing:
00357 
00358    Mode       User\tGroup\tSize\tDate               Name */
00359 
00360 void
00361 print_arelt_descr (FILE *file, bfd *abfd, bfd_boolean verbose)
00362 {
00363   struct stat buf;
00364 
00365   if (verbose)
00366     {
00367       if (bfd_stat_arch_elt (abfd, &buf) == 0)
00368        {
00369          char modebuf[11];
00370          char timebuf[40];
00371          time_t when = buf.st_mtime;
00372          const char *ctime_result = (const char *) ctime (&when);
00373 
00374          /* POSIX format:  skip weekday and seconds from ctime output.  */
00375          sprintf (timebuf, "%.12s %.4s", ctime_result + 4, ctime_result + 20);
00376 
00377          mode_string (buf.st_mode, modebuf);
00378          modebuf[10] = '\0';
00379          /* POSIX 1003.2/D11 says to skip first character (entry type).  */
00380          fprintf (file, "%s %ld/%ld %6ld %s ", modebuf + 1,
00381                  (long) buf.st_uid, (long) buf.st_gid,
00382                  (long) buf.st_size, timebuf);
00383        }
00384     }
00385 
00386   fprintf (file, "%s\n", bfd_get_filename (abfd));
00387 }
00388 
00389 /* Return a path for a new temporary file in the same directory
00390    as file PATH.  */
00391 
00392 static char *
00393 template_in_dir (const char *path)
00394 {
00395 #define template "stXXXXXX"
00396   const char *slash = strrchr (path, '/');
00397   char *tmpname;
00398   size_t len;
00399 
00400 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
00401   {
00402     /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
00403     char *bslash = strrchr (path, '\\');
00404 
00405     if (slash == NULL || (bslash != NULL && bslash > slash))
00406       slash = bslash;
00407     if (slash == NULL && path[0] != '\0' && path[1] == ':')
00408       slash = path + 1;
00409   }
00410 #endif
00411 
00412   if (slash != (char *) NULL)
00413     {
00414       len = slash - path;
00415       tmpname = xmalloc (len + sizeof (template) + 2);
00416       memcpy (tmpname, path, len);
00417 
00418 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
00419       /* If tmpname is "X:", appending a slash will make it a root
00420         directory on drive X, which is NOT the same as the current
00421         directory on drive X.  */
00422       if (len == 2 && tmpname[1] == ':')
00423        tmpname[len++] = '.';
00424 #endif
00425       tmpname[len++] = '/';
00426     }
00427   else
00428     {
00429       tmpname = xmalloc (sizeof (template));
00430       len = 0;
00431     }
00432 
00433   memcpy (tmpname + len, template, sizeof (template));
00434   return tmpname;
00435 #undef template
00436 }
00437 
00438 /* Return the name of a created temporary file in the same directory
00439    as FILENAME.  */
00440 
00441 char *
00442 make_tempname (char *filename)
00443 {
00444   char *tmpname = template_in_dir (filename);
00445   int fd;
00446 
00447 #ifdef HAVE_MKSTEMP
00448   fd = mkstemp (tmpname);
00449 #else
00450   tmpname = mktemp (tmpname);
00451   if (tmpname == NULL)
00452     return NULL;
00453   fd = open (tmpname, O_RDWR | O_CREAT | O_EXCL, 0600);
00454 #endif
00455   if (fd == -1)
00456     return NULL;
00457   close (fd);
00458   return tmpname;
00459 }
00460 
00461 /* Return the name of a created temporary directory inside the
00462    directory containing FILENAME.  */
00463 
00464 char *
00465 make_tempdir (char *filename)
00466 {
00467   char *tmpname = template_in_dir (filename);
00468 
00469 #ifdef HAVE_MKDTEMP
00470   return mkdtemp (tmpname);
00471 #else
00472   tmpname = mktemp (tmpname);
00473   if (tmpname == NULL)
00474     return NULL;
00475 #if defined (_WIN32) && !defined (__CYGWIN32__)
00476   if (mkdir (tmpname) != 0)
00477     return NULL;
00478 #else
00479   if (mkdir (tmpname, 0700) != 0)
00480     return NULL;
00481 #endif
00482   return tmpname;
00483 #endif
00484 }
00485 
00486 /* Parse a string into a VMA, with a fatal error if it can't be
00487    parsed.  */
00488 
00489 bfd_vma
00490 parse_vma (const char *s, const char *arg)
00491 {
00492   bfd_vma ret;
00493   const char *end;
00494 
00495   ret = bfd_scan_vma (s, &end, 0);
00496 
00497   if (*end != '\0')
00498     fatal (_("%s: bad number: %s"), arg, s);
00499 
00500   return ret;
00501 }
00502 
00503 /* Returns the size of the named file.  If the file does not
00504    exist, or if it is not a real file, then a suitable non-fatal
00505    error message is printed and zero is returned.  */
00506 
00507 off_t
00508 get_file_size (const char * file_name)
00509 {
00510   struct stat statbuf;
00511   
00512   if (stat (file_name, &statbuf) < 0)
00513     {
00514       if (errno == ENOENT)
00515        non_fatal (_("'%s': No such file"), file_name);
00516       else
00517        non_fatal (_("Warning: could not locate '%s'.  reason: %s"),
00518                  file_name, strerror (errno));
00519     }  
00520   else if (! S_ISREG (statbuf.st_mode))
00521     non_fatal (_("Warning: '%s' is not an ordinary file"), file_name);
00522   else
00523     return statbuf.st_size;
00524 
00525   return 0;
00526 }
00527 
00528 /* Return the filename in a static buffer.  */
00529 
00530 const char *
00531 bfd_get_archive_filename (bfd *abfd)
00532 {
00533   static size_t curr = 0;
00534   static char *buf;
00535   size_t needed;
00536 
00537   assert (abfd != NULL);
00538   
00539   if (!abfd->my_archive)
00540     return bfd_get_filename (abfd);
00541 
00542   needed = (strlen (bfd_get_filename (abfd->my_archive))
00543            + strlen (bfd_get_filename (abfd)) + 3);
00544   if (needed > curr)
00545     {
00546       if (curr)
00547        free (buf);
00548       curr = needed + (needed >> 1);
00549       buf = bfd_malloc (curr);
00550       /* If we can't malloc, fail safe by returning just the file name.
00551         This function is only used when building error messages.  */
00552       if (!buf)
00553        {
00554          curr = 0;
00555          return bfd_get_filename (abfd);
00556        }
00557     }
00558   sprintf (buf, "%s(%s)", bfd_get_filename (abfd->my_archive),
00559           bfd_get_filename (abfd));
00560   return buf;
00561 }