mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-25 04:49:54 +08:00
x86: Add _bfd_x86_elf_finish_dynamic_sections
Extract the common parts of elf_i386_finish_dynamic_sections and elf_x86_64_finish_dynamic_sections into a separate function in elfxx-x86.c. * elf32-i386.c (elf_i386_finish_dynamic_sections): Call _bfd_x86_elf_finish_dynamic_sections. * elf64-x86-64.c (elf_x86_64_finish_dynamic_sections): Likewise. * elfxx-x86.c (_bfd_x86_elf_finish_dynamic_sections): New function. * elfxx-x86.h (_bfd_x86_elf_finish_dynamic_sections): New prototype.
This commit is contained in:
@ -1,3 +1,13 @@
|
|||||||
|
2017-10-14 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
|
* elf32-i386.c (elf_i386_finish_dynamic_sections): Call
|
||||||
|
_bfd_x86_elf_finish_dynamic_sections.
|
||||||
|
* elf64-x86-64.c (elf_x86_64_finish_dynamic_sections): Likewise.
|
||||||
|
* elfxx-x86.c (_bfd_x86_elf_finish_dynamic_sections): New
|
||||||
|
function.
|
||||||
|
* elfxx-x86.h (_bfd_x86_elf_finish_dynamic_sections): New
|
||||||
|
prototype.
|
||||||
|
|
||||||
2017-10-14 H.J. Lu <hongjiu.lu@intel.com>
|
2017-10-14 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
PR ld/21384
|
PR ld/21384
|
||||||
|
306
bfd/elf32-i386.c
306
bfd/elf32-i386.c
@ -4012,262 +4012,102 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
|
|||||||
struct bfd_link_info *info)
|
struct bfd_link_info *info)
|
||||||
{
|
{
|
||||||
struct elf_x86_link_hash_table *htab;
|
struct elf_x86_link_hash_table *htab;
|
||||||
bfd *dynobj;
|
|
||||||
asection *sdyn;
|
|
||||||
const struct elf_i386_backend_data *abed;
|
|
||||||
|
|
||||||
htab = elf_x86_hash_table (info, I386_ELF_DATA);
|
htab = _bfd_x86_elf_finish_dynamic_sections (output_bfd, info);
|
||||||
if (htab == NULL)
|
if (htab == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
dynobj = htab->elf.dynobj;
|
if (!htab->elf.dynamic_sections_created)
|
||||||
sdyn = bfd_get_linker_section (dynobj, ".dynamic");
|
return TRUE;
|
||||||
abed = get_elf_i386_backend_data (output_bfd);
|
|
||||||
|
|
||||||
if (htab->elf.dynamic_sections_created)
|
if (htab->elf.splt && htab->elf.splt->size > 0)
|
||||||
{
|
{
|
||||||
Elf32_External_Dyn *dyncon, *dynconend;
|
/* UnixWare sets the entsize of .plt to 4, although that doesn't
|
||||||
|
really seem like the right value. */
|
||||||
|
elf_section_data (htab->elf.splt->output_section)
|
||||||
|
->this_hdr.sh_entsize = 4;
|
||||||
|
|
||||||
if (sdyn == NULL || htab->elf.sgot == NULL)
|
if (htab->plt.has_plt0)
|
||||||
abort ();
|
|
||||||
|
|
||||||
dyncon = (Elf32_External_Dyn *) sdyn->contents;
|
|
||||||
dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
|
|
||||||
for (; dyncon < dynconend; dyncon++)
|
|
||||||
{
|
{
|
||||||
Elf_Internal_Dyn dyn;
|
/* Fill in the special first entry in the procedure linkage
|
||||||
asection *s;
|
table. */
|
||||||
|
const struct elf_i386_backend_data *abed
|
||||||
|
= get_elf_i386_backend_data (output_bfd);
|
||||||
|
|
||||||
bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
|
memcpy (htab->elf.splt->contents, htab->plt.plt0_entry,
|
||||||
|
htab->lazy_plt->plt0_entry_size);
|
||||||
switch (dyn.d_tag)
|
memset (htab->elf.splt->contents + htab->lazy_plt->plt0_entry_size,
|
||||||
|
abed->plt0_pad_byte,
|
||||||
|
htab->plt.plt_entry_size - htab->lazy_plt->plt0_entry_size);
|
||||||
|
if (!bfd_link_pic (info))
|
||||||
{
|
{
|
||||||
default:
|
bfd_put_32 (output_bfd,
|
||||||
if (htab->is_vxworks
|
(htab->elf.sgotplt->output_section->vma
|
||||||
&& elf_vxworks_finish_dynamic_entry (output_bfd, &dyn))
|
+ htab->elf.sgotplt->output_offset
|
||||||
break;
|
+ 4),
|
||||||
continue;
|
htab->elf.splt->contents
|
||||||
|
+ htab->lazy_plt->plt0_got1_offset);
|
||||||
|
bfd_put_32 (output_bfd,
|
||||||
|
(htab->elf.sgotplt->output_section->vma
|
||||||
|
+ htab->elf.sgotplt->output_offset
|
||||||
|
+ 8),
|
||||||
|
htab->elf.splt->contents
|
||||||
|
+ htab->lazy_plt->plt0_got2_offset);
|
||||||
|
|
||||||
case DT_PLTGOT:
|
if (htab->is_vxworks)
|
||||||
s = htab->elf.sgotplt;
|
|
||||||
dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DT_JMPREL:
|
|
||||||
s = htab->elf.srelplt;
|
|
||||||
dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DT_PLTRELSZ:
|
|
||||||
s = htab->elf.srelplt;
|
|
||||||
dyn.d_un.d_val = s->size;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (htab->elf.splt && htab->elf.splt->size > 0)
|
|
||||||
{
|
|
||||||
/* UnixWare sets the entsize of .plt to 4, although that doesn't
|
|
||||||
really seem like the right value. */
|
|
||||||
elf_section_data (htab->elf.splt->output_section)
|
|
||||||
->this_hdr.sh_entsize = 4;
|
|
||||||
|
|
||||||
if (htab->plt.has_plt0)
|
|
||||||
{
|
|
||||||
/* Fill in the special first entry in the procedure linkage
|
|
||||||
table. */
|
|
||||||
memcpy (htab->elf.splt->contents, htab->plt.plt0_entry,
|
|
||||||
htab->lazy_plt->plt0_entry_size);
|
|
||||||
memset (htab->elf.splt->contents + htab->lazy_plt->plt0_entry_size,
|
|
||||||
abed->plt0_pad_byte,
|
|
||||||
htab->plt.plt_entry_size - htab->lazy_plt->plt0_entry_size);
|
|
||||||
if (!bfd_link_pic (info))
|
|
||||||
{
|
{
|
||||||
bfd_put_32 (output_bfd,
|
Elf_Internal_Rela rel;
|
||||||
(htab->elf.sgotplt->output_section->vma
|
int num_plts = (htab->elf.splt->size
|
||||||
+ htab->elf.sgotplt->output_offset
|
/ htab->plt.plt_entry_size) - 1;
|
||||||
+ 4),
|
unsigned char *p;
|
||||||
htab->elf.splt->contents
|
asection *srelplt2 = htab->srelplt2;
|
||||||
+ htab->lazy_plt->plt0_got1_offset);
|
|
||||||
bfd_put_32 (output_bfd,
|
|
||||||
(htab->elf.sgotplt->output_section->vma
|
|
||||||
+ htab->elf.sgotplt->output_offset
|
|
||||||
+ 8),
|
|
||||||
htab->elf.splt->contents
|
|
||||||
+ htab->lazy_plt->plt0_got2_offset);
|
|
||||||
|
|
||||||
if (htab->is_vxworks)
|
/* Generate a relocation for _GLOBAL_OFFSET_TABLE_
|
||||||
|
+ 4. On IA32 we use REL relocations so the
|
||||||
|
addend goes in the PLT directly. */
|
||||||
|
rel.r_offset = (htab->elf.splt->output_section->vma
|
||||||
|
+ htab->elf.splt->output_offset
|
||||||
|
+ htab->lazy_plt->plt0_got1_offset);
|
||||||
|
rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
|
||||||
|
R_386_32);
|
||||||
|
bfd_elf32_swap_reloc_out (output_bfd, &rel,
|
||||||
|
srelplt2->contents);
|
||||||
|
/* Generate a relocation for _GLOBAL_OFFSET_TABLE_
|
||||||
|
+ 8. */
|
||||||
|
rel.r_offset = (htab->elf.splt->output_section->vma
|
||||||
|
+ htab->elf.splt->output_offset
|
||||||
|
+ htab->lazy_plt->plt0_got2_offset);
|
||||||
|
rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
|
||||||
|
R_386_32);
|
||||||
|
bfd_elf32_swap_reloc_out (output_bfd, &rel,
|
||||||
|
srelplt2->contents +
|
||||||
|
sizeof (Elf32_External_Rel));
|
||||||
|
/* Correct the .rel.plt.unloaded relocations. */
|
||||||
|
p = srelplt2->contents;
|
||||||
|
if (bfd_link_pic (info))
|
||||||
|
p += PLTRESOLVE_RELOCS_SHLIB * sizeof (Elf32_External_Rel);
|
||||||
|
else
|
||||||
|
p += PLTRESOLVE_RELOCS * sizeof (Elf32_External_Rel);
|
||||||
|
|
||||||
|
for (; num_plts; num_plts--)
|
||||||
{
|
{
|
||||||
Elf_Internal_Rela rel;
|
bfd_elf32_swap_reloc_in (output_bfd, p, &rel);
|
||||||
int num_plts = (htab->elf.splt->size
|
|
||||||
/ htab->plt.plt_entry_size) - 1;
|
|
||||||
unsigned char *p;
|
|
||||||
asection *srelplt2 = htab->srelplt2;
|
|
||||||
|
|
||||||
/* Generate a relocation for _GLOBAL_OFFSET_TABLE_
|
|
||||||
+ 4. On IA32 we use REL relocations so the
|
|
||||||
addend goes in the PLT directly. */
|
|
||||||
rel.r_offset = (htab->elf.splt->output_section->vma
|
|
||||||
+ htab->elf.splt->output_offset
|
|
||||||
+ htab->lazy_plt->plt0_got1_offset);
|
|
||||||
rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
|
rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
|
||||||
R_386_32);
|
R_386_32);
|
||||||
bfd_elf32_swap_reloc_out (output_bfd, &rel,
|
bfd_elf32_swap_reloc_out (output_bfd, &rel, p);
|
||||||
srelplt2->contents);
|
p += sizeof (Elf32_External_Rel);
|
||||||
/* Generate a relocation for _GLOBAL_OFFSET_TABLE_
|
|
||||||
+ 8. */
|
bfd_elf32_swap_reloc_in (output_bfd, p, &rel);
|
||||||
rel.r_offset = (htab->elf.splt->output_section->vma
|
rel.r_info = ELF32_R_INFO (htab->elf.hplt->indx,
|
||||||
+ htab->elf.splt->output_offset
|
|
||||||
+ htab->lazy_plt->plt0_got2_offset);
|
|
||||||
rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
|
|
||||||
R_386_32);
|
R_386_32);
|
||||||
bfd_elf32_swap_reloc_out (output_bfd, &rel,
|
bfd_elf32_swap_reloc_out (output_bfd, &rel, p);
|
||||||
srelplt2->contents +
|
p += sizeof (Elf32_External_Rel);
|
||||||
sizeof (Elf32_External_Rel));
|
|
||||||
/* Correct the .rel.plt.unloaded relocations. */
|
|
||||||
p = srelplt2->contents;
|
|
||||||
if (bfd_link_pic (info))
|
|
||||||
p += PLTRESOLVE_RELOCS_SHLIB * sizeof (Elf32_External_Rel);
|
|
||||||
else
|
|
||||||
p += PLTRESOLVE_RELOCS * sizeof (Elf32_External_Rel);
|
|
||||||
|
|
||||||
for (; num_plts; num_plts--)
|
|
||||||
{
|
|
||||||
bfd_elf32_swap_reloc_in (output_bfd, p, &rel);
|
|
||||||
rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
|
|
||||||
R_386_32);
|
|
||||||
bfd_elf32_swap_reloc_out (output_bfd, &rel, p);
|
|
||||||
p += sizeof (Elf32_External_Rel);
|
|
||||||
|
|
||||||
bfd_elf32_swap_reloc_in (output_bfd, p, &rel);
|
|
||||||
rel.r_info = ELF32_R_INFO (htab->elf.hplt->indx,
|
|
||||||
R_386_32);
|
|
||||||
bfd_elf32_swap_reloc_out (output_bfd, &rel, p);
|
|
||||||
p += sizeof (Elf32_External_Rel);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (htab->plt_got != NULL && htab->plt_got->size > 0)
|
|
||||||
elf_section_data (htab->plt_got->output_section)
|
|
||||||
->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size;
|
|
||||||
|
|
||||||
if (htab->plt_second != NULL && htab->plt_second->size > 0)
|
|
||||||
elf_section_data (htab->plt_second->output_section)
|
|
||||||
->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fill in the first three entries in the global offset table. */
|
|
||||||
if (htab->elf.sgotplt && htab->elf.sgotplt->size > 0)
|
|
||||||
{
|
|
||||||
if (bfd_is_abs_section (htab->elf.sgotplt->output_section))
|
|
||||||
{
|
|
||||||
_bfd_error_handler
|
|
||||||
(_("discarded output section: `%A'"), htab->elf.sgotplt);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bfd_put_32 (output_bfd,
|
|
||||||
(sdyn == NULL ? 0
|
|
||||||
: sdyn->output_section->vma + sdyn->output_offset),
|
|
||||||
htab->elf.sgotplt->contents);
|
|
||||||
bfd_put_32 (output_bfd, 0, htab->elf.sgotplt->contents + 4);
|
|
||||||
bfd_put_32 (output_bfd, 0, htab->elf.sgotplt->contents + 8);
|
|
||||||
|
|
||||||
elf_section_data (htab->elf.sgotplt->output_section)->this_hdr.sh_entsize = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Adjust .eh_frame for .plt section. */
|
|
||||||
if (htab->plt_eh_frame != NULL
|
|
||||||
&& htab->plt_eh_frame->contents != NULL)
|
|
||||||
{
|
|
||||||
if (htab->elf.splt != NULL
|
|
||||||
&& htab->elf.splt->size != 0
|
|
||||||
&& (htab->elf.splt->flags & SEC_EXCLUDE) == 0
|
|
||||||
&& htab->elf.splt->output_section != NULL
|
|
||||||
&& htab->plt_eh_frame->output_section != NULL)
|
|
||||||
{
|
|
||||||
bfd_vma plt_start = htab->elf.splt->output_section->vma;
|
|
||||||
bfd_vma eh_frame_start = htab->plt_eh_frame->output_section->vma
|
|
||||||
+ htab->plt_eh_frame->output_offset
|
|
||||||
+ PLT_FDE_START_OFFSET;
|
|
||||||
bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
|
|
||||||
htab->plt_eh_frame->contents
|
|
||||||
+ PLT_FDE_START_OFFSET);
|
|
||||||
}
|
|
||||||
if (htab->plt_eh_frame->sec_info_type
|
|
||||||
== SEC_INFO_TYPE_EH_FRAME)
|
|
||||||
{
|
|
||||||
if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
|
|
||||||
htab->plt_eh_frame,
|
|
||||||
htab->plt_eh_frame->contents))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Adjust .eh_frame for .plt.got section. */
|
|
||||||
if (htab->plt_got_eh_frame != NULL
|
|
||||||
&& htab->plt_got_eh_frame->contents != NULL)
|
|
||||||
{
|
|
||||||
if (htab->plt_got != NULL
|
|
||||||
&& htab->plt_got->size != 0
|
|
||||||
&& (htab->plt_got->flags & SEC_EXCLUDE) == 0
|
|
||||||
&& htab->plt_got->output_section != NULL
|
|
||||||
&& htab->plt_got_eh_frame->output_section != NULL)
|
|
||||||
{
|
|
||||||
bfd_vma plt_start = htab->plt_got->output_section->vma;
|
|
||||||
bfd_vma eh_frame_start = htab->plt_got_eh_frame->output_section->vma
|
|
||||||
+ htab->plt_got_eh_frame->output_offset
|
|
||||||
+ PLT_FDE_START_OFFSET;
|
|
||||||
bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
|
|
||||||
htab->plt_got_eh_frame->contents
|
|
||||||
+ PLT_FDE_START_OFFSET);
|
|
||||||
}
|
|
||||||
if (htab->plt_got_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME)
|
|
||||||
{
|
|
||||||
if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
|
|
||||||
htab->plt_got_eh_frame,
|
|
||||||
htab->plt_got_eh_frame->contents))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Adjust .eh_frame for the second PLT section. */
|
|
||||||
if (htab->plt_second_eh_frame != NULL
|
|
||||||
&& htab->plt_second_eh_frame->contents != NULL)
|
|
||||||
{
|
|
||||||
if (htab->plt_second != NULL
|
|
||||||
&& htab->plt_second->size != 0
|
|
||||||
&& (htab->plt_second->flags & SEC_EXCLUDE) == 0
|
|
||||||
&& htab->plt_second->output_section != NULL
|
|
||||||
&& htab->plt_second_eh_frame->output_section != NULL)
|
|
||||||
{
|
|
||||||
bfd_vma plt_start = htab->plt_second->output_section->vma;
|
|
||||||
bfd_vma eh_frame_start
|
|
||||||
= (htab->plt_second_eh_frame->output_section->vma
|
|
||||||
+ htab->plt_second_eh_frame->output_offset
|
|
||||||
+ PLT_FDE_START_OFFSET);
|
|
||||||
bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
|
|
||||||
htab->plt_second_eh_frame->contents
|
|
||||||
+ PLT_FDE_START_OFFSET);
|
|
||||||
}
|
|
||||||
if (htab->plt_second_eh_frame->sec_info_type
|
|
||||||
== SEC_INFO_TYPE_EH_FRAME)
|
|
||||||
{
|
|
||||||
if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
|
|
||||||
htab->plt_second_eh_frame,
|
|
||||||
htab->plt_second_eh_frame->contents))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (htab->elf.sgot && htab->elf.sgot->size > 0)
|
|
||||||
elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 4;
|
|
||||||
|
|
||||||
/* Fill PLT entries for undefined weak symbols in PIE. */
|
/* Fill PLT entries for undefined weak symbols in PIE. */
|
||||||
if (bfd_link_pie (info))
|
if (bfd_link_pie (info))
|
||||||
bfd_hash_traverse (&info->hash->table,
|
bfd_hash_traverse (&info->hash->table,
|
||||||
|
@ -4360,273 +4360,91 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
|
|||||||
struct bfd_link_info *info)
|
struct bfd_link_info *info)
|
||||||
{
|
{
|
||||||
struct elf_x86_link_hash_table *htab;
|
struct elf_x86_link_hash_table *htab;
|
||||||
bfd *dynobj;
|
|
||||||
asection *sdyn;
|
|
||||||
|
|
||||||
htab = elf_x86_hash_table (info, X86_64_ELF_DATA);
|
htab = _bfd_x86_elf_finish_dynamic_sections (output_bfd, info);
|
||||||
if (htab == NULL)
|
if (htab == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
dynobj = htab->elf.dynobj;
|
if (! htab->elf.dynamic_sections_created)
|
||||||
sdyn = bfd_get_linker_section (dynobj, ".dynamic");
|
return TRUE;
|
||||||
|
|
||||||
if (htab->elf.dynamic_sections_created)
|
if (htab->elf.splt && htab->elf.splt->size > 0)
|
||||||
{
|
{
|
||||||
bfd_byte *dyncon, *dynconend;
|
elf_section_data (htab->elf.splt->output_section)
|
||||||
const struct elf_backend_data *bed;
|
->this_hdr.sh_entsize = htab->plt.plt_entry_size;
|
||||||
bfd_size_type sizeof_dyn;
|
|
||||||
|
|
||||||
if (sdyn == NULL || htab->elf.sgot == NULL)
|
if (htab->plt.has_plt0)
|
||||||
abort ();
|
|
||||||
|
|
||||||
bed = get_elf_backend_data (dynobj);
|
|
||||||
sizeof_dyn = bed->s->sizeof_dyn;
|
|
||||||
dyncon = sdyn->contents;
|
|
||||||
dynconend = sdyn->contents + sdyn->size;
|
|
||||||
for (; dyncon < dynconend; dyncon += sizeof_dyn)
|
|
||||||
{
|
{
|
||||||
Elf_Internal_Dyn dyn;
|
/* Fill in the special first entry in the procedure linkage
|
||||||
asection *s;
|
table. */
|
||||||
|
memcpy (htab->elf.splt->contents,
|
||||||
(*bed->s->swap_dyn_in) (dynobj, dyncon, &dyn);
|
htab->lazy_plt->plt0_entry,
|
||||||
|
htab->lazy_plt->plt0_entry_size);
|
||||||
switch (dyn.d_tag)
|
/* Add offset for pushq GOT+8(%rip), since the instruction
|
||||||
{
|
uses 6 bytes subtract this value. */
|
||||||
default:
|
bfd_put_32 (output_bfd,
|
||||||
continue;
|
(htab->elf.sgotplt->output_section->vma
|
||||||
|
+ htab->elf.sgotplt->output_offset
|
||||||
case DT_PLTGOT:
|
+ 8
|
||||||
s = htab->elf.sgotplt;
|
- htab->elf.splt->output_section->vma
|
||||||
dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
|
- htab->elf.splt->output_offset
|
||||||
break;
|
- 6),
|
||||||
|
(htab->elf.splt->contents
|
||||||
case DT_JMPREL:
|
+ htab->lazy_plt->plt0_got1_offset));
|
||||||
dyn.d_un.d_ptr = htab->elf.srelplt->output_section->vma;
|
/* Add offset for the PC-relative instruction accessing
|
||||||
break;
|
GOT+16, subtracting the offset to the end of that
|
||||||
|
instruction. */
|
||||||
case DT_PLTRELSZ:
|
bfd_put_32 (output_bfd,
|
||||||
s = htab->elf.srelplt->output_section;
|
(htab->elf.sgotplt->output_section->vma
|
||||||
dyn.d_un.d_val = s->size;
|
+ htab->elf.sgotplt->output_offset
|
||||||
break;
|
+ 16
|
||||||
|
- htab->elf.splt->output_section->vma
|
||||||
case DT_TLSDESC_PLT:
|
- htab->elf.splt->output_offset
|
||||||
s = htab->elf.splt;
|
- htab->lazy_plt->plt0_got2_insn_end),
|
||||||
dyn.d_un.d_ptr = s->output_section->vma + s->output_offset
|
(htab->elf.splt->contents
|
||||||
+ htab->tlsdesc_plt;
|
+ htab->lazy_plt->plt0_got2_offset));
|
||||||
break;
|
|
||||||
|
|
||||||
case DT_TLSDESC_GOT:
|
|
||||||
s = htab->elf.sgot;
|
|
||||||
dyn.d_un.d_ptr = s->output_section->vma + s->output_offset
|
|
||||||
+ htab->tlsdesc_got;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
(*bed->s->swap_dyn_out) (output_bfd, &dyn, dyncon);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (htab->elf.splt && htab->elf.splt->size > 0)
|
if (htab->tlsdesc_plt)
|
||||||
{
|
{
|
||||||
elf_section_data (htab->elf.splt->output_section)
|
bfd_put_64 (output_bfd, (bfd_vma) 0,
|
||||||
->this_hdr.sh_entsize = htab->plt.plt_entry_size;
|
htab->elf.sgot->contents + htab->tlsdesc_got);
|
||||||
|
|
||||||
if (htab->plt.has_plt0)
|
memcpy (htab->elf.splt->contents + htab->tlsdesc_plt,
|
||||||
{
|
htab->lazy_plt->plt0_entry,
|
||||||
/* Fill in the special first entry in the procedure linkage
|
htab->lazy_plt->plt0_entry_size);
|
||||||
table. */
|
|
||||||
memcpy (htab->elf.splt->contents,
|
|
||||||
htab->lazy_plt->plt0_entry,
|
|
||||||
htab->lazy_plt->plt0_entry_size);
|
|
||||||
/* Add offset for pushq GOT+8(%rip), since the instruction
|
|
||||||
uses 6 bytes subtract this value. */
|
|
||||||
bfd_put_32 (output_bfd,
|
|
||||||
(htab->elf.sgotplt->output_section->vma
|
|
||||||
+ htab->elf.sgotplt->output_offset
|
|
||||||
+ 8
|
|
||||||
- htab->elf.splt->output_section->vma
|
|
||||||
- htab->elf.splt->output_offset
|
|
||||||
- 6),
|
|
||||||
(htab->elf.splt->contents
|
|
||||||
+ htab->lazy_plt->plt0_got1_offset));
|
|
||||||
/* Add offset for the PC-relative instruction accessing
|
|
||||||
GOT+16, subtracting the offset to the end of that
|
|
||||||
instruction. */
|
|
||||||
bfd_put_32 (output_bfd,
|
|
||||||
(htab->elf.sgotplt->output_section->vma
|
|
||||||
+ htab->elf.sgotplt->output_offset
|
|
||||||
+ 16
|
|
||||||
- htab->elf.splt->output_section->vma
|
|
||||||
- htab->elf.splt->output_offset
|
|
||||||
- htab->lazy_plt->plt0_got2_insn_end),
|
|
||||||
(htab->elf.splt->contents
|
|
||||||
+ htab->lazy_plt->plt0_got2_offset));
|
|
||||||
|
|
||||||
if (htab->tlsdesc_plt)
|
/* Add offset for pushq GOT+8(%rip), since the
|
||||||
{
|
instruction uses 6 bytes subtract this value. */
|
||||||
bfd_put_64 (output_bfd, (bfd_vma) 0,
|
bfd_put_32 (output_bfd,
|
||||||
htab->elf.sgot->contents + htab->tlsdesc_got);
|
(htab->elf.sgotplt->output_section->vma
|
||||||
|
+ htab->elf.sgotplt->output_offset
|
||||||
memcpy (htab->elf.splt->contents + htab->tlsdesc_plt,
|
+ 8
|
||||||
htab->lazy_plt->plt0_entry,
|
- htab->elf.splt->output_section->vma
|
||||||
htab->lazy_plt->plt0_entry_size);
|
- htab->elf.splt->output_offset
|
||||||
|
- htab->tlsdesc_plt
|
||||||
/* Add offset for pushq GOT+8(%rip), since the
|
- 6),
|
||||||
instruction uses 6 bytes subtract this value. */
|
(htab->elf.splt->contents
|
||||||
bfd_put_32 (output_bfd,
|
+ htab->tlsdesc_plt
|
||||||
(htab->elf.sgotplt->output_section->vma
|
+ htab->lazy_plt->plt0_got1_offset));
|
||||||
+ htab->elf.sgotplt->output_offset
|
/* Add offset for the PC-relative instruction accessing
|
||||||
+ 8
|
GOT+TDG, where TDG stands for htab->tlsdesc_got,
|
||||||
- htab->elf.splt->output_section->vma
|
subtracting the offset to the end of that
|
||||||
- htab->elf.splt->output_offset
|
instruction. */
|
||||||
- htab->tlsdesc_plt
|
bfd_put_32 (output_bfd,
|
||||||
- 6),
|
(htab->elf.sgot->output_section->vma
|
||||||
(htab->elf.splt->contents
|
+ htab->elf.sgot->output_offset
|
||||||
+ htab->tlsdesc_plt
|
+ htab->tlsdesc_got
|
||||||
+ htab->lazy_plt->plt0_got1_offset));
|
- htab->elf.splt->output_section->vma
|
||||||
/* Add offset for the PC-relative instruction accessing
|
- htab->elf.splt->output_offset
|
||||||
GOT+TDG, where TDG stands for htab->tlsdesc_got,
|
- htab->tlsdesc_plt
|
||||||
subtracting the offset to the end of that
|
- htab->lazy_plt->plt0_got2_insn_end),
|
||||||
instruction. */
|
(htab->elf.splt->contents
|
||||||
bfd_put_32 (output_bfd,
|
+ htab->tlsdesc_plt
|
||||||
(htab->elf.sgot->output_section->vma
|
+ htab->lazy_plt->plt0_got2_offset));
|
||||||
+ htab->elf.sgot->output_offset
|
|
||||||
+ htab->tlsdesc_got
|
|
||||||
- htab->elf.splt->output_section->vma
|
|
||||||
- htab->elf.splt->output_offset
|
|
||||||
- htab->tlsdesc_plt
|
|
||||||
- htab->lazy_plt->plt0_got2_insn_end),
|
|
||||||
(htab->elf.splt->contents
|
|
||||||
+ htab->tlsdesc_plt
|
|
||||||
+ htab->lazy_plt->plt0_got2_offset));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (htab->plt_got != NULL && htab->plt_got->size > 0)
|
|
||||||
elf_section_data (htab->plt_got->output_section)
|
|
||||||
->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size;
|
|
||||||
|
|
||||||
if (htab->plt_second != NULL && htab->plt_second->size > 0)
|
|
||||||
elf_section_data (htab->plt_second->output_section)
|
|
||||||
->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* GOT is always created in setup_gnu_properties. But it may not be
|
|
||||||
needed. */
|
|
||||||
if (htab->elf.sgotplt && htab->elf.sgotplt->size > 0)
|
|
||||||
{
|
|
||||||
if (bfd_is_abs_section (htab->elf.sgotplt->output_section))
|
|
||||||
{
|
|
||||||
_bfd_error_handler
|
|
||||||
(_("discarded output section: `%A'"), htab->elf.sgotplt);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the first entry in the global offset table to the address of
|
|
||||||
the dynamic section. */
|
|
||||||
if (sdyn == NULL)
|
|
||||||
bfd_put_64 (output_bfd, (bfd_vma) 0, htab->elf.sgotplt->contents);
|
|
||||||
else
|
|
||||||
bfd_put_64 (output_bfd,
|
|
||||||
sdyn->output_section->vma + sdyn->output_offset,
|
|
||||||
htab->elf.sgotplt->contents);
|
|
||||||
/* Write GOT[1] and GOT[2], needed for the dynamic linker. */
|
|
||||||
bfd_put_64 (output_bfd, (bfd_vma) 0,
|
|
||||||
htab->elf.sgotplt->contents + GOT_ENTRY_SIZE);
|
|
||||||
bfd_put_64 (output_bfd, (bfd_vma) 0,
|
|
||||||
htab->elf.sgotplt->contents + GOT_ENTRY_SIZE*2);
|
|
||||||
|
|
||||||
elf_section_data (htab->elf.sgotplt->output_section)->this_hdr.sh_entsize
|
|
||||||
= GOT_ENTRY_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Adjust .eh_frame for .plt section. */
|
|
||||||
if (htab->plt_eh_frame != NULL
|
|
||||||
&& htab->plt_eh_frame->contents != NULL)
|
|
||||||
{
|
|
||||||
if (htab->elf.splt != NULL
|
|
||||||
&& htab->elf.splt->size != 0
|
|
||||||
&& (htab->elf.splt->flags & SEC_EXCLUDE) == 0
|
|
||||||
&& htab->elf.splt->output_section != NULL
|
|
||||||
&& htab->plt_eh_frame->output_section != NULL)
|
|
||||||
{
|
|
||||||
bfd_vma plt_start = htab->elf.splt->output_section->vma;
|
|
||||||
bfd_vma eh_frame_start = htab->plt_eh_frame->output_section->vma
|
|
||||||
+ htab->plt_eh_frame->output_offset
|
|
||||||
+ PLT_FDE_START_OFFSET;
|
|
||||||
bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
|
|
||||||
htab->plt_eh_frame->contents
|
|
||||||
+ PLT_FDE_START_OFFSET);
|
|
||||||
}
|
|
||||||
if (htab->plt_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME)
|
|
||||||
{
|
|
||||||
if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
|
|
||||||
htab->plt_eh_frame,
|
|
||||||
htab->plt_eh_frame->contents))
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Adjust .eh_frame for .plt.got section. */
|
|
||||||
if (htab->plt_got_eh_frame != NULL
|
|
||||||
&& htab->plt_got_eh_frame->contents != NULL)
|
|
||||||
{
|
|
||||||
if (htab->plt_got != NULL
|
|
||||||
&& htab->plt_got->size != 0
|
|
||||||
&& (htab->plt_got->flags & SEC_EXCLUDE) == 0
|
|
||||||
&& htab->plt_got->output_section != NULL
|
|
||||||
&& htab->plt_got_eh_frame->output_section != NULL)
|
|
||||||
{
|
|
||||||
bfd_vma plt_start = htab->plt_got->output_section->vma;
|
|
||||||
bfd_vma eh_frame_start = htab->plt_got_eh_frame->output_section->vma
|
|
||||||
+ htab->plt_got_eh_frame->output_offset
|
|
||||||
+ PLT_FDE_START_OFFSET;
|
|
||||||
bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
|
|
||||||
htab->plt_got_eh_frame->contents
|
|
||||||
+ PLT_FDE_START_OFFSET);
|
|
||||||
}
|
|
||||||
if (htab->plt_got_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME)
|
|
||||||
{
|
|
||||||
if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
|
|
||||||
htab->plt_got_eh_frame,
|
|
||||||
htab->plt_got_eh_frame->contents))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Adjust .eh_frame for the second PLT section. */
|
|
||||||
if (htab->plt_second_eh_frame != NULL
|
|
||||||
&& htab->plt_second_eh_frame->contents != NULL)
|
|
||||||
{
|
|
||||||
if (htab->plt_second != NULL
|
|
||||||
&& htab->plt_second->size != 0
|
|
||||||
&& (htab->plt_second->flags & SEC_EXCLUDE) == 0
|
|
||||||
&& htab->plt_second->output_section != NULL
|
|
||||||
&& htab->plt_second_eh_frame->output_section != NULL)
|
|
||||||
{
|
|
||||||
bfd_vma plt_start = htab->plt_second->output_section->vma;
|
|
||||||
bfd_vma eh_frame_start
|
|
||||||
= (htab->plt_second_eh_frame->output_section->vma
|
|
||||||
+ htab->plt_second_eh_frame->output_offset
|
|
||||||
+ PLT_FDE_START_OFFSET);
|
|
||||||
bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
|
|
||||||
htab->plt_second_eh_frame->contents
|
|
||||||
+ PLT_FDE_START_OFFSET);
|
|
||||||
}
|
|
||||||
if (htab->plt_second_eh_frame->sec_info_type
|
|
||||||
== SEC_INFO_TYPE_EH_FRAME)
|
|
||||||
{
|
|
||||||
if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
|
|
||||||
htab->plt_second_eh_frame,
|
|
||||||
htab->plt_second_eh_frame->contents))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (htab->elf.sgot && htab->elf.sgot->size > 0)
|
|
||||||
elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize
|
|
||||||
= GOT_ENTRY_SIZE;
|
|
||||||
|
|
||||||
/* Fill PLT entries for undefined weak symbols in PIE. */
|
/* Fill PLT entries for undefined weak symbols in PIE. */
|
||||||
if (bfd_link_pie (info))
|
if (bfd_link_pie (info))
|
||||||
bfd_hash_traverse (&info->hash->table,
|
bfd_hash_traverse (&info->hash->table,
|
||||||
|
218
bfd/elfxx-x86.c
218
bfd/elfxx-x86.c
@ -1294,6 +1294,224 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Finish up the x86 dynamic sections. */
|
||||||
|
|
||||||
|
struct elf_x86_link_hash_table *
|
||||||
|
_bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd,
|
||||||
|
struct bfd_link_info *info)
|
||||||
|
{
|
||||||
|
struct elf_x86_link_hash_table *htab;
|
||||||
|
const struct elf_backend_data *bed;
|
||||||
|
bfd *dynobj;
|
||||||
|
asection *sdyn;
|
||||||
|
bfd_byte *dyncon, *dynconend;
|
||||||
|
bfd_size_type sizeof_dyn;
|
||||||
|
|
||||||
|
bed = get_elf_backend_data (output_bfd);
|
||||||
|
htab = elf_x86_hash_table (info, bed->target_id);
|
||||||
|
if (htab == NULL)
|
||||||
|
return htab;
|
||||||
|
|
||||||
|
dynobj = htab->elf.dynobj;
|
||||||
|
sdyn = bfd_get_linker_section (dynobj, ".dynamic");
|
||||||
|
|
||||||
|
/* GOT is always created in setup_gnu_properties. But it may not be
|
||||||
|
needed. .got.plt section may be needed for static IFUNC. */
|
||||||
|
if (htab->elf.sgotplt && htab->elf.sgotplt->size > 0)
|
||||||
|
{
|
||||||
|
bfd_vma dynamic_addr;
|
||||||
|
|
||||||
|
if (bfd_is_abs_section (htab->elf.sgotplt->output_section))
|
||||||
|
{
|
||||||
|
_bfd_error_handler
|
||||||
|
(_("discarded output section: `%A'"), htab->elf.sgotplt);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
elf_section_data (htab->elf.sgotplt->output_section)->this_hdr.sh_entsize
|
||||||
|
= htab->got_entry_size;
|
||||||
|
|
||||||
|
dynamic_addr = (sdyn == NULL
|
||||||
|
? (bfd_vma) 0
|
||||||
|
: sdyn->output_section->vma + sdyn->output_offset);
|
||||||
|
|
||||||
|
/* Set the first entry in the global offset table to the address
|
||||||
|
of the dynamic section. Write GOT[1] and GOT[2], needed for
|
||||||
|
the dynamic linker. */
|
||||||
|
if (htab->got_entry_size == 8)
|
||||||
|
{
|
||||||
|
bfd_put_64 (output_bfd, dynamic_addr,
|
||||||
|
htab->elf.sgotplt->contents);
|
||||||
|
bfd_put_64 (output_bfd, (bfd_vma) 0,
|
||||||
|
htab->elf.sgotplt->contents + 8);
|
||||||
|
bfd_put_64 (output_bfd, (bfd_vma) 0,
|
||||||
|
htab->elf.sgotplt->contents + 8*2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bfd_put_32 (output_bfd, dynamic_addr,
|
||||||
|
htab->elf.sgotplt->contents);
|
||||||
|
bfd_put_32 (output_bfd, 0,
|
||||||
|
htab->elf.sgotplt->contents + 4);
|
||||||
|
bfd_put_32 (output_bfd, 0,
|
||||||
|
htab->elf.sgotplt->contents + 4*2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!htab->elf.dynamic_sections_created)
|
||||||
|
return htab;
|
||||||
|
|
||||||
|
if (sdyn == NULL || htab->elf.sgot == NULL)
|
||||||
|
abort ();
|
||||||
|
|
||||||
|
sizeof_dyn = bed->s->sizeof_dyn;
|
||||||
|
dyncon = sdyn->contents;
|
||||||
|
dynconend = sdyn->contents + sdyn->size;
|
||||||
|
for (; dyncon < dynconend; dyncon += sizeof_dyn)
|
||||||
|
{
|
||||||
|
Elf_Internal_Dyn dyn;
|
||||||
|
asection *s;
|
||||||
|
|
||||||
|
(*bed->s->swap_dyn_in) (dynobj, dyncon, &dyn);
|
||||||
|
|
||||||
|
switch (dyn.d_tag)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
if (htab->is_vxworks
|
||||||
|
&& elf_vxworks_finish_dynamic_entry (output_bfd, &dyn))
|
||||||
|
break;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case DT_PLTGOT:
|
||||||
|
s = htab->elf.sgotplt;
|
||||||
|
dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DT_JMPREL:
|
||||||
|
dyn.d_un.d_ptr = htab->elf.srelplt->output_section->vma;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DT_PLTRELSZ:
|
||||||
|
s = htab->elf.srelplt->output_section;
|
||||||
|
dyn.d_un.d_val = s->size;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DT_TLSDESC_PLT:
|
||||||
|
s = htab->elf.splt;
|
||||||
|
dyn.d_un.d_ptr = s->output_section->vma + s->output_offset
|
||||||
|
+ htab->tlsdesc_plt;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DT_TLSDESC_GOT:
|
||||||
|
s = htab->elf.sgot;
|
||||||
|
dyn.d_un.d_ptr = s->output_section->vma + s->output_offset
|
||||||
|
+ htab->tlsdesc_got;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*bed->s->swap_dyn_out) (output_bfd, &dyn, dyncon);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (htab->plt_got != NULL && htab->plt_got->size > 0)
|
||||||
|
elf_section_data (htab->plt_got->output_section)
|
||||||
|
->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size;
|
||||||
|
|
||||||
|
if (htab->plt_second != NULL && htab->plt_second->size > 0)
|
||||||
|
elf_section_data (htab->plt_second->output_section)
|
||||||
|
->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size;
|
||||||
|
|
||||||
|
/* Adjust .eh_frame for .plt section. */
|
||||||
|
if (htab->plt_eh_frame != NULL
|
||||||
|
&& htab->plt_eh_frame->contents != NULL)
|
||||||
|
{
|
||||||
|
if (htab->elf.splt != NULL
|
||||||
|
&& htab->elf.splt->size != 0
|
||||||
|
&& (htab->elf.splt->flags & SEC_EXCLUDE) == 0
|
||||||
|
&& htab->elf.splt->output_section != NULL
|
||||||
|
&& htab->plt_eh_frame->output_section != NULL)
|
||||||
|
{
|
||||||
|
bfd_vma plt_start = htab->elf.splt->output_section->vma;
|
||||||
|
bfd_vma eh_frame_start = htab->plt_eh_frame->output_section->vma
|
||||||
|
+ htab->plt_eh_frame->output_offset
|
||||||
|
+ PLT_FDE_START_OFFSET;
|
||||||
|
bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
|
||||||
|
htab->plt_eh_frame->contents
|
||||||
|
+ PLT_FDE_START_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (htab->plt_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME)
|
||||||
|
{
|
||||||
|
if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
|
||||||
|
htab->plt_eh_frame,
|
||||||
|
htab->plt_eh_frame->contents))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adjust .eh_frame for .plt.got section. */
|
||||||
|
if (htab->plt_got_eh_frame != NULL
|
||||||
|
&& htab->plt_got_eh_frame->contents != NULL)
|
||||||
|
{
|
||||||
|
if (htab->plt_got != NULL
|
||||||
|
&& htab->plt_got->size != 0
|
||||||
|
&& (htab->plt_got->flags & SEC_EXCLUDE) == 0
|
||||||
|
&& htab->plt_got->output_section != NULL
|
||||||
|
&& htab->plt_got_eh_frame->output_section != NULL)
|
||||||
|
{
|
||||||
|
bfd_vma plt_start = htab->plt_got->output_section->vma;
|
||||||
|
bfd_vma eh_frame_start = htab->plt_got_eh_frame->output_section->vma
|
||||||
|
+ htab->plt_got_eh_frame->output_offset
|
||||||
|
+ PLT_FDE_START_OFFSET;
|
||||||
|
bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
|
||||||
|
htab->plt_got_eh_frame->contents
|
||||||
|
+ PLT_FDE_START_OFFSET);
|
||||||
|
}
|
||||||
|
if (htab->plt_got_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME)
|
||||||
|
{
|
||||||
|
if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
|
||||||
|
htab->plt_got_eh_frame,
|
||||||
|
htab->plt_got_eh_frame->contents))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adjust .eh_frame for the second PLT section. */
|
||||||
|
if (htab->plt_second_eh_frame != NULL
|
||||||
|
&& htab->plt_second_eh_frame->contents != NULL)
|
||||||
|
{
|
||||||
|
if (htab->plt_second != NULL
|
||||||
|
&& htab->plt_second->size != 0
|
||||||
|
&& (htab->plt_second->flags & SEC_EXCLUDE) == 0
|
||||||
|
&& htab->plt_second->output_section != NULL
|
||||||
|
&& htab->plt_second_eh_frame->output_section != NULL)
|
||||||
|
{
|
||||||
|
bfd_vma plt_start = htab->plt_second->output_section->vma;
|
||||||
|
bfd_vma eh_frame_start
|
||||||
|
= (htab->plt_second_eh_frame->output_section->vma
|
||||||
|
+ htab->plt_second_eh_frame->output_offset
|
||||||
|
+ PLT_FDE_START_OFFSET);
|
||||||
|
bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
|
||||||
|
htab->plt_second_eh_frame->contents
|
||||||
|
+ PLT_FDE_START_OFFSET);
|
||||||
|
}
|
||||||
|
if (htab->plt_second_eh_frame->sec_info_type
|
||||||
|
== SEC_INFO_TYPE_EH_FRAME)
|
||||||
|
{
|
||||||
|
if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
|
||||||
|
htab->plt_second_eh_frame,
|
||||||
|
htab->plt_second_eh_frame->contents))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (htab->elf.sgot && htab->elf.sgot->size > 0)
|
||||||
|
elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize
|
||||||
|
= htab->got_entry_size;
|
||||||
|
|
||||||
|
return htab;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bfd_boolean
|
bfd_boolean
|
||||||
_bfd_x86_elf_always_size_sections (bfd *output_bfd,
|
_bfd_x86_elf_always_size_sections (bfd *output_bfd,
|
||||||
struct bfd_link_info *info)
|
struct bfd_link_info *info)
|
||||||
|
@ -601,6 +601,9 @@ extern bfd_boolean _bfd_x86_elf_link_check_relocs
|
|||||||
extern bfd_boolean _bfd_x86_elf_size_dynamic_sections
|
extern bfd_boolean _bfd_x86_elf_size_dynamic_sections
|
||||||
(bfd *, struct bfd_link_info *);
|
(bfd *, struct bfd_link_info *);
|
||||||
|
|
||||||
|
extern struct elf_x86_link_hash_table *_bfd_x86_elf_finish_dynamic_sections
|
||||||
|
(bfd *, struct bfd_link_info *);
|
||||||
|
|
||||||
extern bfd_boolean _bfd_x86_elf_always_size_sections
|
extern bfd_boolean _bfd_x86_elf_always_size_sections
|
||||||
(bfd *, struct bfd_link_info *);
|
(bfd *, struct bfd_link_info *);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user