* elf32-ppc.c: Include dwarf2.h.
[deliverable/binutils-gdb.git] / bfd / format.c
index 9d9ee86bac40939eb8f316570cdacdc7f26d02a6..66b9051efe55814c0e34d880d23a6e2bc83b7b61 100644 (file)
@@ -1,13 +1,13 @@
 /* Generic BFD support for file formats.
 /* Generic BFD support for file formats.
-   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2002, 2003
-   Free Software Foundation, Inc.
+   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2002,
+   2003, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
    Written by Cygnus Support.
 
    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
    Written by Cygnus Support.
 
    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
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -17,7 +17,9 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
 
    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.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
 
 /*
 SECTION
 
 /*
 SECTION
@@ -38,10 +40,12 @@ SECTION
 
        The BFD contains the result of an executable core dump.
 
 
        The BFD contains the result of an executable core dump.
 
+SUBSECTION
+       File format functions
 */
 
 */
 
-#include "bfd.h"
 #include "sysdep.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "libbfd.h"
 
 /* IMPORT from targets.c.  */
 #include "libbfd.h"
 
 /* IMPORT from targets.c.  */
@@ -117,10 +121,13 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
   extern const bfd_target binary_vec;
   const bfd_target * const *target;
   const bfd_target **matching_vector = NULL;
   extern const bfd_target binary_vec;
   const bfd_target * const *target;
   const bfd_target **matching_vector = NULL;
-  const bfd_target *save_targ, *right_targ, *ar_right_targ;
-  int match_count;
+  const bfd_target *save_targ, *right_targ, *ar_right_targ, *match_targ;
+  int match_count, best_count, best_match;
   int ar_match_index;
 
   int ar_match_index;
 
+  if (matching != NULL)
+    *matching = NULL;
+
   if (!bfd_read_p (abfd)
       || (unsigned int) abfd->format >= (unsigned int) bfd_type_end)
     {
   if (!bfd_read_p (abfd)
       || (unsigned int) abfd->format >= (unsigned int) bfd_type_end)
     {
@@ -137,19 +144,21 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
   match_count = 0;
   ar_match_index = _bfd_target_vector_entries;
 
   match_count = 0;
   ar_match_index = _bfd_target_vector_entries;
 
-  if (matching)
+  if (matching != NULL || *bfd_associated_vector != NULL)
     {
       bfd_size_type amt;
 
     {
       bfd_size_type amt;
 
-      *matching = NULL;
       amt = sizeof (*matching_vector) * 2 * _bfd_target_vector_entries;
       amt = sizeof (*matching_vector) * 2 * _bfd_target_vector_entries;
-      matching_vector = bfd_malloc (amt);
+      matching_vector = (const bfd_target **) bfd_malloc (amt);
       if (!matching_vector)
        return FALSE;
     }
 
   right_targ = 0;
   ar_right_targ = 0;
       if (!matching_vector)
        return FALSE;
     }
 
   right_targ = 0;
   ar_right_targ = 0;
+  match_targ = 0;
+  best_match = 256;
+  best_count = 0;
 
   /* Presume the answer is yes.  */
   abfd->format = format;
 
   /* Presume the answer is yes.  */
   abfd->format = format;
@@ -158,23 +167,12 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
   if (!abfd->target_defaulted)
     {
       if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)        /* rewind! */
   if (!abfd->target_defaulted)
     {
       if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)        /* rewind! */
-       {
-         if (matching)
-           free (matching_vector);
-         return FALSE;
-       }
+       goto err_ret;
 
       right_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
 
       if (right_targ)
 
       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.  */
-       }
+       goto ok_ret;
 
       /* For a long time the code has dropped through to check all
         targets if the specified target was wrong.  I don't know why,
 
       /* For a long time the code has dropped through to check all
         targets if the specified target was wrong.  I don't know why,
@@ -189,17 +187,7 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
         this sort, I changed this test to check only for the binary
         target.  */
       if (format == bfd_archive && save_targ == &binary_vec)
         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;
-       }
+       goto err_unrecog;
     }
 
   for (target = bfd_target_vector; *target != NULL; target++)
     }
 
   for (target = bfd_target_vector; *target != NULL; target++)
@@ -207,17 +195,16 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
       const bfd_target *temp;
       bfd_error_type err;
 
       const bfd_target *temp;
       bfd_error_type err;
 
-      if (*target == &binary_vec)
+      /* Don't check the default target twice.  */
+      if (*target == &binary_vec
+         || (!abfd->target_defaulted && *target == save_targ)
+         || (*target)->match_priority > best_match)
        continue;
 
       abfd->xvec = *target;    /* Change BFD's target temporarily.  */
 
       if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
        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;
