This is the mail archive of the binutils-cvs@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]

[binutils-gdb] PR22458, failure to choose a matching ELF target


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=7cf7fcc83ca9fb4c4b591b3142bcf12e6e8a2aa5

commit 7cf7fcc83ca9fb4c4b591b3142bcf12e6e8a2aa5
Author: Alan Modra <amodra@gmail.com>
Date:   Wed May 16 11:33:48 2018 +0930

    PR22458, failure to choose a matching ELF target
    
    https://sourceware.org/ml/binutils/2013-05/msg00271.html was supposed
    to banish "file format is ambiguous" errors for ELF.  It didn't,
    because the code supposedly detecting formats that implement
    match_priority didn't work.  That was due to not placing all matching
    targets into the vector of matching targets.  ELF objects should all
    match the generic ELF target (priority 2), plus one or more machine
    specific targets (priority 1), and perhaps a single machine specific
    target with OS/ABI set (priority 0, best match).  So the armel object
    in the testcase actually matches elf32-littlearm,
    elf32-littlearm-symbian, and elf32-littlearm-vxworks (all priority 1),
    and elf32-little (priority 2).  As the PR reported, elf32-little
    wasn't seen as matching.  Fixing that part of the problem wasn't too
    difficult but matching the generic ELF target as well as the ARM ELF
    targets resulted in ARM testsuite failures.
    
    These proved to be the annoying reordering of stubs that occurs from
    time to time due to the stub names containing the section id.
    Matching another target causes more sections to be created in
    elf_object_p.  If section ids change, stub names change, which results
    in different hashing and can therefore result in different hash table
    traversal and stub creation order.  That particular problem is fixed
    by resetting section_id to the initial state before attempting each
    target match, and taking a snapshot of its value after a successful
    match.
    
    	PR 22458
    	* format.c (struct bfd_preserve): Add section_id.
    	(bfd_preserve_save, bfd_preserve_restore): Save and restore
    	_bfd_section_id.
    	(bfd_reinit): Set _bfd_section_id.
    	(bfd_check_format_matches): Put all matches of any priority into
    	matching_vector.  Save initial section id and start each attempted
    	match at that section id.
    	* libbfd-in.h (_bfd_section_id): Declare.
    	* section.c (_bfd_section_id): Rename from section_id and make
    	global.  Adjust uses.
    	(bfd_get_next_section_id): Delete.
    	* elf64-ppc.c (ppc64_elf_setup_section_lists): Replace use of
    	bfd_get_section_id with _bfd_section_id.
    	* libbfd.h: Regenerate.
    	* bfd-in2.h: Regenerate.

Diff:
---
 bfd/ChangeLog   | 19 +++++++++++++++++++
 bfd/bfd-in2.h   |  2 --
 bfd/elf64-ppc.c |  2 +-
 bfd/format.c    | 24 +++++++++++++++---------
 bfd/libbfd-in.h |  3 +++
 bfd/libbfd.h    |  3 +++
 bfd/section.c   | 23 +++--------------------
 7 files changed, 44 insertions(+), 32 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 655c0ad..8ef34ef 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,22 @@
+2018-05-16  Alan Modra  <amodra@gmail.com>
+
+	PR 22458
+	* format.c (struct bfd_preserve): Add section_id.
+	(bfd_preserve_save, bfd_preserve_restore): Save and restore
+	_bfd_section_id.
+	(bfd_reinit): Set _bfd_section_id.
+	(bfd_check_format_matches): Put all matches of any priority into
+	matching_vector.  Save initial section id and start each attempted
+	match at that section id.
+	* libbfd-in.h (_bfd_section_id): Declare.
+	* section.c (_bfd_section_id): Rename from section_id and make
+	global.  Adjust uses.
+	(bfd_get_next_section_id): Delete.
+	* elf64-ppc.c (ppc64_elf_setup_section_lists): Replace use of
+	bfd_get_section_id with _bfd_section_id.
+	* libbfd.h: Regenerate.
+	* bfd-in2.h: Regenerate.
+
 2018-05-15  Christophe Guillon  <christophe.guillon@st.com>
 
 	* coffcode.h (coff_bigobj_swap_aux_in): Make sure that all fields
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 4822686..5f7ecd3 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -1892,8 +1892,6 @@ asection *bfd_make_section_with_flags
 
 asection *bfd_make_section (bfd *, const char *name);
 
