1 |
/* Generic BFD support for file formats. |
/* Generic BFD support for file formats. |
2 |
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2002 |
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2002, |
3 |
Free Software Foundation, Inc. |
2003, 2005 Free Software Foundation, Inc. |
4 |
Written by Cygnus Support. |
Written by Cygnus Support. |
5 |
|
|
6 |
This file is part of BFD, the Binary File Descriptor library. |
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 |
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 |
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 |
the Free Software Foundation; either version 2 of the License, or |
11 |
(at your option) any later version. |
(at your option) any later version. |
12 |
|
|
13 |
This program is distributed in the hope that it will be useful, |
This program is distributed in the hope that it will be useful, |
14 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 |
GNU General Public License for more details. |
GNU General Public License for more details. |
17 |
|
|
18 |
You should have received a copy of the GNU General Public License |
You should have received a copy of the GNU General Public License |
19 |
along with this program; if not, write to the Free Software |
along with this program; if not, write to the Free Software |
20 |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
21 |
|
|
22 |
/* |
/* |
23 |
SECTION |
SECTION |
52 |
bfd_check_format |
bfd_check_format |
53 |
|
|
54 |
SYNOPSIS |
SYNOPSIS |
55 |
boolean bfd_check_format(bfd *abfd, bfd_format format); |
bfd_boolean bfd_check_format (bfd *abfd, bfd_format format); |
56 |
|
|
57 |
DESCRIPTION |
DESCRIPTION |
58 |
Verify if the file attached to the BFD @var{abfd} is compatible |
Verify if the file attached to the BFD @var{abfd} is compatible |
67 |
matches, it is used. If not, exactly one target must recognize |
matches, it is used. If not, exactly one target must recognize |
68 |
the file, or an error results. |
the file, or an error results. |
69 |
|
|
70 |
The function returns <<true>> on success, otherwise <<false>> |
The function returns <<TRUE>> on success, otherwise <<FALSE>> |
71 |
with one of the following error codes: |
with one of the following error codes: |
72 |
|
|
73 |
o <<bfd_error_invalid_operation>> - |
o <<bfd_error_invalid_operation>> - |
85 |
more than one backend recognised the file format. |
more than one backend recognised the file format. |
86 |
*/ |
*/ |
87 |
|
|
88 |
boolean |
bfd_boolean |
89 |
bfd_check_format (abfd, format) |
bfd_check_format (bfd *abfd, bfd_format format) |
|
bfd *abfd; |
|
|
bfd_format format; |
|
90 |
{ |
{ |
91 |
return bfd_check_format_matches (abfd, format, NULL); |
return bfd_check_format_matches (abfd, format, NULL); |
92 |
} |
} |
96 |
bfd_check_format_matches |
bfd_check_format_matches |
97 |
|
|
98 |
SYNOPSIS |
SYNOPSIS |
99 |
boolean bfd_check_format_matches(bfd *abfd, bfd_format format, char ***matching); |
bfd_boolean bfd_check_format_matches |
100 |
|
(bfd *abfd, bfd_format format, char ***matching); |
101 |
|
|
102 |
DESCRIPTION |
DESCRIPTION |
103 |
Like <<bfd_check_format>>, except when it returns false with |
Like <<bfd_check_format>>, except when it returns FALSE with |
104 |
<<bfd_errno>> set to <<bfd_error_file_ambiguously_recognized>>. In that |
<<bfd_errno>> set to <<bfd_error_file_ambiguously_recognized>>. In that |
105 |
case, if @var{matching} is not NULL, it will be filled in with |
case, if @var{matching} is not NULL, it will be filled in with |
106 |
a NULL-terminated list of the names of the formats that matched, |
a NULL-terminated list of the names of the formats that matched, |
111 |
should free it. |
should free it. |
112 |
*/ |
*/ |
113 |
|
|
114 |
boolean |
bfd_boolean |
115 |
bfd_check_format_matches (abfd, format, matching) |
bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching) |
|
bfd *abfd; |
|
|
bfd_format format; |
|
|
char ***matching; |
|
116 |
{ |
{ |
117 |
extern const bfd_target binary_vec; |
extern const bfd_target binary_vec; |
118 |
const bfd_target * const *target, *save_targ, *right_targ, *ar_right_targ; |
const bfd_target * const *target; |
119 |
char **matching_vector = NULL; |
const bfd_target **matching_vector = NULL; |
120 |
|
const bfd_target *save_targ, *right_targ, *ar_right_targ; |
121 |
int match_count; |
int match_count; |
122 |
int ar_match_index; |
int ar_match_index; |
123 |
|
|
125 |
|| (unsigned int) abfd->format >= (unsigned int) bfd_type_end) |
|| (unsigned int) abfd->format >= (unsigned int) bfd_type_end) |
126 |
{ |
{ |
127 |
bfd_set_error (bfd_error_invalid_operation); |
bfd_set_error (bfd_error_invalid_operation); |
128 |
return false; |
return FALSE; |
129 |
} |
} |
130 |
|
|
131 |
if (abfd->format != bfd_unknown) |
if (abfd->format != bfd_unknown) |
142 |
bfd_size_type amt; |
bfd_size_type amt; |
143 |
|
|
144 |
*matching = NULL; |
*matching = NULL; |
145 |
amt = sizeof (char *) * 2 * _bfd_target_vector_entries; |
amt = sizeof (*matching_vector) * 2 * _bfd_target_vector_entries; |
146 |
matching_vector = (char **) bfd_malloc (amt); |
matching_vector = bfd_malloc (amt); |
147 |
if (!matching_vector) |
if (!matching_vector) |
148 |
return false; |
return FALSE; |
149 |
} |
} |
150 |
|
|
151 |
right_targ = 0; |
right_targ = 0; |
158 |
if (!abfd->target_defaulted) |
if (!abfd->target_defaulted) |
159 |
{ |
{ |
160 |
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) /* rewind! */ |
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) /* rewind! */ |
161 |
return false; |
{ |
162 |
|
if (matching) |
163 |
|
free (matching_vector); |
164 |
|
return FALSE; |
165 |
|
} |
166 |
|
|
167 |
right_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd)); |
right_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd)); |
168 |
|
|
173 |
if (matching) |
if (matching) |
174 |
free (matching_vector); |
free (matching_vector); |
175 |
|
|
176 |
return true; /* File position has moved, BTW. */ |
return TRUE; /* File position has moved, BTW. */ |
177 |
} |
} |
178 |
|
|
179 |
/* For a long time the code has dropped through to check all |
/* For a long time the code has dropped through to check all |
198 |
|
|
199 |
bfd_set_error (bfd_error_file_not_recognized); |
bfd_set_error (bfd_error_file_not_recognized); |
200 |
|
|
201 |
return false; |
return FALSE; |
202 |
} |
} |
203 |
} |
} |
204 |
|
|
210 |
if (*target == &binary_vec) |
if (*target == &binary_vec) |
211 |
continue; |
continue; |
212 |
|
|
213 |
abfd->xvec = *target; /* Change BFD's target temporarily */ |
abfd->xvec = *target; /* Change BFD's target temporarily. */ |
214 |
|
|
215 |
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) |
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) |
216 |
return false; |
{ |
217 |
|
if (matching) |
218 |
|
free (matching_vector); |
219 |
|
return FALSE; |
220 |
|
} |
221 |
|
|
222 |
/* If _bfd_check_format neglects to set bfd_error, assume |
/* If _bfd_check_format neglects to set bfd_error, assume |
223 |
bfd_error_wrong_format. We didn't used to even pay any |
bfd_error_wrong_format. We didn't used to even pay any |
228 |
temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd)); |
temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd)); |
229 |
|
|
230 |
if (temp) |
if (temp) |
231 |
{ /* This format checks out as ok! */ |
{ |
232 |
|
/* This format checks out as ok! */ |
233 |
right_targ = temp; |
right_targ = temp; |
234 |
|
|
235 |
/* If this is the default target, accept it, even if other |
/* If this is the default target, accept it, even if other |
242 |
} |
} |
243 |
|
|
244 |
if (matching) |
if (matching) |
245 |
matching_vector[match_count] = temp->name; |
matching_vector[match_count] = temp; |
246 |
|
|
247 |
match_count++; |
match_count++; |
|
|
|
|
#ifdef GNU960 |
|
|
/* Big- and little-endian b.out archives look the same, but it |
|
|
doesn't matter: there is no difference in their headers, and |
|
|
member file byte orders will (I hope) be handled appropriately |
|
|
by bfd. Ditto for big and little coff archives. And the 4 |
|
|
coff/b.out object formats are unambiguous. So accept the |
|
|
first match we find. */ |
|
|
break; |
|
|
#endif |
|
248 |
} |
} |
249 |
else if ((err = bfd_get_error ()) == bfd_error_wrong_object_format |
else if ((err = bfd_get_error ()) == bfd_error_wrong_object_format |
250 |
|| err == bfd_error_file_ambiguously_recognized) |
|| err == bfd_error_file_ambiguously_recognized) |
255 |
if (ar_right_targ != bfd_default_vector[0]) |
if (ar_right_targ != bfd_default_vector[0]) |
256 |
ar_right_targ = *target; |
ar_right_targ = *target; |
257 |
if (matching) |
if (matching) |
258 |
matching_vector[ar_match_index] = (*target)->name; |
matching_vector[ar_match_index] = *target; |
259 |
ar_match_index++; |
ar_match_index++; |
260 |
} |
} |
261 |
else if (err != bfd_error_wrong_format) |
else if (err != bfd_error_wrong_format) |
266 |
if (matching) |
if (matching) |
267 |
free (matching_vector); |
free (matching_vector); |
268 |
|
|
269 |
return false; |
return FALSE; |
270 |
} |
} |
271 |
} |
} |
272 |
|
|
274 |
{ |
{ |
275 |
/* Try partial matches. */ |
/* Try partial matches. */ |
276 |
right_targ = ar_right_targ; |
right_targ = ar_right_targ; |
277 |
|
|
278 |
if (right_targ == bfd_default_vector[0]) |
if (right_targ == bfd_default_vector[0]) |
279 |
{ |
{ |
280 |
match_count = 1; |
match_count = 1; |
282 |
else |
else |
283 |
{ |
{ |
284 |
match_count = ar_match_index - _bfd_target_vector_entries; |
match_count = ar_match_index - _bfd_target_vector_entries; |
285 |
|
|
286 |
if (matching && match_count > 1) |
if (matching && match_count > 1) |
287 |
|
memcpy (matching_vector, |
288 |
|
matching_vector + _bfd_target_vector_entries, |
289 |
|
sizeof (*matching_vector) * match_count); |
290 |
|
} |
291 |
|
} |
292 |
|
|
293 |
|
if (match_count > 1 |
294 |
|
&& bfd_associated_vector != NULL |
295 |
|
&& matching) |
296 |
|
{ |
297 |
|
const bfd_target * const *assoc = bfd_associated_vector; |
298 |
|
|
299 |
|
while ((right_targ = *assoc++) != NULL) |
300 |
|
{ |
301 |
|
int i = match_count; |
302 |
|
|
303 |
|
while (--i >= 0) |
304 |
|
if (matching_vector[i] == right_targ) |
305 |
|
break; |
306 |
|
|
307 |
|
if (i >= 0) |
308 |
{ |
{ |
309 |
memcpy (matching_vector, |
match_count = 1; |
310 |
matching_vector + _bfd_target_vector_entries, |
break; |
|
sizeof (char *) * match_count); |
|
311 |
} |
} |
312 |
} |
} |
313 |
} |
} |
319 |
if (matching) |
if (matching) |
320 |
free (matching_vector); |
free (matching_vector); |
321 |
|
|
322 |
return true; /* File position has moved, BTW. */ |
return TRUE; /* File position has moved, BTW. */ |
323 |
} |
} |
324 |
|
|
325 |
abfd->xvec = save_targ; /* Restore original target type. */ |
abfd->xvec = save_targ; /* Restore original target type. */ |
338 |
|
|
339 |
if (matching) |
if (matching) |
340 |
{ |
{ |
341 |
*matching = matching_vector; |
*matching = (char **) matching_vector; |
342 |
matching_vector[match_count] = NULL; |
matching_vector[match_count] = NULL; |
343 |
|
/* Return target names. This is a little nasty. Maybe we |
344 |
|
should do another bfd_malloc? */ |
345 |
|
while (--match_count >= 0) |
346 |
|
{ |
347 |
|
const char *name = matching_vector[match_count]->name; |
348 |
|
*(const char **) &matching_vector[match_count] = name; |
349 |
|
} |
350 |
} |
} |
351 |
} |
} |
352 |
|
|
353 |
return false; |
return FALSE; |
354 |
} |
} |
355 |
|
|
356 |
/* |
/* |
358 |
bfd_set_format |
bfd_set_format |
359 |
|
|
360 |
SYNOPSIS |
SYNOPSIS |
361 |
boolean bfd_set_format(bfd *abfd, bfd_format format); |
bfd_boolean bfd_set_format (bfd *abfd, bfd_format format); |
362 |
|
|
363 |
DESCRIPTION |
DESCRIPTION |
364 |
This function sets the file format of the BFD @var{abfd} to the |
This function sets the file format of the BFD @var{abfd} to the |
367 |
is not open for writing, then an error occurs. |
is not open for writing, then an error occurs. |
368 |
*/ |
*/ |
369 |
|
|
370 |
boolean |
bfd_boolean |
371 |
bfd_set_format (abfd, format) |
bfd_set_format (bfd *abfd, bfd_format format) |
|
bfd *abfd; |
|
|
bfd_format format; |
|
372 |
{ |
{ |
373 |
if (bfd_read_p (abfd) |
if (bfd_read_p (abfd) |
374 |
|| (unsigned int) abfd->format >= (unsigned int) bfd_type_end) |
|| (unsigned int) abfd->format >= (unsigned int) bfd_type_end) |
375 |
{ |
{ |
376 |
bfd_set_error (bfd_error_invalid_operation); |
bfd_set_error (bfd_error_invalid_operation); |
377 |
return false; |
return FALSE; |
378 |
} |
} |
379 |
|
|
380 |
if (abfd->format != bfd_unknown) |
if (abfd->format != bfd_unknown) |
386 |
if (!BFD_SEND_FMT (abfd, _bfd_set_format, (abfd))) |
if (!BFD_SEND_FMT (abfd, _bfd_set_format, (abfd))) |
387 |
{ |
{ |
388 |
abfd->format = bfd_unknown; |
abfd->format = bfd_unknown; |
389 |
return false; |
return FALSE; |
390 |
} |
} |
391 |
|
|
392 |
return true; |
return TRUE; |
393 |
} |
} |
394 |
|
|
395 |
/* |
/* |
397 |
bfd_format_string |
bfd_format_string |
398 |
|
|
399 |
SYNOPSIS |
SYNOPSIS |
400 |
const char *bfd_format_string(bfd_format format); |
const char *bfd_format_string (bfd_format format); |
401 |
|
|
402 |
DESCRIPTION |
DESCRIPTION |
403 |
Return a pointer to a const string |
Return a pointer to a const string |
406 |
*/ |
*/ |
407 |
|
|
408 |
const char * |
const char * |
409 |
bfd_format_string (format) |
bfd_format_string (bfd_format format) |
|
bfd_format format; |
|
410 |
{ |
{ |
411 |
if (((int)format <(int) bfd_unknown) |
if (((int) format < (int) bfd_unknown) |
412 |
|| ((int)format >=(int) bfd_type_end)) |
|| ((int) format >= (int) bfd_type_end)) |
413 |
return "invalid"; |
return "invalid"; |
414 |
|
|
415 |
switch (format) |
switch (format) |
416 |
{ |
{ |
417 |
case bfd_object: |
case bfd_object: |
418 |
return "object"; /* Linker/assember/compiler output. */ |
return "object"; /* Linker/assembler/compiler output. */ |
419 |
case bfd_archive: |
case bfd_archive: |
420 |
return "archive"; /* Object archive file. */ |
return "archive"; /* Object archive file. */ |
421 |
case bfd_core: |
case bfd_core: |