Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5217 serge 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
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
 
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 		/* ctime, maybe time_t */
33
#include 
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
 
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 VPARAMS ((const char *format, ...))
131
{
132
  VA_OPEN (args, format);
133
  VA_FIXEDARG (args, const char *, format);
134
 
135
  report (format, args);
136
  VA_CLOSE (args);
137
  xexit (1);
138
}
139
 
140
void
141
non_fatal VPARAMS ((const char *format, ...))
142
{
143
  VA_OPEN (args, format);
144
  VA_FIXEDARG (args, const char *, format);
145
 
146
  report (format, args);
147
  VA_CLOSE (args);
148
}
149
 
150
/* Set the default BFD target based on the configured target.  Doing
151
   this permits the binutils to be configured for a particular target,
152
   and linked against a shared BFD library which was configured for a
153
   different target.  */
154
 
155
void
156
set_default_bfd_target (void)
157
{
158
  /* The macro TARGET is defined by Makefile.  */
159
  const char *target = TARGET;
160
 
161
  if (! bfd_set_default_target (target))
162
    fatal (_("can't set BFD default target to `%s': %s"),
163
	   target, bfd_errmsg (bfd_get_error ()));
164
}
165
 
166
/* After a FALSE return from bfd_check_format_matches with
167
   bfd_get_error () == bfd_error_file_ambiguously_recognized, print
168
   the possible matching targets.  */
169
 
170
void
171
list_matching_formats (char **p)
172
{
173
  fflush (stdout);
174
  fprintf (stderr, _("%s: Matching formats:"), program_name);
175
  while (*p)
176
    fprintf (stderr, " %s", *p++);
177
  fputc ('\n', stderr);
178
}
179
 
180
/* List the supported targets.  */
181
 
182
void
183
list_supported_targets (const char *name, FILE *f)
184
{
185
  int t;
186
  const char **targ_names;
187
 
188
  if (name == NULL)
189
    fprintf (f, _("Supported targets:"));
190
  else
191
    fprintf (f, _("%s: supported targets:"), name);
192
 
193
  targ_names = bfd_target_list ();
194
  for (t = 0; targ_names[t] != NULL; t++)
195
    fprintf (f, " %s", targ_names[t]);
196
  fprintf (f, "\n");
197
  free (targ_names);
198
}
199
 
200
/* List the supported architectures.  */
201
 
202
void
203
list_supported_architectures (const char *name, FILE *f)
204
{
205
  const char ** arch;
206
  const char ** arches;
207
 
208
  if (name == NULL)
209
    fprintf (f, _("Supported architectures:"));
210
  else
211
    fprintf (f, _("%s: supported architectures:"), name);
212
 
213
  for (arch = arches = bfd_arch_list (); *arch; arch++)
214
    fprintf (f, " %s", *arch);
215
  fprintf (f, "\n");
216
  free (arches);
217
}
218
 
219
/* The length of the longest architecture name + 1.  */
220
#define LONGEST_ARCH sizeof ("powerpc:common")
221
 
222
static const char *
223
endian_string (enum bfd_endian endian)
224
{
225
  switch (endian)
226
    {
227
    case BFD_ENDIAN_BIG: return _("big endian");
228
    case BFD_ENDIAN_LITTLE: return _("little endian");
229
    default: return _("endianness unknown");
230
    }
231
}
232
 
233
/* List the targets that BFD is configured to support, each followed
234
   by its endianness and the architectures it supports.  */
235
 
