x86: SYSENTER/SYSEXIT are unavailable in 64-bit mode on AMD
[deliverable/binutils-gdb.git] / binutils / bucomm.c
... / ...
CommitLineData
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\f
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\f
39/* Error reporting. */
40
41char *program_name;
42
43void
44bfd_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
72void
73bfd_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
113void
114bfd_fatal (const char *string)
115{
116 bfd_nonfatal (string);
117 xexit (1);
118}
119
120void
121report (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
129void
130fatal (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
141void
142non_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
157void
158set_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
172void
173list_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
184void
185list_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
204void
205list_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\f
221static const char *
222endian_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
234struct 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
256static int
257do_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
310static void
311display_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
327static int
328do_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
342static void
343do_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
351static void
352do_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
374static void
375display_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
419int
420display_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\f
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
437void
438print_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
485static char *
486template_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
534char *
535make_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
560char *
561make_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
585bfd_vma
586parse_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
603off_t
604get_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
634const char *
635bfd_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
665bfd_boolean
666is_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}
This page took 0.030591 seconds and 4 git commands to generate.