aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiong Wang <jiong.wang@arm.com>2017-06-29 11:47:43 +0100
committerJiong Wang <jiong.wang@arm.com>2017-06-29 11:47:43 +0100
commitff07562f1e369b6e37eafb2a888dc48fa2453e86 (patch)
tree02a834f2d636d5382e44a33e6c6b854cd1c66366
parent2aff25ba76035d2f1f48ea8a6c4b7e498ee31790 (diff)
[AArch64] Only override the symbol dynamic decision on undefined weak symbol
This fix is an adaption of the x86-64 PR ld/21402 fix to AArch64. After the generic code deciding one symbol is not dynamic, AArch64 backend only overrides the decision on undefined weak symbols. bfd/ PR ld/21402 * elfnn-aarch64.c (elfNN_aarch64_allocate_dynrelocs): Only make undefined weak symbols into dynamic. (elfNN_aarch64_final_link_relocate): Generate runtime RELATIVE relocation for non-dynamic symbols. (elfNN_aarch64_finish_dynamic_symbol): Add sanity check.
-rw-r--r--bfd/ChangeLog9
-rw-r--r--bfd/elfnn-aarch64.c82
2 files changed, 68 insertions, 23 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 8975b265ad..5045c818d3 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,14 @@
2017-06-29 Jiong Wang <jiong.wang@arm.com>
+ PR ld/21402
+ * elfnn-aarch64.c (elfNN_aarch64_allocate_dynrelocs): Only make
+ undefined weak symbols into dynamic.
+ (elfNN_aarch64_final_link_relocate): Generate runtime RELATIVE
+ relocation for non-dynamic symbols.
+ (elfNN_aarch64_finish_dynamic_symbol): Add sanity check.
+
+2017-06-29 Jiong Wang <jiong.wang@arm.com>
+
* elfnn-aarch64.c (aarch64_relocation_aginst_gp_p): New function.
(elfNN_aarch64_final_link_relocate): Delete duplicated code for
BFD_RELOC_AARCH64_LD64_GOTOFF_LO15, BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC,
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 4817e4254b..11954486e1 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -4944,11 +4944,13 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
= elfNN_aarch64_bfd_reloc_from_howto (howto);
unsigned long r_symndx;
bfd_byte *hit_data = contents + rel->r_offset;
- bfd_vma place, off;
+ bfd_vma place, off, got_entry_addr;
bfd_signed_vma signed_addend;
struct elf_aarch64_link_hash_table *globals;
bfd_boolean weak_undef_p;
+ bfd_boolean relative_reloc;
asection *base_got;
+ bfd_vma orig_value = value;
globals = elf_aarch64_hash_table (info);
@@ -5383,12 +5385,32 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
if (globals->root.sgot == NULL)
BFD_ASSERT (h != NULL);
+ relative_reloc = FALSE;
if (h != NULL)
{
bfd_vma addend = 0;
+
+ /* If a symbol is not dynamic and is not undefined weak, bind it
+ locally and generate a RELATIVE relocation under PIC mode.
+
+ NOTE: one symbol may be referenced by several relocations, we
+ should only generate one RELATIVE relocation for that symbol.
+ Therefore, check GOT offset mark first. */
+ if (h->dynindx == -1
+ && !h->forced_local
+ && h->root.type != bfd_link_hash_undefweak
+ && bfd_link_pic (info)
+ && !symbol_got_offset_mark_p (input_bfd, h, r_symndx))
+ relative_reloc = TRUE;
+
value = aarch64_calculate_got_entry_vma (h, globals, info, value,
output_bfd,
unresolved_reloc_p);
+ /* Record the GOT entry address which will be used when generating
+ RELATIVE relocation. */
+ if (relative_reloc)
+ got_entry_addr = value;
+
if (aarch64_relocation_aginst_gp_p (bfd_r_type))
addend = (globals->root.sgot->output_section->vma
+ globals->root.sgot->output_offset);
@@ -5414,32 +5436,20 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
off = symbol_got_offset (input_bfd, h, r_symndx);
base_got = globals->root.sgot;
- bfd_vma got_entry_addr = (base_got->output_section->vma
- + base_got->output_offset + off);
+ got_entry_addr = (base_got->output_section->vma
+ + base_got->output_offset + off);
if (!symbol_got_offset_mark_p (input_bfd, h, r_symndx))
{
bfd_put_64 (output_bfd, value, base_got->contents + off);
+ /* For local symbol, we have done absolute relocation in static
+ linking stage. While for shared library, we need to update the
+ content of GOT entry according to the shared object's runtime
+ base address. So, we need to generate a R_AARCH64_RELATIVE reloc
+ for dynamic linker. */
if (bfd_link_pic (info))
- {
- asection *s;
- Elf_Internal_Rela outrel;
-
- /* For local symbol, we have done absolute relocation in static
- linking stageh. While for share library, we need to update
- the content of GOT entry according to the share objects
- loading base address. So we need to generate a
- R_AARCH64_RELATIVE reloc for dynamic linker. */
- s = globals->root.srelgot;
- if (s == NULL)
- abort ();
-
- outrel.r_offset = got_entry_addr;
- outrel.r_info = ELFNN_R_INFO (0, AARCH64_R (RELATIVE));
- outrel.r_addend = value;
- elf_append_rela (output_bfd, s, &outrel);
- }
+ relative_reloc = TRUE;
symbol_got_offset_mark (input_bfd, h, r_symndx);
}
@@ -5454,6 +5464,21 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
addend, weak_undef_p);
}
+
+ if (relative_reloc)
+ {
+ asection *s;
+ Elf_Internal_Rela outrel;
+
+ s = globals->root.srelgot;
+ if (s == NULL)
+ abort ();
+
+ outrel.r_offset = got_entry_addr;
+ outrel.r_info = ELFNN_R_INFO (0, AARCH64_R (RELATIVE));
+ outrel.r_addend = orig_value;
+ elf_append_rela (output_bfd, s, &outrel);
+ }
break;
case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
@@ -8021,7 +8046,8 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
{
/* Make sure this symbol is output as a dynamic symbol.
Undefined weak syms won't yet be marked as dynamic. */
- if (h->dynindx == -1 && !h->forced_local)
+ if (h->dynindx == -1 && !h->forced_local
+ && h->root.type == bfd_link_hash_undefweak)
{
if (!bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
@@ -8102,7 +8128,8 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
/* Make sure this symbol is output as a dynamic symbol.
Undefined weak syms won't yet be marked as dynamic. */
- if (dyn && h->dynindx == -1 && !h->forced_local)
+ if (dyn && h->dynindx == -1 && !h->forced_local
+ && h->root.type == bfd_link_hash_undefweak)
{
if (!bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
@@ -8221,6 +8248,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
symbol in PIEs. */
else if (h->dynindx == -1
&& !h->forced_local
+ && h->root.type == bfd_link_hash_undefweak
&& !bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
@@ -8243,6 +8271,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
Undefined weak syms won't yet be marked as dynamic. */
if (h->dynindx == -1
&& !h->forced_local
+ && h->root.type == bfd_link_hash_undefweak
&& !bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
@@ -8863,6 +8892,13 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd,
struct elf_aarch64_link_hash_table *htab;
htab = elf_aarch64_hash_table (info);
+ /* Sanity check to make sure no unexpected symbol reaches here. */
+ if (h->dynindx == -1
+ && !h->forced_local
+ && h->root.type != bfd_link_hash_undefweak
+ && bfd_link_pic (info))
+ abort ();
+
if (h->plt.offset != (bfd_vma) - 1)
{
asection *plt, *gotplt, *relplt;