236
static int
237
display_target_list (void)
238
{
239
  char *dummy_name;
240
  int t;
241
  int ret = 1;
242
 
243
  dummy_name = make_temp_file (NULL);
244
  for (t = 0; bfd_target_vector[t]; t++)
245
    {
246
      const bfd_target *p = bfd_target_vector[t];
247
      bfd *abfd = bfd_openw (dummy_name, p->name);
248
      int a;
249
 
250
      printf (_("%s\n (header %s, data %s)\n"), p->name,
251
	      endian_string (p->header_byteorder),
252
	      endian_string (p->byteorder));
253
 
254
      if (abfd == NULL)
255
	{
256
          bfd_nonfatal (dummy_name);
257
          ret = 0;
258
	  continue;
259
	}
260
 
261
      if (! bfd_set_format (abfd, bfd_object))
262
	{
263
	  if (bfd_get_error () != bfd_error_invalid_operation)
264
            {
265
	      bfd_nonfatal (p->name);
266
              ret = 0;
267
            }
268
	  bfd_close_all_done (abfd);
269
	  continue;
270
	}
271
 
272
      for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++)
273
	if (bfd_set_arch_mach (abfd, (enum bfd_architecture) a, 0))
274
	  printf ("  %s\n",
275
		  bfd_printable_arch_mach ((enum bfd_architecture) a, 0));
276
      bfd_close_all_done (abfd);
277
    }
278
  unlink (dummy_name);
279
  free (dummy_name);
280
 
281
  return ret;
282
}
283
 
284
/* Print a table showing which architectures are supported for entries
285
   FIRST through LAST-1 of bfd_target_vector (targets across,
286
   architectures down).  */
287
 
288
static int
289
display_info_table (int first, int last)
290
{
291
  int t;
292
  int ret = 1;
293
  char *dummy_name;
294
  int a;
295
 
296
  /* Print heading of target names.  */
297
  printf ("\n%*s", (int) LONGEST_ARCH, " ");
298
  for (t = first; t < last && bfd_target_vector[t]; t++)
299
    printf ("%s ", bfd_target_vector[t]->name);
300
  putchar ('\n');
301
 
302
  dummy_name = make_temp_file (NULL);
303
  for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++)
304
    if (strcmp (bfd_printable_arch_mach ((enum bfd_architecture) a, 0),
305
                "UNKNOWN!") != 0)
306
      {
307
	printf ("%*s ", (int) LONGEST_ARCH - 1,
308
		bfd_printable_arch_mach ((enum bfd_architecture) a, 0));
309
	for (t = first; t < last && bfd_target_vector[t]; t++)
310
	  {
311
	    const bfd_target *p = bfd_target_vector[t];
312
	    bfd_boolean ok = TRUE;
313
	    bfd *abfd = bfd_openw (dummy_name, p->name);
314
 
315
	    if (abfd == NULL)
316
	      {
317
		bfd_nonfatal (p->name);
318
                ret = 0;
319
		ok = FALSE;
320
	      }
321
 
322
	    if (ok)
323
	      {
324
		if (! bfd_set_format (abfd, bfd_object))
325
		  {
326
		    if (bfd_get_error () != bfd_error_invalid_operation)
327
                      {
328
		        bfd_nonfatal (p->name);
329
                        ret = 0;
330
                      }
331
		    ok = FALSE;
332
		  }
333
	      }
334
 
335
	    if (ok)
336
	      {
337
		if (! bfd_set_arch_mach (abfd, (enum bfd_architecture) a, 0))
338
		  ok = FALSE;
339
	      }
340
 
341
	    if (ok)
342
	      printf ("%s ", p->name);
343
	    else
344
	      {
345
		int l = strlen (p->name);
346
		while (l--)
347
		  putchar ('-');
348
		putchar (' ');
349
	      }
350
	    if (abfd != NULL)
351
	      bfd_close_all_done (abfd);
352
	  }
353
	putchar ('\n');
354
      }
355
  unlink (dummy_name);
356
  free (dummy_name);
357
 
358
  return ret;
359
}
360
 
361
/* Print tables of all the target-architecture combinations that
362
   BFD has been configured to support.  */
363
 
