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