X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Fformat.c;h=6a34dd2bea488b2b93bf7d34e8304f222ddcc8de;hb=62b3e31101ef2dfb96ee4652d5145e722b335e31;hp=c9f1f9cd4be3f6f2c521956114a386b7470eefdb;hpb=27e232885db363fb545fd2f450e72d929e59b8f6;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/format.c b/bfd/format.c index c9f1f9cd4b..6a34dd2bea 100644 --- a/bfd/format.c +++ b/bfd/format.c @@ -1,29 +1,30 @@ /* Generic BFD support for file formats. - Copyright (C) 1990, 91, 92, 93, 94, 95, 1999 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2002, + 2003, 2005 Free Software Foundation, Inc. Written by Cygnus Support. -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ /* SECTION File formats A format is a BFD concept of high level file contents type. The - formats supported by BFD are: + formats supported by BFD are: o <> @@ -37,7 +38,8 @@ SECTION The BFD contains the result of an executable core dump. - +SUBSECTION + File format functions */ #include "bfd.h" @@ -52,7 +54,7 @@ FUNCTION bfd_check_format SYNOPSIS - boolean bfd_check_format(bfd *abfd, bfd_format format); + bfd_boolean bfd_check_format (bfd *abfd, bfd_format format); DESCRIPTION Verify if the file attached to the BFD @var{abfd} is compatible @@ -67,8 +69,8 @@ DESCRIPTION matches, it is used. If not, exactly one target must recognize the file, or an error results. - The function returns <> on success, otherwise <> - with one of the following error codes: + The function returns <> on success, otherwise <> + with one of the following error codes: o <> - if <> is not one of <>, <> or @@ -85,10 +87,8 @@ DESCRIPTION more than one backend recognised the file format. */ -boolean -bfd_check_format (abfd, format) - bfd *abfd; - bfd_format format; +bfd_boolean +bfd_check_format (bfd *abfd, bfd_format format) { return bfd_check_format_matches (abfd, format, NULL); } @@ -98,10 +98,11 @@ FUNCTION bfd_check_format_matches SYNOPSIS - boolean bfd_check_format_matches(bfd *abfd, bfd_format format, char ***matching); + bfd_boolean bfd_check_format_matches + (bfd *abfd, bfd_format format, char ***matching); DESCRIPTION - Like <>, except when it returns false with + Like <>, except when it returns FALSE with <> set to <>. In that case, if @var{matching} is not NULL, it will be filled in with a NULL-terminated list of the names of the formats that matched, @@ -109,160 +110,267 @@ DESCRIPTION Then the user may choose a format and try again. When done with the list that @var{matching} points to, the caller - should free it. + should free it. */ -boolean -bfd_check_format_matches (abfd, format, matching) - bfd *abfd; - bfd_format format; - char ***matching; +bfd_boolean +bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching) { extern const bfd_target binary_vec; - const bfd_target * const *target, *save_targ, *right_targ; - char **matching_vector = NULL; + const bfd_target * const *target; + const bfd_target **matching_vector = NULL; + const bfd_target *save_targ, *right_targ, *ar_right_targ; int match_count; + int ar_match_index; - if (!bfd_read_p (abfd) || - ((int)(abfd->format) < (int)bfd_unknown) || - ((int)(abfd->format) >= (int)bfd_type_end)) { - bfd_set_error (bfd_error_invalid_operation); - return false; - } + if (!bfd_read_p (abfd) + || (unsigned int) abfd->format >= (unsigned int) bfd_type_end) + { + bfd_set_error (bfd_error_invalid_operation); + return FALSE; + } if (abfd->format != bfd_unknown) - return (abfd->format == format)? true: false; - + return abfd->format == format; - /* Since the target type was defaulted, check them + /* Since the target type was defaulted, check them all in the hope that one will be uniquely recognized. */ - save_targ = abfd->xvec; match_count = 0; + ar_match_index = _bfd_target_vector_entries; + if (matching) { - matching_vector = - (char **) bfd_malloc (sizeof (char *) * - (_bfd_target_vector_entries + 1)); + bfd_size_type amt; + + *matching = NULL; + amt = sizeof (*matching_vector) * 2 * _bfd_target_vector_entries; + matching_vector = bfd_malloc (amt); if (!matching_vector) - return false; - matching_vector[0] = NULL; - *matching = matching_vector; + return FALSE; } - right_targ = 0; + right_targ = 0; + ar_right_targ = 0; - /* presume the answer is yes */ + /* Presume the answer is yes. */ abfd->format = format; /* If the target type was explicitly specified, just check that target. */ + if (!abfd->target_defaulted) + { + if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) /* rewind! */ + { + if (matching) + free (matching_vector); + return FALSE; + } - if (!abfd->target_defaulted) { - if (bfd_seek (abfd, (file_ptr)0, SEEK_SET) != 0) /* rewind! */ - return false; - right_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd)); - if (right_targ) { - abfd->xvec = right_targ; /* Set the target as returned */ - if (matching) - free (matching_vector); - return true; /* File position has moved, BTW */ - } + right_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd)); - /* For a long time the code has dropped through to check all - targets if the specified target was wrong. I don't know why, - and I'm reluctant to change it. However, in the case of an - archive, it can cause problems. If the specified target does - not permit archives (e.g., the binary target), then we should - not allow some other target to recognize it as an archive, but - should instead allow the specified target to recognize it as an - object. When I first made this change, it broke the PE target, - because the specified pei-i386 target did not recognize the - actual pe-i386 archive. Since there may be other problems of - this sort, I changed this test to check only for the binary - target. */ - - if (format == bfd_archive && save_targ == &binary_vec) - { - abfd->xvec = save_targ; - abfd->format = bfd_unknown; - if (matching) - free (matching_vector); - bfd_set_error (bfd_error_file_not_recognized); - return false; - } - } - - for (target = bfd_target_vector; *target != NULL; target++) { - const bfd_target *temp; - - if (*target == &binary_vec) - continue; - - abfd->xvec = *target; /* Change BFD's target temporarily */ - if (bfd_seek (abfd, (file_ptr)0, SEEK_SET) != 0) - return false; - /* If _bfd_check_format neglects to set bfd_error, assume bfd_error_wrong_format. - We didn't used to even pay any attention to bfd_error, so I suspect - that some _bfd_check_format might have this problem. */ - bfd_set_error (bfd_error_wrong_format); - temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd)); - if (temp) { /* This format checks out as ok! */ - right_targ = temp; - if (matching) + if (right_targ) + { + abfd->xvec = right_targ; /* Set the target as returned. */ + + if (matching) + free (matching_vector); + + /* If the file was opened for update, then `output_has_begun' + some time ago when the file was created. Do not recompute + sections sizes or alignments in _bfd_set_section_contents. + We can not set this flag until after checking the format, + because it will interfere with creation of BFD sections. */ + if (abfd->direction == both_direction) + abfd->output_has_begun = TRUE; + + return TRUE; /* File position has moved, BTW. */ + } + + /* For a long time the code has dropped through to check all + targets if the specified target was wrong. I don't know why, + and I'm reluctant to change it. However, in the case of an + archive, it can cause problems. If the specified target does + not permit archives (e.g., the binary target), then we should + not allow some other target to recognize it as an archive, but + should instead allow the specified target to recognize it as an + object. When I first made this change, it broke the PE target, + because the specified pei-i386 target did not recognize the + actual pe-i386 archive. Since there may be other problems of + this sort, I changed this test to check only for the binary + target. */ + if (format == bfd_archive && save_targ == &binary_vec) { - matching_vector[match_count] = temp->name; - matching_vector[match_count + 1] = NULL; + abfd->xvec = save_targ; + abfd->format = bfd_unknown; + + if (matching) + free (matching_vector); + + bfd_set_error (bfd_error_file_not_recognized); + + return FALSE; } - match_count++; - /* If this is the default target, accept it, even if other targets - might match. People who want those other targets have to set - the GNUTARGET variable. */ - if (temp == bfd_default_vector[0]) + } + + for (target = bfd_target_vector; *target != NULL; target++) + { + const bfd_target *temp; + bfd_error_type err; + + /* Don't check the default target twice. */ + if (*target == &binary_vec + || (!abfd->target_defaulted && *target == save_targ)) + continue; + + abfd->xvec = *target; /* Change BFD's target temporarily. */ + + if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) { if (matching) + free (matching_vector); + return FALSE; + } + + /* If _bfd_check_format neglects to set bfd_error, assume + bfd_error_wrong_format. We didn't used to even pay any + attention to bfd_error, so I suspect that some + _bfd_check_format might have this problem. */ + bfd_set_error (bfd_error_wrong_format); + + temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd)); + + if (temp) + { + /* This format checks out as ok! */ + right_targ = temp; + + /* If this is the default target, accept it, even if other + targets might match. People who want those other targets + have to set the GNUTARGET variable. */ + if (temp == bfd_default_vector[0]) { - matching_vector[0] = temp->name; - matching_vector[1] = NULL; + match_count = 1; + break; } + + if (matching) + matching_vector[match_count] = temp; + + match_count++; + } + else if ((err = bfd_get_error ()) == bfd_error_wrong_object_format + || err == bfd_error_file_ambiguously_recognized) + { + /* An archive with objects of the wrong type, or an + ambiguous match. We want this target to match if we get + no better matches. */ + if (ar_right_targ != bfd_default_vector[0]) + ar_right_targ = *target; + if (matching) + matching_vector[ar_match_index] = *target; + ar_match_index++; + } + else if (err != bfd_error_wrong_format) + { + abfd->xvec = save_targ; + abfd->format = bfd_unknown; + + if (matching) + free (matching_vector); + + return FALSE; + } + } + + if (match_count == 0) + { + /* Try partial matches. */ + right_targ = ar_right_targ; + + if (right_targ == bfd_default_vector[0]) + { match_count = 1; - break; } -#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 - } else if (bfd_get_error () != bfd_error_wrong_format) { - abfd->xvec = save_targ; - abfd->format = bfd_unknown; - if (matching && bfd_get_error () != bfd_error_file_ambiguously_recognized) + else + { + match_count = ar_match_index - _bfd_target_vector_entries; + + if (matching && match_count > 1) + memcpy (matching_vector, + matching_vector + _bfd_target_vector_entries, + sizeof (*matching_vector) * match_count); + } + } + + if (match_count > 1 + && bfd_associated_vector != NULL + && matching) + { + const bfd_target * const *assoc = bfd_associated_vector; + + while ((right_targ = *assoc++) != NULL) + { + int i = match_count; + + while (--i >= 0) + if (matching_vector[i] == right_targ) + break; + + if (i >= 0) + { + match_count = 1; + break; + } + } + } + + if (match_count == 1) + { + abfd->xvec = right_targ; /* Change BFD's target permanently. */ + + if (matching) free (matching_vector); - return false; + + /* If the file was opened for update, then `output_has_begun' + some time ago when the file was created. Do not recompute + sections sizes or alignments in _bfd_set_section_contents. + We can not set this flag until after checking the format, + because it will interfere with creation of BFD sections. */ + if (abfd->direction == both_direction) + abfd->output_has_begun = TRUE; + + return TRUE; /* File position has moved, BTW. */ } - } - if (match_count == 1) { - abfd->xvec = right_targ; /* Change BFD's target permanently */ - if (matching) - free (matching_vector); - return true; /* File position has moved, BTW */ - } + abfd->xvec = save_targ; /* Restore original target type. */ + abfd->format = bfd_unknown; /* Restore original format. */ - abfd->xvec = save_targ; /* Restore original target type */ - abfd->format = bfd_unknown; /* Restore original format */ if (match_count == 0) { bfd_set_error (bfd_error_file_not_recognized); + if (matching) free (matching_vector); } else - bfd_set_error (bfd_error_file_ambiguously_recognized); - return false; + { + bfd_set_error (bfd_error_file_ambiguously_recognized); + + if (matching) + { + *matching = (char **) matching_vector; + matching_vector[match_count] = NULL; + /* Return target names. This is a little nasty. Maybe we + should do another bfd_malloc? */ + while (--match_count >= 0) + { + const char *name = matching_vector[match_count]->name; + *(const char **) &matching_vector[match_count] = name; + } + } + } + + return FALSE; } /* @@ -270,50 +378,46 @@ FUNCTION bfd_set_format SYNOPSIS - boolean bfd_set_format(bfd *abfd, bfd_format format); + bfd_boolean bfd_set_format (bfd *abfd, bfd_format format); DESCRIPTION This function sets the file format of the BFD @var{abfd} to the format @var{format}. If the target set in the BFD does not support the format requested, the format is invalid, or the BFD is not open for writing, then an error occurs. - */ -boolean -bfd_set_format (abfd, format) - bfd *abfd; - bfd_format format; +bfd_boolean +bfd_set_format (bfd *abfd, bfd_format format) { - - if (bfd_read_p (abfd) || - ((int)abfd->format < (int)bfd_unknown) || - ((int)abfd->format >= (int)bfd_type_end)) { - bfd_set_error (bfd_error_invalid_operation); - return false; - } + if (bfd_read_p (abfd) + || (unsigned int) abfd->format >= (unsigned int) bfd_type_end) + { + bfd_set_error (bfd_error_invalid_operation); + return FALSE; + } if (abfd->format != bfd_unknown) - return (abfd->format == format) ? true:false; + return abfd->format == format; - /* presume the answer is yes */ + /* Presume the answer is yes. */ abfd->format = format; - if (!BFD_SEND_FMT (abfd, _bfd_set_format, (abfd))) { - abfd->format = bfd_unknown; - return false; - } + if (!BFD_SEND_FMT (abfd, _bfd_set_format, (abfd))) + { + abfd->format = bfd_unknown; + return FALSE; + } - return true; + return TRUE; } - /* FUNCTION bfd_format_string SYNOPSIS - CONST char *bfd_format_string(bfd_format format); + const char *bfd_format_string (bfd_format format); DESCRIPTION Return a pointer to a const string @@ -321,22 +425,22 @@ DESCRIPTION depending upon the value of @var{format}. */ -CONST char * -bfd_format_string (format) - bfd_format format; +const char * +bfd_format_string (bfd_format format) { - if (((int)format <(int) bfd_unknown) - || ((int)format >=(int) bfd_type_end)) + if (((int) format < (int) bfd_unknown) + || ((int) format >= (int) bfd_type_end)) return "invalid"; - - switch (format) { - case bfd_object: - return "object"; /* linker/assember/compiler output */ - case bfd_archive: - return "archive"; /* object archive file */ - case bfd_core: - return "core"; /* core dump */ - default: - return "unknown"; - } + + switch (format) + { + case bfd_object: + return "object"; /* Linker/assembler/compiler output. */ + case bfd_archive: + return "archive"; /* Object archive file. */ + case bfd_core: + return "core"; /* Core dump. */ + default: + return "unknown"; + } }