relocation type. We also use ELF_ST_TYPE instead of ELF64_ST_TYPE
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:
type, rightshift, size, bitsize, pc_relative, bitpos, complain_on_overflow,
special_function, name, partial_inplace, src_mask, dst_mask, pcrel_offset. */
\f
/* 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. */
#define GOT_ENTRY_SIZE 8
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. */
struct elf_x86_64_backend_data
get_elf_x86_64_arch_data (get_elf_backend_data (abfd))
/* 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 */
+ LAZY_PLT_ENTRY_SIZE, /* plt0_entry_size */
elf_x86_64_lazy_plt_entry, /* plt_entry */
LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
2, /* plt0_got1_offset */
6, /* plt_got_insn_size */
LAZY_PLT_ENTRY_SIZE, /* plt_plt_insn_end */
6, /* plt_lazy_offset */
+ elf_x86_64_lazy_plt0_entry, /* pic_plt0_entry */
+ elf_x86_64_lazy_plt_entry, /* pic_plt_entry */
elf_x86_64_eh_frame_lazy_plt, /* eh_frame_plt */
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, /* pic_plt_entry */
NON_LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
2, /* plt_got_offset */
6, /* plt_got_insn_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 */
+ LAZY_PLT_ENTRY_SIZE, /* plt0_entry_size */
elf_x86_64_lazy_bnd_plt_entry, /* plt_entry */
LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
2, /* plt0_got1_offset */
1+6, /* plt_got_insn_size */
11, /* plt_plt_insn_end */
0, /* plt_lazy_offset */
+ elf_x86_64_lazy_bnd_plt0_entry, /* pic_plt0_entry */
+ elf_x86_64_lazy_bnd_plt_entry, /* pic_plt_entry */
elf_x86_64_eh_frame_lazy_bnd_plt, /* eh_frame_plt */
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, /* pic_plt_entry */
NON_LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
1+2, /* plt_got_offset */
1+6, /* plt_got_insn_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 */
+ LAZY_PLT_ENTRY_SIZE, /* plt0_entry_size */
elf_x86_64_lazy_ibt_plt_entry, /* plt_entry */
LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
2, /* plt0_got1_offset */
4+1+6, /* plt_got_insn_size */
4+1+5+5, /* plt_plt_insn_end */
0, /* plt_lazy_offset */
+ elf_x86_64_lazy_bnd_plt0_entry, /* pic_plt0_entry */
+ elf_x86_64_lazy_ibt_plt_entry, /* pic_plt_entry */
elf_x86_64_eh_frame_lazy_ibt_plt, /* eh_frame_plt */
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 */
+ LAZY_PLT_ENTRY_SIZE, /* plt0_entry_size */
elf_x32_lazy_ibt_plt_entry, /* plt_entry */
LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
2, /* plt0_got1_offset */
4+6, /* plt_got_insn_size */
4+5+5, /* plt_plt_insn_end */
0, /* plt_lazy_offset */
+ elf_x86_64_lazy_plt0_entry, /* pic_plt0_entry */
+ elf_x32_lazy_ibt_plt_entry, /* pic_plt_entry */
elf_x32_eh_frame_lazy_ibt_plt, /* eh_frame_plt */
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, /* pic_plt_entry */
LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
4+1+2, /* plt_got_offset */
4+1+6, /* plt_got_insn_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, /* pic_plt_entry */
LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
4+2, /* plt_got_offset */
4+6, /* plt_got_insn_size */
&& elf_tdata (bfd) != NULL \
&& elf_object_id (bfd) == X86_64_ELF_DATA)
-static bfd_boolean
-elf_x86_64_mkobject (bfd *abfd)
-{
- return bfd_elf_allocate_object (abfd, sizeof (struct elf_x86_obj_tdata),
- 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_next_tls_desc_index(htab) \
- ((struct elf_x86_64_link_hash_table *) (htab))->next_tls_desc_index
-
-#define elf_x86_64_srelplt2(htab) \
- ((struct elf_x86_64_link_hash_table *) (htab))->srelplt2
-
-#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) \
((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
elf64_x86_64_elf_object_p (bfd *abfd)
{
return FALSE;
}
-/* Return the section that should be marked against GC for a given
- relocation. */
-
-static asection *
-elf_x86_64_gc_mark_hook (asection *sec,
- struct bfd_link_info *info,
- Elf_Internal_Rela *rel,
- struct elf_link_hash_entry *h,
- Elf_Internal_Sym *sym)
-{
- if (h != NULL)
- switch (ELF32_R_TYPE (rel->r_info))
- {
- case R_X86_64_GNU_VTINHERIT:
- case R_X86_64_GNU_VTENTRY:
- return NULL;
- }
-
- return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
-}
-
-/* Adjust a symbol defined by a dynamic object and referenced by a
- regular object. The current definition is in some section of the
- dynamic object, but we're not including those sections. We have to
- change the definition to something the rest of the link can
- understand. */
-
-static bfd_boolean
-elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info,
- struct elf_link_hash_entry *h)
-{
- struct elf_x86_link_hash_table *htab;
- asection *s, *srel;
- struct elf_x86_link_hash_entry *eh;
- struct elf_dyn_relocs *p;
-
- /* STT_GNU_IFUNC symbol must go through PLT. */
- if (h->type == STT_GNU_IFUNC)
- {
- /* All local STT_GNU_IFUNC references must be treate as local
- calls via local PLT. */
- if (h->ref_regular
- && SYMBOL_CALLS_LOCAL (info, h))
- {
- bfd_size_type pc_count = 0, count = 0;
- struct elf_dyn_relocs **pp;
-
- eh = (struct elf_x86_link_hash_entry *) h;
- for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
- {
- pc_count += p->pc_count;
- p->count -= p->pc_count;
- p->pc_count = 0;
- count += p->count;
- if (p->count == 0)
- *pp = p->next;
- else
- pp = &p->next;
- }
-
- if (pc_count || count)
- {
- h->non_got_ref = 1;
- if (pc_count)
- {
- /* Increment PLT reference count only for PC-relative
- references. */
- h->needs_plt = 1;
- if (h->plt.refcount <= 0)
- h->plt.refcount = 1;
- else
- h->plt.refcount += 1;
- }
- }
- }
-
- if (h->plt.refcount <= 0)
- {
- h->plt.offset = (bfd_vma) -1;
- h->needs_plt = 0;
- }
- return TRUE;
- }
-
- /* If this is a function, put it in the procedure linkage table. We
- will fill in the contents of the procedure linkage table later,
- when we know the address of the .got section. */
- if (h->type == STT_FUNC
- || h->needs_plt)
- {
- if (h->plt.refcount <= 0
- || SYMBOL_CALLS_LOCAL (info, h)
- || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
- && h->root.type == bfd_link_hash_undefweak))
- {
- /* This case can occur if we saw a PLT32 reloc in an input
- file, but the symbol was never referred to by a dynamic
- object, or if all references were garbage collected. In
- such a case, we don't actually need to build a procedure
- linkage table, and we can just do a PC32 reloc instead. */
- h->plt.offset = (bfd_vma) -1;
- h->needs_plt = 0;
- }
-
- return TRUE;
- }
- else
- /* It's possible that we incorrectly decided a .plt reloc was
- needed for an R_X86_64_PC32 reloc to a non-function sym in
- check_relocs. We can't decide accurately between function and
- non-function syms in check-relocs; Objects loaded later in
- the link may change h->type. So fix it now. */
- h->plt.offset = (bfd_vma) -1;
-
- eh = (struct elf_x86_link_hash_entry *) h;
-
- /* If this is a weak symbol, and there is a real definition, the
- processor independent code will have arranged for us to see the
- real definition first, and we can just use the same value. */
- if (h->u.weakdef != NULL)
- {
- BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
- || h->u.weakdef->root.type == bfd_link_hash_defweak);
- h->root.u.def.section = h->u.weakdef->root.u.def.section;
- h->root.u.def.value = h->u.weakdef->root.u.def.value;
- if (ELIMINATE_COPY_RELOCS
- || info->nocopyreloc
- || SYMBOL_NO_COPYRELOC (info, eh))
- {
- h->non_got_ref = h->u.weakdef->non_got_ref;
- eh->needs_copy = h->u.weakdef->needs_copy;
- }
- return TRUE;
- }
-
- /* This is a reference to a symbol defined by a dynamic object which
- is not a function. */
-
- /* If we are creating a shared library, we must presume that the
- only references to the symbol are via the global offset table.
- For such cases we need not do anything here; the relocations will
- be handled correctly by relocate_section. */
- if (!bfd_link_executable (info))
- return TRUE;
-
- /* If there are no references to this symbol that do not use the
- GOT, we don't need to generate a copy reloc. */
- if (!h->non_got_ref)
- return TRUE;
-
- /* If -z nocopyreloc was given, we won't generate them either. */
- if (info->nocopyreloc || SYMBOL_NO_COPYRELOC (info, eh))
- {
- h->non_got_ref = 0;
- return TRUE;
- }
-
- if (ELIMINATE_COPY_RELOCS)
- {
- eh = (struct elf_x86_link_hash_entry *) h;
- for (p = eh->dyn_relocs; p != NULL; p = p->next)
- {
- s = p->sec->output_section;
- if (s != NULL && (s->flags & SEC_READONLY) != 0)
- break;
- }
-
- /* If we didn't find any dynamic relocs in read-only sections, then
- we'll be keeping the dynamic relocs and avoiding the copy reloc. */
- if (p == NULL)
- {
- h->non_got_ref = 0;
- return TRUE;
- }
- }
-
- /* We must allocate the symbol in our .dynbss section, which will
- become part of the .bss section of the executable. There will be
- an entry for this symbol in the .dynsym section. The dynamic
- object will contain position independent code, so all references
- from the dynamic object to this symbol will go through the global
- offset table. The dynamic linker will use the .dynsym entry to
- determine the address it must put in the global offset table, so
- both the dynamic object and the regular object will refer to the
- same memory location for the variable. */
-
- htab = elf_x86_hash_table (info, X86_64_ELF_DATA);
- if (htab == NULL)
- return FALSE;
-
- /* We must generate a R_X86_64_COPY reloc to tell the dynamic linker
- to copy the initial value out of the dynamic object and into the
- runtime process image. */
- if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
- {
- s = htab->elf.sdynrelro;
- srel = htab->elf.sreldynrelro;
- }
- else
- {
- s = htab->elf.sdynbss;
- srel = htab->elf.srelbss;
- }
- if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
- {
- const struct elf_backend_data *bed;
- bed = get_elf_backend_data (info->output_bfd);
- srel->size += bed->s->sizeof_rela;
- h->needs_copy = 1;
- }
-
- return _bfd_elf_adjust_dynamic_copy (info, h, s);
-}
-
/* Allocate space in .plt, .got and associated reloc sections for
dynamic relocs. */
const struct elf_backend_data *bed;
unsigned int plt_entry_size;
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)
return TRUE;
return FALSE;
bed = get_elf_backend_data (info->output_bfd);
- plt_layout = &elf_x86_64_plt (htab);
- non_lazy_plt_layout = elf_x86_64_non_lazy_plt (htab);
- plt_entry_size = plt_layout->plt_entry_size;
+ plt_entry_size = htab->plt.plt_entry_size;
resolved_to_zero = UNDEFINED_WEAK_RESOLVED_TO_ZERO (info,
X86_64_ELF_DATA,
&eh->dyn_relocs,
&htab->readonly_dynrelocs_against_ifunc,
plt_entry_size,
- (plt_layout->has_plt0
+ (htab->plt.has_plt0
* plt_entry_size),
GOT_ENTRY_SIZE, TRUE))
{
eh->plt_second.offset = s->size;
/* 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;
first entry. The .plt section is used by prelink to undo
prelinking for dynamic relocations. */
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)
eh->plt_got.offset = got_s->size;
/* Make room for this entry. */
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
{
s->size += plt_entry_size;
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,
which will be placed in the .got section by the linker
bfd_boolean relocs;
bfd *ibfd;
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);
if (htab == NULL)
if (dynobj == NULL)
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
relocs. */
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
/* Reserve room for the initial entry.
FIXME: we could probably do away with it in this case. */
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->elf.splt->size += plt_layout->plt_entry_size;
+ htab->elf.splt->size += htab->plt.plt_entry_size;
}
}
&& htab->elf.splt != NULL
&& htab->elf.splt->size != 0
&& !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
&& htab->plt_got != NULL
&& htab->plt_got->size != 0
&& !bfd_is_abs_section (htab->plt_got->output_section))
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
identical. */
&& htab->plt_second->size != 0
&& !bfd_is_abs_section (htab->plt_second->output_section))
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.
&& htab->plt_eh_frame->contents != NULL)
{
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,
htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET);
}
&& htab->plt_got_eh_frame->contents != NULL)
{
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);
bfd_put_32 (dynobj, htab->plt_got->size,
(htab->plt_got_eh_frame->contents
&& htab->plt_second_eh_frame->contents != NULL)
{
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);
bfd_put_32 (dynobj, htab->plt_second->size,
(htab->plt_second_eh_frame->contents
htab = elf_x86_hash_table (info, X86_64_ELF_DATA);
if (htab == NULL)
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);
sym_hashes = elf_sym_hashes (input_bfd);
local_got_offsets = elf_local_got_offsets (input_bfd);
if (htab->elf.splt != NULL)
{
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;
base_got = htab->elf.sgotplt;
}
finish_dynamic_symbol would use that as offset into
.got. */
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;
base_got = htab->elf.sgotplt;
}
bfd_boolean use_plt_second;
struct elf_x86_link_hash_entry *eh;
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);
if (htab == NULL)
if (eh->no_finish_dynamic_symbol)
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
resolved undefined weak symbols in executable so that their
references have value 0 at run-time. */
if (plt == htab->elf.splt)
{
- got_offset = (h->plt.offset / plt_layout->plt_entry_size
- - plt_layout->has_plt0);
+ got_offset = (h->plt.offset / htab->plt.plt_entry_size
+ - htab->plt.has_plt0);
got_offset = (got_offset + 3) * GOT_ENTRY_SIZE;
}
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;
}
/* Fill in the entry in the procedure linkage table. */
- memcpy (plt->contents + h->plt.offset, plt_layout->plt_entry,
- plt_layout->plt_entry_size);
+ memcpy (plt->contents + h->plt.offset, htab->plt.plt_entry,
+ htab->plt.plt_entry_size);
if (use_plt_second)
{
memcpy (htab->plt_second->contents + eh->plt_second.offset,
- non_lazy_plt_layout->plt_entry,
- non_lazy_plt_layout->plt_entry_size);
+ htab->non_lazy_plt->plt_entry,
+ htab->non_lazy_plt->plt_entry_size);
resolved_plt = htab->plt_second;
plt_offset = eh->plt_second.offset;
- resolved_plt->output_section->vma
- resolved_plt->output_offset
- plt_offset
- - plt_layout->plt_got_insn_size);
+ - htab->plt.plt_got_insn_size);
/* Check PC-relative offset overflow in PLT entry. */
if ((plt_got_pcrel_offset + 0x80000000) > 0xffffffff)
bfd_put_32 (output_bfd, plt_got_pcrel_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
points to the second part of the PLT entry. Leave the entry
against undefined weak symbol in PIE. */
if (!local_undefweak)
{
- if (plt_layout->has_plt0)
+ if (htab->plt.has_plt0)
bfd_put_64 (output_bfd, (plt->output_section->vma
+ plt->output_offset
+ h->plt.offset
- + lazy_plt_layout->plt_lazy_offset),
+ + htab->lazy_plt->plt_lazy_offset),
gotplt->contents + got_offset);
/* Fill in the entry in the .rela.plt section. */
/* Don't fill the second and third slots in PLT entry for
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
- = h->plt.offset + lazy_plt_layout->plt_plt_insn_end;
+ = h->plt.offset + htab->lazy_plt->plt_plt_insn_end;
/* Put relocation index. */
bfd_put_32 (output_bfd, plt_index,
(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
check relocation index for overflow since branch displacement
output_bfd, h->root.root.string);
bfd_put_32 (output_bfd, - plt0_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);
/* Fill in the entry in the GOT procedure linkage table. */
plt_offset = eh->plt_got.offset;
memcpy (plt->contents + plt_offset,
- non_lazy_plt_layout->plt_entry,
- non_lazy_plt_layout->plt_entry_size);
+ htab->non_lazy_plt->plt_entry,
+ htab->non_lazy_plt->plt_entry_size);
/* Put offset the PC-relative instruction referring to the GOT
entry, subtracting the size of that instruction. */
- plt->output_section->vma
- plt->output_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. */
got_after_plt = got->output_section->vma > plt->output_section->vma;
bfd_put_32 (output_bfd, got_pcrel_offset,
(plt->contents + plt_offset
- + non_lazy_plt_layout->plt_got_offset));
+ + htab->non_lazy_plt->plt_got_offset));
}
if (!local_undefweak
else if (bfd_link_pic (info)
&& SYMBOL_REFERENCES_LOCAL (info, h))
{
- if (!h->def_regular)
+ if (!(h->def_regular || ELF_COMMON_DEF_P (h)))
return FALSE;
BFD_ASSERT((h->got.offset & 1) != 0);
rela.r_info = htab->r_info (0, R_X86_64_RELATIVE);
bfd_byte *dyncon, *dynconend;
const struct elf_backend_data *bed;
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)
abort ();
(*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)
{
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
table. */
memcpy (htab->elf.splt->contents,
- lazy_plt_layout->plt0_entry,
- lazy_plt_layout->plt_entry_size);
+ htab->lazy_plt->plt0_entry,
+ htab->lazy_plt->plt0_entry_size);
/* Add offset for pushq GOT+8(%rip), since the instruction
uses 6 bytes subtract this value. */
bfd_put_32 (output_bfd,
- htab->elf.splt->output_offset
- 6),
(htab->elf.splt->contents
- + lazy_plt_layout->plt0_got1_offset));
+ + htab->lazy_plt->plt0_got1_offset));
/* Add offset for the PC-relative instruction accessing
GOT+16, subtracting the offset to the end of that
instruction. */
+ 16
- htab->elf.splt->output_section->vma
- htab->elf.splt->output_offset
- - lazy_plt_layout->plt0_got2_insn_end),
+ - htab->lazy_plt->plt0_got2_insn_end),
(htab->elf.splt->contents
- + lazy_plt_layout->plt0_got2_offset));
+ + htab->lazy_plt->plt0_got2_offset));
if (htab->tlsdesc_plt)
{
htab->elf.sgot->contents + htab->tlsdesc_got);
memcpy (htab->elf.splt->contents + htab->tlsdesc_plt,
- lazy_plt_layout->plt0_entry,
- lazy_plt_layout->plt_entry_size);
+ htab->lazy_plt->plt0_entry,
+ htab->lazy_plt->plt0_entry_size);
/* Add offset for pushq GOT+8(%rip), since the
instruction uses 6 bytes subtract this value. */
- 6),
(htab->elf.splt->contents
+ htab->tlsdesc_plt
- + lazy_plt_layout->plt0_got1_offset));
+ + htab->lazy_plt->plt0_got1_offset));
/* Add offset for the PC-relative instruction accessing
GOT+TDG, where TDG stands for htab->tlsdesc_got,
subtracting the offset to the end of that
- htab->elf.splt->output_section->vma
- htab->elf.splt->output_offset
- htab->tlsdesc_plt
- - lazy_plt_layout->plt0_got2_insn_end),
+ - htab->lazy_plt->plt0_got2_insn_end),
(htab->elf.splt->contents
+ 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)
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)
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
return TRUE;
}
-enum elf_x86_64_plt_type
-{
- plt_non_lazy = 0,
- plt_lazy = 1 << 0,
- plt_second = 1 << 1,
- plt_unknown = -1
-};
-
-struct elf_x86_64_plt
-{
- const char *name;
- asection *sec;
- bfd_byte *contents;
- enum elf_x86_64_plt_type type;
- unsigned int plt_got_offset;
- unsigned int plt_got_insn_size;
- unsigned int plt_entry_size;
- long count;
-};
-
/* 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
dynamic relocations. */
asymbol **dynsyms,
asymbol **ret)
{
- long size, count, i, n, len;
+ long count, i, n;
int j;
- unsigned int plt_got_offset, plt_entry_size, plt_got_insn_size;
- asymbol *s;
bfd_byte *plt_contents;
- long dynrelcount, relsize;
- arelent **dynrelbuf, *p;
- const struct elf_x86_64_lazy_plt_layout *lazy_plt;
- const struct elf_x86_64_non_lazy_plt_layout *non_lazy_plt;
- const struct elf_x86_64_lazy_plt_layout *lazy_bnd_plt;
- const struct elf_x86_64_non_lazy_plt_layout *non_lazy_bnd_plt;
- const struct elf_x86_64_lazy_plt_layout *lazy_ibt_plt;
- const struct elf_x86_64_non_lazy_plt_layout *non_lazy_ibt_plt;
+ long relsize;
+ const struct elf_x86_lazy_plt_layout *lazy_plt;
+ const struct elf_x86_non_lazy_plt_layout *non_lazy_plt;
+ const struct elf_x86_lazy_plt_layout *lazy_bnd_plt;
+ const struct elf_x86_non_lazy_plt_layout *non_lazy_bnd_plt;
+ const struct elf_x86_lazy_plt_layout *lazy_ibt_plt;
+ const struct elf_x86_non_lazy_plt_layout *non_lazy_ibt_plt;
asection *plt;
- char *names;
- enum elf_x86_64_plt_type plt_type;
- struct elf_x86_64_plt plts[] =
+ enum elf_x86_plt_type plt_type;
+ struct elf_x86_plt plts[] =
{
{ ".plt", NULL, NULL, plt_unknown, 0, 0, 0, 0 },
{ ".plt.got", NULL, NULL, plt_non_lazy, 0, 0, 0, 0 },
plts[j].contents = plt_contents;
}
- if (count == 0)
- return -1;
-
- dynrelbuf = (arelent **) bfd_malloc (relsize);
- if (dynrelbuf == NULL)
- return -1;
-
- dynrelcount = bfd_canonicalize_dynamic_reloc (abfd, dynrelbuf,
- dynsyms);
-
- /* Sort the relocs by address. */
- qsort (dynrelbuf, dynrelcount, sizeof (arelent *),
- _bfd_x86_elf_compare_relocs);
-
- size = count * sizeof (asymbol);
-
- /* Allocate space for @plt suffixes. */
- n = 0;
- for (i = 0; i < dynrelcount; i++)
- {
- p = dynrelbuf[i];
- size += strlen ((*p->sym_ptr_ptr)->name) + sizeof ("@plt");
- if (p->addend != 0)
- size += sizeof ("+0x") - 1 + 8 + 8 * ABI_64_P (abfd);
- }
-
- s = *ret = (asymbol *) bfd_zmalloc (size);
- if (s == NULL)
- goto bad_return;
-
- /* Check for each PLT section. */
- names = (char *) (s + count);
- size = 0;
- n = 0;
- for (j = 0; plts[j].name != NULL; j++)
- if ((plt_contents = plts[j].contents) != NULL)
- {
- long k;
- bfd_vma offset;
-
- plt_got_offset = plts[j].plt_got_offset;
- plt_got_insn_size = plts[j].plt_got_insn_size;
- plt_entry_size = plts[j].plt_entry_size;
-
- plt = plts[j].sec;
-
- if ((plts[j].type & plt_lazy))
- {
- /* Skip PLT0 in lazy PLT. */
- k = 1;
- offset = plt_entry_size;
- }
- else
- {
- k = 0;
- offset = 0;
- }
-
- /* Check each PLT entry against dynamic relocations. */
- for (; k < plts[j].count; k++)
- {
- int off;
- bfd_vma got_vma;
- long min, max, mid;
-
- /* Get the PC-relative offset, a signed 32-bit integer. */
- off = H_GET_32 (abfd, (plt_contents + offset
- + plt_got_offset));
- got_vma = plt->vma + offset + off + plt_got_insn_size;
-
- /* Binary search. */
- p = dynrelbuf[0];
- min = 0;
- max = dynrelcount;
- while ((min + 1) < max)
- {
- arelent *r;
-
- mid = (min + max) / 2;
- r = dynrelbuf[mid];
- if (got_vma > r->address)
- min = mid;
- else if (got_vma < r->address)
- max = mid;
- else
- {
- p = r;
- break;
- }
- }
-
- /* Skip unknown relocation. PR 17512: file: bc9d6cf5. */
- if (got_vma == p->address
- && p->howto != NULL
- && (p->howto->type == R_X86_64_JUMP_SLOT
- || p->howto->type == R_X86_64_GLOB_DAT
- || p->howto->type == R_X86_64_IRELATIVE))
- {
- *s = **p->sym_ptr_ptr;
- /* Undefined syms won't have BSF_LOCAL or BSF_GLOBAL
- set. Since we are defining a symbol, ensure one
- of them is set. */
- if ((s->flags & BSF_LOCAL) == 0)
- s->flags |= BSF_GLOBAL;
- s->flags |= BSF_SYNTHETIC;
- /* This is no longer a section symbol. */
- s->flags &= ~BSF_SECTION_SYM;
- s->section = plt;
- s->the_bfd = plt->owner;
- s->value = offset;
- s->udata.p = NULL;
- s->name = names;
- len = strlen ((*p->sym_ptr_ptr)->name);
- memcpy (names, (*p->sym_ptr_ptr)->name, len);
- names += len;
- if (p->addend != 0)
- {
- char buf[30], *a;
-
- memcpy (names, "+0x", sizeof ("+0x") - 1);
- names += sizeof ("+0x") - 1;
- bfd_sprintf_vma (abfd, buf, p->addend);
- for (a = buf; *a == '0'; ++a)
- ;
- size = strlen (a);
- memcpy (names, a, size);
- names += size;
- }
- memcpy (names, "@plt", sizeof ("@plt"));
- names += sizeof ("@plt");
- n++;
- s++;
- }
- offset += plt_entry_size;
- }
- }
-
- /* PLT entries with R_X86_64_TLSDESC relocations are skipped. */
- if (n == 0)
- {
-bad_return:
- count = -1;
- }
- else
- count = n;
-
- for (j = 0; plts[j].name != NULL; j++)
- if (plts[j].contents != NULL)
- free (plts[j].contents);
-
- free (dynrelbuf);
-
- return count;
+ return _bfd_x86_elf_get_synthetic_symtab (abfd, count, relsize,
+ (bfd_vma) 0, plts, dynsyms,
+ ret);
}
/* Handle an x86-64 specific section when reading an object file. This
static bfd *
elf_x86_64_link_setup_gnu_properties (struct bfd_link_info *info)
{
- bfd_boolean normal_target;
- bfd_boolean lazy_plt;
- asection *sec, *pltsec;
- bfd *dynobj;
- bfd_boolean use_ibt_plt;
- unsigned int plt_alignment, features;
- struct elf_x86_link_hash_table *htab;
- bfd *pbfd;
- bfd *ebfd = NULL;
- 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;
- if (info->ibt)
- features = GNU_PROPERTY_X86_FEATURE_1_IBT;
- if (info->shstk)
- features |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
-
- /* Find a normal input file with GNU property note. */
- for (pbfd = info->input_bfds;
- pbfd != NULL;
- pbfd = pbfd->link.next)
- if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour
- && bfd_count_sections (pbfd) != 0)
- {
- ebfd = pbfd;
-
- if (elf_properties (pbfd) != NULL)
- break;
- }
+ struct elf_x86_plt_layout_table plt_layout;
- if (ebfd != NULL && features)
+ plt_layout.is_vxworks = FALSE;
+ if (get_elf_x86_64_backend_data (info->output_bfd)->os == is_normal)
{
- /* If features is set, add GNU_PROPERTY_X86_FEATURE_1_IBT and
- GNU_PROPERTY_X86_FEATURE_1_SHSTK. */
- prop = _bfd_elf_get_property (ebfd,
- GNU_PROPERTY_X86_FEATURE_1_AND,
- 4);
- prop->u.number |= features;
- prop->pr_kind = property_number;
-
- /* Create the GNU property note section if needed. */
- if (pbfd == NULL)
+ if (info->bndplt)
{
- sec = bfd_make_section_with_flags (ebfd,
- NOTE_GNU_PROPERTY_SECTION_NAME,
- (SEC_ALLOC
- | SEC_LOAD
- | SEC_IN_MEMORY
- | SEC_READONLY
- | SEC_HAS_CONTENTS
- | SEC_DATA));
- if (sec == NULL)
- info->callbacks->einfo (_("%F: failed to create GNU property section\n"));
-
- if (!bfd_set_section_alignment (ebfd, sec,
- ABI_64_P (ebfd) ? 3 : 2))
- {
-error_alignment:
- info->callbacks->einfo (_("%F%A: failed to align section\n"),
- sec);
- }
-
- elf_section_type (sec) = SHT_NOTE;
- }
- }
-
- pbfd = _bfd_elf_link_setup_gnu_properties (info);
-
- if (bfd_link_relocatable (info))
- return pbfd;
-
- htab = elf_x86_hash_table (info, X86_64_ELF_DATA);
- if (htab == NULL)
- return pbfd;
-
- use_ibt_plt = info->ibtplt || info->ibt;
- if (!use_ibt_plt && pbfd != NULL)
- {
- /* Check if GNU_PROPERTY_X86_FEATURE_1_IBT is on. */
- elf_property_list *p;
-
- /* The property list is sorted in order of type. */
- for (p = elf_properties (pbfd); p; p = p->next)
- {
- if (GNU_PROPERTY_X86_FEATURE_1_AND == p->property.pr_type)
- {
- use_ibt_plt = !!(p->property.u.number
- & GNU_PROPERTY_X86_FEATURE_1_IBT);
- break;
- }
- else if (GNU_PROPERTY_X86_FEATURE_1_AND < p->property.pr_type)
- break;
- }
- }
-
- dynobj = htab->elf.dynobj;
-
- /* Set htab->elf.dynobj here so that there is no need to check and
- set it in check_relocs. */
- if (dynobj == NULL)
- {
- if (pbfd != NULL)
- {
- htab->elf.dynobj = pbfd;
- dynobj = pbfd;
+ plt_layout.lazy_plt = &elf_x86_64_lazy_bnd_plt;
+ plt_layout.non_lazy_plt = &elf_x86_64_non_lazy_bnd_plt;
}
else
{
- bfd *abfd;
-
- /* Find a normal input file to hold linker created
- sections. */
- for (abfd = info->input_bfds;
- abfd != NULL;
- abfd = abfd->link.next)
- if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
- && (abfd->flags
- & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0)
- {
- htab->elf.dynobj = abfd;
- dynobj = abfd;
- break;
- }
+ plt_layout.lazy_plt = &elf_x86_64_lazy_plt;
+ plt_layout.non_lazy_plt = &elf_x86_64_non_lazy_plt;
}
- }
- plt_layout = &elf_x86_64_plt (htab);
-
- /* 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
- canonical function address. */
- plt_layout->has_plt0 = 1;
-
- if (get_elf_x86_64_backend_data (info->output_bfd)->os
- == is_normal)
- {
- if (use_ibt_plt)
- {
- if (ABI_64_P (dynobj))
- {
- elf_x86_64_lazy_plt (htab)
- = &elf_x86_64_lazy_ibt_plt;
- elf_x86_64_non_lazy_plt (htab)
- = &elf_x86_64_non_lazy_ibt_plt;
- }
- else
- {
- elf_x86_64_lazy_plt (htab)
- = &elf_x32_lazy_ibt_plt;
- elf_x86_64_non_lazy_plt (htab)
- = &elf_x32_non_lazy_ibt_plt;
- }
- }
- else if (info->bndplt)
+ if (ABI_64_P (info->output_bfd))
{
- elf_x86_64_lazy_plt (htab) = &elf_x86_64_lazy_bnd_plt;
- elf_x86_64_non_lazy_plt (htab) = &elf_x86_64_non_lazy_bnd_plt;
+ plt_layout.lazy_ibt_plt = &elf_x86_64_lazy_ibt_plt;
+ plt_layout.non_lazy_ibt_plt = &elf_x86_64_non_lazy_ibt_plt;
}
else
{
- elf_x86_64_lazy_plt (htab) = &elf_x86_64_lazy_plt;
- elf_x86_64_non_lazy_plt (htab) = &elf_x86_64_non_lazy_plt;
+ plt_layout.lazy_ibt_plt = &elf_x32_lazy_ibt_plt;
+ plt_layout.non_lazy_ibt_plt = &elf_x32_non_lazy_ibt_plt;
}
- normal_target = TRUE;
- }
- else
- {
- elf_x86_64_lazy_plt (htab) = &elf_x86_64_nacl_plt;
- elf_x86_64_non_lazy_plt (htab) = NULL;
- 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;
-
- /* If the non-lazy PLT is available, use it for all PLT entries if
- there are no PLT0 or no .plt section. */
- if (non_lazy_plt_layout != NULL
- && (!plt_layout->has_plt0 || pltsec == NULL))
- {
- lazy_plt = FALSE;
- plt_layout->plt_entry
- = non_lazy_plt_layout->plt_entry;
- plt_layout->plt_entry_size
- = non_lazy_plt_layout->plt_entry_size;
- plt_layout->plt_got_offset
- = non_lazy_plt_layout->plt_got_offset;
- plt_layout->plt_got_insn_size
- = non_lazy_plt_layout->plt_got_insn_size;
- 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;
+ plt_layout.normal_target = TRUE;
}
else
{
- lazy_plt = TRUE;
- plt_layout->plt_entry
- = lazy_plt_layout->plt_entry;
- plt_layout->plt_entry_size
- = lazy_plt_layout->plt_entry_size;
- plt_layout->plt_got_offset
- = lazy_plt_layout->plt_got_offset;
- plt_layout->plt_got_insn_size
- = lazy_plt_layout->plt_got_insn_size;
- plt_layout->eh_frame_plt_size
- = lazy_plt_layout->eh_frame_plt_size;
- plt_layout->eh_frame_plt
- = lazy_plt_layout->eh_frame_plt;
- }
-
- /* Return if there are no normal input files. */
- if (dynobj == NULL)
- return pbfd;
-
- /* Since create_dynamic_sections isn't always called, but GOT
- relocations need GOT relocations, create them here so that we
- don't need to do it in check_relocs. */
- if (htab->elf.sgot == NULL
- && !_bfd_elf_create_got_section (dynobj, info))
- info->callbacks->einfo (_("%F: failed to create GOT sections\n"));
-
- /* Align .got and .got.plt sections to their entry size. Do it here
- instead of in create_dynamic_sections so that they are always
- properly aligned even if create_dynamic_sections isn't called. */
- sec = htab->elf.sgot;
- if (!bfd_set_section_alignment (dynobj, sec, 3))
- goto error_alignment;
-
- sec = htab->elf.sgotplt;
- if (!bfd_set_section_alignment (dynobj, sec, 3))
- goto error_alignment;
-
- /* Create the ifunc sections here so that check_relocs can be
- simplified. */
- if (!_bfd_elf_create_ifunc_sections (dynobj, info))
- info->callbacks->einfo (_("%F: failed to create ifunc sections\n"));
-
- plt_alignment = bfd_log2 (plt_layout->plt_entry_size);
-
- if (pltsec != NULL)
- {
- /* Whe creating executable, set the contents of the .interp
- section to the interpreter. */
- if (bfd_link_executable (info) && !info->nointerp)
- {
- asection *s = bfd_get_linker_section (dynobj, ".interp");
- if (s == NULL)
- abort ();
- s->size = htab->dynamic_interpreter_size;
- s->contents = (unsigned char *) htab->dynamic_interpreter;
- htab->interp = s;
- }
-
- /* Don't change PLT section alignment for NaCl since it uses
- 64-byte PLT entry and sets PLT section alignment to 32
- bytes. Don't create additional PLT sections for NaCl. */
- if (normal_target)
- {
- const struct elf_backend_data *bed
- = get_elf_backend_data (dynobj);
- flagword pltflags = (bed->dynamic_sec_flags
- | SEC_ALLOC
- | SEC_CODE
- | SEC_LOAD
- | SEC_READONLY);
- unsigned int non_lazy_plt_alignment
- = bfd_log2 (non_lazy_plt_layout->plt_entry_size);
-
- sec = pltsec;
- if (!bfd_set_section_alignment (sec->owner, sec,
- plt_alignment))
- goto error_alignment;
-
- /* Create the GOT procedure linkage table. */
- sec = bfd_make_section_anyway_with_flags (dynobj,
- ".plt.got",
- pltflags);
- if (sec == NULL)
- info->callbacks->einfo (_("%F: failed to create GOT PLT section\n"));
-
- if (!bfd_set_section_alignment (dynobj, sec,
- non_lazy_plt_alignment))
- goto error_alignment;
-
- htab->plt_got = sec;
-
- if (lazy_plt)
- {
- sec = NULL;
-
- if (use_ibt_plt)
- {
- /* Create the second PLT for Intel IBT support. IBT
- PLT is supported only for non-NaCl target and is
- is needed only for lazy binding. */
- sec = bfd_make_section_anyway_with_flags (dynobj,
- ".plt.sec",
- pltflags);
- if (sec == NULL)
- info->callbacks->einfo (_("%F: failed to create IBT-enabled PLT section\n"));
-
- if (!bfd_set_section_alignment (dynobj, sec,
- plt_alignment))
- goto error_alignment;
- }
- else if (info->bndplt && ABI_64_P (dynobj))
- {
- /* Create the second PLT for Intel MPX support. MPX
- PLT is supported only for non-NaCl target in 64-bit
- mode and is needed only for lazy binding. */
- sec = bfd_make_section_anyway_with_flags (dynobj,
- ".plt.sec",
- pltflags);
- if (sec == NULL)
- info->callbacks->einfo (_("%F: failed to create BND PLT section\n"));
-
- if (!bfd_set_section_alignment (dynobj, sec,
- non_lazy_plt_alignment))
- goto error_alignment;
- }
-
- htab->plt_second = sec;
- }
- }
-
- if (!info->no_ld_generated_unwind_info)
- {
- flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
- | SEC_HAS_CONTENTS | SEC_IN_MEMORY
- | SEC_LINKER_CREATED);
-
- sec = bfd_make_section_anyway_with_flags (dynobj,
- ".eh_frame",
- flags);
- if (sec == NULL)
- info->callbacks->einfo (_("%F: failed to create PLT .eh_frame section\n"));
-
- if (!bfd_set_section_alignment (dynobj, sec,
- ABI_64_P (dynobj) ? 3 : 2))
- goto error_alignment;
-
- htab->plt_eh_frame = sec;
-
- if (htab->plt_got != NULL)
- {
- sec = bfd_make_section_anyway_with_flags (dynobj,
- ".eh_frame",
- flags);
- if (sec == NULL)
- info->callbacks->einfo (_("%F: failed to create GOT PLT .eh_frame section\n"));
-
- if (!bfd_set_section_alignment (dynobj, sec,
- ABI_64_P (dynobj) ? 3 : 2))
- goto error_alignment;
-
- htab->plt_got_eh_frame = sec;
- }
-
- if (htab->plt_second != NULL)
- {
- sec = bfd_make_section_anyway_with_flags (dynobj,
- ".eh_frame",
- flags);
- if (sec == NULL)
- info->callbacks->einfo (_("%F: failed to create BND PLT .eh_frame section\n"));
-
- if (!bfd_set_section_alignment (dynobj, sec, 3))
- goto error_alignment;
-
- htab->plt_second_eh_frame = sec;
- }
- }
- }
-
- if (normal_target)
- {
- /* The .iplt section is used for IFUNC symbols in static
- executables. */
- sec = htab->elf.iplt;
- if (sec != NULL
- && !bfd_set_section_alignment (sec->owner, sec,
- plt_alignment))
- goto error_alignment;
+ plt_layout.lazy_plt = &elf_x86_64_nacl_plt;
+ plt_layout.non_lazy_plt = NULL;
+ plt_layout.lazy_ibt_plt = NULL;
+ plt_layout.non_lazy_ibt_plt = NULL;
+ plt_layout.normal_target = FALSE;
}
- return pbfd;
+ return _bfd_x86_elf_link_setup_gnu_properties (info, &plt_layout);
}
static const struct bfd_elf_special_section
#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_name_lookup \
elf_x86_64_reloc_name_lookup
-#define elf_backend_adjust_dynamic_symbol elf_x86_64_adjust_dynamic_symbol
#define elf_backend_relocs_compatible elf_x86_64_relocs_compatible
#define elf_backend_check_relocs elf_x86_64_check_relocs
#define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections
#define elf_backend_finish_dynamic_sections elf_x86_64_finish_dynamic_sections
#define elf_backend_finish_dynamic_symbol elf_x86_64_finish_dynamic_symbol
#define elf_backend_output_arch_local_syms elf_x86_64_output_arch_local_syms
-#define elf_backend_gc_mark_hook elf_x86_64_gc_mark_hook
#define elf_backend_grok_prstatus elf_x86_64_grok_prstatus
#define elf_backend_grok_psinfo elf_x86_64_grok_psinfo
#ifdef CORE_HEADER
#define elf_backend_size_dynamic_sections elf_x86_64_size_dynamic_sections
#define elf_backend_init_index_section _bfd_elf_init_1_index_section
#define elf_backend_object_p elf64_x86_64_elf_object_p
-#define bfd_elf64_mkobject elf_x86_64_mkobject
#define bfd_elf64_get_synthetic_symtab elf_x86_64_get_synthetic_symtab
#define elf_backend_section_from_shdr \
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 */
+ NACL_PLT_ENTRY_SIZE, /* plt0_entry_size */
elf_x86_64_nacl_plt_entry, /* plt_entry */
NACL_PLT_ENTRY_SIZE, /* plt_entry_size */
2, /* plt0_got1_offset */
7, /* plt_got_insn_size */
42, /* plt_plt_insn_end */
32, /* plt_lazy_offset */
+ elf_x86_64_nacl_plt0_entry, /* pic_plt0_entry */
+ elf_x86_64_nacl_plt_entry, /* pic_plt_entry */
elf_x86_64_nacl_eh_frame_plt, /* eh_frame_plt */
sizeof (elf_x86_64_nacl_eh_frame_plt) /* eh_frame_plt_size */
};
#undef elf32_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 \
elf_x86_64_reloc_type_lookup
#define bfd_elf32_bfd_reloc_name_lookup \
elf_x86_64_reloc_name_lookup
-#define bfd_elf32_mkobject \
- elf_x86_64_mkobject
#define bfd_elf32_get_synthetic_symtab \
elf_x86_64_get_synthetic_symtab