@@ -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
@@ -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)
{
@@ -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)
.{
@@ -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;
}
@@ -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);
@@ -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;
}
@@ -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"),
@@ -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);
@@ -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"
new file mode 100644
@@ -0,0 +1,2 @@
+#include <stdio.h>
+int puts(const char *s) { return 0; }
new file mode 100644
@@ -0,0 +1,2 @@
+#include <stdio.h>
+int main() { printf("hi\n"); return 0; }