format.c revision 60484
1/* Generic BFD support for file formats.
2   Copyright (C) 1990, 91, 92, 93, 94, 95, 1999 Free Software Foundation, Inc.
3   Written by Cygnus Support.
4
5This file is part of BFD, the Binary File Descriptor library.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21/*
22SECTION
23	File formats
24
25	A format is a BFD concept of high level file contents type. The
26	formats supported by BFD are:
27
28	o <<bfd_object>>
29
30	The BFD may contain data, symbols, relocations and debug info.
31
32	o <<bfd_archive>>
33
34	The BFD contains other BFDs and an optional index.
35
36	o <<bfd_core>>
37
38	The BFD contains the result of an executable core dump.
39
40
41*/
42
43#include "bfd.h"
44#include "sysdep.h"
45#include "libbfd.h"
46
47/* IMPORT from targets.c.  */
48extern const size_t _bfd_target_vector_entries;
49
50/*
51FUNCTION
52	bfd_check_format
53
54SYNOPSIS
55	boolean bfd_check_format(bfd *abfd, bfd_format format);
56
57DESCRIPTION
58	Verify if the file attached to the BFD @var{abfd} is compatible
59	with the format @var{format} (i.e., one of <<bfd_object>>,
60	<<bfd_archive>> or <<bfd_core>>).
61
62	If the BFD has been set to a specific target before the
63	call, only the named target and format combination is
64	checked. If the target has not been set, or has been set to
65	<<default>>, then all the known target backends is
66	interrogated to determine a match.  If the default target
67	matches, it is used.  If not, exactly one target must recognize
68	the file, or an error results.
69
70	The function returns <<true>> on success, otherwise <<false>>
71	with one of the following error codes:
72
73	o <<bfd_error_invalid_operation>> -
74	if <<format>> is not one of <<bfd_object>>, <<bfd_archive>> or
75	<<bfd_core>>.
76
77	o <<bfd_error_system_call>> -
78	if an error occured during a read - even some file mismatches
79	can cause bfd_error_system_calls.
80
81	o <<file_not_recognised>> -
82	none of the backends recognised the file format.
83
84	o <<bfd_error_file_ambiguously_recognized>> -
85	more than one backend recognised the file format.
86*/
87
88boolean
89bfd_check_format (abfd, format)
90     bfd *abfd;
91     bfd_format format;
92{
93  return bfd_check_format_matches (abfd, format, NULL);
94}
95
96/*
97FUNCTION
98	bfd_check_format_matches
99
100SYNOPSIS
101	boolean bfd_check_format_matches(bfd *abfd, bfd_format format, char ***matching);
102
103DESCRIPTION
104	Like <<bfd_check_format>>, except when it returns false with
105	<<bfd_errno>> set to <<bfd_error_file_ambiguously_recognized>>.  In that
106	case, if @var{matching} is not NULL, it will be filled in with
107	a NULL-terminated list of the names of the formats that matched,
108	allocated with <<malloc>>.
109	Then the user may choose a format and try again.
110
111	When done with the list that @var{matching} points to, the caller
112	should free it.
113*/
114
115boolean
116bfd_check_format_matches (abfd, format, matching)
117     bfd *abfd;
118     bfd_format format;
119     char ***matching;
120{
121  extern const bfd_target binary_vec;
122  const bfd_target * const *target, *save_targ, *right_targ;
123  char **matching_vector = NULL;
124  int match_count;
125
126  if (!bfd_read_p (abfd) ||
127      ((int)(abfd->format) < (int)bfd_unknown) ||
128      ((int)(abfd->format) >= (int)bfd_type_end)) {
129    bfd_set_error (bfd_error_invalid_operation);
130    return false;
131  }
132
133  if (abfd->format != bfd_unknown)
134    return (abfd->format == format)? true: false;
135
136
137  /* Since the target type was defaulted, check them
138     all in the hope that one will be uniquely recognized.  */
139
140  save_targ = abfd->xvec;
141  match_count = 0;
142  if (matching)
143    {
144      matching_vector =
145	(char **) bfd_malloc (sizeof (char *) *
146			      (_bfd_target_vector_entries + 1));
147      if (!matching_vector)
148	return false;
149      matching_vector[0] = NULL;
150      *matching = matching_vector;
151    }
152  right_targ = 0;
153
154
155  /* presume the answer is yes */
156  abfd->format = format;
157
158  /* If the target type was explicitly specified, just check that target.  */
159
160  if (!abfd->target_defaulted) {
161    if (bfd_seek (abfd, (file_ptr)0, SEEK_SET) != 0)	/* rewind! */
162      return false;
163    right_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
164    if (right_targ) {
165      abfd->xvec = right_targ;		/* Set the target as returned */
166      if (matching)
167	free (matching_vector);
168      return true;			/* File position has moved, BTW */
169    }
170
171    /* For a long time the code has dropped through to check all
172       targets if the specified target was wrong.  I don't know why,
173       and I'm reluctant to change it.  However, in the case of an
174       archive, it can cause problems.  If the specified target does
175       not permit archives (e.g., the binary target), then we should
176       not allow some other target to recognize it as an archive, but
177       should instead allow the specified target to recognize it as an
178       object.  When I first made this change, it broke the PE target,
179       because the specified pei-i386 target did not recognize the
180       actual pe-i386 archive.  Since there may be other problems of
181       this sort, I changed this test to check only for the binary
182       target.  */
183
184    if (format == bfd_archive && save_targ == &binary_vec)
185      {
186	abfd->xvec = save_targ;
187	abfd->format = bfd_unknown;
188	if (matching)
189	  free (matching_vector);
190	bfd_set_error (bfd_error_file_not_recognized);
191	return false;
192      }
193  }
194
195  for (target = bfd_target_vector; *target != NULL; target++) {
196    const bfd_target *temp;
197
198    if (*target == &binary_vec)
199      continue;
200
201    abfd->xvec = *target;	/* Change BFD's target temporarily */
202    if (bfd_seek (abfd, (file_ptr)0, SEEK_SET) != 0)
203      return false;
204    /* If _bfd_check_format neglects to set bfd_error, assume bfd_error_wrong_format.
205       We didn't used to even pay any attention to bfd_error, so I suspect
206       that some _bfd_check_format might have this problem.  */
207    bfd_set_error (bfd_error_wrong_format);
208    temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
209    if (temp) {				/* This format checks out as ok! */
210      right_targ = temp;
211      if (matching)
212	{
213	  matching_vector[match_count] = temp->name;
214	  matching_vector[match_count + 1] = NULL;
215	}
216      match_count++;
217      /* If this is the default target, accept it, even if other targets
218	 might match.  People who want those other targets have to set
219	 the GNUTARGET variable.  */
220      if (temp == bfd_default_vector[0])
221	{
222	  if (matching)
223	    {
224	      matching_vector[0] = temp->name;
225	      matching_vector[1] = NULL;
226	    }
227	  match_count = 1;
228	  break;
229	}
230#ifdef GNU960
231      /* Big- and little-endian b.out archives look the same, but it doesn't
232       * matter: there is no difference in their headers, and member file byte
233       * orders will (I hope) be handled appropriately by bfd.  Ditto for big
234       * and little coff archives.  And the 4 coff/b.out object formats are
235       * unambiguous.  So accept the first match we find.
236       */
237      break;
238#endif
239    } else if (bfd_get_error () != bfd_error_wrong_format) {
240      abfd->xvec = save_targ;
241      abfd->format = bfd_unknown;
242      if (matching && bfd_get_error () != bfd_error_file_ambiguously_recognized)
243	free (matching_vector);
244      return false;
245    }
246  }
247
248  if (match_count == 1) {
249    abfd->xvec = right_targ;		/* Change BFD's target permanently */
250    if (matching)
251      free (matching_vector);
252    return true;			/* File position has moved, BTW */
253  }
254
255  abfd->xvec = save_targ;		/* Restore original target type */
256  abfd->format = bfd_unknown;		/* Restore original format */
257  if (match_count == 0)
258    {
259      bfd_set_error (bfd_error_file_not_recognized);
260      if (matching)
261	free (matching_vector);
262    }
263  else
264    bfd_set_error (bfd_error_file_ambiguously_recognized);
265  return false;
266}
267
268/*
269FUNCTION
270	bfd_set_format
271
272SYNOPSIS
273	boolean bfd_set_format(bfd *abfd, bfd_format format);
274
275DESCRIPTION
276	This function sets the file format of the BFD @var{abfd} to the
277	format @var{format}. If the target set in the BFD does not
278	support the format requested, the format is invalid, or the BFD
279	is not open for writing, then an error occurs.
280
281*/
282
283boolean
284bfd_set_format (abfd, format)
285     bfd *abfd;
286     bfd_format format;
287{
288
289  if (bfd_read_p (abfd) ||
290      ((int)abfd->format < (int)bfd_unknown) ||
291      ((int)abfd->format >= (int)bfd_type_end)) {
292    bfd_set_error (bfd_error_invalid_operation);
293    return false;
294  }
295
296  if (abfd->format != bfd_unknown)
297    return (abfd->format == format) ? true:false;
298
299  /* presume the answer is yes */
300  abfd->format = format;
301
302  if (!BFD_SEND_FMT (abfd, _bfd_set_format, (abfd))) {
303    abfd->format = bfd_unknown;
304    return false;
305  }
306
307  return true;
308}
309
310
311/*
312FUNCTION
313	bfd_format_string
314
315SYNOPSIS
316	CONST char *bfd_format_string(bfd_format format);
317
318DESCRIPTION
319	Return a pointer to a const string
320	<<invalid>>, <<object>>, <<archive>>, <<core>>, or <<unknown>>,
321	depending upon the value of @var{format}.
322*/
323
324CONST char *
325bfd_format_string (format)
326     bfd_format format;
327{
328  if (((int)format <(int) bfd_unknown)
329      || ((int)format >=(int) bfd_type_end))
330    return "invalid";
331
332  switch (format) {
333  case bfd_object:
334    return "object";		/* linker/assember/compiler output */
335  case bfd_archive:
336    return "archive";		/* object archive file */
337  case bfd_core:
338    return "core";		/* core dump */
339  default:
340    return "unknown";
341  }
342}
343