1 /* bucomm.c -- Bin Utils COMmon code. 2 Copyright (C) 1991-2020 Free Software Foundation, Inc. 3 4 This file is part of GNU Binutils. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 19 02110-1301, USA. */ 20 21 /* We might put this in a library someday so it could be dynamically 22 loaded, but for now it's not necessary. */ 23 24 #include "sysdep.h" 25 #include "bfd.h" 26 #include "libiberty.h" 27 #include "filenames.h" 28 29 #include <time.h> /* ctime, maybe time_t */ 30 #include <assert.h> 31 #include "bucomm.h" 32 33 #ifndef HAVE_TIME_T_IN_TIME_H 34 #ifndef HAVE_TIME_T_IN_TYPES_H 35 typedef long time_t; 36 #endif 37 #endif 38 39 /* Error reporting. */ 40 41 char *program_name; 42 43 void 44 bfd_nonfatal (const char *string) 45 { 46 const char *errmsg; 47 enum bfd_error err = bfd_get_error (); 48 49 if (err == bfd_error_no_error) 50 errmsg = _("cause of error unknown"); 51 else 52 errmsg = bfd_errmsg (err); 53 fflush (stdout); 54 if (string) 55 fprintf (stderr, "%s: %s: %s\n", program_name, string, errmsg); 56 else 57 fprintf (stderr, "%s: %s\n", program_name, errmsg); 58 } 59 60 /* Issue a non fatal error message. FILENAME, or if NULL then BFD, 61 are used to indicate the problematic file. SECTION, if non NULL, 62 is used to provide a section name. If FORMAT is non-null, then it 63 is used to print additional information via vfprintf. Finally the 64 bfd error message is printed. In summary, error messages are of 65 one of the following forms: 66 67 PROGRAM: file: bfd-error-message 68 PROGRAM: file[section]: bfd-error-message 69 PROGRAM: file: printf-message: bfd-error-message 70 PROGRAM: file[section]: printf-message: bfd-error-message. */ 71 72 void 73 bfd_nonfatal_message (const char *filename, 74 const bfd *abfd, 75 const asection *section, 76 const char *format, ...) 77 { 78 const char *errmsg; 79 const char *section_name; 80 va_list args; 81 enum bfd_error err = bfd_get_error (); 82 83 if (err == bfd_error_no_error) 84 errmsg = _("cause of error unknown"); 85 else 86 errmsg = bfd_errmsg (err); 87 fflush (stdout); 88 section_name = NULL; 89 va_start (args, format); 90 fprintf (stderr, "%s", program_name); 91 92 if (abfd) 93 { 94 if (!filename) 95 filename = bfd_get_archive_filename (abfd); 96 if (section) 97 section_name = bfd_section_name (section); 98 } 99 if (section_name) 100 fprintf (stderr, ": %s[%s]", filename, section_name); 101 else 102 fprintf (stderr, ": %s", filename); 103 104 if (format) 105 { 106 fprintf (stderr, ": "); 107 vfprintf (stderr, format, args); 108 } 109 fprintf (stderr, ": %s\n", errmsg); 110 va_end (args); 111 } 112 113 void 114 bfd_fatal (const char *string) 115 { 116 bfd_nonfatal (string); 117 xexit (1); 118 } 119 120 void 121 report (const char * format, va_list args) 122 { 123 fflush (stdout); 124 fprintf (stderr, "%s: ", program_name); 125 vfprintf (stderr, format, args); 126 putc ('\n', stderr); 127 } 128 129 void 130 fatal (const char *format, ...) 131 { 132 va_list args; 133 134 va_start (args, format); 135 136 report (format, args); 137 va_end (args); 138 xexit (1); 139 } 140 141 void 142 non_fatal (const char *format, ...) 143 { 144 va_list args; 145 146 va_start (args, format); 147 148 report (format, args); 149 va_end (args); 150 } 151 152 /* Set the default BFD target based on the configured target. Doing 153 this permits the binutils to be configured for a particular target, 154 and linked against a shared BFD library which was configured for a 155 different target. */ 156 157 void 158 set_default_bfd_target (void) 159 { 160 /* The macro TARGET is defined by Makefile. */ 161 const char *target = TARGET; 162 163 if (! bfd_set_default_target (target)) 164 fatal (_("can't set BFD default target to `%s': %s"), 165 target, bfd_errmsg (bfd_get_error ())); 166 } 167 168 /* After a FALSE return from bfd_check_format_matches with 169 bfd_get_error () == bfd_error_file_ambiguously_recognized, print 170 the possible matching targets. */ 171 172 void 173 list_matching_formats (char **p) 174 { 175 fflush (stdout); 176 fprintf (stderr, _("%s: Matching formats:"), program_name); 177 while (*p) 178 fprintf (stderr, " %s", *p++); 179 fputc ('\n', stderr); 180 } 181 182 /* List the supported targets. */ 183 184 void 185 list_supported_targets (const char *name, FILE *f) 186 { 187 int t; 188 const char **targ_names; 189 190 if (name == NULL) 191 fprintf (f, _("Supported targets:")); 192 else 193 fprintf (f, _("%s: supported targets:"), name); 194 195 targ_names = bfd_target_list (); 196 for (t = 0; targ_names[t] != NULL; t++) 197 fprintf (f, " %s", targ_names[t]); 198 fprintf (f, "\n"); 199 free (targ_names); 200 } 201 202 /* List the supported architectures. */ 203 204 void 205 list_supported_architectures (const char *name, FILE *f) 206 { 207 const char ** arch; 208 const char ** arches; 209 210 if (name == NULL) 211 fprintf (f, _("Supported architectures:")); 212 else 213 fprintf (f, _("%s: supported architectures:"), name); 214 215 for (arch = arches = bfd_arch_list (); *arch; arch++) 216 fprintf (f, " %s", *arch); 217 fprintf (f, "\n"); 218 free (arches); 219 } 220 221 static const char * 222 endian_string (enum bfd_endian endian) 223 { 224 switch (endian) 225 { 226 case BFD_ENDIAN_BIG: return _("big endian"); 227 case BFD_ENDIAN_LITTLE: return _("little endian"); 228 default: return _("endianness unknown"); 229 } 230 } 231 232 /* Data passed to do_display_target and other target iterators. */ 233 234 struct display_target { 235 /* Temp file. */ 236 char *filename; 237 /* Return status. */ 238 int error; 239 /* Number of targets. */ 240 int count; 241 /* Size of info in bytes. */ 242 size_t alloc; 243 /* Per-target info. */ 244 struct { 245 /* Target name. */ 246 const char *name; 247 /* Non-zero if target/arch combination supported. */ 248 unsigned char arch[bfd_arch_last - bfd_arch_obscure - 1]; 249 } *info; 250 }; 251 252 /* List the targets that BFD is configured to support, each followed 253 by its endianness and the architectures it supports. Also build 254 info about target/archs. */ 255 256 static int 257 do_display_target (const bfd_target *targ, void *data) 258 { 259 struct display_target *param = (struct display_target *) data; 260 bfd *abfd; 261 size_t amt; 262 263 param->count += 1; 264 amt = param->count * sizeof (*param->info); 265 if (param->alloc < amt) 266 { 267 size_t size = ((param->count < 64 ? 64 : param->count) 268 * sizeof (*param->info) * 2); 269 param->info = xrealloc (param->info, size); 270 memset ((char *) param->info + param->alloc, 0, size - param->alloc); 271 param->alloc = size; 272 } 273 param->info[param->count - 1].name = targ->name; 274 275 printf (_("%s\n (header %s, data %s)\n"), targ->name, 276 endian_string (targ->header_byteorder), 277 endian_string (targ->byteorder)); 278 279 abfd = bfd_openw (param->filename, targ->name); 280 if (abfd == NULL) 281 { 282 bfd_nonfatal (param->filename); 283 param->error = 1; 284 } 285 else if (!bfd_set_format (abfd, bfd_object)) 286 { 287 if (bfd_get_error () != bfd_error_invalid_operation) 288 { 289 bfd_nonfatal (targ->name); 290 param->error = 1; 291 } 292 } 293 else 294 { 295 enum bfd_architecture a; 296 297 for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++) 298 if (bfd_set_arch_mach (abfd, a, 0)) 299 { 300 printf (" %s\n", bfd_printable_arch_mach (a, 0)); 301 param->info[param->count - 1].arch[a - bfd_arch_obscure - 1] = 1; 302 } 303 } 304 if (abfd != NULL) 305 bfd_close_all_done (abfd); 306 307 return param->error; 308 } 309 310 static void 311 display_target_list (struct display_target *arg) 312 { 313 arg->filename = make_temp_file (NULL); 314 arg->error = 0; 315 arg->count = 0; 316 arg->alloc = 0; 317 arg->info = NULL; 318 319 bfd_iterate_over_targets (do_display_target, arg); 320 321 unlink (arg->filename); 322 free (arg->filename); 323 } 324 325 /* Calculate how many targets we can print across the page. */ 326 327 static int 328 do_info_size (int targ, int width, const struct display_target *arg) 329 { 330 while (targ < arg->count) 331 { 332 width -= strlen (arg->info[targ].name) + 1; 333 if (width < 0) 334 return targ; 335 ++targ; 336 } 337 return targ; 338 } 339 340 /* Print header of target names. */ 341 342 static void 343 do_info_header (int targ, int stop_targ, const struct display_target *arg) 344 { 345 while (targ != stop_targ) 346 printf ("%s ", arg->info[targ++].name); 347 } 348 349 /* Print a table row. */ 350 351 static void 352 do_info_row (int targ, int stop_targ, enum bfd_architecture a, 353 const struct display_target *arg) 354 { 355 while (targ != stop_targ) 356 { 357 if (arg->info[targ].arch[a - bfd_arch_obscure - 1]) 358 fputs (arg->info[targ].name, stdout); 359 else 360 { 361 int l = strlen (arg->info[targ].name); 362 while (l--) 363 putchar ('-'); 364 } 365 ++targ; 366 if (targ != stop_targ) 367 putchar (' '); 368 } 369 } 370 371 /* Print tables of all the target-architecture combinations that 372 BFD has been configured to support. */ 373 374 static void 375 display_target_tables (const struct display_target *arg) 376 { 377 const char *columns; 378 int width, start_targ, stop_targ; 379 enum bfd_architecture arch; 380 int longest_arch = 0; 381 382 for (arch = bfd_arch_obscure + 1; arch < bfd_arch_last; arch++) 383 { 384 const char *s = bfd_printable_arch_mach (arch, 0); 385 int len = strlen (s); 386 if (len > longest_arch) 387 longest_arch = len; 388 } 389 390 width = 0; 391 columns = getenv ("COLUMNS"); 392 if (columns != NULL) 393 width = atoi (columns); 394 if (width == 0) 395 width = 80; 396 397 for (start_targ = 0; start_targ < arg->count; start_targ = stop_targ) 398 { 399 stop_targ = do_info_size (start_targ, width - longest_arch - 1, arg); 400 401 printf ("\n%*s", longest_arch + 1, " "); 402 do_info_header (start_targ, stop_targ, arg); 403 putchar ('\n'); 404 405 for (arch = bfd_arch_obscure + 1; arch < bfd_arch_last; arch++) 406 { 407 if (strcmp (bfd_printable_arch_mach (arch, 0), "UNKNOWN!") != 0) 408 { 409 printf ("%*s ", longest_arch, 410 bfd_printable_arch_mach (arch, 0)); 411 412 do_info_row (start_targ, stop_targ, arch, arg); 413 putchar ('\n'); 414 } 415 } 416 } 417 } 418 419 int 420 display_info (void) 421 { 422 struct display_target arg; 423 424 printf (_("BFD header file version %s\n"), BFD_VERSION_STRING); 425 426 display_target_list (&arg); 427 if (!arg.error) 428 display_target_tables (&arg); 429 430 return arg.error; 431 } 432 433 /* Display the archive header for an element as if it were an ls -l listing: 434 435 Mode User\tGroup\tSize\tDate Name */ 436 437 void 438 print_arelt_descr (FILE *file, bfd *abfd, bfd_boolean verbose, bfd_boolean offsets) 439 { 440 struct stat buf; 441 442 if (verbose) 443 { 444 if (bfd_stat_arch_elt (abfd, &buf) == 0) 445 { 446 char modebuf[11]; 447 char timebuf[40]; 448 time_t when = buf.st_mtime; 449 const char *ctime_result = (const char *) ctime (&when); 450 bfd_size_type size; 451 452 /* PR binutils/17605: Check for corrupt time values. */ 453 if (ctime_result == NULL) 454 sprintf (timebuf, _("<time data corrupt>")); 455 else 456 /* POSIX format: skip weekday and seconds from ctime output. */ 457 sprintf (timebuf, "%.12s %.4s", ctime_result + 4, ctime_result + 20); 458 459 mode_string (buf.st_mode, modebuf); 460 modebuf[10] = '\0'; 461 size = buf.st_size; 462 /* POSIX 1003.2/D11 says to skip first character (entry type). */ 463 fprintf (file, "%s %ld/%ld %6" BFD_VMA_FMT "u %s ", modebuf + 1, 464 (long) buf.st_uid, (long) buf.st_gid, 465 size, timebuf); 466 } 467 } 468 469 fprintf (file, "%s", bfd_get_filename (abfd)); 470 471 if (offsets) 472 { 473 if (bfd_is_thin_archive (abfd) && abfd->proxy_origin) 474 fprintf (file, " 0x%lx", (unsigned long) abfd->proxy_origin); 475 else if (!bfd_is_thin_archive (abfd) && abfd->origin) 476 fprintf (file, " 0x%lx", (unsigned long) abfd->origin); 477 } 478 479 fprintf (file, "\n"); 480 } 481 482 /* Return a path for a new temporary file in the same directory 483 as file PATH. */ 484 485 static char * 486 template_in_dir (const char *path) 487 { 488 #define template "stXXXXXX" 489 const char *slash = strrchr (path, '/'); 490 char *tmpname; 491 size_t len; 492 493 #ifdef HAVE_DOS_BASED_FILE_SYSTEM 494 { 495 /* We could have foo/bar\\baz, or foo\\bar, or d:bar. */ 496 char *bslash = strrchr (path, '\\'); 497 498 if (slash == NULL || (bslash != NULL && bslash > slash)) 499 slash = bslash; 500 if (slash == NULL && path[0] != '\0' && path[1] == ':') 501 slash = path + 1; 502 } 503 #endif 504 505 if (slash != (char *) NULL) 506 { 507 len = slash - path; 508 tmpname = (char *) xmalloc (len + sizeof (template) + 2); 509 memcpy (tmpname, path, len); 510 511 #ifdef HAVE_DOS_BASED_FILE_SYSTEM 512 /* If tmpname is "X:", appending a slash will make it a root 513 directory on drive X, which is NOT the same as the current 514 directory on drive X. */ 515 if (len == 2 && tmpname[1] == ':') 516 tmpname[len++] = '.'; 517 #endif 518 tmpname[len++] = '/'; 519 } 520 else 521 { 522 tmpname = (char *) xmalloc (sizeof (template)); 523 len = 0; 524 } 525 526 memcpy (tmpname + len, template, sizeof (template)); 527 return tmpname; 528 #undef template 529 } 530 531 /* Return the name of a created temporary file in the same directory 532 as FILENAME. */ 533 534 char * 535 make_tempname (const char *filename) 536 { 537 char *tmpname = template_in_dir (filename); 538 int fd; 539 540 #ifdef HAVE_MKSTEMP 541 fd = mkstemp (tmpname); 542 #else 543 tmpname = mktemp (tmpname); 544 if (tmpname == NULL) 545 return NULL; 546 fd = open (tmpname, O_RDWR | O_CREAT | O_EXCL, 0600); 547 #endif 548 if (fd == -1) 549 { 550 free (tmpname); 551 return NULL; 552 } 553 close (fd); 554 return tmpname; 555 } 556 557 /* Return the name of a created temporary directory inside the 558 directory containing FILENAME. */ 559 560 char * 561 make_tempdir (const char *filename) 562 { 563 char *tmpname = template_in_dir (filename); 564 565 #ifdef HAVE_MKDTEMP 566 return mkdtemp (tmpname); 567 #else 568 tmpname = mktemp (tmpname); 569 if (tmpname == NULL) 570 return NULL; 571 #if defined (_WIN32) && !defined (__CYGWIN32__) 572 if (mkdir (tmpname) != 0) 573 return NULL; 574 #else 575 if (mkdir (tmpname, 0700) != 0) 576 return NULL; 577 #endif 578 return tmpname; 579 #endif 580 } 581 582 /* Parse a string into a VMA, with a fatal error if it can't be 583 parsed. */ 584 585 bfd_vma 586 parse_vma (const char *s, const char *arg) 587 { 588 bfd_vma ret; 589 const char *end; 590 591 ret = bfd_scan_vma (s, &end, 0); 592 593 if (*end != '\0') 594 fatal (_("%s: bad number: %s"), arg, s); 595 596 return ret; 597 } 598 599 /* Returns the size of the named file. If the file does not 600 exist, or if it is not a real file, then a suitable non-fatal 601 error message is printed and (off_t) -1 is returned. */ 602 603 off_t 604 get_file_size (const char * file_name) 605 { 606 struct stat statbuf; 607 608 if (file_name == NULL) 609 return (off_t) -1; 610 611 if (stat (file_name, &statbuf) < 0) 612 { 613 if (errno == ENOENT) 614 non_fatal (_("'%s': No such file"), file_name); 615 else 616 non_fatal (_("Warning: could not locate '%s'. reason: %s"), 617 file_name, strerror (errno)); 618 } 619 else if (S_ISDIR (statbuf.st_mode)) 620 non_fatal (_("Warning: '%s' is a directory"), file_name); 621 else if (! S_ISREG (statbuf.st_mode)) 622 non_fatal (_("Warning: '%s' is not an ordinary file"), file_name); 623 else if (statbuf.st_size < 0) 624 non_fatal (_("Warning: '%s' has negative size, probably it is too large"), 625 file_name); 626 else 627 return statbuf.st_size; 628 629 return (off_t) -1; 630 } 631 632 /* Return the filename in a static buffer. */ 633 634 const char * 635 bfd_get_archive_filename (const bfd *abfd) 636 { 637 static size_t curr = 0; 638 static char *buf; 639 size_t needed; 640 641 assert (abfd != NULL); 642 643 if (abfd->my_archive == NULL 644 || bfd_is_thin_archive (abfd->my_archive)) 645 return bfd_get_filename (abfd); 646 647 needed = (strlen (bfd_get_filename (abfd->my_archive)) 648 + strlen (bfd_get_filename (abfd)) + 3); 649 if (needed > curr) 650 { 651 if (curr) 652 free (buf); 653 curr = needed + (needed >> 1); 654 buf = (char *) xmalloc (curr); 655 } 656 sprintf (buf, "%s(%s)", bfd_get_filename (abfd->my_archive), 657 bfd_get_filename (abfd)); 658 return buf; 659 } 660 661 /* Returns TRUE iff PATHNAME, a filename of an archive member, 662 is valid for writing. For security reasons absolute paths 663 and paths containing /../ are not allowed. See PR 17533. */ 664 665 bfd_boolean 666 is_valid_archive_path (char const * pathname) 667 { 668 const char * n = pathname; 669 670 if (IS_ABSOLUTE_PATH (n)) 671 return FALSE; 672 673 while (*n) 674 { 675 if (*n == '.' && *++n == '.' && ( ! *++n || IS_DIR_SEPARATOR (*n))) 676 return FALSE; 677 678 while (*n && ! IS_DIR_SEPARATOR (*n)) 679 n++; 680 while (IS_DIR_SEPARATOR (*n)) 681 n++; 682 } 683 684 return TRUE; 685 } 686