ld: Add LTO and none-LTO output support for ld -r

Link with mixed IR/non-IR objects

* 2 kinds of object files
  o non-IR object file has
    * non-IR sections
  o IR object file has
    * IR sections
    * non-IR sections
    * The output of "ld -r" with mixed IR/non-IR objects should work with:
        o Compilers/linkers with IR support.
	o Compilers/linkers without IR support.
* Add the mixed object file which has
  o IR sections
  o non-IR sections:
    * Object codes from IR sections.
    * Object codes from non-IR object files.
  o Object-only section:
    * With section name ".gnu_object_only" and SHT_GNU_OBJECT_ONLY type
    on ELF:
    https://gitlab.com/x86-psABIs/Linux-ABI
    #define SHT_GNU_OBJECT_ONLY 0x6ffffff8	/* Object only */
    * Contain non-IR object file.
    * Input is discarded after link.
* Linker action:
  o Classify each input object file:
    * If there is a ".gnu_object_only" section, it is a mixed object file.
    * If there is a IR section, it is an IR object file.
    * Otherwise, it is a non-IR object file.
  o Relocatable non-IR link:
    * Prepare for an object-only output.
    * Prepare for a regular output.
    * For each mixed object file:
      * Add IR and non-IR sections to the regular output.
      * For object-only section:
	* Extract object only file.
	* Add it to the object-only output.
	* Discard object-only section.
    * For each IR object file:
      * Add IR and non-IR sections to the regular output.
    * For each non-IR object file:
      * Add non-IR sections to the regular output.
      * Add non-IR sections to the object-only output.
    * Final output:
      * If there are IR objects, non-IR objects and the object-only
      output isn't empty:
	* Put the object-only output into the object-only section.
	* Add the object-only section to the regular output.
	* Remove the object-only output.
  o Normal link and relocatable IR link:
    * Prepare for output.
    * IR link:
      * For each mixed object file:
	* Compile and add IR sections to the output.
	* Discard non-IR sections.
	* Object-only section:
	  * Extract object only file.
	  * Add it to the output.
	  * Discard object-only section.
      * For each IR object file:
        * Compile and add IR sections to the output.
	* Discard non-IR sections.
      * For each non-IR object file:
	* Add non-IR sections to the output.
    * Non-IR link:
      * For each mixed object file:
	* Add non-IR sections to the output.
	* Discard IR sections and object-only section.
      * For each IR object file:
	* Add non-IR sections to the output.
	* Discard IR sections.
      * For each non-IR object file:
	* Add non-IR sections to the output.

This is useful for Linux kernel build with LTO.

bfd/

	PR ld/12291
	PR ld/12430
	PR ld/13298
	* bfd.c (bfd_lto_object_type): Add lto_mixed_object.
	(bfd): Add object_only_section.
	(bfd_group_signature): New.
	* elf.c (special_sections_g): Add .gnu_object_only.
	* format.c: Include "plugin-api.h" and "plugin.h" if
	BFD_SUPPORTS_PLUGINS is defined.
	(bfd_set_lto_type): Set type to lto_mixed_object for
	GNU_OBJECT_ONLY_SECTION_NAME section.
	(bfd_check_format_matches): Don't check the plugin target twice
	if the plugin target is explicitly specified.
	* opncls.c (bfd_extract_object_only_section): New.
	* plugin.c (bfd_plugin_fake_text_section): New.
	(bfd_plugin_fake_data_section): Likewise.
	(bfd_plugin_fake_bss_section): Likewise.
	(bfd_plugin_fake_common_section): Likewise.
	(bfd_plugin_get_symbols_in_object_only): Likewise.
	* plugin.c (add_symbols): Call
	bfd_plugin_get_symbols_in_object_only and count
	plugin_data->object_only_nsyms.
	(bfd_plugin_get_symtab_upper_bound): Count
	plugin_data->object_only_nsyms.
	bfd_plugin_get_symbols_in_object_only and add symbols from
	object only section.
	(bfd_plugin_canonicalize_symtab): Remove fake_section,
	fake_data_section, fake_bss_section and fake_common_section.
	Set udata.p to NULL.  Use bfd_plugin_fake_text_section,
	bfd_plugin_fake_data_section, bfd_plugin_fake_bss_section and
	bfd_plugin_fake_common_section.
	Set udata.p to NULL.
	* plugin.h (plugin_data_struct): Add object_only_nsyms and
	object_only_syms.
	* section.c (GNU_OBJECT_ONLY_SECTION_NAME): New.
	* bfd-in2.h: Regenerated.

binutils/

	PR ld/12291
	PR ld/12430
	PR ld/13298
	* objcopy.c (group_signature): Removed.
	(is_strip_section): Replace group_signature with
	bfd_group_signature.
	(setup_section): Likewise.
	* readelf.c (get_os_specific_section_type_name): Handle
	SHT_GNU_OBJECT_ONLY.

gas/

	PR ld/12291
	PR ld/12430
	PR ld/13298
	* testsuite/gas/elf/section9.s: Add the .gnu_object_only test.
	* testsuite/gas/elf/section9.d: Updated.

include/

	PR ld/12291
	PR ld/12430
	PR ld/13298
	* elf/common.h (SHT_GNU_OBJECT_ONLY): New.

