x86: Add _bfd_x86_elf_link_hash_table_create

Share _bfd_x86_elf_link_hash_table_create in elf32-i386.c and
elf64-x86-64.c by:

1. Replace elf_i386_lazy_plt_layout, elf_i386_non_lazy_plt_layout,
elf_i386_plt_layout, elf_x86_64_lazy_plt_layout,
elf_x86_64_non_lazy_plt_layout and elf_x86_64_plt_layout with
elf_x86_lazy_plt_layout, elf_x86_non_lazy_plt_layout and
elf_x86_plt_layout.
2. Move plt, lazy_plt, non_lazy_plt, srelplt2 and next_tls_desc_index
from elf_i386_link_hash_table to elf_x86_link_hash_table.
3. Remove elf_i386_link_hash_table and elf_x86_64_link_hash_table.

	* elf32-i386.c (ELF_DYNAMIC_INTERPRETER): Removed.
	(elf_i386_lazy_plt_layout): Likewise.
	(elf_i386_non_lazy_plt_layout): Likewise.
	(elf_i386_plt_layout): Likewise.
	(elf_i386_link_hash_table): Likewise.
	(elf_i386_next_tls_desc_index): Likewise.
	(elf_i386_srelplt2): Likewise.
	(elf_i386_plt): Likewise.
	(elf_i386_lazy_plt): Likewise.
	(elf_i386_non_lazy_plt): Likewise.
	(elf_i386_link_hash_table_create): Likewise.
	(bfd_elf32_bfd_link_hash_table_create): Likewise.
	(elf_i386_lazy_plt): Updated.
	(elf_i386_non_lazy_plt): Likewise.
	(elf_i386_lazy_ibt_plt): Likewise.
	(elf_i386_non_lazy_ibt_plt): Likewise.
	(elf_i386_allocate_dynrelocs): Likewise.
	(elf_i386_size_dynamic_sections): Likewise.
	(elf_i386_relocate_section): Likewise.
	(elf_i386_finish_dynamic_symbol): Likewise.
	(elf_i386_finish_dynamic_sections): Likewise.
	(elf_i386_get_synthetic_symtab): Likewise.
	(elf_i386_link_setup_gnu_properties): Likewise.
	(elf_i386_nacl_plt): Likewise.
	* elf64-x86-64.c (ABI_64_P): Removed.
	(ELF64_DYNAMIC_INTERPRETER): Likewise.
	(ELF32_DYNAMIC_INTERPRETER): Likewise.
	(elf_x86_64_lazy_plt_layout): Likewise.
	(elf_x86_64_non_lazy_plt_layout): Likewise.
	(elf_x86_64_plt_layout): Likewise.
	(elf_x86_64_link_hash_table): Likewise.
	(elf_x86_64_plt): Likewise.
	(elf_x86_64_lazy_plt): Likewise.
	(elf_x86_64_non_lazy_plt): Likewise.
	(elf_x86_64_link_hash_table_create): Likewise.
	(bfd_elf64_bfd_link_hash_table_create): Likewise.
	(bfd_elf32_bfd_link_hash_table_create): Likewise.
	(elf_x86_64_lazy_plt): Updated.
	(elf_x86_64_non_lazy_plt): Likewise.
	(elf_x86_64_lazy_bnd_plt): Likewise.
	(elf_x86_64_non_lazy_bnd_plt): Likewise.
	(elf_x86_64_lazy_ibt_plt): Likewise.
	(elf_x32_lazy_ibt_plt): Likewise.
	(elf_x86_64_non_lazy_ibt_plt): Likewise.
	(elf_x32_non_lazy_ibt_plt): Likewise.
	(elf_x86_64_allocate_dynrelocs): Likewise.
	(elf_x86_64_size_dynamic_sections): Likewise.
	(elf_x86_64_relocate_section): Likewise.
	(elf_x86_64_finish_dynamic_symbol): Likewise.
	(elf_x86_64_finish_dynamic_sections): Likewise.
	(elf_x86_64_get_synthetic_symtab): Likewise.
	(elf_x86_64_link_setup_gnu_properties): Likewise.
	(elf_x86_64_nacl_plt): Likewise.
	* elfxx-x86.c: Include "objalloc.h", "elf/i386.h" and
	"elf/x86-64.h".
	(ELF32_DYNAMIC_INTERPRETER): New.
	(ELF64_DYNAMIC_INTERPRETER): Likewise.
	(ELFX32_DYNAMIC_INTERPRETER): Likewise.
	(_bfd_x86_elf_link_hash_table_create): Likewise.
	(_bfd_x86_elf_link_hash_table_free): Renamed to ...
	(elf_x86_link_hash_table_free): This.  Make it static.
	* elfxx-x86.h: Don't include "objalloc.h".
	(ABI_64_P): New.
	(elf_x86_lazy_plt_layout): Likewise.
	(elf_x86_non_lazy_plt_layout): Likewise.
	(elf_x86_plt_layout): Likewise.
	(_bfd_x86_elf_link_hash_table_create): Likewise.
	(bfd_elf64_bfd_link_hash_table_create): Likewise.
	(bfd_elf32_bfd_link_hash_table_create): Likewise.
	(elf_x86_link_hash_table): Add plt, lazy_plt, non_lazy_plt,
	srelplt2 and next_tls_desc_index.
	(_bfd_x86_elf_link_hash_table_free): Removed.
This commit is contained in:
H.J. Lu
2017-08-30 09:10:08 -07:00
parent 70e65ca8e5
commit 765e526c75
5 changed files with 515 additions and 604 deletions

View File

@ -1,3 +1,78 @@
2017-08-30 H.J. Lu <hongjiu.lu@intel.com>
* elf32-i386.c (ELF_DYNAMIC_INTERPRETER): Removed.
(elf_i386_lazy_plt_layout): Likewise.
(elf_i386_non_lazy_plt_layout): Likewise.
(elf_i386_plt_layout): Likewise.
(elf_i386_link_hash_table): Likewise.
(elf_i386_next_tls_desc_index): Likewise.
(elf_i386_srelplt2): Likewise.
(elf_i386_plt): Likewise.
(elf_i386_lazy_plt): Likewise.
(elf_i386_non_lazy_plt): Likewise.
(elf_i386_link_hash_table_create): Likewise.
(bfd_elf32_bfd_link_hash_table_create): Likewise.
(elf_i386_lazy_plt): Updated.
(elf_i386_non_lazy_plt): Likewise.
(elf_i386_lazy_ibt_plt): Likewise.
(elf_i386_non_lazy_ibt_plt): Likewise.
(elf_i386_allocate_dynrelocs): Likewise.
(elf_i386_size_dynamic_sections): Likewise.
(elf_i386_relocate_section): Likewise.
(elf_i386_finish_dynamic_symbol): Likewise.
(elf_i386_finish_dynamic_sections): Likewise.
(elf_i386_get_synthetic_symtab): Likewise.
(elf_i386_link_setup_gnu_properties): Likewise.
(elf_i386_nacl_plt): Likewise.
* elf64-x86-64.c (ABI_64_P): Removed.
(ELF64_DYNAMIC_INTERPRETER): Likewise.
(ELF32_DYNAMIC_INTERPRETER): Likewise.
(elf_x86_64_lazy_plt_layout): Likewise.
(elf_x86_64_non_lazy_plt_layout): Likewise.
(elf_x86_64_plt_layout): Likewise.
(elf_x86_64_link_hash_table): Likewise.
(elf_x86_64_plt): Likewise.
(elf_x86_64_lazy_plt): Likewise.
(elf_x86_64_non_lazy_plt): Likewise.
(elf_x86_64_link_hash_table_create): Likewise.
(bfd_elf64_bfd_link_hash_table_create): Likewise.
(bfd_elf32_bfd_link_hash_table_create): Likewise.
(elf_x86_64_lazy_plt): Updated.
(elf_x86_64_non_lazy_plt): Likewise.
(elf_x86_64_lazy_bnd_plt): Likewise.
(elf_x86_64_non_lazy_bnd_plt): Likewise.
(elf_x86_64_lazy_ibt_plt): Likewise.
(elf_x32_lazy_ibt_plt): Likewise.
(elf_x86_64_non_lazy_ibt_plt): Likewise.
(elf_x32_non_lazy_ibt_plt): Likewise.
(elf_x86_64_allocate_dynrelocs): Likewise.
(elf_x86_64_size_dynamic_sections): Likewise.
(elf_x86_64_relocate_section): Likewise.
(elf_x86_64_finish_dynamic_symbol): Likewise.
(elf_x86_64_finish_dynamic_sections): Likewise.
(elf_x86_64_get_synthetic_symtab): Likewise.
(elf_x86_64_link_setup_gnu_properties): Likewise.
(elf_x86_64_nacl_plt): Likewise.
* elfxx-x86.c: Include "objalloc.h", "elf/i386.h" and
"elf/x86-64.h".
(ELF32_DYNAMIC_INTERPRETER): New.
(ELF64_DYNAMIC_INTERPRETER): Likewise.
(ELFX32_DYNAMIC_INTERPRETER): Likewise.
(_bfd_x86_elf_link_hash_table_create): Likewise.
(_bfd_x86_elf_link_hash_table_free): Renamed to ...
(elf_x86_link_hash_table_free): This. Make it static.
* elfxx-x86.h: Don't include "objalloc.h".
(ABI_64_P): New.
(elf_x86_lazy_plt_layout): Likewise.
(elf_x86_non_lazy_plt_layout): Likewise.
(elf_x86_plt_layout): Likewise.
(_bfd_x86_elf_link_hash_table_create): Likewise.
(bfd_elf64_bfd_link_hash_table_create): Likewise.
(bfd_elf32_bfd_link_hash_table_create): Likewise.
(elf_x86_link_hash_table): Add plt, lazy_plt, non_lazy_plt,
srelplt2 and next_tls_desc_index.
(_bfd_x86_elf_link_hash_table_free): Removed.
2017-08-30 Maciej W. Rozycki <macro@imgtec.com> 2017-08-30 Maciej W. Rozycki <macro@imgtec.com>
* elfxx-mips.c (mips_elf_perform_relocation): Correct microMIPS * elfxx-mips.c (mips_elf_perform_relocation): Correct microMIPS

View File

