diff options
-rw-r--r-- | bfd/archive.c | 3 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 20 | ||||
-rw-r--r-- | bfd/bfd.c | 20 | ||||
-rw-r--r-- | bfd/elf.c | 22 | ||||
-rw-r--r-- | bfd/elflink.c | 2 | ||||
-rw-r--r-- | bfd/format.c | 51 | ||||
-rw-r--r-- | binutils/nm.c | 6 | ||||
-rw-r--r-- | ld/ldmain.c | 5 | ||||
-rw-r--r-- | ld/testsuite/ld-plugin/lto.exp | 35 | ||||
-rw-r--r-- | ld/testsuite/ld-plugin/pr23935a.c | 2 | ||||
-rw-r--r-- | ld/testsuite/ld-plugin/pr23935b.c | 2 |
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) { @@ -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; } 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; } |