diff options
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/archive.c | 9 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 10 | ||||
-rw-r--r-- | bfd/bfd.c | 3 | ||||
-rw-r--r-- | bfd/bfd.m4 | 21 | ||||
-rw-r--r-- | bfd/elflink.c | 1 | ||||
-rw-r--r-- | bfd/elfnn-loongarch.c | 102 | ||||
-rw-r--r-- | bfd/format.c | 145 | ||||
-rw-r--r-- | bfd/plugin.c | 37 | ||||
-rw-r--r-- | bfd/plugin.h | 12 | ||||
-rw-r--r-- | bfd/version.h | 2 |
10 files changed, 165 insertions, 177 deletions
diff --git a/bfd/archive.c b/bfd/archive.c index c61d4b1..52d3119 100644 --- a/bfd/archive.c +++ b/bfd/archive.c @@ -141,6 +141,9 @@ SUBSECTION #include "hashtab.h" #include "filenames.h" #include "bfdlink.h" +#if BFD_SUPPORTS_PLUGINS +#include "plugin.h" +#endif #ifndef errno extern int errno; @@ -2343,6 +2346,9 @@ _bfd_compute_and_write_armap (bfd *arch, unsigned int elength) long src_count; if (bfd_get_lto_type (current) == lto_slim_ir_object +#if BFD_SUPPORTS_PLUGINS + && !bfd_plugin_target_p (current->xvec) +#endif && report_plugin_err) { report_plugin_err = false; @@ -2400,6 +2406,9 @@ _bfd_compute_and_write_armap (bfd *arch, unsigned int elength) if (bfd_lto_slim_symbol_p (current, syms[src_count]->name) +#if BFD_SUPPORTS_PLUGINS + && !bfd_plugin_target_p (current->xvec) +#endif && report_plugin_err) { report_plugin_err = false; diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 2ff3e93..12512a3 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -2131,6 +2131,9 @@ struct bfd /* Set if this is the linker input BFD. */ unsigned int is_linker_input : 1; + /* Set if this is the strip input BFD. */ + unsigned int is_strip_input : 1; + /* If this is an input for a compiler plug-in library. */ ENUM_BITFIELD (bfd_plugin_format) plugin_format : 2; @@ -2903,15 +2906,8 @@ bool generic_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd); /* Extracted from format.c. */ -bool bfd_check_format_lto (bfd *abfd, bfd_format format, - bool lto_sections_removed); - bool bfd_check_format (bfd *abfd, bfd_format format); -bool bfd_check_format_matches_lto - (bfd *abfd, bfd_format format, char ***matching, - bool lto_sections_removed); - bool bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching); @@ -296,6 +296,9 @@ CODE_FRAGMENT . {* Set if this is the linker input BFD. *} . unsigned int is_linker_input : 1; . +. {* Set if this is the strip input BFD. *} +. unsigned int is_strip_input : 1; +. . {* If this is an input for a compiler plug-in library. *} . ENUM_BITFIELD (bfd_plugin_format) plugin_format : 2; . @@ -29,12 +29,12 @@ AC_DEFUN([BFD_HAVE_SYS_PROCFS_TYPE], [AC_REQUIRE([BFD_SYS_PROCFS_H]) AC_MSG_CHECKING([for $1 in sys/procfs.h]) AC_CACHE_VAL(bfd_cv_have_sys_procfs_type_$1, - [AC_TRY_COMPILE([ + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #define _SYSCALL32 -#include <sys/procfs.h>], - [$1 avar], - bfd_cv_have_sys_procfs_type_$1=yes, - bfd_cv_have_sys_procfs_type_$1=no +#include <sys/procfs.h>]], + [[$1 avar]])], + [bfd_cv_have_sys_procfs_type_$1=yes], + [bfd_cv_have_sys_procfs_type_$1=no] )]) if test $bfd_cv_have_sys_procfs_type_$1 = yes; then AC_DEFINE([HAVE_]translit($1, [a-z], [A-Z]), 1, @@ -49,12 +49,12 @@ AC_DEFUN([BFD_HAVE_SYS_PROCFS_TYPE_MEMBER], [AC_REQUIRE([BFD_SYS_PROCFS_H]) AC_MSG_CHECKING([for $1.$2 in sys/procfs.h]) AC_CACHE_VAL(bfd_cv_have_sys_procfs_type_member_$1_$2, - [AC_TRY_COMPILE([ + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #define _SYSCALL32 -#include <sys/procfs.h>], - [$1 avar; void* aref = (void*) &avar.$2], - bfd_cv_have_sys_procfs_type_member_$1_$2=yes, - bfd_cv_have_sys_procfs_type_member_$1_$2=no +#include <sys/procfs.h>]], + [[$1 avar; void* aref = (void*) &avar.$2]])], + [bfd_cv_have_sys_procfs_type_member_$1_$2=yes], + [bfd_cv_have_sys_procfs_type_member_$1_$2=no] )]) if test $bfd_cv_have_sys_procfs_type_member_$1_$2 = yes; then AC_DEFINE([HAVE_]translit($1, [a-z], [A-Z])[_]translit($2, [a-z], [A-Z]), 1, @@ -62,4 +62,3 @@ AC_DEFUN([BFD_HAVE_SYS_PROCFS_TYPE_MEMBER], fi AC_MSG_RESULT($bfd_cv_have_sys_procfs_type_member_$1_$2) ]) - diff --git a/bfd/elflink.c b/bfd/elflink.c index c4f57cf..cdd58b2 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -28,7 +28,6 @@ #include "libiberty.h" #include "objalloc.h" #if BFD_SUPPORTS_PLUGINS -#include "plugin-api.h" #include "plugin.h" #endif diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c index 1ddea2f..8beb3d8 100644 --- a/bfd/elfnn-loongarch.c +++ b/bfd/elfnn-loongarch.c @@ -4903,6 +4903,60 @@ loongarch_relax_delete_or_nop (bfd *abfd, bfd_put (32, abfd, LARCH_NOP, contents + addr); } +/* If some bytes in a symbol is deleted, we need to adjust its size. */ +static void +loongarch_relax_resize_symbol (bfd_size_type *size, bfd_vma orig_value, + splay_tree pdops) +{ + splay_tree_key key = (splay_tree_key)orig_value; + bfd_vma orig_end = orig_value + *size; + splay_tree_node node = splay_tree_predecessor (pdops, key); + + if (node) + { + bfd_vma addr = (bfd_vma)node->key; + struct pending_delete_op *op = (struct pending_delete_op *)node->value; + + /* This shouldn't happen unless people write something really insane like + .reloc ., R_LARCH_ALIGN, 60 + .rept 15 + 1: nop + .endr + .set x, 1b + .size x, . - 1b + But let's just try to make it "work" anyway. */ + if (orig_value < addr + op->size) + { + bfd_size_type n_deleted = op->size - (orig_value - addr); + if (n_deleted >= *size) + { + *size = 0; + return; + } + + *size -= n_deleted; + } + } + + node = splay_tree_lookup (pdops, key); + if (!node) + node = splay_tree_successor (pdops, key); + + for (; node; node = splay_tree_successor (pdops, node->key)) + { + bfd_vma addr = (bfd_vma)node->key; + struct pending_delete_op *op = (struct pending_delete_op *)node->value; + + if (addr >= orig_end) + return; + + if (orig_end < addr + op->size) + *size -= orig_end - addr; + else + *size -= op->size; + } +} + static void loongarch_relax_perform_deletes (bfd *abfd, asection *sec, struct bfd_link_info *link_info) @@ -5001,30 +5055,8 @@ loongarch_relax_perform_deletes (bfd *abfd, asection *sec, sym->st_value = loongarch_calc_relaxed_addr (link_info, orig_value); - /* If the symbol *spans* some deleted bytes, that is its *end* is in - the moved bytes but its *start* isn't, then we must adjust its - size. - - This test needs to use the original value of st_value, otherwise - we might accidentally decrease size when deleting bytes right - before the symbol. */ - bfd_vma sym_end = orig_value + sym->st_size; - if (sym_end <= toaddr) - { - splay_tree_node node = splay_tree_predecessor ( - pdops, (splay_tree_key)orig_value); - for (; node; node = splay_tree_successor (pdops, node->key)) - { - bfd_vma addr = (bfd_vma)node->key; - struct pending_delete_op *op - = (struct pending_delete_op *)node->value; - - if (addr >= sym_end) - break; - if (orig_value <= addr && sym_end > addr) - sym->st_size -= op->size; - } - } + if (orig_value + sym->st_size <= toaddr) + loongarch_relax_resize_symbol (&sym->st_size, orig_value, pdops); } } @@ -5071,29 +5103,13 @@ loongarch_relax_perform_deletes (bfd *abfd, asection *sec, { bfd_vma orig_value = sym_hash->root.u.def.value; - /* As above, adjust the value. */ + /* As above, adjust the value and size. */ if (orig_value <= toaddr) sym_hash->root.u.def.value = loongarch_calc_relaxed_addr (link_info, orig_value); - /* As above, adjust the size if needed. */ - bfd_vma sym_end = orig_value + sym_hash->size; - if (sym_end <= toaddr) - { - splay_tree_node node = splay_tree_predecessor ( - pdops, (splay_tree_key)orig_value); - for (; node; node = splay_tree_successor (pdops, node->key)) - { - bfd_vma addr = (bfd_vma)node->key; - struct pending_delete_op *op - = (struct pending_delete_op *)node->value; - - if (addr >= sym_end) - break; - if (orig_value <= addr && sym_end > addr) - sym_hash->size -= op->size; - } - } + if (orig_value + sym_hash->size <= toaddr) + loongarch_relax_resize_symbol (&sym_hash->size, orig_value, pdops); } } } diff --git a/bfd/format.c b/bfd/format.c index f3a0774..fba8d2a 100644 --- a/bfd/format.c +++ b/bfd/format.c @@ -47,7 +47,6 @@ SUBSECTION #include "bfd.h" #include "libbfd.h" #if BFD_SUPPORTS_PLUGINS -#include "plugin-api.h" #include "plugin.h" #endif @@ -56,19 +55,16 @@ extern const size_t _bfd_target_vector_entries; /* FUNCTION - bfd_check_format_lto + bfd_check_format SYNOPSIS - bool bfd_check_format_lto (bfd *abfd, bfd_format format, - bool lto_sections_removed); + bool bfd_check_format (bfd *abfd, bfd_format format); DESCRIPTION Verify if the file attached to the BFD @var{abfd} is compatible with the format @var{format} (i.e., one of <<bfd_object>>, <<bfd_archive>> or <<bfd_core>>). - If LTO_SECTION_REMOVED is true, ignore plugin target. - If the BFD has been set to a specific target before the call, only the named target and format combination is checked. If the target has not been set, or has been set to @@ -103,30 +99,9 @@ DESCRIPTION */ bool -bfd_check_format_lto (bfd *abfd, bfd_format format, - bool lto_sections_removed) -{ - return bfd_check_format_matches_lto (abfd, format, NULL, - lto_sections_removed); -} - - -/* -FUNCTION - bfd_check_format - -SYNOPSIS - bool bfd_check_format (bfd *abfd, bfd_format format); - -DESCRIPTION - Similar to bfd_check_format_plugin, except plugin target isn't - ignored. -*/ - -bool bfd_check_format (bfd *abfd, bfd_format format) { - return bfd_check_format_matches_lto (abfd, format, NULL, false); + return bfd_check_format_matches (abfd, format, NULL); } struct bfd_preserve @@ -413,6 +388,11 @@ bfd_set_lto_type (bfd *abfd ATTRIBUTE_UNUSED) abfd->object_only_section = sec; break; } + else if (strcmp (sec->name, ".llvm.lto") == 0) + { + type = lto_fat_ir_object; + break; + } else if (lsection.major_version == 0 && startswith (sec->name, ".gnu.lto_.lto.") && bfd_get_section_contents (abfd, sec, &lsection, 0, @@ -431,36 +411,32 @@ bfd_set_lto_type (bfd *abfd ATTRIBUTE_UNUSED) /* FUNCTION - bfd_check_format_matches_lto + bfd_check_format_matches SYNOPSIS - bool bfd_check_format_matches_lto - (bfd *abfd, bfd_format format, char ***matching, - bool lto_sections_removed); + bool bfd_check_format_matches + (bfd *abfd, bfd_format format, char ***matching); DESCRIPTION Like <<bfd_check_format>>, except when it returns FALSE with - <<bfd_errno>> set to <<bfd_error_file_ambiguously_recognized>>. In that - case, if @var{matching} is not NULL, it will be filled in with - a NULL-terminated list of the names of the formats that matched, - allocated with <<malloc>>. + <<bfd_errno>> set to <<bfd_error_file_ambiguously_recognized>>. + In that case, if @var{matching} is not NULL, it will be filled + in with a NULL-terminated list of the names of the formats + that matched, allocated with <<malloc>>. Then the user may choose a format and try again. When done with the list that @var{matching} points to, the caller should free it. - - If LTO_SECTION_REMOVED is true, ignore plugin target. */ bool -bfd_check_format_matches_lto (bfd *abfd, bfd_format format, - char ***matching, - bool lto_sections_removed ATTRIBUTE_UNUSED) +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; + const bfd_target *fail_targ; int match_count, best_count, best_match; int ar_match_index; unsigned int initial_section_id = _bfd_section_id; @@ -481,10 +457,7 @@ bfd_check_format_matches_lto (bfd *abfd, bfd_format format, } if (abfd->format != bfd_unknown) - { - bfd_set_lto_type (abfd); - return abfd->format == format; - } + return abfd->format == format; if (matching != NULL || *bfd_associated_vector != NULL) { @@ -524,20 +497,34 @@ bfd_check_format_matches_lto (bfd *abfd, bfd_format format, if (!bfd_preserve_save (abfd, &preserve, NULL)) goto err_ret; - /* If the target type was explicitly specified, just check that target. - If LTO_SECTION_REMOVED is true, don't match the plugin target. */ + /* If the target type was explicitly specified, just check that target. */ + fail_targ = NULL; if (!abfd->target_defaulted #if BFD_SUPPORTS_PLUGINS - && (!lto_sections_removed || !bfd_plugin_target_p (abfd->xvec)) + && !(abfd->plugin_format == bfd_plugin_no + && bfd_plugin_target_p (save_targ)) #endif - ) + ) { if (bfd_seek (abfd, 0, SEEK_SET) != 0) /* rewind! */ goto err_ret; cleanup = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd)); - if (cleanup) + /* When called from strip, don't treat archive member nor + standalone fat IR object as an IR object. For archive + member, it will be copied as an unknown object if the + plugin target is in use or it is a slim IR object. For + standalone fat IR object, it will be copied as non-IR + object. */ + if (cleanup +#if BFD_SUPPORTS_PLUGINS + && (!abfd->is_strip_input + || !bfd_plugin_target_p (abfd->xvec) + || (abfd->lto_type != lto_fat_ir_object + && abfd->my_archive == NULL)) +#endif + ) goto ok_ret; /* For a long time the code has dropped through to check all @@ -554,10 +541,10 @@ bfd_check_format_matches_lto (bfd *abfd, bfd_format format, target. */ if (format == bfd_archive && save_targ == &binary_vec) goto err_unrecog; + fail_targ = save_targ; } - /* Since the target type was defaulted, check them all in the hope - that one will be uniquely recognized. */ + /* Check all targets in the hope that one will be recognized. */ right_targ = NULL; ar_right_targ = NULL; match_targ = NULL; @@ -571,26 +558,26 @@ bfd_check_format_matches_lto (bfd *abfd, bfd_format format, void **high_water; /* The binary target matches anything, so don't return it when - searching. Don't match the plugin target if we have another - alternative since we want to properly set the input format - before allowing a plugin to claim the file. Also, don't - check the default target twice. If LTO_SECTION_REMOVED is - true, don't match the plugin target. */ + searching. Also, don't check the current target twice when + it has failed already. + Don't match the plugin target during linking if we have + another alternative since we want to properly set the input + format before allowing a plugin to claim the file. + Also as an optimisation don't match the plugin target when + abfd->plugin_format is set to bfd_plugin_no. (This occurs + when LTO sections have been stripped or when we have a + recursive call here from the plugin object_p via + bfd_plugin_get_symbols_in_object_only.) */ if (*target == &binary_vec + || *target == fail_targ #if BFD_SUPPORTS_PLUGINS - || ((lto_sections_removed || match_count != 0) + || (((abfd->is_linker_input && match_count != 0) + || abfd->plugin_format == bfd_plugin_no) && bfd_plugin_target_p (*target)) #endif - || (!abfd->target_defaulted && *target == save_targ)) + ) continue; -#if BFD_SUPPORTS_PLUGINS - /* If the plugin target is explicitly specified when a BFD file - is opened, don't check it twice. */ - if (bfd_plugin_specified_p () && bfd_plugin_target_p (*target)) - continue; -#endif - /* If we already tried a match, the bfd is modified and may have sections attached, which will confuse the next _bfd_check_format call. */ @@ -833,32 +820,6 @@ bfd_check_format_matches_lto (bfd *abfd, bfd_format format, /* FUNCTION - bfd_check_format_matches - -SYNOPSIS - bool bfd_check_format_matches - (bfd *abfd, bfd_format format, char ***matching); - -DESCRIPTION - Like <<bfd_check_format>>, except when it returns FALSE with - <<bfd_errno>> set to <<bfd_error_file_ambiguously_recognized>>. In that - case, if @var{matching} is not NULL, it will be filled in with - a NULL-terminated list of the names of the formats that matched, - allocated with <<malloc>>. - Then the user may choose a format and try again. - - When done with the list that @var{matching} points to, the caller - should free it. -*/ - -bool -bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching) -{ - return bfd_check_format_matches_lto (abfd, format, matching, false); -} - -/* -FUNCTION bfd_set_format SYNOPSIS diff --git a/bfd/plugin.c b/bfd/plugin.c index 1c72b74..733e7f0 100644 --- a/bfd/plugin.c +++ b/bfd/plugin.c @@ -138,6 +138,14 @@ struct plugin_list_entry const char *plugin_name; }; +struct plugin_data_struct +{ + int nsyms; + const struct ld_plugin_symbol *syms; + int object_only_nsyms; + asymbol **object_only_syms; +}; + static const char *plugin_program_name; void @@ -196,16 +204,23 @@ bfd_plugin_get_symbols_in_object_only (bfd *abfd) abfd->filename, bfd_errmsg (bfd_get_error ())); return; } - else if (!bfd_check_format (nbfd, bfd_object)) + /* Prevent this recursive call into bfd_check_format from + attempting to load the plugin again while it is running. */ + nbfd->plugin_format = bfd_plugin_no; + if (!bfd_check_format (nbfd, bfd_object)) { /* There is no object only section if it isn't a bfd_object file. */ bfd_close (nbfd); return; } + + /* Copy LTO type derived from input sections. */ + abfd->lto_type = nbfd->lto_type; } else { + BFD_ASSERT (abfd->plugin_format == bfd_plugin_no); if (!bfd_check_format (abfd, bfd_object)) { (*_bfd_error_handler) @@ -239,6 +254,9 @@ bfd_plugin_get_symbols_in_object_only (bfd *abfd) /* Open the file containing object only section. */ nbfd = bfd_openr (object_only_file, NULL); + /* Prevent this recursive call into bfd_check_format from + attempting to load the plugin again while it is running. */ + nbfd->plugin_format = bfd_plugin_no; if (!bfd_check_format (nbfd, bfd_object)) { (*_bfd_error_handler) @@ -326,9 +344,8 @@ add_symbols (void * handle, const struct ld_plugin_symbol * syms) { bfd *abfd = handle; - struct plugin_data_struct *plugin_data = - bfd_alloc (abfd, sizeof (plugin_data_struct)); - + struct plugin_data_struct *plugin_data = bfd_alloc (abfd, + sizeof (*plugin_data)); if (!plugin_data) return LDPS_ERR; @@ -598,6 +615,10 @@ try_load_plugin (const char *pname, if (status != LDPS_OK) goto short_circuit; + /* Setting bfd_plugin_no here prevents recursive calls into + bfd_check_format from within the plugin (unless the plugin opens + another bfd.) Attempting to load the plugin again while it is + running is *not* a good idea. */ abfd->plugin_format = bfd_plugin_no; if (!current_plugin->claim_file) @@ -627,14 +648,6 @@ bfd_plugin_set_plugin (const char *p) plugin_name = p; } -/* Return TRUE if a plugin library is used. */ - -bool -bfd_plugin_specified_p (void) -{ - return plugin_list != NULL; -} - /* Return TRUE if ABFD can be claimed by linker LTO plugin. */ bool diff --git a/bfd/plugin.h b/bfd/plugin.h index f61e616..d981c51 100644 --- a/bfd/plugin.h +++ b/bfd/plugin.h @@ -21,22 +21,14 @@ #ifndef _PLUGIN_H_ #define _PLUGIN_H_ +struct ld_plugin_input_file; + void bfd_plugin_set_program_name (const char *); int bfd_plugin_open_input (bfd *, struct ld_plugin_input_file *); void bfd_plugin_set_plugin (const char *); bool bfd_plugin_target_p (const bfd_target *); -bool bfd_plugin_specified_p (void); bool bfd_link_plugin_object_p (bfd *); void register_ld_plugin_object_p (bfd_cleanup (*object_p) (bfd *, bool)); void bfd_plugin_close_file_descriptor (bfd *, int); -typedef struct plugin_data_struct -{ - int nsyms; - const struct ld_plugin_symbol *syms; - int object_only_nsyms; - asymbol **object_only_syms; -} -plugin_data_struct; - #endif diff --git a/bfd/version.h b/bfd/version.h index 882d0b0..89f11ee 100644 --- a/bfd/version.h +++ b/bfd/version.h @@ -16,7 +16,7 @@ In releases, the date is not included in either version strings or sonames. */ -#define BFD_VERSION_DATE 20250805 +#define BFD_VERSION_DATE 20250807 #define BFD_VERSION @bfd_version@ #define BFD_VERSION_STRING @bfd_version_package@ @bfd_version_string@ #define REPORT_BUGS_TO @report_bugs_to@ |