ld/

	PR ld/12291
	PR ld/12430
	PR ld/13298
	* ld.h (ld_config_type): Add emit_gnu_object_only and
	emitting_gnu_object_only.
	* ldelf.c (orphan_init_done): Make it file scope.
	(ldelf_place_orphan): Rename hold to orig_hold.  Initialize hold
	from orig_hold at run-time.
	(ldelf_finish): New.
	* ldelf.h (ldelf_finish): New.
	* ldexp.c (ldexp_init): Take a bfd_boolean argument to supprt
	object-only output.
	(ldexp_finish): Likewise.
	* ldexp.h (ldexp_init): Take a bfd_boolean argument.
	(ldexp_finish): Likewise.
	* ldfile.c (ldfile_try_open_bfd): Call
	cmdline_check_object_only_section.
	* ldlang.c: Include "ldwrite.h" and elf-bfd.h.
	* ldlang.c (cmdline_object_only_file_list): New.
	(cmdline_object_only_archive_list): Likewise.
	(cmdline_temp_object_only_list): Likewise.
	(cmdline_lists_init): Likewise.
	(cmdline_list_new): Likewise.
	(cmdline_list_append): Likewise.
	(print_cmdline_list): Likewise.
	(cmdline_on_object_only_archive_list_p): Likewise.
	(cmdline_object_only_list_append): Likewise.
	(cmdline_get_object_only_input_files): Likewise.
	(cmdline_arg): Likewise.
	(setup_section): Likewise.
	(copy_section): Likewise.
	(cmdline_fopen_temp): Likewise.
	(cmdline_add_object_only_section): Likewise.
	(cmdline_emit_object_only_section): Likewise.
	(cmdline_extract_object_only_section): Likewise.
	(cmdline_check_object_only_section): Likewise.
	(cmdline_remove_object_only_files): Likewise.
	(lang_init): Take a bfd_boolean argument to supprt object-only
	output.  Call cmdline_lists_init.
	(load_symbols): Call cmdline_on_object_only_archive_list_p
	to check if an archive member should be loaded.
	(lang_process): Handle object-only link.
	* ldlang.h (lang_init): Take a bfd_boolean argument.
	(cmdline_enum_type): New.
	(cmdline_header_type): Likewise.
	(cmdline_file_type): Likewise.
	(cmdline_bfd_type): Likewise.
	(cmdline_union_type): Likewise.
	(cmdline_list_type): Likewise.
	(cmdline_emit_object_only_section): Likewise.
	(cmdline_check_object_only_section): Likewise.
	(cmdline_remove_object_only_files): Likewise.
	* ldmain.c (main): Call xatexit with
	cmdline_remove_object_only_files.  Pass FALSE to lang_init,
	ldexp_init and ldexp_finish.  Use ld_parse_linker_script.
	Set link_info.output_bfd to NULL after close.  Call
	cmdline_emit_object_only_section if needed.
	(add_archive_element): Call cmdline_check_object_only_section.
	(ld_parse_linker_script): New.
	* ldmain.h (ld_parse_linker_script): New.
	* plugin.c (plugin_maybe_claim): Call
	cmdline_check_object_only_section on claimed IR files.
	* scripttempl/elf.sc: Also discard .gnu_object_only sections.
	* scripttempl/elf64hppa.sc: Likewise.
	* scripttempl/elfxtensa.sc: Likewise.
	* scripttempl/mep.sc: Likewise.
	* scripttempl/pe.sc: Likewise.
	* scripttempl/pep.sc: Likewise.
	* emultempl/aarch64elf.em (gld${EMULATION_NAME}_finish): Replace
	finish_default with ldelf_finish.
	* emultempl/alphaelf.em (alpha_finish): Likewise.
	* emultempl/avrelf.em (avr_finish): Likewise.
	* emultempl/elf.em (ld_${EMULATION_NAME}_emulation): Likewise.
	* emultempl/ppc32elf.em (ppc_finish): Likewise.
	* emultempl/ppc64elf.em (gld${EMULATION_NAME}_finish): Likewise.
	* emultempl/spuelf.em (gld${EMULATION_NAME}_finish): Likewise.
	* testsuite/ld-plugin/lto-10.out: New file.
	* testsuite/ld-plugin/lto-10a.c: Likewise.
	* testsuite/ld-plugin/lto-10b.c: Likewise.
	* testsuite/ld-plugin/lto-10r.d: Likewise.
	* testsuite/ld-plugin/lto-4.out: Likewise.
	* testsuite/ld-plugin/lto-4a.c: Likewise.
	* testsuite/ld-plugin/lto-4b.c: Likewise.
	* testsuite/ld-plugin/lto-4c.c: Likewise.
	* testsuite/ld-plugin/lto-4r-a.d: Likewise.
	* testsuite/ld-plugin/lto-4r-b.d: Likewise.
	* testsuite/ld-plugin/lto-4r-c.d: Likewise.
	* testsuite/ld-plugin/lto-4r-d.d: Likewise.
	* testsuite/ld-plugin/lto.exp (lto_link_tests): Prepare for
	"LTO 4[acd]", "lto-4r-[abcd]" and "LTO 10" tests.
	(lto_run_tests): Add "LTO 4[acd]" and "LTO 10" tests.
	Build liblto-4.a.  Run "lto-4r-[abcd]" tests.
	Run lto-10r and create tmpdir/lto-10.o.
	Add test for nm on mixed LTO/non-LTO object.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
This commit is contained in:
H.J. Lu 2013-11-04 09:17:45 -08:00
parent 127f733f88
commit 9b854f169d
51 changed files with 1653 additions and 125 deletions

View File

@ -925,6 +925,9 @@ extern asection _bfd_std_section[4];
#define BFD_COM_SECTION_NAME "*COM*"
#define BFD_IND_SECTION_NAME "*IND*"
/* GNU object-only section name. */
#define GNU_OBJECT_ONLY_SECTION_NAME ".gnu_object_only"
/* Pointer to the common section. */
#define bfd_com_section_ptr (&_bfd_std_section[0])
/* Pointer to the undefined section. */
@ -1962,7 +1965,8 @@ 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. */
lto_fat_ir_object, /* A fat LTO IR object. */
lto_mixed_object /* A mixed LTO IR object. */
};
struct bfd_mmapped_entry
@ -2185,7 +2189,7 @@ struct bfd
unsigned int read_only : 1;
/* LTO object type. */
ENUM_BITFIELD (bfd_lto_object_type) lto_type : 2;
ENUM_BITFIELD (bfd_lto_object_type) lto_type : 3;
/* Set if this BFD is currently being processed by
bfd_check_format_matches. This is checked by the cache to
@ -2217,6 +2221,9 @@ struct bfd
/* The last section on the section list. */
struct bfd_section *section_last;
/* The object-only section on the section list. */
struct bfd_section *object_only_section;
/* The number of sections. */
unsigned int section_count;
@ -2790,6 +2797,8 @@ bfd_vma bfd_emul_get_commonpagesize (const char *);
char *bfd_demangle (bfd *, const char *, int);
asymbol *bfd_group_signature (asection *group, asymbol **isympp);
/* Extracted from bfdio.c. */
bfd_size_type bfd_read (void *, bfd_size_type, bfd *)
ATTRIBUTE_WARN_UNUSED_RESULT;
@ -3073,6 +3082,9 @@ char *bfd_follow_build_id_debuglink (bfd *abfd, const char *dir);
const char *bfd_set_filename (bfd *abfd, const char *filename);
const char *bfd_extract_object_only_section
(bfd *abfd);
/* Extracted from reloc.c. */
typedef enum bfd_reloc_status
{

View File

@ -80,7 +80,8 @@ EXTERNAL
. 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. *}
. lto_fat_ir_object, {* A fat LTO IR object. *}
. lto_mixed_object {* A mixed LTO IR object. *}
. };
.
.struct bfd_mmapped_entry
@ -306,7 +307,7 @@ CODE_FRAGMENT
. unsigned int read_only : 1;
.
. {* LTO object type. *}
. ENUM_BITFIELD (bfd_lto_object_type) lto_type : 2;
. ENUM_BITFIELD (bfd_lto_object_type) lto_type : 3;
.
. {* Set if this BFD is currently being processed by
. bfd_check_format_matches. This is checked by the cache to
@ -338,6 +339,9 @@ CODE_FRAGMENT
. {* The last section on the section list. *}
. struct bfd_section *section_last;
.
. {* The object-only section on the section list. *}
. struct bfd_section *object_only_section;
.
. {* The number of sections. *}
. unsigned int section_count;
.
@ -3034,3 +3038,41 @@ _bfd_get_link_info (bfd *abfd)
return elf_link_info (abfd);
}
/*
FUNCTION
bfd_group_signature
SYNOPSIS
asymbol *bfd_group_signature (asection *group, asymbol **isympp);
DESCRIPTION
Return a pointer to the symbol used as a signature for GROUP.
*/
asymbol *
bfd_group_signature (asection *group, asymbol **isympp)
{
bfd *abfd = group->owner;
Elf_Internal_Shdr *ghdr;
/* PR 20089: An earlier error may have prevented us from loading the
symbol table. */
if (isympp == NULL)
return NULL;
if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
return NULL;
ghdr = &elf_section_data (group)->this_hdr;
if (ghdr->sh_link == elf_onesymtab (abfd))
{
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
Elf_Internal_Shdr *symhdr = &elf_symtab_hdr (abfd);
if (ghdr->sh_info > 0
&& ghdr->sh_info < symhdr->sh_size / bed->s->sizeof_sym)
return isympp[ghdr->sh_info - 1];
}
return NULL;
}

