133965Sjdp/* Generic BFD support for file formats.
2218822Sdim   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2002,
3218822Sdim   2003, 2005, 2007 Free Software Foundation, Inc.
433965Sjdp   Written by Cygnus Support.
533965Sjdp
6130561Sobrien   This file is part of BFD, the Binary File Descriptor library.
733965Sjdp
8130561Sobrien   This program is free software; you can redistribute it and/or modify
9130561Sobrien   it under the terms of the GNU General Public License as published by
10130561Sobrien   the Free Software Foundation; either version 2 of the License, or
11130561Sobrien   (at your option) any later version.
1233965Sjdp
13130561Sobrien   This program is distributed in the hope that it will be useful,
14130561Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
15130561Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16130561Sobrien   GNU General Public License for more details.
1733965Sjdp
18130561Sobrien   You should have received a copy of the GNU General Public License
19130561Sobrien   along with this program; if not, write to the Free Software
20218822Sdim   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
2133965Sjdp
2233965Sjdp/*
2333965SjdpSECTION
2433965Sjdp	File formats
2533965Sjdp
2633965Sjdp	A format is a BFD concept of high level file contents type. The
2777298Sobrien	formats supported by BFD are:
2833965Sjdp
2933965Sjdp	o <<bfd_object>>
3033965Sjdp
3133965Sjdp	The BFD may contain data, symbols, relocations and debug info.
3233965Sjdp
3333965Sjdp	o <<bfd_archive>>
3433965Sjdp
3533965Sjdp	The BFD contains other BFDs and an optional index.
3633965Sjdp
3733965Sjdp	o <<bfd_core>>
3833965Sjdp
3933965Sjdp	The BFD contains the result of an executable core dump.
4033965Sjdp
41218822SdimSUBSECTION
42218822Sdim	File format functions
4333965Sjdp*/
4433965Sjdp
45218822Sdim#include "sysdep.h"
4633965Sjdp#include "bfd.h"
4733965Sjdp#include "libbfd.h"
4833965Sjdp
4933965Sjdp/* IMPORT from targets.c.  */
5033965Sjdpextern const size_t _bfd_target_vector_entries;
5133965Sjdp
5233965Sjdp/*
5333965SjdpFUNCTION
5433965Sjdp	bfd_check_format
5533965Sjdp
5633965SjdpSYNOPSIS
57130561Sobrien	bfd_boolean bfd_check_format (bfd *abfd, bfd_format format);
5833965Sjdp
5933965SjdpDESCRIPTION
6033965Sjdp	Verify if the file attached to the BFD @var{abfd} is compatible
6133965Sjdp	with the format @var{format} (i.e., one of <<bfd_object>>,
6233965Sjdp	<<bfd_archive>> or <<bfd_core>>).
6333965Sjdp
6433965Sjdp	If the BFD has been set to a specific target before the
6533965Sjdp	call, only the named target and format combination is
6633965Sjdp	checked. If the target has not been set, or has been set to
6733965Sjdp	<<default>>, then all the known target backends is
6833965Sjdp	interrogated to determine a match.  If the default target
6933965Sjdp	matches, it is used.  If not, exactly one target must recognize
7033965Sjdp	the file, or an error results.
7133965Sjdp
72130561Sobrien	The function returns <<TRUE>> on success, otherwise <<FALSE>>
7377298Sobrien	with one of the following error codes:
7433965Sjdp
7533965Sjdp	o <<bfd_error_invalid_operation>> -
7633965Sjdp	if <<format>> is not one of <<bfd_object>>, <<bfd_archive>> or
7733965Sjdp	<<bfd_core>>.
7833965Sjdp
7933965Sjdp	o <<bfd_error_system_call>> -
8033965Sjdp	if an error occured during a read - even some file mismatches
8133965Sjdp	can cause bfd_error_system_calls.
8233965Sjdp
8333965Sjdp	o <<file_not_recognised>> -
8433965Sjdp	none of the backends recognised the file format.
8533965Sjdp
8633965Sjdp	o <<bfd_error_file_ambiguously_recognized>> -
8733965Sjdp	more than one backend recognised the file format.
8833965Sjdp*/
8933965Sjdp
90130561Sobrienbfd_boolean
91130561Sobrienbfd_check_format (bfd *abfd, bfd_format format)
9233965Sjdp{
9333965Sjdp  return bfd_check_format_matches (abfd, format, NULL);
9433965Sjdp}
9533965Sjdp
9633965Sjdp/*
9733965SjdpFUNCTION
9833965Sjdp	bfd_check_format_matches
9933965Sjdp
10033965SjdpSYNOPSIS
101130561Sobrien	bfd_boolean bfd_check_format_matches
102130561Sobrien	  (bfd *abfd, bfd_format format, char ***matching);
10333965Sjdp
10433965SjdpDESCRIPTION
105130561Sobrien	Like <<bfd_check_format>>, except when it returns FALSE with
10633965Sjdp	<<bfd_errno>> set to <<bfd_error_file_ambiguously_recognized>>.  In that
10733965Sjdp	case, if @var{matching} is not NULL, it will be filled in with
10833965Sjdp	a NULL-terminated list of the names of the formats that matched,
10933965Sjdp	allocated with <<malloc>>.
11033965Sjdp	Then the user may choose a format and try again.
11133965Sjdp
11233965Sjdp	When done with the list that @var{matching} points to, the caller
11377298Sobrien	should free it.
11433965Sjdp*/
11533965Sjdp
116130561Sobrienbfd_boolean
117130561Sobrienbfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
11833965Sjdp{
11960484Sobrien  extern const bfd_target binary_vec;
120130561Sobrien  const bfd_target * const *target;
121130561Sobrien  const bfd_target **matching_vector = NULL;
122130561Sobrien  const bfd_target *save_targ, *right_targ, *ar_right_targ;
12333965Sjdp  int match_count;
12489857Sobrien  int ar_match_index;
12533965Sjdp
12689857Sobrien  if (!bfd_read_p (abfd)
12789857Sobrien      || (unsigned int) abfd->format >= (unsigned int) bfd_type_end)
12877298Sobrien    {
12977298Sobrien      bfd_set_error (bfd_error_invalid_operation);
130130561Sobrien      return FALSE;
13177298Sobrien    }
13233965Sjdp
13333965Sjdp  if (abfd->format != bfd_unknown)
134130561Sobrien    return abfd->format == format;
13533965Sjdp
13677298Sobrien  /* Since the target type was defaulted, check them
13733965Sjdp     all in the hope that one will be uniquely recognized.  */
13833965Sjdp  save_targ = abfd->xvec;
13933965Sjdp  match_count = 0;
14089857Sobrien  ar_match_index = _bfd_target_vector_entries;
14177298Sobrien
14233965Sjdp  if (matching)
14333965Sjdp    {
14489857Sobrien      bfd_size_type amt;
14589857Sobrien
14689857Sobrien      *matching = NULL;
147130561Sobrien      amt = sizeof (*matching_vector) * 2 * _bfd_target_vector_entries;
148130561Sobrien      matching_vector = bfd_malloc (amt);
14933965Sjdp      if (!matching_vector)
150130561Sobrien	return FALSE;
15133965Sjdp    }
15277298Sobrien
15333965Sjdp  right_targ = 0;
15489857Sobrien  ar_right_targ = 0;
15533965Sjdp
15677298Sobrien  /* Presume the answer is yes.  */
15733965Sjdp  abfd->format = format;
15833965Sjdp
15933965Sjdp  /* If the target type was explicitly specified, just check that target.  */
16077298Sobrien  if (!abfd->target_defaulted)
16177298Sobrien    {
16289857Sobrien      if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)	/* rewind! */
163130561Sobrien	{
164130561Sobrien	  if (matching)
165130561Sobrien	    free (matching_vector);
166130561Sobrien	  return FALSE;
167130561Sobrien	}
16833965Sjdp
16977298Sobrien      right_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
17077298Sobrien
17177298Sobrien      if (right_targ)
17277298Sobrien	{
17377298Sobrien	  abfd->xvec = right_targ;	/* Set the target as returned.  */
17477298Sobrien
17577298Sobrien	  if (matching)
17677298Sobrien	    free (matching_vector);
17777298Sobrien
178218822Sdim	  /* If the file was opened for update, then `output_has_begun'
179218822Sdim	     some time ago when the file was created.  Do not recompute
180218822Sdim	     sections sizes or alignments in _bfd_set_section_contents.
181218822Sdim	     We can not set this flag until after checking the format,
182218822Sdim	     because it will interfere with creation of BFD sections.  */
183218822Sdim	  if (abfd->direction == both_direction)
184218822Sdim	    abfd->output_has_begun = TRUE;
185218822Sdim
186130561Sobrien	  return TRUE;			/* File position has moved, BTW.  */
18777298Sobrien	}
18877298Sobrien
18977298Sobrien      /* For a long time the code has dropped through to check all
19077298Sobrien	 targets if the specified target was wrong.  I don't know why,
19177298Sobrien	 and I'm reluctant to change it.  However, in the case of an
19277298Sobrien	 archive, it can cause problems.  If the specified target does
19377298Sobrien	 not permit archives (e.g., the binary target), then we should
19477298Sobrien	 not allow some other target to recognize it as an archive, but
19577298Sobrien	 should instead allow the specified target to recognize it as an
19677298Sobrien	 object.  When I first made this change, it broke the PE target,
19777298Sobrien	 because the specified pei-i386 target did not recognize the
19877298Sobrien	 actual pe-i386 archive.  Since there may be other problems of
19977298Sobrien	 this sort, I changed this test to check only for the binary
20077298Sobrien	 target.  */
20177298Sobrien      if (format == bfd_archive && save_targ == &binary_vec)
20277298Sobrien	{
20377298Sobrien	  abfd->xvec = save_targ;
20477298Sobrien	  abfd->format = bfd_unknown;
20577298Sobrien
20677298Sobrien	  if (matching)
20777298Sobrien	    free (matching_vector);
20877298Sobrien
20977298Sobrien	  bfd_set_error (bfd_error_file_not_recognized);
21077298Sobrien
211130561Sobrien	  return FALSE;
21277298Sobrien	}
21333965Sjdp    }
21460484Sobrien
21577298Sobrien  for (target = bfd_target_vector; *target != NULL; target++)
21677298Sobrien    {
21777298Sobrien      const bfd_target *temp;
21889857Sobrien      bfd_error_type err;
21960484Sobrien
220218822Sdim      /* Don't check the default target twice.  */
221218822Sdim      if (*target == &binary_vec
222218822Sdim	  || (!abfd->target_defaulted && *target == save_targ))
22377298Sobrien	continue;
22477298Sobrien
225130561Sobrien      abfd->xvec = *target;	/* Change BFD's target temporarily.  */
22677298Sobrien
22789857Sobrien      if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
228130561Sobrien	{
229130561Sobrien	  if (matching)
230130561Sobrien	    free (matching_vector);
231130561Sobrien	  return FALSE;
232130561Sobrien	}
23333965Sjdp
23477298Sobrien      /* If _bfd_check_format neglects to set bfd_error, assume
23577298Sobrien	 bfd_error_wrong_format.  We didn't used to even pay any
23677298Sobrien	 attention to bfd_error, so I suspect that some
23777298Sobrien	 _bfd_check_format might have this problem.  */
23877298Sobrien      bfd_set_error (bfd_error_wrong_format);
23933965Sjdp
24077298Sobrien      temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
24133965Sjdp
24277298Sobrien      if (temp)
243130561Sobrien	{
244130561Sobrien	  /* This format checks out as ok!  */
24577298Sobrien	  right_targ = temp;
24677298Sobrien
24777298Sobrien	  /* If this is the default target, accept it, even if other
24877298Sobrien	     targets might match.  People who want those other targets
24977298Sobrien	     have to set the GNUTARGET variable.  */
25077298Sobrien	  if (temp == bfd_default_vector[0])
25177298Sobrien	    {
25277298Sobrien	      match_count = 1;
25377298Sobrien	      break;
25477298Sobrien	    }
25589857Sobrien
25689857Sobrien	  if (matching)
257130561Sobrien	    matching_vector[match_count] = temp;
25889857Sobrien
25989857Sobrien	  match_count++;
26033965Sjdp	}
26189857Sobrien      else if ((err = bfd_get_error ()) == bfd_error_wrong_object_format
26289857Sobrien	       || err == bfd_error_file_ambiguously_recognized)
26377298Sobrien	{
26489857Sobrien	  /* An archive with objects of the wrong type, or an
26589857Sobrien	     ambiguous match.  We want this target to match if we get
26689857Sobrien	     no better matches.  */
26789857Sobrien	  if (ar_right_targ != bfd_default_vector[0])
26889857Sobrien	    ar_right_targ = *target;
26989857Sobrien	  if (matching)
270130561Sobrien	    matching_vector[ar_match_index] = *target;
27189857Sobrien	  ar_match_index++;
27289857Sobrien	}
27389857Sobrien      else if (err != bfd_error_wrong_format)
27489857Sobrien	{
27577298Sobrien	  abfd->xvec = save_targ;
27677298Sobrien	  abfd->format = bfd_unknown;
27777298Sobrien
27889857Sobrien	  if (matching)
27977298Sobrien	    free (matching_vector);
28077298Sobrien
281130561Sobrien	  return FALSE;
28277298Sobrien	}
28377298Sobrien    }
28477298Sobrien
28589857Sobrien  if (match_count == 0)
28689857Sobrien    {
28789857Sobrien      /* Try partial matches.  */
28889857Sobrien      right_targ = ar_right_targ;
289130561Sobrien
29089857Sobrien      if (right_targ == bfd_default_vector[0])
29189857Sobrien	{
29289857Sobrien	  match_count = 1;
29389857Sobrien	}
29489857Sobrien      else
29589857Sobrien	{
29689857Sobrien	  match_count = ar_match_index - _bfd_target_vector_entries;
297130561Sobrien
29889857Sobrien	  if (matching && match_count > 1)
299130561Sobrien	    memcpy (matching_vector,
300130561Sobrien		    matching_vector + _bfd_target_vector_entries,
301130561Sobrien		    sizeof (*matching_vector) * match_count);
302130561Sobrien	}
303130561Sobrien    }
304130561Sobrien
305130561Sobrien  if (match_count > 1
306130561Sobrien      && bfd_associated_vector != NULL
307130561Sobrien      && matching)
308130561Sobrien    {
309130561Sobrien      const bfd_target * const *assoc = bfd_associated_vector;
310130561Sobrien
311130561Sobrien      while ((right_targ = *assoc++) != NULL)
312130561Sobrien	{
313130561Sobrien	  int i = match_count;
314130561Sobrien
315130561Sobrien	  while (--i >= 0)
316130561Sobrien	    if (matching_vector[i] == right_targ)
317130561Sobrien	      break;
318130561Sobrien
319130561Sobrien	  if (i >= 0)
32089857Sobrien	    {
321130561Sobrien	      match_count = 1;
322130561Sobrien	      break;
32389857Sobrien	    }
32489857Sobrien	}
32589857Sobrien    }
32689857Sobrien
32777298Sobrien  if (match_count == 1)
32877298Sobrien    {
32977298Sobrien      abfd->xvec = right_targ;		/* Change BFD's target permanently.  */
33077298Sobrien
33177298Sobrien      if (matching)
33233965Sjdp	free (matching_vector);
33377298Sobrien
334218822Sdim      /* If the file was opened for update, then `output_has_begun'
335218822Sdim	 some time ago when the file was created.  Do not recompute
336218822Sdim	 sections sizes or alignments in _bfd_set_section_contents.
337218822Sdim	 We can not set this flag until after checking the format,
338218822Sdim	 because it will interfere with creation of BFD sections.  */
339218822Sdim      if (abfd->direction == both_direction)
340218822Sdim	abfd->output_has_begun = TRUE;
341218822Sdim
342130561Sobrien      return TRUE;			/* File position has moved, BTW.  */
34333965Sjdp    }
34433965Sjdp
34577298Sobrien  abfd->xvec = save_targ;		/* Restore original target type.  */
34677298Sobrien  abfd->format = bfd_unknown;		/* Restore original format.  */
34733965Sjdp
34833965Sjdp  if (match_count == 0)
34933965Sjdp    {
35033965Sjdp      bfd_set_error (bfd_error_file_not_recognized);
35177298Sobrien
35233965Sjdp      if (matching)
35333965Sjdp	free (matching_vector);
35433965Sjdp    }
35533965Sjdp  else
35689857Sobrien    {
35789857Sobrien      bfd_set_error (bfd_error_file_ambiguously_recognized);
35877298Sobrien
35989857Sobrien      if (matching)
36089857Sobrien	{
361130561Sobrien	  *matching = (char **) matching_vector;
36289857Sobrien	  matching_vector[match_count] = NULL;
363130561Sobrien	  /* Return target names.  This is a little nasty.  Maybe we
364130561Sobrien	     should do another bfd_malloc?  */
365130561Sobrien	  while (--match_count >= 0)
366130561Sobrien	    {
367130561Sobrien	      const char *name = matching_vector[match_count]->name;
368130561Sobrien	      *(const char **) &matching_vector[match_count] = name;
369130561Sobrien	    }
37089857Sobrien	}
37189857Sobrien    }
37289857Sobrien
373130561Sobrien  return FALSE;
37433965Sjdp}
37533965Sjdp
37633965Sjdp/*
37733965SjdpFUNCTION
37833965Sjdp	bfd_set_format
37933965Sjdp
38033965SjdpSYNOPSIS
381130561Sobrien	bfd_boolean bfd_set_format (bfd *abfd, bfd_format format);
38233965Sjdp
38333965SjdpDESCRIPTION
38433965Sjdp	This function sets the file format of the BFD @var{abfd} to the
38533965Sjdp	format @var{format}. If the target set in the BFD does not
38633965Sjdp	support the format requested, the format is invalid, or the BFD
38733965Sjdp	is not open for writing, then an error occurs.
38833965Sjdp*/
38933965Sjdp
390130561Sobrienbfd_boolean
391130561Sobrienbfd_set_format (bfd *abfd, bfd_format format)
39233965Sjdp{
39389857Sobrien  if (bfd_read_p (abfd)
39489857Sobrien      || (unsigned int) abfd->format >= (unsigned int) bfd_type_end)
39577298Sobrien    {
39677298Sobrien      bfd_set_error (bfd_error_invalid_operation);
397130561Sobrien      return FALSE;
39877298Sobrien    }
39933965Sjdp
40033965Sjdp  if (abfd->format != bfd_unknown)
401130561Sobrien    return abfd->format == format;
40233965Sjdp
40377298Sobrien  /* Presume the answer is yes.  */
40433965Sjdp  abfd->format = format;
40533965Sjdp
40677298Sobrien  if (!BFD_SEND_FMT (abfd, _bfd_set_format, (abfd)))
40777298Sobrien    {
40877298Sobrien      abfd->format = bfd_unknown;
409130561Sobrien      return FALSE;
41077298Sobrien    }
41133965Sjdp
412130561Sobrien  return TRUE;
41333965Sjdp}
41433965Sjdp
41533965Sjdp/*
41633965SjdpFUNCTION
41733965Sjdp	bfd_format_string
41833965Sjdp
41933965SjdpSYNOPSIS
420130561Sobrien	const char *bfd_format_string (bfd_format format);
42133965Sjdp
42233965SjdpDESCRIPTION
42333965Sjdp	Return a pointer to a const string
42433965Sjdp	<<invalid>>, <<object>>, <<archive>>, <<core>>, or <<unknown>>,
42533965Sjdp	depending upon the value of @var{format}.
42633965Sjdp*/
42733965Sjdp
42889857Sobrienconst char *
429130561Sobrienbfd_format_string (bfd_format format)
43033965Sjdp{
431130561Sobrien  if (((int) format < (int) bfd_unknown)
432130561Sobrien      || ((int) format >= (int) bfd_type_end))
43333965Sjdp    return "invalid";
43477298Sobrien
43577298Sobrien  switch (format)
43677298Sobrien    {
43777298Sobrien    case bfd_object:
438130561Sobrien      return "object";		/* Linker/assembler/compiler output.  */
43977298Sobrien    case bfd_archive:
44077298Sobrien      return "archive";		/* Object archive file.  */
44177298Sobrien    case bfd_core:
44277298Sobrien      return "core";		/* Core dump.  */
44377298Sobrien    default:
44477298Sobrien      return "unknown";
44577298Sobrien    }
44633965Sjdp}
447