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:
H.J. Lu
2017-10-14 11:29:58 -07:00
parent 5d84490bf6
commit 9577f60b5a
5 changed files with 373 additions and 484 deletions

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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)

View File

@ -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 *);