This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: PATCH: Should ld cache bfd_check_format return?


On Thu, Apr 20, 2006 at 09:18:00AM +0930, Alan Modra wrote:
> On Wed, Apr 19, 2006 at 01:44:44PM -0700, H. J. Lu wrote:
> > On Wed, Apr 19, 2006 at 07:21:24AM -0700, H. J. Lu wrote:
> > > load_symbols does
> > > 
> > > 	ldfile_open_file (entry);
> > > 
> > > 	if (! bfd_check_format (entry->the_bfd, bfd_archive)
> > > 	    && ! bfd_check_format_matches (entry->the_bfd, bfd_object, &matching))
> > > 
> > > ldfile_open_file also calls bfd_check_format. Should ld cache
> > > bfd_check_format return?
> > > 
> > 
> > This patch caches bfd_check_format return.
> 
> We already cache in bfd->format.
> 

But we only cache the postive result. We will do the whole check for
bfd_archive over and over on a bfd_object file. This patch also caches
the negative result. I also clean up the linker a little bit to make
it easier to read.

BTW, I changed

(unsigned int) abfd->format >= (unsigned int) bfd_type_end)

to

(unsigned int) format >= (unsigned int) bfd_type_end

abfd->format will always be valid. We never put garbage on it.



H.J.
----
bfd/

2006-04-20  H.J. Lu  <hongjiu.lu@intel.com>

	* bfd-in.h (bfd_format): Add bfd_object_mask and bfd_type_max.
	(bfd_format_negative_bit): New.
	* bfd-in2.h: Regenerated.

	* format.c (bfd_check_format_matches): Check format instead of
	abfd->format. Cache and check negative result.
	(bfd_set_format): Likewise.

ld/

2006-04-20  H.J. Lu  <hongjiu.lu@intel.com>

	* ldfile.c (ldfile_try_open_bfd): Cleanup.
	* ldlang.c (load_symbols): Only call bfd_check_format_matches
	to get the last of matching targets for error.

--- binutils/bfd/bfd-in.h.format	2006-03-16 12:37:42.000000000 -0800
+++ binutils/bfd/bfd-in.h	2006-04-20 07:24:37.000000000 -0700
@@ -168,13 +168,19 @@ typedef unsigned char bfd_byte;
 typedef enum bfd_format
 {
   bfd_unknown = 0,	/* File format is unknown.  */
-  bfd_object,		/* Linker/assembler/compiler output.  */
-  bfd_archive,		/* Object archive file.  */
-  bfd_core,		/* Core dump.  */
-  bfd_type_end		/* Marks the end; don't use it!  */
+  bfd_object = 1,	/* Linker/assembler/compiler output.  */
+  bfd_archive = 2,	/* Object archive file.  */
+  bfd_core = 3,		/* Core dump.  */
+  bfd_object_mask = 0x3,
+  bfd_type_end = 4,	/* Marks the end; don't use it!  */
+  /* Make sure that bfd_format is big enough to hold 1 << (3 + 1).  */
+  bfd_type_max = 1 << 4
 }
 bfd_format;
 
+/* The bit to indicate that file isn't FORMAT.  */
+#define bfd_format_negative_bit(format) (1 << ((format) + 1))
+
 /* Values that may appear in the flags field of a BFD.  These also
    appear in the object_flags field of the bfd_target structure, where
    they indicate the set of flags used by that backend (not all flags
--- binutils/bfd/format.c.format	2005-12-14 09:20:29.000000000 -0800
+++ binutils/bfd/format.c	2006-04-20 07:26:19.000000000 -0700
@@ -122,16 +122,26 @@ bfd_check_format_matches (bfd *abfd, bfd
   const bfd_target *save_targ, *right_targ, *ar_right_targ;
   int match_count;
   int ar_match_index;
+  bfd_format save_format;
 
-  if (!bfd_read_p (abfd)
-      || (unsigned int) abfd->format >= (unsigned int) bfd_type_end)
+  if ((unsigned int) format >= (unsigned int) bfd_type_end
+      || !bfd_read_p (abfd))
     {
       bfd_set_error (bfd_error_invalid_operation);
       return FALSE;
     }
 
   if (abfd->format != bfd_unknown)
-    return abfd->format == format;
+    {
+      if ((abfd->format & bfd_object_mask) != 0)
+	return abfd->format == format;
+      /* FIXME: If caller wants the list of matching targets, we can't
+	 just return.  */
+      else if (!matching
+	       && (abfd->format
+		   & bfd_format_negative_bit (format)) != 0)
+	return FALSE;
+    }
 
   /* Since the target type was defaulted, check them
      all in the hope that one will be uniquely recognized.  */