View File

@ -3014,6 +3014,7 @@ static const struct bfd_elf_special_section special_sections_g[] =
{ STRING_COMMA_LEN (".gnu.linkonce.p"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
{ STRING_COMMA_LEN (".gnu.lto_"), -1, SHT_PROGBITS, SHF_EXCLUDE },
{ STRING_COMMA_LEN (".got"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
{ STRING_COMMA_LEN (".gnu_object_only"), 0, SHT_GNU_OBJECT_ONLY, SHF_EXCLUDE },
{ STRING_COMMA_LEN (".gnu.version"), 0, SHT_GNU_versym, 0 },
{ STRING_COMMA_LEN (".gnu.version_d"), 0, SHT_GNU_verdef, 0 },
{ STRING_COMMA_LEN (".gnu.version_r"), 0, SHT_GNU_verneed, 0 },

View File

@ -46,6 +46,10 @@ SUBSECTION
#include "sysdep.h"
#include "bfd.h"
#include "libbfd.h"
#if BFD_SUPPORTS_PLUGINS
#include "plugin-api.h"
#include "plugin.h"
#endif
/* IMPORT from targets.c. */
extern const size_t _bfd_target_vector_entries;
@ -349,23 +353,32 @@ 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)
&& (abfd->flags
& (DYNAMIC
| (bfd_get_flavour (abfd) == bfd_target_elf_flavour
? EXEC_P : 0))) == 0)
{
asection *sec;
enum bfd_lto_object_type type = lto_non_ir_object;
struct lto_section lsection;
struct lto_section lsection = { 0, 0, 0, 0 };
/* 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 (strcmp (sec->name, GNU_OBJECT_ONLY_SECTION_NAME) == 0)
{
type = lto_mixed_object;
abfd->object_only_section = sec;
break;
}
else if (lsection.major_version == 0
&& 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;
@ -397,9 +410,6 @@ bool
bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
{
extern const bfd_target binary_vec;
#if BFD_SUPPORTS_PLUGINS
extern const bfd_target plugin_vec;
#endif
const bfd_target * const *target;
const bfd_target **matching_vector = NULL;
const bfd_target *save_targ, *right_targ, *ar_right_targ, *match_targ;
@ -507,11 +517,18 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
check the default target twice. */
if (*target == &binary_vec
#if BFD_SUPPORTS_PLUGINS
|| (match_count != 0 && *target == &plugin_vec)
|| (match_count != 0 && 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. */

View File

@ -2054,3 +2054,69 @@ bfd_set_filename (bfd *abfd, const char *filename)
return n;
}
/*
FUNCTION
bfd_extract_object_only_section
SYNOPSIS
const char *bfd_extract_object_only_section
(bfd *abfd);
DESCRIPTION
Takes a @var{ABFD} and extract the .gnu_object_only section into
a temporary file.
RETURNS
The name of the temporary file is returned if all is ok.
Otherwise <<NULL>> is returned and bfd_error is set.
*/
const char *
bfd_extract_object_only_section (bfd *abfd)
{
asection *sec = abfd->object_only_section;
const char *name;
FILE *file;
bfd_byte *memhunk = NULL;
size_t off, size;
bfd_error_type err;
/* Get a temporary object-only file. */
name = make_temp_file (".obj-only.o");
/* Open the object-only file. */
file = _bfd_real_fopen (name, FOPEN_WB);
if (!bfd_get_full_section_contents (abfd, sec, &memhunk))
{
err = bfd_get_error ();
loser:
free (memhunk);
fclose (file);
unlink (name);
bfd_set_error (err);
return NULL;
}
off = 0;
size = sec->size;
while (off != size)
{
size_t written, nwrite = size - off;
written = fwrite (memhunk + off, 1, nwrite, file);
if (written < nwrite && ferror (file))
{
err = bfd_error_system_call;
goto loser;
}
off += written;
}
free (memhunk);
fclose (file);
return name;
}

View File

@ -160,6 +160,158 @@ register_claim_file (ld_plugin_claim_file_handler handler)
return LDPS_OK;
}
static asection bfd_plugin_fake_text_section
= BFD_FAKE_SECTION (bfd_plugin_fake_text_section, NULL, "plug", 0,
SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS);
static asection bfd_plugin_fake_data_section
= BFD_FAKE_SECTION (bfd_plugin_fake_data_section, NULL, "plug", 0,
SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS);
static asection bfd_plugin_fake_bss_section
= BFD_FAKE_SECTION (bfd_plugin_fake_bss_section, NULL, "plug", 0,
SEC_ALLOC);
static asection bfd_plugin_fake_common_section
= BFD_FAKE_SECTION (bfd_plugin_fake_common_section, NULL, NULL,
0, SEC_IS_COMMON);
/* Get symbols from object only section. */
static void
bfd_plugin_get_symbols_in_object_only (bfd *abfd)
{
struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
const char *object_only_file;
bfd *nbfd;
long storage;
long object_only_nsyms, added_nsyms, i;
asymbol **object_only_syms, **added_syms;
plugin_data->object_only_syms = NULL;
plugin_data->object_only_nsyms = 0;
if (abfd->sections == NULL && abfd->my_archive == NULL)
{
nbfd = bfd_openr (abfd->filename, NULL);
if (nbfd == NULL)
{
(*_bfd_error_handler)
(_("%s: failed to open to extract object only section: %s"),
abfd->filename, bfd_errmsg (bfd_get_error ()));
return;
}
else 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;
}
}
else
{
if (!bfd_check_format (abfd, bfd_object))
{
(*_bfd_error_handler)
(_("%pB: invalid file to extract object only section: %s"),
abfd, bfd_errmsg (bfd_get_error ()));
return;
}
nbfd = abfd;
}
if (nbfd->lto_type == lto_mixed_object
&& (nbfd->flags & HAS_SYMS) != 0)
{
object_only_file = bfd_extract_object_only_section (nbfd);
if (object_only_file == NULL)
(*_bfd_error_handler)
(_("%pB: failed to extract object only section: %s"),
abfd, bfd_errmsg (bfd_get_error ()));
}
else
object_only_file = NULL;
/* Close the new bfd we just opened. */
if (nbfd != abfd)
bfd_close (nbfd);
/* Return if there is no object only section or there is no
symbol in object only section. */
if (!object_only_file)
return;
/* Open the file containing object only section. */
nbfd = bfd_openr (object_only_file, NULL);
if (!bfd_check_format (nbfd, bfd_object))
{
(*_bfd_error_handler)
(_("%pB: failed to open object only section: %s"),
abfd, bfd_errmsg (bfd_get_error ()));
goto quit;
}
storage = bfd_get_symtab_upper_bound (nbfd);
if (storage <= 0)
{
if (storage < 0)
(*_bfd_error_handler)
(_("%pB: failed to get symbol table in object only section: %s"),
abfd, bfd_errmsg (bfd_get_error ()));
goto quit;
}
object_only_syms = (asymbol **) bfd_malloc (storage);
object_only_nsyms = bfd_canonicalize_symtab (nbfd, object_only_syms);
/* FIXME: We waste some spaces if not all symbols are copied. */
added_syms = (asymbol **) bfd_alloc (abfd, storage);
added_nsyms = 0;
/* Copy only global symbols from object only section. */
for (i = 0; i < object_only_nsyms; i++)
{
asection *sec = object_only_syms[i]->section;
flagword flags = object_only_syms[i]->flags;
asymbol *s;
if (bfd_is_com_section (sec))
sec = &bfd_plugin_fake_common_section;
else if (bfd_is_und_section (sec))
;
else if ((flags & (BSF_GLOBAL | BSF_WEAK | BSF_GNU_UNIQUE)) != 0)
{
if ((sec->flags & SEC_CODE) != 0)
sec = &bfd_plugin_fake_text_section;
else if ((sec->flags & SEC_LOAD) != 0)
sec = &bfd_plugin_fake_data_section;
else
sec = &bfd_plugin_fake_bss_section;
}
else
continue;
s = bfd_alloc (abfd, sizeof (asymbol));
BFD_ASSERT (s);
added_syms[added_nsyms++] = s;
s->section = sec;
s->the_bfd = abfd;
s->name = xstrdup (object_only_syms[i]->name);
s->value = 0;
s->flags = flags;
s->udata.p = NULL;
}
plugin_data->object_only_syms = added_syms;
plugin_data->object_only_nsyms = added_nsyms;
free (object_only_syms);
quit:
/* Close and remove the object only section file. */
bfd_close (nbfd);
unlink (object_only_file);
}
/* Register a claim-file handler, version 2. */
@ -185,10 +337,13 @@ add_symbols (void * handle,
plugin_data->nsyms = nsyms;
plugin_data->syms = syms;
if (nsyms != 0)
abfd->tdata.plugin_data = plugin_data;
bfd_plugin_get_symbols_in_object_only (abfd);
if ((nsyms + plugin_data->object_only_nsyms) != 0)
abfd->flags |= HAS_SYMS;
abfd->tdata.plugin_data = plugin_data;
return LDPS_OK;
}
@ -678,7 +833,8 @@ static long
bfd_plugin_get_symtab_upper_bound (bfd *abfd)
{
struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
long nsyms = plugin_data->nsyms;
/* Add symbols from object only section. */
long nsyms = plugin_data->nsyms + plugin_data->object_only_nsyms;
BFD_ASSERT (nsyms >= 0);
@ -712,18 +868,7 @@ bfd_plugin_canonicalize_symtab (bfd *abfd,
struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
long nsyms = plugin_data->nsyms;
const struct ld_plugin_symbol *syms = plugin_data->syms;
static asection fake_text_section
= BFD_FAKE_SECTION (fake_text_section, NULL, "plug", 0,
SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS);
static asection fake_data_section
= BFD_FAKE_SECTION (fake_data_section, NULL, "plug", 0,
SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS);
static asection fake_bss_section
= BFD_FAKE_SECTION (fake_bss_section, NULL, "plug", 0,
SEC_ALLOC);
static asection fake_common_section
= BFD_FAKE_SECTION (fake_common_section, NULL, "plug", 0, SEC_IS_COMMON);
int i;
int i, j;
for (i = 0; i < nsyms; i++)
{
@ -736,10 +881,11 @@ bfd_plugin_canonicalize_symtab (bfd *abfd,
s->name = syms[i].name;
s->value = 0;
s->flags = convert_flags (&syms[i]);
s->udata.p = NULL;
switch (syms[i].def)
{
case LDPK_COMMON:
s->section = &fake_common_section;
s->section = &bfd_plugin_fake_common_section;
break;
case LDPK_UNDEF:
case LDPK_WEAKUNDEF:
@ -755,25 +901,28 @@ bfd_plugin_canonicalize_symtab (bfd *abfd,
case LDST_UNKNOWN:
/* What is the best fake section for LDST_UNKNOWN? */
case LDST_FUNCTION:
s->section = &fake_text_section;
s->section = &bfd_plugin_fake_text_section;
break;
case LDST_VARIABLE:
if (syms[i].section_kind == LDSSK_BSS)
s->section = &fake_bss_section;
s->section = &bfd_plugin_fake_bss_section;
else
s->section = &fake_data_section;
s->section = &bfd_plugin_fake_data_section;
break;
}
else
s->section = &fake_text_section;
s->section = &bfd_plugin_fake_text_section;
break;
default:
BFD_ASSERT (0);
}
s->udata.p = (void *) &syms[i];
}
/* Copy symbols from object only section. */
nsyms += plugin_data->object_only_nsyms;
for (j = 0; j < plugin_data->object_only_nsyms; j++, i++)
alocation[i] = plugin_data->object_only_syms[j];
return nsyms;
}

View File

@ -34,6 +34,8 @@ typedef struct plugin_data_struct
{
int nsyms;
const struct ld_plugin_symbol *syms;
int object_only_nsyms;
asymbol **object_only_syms;
}
plugin_data_struct;

View File

@ -661,6 +661,9 @@ EXTERNAL
.#define BFD_COM_SECTION_NAME "*COM*"
.#define BFD_IND_SECTION_NAME "*IND*"
.
.{* GNU object-only section name. *}
.#define GNU_OBJECT_ONLY_SECTION_NAME ".gnu_object_only"
.
.{* Pointer to the common section. *}
.#define bfd_com_section_ptr (&_bfd_std_section[0])
.{* Pointer to the undefined section. *}

View File

@ -1266,34 +1266,6 @@ is_specified_symbol (const char *name, htab_t htab)
return htab_find (htab, name) != NULL;
}
/* Return a pointer to the symbol used as a signature for GROUP. */
static asymbol *
group_signature (asection *group)
{
bfd *abfd = group->owner;
Elf_Internal_Shdr *ghdr;
/* PR 20089: An earlier error may have prevented us from loading the symbol table. */
if (isympp == NULL)
return NULL;
if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
return NULL;
ghdr = &elf_section_data (group)->this_hdr;
if (ghdr->sh_link == elf_onesymtab (abfd))
{
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
Elf_Internal_Shdr *symhdr = &elf_symtab_hdr (abfd);
if (ghdr->sh_info > 0
&& ghdr->sh_info < symhdr->sh_size / bed->s->sizeof_sym)
return isympp[ghdr->sh_info - 1];
}
return NULL;
}
/* Return TRUE if the section is a DWO section. */
static bool
@ -1438,7 +1410,7 @@ is_strip_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
const char *gname;
asection *elt, *first;
gsym = group_signature (sec);
gsym = bfd_group_signature (sec, isympp);
/* Strip groups without a valid signature. */
if (gsym == NULL)
return true;
@ -4398,7 +4370,7 @@ setup_section (bfd *ibfd, sec_ptr isection, bfd *obfd)
if ((isection->flags & SEC_GROUP) != 0)
{
asymbol *gsym = group_signature (isection);
asymbol *gsym = bfd_group_signature (isection, isympp);
if (gsym != NULL)
{

View File

@ -5941,6 +5941,7 @@ get_os_specific_section_type_name (Filedata * filedata, unsigned int sh_type)
case SHT_GNU_ATTRIBUTES: return "GNU_ATTRIBUTES";
case SHT_GNU_HASH: return "GNU_HASH";
case SHT_GNU_LIBLIST: return "GNU_LIBLIST";
case SHT_GNU_OBJECT_ONLY: return "GNU_OBJECT_ONLY";
case SHT_SUNW_move: return "SUNW_MOVE";
case SHT_SUNW_COMDAT: return "SUNW_COMDAT";

View File

@ -4,4 +4,5 @@
#...
[ ]*\[.*\][ ]+\.gnu\.lto_main[ ]+PROGBITS.*[ ]+E[ ]+.*
[ ]*\[.*\][ ]+\.gnu\.lto_\.pureconst[ ]+PROGBITS.*[ ]+E[ ]+.*
[ ]*\[.*\][ ]+\.gnu_object_only[ ]+GNU_OBJECT_ONLY.*[ ]+E[ ]+.*
#pass

View File

@ -2,3 +2,5 @@
.byte 0,0,0,0
.section .gnu.lto_.pureconst,"",%progbits
.byte 0,0,0,0
.section .gnu_object_only
.byte 0,0,0,0

View File

@ -572,6 +572,7 @@
#define SHT_GNU_HASH 0x6ffffff6 /* GNU style symbol hash table */
#define SHT_GNU_LIBLIST 0x6ffffff7 /* List of prelink dependencies */
#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */
#define SHT_GNU_OBJECT_ONLY 0x6ffffff9 /* Object only */
#define SHT_SUNW_move 0x6ffffffa
#define SHT_SUNW_COMDAT 0x6ffffffb

View File

@ -309,7 +309,7 @@ gld${EMULATION_NAME}_finish (void)
}
}
finish_default ();
ldelf_finish ();
}
/* This is a convenient point to tell BFD about target specific flags.

View File

@ -104,7 +104,7 @@ alpha_finish (void)
if (limit_32bit)
elf_elfheader (link_info.output_bfd)->e_flags |= EF_ALPHA_32BIT;
finish_default ();
ldelf_finish ();
}
EOF

View File

@ -456,7 +456,7 @@ gld${EMULATION_NAME}_finish (void)
}
}
finish_default ();
ldelf_finish ();
if (params.thumb_entry_symbol)
{

View File

@ -227,7 +227,7 @@ avr_finish (void)
elf_elfheader (abfd)->e_flags &= ~EF_AVR_LINKRELAX_PREPARED;
}
finish_default ();
ldelf_finish ();
}
EOF

View File

@ -1173,6 +1173,7 @@ LDEMUL_BEFORE_PLACE_ORPHANS=${LDEMUL_BEFORE_PLACE_ORPHANS-ldelf_before_place_orp
LDEMUL_AFTER_ALLOCATION=${LDEMUL_AFTER_ALLOCATION-gld${EMULATION_NAME}_after_allocation}
LDEMUL_SET_OUTPUT_ARCH=${LDEMUL_SET_OUTPUT_ARCH-ldelf_set_output_arch}
LDEMUL_BEFORE_ALLOCATION=${LDEMUL_BEFORE_ALLOCATION-gld${EMULATION_NAME}_before_allocation}
LDEMUL_FINISH=${LDEMUL_FINISH-ldelf_finish}
LDEMUL_OPEN_DYNAMIC_ARCHIVE=${LDEMUL_OPEN_DYNAMIC_ARCHIVE-ldelf_open_dynamic_archive}
LDEMUL_PLACE_ORPHAN=${LDEMUL_PLACE_ORPHAN-ldelf_place_orphan}
LDEMUL_ADD_OPTIONS=gld${EMULATION_NAME}_add_options

View File

@ -238,7 +238,7 @@ ppc_finish (void)
lang_for_each_statement (no_zero_padding);
if (!ppc_finish_symbols (&link_info))
einfo (_("%X%P: ppc_finish_symbols problem %E\n"));
finish_default ();
ldelf_finish ();
}
EOF

View File

@ -616,7 +616,7 @@ gld${EMULATION_NAME}_finish (void)
fflush (stderr);
free (msg);
finish_default ();
ldelf_finish ();
}

View File

@ -432,7 +432,7 @@ gld${EMULATION_NAME}_finish (void)
einfo (_("%P: --auto-overlay ignored with zero local store range\n"));
}
finish_default ();
ldelf_finish ();
}
static char *

View File

@ -306,6 +306,12 @@ typedef struct
/* If set, store plugin intermediate files permanently. */
bool plugin_save_temps;
/* If set, if the .gnu_object_only section should be created. */
bool emit_gnu_object_only;
/* If set, if the .gnu_object_only section is being created. */
bool emitting_gnu_object_only;
/* If set, print discarded sections in map file output. */
bool print_map_discarded;

View File

@ -63,6 +63,7 @@ static lang_input_statement_type *global_found;
static struct stat global_stat;
static struct bfd_link_needed_list *global_vercheck_needed;
static bool global_vercheck_failed;
static bool orphan_init_done;
void
ldelf_after_parse (void)
@ -2101,7 +2102,7 @@ elf_orphan_compatible (asection *in, asection *out)
lang_output_section_statement_type *
ldelf_place_orphan (asection *s, const char *secname, int constraint)
{
static struct orphan_save hold[] =
static struct orphan_save orig_hold[] =
{
{ ".text",
SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE,
@ -2131,6 +2132,7 @@ ldelf_place_orphan (asection *s, const char *secname, int constraint)
SEC_HAS_CONTENTS,
0, 0, 0, 0 },
};
static struct orphan_save hold[ARRAY_SIZE (orig_hold)];
enum orphan_save_index
{
orphan_text = 0,
@ -2143,7 +2145,6 @@ ldelf_place_orphan (asection *s, const char *secname, int constraint)
orphan_sdata,
orphan_nonalloc
};
static int orphan_init_done = 0;
struct orphan_save *place;
lang_output_section_statement_type *after;
lang_output_section_statement_type *os;
@ -2272,16 +2273,23 @@ ldelf_place_orphan (asection *s, const char *secname, int constraint)
if (!orphan_init_done)
{
struct orphan_save *ho;
struct orphan_save *ho, *horig;
for (ho = hold; ho < hold + sizeof (hold) / sizeof (hold[0]); ++ho)
for (ho = hold, horig = orig_hold;
ho < hold + ARRAY_SIZE (hold);
++ho, ++horig)
{
*ho = *horig;
if (ho->name != NULL)
if (ho->name != NULL)
{
ho->os = lang_output_section_find (ho->name);
if (ho->os != NULL && ho->os->flags == 0)
ho->os->flags = ho->flags;
}
orphan_init_done = 1;
}
orphan_init_done = true;
}
/* If this is a final link, then always put .gnu.warning.SYMBOL
@ -2428,3 +2436,13 @@ ldelf_set_output_arch (void)
if (link_info.output_bfd->xvec->flavour == bfd_target_elf_flavour)
elf_link_info (link_info.output_bfd) = &link_info;
}
void
ldelf_finish (void)
{
/* Support the object-only output. */
if (config.emit_gnu_object_only)
orphan_init_done = false;
finish_default ();
}

View File

@ -21,6 +21,7 @@
extern const char *ldelf_emit_note_gnu_build_id;
extern const char *ldelf_emit_note_fdo_package_metadata;
extern void ldelf_finish (void);
extern void ldelf_after_parse (void);
extern bool ldelf_load_symbols (lang_input_statement_type *);
extern void ldelf_before_plugin_all_symbols_read (int, int, int, int,

View File

@ -1699,14 +1699,15 @@ align_n (bfd_vma value, bfd_vma align)
}
void
ldexp_init (void)
ldexp_init (bool object_only)
{
/* The value "13" is ad-hoc, somewhat related to the expected number of
assignments in a linker script. */
if (!bfd_hash_table_init_n (&definedness_table,
definedness_newfunc,
sizeof (struct definedness_hash_entry),
13))
if (!object_only
&& !bfd_hash_table_init_n (&definedness_table,
definedness_newfunc,
sizeof (struct definedness_hash_entry),
13))
einfo (_("%F%P: can not create hash table: %E\n"));
}
@ -1763,7 +1764,8 @@ ldexp_is_final_sym_absolute (const struct bfd_link_hash_entry *h)
}
void
ldexp_finish (void)
ldexp_finish (bool object_only)
{
bfd_hash_table_free (&definedness_table);
if (!object_only)
bfd_hash_table_free (&definedness_table);
}

View File

@ -250,9 +250,9 @@ fill_type *exp_get_fill
(etree_type *, fill_type *, char *);
bfd_vma exp_get_abs_int
(etree_type *, int, char *);
void ldexp_init (void);
void ldexp_init (bool);
void ldexp_finalize_syms (void);
bool ldexp_is_final_sym_absolute (const struct bfd_link_hash_entry *);
void ldexp_finish (void);
void ldexp_finish (bool);
#endif

View File

@ -532,7 +532,9 @@ ldfile_try_open_bfd (const char *attempt,
&& !no_more_claiming
&& bfd_check_format (entry->the_bfd, bfd_object))
plugin_maybe_claim (entry);
else
#endif /* BFD_SUPPORTS_PLUGINS */
cmdline_check_object_only_section (entry->the_bfd, false);
/* It opened OK, the format checked out, and the plugins have had
their chance to claim it, so this is success. */

File diff suppressed because it is too large Load Diff

View File

@ -552,7 +552,7 @@ extern struct asneeded_minfo **asneeded_list_tail;
extern void (*output_bfd_hash_table_free_fn) (struct bfd_link_hash_table *);
extern void lang_init
(void);
(bool);
extern void lang_finish
(void);
extern lang_memory_region_type * lang_memory_region_lookup
@ -746,4 +746,46 @@ print_one_symbol (struct bfd_link_hash_entry *, void *);
extern void lang_add_version_string
(void);
typedef enum
{
cmdline_is_file_enum,
cmdline_is_bfd_enum
} cmdline_enum_type;
typedef struct cmdline_header_struct
{
union cmdline_union *next;
cmdline_enum_type type;
} cmdline_header_type;
typedef struct cmdline_file_struct
{
cmdline_header_type header;
const char *filename;
} cmdline_file_type;
typedef struct cmdline_bfd_struct
{
cmdline_header_type header;
bfd *abfd;
} cmdline_bfd_type;
typedef union cmdline_union
{
cmdline_header_type header;
cmdline_file_type file;
cmdline_bfd_type abfd;
} cmdline_union_type;
typedef struct cmdline_list
{
cmdline_union_type *head;
cmdline_union_type **tail;
} cmdline_list_type;
extern void cmdline_emit_object_only_section (void);
extern void cmdline_check_object_only_section (bfd *, bool);
extern void cmdline_remove_object_only_files (void);
#endif

View File

@ -302,6 +302,9 @@ main (int argc, char **argv)
xatexit (ld_cleanup);
/* Remove temporary object-only files. */
xatexit (cmdline_remove_object_only_files);
/* Set up the sysroot directory. */
ld_sysroot = get_sysroot (argc, argv);
if (*ld_sysroot)
@ -391,8 +394,8 @@ main (int argc, char **argv)
emulation = get_emulation (argc, argv);
ldemul_choose_mode (emulation);
default_target = ldemul_choose_target (argc, argv);
lang_init ();
ldexp_init ();
lang_init (false);
ldexp_init (false);
ldemul_before_parse ();
lang_has_input_file = false;
parse_args (argc, argv);
@ -407,34 +410,7 @@ main (int argc, char **argv)
ldemul_set_symbols ();
/* If we have not already opened and parsed a linker script,
try the default script from command line first. */
if (saved_script_handle == NULL
&& command_line.default_script != NULL)
{
ldfile_open_script_file (command_line.default_script);
parser_input = input_script;
yyparse ();
}
/* If we have not already opened and parsed a linker script
read the emulation's appropriate default script. */
if (saved_script_handle == NULL)
{
int isfile;
char *s = ldemul_get_script (&isfile);
if (isfile)
ldfile_open_default_command_file (s);
else
{
lex_string = s;
lex_redirect (s, _("built in linker script"), 1);
}
parser_input = input_script;
yyparse ();
lex_string = NULL;
}
ld_parse_linker_script ();
if (verbose)
{
@ -572,7 +548,7 @@ main (int argc, char **argv)
fprintf (stderr, "lookup = %p val %lx\n", h, h ? h->u.def.value : 1);
}
#endif
ldexp_finish ();
ldexp_finish (false);
lang_finish ();
if (config.dependency_file != NULL)
@ -597,6 +573,8 @@ main (int argc, char **argv)
if (!bfd_close (obfd))
einfo (_("%F%P: %s: final close failed: %E\n"), output_filename);
link_info.output_bfd = NULL;
/* If the --force-exe-suffix is enabled, and we're making an
executable file and it doesn't end in .exe, copy it to one
which does. */
@ -644,6 +622,9 @@ main (int argc, char **argv)
}
}
if (config.emit_gnu_object_only)
cmdline_emit_object_only_section ();
if (config.stats)
{
long run_time = get_run_time () - start_time;
@ -951,7 +932,9 @@ add_archive_element (struct bfd_link_info *info,
*subsbfd = input->the_bfd;
}
}
else
#endif /* BFD_SUPPORTS_PLUGINS */
cmdline_check_object_only_section (input->the_bfd, false);
if (link_info.input_bfds_tail == &input->the_bfd->link.next
|| input->the_bfd->link.next != NULL)
@ -1694,3 +1677,38 @@ notice (struct bfd_link_info *info,
return true;
}
/* Parse the linker script. */
void
ld_parse_linker_script (void)
{
/* If we have not already opened and parsed a linker script,
try the default script from command line first. */
if (saved_script_handle == NULL
&& command_line.default_script != NULL)
{
ldfile_open_script_file (command_line.default_script);
parser_input = input_script;
yyparse ();
}
/* If we have not already opened and parsed a linker script
read the emulation's appropriate default script. */
if (saved_script_handle == NULL)
{
int isfile;
char *s = ldemul_get_script (&isfile);
if (isfile)
ldfile_open_default_command_file (s);
else
{
lex_string = s;
lex_redirect (s, _("built in linker script"), 1);
}
parser_input = input_script;
yyparse ();
lex_string = NULL;
}
}

