Change embedded documentation to use consistent indentation and to split up
[external/binutils.git] / bfd / format.c
1 /* Generic BFD support for file formats.
2    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2002, 2003
3    Free Software Foundation, Inc.
4    Written by Cygnus Support.
5
6    This file is part of BFD, the Binary File Descriptor library.
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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21
22 /*
23 SECTION
24         File formats
25
26         A format is a BFD concept of high level file contents type. The
27         formats supported by BFD are:
28
29         o <<bfd_object>>
30
31         The BFD may contain data, symbols, relocations and debug info.
32
33         o <<bfd_archive>>
34
35         The BFD contains other BFDs and an optional index.
36
37         o <<bfd_core>>
38
39         The BFD contains the result of an executable core dump.
40
41 */
42
43 #include "bfd.h"
44 #include "sysdep.h"
45 #include "libbfd.h"
46
47 /* IMPORT from targets.c.  */
48 extern const size_t _bfd_target_vector_entries;
49
50 /*
51 FUNCTION
52         bfd_check_format
53
54 SYNOPSIS
55         bfd_boolean bfd_check_format (bfd *abfd, bfd_format format);
56
57 DESCRIPTION
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
88 bfd_boolean
89 bfd_check_format (abfd, format)
90      bfd *abfd;
91      bfd_format format;
92 {
93   return bfd_check_format_matches (abfd, format, NULL);
94 }
95
96 /*
97 FUNCTION
98         bfd_check_format_matches
99
100 SYNOPSIS
101         bfd_boolean bfd_check_format_matches (bfd *abfd, bfd_format format,
102                                               char ***matching);
103
104 DESCRIPTION
105         Like <<bfd_check_format>>, except when it returns FALSE with
106         <<bfd_errno>> set to <<bfd_error_file_ambiguously_recognized>>.  In that
107         case, if @var{matching} is not NULL, it will be filled in with
108         a NULL-terminated list of the names of the formats that matched,
109         allocated with <<malloc>>.
110         Then the user may choose a format and try again.
111
112         When done with the list that @var{matching} points to, the caller
113         should free it.
114 */
115
116 bfd_boolean
117 bfd_check_format_matches (abfd, format, matching)
118      bfd *abfd;
119      bfd_format format;
120      char ***matching;
121 {
122   extern const bfd_target binary_vec;
123   const bfd_target * const *target;
124   const bfd_target **matching_vector = NULL;
125   const bfd_target *save_targ, *right_targ, *ar_right_targ;
126   int match_count;
127   int ar_match_index;
128
129   if (!bfd_read_p (abfd)
130       || (unsigned int) abfd->format >= (unsigned int) bfd_type_end)
131     {
132       bfd_set_error (bfd_error_invalid_operation);
133       return FALSE;
134     }
135
136   if (abfd->format != bfd_unknown)
137     return abfd->format == format;
138
139   /* Since the target type was defaulted, check them
140      all in the hope that one will be uniquely recognized.  */
141   save_targ = abfd->xvec;
142   match_count = 0;
143   ar_match_index = _bfd_target_vector_entries;
144
145   if (matching)
146     {
147       bfd_size_type amt;
148
149       *matching = NULL;
150       amt = sizeof (*matching_vector) * 2 * _bfd_target_vector_entries;
151       matching_vector = (const bfd_target **) bfd_malloc (amt);
152       if (!matching_vector)
153         return FALSE;
154     }
155
156   right_targ = 0;
157   ar_right_targ = 0;
158
159   /* Presume the answer is yes.  */
160   abfd->format = format;
161
162   /* If the target type was explicitly specified, just check that target.  */
163   if (!abfd->target_defaulted)
164     {
165       if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) /* rewind! */
166         return FALSE;
167
168       right_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
169
170       if (right_targ)
171         {
172           abfd->xvec = right_targ;      /* Set the target as returned.  */
173
174           if (matching)
175             free ((PTR) matching_vector);
176
177           return TRUE;                  /* File position has moved, BTW.  */
178         }
179
180       /* For a long time the code has dropped through to check all
181          targets if the specified target was wrong.  I don't know why,
182          and I'm reluctant to change it.  However, in the case of an
183          archive, it can cause problems.  If the specified target does
184          not permit archives (e.g., the binary target), then we should
185          not allow some other target to recognize it as an archive, but
186          should instead allow the specified target to recognize it as an
187          object.  When I first made this change, it broke the PE target,
188          because the specified pei-i386 target did not recognize the
189          actual pe-i386 archive.  Since there may be other problems of
190          this sort, I changed this test to check only for the binary
191          target.  */
192       if (format == bfd_archive && save_targ == &binary_vec)
193         {
194           abfd->xvec = save_targ;
195           abfd->format = bfd_unknown;
196
197           if (matching)
198             free ((PTR) matching_vector);
199
200           bfd_set_error (bfd_error_file_not_recognized);
201
202           return FALSE;
203         }
204     }
205
206   for (target = bfd_target_vector; *target != NULL; target++)
207     {
208       const bfd_target *temp;
209       bfd_error_type err;
210
211       if (*target == &binary_vec)
212         continue;
213
214       abfd->xvec = *target;     /* Change BFD's target temporarily.  */
215
216       if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
217         return FALSE;
218
219       /* If _bfd_check_format neglects to set bfd_error, assume
220          bfd_error_wrong_format.  We didn't used to even pay any
221          attention to bfd_error, so I suspect that some
222          _bfd_check_format might have this problem.  */
223       bfd_set_error (bfd_error_wrong_format);
224
225       temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
226
227       if (temp)
228         {
229           /* This format checks out as ok!  */
230           right_targ = temp;
231
232           /* If this is the default target, accept it, even if other
233              targets might match.  People who want those other targets
234              have to set the GNUTARGET variable.  */
235           if (temp == bfd_default_vector[0])
236             {
237               match_count = 1;
238               break;
239             }
240
241           if (matching)
242             matching_vector[match_count] = temp;
243
244           match_count++;
245
246 #ifdef GNU960
247           /* Big- and little-endian b.out archives look the same, but it
248              doesn't matter: there is no difference in their headers, and
249              member file byte orders will (I hope) be handled appropriately
250              by bfd.  Ditto for big and little coff archives.  And the 4
251              coff/b.out object formats are unambiguous.  So accept the
252              first match we find.  */
253           break;
254 #endif
255         }
256       else if ((err = bfd_get_error ()) == bfd_error_wrong_object_format
257                || err == bfd_error_file_ambiguously_recognized)
258         {
259           /* An archive with objects of the wrong type, or an
260              ambiguous match.  We want this target to match if we get
261              no better matches.  */
262           if (ar_right_targ != bfd_default_vector[0])
263             ar_right_targ = *target;
264           if (matching)
265             matching_vector[ar_match_index] = *target;
266           ar_match_index++;
267         }
268       else if (err != bfd_error_wrong_format)
269         {
270           abfd->xvec = save_targ;
271           abfd->format = bfd_unknown;
272
273           if (matching)
274             free ((PTR) matching_vector);
275
276           return FALSE;
277         }
278     }
279
280   if (match_count == 0)
281     {
282       /* Try partial matches.  */
283       right_targ = ar_right_targ;
284
285       if (right_targ == bfd_default_vector[0])
286         {
287           match_count = 1;
288         }
289       else
290         {
291           match_count = ar_match_index - _bfd_target_vector_entries;
292
293           if (matching && match_count > 1)
294             memcpy (matching_vector,
295                     matching_vector + _bfd_target_vector_entries,
296                     sizeof (*matching_vector) * match_count);
297         }
298     }
299
300   if (match_count > 1 && bfd_associated_vector != NULL)
301     {
302       const bfd_target * const *assoc = bfd_associated_vector;
303
304       while ((right_targ = *assoc++) != NULL)
305         {
306           int i = match_count;
307
308           while (--i >= 0)
309             if (matching_vector[i] == right_targ)
310               break;
311
312           if (i >= 0)
313             {
314               match_count = 1;
315               break;
316             }
317         }
318     }
319
320   if (match_count == 1)
321     {
322       abfd->xvec = right_targ;          /* Change BFD's target permanently.  */
323
324       if (matching)
325         free ((PTR) matching_vector);
326
327       return TRUE;                      /* File position has moved, BTW.  */
328     }
329
330   abfd->xvec = save_targ;               /* Restore original target type.  */
331   abfd->format = bfd_unknown;           /* Restore original format.  */
332
333   if (match_count == 0)
334     {
335       bfd_set_error (bfd_error_file_not_recognized);
336
337       if (matching)
338         free ((PTR) matching_vector);
339     }
340   else
341     {
342       bfd_set_error (bfd_error_file_ambiguously_recognized);
343
344       if (matching)
345         {
346           *matching = (char **) matching_vector;
347           matching_vector[match_count] = NULL;
348           /* Return target names.  This is a little nasty.  Maybe we
349              should do another bfd_malloc?  */
350           while (--match_count >= 0)
351             {
352               const char *name = matching_vector[match_count]->name;
353               *(const char **) &matching_vector[match_count] = name;
354             }
355         }
356     }
357
358   return FALSE;
359 }
360
361 /*
362 FUNCTION
363         bfd_set_format
364
365 SYNOPSIS
366         bfd_boolean bfd_set_format (bfd *abfd, bfd_format format);
367
368 DESCRIPTION
369         This function sets the file format of the BFD @var{abfd} to the
370         format @var{format}. If the target set in the BFD does not
371         support the format requested, the format is invalid, or the BFD
372         is not open for writing, then an error occurs.
373 */
374
375 bfd_boolean
376 bfd_set_format (abfd, format)
377      bfd *abfd;
378      bfd_format format;
379 {
380   if (bfd_read_p (abfd)
381       || (unsigned int) abfd->format >= (unsigned int) bfd_type_end)
382     {
383       bfd_set_error (bfd_error_invalid_operation);
384       return FALSE;
385     }
386
387   if (abfd->format != bfd_unknown)
388     return abfd->format == format;
389
390   /* Presume the answer is yes.  */
391   abfd->format = format;
392
393   if (!BFD_SEND_FMT (abfd, _bfd_set_format, (abfd)))
394     {
395       abfd->format = bfd_unknown;
396       return FALSE;
397     }
398
399   return TRUE;
400 }
401
402 /*
403 FUNCTION
404         bfd_format_string
405
406 SYNOPSIS
407         const char *bfd_format_string (bfd_format format);
408
409 DESCRIPTION
410         Return a pointer to a const string
411         <<invalid>>, <<object>>, <<archive>>, <<core>>, or <<unknown>>,
412         depending upon the value of @var{format}.
413 */
414
415 const char *
416 bfd_format_string (format)
417      bfd_format format;
418 {
419   if (((int)format <(int) bfd_unknown)
420       || ((int)format >=(int) bfd_type_end))
421     return "invalid";
422
423   switch (format)
424     {
425     case bfd_object:
426       return "object";          /* Linker/assember/compiler output.  */
427     case bfd_archive:
428       return "archive";         /* Object archive file.  */
429     case bfd_core:
430       return "core";            /* Core dump.  */
431     default:
432       return "unknown";
433     }
434 }