364
static int
365
display_target_tables (void)
366
{
367
  int t;
368
  int columns;
369
  int ret = 1;
370
  char *colum;
371
 
372
  columns = 0;
373
  colum = getenv ("COLUMNS");
374
  if (colum != NULL)
375
    columns = atoi (colum);
376
  if (columns == 0)
377
    columns = 80;
378
 
379
  t = 0;
380
  while (bfd_target_vector[t] != NULL)
381
    {
382
      int oldt = t, wid;
383
 
384
      wid = LONGEST_ARCH + strlen (bfd_target_vector[t]->name) + 1;
385
      ++t;
386
      while (wid < columns && bfd_target_vector[t] != NULL)
387
	{
388
	  int newwid;
389
 
390
	  newwid = wid + strlen (bfd_target_vector[t]->name) + 1;
391
	  if (newwid >= columns)
392
	    break;
393
	  wid = newwid;
394
	  ++t;
395
	}
396
      if (! display_info_table (oldt, t))
397
        ret = 0;
398
    }
399
 
400
  return ret;
401
}
402
 
403
int
404
display_info (void)
405
{
406
  printf (_("BFD header file version %s\n"), BFD_VERSION_STRING);
407
  if (! display_target_list () || ! display_target_tables ())
408
    return 1;
409
  else
410
    return 0;
411
}
412
 
413
/* Display the archive header for an element as if it were an ls -l listing:
414
 
415
   Mode       User\tGroup\tSize\tDate               Name */
416
 
417
void
418
print_arelt_descr (FILE *file, bfd *abfd, bfd_boolean verbose)
419
{
420
  struct stat buf;
421
 
422
  if (verbose)
423
    {
424
      if (bfd_stat_arch_elt (abfd, &buf) == 0)
425
	{
426
	  char modebuf[11];
427
	  char timebuf[40];
428
	  time_t when = buf.st_mtime;
429
	  const char *ctime_result = (const char *) ctime (&when);
430
	  bfd_size_type size;
431
 
432
	  /* POSIX format:  skip weekday and seconds from ctime output.  */
433
	  sprintf (timebuf, "%.12s %.4s", ctime_result + 4, ctime_result + 20);
434
 
435
	  mode_string (buf.st_mode, modebuf);
436
	  modebuf[10] = '\0';
437
	  size = buf.st_size;
438
	  /* POSIX 1003.2/D11 says to skip first character (entry type).  */
439
	  fprintf (file, "%s %ld/%ld %6" BFD_VMA_FMT "u %s ", modebuf + 1,
440
		   (long) buf.st_uid, (long) buf.st_gid,
441
		   size, timebuf);
442
	}
443
    }
444
 
445
  fprintf (file, "%s\n", bfd_get_filename (abfd));
446
}
447
 
448
/* Return a path for a new temporary file in the same directory
449
   as file PATH.  */
450
 
451
static char *
452
template_in_dir (const char *path)
453
{
454
#define template "stXXXXXX"
455
  const char *slash = strrchr (path, '/');
456
  char *tmpname;
457
  size_t len;
458
 
459
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
460
  {
461
    /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
462
    char *bslash = strrchr (path, '\\');
463
 
464
    if (slash == NULL || (bslash != NULL && bslash > slash))
465
      slash = bslash;
466
    if (slash == NULL && path[0] != '\0' && path[1] == ':')
467
      slash = path + 1;
468
  }
469
#endif
470
 
471
  if (slash != (char *) NULL)
472
    {
473
      len = slash - path;
474
      tmpname = (char *) xmalloc (len + sizeof (template) + 2);
475
      memcpy (tmpname, path, len);
476
 
477
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
478
      /* If tmpname is "X:", appending a slash will make it a root
479
	 directory on drive X, which is NOT the same as the current
480
	 directory on drive X.  */
481
      if (len == 2 && tmpname[1] == ':')
482
	tmpname[len++] = '.';
483
#endif
484
      tmpname[len++] = '/';
485
    }
486
  else
487
    {
488
      tmpname = (char *) xmalloc (sizeof (template));
489
      len = 0;
490
    }
491
 
492
  memcpy (tmpname + len, template, sizeof (template));
493
  return tmpname;
494
#undef template
495
}
496
 
497
/* Return the name of a created temporary file in the same directory
498
   as FILENAME.  */
499
 
