+2011-04-27 Alan Modra <amodra@gmail.com>
+
+ Backport from mainline
+ 2011-04-24 Alan Modra <amodra@gmail.com>
+ PR ld/12365
+ PR ld/12696
+ * coff-aux.c (coff_m68k_aux_link_add_one_symbol): Update "notice" call.
+ * linker.c (_bfd_link_hash_newfunc): Clear bitfields.
+ (_bfd_generic_link_add_one_symbol): Update "notice" call.
+ * elflink.c (_bfd_elf_merge_symbol): Don't skip weak redefs when
+ it is a redef of an IR symbol in a real BFD.
+
+ 2011-04-20 Alan Modra <amodra@gmail.com>
+ PR ld/12365
+ * elfcode.h (elf_slurp_symbol_table): Put common plugin IR symbols
+ in their own common section.
+ * elflink.c (elf_link_add_object_symbols): Likewise.
+ * linker.c (generic_link_check_archive_element): Don't lose flags
+ if common section is pre-existing.
+ (_bfd_generic_link_add_one_symbol): Likewise.
+
+ 2011-04-20 Alan Modra <amodra@gmail.com>
+ PR ld/12365
+ * elflink.c (_bfd_elf_merge_symbol): Update multiple_common calls.
+ * linker.c (_bfd_generic_link_add_one_symbol): Likewise. Call
+ multiple_definition regardless of allow_multiple_definition.
+ * simple.c (simple_dummy_multiple_definition): Update.
+ * xcofflink.c (xcoff_link_add_symbols): Update multiple_definition
+ calls.
+
+ 2011-04-18 Alan Modra <amodra@gmail.com>
+ PR ld/12365
+ PR ld/12672
+ * bfd.c (BFD_PLUGIN): Define.
+ (BFD_FLAGS_SAVED, BFD_FLAGS_FOR_BFD_USE_MASK): Add BFD_PLUGIN.
+ * bfd-in2.h: Regenerate.
+ * elflink.c (elf_link_output_extsym): Strip undefined plugin syms.
+ * opncls.c (bfd_make_readable): Don't lose original bfd flags.
+
+ 2011-04-11 Mark Wielaard <mjw@redhat.com>
+ PR 10549
+ * elf-bfd.h (has_ifunc_symbols): Renamed to has_gnu_symbols.
+ (has_gnu_symbols): Renamed from has_ifunc_symbols.
+ * elf.c (_bfd_elf_set_osabi): Use new has_gnu_symbols name.
+ * elf32-i386.c (elf_i386_add_symbol_hook): Likewise.
+ * elf32-ppc.c (ppc_elf_add_symbol_hook): Likewise.
+ * elf32-sparc.c (elf32_sparc_add_symbol_hook): Likewise.
+ * elf64-ppc.c (ppc64_elf_add_symbol_hook): Likewise.
+ * elf64-sparc.c (elf64_sparc_add_symbol_hook): Likewise.
+ * elf64-x86-64.c (elf_x86_64_add_symbol_hook): Likewise.
+
+ 2011-02-25 Rafael Ávila de Espíndola <respindola@mozilla.com>
+ * plugin.c (bfd_plugin_object_p): Correctly set the filesize
+ and handle claim_file seeking. Only try to load the plugin once.
+
+ 2010-12-12 H.J. Lu <hongjiu.lu@intel.com>
+ * elf.c (special_sections_g): Add ".gnu.lto_".
+
2011-04-20 Jan Kratochvil <jan.kratochvil@redhat.com>
* elf-bfd.h (RELOC_AGAINST_DISCARDED_SECTION): Fix +1 overrun of
/* Decompress sections in this BFD. */
#define BFD_DECOMPRESS 0x10000
+ /* BFD is a dummy, for plugins. */
+#define BFD_PLUGIN 0x20000
+
/* Flags bits to be saved in bfd_preserve_save. */
#define BFD_FLAGS_SAVED \
- (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS)
+ (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_PLUGIN)
/* Flags bits which are for BFD use only. */
#define BFD_FLAGS_FOR_BFD_USE_MASK \
(BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \
- | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT)
+ | BFD_PLUGIN | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT)
/* Currently my_archive is tested before adding origin to
anything. I believe that this can become always an add of
. {* Decompress sections in this BFD. *}
.#define BFD_DECOMPRESS 0x10000
.
+. {* BFD is a dummy, for plugins. *}
+.#define BFD_PLUGIN 0x20000
+.
. {* Flags bits to be saved in bfd_preserve_save. *}
.#define BFD_FLAGS_SAVED \
-. (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS)
+. (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_PLUGIN)
.
. {* Flags bits which are for BFD use only. *}
.#define BFD_FLAGS_FOR_BFD_USE_MASK \
. (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \
-. | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT)
+. | BFD_PLUGIN | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT)
.
. {* Currently my_archive is tested before adding origin to
. anything. I believe that this can become always an add of
&& (bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE)
!= (struct bfd_hash_entry *) NULL))
{
- if (! (*info->callbacks->notice) (info, name, abfd, section, value))
+ if (! (*info->callbacks->notice) (info, h, abfd, section, value))
return FALSE;
}
bfd_byte *build_id;
/* True if the bfd contains symbols that have the STT_GNU_IFUNC
- symbol type. Used to set the osabi field in the ELF header
- structure. */
- bfd_boolean has_ifunc_symbols;
+ symbol type or STB_GNU_UNIQUE binding. Used to set the osabi
+ field in the ELF header structure. */
+ bfd_boolean has_gnu_symbols;
/* An identifier used to distinguish different target
specific extensions to this structure. */
static const struct bfd_elf_special_section special_sections_g[] =
{
{ STRING_COMMA_LEN (".gnu.linkonce.b"), -2, SHT_NOBITS, 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.version"), 0, SHT_GNU_versym, 0 },
{ STRING_COMMA_LEN (".gnu.version_d"), 0, SHT_GNU_verdef, 0 },
/* To make things simpler for the loader on Linux systems we set the
osabi field to ELFOSABI_LINUX if the binary contains symbols of
- the STT_GNU_IFUNC type. */
+ the STT_GNU_IFUNC type or STB_GNU_UNIQUE binding. */
if (i_ehdrp->e_ident[EI_OSABI] == ELFOSABI_NONE
- && elf_tdata (abfd)->has_ifunc_symbols)
+ && elf_tdata (abfd)->has_gnu_symbols)
i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_LINUX;
}
bfd_vma * valp ATTRIBUTE_UNUSED)
{
if ((abfd->flags & DYNAMIC) == 0
- && ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
- elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE;
+ && (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
+ || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE))
+ elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE;
return TRUE;
}
}
if ((abfd->flags & DYNAMIC) == 0
- && ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
- elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE;
+ && (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
+ || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE))
+ elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE;
return TRUE;
}
bfd_vma * valp ATTRIBUTE_UNUSED)
{
if ((abfd->flags & DYNAMIC) == 0
- && ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
- elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE;
+ && (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
+ || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE))
+ elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE;
return TRUE;
}
asection **sec,
bfd_vma *value ATTRIBUTE_UNUSED)
{
+ if ((ibfd->flags & DYNAMIC) == 0
+ && ELF_ST_BIND (isym->st_info) == STB_GNU_UNIQUE)
+ elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE;
+
if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
{
if ((ibfd->flags & DYNAMIC) == 0)
- elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE;
+ elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE;
}
else if (ELF_ST_TYPE (isym->st_info) == STT_FUNC)
;
static const char *const stt_types[] = { "NOTYPE", "OBJECT", "FUNCTION" };
if ((abfd->flags & DYNAMIC) == 0
- && ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
- elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE;
+ && (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
+ || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE))
+ elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE;
if (ELF_ST_TYPE (sym->st_info) == STT_REGISTER)
{
}
if ((abfd->flags & DYNAMIC) == 0
- && ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
- elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE;
+ && (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
+ || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE))
+ elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE;
return TRUE;
}
else if (isym->st_shndx == SHN_COMMON)
{
sym->symbol.section = bfd_com_section_ptr;
+ if ((abfd->flags & BFD_PLUGIN) != 0)
+ {
+ asection *xc = bfd_get_section_by_name (abfd, "COMMON");
+
+ if (xc == NULL)
+ {
+ flagword flags = (SEC_ALLOC | SEC_IS_COMMON | SEC_KEEP
+ | SEC_EXCLUDE);
+ xc = bfd_make_section_with_flags (abfd, "COMMON", flags);
+ if (xc == NULL)
+ goto error_return;
+ }
+ sym->symbol.section = xc;
+ }
/* Elf puts the alignment into the `value' field, and
the size into the `size' field. BFD wants to see the
size in the value field, and doesn't care (at the
symbols defined in dynamic objects. */
if (! ((*info->callbacks->multiple_common)
- (info, h->root.root.string, oldbfd, bfd_link_hash_common,
- h->size, abfd, bfd_link_hash_common, sym->st_size)))
+ (info, &h->root, abfd, bfd_link_hash_common, sym->st_size)))
return FALSE;
if (sym->st_size > h->size)
/* Skip weak definitions of symbols that are already defined. */
if (newdef && olddef && newweak)
{
- *skip = TRUE;
+ /* Don't skip new non-IR weak syms. */
+ if (!((oldbfd->flags & BFD_PLUGIN) != 0
+ && (abfd->flags & BFD_PLUGIN) == 0))
+ *skip = TRUE;
/* Merge st_other. If the symbol already has a dynamic index,
but visibility says it should not be visible, turn it into a
common symbol, but we don't know what to use for the section
or the alignment. */
if (! ((*info->callbacks->multiple_common)
- (info, h->root.root.string, oldbfd, bfd_link_hash_common,
- h->size, abfd, bfd_link_hash_common, sym->st_size)))
+ (info, &h->root, abfd, bfd_link_hash_common, sym->st_size)))
return FALSE;
/* If the presumed common symbol in the dynamic object is
goto error_free_vers;
if (isym->st_shndx == SHN_COMMON
- && ELF_ST_TYPE (isym->st_info) == STT_TLS
- && !info->relocatable)
+ && (abfd->flags & BFD_PLUGIN) != 0)
+ {
+ asection *xc = bfd_get_section_by_name (abfd, "COMMON");
+
+ if (xc == NULL)
+ {
+ flagword sflags = (SEC_ALLOC | SEC_IS_COMMON | SEC_KEEP
+ | SEC_EXCLUDE);
+ xc = bfd_make_section_with_flags (abfd, "COMMON", sflags);
+ if (xc == NULL)
+ goto error_free_vers;
+ }
+ sec = xc;
+ }
+ else if (isym->st_shndx == SHN_COMMON
+ && ELF_ST_TYPE (isym->st_info) == STT_TLS
+ && !info->relocatable)
{
asection *tcomm = bfd_get_section_by_name (abfd, ".tcommon");
if (tcomm == NULL)
{
- tcomm = bfd_make_section_with_flags (abfd, ".tcommon",
- (SEC_ALLOC
- | SEC_IS_COMMON
- | SEC_LINKER_CREATED
- | SEC_THREAD_LOCAL));
+ flagword sflags = (SEC_ALLOC | SEC_THREAD_LOCAL | SEC_IS_COMMON
+ | SEC_LINKER_CREATED);
+ tcomm = bfd_make_section_with_flags (abfd, ".tcommon", sflags);
if (tcomm == NULL)
goto error_free_vers;
}
|| h->root.type == bfd_link_hash_defweak)
&& elf_discarded_section (h->root.u.def.section))
strip = TRUE;
+ else if ((h->root.type == bfd_link_hash_undefined
+ || h->root.type == bfd_link_hash_undefweak)
+ && h->root.u.undef.abfd != NULL
+ && (h->root.u.undef.abfd->flags & BFD_PLUGIN) != 0)
+ strip = TRUE;
else
strip = FALSE;
struct bfd_link_hash_entry *h = (struct bfd_link_hash_entry *) entry;
/* Initialize the local fields. */
- h->type = bfd_link_hash_new;
- memset (&h->u.undef.next, 0,
- (sizeof (struct bfd_link_hash_entry)
- - offsetof (struct bfd_link_hash_entry, u.undef.next)));
+ memset ((char *) &h->root + sizeof (h->root), 0,
+ sizeof (*h) - sizeof (h->root));
}
return entry;
else
h->u.c.p->section = bfd_make_section_old_way (symbfd,
p->section->name);
- h->u.c.p->section->flags = SEC_ALLOC;
+ h->u.c.p->section->flags |= SEC_ALLOC;
}
else
{
|| (info->notice_hash != NULL
&& bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL))
{
- if (! (*info->callbacks->notice) (info, h->root.string, abfd, section,
- value))
+ if (! (*info->callbacks->notice) (info, h, abfd, section, value))
return FALSE;
}
previously common. */
BFD_ASSERT (h->type == bfd_link_hash_common);
if (! ((*info->callbacks->multiple_common)
- (info, h->root.string,
- h->u.c.p->section->owner, bfd_link_hash_common, h->u.c.size,
- abfd, bfd_link_hash_defined, 0)))
+ (info, h, abfd, bfd_link_hash_defined, 0)))
return FALSE;
/* Fall through. */
case DEF:
if (section == bfd_com_section_ptr)
{
h->u.c.p->section = bfd_make_section_old_way (abfd, "COMMON");
- h->u.c.p->section->flags = SEC_ALLOC;
+ h->u.c.p->section->flags |= SEC_ALLOC;
}
else if (section->owner != abfd)
{
h->u.c.p->section = bfd_make_section_old_way (abfd,
section->name);
- h->u.c.p->section->flags = SEC_ALLOC;
+ h->u.c.p->section->flags |= SEC_ALLOC;
}
else
h->u.c.p->section = section;
two sizes, and use the section required by the larger symbol. */
BFD_ASSERT (h->type == bfd_link_hash_common);
if (! ((*info->callbacks->multiple_common)
- (info, h->root.string,
- h->u.c.p->section->owner, bfd_link_hash_common, h->u.c.size,
- abfd, bfd_link_hash_common, value)))
+ (info, h, abfd, bfd_link_hash_common, value)))
return FALSE;
if (value > h->u.c.size)
{
{
h->u.c.p->section
= bfd_make_section_old_way (abfd, "COMMON");
- h->u.c.p->section->flags = SEC_ALLOC;
+ h->u.c.p->section->flags |= SEC_ALLOC;
}
else if (section->owner != abfd)
{
h->u.c.p->section
= bfd_make_section_old_way (abfd, section->name);
- h->u.c.p->section->flags = SEC_ALLOC;
+ h->u.c.p->section->flags |= SEC_ALLOC;
}
else
h->u.c.p->section = section;
break;
case CREF:
- {
- bfd *obfd;
-
- /* We have found a common definition for a symbol which
- was already defined. FIXME: It would nice if we could
- report the BFD which defined an indirect symbol, but we
- don't have anywhere to store the information. */
- if (h->type == bfd_link_hash_defined
- || h->type == bfd_link_hash_defweak)
- obfd = h->u.def.section->owner;
- else
- obfd = NULL;
- if (! ((*info->callbacks->multiple_common)
- (info, h->root.string, obfd, h->type, 0,
- abfd, bfd_link_hash_common, value)))
- return FALSE;
- }
+ /* We have found a common definition for a symbol which
+ was already defined. */
+ if (! ((*info->callbacks->multiple_common)
+ (info, h, abfd, bfd_link_hash_common, value)))
+ return FALSE;
break;
case MIND:
/* Fall through. */
case MDEF:
/* Handle a multiple definition. */
- if (!info->allow_multiple_definition)
- {
- asection *msec = NULL;
- bfd_vma mval = 0;
-
- switch (h->type)
- {
- case bfd_link_hash_defined:
- msec = h->u.def.section;
- mval = h->u.def.value;
- break;
- case bfd_link_hash_indirect:
- msec = bfd_ind_section_ptr;
- mval = 0;
- break;
- default:
- abort ();
- }
-
- /* Ignore a redefinition of an absolute symbol to the
- same value; it's harmless. */
- if (h->type == bfd_link_hash_defined
- && bfd_is_abs_section (msec)
- && bfd_is_abs_section (section)
- && value == mval)
- break;
-
- if (! ((*info->callbacks->multiple_definition)
- (info, h->root.string, msec->owner, msec, mval,
- abfd, section, value)))
- return FALSE;
- }
+ if (! ((*info->callbacks->multiple_definition)
+ (info, h, abfd, section, value)))
+ return FALSE;
break;
case CIND:
/* Create an indirect symbol from an existing common symbol. */
BFD_ASSERT (h->type == bfd_link_hash_common);
if (! ((*info->callbacks->multiple_common)
- (info, h->root.string,
- h->u.c.p->section->owner, bfd_link_hash_common, h->u.c.size,
- abfd, bfd_link_hash_indirect, 0)))
+ (info, h, abfd, bfd_link_hash_indirect, 0)))
return FALSE;
/* Fall through. */
case IND:
abfd->section_count = 0;
abfd->usrdata = NULL;
abfd->cacheable = FALSE;
- abfd->flags = BFD_IN_MEMORY;
+ abfd->flags |= BFD_IN_MEMORY;
abfd->mtime_set = FALSE;
abfd->target_defaulted = TRUE;
bfd_plugin_object_p (bfd *abfd)
{
int claimed = 0;
- int t = load_plugin ();
struct ld_plugin_input_file file;
bfd *iobfd;
+ static int have_loaded = 0;
+ static int have_plugin = 0;
- if (!t)
+ if (!have_loaded)
+ {
+ have_loaded = 1;
+ have_plugin = load_plugin ();
+ }
+ if (!have_plugin)
return NULL;
file.name = abfd->filename;
{
iobfd = abfd;
file.offset = 0;
- file.filesize = 0; /*FIXME*/
+ file.filesize = 0;
}
if (!iobfd->iostream && !bfd_open_file (iobfd))
file.fd = fileno ((FILE *) iobfd->iostream);
+ if (!abfd->my_archive)
+ {
+ struct stat stat_buf;
+ if (fstat (file.fd, &stat_buf))
+ return NULL;
+ file.filesize = stat_buf.st_size;
+ }
+
file.handle = abfd;
+ off_t cur_offset = lseek(file.fd, 0, SEEK_CUR);
claim_file (&file, &claimed);
+ lseek(file.fd, cur_offset, SEEK_SET);
if (!claimed)
return NULL;
static bfd_boolean
simple_dummy_multiple_definition (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
- const char *name ATTRIBUTE_UNUSED,
- bfd *obfd ATTRIBUTE_UNUSED,
- asection *osec ATTRIBUTE_UNUSED,
- bfd_vma oval ATTRIBUTE_UNUSED,
+ struct bfd_link_hash_entry *h ATTRIBUTE_UNUSED,
bfd *nbfd ATTRIBUTE_UNUSED,
asection *nsec ATTRIBUTE_UNUSED,
bfd_vma nval ATTRIBUTE_UNUSED)
handle them, and that would only be a warning,
not an error. */
if (! ((*info->callbacks->multiple_definition)
- (info, (*sym_hash)->root.root.string,
- NULL, NULL, (bfd_vma) 0,
- (*sym_hash)->root.u.def.section->owner,
- (*sym_hash)->root.u.def.section,
- (*sym_hash)->root.u.def.value)))
+ (info, &(*sym_hash)->root, NULL, NULL, (bfd_vma) 0)))
goto error_return;
/* Try not to give this error too many times. */
(*sym_hash)->flags &= ~XCOFF_MULTIPLY_DEFINED;
|| h->root.u.def.value != val))
{
if (! ((*info->callbacks->multiple_definition)
- (info, h->root.root.string, h->root.u.def.section->owner,
- h->root.u.def.section, h->root.u.def.value,
- output_bfd, bfd_abs_section_ptr, val)))
+ (info, &h->root, output_bfd, bfd_abs_section_ptr, val)))
return FALSE;
}
+2011-04-27 Alan Modra <amodra@gmail.com>
+
+ Apply from mainline.
+ 2010-12-12 H.J. Lu <hongjiu.lu@intel.com>
+ * gas/elf/elf.exp: Run section9.
+ * gas/elf/section9.d: New.
+ * gas/elf/section9.s: Likewise.
+
2011-02-10 Vincent Rivière <vincent.riviere@freesbee.fr>
PR gas/6957
run_dump_test "section6"
run_dump_test "section7"
run_dump_test "section8"
+ run_dump_test "section9"
run_dump_test "dwarf2-1"
run_dump_test "dwarf2-2"
run_dump_test "dwarf2-3"
+2011-04-27 Alan Modra <amodra@gmail.com>
+
+ Backport from mainline.
+ 2011-04-24 Alan Modra <amodra@gmail.com>
+ PR ld/12365
+ PR ld/12696
+ * bfdlink.h (ENUM_BITFIELD): Define.
+ (struct bfd_link_hash_entry): Make "type" a bitfield. Add "non_ir_ref".
+ (struct bfd_link_callbacks <notice>): Pass bfd_link_hash_entry pointer
+ rather than "name".
+
+ 2011-04-20 Alan Modra <amodra@gmail.com>
+ PR ld/12365
+ * bfdlink.h (struct bfd_link_callbacks): Modify multiple_definition
+ and multiple_common parameters to pass in a bfd_link_hash_entry
+ pointer rather than name,bfd etc. found in the hash entry.
+
2010-11-25 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
* opcode/s390.h (enum s390_opcode_cpu_val): Add S390_OPCODE_MAXCPU.
* simple-object.h: New file.
-2010-10-15 Dave Korn <dave.korn.cygwin@gmail.com>
+2010-10-15 Dave Korn <dave.korn.cygwin@gmail.com>
Sync LD plugin patch series (part 1/6) with src/include/.
* plugin-api.h (LDPT_GNU_LD_VERSION): New ld_plugin_tag enum member.
-2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com>
+2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com>
Apply LD plugin patch series (part 6/6).
* bfdlink.h (struct_bfd_link_callbacks): Document new argument
to add_archive_element callback used to return a replacement bfd which
is to be added to the hash table in place of the original element.
-2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com>
+2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com>
Apply LD plugin patch series (part 1/6).
* plugin-api.h (LDPT_GNU_LD_VERSION): New ld_plugin_tag enum member.
#ifndef BFDLINK_H
#define BFDLINK_H
+#if (__GNUC__ * 1000 + __GNUC_MINOR__ > 2000)
+#define ENUM_BITFIELD(TYPE) __extension__ enum TYPE
+#else
+#define ENUM_BITFIELD(TYPE) unsigned int
+#endif
+
/* Which symbols to strip during a link. */
enum bfd_link_strip
{
struct bfd_hash_entry root;
/* Type of this entry. */
- enum bfd_link_hash_type type;
+ ENUM_BITFIELD (bfd_link_hash_type) type : 8;
+
+ unsigned int non_ir_ref : 1;
/* A union of information depending upon the type. */
union
bfd_boolean (*add_archive_element)
(struct bfd_link_info *, bfd *abfd, const char *name, bfd **subsbfd);
/* A function which is called when a symbol is found with multiple
- definitions. NAME is the symbol which is defined multiple times.
- OBFD is the old BFD, OSEC is the old section, OVAL is the old
- value, NBFD is the new BFD, NSEC is the new section, and NVAL is
- the new value. OBFD may be NULL. OSEC and NSEC may be
- bfd_com_section or bfd_ind_section. */
+ definitions. H is the symbol which is defined multiple times.
+ NBFD is the new BFD, NSEC is the new section, and NVAL is the new
+ value. NSEC may be bfd_com_section or bfd_ind_section. */
bfd_boolean (*multiple_definition)
- (struct bfd_link_info *, const char *name,
- bfd *obfd, asection *osec, bfd_vma oval,
+ (struct bfd_link_info *, struct bfd_link_hash_entry *h,
bfd *nbfd, asection *nsec, bfd_vma nval);
/* A function which is called when a common symbol is defined
- multiple times. NAME is the symbol appearing multiple times.
- OBFD is the BFD of the existing symbol; it may be NULL if this is
- not known. OTYPE is the type of the existing symbol, which may
- be bfd_link_hash_defined, bfd_link_hash_defweak,
- bfd_link_hash_common, or bfd_link_hash_indirect. If OTYPE is
- bfd_link_hash_common, OSIZE is the size of the existing symbol.
+ multiple times. H is the symbol appearing multiple times.
NBFD is the BFD of the new symbol. NTYPE is the type of the new
symbol, one of bfd_link_hash_defined, bfd_link_hash_common, or
bfd_link_hash_indirect. If NTYPE is bfd_link_hash_common, NSIZE
is the size of the new symbol. */
bfd_boolean (*multiple_common)
- (struct bfd_link_info *, const char *name,
- bfd *obfd, enum bfd_link_hash_type otype, bfd_vma osize,
+ (struct bfd_link_info *, struct bfd_link_hash_entry *h,
bfd *nbfd, enum bfd_link_hash_type ntype, bfd_vma nsize);
/* A function which is called to add a symbol to a set. ENTRY is
the link hash table entry for the set itself (e.g.,
(struct bfd_link_info *, const char *name,
bfd *abfd, asection *section, bfd_vma address);
/* A function which is called when a symbol in notice_hash is
- defined or referenced. NAME is the symbol. ABFD, SECTION and
- ADDRESS are the value of the symbol. If SECTION is
+ defined or referenced. H is the symbol. ABFD, SECTION and
+ ADDRESS are the (new) value of the symbol. If SECTION is
bfd_und_section, this is a reference. */
bfd_boolean (*notice)
- (struct bfd_link_info *, const char *name,
+ (struct bfd_link_info *, struct bfd_link_hash_entry *h,
bfd *abfd, asection *section, bfd_vma address);
/* Error or warning link info message. */
void (*einfo)
+2011-04-27 Alan Modra <amodra@gmail.com>
+
+ Backport from mainline.
+ 2011-04-24 Alan Modra <amodra@gmail.com>
+ PR ld/12365
+ PR ld/12696
+ * ldmain.c (notice): Delete "name" param, add "h".
+ * plugin.c (plugin_notice): Likewise. Set non_ir_ref. Handle
+ redefinitions of IR symbols in real BFDs.
+ (plugin_multiple_definition, plugin_multiple_common): Delete.
+ (non_ironly_hash, init_non_ironly_hash): Delete.
+ (is_visible_from_outside): Traverse entry_symbol chain.
+ (get_symbols): Use non_ir_ref flag rather than hash lookup.
+
+ 2011-04-20 Alan Modra <amodra@gmail.com>
+ PR ld/12365
+ * ldfile.c (ldfile_try_open_bfd): Move code creating and switching
+ to plugin IR BFD..
+ * ldmain.c (add_archive_element): ..and similar code here..
+ * plugin.c (plugin_maybe_claim): ..to here. New function.
+ (plugin_call_claim_file): Make static.
+ (asymbol_from_plugin_symbol): Set ELF st_shndx for common syms.
+ (plugin_multiple_common): New function.
+ (plugin_call_all_symbols_read): Hook in plugin_multiple_common.
+ * plugin.h (plugin_call_claim_file): Don't declare.
+ (plugin_maybe_claim): Declare.
+
+ 2011-04-20 Alan Modra <amodra@gmail.com>
+ PR ld/12365
+ * ldmain.c (multiple_definition): Take a bfd_link_hash_entry
+ pointer arg rather than "name", "obfd", "osec", "oval". Add code
+ removed from linker.c. Hack around xcofflink.c oddity in
+ passing NULL nbfd.
+ (multiple_common): Similarly.
+ * plugin.c (orig_allow_multiple_defs): Delete.
+ (plugin_call_all_symbols_read): Don't twiddle allow_multiple_definition.
+ (plugin_multiple_definition): Update.
+
+ 2011-04-18 Alan Modra <amodra@gmail.com>
+ PR ld/12365
+ PR ld/12672
+ * ldfile.c (ldfile_try_open_bfd): Don't attempt any plugin action
+ when no_more_claiming.
+ * ldmain.c (add_archive_element): Likewise.
+ (multiple_definition): Remove plugin_multiple_definition call.
+ (notice): Remove plugin_notice call.
+ * ldlang.c (lang_list_insert_after, void lang_list_remove_tail): Move.
+ Delete prototype.
+ (plugin_insert): New static var.
+ (open_input_bfds): Only rescan libs after plugin insert point.
+ (lang_gc_sections): Omit plugin claimed files.
+ (lang_process): Set plugin_insert. Only rescan when plugin adds
+ objects.
+ * plugin.h (no_more_claiming): Declare.
+ (plugin_notice, plugin_multiple_definition): Don't declare.
+ * plugin.c: Formatting.
+ (orig_notice_all, orig_allow_multiple_defs, orig_callbacks,
+ plugin_callbacks): New static vars.
+ (no_more_claiming): Make global.
+ (plugin_cached_allow_multiple_defs): Delete.
+ (plugin_get_ir_dummy_bfd): Set SEC_EXCLUDE on dummy .text section,
+ use newer bfd_make_section variant. Make COMMON section too.
+ Error handling. Correct setting of gp size.
+ (asymbol_from_plugin_symbol): Properly cast last arg of concat.
+ (message): Likewise for ACONCAT.
+ (asymbol_from_plugin_symbol): Use our COMMON section.
+ (get_symbols): When report_plugin_symbols, show visibility too.
+ (init_non_ironly_hash): Move. Don't test non_ironly_hash.
+ (plugin_load_plugins): Save state of linker callbacks, set up to
+ call plugin_notice instead. Call init_non_ironly_hash here.
+ (plugin_call_all_symbols_read): Set plugin_multiple_definition in
+ plugin callbacks.
+ (plugin_notice): Rewrite.
+ (plugin_multiple_definition): Make static, call original callback.
+
+ 2011-04-15 Alan Modra <amodra@gmail.com>
+ PR ld/12672
+ * ldlang.c (enum open_bfd_mode): New.
+ (open_input_bfds): Replace "force" param with "mode". Reload
+ archives for rescan. Update all callers.
+ (lang_process): Make another open_input_bfds pass for plugins.
+
+ 2011-03-23 Joseph Myers <joseph@codesourcery.com>
+ * lexsup.c (parse_args): Only set report_plugin_symbols if plugins
+ are enabled. Mark level as possibly unused.
+
+ 2011-03-10 Dave Korn <dave.korn.cygwin@gmail.com>
+ * plugin.c (get_symbols): Use wrapped lookup for undefined symbols.
+
+ 2011-03-10 Dave Korn <dave.korn.cygwin@gmail.com>
+ * ldlang.c (lang_check): Don't run checks on dummy IR BFDs.
+
+ 2011-03-10 Dave Korn <dave.korn.cygwin@gmail.com>
+ * ldlang.h (lang_input_statement_type): Add new 'claim_archive' flag,
+ wrapping both it and 'claim' flag in #ifdef ENABLE_PLUGINS.
+ * ldmain.c (add_archive_element): Set it if the member is claimed.
+ * ldlang.c (new_afile): Initialise claim_archive and claimed members.
+ (find_replacements_insert_point): New helper function.
+ (lang_process): After adding and opening replacement files passed
+ from plugin, splice them into correct place in statement list and
+ file chains to preserve critical link order.
+ (lang_list_insert_after): New helper function.
+ (lang_list_remove_tail): Likewise.
+
+ 2011-03-10 Dave Korn <dave.korn.cygwin@gmail.com>
+ * plugin.c (IRONLY_SUFFIX): Revise to nicely human-readable form.
+ (IRONLY_SUFFIX_LEN): Delete.
+ (plugin_get_ir_dummy_bfd): Don't append IRONLY_SUFFIX.
+ (is_ir_dummy_bfd): Don't look for suffix; check claimed flag of
+ enclosing lang input statement instead.
+
+ 2011-03-04 H.J. Lu <hongjiu.lu@intel.com>
+ * ld.texinfo: Document --verbose[=NUMBER].
+ * lexsup.c (ld_options): Update --verbose.
+ (parse_args): Set report_plugin_symbols.
+ * plugin.c (report_plugin_symbols): New.
+ (get_symbols): Report plugin symbols if report_plugin_symbols
+ is TRUE.
+ * plugin.h (report_plugin_symbols): New.
+
+ 2011-02-24 H.J. Lu <hongjiu.lu@intel.com>
+ PR ld/12507
+ * plugin.c (get_symbols): Don't check entry symbol here.
+ (init_non_ironly_hash): Add entry_symbol chain into
+ non_ironly_hash.
+
+ 2011-02-24 H.J. Lu <hongjiu.lu@intel.com>
+ PR ld/12507
+ * plugin.c (get_symbols): Don't mark entry symbol IR only.
+
+ 2010-12-06 H.J. Lu <hongjiu.lu@intel.com>
+ * lexsup.c (ld_options): Add -flto and -flto-partition= for
+ GCC LTO option compatibility.
+
+ 2010-12-01 H.J. Lu <hongjiu.lu@intel.com>
+ * plugin.h: Re-indent.
+
2011-04-20 Tristan Gingold <gingold@adacore.com>
* emultempl/aix.em (_add_options): Ignore -bbigtoc switch.
unresolved symbol but the option @option{--warn-unresolved-symbols}
can change this to a warning.
-@kindex --verbose
-@cindex verbose
+@kindex --verbose[=@var{NUMBER}]
+@cindex verbose[=@var{NUMBER}]
@item --dll-verbose
-@itemx --verbose
+@itemx --verbose[=@var{NUMBER}]
Display the version number for @command{ld} and list the linker emulations
supported. Display which input files can and cannot be opened. Display
-the linker script being used by the linker.
+the linker script being used by the linker. If the optional @var{NUMBER}
+argument > 1, plugin symbol status will also be displayed.
@kindex --version-script=@var{version-scriptfile}
@cindex version script, symbol versions
will be needed when and if we want to bfd_create a new
one using this one as a template. */
if (bfd_check_format (entry->the_bfd, bfd_object)
- && plugin_active_plugins_p ())
+ && plugin_active_plugins_p ()
+ && !no_more_claiming)
{
int fd = open (attempt, O_RDONLY | O_BINARY);
if (fd >= 0)
{
struct ld_plugin_input_file file;
- int claimed = 0;
file.name = attempt;
file.offset = 0;
file.filesize = lseek (fd, 0, SEEK_END);
file.fd = fd;
- /* We create a dummy BFD, initially empty, to house
- whatever symbols the plugin may want to add. */
- file.handle = plugin_get_ir_dummy_bfd (attempt, entry->the_bfd);
- if (plugin_call_claim_file (&file, &claimed))
- einfo (_("%P%F: %s: plugin reported error claiming file\n"),
- plugin_error_plugin ());
- /* fd belongs to us, not the plugin; but we don't need it. */
- close (fd);
- if (claimed)
- {
- /* Discard the real file's BFD and substitute the dummy one. */
- bfd_close (entry->the_bfd);
- entry->the_bfd = file.handle;
- entry->claimed = TRUE;
- bfd_make_readable (entry->the_bfd);
- }
- else
- {
- /* If plugin didn't claim the file, we don't need the dummy
- bfd. Can't avoid speculatively creating it, alas. */
- bfd_close_all_done (file.handle);
- entry->claimed = FALSE;
- }
+ plugin_maybe_claim (&file, entry);
}
}
#endif /* ENABLE_PLUGINS */
p->whole_archive = whole_archive;
p->loaded = FALSE;
p->missing_file = FALSE;
+#ifdef ENABLE_PLUGINS
+ p->claimed = FALSE;
+ p->claim_archive = FALSE;
+#endif /* ENABLE_PLUGINS */
lang_statement_append (&input_file_chain,
(lang_statement_union_type *) p,
/* Open all the input files. */
+enum open_bfd_mode
+ {
+ OPEN_BFD_NORMAL = 0,
+ OPEN_BFD_FORCE = 1,
+ OPEN_BFD_RESCAN = 2
+ };
+#ifdef ENABLE_PLUGINS
+static lang_input_statement_type *plugin_insert = NULL;
+#endif
+
static void
-open_input_bfds (lang_statement_union_type *s, bfd_boolean force)
+open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
{
for (; s != NULL; s = s->header.next)
{
switch (s->header.type)
{
case lang_constructors_statement_enum:
- open_input_bfds (constructor_list.head, force);
+ open_input_bfds (constructor_list.head, mode);
break;
case lang_output_section_statement_enum:
- open_input_bfds (s->output_section_statement.children.head, force);
+ open_input_bfds (s->output_section_statement.children.head, mode);
break;
case lang_wild_statement_enum:
/* Maybe we should load the file's symbols. */
- if (s->wild_statement.filename
+ if ((mode & OPEN_BFD_RESCAN) == 0
+ && s->wild_statement.filename
&& !wildcardp (s->wild_statement.filename)
&& !archive_path (s->wild_statement.filename))
lookup_name (s->wild_statement.filename);
- open_input_bfds (s->wild_statement.children.head, force);
+ open_input_bfds (s->wild_statement.children.head, mode);
break;
case lang_group_statement_enum:
{
do
{
undefs = link_info.hash->undefs_tail;
- open_input_bfds (s->group_statement.children.head, TRUE);
+ open_input_bfds (s->group_statement.children.head,
+ mode | OPEN_BFD_FORCE);
}
while (undefs != link_info.hash->undefs_tail);
}
/* If we are being called from within a group, and this
is an archive which has already been searched, then
force it to be researched unless the whole archive
- has been loaded already. */
- if (force
+ has been loaded already. Do the same for a rescan. */
+ if (mode != OPEN_BFD_NORMAL
+#ifdef ENABLE_PLUGINS
+ && ((mode & OPEN_BFD_RESCAN) == 0
+ || plugin_insert == NULL)
+#endif
&& !s->input_statement.whole_archive
&& s->input_statement.loaded
&& bfd_check_format (s->input_statement.the_bfd,
}
}
}
+#ifdef ENABLE_PLUGINS
+ /* If we have found the point at which a plugin added new
+ files, clear plugin_insert to enable archive rescan. */
+ if (&s->input_statement == plugin_insert)
+ plugin_insert = NULL;
+#endif
break;
case lang_assignment_statement_enum:
if (s->assignment_statement.exp->assign.hidden)
for (file = file_chain.head; file != NULL; file = file->input_statement.next)
{
+#ifdef ENABLE_PLUGINS
+ /* Don't check format of files claimed by plugin. */
+ if (file->input_statement.claimed)
+ continue;
+#endif /* ENABLE_PLUGINS */
input_bfd = file->input_statement.the_bfd;
compatible
= bfd_arch_get_compatible (input_bfd, link_info.output_bfd,
LANG_FOR_EACH_INPUT_STATEMENT (f)
{
asection *sec;
+#ifdef ENABLE_PLUGINS
+ if (f->claimed)
+ continue;
+#endif
for (sec = f->the_bfd->sections; sec != NULL; sec = sec->next)
if ((sec->flags & SEC_DEBUGGING) == 0)
sec->flags &= ~SEC_EXCLUDE;
}
}
+#ifdef ENABLE_PLUGINS
+/* Find the insert point for the plugin's replacement files. We
+ place them after the first claimed real object file, or if the
+ first claimed object is an archive member, after the last real
+ object file immediately preceding the archive. In the event
+ no objects have been claimed at all, we return the first dummy
+ object file on the list as the insert point; that works, but
+ the callee must be careful when relinking the file_chain as it
+ is not actually on that chain, only the statement_list and the
+ input_file list; in that case, the replacement files must be
+ inserted at the head of the file_chain. */
+
+static lang_input_statement_type *
+find_replacements_insert_point (void)
+{
+ lang_input_statement_type *claim1, *lastobject;
+ lastobject = &input_file_chain.head->input_statement;
+ for (claim1 = &file_chain.head->input_statement;
+ claim1 != NULL;
+ claim1 = &claim1->next->input_statement)
+ {
+ if (claim1->claimed)
+ return claim1->claim_archive ? lastobject : claim1;
+ /* Update lastobject if this is a real object file. */
+ if (claim1->the_bfd && (claim1->the_bfd->my_archive == NULL))
+ lastobject = claim1;
+ }
+ /* No files were claimed by the plugin. Choose the last object
+ file found on the list (maybe the first, dummy entry) as the
+ insert point. */
+ return lastobject;
+}
+
+/* Insert SRCLIST into DESTLIST after given element by chaining
+ on FIELD as the next-pointer. (Counterintuitively does not need
+ a pointer to the actual after-node itself, just its chain field.) */
+
+static void
+lang_list_insert_after (lang_statement_list_type *destlist,
+ lang_statement_list_type *srclist,
+ lang_statement_union_type **field)
+{
+ *(srclist->tail) = *field;
+ *field = srclist->head;
+ if (destlist->tail == field)
+ destlist->tail = srclist->tail;
+}
+
+/* Detach new nodes added to DESTLIST since the time ORIGLIST
+ was taken as a copy of it and leave them in ORIGLIST. */
+
+static void
+lang_list_remove_tail (lang_statement_list_type *destlist,
+ lang_statement_list_type *origlist)
+{
+ union lang_statement_union **savetail;
+ /* Check that ORIGLIST really is an earlier state of DESTLIST. */
+ ASSERT (origlist->head == destlist->head);
+ savetail = origlist->tail;
+ origlist->head = *(savetail);
+ origlist->tail = destlist->tail;
+ destlist->tail = savetail;
+ *savetail = NULL;
+}
+#endif /* ENABLE_PLUGINS */
+
void
lang_process (void)
{
/* Create a bfd for each input file. */
current_target = default_target;
- open_input_bfds (statement_list.head, FALSE);
+ open_input_bfds (statement_list.head, OPEN_BFD_NORMAL);
#ifdef ENABLE_PLUGINS
+ if (plugin_active_plugins_p ())
{
- union lang_statement_union **listend;
+ lang_statement_list_type added;
+ lang_statement_list_type files, inputfiles;
+
/* Now all files are read, let the plugin(s) decide if there
are any more to be added to the link before we call the
- emulation's after_open hook. */
- listend = statement_list.tail;
- ASSERT (!*listend);
+ emulation's after_open hook. We create a private list of
+ input statements for this purpose, which we will eventually
+ insert into the global statment list after the first claimed
+ file. */
+ added = *stat_ptr;
+ /* We need to manipulate all three chains in synchrony. */
+ files = file_chain;
+ inputfiles = input_file_chain;
if (plugin_call_all_symbols_read ())
einfo (_("%P%F: %s: plugin reported error after all symbols read\n"),
plugin_error_plugin ());
- /* If any new files were added, they will be on the end of the
- statement list, and we can open them now by getting open_input_bfds
- to carry on from where it ended last time. */
- if (*listend)
- open_input_bfds (*listend, FALSE);
+ /* Open any newly added files, updating the file chains. */
+ open_input_bfds (added.head, OPEN_BFD_NORMAL);
+ /* Restore the global list pointer now they have all been added. */
+ lang_list_remove_tail (stat_ptr, &added);
+ /* And detach the fresh ends of the file lists. */
+ lang_list_remove_tail (&file_chain, &files);
+ lang_list_remove_tail (&input_file_chain, &inputfiles);
+ /* Were any new files added? */
+ if (added.head != NULL)
+ {
+ /* If so, we will insert them into the statement list immediately
+ after the first input file that was claimed by the plugin. */
+ plugin_insert = find_replacements_insert_point ();
+ /* If a plugin adds input files without having claimed any, we
+ don't really have a good idea where to place them. Just putting
+ them at the start or end of the list is liable to leave them
+ outside the crtbegin...crtend range. */
+ ASSERT (plugin_insert != NULL);
+ /* Splice the new statement list into the old one. */
+ lang_list_insert_after (stat_ptr, &added,
+ &plugin_insert->header.next);
+ /* Likewise for the file chains. */
+ lang_list_insert_after (&input_file_chain, &inputfiles,
+ &plugin_insert->next_real_file);
+ /* We must be careful when relinking file_chain; we may need to
+ insert the new files at the head of the list if the insert
+ point chosen is the dummy first input file. */
+ if (plugin_insert->filename)
+ lang_list_insert_after (&file_chain, &files, &plugin_insert->next);
+ else
+ lang_list_insert_after (&file_chain, &files, &file_chain.head);
+
+ /* Rescan archives in case new undefined symbols have appeared. */
+ open_input_bfds (statement_list.head, OPEN_BFD_RESCAN);
+ }
}
#endif /* ENABLE_PLUGINS */
/* Set if the file does not exist. */
unsigned int missing_file : 1;
+#ifdef ENABLE_PLUGINS
/* Set if the file was claimed by a plugin. */
unsigned int claimed : 1;
+ /* Set if the file was claimed from an archive. */
+ unsigned int claim_archive : 1;
+#endif /* ENABLE_PLUGINS */
+
} lang_input_statement_type;
typedef struct
static bfd_boolean add_archive_element
(struct bfd_link_info *, bfd *, const char *, bfd **);
static bfd_boolean multiple_definition
- (struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma,
+ (struct bfd_link_info *, struct bfd_link_hash_entry *,
bfd *, asection *, bfd_vma);
static bfd_boolean multiple_common
- (struct bfd_link_info *, const char *, bfd *, enum bfd_link_hash_type,
- bfd_vma, bfd *, enum bfd_link_hash_type, bfd_vma);
+ (struct bfd_link_info *, struct bfd_link_hash_entry *,
+ bfd *, enum bfd_link_hash_type, bfd_vma);
static bfd_boolean add_to_set
(struct bfd_link_info *, struct bfd_link_hash_entry *,
bfd_reloc_code_real_type, bfd *, asection *, bfd_vma);
static bfd_boolean unattached_reloc
(struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma);
static bfd_boolean notice
- (struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma);
+ (struct bfd_link_info *, struct bfd_link_hash_entry *,
+ bfd *, asection *, bfd_vma);
static struct bfd_link_callbacks link_callbacks =
{
BFD, but we still want to output the original BFD filename. */
orig_input = *input;
#ifdef ENABLE_PLUGINS
- if (bfd_my_archive (abfd) != NULL && plugin_active_plugins_p ())
+ if (bfd_my_archive (abfd) != NULL
+ && plugin_active_plugins_p ()
+ && !no_more_claiming)
{
/* We must offer this archive member to the plugins to claim. */
int fd = open (bfd_my_archive (abfd)->filename, O_RDONLY | O_BINARY);
if (fd >= 0)
{
struct ld_plugin_input_file file;
- int claimed = 0;
+
/* Offset and filesize must refer to the individual archive
member, not the whole file, and must exclude the header.
Fortunately for us, that is how the data is stored in the
file.offset = abfd->origin;
file.filesize = arelt_size (abfd);
file.fd = fd;
- /* We create a dummy BFD, initially empty, to house
- whatever symbols the plugin may want to add. */
- file.handle = plugin_get_ir_dummy_bfd (abfd->filename, abfd);
- if (plugin_call_claim_file (&file, &claimed))
- einfo (_("%P%F: %s: plugin reported error claiming file\n"),
- plugin_error_plugin ());
- /* fd belongs to us, not the plugin; but we don't need it. */
- close (fd);
- if (claimed)
+ plugin_maybe_claim (&file, input);
+ if (input->claimed)
{
- /* Substitute the dummy BFD. */
- input->the_bfd = file.handle;
- input->claimed = TRUE;
- bfd_make_readable (input->the_bfd);
+ input->claim_archive = TRUE;
*subsbfd = input->the_bfd;
}
- else
- {
- /* Abandon the dummy BFD. */
- bfd_close_all_done (file.handle);
- input->claimed = FALSE;
- }
}
}
#endif /* ENABLE_PLUGINS */
multiple times. */
static bfd_boolean
-multiple_definition (struct bfd_link_info *info ATTRIBUTE_UNUSED,
- const char *name,
- bfd *obfd,
- asection *osec,
- bfd_vma oval,
+multiple_definition (struct bfd_link_info *info,
+ struct bfd_link_hash_entry *h,
bfd *nbfd,
asection *nsec,
bfd_vma nval)
{
-#ifdef ENABLE_PLUGINS
- /* We may get called back even when --allow-multiple-definition is in
- effect, as the plugin infrastructure needs to use this hook in
- order to swap out IR-only symbols for real ones. In that case,
- it will let us know not to continue by returning TRUE even if this
- is not an IR-only vs. non-IR symbol conflict. */
- if (plugin_multiple_definition (info, name, obfd, osec, oval, nbfd,
- nsec, nval))
+ const char *name;
+ bfd *obfd;
+ asection *osec;
+ bfd_vma oval;
+
+ if (info->allow_multiple_definition)
+ return TRUE;
+
+ switch (h->type)
+ {
+ case bfd_link_hash_defined:
+ osec = h->u.def.section;
+ oval = h->u.def.value;
+ obfd = h->u.def.section->owner;
+ break;
+ case bfd_link_hash_indirect:
+ osec = bfd_ind_section_ptr;
+ oval = 0;
+ obfd = NULL;
+ break;
+ default:
+ abort ();
+ }
+
+ /* Ignore a redefinition of an absolute symbol to the
+ same value; it's harmless. */
+ if (h->type == bfd_link_hash_defined
+ && bfd_is_abs_section (osec)
+ && bfd_is_abs_section (nsec)
+ && nval == oval)
return TRUE;
-#endif /* ENABLE_PLUGINS */
/* If either section has the output_section field set to
bfd_abs_section_ptr, it means that the section is being
discarded, and this is not really a multiple definition at all.
-FIXME: It would be cleaner to somehow ignore symbols defined in
-sections which are being discarded. */
+ FIXME: It would be cleaner to somehow ignore symbols defined in
+ sections which are being discarded. */
if ((osec->output_section != NULL
&& ! bfd_is_abs_section (osec)
&& bfd_is_abs_section (osec->output_section))
&& bfd_is_abs_section (nsec->output_section)))
return TRUE;
+ name = h->root.string;
+ if (nbfd == NULL)
+ {
+ nbfd = obfd;
+ nsec = osec;
+ nval = oval;
+ obfd = NULL;
+ }
einfo (_("%X%C: multiple definition of `%T'\n"),
nbfd, nsec, nval, name);
if (obfd != NULL)
static bfd_boolean
multiple_common (struct bfd_link_info *info ATTRIBUTE_UNUSED,
- const char *name,
- bfd *obfd,
- enum bfd_link_hash_type otype,
- bfd_vma osize,
+ struct bfd_link_hash_entry *h,
bfd *nbfd,
enum bfd_link_hash_type ntype,
bfd_vma nsize)
{
- if (! config.warn_common)
+ const char *name;
+ bfd *obfd;
+ enum bfd_link_hash_type otype;
+ bfd_vma osize;
+
+ if (!config.warn_common)
return TRUE;
+ name = h->root.string;
+ otype = h->type;
+ if (otype == bfd_link_hash_common)
+ {
+ obfd = h->u.c.p->section->owner;
+ osize = h->u.c.size;
+ }
+ else if (otype == bfd_link_hash_defined
+ || otype == bfd_link_hash_defweak)
+ {
+ obfd = h->u.def.section->owner;
+ osize = 0;
+ }
+ else
+ {
+ /* FIXME: It would nice if we could report the BFD which defined
+ an indirect symbol, but we don't have anywhere to store the
+ information. */
+ obfd = NULL;
+ osize = 0;
+ }
+
if (ntype == bfd_link_hash_defined
|| ntype == bfd_link_hash_defweak
|| ntype == bfd_link_hash_indirect)
static bfd_boolean
notice (struct bfd_link_info *info,
- const char *name,
+ struct bfd_link_hash_entry *h,
bfd *abfd,
asection *section,
bfd_vma value)
{
- if (name == NULL)
+ const char *name;
+
+ if (h == NULL)
{
if (command_line.cref || nocrossref_list != NULL)
return handle_asneeded_cref (abfd, (enum notice_asneeded_action) value);
return TRUE;
}
-#ifdef ENABLE_PLUGINS
- /* We should hide symbols in the dummy IR BFDs from the nocrossrefs list
- and let the real object files that are generated and added later trip
- the error instead. Similarly would be better to trace the real symbol
- from the real file than the temporary dummy. */
- if (!plugin_notice (info, name, abfd, section, value))
- return TRUE;
-#endif /* ENABLE_PLUGINS */
-
+ name = h->root.string;
if (info->notice_hash != NULL
- && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL)
+ && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL)
{
if (bfd_is_und_section (section))
einfo ("%B: reference to %s\n", abfd, name);
'\0', N_("PLUGIN"), N_("Load named plugin"), ONE_DASH },
{ {"plugin-opt", required_argument, NULL, OPTION_PLUGIN_OPT},
'\0', N_("ARG"), N_("Send arg to last-loaded plugin"), ONE_DASH },
+ { {"flto", optional_argument, NULL, OPTION_IGNORE},
+ '\0', NULL, N_("Ignored for GCC LTO option compatibility"),
+ ONE_DASH },
+ { {"flto-partition=", required_argument, NULL, OPTION_IGNORE},
+ '\0', NULL, N_("Ignored for GCC LTO option compatibility"),
+ ONE_DASH },
#endif /* ENABLE_PLUGINS */
{ {"Qy", no_argument, NULL, OPTION_IGNORE},
'\0', NULL, N_("Ignored for SVR4 compatibility"), ONE_DASH },
" ignore-all, report-all, ignore-in-object-files,\n"
" ignore-in-shared-libs"),
TWO_DASHES },
- { {"verbose", no_argument, NULL, OPTION_VERBOSE},
- '\0', NULL, N_("Output lots of information during link"), TWO_DASHES },
+ { {"verbose", optional_argument, NULL, OPTION_VERBOSE},
+ '\0', N_("[=NUMBER]"),
+ N_("Output lots of information during link"), TWO_DASHES },
{ {"dll-verbose", no_argument, NULL, OPTION_VERBOSE}, /* Linux. */
'\0', NULL, NULL, NO_HELP },
{ {"version-script", required_argument, NULL, OPTION_VERSION_SCRIPT },
version_printed = TRUE;
trace_file_tries = TRUE;
overflow_cutoff_limit = -2;
+ if (optarg != NULL)
+ {
+ char *end;
+ int level ATTRIBUTE_UNUSED = strtoul (optarg, &end, 0);
+ if (*end)
+ einfo (_("%P%F: invalid number `%s'\n"), optarg);
+#ifdef ENABLE_PLUGINS
+ report_plugin_symbols = level > 1;
+#endif /* ENABLE_PLUGINS */
+ }
break;
case 'v':
ldversion (0);
#include <Windows.h>
#endif
+/* Report plugin symbols. */
+bfd_boolean report_plugin_symbols;
+
/* The suffix to append to the name of the real (claimed) object file
when generating a dummy BFD to hold the IR symbols sent from the
- plugin. */
-#define IRONLY_SUFFIX ".ironly\004"
-
-/* This is sizeof an array of chars, not sizeof a const char *. We
- also have to avoid inadvertently counting the trailing NUL. */
-#define IRONLY_SUFFIX_LEN (sizeof (IRONLY_SUFFIX) - 1)
+ plugin. For cosmetic use only; appears in maps, crefs etc. */
+#define IRONLY_SUFFIX " (symbol from plugin)"
/* Stores a single argument passed to a plugin. */
typedef struct plugin_arg
/* Last plugin to cause an error, if any. */
static const char *error_plugin = NULL;
-/* A hash table that records symbols referenced by non-IR files. Used
- at get_symbols time to determine whether any prevailing defs from
- IR files are referenced only from other IR files, so tthat we can
- we can distinguish the LDPR_PREVAILING_DEF and LDPR_PREVAILING_DEF_IRONLY
- cases when establishing symbol resolutions. */
-static struct bfd_hash_table *non_ironly_hash = NULL;
+/* State of linker "notice" interface before we poked at it. */
+static bfd_boolean orig_notice_all;
+
+/* Original linker callbacks, and the plugin version. */
+static const struct bfd_link_callbacks *orig_callbacks;
+static struct bfd_link_callbacks plugin_callbacks;
/* Set at all symbols read time, to avoid recursively offering the plugin
its own newly-added input files and libs to claim. */
-static bfd_boolean no_more_claiming = FALSE;
-
-/* If the --allow-multiple-definition command-line option is active, we
- have to disable it so that BFD always calls our hook, and simulate the
- effect (when not resolving IR vs. real symbols) ourselves by ensuring
- TRUE is returned from the hook. */
-static bfd_boolean plugin_cached_allow_multiple_defs = FALSE;
+bfd_boolean no_more_claiming = FALSE;
/* List of tags to set in the constant leading part of the tv array. */
static const enum ld_plugin_tag tv_header_tags[] =
/* How many entries in the constant leading part of the tv array. */
static const size_t tv_header_size = ARRAY_SIZE (tv_header_tags);
+/* Forward references. */
+static bfd_boolean plugin_notice (struct bfd_link_info *info,
+ struct bfd_link_hash_entry *h, bfd *abfd,
+ asection *section, bfd_vma value);
+
#if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
#define RTLD_NOW 0 /* Dummy value. */
bfd *
plugin_get_ir_dummy_bfd (const char *name, bfd *srctemplate)
{
- asection *sec;
bfd *abfd;
bfd_use_reserved_id = 1;
- abfd = bfd_create (concat (name, IRONLY_SUFFIX, (const char *)NULL),
+ abfd = bfd_create (concat (name, IRONLY_SUFFIX, (const char *) NULL),
srctemplate);
- bfd_set_arch_info (abfd, bfd_get_arch_info (srctemplate));
- bfd_make_writable (abfd);
- bfd_copy_private_bfd_data (srctemplate, abfd);
- bfd_set_gp_size (abfd, bfd_get_gp_size (abfd));
- /* Create a minimal set of sections to own the symbols. */
- sec = bfd_make_section_old_way (abfd, ".text");
- bfd_set_section_flags (abfd, sec,
- (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY
- | SEC_ALLOC | SEC_LOAD | SEC_KEEP));
- sec->output_section = sec;
- sec->output_offset = 0;
- return abfd;
+ if (abfd != NULL)
+ {
+ abfd->flags |= BFD_LINKER_CREATED | BFD_PLUGIN;
+ bfd_set_arch_info (abfd, bfd_get_arch_info (srctemplate));
+ bfd_set_gp_size (abfd, bfd_get_gp_size (srctemplate));
+ if (bfd_make_writable (abfd)
+ && bfd_copy_private_bfd_data (srctemplate, abfd))
+ {
+ flagword flags;
+
+ /* Create sections to own the symbols. */
+ flags = (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY
+ | SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_EXCLUDE);
+ if (bfd_make_section_anyway_with_flags (abfd, ".text", flags))
+ return abfd;
+ }
+ }
+ einfo (_("could not create dummy IR bfd: %F%E\n"));
+ return NULL;
}
/* Check if the BFD passed in is an IR dummy object file. */
static bfd_boolean
is_ir_dummy_bfd (const bfd *abfd)
{
- size_t namlen;
-
- if (abfd == NULL)
- return FALSE;
- namlen = strlen (abfd->filename);
- if (namlen < IRONLY_SUFFIX_LEN)
- return FALSE;
- return !strcmp (abfd->filename + namlen - IRONLY_SUFFIX_LEN, IRONLY_SUFFIX);
+ /* ABFD can sometimes legitimately be NULL, e.g. when called from one
+ of the linker callbacks for a symbol in the *ABS* or *UND* sections.
+ Likewise, the usrdata field may be NULL if ABFD was added by the
+ backend without a corresponding input statement, as happens e.g.
+ when processing DT_NEEDED dependencies. */
+ return (abfd
+ && abfd->usrdata
+ && ((lang_input_statement_type *)(abfd->usrdata))->claimed);
}
/* Helpers to convert between BFD and GOLD symbol formats. */
asym->the_bfd = abfd;
asym->name = (ldsym->version
- ? concat (ldsym->name, "@", ldsym->version, NULL)
+ ? concat (ldsym->name, "@", ldsym->version, (const char *) NULL)
: ldsym->name);
asym->value = 0;
switch (ldsym->def)
asym->value = ldsym->size;
/* For ELF targets, set alignment of common symbol to 1. */
if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
- ((elf_symbol_type *) asym)->internal_elf_sym.st_value = 1;
+ {
+ ((elf_symbol_type *) asym)->internal_elf_sym.st_shndx = SHN_COMMON;
+ ((elf_symbol_type *) asym)->internal_elf_sym.st_value = 1;
+ }
break;
default:
is_visible_from_outside (struct ld_plugin_symbol *lsym, asection *section,
struct bfd_link_hash_entry *blhe)
{
+ struct bfd_sym_chain *sym;
+
/* Section's owner may be NULL if it is the absolute
section, fortunately is_ir_dummy_bfd handles that. */
if (!is_ir_dummy_bfd (section->owner))
return (lsym->visibility == LDPV_DEFAULT
|| lsym->visibility == LDPV_PROTECTED);
}
+
+ for (sym = &entry_symbol; sym != NULL; sym = sym->next)
+ if (sym->name
+ && strcmp (sym->name, blhe->root.string) == 0)
+ return TRUE;
+
return FALSE;
}
struct bfd_link_hash_entry *blhe;
bfd_boolean ironly;
asection *owner_sec;
-
- blhe = bfd_link_hash_lookup (link_info.hash, syms[n].name,
- FALSE, FALSE, TRUE);
+ if (syms[n].def != LDPK_UNDEF)
+ blhe = bfd_link_hash_lookup (link_info.hash, syms[n].name,
+ FALSE, FALSE, TRUE);
+ else
+ blhe = bfd_wrapped_link_hash_lookup (link_info.output_bfd, &link_info,
+ syms[n].name, FALSE, FALSE, TRUE);
if (!blhe)
{
syms[n].resolution = LDPR_UNKNOWN;
- continue;
+ goto report_symbol;
}
/* Determine resolution from blhe type and symbol's original type. */
|| blhe->type == bfd_link_hash_undefweak)
{
syms[n].resolution = LDPR_UNDEF;
- continue;
+ goto report_symbol;
}
if (blhe->type != bfd_link_hash_defined
&& blhe->type != bfd_link_hash_defweak
/* Find out which section owns the symbol. Since it's not undef,
it must have an owner; if it's not a common symbol, both defs
and weakdefs keep it in the same place. */
- owner_sec = (blhe->type == bfd_link_hash_common)
- ? blhe->u.c.p->section
- : blhe->u.def.section;
+ owner_sec = (blhe->type == bfd_link_hash_common
+ ? blhe->u.c.p->section
+ : blhe->u.def.section);
/* We need to know if the sym is referenced from non-IR files. Or
even potentially-referenced, perhaps in a future final link if
this is a partial one, perhaps dynamically at load-time if the
symbol is externally visible. */
- ironly = !is_visible_from_outside (&syms[n], owner_sec, blhe)
- && !bfd_hash_lookup (non_ironly_hash, syms[n].name, FALSE, FALSE);
+ ironly = !(blhe->non_ir_ref
+ || is_visible_from_outside (&syms[n], owner_sec, blhe));
/* If it was originally undefined or common, then it has been
resolved; determine how. */
syms[n].resolution = LDPR_RESOLVED_DYN;
else
syms[n].resolution = LDPR_RESOLVED_EXEC;
- continue;
+ goto report_symbol;
}
/* Was originally def, or weakdef. Does it prevail? If the
syms[n].resolution = (ironly
? LDPR_PREVAILING_DEF_IRONLY
: LDPR_PREVAILING_DEF);
- continue;
+ goto report_symbol;
}
/* Was originally def, weakdef, or common, but has been pre-empted. */
- syms[n].resolution = is_ir_dummy_bfd (owner_sec->owner)
- ? LDPR_PREEMPTED_IR
- : LDPR_PREEMPTED_REG;
+ syms[n].resolution = (is_ir_dummy_bfd (owner_sec->owner)
+ ? LDPR_PREEMPTED_IR
+ : LDPR_PREEMPTED_REG);
+
+ report_symbol:
+ if (report_plugin_symbols)
+ einfo (_("%P: %B: symbol `%s' "
+ "definition: %d, visibility: %d, resolution: %d\n"),
+ abfd, syms[n].name,
+ syms[n].def, syms[n].visibility, syms[n].resolution);
}
return LDPS_OK;
}
case LDPL_FATAL:
case LDPL_ERROR:
default:
- {
- char *newfmt = ACONCAT ((level == LDPL_FATAL
- ? "%P%F: " : "%P%X: ",
- format, "\n", NULL));
- fflush (stdout);
- vfinfo (stderr, newfmt, args, TRUE);
- fflush (stderr);
- }
+ {
+ char *newfmt = ACONCAT ((level == LDPL_FATAL ? "%P%F: " : "%P%X: ",
+ format, "\n", (const char *) NULL));
+ fflush (stdout);
+ vfinfo (stderr, newfmt, args, TRUE);
+ fflush (stderr);
+ }
break;
}
/* Since plugin(s) inited ok, assume they're going to want symbol
resolutions, which needs us to track which symbols are referenced
by non-IR files using the linker's notice callback. */
+ orig_notice_all = link_info.notice_all;
+ orig_callbacks = link_info.callbacks;
+ plugin_callbacks = *orig_callbacks;
+ plugin_callbacks.notice = &plugin_notice;
link_info.notice_all = TRUE;
+ link_info.callbacks = &plugin_callbacks;
return 0;
}
/* Call 'claim file' hook for all plugins. */
-int
+static int
plugin_call_claim_file (const struct ld_plugin_input_file *file, int *claimed)
{
plugin_t *curplug = plugins_list;
return plugin_error_p () ? -1 : 0;
}
+void
+plugin_maybe_claim (struct ld_plugin_input_file *file,
+ lang_input_statement_type *entry)
+{
+ int claimed = 0;
+
+ /* We create a dummy BFD, initially empty, to house whatever symbols
+ the plugin may want to add. */
+ file->handle = plugin_get_ir_dummy_bfd (entry->the_bfd->filename,
+ entry->the_bfd);
+ if (plugin_call_claim_file (file, &claimed))
+ einfo (_("%P%F: %s: plugin reported error claiming file\n"),
+ plugin_error_plugin ());
+ /* fd belongs to us, not the plugin; but we don't need it. */
+ close (file->fd);
+ if (claimed)
+ {
+ /* Discard the real file's BFD and substitute the dummy one. */
+
+ /* BFD archive handling caches elements so we can't call
+ bfd_close for archives. */
+ if (entry->the_bfd->my_archive == NULL)
+ bfd_close (entry->the_bfd);
+ entry->the_bfd = file->handle;
+ entry->claimed = TRUE;
+ bfd_make_readable (entry->the_bfd);
+ }
+ else
+ {
+ /* If plugin didn't claim the file, we don't need the dummy bfd.
+ Can't avoid speculatively creating it, alas. */
+ bfd_close_all_done (file->handle);
+ entry->claimed = FALSE;
+ }
+}
+
/* Call 'all symbols read' hook for all plugins. */
int
plugin_call_all_symbols_read (void)
/* Disable any further file-claiming. */
no_more_claiming = TRUE;
- /* If --allow-multiple-definition is in effect, we need to disable it,
- as the plugin infrastructure relies on the multiple_definition
- callback to swap out the dummy IR-only BFDs for new real ones
- when it starts opening the files added during this callback. */
- plugin_cached_allow_multiple_defs = link_info.allow_multiple_definition;
- link_info.allow_multiple_definition = FALSE;
-
while (curplug)
{
if (curplug->all_symbols_read_handler)
plugin_error_plugin ());
}
-/* Lazily init the non_ironly hash table. */
-static void
-init_non_ironly_hash (void)
-{
- if (non_ironly_hash == NULL)
- {
- non_ironly_hash =
- (struct bfd_hash_table *) xmalloc (sizeof (struct bfd_hash_table));
- if (!bfd_hash_table_init_n (non_ironly_hash,
- bfd_hash_newfunc,
- sizeof (struct bfd_hash_entry),
- 61))
- einfo (_("%P%F: bfd_hash_table_init failed: %E\n"));
- }
-}
-
/* To determine which symbols should be resolved LDPR_PREVAILING_DEF
and which LDPR_PREVAILING_DEF_IRONLY, we notice all the symbols as
- the linker adds them to the linker hash table. If we see a symbol
- being referenced from a non-IR file, we add it to the non_ironly hash
- table. If we can't find it there at get_symbols time, we know that
- it was referenced only by IR files. We have to notice_all symbols,
- because we won't necessarily know until later which ones will be
- contributed by IR files. */
-bfd_boolean
-plugin_notice (struct bfd_link_info *info ATTRIBUTE_UNUSED,
- const char *name, bfd *abfd,
- asection *section, bfd_vma value ATTRIBUTE_UNUSED)
-{
- bfd_boolean is_ref = bfd_is_und_section (section);
- bfd_boolean is_dummy = is_ir_dummy_bfd (abfd);
- init_non_ironly_hash ();
- /* We only care about refs, not defs, indicated by section pointing
- to the undefined section (according to the bfd linker notice callback
- interface definition). */
- if (is_ref && !is_dummy)
- {
- /* This is a ref from a non-IR file, so note the ref'd symbol
- in the non-IR-only hash. */
- if (!bfd_hash_lookup (non_ironly_hash, name, TRUE, TRUE))
- einfo (_("%P%X: %s: hash table failure adding symbol %s\n"),
- abfd->filename, name);
- }
- else if (!is_ref && is_dummy)
+ the linker adds them to the linker hash table. Mark those
+ referenced from a non-IR file with non_ir_ref. We have to
+ notice_all symbols, because we won't necessarily know until later
+ which ones will be contributed by IR files. */
+static bfd_boolean
+plugin_notice (struct bfd_link_info *info,
+ struct bfd_link_hash_entry *h,
+ bfd *abfd,
+ asection *section,
+ bfd_vma value)
+{
+ if (h != NULL)
{
- /* No further processing since this is a def from an IR dummy BFD. */
- return FALSE;
+ /* No further processing if this def/ref is from an IR dummy BFD. */
+ if (is_ir_dummy_bfd (abfd))
+ return TRUE;
+
+ /* If this is a ref, set non_ir_ref. */
+ if (bfd_is_und_section (section))
+ h->non_ir_ref = TRUE;
+
+ /* Otherwise, it must be a new def. Ensure any symbol defined
+ in an IR dummy BFD takes on a new value from a real BFD.
+ Weak symbols are not normally overridden by a new weak
+ definition, and strong symbols will normally cause multiple
+ definition errors. Avoid this by making the symbol appear
+ to be undefined. */
+ else if (((h->type == bfd_link_hash_defweak
+ || h->type == bfd_link_hash_defined)
+ && is_ir_dummy_bfd (h->u.def.section->owner))
+ || (h->type == bfd_link_hash_common
+ && is_ir_dummy_bfd (h->u.c.p->section->owner)))
+ h->type = bfd_link_hash_undefweak;
}
/* Continue with cref/nocrossref/trace-sym processing. */
+ if (h == NULL
+ || orig_notice_all
+ || (info->notice_hash != NULL
+ && bfd_hash_lookup (info->notice_hash, h->root.string,
+ FALSE, FALSE) != NULL))
+ return (*orig_callbacks->notice) (info, h, abfd, section, value);
return TRUE;
}
-
-/* When we add new object files to the link at all symbols read time,
- these contain the real code and symbols generated from the IR files,
- and so duplicate all the definitions already supplied by the dummy
- IR-only BFDs that we created at claim files time. We use the linker's
- multiple-definitions callback hook to fix up the clash, discarding
- the symbol from the IR-only BFD in favour of the symbol from the
- real BFD. We return true if this was not-really-a-clash because
- we've fixed it up, or anyway if --allow-multiple-definition was in
- effect (before we disabled it to ensure we got called back). */
-bfd_boolean
-plugin_multiple_definition (struct bfd_link_info *info, const char *name,
- bfd *obfd, asection *osec ATTRIBUTE_UNUSED,
- bfd_vma oval ATTRIBUTE_UNUSED,
- bfd *nbfd, asection *nsec, bfd_vma nval)
-{
- if (is_ir_dummy_bfd (obfd))
- {
- struct bfd_link_hash_entry *blhe
- = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, FALSE);
- if (!blhe)
- einfo (_("%P%X: %s: can't find IR symbol '%s'\n"), nbfd->filename,
- name);
- else if (blhe->type != bfd_link_hash_defined)
- einfo (_("%P%x: %s: bad IR symbol type %d\n"), name, blhe->type);
- /* Replace it with new details. */
- blhe->u.def.section = nsec;
- blhe->u.def.value = nval;
- return TRUE;
- }
- return plugin_cached_allow_multiple_defs;
-}
#ifndef GLD_PLUGIN_H
#define GLD_PLUGIN_H
+/* Report plugin symbols. */
+extern bfd_boolean report_plugin_symbols;
+
+/* Set at all symbols read time, to avoid recursively offering the plugin
+ its own newly-added input files and libs to claim. */
+extern bfd_boolean no_more_claiming;
/* This is the only forward declaration we need to avoid having
to include the plugin-api.h header in order to use this file. */
extern const char *plugin_error_plugin (void);
/* Call 'claim file' hook for all plugins. */
-extern int plugin_call_claim_file (const struct ld_plugin_input_file *file,
- int *claimed);
+extern void plugin_maybe_claim (struct ld_plugin_input_file *,
+ lang_input_statement_type *);
/* Call 'all symbols read' hook for all plugins. */
extern int plugin_call_all_symbols_read (void);
add_symbols hook has been called so that it can be read when linking. */
extern bfd *plugin_get_ir_dummy_bfd (const char *name, bfd *template);
-/* Notice-symbol bfd linker callback hook. */
-extern bfd_boolean plugin_notice (struct bfd_link_info *info,
- const char *name, bfd *abfd, asection *section,
- bfd_vma value);
-
-/* Multiple-definition bfd linker callback hook. */
-extern bfd_boolean plugin_multiple_definition (struct bfd_link_info *info,
- const char *name,
- bfd *obfd, asection *osec, bfd_vma oval,
- bfd *nbfd, asection *nsec, bfd_vma nval);
-
#endif /* !def GLD_PLUGIN_H */
+2011-04-27 Alan Modra <amodra@gmail.com>
+
+ Backport from mainline.
+ 2011-04-19 H.J. Lu <hongjiu.lu@intel.com>
+ * ld-plugin/plugin-ignore.d: Removed.
+
+ 2011-04-18 H.J. Lu <hongjiu.lu@intel.com>
+ * ld-plugin/plugin-7.d: Update expected LTO linker errors for
+ GCC 4.6.
+ * ld-plugin/plugin-8.d: Likewise.
+
+ 2011-04-18 Alan Modra <amodra@gmail.com>
+ * ld-plugin/plugin-7.d: Adjust for plugin changes.
+ * ld-plugin/plugin-8.d: Likewise.
+ * ld-plugin/plugin.exp: Pass --verbose=2 for visibility test, and
+ compare ld output to..
+ * ld-plugin/plugin-12.d: New.
+
+ 2011-04-11 Mark Wielaard <mjw@redhat.com>
+ PR 10549
+ * ld-unique: New directory.
+ * ld-unique/unique.exp: New file: Run the UNIQUE tests.
+ * ld-unique/unique.s: New test file.
+ * ld-unique/unique_empty.s: Likewise.
+ * ld-unique/unique_shared.s: Likewise.
+
2011-04-11 Alan Modra <amodra@gmail.com>
* ld-elf/eh-frame-hdr.d: xfail avr.
hook called: claim_file tmpdir/text.o \[@0/.* not claimed
#...
hook called: all symbols read.
+`func' referenced in section `\.text.*' of tmpdir/main.o: defined in discarded section .*
hook called: cleanup.
#...
hook called: all symbols read.
Sym: '_?func' Resolution: LDPR_PREVAILING_DEF
Sym: '_?func2' Resolution: LDPR_PREVAILING_DEF_IRONLY
+`func' referenced in section `\.text.*' of tmpdir/main.o: defined in discarded section .*
hook called: cleanup.
#...
set testobjfiles_notext "tmpdir/main.o tmpdir/func.o"
# Rather than having libs we just define dummy values for anything
# we may need to link a target exe; we aren't going to run it anyway.
-set libs "[ld_simple_link_defsyms] --defsym ${_}printf=0 --defsym ${_}puts=0"
+set libs "[ld_simple_link_defsyms] --defsym ${_}printf=${_}main --defsym ${_}puts=${_}main"
set plugin_tests [list \
[list "load plugin" "-plugin $plugin_path \
-plugin-opt sym:${_}func2::0:2:0 \
-plugin-opt sym:${_}func3::0:3:0 \
-plugin-opt dumpresolutions \
- $testobjfiles $libs" "" "" {{ld plugin-ignore.d} \
- {readelf -s plugin-vis-1.d}} "main.x" ] \
+ -plugin-opt add:tmpdir/func.o \
+ $testobjfiles $libs --verbose=2" "" "" {{ld plugin-12.d}} "main.x" ] \
]
if { !$can_compile || $failed_compile } {