]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - binutils/bucomm.c
8272d6a3c34568f9db4a8b30b9b92ced92e80724
[thirdparty/binutils-gdb.git] / binutils / bucomm.c
1 /* bucomm.c -- Bin Utils COMmon code.
2 Copyright 1991, 1992, 1993, 1994, 1995, 1997, 1998, 2000, 2001, 2002,
3 2003, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2014
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 \f
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 <time.h> /* ctime, maybe time_t */
33 #include <assert.h>
34 #include "bucomm.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 \f
47 /* Error reporting. */
48
49 char *program_name;
50
51 void
52 bfd_nonfatal (const char *string)
53 {
54 const char *errmsg;
55
56 errmsg = bfd_errmsg (bfd_get_error ());
57 fflush (stdout);
58 if (string)
59 fprintf (stderr, "%s: %s: %s\n", program_name, string, errmsg);
60 else
61 fprintf (stderr, "%s: %s\n", program_name, errmsg);
62 }
63
64 /* Issue a non fatal error message. FILENAME, or if NULL then BFD,
65 are used to indicate the problematic file. SECTION, if non NULL,
66 is used to provide a section name. If FORMAT is non-null, then it
67 is used to print additional information via vfprintf. Finally the
68 bfd error message is printed. In summary, error messages are of
69 one of the following forms:
70
71 PROGRAM:file: bfd-error-message
72 PROGRAM:file[section]: bfd-error-message
73 PROGRAM:file: printf-message: bfd-error-message
74 PROGRAM:file[section]: printf-message: bfd-error-message. */
75
76 void
77 bfd_nonfatal_message (const char *filename,
78 const bfd *abfd,
79 const asection *section,
80 const char *format, ...)
81 {
82 const char *errmsg;
83 const char *section_name;
84 va_list args;
85
86 errmsg = bfd_errmsg (bfd_get_error ());
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_get_section_name (abfd, 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 \f
221 /* The length of the longest architecture name + 1. */
222 #define LONGEST_ARCH sizeof ("powerpc:common")
223
224 static const char *
225 endian_string (enum bfd_endian endian)
226 {
227 switch (endian)
228 {
229 case BFD_ENDIAN_BIG: return _("big endian");
230 case BFD_ENDIAN_LITTLE: return _("little endian");
231 default: return _("endianness unknown");
232 }
233 }
234
235 /* List the targets that BFD is configured to support, each followed
236 by its endianness and the architectures it supports. */
237
238 static int
239 display_target_list (void)
240 {
241 char *dummy_name;
242 int t;
243 int ret = 1;
244
245 dummy_name = make_temp_file (NULL);
246 for (t = 0; bfd_target_vector[t]; t++)
247 {
248 const bfd_target *p = bfd_target_vector[t];
249 bfd *abfd = bfd_openw (dummy_name, p->name);
250 int a;
251
252 printf (_("%s\n (header %s, data %s)\n"), p->name,
253 endian_string (p->header_byteorder),
254 endian_string (p->byteorder));
255
256 if (abfd == NULL)
257 {
258 bfd_nonfatal (dummy_name);
259 ret = 0;
260 continue;
261 }
262
263 if (! bfd_set_format (abfd, bfd_object))
264 {
265 if (bfd_get_error () != bfd_error_invalid_operation)
266 {
267 bfd_nonfatal (p->name);
268 ret = 0;
269 }
270 bfd_close_all_done (abfd);
271 continue;
272 }
273
274 for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++)
275 if (bfd_set_arch_mach (abfd, (enum bfd_architecture) a, 0))
276 printf (" %s\n",
277 bfd_printable_arch_mach ((enum bfd_architecture) a, 0));
278 bfd_close_all_done (abfd);
279 }
280 unlink (dummy_name);
281 free (dummy_name);
282
283 return ret;
284 }
285
286 /* Print a table showing which architectures are supported for entries
287 FIRST through LAST-1 of bfd_target_vector (targets across,
288 architectures down). */
289
290 static int
291 display_info_table (int first, int last)
292 {
293 int t;
294 int ret = 1;
295 char *dummy_name;
296 int a;
297
298 /* Print heading of target names. */
299 printf ("\n%*s", (int) LONGEST_ARCH, " ");
300 for (t = first; t < last && bfd_target_vector[t]; t++)
301 printf ("%s ", bfd_target_vector[t]->name);
302 putchar ('\n');
303
304 dummy_name = make_temp_file (NULL);
305 for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++)
306 if (strcmp (bfd_printable_arch_mach ((enum bfd_architecture) a, 0),
307 "UNKNOWN!") != 0)
308 {
309 printf ("%*s ", (int) LONGEST_ARCH - 1,
310 bfd_printable_arch_mach ((enum bfd_architecture) a, 0));
311 for (t = first; t < last && bfd_target_vector[t]; t++)
312 {
313 const bfd_target *p = bfd_target_vector[t];
314 bfd_boolean ok = TRUE;
315 bfd *abfd = bfd_openw (dummy_name, p->name);
316
317 if (abfd == NULL)
318 {
319 bfd_nonfatal (p->name);
320 ret = 0;
321 ok = FALSE;
322 }
323
324 if (ok)
325 {
326 if (! bfd_set_format (abfd, bfd_object))
327 {
328 if (bfd_get_error () != bfd_error_invalid_operation)
329 {
330 bfd_nonfatal (p->name);
331 ret = 0;
332 }
333 ok = FALSE;
334 }
335 }
336
337 if (ok)
338 {
339 if (! bfd_set_arch_mach (abfd, (enum bfd_architecture) a, 0))
340 ok = FALSE;
341 }
342
343 if (ok)
344 printf ("%s ", p->name);
345 else
346 {
347 int l = strlen (p->name);
348 while (l--)
349 putchar ('-');
350 putchar (' ');
351 }
352 if (abfd != NULL)
353 bfd_close_all_done (abfd);
354 }
355 putchar ('\n');
356 }
357 unlink (dummy_name);
358 free (dummy_name);
359
360 return ret;
361 }
362
363 /* Print tables of all the target-architecture combinations that
364 BFD has been configured to support. */
365
366 static int
367 display_target_tables (void)
368 {
369 int t;
370 int columns;
371 int ret = 1;
372 char *colum;
373
374 columns = 0;
375 colum = getenv ("COLUMNS");
376 if (colum != NULL)
377 columns = atoi (colum);
378 if (columns == 0)
379 columns = 80;
380
381 t = 0;
382 while (bfd_target_vector[t] != NULL)
383 {
384 int oldt = t, wid;
385
386 wid = LONGEST_ARCH + strlen (bfd_target_vector[t]->name) + 1;
387 ++t;
388 while (wid < columns && bfd_target_vector[t] != NULL)
389 {
390 int newwid;
391
392 newwid = wid + strlen (bfd_target_vector[t]->name) + 1;
393 if (newwid >= columns)
394 break;
395 wid = newwid;
396 ++t;
397 }
398 if (! display_info_table (oldt, t))
399 ret = 0;
400 }
401
402 return ret;
403 }
404
405 int
406 display_info (void)
407 {
408 printf (_("BFD header file version %s\n"), BFD_VERSION_STRING);
409 if (! display_target_list () || ! display_target_tables ())
410 return 1;
411 else
412 return 0;
413 }
414 \f
415 /* Display the archive header for an element as if it were an ls -l listing:
416
417 Mode User\tGroup\tSize\tDate Name */
418
419 void
420 print_arelt_descr (FILE *file, bfd *abfd, bfd_boolean verbose)
421 {
422 struct stat buf;
423
424 if (verbose)
425 {
426 if (bfd_stat_arch_elt (abfd, &buf) == 0)
427 {
428 char modebuf[11];
429 char timebuf[40];
430 time_t when = buf.st_mtime;
431 const char *ctime_result = (const char *) ctime (&when);
432 bfd_size_type size;
433
434 /* POSIX format: skip weekday and seconds from ctime output. */
435 sprintf (timebuf, "%.12s %.4s", ctime_result + 4, ctime_result + 20);
436
437 mode_string (buf.st_mode, modebuf);
438 modebuf[10] = '\0';
439 size = buf.st_size;
440 /* POSIX 1003.2/D11 says to skip first character (entry type). */
441 fprintf (file, "%s %ld/%ld %6" BFD_VMA_FMT "u %s ", modebuf + 1,
442 (long) buf.st_uid, (long) buf.st_gid,
443 size, timebuf);
444 }
445 }
446
447 fprintf (file, "%s\n", bfd_get_filename (abfd));
448 }
449
450 /* Return a path for a new temporary file in the same directory
451 as file PATH. */
452
453 static char *
454 template_in_dir (const char *path)
455 {
456 #define template "stXXXXXX"
457 const char *slash = strrchr (path, '/');
458 char *tmpname;
459 size_t len;
460
461 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
462 {
463 /* We could have foo/bar\\baz, or foo\\bar, or d:bar. */
464 char *bslash = strrchr (path, '\\');
465
466 if (slash == NULL || (bslash != NULL && bslash > slash))
467 slash = bslash;
468 if (slash == NULL && path[0] != '\0' && path[1] == ':')
469 slash = path + 1;
470 }
471 #endif
472
473 if (slash != (char *) NULL)
474 {
475 len = slash - path;
476 tmpname = (char *) xmalloc (len + sizeof (template) + 2);
477 memcpy (tmpname, path, len);
478
479 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
480 /* If tmpname is "X:", appending a slash will make it a root
481 directory on drive X, which is NOT the same as the current
482 directory on drive X. */
483 if (len == 2 && tmpname[1] == ':')
484 tmpname[len++] = '.';
485 #endif
486 tmpname[len++] = '/';
487 }
488 else
489 {
490 tmpname = (char *) xmalloc (sizeof (template));
491 len = 0;
492 }
493
494 memcpy (tmpname + len, template, sizeof (template));
495 return tmpname;
496 #undef template
497 }
498
499 /* Return the name of a created temporary file in the same directory
500 as FILENAME. */
501
502 char *
503 make_tempname (char *filename)
504 {
505 char *tmpname = template_in_dir (filename);
506 int fd;
507
508 #ifdef HAVE_MKSTEMP
509 fd = mkstemp (tmpname);
510 #else
511 tmpname = mktemp (tmpname);
512 if (tmpname == NULL)
513 return NULL;
514 fd = open (tmpname, O_RDWR | O_CREAT | O_EXCL, 0600);
515 #endif
516 if (fd == -1)
517 {
518 free (tmpname);
519 return NULL;
520 }
521 close (fd);
522 return tmpname;
523 }
524
525 /* Return the name of a created temporary directory inside the
526 directory containing FILENAME. */
527
528 char *
529 make_tempdir (char *filename)
530 {
531 char *tmpname = template_in_dir (filename);
532
533 #ifdef HAVE_MKDTEMP
534 return mkdtemp (tmpname);
535 #else
536 tmpname = mktemp (tmpname);
537 if (tmpname == NULL)
538 return NULL;
539 #if defined (_WIN32) && !defined (__CYGWIN32__)
540 if (mkdir (tmpname) != 0)
541 return NULL;
542 #else
543 if (mkdir (tmpname, 0700) != 0)
544 return NULL;
545 #endif
546 return tmpname;
547 #endif
548 }
549
550 /* Parse a string into a VMA, with a fatal error if it can't be
551 parsed. */
552
553 bfd_vma
554 parse_vma (const char *s, const char *arg)
555 {
556 bfd_vma ret;
557 const char *end;
558
559 ret = bfd_scan_vma (s, &end, 0);
560
561 if (*end != '\0')
562 fatal (_("%s: bad number: %s"), arg, s);
563
564 return ret;
565 }
566
567 /* Returns the size of the named file. If the file does not
568 exist, or if it is not a real file, then a suitable non-fatal
569 error message is printed and (off_t) -1 is returned. */
570
571 off_t
572 get_file_size (const char * file_name)
573 {
574 struct stat statbuf;
575
576 if (stat (file_name, &statbuf) < 0)
577 {
578 if (errno == ENOENT)
579 non_fatal (_("'%s': No such file"), file_name);
580 else
581 non_fatal (_("Warning: could not locate '%s'. reason: %s"),
582 file_name, strerror (errno));
583 }
584 else if (! S_ISREG (statbuf.st_mode))
585 non_fatal (_("Warning: '%s' is not an ordinary file"), file_name);
586 else if (statbuf.st_size < 0)
587 non_fatal (_("Warning: '%s' has negative size, probably it is too large"),
588 file_name);
589 else
590 return statbuf.st_size;
591
592 return (off_t) -1;
593 }
594
595 /* Return the filename in a static buffer. */
596
597 const char *
598 bfd_get_archive_filename (const bfd *abfd)
599 {
600 static size_t curr = 0;
601 static char *buf;
602 size_t needed;
603
604 assert (abfd != NULL);
605
606 if (!abfd->my_archive)
607 return bfd_get_filename (abfd);
608
609 needed = (strlen (bfd_get_filename (abfd->my_archive))
610 + strlen (bfd_get_filename (abfd)) + 3);
611 if (needed > curr)
612 {
613 if (curr)
614 free (buf);
615 curr = needed + (needed >> 1);
616 buf = (char *) bfd_malloc (curr);
617 /* If we can't malloc, fail safe by returning just the file name.
618 This function is only used when building error messages. */
619 if (!buf)
620 {
621 curr = 0;
622 return bfd_get_filename (abfd);
623 }
624 }
625 sprintf (buf, "%s(%s)", bfd_get_filename (abfd->my_archive),
626 bfd_get_filename (abfd));
627 return buf;
628 }