aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2017-04-19 01:26:57 +0930
committerAlan Modra <amodra@gmail.com>2017-04-19 20:39:52 +0930
commit954b63d4c8645f86e40c7ef6c6d60acd2bf019de (patch)
tree7e351a33b44fe2672265e418e9d3d4f9e38215d1 /bfd
parent951787ed6d13f8f441d93fc3f6fb870c234774af (diff)
downloadgdb-954b63d4c8645f86e40c7ef6c6d60acd2bf019de.zip
gdb-954b63d4c8645f86e40c7ef6c6d60acd2bf019de.tar.gz
gdb-954b63d4c8645f86e40c7ef6c6d60acd2bf019de.tar.bz2
Implement -z dynamic-undefined-weak
-z nodynamic-undefined-weak is only implemented for x86. (The sparc backend has some support code but doesn't enable the option by including ld/emulparams/dynamic_undefined_weak.sh, and since the support looks like it may be broken I haven't enabled it.) This patch adds the complementary -z dynamic-undefined-weak, extends both options to affect building of shared libraries as well as executables, and adds support for the option on powerpc. include/ * bfdlink.h (struct bfd_link_info <dynamic_undefined_weak>): Revise comment. bfd/ * elflink.c (_bfd_elf_adjust_dynamic_symbol): Hide undefweak or make dynamic for info->dynamic_undefined_weak 0 and 1. * elf32-ppc.c:Formatting. (ensure_undefweak_dynamic): Don't make dynamic when info->dynamic_undefined_weak is zero. (allocate_dynrelocs): Discard undefweak dyn_relocs for info->dynamic_undefined_weak. Discard undef dyn_relocs when not default visibility. Discard undef and undefweak dyn_relocs earlier. (ppc_elf_relocate_section): Adjust to suit. * elf64-ppc.c: Formatting. (ensure_undefweak_dynamic): Don't make dynamic when info->dynamic_undefined_weak is zero. (allocate_dynrelocs): Discard undefweak dyn_relocs for info->dynamic_undefined_weak. Discard them earlier. ld/ * ld.texinfo (dynamic-undefined-weak): Document. (nodynamic-undefined-weak): Document that this option now can be used with shared libs. * emulparams/dynamic_undefined_weak.sh: Support -z dynamic-undefined-weak. * emulparams/elf32ppccommon.sh: Include dynamic_undefined_weak.sh. * testsuite/ld-undefined/weak-undef.exp (undef_weak_so), (undef_weak_exe): New. Use them. Add -z dynamic-undefined-weak and -z nodynamic-undefined-weak tests. * Makefile.am: Update powerpc dependencies. * Makefile.in: Regenerate.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog18
-rw-r--r--bfd/elf32-ppc.c46
-rw-r--r--bfd/elf64-ppc.c22
-rw-r--r--bfd/elflink.c18
4 files changed, 73 insertions, 31 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index f1ca8b4..b66ade6 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,21 @@
+2017-04-19 Alan Modra <amodra@gmail.com>
+
+ * elflink.c (_bfd_elf_adjust_dynamic_symbol): Hide undefweak
+ or make dynamic for info->dynamic_undefined_weak 0 and 1.
+ * elf32-ppc.c:Formatting.
+ (ensure_undefweak_dynamic): Don't make dynamic when
+ info->dynamic_undefined_weak is zero.
+ (allocate_dynrelocs): Discard undefweak dyn_relocs for
+ info->dynamic_undefined_weak. Discard undef dyn_relocs when
+ not default visibility. Discard undef and undefweak
+ dyn_relocs earlier.
+ (ppc_elf_relocate_section): Adjust to suit.
+ * elf64-ppc.c: Formatting.
+ (ensure_undefweak_dynamic): Don't make dynamic when
+ info->dynamic_undefined_weak is zero.
+ (allocate_dynrelocs): Discard undefweak dyn_relocs for
+ info->dynamic_undefined_weak. Discard them earlier.
+
2017-04-17 H.J. Lu <hongjiu.lu@intel.com>
PR ld/21389
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index 4bd58e2..6a24a46 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -2609,7 +2609,7 @@ ppc_elf_modify_segment_map (bfd *abfd,
amt += (m->count - j - 1) * sizeof (asection *);
n = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
if (n == NULL)
- return FALSE;
+ return FALSE;
n->p_type = PT_LOAD;
n->count = m->count - j;
@@ -5947,6 +5947,7 @@ ensure_undefweak_dynamic (struct bfd_link_info *info,
struct elf_link_hash_table *htab = elf_hash_table (info);
if (htab->dynamic_sections_created
+ && info->dynamic_undefined_weak != 0
&& h->root.type == bfd_link_hash_undefweak
&& h->dynindx == -1
&& !h->forced_local
@@ -6036,6 +6037,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
else
eh->elf.got.offset = (bfd_vma) -1;
+ /* If no dynamic sections we can't have dynamic relocs, except for
+ IFUNCs which are handled even in static executables. */
if (!htab->elf.dynamic_sections_created
&& h->type != STT_GNU_IFUNC)
eh->dyn_relocs = NULL;
@@ -6050,13 +6053,25 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
changes. */
else if (bfd_link_pic (info))
{
+ /* Discard relocs on undefined symbols that must be local. */
+ if (h->root.type == bfd_link_hash_undefined
+ && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+ eh->dyn_relocs = NULL;
+
+ /* Also discard relocs on undefined weak syms with non-default
+ visibility, or when dynamic_undefined_weak says so. */
+ else if (h->root.type == bfd_link_hash_undefweak
+ && (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+ || info->dynamic_undefined_weak == 0))
+ eh->dyn_relocs = NULL;
+
/* Relocs that use pc_count are those that appear on a call insn,
or certain REL relocs (see must_be_dyn_reloc) that can be
generated via assembly. We want calls to protected symbols to
resolve directly to the function rather than going via the plt.
If people want function pointer comparisons to work as expected
then they should avoid writing weird assembly. */
- if (SYMBOL_CALLS_LOCAL (info, h))
+ else if (SYMBOL_CALLS_LOCAL (info, h))
{
struct elf_dyn_relocs **pp;
@@ -6084,24 +6099,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
}
}
- /* Discard relocs on undefined symbols that must be local. */
- if (eh->dyn_relocs != NULL
- && h->root.type == bfd_link_hash_undefined
- && (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
- || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL))
- eh->dyn_relocs = NULL;
-
- /* Also discard relocs on undefined weak syms with non-default
- visibility. */
- if (eh->dyn_relocs != NULL
- && h->root.type == bfd_link_hash_undefweak)
+ if (eh->dyn_relocs != NULL)
{
- if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
- eh->dyn_relocs = NULL;
-
/* Make sure undefined weak symbols are output as a dynamic
symbol in PIEs. */
- else if (!ensure_undefweak_dynamic (info, h))
+ if (!ensure_undefweak_dynamic (info, h))
return FALSE;
}
}
@@ -8859,10 +8861,10 @@ ppc_elf_relocate_section (bfd *output_bfd,
if ((bfd_link_pic (info)
&& !(h != NULL
&& ((h->root.type == bfd_link_hash_undefined
- && (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
- || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL))
+ && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
|| (h->root.type == bfd_link_hash_undefweak
- && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)))
+ && (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+ || info->dynamic_undefined_weak == 0))))
&& (must_be_dyn_reloc (info, r_type)
|| !SYMBOL_CALLS_LOCAL (info, h)))
|| (ELIMINATE_COPY_RELOCS
@@ -10979,7 +10981,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
#define elf_backend_finish_dynamic_sections ppc_elf_finish_dynamic_sections
#define elf_backend_fake_sections ppc_elf_fake_sections
#define elf_backend_additional_program_headers ppc_elf_additional_program_headers
-#define elf_backend_modify_segment_map ppc_elf_modify_segment_map
+#define elf_backend_modify_segment_map ppc_elf_modify_segment_map
#define elf_backend_grok_prstatus ppc_elf_grok_prstatus
#define elf_backend_grok_psinfo ppc_elf_grok_psinfo
#define elf_backend_write_core_note ppc_elf_write_core_note
@@ -11049,7 +11051,7 @@ ppc_elf_vxworks_link_hash_table_create (bfd *abfd)
if (ret)
{
struct ppc_elf_link_hash_table *htab
- = (struct ppc_elf_link_hash_table *)ret;
+ = (struct ppc_elf_link_hash_table *)ret;
htab->is_vxworks = 1;
htab->plt_type = PLT_VXWORKS;
htab->plt_entry_size = VXWORKS_PLT_ENTRY_SIZE;
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index e48d67d..fc69964 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -9695,6 +9695,7 @@ ensure_undefweak_dynamic (struct bfd_link_info *info,
struct elf_link_hash_table *htab = elf_hash_table (info);
if (htab->dynamic_sections_created
+ && info->dynamic_undefined_weak != 0
&& h->root.type == bfd_link_hash_undefweak
&& h->dynindx == -1
&& !h->forced_local
@@ -9785,10 +9786,19 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
allocate_got (h, info, gent);
}
+ /* If no dynamic sections we can't have dynamic relocs, except for
+ IFUNCs which are handled even in static executables. */
if (!htab->elf.dynamic_sections_created
&& h->type != STT_GNU_IFUNC)
eh->dyn_relocs = NULL;
+ /* Also discard relocs on undefined weak syms with non-default
+ visibility, or when dynamic_undefined_weak says so. */
+ else if (h->root.type == bfd_link_hash_undefweak
+ && (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+ || info->dynamic_undefined_weak == 0))
+ eh->dyn_relocs = NULL;
+
if (eh->dyn_relocs != NULL)
{
struct elf_dyn_relocs *p, **pp;
@@ -9821,17 +9831,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
}
}
- /* Also discard relocs on undefined weak syms with
- non-default visibility. */
- if (eh->dyn_relocs != NULL
- && h->root.type == bfd_link_hash_undefweak)
+ if (eh->dyn_relocs != NULL)
{
- if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
- eh->dyn_relocs = NULL;
-
/* Make sure this symbol is output as a dynamic symbol.
Undefined weak syms won't yet be marked as dynamic. */
- else if (!ensure_undefweak_dynamic (info, h))
+ if (!ensure_undefweak_dynamic (info, h))
return FALSE;
}
}
@@ -14320,7 +14324,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
addend = 0;
reloc_dest = DEST_STUB;
- if ((stub_entry->stub_type == ppc_stub_plt_call
+ if ((stub_entry->stub_type == ppc_stub_plt_call
|| stub_entry->stub_type == ppc_stub_plt_call_r2save)
&& (ALWAYS_EMIT_R2SAVE
|| stub_entry->stub_type == ppc_stub_plt_call_r2save)
diff --git a/bfd/elflink.c b/bfd/elflink.c
index b93d4f3..0add01b 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -2803,6 +2803,24 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
if (! _bfd_elf_fix_symbol_flags (h, eif))
return FALSE;
+ if (h->root.type == bfd_link_hash_undefweak)
+ {
+ if (eif->info->dynamic_undefined_weak == 0)
+ _bfd_elf_link_hash_hide_symbol (eif->info, h, TRUE);
+ else if (eif->info->dynamic_undefined_weak > 0
+ && h->ref_regular
+ && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+ && !bfd_hide_sym_by_version (eif->info->version_info,
+ h->root.root.string))
+ {
+ if (!bfd_elf_link_record_dynamic_symbol (eif->info, h))
+ {
+ eif->failed = TRUE;
+ return FALSE;
+ }
+ }
+ }
+
/* If this symbol does not require a PLT entry, and it is not
defined by a dynamic object, or is not referenced by a regular
object, ignore it. We do have to handle a weak defined symbol,