129615Sjmg/* bucomm.c -- Bin Utils COMmon code. 229615Sjmg Copyright 1991, 1992, 1993, 1994, 1995, 1997, 1998, 2000, 2001, 2002, 2003 329615Sjmg Free Software Foundation, Inc. 429615Sjmg 529615Sjmg This file is part of GNU Binutils. 629615Sjmg 729615Sjmg This program is free software; you can redistribute it and/or modify 829615Sjmg it under the terms of the GNU General Public License as published by 929615Sjmg the Free Software Foundation; either version 2 of the License, or 1029615Sjmg (at your option) any later version. 1129615Sjmg 1229615Sjmg This program is distributed in the hope that it will be useful, 1329615Sjmg but WITHOUT ANY WARRANTY; without even the implied warranty of 1429615Sjmg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1529615Sjmg GNU General Public License for more details. 1629615Sjmg 1729615Sjmg You should have received a copy of the GNU General Public License 1829615Sjmg along with this program; if not, write to the Free Software 1929615Sjmg Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 2029615Sjmg 02110-1301, USA. */ 2129615Sjmg 2229615Sjmg/* We might put this in a library someday so it could be dynamically 2329615Sjmg loaded, but for now it's not necessary. */ 2429615Sjmg 2529615Sjmg#include "bfd.h" 2629615Sjmg#include "bfdver.h" 27124125Scharnier#include "libiberty.h" 28124125Scharnier#include "bucomm.h" 29124125Scharnier#include "filenames.h" 3029615Sjmg#include "libbfd.h" 3129615Sjmg 32124125Scharnier#include <sys/stat.h> 3329615Sjmg#include <time.h> /* ctime, maybe time_t */ 3429615Sjmg#include <assert.h> 3529615Sjmg 3629615Sjmg#ifndef HAVE_TIME_T_IN_TIME_H 3729615Sjmg#ifndef HAVE_TIME_T_IN_TYPES_H 3829615Sjmgtypedef long time_t; 3929615Sjmg#endif 4029615Sjmg#endif 4150786Speter 4229615Sjmgstatic const char * endian_string (enum bfd_endian); 4329615Sjmgstatic int display_target_list (void); 4429615Sjmgstatic int display_info_table (int, int); 4529615Sjmgstatic int display_target_tables (void); 4629615Sjmg 4729615Sjmg/* Error reporting. */ 4829615Sjmg 4929615Sjmgchar *program_name; 5029615Sjmg 5129615Sjmgvoid 5229615Sjmgbfd_nonfatal (const char *string) 5329615Sjmg{ 5429615Sjmg const char *errmsg = bfd_errmsg (bfd_get_error ()); 5529615Sjmg 5639144Seivind if (string) 5729615Sjmg fprintf (stderr, "%s: %s: %s\n", program_name, string, errmsg); 5829615Sjmg else 5929615Sjmg fprintf (stderr, "%s: %s\n", program_name, errmsg); 6029615Sjmg} 6129615Sjmg 6229615Sjmgvoid 6329615Sjmgbfd_fatal (const char *string) 6429615Sjmg{ 6529615Sjmg bfd_nonfatal (string); 6629615Sjmg xexit (1); 6731135Sjmg} 6829615Sjmg 6929615Sjmgvoid 7029615Sjmgreport (const char * format, va_list args) 7129615Sjmg{ 7229615Sjmg fprintf (stderr, "%s: ", program_name); 7329615Sjmg vfprintf (stderr, format, args); 7429615Sjmg putc ('\n', stderr); 7529615Sjmg} 7629615Sjmg 7729615Sjmgvoid 7829615Sjmgfatal VPARAMS ((const char *format, ...)) 7929615Sjmg{ 8029615Sjmg VA_OPEN (args, format); 8129615Sjmg VA_FIXEDARG (args, const char *, format); 8229615Sjmg 8329615Sjmg report (format, args); 8429615Sjmg VA_CLOSE (args); 8529615Sjmg xexit (1); 8629615Sjmg} 8729615Sjmg 8829615Sjmgvoid 8929615Sjmgnon_fatal VPARAMS ((const char *format, ...)) 9029615Sjmg{ 9129615Sjmg VA_OPEN (args, format); 9229615Sjmg VA_FIXEDARG (args, const char *, format); 9329615Sjmg 9429615Sjmg report (format, args); 9529615Sjmg VA_CLOSE (args); 9629615Sjmg} 9729615Sjmg 9829615Sjmg/* Set the default BFD target based on the configured target. Doing 9929615Sjmg this permits the binutils to be configured for a particular target, 10029615Sjmg and linked against a shared BFD library which was configured for a 10129615Sjmg different target. */ 10229615Sjmg 10329615Sjmgvoid 10429615Sjmgset_default_bfd_target (void) 10529615Sjmg{ 10629615Sjmg /* The macro TARGET is defined by Makefile. */ 10729615Sjmg const char *target = TARGET; 10829615Sjmg 10929615Sjmg if (! bfd_set_default_target (target)) 11029615Sjmg fatal (_("can't set BFD default target to `%s': %s"), 11129615Sjmg target, bfd_errmsg (bfd_get_error ())); 11229615Sjmg} 11329615Sjmg 11429615Sjmg/* After a FALSE return from bfd_check_format_matches with 11529615Sjmg bfd_get_error () == bfd_error_file_ambiguously_recognized, print 11629615Sjmg the possible matching targets. */ 11750786Speter 11829615Sjmgvoid 11929615Sjmglist_matching_formats (char **p) 12029615Sjmg{ 12129615Sjmg fprintf (stderr, _("%s: Matching formats:"), program_name); 12229615Sjmg while (*p) 12329615Sjmg fprintf (stderr, " %s", *p++); 12429615Sjmg fputc ('\n', stderr); 12529615Sjmg} 12629615Sjmg 12729615Sjmg/* List the supported targets. */ 12829615Sjmg 12929615Sjmgvoid 13029615Sjmglist_supported_targets (const char *name, FILE *f) 13129615Sjmg{ 13229615Sjmg int t; 13329615Sjmg const char **targ_names = bfd_target_list (); 13429615Sjmg 13529615Sjmg if (name == NULL) 13629615Sjmg fprintf (f, _("Supported targets:")); 13729615Sjmg else 13829615Sjmg fprintf (f, _("%s: supported targets:"), name); 13929615Sjmg 14029615Sjmg for (t = 0; targ_names[t] != NULL; t++) 14129615Sjmg fprintf (f, " %s", targ_names[t]); 14229615Sjmg fprintf (f, "\n"); 14329615Sjmg free (targ_names); 14429615Sjmg} 14529615Sjmg 14629615Sjmg/* List the supported architectures. */ 14729615Sjmg 14829615Sjmgvoid 14929615Sjmglist_supported_architectures (const char *name, FILE *f) 15029615Sjmg{ 15129615Sjmg const char **arch; 15229615Sjmg 15329615Sjmg if (name == NULL) 15429615Sjmg fprintf (f, _("Supported architectures:")); 15529615Sjmg else 15629615Sjmg fprintf (f, _("%s: supported architectures:"), name); 15729615Sjmg 15829615Sjmg for (arch = bfd_arch_list (); *arch; arch++) 15929615Sjmg fprintf (f, " %s", *arch); 16029615Sjmg fprintf (f, "\n"); 16129615Sjmg} 16229615Sjmg 16329615Sjmg/* The length of the longest architecture name + 1. */ 16429615Sjmg#define LONGEST_ARCH sizeof ("powerpc:common") 16529615Sjmg 16629615Sjmgstatic const char * 16729615Sjmgendian_string (enum bfd_endian endian) 16829615Sjmg{ 16929615Sjmg switch (endian) 17029615Sjmg { 17129615Sjmg case BFD_ENDIAN_BIG: return "big endian"; 17229615Sjmg case BFD_ENDIAN_LITTLE: return "little endian"; 17329615Sjmg default: return "endianness unknown"; 17450786Speter } 17529615Sjmg} 17629615Sjmg 17729615Sjmg/* List the targets that BFD is configured to support, each followed 17829615Sjmg by its endianness and the architectures it supports. */ 17929615Sjmg 18029615Sjmgstatic int 18129615Sjmgdisplay_target_list (void) 18229615Sjmg{ 18329615Sjmg char *dummy_name; 18450786Speter int t; 18529615Sjmg int ret = 1; 18629615Sjmg 18729615Sjmg dummy_name = make_temp_file (NULL); 18829615Sjmg for (t = 0; bfd_target_vector[t]; t++) 18929615Sjmg { 19029615Sjmg const bfd_target *p = bfd_target_vector[t]; 19129615Sjmg bfd *abfd = bfd_openw (dummy_name, p->name); 19229615Sjmg enum bfd_architecture a; 19329615Sjmg 19429615Sjmg printf ("%s\n (header %s, data %s)\n", p->name, 19529615Sjmg endian_string (p->header_byteorder), 19629615Sjmg endian_string (p->byteorder)); 19729615Sjmg 19829615Sjmg if (abfd == NULL) 19929615Sjmg { 20029615Sjmg bfd_nonfatal (dummy_name); 20129615Sjmg ret = 0; 20229615Sjmg continue; 20329615Sjmg } 20429615Sjmg 20529615Sjmg if (! bfd_set_format (abfd, bfd_object)) 20629615Sjmg { 20729615Sjmg if (bfd_get_error () != bfd_error_invalid_operation) 20829615Sjmg { 20929615Sjmg bfd_nonfatal (p->name); 21029615Sjmg ret = 0; 21129615Sjmg } 21229615Sjmg bfd_close_all_done (abfd); 21329615Sjmg continue; 21429615Sjmg } 21529615Sjmg 21629615Sjmg for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++) 21729615Sjmg if (bfd_set_arch_mach (abfd, (enum bfd_architecture) a, 0)) 21829615Sjmg printf (" %s\n", 21929615Sjmg bfd_printable_arch_mach ((enum bfd_architecture) a, 0)); 22029615Sjmg bfd_close_all_done (abfd); 22129615Sjmg } 22229615Sjmg unlink (dummy_name); 22329615Sjmg free (dummy_name); 22429615Sjmg 22529615Sjmg return ret; 22629615Sjmg} 22729615Sjmg 22829615Sjmg/* Print a table showing which architectures are supported for entries 22929615Sjmg FIRST through LAST-1 of bfd_target_vector (targets across, 23029615Sjmg architectures down). */ 23129615Sjmg 23229615Sjmgstatic int 23329615Sjmgdisplay_info_table (int first, int last) 23429615Sjmg{ 23529615Sjmg int t; 23629615Sjmg int ret = 1; 23729615Sjmg char *dummy_name; 23829615Sjmg enum bfd_architecture a; 23929615Sjmg 24029615Sjmg /* Print heading of target names. */ 24129615Sjmg printf ("\n%*s", (int) LONGEST_ARCH, " "); 24229615Sjmg for (t = first; t < last && bfd_target_vector[t]; t++) 24329615Sjmg printf ("%s ", bfd_target_vector[t]->name); 24429615Sjmg putchar ('\n'); 24529615Sjmg 24629615Sjmg dummy_name = make_temp_file (NULL); 24729615Sjmg for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++) 24829615Sjmg if (strcmp (bfd_printable_arch_mach (a, 0), "UNKNOWN!") != 0) 24929615Sjmg { 25029615Sjmg printf ("%*s ", (int) LONGEST_ARCH - 1, 25129615Sjmg bfd_printable_arch_mach (a, 0)); 25229615Sjmg for (t = first; t < last && bfd_target_vector[t]; t++) 25329615Sjmg { 25429615Sjmg const bfd_target *p = bfd_target_vector[t]; 25529615Sjmg bfd_boolean ok = TRUE; 25629615Sjmg bfd *abfd = bfd_openw (dummy_name, p->name); 25729615Sjmg 25829615Sjmg if (abfd == NULL) 25929615Sjmg { 26029615Sjmg bfd_nonfatal (p->name); 26129615Sjmg ret = 0; 26229615Sjmg ok = FALSE; 26329615Sjmg } 26429615Sjmg 26529615Sjmg if (ok) 26629615Sjmg { 26729615Sjmg if (! bfd_set_format (abfd, bfd_object)) 26829615Sjmg { 26929615Sjmg if (bfd_get_error () != bfd_error_invalid_operation) 27029615Sjmg { 27129615Sjmg bfd_nonfatal (p->name); 27229615Sjmg ret = 0; 27329615Sjmg } 27429615Sjmg ok = FALSE; 27529615Sjmg } 27629615Sjmg } 27729615Sjmg 27829615Sjmg if (ok) 27929615Sjmg { 28029615Sjmg if (! bfd_set_arch_mach (abfd, a, 0)) 28129615Sjmg ok = FALSE; 28229615Sjmg } 28329615Sjmg 28429615Sjmg if (ok) 28529615Sjmg printf ("%s ", p->name); 28629615Sjmg else 28729615Sjmg { 28829615Sjmg int l = strlen (p->name); 28929615Sjmg while (l--) 29029615Sjmg putchar ('-'); 29129615Sjmg putchar (' '); 29229615Sjmg } 29329615Sjmg if (abfd != NULL) 29429615Sjmg bfd_close_all_done (abfd); 29529615Sjmg } 29629615Sjmg putchar ('\n'); 29729615Sjmg } 29829615Sjmg unlink (dummy_name); 29929615Sjmg free (dummy_name); 30029615Sjmg 30129615Sjmg return ret; 30229615Sjmg} 30329615Sjmg 30429615Sjmg/* Print tables of all the target-architecture combinations that 30529615Sjmg BFD has been configured to support. */ 30629615Sjmg 30729615Sjmgstatic int 30850786Speterdisplay_target_tables (void) 30929615Sjmg{ 31029615Sjmg int t; 31129615Sjmg int columns; 31250786Speter int ret = 1; 31329615Sjmg char *colum; 31429615Sjmg 31529615Sjmg columns = 0; 31629615Sjmg colum = getenv ("COLUMNS"); 31729615Sjmg if (colum != NULL) 31829615Sjmg columns = atoi (colum); 31929615Sjmg if (columns == 0) 32029615Sjmg columns = 80; 32129615Sjmg 32229615Sjmg t = 0; 32329615Sjmg while (bfd_target_vector[t] != NULL) 32429615Sjmg { 32529615Sjmg int oldt = t, wid; 32629615Sjmg 32729615Sjmg wid = LONGEST_ARCH + strlen (bfd_target_vector[t]->name) + 1; 32829615Sjmg ++t; 32929615Sjmg while (wid < columns && bfd_target_vector[t] != NULL) 33029615Sjmg { 33129615Sjmg int newwid; 33250786Speter 33329615Sjmg newwid = wid + strlen (bfd_target_vector[t]->name) + 1; 33429615Sjmg if (newwid >= columns) 33529615Sjmg break; 33629615Sjmg wid = newwid; 33729615Sjmg ++t; 33829615Sjmg } 33929615Sjmg if (! display_info_table (oldt, t)) 34050786Speter ret = 0; 34129615Sjmg } 34229615Sjmg 34329615Sjmg return ret; 34429615Sjmg} 34529615Sjmg 34629615Sjmgint 34729615Sjmgdisplay_info (void) 34829615Sjmg{ 34929615Sjmg printf (_("BFD header file version %s\n"), BFD_VERSION_STRING); 35029615Sjmg if (! display_target_list () || ! display_target_tables ()) 35129615Sjmg return 1; 35229615Sjmg else 35329615Sjmg return 0; 35429615Sjmg} 35529615Sjmg 35629615Sjmg/* Display the archive header for an element as if it were an ls -l listing: 35729615Sjmg 35829615Sjmg Mode User\tGroup\tSize\tDate Name */ 35929615Sjmg 36029615Sjmgvoid 36129615Sjmgprint_arelt_descr (FILE *file, bfd *abfd, bfd_boolean verbose) 36250786Speter{ 36329615Sjmg struct stat buf; 36429615Sjmg 36529615Sjmg if (verbose) 36629615Sjmg { 36729615Sjmg if (bfd_stat_arch_elt (abfd, &buf) == 0) 36829615Sjmg { 36929615Sjmg char modebuf[11]; 37050786Speter char timebuf[40]; 37129615Sjmg time_t when = buf.st_mtime; 37229615Sjmg const char *ctime_result = (const char *) ctime (&when); 37329615Sjmg 37429615Sjmg /* POSIX format: skip weekday and seconds from ctime output. */ 37529615Sjmg sprintf (timebuf, "%.12s %.4s", ctime_result + 4, ctime_result + 20); 37629615Sjmg 37729615Sjmg mode_string (buf.st_mode, modebuf); 37829615Sjmg modebuf[10] = '\0'; 37929615Sjmg /* POSIX 1003.2/D11 says to skip first character (entry type). */ 38029615Sjmg fprintf (file, "%s %ld/%ld %6ld %s ", modebuf + 1, 38129615Sjmg (long) buf.st_uid, (long) buf.st_gid, 38229615Sjmg (long) buf.st_size, timebuf); 38329615Sjmg } 38429615Sjmg } 38529615Sjmg 38650786Speter fprintf (file, "%s\n", bfd_get_filename (abfd)); 38729615Sjmg} 38829615Sjmg 38950786Speter/* Return the name of a temporary file in the same directory as FILENAME. */ 39029615Sjmg 39129615Sjmgchar * 39229615Sjmgmake_tempname (char *filename, int isdir) 39329615Sjmg{ 39429615Sjmg static char template[] = "stXXXXXX"; 39529615Sjmg char *tmpname; 39629615Sjmg char *slash = strrchr (filename, '/'); 39729615Sjmg char c = '/'; 39829615Sjmg 39950786Speter#ifdef HAVE_DOS_BASED_FILE_SYSTEM 40029615Sjmg { 40129615Sjmg /* We could have foo/bar\\baz, or foo\\bar, or d:bar. */ 40229615Sjmg char *bslash = strrchr (filename, '\\'); 40329615Sjmg if (slash == NULL || (bslash != NULL && bslash > slash)) 40429615Sjmg slash = bslash; 40550786Speter if (slash == NULL && filename[0] != '\0' && filename[1] == ':') 40629615Sjmg slash = filename + 1; 40729615Sjmg } 40829615Sjmg#endif 40950786Speter 41029615Sjmg if (slash != (char *) NULL) 41129615Sjmg { 41250786Speter c = *slash; 41329615Sjmg *slash = 0; 41429615Sjmg tmpname = xmalloc (strlen (filename) + sizeof (template) + 2); 41529615Sjmg strcpy (tmpname, filename); 41629615Sjmg#ifdef HAVE_DOS_BASED_FILE_SYSTEM 41729615Sjmg /* If tmpname is "X:", appending a slash will make it a root 41829615Sjmg directory on drive X, which is NOT the same as the current 41929615Sjmg directory on drive X. */ 42029615Sjmg if (tmpname[1] == ':' && tmpname[2] == '\0') 42129615Sjmg strcat (tmpname, "."); 42229615Sjmg#endif 42329615Sjmg strcat (tmpname, "/"); 42429615Sjmg strcat (tmpname, template); 42529615Sjmg } 42629615Sjmg else 42729615Sjmg { 42829615Sjmg tmpname = xmalloc (sizeof (template)); 42950786Speter strcpy (tmpname, template); 43029615Sjmg } 43129615Sjmg 43229615Sjmg if (isdir) 43329615Sjmg { 43429615Sjmg if (mkdtemp (tmpname) == (char *) NULL) 43529615Sjmg tmpname = NULL; 43629615Sjmg } 43729615Sjmg else 43829615Sjmg { 43929615Sjmg int fd; 44050786Speter 44129615Sjmg fd = mkstemp (tmpname); 44229615Sjmg if (fd == -1) 44329615Sjmg tmpname = NULL; 44429615Sjmg else 44529615Sjmg close (fd); 44629615Sjmg } 44729615Sjmg if (slash != (char *) NULL) 44829615Sjmg *slash = c; 44950786Speter 45029615Sjmg return tmpname; 45129615Sjmg} 45250786Speter 45329615Sjmg/* Parse a string into a VMA, with a fatal error if it can't be 45429615Sjmg parsed. */ 45550786Speter 45629615Sjmgbfd_vma 45729615Sjmgparse_vma (const char *s, const char *arg) 45850786Speter{ 45929615Sjmg bfd_vma ret; 46029615Sjmg const char *end; 46150786Speter 46250786Speter ret = bfd_scan_vma (s, &end, 0); 46329615Sjmg 46429615Sjmg if (*end != '\0') 46550786Speter fatal (_("%s: bad number: %s"), arg, s); 46629615Sjmg 46729615Sjmg return ret; 46829615Sjmg} 46929615Sjmg 47029615Sjmg/* Returns the size of the named file. If the file does not 47129615Sjmg exist, or if it is not a real file, then a suitable non-fatal 47229615Sjmg error message is printed and zero is returned. */ 47329615Sjmg 47429615Sjmgoff_t 47529615Sjmgget_file_size (const char * file_name) 47629615Sjmg{ 47729615Sjmg struct stat statbuf; 47829615Sjmg 47929615Sjmg if (stat (file_name, &statbuf) < 0) 48029615Sjmg { 48129615Sjmg if (errno == ENOENT) 48229615Sjmg non_fatal (_("'%s': No such file"), file_name); 48329615Sjmg else 48429615Sjmg non_fatal (_("Warning: could not locate '%s'. reason: %s"), 48529615Sjmg file_name, strerror (errno)); 48629615Sjmg } 48729615Sjmg else if (! S_ISREG (statbuf.st_mode)) 48850786Speter non_fatal (_("Warning: '%s' is not an ordinary file"), file_name); 48950786Speter else 49029615Sjmg return statbuf.st_size; 49129615Sjmg 49229615Sjmg return 0; 49329615Sjmg} 49429615Sjmg 49529615Sjmg/* Return the filename in a static buffer. */ 49639144Seivind 49729615Sjmgconst char * 49829615Sjmgbfd_get_archive_filename (bfd *abfd) 49939144Seivind{ 50039144Seivind static size_t curr = 0; 50129615Sjmg static char *buf; 50229615Sjmg size_t needed; 50339144Seivind 50429615Sjmg assert (abfd != NULL); 50529615Sjmg 50629615Sjmg if (!abfd->my_archive) 50729615Sjmg return bfd_get_filename (abfd); 50846422Sluoqi 50946422Sluoqi needed = (strlen (bfd_get_filename (abfd->my_archive)) 51029615Sjmg + strlen (bfd_get_filename (abfd)) + 3); 51146422Sluoqi if (needed > curr) 51229615Sjmg { 51329615Sjmg if (curr) 51429615Sjmg free (buf); 51529615Sjmg curr = needed + (needed >> 1); 51629615Sjmg buf = bfd_malloc (curr); 51739144Seivind /* If we can't malloc, fail safe by returning just the file name. 51829615Sjmg This function is only used when building error messages. */ 51929615Sjmg if (!buf) 52029615Sjmg { 52129615Sjmg curr = 0; 52229615Sjmg return bfd_get_filename (abfd); 52350786Speter } 52429615Sjmg } 52529615Sjmg sprintf (buf, "%s(%s)", bfd_get_filename (abfd->my_archive), 52629615Sjmg bfd_get_filename (abfd)); 52729615Sjmg return buf; 52829615Sjmg} 52929615Sjmg