Back to index

cell-binutils  2.17cvs20070401
format.c
Go to the documentation of this file.
00001 /* Generic BFD support for file formats.
00002    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2002,
00003    2003, 2005 Free Software Foundation, Inc.
00004    Written by Cygnus Support.
00005 
00006    This file is part of BFD, the Binary File Descriptor library.
00007 
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2 of the License, or
00011    (at your option) any later version.
00012 
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with this program; if not, write to the Free Software
00020    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00021 
00022 /*
00023 SECTION
00024        File formats
00025 
00026        A format is a BFD concept of high level file contents type. The
00027        formats supported by BFD are:
00028 
00029        o <<bfd_object>>
00030 
00031        The BFD may contain data, symbols, relocations and debug info.
00032 
00033        o <<bfd_archive>>
00034 
00035        The BFD contains other BFDs and an optional index.
00036 
00037        o <<bfd_core>>
00038 
00039        The BFD contains the result of an executable core dump.
00040 
00041 SUBSECTION
00042        File format functions
00043 */
00044 
00045 #include "bfd.h"
00046 #include "sysdep.h"
00047 #include "libbfd.h"
00048 
00049 /* IMPORT from targets.c.  */
00050 extern const size_t _bfd_target_vector_entries;
00051 
00052 /*
00053 FUNCTION
00054        bfd_check_format
00055 
00056 SYNOPSIS
00057        bfd_boolean bfd_check_format (bfd *abfd, bfd_format format);
00058 
00059 DESCRIPTION
00060        Verify if the file attached to the BFD @var{abfd} is compatible
00061        with the format @var{format} (i.e., one of <<bfd_object>>,
00062        <<bfd_archive>> or <<bfd_core>>).
00063 
00064        If the BFD has been set to a specific target before the
00065        call, only the named target and format combination is
00066        checked. If the target has not been set, or has been set to
00067        <<default>>, then all the known target backends is
00068        interrogated to determine a match.  If the default target
00069        matches, it is used.  If not, exactly one target must recognize
00070        the file, or an error results.
00071 
00072        The function returns <<TRUE>> on success, otherwise <<FALSE>>
00073        with one of the following error codes:
00074 
00075        o <<bfd_error_invalid_operation>> -
00076        if <<format>> is not one of <<bfd_object>>, <<bfd_archive>> or
00077        <<bfd_core>>.
00078 
00079        o <<bfd_error_system_call>> -
00080        if an error occured during a read - even some file mismatches
00081        can cause bfd_error_system_calls.
00082 
00083        o <<file_not_recognised>> -
00084        none of the backends recognised the file format.
00085 
00086        o <<bfd_error_file_ambiguously_recognized>> -
00087        more than one backend recognised the file format.
00088 */
00089 
00090 bfd_boolean
00091 bfd_check_format (bfd *abfd, bfd_format format)
00092 {
00093   return bfd_check_format_matches (abfd, format, NULL);
00094 }
00095 
00096 /*
00097 FUNCTION
00098        bfd_check_format_matches
00099 
00100 SYNOPSIS
00101        bfd_boolean bfd_check_format_matches
00102          (bfd *abfd, bfd_format format, char ***matching);
00103 
00104 DESCRIPTION
00105        Like <<bfd_check_format>>, except when it returns FALSE with
00106        <<bfd_errno>> set to <<bfd_error_file_ambiguously_recognized>>.  In that
00107        case, if @var{matching} is not NULL, it will be filled in with
00108        a NULL-terminated list of the names of the formats that matched,
00109        allocated with <<malloc>>.
00110        Then the user may choose a format and try again.
00111 
00112        When done with the list that @var{matching} points to, the caller
00113        should free it.
00114 */
00115 
00116 bfd_boolean
00117 bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
00118 {
00119   extern const bfd_target binary_vec;
00120   const bfd_target * const *target;
00121   const bfd_target **matching_vector = NULL;
00122   const bfd_target *save_targ, *right_targ, *ar_right_targ;
00123   int match_count;
00124   int ar_match_index;
00125 
00126   if (!bfd_read_p (abfd)
00127       || (unsigned int) abfd->format >= (unsigned int) bfd_type_end)
00128     {
00129       bfd_set_error (bfd_error_invalid_operation);
00130       return FALSE;
00131     }
00132 
00133   if (abfd->format != bfd_unknown)
00134     return abfd->format == format;
00135 
00136   /* Since the target type was defaulted, check them
00137      all in the hope that one will be uniquely recognized.  */
00138   save_targ = abfd->xvec;
00139   match_count = 0;
00140   ar_match_index = _bfd_target_vector_entries;
00141 
00142   if (matching)
00143     {
00144       bfd_size_type amt;
00145 
00146       *matching = NULL;
00147       amt = sizeof (*matching_vector) * 2 * _bfd_target_vector_entries;
00148       matching_vector = bfd_malloc (amt);
00149       if (!matching_vector)
00150        return FALSE;
00151     }
00152 
00153   right_targ = 0;
00154   ar_right_targ = 0;
00155 
00156   /* Presume the answer is yes.  */
00157   abfd->format = format;
00158 
00159   /* If the target type was explicitly specified, just check that target.  */
00160   if (!abfd->target_defaulted)
00161     {
00162       if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) /* rewind! */
00163        {
00164          if (matching)
00165            free (matching_vector);
00166          return FALSE;
00167        }
00168 
00169       right_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
00170 
00171       if (right_targ)
00172        {
00173          abfd->xvec = right_targ;  /* Set the target as returned.  */
00174 
00175          if (matching)
00176            free (matching_vector);
00177 
00178          /* If the file was opened for update, then `output_has_begun'
00179             some time ago when the file was created.  Do not recompute
00180             sections sizes or alignments in _bfd_set_section_contents.
00181             We can not set this flag until after checking the format,
00182             because it will interfere with creation of BFD sections.  */
00183          if (abfd->direction == both_direction)
00184            abfd->output_has_begun = TRUE;
00185 
00186          return TRUE;                     /* File position has moved, BTW.  */
00187        }
00188 
00189       /* For a long time the code has dropped through to check all
00190         targets if the specified target was wrong.  I don't know why,
00191         and I'm reluctant to change it.  However, in the case of an
00192         archive, it can cause problems.  If the specified target does
00193         not permit archives (e.g., the binary target), then we should
00194         not allow some other target to recognize it as an archive, but
00195         should instead allow the specified target to recognize it as an
00196         object.  When I first made this change, it broke the PE target,
00197         because the specified pei-i386 target did not recognize the
00198         actual pe-i386 archive.  Since there may be other problems of
00199         this sort, I changed this test to check only for the binary
00200         target.  */
00201       if (format == bfd_archive && save_targ == &binary_vec)
00202        {
00203          abfd->xvec = save_targ;
00204          abfd->format = bfd_unknown;
00205 
00206          if (matching)
00207            free (matching_vector);
00208 
00209          bfd_set_error (bfd_error_file_not_recognized);
00210 
00211          return FALSE;
00212        }
00213     }
00214 
00215   for (target = bfd_target_vector; *target != NULL; target++)
00216     {
00217       const bfd_target *temp;
00218       bfd_error_type err;
00219 
00220       /* Don't check the default target twice.  */
00221       if (*target == &binary_vec
00222          || (!abfd->target_defaulted && *target == save_targ))
00223        continue;
00224 
00225       abfd->xvec = *target; /* Change BFD's target temporarily.  */
00226 
00227       if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
00228        {
00229          if (matching)
00230            free (matching_vector);
00231          return FALSE;
00232        }
00233 
00234       /* If _bfd_check_format neglects to set bfd_error, assume
00235         bfd_error_wrong_format.  We didn't used to even pay any
00236         attention to bfd_error, so I suspect that some
00237         _bfd_check_format might have this problem.  */
00238       bfd_set_error (bfd_error_wrong_format);
00239 
00240       temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
00241 
00242       if (temp)
00243        {
00244          /* This format checks out as ok!  */
00245          right_targ = temp;
00246 
00247          /* If this is the default target, accept it, even if other
00248             targets might match.  People who want those other targets
00249             have to set the GNUTARGET variable.  */
00250          if (temp == bfd_default_vector[0])
00251            {
00252              match_count = 1;
00253              break;
00254            }
00255 
00256          if (matching)
00257            matching_vector[match_count] = temp;
00258 
00259          match_count++;
00260        }
00261       else if ((err = bfd_get_error ()) == bfd_error_wrong_object_format
00262               || err == bfd_error_file_ambiguously_recognized)
00263        {
00264          /* An archive with objects of the wrong type, or an
00265             ambiguous match.  We want this target to match if we get
00266             no better matches.  */
00267          if (ar_right_targ != bfd_default_vector[0])
00268            ar_right_targ = *target;
00269          if (matching)
00270            matching_vector[ar_match_index] = *target;
00271          ar_match_index++;
00272        }
00273       else if (err != bfd_error_wrong_format)
00274        {
00275          abfd->xvec = save_targ;
00276          abfd->format = bfd_unknown;
00277 
00278          if (matching)
00279            free (matching_vector);
00280 
00281          return FALSE;
00282        }
00283     }
00284 
00285   if (match_count == 0)
00286     {
00287       /* Try partial matches.  */
00288       right_targ = ar_right_targ;
00289 
00290       if (right_targ == bfd_default_vector[0])
00291        {
00292          match_count = 1;
00293        }
00294       else
00295        {
00296          match_count = ar_match_index - _bfd_target_vector_entries;
00297 
00298          if (matching && match_count > 1)
00299            memcpy (matching_vector,
00300                   matching_vector + _bfd_target_vector_entries,
00301                   sizeof (*matching_vector) * match_count);
00302        }
00303     }
00304 
00305   if (match_count > 1
00306       && bfd_associated_vector != NULL
00307       && matching)
00308     {
00309       const bfd_target * const *assoc = bfd_associated_vector;
00310 
00311       while ((right_targ = *assoc++) != NULL)
00312        {
00313          int i = match_count;
00314 
00315          while (--i >= 0)
00316            if (matching_vector[i] == right_targ)
00317              break;
00318 
00319          if (i >= 0)
00320            {
00321              match_count = 1;
00322              break;
00323            }
00324        }
00325     }
00326 
00327   if (match_count == 1)
00328     {
00329       abfd->xvec = right_targ;            /* Change BFD's target permanently.  */
00330 
00331       if (matching)
00332        free (matching_vector);
00333 
00334       /* If the file was opened for update, then `output_has_begun'
00335         some time ago when the file was created.  Do not recompute
00336         sections sizes or alignments in _bfd_set_section_contents.
00337         We can not set this flag until after checking the format,
00338         because it will interfere with creation of BFD sections.  */
00339       if (abfd->direction == both_direction)
00340        abfd->output_has_begun = TRUE;
00341 
00342       return TRUE;                 /* File position has moved, BTW.  */
00343     }
00344 
00345   abfd->xvec = save_targ;          /* Restore original target type.  */
00346   abfd->format = bfd_unknown;             /* Restore original format.  */
00347 
00348   if (match_count == 0)
00349     {
00350       bfd_set_error (bfd_error_file_not_recognized);
00351 
00352       if (matching)
00353        free (matching_vector);
00354     }
00355   else
00356     {
00357       bfd_set_error (bfd_error_file_ambiguously_recognized);
00358 
00359       if (matching)
00360        {
00361          *matching = (char **) matching_vector;
00362          matching_vector[match_count] = NULL;
00363          /* Return target names.  This is a little nasty.  Maybe we
00364             should do another bfd_malloc?  */
00365          while (--match_count >= 0)
00366            {
00367              const char *name = matching_vector[match_count]->name;
00368              *(const char **) &matching_vector[match_count] = name;
00369            }
00370        }
00371     }
00372 
00373   return FALSE;
00374 }
00375 
00376 /*
00377 FUNCTION
00378        bfd_set_format
00379 
00380 SYNOPSIS
00381        bfd_boolean bfd_set_format (bfd *abfd, bfd_format format);
00382 
00383 DESCRIPTION
00384        This function sets the file format of the BFD @var{abfd} to the
00385        format @var{format}. If the target set in the BFD does not
00386        support the format requested, the format is invalid, or the BFD
00387        is not open for writing, then an error occurs.
00388 */
00389 
00390 bfd_boolean
00391 bfd_set_format (bfd *abfd, bfd_format format)
00392 {
00393   if (bfd_read_p (abfd)
00394       || (unsigned int) abfd->format >= (unsigned int) bfd_type_end)
00395     {
00396       bfd_set_error (bfd_error_invalid_operation);
00397       return FALSE;
00398     }
00399 
00400   if (abfd->format != bfd_unknown)
00401     return abfd->format == format;
00402 
00403   /* Presume the answer is yes.  */
00404   abfd->format = format;
00405 
00406   if (!BFD_SEND_FMT (abfd, _bfd_set_format, (abfd)))
00407     {
00408       abfd->format = bfd_unknown;
00409       return FALSE;
00410     }
00411 
00412   return TRUE;
00413 }
00414 
00415 /*
00416 FUNCTION
00417        bfd_format_string
00418 
00419 SYNOPSIS
00420        const char *bfd_format_string (bfd_format format);
00421 
00422 DESCRIPTION
00423        Return a pointer to a const string
00424        <<invalid>>, <<object>>, <<archive>>, <<core>>, or <<unknown>>,
00425        depending upon the value of @var{format}.
00426 */
00427 
00428 const char *
00429 bfd_format_string (bfd_format format)
00430 {
00431   if (((int) format < (int) bfd_unknown)
00432       || ((int) format >= (int) bfd_type_end))
00433     return "invalid";
00434 
00435   switch (format)
00436     {
00437     case bfd_object:
00438       return "object";             /* Linker/assembler/compiler output.  */
00439     case bfd_archive:
00440       return "archive";            /* Object archive file.  */
00441     case bfd_core:
00442       return "core";        /* Core dump.  */
00443     default:
00444       return "unknown";
00445     }
00446 }