@ -522,12 +522,6 @@ elf_i386_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
early in the link process, elf_i386_finish_dynamic_sections is early in the link process, elf_i386_finish_dynamic_sections is
one of the last functions. */ one of the last functions. */
/* The name of the dynamic interpreter. This is put in the .interp
section. */
#define ELF_DYNAMIC_INTERPRETER "/usr/lib/libc.so.1"
/* The size in bytes of an entry in the lazy procedure linkage table. */ /* The size in bytes of an entry in the lazy procedure linkage table. */
#define LAZY_PLT_ENTRY_SIZE 16 #define LAZY_PLT_ENTRY_SIZE 16
@ -758,94 +752,21 @@ static const bfd_byte elf_i386_eh_frame_non_lazy_plt[] =
DW_CFA_nop, DW_CFA_nop, DW_CFA_nop DW_CFA_nop, DW_CFA_nop, DW_CFA_nop
}; };
struct elf_i386_lazy_plt_layout
{
/* The first entry in an absolute lazy procedure linkage table looks
like this. */
const bfd_byte *plt0_entry;
unsigned int plt0_entry_size;
/* Offsets into plt0_entry that are to be replaced with GOT[1] and
GOT[2]. */
unsigned int plt0_got1_offset;
unsigned int plt0_got2_offset;
/* Later entries in an absolute lazy procedure linkage table look
like this. */
const bfd_byte *plt_entry;
unsigned int plt_entry_size;
/* Offsets into plt_entry that are to be replaced with... */
unsigned int plt_got_offset; /* ... address of this symbol in .got. */
unsigned int plt_reloc_offset; /* ... offset into relocation table. */
unsigned int plt_plt_offset; /* ... offset to start of .plt. */
/* Offset into plt_entry where the initial value of the GOT entry
points. */
unsigned int plt_lazy_offset;
/* The first entry in a PIC lazy procedure linkage table looks like
this. */
const bfd_byte *pic_plt0_entry;
/* Subsequent entries in a PIC lazy procedure linkage table look
like this. */
const bfd_byte *pic_plt_entry;
/* .eh_frame covering the lazy .plt section. */
const bfd_byte *eh_frame_plt;
unsigned int eh_frame_plt_size;
};
struct elf_i386_non_lazy_plt_layout
{
/* Entries in an absolute non-lazy procedure linkage table look like
this. */
const bfd_byte *plt_entry;
/* Entries in a PIC non-lazy procedure linkage table look like this. */
const bfd_byte *pic_plt_entry;
unsigned int plt_entry_size;
/* Offsets into plt_entry that are to be replaced with... */
unsigned int plt_got_offset; /* ... address of this symbol in .got. */
/* .eh_frame covering the non-lazy .plt section. */
const bfd_byte *eh_frame_plt;
unsigned int eh_frame_plt_size;
};
struct elf_i386_plt_layout
{
/* The first entry in a lazy procedure linkage table looks like this. */
const bfd_byte *plt0_entry;
/* Entries in a procedure linkage table look like this. */
const bfd_byte *plt_entry;
unsigned int plt_entry_size;
/* 1 has PLT0. */
unsigned int has_plt0;
/* Offsets into plt_entry that are to be replaced with... */
unsigned int plt_got_offset; /* ... address of this symbol in .got. */
/* .eh_frame covering the .plt section. */
const bfd_byte *eh_frame_plt;
unsigned int eh_frame_plt_size;
};
/* These are the standard parameters. */ /* These are the standard parameters. */
static const struct elf_i386_lazy_plt_layout elf_i386_lazy_plt = static const struct elf_x86_lazy_plt_layout elf_i386_lazy_plt =
{ {
elf_i386_lazy_plt0_entry, /* plt0_entry */ elf_i386_lazy_plt0_entry, /* plt0_entry */
sizeof (elf_i386_lazy_plt0_entry), /* plt0_entry_size */ sizeof (elf_i386_lazy_plt0_entry), /* plt0_entry_size */
2, /* plt0_got1_offset */
8, /* plt0_got2_offset */
elf_i386_lazy_plt_entry, /* plt_entry */ elf_i386_lazy_plt_entry, /* plt_entry */
LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
2, /* plt0_got1_offset */
8, /* plt0_got2_offset */
0, /* plt0_got2_insn_end */
2, /* plt_got_offset */ 2, /* plt_got_offset */
7, /* plt_reloc_offset */ 7, /* plt_reloc_offset */
12, /* plt_plt_offset */ 12, /* plt_plt_offset */
0, /* plt_got_insn_size */
0, /* plt_plt_insn_end */
6, /* plt_lazy_offset */ 6, /* plt_lazy_offset */
elf_i386_pic_lazy_plt0_entry, /* pic_plt0_entry */ elf_i386_pic_lazy_plt0_entry, /* pic_plt0_entry */
elf_i386_pic_lazy_plt_entry, /* pic_plt_entry */ elf_i386_pic_lazy_plt_entry, /* pic_plt_entry */
@ -853,27 +774,31 @@ static const struct elf_i386_lazy_plt_layout elf_i386_lazy_plt =
sizeof (elf_i386_eh_frame_lazy_plt) /* eh_frame_plt_size */ sizeof (elf_i386_eh_frame_lazy_plt) /* eh_frame_plt_size */
}; };
static const struct elf_i386_non_lazy_plt_layout elf_i386_non_lazy_plt = static const struct elf_x86_non_lazy_plt_layout elf_i386_non_lazy_plt =
{ {
elf_i386_non_lazy_plt_entry, /* plt_entry */ elf_i386_non_lazy_plt_entry, /* plt_entry */
elf_i386_pic_non_lazy_plt_entry, /* pic_plt_entry */ elf_i386_pic_non_lazy_plt_entry, /* pic_plt_entry */
NON_LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ NON_LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
2, /* plt_got_offset */ 2, /* plt_got_offset */
0, /* plt_got_insn_size */
elf_i386_eh_frame_non_lazy_plt, /* eh_frame_plt */ elf_i386_eh_frame_non_lazy_plt, /* eh_frame_plt */
sizeof (elf_i386_eh_frame_non_lazy_plt) /* eh_frame_plt_size */ sizeof (elf_i386_eh_frame_non_lazy_plt) /* eh_frame_plt_size */
}; };
static const struct elf_i386_lazy_plt_layout elf_i386_lazy_ibt_plt = static const struct elf_x86_lazy_plt_layout elf_i386_lazy_ibt_plt =
{ {
elf_i386_lazy_ibt_plt0_entry, /* plt0_entry */ elf_i386_lazy_ibt_plt0_entry, /* plt0_entry */
sizeof (elf_i386_lazy_ibt_plt0_entry), /* plt0_entry_size */ sizeof (elf_i386_lazy_ibt_plt0_entry), /* plt0_entry_size */
2, /* plt0_got1_offset */
8, /* plt0_got2_offset */
elf_i386_lazy_ibt_plt_entry, /* plt_entry */ elf_i386_lazy_ibt_plt_entry, /* plt_entry */
LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
2, /* plt0_got1_offset */
8, /* plt0_got2_offset */
0, /* plt0_got2_insn_end */
4+2, /* plt_got_offset */ 4+2, /* plt_got_offset */
4+1, /* plt_reloc_offset */ 4+1, /* plt_reloc_offset */
4+6, /* plt_plt_offset */ 4+6, /* plt_plt_offset */
0, /* plt_got_insn_size */
0, /* plt_plt_insn_end */
0, /* plt_lazy_offset */ 0, /* plt_lazy_offset */
elf_i386_pic_lazy_ibt_plt0_entry, /* pic_plt0_entry */ elf_i386_pic_lazy_ibt_plt0_entry, /* pic_plt0_entry */
elf_i386_lazy_ibt_plt_entry, /* pic_plt_entry */ elf_i386_lazy_ibt_plt_entry, /* pic_plt_entry */
@ -881,12 +806,13 @@ static const struct elf_i386_lazy_plt_layout elf_i386_lazy_ibt_plt =
sizeof (elf_i386_eh_frame_lazy_ibt_plt) /* eh_frame_plt_size */ sizeof (elf_i386_eh_frame_lazy_ibt_plt) /* eh_frame_plt_size */
}; };
static const struct elf_i386_non_lazy_plt_layout elf_i386_non_lazy_ibt_plt = static const struct elf_x86_non_lazy_plt_layout elf_i386_non_lazy_ibt_plt =
{ {
elf_i386_non_lazy_ibt_plt_entry, /* plt_entry */ elf_i386_non_lazy_ibt_plt_entry, /* plt_entry */
elf_i386_pic_non_lazy_ibt_plt_entry,/* pic_plt_entry */ elf_i386_pic_non_lazy_ibt_plt_entry,/* pic_plt_entry */
LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
4+2, /* plt_got_offset */ 4+2, /* plt_got_offset */
0, /* plt_got_insn_size */
elf_i386_eh_frame_non_lazy_plt, /* eh_frame_plt */ elf_i386_eh_frame_non_lazy_plt, /* eh_frame_plt */
sizeof (elf_i386_eh_frame_non_lazy_plt) /* eh_frame_plt_size */ sizeof (elf_i386_eh_frame_non_lazy_plt) /* eh_frame_plt_size */
}; };
@ -955,88 +881,9 @@ elf_i386_mkobject (bfd *abfd)
I386_ELF_DATA); I386_ELF_DATA);
} }
/* i386 ELF linker hash table. */
struct elf_i386_link_hash_table
{
struct elf_x86_link_hash_table x86;
/* Parameters describing PLT generation, lazy or non-lazy. */
struct elf_i386_plt_layout plt;
/* Parameters describing lazy PLT generation. */
const struct elf_i386_lazy_plt_layout *lazy_plt;
/* Parameters describing non-lazy PLT generation. */
const struct elf_i386_non_lazy_plt_layout *non_lazy_plt;
/* The (unloaded but important) .rel.plt.unloaded section on VxWorks. */
asection *srelplt2;
/* The index of the next unused R_386_TLS_DESC slot in .rel.plt. */
bfd_vma next_tls_desc_index;
};
#define elf_i386_next_tls_desc_index(htab) \
((struct elf_i386_link_hash_table *) (htab))->next_tls_desc_index
#define elf_i386_srelplt2(htab) \
((struct elf_i386_link_hash_table *) (htab))->srelplt2
#define elf_i386_plt(htab) \
((struct elf_i386_link_hash_table *) (htab))->plt
#define elf_i386_lazy_plt(htab) \
((struct elf_i386_link_hash_table *) (htab))->lazy_plt
#define elf_i386_non_lazy_plt(htab) \
((struct elf_i386_link_hash_table *) (htab))->non_lazy_plt
#define elf_i386_compute_jump_table_size(htab) \ #define elf_i386_compute_jump_table_size(htab) \
((htab)->elf.srelplt->reloc_count * 4) ((htab)->elf.srelplt->reloc_count * 4)
/* Create an i386 ELF linker hash table. */
static struct bfd_link_hash_table *
elf_i386_link_hash_table_create (bfd *abfd)
{
struct elf_x86_link_hash_table *ret;
bfd_size_type amt = sizeof (struct elf_i386_link_hash_table);
ret = (struct elf_x86_link_hash_table *) bfd_zmalloc (amt);
if (ret == NULL)
return NULL;
if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd,
_bfd_x86_elf_link_hash_newfunc,
sizeof (struct elf_x86_link_hash_entry),
I386_ELF_DATA))
{
free (ret);
return NULL;
}
ret->r_info = elf32_r_info;
ret->r_sym = elf32_r_sym;
ret->pointer_r_type = R_386_32;
ret->dynamic_interpreter_size = sizeof ELF_DYNAMIC_INTERPRETER;
ret->dynamic_interpreter = ELF_DYNAMIC_INTERPRETER;
ret->tls_get_addr = "___tls_get_addr";
ret->loc_hash_table = htab_try_create (1024,
_bfd_x86_elf_local_htab_hash,
_bfd_x86_elf_local_htab_eq,
NULL);
ret->loc_hash_memory = objalloc_create ();
if (!ret->loc_hash_table || !ret->loc_hash_memory)
{
_bfd_x86_elf_link_hash_table_free (abfd);
return NULL;
}
ret->elf.root.hash_table_free = _bfd_x86_elf_link_hash_table_free;
return &ret->elf.root;
}
/* Return TRUE if the TLS access code sequence support transition /* Return TRUE if the TLS access code sequence support transition
from R_TYPE. */ from R_TYPE. */
@ -2362,8 +2209,6 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
unsigned plt_entry_size; unsigned plt_entry_size;
bfd_boolean resolved_to_zero; bfd_boolean resolved_to_zero;
const struct elf_i386_backend_data *bed; const struct elf_i386_backend_data *bed;
const struct elf_i386_plt_layout *plt_layout;
const struct elf_i386_non_lazy_plt_layout *non_lazy_plt_layout;
if (h->root.type == bfd_link_hash_indirect) if (h->root.type == bfd_link_hash_indirect)
return TRUE; return TRUE;
@ -2377,9 +2222,7 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
bed = get_elf_i386_backend_data (info->output_bfd); bed = get_elf_i386_backend_data (info->output_bfd);
plt_layout = &elf_i386_plt (htab); plt_entry_size = htab->plt.plt_entry_size;
non_lazy_plt_layout = elf_i386_non_lazy_plt (htab);
plt_entry_size = plt_layout->plt_entry_size;
resolved_to_zero = UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, resolved_to_zero = UNDEFINED_WEAK_RESOLVED_TO_ZERO (info,
I386_ELF_DATA, I386_ELF_DATA,
@ -2417,7 +2260,7 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
if (_bfd_elf_allocate_ifunc_dyn_relocs (info, h, &eh->dyn_relocs, if (_bfd_elf_allocate_ifunc_dyn_relocs (info, h, &eh->dyn_relocs,
&htab->readonly_dynrelocs_against_ifunc, &htab->readonly_dynrelocs_against_ifunc,
plt_entry_size, plt_entry_size,
(plt_layout->has_plt0 (htab->plt.has_plt0
* plt_entry_size), * plt_entry_size),
4, TRUE)) 4, TRUE))
{ {
@ -2428,7 +2271,7 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
eh->plt_second.offset = s->size; eh->plt_second.offset = s->size;
/* Make room for this entry in the second PLT section. */ /* Make room for this entry in the second PLT section. */
s->size += non_lazy_plt_layout->plt_entry_size; s->size += htab->non_lazy_plt->plt_entry_size;
} }
return TRUE; return TRUE;
@ -2470,7 +2313,7 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
first entry. The .plt section is used by prelink to undo first entry. The .plt section is used by prelink to undo
prelinking for dynamic relocations. */ prelinking for dynamic relocations. */
if (s->size == 0) if (s->size == 0)
s->size = plt_layout->has_plt0 * plt_entry_size; s->size = htab->plt.has_plt0 * plt_entry_size;
if (use_plt_got) if (use_plt_got)
eh->plt_got.offset = got_s->size; eh->plt_got.offset = got_s->size;
@ -2515,12 +2358,12 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
/* Make room for this entry. */ /* Make room for this entry. */
if (use_plt_got) if (use_plt_got)
got_s->size += non_lazy_plt_layout->plt_entry_size; got_s->size += htab->non_lazy_plt->plt_entry_size;
else else
{ {
s->size += plt_entry_size; s->size += plt_entry_size;
if (second_s) if (second_s)
second_s->size += non_lazy_plt_layout->plt_entry_size; second_s->size += htab->non_lazy_plt->plt_entry_size;
/* We also need to make an entry in the .got.plt section, /* We also need to make an entry in the .got.plt section,
which will be placed in the .got section by the linker which will be placed in the .got section by the linker
@ -2548,7 +2391,7 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
R_386_32 relocation for _GLOBAL_OFFSET_TABLE_ + 4 and an R_386_32 relocation for _GLOBAL_OFFSET_TABLE_ + 4 and an
R_386_32 relocation for _GLOBAL_OFFSET_TABLE_ + 8. */ R_386_32 relocation for _GLOBAL_OFFSET_TABLE_ + 8. */
asection *srelplt2 = elf_i386_srelplt2 (htab); asection *srelplt2 = htab->srelplt2;
if (h->plt.offset == plt_entry_size) if (h->plt.offset == plt_entry_size)
srelplt2->size += (sizeof (Elf32_External_Rel) * 2); srelplt2->size += (sizeof (Elf32_External_Rel) * 2);
@ -3096,10 +2939,8 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
so that R_386_IRELATIVE entries come last. */ so that R_386_IRELATIVE entries come last. */
if (htab->elf.srelplt) if (htab->elf.srelplt)
{ {
elf_i386_next_tls_desc_index(htab) htab->next_tls_desc_index = htab->elf.srelplt->reloc_count;
= htab->elf.srelplt->reloc_count; htab->sgotplt_jump_table_size = htab->next_tls_desc_index * 4;
htab->sgotplt_jump_table_size
= elf_i386_next_tls_desc_index(htab) * 4;
htab->next_irelative_index = htab->elf.srelplt->reloc_count - 1; htab->next_irelative_index = htab->elf.srelplt->reloc_count - 1;
} }
else if (htab->elf.irelplt) else if (htab->elf.irelplt)
@ -3131,14 +2972,14 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
&& htab->elf.splt != NULL && htab->elf.splt != NULL
&& htab->elf.splt->size != 0 && htab->elf.splt->size != 0
&& !bfd_is_abs_section (htab->elf.splt->output_section)) && !bfd_is_abs_section (htab->elf.splt->output_section))
htab->plt_eh_frame->size = elf_i386_plt (htab).eh_frame_plt_size; htab->plt_eh_frame->size = htab->plt.eh_frame_plt_size;
if (htab->plt_got_eh_frame != NULL if (htab->plt_got_eh_frame != NULL
&& htab->plt_got != NULL && htab->plt_got != NULL
&& htab->plt_got->size != 0 && htab->plt_got->size != 0
&& !bfd_is_abs_section (htab->plt_got->output_section)) && !bfd_is_abs_section (htab->plt_got->output_section))
htab->plt_got_eh_frame->size htab->plt_got_eh_frame->size
= elf_i386_non_lazy_plt (htab)->eh_frame_plt_size; = htab->non_lazy_plt->eh_frame_plt_size;
/* Unwind info for the second PLT and .plt.got sections are /* Unwind info for the second PLT and .plt.got sections are
identical. */ identical. */
@ -3147,7 +2988,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
&& htab->plt_second->size != 0 && htab->plt_second->size != 0
&& !bfd_is_abs_section (htab->plt_second->output_section)) && !bfd_is_abs_section (htab->plt_second->output_section))
htab->plt_second_eh_frame->size htab->plt_second_eh_frame->size
= elf_i386_non_lazy_plt (htab)->eh_frame_plt_size; = htab->non_lazy_plt->eh_frame_plt_size;
} }
/* We now have determined the sizes of the various dynamic sections. /* We now have determined the sizes of the various dynamic sections.
@ -3189,7 +3030,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
{ {
if (s->size != 0 if (s->size != 0
&& s != htab->elf.srelplt && s != htab->elf.srelplt
&& s != elf_i386_srelplt2 (htab)) && s != htab->srelplt2)
relocs = TRUE; relocs = TRUE;
/* We use the reloc_count field as a counter if we need /* We use the reloc_count field as a counter if we need
@ -3235,7 +3076,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
&& htab->plt_eh_frame->contents != NULL) && htab->plt_eh_frame->contents != NULL)
{ {
memcpy (htab->plt_eh_frame->contents, memcpy (htab->plt_eh_frame->contents,
elf_i386_plt (htab).eh_frame_plt, htab->plt.eh_frame_plt,
htab->plt_eh_frame->size); htab->plt_eh_frame->size);
bfd_put_32 (dynobj, htab->elf.splt->size, bfd_put_32 (dynobj, htab->elf.splt->size,
htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET); htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET);
@ -3245,7 +3086,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
&& htab->plt_got_eh_frame->contents != NULL) && htab->plt_got_eh_frame->contents != NULL)
{ {
memcpy (htab->plt_got_eh_frame->contents, memcpy (htab->plt_got_eh_frame->contents,
elf_i386_non_lazy_plt (htab)->eh_frame_plt, htab->non_lazy_plt->eh_frame_plt,
htab->plt_got_eh_frame->size); htab->plt_got_eh_frame->size);
bfd_put_32 (dynobj, htab->plt_got->size, bfd_put_32 (dynobj, htab->plt_got->size,
(htab->plt_got_eh_frame->contents (htab->plt_got_eh_frame->contents
@ -3256,7 +3097,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
&& htab->plt_second_eh_frame->contents != NULL) && htab->plt_second_eh_frame->contents != NULL)
{ {
memcpy (htab->plt_second_eh_frame->contents, memcpy (htab->plt_second_eh_frame->contents,
elf_i386_non_lazy_plt (htab)->eh_frame_plt, htab->non_lazy_plt->eh_frame_plt,
htab->plt_second_eh_frame->size); htab->plt_second_eh_frame->size);
bfd_put_32 (dynobj, htab->plt_second->size, bfd_put_32 (dynobj, htab->plt_second->size,
(htab->plt_second_eh_frame->contents (htab->plt_second_eh_frame->contents
@ -3431,7 +3272,7 @@ elf_i386_relocate_section (bfd *output_bfd,
_bfd_x86_elf_set_tls_module_base (info); _bfd_x86_elf_set_tls_module_base (info);
plt_entry_size = elf_i386_plt (htab).plt_entry_size; plt_entry_size = htab->plt.plt_entry_size;
rel = wrel = relocs; rel = wrel = relocs;
relend = relocs + input_section->reloc_count; relend = relocs + input_section->reloc_count;
@ -3676,7 +3517,7 @@ elf_i386_relocate_section (bfd *output_bfd,
if (htab->elf.splt != NULL) if (htab->elf.splt != NULL)
{ {
plt_index = (h->plt.offset / plt_entry_size plt_index = (h->plt.offset / plt_entry_size
- elf_i386_plt (htab).has_plt0); - htab->plt.has_plt0);
off = (plt_index + 3) * 4; off = (plt_index + 3) * 4;
base_got = htab->elf.sgotplt; base_got = htab->elf.sgotplt;
} }
@ -3894,7 +3735,7 @@ do_ifunc_pointer:
else else
/* Use GOTPLT entry. */ /* Use GOTPLT entry. */
relocation = (h->plt.offset / plt_entry_size relocation = (h->plt.offset / plt_entry_size
- elf_i386_plt (htab).has_plt0 + 3) * 4; - htab->plt.has_plt0 + 3) * 4;
if (!bfd_link_pic (info)) if (!bfd_link_pic (info))
{ {
@ -4523,7 +4364,7 @@ disallow_got32:
+ htab->sgotplt_jump_table_size); + htab->sgotplt_jump_table_size);
sreloc = htab->elf.srelplt; sreloc = htab->elf.srelplt;
loc = sreloc->contents; loc = sreloc->contents;
loc += (elf_i386_next_tls_desc_index (htab)++ loc += (htab->next_tls_desc_index++
* sizeof (Elf32_External_Rel)); * sizeof (Elf32_External_Rel));
BFD_ASSERT (loc + sizeof (Elf32_External_Rel) BFD_ASSERT (loc + sizeof (Elf32_External_Rel)
<= sreloc->contents + sreloc->size); <= sreloc->contents + sreloc->size);
@ -4983,19 +4824,13 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
struct elf_x86_link_hash_entry *eh; struct elf_x86_link_hash_entry *eh;
bfd_boolean local_undefweak; bfd_boolean local_undefweak;
bfd_boolean use_plt_second; bfd_boolean use_plt_second;
const struct elf_i386_plt_layout *plt_layout;
const struct elf_i386_lazy_plt_layout *lazy_plt_layout;
const struct elf_i386_non_lazy_plt_layout *non_lazy_plt_layout;
htab = elf_x86_hash_table (info, I386_ELF_DATA); htab = elf_x86_hash_table (info, I386_ELF_DATA);
if (htab == NULL) if (htab == NULL)
return FALSE; return FALSE;
abed = get_elf_i386_backend_data (output_bfd); abed = get_elf_i386_backend_data (output_bfd);
plt_layout = &elf_i386_plt (htab); plt_entry_size = htab->plt.plt_entry_size;
lazy_plt_layout = elf_i386_lazy_plt (htab);
non_lazy_plt_layout = elf_i386_non_lazy_plt (htab);
plt_entry_size = plt_layout->plt_entry_size;
/* Use the second PLT section only if there is .plt section. */ /* Use the second PLT section only if there is .plt section. */
use_plt_second = htab->elf.splt != NULL && htab->plt_second != NULL; use_plt_second = htab->elf.splt != NULL && htab->plt_second != NULL;
@ -5061,7 +4896,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
if (plt == htab->elf.splt) if (plt == htab->elf.splt)
{ {
got_offset = (h->plt.offset / plt_entry_size got_offset = (h->plt.offset / plt_entry_size
- plt_layout->has_plt0); - htab->plt.has_plt0);
got_offset = (got_offset + 3) * 4; got_offset = (got_offset + 3) * 4;
} }
else else
@ -5072,18 +4907,18 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
/* Fill in the entry in the procedure linkage table and update /* Fill in the entry in the procedure linkage table and update
the first slot. */ the first slot. */
memcpy (plt->contents + h->plt.offset, plt_layout->plt_entry, memcpy (plt->contents + h->plt.offset, htab->plt.plt_entry,
plt_entry_size); plt_entry_size);
if (use_plt_second) if (use_plt_second)
{ {
const bfd_byte *plt_entry; const bfd_byte *plt_entry;
if (bfd_link_pic (info)) if (bfd_link_pic (info))
plt_entry = non_lazy_plt_layout->pic_plt_entry; plt_entry = htab->non_lazy_plt->pic_plt_entry;
else else
plt_entry = non_lazy_plt_layout->plt_entry; plt_entry = htab->non_lazy_plt->plt_entry;
memcpy (htab->plt_second->contents + eh->plt_second.offset, memcpy (htab->plt_second->contents + eh->plt_second.offset,
plt_entry, non_lazy_plt_layout->plt_entry_size); plt_entry, htab->non_lazy_plt->plt_entry_size);
resolved_plt = htab->plt_second; resolved_plt = htab->plt_second;
plt_offset = eh->plt_second.offset; plt_offset = eh->plt_second.offset;
@ -5101,7 +4936,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
+ gotplt->output_offset + gotplt->output_offset
+ got_offset), + got_offset),
resolved_plt->contents + plt_offset resolved_plt->contents + plt_offset
+ plt_layout->plt_got_offset); + htab->plt.plt_got_offset);
if (abed->os == is_vxworks) if (abed->os == is_vxworks)
{ {
@ -5111,8 +4946,8 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
for this PLT entry. */ for this PLT entry. */
/* S: Current slot number (zero-based). */ /* S: Current slot number (zero-based). */
s = ((h->plt.offset - plt_layout->plt_entry_size) s = ((h->plt.offset - htab->plt.plt_entry_size)
/ plt_layout->plt_entry_size); / htab->plt.plt_entry_size);
/* K: Number of relocations for PLTResolve. */ /* K: Number of relocations for PLTResolve. */
if (bfd_link_pic (info)) if (bfd_link_pic (info))
k = PLTRESOLVE_RELOCS_SHLIB; k = PLTRESOLVE_RELOCS_SHLIB;
@ -5121,7 +4956,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
/* Skip the PLTresolve relocations, and the relocations for /* Skip the PLTresolve relocations, and the relocations for
the other PLT slots. */ the other PLT slots. */
reloc_index = k + s * PLT_NON_JUMP_SLOT_RELOCS; reloc_index = k + s * PLT_NON_JUMP_SLOT_RELOCS;
loc = (elf_i386_srelplt2 (htab)->contents + reloc_index loc = (htab->srelplt2->contents + reloc_index
* sizeof (Elf32_External_Rel)); * sizeof (Elf32_External_Rel));
rel.r_offset = (plt->output_section->vma rel.r_offset = (plt->output_section->vma
@ -5144,7 +4979,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
{ {
bfd_put_32 (output_bfd, got_offset, bfd_put_32 (output_bfd, got_offset,
resolved_plt->contents + plt_offset resolved_plt->contents + plt_offset
+ plt_layout->plt_got_offset); + htab->plt.plt_got_offset);
} }
/* Fill in the entry in the global offset table. Leave the entry /* Fill in the entry in the global offset table. Leave the entry
@ -5152,12 +4987,12 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
against undefined weak symbol in PIE. */ against undefined weak symbol in PIE. */
if (!local_undefweak) if (!local_undefweak)
{ {
if (plt_layout->has_plt0) if (htab->plt.has_plt0)
bfd_put_32 (output_bfd, bfd_put_32 (output_bfd,
(plt->output_section->vma (plt->output_section->vma
+ plt->output_offset + plt->output_offset
+ h->plt.offset + h->plt.offset
+ lazy_plt_layout->plt_lazy_offset), + htab->lazy_plt->plt_lazy_offset),
gotplt->contents + got_offset); gotplt->contents + got_offset);
/* Fill in the entry in the .rel.plt section. */ /* Fill in the entry in the .rel.plt section. */
@ -5197,17 +5032,17 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
/* Don't fill the second and third slots in PLT entry for /* Don't fill the second and third slots in PLT entry for
static executables nor without PLT0. */ static executables nor without PLT0. */
if (plt == htab->elf.splt && plt_layout->has_plt0) if (plt == htab->elf.splt && htab->plt.has_plt0)
{ {
bfd_put_32 (output_bfd, bfd_put_32 (output_bfd,
plt_index * sizeof (Elf32_External_Rel), plt_index * sizeof (Elf32_External_Rel),
plt->contents + h->plt.offset plt->contents + h->plt.offset
+ lazy_plt_layout->plt_reloc_offset); + htab->lazy_plt->plt_reloc_offset);
bfd_put_32 (output_bfd, bfd_put_32 (output_bfd,
- (h->plt.offset - (h->plt.offset
+ lazy_plt_layout->plt_plt_offset + 4), + htab->lazy_plt->plt_plt_offset + 4),
(plt->contents + h->plt.offset (plt->contents + h->plt.offset
+ lazy_plt_layout->plt_plt_offset)); + htab->lazy_plt->plt_plt_offset));
} }
} }
} }
@ -5232,12 +5067,12 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
/* Fill in the entry in the GOT procedure linkage table. */ /* Fill in the entry in the GOT procedure linkage table. */
if (! bfd_link_pic (info)) if (! bfd_link_pic (info))
{ {
got_plt_entry = non_lazy_plt_layout->plt_entry; got_plt_entry = htab->non_lazy_plt->plt_entry;
got_offset += got->output_section->vma + got->output_offset; got_offset += got->output_section->vma + got->output_offset;
} }
else else
{ {
got_plt_entry = non_lazy_plt_layout->pic_plt_entry; got_plt_entry = htab->non_lazy_plt->pic_plt_entry;
got_offset += (got->output_section->vma got_offset += (got->output_section->vma
+ got->output_offset + got->output_offset
- gotplt->output_section->vma - gotplt->output_section->vma
@ -5246,10 +5081,10 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
plt_offset = eh->plt_got.offset; plt_offset = eh->plt_got.offset;
memcpy (plt->contents + plt_offset, got_plt_entry, memcpy (plt->contents + plt_offset, got_plt_entry,
non_lazy_plt_layout->plt_entry_size); htab->non_lazy_plt->plt_entry_size);
bfd_put_32 (output_bfd, got_offset, bfd_put_32 (output_bfd, got_offset,
(plt->contents + plt_offset (plt->contents + plt_offset
+ non_lazy_plt_layout->plt_got_offset)); + htab->non_lazy_plt->plt_got_offset));
} }
if (!local_undefweak if (!local_undefweak
@ -5505,9 +5340,6 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
if (htab->elf.dynamic_sections_created) if (htab->elf.dynamic_sections_created)
{ {
Elf32_External_Dyn *dyncon, *dynconend; Elf32_External_Dyn *dyncon, *dynconend;
const struct elf_i386_plt_layout *plt_layout;
const struct elf_i386_lazy_plt_layout *lazy_plt_layout;
const struct elf_i386_non_lazy_plt_layout *non_lazy_plt_layout;
if (sdyn == NULL || htab->elf.sgot == NULL) if (sdyn == NULL || htab->elf.sgot == NULL)
abort (); abort ();
@ -5548,10 +5380,6 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
} }
plt_layout = &elf_i386_plt (htab);
lazy_plt_layout = elf_i386_lazy_plt (htab);
non_lazy_plt_layout = elf_i386_non_lazy_plt (htab);
if (htab->elf.splt && htab->elf.splt->size > 0) if (htab->elf.splt && htab->elf.splt->size > 0)
{ {
/* UnixWare sets the entsize of .plt to 4, although that doesn't /* UnixWare sets the entsize of .plt to 4, although that doesn't
@ -5559,15 +5387,15 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
elf_section_data (htab->elf.splt->output_section) elf_section_data (htab->elf.splt->output_section)
->this_hdr.sh_entsize = 4; ->this_hdr.sh_entsize = 4;
if (plt_layout->has_plt0) if (htab->plt.has_plt0)
{ {
/* Fill in the special first entry in the procedure linkage /* Fill in the special first entry in the procedure linkage
table. */ table. */
memcpy (htab->elf.splt->contents, plt_layout->plt0_entry, memcpy (htab->elf.splt->contents, htab->plt.plt0_entry,
lazy_plt_layout->plt0_entry_size); htab->lazy_plt->plt0_entry_size);
memset (htab->elf.splt->contents + lazy_plt_layout->plt0_entry_size, memset (htab->elf.splt->contents + htab->lazy_plt->plt0_entry_size,
abed->plt0_pad_byte, abed->plt0_pad_byte,
plt_layout->plt_entry_size - lazy_plt_layout->plt0_entry_size); htab->plt.plt_entry_size - htab->lazy_plt->plt0_entry_size);
if (!bfd_link_pic (info)) if (!bfd_link_pic (info))
{ {
bfd_put_32 (output_bfd, bfd_put_32 (output_bfd,
@ -5575,28 +5403,28 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
+ htab->elf.sgotplt->output_offset + htab->elf.sgotplt->output_offset
+ 4), + 4),
htab->elf.splt->contents htab->elf.splt->contents
+ lazy_plt_layout->plt0_got1_offset); + htab->lazy_plt->plt0_got1_offset);
bfd_put_32 (output_bfd, bfd_put_32 (output_bfd,
(htab->elf.sgotplt->output_section->vma (htab->elf.sgotplt->output_section->vma
+ htab->elf.sgotplt->output_offset + htab->elf.sgotplt->output_offset
+ 8), + 8),
htab->elf.splt->contents htab->elf.splt->contents
+ lazy_plt_layout->plt0_got2_offset); + htab->lazy_plt->plt0_got2_offset);
if (abed->os == is_vxworks) if (abed->os == is_vxworks)
{ {
Elf_Internal_Rela rel; Elf_Internal_Rela rel;
int num_plts = (htab->elf.splt->size int num_plts = (htab->elf.splt->size
/ plt_layout->plt_entry_size) - 1; / htab->plt.plt_entry_size) - 1;
unsigned char *p; unsigned char *p;
asection *srelplt2 = elf_i386_srelplt2 (htab); asection *srelplt2 = htab->srelplt2;
/* Generate a relocation for _GLOBAL_OFFSET_TABLE_ /* Generate a relocation for _GLOBAL_OFFSET_TABLE_
+ 4. On IA32 we use REL relocations so the + 4. On IA32 we use REL relocations so the
addend goes in the PLT directly. */ addend goes in the PLT directly. */
rel.r_offset = (htab->elf.splt->output_section->vma rel.r_offset = (htab->elf.splt->output_section->vma
+ htab->elf.splt->output_offset + htab->elf.splt->output_offset
+ lazy_plt_layout->plt0_got1_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,
@ -5605,7 +5433,7 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
+ 8. */ + 8. */
rel.r_offset = (htab->elf.splt->output_section->vma rel.r_offset = (htab->elf.splt->output_section->vma
+ htab->elf.splt->output_offset + htab->elf.splt->output_offset
+ lazy_plt_layout->plt0_got2_offset); + htab->lazy_plt->plt0_got2_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,
@ -5639,11 +5467,11 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
if (htab->plt_got != NULL && htab->plt_got->size > 0) if (htab->plt_got != NULL && htab->plt_got->size > 0)
elf_section_data (htab->plt_got->output_section) elf_section_data (htab->plt_got->output_section)
->this_hdr.sh_entsize = non_lazy_plt_layout->plt_entry_size; ->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size;
if (htab->plt_second != NULL && htab->plt_second->size > 0) if (htab->plt_second != NULL && htab->plt_second->size > 0)
elf_section_data (htab->plt_second->output_section) elf_section_data (htab->plt_second->output_section)
->this_hdr.sh_entsize = non_lazy_plt_layout->plt_entry_size; ->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size;
} }
/* Fill in the first three entries in the global offset table. */ /* Fill in the first three entries in the global offset table. */
@ -5811,7 +5639,7 @@ struct elf_i386_plt
}; };
/* Forward declaration. */ /* Forward declaration. */
static const struct elf_i386_lazy_plt_layout elf_i386_nacl_plt; static const struct elf_x86_lazy_plt_layout elf_i386_nacl_plt;
/* Similar to _bfd_elf_get_synthetic_symtab. Support PLTs with all /* Similar to _bfd_elf_get_synthetic_symtab. Support PLTs with all
dynamic relocations. */ dynamic relocations. */
@ -5831,10 +5659,10 @@ elf_i386_get_synthetic_symtab (bfd *abfd,
bfd_byte *plt_contents; bfd_byte *plt_contents;
long dynrelcount, relsize; long dynrelcount, relsize;
arelent **dynrelbuf, *p; arelent **dynrelbuf, *p;
const struct elf_i386_lazy_plt_layout *lazy_plt; const struct elf_x86_lazy_plt_layout *lazy_plt;
const struct elf_i386_non_lazy_plt_layout *non_lazy_plt; const struct elf_x86_non_lazy_plt_layout *non_lazy_plt;
const struct elf_i386_lazy_plt_layout *lazy_ibt_plt; const struct elf_x86_lazy_plt_layout *lazy_ibt_plt;
const struct elf_i386_non_lazy_plt_layout *non_lazy_ibt_plt; const struct elf_x86_non_lazy_plt_layout *non_lazy_ibt_plt;
asection *plt; asection *plt;
bfd_vma got_addr; bfd_vma got_addr;
char *names; char *names;
@ -6198,9 +6026,6 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info)
bfd *pbfd; bfd *pbfd;
bfd *ebfd = NULL; bfd *ebfd = NULL;
elf_property *prop; elf_property *prop;
struct elf_i386_plt_layout *plt_layout;
const struct elf_i386_lazy_plt_layout *lazy_plt_layout;
const struct elf_i386_non_lazy_plt_layout *non_lazy_plt_layout;
features = 0; features = 0;
if (info->ibt) if (info->ibt)
@ -6316,12 +6141,10 @@ error_alignment:
} }
} }
plt_layout = &elf_i386_plt (htab);
/* Even when lazy binding is disabled by "-z now", the PLT0 entry may /* Even when lazy binding is disabled by "-z now", the PLT0 entry may
still be used with LD_AUDIT or LD_PROFILE if PLT entry is used for still be used with LD_AUDIT or LD_PROFILE if PLT entry is used for
canonical function address. */ canonical function address. */
plt_layout->has_plt0 = 1; htab->plt.has_plt0 = 1;
normal_target = FALSE; normal_target = FALSE;
switch (get_elf_i386_backend_data (info->output_bfd)->os) switch (get_elf_i386_backend_data (info->output_bfd)->os)
@ -6329,82 +6152,70 @@ error_alignment:
case is_normal: case is_normal:
if (use_ibt_plt) if (use_ibt_plt)
{ {
elf_i386_lazy_plt (htab) = &elf_i386_lazy_ibt_plt; htab->lazy_plt = &elf_i386_lazy_ibt_plt;
elf_i386_non_lazy_plt (htab) = &elf_i386_non_lazy_ibt_plt; htab->non_lazy_plt = &elf_i386_non_lazy_ibt_plt;
} }
else else
{ {
elf_i386_lazy_plt (htab) = &elf_i386_lazy_plt; htab->lazy_plt = &elf_i386_lazy_plt;
elf_i386_non_lazy_plt (htab) = &elf_i386_non_lazy_plt; htab->non_lazy_plt = &elf_i386_non_lazy_plt;
} }
normal_target = TRUE; normal_target = TRUE;
break; break;
case is_vxworks: case is_vxworks:
elf_i386_lazy_plt (htab) = &elf_i386_lazy_plt; htab->lazy_plt = &elf_i386_lazy_plt;
elf_i386_non_lazy_plt (htab) = NULL; htab->non_lazy_plt = NULL;
if (!elf_vxworks_create_dynamic_sections (dynobj, info, if (!elf_vxworks_create_dynamic_sections (dynobj, info,
&elf_i386_srelplt2 (htab))) &htab->srelplt2))
info->callbacks->einfo (_("%F: failed to create VxWorks dynamic sections\n")); info->callbacks->einfo (_("%F: failed to create VxWorks dynamic sections\n"));
break; break;
case is_nacl: case is_nacl:
elf_i386_lazy_plt (htab) = &elf_i386_nacl_plt; htab->lazy_plt = &elf_i386_nacl_plt;
elf_i386_non_lazy_plt (htab) = NULL; htab->non_lazy_plt = NULL;
break; break;
} }
lazy_plt_layout = elf_i386_lazy_plt (htab);
non_lazy_plt_layout = elf_i386_non_lazy_plt (htab);
pltsec = htab->elf.splt; pltsec = htab->elf.splt;
/* If the non-lazy PLT is available, use it for all PLT entries if /* If the non-lazy PLT is available, use it for all PLT entries if
there are no PLT0 or no .plt section. */ there are no PLT0 or no .plt section. */
if (non_lazy_plt_layout != NULL if (htab->non_lazy_plt != NULL
&& (!plt_layout->has_plt0 || pltsec == NULL)) && (!htab->plt.has_plt0 || pltsec == NULL))
{ {
lazy_plt = FALSE; lazy_plt = FALSE;
if (bfd_link_pic (info)) if (bfd_link_pic (info))
plt_layout->plt_entry htab->plt.plt_entry = htab->non_lazy_plt->pic_plt_entry;
= non_lazy_plt_layout->pic_plt_entry;
else else
plt_layout->plt_entry htab->plt.plt_entry = htab->non_lazy_plt->plt_entry;
= non_lazy_plt_layout->plt_entry; htab->plt.plt_entry_size = htab->non_lazy_plt->plt_entry_size;
plt_layout->plt_entry_size htab->plt.plt_got_offset = htab->non_lazy_plt->plt_got_offset;
= non_lazy_plt_layout->plt_entry_size; htab->plt.eh_frame_plt_size
plt_layout->plt_got_offset = htab->non_lazy_plt->eh_frame_plt_size;
= non_lazy_plt_layout->plt_got_offset; htab->plt.eh_frame_plt = htab->non_lazy_plt->eh_frame_plt;
plt_layout->eh_frame_plt_size
= non_lazy_plt_layout->eh_frame_plt_size;
plt_layout->eh_frame_plt
= non_lazy_plt_layout->eh_frame_plt;
} }
else else
{ {
lazy_plt = TRUE; lazy_plt = TRUE;
if (bfd_link_pic (info)) if (bfd_link_pic (info))
{ {
plt_layout->plt0_entry htab->plt.plt0_entry = htab->lazy_plt->pic_plt0_entry;
= lazy_plt_layout->pic_plt0_entry; htab->plt.plt_entry = htab->lazy_plt->pic_plt_entry;
plt_layout->plt_entry
= lazy_plt_layout->pic_plt_entry;
} }
else else
{ {
plt_layout->plt0_entry htab->plt.plt0_entry = htab->lazy_plt->plt0_entry;
= lazy_plt_layout->plt0_entry; htab->plt.plt_entry = htab->lazy_plt->plt_entry;
plt_layout->plt_entry
= lazy_plt_layout->plt_entry;
} }
plt_layout->plt_entry_size
= lazy_plt_layout->plt_entry_size; htab->plt.plt_entry_size = htab->lazy_plt->plt_entry_size;
plt_layout->plt_got_offset htab->plt.plt_got_offset = htab->lazy_plt->plt_got_offset;
= lazy_plt_layout->plt_got_offset; htab->plt.eh_frame_plt_size = htab->lazy_plt->eh_frame_plt_size;
plt_layout->eh_frame_plt_size htab->plt.eh_frame_plt = htab->lazy_plt->eh_frame_plt;
= lazy_plt_layout->eh_frame_plt_size;
plt_layout->eh_frame_plt
= lazy_plt_layout->eh_frame_plt;
} }
/* This is unused for i386. */
htab->plt.plt_got_insn_size = 0;
/* Return if there are no normal input files. */ /* Return if there are no normal input files. */
if (dynobj == NULL) if (dynobj == NULL)
return pbfd; return pbfd;
@ -6421,7 +6232,7 @@ error_alignment:
if (!_bfd_elf_create_ifunc_sections (dynobj, info)) if (!_bfd_elf_create_ifunc_sections (dynobj, info))
info->callbacks->einfo (_("%F: failed to create ifunc sections\n")); info->callbacks->einfo (_("%F: failed to create ifunc sections\n"));
plt_alignment = bfd_log2 (plt_layout->plt_entry_size); plt_alignment = bfd_log2 (htab->plt.plt_entry_size);
if (pltsec != NULL) if (pltsec != NULL)
{ {
@ -6450,7 +6261,7 @@ error_alignment:
| SEC_LOAD | SEC_LOAD
| SEC_READONLY); | SEC_READONLY);
unsigned int non_lazy_plt_alignment unsigned int non_lazy_plt_alignment
= bfd_log2 (non_lazy_plt_layout->plt_entry_size); = bfd_log2 (htab->non_lazy_plt->plt_entry_size);
sec = pltsec; sec = pltsec;
if (!bfd_set_section_alignment (sec->owner, sec, if (!bfd_set_section_alignment (sec->owner, sec,
@ -6567,7 +6378,6 @@ error_alignment:
#define bfd_elf32_mkobject elf_i386_mkobject #define bfd_elf32_mkobject elf_i386_mkobject
#define bfd_elf32_bfd_is_local_label_name elf_i386_is_local_label_name #define bfd_elf32_bfd_is_local_label_name elf_i386_is_local_label_name
#define bfd_elf32_bfd_link_hash_table_create elf_i386_link_hash_table_create
#define bfd_elf32_bfd_reloc_type_lookup elf_i386_reloc_type_lookup #define bfd_elf32_bfd_reloc_type_lookup elf_i386_reloc_type_lookup
#define bfd_elf32_bfd_reloc_name_lookup elf_i386_reloc_name_lookup #define bfd_elf32_bfd_reloc_name_lookup elf_i386_reloc_name_lookup
#define bfd_elf32_get_synthetic_symtab elf_i386_get_synthetic_symtab #define bfd_elf32_get_synthetic_symtab elf_i386_get_synthetic_symtab
@ -6919,17 +6729,20 @@ static const bfd_byte elf_i386_nacl_eh_frame_plt[] =
DW_CFA_nop, DW_CFA_nop DW_CFA_nop, DW_CFA_nop
}; };
static const struct elf_i386_lazy_plt_layout elf_i386_nacl_plt = static const struct elf_x86_lazy_plt_layout elf_i386_nacl_plt =
{ {
elf_i386_nacl_plt0_entry, /* plt0_entry */ elf_i386_nacl_plt0_entry, /* plt0_entry */
sizeof (elf_i386_nacl_plt0_entry), /* plt0_entry_size */ sizeof (elf_i386_nacl_plt0_entry), /* plt0_entry_size */
2, /* plt0_got1_offset */
8, /* plt0_got2_offset */
elf_i386_nacl_plt_entry, /* plt_entry */ elf_i386_nacl_plt_entry, /* plt_entry */
NACL_PLT_ENTRY_SIZE, /* plt_entry_size */ NACL_PLT_ENTRY_SIZE, /* plt_entry_size */
2, /* plt0_got1_offset */
8, /* plt0_got2_offset */
0, /* plt0_got2_insn_end */
2, /* plt_got_offset */ 2, /* plt_got_offset */
33, /* plt_reloc_offset */ 33, /* plt_reloc_offset */
38, /* plt_plt_offset */ 38, /* plt_plt_offset */
0, /* plt_got_insn_size */
0, /* plt_plt_insn_end */
32, /* plt_lazy_offset */ 32, /* plt_lazy_offset */
elf_i386_nacl_pic_plt0_entry, /* pic_plt0_entry */ elf_i386_nacl_pic_plt0_entry, /* pic_plt0_entry */
elf_i386_nacl_pic_plt_entry, /* pic_plt_entry */ elf_i386_nacl_pic_plt_entry, /* pic_plt_entry */

View File

@ -40,9 +40,6 @@
relocation type. We also use ELF_ST_TYPE instead of ELF64_ST_TYPE relocation type. We also use ELF_ST_TYPE instead of ELF64_ST_TYPE
since they are the same. */ since they are the same. */
#define ABI_64_P(abfd) \
(get_elf_backend_data (abfd)->s->elfclass == ELFCLASS64)
/* The relocation "howto" table. Order of fields: /* The relocation "howto" table. Order of fields:
type, rightshift, size, bitsize, pc_relative, bitpos, complain_on_overflow, type, rightshift, size, bitsize, pc_relative, bitpos, complain_on_overflow,
special_function, name, partial_inplace, src_mask, dst_mask, pcrel_offset. */ special_function, name, partial_inplace, src_mask, dst_mask, pcrel_offset. */
@ -521,12 +518,6 @@ elf_x86_64_write_core_note (bfd *abfd, char *buf, int *bufsiz,
/* Functions for the x86-64 ELF linker. */ /* Functions for the x86-64 ELF linker. */
/* The name of the dynamic interpreter. This is put in the .interp
section. */
#define ELF64_DYNAMIC_INTERPRETER "/lib/ld64.so.1"
#define ELF32_DYNAMIC_INTERPRETER "/lib/ldx32.so.1"
/* The size in bytes of an entry in the global offset table. */ /* The size in bytes of an entry in the global offset table. */
#define GOT_ENTRY_SIZE 8 #define GOT_ENTRY_SIZE 8
@ -823,77 +814,6 @@ static const bfd_byte elf_x86_64_eh_frame_non_lazy_plt[] =
DW_CFA_nop, DW_CFA_nop, DW_CFA_nop DW_CFA_nop, DW_CFA_nop, DW_CFA_nop
}; };
struct elf_x86_64_lazy_plt_layout
{
/* Templates for the initial PLT entry and for subsequent entries. */
const bfd_byte *plt0_entry;
const bfd_byte *plt_entry;
unsigned int plt_entry_size; /* Size of each PLT entry. */
/* Offsets into plt0_entry that are to be replaced with GOT[1] and GOT[2]. */
unsigned int plt0_got1_offset;
unsigned int plt0_got2_offset;
/* Offset of the end of the PC-relative instruction containing
plt0_got2_offset. */
unsigned int plt0_got2_insn_end;
/* Offsets into plt_entry that are to be replaced with... */
unsigned int plt_got_offset; /* ... address of this symbol in .got. */
unsigned int plt_reloc_offset; /* ... offset into relocation table. */
unsigned int plt_plt_offset; /* ... offset to start of .plt. */
/* Length of the PC-relative instruction containing plt_got_offset. */
unsigned int plt_got_insn_size;
/* Offset of the end of the PC-relative jump to plt0_entry. */
unsigned int plt_plt_insn_end;
/* Offset into plt_entry where the initial value of the GOT entry points. */
unsigned int plt_lazy_offset;
/* .eh_frame covering the lazy .plt section. */
const bfd_byte *eh_frame_plt;
unsigned int eh_frame_plt_size;
};
struct elf_x86_64_non_lazy_plt_layout
{
/* Template for the lazy PLT entries. */
const bfd_byte *plt_entry;
unsigned int plt_entry_size; /* Size of each PLT entry. */
/* Offsets into plt_entry that are to be replaced with... */
unsigned int plt_got_offset; /* ... address of this symbol in .got. */
/* Length of the PC-relative instruction containing plt_got_offset. */
unsigned int plt_got_insn_size;
/* .eh_frame covering the non-lazy .plt section. */
const bfd_byte *eh_frame_plt;
unsigned int eh_frame_plt_size;
};
struct elf_x86_64_plt_layout
{
/* Template for the PLT entries. */
const bfd_byte *plt_entry;
unsigned int plt_entry_size; /* Size of each PLT entry. */
/* 1 has PLT0. */
unsigned int has_plt0;
/* Offsets into plt_entry that are to be replaced with... */
unsigned int plt_got_offset; /* ... address of this symbol in .got. */
/* Length of the PC-relative instruction containing plt_got_offset. */
unsigned int plt_got_insn_size;
/* .eh_frame covering the .plt section. */
const bfd_byte *eh_frame_plt;
unsigned int eh_frame_plt_size;
};
/* Architecture-specific backend data for x86-64. */ /* Architecture-specific backend data for x86-64. */
struct elf_x86_64_backend_data struct elf_x86_64_backend_data
@ -913,9 +833,10 @@ struct elf_x86_64_backend_data
get_elf_x86_64_arch_data (get_elf_backend_data (abfd)) get_elf_x86_64_arch_data (get_elf_backend_data (abfd))
/* These are the standard parameters. */ /* These are the standard parameters. */
static const struct elf_x86_64_lazy_plt_layout elf_x86_64_lazy_plt = static const struct elf_x86_lazy_plt_layout elf_x86_64_lazy_plt =
{ {
elf_x86_64_lazy_plt0_entry, /* plt0_entry */ elf_x86_64_lazy_plt0_entry, /* plt0_entry */
LAZY_PLT_ENTRY_SIZE, /* plt0_entry_size */
elf_x86_64_lazy_plt_entry, /* plt_entry */ elf_x86_64_lazy_plt_entry, /* plt_entry */
LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
2, /* plt0_got1_offset */ 2, /* plt0_got1_offset */
@ -927,13 +848,16 @@ static const struct elf_x86_64_lazy_plt_layout elf_x86_64_lazy_plt =
6, /* plt_got_insn_size */ 6, /* plt_got_insn_size */
LAZY_PLT_ENTRY_SIZE, /* plt_plt_insn_end */ LAZY_PLT_ENTRY_SIZE, /* plt_plt_insn_end */
6, /* plt_lazy_offset */ 6, /* plt_lazy_offset */
NULL, /* pic_plt0_entry */
NULL, /* pic_plt_entry */
elf_x86_64_eh_frame_lazy_plt, /* eh_frame_plt */ elf_x86_64_eh_frame_lazy_plt, /* eh_frame_plt */
sizeof (elf_x86_64_eh_frame_lazy_plt) /* eh_frame_plt_size */ sizeof (elf_x86_64_eh_frame_lazy_plt) /* eh_frame_plt_size */
}; };
static const struct elf_x86_64_non_lazy_plt_layout elf_x86_64_non_lazy_plt = static const struct elf_x86_non_lazy_plt_layout elf_x86_64_non_lazy_plt =
{ {
elf_x86_64_non_lazy_plt_entry, /* plt_entry */ elf_x86_64_non_lazy_plt_entry, /* plt_entry */
NULL, /* pic_plt_entry */
NON_LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ NON_LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
2, /* plt_got_offset */ 2, /* plt_got_offset */
6, /* plt_got_insn_size */ 6, /* plt_got_insn_size */
@ -941,9 +865,10 @@ static const struct elf_x86_64_non_lazy_plt_layout elf_x86_64_non_lazy_plt =
sizeof (elf_x86_64_eh_frame_non_lazy_plt) /* eh_frame_plt_size */ sizeof (elf_x86_64_eh_frame_non_lazy_plt) /* eh_frame_plt_size */
}; };
static const struct elf_x86_64_lazy_plt_layout elf_x86_64_lazy_bnd_plt = static const struct elf_x86_lazy_plt_layout elf_x86_64_lazy_bnd_plt =
{ {
elf_x86_64_lazy_bnd_plt0_entry, /* plt0_entry */ elf_x86_64_lazy_bnd_plt0_entry, /* plt0_entry */
LAZY_PLT_ENTRY_SIZE, /* plt0_entry_size */
elf_x86_64_lazy_bnd_plt_entry, /* plt_entry */ elf_x86_64_lazy_bnd_plt_entry, /* plt_entry */
LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
2, /* plt0_got1_offset */ 2, /* plt0_got1_offset */
@ -955,13 +880,16 @@ static const struct elf_x86_64_lazy_plt_layout elf_x86_64_lazy_bnd_plt =
1+6, /* plt_got_insn_size */ 1+6, /* plt_got_insn_size */
11, /* plt_plt_insn_end */ 11, /* plt_plt_insn_end */
0, /* plt_lazy_offset */ 0, /* plt_lazy_offset */
NULL, /* pic_plt0_entry */
NULL, /* pic_plt_entry */
elf_x86_64_eh_frame_lazy_bnd_plt, /* eh_frame_plt */ elf_x86_64_eh_frame_lazy_bnd_plt, /* eh_frame_plt */
sizeof (elf_x86_64_eh_frame_lazy_bnd_plt) /* eh_frame_plt_size */ sizeof (elf_x86_64_eh_frame_lazy_bnd_plt) /* eh_frame_plt_size */
}; };
static const struct elf_x86_64_non_lazy_plt_layout elf_x86_64_non_lazy_bnd_plt = static const struct elf_x86_non_lazy_plt_layout elf_x86_64_non_lazy_bnd_plt =
{ {
elf_x86_64_non_lazy_bnd_plt_entry, /* plt_entry */ elf_x86_64_non_lazy_bnd_plt_entry, /* plt_entry */
NULL, /* pic_plt_entry */
NON_LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ NON_LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
1+2, /* plt_got_offset */ 1+2, /* plt_got_offset */
1+6, /* plt_got_insn_size */ 1+6, /* plt_got_insn_size */
@ -969,9 +897,10 @@ static const struct elf_x86_64_non_lazy_plt_layout elf_x86_64_non_lazy_bnd_plt =
sizeof (elf_x86_64_eh_frame_non_lazy_plt) /* eh_frame_plt_size */ sizeof (elf_x86_64_eh_frame_non_lazy_plt) /* eh_frame_plt_size */
}; };
static const struct elf_x86_64_lazy_plt_layout elf_x86_64_lazy_ibt_plt = static const struct elf_x86_lazy_plt_layout elf_x86_64_lazy_ibt_plt =
{ {
elf_x86_64_lazy_bnd_plt0_entry, /* plt0_entry */ elf_x86_64_lazy_bnd_plt0_entry, /* plt0_entry */
LAZY_PLT_ENTRY_SIZE, /* plt0_entry_size */
elf_x86_64_lazy_ibt_plt_entry, /* plt_entry */ elf_x86_64_lazy_ibt_plt_entry, /* plt_entry */
LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
2, /* plt0_got1_offset */ 2, /* plt0_got1_offset */
@ -983,13 +912,16 @@ static const struct elf_x86_64_lazy_plt_layout elf_x86_64_lazy_ibt_plt =
4+1+6, /* plt_got_insn_size */ 4+1+6, /* plt_got_insn_size */
4+1+5+5, /* plt_plt_insn_end */ 4+1+5+5, /* plt_plt_insn_end */
0, /* plt_lazy_offset */ 0, /* plt_lazy_offset */
NULL, /* pic_plt0_entry */
NULL, /* pic_plt_entry */
elf_x86_64_eh_frame_lazy_ibt_plt, /* eh_frame_plt */ elf_x86_64_eh_frame_lazy_ibt_plt, /* eh_frame_plt */
sizeof (elf_x86_64_eh_frame_lazy_ibt_plt) /* eh_frame_plt_size */ sizeof (elf_x86_64_eh_frame_lazy_ibt_plt) /* eh_frame_plt_size */
}; };
static const struct elf_x86_64_lazy_plt_layout elf_x32_lazy_ibt_plt = static const struct elf_x86_lazy_plt_layout elf_x32_lazy_ibt_plt =
{ {
elf_x86_64_lazy_plt0_entry, /* plt0_entry */ elf_x86_64_lazy_plt0_entry, /* plt0_entry */
LAZY_PLT_ENTRY_SIZE, /* plt0_entry_size */
elf_x32_lazy_ibt_plt_entry, /* plt_entry */ elf_x32_lazy_ibt_plt_entry, /* plt_entry */
LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
2, /* plt0_got1_offset */ 2, /* plt0_got1_offset */
@ -1001,13 +933,16 @@ static const struct elf_x86_64_lazy_plt_layout elf_x32_lazy_ibt_plt =
4+6, /* plt_got_insn_size */ 4+6, /* plt_got_insn_size */
4+5+5, /* plt_plt_insn_end */ 4+5+5, /* plt_plt_insn_end */
0, /* plt_lazy_offset */ 0, /* plt_lazy_offset */
NULL, /* pic_plt0_entry */
NULL, /* pic_plt_entry */
elf_x32_eh_frame_lazy_ibt_plt, /* eh_frame_plt */ elf_x32_eh_frame_lazy_ibt_plt, /* eh_frame_plt */
sizeof (elf_x32_eh_frame_lazy_ibt_plt) /* eh_frame_plt_size */ sizeof (elf_x32_eh_frame_lazy_ibt_plt) /* eh_frame_plt_size */
}; };
static const struct elf_x86_64_non_lazy_plt_layout elf_x86_64_non_lazy_ibt_plt = static const struct elf_x86_non_lazy_plt_layout elf_x86_64_non_lazy_ibt_plt =
{ {
elf_x86_64_non_lazy_ibt_plt_entry, /* plt_entry */ elf_x86_64_non_lazy_ibt_plt_entry, /* plt_entry */
NULL, /* pic_plt_entry */
LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
4+1+2, /* plt_got_offset */ 4+1+2, /* plt_got_offset */
4+1+6, /* plt_got_insn_size */ 4+1+6, /* plt_got_insn_size */
@ -1015,9 +950,10 @@ static const struct elf_x86_64_non_lazy_plt_layout elf_x86_64_non_lazy_ibt_plt =
sizeof (elf_x86_64_eh_frame_non_lazy_plt) /* eh_frame_plt_size */ sizeof (elf_x86_64_eh_frame_non_lazy_plt) /* eh_frame_plt_size */
}; };
static const struct elf_x86_64_non_lazy_plt_layout elf_x32_non_lazy_ibt_plt = static const struct elf_x86_non_lazy_plt_layout elf_x32_non_lazy_ibt_plt =
{ {
elf_x32_non_lazy_ibt_plt_entry, /* plt_entry */ elf_x32_non_lazy_ibt_plt_entry, /* plt_entry */
NULL, /* pic_plt_entry */
LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
4+2, /* plt_got_offset */ 4+2, /* plt_got_offset */
4+6, /* plt_got_insn_size */ 4+6, /* plt_got_insn_size */
@ -1056,88 +992,9 @@ elf_x86_64_mkobject (bfd *abfd)
X86_64_ELF_DATA); X86_64_ELF_DATA);
} }
/* x86-64 ELF linker hash table. */
struct elf_x86_64_link_hash_table
{
struct elf_x86_link_hash_table x86;
/* Parameters describing PLT generation, lazy or non-lazy. */
struct elf_x86_64_plt_layout plt;
/* Parameters describing lazy PLT generation. */
const struct elf_x86_64_lazy_plt_layout *lazy_plt;
/* Parameters describing non-lazy PLT generation. */
const struct elf_x86_64_non_lazy_plt_layout *non_lazy_plt;
};
#define elf_x86_64_plt(htab) \
((struct elf_x86_64_link_hash_table *) (htab))->plt
#define elf_x86_64_lazy_plt(htab) \
((struct elf_x86_64_link_hash_table *) (htab))->lazy_plt
#define elf_x86_64_non_lazy_plt(htab) \
((struct elf_x86_64_link_hash_table *) (htab))->non_lazy_plt
#define elf_x86_64_compute_jump_table_size(htab) \ #define elf_x86_64_compute_jump_table_size(htab) \
((htab)->elf.srelplt->reloc_count * GOT_ENTRY_SIZE) ((htab)->elf.srelplt->reloc_count * GOT_ENTRY_SIZE)
/* Create an X86-64 ELF linker hash table. */
static struct bfd_link_hash_table *
elf_x86_64_link_hash_table_create (bfd *abfd)
{
struct elf_x86_link_hash_table *ret;
bfd_size_type amt = sizeof (struct elf_x86_64_link_hash_table);
ret = (struct elf_x86_link_hash_table *) bfd_zmalloc (amt);
if (ret == NULL)
return NULL;
if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd,
_bfd_x86_elf_link_hash_newfunc,
sizeof (struct elf_x86_link_hash_entry),
X86_64_ELF_DATA))
{
free (ret);
return NULL;
}
if (ABI_64_P (abfd))
{
ret->r_info = elf64_r_info;
ret->r_sym = elf64_r_sym;
ret->pointer_r_type = R_X86_64_64;
ret->dynamic_interpreter = ELF64_DYNAMIC_INTERPRETER;
ret->dynamic_interpreter_size = sizeof ELF64_DYNAMIC_INTERPRETER;
}
else
{
ret->r_info = elf32_r_info;
ret->r_sym = elf32_r_sym;
ret->pointer_r_type = R_X86_64_32;
ret->dynamic_interpreter = ELF32_DYNAMIC_INTERPRETER;
ret->dynamic_interpreter_size = sizeof ELF32_DYNAMIC_INTERPRETER;
}
ret->tls_get_addr = "__tls_get_addr";
ret->loc_hash_table = htab_try_create (1024,
_bfd_x86_elf_local_htab_hash,
_bfd_x86_elf_local_htab_eq,
NULL);
ret->loc_hash_memory = objalloc_create ();
if (!ret->loc_hash_table || !ret->loc_hash_memory)
{
_bfd_x86_elf_link_hash_table_free (abfd);
return NULL;
}
ret->elf.root.hash_table_free = _bfd_x86_elf_link_hash_table_free;
return &ret->elf.root;
}
static bfd_boolean static bfd_boolean
elf64_x86_64_elf_object_p (bfd *abfd) elf64_x86_64_elf_object_p (bfd *abfd)
{ {
@ -2791,8 +2648,6 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
const struct elf_backend_data *bed; const struct elf_backend_data *bed;
unsigned int plt_entry_size; unsigned int plt_entry_size;
bfd_boolean resolved_to_zero; bfd_boolean resolved_to_zero;
const struct elf_x86_64_plt_layout *plt_layout;
const struct elf_x86_64_non_lazy_plt_layout *non_lazy_plt_layout;
if (h->root.type == bfd_link_hash_indirect) if (h->root.type == bfd_link_hash_indirect)
return TRUE; return TRUE;
@ -2805,9 +2660,7 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
return FALSE; return FALSE;
bed = get_elf_backend_data (info->output_bfd); bed = get_elf_backend_data (info->output_bfd);
plt_layout = &elf_x86_64_plt (htab); plt_entry_size = htab->plt.plt_entry_size;
non_lazy_plt_layout = elf_x86_64_non_lazy_plt (htab);
plt_entry_size = plt_layout->plt_entry_size;
resolved_to_zero = UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, resolved_to_zero = UNDEFINED_WEAK_RESOLVED_TO_ZERO (info,
X86_64_ELF_DATA, X86_64_ELF_DATA,
@ -2846,7 +2699,7 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
&eh->dyn_relocs, &eh->dyn_relocs,
&htab->readonly_dynrelocs_against_ifunc, &htab->readonly_dynrelocs_against_ifunc,
plt_entry_size, plt_entry_size,
(plt_layout->has_plt0 (htab->plt.has_plt0
* plt_entry_size), * plt_entry_size),
GOT_ENTRY_SIZE, TRUE)) GOT_ENTRY_SIZE, TRUE))
{ {
@ -2857,7 +2710,7 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
eh->plt_second.offset = s->size; eh->plt_second.offset = s->size;
/* Make room for this entry in the second PLT section. */ /* Make room for this entry in the second PLT section. */
s->size += non_lazy_plt_layout->plt_entry_size; s->size += htab->non_lazy_plt->plt_entry_size;
} }
return TRUE; return TRUE;
@ -2899,7 +2752,7 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
first entry. The .plt section is used by prelink to undo first entry. The .plt section is used by prelink to undo
prelinking for dynamic relocations. */ prelinking for dynamic relocations. */
if (s->size == 0) if (s->size == 0)
s->size = plt_layout->has_plt0 * plt_entry_size; s->size = htab->plt.has_plt0 * plt_entry_size;
if (use_plt_got) if (use_plt_got)
eh->plt_got.offset = got_s->size; eh->plt_got.offset = got_s->size;
@ -2944,12 +2797,12 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
/* Make room for this entry. */ /* Make room for this entry. */
if (use_plt_got) if (use_plt_got)
got_s->size += non_lazy_plt_layout->plt_entry_size; got_s->size += htab->non_lazy_plt->plt_entry_size;
else else
{ {
s->size += plt_entry_size; s->size += plt_entry_size;
if (second_s) if (second_s)
second_s->size += non_lazy_plt_layout->plt_entry_size; second_s->size += htab->non_lazy_plt->plt_entry_size;
/* We also need to make an entry in the .got.plt section, /* We also need to make an entry in the .got.plt section,
which will be placed in the .got section by the linker which will be placed in the .got section by the linker
@ -3332,8 +3185,6 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
bfd_boolean relocs; bfd_boolean relocs;
bfd *ibfd; bfd *ibfd;
const struct elf_backend_data *bed; const struct elf_backend_data *bed;
const struct elf_x86_64_plt_layout *plt_layout;
const struct elf_x86_64_non_lazy_plt_layout *non_lazy_plt_layout;
htab = elf_x86_hash_table (info, X86_64_ELF_DATA); htab = elf_x86_hash_table (info, X86_64_ELF_DATA);
if (htab == NULL) if (htab == NULL)
@ -3344,9 +3195,6 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
if (dynobj == NULL) if (dynobj == NULL)
abort (); abort ();
plt_layout = &elf_x86_64_plt (htab);
non_lazy_plt_layout = elf_x86_64_non_lazy_plt (htab);
/* Set up .got offsets for local syms, and space for local dynamic /* Set up .got offsets for local syms, and space for local dynamic
relocs. */ relocs. */
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
@ -3503,9 +3351,9 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
/* Reserve room for the initial entry. /* Reserve room for the initial entry.
FIXME: we could probably do away with it in this case. */ FIXME: we could probably do away with it in this case. */
if (htab->elf.splt->size == 0) if (htab->elf.splt->size == 0)
htab->elf.splt->size = plt_layout->plt_entry_size; htab->elf.splt->size = htab->plt.plt_entry_size;
htab->tlsdesc_plt = htab->elf.splt->size; htab->tlsdesc_plt = htab->elf.splt->size;
htab->elf.splt->size += plt_layout->plt_entry_size; htab->elf.splt->size += htab->plt.plt_entry_size;
} }
} }
@ -3534,14 +3382,14 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
&& htab->elf.splt != NULL && htab->elf.splt != NULL
&& htab->elf.splt->size != 0 && htab->elf.splt->size != 0
&& !bfd_is_abs_section (htab->elf.splt->output_section)) && !bfd_is_abs_section (htab->elf.splt->output_section))
htab->plt_eh_frame->size = plt_layout->eh_frame_plt_size; htab->plt_eh_frame->size = htab->plt.eh_frame_plt_size;
if (htab->plt_got_eh_frame != NULL if (htab->plt_got_eh_frame != NULL
&& htab->plt_got != NULL && htab->plt_got != NULL
&& htab->plt_got->size != 0 && htab->plt_got->size != 0
&& !bfd_is_abs_section (htab->plt_got->output_section)) && !bfd_is_abs_section (htab->plt_got->output_section))
htab->plt_got_eh_frame->size htab->plt_got_eh_frame->size
= non_lazy_plt_layout->eh_frame_plt_size; = htab->non_lazy_plt->eh_frame_plt_size;
/* Unwind info for the second PLT and .plt.got sections are /* Unwind info for the second PLT and .plt.got sections are
identical. */ identical. */
@ -3550,7 +3398,7 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
&& htab->plt_second->size != 0 && htab->plt_second->size != 0
&& !bfd_is_abs_section (htab->plt_second->output_section)) && !bfd_is_abs_section (htab->plt_second->output_section))
htab->plt_second_eh_frame->size htab->plt_second_eh_frame->size
= non_lazy_plt_layout->eh_frame_plt_size; = htab->non_lazy_plt->eh_frame_plt_size;
} }
/* We now have determined the sizes of the various dynamic sections. /* We now have determined the sizes of the various dynamic sections.
@ -3626,7 +3474,7 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
&& htab->plt_eh_frame->contents != NULL) && htab->plt_eh_frame->contents != NULL)
{ {
memcpy (htab->plt_eh_frame->contents, memcpy (htab->plt_eh_frame->contents,
plt_layout->eh_frame_plt, htab->plt_eh_frame->size); htab->plt.eh_frame_plt, htab->plt_eh_frame->size);
bfd_put_32 (dynobj, htab->elf.splt->size, bfd_put_32 (dynobj, htab->elf.splt->size,
htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET); htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET);
} }
@ -3635,7 +3483,7 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
&& htab->plt_got_eh_frame->contents != NULL) && htab->plt_got_eh_frame->contents != NULL)
{ {
memcpy (htab->plt_got_eh_frame->contents, memcpy (htab->plt_got_eh_frame->contents,
non_lazy_plt_layout->eh_frame_plt, htab->non_lazy_plt->eh_frame_plt,
htab->plt_got_eh_frame->size); htab->plt_got_eh_frame->size);
bfd_put_32 (dynobj, htab->plt_got->size, bfd_put_32 (dynobj, htab->plt_got->size,
(htab->plt_got_eh_frame->contents (htab->plt_got_eh_frame->contents
@ -3646,7 +3494,7 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
&& htab->plt_second_eh_frame->contents != NULL) && htab->plt_second_eh_frame->contents != NULL)
{ {
memcpy (htab->plt_second_eh_frame->contents, memcpy (htab->plt_second_eh_frame->contents,
non_lazy_plt_layout->eh_frame_plt, htab->non_lazy_plt->eh_frame_plt,
htab->plt_second_eh_frame->size); htab->plt_second_eh_frame->size);
bfd_put_32 (dynobj, htab->plt_second->size, bfd_put_32 (dynobj, htab->plt_second->size,
(htab->plt_second_eh_frame->contents (htab->plt_second_eh_frame->contents
@ -3792,7 +3640,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
htab = elf_x86_hash_table (info, X86_64_ELF_DATA); htab = elf_x86_hash_table (info, X86_64_ELF_DATA);
if (htab == NULL) if (htab == NULL)
return FALSE; return FALSE;
plt_entry_size = elf_x86_64_plt (htab).plt_entry_size; plt_entry_size = htab->plt.plt_entry_size;
symtab_hdr = &elf_symtab_hdr (input_bfd); symtab_hdr = &elf_symtab_hdr (input_bfd);
sym_hashes = elf_sym_hashes (input_bfd); sym_hashes = elf_sym_hashes (input_bfd);
local_got_offsets = elf_local_got_offsets (input_bfd); local_got_offsets = elf_local_got_offsets (input_bfd);
@ -3970,7 +3818,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
if (htab->elf.splt != NULL) if (htab->elf.splt != NULL)
{ {
plt_index = (h->plt.offset / plt_entry_size plt_index = (h->plt.offset / plt_entry_size
- elf_x86_64_plt (htab).has_plt0); - htab->plt.has_plt0);
off = (plt_index + 3) * GOT_ENTRY_SIZE; off = (plt_index + 3) * GOT_ENTRY_SIZE;
base_got = htab->elf.sgotplt; base_got = htab->elf.sgotplt;
} }
@ -4201,7 +4049,7 @@ do_ifunc_pointer:
finish_dynamic_symbol would use that as offset into finish_dynamic_symbol would use that as offset into
.got. */ .got. */
bfd_vma plt_index = (h->plt.offset / plt_entry_size bfd_vma plt_index = (h->plt.offset / plt_entry_size
- elf_x86_64_plt (htab).has_plt0); - htab->plt.has_plt0);
off = (plt_index + 3) * GOT_ENTRY_SIZE; off = (plt_index + 3) * GOT_ENTRY_SIZE;
base_got = htab->elf.sgotplt; base_got = htab->elf.sgotplt;
} }
@ -5356,9 +5204,6 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
bfd_boolean use_plt_second; bfd_boolean use_plt_second;
struct elf_x86_link_hash_entry *eh; struct elf_x86_link_hash_entry *eh;
bfd_boolean local_undefweak; bfd_boolean local_undefweak;
const struct elf_x86_64_plt_layout *plt_layout;
const struct elf_x86_64_lazy_plt_layout *lazy_plt_layout;
const struct elf_x86_64_non_lazy_plt_layout *non_lazy_plt_layout;
htab = elf_x86_hash_table (info, X86_64_ELF_DATA); htab = elf_x86_hash_table (info, X86_64_ELF_DATA);
if (htab == NULL) if (htab == NULL)
@ -5371,10 +5216,6 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
if (eh->no_finish_dynamic_symbol) if (eh->no_finish_dynamic_symbol)
abort (); abort ();
plt_layout = &elf_x86_64_plt (htab);
lazy_plt_layout = elf_x86_64_lazy_plt (htab);
non_lazy_plt_layout = elf_x86_64_non_lazy_plt (htab);
/* We keep PLT/GOT entries without dynamic PLT/GOT relocations for /* We keep PLT/GOT entries without dynamic PLT/GOT relocations for
resolved undefined weak symbols in executable so that their resolved undefined weak symbols in executable so that their
references have value 0 at run-time. */ references have value 0 at run-time. */
@ -5433,24 +5274,24 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
if (plt == htab->elf.splt) if (plt == htab->elf.splt)
{ {
got_offset = (h->plt.offset / plt_layout->plt_entry_size got_offset = (h->plt.offset / htab->plt.plt_entry_size
- plt_layout->has_plt0); - htab->plt.has_plt0);
got_offset = (got_offset + 3) * GOT_ENTRY_SIZE; got_offset = (got_offset + 3) * GOT_ENTRY_SIZE;
} }
else else
{ {
got_offset = h->plt.offset / plt_layout->plt_entry_size; got_offset = h->plt.offset / htab->plt.plt_entry_size;
got_offset = got_offset * GOT_ENTRY_SIZE; got_offset = got_offset * GOT_ENTRY_SIZE;
} }
/* Fill in the entry in the procedure linkage table. */ /* Fill in the entry in the procedure linkage table. */
memcpy (plt->contents + h->plt.offset, plt_layout->plt_entry, memcpy (plt->contents + h->plt.offset, htab->plt.plt_entry,
plt_layout->plt_entry_size); htab->plt.plt_entry_size);
if (use_plt_second) if (use_plt_second)
{ {
memcpy (htab->plt_second->contents + eh->plt_second.offset, memcpy (htab->plt_second->contents + eh->plt_second.offset,
non_lazy_plt_layout->plt_entry, htab->non_lazy_plt->plt_entry,
non_lazy_plt_layout->plt_entry_size); htab->non_lazy_plt->plt_entry_size);
resolved_plt = htab->plt_second; resolved_plt = htab->plt_second;
plt_offset = eh->plt_second.offset; plt_offset = eh->plt_second.offset;
@ -5471,7 +5312,7 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
- resolved_plt->output_section->vma - resolved_plt->output_section->vma
- resolved_plt->output_offset - resolved_plt->output_offset
- plt_offset - plt_offset
- plt_layout->plt_got_insn_size); - htab->plt.plt_got_insn_size);
/* Check PC-relative offset overflow in PLT entry. */ /* Check PC-relative offset overflow in PLT entry. */
if ((plt_got_pcrel_offset + 0x80000000) > 0xffffffff) if ((plt_got_pcrel_offset + 0x80000000) > 0xffffffff)
@ -5481,7 +5322,7 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
bfd_put_32 (output_bfd, plt_got_pcrel_offset, bfd_put_32 (output_bfd, plt_got_pcrel_offset,
(resolved_plt->contents + plt_offset (resolved_plt->contents + plt_offset
+ plt_layout->plt_got_offset)); + htab->plt.plt_got_offset));
/* Fill in the entry in the global offset table, initially this /* Fill in the entry in the global offset table, initially this
points to the second part of the PLT entry. Leave the entry points to the second part of the PLT entry. Leave the entry
@ -5489,11 +5330,11 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
against undefined weak symbol in PIE. */ against undefined weak symbol in PIE. */
if (!local_undefweak) if (!local_undefweak)
{ {
if (plt_layout->has_plt0) if (htab->plt.has_plt0)
bfd_put_64 (output_bfd, (plt->output_section->vma bfd_put_64 (output_bfd, (plt->output_section->vma
+ plt->output_offset + plt->output_offset
+ h->plt.offset + h->plt.offset
+ lazy_plt_layout->plt_lazy_offset), + htab->lazy_plt->plt_lazy_offset),
gotplt->contents + got_offset); gotplt->contents + got_offset);
/* Fill in the entry in the .rela.plt section. */ /* Fill in the entry in the .rela.plt section. */
@ -5528,15 +5369,15 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
/* Don't fill the second and third slots in PLT entry for /* Don't fill the second and third slots in PLT entry for
static executables nor without PLT0. */ static executables nor without PLT0. */
if (plt == htab->elf.splt && plt_layout->has_plt0) if (plt == htab->elf.splt && htab->plt.has_plt0)
{ {
bfd_vma plt0_offset bfd_vma plt0_offset
= h->plt.offset + lazy_plt_layout->plt_plt_insn_end; = h->plt.offset + htab->lazy_plt->plt_plt_insn_end;
/* Put relocation index. */ /* Put relocation index. */
bfd_put_32 (output_bfd, plt_index, bfd_put_32 (output_bfd, plt_index,
(plt->contents + h->plt.offset (plt->contents + h->plt.offset
+ lazy_plt_layout->plt_reloc_offset)); + htab->lazy_plt->plt_reloc_offset));
/* Put offset for jmp .PLT0 and check for overflow. We don't /* Put offset for jmp .PLT0 and check for overflow. We don't
check relocation index for overflow since branch displacement check relocation index for overflow since branch displacement
@ -5547,7 +5388,7 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
output_bfd, h->root.root.string); output_bfd, h->root.root.string);
bfd_put_32 (output_bfd, - plt0_offset, bfd_put_32 (output_bfd, - plt0_offset,
(plt->contents + h->plt.offset (plt->contents + h->plt.offset
+ lazy_plt_layout->plt_plt_offset)); + htab->lazy_plt->plt_plt_offset));
} }
bed = get_elf_backend_data (output_bfd); bed = get_elf_backend_data (output_bfd);
@ -5578,8 +5419,8 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
/* Fill in the entry in the GOT procedure linkage table. */ /* Fill in the entry in the GOT procedure linkage table. */
plt_offset = eh->plt_got.offset; plt_offset = eh->plt_got.offset;
memcpy (plt->contents + plt_offset, memcpy (plt->contents + plt_offset,
non_lazy_plt_layout->plt_entry, htab->non_lazy_plt->plt_entry,
non_lazy_plt_layout->plt_entry_size); htab->non_lazy_plt->plt_entry_size);
/* Put offset the PC-relative instruction referring to the GOT /* Put offset the PC-relative instruction referring to the GOT
entry, subtracting the size of that instruction. */ entry, subtracting the size of that instruction. */
@ -5589,7 +5430,7 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
- plt->output_section->vma - plt->output_section->vma
- plt->output_offset - plt->output_offset
- plt_offset - plt_offset
- non_lazy_plt_layout->plt_got_insn_size); - htab->non_lazy_plt->plt_got_insn_size);
/* Check PC-relative offset overflow in GOT PLT entry. */ /* Check PC-relative offset overflow in GOT PLT entry. */
got_after_plt = got->output_section->vma > plt->output_section->vma; got_after_plt = got->output_section->vma > plt->output_section->vma;
@ -5601,7 +5442,7 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
bfd_put_32 (output_bfd, got_pcrel_offset, bfd_put_32 (output_bfd, got_pcrel_offset,
(plt->contents + plt_offset (plt->contents + plt_offset
+ non_lazy_plt_layout->plt_got_offset)); + htab->non_lazy_plt->plt_got_offset));
} }
if (!local_undefweak if (!local_undefweak
@ -5865,9 +5706,6 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
bfd_byte *dyncon, *dynconend; bfd_byte *dyncon, *dynconend;
const struct elf_backend_data *bed; const struct elf_backend_data *bed;
bfd_size_type sizeof_dyn; bfd_size_type sizeof_dyn;
const struct elf_x86_64_plt_layout *plt_layout;
const struct elf_x86_64_lazy_plt_layout *lazy_plt_layout;
const struct elf_x86_64_non_lazy_plt_layout *non_lazy_plt_layout;
if (sdyn == NULL || htab->elf.sgot == NULL) if (sdyn == NULL || htab->elf.sgot == NULL)
abort (); abort ();
@ -5918,22 +5756,18 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
(*bed->s->swap_dyn_out) (output_bfd, &dyn, dyncon); (*bed->s->swap_dyn_out) (output_bfd, &dyn, dyncon);
} }
plt_layout = &elf_x86_64_plt (htab);
lazy_plt_layout = elf_x86_64_lazy_plt (htab);
non_lazy_plt_layout = elf_x86_64_non_lazy_plt (htab);
if (htab->elf.splt && htab->elf.splt->size > 0) if (htab->elf.splt && htab->elf.splt->size > 0)
{ {
elf_section_data (htab->elf.splt->output_section) elf_section_data (htab->elf.splt->output_section)
->this_hdr.sh_entsize = plt_layout->plt_entry_size; ->this_hdr.sh_entsize = htab->plt.plt_entry_size;
if (plt_layout->has_plt0) if (htab->plt.has_plt0)
{ {
/* Fill in the special first entry in the procedure linkage /* Fill in the special first entry in the procedure linkage
table. */ table. */
memcpy (htab->elf.splt->contents, memcpy (htab->elf.splt->contents,
lazy_plt_layout->plt0_entry, htab->lazy_plt->plt0_entry,
lazy_plt_layout->plt_entry_size); htab->lazy_plt->plt0_entry_size);
/* Add offset for pushq GOT+8(%rip), since the instruction /* Add offset for pushq GOT+8(%rip), since the instruction
uses 6 bytes subtract this value. */ uses 6 bytes subtract this value. */
bfd_put_32 (output_bfd, bfd_put_32 (output_bfd,
@ -5944,7 +5778,7 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
- htab->elf.splt->output_offset - htab->elf.splt->output_offset
- 6), - 6),
(htab->elf.splt->contents (htab->elf.splt->contents
+ lazy_plt_layout->plt0_got1_offset)); + htab->lazy_plt->plt0_got1_offset));
/* Add offset for the PC-relative instruction accessing /* Add offset for the PC-relative instruction accessing
GOT+16, subtracting the offset to the end of that GOT+16, subtracting the offset to the end of that
instruction. */ instruction. */
@ -5954,9 +5788,9 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
+ 16 + 16
- htab->elf.splt->output_section->vma - htab->elf.splt->output_section->vma
- htab->elf.splt->output_offset - htab->elf.splt->output_offset
- lazy_plt_layout->plt0_got2_insn_end), - htab->lazy_plt->plt0_got2_insn_end),
(htab->elf.splt->contents (htab->elf.splt->contents
+ lazy_plt_layout->plt0_got2_offset)); + htab->lazy_plt->plt0_got2_offset));
if (htab->tlsdesc_plt) if (htab->tlsdesc_plt)
{ {
@ -5964,8 +5798,8 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
htab->elf.sgot->contents + htab->tlsdesc_got); htab->elf.sgot->contents + htab->tlsdesc_got);
memcpy (htab->elf.splt->contents + htab->tlsdesc_plt, memcpy (htab->elf.splt->contents + htab->tlsdesc_plt,
lazy_plt_layout->plt0_entry, htab->lazy_plt->plt0_entry,
lazy_plt_layout->plt_entry_size); htab->lazy_plt->plt0_entry_size);
/* Add offset for pushq GOT+8(%rip), since the /* Add offset for pushq GOT+8(%rip), since the
instruction uses 6 bytes subtract this value. */ instruction uses 6 bytes subtract this value. */
@ -5979,7 +5813,7 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
- 6), - 6),
(htab->elf.splt->contents (htab->elf.splt->contents
+ htab->tlsdesc_plt + htab->tlsdesc_plt
+ lazy_plt_layout->plt0_got1_offset)); + htab->lazy_plt->plt0_got1_offset));
/* Add offset for the PC-relative instruction accessing /* Add offset for the PC-relative instruction accessing
GOT+TDG, where TDG stands for htab->tlsdesc_got, GOT+TDG, where TDG stands for htab->tlsdesc_got,
subtracting the offset to the end of that subtracting the offset to the end of that
@ -5991,21 +5825,21 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
- htab->elf.splt->output_section->vma - htab->elf.splt->output_section->vma
- htab->elf.splt->output_offset - htab->elf.splt->output_offset
- htab->tlsdesc_plt - htab->tlsdesc_plt
- lazy_plt_layout->plt0_got2_insn_end), - htab->lazy_plt->plt0_got2_insn_end),
(htab->elf.splt->contents (htab->elf.splt->contents
+ htab->tlsdesc_plt + htab->tlsdesc_plt
+ lazy_plt_layout->plt0_got2_offset)); + htab->lazy_plt->plt0_got2_offset));
} }
} }
} }
if (htab->plt_got != NULL && htab->plt_got->size > 0) if (htab->plt_got != NULL && htab->plt_got->size > 0)
elf_section_data (htab->plt_got->output_section) elf_section_data (htab->plt_got->output_section)
->this_hdr.sh_entsize = non_lazy_plt_layout->plt_entry_size; ->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size;
if (htab->plt_second != NULL && htab->plt_second->size > 0) if (htab->plt_second != NULL && htab->plt_second->size > 0)
elf_section_data (htab->plt_second->output_section) elf_section_data (htab->plt_second->output_section)
->this_hdr.sh_entsize = non_lazy_plt_layout->plt_entry_size; ->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size;
} }
/* GOT is always created in setup_gnu_properties. But it may not be /* GOT is always created in setup_gnu_properties. But it may not be
@ -6182,7 +6016,7 @@ struct elf_x86_64_plt
}; };
/* Forward declaration. */ /* Forward declaration. */
static const struct elf_x86_64_lazy_plt_layout elf_x86_64_nacl_plt; static const struct elf_x86_lazy_plt_layout elf_x86_64_nacl_plt;
/* Similar to _bfd_elf_get_synthetic_symtab. Support PLTs with all /* Similar to _bfd_elf_get_synthetic_symtab. Support PLTs with all
dynamic relocations. */ dynamic relocations. */
@ -6202,12 +6036,12 @@ elf_x86_64_get_synthetic_symtab (bfd *abfd,
bfd_byte *plt_contents; bfd_byte *plt_contents;
long dynrelcount, relsize; long dynrelcount, relsize;
arelent **dynrelbuf, *p; arelent **dynrelbuf, *p;
const struct elf_x86_64_lazy_plt_layout *lazy_plt; const struct elf_x86_lazy_plt_layout *lazy_plt;
const struct elf_x86_64_non_lazy_plt_layout *non_lazy_plt; const struct elf_x86_non_lazy_plt_layout *non_lazy_plt;
const struct elf_x86_64_lazy_plt_layout *lazy_bnd_plt; const struct elf_x86_lazy_plt_layout *lazy_bnd_plt;
const struct elf_x86_64_non_lazy_plt_layout *non_lazy_bnd_plt; const struct elf_x86_non_lazy_plt_layout *non_lazy_bnd_plt;
const struct elf_x86_64_lazy_plt_layout *lazy_ibt_plt; const struct elf_x86_lazy_plt_layout *lazy_ibt_plt;
const struct elf_x86_64_non_lazy_plt_layout *non_lazy_ibt_plt; const struct elf_x86_non_lazy_plt_layout *non_lazy_ibt_plt;
asection *plt; asection *plt;
char *names; char *names;
enum elf_x86_64_plt_type plt_type; enum elf_x86_64_plt_type plt_type;
@ -6730,9 +6564,6 @@ elf_x86_64_link_setup_gnu_properties (struct bfd_link_info *info)
bfd *pbfd; bfd *pbfd;
bfd *ebfd = NULL; bfd *ebfd = NULL;
elf_property *prop; elf_property *prop;
struct elf_x86_64_plt_layout *plt_layout;
const struct elf_x86_64_lazy_plt_layout *lazy_plt_layout;
const struct elf_x86_64_non_lazy_plt_layout *non_lazy_plt_layout;
features = 0; features = 0;
if (info->ibt) if (info->ibt)
@ -6849,12 +6680,10 @@ error_alignment:
} }
} }
plt_layout = &elf_x86_64_plt (htab);
/* Even when lazy binding is disabled by "-z now", the PLT0 entry may /* Even when lazy binding is disabled by "-z now", the PLT0 entry may
still be used with LD_AUDIT or LD_PROFILE if PLT entry is used for still be used with LD_AUDIT or LD_PROFILE if PLT entry is used for
canonical function address. */ canonical function address. */
plt_layout->has_plt0 = 1; htab->plt.has_plt0 = 1;
if (get_elf_x86_64_backend_data (info->output_bfd)->os if (get_elf_x86_64_backend_data (info->output_bfd)->os
== is_normal) == is_normal)
@ -6863,79 +6692,71 @@ error_alignment:
{ {
if (ABI_64_P (dynobj)) if (ABI_64_P (dynobj))
{ {
elf_x86_64_lazy_plt (htab) htab->lazy_plt
= &elf_x86_64_lazy_ibt_plt; = &elf_x86_64_lazy_ibt_plt;
elf_x86_64_non_lazy_plt (htab) htab->non_lazy_plt
= &elf_x86_64_non_lazy_ibt_plt; = &elf_x86_64_non_lazy_ibt_plt;
} }
else else
{ {
elf_x86_64_lazy_plt (htab) htab->lazy_plt
= &elf_x32_lazy_ibt_plt; = &elf_x32_lazy_ibt_plt;
elf_x86_64_non_lazy_plt (htab) htab->non_lazy_plt
= &elf_x32_non_lazy_ibt_plt; = &elf_x32_non_lazy_ibt_plt;
} }
} }
else if (info->bndplt) else if (info->bndplt)
{ {
elf_x86_64_lazy_plt (htab) = &elf_x86_64_lazy_bnd_plt; htab->lazy_plt = &elf_x86_64_lazy_bnd_plt;
elf_x86_64_non_lazy_plt (htab) = &elf_x86_64_non_lazy_bnd_plt; htab->non_lazy_plt = &elf_x86_64_non_lazy_bnd_plt;
} }
else else
{ {
elf_x86_64_lazy_plt (htab) = &elf_x86_64_lazy_plt; htab->lazy_plt = &elf_x86_64_lazy_plt;
elf_x86_64_non_lazy_plt (htab) = &elf_x86_64_non_lazy_plt; htab->non_lazy_plt = &elf_x86_64_non_lazy_plt;
} }
normal_target = TRUE; normal_target = TRUE;
} }
else else
{ {
elf_x86_64_lazy_plt (htab) = &elf_x86_64_nacl_plt; htab->lazy_plt = &elf_x86_64_nacl_plt;
elf_x86_64_non_lazy_plt (htab) = NULL; htab->non_lazy_plt = NULL;
normal_target = FALSE; normal_target = FALSE;
} }
lazy_plt_layout = elf_x86_64_lazy_plt (htab);
non_lazy_plt_layout = elf_x86_64_non_lazy_plt (htab);
pltsec = htab->elf.splt; pltsec = htab->elf.splt;
/* If the non-lazy PLT is available, use it for all PLT entries if /* If the non-lazy PLT is available, use it for all PLT entries if
there are no PLT0 or no .plt section. */ there are no PLT0 or no .plt section. */
if (non_lazy_plt_layout != NULL if (htab->non_lazy_plt != NULL
&& (!plt_layout->has_plt0 || pltsec == NULL)) && (!htab->plt.has_plt0 || pltsec == NULL))
{ {
lazy_plt = FALSE; lazy_plt = FALSE;
plt_layout->plt_entry htab->plt.plt_entry = htab->non_lazy_plt->plt_entry;
= non_lazy_plt_layout->plt_entry; htab->plt.plt_entry_size = htab->non_lazy_plt->plt_entry_size;
plt_layout->plt_entry_size htab->plt.plt_got_offset = htab->non_lazy_plt->plt_got_offset;
= non_lazy_plt_layout->plt_entry_size; htab->plt.plt_got_insn_size
plt_layout->plt_got_offset = htab->non_lazy_plt->plt_got_insn_size;
= non_lazy_plt_layout->plt_got_offset; htab->plt.eh_frame_plt_size
plt_layout->plt_got_insn_size = htab->non_lazy_plt->eh_frame_plt_size;
= non_lazy_plt_layout->plt_got_insn_size; htab->plt.eh_frame_plt = htab->non_lazy_plt->eh_frame_plt;
plt_layout->eh_frame_plt_size
= non_lazy_plt_layout->eh_frame_plt_size;
plt_layout->eh_frame_plt
= non_lazy_plt_layout->eh_frame_plt;
} }
else else
{ {
lazy_plt = TRUE; lazy_plt = TRUE;
plt_layout->plt_entry htab->plt.plt_entry = htab->lazy_plt->plt_entry;
= lazy_plt_layout->plt_entry; htab->plt.plt_entry_size = htab->lazy_plt->plt_entry_size;
plt_layout->plt_entry_size htab->plt.plt_got_offset = htab->lazy_plt->plt_got_offset;
= lazy_plt_layout->plt_entry_size; htab->plt.plt_got_insn_size
plt_layout->plt_got_offset = htab->lazy_plt->plt_got_insn_size;
= lazy_plt_layout->plt_got_offset; htab->plt.eh_frame_plt_size
plt_layout->plt_got_insn_size = htab->lazy_plt->eh_frame_plt_size;
= lazy_plt_layout->plt_got_insn_size; htab->plt.eh_frame_plt = htab->lazy_plt->eh_frame_plt;
plt_layout->eh_frame_plt_size
= lazy_plt_layout->eh_frame_plt_size;
plt_layout->eh_frame_plt
= lazy_plt_layout->eh_frame_plt;
} }
/* This is unused for x86-64. */
htab->plt.plt0_entry = NULL;
/* Return if there are no normal input files. */ /* Return if there are no normal input files. */
if (dynobj == NULL) if (dynobj == NULL)
return pbfd; return pbfd;
@ -6963,7 +6784,7 @@ error_alignment:
if (!_bfd_elf_create_ifunc_sections (dynobj, info)) if (!_bfd_elf_create_ifunc_sections (dynobj, info))
info->callbacks->einfo (_("%F: failed to create ifunc sections\n")); info->callbacks->einfo (_("%F: failed to create ifunc sections\n"));
plt_alignment = bfd_log2 (plt_layout->plt_entry_size); plt_alignment = bfd_log2 (htab->plt.plt_entry_size);
if (pltsec != NULL) if (pltsec != NULL)
{ {
@ -6992,7 +6813,7 @@ error_alignment:
| SEC_LOAD | SEC_LOAD
| SEC_READONLY); | SEC_READONLY);
unsigned int non_lazy_plt_alignment unsigned int non_lazy_plt_alignment
= bfd_log2 (non_lazy_plt_layout->plt_entry_size); = bfd_log2 (htab->non_lazy_plt->plt_entry_size);
sec = pltsec; sec = pltsec;
if (!bfd_set_section_alignment (sec->owner, sec, if (!bfd_set_section_alignment (sec->owner, sec,
@ -7150,8 +6971,6 @@ elf_x86_64_special_sections[]=
#define elf_info_to_howto elf_x86_64_info_to_howto #define elf_info_to_howto elf_x86_64_info_to_howto
#define bfd_elf64_bfd_link_hash_table_create \
elf_x86_64_link_hash_table_create
#define bfd_elf64_bfd_reloc_type_lookup elf_x86_64_reloc_type_lookup #define bfd_elf64_bfd_reloc_type_lookup elf_x86_64_reloc_type_lookup
#define bfd_elf64_bfd_reloc_name_lookup \ #define bfd_elf64_bfd_reloc_name_lookup \
elf_x86_64_reloc_name_lookup elf_x86_64_reloc_name_lookup
@ -7401,9 +7220,10 @@ static const bfd_byte elf_x86_64_nacl_eh_frame_plt[] =
DW_CFA_nop, DW_CFA_nop DW_CFA_nop, DW_CFA_nop
}; };
static const struct elf_x86_64_lazy_plt_layout elf_x86_64_nacl_plt = static const struct elf_x86_lazy_plt_layout elf_x86_64_nacl_plt =
{ {
elf_x86_64_nacl_plt0_entry, /* plt0_entry */ elf_x86_64_nacl_plt0_entry, /* plt0_entry */
NACL_PLT_ENTRY_SIZE, /* plt0_entry_size */
elf_x86_64_nacl_plt_entry, /* plt_entry */ elf_x86_64_nacl_plt_entry, /* plt_entry */
NACL_PLT_ENTRY_SIZE, /* plt_entry_size */ NACL_PLT_ENTRY_SIZE, /* plt_entry_size */
2, /* plt0_got1_offset */ 2, /* plt0_got1_offset */
@ -7415,6 +7235,8 @@ static const struct elf_x86_64_lazy_plt_layout elf_x86_64_nacl_plt =
7, /* plt_got_insn_size */ 7, /* plt_got_insn_size */
42, /* plt_plt_insn_end */ 42, /* plt_plt_insn_end */
32, /* plt_lazy_offset */ 32, /* plt_lazy_offset */
NULL, /* pic_plt0_entry */
NULL, /* pic_plt_entry */
elf_x86_64_nacl_eh_frame_plt, /* eh_frame_plt */ elf_x86_64_nacl_eh_frame_plt, /* eh_frame_plt */
sizeof (elf_x86_64_nacl_eh_frame_plt) /* eh_frame_plt_size */ sizeof (elf_x86_64_nacl_eh_frame_plt) /* eh_frame_plt_size */
}; };
@ -7455,8 +7277,6 @@ elf32_x86_64_nacl_elf_object_p (bfd *abfd)
#undef elf32_bed #undef elf32_bed
#define elf32_bed elf32_x86_64_nacl_bed #define elf32_bed elf32_x86_64_nacl_bed
#define bfd_elf32_bfd_link_hash_table_create \
elf_x86_64_link_hash_table_create
#define bfd_elf32_bfd_reloc_type_lookup \ #define bfd_elf32_bfd_reloc_type_lookup \
elf_x86_64_reloc_type_lookup elf_x86_64_reloc_type_lookup
#define bfd_elf32_bfd_reloc_name_lookup \ #define bfd_elf32_bfd_reloc_name_lookup \

View File

@ -19,6 +19,16 @@
MA 02110-1301, USA. */ MA 02110-1301, USA. */
#include "elfxx-x86.h" #include "elfxx-x86.h"
#include "objalloc.h"
#include "elf/i386.h"
#include "elf/x86-64.h"
/* The name of the dynamic interpreter. This is put in the .interp
section. */
#define ELF32_DYNAMIC_INTERPRETER "/usr/lib/libc.so.1"
#define ELF64_DYNAMIC_INTERPRETER "/lib/ld64.so.1"
#define ELFX32_DYNAMIC_INTERPRETER "/lib/ldx32.so.1"
/* _TLS_MODULE_BASE_ needs to be treated especially when linking /* _TLS_MODULE_BASE_ needs to be treated especially when linking
executables. Rather than setting it to the beginning of the TLS executables. Rather than setting it to the beginning of the TLS
@ -217,8 +227,8 @@ _bfd_x86_elf_local_htab_eq (const void *ptr1, const void *ptr2)
/* Destroy an x86 ELF linker hash table. */ /* Destroy an x86 ELF linker hash table. */
void static void
_bfd_x86_elf_link_hash_table_free (bfd *obfd) elf_x86_link_hash_table_free (bfd *obfd)
{ {
struct elf_x86_link_hash_table *htab struct elf_x86_link_hash_table *htab
= (struct elf_x86_link_hash_table *) obfd->link.hash; = (struct elf_x86_link_hash_table *) obfd->link.hash;
@ -230,6 +240,77 @@ _bfd_x86_elf_link_hash_table_free (bfd *obfd)
_bfd_elf_link_hash_table_free (obfd); _bfd_elf_link_hash_table_free (obfd);
} }
/* Create an x86 ELF linker hash table. */
struct bfd_link_hash_table *
_bfd_x86_elf_link_hash_table_create (bfd *abfd)
{
struct elf_x86_link_hash_table *ret;
const struct elf_backend_data *bed;
bfd_size_type amt = sizeof (struct elf_x86_link_hash_table);
ret = (struct elf_x86_link_hash_table *) bfd_zmalloc (amt);
if (ret == NULL)
return NULL;
bed = get_elf_backend_data (abfd);
if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd,
_bfd_x86_elf_link_hash_newfunc,
sizeof (struct elf_x86_link_hash_entry),
bed->target_id))
{
free (ret);
return NULL;
}
#ifdef BFD64
if (ABI_64_P (abfd))
{
ret->r_info = elf64_r_info;
ret->r_sym = elf64_r_sym;
ret->pointer_r_type = R_X86_64_64;
ret->dynamic_interpreter = ELF64_DYNAMIC_INTERPRETER;
ret->dynamic_interpreter_size = sizeof ELF64_DYNAMIC_INTERPRETER;
ret->tls_get_addr = "__tls_get_addr";
}
else
#endif
{
ret->r_info = elf32_r_info;
ret->r_sym = elf32_r_sym;
if (bed->elf_machine_code == EM_X86_64)
{
ret->pointer_r_type = R_X86_64_32;
ret->dynamic_interpreter = ELFX32_DYNAMIC_INTERPRETER;
ret->dynamic_interpreter_size
= sizeof ELFX32_DYNAMIC_INTERPRETER;
ret->tls_get_addr = "__tls_get_addr";
}
else
{
ret->pointer_r_type = R_386_32;
ret->dynamic_interpreter = ELF32_DYNAMIC_INTERPRETER;
ret->dynamic_interpreter_size
= sizeof ELF32_DYNAMIC_INTERPRETER;
ret->tls_get_addr = "___tls_get_addr";
}
}
ret->loc_hash_table = htab_try_create (1024,
_bfd_x86_elf_local_htab_hash,
_bfd_x86_elf_local_htab_eq,
NULL);
ret->loc_hash_memory = objalloc_create ();
if (!ret->loc_hash_table || !ret->loc_hash_memory)
{
elf_x86_link_hash_table_free (abfd);
return NULL;
}
ret->elf.root.hash_table_free = elf_x86_link_hash_table_free;
return &ret->elf.root;
}
/* Sort relocs into address order. */ /* Sort relocs into address order. */
int int

