Handle CRLF when reading XML on Windows
[deliverable/binutils-gdb.git] / bfd / format.c
index e2afa3b2b4a25b31129bdc62da7cb4c98c488e7e..1d1363d18403cef706ec1a81f164c5b6521dd20f 100644 (file)
@@ -1,6 +1,5 @@
 /* Generic BFD support for file formats.
-   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2002,
-   2003, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
+   Copyright (C) 1990-2019 Free Software Foundation, Inc.
    Written by Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -104,7 +103,9 @@ struct bfd_preserve
   struct bfd_section *sections;
   struct bfd_section *section_last;
   unsigned int section_count;
+  unsigned int section_id;
   struct bfd_hash_table section_htab;
+  const struct bfd_build_id *build_id;
 };
 
 /* When testing an object for compatibility with a particular target
@@ -125,8 +126,10 @@ bfd_preserve_save (bfd *abfd, struct bfd_preserve *preserve)
   preserve->sections = abfd->sections;
   preserve->section_last = abfd->section_last;
   preserve->section_count = abfd->section_count;
+  preserve->section_id = _bfd_section_id;
   preserve->section_htab = abfd->section_htab;
   preserve->marker = bfd_alloc (abfd, 1);
+  preserve->build_id = abfd->build_id;
   if (preserve->marker == NULL)
     return FALSE;
 
@@ -137,12 +140,13 @@ bfd_preserve_save (bfd *abfd, struct bfd_preserve *preserve)
 /* Clear out a subset of BFD state.  */
 
 static void
-bfd_reinit (bfd *abfd)
+bfd_reinit (bfd *abfd, unsigned int section_id)
 {
   abfd->tdata.any = NULL;
   abfd->arch_info = &bfd_default_arch_struct;
   abfd->flags &= BFD_FLAGS_SAVED;
   bfd_section_list_clear (abfd);
+  _bfd_section_id = section_id;
 }
 
 /* Restores bfd state saved by bfd_preserve_save.  */
@@ -159,6 +163,8 @@ bfd_preserve_restore (bfd *abfd, struct bfd_preserve *preserve)
   abfd->sections = preserve->sections;
   abfd->section_last = preserve->section_last;
   abfd->section_count = preserve->section_count;
+  _bfd_section_id = preserve->section_id;
+  abfd->build_id = preserve->build_id;
 
   /* bfd_release frees all memory more recently bfd_alloc'd than
      its arg, as well as its arg.  */
@@ -204,11 +210,15 @@ bfd_boolean
 bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
 {
   extern const bfd_target binary_vec;
+#if BFD_SUPPORTS_PLUGINS
+  extern const bfd_target plugin_vec;
+#endif
   const bfd_target * const *target;
   const bfd_target **matching_vector = NULL;
   const bfd_target *save_targ, *right_targ, *ar_right_targ, *match_targ;
   int match_count, best_count, best_match;
   int ar_match_index;
+  unsigned int initial_section_id = _bfd_section_id;
   struct bfd_preserve preserve;
 
   if (matching != NULL)
@@ -280,16 +290,22 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
     {
       const bfd_target *temp;
 
-      /* Don't check the default target twice.  */
+      /* The binary target matches anything, so don't return it when
+        searching.  Don't match the plugin target if we have another
+        alternative since we want to properly set the input format
+        before allowing a plugin to claim the file.  Also, don't
+        check the default target twice.  */
       if (*target == &binary_vec
-         || (!abfd->target_defaulted && *target == save_targ)
-         || (*target)->match_priority > best_match)
+#if BFD_SUPPORTS_PLUGINS
+         || (match_count != 0 && *target == &plugin_vec)
+#endif
+         || (!abfd->target_defaulted && *target == save_targ))
        continue;
 
       /* If we already tried a match, the bfd is modified and may
         have sections attached, which will confuse the next
         _bfd_check_format call.  */
-      bfd_reinit (abfd);
+      bfd_reinit (abfd, initial_section_id);
 
       /* Change BFD's target temporarily.  */
       abfd->xvec = *target;
@@ -306,6 +322,16 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
       temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
       if (temp)
        {
+         int match_priority = temp->match_priority;
+#if BFD_SUPPORTS_PLUGINS
+         /* If this object can be handled by a plugin, give that the
+            lowest priority; objects both handled by a plugin and
+            with an underlying object format will be claimed
+            separately by the plugin.  */
+         if (*target == &plugin_vec)
+           match_priority = (*target)->match_priority;
+#endif
+
          match_targ = temp;
          if (preserve.marker != NULL)
            bfd_preserve_finish (abfd, &preserve);
@@ -314,9 +340,6 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
              || (bfd_has_map (abfd)
                  && bfd_get_error () != bfd_error_wrong_object_format))
            {
-             /* 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.  */
@@ -327,12 +350,17 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
                matching_vector[match_count] = temp;
              match_count++;
 
-             if (temp->match_priority < best_match)
+             if (match_priority < best_match)
                {
-                 best_match = temp->match_priority;
+                 best_match = match_priority;
                  best_count = 0;
                }
-             best_count++;
+             if (match_priority <= best_match)
+               {
+                 /* This format checks out as ok!  */
+                 right_targ = temp;
+                 best_count++;
+               }
            }
          else
            {
@@ -376,6 +404,9 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
        }
     }
 
+  /* We have more than one equally good match.  If any of the best
+     matches is a target in config.bfd targ_defvec or targ_selvecs,
+     choose it.  */
   if (match_count > 1)
     {
       const bfd_target * const *assoc = bfd_associated_vector;
@@ -385,7 +416,8 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
          int i = match_count;
 
          while (--i >= 0)
-           if (matching_vector[i] == right_targ)
+           if (matching_vector[i] == right_targ
+               && right_targ->match_priority <= best_match)
              break;
 
          if (i >= 0)
@@ -396,6 +428,22 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
        }
     }
 
+  /* We still have more than one equally good match, and at least some
+     of the targets support match priority.  Choose the first of the
+     best matches.  */
+  if (matching_vector && match_count > 1 && best_count != match_count)
+    {
+      int i;
+
+      for (i = 0; i < match_count; i++)
+       {
+         right_targ = matching_vector[i];
+         if (right_targ->match_priority <= best_match)
+           break;
+       }
+      match_count = 1;
+    }
+
   /* There is way too much undoing of half-known state here.  We
      really shouldn't iterate on live bfd's.  Note that saving the
      whole bfd and restoring it would be even worse; the first thing
@@ -411,7 +459,7 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
         state (except possibly for XVEC).  */
       if (match_targ != right_targ)
        {
-         bfd_reinit (abfd);
+         bfd_reinit (abfd, initial_section_id);
          if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
            goto err_ret;
          match_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
This page took 0.027361 seconds and 4 git commands to generate.