mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-22 19:09:31 +08:00
[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.
This commit is contained in:
@ -1,3 +1,12 @@
|
|||||||
|
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>
|
2017-06-29 Jiong Wang <jiong.wang@arm.com>
|
||||||
|
|
||||||
* elfnn-aarch64.c (aarch64_relocation_aginst_gp_p): New function.
|
* elfnn-aarch64.c (aarch64_relocation_aginst_gp_p): New function.
|
||||||
|
@ -4944,11 +4944,13 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
|
|||||||
= elfNN_aarch64_bfd_reloc_from_howto (howto);
|
= elfNN_aarch64_bfd_reloc_from_howto (howto);
|
||||||
unsigned long r_symndx;
|
unsigned long r_symndx;
|
||||||
bfd_byte *hit_data = contents + rel->r_offset;
|
bfd_byte *hit_data = contents + rel->r_offset;
|
||||||
bfd_vma place, off;
|
bfd_vma place, off, got_entry_addr;
|
||||||
bfd_signed_vma signed_addend;
|
bfd_signed_vma signed_addend;
|
||||||
struct elf_aarch64_link_hash_table *globals;
|
struct elf_aarch64_link_hash_table *globals;
|
||||||
bfd_boolean weak_undef_p;
|
bfd_boolean weak_undef_p;
|
||||||
|
bfd_boolean relative_reloc;
|
||||||
asection *base_got;
|
asection *base_got;
|
||||||
|
bfd_vma orig_value = value;
|
||||||
|
|
||||||
globals = elf_aarch64_hash_table (info);
|
globals = elf_aarch64_hash_table (info);
|
||||||
|
|
||||||
@ -5383,12 +5385,32 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
|
|||||||
if (globals->root.sgot == NULL)
|
if (globals->root.sgot == NULL)
|
||||||
BFD_ASSERT (h != NULL);
|
BFD_ASSERT (h != NULL);
|
||||||
|
|
||||||
|
relative_reloc = FALSE;
|
||||||
if (h != NULL)
|
if (h != NULL)
|
||||||
{
|
{
|
||||||
bfd_vma addend = 0;
|
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,
|
value = aarch64_calculate_got_entry_vma (h, globals, info, value,
|
||||||
output_bfd,
|
output_bfd,
|
||||||
unresolved_reloc_p);
|
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))
|
if (aarch64_relocation_aginst_gp_p (bfd_r_type))
|
||||||
addend = (globals->root.sgot->output_section->vma
|
addend = (globals->root.sgot->output_section->vma
|
||||||
+ globals->root.sgot->output_offset);
|
+ 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);
|
off = symbol_got_offset (input_bfd, h, r_symndx);
|
||||||
base_got = globals->root.sgot;
|
base_got = globals->root.sgot;
|
||||||
bfd_vma got_entry_addr = (base_got->output_section->vma
|
got_entry_addr = (base_got->output_section->vma
|
||||||
+ base_got->output_offset + off);
|
+ base_got->output_offset + off);
|
||||||
|
|
||||||
if (!symbol_got_offset_mark_p (input_bfd, h, r_symndx))
|
if (!symbol_got_offset_mark_p (input_bfd, h, r_symndx))
|
||||||
{
|
{
|
||||||
bfd_put_64 (output_bfd, value, base_got->contents + off);
|
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))
|
if (bfd_link_pic (info))
|
||||||
{
|
relative_reloc = TRUE;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
symbol_got_offset_mark (input_bfd, h, r_symndx);
|
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,
|
value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
|
||||||
addend, weak_undef_p);
|
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;
|
break;
|
||||||
|
|
||||||
case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
|
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.
|
/* Make sure this symbol is output as a dynamic symbol.
|
||||||
Undefined weak syms won't yet be marked as dynamic. */
|
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))
|
if (!bfd_elf_link_record_dynamic_symbol (info, h))
|
||||||
return FALSE;
|
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.
|
/* Make sure this symbol is output as a dynamic symbol.
|
||||||
Undefined weak syms won't yet be marked as dynamic. */
|
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))
|
if (!bfd_elf_link_record_dynamic_symbol (info, h))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -8221,6 +8248,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||||||
symbol in PIEs. */
|
symbol in PIEs. */
|
||||||
else if (h->dynindx == -1
|
else if (h->dynindx == -1
|
||||||
&& !h->forced_local
|
&& !h->forced_local
|
||||||
|
&& h->root.type == bfd_link_hash_undefweak
|
||||||
&& !bfd_elf_link_record_dynamic_symbol (info, h))
|
&& !bfd_elf_link_record_dynamic_symbol (info, h))
|
||||||
return FALSE;
|
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. */
|
Undefined weak syms won't yet be marked as dynamic. */
|
||||||
if (h->dynindx == -1
|
if (h->dynindx == -1
|
||||||
&& !h->forced_local
|
&& !h->forced_local
|
||||||
|
&& h->root.type == bfd_link_hash_undefweak
|
||||||
&& !bfd_elf_link_record_dynamic_symbol (info, h))
|
&& !bfd_elf_link_record_dynamic_symbol (info, h))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@ -8863,6 +8892,13 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd,
|
|||||||
struct elf_aarch64_link_hash_table *htab;
|
struct elf_aarch64_link_hash_table *htab;
|
||||||
htab = elf_aarch64_hash_table (info);
|
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)
|
if (h->plt.offset != (bfd_vma) - 1)
|
||||||
{
|
{
|
||||||
asection *plt, *gotplt, *relplt;
|
asection *plt, *gotplt, *relplt;
|
||||||
|
Reference in New Issue
Block a user