@@ -154,6 +164,7 @@ bfd_check_format_matches (bfd *abfd, bfd
   ar_right_targ = 0;
 
   /* Presume the answer is yes.  */
+  save_format = abfd->format | bfd_format_negative_bit (format);
   abfd->format = format;
 
   /* If the target type was explicitly specified, just check that target.  */
@@ -201,7 +212,7 @@ bfd_check_format_matches (bfd *abfd, bfd
       if (format == bfd_archive && save_targ == &binary_vec)
 	{
 	  abfd->xvec = save_targ;
-	  abfd->format = bfd_unknown;
+	  abfd->format = save_format;
 
 	  if (matching)
 	    free (matching_vector);
@@ -273,7 +284,7 @@ bfd_check_format_matches (bfd *abfd, bfd
       else if (err != bfd_error_wrong_format)
 	{
 	  abfd->xvec = save_targ;
-	  abfd->format = bfd_unknown;
+	  abfd->format = save_format;
 
 	  if (matching)
 	    free (matching_vector);
@@ -343,7 +354,7 @@ bfd_check_format_matches (bfd *abfd, bfd
     }
 
   abfd->xvec = save_targ;		/* Restore original target type.  */
-  abfd->format = bfd_unknown;		/* Restore original format.  */
+  abfd->format = save_format;		/* Restore original format.  */
 
   if (match_count == 0)
     {
@@ -390,22 +401,30 @@ DESCRIPTION
 bfd_boolean
 bfd_set_format (bfd *abfd, bfd_format format)
 {
-  if (bfd_read_p (abfd)
-      || (unsigned int) abfd->format >= (unsigned int) bfd_type_end)
+  bfd_format save_format;
+
+  if ((unsigned int) format >= (unsigned int) bfd_type_end
+      || !bfd_write_p (abfd))
     {
       bfd_set_error (bfd_error_invalid_operation);
       return FALSE;
     }
 
   if (abfd->format != bfd_unknown)
-    return abfd->format == format;
+    {
+      if ((abfd->format & bfd_object_mask) != 0)
+	return abfd->format == format;
+      else if ((abfd->format & bfd_format_negative_bit (format)) != 0)
+	return FALSE;
+    }
 
   /* Presume the answer is yes.  */
+  save_format = abfd->format | bfd_format_negative_bit (format);
   abfd->format = format;
 
   if (!BFD_SEND_FMT (abfd, _bfd_set_format, (abfd)))
     {
-      abfd->format = bfd_unknown;
+      abfd->format = save_format;
       return FALSE;
     }
 
--- binutils/ld/ldfile.c.format	2005-05-16 11:04:40.000000000 -0700
+++ binutils/ld/ldfile.c	2006-04-20 07:09:07.000000000 -0700
@@ -159,18 +159,20 @@ ldfile_try_open_bfd (const char *attempt
       bfd *check;
 
       if (bfd_check_format (entry->the_bfd, bfd_archive))
-	check = bfd_openr_next_archived_file (entry->the_bfd, NULL);
+	{
+	  check = bfd_openr_next_archived_file (entry->the_bfd, NULL);
+	  if (!check || !bfd_check_format (check, bfd_object))
+	    /* No further check on unknown file.  */
+	    return TRUE;
+	}
       else
-	check = entry->the_bfd;
-
-      if (check != NULL)
 	{
-	  if (! bfd_check_format (check, bfd_object))
+	  check = entry->the_bfd;
+	  if (!bfd_check_format (entry->the_bfd, bfd_object))
 	    {
-	      if (check == entry->the_bfd
-		  && entry->search_dirs_flag
+	      if (entry->search_dirs_flag
 		  && bfd_get_error () == bfd_error_file_not_recognized
-		  && ! ldemul_unrecognized_file (entry))
+		  && !ldemul_unrecognized_file (entry))
 		{
 		  int token, skip = 0;
 		  char *arg, *arg1, *arg2, *arg3;
@@ -254,37 +256,37 @@ ldfile_try_open_bfd (const char *attempt
 		    {
 		      einfo (_("%P: skipping incompatible %s when searching for %s\n"),
 			     attempt, entry->local_sym_name);
-		      bfd_close (entry->the_bfd);
-		      entry->the_bfd = NULL;
-		      return FALSE;
+		      goto bad;
 		    }
 		}
+
+	      /* No further check on unknown file.  */
 	      return TRUE;
 	    }
 
-	  if (!entry->dynamic && (entry->the_bfd->flags & DYNAMIC) != 0)
+	  if (!entry->dynamic
+	      && (entry->the_bfd->flags & DYNAMIC) != 0)
 	    {
 	      einfo (_("%F%P: attempted static link of dynamic object `%s'\n"),
 		     attempt);
-	      bfd_close (entry->the_bfd);
-	      entry->the_bfd = NULL;
-	      return FALSE;
+	      goto bad;
 	    }
+	}
 
-	  if (entry->search_dirs_flag
-	      && !bfd_arch_get_compatible (check, output_bfd,
-					   command_line.accept_unknown_input_arch)
-	      /* XCOFF archives can have 32 and 64 bit objects.  */
-	      && ! (bfd_get_flavour (check) == bfd_target_xcoff_flavour
-		    && bfd_get_flavour (output_bfd) == bfd_target_xcoff_flavour
-		    && bfd_check_format (entry->the_bfd, bfd_archive)))
-	    {
-	      einfo (_("%P: skipping incompatible %s when searching for %s\n"),
-		     attempt, entry->local_sym_name);
-	      bfd_close (entry->the_bfd);
-	      entry->the_bfd = NULL;
-	      return FALSE;
-	    }
+      if (entry->search_dirs_flag
+	  && !bfd_arch_get_compatible (check, output_bfd,
+				       command_line.accept_unknown_input_arch)
+	  /* XCOFF archives can have 32 and 64 bit objects.  */
+	  && ! (bfd_get_flavour (check) == bfd_target_xcoff_flavour
+		&& bfd_get_flavour (output_bfd) == bfd_target_xcoff_flavour
+		&& bfd_check_format (entry->the_bfd, bfd_archive)))
+	{
+	  einfo (_("%P: skipping incompatible %s when searching for %s\n"),
+		 attempt, entry->local_sym_name);
+bad:
+	  bfd_close (entry->the_bfd);
+	  entry->the_bfd = NULL;
+	  return FALSE;
 	}
     }
 
--- binutils/ld/ldlang.c.format	2006-04-14 14:44:46.000000000 -0700
+++ binutils/ld/ldlang.c	2006-04-20 07:09:07.000000000 -0700
@@ -2309,15 +2309,13 @@ static bfd_boolean
 load_symbols (lang_input_statement_type *entry,
 	      lang_statement_list_type *place)
 {
-  char **matching;
-
   if (entry->loaded)
     return TRUE;
 
   ldfile_open_file (entry);
 
   if (! bfd_check_format (entry->the_bfd, bfd_archive)
-      && ! bfd_check_format_matches (entry->the_bfd, bfd_object, &matching))
+      && ! bfd_check_format (entry->the_bfd, bfd_object))
     {
       bfd_error_type err;
       lang_statement_list_type *hold;
@@ -2337,7 +2335,10 @@ load_symbols (lang_input_statement_type 
 
 	  einfo (_("%B: file not recognized: %E\n"), entry->the_bfd);
 	  einfo (_("%B: matching formats:"), entry->the_bfd);
-	  for (p = matching; *p != NULL; p++)
+
+	  /* Get the list of matching targets.  */
+	  bfd_check_format_matches (entry->the_bfd, bfd_object, &p);
+	  for (; *p != NULL; p++)
 	    einfo (" %s", *p);
 	  einfo ("%F\n");
 	}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]