gdb/
[deliverable/binutils-gdb.git] / bfd / format.c
index 3de399f5af29a4609b5f0c9998df630c3da9dfb9..66b9051efe55814c0e34d880d23a6e2bc83b7b61 100644 (file)
@@ -121,8 +121,8 @@ 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;
-  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;
 
   if (matching != NULL)
@@ -149,13 +149,16 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
       bfd_size_type amt;
 
       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;
+  match_targ = 0;
+  best_match = 256;
+  best_count = 0;
 
   /* Presume the answer is yes.  */
   abfd->format = format;
@@ -194,7 +197,8 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
 
       /* Don't check the default target twice.  */
       if (*target == &binary_vec
-         || (!abfd->target_defaulted && *target == save_targ))
+         || (!abfd->target_defaulted && *target == save_targ)
+         || (*target)->match_priority > best_match)
        continue;
 
       abfd->xvec = *target;    /* Change BFD's target temporarily.  */
@@ -209,6 +213,8 @@ 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));
+      if (temp)
+       match_targ = temp;
 
       if (temp && (abfd->format != bfd_archive || bfd_has_map (abfd)))
        {
@@ -219,14 +225,18 @@ 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])
-           {
-             match_count = 1;
-             break;
-           }
+           goto ok_ret;
 
          if (matching_vector)
            matching_vector[match_count] = temp;
          match_count++;
+
+         if (temp->match_priority < best_match)
+           {
+             best_match = temp->match_priority;
+             best_count = 0;
+           }
+         best_count++;
        }
       else if (temp
               || (err = bfd_get_error ()) == bfd_error_wrong_object_format
@@ -245,6 +255,9 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
        goto err_ret;
     }
 
+  if (best_count == 1)
+    match_count = 1;
+
   if (match_count == 0)
     {
       /* Try partial matches.  */
@@ -287,9 +300,18 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
 
   if (match_count == 1)
     {
-    ok_ret:
-      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));
+       }
 
+    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.
This page took 0.024907 seconds and 4 git commands to generate.