Home | History | Annotate | Line # | Download | only in bfd
format.c revision 1.10
      1 /* Generic BFD support for file formats.
      2    Copyright (C) 1990-2022 Free Software Foundation, Inc.
      3    Written by Cygnus Support.
      4 
      5    This file is part of BFD, the Binary File Descriptor library.
      6 
      7    This program is free software; you can redistribute it and/or modify
      8    it under the terms of the GNU General Public License as published by
      9    the Free Software Foundation; either version 3 of the License, or
     10    (at your option) any later version.
     11 
     12    This program is distributed in the hope that it will be useful,
     13    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15    GNU General Public License for more details.
     16 
     17    You should have received a copy of the GNU General Public License
     18    along with this program; if not, write to the Free Software
     19    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     20    MA 02110-1301, USA.  */
     21 
     22 
     23 /*
     24 SECTION
     25 	File formats
     26 
     27 	A format is a BFD concept of high level file contents type. The
     28 	formats supported by BFD are:
     29 
     30 	o <<bfd_object>>
     31 
     32 	The BFD may contain data, symbols, relocations and debug info.
     33 
     34 	o <<bfd_archive>>
     35 
     36 	The BFD contains other BFDs and an optional index.
     37 
     38 	o <<bfd_core>>
     39 
     40 	The BFD contains the result of an executable core dump.
     41 
     42 SUBSECTION
     43 	File format functions
     44 */
     45 
     46 #include "sysdep.h"
     47 #include "bfd.h"
     48 #include "libbfd.h"
     49 
     50 /* IMPORT from targets.c.  */
     51 extern const size_t _bfd_target_vector_entries;
     52 
     53 /*
     54 FUNCTION
     55 	bfd_check_format
     56 
     57 SYNOPSIS
     58 	bool bfd_check_format (bfd *abfd, bfd_format format);
     59 
     60 DESCRIPTION
     61 	Verify if the file attached to the BFD @var{abfd} is compatible
     62 	with the format @var{format} (i.e., one of <<bfd_object>>,
     63 	<<bfd_archive>> or <<bfd_core>>).
     64 
     65 	If the BFD has been set to a specific target before the
     66 	call, only the named target and format combination is
     67 	checked. If the target has not been set, or has been set to
     68 	<<default>>, then all the known target backends is
     69 	interrogated to determine a match.  If the default target
     70 	matches, it is used.  If not, exactly one target must recognize
     71 	the file, or an error results.
     72 
     73 	The function returns <<TRUE>> on success, otherwise <<FALSE>>
     74 	with one of the following error codes:
     75 
     76 	o <<bfd_error_invalid_operation>> -
     77 	if <<format>> is not one of <<bfd_object>>, <<bfd_archive>> or
     78 	<<bfd_core>>.
     79 
     80 	o <<bfd_error_system_call>> -
     81 	if an error occured during a read - even some file mismatches
     82 	can cause bfd_error_system_calls.
     83 
     84 	o <<file_not_recognised>> -
     85 	none of the backends recognised the file format.
     86 
     87 	o <<bfd_error_file_ambiguously_recognized>> -
     88 	more than one backend recognised the file format.
     89 */
     90 
     91 bool
     92 bfd_check_format (bfd *abfd, bfd_format format)
     93 {
     94   return bfd_check_format_matches (abfd, format, NULL);
     95 }
     96 
     97 struct bfd_preserve
     98 {
     99   void *marker;
    100   void *tdata;
    101   flagword flags;
    102   const struct bfd_arch_info *arch_info;
    103   struct bfd_section *sections;
    104   struct bfd_section *section_last;
    105   unsigned int section_count;
    106   unsigned int section_id;
    107   struct bfd_hash_table section_htab;
    108   const struct bfd_build_id *build_id;
    109   bfd_cleanup cleanup;
    110 };
    111 
    112 /* When testing an object for compatibility with a particular target
    113    back-end, the back-end object_p function needs to set up certain
    114    fields in the bfd on successfully recognizing the object.  This
    115    typically happens in a piecemeal fashion, with failures possible at
    116    many points.  On failure, the bfd is supposed to be restored to its
    117    initial state, which is virtually impossible.  However, restoring a
    118    subset of the bfd state works in practice.  This function stores
    119    the subset.  */
    120 
    121 static bool
    122 bfd_preserve_save (bfd *abfd, struct bfd_preserve *preserve,
    123 		   bfd_cleanup cleanup)
    124 {
    125   preserve->tdata = abfd->tdata.any;
    126   preserve->arch_info = abfd->arch_info;
    127   preserve->flags = abfd->flags;
    128   preserve->sections = abfd->sections;
    129   preserve->section_last = abfd->section_last;
    130   preserve->section_count = abfd->section_count;
    131   preserve->section_id = _bfd_section_id;
    132   preserve->section_htab = abfd->section_htab;
    133   preserve->marker = bfd_alloc (abfd, 1);
    134   preserve->build_id = abfd->build_id;
    135   preserve->cleanup = cleanup;
    136   if (preserve->marker == NULL)
    137     return false;
    138 
    139   return bfd_hash_table_init (&abfd->section_htab, bfd_section_hash_newfunc,
    140 			      sizeof (struct section_hash_entry));
    141 }
    142 
    143 /* Clear out a subset of BFD state.  */
    144 
    145 static void
    146 bfd_reinit (bfd *abfd, unsigned int section_id, bfd_cleanup cleanup)
    147 {
    148   _bfd_section_id = section_id;
    149   if (cleanup)
    150     cleanup (abfd);
    151   abfd->tdata.any = NULL;
    152   abfd->arch_info = &bfd_default_arch_struct;
    153   abfd->flags &= BFD_FLAGS_SAVED;
    154   abfd->build_id = NULL;
    155   bfd_section_list_clear (abfd);
    156 }
    157 
    158 /* Restores bfd state saved by bfd_preserve_save.  */
    159 
    160 static bfd_cleanup
    161 bfd_preserve_restore (bfd *abfd, struct bfd_preserve *preserve)
    162 {
    163   bfd_hash_table_free (&abfd->section_htab);
    164 
    165   abfd->tdata.any = preserve->tdata;
    166   abfd->arch_info = preserve->arch_info;
    167   abfd->flags = preserve->flags;
    168   abfd->section_htab = preserve->section_htab;
    169   abfd->sections = preserve->sections;
    170   abfd->section_last = preserve->section_last;
    171   abfd->section_count = preserve->section_count;
    172   _bfd_section_id = preserve->section_id;
    173   abfd->build_id = preserve->build_id;
    174 
    175   /* bfd_release frees all memory more recently bfd_alloc'd than
    176      its arg, as well as its arg.  */
    177   bfd_release (abfd, preserve->marker);
    178   preserve->marker = NULL;
    179   return preserve->cleanup;
    180 }
    181 
    182 /* Called when the bfd state saved by bfd_preserve_save is no longer
    183    needed.  */
    184 
    185 static void
    186 bfd_preserve_finish (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_preserve *preserve)
    187 {
    188   if (preserve->cleanup)
    189     {
    190       /* Run the cleanup, assuming that all it will need is the
    191 	 tdata at the time the cleanup was returned.  */
    192       void *tdata = abfd->tdata.any;
    193       abfd->tdata.any = preserve->tdata;
    194       preserve->cleanup (abfd);
    195       abfd->tdata.any = tdata;
    196     }
    197   /* It would be nice to be able to free more memory here, eg. old
    198      tdata, but that's not possible since these blocks are sitting
    199      inside bfd_alloc'd memory.  The section hash is on a separate
    200      objalloc.  */
    201   bfd_hash_table_free (&preserve->section_htab);
    202   preserve->marker = NULL;
    203 }
    204 
    205 static void
    206 print_warnmsg (struct per_xvec_message **list)
    207 {
    208   fflush (stdout);
    209   fprintf (stderr, "%s: ", _bfd_get_error_program_name ());
    210 
    211   for (struct per_xvec_message *warn = *list; warn; warn = warn->next)
    212     {
    213       fputs (warn->message, stderr);
    214       fputc ('\n', stderr);
    215     }
    216   fflush (stderr);
    217 }
    218 
    219 static void
    220 clear_warnmsg (struct per_xvec_message **list)
    221 {
    222   struct per_xvec_message *warn = *list;
    223   while (warn)
    224     {
    225       struct per_xvec_message *next = warn->next;
    226       free (warn);
    227       warn = next;
    228     }
    229   *list = NULL;
    230 }
    231 
    232 static void
    233 null_error_handler (const char *fmt ATTRIBUTE_UNUSED,
    234 		    va_list ap ATTRIBUTE_UNUSED)
    235 {
    236 }
    237 
    238 /*
    239 FUNCTION
    240 	bfd_check_format_matches
    241 
    242 SYNOPSIS
    243 	bool bfd_check_format_matches
    244 	  (bfd *abfd, bfd_format format, char ***matching);
    245 
    246 DESCRIPTION
    247 	Like <<bfd_check_format>>, except when it returns FALSE with
    248 	<<bfd_errno>> set to <<bfd_error_file_ambiguously_recognized>>.  In that
    249 	case, if @var{matching} is not NULL, it will be filled in with
    250 	a NULL-terminated list of the names of the formats that matched,
    251 	allocated with <<malloc>>.
    252 	Then the user may choose a format and try again.
    253 
    254 	When done with the list that @var{matching} points to, the caller
    255 	should free it.
    256 */
    257 
    258 bool
    259 bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
    260 {
    261   extern const bfd_target binary_vec;
    262 #if BFD_SUPPORTS_PLUGINS
    263   extern const bfd_target plugin_vec;
    264 #endif
    265   const bfd_target * const *target;
    266   const bfd_target **matching_vector = NULL;
    267   const bfd_target *save_targ, *right_targ, *ar_right_targ, *match_targ;
    268   int match_count, best_count, best_match;
    269   int ar_match_index;
    270   unsigned int initial_section_id = _bfd_section_id;
    271   struct bfd_preserve preserve, preserve_match;
    272   bfd_cleanup cleanup = NULL;
    273   bfd_error_handler_type orig_error_handler;
    274   static int in_check_format;
    275 
    276   if (matching != NULL)
    277     *matching = NULL;
    278 
    279   if (!bfd_read_p (abfd)
    280       || (unsigned int) abfd->format >= (unsigned int) bfd_type_end)
    281     {
    282       bfd_set_error (bfd_error_invalid_operation);
    283       return false;
    284     }
    285 
    286   if (abfd->format != bfd_unknown)
    287     return abfd->format == format;
    288 
    289   if (matching != NULL || *bfd_associated_vector != NULL)
    290     {
    291       size_t amt;
    292 
    293       amt = sizeof (*matching_vector) * 2 * _bfd_target_vector_entries;
    294       matching_vector = (const bfd_target **) bfd_malloc (amt);
    295       if (!matching_vector)
    296 	return false;
    297     }
    298 
    299   /* Presume the answer is yes.  */
    300   abfd->format = format;
    301   save_targ = abfd->xvec;
    302 
    303   /* Don't report errors on recursive calls checking the first element
    304      of an archive.  */
    305   if (in_check_format)
    306     orig_error_handler = bfd_set_error_handler (null_error_handler);
    307   else
    308     orig_error_handler = _bfd_set_error_handler_caching (abfd);
    309   ++in_check_format;
    310 
    311   preserve_match.marker = NULL;
    312   if (!bfd_preserve_save (abfd, &preserve, NULL))
    313     goto err_ret;
    314 
    315   /* If the target type was explicitly specified, just check that target.  */
    316   if (!abfd->target_defaulted)
    317     {
    318       if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)	/* rewind! */
    319 	goto err_ret;
    320 
    321       cleanup = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
    322 
    323       if (cleanup)
    324 	goto ok_ret;
    325 
    326       /* For a long time the code has dropped through to check all
    327 	 targets if the specified target was wrong.  I don't know why,
    328 	 and I'm reluctant to change it.  However, in the case of an
    329 	 archive, it can cause problems.  If the specified target does
    330 	 not permit archives (e.g., the binary target), then we should
    331 	 not allow some other target to recognize it as an archive, but
    332 	 should instead allow the specified target to recognize it as an
    333 	 object.  When I first made this change, it broke the PE target,
    334 	 because the specified pei-i386 target did not recognize the
    335 	 actual pe-i386 archive.  Since there may be other problems of
    336 	 this sort, I changed this test to check only for the binary
    337 	 target.  */
    338       if (format == bfd_archive && save_targ == &binary_vec)
    339 	goto err_unrecog;
    340     }
    341 
    342   /* Since the target type was defaulted, check them all in the hope
    343      that one will be uniquely recognized.  */
    344   right_targ = NULL;
    345   ar_right_targ = NULL;
    346   match_targ = NULL;
    347   best_match = 256;
    348   best_count = 0;
    349   match_count = 0;
    350   ar_match_index = _bfd_target_vector_entries;
    351 
    352   for (target = bfd_target_vector; *target != NULL; target++)
    353     {
    354       void **high_water;
    355 
    356       /* The binary target matches anything, so don't return it when
    357 	 searching.  Don't match the plugin target if we have another
    358 	 alternative since we want to properly set the input format
    359 	 before allowing a plugin to claim the file.  Also, don't
    360 	 check the default target twice.  */
    361       if (*target == &binary_vec
    362 #if BFD_SUPPORTS_PLUGINS
    363 	  || (match_count != 0 && *target == &plugin_vec)
    364 #endif
    365 	  || (!abfd->target_defaulted && *target == save_targ))
    366 	continue;
    367 
    368       /* If we already tried a match, the bfd is modified and may
    369 	 have sections attached, which will confuse the next
    370 	 _bfd_check_format call.  */
    371       bfd_reinit (abfd, initial_section_id, cleanup);
    372       /* Free bfd_alloc memory too.  If we have matched and preserved
    373 	 a target then the high water mark is that much higher.  */
    374       if (preserve_match.marker)
    375 	high_water = &preserve_match.marker;
    376       else
    377 	high_water = &preserve.marker;
    378       bfd_release (abfd, *high_water);
    379       *high_water = bfd_alloc (abfd, 1);
    380 
    381       /* Change BFD's target temporarily.  */
    382       abfd->xvec = *target;
    383 
    384       if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
    385 	goto err_ret;
    386 
    387       cleanup = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
    388       if (cleanup)
    389 	{
    390 	  int match_priority = abfd->xvec->match_priority;
    391 #if BFD_SUPPORTS_PLUGINS
    392 	  /* If this object can be handled by a plugin, give that the
    393 	     lowest priority; objects both handled by a plugin and
    394 	     with an underlying object format will be claimed
    395 	     separately by the plugin.  */
    396 	  if (*target == &plugin_vec)
    397 	    match_priority = (*target)->match_priority;
    398 #endif
    399 
    400 	  if (abfd->format != bfd_archive
    401 	      || (bfd_has_map (abfd)
    402 		  && bfd_get_error () != bfd_error_wrong_object_format))
    403 	    {
    404 	      /* If this is the default target, accept it, even if
    405 		 other targets might match.  People who want those
    406 		 other targets have to set the GNUTARGET variable.  */
    407 	      if (abfd->xvec == bfd_default_vector[0])
    408 		goto ok_ret;
    409 
    410 	      if (matching_vector)
    411 		matching_vector[match_count] = abfd->xvec;
    412 	      match_count++;
    413 
    414 	      if (match_priority < best_match)
    415 		{
    416 		  best_match = match_priority;
    417 		  best_count = 0;
    418 		}
    419 	      if (match_priority <= best_match)
    420 		{
    421 		  /* This format checks out as ok!  */
    422 		  right_targ = abfd->xvec;
    423 		  best_count++;
    424 		}
    425 	    }
    426 	  else
    427 	    {
    428 	      /* An archive with no armap or objects of the wrong
    429 		 type.  We want this target to match if we get no
    430 		 better matches.  */
    431 	      if (ar_right_targ != bfd_default_vector[0])
    432 		ar_right_targ = *target;
    433 	      if (matching_vector)
    434 		matching_vector[ar_match_index] = *target;
    435 	      ar_match_index++;
    436 	    }
    437 
    438 	  if (preserve_match.marker == NULL)
    439 	    {
    440 	      match_targ = abfd->xvec;
    441 	      if (!bfd_preserve_save (abfd, &preserve_match, cleanup))
    442 		goto err_ret;
    443 	      cleanup = NULL;
    444 	    }
    445 	}
    446     }
    447 
    448   if (best_count == 1)
    449     match_count = 1;
    450 
    451   if (match_count == 0)
    452     {
    453       /* Try partial matches.  */
    454       right_targ = ar_right_targ;
    455 
    456       if (right_targ == bfd_default_vector[0])
    457 	{
    458 	  match_count = 1;
    459 	}
    460       else
    461 	{
    462 	  match_count = ar_match_index - _bfd_target_vector_entries;
    463 
    464 	  if (matching_vector && match_count > 1)
    465 	    memcpy (matching_vector,
    466 		    matching_vector + _bfd_target_vector_entries,
    467 		    sizeof (*matching_vector) * match_count);
    468 	}
    469     }
    470 
    471   /* We have more than one equally good match.  If any of the best
    472      matches is a target in config.bfd targ_defvec or targ_selvecs,
    473      choose it.  */
    474   if (match_count > 1)
    475     {
    476       const bfd_target * const *assoc = bfd_associated_vector;
    477 
    478       while ((right_targ = *assoc++) != NULL)
    479 	{
    480 	  int i = match_count;
    481 
    482 	  while (--i >= 0)
    483 	    if (matching_vector[i] == right_targ
    484 		&& right_targ->match_priority <= best_match)
    485 	      break;
    486 
    487 	  if (i >= 0)
    488 	    {
    489 	      match_count = 1;
    490 	      break;
    491 	    }
    492 	}
    493     }
    494 
    495   /* We still have more than one equally good match, and at least some
    496      of the targets support match priority.  Choose the first of the
    497      best matches.  */
    498   if (matching_vector && match_count > 1 && best_count != match_count)
    499     {
    500       int i;
    501 
    502       for (i = 0; i < match_count; i++)
    503 	{
    504 	  right_targ = matching_vector[i];
    505 	  if (right_targ->match_priority <= best_match)
    506 	    break;
    507 	}
    508       match_count = 1;
    509     }
    510 
    511   /* There is way too much undoing of half-known state here.  We
    512      really shouldn't iterate on live bfd's.  Note that saving the
    513      whole bfd and restoring it would be even worse; the first thing
    514      you notice is that the cached bfd file position gets out of sync.  */
    515   if (preserve_match.marker != NULL)
    516     cleanup = bfd_preserve_restore (abfd, &preserve_match);
    517 
    518   if (match_count == 1)
    519     {
    520       abfd->xvec = right_targ;
    521       /* If we come out of the loop knowing that the last target that
    522 	 matched is the one we want, then ABFD should still be in a usable
    523 	 state (except possibly for XVEC).  This is not just an
    524 	 optimisation.  In the case of plugins a match against the
    525 	 plugin target can result in the bfd being changed such that
    526 	 it no longer matches the plugin target, nor will it match
    527 	 RIGHT_TARG again.  */
    528       if (match_targ != right_targ)
    529 	{
    530 	  bfd_reinit (abfd, initial_section_id, cleanup);
    531 	  bfd_release (abfd, preserve.marker);
    532 	  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
    533 	    goto err_ret;
    534 	  cleanup = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
    535 	  BFD_ASSERT (cleanup != NULL);
    536 	}
    537 
    538     ok_ret:
    539       /* If the file was opened for update, then `output_has_begun'
    540 	 some time ago when the file was created.  Do not recompute
    541 	 sections sizes or alignments in _bfd_set_section_contents.
    542 	 We can not set this flag until after checking the format,
    543 	 because it will interfere with creation of BFD sections.  */
    544       if (abfd->direction == both_direction)
    545 	abfd->output_has_begun = true;
    546 
    547       free (matching_vector);
    548       if (preserve_match.marker != NULL)
    549 	bfd_preserve_finish (abfd, &preserve_match);
    550       bfd_preserve_finish (abfd, &preserve);
    551       bfd_set_error_handler (orig_error_handler);
    552 
    553       struct per_xvec_message **list = _bfd_per_xvec_warn (abfd->xvec, 0);
    554       if (*list)
    555 	print_warnmsg (list);
    556       list = _bfd_per_xvec_warn (NULL, 0);
    557       for (size_t i = 0; i < _bfd_target_vector_entries + 1; i++)
    558 	clear_warnmsg (list++);
    559       --in_check_format;
    560 
    561       /* File position has moved, BTW.  */
    562       return true;
    563     }
    564 
    565   if (match_count == 0)
    566     {
    567     err_unrecog:
    568       bfd_set_error (bfd_error_file_not_recognized);
    569     err_ret:
    570       if (cleanup)
    571 	cleanup (abfd);
    572       abfd->xvec = save_targ;
    573       abfd->format = bfd_unknown;
    574       free (matching_vector);
    575       goto out;
    576     }
    577 
    578   /* Restore original target type and format.  */
    579   abfd->xvec = save_targ;
    580   abfd->format = bfd_unknown;
    581   bfd_set_error (bfd_error_file_ambiguously_recognized);
    582 
    583   if (matching)
    584     {
    585       *matching = (char **) matching_vector;
    586       matching_vector[match_count] = NULL;
    587       /* Return target names.  This is a little nasty.  Maybe we
    588 	 should do another bfd_malloc?  */
    589       while (--match_count >= 0)
    590 	{
    591 	  const char *name = matching_vector[match_count]->name;
    592 	  *(const char **) &matching_vector[match_count] = name;
    593 	}
    594     }
    595   else
    596     free (matching_vector);
    597   if (cleanup)
    598     cleanup (abfd);
    599  out:
    600   if (preserve_match.marker != NULL)
    601     bfd_preserve_finish (abfd, &preserve_match);
    602   bfd_preserve_restore (abfd, &preserve);
    603   bfd_set_error_handler (orig_error_handler);
    604   struct per_xvec_message **list = _bfd_per_xvec_warn (NULL, 0);
    605   struct per_xvec_message **one = NULL;
    606   for (size_t i = 0; i < _bfd_target_vector_entries + 1; i++)
    607     {
    608       if (list[i])
    609 	{
    610 	  if (!one)
    611 	    one = list + i;
    612 	  else
    613 	    {
    614 	      one = NULL;
    615 	      break;
    616 	    }
    617 	}
    618     }
    619   if (one)
    620     print_warnmsg (one);
    621   for (size_t i = 0; i < _bfd_target_vector_entries + 1; i++)
    622     clear_warnmsg (list++);
    623   --in_check_format;
    624   return false;
    625 }
    626 
    627 /*
    628 FUNCTION
    629 	bfd_set_format
    630 
    631 SYNOPSIS
    632 	bool bfd_set_format (bfd *abfd, bfd_format format);
    633 
    634 DESCRIPTION
    635 	This function sets the file format of the BFD @var{abfd} to the
    636 	format @var{format}. If the target set in the BFD does not
    637 	support the format requested, the format is invalid, or the BFD
    638 	is not open for writing, then an error occurs.
    639 */
    640 
    641 bool
    642 bfd_set_format (bfd *abfd, bfd_format format)
    643 {
    644   if (bfd_read_p (abfd)
    645       || (unsigned int) abfd->format >= (unsigned int) bfd_type_end)
    646     {
    647       bfd_set_error (bfd_error_invalid_operation);
    648       return false;
    649     }
    650 
    651   if (abfd->format != bfd_unknown)
    652     return abfd->format == format;
    653 
    654   /* Presume the answer is yes.  */
    655   abfd->format = format;
    656 
    657   if (!BFD_SEND_FMT (abfd, _bfd_set_format, (abfd)))
    658     {
    659       abfd->format = bfd_unknown;
    660       return false;
    661     }
    662 
    663   return true;
    664 }
    665 
    666 /*
    667 FUNCTION
    668 	bfd_format_string
    669 
    670 SYNOPSIS
    671 	const char *bfd_format_string (bfd_format format);
    672 
    673 DESCRIPTION
    674 	Return a pointer to a const string
    675 	<<invalid>>, <<object>>, <<archive>>, <<core>>, or <<unknown>>,
    676 	depending upon the value of @var{format}.
    677 */
    678 
    679 const char *
    680 bfd_format_string (bfd_format format)
    681 {
    682   if (((int) format < (int) bfd_unknown)
    683       || ((int) format >= (int) bfd_type_end))
    684     return "invalid";
    685 
    686   switch (format)
    687     {
    688     case bfd_object:
    689       return "object";		/* Linker/assembler/compiler output.  */
    690     case bfd_archive:
    691       return "archive";		/* Object archive file.  */
    692     case bfd_core:
    693       return "core";		/* Core dump.  */
    694     default:
    695       return "unknown";
    696     }
    697 }
    698