View File

@ -63,4 +63,6 @@ extern void add_ignoresym (struct bfd_link_info *, const char *);
extern void add_keepsyms_file (const char *);
extern void track_dependency_files (const char *);
extern void ld_parse_linker_script (void);
#endif

View File

@ -1341,6 +1341,9 @@ plugin_maybe_claim (lang_input_statement_type *entry)
{
bfd *abfd = entry->the_bfd->plugin_dummy_bfd;
/* Check object only section. */
cmdline_check_object_only_section (entry->the_bfd, true);
/* Discard the real file's BFD and substitute the dummy one. */
/* We can't call bfd_close on archives. BFD archive handling

View File

@ -244,7 +244,7 @@ RELA_IPLT=".rela.iplt ${RELOCATING-0} :
DYNAMIC=".dynamic ${RELOCATING-0} : { *(.dynamic) }"
RODATA=".${RODATA_NAME} ${RELOCATING-0} : { *(.${RODATA_NAME}${RELOCATING+ .${RODATA_NAME}.* .gnu.linkonce.r.*}) }"
DATARELRO=".data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }"
DISCARDED="/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }"
DISCARDED="/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) *(.gnu_object_only) }"
if test -z "${NO_SMALL_DATA}"; then
SBSS=".${SBSS_NAME} ${RELOCATING-0} :
{

View File

@ -132,7 +132,7 @@ fi
DYNAMIC=".dynamic ${RELOCATING-0} : { *(.dynamic) }"
RODATA=".rodata ${RELOCATING-0} : { *(.rodata${RELOCATING+ .rodata.* .gnu.linkonce.r.*}) }"
DATARELRO=".data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }"
DISCARDED="/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }"
DISCARDED="/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) *(.gnu_object_only) }"
if test -z "${NO_SMALL_DATA}"; then
SBSS=".sbss ${RELOCATING-0} :
{

View File

@ -145,7 +145,7 @@ fi
DYNAMIC=".dynamic ${RELOCATING-0} : { *(.dynamic) }"
RODATA=".rodata ${RELOCATING-0} : { *(.rodata${RELOCATING+ .rodata.* .gnu.linkonce.r.*}) }"
DATARELRO=".data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }"
DISCARDED="/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }"
DISCARDED="/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) *(.gnu_object_only) }"
INIT_LIT=".init.literal 0 : { *(.init.literal) }"
INIT=".init 0 : { KEEP (*(SORT_NONE(.init))) }"
FINI_LIT=".fini.literal 0 : { *(.fini.literal) }"

View File

@ -119,7 +119,7 @@ fi
DYNAMIC=".dynamic ${RELOCATING-0} : { *(.dynamic) }"
RODATA=".rodata ${RELOCATING-0} : { *(.rodata${RELOCATING+ .rodata.* .gnu.linkonce.r.*}) }"
DATARELRO=".data.rel.ro : { *(.data.rel.ro.local) *(.data.rel.ro .data.rel.ro.*) }"
DISCARDED="/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }"
DISCARDED="/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) *(.gnu_object_only) }"
if test -z "${NO_SMALL_DATA}"; then
SBSS=".sbss ${RELOCATING-0} :
{

View File

@ -230,6 +230,7 @@ SECTIONS
${RELOCATING+ *(.drectve)}
${RELOCATING+ *(.note.GNU-stack)}
${RELOCATING+ *(.gnu.lto_*)}
${RELOCATING+ *(.gnu_object_only)}
}
.idata ${RELOCATING+BLOCK(__section_alignment__)} :

View File

@ -237,6 +237,7 @@ SECTIONS
${RELOCATING+ *(.drectve)}
${RELOCATING+ *(.note.GNU-stack)}
${RELOCATING+ *(.gnu.lto_*)}
${RELOCATING+ *(.gnu_object_only)}
}
.idata ${RELOCATING+BLOCK(__section_alignment__)} :

View File

@ -0,0 +1 @@
hello

View File

@ -0,0 +1,6 @@
extern int foo(void);
int main(void)
{
return foo();
}

View File

@ -0,0 +1,7 @@
#include <stdio.h>
int foo(void)
{
printf ("hello\n");
return 0;
}

View File

@ -0,0 +1,9 @@
#ld: -r tmpdir/lto-10a.o tmpdir/lto-10b.o
#source: dummy.s
#objdump: -h
#...
*[0-9]+ +\.gnu\.lto_\.[0-9a-zA-Z_\.]+ +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ .*
#...
*[0-9]+ +\.gnu_object_only +[0-9a-f]+ +0+ +0+ +0+[1-9a-f][0-9a-f]+ +.*
#pass

View File

@ -0,0 +1,2 @@
hello bar
hello foo

View File

@ -0,0 +1,7 @@
extern void foo(void);
int main(void)
{
foo();
return 0;
}

View File

@ -0,0 +1,9 @@
#include <stdio.h>
extern void bar (void);
void foo(void)
{
bar ();
printf ("hello foo\n");
}

View File

@ -0,0 +1,6 @@
#include <stdio.h>
void bar (void)
{
printf ("hello bar\n");
}

View File

@ -0,0 +1,7 @@
#ld: -r tmpdir/lto-4a.o tmpdir/lto-4b.o tmpdir/lto-4c.o
#source: dummy.s
#objdump: -h
#...
.* .gnu_object_only.*
#pass

View File

@ -0,0 +1,7 @@
#ld: -r tmpdir/lto-4a.o tmpdir/lto-4b.o
#source: dummy.s
#objdump: -h
#...
.* .gnu_object_only.*
#pass

View File

@ -0,0 +1,7 @@
#ld: -r tmpdir/lto-4r-b.o tmpdir/lto-4c.o --no-warn-execstack --no-error-execstack
#source: dummy.s
#objdump: -h
#...
.* .gnu_object_only.*
#pass

View File

@ -0,0 +1,7 @@
#ld: -r --whole-archive tmpdir/liblto-4.a
#source: dummy.s
#objdump: -h
#...
.* .gnu_object_only.*
#pass

View File

@ -72,6 +72,15 @@ set lto_link_tests [list \
[list "Build liblto-3.a" \
"" "-flto $lto_fat" \
{lto-3b.c} {} "liblto-3.a"] \
[list "Compile 4a" \
"" "-flto $lto_fat" \
{lto-4a.c} {} ""] \
[list "Compile 4b" \
"" "-O2" \
{lto-4b.c} {} ""] \
[list "Compile 4c" \
"" "-O2" \
{lto-4c.c} {} ""] \
[list "Compile 5a" \
"" "-flto $lto_fat" \
{lto-5a.c} {} ""] \
@ -84,6 +93,12 @@ set lto_link_tests [list \
[list "Compile 9" \
"" "-O2 -finline -flto" \
{lto-9.cc} {} "" "c++"] \
[list "Compile 10a" \
"" "-O2" \
{lto-10a.c} {} ""] \
[list "Compile 10b" \
"" "-O2 -flto $lto_fat" \
{lto-10b.c} {} ""] \
[list "Compile 11a" \
"" "-O -flto" \
{lto-11a.c} {} ""] \
@ -711,9 +726,29 @@ set lto_run_tests [list \
[list "LTO 3c" \
"-O2 -flto -fuse-linker-plugin tmpdir/lto-3a.o tmpdir/lto-3c.o -Wl,--whole-archive tmpdir/liblto-3.a -Wl,--no-whole-archive tmpdir/liblto-3.a" "" \
{dummy.c} "lto-3d.exe" "lto-3.out" "" "c"] \
[list "LTO 4a" \
"-O2 -flto -fuse-linker-plugin \
-Wl,--no-warn-execstack,--no-error-execstack \
tmpdir/lto-4r-a.o" "" \
{dummy.c} "lto-4a.exe" "lto-4.out" "" "c"] \
[list "LTO 4c" \
"-O2 -flto -fuse-linker-plugin \
-Wl,--no-warn-execstack,--no-error-execstack \
tmpdir/lto-4r-c.o" "" \
{dummy.c} "lto-4c.exe" "lto-4.out" "" "c"] \
[list "LTO 4d" \
"-O2 -flto -fuse-linker-plugin \
-Wl,--no-warn-execstack,--no-error-execstack \
tmpdir/lto-4r-d.o" "" \
{dummy.c} "lto-4d.exe" "lto-4.out" "" "c"] \
[list "LTO 5" \
"-O2 -flto -fuse-linker-plugin tmpdir/lto-5.o" "" \
{dummy.c} "lto-5.exe" "lto-5.out" "" "c"] \
[list "LTO 10" \
"-O2 -flto -fuse-linker-plugin \
-Wl,--no-warn-execstack,--no-error-execstack \
tmpdir/lto-10.o" "" \
{dummy.c} "lto-10.exe" "lto-10.out" "" "c"] \
[list "LTO 11" \
"-O -flto -fuse-linker-plugin tmpdir/liblto-11.a" "" \
{dummy.c} "lto-11.exe" "lto-11.out" "" "c"] \
@ -979,6 +1014,15 @@ if [string match "" $exec_output] then {
fail "PR ld/28138 (build only)"
}
set testname "Build liblto-4.a"
remote_file host delete "tmpdir/liblto-4.a"
set catch_output [run_host_cmd "$ar" "rc tmpdir/liblto-4.a tmpdir/lto-4a.o tmpdir/lto-4b.o tmpdir/lto-4c.o"]
if {![string match "" $catch_output]} {
unresolved $testname
restore_notify
return
}
set testname "Build liblto-11.a"
remote_file host delete "tmpdir/liblto-11.a"
set catch_output [run_host_cmd "$ar" "rc $plug_opt tmpdir/liblto-11.a tmpdir/lto-11a.o tmpdir/lto-11b.o tmpdir/lto-11c.o"]
@ -1091,8 +1135,30 @@ if { [at_least_gcc_version 4 7] } {
# Run "ld -r" to generate inputs for complex LTO tests.
run_dump_test "lto-3r"
remote_exec host "mv" "tmpdir/dump tmpdir/lto-3.o"
run_dump_test "lto-4r-a"
remote_exec host "mv" "tmpdir/dump tmpdir/lto-4r-a.o"
run_dump_test "lto-4r-b"
remote_exec host "mv" "tmpdir/dump tmpdir/lto-4r-b.o"
run_dump_test "lto-4r-c"
remote_exec host "mv" "tmpdir/dump tmpdir/lto-4r-c.o"
run_dump_test "lto-4r-d"
remote_exec host "mv" "tmpdir/dump tmpdir/lto-4r-d.o"
run_dump_test "lto-5r"
remote_exec host "mv" "tmpdir/dump tmpdir/lto-5.o"
run_dump_test "lto-10r"
remote_exec host "mv" "tmpdir/dump tmpdir/lto-10.o"
set testname "nm mixed object"
set lto_plugin [string trim [run_host_cmd "$CC_FOR_TARGET" "-print-prog-name=liblto_plugin.so"]]
if { [ regexp "liblto_plugin.so" $lto_plugin ] } {
set exec_output [run_host_cmd "$NM" "--plugin $lto_plugin tmpdir/lto-10.o"]
if { [ regexp "T main" $exec_output ] } {
pass $testname
} {
fail $testname
}
} {
fail $testname
}
run_cc_link_tests $lto_link_symbol_tests