1/* bucomm.c -- Bin Utils COMmon code. 2 Copyright 1991, 1992, 1993, 1994, 1995, 1997, 1998, 2000, 2001, 2002, 3 2003, 2006, 2007 4 Free Software Foundation, Inc. 5 6 This file is part of GNU Binutils. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 21 02110-1301, USA. */ 22 23/* We might put this in a library someday so it could be dynamically 24 loaded, but for now it's not necessary. */ 25 26#include "sysdep.h" 27#include "bfd.h" 28#include "libiberty.h" 29#include "filenames.h" 30#include "libbfd.h" 31 32#include <sys/stat.h> 33#include <time.h> /* ctime, maybe time_t */ 34#include <assert.h> 35#include "bucomm.h" 36 37#ifndef HAVE_TIME_T_IN_TIME_H 38#ifndef HAVE_TIME_T_IN_TYPES_H 39typedef long time_t; 40#endif 41#endif 42 43static const char * endian_string (enum bfd_endian); 44static int display_target_list (void); 45static int display_info_table (int, int); 46static int display_target_tables (void); 47 48/* Error reporting. */ 49 50char *program_name; 51 52void 53bfd_nonfatal (const char *string) 54{ 55 const char *errmsg = bfd_errmsg (bfd_get_error ()); 56 57 if (string) 58 fprintf (stderr, "%s: %s: %s\n", program_name, string, errmsg); 59 else 60 fprintf (stderr, "%s: %s\n", program_name, errmsg); 61} 62 63void 64bfd_fatal (const char *string) 65{ 66 bfd_nonfatal (string); 67 xexit (1); 68} 69 70void 71report (const char * format, va_list args) 72{ 73 fprintf (stderr, "%s: ", program_name); 74 vfprintf (stderr, format, args); 75 putc ('\n', stderr); 76} 77 78void 79fatal VPARAMS ((const char *format, ...)) 80{ 81 VA_OPEN (args, format); 82 VA_FIXEDARG (args, const char *, format); 83 84 report (format, args); 85 VA_CLOSE (args); 86 xexit (1); 87} 88 89void 90non_fatal VPARAMS ((const char *format, ...)) 91{ 92 VA_OPEN (args, format); 93 VA_FIXEDARG (args, const char *, format); 94 95 report (format, args); 96 VA_CLOSE (args); 97} 98 99/* Set the default BFD target based on the configured target. Doing 100 this permits the binutils to be configured for a particular target, 101 and linked against a shared BFD library which was configured for a 102 different target. */ 103 104void 105set_default_bfd_target (void) 106{ 107 /* The macro TARGET is defined by Makefile. */ 108 const char *target = TARGET; 109 110 if (! bfd_set_default_target (target)) 111 fatal (_("can't set BFD default target to `%s': %s"), 112 target, bfd_errmsg (bfd_get_error ())); 113} 114 115/* After a FALSE return from bfd_check_format_matches with 116 bfd_get_error () == bfd_error_file_ambiguously_recognized, print 117 the possible matching targets. */ 118 119void 120list_matching_formats (char **p) 121{ 122 fprintf (stderr, _("%s: Matching formats:"), program_name); 123 while (*p) 124 fprintf (stderr, " %s", *p++); 125 fputc ('\n', stderr); 126} 127 128/* List the supported targets. */ 129 130void 131list_supported_targets (const char *name, FILE *f) 132{ 133 int t; 134 const char **targ_names = bfd_target_list (); 135 136 if (name == NULL) 137 fprintf (f, _("Supported targets:")); 138 else 139 fprintf (f, _("%s: supported targets:"), name); 140 141 for (t = 0; targ_names[t] != NULL; t++) 142 fprintf (f, " %s", targ_names[t]); 143 fprintf (f, "\n"); 144 free (targ_names); 145} 146 147/* List the supported architectures. */ 148 149void 150list_supported_architectures (const char *name, FILE *f) 151{ 152 const char **arch; 153 154 if (name == NULL) 155 fprintf (f, _("Supported architectures:")); 156 else 157 fprintf (f, _("%s: supported architectures:"), name); 158 159 for (arch = bfd_arch_list (); *arch; arch++) 160 fprintf (f, " %s", *arch); 161 fprintf (f, "\n"); 162} 163 164/* The length of the longest architecture name + 1. */ 165#define LONGEST_ARCH sizeof ("powerpc:common") 166 167static const char * 168endian_string (enum bfd_endian endian) 169{ 170 switch (endian) 171 { 172 case BFD_ENDIAN_BIG: return "big endian"; 173 case BFD_ENDIAN_LITTLE: return "little endian"; 174 default: return "endianness unknown"; 175 } 176} 177 178/* List the targets that BFD is configured to support, each followed 179 by its endianness and the architectures it supports. */ 180 181static int 182display_target_list (void) 183{ 184 char *dummy_name; 185 int t; 186 int ret = 1; 187 188 dummy_name = make_temp_file (NULL); 189 for (t = 0; bfd_target_vector[t]; t++) 190 { 191 const bfd_target *p = bfd_target_vector[t]; 192 bfd *abfd = bfd_openw (dummy_name, p->name); 193 enum bfd_architecture a; 194 195 printf ("%s\n (header %s, data %s)\n", p->name, 196 endian_string (p->header_byteorder), 197 endian_string (p->byteorder)); 198 199 if (abfd == NULL) 200 { 201 bfd_nonfatal (dummy_name); 202 ret = 0; 203 continue; 204 } 205 206 if (! bfd_set_format (abfd, bfd_object)) 207 { 208 if (bfd_get_error () != bfd_error_invalid_operation) 209 { 210 bfd_nonfatal (p->name); 211 ret = 0; 212 } 213 bfd_close_all_done (abfd); 214 continue; 215 } 216 217 for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++) 218 if (bfd_set_arch_mach (abfd, (enum bfd_architecture) a, 0)) 219 printf (" %s\n", 220 bfd_printable_arch_mach ((enum bfd_architecture) a, 0)); 221 bfd_close_all_done (abfd); 222 } 223 unlink (dummy_name); 224 free (dummy_name); 225 226 return ret; 227} 228 229/* Print a table showing which architectures are supported for entries 230 FIRST through LAST-1 of bfd_target_vector (targets across, 231 architectures down). */ 232 233static int 234display_info_table (int first, int last) 235{ 236 int t; 237 int ret = 1; 238 char *dummy_name; 239 enum bfd_architecture a; 240 241 /* Print heading of target names. */ 242 printf ("\n%*s", (int) LONGEST_ARCH, " "); 243 for (t = first; t < last && bfd_target_vector[t]; t++) 244 printf ("%s ", bfd_target_vector[t]->name); 245 putchar ('\n'); 246 247 dummy_name = make_temp_file (NULL); 248 for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++) 249 if (strcmp (bfd_printable_arch_mach (a, 0), "UNKNOWN!") != 0) 250 { 251 printf ("%*s ", (int) LONGEST_ARCH - 1, 252 bfd_printable_arch_mach (a, 0)); 253 for (t = first; t < last && bfd_target_vector[t]; t++) 254 { 255 const bfd_target *p = bfd_target_vector[t]; 256 bfd_boolean ok = TRUE; 257 bfd *abfd = bfd_openw (dummy_name, p->name); 258 259 if (abfd == NULL) 260 { 261 bfd_nonfatal (p->name); 262 ret = 0; 263 ok = FALSE; 264 } 265 266 if (ok) 267 { 268 if (! bfd_set_format (abfd, bfd_object)) 269 { 270 if (bfd_get_error () != bfd_error_invalid_operation) 271 { 272 bfd_nonfatal (p->name); 273 ret = 0; 274 } 275 ok = FALSE; 276 } 277 } 278 279 if (ok) 280 { 281 if (! bfd_set_arch_mach (abfd, a, 0)) 282 ok = FALSE; 283 } 284 285 if (ok) 286 printf ("%s ", p->name); 287 else 288 { 289 int l = strlen (p->name); 290 while (l--) 291 putchar ('-'); 292 putchar (' '); 293 } 294 if (abfd != NULL) 295 bfd_close_all_done (abfd); 296 } 297 putchar ('\n'); 298 } 299 unlink (dummy_name); 300 free (dummy_name); 301 302 return ret; 303} 304 305/* Print tables of all the target-architecture combinations that 306 BFD has been configured to support. */ 307 308static int 309display_target_tables (void) 310{ 311 int t; 312 int columns; 313 int ret = 1; 314 char *colum; 315 316 columns = 0; 317 colum = getenv ("COLUMNS"); 318 if (colum != NULL) 319 columns = atoi (colum); 320 if (columns == 0) 321 columns = 80; 322 323 t = 0; 324 while (bfd_target_vector[t] != NULL) 325 { 326 int oldt = t, wid; 327 328 wid = LONGEST_ARCH + strlen (bfd_target_vector[t]->name) + 1; 329 ++t; 330 while (wid < columns && bfd_target_vector[t] != NULL) 331 { 332 int newwid; 333 334 newwid = wid + strlen (bfd_target_vector[t]->name) + 1; 335 if (newwid >= columns) 336 break; 337 wid = newwid; 338 ++t; 339 } 340 if (! display_info_table (oldt, t)) 341 ret = 0; 342 } 343 344 return ret; 345} 346 347int 348display_info (void) 349{ 350 printf (_("BFD header file version %s\n"), BFD_VERSION_STRING); 351 if (! display_target_list () || ! display_target_tables ()) 352 return 1; 353 else 354 return 0; 355} 356 357/* Display the archive header for an element as if it were an ls -l listing: 358 359 Mode User\tGroup\tSize\tDate Name */ 360 361void 362print_arelt_descr (FILE *file, bfd *abfd, bfd_boolean verbose) 363{ 364 struct stat buf; 365 366 if (verbose) 367 { 368 if (bfd_stat_arch_elt (abfd, &buf) == 0) 369 { 370 char modebuf[11]; 371 char timebuf[40]; 372 time_t when = buf.st_mtime; 373 const char *ctime_result = (const char *) ctime (&when); 374 375 /* POSIX format: skip weekday and seconds from ctime output. */ 376 sprintf (timebuf, "%.12s %.4s", ctime_result + 4, ctime_result + 20); 377 378 mode_string (buf.st_mode, modebuf); 379 modebuf[10] = '\0'; 380 /* POSIX 1003.2/D11 says to skip first character (entry type). */ 381 fprintf (file, "%s %ld/%ld %6ld %s ", modebuf + 1, 382 (long) buf.st_uid, (long) buf.st_gid, 383 (long) buf.st_size, timebuf); 384 } 385 } 386 387 fprintf (file, "%s\n", bfd_get_filename (abfd)); 388} 389 390/* Return a path for a new temporary file in the same directory 391 as file PATH. */ 392 393static char * 394template_in_dir (const char *path) 395{ 396#define template "stXXXXXX" 397 const char *slash = strrchr (path, '/'); 398 char *tmpname; 399 size_t len; 400 401#ifdef HAVE_DOS_BASED_FILE_SYSTEM 402 { 403 /* We could have foo/bar\\baz, or foo\\bar, or d:bar. */ 404 char *bslash = strrchr (path, '\\'); 405 406 if (slash == NULL || (bslash != NULL && bslash > slash)) 407 slash = bslash; 408 if (slash == NULL && path[0] != '\0' && path[1] == ':') 409 slash = path + 1; 410 } 411#endif 412 413 if (slash != (char *) NULL) 414 { 415 len = slash - path; 416 tmpname = xmalloc (len + sizeof (template) + 2); 417 memcpy (tmpname, path, len); 418 419#ifdef HAVE_DOS_BASED_FILE_SYSTEM 420 /* If tmpname is "X:", appending a slash will make it a root 421 directory on drive X, which is NOT the same as the current 422 directory on drive X. */ 423 if (len == 2 && tmpname[1] == ':') 424 tmpname[len++] = '.'; 425#endif 426 tmpname[len++] = '/'; 427 } 428 else 429 { 430 tmpname = xmalloc (sizeof (template)); 431 len = 0; 432 } 433 434 memcpy (tmpname + len, template, sizeof (template)); 435 return tmpname; 436#undef template 437} 438 439/* Return the name of a created temporary file in the same directory 440 as FILENAME. */ 441 442char * 443make_tempname (char *filename) 444{ 445 char *tmpname = template_in_dir (filename); 446 int fd; 447 448#ifdef HAVE_MKSTEMP 449 fd = mkstemp (tmpname); 450#else 451 tmpname = mktemp (tmpname); 452 if (tmpname == NULL) 453 return NULL; 454 fd = open (tmpname, O_RDWR | O_CREAT | O_EXCL, 0600); 455#endif 456 if (fd == -1) 457 return NULL; 458 close (fd); 459 return tmpname; 460} 461 462/* Return the name of a created temporary directory inside the 463 directory containing FILENAME. */ 464 465char * 466make_tempdir (char *filename) 467{ 468 char *tmpname = template_in_dir (filename); 469 470#ifdef HAVE_MKDTEMP 471 return mkdtemp (tmpname); 472#else 473 tmpname = mktemp (tmpname); 474 if (tmpname == NULL) 475 return NULL; 476#if defined (_WIN32) && !defined (__CYGWIN32__) 477 if (mkdir (tmpname) != 0) 478 return NULL; 479#else 480 if (mkdir (tmpname, 0700) != 0) 481 return NULL; 482#endif 483 return tmpname; 484#endif 485} 486 487/* Parse a string into a VMA, with a fatal error if it can't be 488 parsed. */ 489 490bfd_vma 491parse_vma (const char *s, const char *arg) 492{ 493 bfd_vma ret; 494 const char *end; 495 496 ret = bfd_scan_vma (s, &end, 0); 497 498 if (*end != '\0') 499 fatal (_("%s: bad number: %s"), arg, s); 500 501 return ret; 502} 503 504/* Returns the size of the named file. If the file does not 505 exist, or if it is not a real file, then a suitable non-fatal 506 error message is printed and zero is returned. */ 507 508off_t 509get_file_size (const char * file_name) 510{ 511 struct stat statbuf; 512 513 if (stat (file_name, &statbuf) < 0) 514 { 515 if (errno == ENOENT) 516 non_fatal (_("'%s': No such file"), file_name); 517 else 518 non_fatal (_("Warning: could not locate '%s'. reason: %s"), 519 file_name, strerror (errno)); 520 } 521 else if (! S_ISREG (statbuf.st_mode)) 522 non_fatal (_("Warning: '%s' is not an ordinary file"), file_name); 523 else 524 return statbuf.st_size; 525 526 return 0; 527} 528 529/* Return the filename in a static buffer. */ 530 531const char * 532bfd_get_archive_filename (bfd *abfd) 533{ 534 static size_t curr = 0; 535 static char *buf; 536 size_t needed; 537 538 assert (abfd != NULL); 539 540 if (!abfd->my_archive) 541 return bfd_get_filename (abfd); 542 543 needed = (strlen (bfd_get_filename (abfd->my_archive)) 544 + strlen (bfd_get_filename (abfd)) + 3); 545 if (needed > curr) 546 { 547 if (curr) 548 free (buf); 549 curr = needed + (needed >> 1); 550 buf = bfd_malloc (curr); 551 /* If we can't malloc, fail safe by returning just the file name. 552 This function is only used when building error messages. */ 553 if (!buf) 554 { 555 curr = 0; 556 return bfd_get_filename (abfd); 557 } 558 } 559 sprintf (buf, "%s(%s)", bfd_get_filename (abfd->my_archive), 560 bfd_get_filename (abfd)); 561 return buf; 562} 563