X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Fformat.c;h=f60f0caa6fc049bb051055c38bd8123e49c22530;hb=86fb1dece37497b267579ed4f062d280cd5760cd;hp=fb9fdc0d160c02e8851617f787a600df74023fa7;hpb=fa803dc60f0bf01297674c41d001798e18ade4dc;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/format.c b/bfd/format.c index fb9fdc0d16..f60f0caa6f 100644 --- a/bfd/format.c +++ b/bfd/format.c @@ -1,5 +1,6 @@ /* Generic BFD support for file formats. - Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001 + Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -16,14 +17,14 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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,6 @@ SECTION The BFD contains the result of an executable core dump. - */ #include "bfd.h" @@ -45,7 +45,7 @@ SECTION #include "libbfd.h" /* IMPORT from targets.c. */ -extern CONST size_t _bfd_target_vector_entries; +extern const size_t _bfd_target_vector_entries; /* FUNCTION @@ -68,20 +68,20 @@ DESCRIPTION the file, or an error results. The function returns <> on success, otherwise <> - with one of the following error codes: + with one of the following error codes: - o <> - + o <> - if <> is not one of <>, <> or <>. - o <> - + o <> - if an error occured during a read - even some file mismatches - can cause system_call_errors. + can cause bfd_error_system_calls. o <> - none of the backends recognised the file format. - o <> - + o <> - more than one backend recognised the file format. */ @@ -102,14 +102,14 @@ SYNOPSIS DESCRIPTION Like <>, except when it returns false with - <> set to <>. In that + <> 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, allocated with <>. 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 @@ -118,119 +118,213 @@ bfd_check_format_matches (abfd, format, matching) bfd_format format; char ***matching; { - bfd_target **target, *save_targ, *right_targ; - char **matching_vector; + extern const bfd_target binary_vec; + const bfd_target * const *target, *save_targ, *right_targ, *ar_right_targ; + char **matching_vector = NULL; 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_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 = matching_vector = - (char **) bfd_xmalloc_by_size_t (sizeof (char *) * - (_bfd_target_vector_entries + 1)); - matching_vector[0] = NULL; + bfd_size_type amt; + + *matching = NULL; + amt = sizeof (char *) * 2 * _bfd_target_vector_entries; + matching_vector = (char **) bfd_malloc (amt); + if (!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! */ + return false; - if (!abfd->target_defaulted) { - bfd_seek (abfd, (file_ptr)0, SEEK_SET); /* rewind! */ + right_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd)); - 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 */ - } - } - - for (target = bfd_target_vector; *target != NULL; target++) { - bfd_target *temp; - - abfd->xvec = *target; /* Change BFD's target temporarily */ - bfd_seek (abfd, (file_ptr)0, SEEK_SET); - /* If _bfd_check_format neglects to set bfd_error, assume 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_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) { - matching_vector[match_count] = temp->name; - matching_vector[match_count + 1] = NULL; + abfd->xvec = right_targ; /* Set the target as returned. */ + + if (matching) + free (matching_vector); + + return true; /* File position has moved, BTW. */ } - 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 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; + bfd_error_type err; + + 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 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; } - match_count = 1; - break; - } + + if (matching) + matching_vector[match_count] = temp->name; + + 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; + /* 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_error != wrong_format) { - abfd->xvec = save_targ; - abfd->format = bfd_unknown; - if (matching && bfd_error != file_ambiguously_recognized) + } + 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)->name; + 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; + } + 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 (char *) * match_count); + } + } + } + + if (match_count == 1) + { + abfd->xvec = right_targ; /* Change BFD's target permanently. */ + + if (matching) free (matching_vector); - return false; + + 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_error = file_not_recognized; + bfd_set_error (bfd_error_file_not_recognized); + if (matching) free (matching_vector); } else - bfd_error = file_ambiguously_recognized; + { + bfd_set_error (bfd_error_file_ambiguously_recognized); + + if (matching) + { + *matching = matching_vector; + matching_vector[match_count] = NULL; + } + } + return false; } @@ -246,7 +340,6 @@ DESCRIPTION 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 @@ -254,35 +347,34 @@ bfd_set_format (abfd, 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_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) ? true : false; - /* 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; } - /* 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 @@ -290,22 +382,23 @@ DESCRIPTION depending upon the value of @var{format}. */ -CONST char * +const char * bfd_format_string (format) 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/assember/compiler output. */ + case bfd_archive: + return "archive"; /* Object archive file. */ + case bfd_core: + return "core"; /* Core dump. */ + default: + return "unknown"; + } }