123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561 |
- #include "sysdep.h"
- #include "bfd.h"
- #include "libbfd.h"
- extern const size_t _bfd_target_vector_entries;
- bfd_boolean
- bfd_check_format (bfd *abfd, bfd_format format)
- {
- return bfd_check_format_matches (abfd, format, NULL);
- }
- struct bfd_preserve
- {
- void *marker;
- void *tdata;
- flagword flags;
- const struct bfd_arch_info *arch_info;
- struct bfd_section *sections;
- struct bfd_section *section_last;
- unsigned int section_count;
- struct bfd_hash_table section_htab;
- };
- static bfd_boolean
- bfd_preserve_save (bfd *abfd, struct bfd_preserve *preserve)
- {
- preserve->tdata = abfd->tdata.any;
- preserve->arch_info = abfd->arch_info;
- preserve->flags = abfd->flags;
- preserve->sections = abfd->sections;
- preserve->section_last = abfd->section_last;
- preserve->section_count = abfd->section_count;
- preserve->section_htab = abfd->section_htab;
- preserve->marker = bfd_alloc (abfd, 1);
- if (preserve->marker == NULL)
- return FALSE;
- return bfd_hash_table_init (&abfd->section_htab, bfd_section_hash_newfunc,
- sizeof (struct section_hash_entry));
- }
- static void
- bfd_reinit (bfd *abfd)
- {
- abfd->tdata.any = NULL;
- abfd->arch_info = &bfd_default_arch_struct;
- abfd->flags &= BFD_FLAGS_SAVED;
- bfd_section_list_clear (abfd);
- }
- static void
- bfd_preserve_restore (bfd *abfd, struct bfd_preserve *preserve)
- {
- bfd_hash_table_free (&abfd->section_htab);
- abfd->tdata.any = preserve->tdata;
- abfd->arch_info = preserve->arch_info;
- abfd->flags = preserve->flags;
- abfd->section_htab = preserve->section_htab;
- abfd->sections = preserve->sections;
- abfd->section_last = preserve->section_last;
- abfd->section_count = preserve->section_count;
-
- bfd_release (abfd, preserve->marker);
- preserve->marker = NULL;
- }
- static void
- bfd_preserve_finish (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_preserve *preserve)
- {
-
- bfd_hash_table_free (&preserve->section_htab);
- preserve->marker = NULL;
- }
- bfd_boolean
- 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, *match_targ;
- int match_count, best_count, best_match;
- int ar_match_index;
- struct bfd_preserve preserve;
- if (matching != NULL)
- *matching = NULL;
- if (!bfd_read_p (abfd)
- || (unsigned int) abfd->format >= (unsigned int) bfd_type_end)
- {
- bfd_set_error (bfd_error_invalid_operation);
- return FALSE;
- }
- if (abfd->format != bfd_unknown)
- return abfd->format == format;
- if (matching != NULL || *bfd_associated_vector != NULL)
- {
- bfd_size_type amt;
- amt = sizeof (*matching_vector) * 2 * _bfd_target_vector_entries;
- matching_vector = (const bfd_target **) bfd_malloc (amt);
- if (!matching_vector)
- return FALSE;
- }
-
- abfd->format = format;
- save_targ = abfd->xvec;
- preserve.marker = NULL;
-
- if (!abfd->target_defaulted)
- {
- if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
- goto err_ret;
- right_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
- if (right_targ)
- goto ok_ret;
-
- if (format == bfd_archive && save_targ == &binary_vec)
- goto err_unrecog;
- }
-
- right_targ = NULL;
- ar_right_targ = NULL;
- match_targ = NULL;
- best_match = 256;
- best_count = 0;
- match_count = 0;
- ar_match_index = _bfd_target_vector_entries;
- for (target = bfd_target_vector; *target != NULL; target++)
- {
- const bfd_target *temp;
-
- if (*target == &binary_vec
- || (!abfd->target_defaulted && *target == save_targ)
- || (*target)->match_priority > best_match)
- continue;
-
- bfd_reinit (abfd);
-
- abfd->xvec = *target;
- if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
- goto err_ret;
-
- bfd_set_error (bfd_error_wrong_format);
- temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
- if (temp)
- {
- match_targ = temp;
- if (preserve.marker != NULL)
- bfd_preserve_finish (abfd, &preserve);
- if (abfd->format != bfd_archive
- || (bfd_has_map (abfd)
- && bfd_get_error () != bfd_error_wrong_object_format))
- {
-
- right_targ = temp;
-
- if (temp == bfd_default_vector[0])
- 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 (ar_right_targ != bfd_default_vector[0])
- ar_right_targ = *target;
- if (matching_vector)
- matching_vector[ar_match_index] = *target;
- ar_match_index++;
- }
- if (!bfd_preserve_save (abfd, &preserve))
- goto err_ret;
- }
- else if (bfd_get_error () != bfd_error_wrong_format)
- goto err_ret;
- }
- if (best_count == 1)
- match_count = 1;
- if (match_count == 0)
- {
-
- right_targ = ar_right_targ;
- if (right_targ == bfd_default_vector[0])
- {
- match_count = 1;
- }
- else
- {
- match_count = ar_match_index - _bfd_target_vector_entries;
- if (matching_vector && match_count > 1)
- memcpy (matching_vector,
- matching_vector + _bfd_target_vector_entries,
- sizeof (*matching_vector) * match_count);
- }
- }
-
- if (match_count > 1)
- {
- const bfd_target * const *assoc = bfd_associated_vector;
- while ((right_targ = *assoc++) != NULL)
- {
- int i = match_count;
- while (--i >= 0)
- if (matching_vector[i] == right_targ
- && right_targ->match_priority <= best_match)
- break;
- if (i >= 0)
- {
- match_count = 1;
- break;
- }
- }
- }
-
- 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;
- }
-
- if (preserve.marker != NULL)
- bfd_preserve_restore (abfd, &preserve);
- if (match_count == 1)
- {
- abfd->xvec = right_targ;
-
- if (match_targ != right_targ)
- {
- bfd_reinit (abfd);
- if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
- goto err_ret;
- match_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
- BFD_ASSERT (match_targ != NULL);
- }
- ok_ret:
-
- if (abfd->direction == both_direction)
- abfd->output_has_begun = TRUE;
- if (matching_vector)
- free (matching_vector);
-
- return TRUE;
- }
- if (match_count == 0)
- {
- err_unrecog:
- bfd_set_error (bfd_error_file_not_recognized);
- err_ret:
- abfd->xvec = save_targ;
- abfd->format = bfd_unknown;
- if (matching_vector)
- free (matching_vector);
- if (preserve.marker != NULL)
- bfd_preserve_restore (abfd, &preserve);
- return FALSE;
- }
-
- abfd->xvec = save_targ;
- abfd->format = bfd_unknown;
- bfd_set_error (bfd_error_file_ambiguously_recognized);
- if (matching)
- {
- *matching = (char **) matching_vector;
- matching_vector[match_count] = NULL;
-
- while (--match_count >= 0)
- {
- const char *name = matching_vector[match_count]->name;
- *(const char **) &matching_vector[match_count] = name;
- }
- }
- return FALSE;
- }
- 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_set_error (bfd_error_invalid_operation);
- return FALSE;
- }
- if (abfd->format != bfd_unknown)
- return abfd->format == format;
-
- abfd->format = format;
- if (!BFD_SEND_FMT (abfd, _bfd_set_format, (abfd)))
- {
- abfd->format = bfd_unknown;
- return FALSE;
- }
- return TRUE;
- }
- const char *
- bfd_format_string (bfd_format format)
- {
- if (((int) format < (int) bfd_unknown)
- || ((int) format >= (int) bfd_type_end))
- return "invalid";
- switch (format)
- {
- case bfd_object:
- return "object";
- case bfd_archive:
- return "archive";
- case bfd_core:
- return "core";
- default:
- return "unknown";
- }
- }
|