-       }
+       goto err_ret;
 
       /* If _bfd_check_format neglects to set bfd_error, assume
         bfd_error_wrong_format.  We didn't used to even pay any
 
       /* If _bfd_check_format neglects to set bfd_error, assume
         bfd_error_wrong_format.  We didn't used to even pay any
@@ -226,8 +213,10 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
       bfd_set_error (bfd_error_wrong_format);
 
       temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
       bfd_set_error (bfd_error_wrong_format);
 
       temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
-
       if (temp)
       if (temp)
+       match_targ = temp;
+
+      if (temp && (abfd->format != bfd_archive || bfd_has_map (abfd)))
        {
          /* This format checks out as ok!  */
          right_targ = temp;
        {
          /* This format checks out as ok!  */
          right_targ = temp;
@@ -236,50 +225,39 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
             targets might match.  People who want those other targets
             have to set the GNUTARGET variable.  */
          if (temp == bfd_default_vector[0])
             targets might match.  People who want those other targets
             have to set the GNUTARGET variable.  */
          if (temp == bfd_default_vector[0])
-           {
-             match_count = 1;
-             break;
-           }
+           goto ok_ret;
 
 
-         if (matching)
+         if (matching_vector)
            matching_vector[match_count] = temp;
            matching_vector[match_count] = temp;
-
          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
+         if (temp->match_priority < best_match)
+           {
+             best_match = temp->match_priority;
+             best_count = 0;
+           }
+         best_count++;
        }
        }
-      else if ((err = bfd_get_error ()) == bfd_error_wrong_object_format
+      else if (temp
+              || (err = bfd_get_error ()) == bfd_error_wrong_object_format
               || err == bfd_error_file_ambiguously_recognized)
        {
               || 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.  */
+         /* An archive with no armap or 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 (ar_right_targ != bfd_default_vector[0])
            ar_right_targ = *target;
-         if (matching)
+         if (matching_vector)
            matching_vector[ar_match_index] = *target;
          ar_match_index++;
        }
       else if (err != bfd_error_wrong_format)
            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;
-       }
+       goto err_ret;
     }
 
     }
 
+  if (best_count == 1)
+    match_count = 1;
+
   if (match_count == 0)
     {
       /* Try partial matches.  */
   if (match_count == 0)
     {
       /* Try partial matches.  */
@@ -293,16 +271,14 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
        {
          match_count = ar_match_index - _bfd_target_vector_entries;
 
        {
          match_count = ar_match_index - _bfd_target_vector_entries;
 
-         if (matching && match_count > 1)
+         if (matching_vector && match_count > 1)
            memcpy (matching_vector,
                    matching_vector + _bfd_target_vector_entries,
                    sizeof (*matching_vector) * match_count);
        }
     }
 
            memcpy (matching_vector,
                    matching_vector + _bfd_target_vector_entries,
                    sizeof (*matching_vector) * match_count);
        }
     }
 
-  if (match_count > 1
-      && bfd_associated_vector != NULL
-      && matching)
+  if (match_count > 1)
     {
       const bfd_target * const *assoc = bfd_associated_vector;
 
     {
       const bfd_target * const *assoc = bfd_associated_vector;
 
@@ -324,42 +300,59 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
 
   if (match_count == 1)
     {
 
   if (match_count == 1)
     {
-      abfd->xvec = right_targ;         /* Change BFD's target permanently.  */
+      abfd->xvec = right_targ;
+      /* If we come out of the loop knowing that the last target that
+        matched is the one we want, then ABFD should still be in a usable
+        state (except possibly for XVEC).  */
+      if (match_targ != right_targ)
+       {
+         if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
+           goto err_ret;
+         match_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
+       }
 
 
-      if (matching)
-       free (matching_vector);
+    ok_ret:
+      /* 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;
 
 
+      if (matching_vector)
+       free (matching_vector);
       return TRUE;                     /* File position has moved, BTW.  */
     }
 
       return TRUE;                     /* File position has moved, BTW.  */
     }
 
-  abfd->xvec = save_targ;              /* Restore original target type.  */
-  abfd->format = bfd_unknown;          /* Restore original format.  */
-
   if (match_count == 0)
     {
   if (match_count == 0)
     {
+    err_unrecog:
       bfd_set_error (bfd_error_file_not_recognized);
       bfd_set_error (bfd_error_file_not_recognized);
-
-      if (matching)
+    err_ret:
+      abfd->xvec = save_targ;
+      abfd->format = bfd_unknown;
+      if (matching_vector)
        free (matching_vector);
        free (matching_vector);
+      return FALSE;
     }
     }
-  else
-    {
-      bfd_set_error (bfd_error_file_ambiguously_recognized);
 
 
-      if (matching)
+  abfd->xvec = save_targ;              /* Restore original target type.  */
+  abfd->format = bfd_unknown;          /* Restore original format.  */
+  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)
        {
        {
-         *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;
-           }
+         const char *name = matching_vector[match_count]->name;
+         *(const char **) &matching_vector[match_count] = name;
        }
     }
        }
     }
-
   return FALSE;
 }
 
   return FALSE;
 }
 
This page took 0.0303909999999999 seconds and 4 git commands to generate.