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