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:
parent
0ee6c332f3
commit
2376f038d1
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue