Initialize GOT slot for local symbol in non-PIC link.

On ARM/VxWorks 7, the R_ARM_TARGET2 relocation used for exception handling
is R_ARM_GOT_PREL; moreover in Ada you can define local exceptions. In this
case, you may end up with a GOT relocation against a local symbol in a
non-PIC link and the ARM linker leaves the GOT slot uninitialized, unlike
for example the i386 or the SPARC linkers in the same situation.

bfd/
	* elf32-arm.c (elf32_arm_final_link_relocate) <R_ARM_GOT32>: Small
	cleanup for the case of a global symbol that binds locally.  Also
	install a value in the GOT slot in the case of a local symbol in
	a non-PIC link.
This commit is contained in:
Eric Botcazou 2018-07-21 15:00:40 +02:00
parent 0ee6c332f3
commit 2376f038d1
2 changed files with 45 additions and 28 deletions

View File

@ -1,3 +1,10 @@
2018-07-21 Eric Botcazou <ebotcazou@adacore.com>
* elf32-arm.c (elf32_arm_final_link_relocate) <R_ARM_GOT32>: Small
cleanup for the case of a global symbol that binds locally. Also
install a value in the GOT slot in the case of a local symbol in
a non-PIC link.
2018-07-20 H.J. Lu <hongjiu.lu@intel.com> 2018-07-20 H.J. Lu <hongjiu.lu@intel.com>
PR ld/23428 PR ld/23428

View File

@ -11502,37 +11502,39 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
&& (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|| h->root.type != bfd_link_hash_undefweak)) || h->root.type != bfd_link_hash_undefweak))
outrel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE); outrel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE);
else if (globals->fdpic_p)
isrofixup = 1;
else else
outrel.r_info = 0; {
outrel.r_info = 0;
if (globals->fdpic_p)
isrofixup = 1;
}
outrel.r_addend = dynreloc_value; outrel.r_addend = dynreloc_value;
} }
/* The GOT entry is initialized to zero by default. /* The GOT entry is initialized to zero by default.
See if we should install a different value. */ See if we should install a different value. */
if (outrel.r_addend != 0 if (outrel.r_addend != 0
&& (outrel.r_info == 0 || globals->use_rel || isrofixup)) && (globals->use_rel || outrel.r_info == 0))
{ {
bfd_put_32 (output_bfd, outrel.r_addend, bfd_put_32 (output_bfd, outrel.r_addend,
sgot->contents + off); sgot->contents + off);
outrel.r_addend = 0; outrel.r_addend = 0;
} }
if (outrel.r_info != 0 && !isrofixup) if (isrofixup)
arm_elf_add_rofixup (output_bfd,
elf32_arm_hash_table(info)->srofixup,
sgot->output_section->vma
+ sgot->output_offset + off);
else if (outrel.r_info != 0)
{ {
outrel.r_offset = (sgot->output_section->vma outrel.r_offset = (sgot->output_section->vma
+ sgot->output_offset + sgot->output_offset
+ off); + off);
elf32_arm_add_dynreloc (output_bfd, info, srelgot, &outrel); elf32_arm_add_dynreloc (output_bfd, info, srelgot, &outrel);
} }
else if (isrofixup)
{
arm_elf_add_rofixup(output_bfd,
elf32_arm_hash_table(info)->srofixup,
sgot->output_section->vma
+ sgot->output_offset + off);
}
h->got.offset |= 1; h->got.offset |= 1;
} }
value = sgot->output_offset + off; value = sgot->output_offset + off;
@ -11553,31 +11555,39 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
off &= ~1; off &= ~1;
else else
{ {
if (globals->use_rel) Elf_Internal_Rela outrel;
int isrofixup = 0;
if (dynreloc_st_type == STT_GNU_IFUNC)
outrel.r_info = ELF32_R_INFO (0, R_ARM_IRELATIVE);
else if (bfd_link_pic (info))
outrel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE);
else
{
outrel.r_info = 0;
if (globals->fdpic_p)
isrofixup = 1;
}
/* The GOT entry is initialized to zero by default.
See if we should install a different value. */
if (globals->use_rel || outrel.r_info == 0)
bfd_put_32 (output_bfd, dynreloc_value, sgot->contents + off); bfd_put_32 (output_bfd, dynreloc_value, sgot->contents + off);
if (bfd_link_pic (info) || dynreloc_st_type == STT_GNU_IFUNC) if (isrofixup)
{ arm_elf_add_rofixup (output_bfd,
Elf_Internal_Rela outrel; globals->srofixup,
sgot->output_section->vma
+ sgot->output_offset + off);
else if (outrel.r_info != 0)
{
outrel.r_addend = addend + dynreloc_value; outrel.r_addend = addend + dynreloc_value;
outrel.r_offset = (sgot->output_section->vma outrel.r_offset = (sgot->output_section->vma
+ sgot->output_offset + sgot->output_offset
+ off); + off);
if (dynreloc_st_type == STT_GNU_IFUNC)
outrel.r_info = ELF32_R_INFO (0, R_ARM_IRELATIVE);
else
outrel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE);
elf32_arm_add_dynreloc (output_bfd, info, srelgot, &outrel); elf32_arm_add_dynreloc (output_bfd, info, srelgot, &outrel);
} }
else if (globals->fdpic_p)
{
/* For FDPIC executables, we use rofixup to fix
address at runtime. */
arm_elf_add_rofixup(output_bfd, globals->srofixup,
sgot->output_section->vma + sgot->output_offset
+ off);
}
local_got_offsets[r_symndx] |= 1; local_got_offsets[r_symndx] |= 1;
} }