aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2018-12-06 11:45:41 -0800
committerH.J. Lu <hjl.tools@gmail.com>2024-03-26 07:17:17 -0700
commitbb9a951fab7a30cc1209c6b8b1716c13456e8b1a (patch)
treec3defd5dc0641dbcd0872ea9b5a738bff9262a2d
parentf4c19f89ef43dbce8065532c808e1aeb05d08994 (diff)
downloadgdb-bb9a951fab7a30cc1209c6b8b1716c13456e8b1a.zip
gdb-bb9a951fab7a30cc1209c6b8b1716c13456e8b1a.tar.gz
gdb-bb9a951fab7a30cc1209c6b8b1716c13456e8b1a.tar.bz2
Don't claim a fat IR object if no IR object should be claimed
When the linker sees an input object containing nothing but IR during rescan, it should ignore it (LTO phase is over). But if the input object is a fat IR object, which has non-IR code as well, it should be used to resolve references as if it did not contain any IR at all. This patch adds lto_type to bfd and linker avoids claiming a fat IR object if no IR object should be claimed. bfd/ PR ld/23935 * archive.c (_bfd_compute_and_write_armap): Check bfd_get_lto_type instead of lto_slim_object. * elflink.c (elf_link_add_object_symbols): Likewise. * bfd.c (bfd_lto_object_type): New. (bfd): Remove lto_slim_object and add lto_type. (bfd_get_lto_type): New function. * elf.c (lto_section): Removed. (_bfd_elf_make_section_from_shdr): Don't set lto_slim_object. * format.c: (lto_section): New. (bfd_set_lto_type): New function. (bfd_check_format_matches): Call bfd_set_lto_type. * bfd-in2.h: Regenerated. binutils/ PR ld/23935 * nm.c (display_rel_file): Check bfd_get_lto_type instead of lto_slim_object. ld/ PR ld/23935 * ldmain.c (add_archive_element): Don't claim a fat IR object if no IR object should be claimed. * testsuite/ld-plugin/lto.exp (pr20103): Adjust fat IR test. Add PR ld/23935 test. * testsuite/ld-plugin/pr23935a.c: New file. * testsuite/ld-plugin/pr23935b.c: Likewise.
-rw-r--r--bfd/archive.c3
-rw-r--r--bfd/bfd-in2.h20
-rw-r--r--bfd/bfd.c20
-rw-r--r--bfd/elf.c22
-rw-r--r--bfd/elflink.c2
-rw-r--r--bfd/format.c51
-rw-r--r--binutils/nm.c6
-rw-r--r--ld/ldmain.c5
-rw-r--r--ld/testsuite/ld-plugin/lto.exp35
-rw-r--r--ld/testsuite/ld-plugin/pr23935a.c2
-rw-r--r--ld/testsuite/ld-plugin/pr23935b.c2
11 files changed, 131 insertions, 37 deletions
diff --git a/bfd/archive.c b/bfd/archive.c
index 9f3fbce..ad76739 100644
--- a/bfd/archive.c
+++ b/bfd/archive.c
@@ -2355,7 +2355,8 @@ _bfd_compute_and_write_armap (bfd *arch, unsigned int elength)
long symcount;
long src_count;
- if (current->lto_slim_object && report_plugin_err)
+ if (bfd_get_lto_type (current) == lto_slim_ir_object
+ && report_plugin_err)
{
report_plugin_err = false;
_bfd_error_handler
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 1166ddd..b332f5a 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -1954,6 +1954,14 @@ struct bfd_build_id
bfd_byte data[1];
};
+enum bfd_lto_object_type
+ {
+ lto_non_object, /* Not an LTO object. */
+ lto_non_ir_object, /* An object without LTO IR. */
+ lto_slim_ir_object, /* A slim LTO IR object. */
+ lto_fat_ir_object /* A fat LTO IR object. */
+ };
+
struct bfd
{
/* The filename the application opened the BFD with. */
@@ -2155,13 +2163,13 @@ struct bfd
/* Set if this is a plugin output file. */
unsigned int lto_output : 1;
- /* Set if this is a slim LTO object not loaded with a compiler plugin. */
- unsigned int lto_slim_object : 1;
-
/* Do not attempt to modify this file. Set when detecting errors
that BFD is not prepared to handle for objcopy/strip. */
unsigned int read_only : 1;
+ /* LTO object type. */
+ ENUM_BITFIELD (bfd_lto_object_type) lto_type : 2;
+
/* Set to dummy BFD created when claimed by a compiler plug-in
library. */
bfd *plugin_dummy_bfd;
@@ -2303,6 +2311,12 @@ bfd_get_format (const bfd *abfd)
return abfd->format;
}
+static inline enum bfd_lto_object_type
+bfd_get_lto_type (const bfd *abfd)
+{
+ return abfd->lto_type;
+}
+
static inline flagword
bfd_get_file_flags (const bfd *abfd)
{
diff --git a/bfd/bfd.c b/bfd/bfd.c
index 54061a3..e579788 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -74,6 +74,14 @@ EXTERNAL
. bfd_byte data[1];
. };
.
+.enum bfd_lto_object_type
+. {
+. lto_non_object, {* Not an LTO object. *}
+. lto_non_ir_object, {* An object without LTO IR. *}
+. lto_slim_ir_object, {* A slim LTO IR object. *}
+. lto_fat_ir_object {* A fat LTO IR object. *}
+. };
+.
CODE_FRAGMENT
.struct bfd
@@ -278,13 +286,13 @@ CODE_FRAGMENT
. {* Set if this is a plugin output file. *}
. unsigned int lto_output : 1;
.
-. {* Set if this is a slim LTO object not loaded with a compiler plugin. *}
-. unsigned int lto_slim_object : 1;
-.
. {* Do not attempt to modify this file. Set when detecting errors
. that BFD is not prepared to handle for objcopy/strip. *}
. unsigned int read_only : 1;
.
+. {* LTO object type. *}
+. ENUM_BITFIELD (bfd_lto_object_type) lto_type : 2;
+.
. {* Set to dummy BFD created when claimed by a compiler plug-in
. library. *}
. bfd *plugin_dummy_bfd;
@@ -428,6 +436,12 @@ EXTERNAL
. return abfd->format;
.}
.
+.static inline enum bfd_lto_object_type
+.bfd_get_lto_type (const bfd *abfd)
+.{
+. return abfd->lto_type;
+.}
+.
.static inline flagword
.bfd_get_file_flags (const bfd *abfd)
.{
diff --git a/bfd/elf.c b/bfd/elf.c
index 8bffd3c..f771754 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -970,18 +970,6 @@ bfd_elf_group_name (bfd *abfd ATTRIBUTE_UNUSED, const asection *sec)
return NULL;
}
-/* This a copy of lto_section defined in GCC (lto-streamer.h). */
-
-struct lto_section
-{
- int16_t major_version;
- int16_t minor_version;
- unsigned char slim_object;
-
- /* Flags is a private field that is not defined publicly. */
- uint16_t flags;
-};
-
/* Make a BFD section from an ELF section. We store a pointer to the
BFD section in the bfd_section field of the header. */
@@ -1261,16 +1249,6 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
}
}
- /* GCC uses .gnu.lto_.lto.<some_hash> as a LTO bytecode information
- section. */
- if (startswith (name, ".gnu.lto_.lto."))
- {
- struct lto_section lsection;
- if (bfd_get_section_contents (abfd, newsect, &lsection, 0,
- sizeof (struct lto_section)))
- abfd->lto_slim_object = lsection.slim_object;
- }
-
return true;
}
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 5a6cb07..24eb30d 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -4785,7 +4785,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
}
if (!bfd_link_relocatable (info)
- && abfd->lto_slim_object)
+ && bfd_get_lto_type (abfd) == lto_slim_ir_object)
{
_bfd_error_handler
(_("%pB: plugin needed to handle lto object"), abfd);
diff --git a/bfd/format.c b/bfd/format.c
index 8f3fc7e..6d95683 100644
--- a/bfd/format.c
+++ b/bfd/format.c
@@ -278,6 +278,50 @@ null_error_handler (const char *fmt ATTRIBUTE_UNUSED,
{
}
+/* This a copy of lto_section defined in GCC (lto-streamer.h). */
+
+struct lto_section
+{
+ int16_t major_version;
+ int16_t minor_version;
+ unsigned char slim_object;
+
+ /* Flags is a private field that is not defined publicly. */
+ uint16_t flags;
+};
+
+/* Set lto_type in ABFD. */
+
+static void
+bfd_set_lto_type (bfd *abfd ATTRIBUTE_UNUSED)
+{
+#if BFD_SUPPORTS_PLUGINS
+ if (abfd->format == bfd_object
+ && abfd->lto_type == lto_non_object
+ && (abfd->flags & (DYNAMIC | EXEC_P)) == 0)
+ {
+ asection *sec;
+ enum bfd_lto_object_type type = lto_non_ir_object;
+ struct lto_section lsection;
+ /* GCC uses .gnu.lto_.lto.<some_hash> as a LTO bytecode information
+ section. */
+ for (sec = abfd->sections; sec != NULL; sec = sec->next)
+ if (startswith (sec->name, ".gnu.lto_.lto.")
+ && bfd_get_section_contents (abfd, sec, &lsection, 0,
+ sizeof (struct lto_section)))
+ {
+ if (lsection.slim_object)
+ type = lto_slim_ir_object;
+ else
+ type = lto_fat_ir_object;
+ break;
+ }
+
+ abfd->lto_type = type;
+ }
+#endif
+}
+
/*
FUNCTION
bfd_check_format_matches
@@ -327,7 +371,10 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
}
if (abfd->format != bfd_unknown)
- return abfd->format == format;
+ {
+ bfd_set_lto_type (abfd);
+ return abfd->format == format;
+ }
if (matching != NULL || *bfd_associated_vector != NULL)
{
@@ -601,6 +648,8 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
clear_warnmsg (list++);
--in_check_format;
+ bfd_set_lto_type (abfd);
+
/* File position has moved, BTW. */
return true;
}
diff --git a/binutils/nm.c b/binutils/nm.c
index a8e915b..faf27c5 100644
--- a/binutils/nm.c
+++ b/binutils/nm.c
@@ -1466,9 +1466,9 @@ display_rel_file (bfd *abfd, bfd *archive_bfd)
free (dyn_syms);
}
- /* lto_slim_object is set to false when a bfd is loaded with a compiler
- LTO plugin. */
- if (abfd->lto_slim_object)
+ /* 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)
{
report_plugin_err = false;
non_fatal (_("%s: plugin needed to handle lto object"),
diff --git a/ld/ldmain.c b/ld/ldmain.c
index 9ae541a..fe38968 100644
--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -902,7 +902,10 @@ add_archive_element (struct bfd_link_info *info,
BFD, but we still want to output the original BFD filename. */
orig_input = *input;
#if BFD_SUPPORTS_PLUGINS
- if (link_info.lto_plugin_active)
+ /* Don't claim a fat IR object if no IR object should be claimed. */
+ if (link_info.lto_plugin_active
+ && (!no_more_claiming
+ || bfd_get_lto_type (abfd) != lto_fat_ir_object))
{
/* We must offer this archive member to the plugins to claim. */
plugin_maybe_claim (input);
diff --git a/ld/testsuite/ld-plugin/lto.exp b/ld/testsuite/ld-plugin/lto.exp
index cf1691f..259a064 100644
--- a/ld/testsuite/ld-plugin/lto.exp
+++ b/ld/testsuite/ld-plugin/lto.exp
@@ -964,10 +964,20 @@ proc pr20103 {cflags libs} {
set testname "PR ld/20103 ($cflags $libs)"
set exec_output [run_host_cmd "$CC_FOR_TARGET" "$cflags $libs"]
+ # NB: Starting from GCC 4.9, -flto is optional for final link.
+ if { [ regexp "fatpr20103" "$libs" ] \
+ && ([regexp " -flto" "$cflags"] \
+ || [at_least_gcc_version 4 9]) } {
+ set result1good "fail"
+ set result1bad "pass"
+ } {
+ set result1good "pass"
+ set result1bad "fail"
+ }
if { [ regexp "undefined reference to `\\.?dead'" $exec_output ] } {
- pass "$testname (1)"
+ $result1good "$testname (1)"
} {
- fail "$testname (1)"
+ $result1bad "$testname (1)"
}
if { [ regexp "plugin needed to handle lto object" $exec_output ] } {
fail "$testname (2)"
@@ -1026,6 +1036,27 @@ if { [check_lto_fat_available] } {
"-O2" \
{dummy.c} {} "pr20103c" \
] \
+ [list "Build fatpr23935.a" \
+ "$plug_opt" \
+ "-flto -fno-builtin -ffat-lto-objects" \
+ {pr23935a.c} \
+ "" \
+ "fatpr23935.a" \
+ ] \
+ [list "Build pr23935b.o" \
+ "$plug_opt" \
+ "-flto -fno-fat-lto-objects" \
+ {pr23935b.c} \
+ ] \
+ [list \
+ "Build pr23935" \
+ "-static -flto -Wl,-emain -nostdlib tmpdir/pr23935b.o \
+ tmpdir/fatpr23935.a" \
+ "-flto -fno-fat-lto-objects" \
+ {dummy.c} \
+ "" \
+ "pr23935" \
+ ] \
]
pr20103 "-O2 -flto" "tmpdir/thinpr20103a.a tmpdir/thinpr20103b.a tmpdir/thinpr20103c.a"
pr20103 "-O2 -flto" "tmpdir/fatpr20103a.a tmpdir/fatpr20103b.a tmpdir/fatpr20103c.a"
diff --git a/ld/testsuite/ld-plugin/pr23935a.c b/ld/testsuite/ld-plugin/pr23935a.c
new file mode 100644
index 0000000..8c73197
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr23935a.c
@@ -0,0 +1,2 @@
+#include <stdio.h>
+int puts(const char *s) { return 0; }
diff --git a/ld/testsuite/ld-plugin/pr23935b.c b/ld/testsuite/ld-plugin/pr23935b.c
new file mode 100644
index 0000000..58ae07e
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr23935b.c
@@ -0,0 +1,2 @@
+#include <stdio.h>
+int main() { printf("hi\n"); return 0; }