View File

@ -24,9 +24,11 @@
#include "libbfd.h" #include "libbfd.h"
#include "elf-bfd.h" #include "elf-bfd.h"
#include "bfd_stdint.h" #include "bfd_stdint.h"
#include "objalloc.h"
#include "hashtab.h" #include "hashtab.h"
#define ABI_64_P(abfd) \
(get_elf_backend_data (abfd)->s->elfclass == ELFCLASS64)
/* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid /* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid
copying dynamic variables from a shared lib into an app's dynbss copying dynamic variables from a shared lib into an app's dynbss
section, and instead use a dynamic relocation to point into the section, and instead use a dynamic relocation to point into the
@ -118,6 +120,105 @@ struct elf_x86_link_hash_entry
bfd_vma tlsdesc_got; bfd_vma tlsdesc_got;
}; };
struct elf_x86_lazy_plt_layout
{
/* The first entry in an absolute lazy procedure linkage table looks
like this. */
const bfd_byte *plt0_entry;
unsigned int plt0_entry_size; /* Size of PLT0 entry. */
/* Later entries in an absolute lazy procedure linkage table look
like this. */
const bfd_byte *plt_entry;
unsigned int plt_entry_size; /* Size of each PLT entry. */
/* Offsets into plt0_entry that are to be replaced with GOT[1] and
GOT[2]. */
unsigned int plt0_got1_offset;
unsigned int plt0_got2_offset;
/* Offset of the end of the PC-relative instruction containing
plt0_got2_offset. This is for x86-64 only. */
unsigned int plt0_got2_insn_end;
/* Offsets into plt_entry that are to be replaced with... */
unsigned int plt_got_offset; /* ... address of this symbol in .got. */
unsigned int plt_reloc_offset; /* ... offset into relocation table. */
unsigned int plt_plt_offset; /* ... offset to start of .plt. */
/* Length of the PC-relative instruction containing plt_got_offset.
This is used for x86-64 only. */
unsigned int plt_got_insn_size;
/* Offset of the end of the PC-relative jump to plt0_entry. This is
used for x86-64 only. */
unsigned int plt_plt_insn_end;
/* Offset into plt_entry where the initial value of the GOT entry
points. */
unsigned int plt_lazy_offset;
/* The first entry in a PIC lazy procedure linkage table looks like
this. This is used for i386 only. */
const bfd_byte *pic_plt0_entry;
/* Subsequent entries in a PIC lazy procedure linkage table look
like this. This is used for i386 only. */
const bfd_byte *pic_plt_entry;
/* .eh_frame covering the lazy .plt section. */
const bfd_byte *eh_frame_plt;
unsigned int eh_frame_plt_size;
};
struct elf_x86_non_lazy_plt_layout
{
/* Entries in an absolute non-lazy procedure linkage table look like
this. */
const bfd_byte *plt_entry;
/* Entries in a PIC non-lazy procedure linkage table look like this.
This is used for i386 only. */
const bfd_byte *pic_plt_entry;
unsigned int plt_entry_size; /* Size of each PLT entry. */
/* Offsets into plt_entry that are to be replaced with... */
unsigned int plt_got_offset; /* ... address of this symbol in .got. */
/* Length of the PC-relative instruction containing plt_got_offset.
This is used for x86-64 only. */
unsigned int plt_got_insn_size;
/* .eh_frame covering the non-lazy .plt section. */
const bfd_byte *eh_frame_plt;
unsigned int eh_frame_plt_size;
};
struct elf_x86_plt_layout
{
/* The first entry in a lazy procedure linkage table looks like this.
This is only used for i386 where absolute PLT0 and PIC PLT0 are
different. */
const bfd_byte *plt0_entry;
/* Entries in a procedure linkage table look like this. */
const bfd_byte *plt_entry;
unsigned int plt_entry_size; /* Size of each PLT entry. */
/* 1 has PLT0. */
unsigned int has_plt0;
/* Offsets into plt_entry that are to be replaced with... */
unsigned int plt_got_offset; /* ... address of this symbol in .got. */
/* Length of the PC-relative instruction containing plt_got_offset.
This is only used for x86-64. */
unsigned int plt_got_insn_size;
/* .eh_frame covering the .plt section. */
const bfd_byte *eh_frame_plt;
unsigned int eh_frame_plt_size;
};
/* The first 3 values in tls_type of x86 ELF linker hash entry. */ /* The first 3 values in tls_type of x86 ELF linker hash entry. */
#define GOT_UNKNOWN 0 #define GOT_UNKNOWN 0
#define GOT_NORMAL 1 #define GOT_NORMAL 1
@ -140,6 +241,15 @@ struct elf_x86_link_hash_table
asection *plt_got; asection *plt_got;
asection *plt_got_eh_frame; asection *plt_got_eh_frame;
/* Parameters describing PLT generation, lazy or non-lazy. */
struct elf_x86_plt_layout plt;
/* Parameters describing lazy PLT generation. */
const struct elf_x86_lazy_plt_layout *lazy_plt;
/* Parameters describing non-lazy PLT generation. */
const struct elf_x86_non_lazy_plt_layout *non_lazy_plt;
union union
{ {
bfd_signed_vma refcount; bfd_signed_vma refcount;
@ -178,6 +288,14 @@ struct elf_x86_link_hash_table
to read-only sections. */ to read-only sections. */
bfd_boolean readonly_dynrelocs_against_ifunc; bfd_boolean readonly_dynrelocs_against_ifunc;
/* The (unloaded but important) .rel.plt.unloaded section on VxWorks.
This is used for i386 only. */
asection *srelplt2;
/* The index of the next unused R_386_TLS_DESC slot in .rel.plt. This
is used for i386 only. */
bfd_vma next_tls_desc_index;
bfd_vma (*r_info) (bfd_vma, bfd_vma); bfd_vma (*r_info) (bfd_vma, bfd_vma);
bfd_vma (*r_sym) (bfd_vma); bfd_vma (*r_sym) (bfd_vma);
unsigned int pointer_r_type; unsigned int pointer_r_type;
@ -228,7 +346,7 @@ extern int _bfd_x86_elf_local_htab_eq
extern struct bfd_hash_entry * _bfd_x86_elf_link_hash_newfunc extern struct bfd_hash_entry * _bfd_x86_elf_link_hash_newfunc
(struct bfd_hash_entry *, struct bfd_hash_table *, const char *); (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
extern void _bfd_x86_elf_link_hash_table_free extern struct bfd_link_hash_table * _bfd_x86_elf_link_hash_table_create
(bfd *); (bfd *);
extern int _bfd_x86_elf_compare_relocs extern int _bfd_x86_elf_compare_relocs
@ -260,6 +378,10 @@ extern enum elf_property_kind _bfd_x86_elf_parse_gnu_properties
extern bfd_boolean _bfd_x86_elf_merge_gnu_properties extern bfd_boolean _bfd_x86_elf_merge_gnu_properties
(struct bfd_link_info *, bfd *, elf_property *, elf_property *); (struct bfd_link_info *, bfd *, elf_property *, elf_property *);
#define bfd_elf64_bfd_link_hash_table_create \
_bfd_x86_elf_link_hash_table_create
#define bfd_elf32_bfd_link_hash_table_create \
_bfd_x86_elf_link_hash_table_create
#define bfd_elf64_bfd_link_check_relocs \ #define bfd_elf64_bfd_link_check_relocs \
_bfd_x86_elf_link_check_relocs _bfd_x86_elf_link_check_relocs
#define bfd_elf32_bfd_link_check_relocs \ #define bfd_elf32_bfd_link_check_relocs \