/* Plugin control for the GNU linker.
- Copyright (C) 2010-2019 Free Software Foundation, Inc.
+ Copyright (C) 2010-2020 Free Software Foundation, Inc.
This file is part of the GNU Binutils.
#include "bfd.h"
#include "bfdlink.h"
#include "bfdver.h"
+#include "ctf-api.h"
#include "ld.h"
#include "ldmain.h"
#include "ldmisc.h"
struct bfd_link_hash_entry *,
bfd *, asection *, bfd_vma, flagword);
-static const bfd_target * plugin_object_p (bfd *);
+static bfd_cleanup plugin_object_p (bfd *);
#if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
return abfd;
}
}
-report_error:
+ report_error:
einfo (_("%F%P: could not create dummy IR bfd: %E\n"));
return NULL;
}
flags = BSF_GLOBAL;
section = bfd_com_section_ptr;
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_shndx = SHN_COMMON;
- ((elf_symbol_type *) asym)->internal_elf_sym.st_value = 1;
- }
break;
default:
asym->flags = flags;
asym->section = section;
- /* Visibility only applies on ELF targets. */
if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
{
elf_symbol_type *elfsym = elf_symbol_from (abfd, asym);
if (!elfsym)
einfo (_("%F%P: %s: non-ELF symbol in ELF BFD!\n"), asym->name);
+
+ if (ldsym->def == LDPK_COMMON)
+ {
+ elfsym->internal_elf_sym.st_shndx = SHN_COMMON;
+ elfsym->internal_elf_sym.st_value = 1;
+ }
+
switch (ldsym->visibility)
{
default:
visibility = STV_HIDDEN;
break;
}
- elfsym->internal_elf_sym.st_other
- = (visibility | (elfsym->internal_elf_sym.st_other
- & ~ELF_ST_VISIBILITY (-1)));
+ elfsym->internal_elf_sym.st_other |= visibility;
}
return LDPS_OK;
return FALSE;
}
-/* Return LTO kind string name that corresponds to INDEX enum value. */
+/* Return LTO kind string name that corresponds to IDX enum value. */
static const char *
-get_lto_kind (unsigned int index)
+get_lto_kind (unsigned int idx)
{
static char buffer[64];
const char *lto_kind_str[5] =
"COMMON"
};
- if (index < ARRAY_SIZE (lto_kind_str))
- return lto_kind_str [index];
+ if (idx < ARRAY_SIZE (lto_kind_str))
+ return lto_kind_str [idx];
- sprintf (buffer, _("unknown LTO kind value %x"), index);
+ sprintf (buffer, _("unknown LTO kind value %x"), idx);
return buffer;
}
-/* Return LTO resolution string name that corresponds to INDEX enum value. */
+/* Return LTO resolution string name that corresponds to IDX enum value. */
static const char *
-get_lto_resolution (unsigned int index)
+get_lto_resolution (unsigned int idx)
{
static char buffer[64];
static const char *lto_resolution_str[10] =
"PREVAILING_DEF_IRONLY_EXP",
};
- if (index < ARRAY_SIZE (lto_resolution_str))
- return lto_resolution_str [index];
+ if (idx < ARRAY_SIZE (lto_resolution_str))
+ return lto_resolution_str [idx];
- sprintf (buffer, _("unknown LTO resolution value %x"), index);
+ sprintf (buffer, _("unknown LTO resolution value %x"), idx);
return buffer;
}
-/* Return LTO visibility string name that corresponds to INDEX enum value. */
+/* Return LTO visibility string name that corresponds to IDX enum value. */
static const char *
-get_lto_visibility (unsigned int index)
+get_lto_visibility (unsigned int idx)
{
static char buffer[64];
const char *lto_visibility_str[4] =
"HIDDEN"
};
- if (index < ARRAY_SIZE (lto_visibility_str))
- return lto_visibility_str [index];
+ if (idx < ARRAY_SIZE (lto_visibility_str))
+ return lto_visibility_str [idx];
- sprintf (buffer, _("unknown LTO visibility value %x"), index);
+ sprintf (buffer, _("unknown LTO visibility value %x"), idx);
return buffer;
}
struct bfd_link_hash_entry *blhe;
asection *owner_sec;
int res;
+ struct bfd_link_hash_entry *h
+ = bfd_link_hash_lookup (link_info.hash, syms[n].name,
+ FALSE, FALSE, TRUE);
+ enum { wrap_none, wrapper, wrapped } wrap_status = wrap_none;
- if (syms[n].def != LDPK_UNDEF)
- blhe = bfd_link_hash_lookup (link_info.hash, syms[n].name,
- FALSE, FALSE, TRUE);
+ if (syms[n].def != LDPK_UNDEF && syms[n].def != LDPK_WEAKUNDEF)
+ {
+ blhe = h;
+ if (blhe && link_info.wrap_hash != NULL)
+ {
+ /* Check if a symbol is a wrapper symbol. */
+ struct bfd_link_hash_entry *unwrap
+ = unwrap_hash_lookup (&link_info, (bfd *) abfd, blhe);
+ if (unwrap && unwrap != h)
+ wrap_status = wrapper;
+ }
+ }
else
- blhe = bfd_wrapped_link_hash_lookup (link_info.output_bfd, &link_info,
- syms[n].name, FALSE, FALSE, TRUE);
+ {
+ blhe = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
+ &link_info, syms[n].name,
+ FALSE, FALSE, TRUE);
+ /* Check if a symbol is a wrapped symbol. */
+ if (blhe && blhe != h)
+ wrap_status = wrapped;
+ }
if (!blhe)
{
/* The plugin is called to claim symbols in an archive element
/* 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. */
- if (blhe->non_ir_ref_regular)
+ symbol is externally visible. Also check for wrapper symbol. */
+ if (blhe->non_ir_ref_regular || wrap_status == wrapper)
res = LDPR_PREVAILING_DEF;
+ else if (wrap_status == wrapped)
+ res = LDPR_RESOLVED_IR;
else if (is_visible_from_outside (&syms[n], blhe))
res = def_ironly_exp;
}
return copy;
}
-static const bfd_target *
+static void
+plugin_cleanup (bfd *abfd ATTRIBUTE_UNUSED)
+{
+}
+
+static bfd_cleanup
plugin_object_p (bfd *ibfd)
{
int claimed;
if (ibfd->plugin_format != bfd_plugin_unknown)
{
if (ibfd->plugin_format == bfd_plugin_yes)
- return ibfd->plugin_dummy_bfd->xvec;
+ return plugin_cleanup;
else
return NULL;
}
/* We create a dummy BFD, initially empty, to house whatever symbols
the plugin may want to add. */
- abfd = plugin_get_ir_dummy_bfd (ibfd->filename, ibfd);
+ abfd = plugin_get_ir_dummy_bfd (bfd_get_filename (ibfd), ibfd);
input = bfd_alloc (abfd, sizeof (*input));
if (input == NULL)
if (!bfd_plugin_open_input (ibfd, &file))
return NULL;
- if (file.name == ibfd->filename)
+ if (file.name == bfd_get_filename (ibfd))
{
/* We must copy filename attached to ibfd if it is not an archive
member since it may be freed by bfd_close below. */
input->use_mmap = FALSE;
input->offset = file.offset;
input->filesize = file.filesize;
- input->name = plugin_strdup (abfd, ibfd->filename);
+ input->name = plugin_strdup (abfd, bfd_get_filename (ibfd));
claimed = 0;
ibfd->plugin_format = bfd_plugin_yes;
ibfd->plugin_dummy_bfd = abfd;
bfd_make_readable (abfd);
- return abfd->xvec;
+ abfd->no_export = ibfd->no_export;
+ return plugin_cleanup;
}
else
{
ref = TRUE;
}
- /* Otherwise, it must be a new def. */
- else
+
+ /* A common symbol should be merged with other commons or
+ defs with the same name. In particular, a common ought
+ to be overridden by a def in a -flto object. In that
+ sense a common is also a ref. */
+ else if (bfd_is_com_section (section))
{
- /* 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. */
- if (((h->type == bfd_link_hash_defweak
- || h->type == bfd_link_hash_defined)
- && is_ir_dummy_bfd (sym_bfd = h->u.def.section->owner))
- || (h->type == bfd_link_hash_common
- && is_ir_dummy_bfd (sym_bfd = h->u.c.p->section->owner)))
+ if (h->type == bfd_link_hash_common
+ && is_ir_dummy_bfd (sym_bfd = h->u.c.p->section->owner))
{
h->type = bfd_link_hash_undefweak;
h->u.undef.abfd = sym_bfd;
}
+ ref = TRUE;
+ }
- /* A common symbol should be merged with other commons or
- defs with the same name. In particular, a common ought
- to be overridden by a def in a -flto object. In that
- sense a common is also a ref. */
- if (bfd_is_com_section (section))
- 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 (sym_bfd = h->u.def.section->owner))
+ || (h->type == bfd_link_hash_common
+ && is_ir_dummy_bfd (sym_bfd = h->u.c.p->section->owner)))
+ {
+ h->type = bfd_link_hash_undefweak;
+ h->u.undef.abfd = sym_bfd;
}
if (ref)