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