-int bfd_get_next_section_id (void);
-
 bfd_boolean bfd_set_section_flags
    (bfd *abfd, asection *sec, flagword flags);
 
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 09377d1..b166558 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -11760,7 +11760,7 @@ ppc64_elf_setup_section_lists (struct bfd_link_info *info)
   if (htab == NULL)
     return -1;
 
-  htab->sec_info_arr_size = bfd_get_next_section_id ();
+  htab->sec_info_arr_size = _bfd_section_id;
   amt = sizeof (*htab->sec_info) * (htab->sec_info_arr_size);
   htab->sec_info = bfd_zmalloc (amt);
   if (htab->sec_info == NULL)
diff --git a/bfd/format.c b/bfd/format.c
index 64d33f7..c4afd97 100644
--- a/bfd/format.c
+++ b/bfd/format.c
@@ -103,6 +103,7 @@ 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;
 };
@@ -125,6 +126,7 @@ 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;
@@ -138,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.  */
@@ -160,6 +163,7 @@ 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
@@ -214,6 +218,7 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
   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)
@@ -287,14 +292,13 @@ 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)
-	  || (*target)->match_priority > best_match)
+	  || (!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;
@@ -329,9 +333,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.  */
@@ -347,7 +348,12 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
 		  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
 	    {
@@ -446,7 +452,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));
diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h
index 0c80f4d..d8b445f 100644
--- a/bfd/libbfd-in.h
+++ b/bfd/libbfd-in.h
@@ -53,6 +53,9 @@ struct section_hash_entry
   asection section;
 };
 
+/* Unique section id.  */
+extern unsigned int _bfd_section_id;
+
 /* tdata for an archive.  For an input archive, cache
    needs to be free()'d.  For an output archive, symdefs do.  */
 
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 66c2a5a..495ffb4 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -58,6 +58,9 @@ struct section_hash_entry
   asection section;
 };
 
+/* Unique section id.  */
+extern unsigned int _bfd_section_id;
+
 /* tdata for an archive.  For an input archive, cache
    needs to be free()'d.  For an output archive, symdefs do.  */
 
diff --git a/bfd/section.c b/bfd/section.c
index 752f291..7ee3f69 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -820,21 +820,21 @@ _bfd_generic_new_section_hook (bfd *abfd, asection *newsect)
   return TRUE;
 }
 
-static unsigned int section_id = 0x10;  /* id 0 to 3 used by STD_SECTION.  */
+unsigned int _bfd_section_id = 0x10;  /* id 0 to 3 used by STD_SECTION.  */
 
 /* Initializes a new section.  NEWSECT->NAME is already set.  */
 
 static asection *
 bfd_section_init (bfd *abfd, asection *newsect)
 {
-  newsect->id = section_id;
+  newsect->id = _bfd_section_id;
   newsect->index = abfd->section_count;
   newsect->owner = abfd;
 
   if (! BFD_SEND (abfd, _new_section_hook, (abfd, newsect)))
     return NULL;
 
-  section_id++;
+  _bfd_section_id++;
   abfd->section_count++;
   bfd_section_list_append (abfd, newsect);
   return newsect;
@@ -1286,23 +1286,6 @@ bfd_make_section (bfd *abfd, const char *name)
 
 /*
 FUNCTION
-	bfd_get_next_section_id
-
-SYNOPSIS
-	int bfd_get_next_section_id (void);
-
-DESCRIPTION
-	Returns the id that the next section created will have.
-*/
-
-int
-bfd_get_next_section_id (void)
-{
-  return section_id;
-}
-
-/*
-FUNCTION
 	bfd_set_section_flags
 
 SYNOPSIS


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