aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/archive.c10
-rw-r--r--bfd/bfd-in2.h10
-rw-r--r--bfd/bfd.c3
-rw-r--r--bfd/elfnn-loongarch.c102
-rw-r--r--bfd/format.c144
-rw-r--r--bfd/plugin.c24
-rw-r--r--bfd/plugin.h1
-rw-r--r--bfd/version.h2
-rw-r--r--binutils/nm.c9
-rw-r--r--binutils/objcopy.c57
-rw-r--r--gdb/arm-linux-tdep.c5
-rw-r--r--gdb/breakpoint.c25
-rw-r--r--gdb/breakpoint.h8
-rw-r--r--gdb/gdbarch-gen.h12
-rw-r--r--gdb/gdbarch_components.py12
-rw-r--r--gdb/infrun.c19
-rw-r--r--gdb/record-full.c4
-rw-r--r--gdb/testsuite/lib/gdb.exp4
-rw-r--r--ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp2
-rw-r--r--ld/testsuite/ld-loongarch-elf/relax-sym-size-1.d7
-rw-r--r--ld/testsuite/ld-loongarch-elf/relax-sym-size-1.s8
-rw-r--r--ld/testsuite/ld-loongarch-elf/relax-sym-size-2.d7
-rw-r--r--ld/testsuite/ld-loongarch-elf/relax-sym-size-2.s19
-rw-r--r--ld/testsuite/ld-plugin/lto-binutils.exp175
-rw-r--r--ld/testsuite/ld-plugin/pr33246.c4
25 files changed, 468 insertions, 205 deletions
diff --git a/bfd/archive.c b/bfd/archive.c
index c61d4b1..697b2ed 100644
--- a/bfd/archive.c
+++ b/bfd/archive.c
@@ -141,6 +141,10 @@ SUBSECTION
#include "hashtab.h"
#include "filenames.h"
#include "bfdlink.h"
+#if BFD_SUPPORTS_PLUGINS
+#include "plugin-api.h"
+#include "plugin.h"
+#endif
#ifndef errno
extern int errno;
@@ -2343,6 +2347,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 +2407,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);
diff --git a/bfd/bfd.c b/bfd/bfd.c
index 858ab5c..4aded68 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -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;
.
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..bd9fa8d 100644
--- a/bfd/format.c
+++ b/bfd/format.c
@@ -56,19 +56,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 +100,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 +389,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 +412,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 +458,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 +498,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 +542,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 +559,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 +821,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..43ca444 100644
--- a/bfd/plugin.c
+++ b/bfd/plugin.c
@@ -196,16 +196,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 +246,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)
@@ -598,6 +608,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 +641,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..6acb5fa 100644
--- a/bfd/plugin.h
+++ b/bfd/plugin.h
@@ -25,7 +25,6 @@ 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);
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@
diff --git a/binutils/nm.c b/binutils/nm.c
index a5d5631..d44083d 100644
--- a/binutils/nm.c
+++ b/binutils/nm.c
@@ -802,6 +802,9 @@ filter_symbols (bfd *abfd, bool is_dynamic, void *minisyms,
continue;
if (bfd_lto_slim_symbol_p (abfd, sym->name)
+#if BFD_SUPPORTS_PLUGINS
+ && !bfd_plugin_target_p (abfd->xvec)
+#endif
&& report_plugin_err)
{
report_plugin_err = false;
@@ -1484,7 +1487,11 @@ display_rel_file (bfd *abfd, bfd *archive_bfd)
/* lto_type is set to lto_non_ir_object when a bfd is loaded with a
compiler LTO plugin. */
- if (bfd_get_lto_type (abfd) == lto_slim_ir_object)
+ if (bfd_get_lto_type (abfd) == lto_slim_ir_object
+#if BFD_SUPPORTS_PLUGINS
+ && !bfd_plugin_target_p (abfd->xvec)
+#endif
+ )
{
report_plugin_err = false;
non_fatal (_("%s: plugin needed to handle lto object"),
diff --git a/binutils/objcopy.c b/binutils/objcopy.c
index 5774711..3404bec 100644
--- a/binutils/objcopy.c
+++ b/binutils/objcopy.c
@@ -170,6 +170,8 @@ static bool sections_removed;
#if BFD_SUPPORTS_PLUGINS
/* TRUE if all GCC LTO sections are to be removed. */
static bool lto_sections_removed;
+#else
+#define lto_sections_removed false
#endif
/* TRUE if only some sections are to be copied. */
@@ -3687,6 +3689,8 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
bool ok_object;
const char *element_name;
+ this_element->is_strip_input = 1;
+
element_name = bfd_get_filename (this_element);
/* PR binutils/17533: Do not allow directory traversal
outside of the current directory tree by archive members. */
@@ -3745,11 +3749,10 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
#if BFD_SUPPORTS_PLUGINS
/* Ignore plugin target if all LTO sections should be removed. */
- ok_object = bfd_check_format_lto (this_element, bfd_object,
- lto_sections_removed);
-#else
- ok_object = bfd_check_format (this_element, bfd_object);
+ if (lto_sections_removed)
+ this_element->plugin_format = bfd_plugin_no;
#endif
+ ok_object = bfd_check_format (this_element, bfd_object);
/* PR binutils/3110: Cope with archives
containing multiple target types. */
@@ -3768,7 +3771,9 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
#if BFD_SUPPORTS_PLUGINS
/* Copy LTO IR file as unknown object. */
- if (bfd_plugin_target_p (this_element->xvec))
+ if ((!lto_sections_removed
+ && this_element->lto_type == lto_slim_ir_object)
+ || bfd_plugin_target_p (this_element->xvec))
ok_object = false;
else
#endif
@@ -3863,6 +3868,25 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
return ok;
}
+static bool
+check_format_object (bfd *ibfd, char ***obj_matching,
+ bool no_plugins ATTRIBUTE_UNUSED)
+{
+#if BFD_SUPPORTS_PLUGINS
+ /* Ignore plugin target first if all LTO sections should be
+ removed. Try with plugin target next if ignoring plugin
+ target fails to match the format. */
+ if (no_plugins && ibfd->plugin_format == bfd_plugin_unknown)
+ {
+ ibfd->plugin_format = bfd_plugin_no;
+ if (bfd_check_format_matches (ibfd, bfd_object, obj_matching))
+ return true;
+ ibfd->plugin_format = bfd_plugin_unknown;
+ }
+#endif
+ return bfd_check_format_matches (ibfd, bfd_object, obj_matching);
+}
+
/* The top-level control. */
static void
@@ -3946,6 +3970,8 @@ copy_file (const char *input_filename, const char *output_filename, int ofd,
break;
}
+ ibfd->is_strip_input = 1;
+
if (bfd_check_format (ibfd, bfd_archive))
{
bool force_output_target;
@@ -3988,21 +4014,7 @@ copy_file (const char *input_filename, const char *output_filename, int ofd,
input_arch, target_defaulted))
status = 1;
}
- else if (
-#if BFD_SUPPORTS_PLUGINS
- /* Ignore plugin target first if all LTO sections should be
- removed. Try with plugin target next if ignoring plugin
- target fails to match the format. */
- bfd_check_format_matches_lto (ibfd, bfd_object, &obj_matching,
- lto_sections_removed)
- || (lto_sections_removed
- && bfd_check_format_matches_lto (ibfd, bfd_object,
- &obj_matching, false))
-#else
- bfd_check_format_matches_lto (ibfd, bfd_object, &obj_matching,
- false)
-#endif
- )
+ else if (check_format_object (ibfd, &obj_matching, lto_sections_removed))
{
bfd *obfd;
do_copy:
@@ -5066,6 +5078,11 @@ strip_main (int argc, char *argv[])
SECTION_CONTEXT_REMOVE)
|| !!find_section_list (".llvm.lto", false,
SECTION_CONTEXT_REMOVE));
+ /* NB: Must keep .gnu.debuglto_* sections unless all GCC LTO sections
+ will be removed to avoid undefined references to symbols in GCC LTO
+ debug sections. */
+ if (!lto_sections_removed)
+ find_section_list (".gnu.debuglto_*", true, SECTION_CONTEXT_KEEP);
#endif
i = optind;
diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
index 2f034af..08526d8 100644
--- a/gdb/arm-linux-tdep.c
+++ b/gdb/arm-linux-tdep.c
@@ -960,6 +960,11 @@ arm_linux_software_single_step (struct regcache *regcache)
struct gdbarch *gdbarch = regcache->arch ();
struct arm_get_next_pcs next_pcs_ctx;
+ /* If the target does have hardware single step, GDB doesn't have
+ to bother software single step. */
+ if (target_can_do_single_step () == 1)
+ return {};
+
arm_get_next_pcs_ctor (&next_pcs_ctx,
&arm_linux_get_next_pcs_ops,
gdbarch_byte_order (gdbarch),
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index f795d7b..d704ad1 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -13998,26 +13998,11 @@ insert_single_step_breakpoint (struct gdbarch *gdbarch,
update_global_location_list (UGLL_INSERT);
}
-/* Try to setup for software single stepping. Return true if
- target_resume() should use hardware single step.
+/* Insert single step breakpoints according to the current state. */
- GDBARCH is the current gdbarch. */
-
-bool
-maybe_software_singlestep (struct gdbarch *gdbarch)
+int
+insert_single_step_breakpoints (struct gdbarch *gdbarch)
{
- if (execution_direction != EXEC_FORWARD)
- return true;
-
- if (target_can_do_single_step () == 1)
- {
- /* The target definitely has hardware single step. */
- return true;
- }
-
- if (!gdbarch_software_single_step_p (gdbarch))
- return true;
-
regcache *regcache = get_thread_regcache (inferior_thread ());
std::vector<CORE_ADDR> next_pcs;
@@ -14031,10 +14016,10 @@ maybe_software_singlestep (struct gdbarch *gdbarch)
for (CORE_ADDR pc : next_pcs)
insert_single_step_breakpoint (gdbarch, aspace, pc);
- return false;
+ return 1;
}
else
- return true;
+ return 0;
}
/* See breakpoint.h. */
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index e9201bc..9341112 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -1884,10 +1884,10 @@ extern void insert_single_step_breakpoint (struct gdbarch *,
const address_space *,
CORE_ADDR);
-/* Try to setup for software single stepping. Return true if
- target_resume() should use hardware single step. GDBARCH is the
- current gdbarch. */
-extern bool maybe_software_singlestep (struct gdbarch *);
+/* Insert all software single step breakpoints for the current frame.
+ Return true if any software single step breakpoints are inserted,
+ otherwise, return false. */
+extern int insert_single_step_breakpoints (struct gdbarch *);
/* Check whether any hardware watchpoints have triggered or not,
according to the target, and record it in each watchpoint's
diff --git a/gdb/gdbarch-gen.h b/gdb/gdbarch-gen.h
index 1e51081..281b97b 100644
--- a/gdb/gdbarch-gen.h
+++ b/gdb/gdbarch-gen.h
@@ -776,10 +776,16 @@ extern void set_gdbarch_get_memtag (struct gdbarch *gdbarch, gdbarch_get_memtag_
extern CORE_ADDR gdbarch_memtag_granule_size (struct gdbarch *gdbarch);
extern void set_gdbarch_memtag_granule_size (struct gdbarch *gdbarch, CORE_ADDR memtag_granule_size);
-/* Return a vector of addresses at which the software single step
- breakpoints should be inserted. An empty vector means software single
- step is not used.
+/* FIXME/cagney/2001-01-18: This should be split in two. A target method that
+ indicates if the target needs software single step. An ISA method to
+ implement it.
+ FIXME/cagney/2001-01-18: The logic is backwards. It should be asking if the
+ target can single step. If not, then implement single step using breakpoints.
+
+ Return a vector of addresses on which the software single step
+ breakpoints should be inserted. NULL means software single step is
+ not used.
Multiple breakpoints may be inserted for some instructions such as
conditional branch. However, each implementation must always evaluate
the condition and only put the breakpoint at the branch destination if
diff --git a/gdb/gdbarch_components.py b/gdb/gdbarch_components.py
index 55df102..91c867e 100644
--- a/gdb/gdbarch_components.py
+++ b/gdb/gdbarch_components.py
@@ -1378,10 +1378,16 @@ For a non-zero value, this represents the number of bytes of memory per tag.
Function(
comment="""
-Return a vector of addresses at which the software single step
-breakpoints should be inserted. An empty vector means software single
-step is not used.
+FIXME/cagney/2001-01-18: This should be split in two. A target method that
+indicates if the target needs software single step. An ISA method to
+implement it.
+FIXME/cagney/2001-01-18: The logic is backwards. It should be asking if the
+target can single step. If not, then implement single step using breakpoints.
+
+Return a vector of addresses on which the software single step
+breakpoints should be inserted. NULL means software single step is
+not used.
Multiple breakpoints may be inserted for some instructions such as
conditional branch. However, each implementation must always evaluate
the condition and only put the breakpoint at the branch destination if
diff --git a/gdb/infrun.c b/gdb/infrun.c
index e0e9ffa..9d3e1b7 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -93,6 +93,8 @@ static void insert_step_resume_breakpoint_at_caller (const frame_info_ptr &);
static void insert_longjmp_resume_breakpoint (struct gdbarch *, CORE_ADDR);
+static bool maybe_software_singlestep (struct gdbarch *gdbarch);
+
static void resume (gdb_signal sig);
static void wait_for_inferior (inferior *inf);
@@ -2357,6 +2359,23 @@ set_schedlock_func (const char *args, int from_tty, struct cmd_list_element *c)
process. */
bool sched_multi = false;
+/* Try to setup for software single stepping. Return true if target_resume()
+ should use hardware single step.
+
+ GDBARCH the current gdbarch. */
+
+static bool
+maybe_software_singlestep (struct gdbarch *gdbarch)
+{
+ bool hw_step = true;
+
+ if (execution_direction == EXEC_FORWARD
+ && gdbarch_software_single_step_p (gdbarch))
+ hw_step = !insert_single_step_breakpoints (gdbarch);
+
+ return hw_step;
+}
+
/* See infrun.h. */
ptid_t
diff --git a/gdb/record-full.c b/gdb/record-full.c
index 7d4ef87..7e3da27 100644
--- a/gdb/record-full.c
+++ b/gdb/record-full.c
@@ -1105,7 +1105,7 @@ record_full_target::resume (ptid_t ptid, int step, enum gdb_signal signal)
record_full_resume_step = 1;
}
else
- step = maybe_software_singlestep (gdbarch);
+ step = !insert_single_step_breakpoints (gdbarch);
}
}
@@ -1277,7 +1277,7 @@ record_full_wait_1 (struct target_ops *ops,
};
reinit_frame_cache ();
- step = maybe_software_singlestep (gdbarch);
+ step = !insert_single_step_breakpoints (gdbarch);
}
if (record_debug)
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 0a582aa..98691df 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -5729,6 +5729,10 @@ proc gdb_simple_compile {name code {type object} {compile_flags {}} {object obj}
set ext "d"
break
}
+ if { "$flag" eq "rust" } {
+ set ext "rs"
+ break
+ }
}
set src [standard_temp_file $name.$ext]
set obj [standard_temp_file $name.$postfix]
diff --git a/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp b/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
index e23cdc8..a33727f 100644
--- a/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
+++ b/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
@@ -48,6 +48,8 @@ if [istarget "loongarch64-*-*"] {
run_dump_test "relax-after-alignment"
run_dump_test "relax-medium-call"
run_dump_test "relax-medium-call-1"
+ run_dump_test "relax-sym-size-1"
+ run_dump_test "relax-sym-size-2"
run_dump_test "check_got_relax"
}
diff --git a/ld/testsuite/ld-loongarch-elf/relax-sym-size-1.d b/ld/testsuite/ld-loongarch-elf/relax-sym-size-1.d
new file mode 100644
index 0000000..eec989f
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/relax-sym-size-1.d
@@ -0,0 +1,7 @@
+#source: relax-sym-size-1.s
+#ld:
+#readelf: -s
+
+#...
+ *[0-9]+: [0-9a-z]+ +8 .* _start
+#...
diff --git a/ld/testsuite/ld-loongarch-elf/relax-sym-size-1.s b/ld/testsuite/ld-loongarch-elf/relax-sym-size-1.s
new file mode 100644
index 0000000..c70ac71
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/relax-sym-size-1.s
@@ -0,0 +1,8 @@
+.p2align 2
+bar:
+ nop
+.globl _start
+_start:
+ la.pcrel $a0, bar
+ ret
+.size _start, . - _start
diff --git a/ld/testsuite/ld-loongarch-elf/relax-sym-size-2.d b/ld/testsuite/ld-loongarch-elf/relax-sym-size-2.d
new file mode 100644
index 0000000..1388099
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/relax-sym-size-2.d
@@ -0,0 +1,7 @@
+#source: relax-sym-size-2.s
+#ld:
+#readelf: -s
+
+#...
+ *[0-9]+: [0-9a-z]+ +64 .* _start
+#...
diff --git a/ld/testsuite/ld-loongarch-elf/relax-sym-size-2.s b/ld/testsuite/ld-loongarch-elf/relax-sym-size-2.s
new file mode 100644
index 0000000..e02e16b
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/relax-sym-size-2.s
@@ -0,0 +1,19 @@
+bar:
+ nop
+.p2align 6
+
+.reloc ., R_LARCH_ALIGN, 60
+.rept 15
+ 1: nop
+.endr
+ la.pcrel $a0, bar
+ ret
+
+.reloc ., R_LARCH_ALIGN, 60
+.rept 15
+ 2: nop
+.endr
+
+.globl _start
+.set _start, 1b
+.size _start, 2b - 1b
diff --git a/ld/testsuite/ld-plugin/lto-binutils.exp b/ld/testsuite/ld-plugin/lto-binutils.exp
index 88d3517..de017f0 100644
--- a/ld/testsuite/ld-plugin/lto-binutils.exp
+++ b/ld/testsuite/ld-plugin/lto-binutils.exp
@@ -355,3 +355,178 @@ run_cc_link_tests [list \
"tmpdir/libstrip-1b-fat-s.a" \
] \
]
+
+proc run_pr33246_test { llvm fat } {
+ global srcdir
+ global subdir
+ global plug_opt
+ global llvm_plug_opt
+ global ar
+ global CLANG_FOR_TARGET
+ global CC_FOR_TARGET
+ global NM
+ global READELF
+ global strip
+
+ set strip_flags "--strip-debug --enable-deterministic-archives"
+
+ set test pr33246
+ set testname "${test}${llvm}${fat} with $strip_flags"
+
+ if { "$llvm" == "-llvm" } {
+ # Skip native x32 and i?86 targets since system LLVMgold.so may
+ # not be compatible with native x32 and i?86 targets binutils.
+ if { [istarget "x86_64-*-linux*-gnux32"]
+ || [istarget "i?86-*-*"]
+ || ![info exists CLANG_FOR_TARGET]
+ || [string match "" $llvm_plug_opt] } then {
+ untested $testname
+ return
+ }
+ set CC $CLANG_FOR_TARGET
+ set binutils_plug_opt "$llvm_plug_opt"
+ } else {
+ if { ![info exists CC_FOR_TARGET]
+ || [string match "" $plug_opt] } then {
+ untested $testname
+ return
+ }
+ set CC $CC_FOR_TARGET
+ set binutils_plug_opt "$plug_opt"
+ }
+
+ append strip_flags " $binutils_plug_opt"
+
+ set src $srcdir/$subdir/${test}.c
+ set obj tmpdir/${test}${llvm}${fat}.o
+ set archive tmpdir/${test}${llvm}${fat}.a
+ set CFLAGS "-c -g -O2 -flto"
+ if { "$fat" == "-fat" } {
+ append CFLAGS " -ffat-lto-objects"
+ } else {
+ append CFLAGS " -fno-fat-lto-objects"
+ }
+
+ set cmd "$CC $CFLAGS -o $obj $src"
+ send_log "$cmd\n"
+ verbose "$cmd" 1
+ catch "exec $cmd" got
+ if ![string match "" $got] then {
+ send_log "$got\n"
+ verbose "$got" 1
+ fail "$testname ($obj)"
+ return
+ }
+
+ set cmd "$strip $strip_flags $obj -o ${obj}.strip"
+ send_log "$cmd\n"
+ verbose "$cmd" 1
+ catch "exec $cmd" got
+ if ![string match "" $got] then {
+ send_log "$got\n"
+ verbose "$got" 1
+ fail "$testname (strip $obj)"
+ return
+ }
+
+ set cmd "$NM $binutils_plug_opt ${obj}.strip"
+ send_log "$cmd\n"
+ verbose "$cmd" 1
+ catch "exec $cmd" got
+ if ![regexp "0+ T foo" $got] then {
+ send_log "$got\n"
+ verbose "$got" 1
+ fail "$testname (strip $obj)"
+ return
+ }
+
+ if { "$fat" == "-fat" } {
+ set cmd "$READELF -SW ${obj}.strip"
+ send_log "$cmd\n"
+ verbose "$cmd" 1
+ catch "exec $cmd" got
+ if [regexp " \.debug_" $got] then {
+ send_log "$got\n"
+ verbose "$got" 1
+ fail "$testname (strip $obj)"
+ return
+ }
+ } else {
+ set cmd "cmp $obj ${obj}.strip"
+ send_log "$cmd\n"
+ verbose "$cmd" 1
+ catch "exec $cmd" got
+ if ![string match "" $got] then {
+ send_log "$got\n"
+ verbose "$got" 1
+ fail "$testname (strip $obj)"
+ return
+ }
+ }
+
+ pass "$testname (strip $obj)"
+
+ set cmd "$ar $binutils_plug_opt -D -s -r -c $archive $obj"
+ send_log "$cmd\n"
+ verbose "$cmd" 1
+ catch "exec $cmd" got
+ if ![string match "" $got] then {
+ send_log "$got\n"
+ verbose "$got" 1
+ fail "$testname ($archive)"
+ return
+ }
+
+ set cmd "$strip $strip_flags $archive -o ${archive}.strip"
+ send_log "$cmd\n"
+ verbose "$cmd" 1
+ catch "exec $cmd" got
+ if ![string match "" $got] then {
+ send_log "$got\n"
+ verbose "$got" 1
+ fail "$testname (strip $archive)"
+ return
+ }
+
+ set cmd "$NM $binutils_plug_opt ${archive}.strip"
+ send_log "$cmd\n"
+ verbose "$cmd" 1
+ catch "exec $cmd" got
+ if ![regexp "0+ T foo" $got] then {
+ send_log "$got\n"
+ verbose "$got" 1
+ fail "$testname (strip $archive)"
+ return
+ }
+
+ if { "$fat" == "-fat" } {
+ set cmd "$READELF -SW ${archive}.strip"
+ send_log "$cmd\n"
+ verbose "$cmd" 1
+ catch "exec $cmd" got
+ if [regexp " \.debug_" $got] then {
+ send_log "$got\n"
+ verbose "$got" 1
+ fail "$testname (strip $archive)"
+ return
+ }
+ } else {
+ set cmd "cmp $archive ${archive}.strip"
+ send_log "$cmd\n"
+ verbose "$cmd" 1
+ catch "exec $cmd" got
+ if ![string match "" $got] then {
+ send_log "$got\n"
+ verbose "$got" 1
+ fail "$testname (strip $archive)"
+ return
+ }
+ }
+
+ pass "$testname (strip $archive)"
+}
+
+run_pr33246_test "" ""
+run_pr33246_test "" "-fat"
+run_pr33246_test "-llvm" ""
+run_pr33246_test "-llvm" "-fat"
diff --git a/ld/testsuite/ld-plugin/pr33246.c b/ld/testsuite/ld-plugin/pr33246.c
new file mode 100644
index 0000000..cd0130c
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr33246.c
@@ -0,0 +1,4 @@
+void
+foo (void)
+{
+}