500
char *
501
make_tempname (char *filename)
502
{
503
  char *tmpname = template_in_dir (filename);
504
  int fd;
505
 
506
#ifdef HAVE_MKSTEMP
507
  fd = mkstemp (tmpname);
508
#else
509
  tmpname = mktemp (tmpname);
510
  if (tmpname == NULL)
511
    return NULL;
512
  fd = open (tmpname, O_RDWR | O_CREAT | O_EXCL, 0600);
513
#endif
514
  if (fd == -1)
515
    {
516
      free (tmpname);
517
      return NULL;
518
    }
519
  close (fd);
520
  return tmpname;
521
}
522
 
523
/* Return the name of a created temporary directory inside the
524
   directory containing FILENAME.  */
525
 
526
char *
527
make_tempdir (char *filename)
528
{
529
  char *tmpname = template_in_dir (filename);
530
 
531
/*
532
#ifdef HAVE_MKDTEMP
533
  return mkdtemp (tmpname);
534
#else
535
  tmpname = mktemp (tmpname);
536
  if (tmpname == NULL)
537
    return NULL;
538
#if defined (_WIN32) && !defined (__CYGWIN32__)
539
  if (mkdir (tmpname) != 0)
540
    return NULL;
541
#else
542
  if (mkdir (tmpname, 0700) != 0)
543
    return NULL;
544
#endif
545
  return tmpname;
546
#endif
547
*/
548
  return NULL;
549
}
550
 
551
/* Parse a string into a VMA, with a fatal error if it can't be
552
   parsed.  */
553
 
554
bfd_vma
555
parse_vma (const char *s, const char *arg)
556
{
557
  bfd_vma ret;
558
  const char *end;
559
 
560
  ret = bfd_scan_vma (s, &end, 0);
561
 
562
  if (*end != '\0')
563
    fatal (_("%s: bad number: %s"), arg, s);
564
 
565
  return ret;
566
}
567
 
568
/* Returns the size of the named file.  If the file does not
569
   exist, or if it is not a real file, then a suitable non-fatal
570
   error message is printed and (off_t) -1 is returned.  */
571
 
572
off_t
573
get_file_size (const char * file_name)
574
{
575
  struct stat statbuf;
576
 
577
  if (stat (file_name, &statbuf) < 0)
578
    {
579
      if (errno == ENOENT)
580
	non_fatal (_("'%s': No such file"), file_name);
581
      else
582
	non_fatal (_("Warning: could not locate '%s'.  reason: %s"),
583
		   file_name, strerror (errno));
584
    }
585
  else if (! S_ISREG (statbuf.st_mode))
586
    non_fatal (_("Warning: '%s' is not an ordinary file"), file_name);
587
  else if (statbuf.st_size < 0)
588
    non_fatal (_("Warning: '%s' has negative size, probably it is too large"),
589
               file_name);
590
  else
591
    return statbuf.st_size;
592
 
593
  return (off_t) -1;
594
}
595
 
596
/* Return the filename in a static buffer.  */
597
 
598
const char *
599
bfd_get_archive_filename (const bfd *abfd)
600
{
601
  static size_t curr = 0;
602
  static char *buf;
603
  size_t needed;
604
 
605
  assert (abfd != NULL);
606
 
607
  if (!abfd->my_archive)
608
    return bfd_get_filename (abfd);
609
 
610
  needed = (strlen (bfd_get_filename (abfd->my_archive))
611
	    + strlen (bfd_get_filename (abfd)) + 3);
612
  if (needed > curr)
613
    {
614
      if (curr)
615
	free (buf);
616
      curr = needed + (needed >> 1);
617
      buf = (char *) bfd_malloc (curr);
618
      /* If we can't malloc, fail safe by returning just the file name.
619
	 This function is only used when building error messages.  */
620
      if (!buf)
621
	{
622
	  curr = 0;
623
	  return bfd_get_filename (abfd);
624
	}
625
    }
626
  sprintf (buf, "%s(%s)", bfd_get_filename (abfd->my_archive),
627
	   bfd_get_filename (abfd));
628
  return buf;
629
}