aboutsummaryrefslogtreecommitdiff
path: root/bfd/elflink.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/elflink.c')
-rw-r--r--bfd/elflink.c148
1 files changed, 84 insertions, 64 deletions
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 666399b..53ec792 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -27,10 +27,7 @@
#include "safe-ctype.h"
#include "libiberty.h"
#include "objalloc.h"
-#if BFD_SUPPORTS_PLUGINS
-#include "plugin-api.h"
#include "plugin.h"
-#endif
#include <limits.h>
#ifndef CHAR_BIT
@@ -2284,68 +2281,85 @@ _bfd_elf_export_symbol (struct elf_link_hash_entry *h, void *data)
return true;
}
-/* Return the glibc version reference if VERSION_DEP is added to the
- list of glibc version dependencies successfully. VERSION_DEP will
- be put into the .gnu.version_r section. GLIBC_MINOR_BASE is the
- pointer to the glibc minor base version. */
+/* Return true if linked against glibc. Otherwise return false. If
+ linked against glibc, add VERSION_DEP to the list of glibc version
+ dependencies and set *AUTO_VERSION to true. If *AUTO_VERSION is
+ true, add VERSION_DEP to the version dependency list only if libc.so
+ defines VERSION_DEP. GLIBC_MINOR_BASE is the pointer to the glibc
+ minor base version. */
-static Elf_Internal_Verneed *
+static bool
elf_link_add_glibc_verneed (struct elf_find_verdep_info *rinfo,
- Elf_Internal_Verneed *glibc_verref,
const char *version_dep,
- int *glibc_minor_base)
+ int *glibc_minor_base,
+ bool *auto_version)
{
Elf_Internal_Verneed *t;
Elf_Internal_Vernaux *a;
size_t amt;
int minor_version = -1;
+ bool added = false;
+ bool glibc = false;
- if (glibc_verref != NULL)
+ for (t = elf_tdata (rinfo->info->output_bfd)->verref;
+ t != NULL;
+ t = t->vn_nextref)
{
- t = glibc_verref;
+ const char *soname = bfd_elf_get_dt_soname (t->vn_bfd);
+ if (soname != NULL && startswith (soname, "libc.so."))
+ break;
+ }
- for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
+ /* Skip the shared library if it isn't libc.so. */
+ if (t == NULL)
+ goto update_auto_version_and_return;
+
+ for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
+ {
+ /* Return if VERSION_DEP dependency has been added. */
+ if (a->vna_nodename == version_dep
+ || strcmp (a->vna_nodename, version_dep) == 0)
{
- /* Return if VERSION_DEP dependency has been added. */
- if (a->vna_nodename == version_dep
- || strcmp (a->vna_nodename, version_dep) == 0)
- return t;
+ glibc = true;
+ goto update_auto_version_and_return;
}
- }
- else
- {
- for (t = elf_tdata (rinfo->info->output_bfd)->verref;
- t != NULL;
- t = t->vn_nextref)
+
+ /* Check if libc.so provides GLIBC_2.XX version. */
+ if (startswith (a->vna_nodename, "GLIBC_2."))
{
- const char *soname = bfd_elf_get_dt_soname (t->vn_bfd);
- if (soname != NULL && startswith (soname, "libc.so."))
- break;
+ minor_version = strtol (a->vna_nodename + 8, NULL, 10);
+ if (minor_version < *glibc_minor_base)
+ *glibc_minor_base = minor_version;
}
+ }
- /* Skip the shared library if it isn't libc.so. */
- if (t == NULL)
- return t;
+ /* Skip if it isn't linked against glibc. */
+ if (minor_version < 0)
+ goto update_auto_version_and_return;
- for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
- {
- /* Return if VERSION_DEP dependency has been added. */
- if (a->vna_nodename == version_dep
- || strcmp (a->vna_nodename, version_dep) == 0)
- return t;
+ glibc = true;
- /* Check if libc.so provides GLIBC_2.XX version. */
- if (startswith (a->vna_nodename, "GLIBC_2."))
- {
- minor_version = strtol (a->vna_nodename + 8, NULL, 10);
- if (minor_version < *glibc_minor_base)
- *glibc_minor_base = minor_version;
- }
- }
+ if (auto_version && *auto_version)
+ {
+ /* Add VERSION_DEP to the version dependency list only if
+ libc.so defines VERSION_DEP. */
- /* Skip if it isn't linked against glibc. */
- if (minor_version < 0)
- return NULL;
+ bool defined = false;
+ Elf_Internal_Verdef *d;
+
+ for (d = elf_tdata (t->vn_bfd)->verdef;
+ d != NULL;
+ d = d->vd_nextdef)
+ if (strcmp (d->vd_nodename, version_dep) == 0)
+ {
+ defined = true;
+ break;
+ }
+
+ /* Set *AUTO_VERSION to false and return true to indicate that
+ libc.so doesn't define VERSION_DEP. */
+ if (!defined)
+ goto update_auto_version_and_return;
}
/* Skip if 2.GLIBC_MINOR_BASE includes VERSION_DEP. */
@@ -2353,7 +2367,7 @@ elf_link_add_glibc_verneed (struct elf_find_verdep_info *rinfo,
{
minor_version = strtol (version_dep + 8, NULL, 10);
if (minor_version <= *glibc_minor_base)
- return NULL;
+ goto update_auto_version_and_return;
}
amt = sizeof *a;
@@ -2361,7 +2375,8 @@ elf_link_add_glibc_verneed (struct elf_find_verdep_info *rinfo,
if (a == NULL)
{
rinfo->failed = true;
- return NULL;
+ glibc = false;
+ goto update_auto_version_and_return;
}
a->vna_nodename = version_dep;
@@ -2372,30 +2387,38 @@ elf_link_add_glibc_verneed (struct elf_find_verdep_info *rinfo,
t->vn_auxptr = a;
- return t;
+ added = true;
+
+ update_auto_version_and_return:
+ if (auto_version)
+ *auto_version = added;
+
+ return glibc;
}
/* Add VERSION_DEP to the list of version dependencies when linked
against glibc. */
-void
+bool
_bfd_elf_link_add_glibc_version_dependency
(struct elf_find_verdep_info *rinfo,
- const char *version_dep[])
+ const char *const version_dep[],
+ bool *auto_version)
{
- Elf_Internal_Verneed *t = NULL;
int glibc_minor_base = INT_MAX;
do
{
- t = elf_link_add_glibc_verneed (rinfo, t, *version_dep,
- &glibc_minor_base);
- /* Return if there is no glibc version reference. */
- if (t == NULL)
- return;
+ /* Return if not linked against glibc. */
+ if (!elf_link_add_glibc_verneed (rinfo, *version_dep,
+ &glibc_minor_base, auto_version))
+ return false;
version_dep++;
+ auto_version++;
}
while (*version_dep != NULL);
+
+ return true;
}
/* Add GLIBC_ABI_DT_RELR to the list of version dependencies when
@@ -2406,12 +2429,12 @@ _bfd_elf_link_add_dt_relr_dependency (struct elf_find_verdep_info *rinfo)
{
if (rinfo->info->enable_dt_relr)
{
- const char *version[] =
+ static const char *const version[] =
{
"GLIBC_ABI_DT_RELR",
NULL
};
- _bfd_elf_link_add_glibc_version_dependency (rinfo, version);
+ _bfd_elf_link_add_glibc_version_dependency (rinfo, version, NULL);
}
}
@@ -3679,11 +3702,8 @@ elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef)
get the correct symbol table. */
if (abfd->plugin_format == bfd_plugin_yes
|| abfd->plugin_format == bfd_plugin_yes_unused
-#if BFD_SUPPORTS_PLUGINS
|| (abfd->plugin_format == bfd_plugin_unknown
- && bfd_link_plugin_object_p (abfd))
-#endif
- )
+ && bfd_link_plugin_object_p (abfd)))
{
/* Use the IR symbol table if the object has been claimed by
plugin. */
@@ -11293,7 +11313,7 @@ _bfd_elf_default_action_discarded (asection *sec)
&& strncmp (sec->name, ".eh_frame.", 10) == 0)
return 0;
- if (strcmp (".sframe", sec->name) == 0)
+ if (elf_section_type (sec) == SHT_GNU_SFRAME)
return 0;
if (strcmp (".gcc_except_table", sec->name) == 0)