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.
+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
2018-05-15 Christophe Guillon <christophe.guillon@st.com>
* coffcode.h (coff_bigobj_swap_aux_in): Make sure that all fields
asection *bfd_make_section (bfd *, const char *name);
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);
bfd_boolean bfd_set_section_flags
(bfd *abfd, asection *sec, flagword flags);
if (htab == NULL)
return -1;
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)
amt = sizeof (*htab->sec_info) * (htab->sec_info_arr_size);
htab->sec_info = bfd_zmalloc (amt);
if (htab->sec_info == NULL)
struct bfd_section *sections;
struct bfd_section *section_last;
unsigned int section_count;
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;
};
struct bfd_hash_table section_htab;
const struct bfd_build_id *build_id;
};
preserve->sections = abfd->sections;
preserve->section_last = abfd->section_last;
preserve->section_count = abfd->section_count;
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;
preserve->section_htab = abfd->section_htab;
preserve->marker = bfd_alloc (abfd, 1);
preserve->build_id = abfd->build_id;
/* Clear out a subset of BFD state. */
static void
/* Clear out a subset of BFD state. */
static void
+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);
{
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. */
}
/* Restores bfd state saved by bfd_preserve_save. */
abfd->sections = preserve->sections;
abfd->section_last = preserve->section_last;
abfd->section_count = preserve->section_count;
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
abfd->build_id = preserve->build_id;
/* bfd_release frees all memory more recently bfd_alloc'd than
const bfd_target *save_targ, *right_targ, *ar_right_targ, *match_targ;
int match_count, best_count, best_match;
int ar_match_index;
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)
struct bfd_preserve preserve;
if (matching != NULL)
/* Don't check the default target twice. */
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)
+ || (!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. */
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, initial_section_id);
/* Change BFD's target temporarily. */
abfd->xvec = *target;
/* Change BFD's target temporarily. */
abfd->xvec = *target;
|| (bfd_has_map (abfd)
&& bfd_get_error () != bfd_error_wrong_object_format))
{
|| (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. */
/* 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. */
best_match = match_priority;
best_count = 0;
}
best_match = match_priority;
best_count = 0;
}
+ if (match_priority <= best_match)
+ {
+ /* This format checks out as ok! */
+ right_targ = temp;
+ best_count++;
+ }
state (except possibly for XVEC). */
if (match_targ != right_targ)
{
state (except possibly for XVEC). */
if (match_targ != right_targ)
{
+ 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));
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
goto err_ret;
match_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
+/* 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. */
/* tdata for an archive. For an input archive, cache
needs to be free()'d. For an output archive, symdefs do. */
+/* 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. */
/* tdata for an archive. For an input archive, cache
needs to be free()'d. For an output archive, symdefs do. */
-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)
{
/* 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;
newsect->index = abfd->section_count;
newsect->owner = abfd;
if (! BFD_SEND (abfd, _new_section_hook, (abfd, newsect)))
return NULL;
abfd->section_count++;
bfd_section_list_append (abfd, newsect);
return newsect;
abfd->section_count++;
bfd_section_list_append (abfd, newsect);
return newsect;
return bfd_make_section_with_flags (abfd, name, 0);
}
return bfd_make_section_with_flags (abfd, name, 0);
}
-/*
-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
/*
FUNCTION
bfd_set_section_flags