Line 27... |
Line 27... |
#include "elf-bfd.h"
|
#include "elf-bfd.h"
|
#include "elf-vxworks.h"
|
#include "elf-vxworks.h"
|
#include "bfd_stdint.h"
|
#include "bfd_stdint.h"
|
#include "objalloc.h"
|
#include "objalloc.h"
|
#include "hashtab.h"
|
#include "hashtab.h"
|
|
#include "dwarf2.h"
|
|
|
/* 386 uses REL relocations instead of RELA. */
|
/* 386 uses REL relocations instead of RELA. */
|
#define USE_REL 1
|
#define USE_REL 1
|
|
|
#include "elf/i386.h"
|
#include "elf/i386.h"
|
Line 572... |
Line 573... |
0, 0, 0, 0, /* replaced with offset into relocation table. */
|
0, 0, 0, 0, /* replaced with offset into relocation table. */
|
0xe9, /* jmp relative */
|
0xe9, /* jmp relative */
|
0, 0, 0, 0 /* replaced with offset to start of .plt. */
|
0, 0, 0, 0 /* replaced with offset to start of .plt. */
|
};
|
};
|
|
|
|
/* .eh_frame covering the .plt section. */
|
|
|
|
static const bfd_byte elf_i386_eh_frame_plt[] =
|
|
{
|
|
#define PLT_CIE_LENGTH 20
|
|
#define PLT_FDE_LENGTH 36
|
|
#define PLT_FDE_START_OFFSET 4 + PLT_CIE_LENGTH + 8
|
|
#define PLT_FDE_LEN_OFFSET 4 + PLT_CIE_LENGTH + 12
|
|
PLT_CIE_LENGTH, 0, 0, 0, /* CIE length */
|
|
0, 0, 0, 0, /* CIE ID */
|
|
1, /* CIE version */
|
|
'z', 'R', 0, /* Augmentation string */
|
|
1, /* Code alignment factor */
|
|
0x7c, /* Data alignment factor */
|
|
8, /* Return address column */
|
|
1, /* Augmentation size */
|
|
DW_EH_PE_pcrel | DW_EH_PE_sdata4, /* FDE encoding */
|
|
DW_CFA_def_cfa, 4, 4, /* DW_CFA_def_cfa: r4 (esp) ofs 4 */
|
|
DW_CFA_offset + 8, 1, /* DW_CFA_offset: r8 (eip) at cfa-4 */
|
|
DW_CFA_nop, DW_CFA_nop,
|
|
|
|
PLT_FDE_LENGTH, 0, 0, 0, /* FDE length */
|
|
PLT_CIE_LENGTH + 8, 0, 0, 0, /* CIE pointer */
|
|
0, 0, 0, 0, /* R_386_PC32 .plt goes here */
|
|
0, 0, 0, 0, /* .plt size goes here */
|
|
0, /* Augmentation size */
|
|
DW_CFA_def_cfa_offset, 8, /* DW_CFA_def_cfa_offset: 8 */
|
|
DW_CFA_advance_loc + 6, /* DW_CFA_advance_loc: 6 to __PLT__+6 */
|
|
DW_CFA_def_cfa_offset, 12, /* DW_CFA_def_cfa_offset: 12 */
|
|
DW_CFA_advance_loc + 10, /* DW_CFA_advance_loc: 10 to __PLT__+16 */
|
|
DW_CFA_def_cfa_expression, /* DW_CFA_def_cfa_expression */
|
|
11, /* Block length */
|
|
DW_OP_breg4, 4, /* DW_OP_breg4 (esp): 4 */
|
|
DW_OP_breg8, 0, /* DW_OP_breg8 (eip): 0 */
|
|
DW_OP_lit15, DW_OP_and, DW_OP_lit11, DW_OP_ge,
|
|
DW_OP_lit2, DW_OP_shl, DW_OP_plus,
|
|
DW_CFA_nop, DW_CFA_nop, DW_CFA_nop, DW_CFA_nop
|
|
};
|
|
|
|
struct elf_i386_plt_layout
|
|
{
|
|
/* The first entry in an absolute 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 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 procedure linkage table looks like this. */
|
|
const bfd_byte *pic_plt0_entry;
|
|
|
|
/* Subsequent entries in a PIC procedure linkage table look like this. */
|
|
const bfd_byte *pic_plt_entry;
|
|
|
|
/* .eh_frame covering the .plt section. */
|
|
const bfd_byte *eh_frame_plt;
|
|
unsigned int eh_frame_plt_size;
|
|
};
|
|
|
|
#define GET_PLT_ENTRY_SIZE(abfd) \
|
|
get_elf_i386_backend_data (abfd)->plt->plt_entry_size
|
|
|
|
/* These are the standard parameters. */
|
|
static const struct elf_i386_plt_layout elf_i386_plt =
|
|
{
|
|
elf_i386_plt0_entry, /* plt0_entry */
|
|
sizeof (elf_i386_plt0_entry), /* plt0_entry_size */
|
|
2, /* plt0_got1_offset */
|
|
8, /* plt0_got2_offset */
|
|
elf_i386_plt_entry, /* plt_entry */
|
|
PLT_ENTRY_SIZE, /* plt_entry_size */
|
|
2, /* plt_got_offset */
|
|
7, /* plt_reloc_offset */
|
|
12, /* plt_plt_offset */
|
|
6, /* plt_lazy_offset */
|
|
elf_i386_pic_plt0_entry, /* pic_plt0_entry */
|
|
elf_i386_pic_plt_entry, /* pic_plt_entry */
|
|
elf_i386_eh_frame_plt, /* eh_frame_plt */
|
|
sizeof (elf_i386_eh_frame_plt), /* eh_frame_plt_size */
|
|
};
|
|
|
|
|
/* On VxWorks, the .rel.plt.unloaded section has absolute relocations
|
/* On VxWorks, the .rel.plt.unloaded section has absolute relocations
|
for the PLTResolve stub and then for each PLT entry. */
|
for the PLTResolve stub and then for each PLT entry. */
|
#define PLTRESOLVE_RELOCS_SHLIB 0
|
#define PLTRESOLVE_RELOCS_SHLIB 0
|
#define PLTRESOLVE_RELOCS 2
|
#define PLTRESOLVE_RELOCS 2
|
#define PLT_NON_JUMP_SLOT_RELOCS 2
|
#define PLT_NON_JUMP_SLOT_RELOCS 2
|
|
|
|
/* Architecture-specific backend data for i386. */
|
|
|
|
struct elf_i386_backend_data
|
|
{
|
|
/* Parameters describing PLT generation. */
|
|
const struct elf_i386_plt_layout *plt;
|
|
|
|
/* Value used to fill the unused bytes of the first PLT entry. */
|
|
bfd_byte plt0_pad_byte;
|
|
|
|
/* True if the target system is VxWorks. */
|
|
int is_vxworks;
|
|
};
|
|
|
|
#define get_elf_i386_backend_data(abfd) \
|
|
((const struct elf_i386_backend_data *) \
|
|
get_elf_backend_data (abfd)->arch_data)
|
|
|
|
/* These are the standard parameters. */
|
|
static const struct elf_i386_backend_data elf_i386_arch_bed =
|
|
{
|
|
&elf_i386_plt, /* plt */
|
|
0, /* plt0_pad_byte */
|
|
0, /* is_vxworks */
|
|
};
|
|
|
|
#define elf_backend_arch_data &elf_i386_arch_bed
|
|
|
/* i386 ELF linker hash entry. */
|
/* i386 ELF linker hash entry. */
|
|
|
struct elf_i386_link_hash_entry
|
struct elf_i386_link_hash_entry
|
{
|
{
|
struct elf_link_hash_entry elf;
|
struct elf_link_hash_entry elf;
|
Line 653... |
Line 777... |
struct elf_link_hash_table elf;
|
struct elf_link_hash_table elf;
|
|
|
/* Short-cuts to get to dynamic linker sections. */
|
/* Short-cuts to get to dynamic linker sections. */
|
asection *sdynbss;
|
asection *sdynbss;
|
asection *srelbss;
|
asection *srelbss;
|
|
asection *plt_eh_frame;
|
|
|
union
|
union
|
{
|
{
|
bfd_signed_vma refcount;
|
bfd_signed_vma refcount;
|
bfd_vma offset;
|
bfd_vma offset;
|
Line 677... |
Line 802... |
void * loc_hash_memory;
|
void * loc_hash_memory;
|
|
|
/* The (unloaded but important) .rel.plt.unloaded section on VxWorks. */
|
/* The (unloaded but important) .rel.plt.unloaded section on VxWorks. */
|
asection *srelplt2;
|
asection *srelplt2;
|
|
|
/* True if the target system is VxWorks. */
|
|
int is_vxworks;
|
|
|
|
/* The index of the next unused R_386_TLS_DESC slot in .rel.plt. */
|
/* The index of the next unused R_386_TLS_DESC slot in .rel.plt. */
|
bfd_vma next_tls_desc_index;
|
bfd_vma next_tls_desc_index;
|
|
|
/* Value used to fill the last word of the first plt entry. */
|
|
bfd_byte plt0_pad_byte;
|
|
};
|
};
|
|
|
/* Get the i386 ELF linker hash table from a link_info structure. */
|
/* Get the i386 ELF linker hash table from a link_info structure. */
|
|
|
#define elf_i386_hash_table(p) \
|
#define elf_i386_hash_table(p) \
|
Line 818... |
Line 937... |
return NULL;
|
return NULL;
|
}
|
}
|
|
|
ret->sdynbss = NULL;
|
ret->sdynbss = NULL;
|
ret->srelbss = NULL;
|
ret->srelbss = NULL;
|
|
ret->plt_eh_frame = NULL;
|
ret->tls_ldm_got.refcount = 0;
|
ret->tls_ldm_got.refcount = 0;
|
ret->next_tls_desc_index = 0;
|
ret->next_tls_desc_index = 0;
|
ret->sgotplt_jump_table_size = 0;
|
ret->sgotplt_jump_table_size = 0;
|
ret->sym_cache.abfd = NULL;
|
ret->sym_cache.abfd = NULL;
|
ret->is_vxworks = 0;
|
|
ret->srelplt2 = NULL;
|
ret->srelplt2 = NULL;
|
ret->plt0_pad_byte = 0;
|
|
ret->tls_module_base = NULL;
|
ret->tls_module_base = NULL;
|
|
|
ret->loc_hash_table = htab_try_create (1024,
|
ret->loc_hash_table = htab_try_create (1024,
|
elf_i386_local_htab_hash,
|
elf_i386_local_htab_hash,
|
elf_i386_local_htab_eq,
|
elf_i386_local_htab_eq,
|
Line 880... |
Line 998... |
|
|
if (!htab->sdynbss
|
if (!htab->sdynbss
|
|| (!info->shared && !htab->srelbss))
|
|| (!info->shared && !htab->srelbss))
|
abort ();
|
abort ();
|
|
|
if (htab->is_vxworks
|
if (get_elf_i386_backend_data (dynobj)->is_vxworks
|
&& !elf_vxworks_create_dynamic_sections (dynobj, info,
|
&& !elf_vxworks_create_dynamic_sections (dynobj, info,
|
&htab->srelplt2))
|
&htab->srelplt2))
|
return FALSE;
|
return FALSE;
|
|
|
|
if (!info->no_ld_generated_unwind_info
|
|
&& bfd_get_section_by_name (dynobj, ".eh_frame") == NULL
|
|
&& htab->elf.splt != NULL)
|
|
{
|
|
flagword flags = get_elf_backend_data (dynobj)->dynamic_sec_flags;
|
|
htab->plt_eh_frame
|
|
= bfd_make_section_with_flags (dynobj, ".eh_frame",
|
|
flags | SEC_READONLY);
|
|
if (htab->plt_eh_frame == NULL
|
|
|| !bfd_set_section_alignment (dynobj, htab->plt_eh_frame, 2))
|
|
return FALSE;
|
|
|
|
htab->plt_eh_frame->size = sizeof (elf_i386_eh_frame_plt);
|
|
htab->plt_eh_frame->contents
|
|
= bfd_alloc (dynobj, htab->plt_eh_frame->size);
|
|
memcpy (htab->plt_eh_frame->contents, elf_i386_eh_frame_plt,
|
|
sizeof (elf_i386_eh_frame_plt));
|
|
}
|
|
|
return TRUE;
|
return TRUE;
|
}
|
}
|
|
|
/* Copy the extra info we tack onto an elf_link_hash_entry. */
|
/* Copy the extra info we tack onto an elf_link_hash_entry. */
|
|
|
Line 2016... |
Line 2153... |
|
|
/* If there aren't any dynamic relocs in read-only sections, then
|
/* If there aren't any dynamic relocs in read-only sections, then
|
we can keep the dynamic relocs and avoid the copy reloc. This
|
we can keep the dynamic relocs and avoid the copy reloc. This
|
doesn't work on VxWorks, where we can not have dynamic relocations
|
doesn't work on VxWorks, where we can not have dynamic relocations
|
(other than copy and jump slot relocations) in an executable. */
|
(other than copy and jump slot relocations) in an executable. */
|
if (ELIMINATE_COPY_RELOCS && !htab->is_vxworks)
|
if (ELIMINATE_COPY_RELOCS
|
|
&& !get_elf_i386_backend_data (info->output_bfd)->is_vxworks)
|
{
|
{
|
struct elf_i386_link_hash_entry * eh;
|
struct elf_i386_link_hash_entry * eh;
|
struct elf_dyn_relocs *p;
|
struct elf_dyn_relocs *p;
|
|
|
eh = (struct elf_i386_link_hash_entry *) h;
|
eh = (struct elf_i386_link_hash_entry *) h;
|
Line 2077... |
Line 2215... |
{
|
{
|
struct bfd_link_info *info;
|
struct bfd_link_info *info;
|
struct elf_i386_link_hash_table *htab;
|
struct elf_i386_link_hash_table *htab;
|
struct elf_i386_link_hash_entry *eh;
|
struct elf_i386_link_hash_entry *eh;
|
struct elf_dyn_relocs *p;
|
struct elf_dyn_relocs *p;
|
|
unsigned plt_entry_size;
|
|
|
if (h->root.type == bfd_link_hash_indirect)
|
if (h->root.type == bfd_link_hash_indirect)
|
return TRUE;
|
return TRUE;
|
|
|
eh = (struct elf_i386_link_hash_entry *) h;
|
eh = (struct elf_i386_link_hash_entry *) h;
|
Line 2088... |
Line 2227... |
info = (struct bfd_link_info *) inf;
|
info = (struct bfd_link_info *) inf;
|
htab = elf_i386_hash_table (info);
|
htab = elf_i386_hash_table (info);
|
if (htab == NULL)
|
if (htab == NULL)
|
return FALSE;
|
return FALSE;
|
|
|
|
plt_entry_size = GET_PLT_ENTRY_SIZE (info->output_bfd);
|
|
|
/* Since STT_GNU_IFUNC symbol must go through PLT, we handle it
|
/* Since STT_GNU_IFUNC symbol must go through PLT, we handle it
|
here if it is defined and referenced in a non-shared object. */
|
here if it is defined and referenced in a non-shared object. */
|
if (h->type == STT_GNU_IFUNC
|
if (h->type == STT_GNU_IFUNC
|
&& h->def_regular)
|
&& h->def_regular)
|
return _bfd_elf_allocate_ifunc_dyn_relocs (info, h,
|
return _bfd_elf_allocate_ifunc_dyn_relocs (info, h, &eh->dyn_relocs,
|
&eh->dyn_relocs,
|
plt_entry_size, 4);
|
PLT_ENTRY_SIZE, 4);
|
|
else if (htab->elf.dynamic_sections_created
|
else if (htab->elf.dynamic_sections_created
|
&& h->plt.refcount > 0)
|
&& h->plt.refcount > 0)
|
{
|
{
|
/* Make sure this symbol is output as a dynamic symbol.
|
/* Make sure this symbol is output as a dynamic symbol.
|
Undefined weak syms won't yet be marked as dynamic. */
|
Undefined weak syms won't yet be marked as dynamic. */
|
Line 2115... |
Line 2255... |
asection *s = htab->elf.splt;
|
asection *s = htab->elf.splt;
|
|
|
/* If this is the first .plt entry, make room for the special
|
/* If this is the first .plt entry, make room for the special
|
first entry. */
|
first entry. */
|
if (s->size == 0)
|
if (s->size == 0)
|
s->size += PLT_ENTRY_SIZE;
|
s->size += plt_entry_size;
|
|
|
h->plt.offset = s->size;
|
h->plt.offset = s->size;
|
|
|
/* If this symbol is not defined in a regular file, and we are
|
/* If this symbol is not defined in a regular file, and we are
|
not generating a shared library, then set the symbol to this
|
not generating a shared library, then set the symbol to this
|
Line 2132... |
Line 2272... |
h->root.u.def.section = s;
|
h->root.u.def.section = s;
|
h->root.u.def.value = h->plt.offset;
|
h->root.u.def.value = h->plt.offset;
|
}
|
}
|
|
|
/* Make room for this entry. */
|
/* Make room for this entry. */
|
s->size += PLT_ENTRY_SIZE;
|
s->size += plt_entry_size;
|
|
|
/* We also need to make an entry in the .got.plt section, which
|
/* We also need to make an entry in the .got.plt section, which
|
will be placed in the .got section by the linker script. */
|
will be placed in the .got section by the linker script. */
|
htab->elf.sgotplt->size += 4;
|
htab->elf.sgotplt->size += 4;
|
|
|
/* We also need to make an entry in the .rel.plt section. */
|
/* We also need to make an entry in the .rel.plt section. */
|
htab->elf.srelplt->size += sizeof (Elf32_External_Rel);
|
htab->elf.srelplt->size += sizeof (Elf32_External_Rel);
|
htab->next_tls_desc_index++;
|
htab->next_tls_desc_index++;
|
|
|
if (htab->is_vxworks && !info->shared)
|
if (get_elf_i386_backend_data (info->output_bfd)->is_vxworks
|
|
&& !info->shared)
|
{
|
{
|
/* VxWorks has a second set of relocations for each PLT entry
|
/* VxWorks has a second set of relocations for each PLT entry
|
in executables. They go in a separate relocation section,
|
in executables. They go in a separate relocation section,
|
which is processed by the kernel loader. */
|
which is processed by the kernel loader. */
|
|
|
/* There are two relocations for the initial PLT entry: an
|
/* There are two relocations for the initial PLT entry: an
|
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. */
|
|
|
if (h->plt.offset == PLT_ENTRY_SIZE)
|
if (h->plt.offset == plt_entry_size)
|
htab->srelplt2->size += (sizeof (Elf32_External_Rel) * 2);
|
htab->srelplt2->size += (sizeof (Elf32_External_Rel) * 2);
|
|
|
/* There are two extra relocations for each subsequent PLT entry:
|
/* There are two extra relocations for each subsequent PLT entry:
|
an R_386_32 relocation for the GOT entry, and an R_386_32
|
an R_386_32 relocation for the GOT entry, and an R_386_32
|
relocation for the PLT entry. */
|
relocation for the PLT entry. */
|
Line 2272... |
Line 2413... |
else
|
else
|
pp = &p->next;
|
pp = &p->next;
|
}
|
}
|
}
|
}
|
|
|
if (htab->is_vxworks)
|
if (get_elf_i386_backend_data (info->output_bfd)->is_vxworks)
|
{
|
{
|
struct elf_dyn_relocs **pp;
|
struct elf_dyn_relocs **pp;
|
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
|
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
|
{
|
{
|
if (strcmp (p->sec->output_section->name, ".tls_vars") == 0)
|
if (strcmp (p->sec->output_section->name, ".tls_vars") == 0)
|
Line 2406... |
Line 2547... |
}
|
}
|
|
|
/* Set the sizes of the dynamic sections. */
|
/* Set the sizes of the dynamic sections. */
|
|
|
static bfd_boolean
|
static bfd_boolean
|
elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
|
struct bfd_link_info *info)
|
|
{
|
{
|
struct elf_i386_link_hash_table *htab;
|
struct elf_i386_link_hash_table *htab;
|
bfd *dynobj;
|
bfd *dynobj;
|
asection *s;
|
asection *s;
|
bfd_boolean relocs;
|
bfd_boolean relocs;
|
Line 2467... |
Line 2607... |
/* Input section has been discarded, either because
|
/* Input section has been discarded, either because
|
it is a copy of a linkonce section or due to
|
it is a copy of a linkonce section or due to
|
linker script /DISCARD/, so we'll be discarding
|
linker script /DISCARD/, so we'll be discarding
|
the relocs too. */
|
the relocs too. */
|
}
|
}
|
else if (htab->is_vxworks
|
else if (get_elf_i386_backend_data (output_bfd)->is_vxworks
|
&& strcmp (p->sec->output_section->name,
|
&& strcmp (p->sec->output_section->name,
|
".tls_vars") == 0)
|
".tls_vars") == 0)
|
{
|
{
|
/* Relocations in vxworks .tls_vars sections are
|
/* Relocations in vxworks .tls_vars sections are
|
handled specially by the loader. */
|
handled specially by the loader. */
|
Line 2665... |
Line 2805... |
s->contents = (unsigned char *) bfd_zalloc (dynobj, s->size);
|
s->contents = (unsigned char *) bfd_zalloc (dynobj, s->size);
|
if (s->contents == NULL)
|
if (s->contents == NULL)
|
return FALSE;
|
return FALSE;
|
}
|
}
|
|
|
|
if (htab->plt_eh_frame != NULL
|
|
&& htab->elf.splt != NULL
|
|
&& htab->elf.splt->size != 0
|
|
&& (htab->elf.splt->flags & SEC_EXCLUDE) == 0)
|
|
bfd_put_32 (dynobj, htab->elf.splt->size,
|
|
htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET);
|
|
|
if (htab->elf.dynamic_sections_created)
|
if (htab->elf.dynamic_sections_created)
|
{
|
{
|
/* Add some entries to the .dynamic section. We fill in the
|
/* Add some entries to the .dynamic section. We fill in the
|
values later, in elf_i386_finish_dynamic_sections, but we
|
values later, in elf_i386_finish_dynamic_sections, but we
|
must add the entries now so that we get the correct size for
|
must add the entries now so that we get the correct size for
|
Line 2709... |
Line 2856... |
{
|
{
|
if (!add_dynamic_entry (DT_TEXTREL, 0))
|
if (!add_dynamic_entry (DT_TEXTREL, 0))
|
return FALSE;
|
return FALSE;
|
}
|
}
|
}
|
}
|
if (htab->is_vxworks
|
if (get_elf_i386_backend_data (output_bfd)->is_vxworks
|
&& !elf_vxworks_add_dynamic_entries (output_bfd, info))
|
&& !elf_vxworks_add_dynamic_entries (output_bfd, info))
|
return FALSE;
|
return FALSE;
|
}
|
}
|
#undef add_dynamic_entry
|
#undef add_dynamic_entry
|
|
|
Line 2872... |
Line 3019... |
bfd_vma *local_got_offsets;
|
bfd_vma *local_got_offsets;
|
bfd_vma *local_tlsdesc_gotents;
|
bfd_vma *local_tlsdesc_gotents;
|
Elf_Internal_Rela *rel;
|
Elf_Internal_Rela *rel;
|
Elf_Internal_Rela *relend;
|
Elf_Internal_Rela *relend;
|
bfd_boolean is_vxworks_tls;
|
bfd_boolean is_vxworks_tls;
|
|
unsigned plt_entry_size;
|
|
|
BFD_ASSERT (is_i386_elf (input_bfd));
|
BFD_ASSERT (is_i386_elf (input_bfd));
|
|
|
htab = elf_i386_hash_table (info);
|
htab = elf_i386_hash_table (info);
|
if (htab == NULL)
|
if (htab == NULL)
|
Line 2884... |
Line 3032... |
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);
|
local_tlsdesc_gotents = elf_i386_local_tlsdesc_gotent (input_bfd);
|
local_tlsdesc_gotents = elf_i386_local_tlsdesc_gotent (input_bfd);
|
/* We have to handle relocations in vxworks .tls_vars sections
|
/* We have to handle relocations in vxworks .tls_vars sections
|
specially, because the dynamic loader is 'weird'. */
|
specially, because the dynamic loader is 'weird'. */
|
is_vxworks_tls = (htab->is_vxworks && info->shared
|
is_vxworks_tls = (get_elf_i386_backend_data (output_bfd)->is_vxworks
|
|
&& info->shared
|
&& !strcmp (input_section->output_section->name,
|
&& !strcmp (input_section->output_section->name,
|
".tls_vars"));
|
".tls_vars"));
|
|
|
elf_i386_set_tls_module_base (info);
|
elf_i386_set_tls_module_base (info);
|
|
|
|
plt_entry_size = GET_PLT_ENTRY_SIZE (output_bfd);
|
|
|
rel = relocs;
|
rel = relocs;
|
relend = relocs + input_section->reloc_count;
|
relend = relocs + input_section->reloc_count;
|
for (; rel < relend; rel++)
|
for (; rel < relend; rel++)
|
{
|
{
|
unsigned int r_type;
|
unsigned int r_type;
|
Line 3156... |
Line 3307... |
even just remember the offset, as finish_dynamic_symbol
|
even just remember the offset, as finish_dynamic_symbol
|
would use that as offset into .got. */
|
would use that as offset into .got. */
|
|
|
if (htab->elf.splt != NULL)
|
if (htab->elf.splt != NULL)
|
{
|
{
|
plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1;
|
plt_index = h->plt.offset / plt_entry_size - 1;
|
off = (plt_index + 3) * 4;
|
off = (plt_index + 3) * 4;
|
base_got = htab->elf.sgotplt;
|
base_got = htab->elf.sgotplt;
|
}
|
}
|
else
|
else
|
{
|
{
|
plt_index = h->plt.offset / PLT_ENTRY_SIZE;
|
plt_index = h->plt.offset / plt_entry_size;
|
off = plt_index * 4;
|
off = plt_index * 4;
|
base_got = htab->elf.igotplt;
|
base_got = htab->elf.igotplt;
|
}
|
}
|
|
|
if (h->dynindx == -1
|
if (h->dynindx == -1
|
Line 4158... |
Line 4309... |
struct bfd_link_info *info,
|
struct bfd_link_info *info,
|
struct elf_link_hash_entry *h,
|
struct elf_link_hash_entry *h,
|
Elf_Internal_Sym *sym)
|
Elf_Internal_Sym *sym)
|
{
|
{
|
struct elf_i386_link_hash_table *htab;
|
struct elf_i386_link_hash_table *htab;
|
|
unsigned plt_entry_size;
|
|
const struct elf_i386_backend_data *abed;
|
|
|
htab = elf_i386_hash_table (info);
|
htab = elf_i386_hash_table (info);
|
if (htab == NULL)
|
if (htab == NULL)
|
return FALSE;
|
return FALSE;
|
|
|
|
abed = get_elf_i386_backend_data (output_bfd);
|
|
plt_entry_size = GET_PLT_ENTRY_SIZE (output_bfd);
|
|
|
if (h->plt.offset != (bfd_vma) -1)
|
if (h->plt.offset != (bfd_vma) -1)
|
{
|
{
|
bfd_vma plt_index;
|
bfd_vma plt_index;
|
bfd_vma got_offset;
|
bfd_vma got_offset;
|
Elf_Internal_Rela rel;
|
Elf_Internal_Rela rel;
|
Line 4211... |
Line 4367... |
|
|
For static executables, we don't reserve anything. */
|
For static executables, we don't reserve anything. */
|
|
|
if (plt == htab->elf.splt)
|
if (plt == htab->elf.splt)
|
{
|
{
|
plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1;
|
plt_index = h->plt.offset / plt_entry_size - 1;
|
got_offset = (plt_index + 3) * 4;
|
got_offset = (plt_index + 3) * 4;
|
}
|
}
|
else
|
else
|
{
|
{
|
plt_index = h->plt.offset / PLT_ENTRY_SIZE;
|
plt_index = h->plt.offset / plt_entry_size;
|
got_offset = plt_index * 4;
|
got_offset = plt_index * 4;
|
}
|
}
|
|
|
/* Fill in the entry in the procedure linkage table. */
|
/* Fill in the entry in the procedure linkage table. */
|
if (! info->shared)
|
if (! info->shared)
|
{
|
{
|
memcpy (plt->contents + h->plt.offset, elf_i386_plt_entry,
|
memcpy (plt->contents + h->plt.offset, abed->plt->plt_entry,
|
PLT_ENTRY_SIZE);
|
abed->plt->plt_entry_size);
|
bfd_put_32 (output_bfd,
|
bfd_put_32 (output_bfd,
|
(gotplt->output_section->vma
|
(gotplt->output_section->vma
|
+ gotplt->output_offset
|
+ gotplt->output_offset
|
+ got_offset),
|
+ got_offset),
|
plt->contents + h->plt.offset + 2);
|
plt->contents + h->plt.offset
|
|
+ abed->plt->plt_got_offset);
|
|
|
if (htab->is_vxworks)
|
if (abed->is_vxworks)
|
{
|
{
|
int s, k, reloc_index;
|
int s, k, reloc_index;
|
|
|
/* Create the R_386_32 relocation referencing the GOT
|
/* Create the R_386_32 relocation referencing the GOT
|
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_ENTRY_SIZE) / PLT_ENTRY_SIZE;
|
s = ((h->plt.offset - abed->plt->plt_entry_size)
|
|
/ abed->plt->plt_entry_size);
|
/* K: Number of relocations for PLTResolve. */
|
/* K: Number of relocations for PLTResolve. */
|
if (info->shared)
|
if (info->shared)
|
k = PLTRESOLVE_RELOCS_SHLIB;
|
k = PLTRESOLVE_RELOCS_SHLIB;
|
else
|
else
|
k = PLTRESOLVE_RELOCS;
|
k = PLTRESOLVE_RELOCS;
|
Line 4269... |
Line 4427... |
loc + sizeof (Elf32_External_Rel));
|
loc + sizeof (Elf32_External_Rel));
|
}
|
}
|
}
|
}
|
else
|
else
|
{
|
{
|
memcpy (plt->contents + h->plt.offset, elf_i386_pic_plt_entry,
|
memcpy (plt->contents + h->plt.offset, abed->plt->pic_plt_entry,
|
PLT_ENTRY_SIZE);
|
abed->plt->plt_entry_size);
|
bfd_put_32 (output_bfd, got_offset,
|
bfd_put_32 (output_bfd, got_offset,
|
plt->contents + h->plt.offset + 2);
|
plt->contents + h->plt.offset
|
|
+ abed->plt->plt_got_offset);
|
}
|
}
|
|
|
/* Don't fill PLT entry for static executables. */
|
/* Don't fill PLT entry for static executables. */
|
if (plt == htab->elf.splt)
|
if (plt == htab->elf.splt)
|
{
|
{
|
bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rel),
|
bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rel),
|
plt->contents + h->plt.offset + 7);
|
plt->contents + h->plt.offset
|
bfd_put_32 (output_bfd, - (h->plt.offset + PLT_ENTRY_SIZE),
|
+ abed->plt->plt_reloc_offset);
|
plt->contents + h->plt.offset + 12);
|
bfd_put_32 (output_bfd, - (h->plt.offset
|
|
+ abed->plt->plt_plt_offset + 4),
|
|
plt->contents + h->plt.offset
|
|
+ abed->plt->plt_plt_offset);
|
}
|
}
|
|
|
/* Fill in the entry in the global offset table. */
|
/* Fill in the entry in the global offset table. */
|
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
|
+ 6),
|
+ abed->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. */
|
rel.r_offset = (gotplt->output_section->vma
|
rel.r_offset = (gotplt->output_section->vma
|
+ gotplt->output_offset
|
+ gotplt->output_offset
|
Line 4430... |
Line 4592... |
|
|
On VxWorks, the _GLOBAL_OFFSET_TABLE_ symbol is not absolute: it
|
On VxWorks, the _GLOBAL_OFFSET_TABLE_ symbol is not absolute: it
|
is relative to the ".got" section. */
|
is relative to the ".got" section. */
|
if (sym != NULL
|
if (sym != NULL
|
&& (strcmp (h->root.root.string, "_DYNAMIC") == 0
|
&& (strcmp (h->root.root.string, "_DYNAMIC") == 0
|
|| (!htab->is_vxworks && h == htab->elf.hgot)))
|
|| (!abed->is_vxworks
|
|
&& h == htab->elf.hgot)))
|
sym->st_shndx = SHN_ABS;
|
sym->st_shndx = SHN_ABS;
|
|
|
return TRUE;
|
return TRUE;
|
}
|
}
|
|
|
Line 4479... |
Line 4642... |
struct bfd_link_info *info)
|
struct bfd_link_info *info)
|
{
|
{
|
struct elf_i386_link_hash_table *htab;
|
struct elf_i386_link_hash_table *htab;
|
bfd *dynobj;
|
bfd *dynobj;
|
asection *sdyn;
|
asection *sdyn;
|
|
const struct elf_i386_backend_data *abed;
|
|
|
htab = elf_i386_hash_table (info);
|
htab = elf_i386_hash_table (info);
|
if (htab == NULL)
|
if (htab == NULL)
|
return FALSE;
|
return FALSE;
|
|
|
dynobj = htab->elf.dynobj;
|
dynobj = htab->elf.dynobj;
|
sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
|
sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
|
|
abed = get_elf_i386_backend_data (output_bfd);
|
|
|
if (htab->elf.dynamic_sections_created)
|
if (htab->elf.dynamic_sections_created)
|
{
|
{
|
Elf32_External_Dyn *dyncon, *dynconend;
|
Elf32_External_Dyn *dyncon, *dynconend;
|
|
|
Line 4506... |
Line 4671... |
bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
|
bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
|
|
|
switch (dyn.d_tag)
|
switch (dyn.d_tag)
|
{
|
{
|
default:
|
default:
|
if (htab->is_vxworks
|
if (abed->is_vxworks
|
&& elf_vxworks_finish_dynamic_entry (output_bfd, &dyn))
|
&& elf_vxworks_finish_dynamic_entry (output_bfd, &dyn))
|
break;
|
break;
|
continue;
|
continue;
|
|
|
case DT_PLTGOT:
|
case DT_PLTGOT:
|
Line 4560... |
Line 4725... |
/* Fill in the first entry in the procedure linkage table. */
|
/* Fill in the first entry in the procedure linkage table. */
|
if (htab->elf.splt && htab->elf.splt->size > 0)
|
if (htab->elf.splt && htab->elf.splt->size > 0)
|
{
|
{
|
if (info->shared)
|
if (info->shared)
|
{
|
{
|
memcpy (htab->elf.splt->contents, elf_i386_pic_plt0_entry,
|
memcpy (htab->elf.splt->contents, abed->plt->pic_plt0_entry,
|
sizeof (elf_i386_pic_plt0_entry));
|
abed->plt->plt0_entry_size);
|
memset (htab->elf.splt->contents + sizeof (elf_i386_pic_plt0_entry),
|
memset (htab->elf.splt->contents + abed->plt->plt0_entry_size,
|
htab->plt0_pad_byte,
|
abed->plt0_pad_byte,
|
PLT_ENTRY_SIZE - sizeof (elf_i386_pic_plt0_entry));
|
abed->plt->plt_entry_size - abed->plt->plt0_entry_size);
|
}
|
}
|
else
|
else
|
{
|
{
|
memcpy (htab->elf.splt->contents, elf_i386_plt0_entry,
|
memcpy (htab->elf.splt->contents, abed->plt->plt0_entry,
|
sizeof(elf_i386_plt0_entry));
|
abed->plt->plt0_entry_size);
|
memset (htab->elf.splt->contents + sizeof (elf_i386_plt0_entry),
|
memset (htab->elf.splt->contents + abed->plt->plt0_entry_size,
|
htab->plt0_pad_byte,
|
abed->plt0_pad_byte,
|
PLT_ENTRY_SIZE - sizeof (elf_i386_plt0_entry));
|
abed->plt->plt_entry_size - abed->plt->plt0_entry_size);
|
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
|
+ 4),
|
+ 4),
|
htab->elf.splt->contents + 2);
|
htab->elf.splt->contents
|
|
+ abed->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 + 8);
|
htab->elf.splt->contents
|
|
+ abed->plt->plt0_got2_offset);
|
|
|
if (htab->is_vxworks)
|
if (abed->is_vxworks)
|
{
|
{
|
Elf_Internal_Rela rel;
|
Elf_Internal_Rela rel;
|
|
|
/* Generate a relocation for _GLOBAL_OFFSET_TABLE_ + 4.
|
/* Generate a relocation for _GLOBAL_OFFSET_TABLE_ + 4.
|
On IA32 we use REL relocations so the addend goes in
|
On IA32 we use REL relocations so the addend goes in
|
the PLT directly. */
|
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
|
+ 2);
|
+ abed->plt->plt0_got1_offset);
|
rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32);
|
rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32);
|
bfd_elf32_swap_reloc_out (output_bfd, &rel,
|
bfd_elf32_swap_reloc_out (output_bfd, &rel,
|
htab->srelplt2->contents);
|
htab->srelplt2->contents);
|
/* Generate a relocation for _GLOBAL_OFFSET_TABLE_ + 8. */
|
/* Generate a relocation for _GLOBAL_OFFSET_TABLE_ + 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
|
+ 8);
|
+ abed->plt->plt0_got2_offset);
|
rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32);
|
rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32);
|
bfd_elf32_swap_reloc_out (output_bfd, &rel,
|
bfd_elf32_swap_reloc_out (output_bfd, &rel,
|
htab->srelplt2->contents +
|
htab->srelplt2->contents +
|
sizeof (Elf32_External_Rel));
|
sizeof (Elf32_External_Rel));
|
}
|
}
|
Line 4614... |
Line 4781... |
really seem like the right value. */
|
really seem like the right value. */
|
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;
|
|
|
/* Correct the .rel.plt.unloaded relocations. */
|
/* Correct the .rel.plt.unloaded relocations. */
|
if (htab->is_vxworks && !info->shared)
|
if (abed->is_vxworks && !info->shared)
|
{
|
{
|
int num_plts = (htab->elf.splt->size / PLT_ENTRY_SIZE) - 1;
|
int num_plts = (htab->elf.splt->size
|
|
/ abed->plt->plt_entry_size) - 1;
|
unsigned char *p;
|
unsigned char *p;
|
|
|
p = htab->srelplt2->contents;
|
p = htab->srelplt2->contents;
|
if (info->shared)
|
if (info->shared)
|
p += PLTRESOLVE_RELOCS_SHLIB * sizeof (Elf32_External_Rel);
|
p += PLTRESOLVE_RELOCS_SHLIB * sizeof (Elf32_External_Rel);
|
Line 4665... |
Line 4833... |
}
|
}
|
|
|
elf_section_data (htab->elf.sgotplt->output_section)->this_hdr.sh_entsize = 4;
|
elf_section_data (htab->elf.sgotplt->output_section)->this_hdr.sh_entsize = 4;
|
}
|
}
|
|
|
|
/* Adjust .eh_frame for .plt section. */
|
|
if (htab->plt_eh_frame != NULL)
|
|
{
|
|
if (htab->elf.splt != NULL
|
|
&& htab->elf.splt->size != 0
|
|
&& (htab->elf.splt->flags & SEC_EXCLUDE) == 0
|
|
&& htab->elf.splt->output_section != NULL
|
|
&& htab->plt_eh_frame->output_section != NULL)
|
|
{
|
|
bfd_vma plt_start = htab->elf.splt->output_section->vma;
|
|
bfd_vma eh_frame_start = htab->plt_eh_frame->output_section->vma
|
|
+ htab->plt_eh_frame->output_offset
|
|
+ PLT_FDE_START_OFFSET;
|
|
bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
|
|
htab->plt_eh_frame->contents
|
|
+ PLT_FDE_START_OFFSET);
|
|
}
|
|
if (htab->plt_eh_frame->sec_info_type
|
|
== ELF_INFO_TYPE_EH_FRAME)
|
|
{
|
|
if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
|
|
htab->plt_eh_frame,
|
|
htab->plt_eh_frame->contents))
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
if (htab->elf.sgot && htab->elf.sgot->size > 0)
|
if (htab->elf.sgot && htab->elf.sgot->size > 0)
|
elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 4;
|
elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 4;
|
|
|
/* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols. */
|
/* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols. */
|
htab_traverse (htab->loc_hash_table,
|
htab_traverse (htab->loc_hash_table,
|
Line 4683... |
Line 4878... |
|
|
static bfd_vma
|
static bfd_vma
|
elf_i386_plt_sym_val (bfd_vma i, const asection *plt,
|
elf_i386_plt_sym_val (bfd_vma i, const asection *plt,
|
const arelent *rel ATTRIBUTE_UNUSED)
|
const arelent *rel ATTRIBUTE_UNUSED)
|
{
|
{
|
return plt->vma + (i + 1) * PLT_ENTRY_SIZE;
|
return plt->vma + (i + 1) * GET_PLT_ENTRY_SIZE (plt->owner);
|
}
|
}
|
|
|
/* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */
|
/* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */
|
|
|
static bfd_boolean
|
static bfd_boolean
|
Line 4732... |
Line 4927... |
#define elf_backend_can_refcount 1
|
#define elf_backend_can_refcount 1
|
#define elf_backend_want_got_plt 1
|
#define elf_backend_want_got_plt 1
|
#define elf_backend_plt_readonly 1
|
#define elf_backend_plt_readonly 1
|
#define elf_backend_want_plt_sym 0
|
#define elf_backend_want_plt_sym 0
|
#define elf_backend_got_header_size 12
|
#define elf_backend_got_header_size 12
|
|
#define elf_backend_plt_alignment 4
|
|
|
/* Support RELA for objdump of prelink objects. */
|
/* Support RELA for objdump of prelink objects. */
|
#define elf_info_to_howto elf_i386_info_to_howto_rel
|
#define elf_info_to_howto elf_i386_info_to_howto_rel
|
#define elf_info_to_howto_rel elf_i386_info_to_howto_rel
|
#define elf_info_to_howto_rel elf_i386_info_to_howto_rel
|
|
|
Line 4832... |
Line 5028... |
#undef elf_backend_want_plt_sym
|
#undef elf_backend_want_plt_sym
|
#define elf_backend_want_plt_sym 1
|
#define elf_backend_want_plt_sym 1
|
|
|
#include "elf32-target.h"
|
#include "elf32-target.h"
|
|
|
/* VxWorks support. */
|
/* Native Client support. */
|
|
|
#undef TARGET_LITTLE_SYM
|
#undef TARGET_LITTLE_SYM
|
#define TARGET_LITTLE_SYM bfd_elf32_i386_vxworks_vec
|
#define TARGET_LITTLE_SYM bfd_elf32_i386_nacl_vec
|
#undef TARGET_LITTLE_NAME
|
#undef TARGET_LITTLE_NAME
|
#define TARGET_LITTLE_NAME "elf32-i386-vxworks"
|
#define TARGET_LITTLE_NAME "elf32-i386-nacl"
|
|
#undef elf32_bed
|
|
#define elf32_bed elf32_i386_nacl_bed
|
|
|
|
#undef ELF_MAXPAGESIZE
|
|
#define ELF_MAXPAGESIZE 0x10000
|
|
|
|
/* Restore defaults. */
|
#undef ELF_OSABI
|
#undef ELF_OSABI
|
|
#undef elf_backend_want_plt_sym
|
|
#define elf_backend_want_plt_sym 0
|
|
#undef elf_backend_post_process_headers
|
|
#define elf_backend_post_process_headers _bfd_elf_set_osabi
|
|
#undef elf_backend_static_tls_alignment
|
|
|
/* Like elf_i386_link_hash_table_create but with tweaks for VxWorks. */
|
/* NaCl uses substantially different PLT entries for the same effects. */
|
|
|
static struct bfd_link_hash_table *
|
#undef elf_backend_plt_alignment
|
elf_i386_vxworks_link_hash_table_create (bfd *abfd)
|
#define elf_backend_plt_alignment 5
|
|
#define NACL_PLT_ENTRY_SIZE 64
|
|
#define NACLMASK 0xe0 /* 32-byte alignment mask. */
|
|
|
|
static const bfd_byte elf_i386_nacl_plt0_entry[] =
|
{
|
{
|
struct bfd_link_hash_table *ret;
|
0xff, 0x35, /* pushl contents of address */
|
struct elf_i386_link_hash_table *htab;
|
0, 0, 0, 0, /* replaced with address of .got + 4. */
|
|
0x8b, 0x0d, /* movl contents of address, %ecx */
|
|
0, 0, 0, 0, /* replaced with address of .got + 8. */
|
|
0x83, 0xe1, NACLMASK, /* andl $NACLMASK, %ecx */
|
|
0xff, 0xe1 /* jmp *%ecx */
|
|
};
|
|
|
ret = elf_i386_link_hash_table_create (abfd);
|
static const bfd_byte elf_i386_nacl_plt_entry[NACL_PLT_ENTRY_SIZE] =
|
if (ret)
|
|
{
|
{
|
htab = (struct elf_i386_link_hash_table *) ret;
|
0x8b, 0x0d, /* movl contents of address, %ecx */
|
htab->is_vxworks = 1;
|
0, 0, 0, 0, /* replaced with GOT slot address. */
|
htab->plt0_pad_byte = 0x90;
|
0x83, 0xe1, NACLMASK, /* andl $NACLMASK, %ecx */
|
}
|
0xff, 0xe1, /* jmp *%ecx */
|
|
|
|
/* Pad to the next 32-byte boundary with nop instructions. */
|
|
0x90,
|
|
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
|
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
|
|
return ret;
|
/* Lazy GOT entries point here (32-byte aligned). */
|
}
|
0x68, /* pushl immediate */
|
|
0, 0, 0, 0, /* replaced with reloc offset. */
|
|
0xe9, /* jmp relative */
|
|
0, 0, 0, 0, /* replaced with offset to .plt. */
|
|
|
|
/* Pad to the next 32-byte boundary with nop instructions. */
|
|
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
|
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
|
0x90, 0x90
|
|
};
|
|
|
|
static const bfd_byte
|
|
elf_i386_nacl_pic_plt0_entry[sizeof (elf_i386_nacl_plt0_entry)] =
|
|
{
|
|
0xff, 0x73, 0x04, /* pushl 4(%ebx) */
|
|
0x8b, 0x4b, 0x08, /* mov 0x8(%ebx), %ecx */
|
|
0x83, 0xe1, 0xe0, /* and $NACLMASK, %ecx */
|
|
0xff, 0xe1, /* jmp *%ecx */
|
|
0x90 /* nop */
|
|
};
|
|
|
|
static const bfd_byte elf_i386_nacl_pic_plt_entry[NACL_PLT_ENTRY_SIZE] =
|
|
{
|
|
0x8b, 0x8b, /* movl offset(%ebx), %ecx */
|
|
0, 0, 0, 0, /* replaced with offset of this symbol in .got. */
|
|
0x83, 0xe1, 0xe0, /* andl $NACLMASK, %ecx */
|
|
0xff, 0xe1, /* jmp *%ecx */
|
|
|
|
/* Pad to the next 32-byte boundary with nop instructions. */
|
|
0x90,
|
|
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
|
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
|
|
|
/* Lazy GOT entries point here (32-byte aligned). */
|
|
0x68, /* pushl immediate */
|
|
0, 0, 0, 0, /* replaced with offset into relocation table. */
|
|
0xe9, /* jmp relative */
|
|
0, 0, 0, 0, /* replaced with offset to start of .plt. */
|
|
|
|
/* Pad to the next 32-byte boundary with nop instructions. */
|
|
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
|
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
|
0x90, 0x90
|
|
};
|
|
|
|
static const bfd_byte elf_i386_nacl_eh_frame_plt[] =
|
|
{
|
|
#if (PLT_CIE_LENGTH != 20 \
|
|
|| PLT_FDE_LENGTH != 36 \
|
|
|| PLT_FDE_START_OFFSET != 4 + PLT_CIE_LENGTH + 8 \
|
|
|| PLT_FDE_LEN_OFFSET != 4 + PLT_CIE_LENGTH + 12)
|
|
# error "Need elf_i386_backend_data parameters for eh_frame_plt offsets!"
|
|
#endif
|
|
PLT_CIE_LENGTH, 0, 0, 0, /* CIE length */
|
|
0, 0, 0, 0, /* CIE ID */
|
|
1, /* CIE version */
|
|
'z', 'R', 0, /* Augmentation string */
|
|
1, /* Code alignment factor */
|
|
0x7c, /* Data alignment factor: -4 */
|
|
8, /* Return address column */
|
|
1, /* Augmentation size */
|
|
DW_EH_PE_pcrel | DW_EH_PE_sdata4, /* FDE encoding */
|
|
DW_CFA_def_cfa, 4, 4, /* DW_CFA_def_cfa: r4 (esp) ofs 4 */
|
|
DW_CFA_offset + 8, 1, /* DW_CFA_offset: r8 (eip) at cfa-4 */
|
|
DW_CFA_nop, DW_CFA_nop,
|
|
|
|
PLT_FDE_LENGTH, 0, 0, 0, /* FDE length */
|
|
PLT_CIE_LENGTH + 8, 0, 0, 0, /* CIE pointer */
|
|
0, 0, 0, 0, /* R_386_PC32 .plt goes here */
|
|
0, 0, 0, 0, /* .plt size goes here */
|
|
0, /* Augmentation size */
|
|
DW_CFA_def_cfa_offset, 8, /* DW_CFA_def_cfa_offset: 8 */
|
|
DW_CFA_advance_loc + 6, /* DW_CFA_advance_loc: 6 to __PLT__+6 */
|
|
DW_CFA_def_cfa_offset, 12, /* DW_CFA_def_cfa_offset: 12 */
|
|
DW_CFA_advance_loc + 58, /* DW_CFA_advance_loc: 58 to __PLT__+64 */
|
|
DW_CFA_def_cfa_expression, /* DW_CFA_def_cfa_expression */
|
|
13, /* Block length */
|
|
DW_OP_breg4, 4, /* DW_OP_breg4 (esp): 4 */
|
|
DW_OP_breg8, 0, /* DW_OP_breg8 (eip): 0 */
|
|
DW_OP_const1u, 63, DW_OP_and, DW_OP_const1u, 37, DW_OP_ge,
|
|
DW_OP_lit2, DW_OP_shl, DW_OP_plus,
|
|
DW_CFA_nop, DW_CFA_nop
|
|
};
|
|
|
|
static const struct elf_i386_plt_layout elf_i386_nacl_plt =
|
|
{
|
|
elf_i386_nacl_plt0_entry, /* plt0_entry */
|
|
sizeof (elf_i386_nacl_plt0_entry), /* plt0_entry_size */
|
|
2, /* plt0_got1_offset */
|
|
8, /* plt0_got2_offset */
|
|
elf_i386_nacl_plt_entry, /* plt_entry */
|
|
NACL_PLT_ENTRY_SIZE, /* plt_entry_size */
|
|
2, /* plt_got_offset */
|
|
33, /* plt_reloc_offset */
|
|
38, /* plt_plt_offset */
|
|
32, /* plt_lazy_offset */
|
|
elf_i386_nacl_pic_plt0_entry, /* pic_plt0_entry */
|
|
elf_i386_nacl_pic_plt_entry, /* pic_plt_entry */
|
|
elf_i386_nacl_eh_frame_plt, /* eh_frame_plt */
|
|
sizeof (elf_i386_nacl_eh_frame_plt),/* eh_frame_plt_size */
|
|
};
|
|
|
|
static const struct elf_i386_backend_data elf_i386_nacl_arch_bed =
|
|
{
|
|
&elf_i386_nacl_plt, /* plt */
|
|
0x90, /* plt0_pad_byte: nop insn */
|
|
0, /* is_vxworks */
|
|
};
|
|
|
|
#undef elf_backend_arch_data
|
|
#define elf_backend_arch_data &elf_i386_nacl_arch_bed
|
|
|
|
#include "elf32-target.h"
|
|
|
|
/* VxWorks support. */
|
|
|
|
#undef TARGET_LITTLE_SYM
|
|
#define TARGET_LITTLE_SYM bfd_elf32_i386_vxworks_vec
|
|
#undef TARGET_LITTLE_NAME
|
|
#define TARGET_LITTLE_NAME "elf32-i386-vxworks"
|
|
#undef ELF_OSABI
|
|
#undef elf_backend_plt_alignment
|
|
#define elf_backend_plt_alignment 4
|
|
|
|
static const struct elf_i386_backend_data elf_i386_vxworks_arch_bed =
|
|
{
|
|
&elf_i386_plt, /* plt */
|
|
0x90, /* plt0_pad_byte */
|
|
1, /* is_vxworks */
|
|
};
|
|
|
|
#undef elf_backend_arch_data
|
|
#define elf_backend_arch_data &elf_i386_vxworks_arch_bed
|
|
|
#undef elf_backend_relocs_compatible
|
#undef elf_backend_relocs_compatible
|
#undef elf_backend_post_process_headers
|
#undef elf_backend_post_process_headers
|
#undef bfd_elf32_bfd_link_hash_table_create
|
|
#define bfd_elf32_bfd_link_hash_table_create \
|
|
elf_i386_vxworks_link_hash_table_create
|
|
#undef elf_backend_add_symbol_hook
|
#undef elf_backend_add_symbol_hook
|
#define elf_backend_add_symbol_hook \
|
#define elf_backend_add_symbol_hook \
|
elf_vxworks_add_symbol_hook
|
elf_vxworks_add_symbol_hook
|
#undef elf_backend_link_output_symbol_hook
|
#undef elf_backend_link_output_symbol_hook
|
#define elf_backend_link_output_symbol_hook \
|
#define elf_backend_link_output_symbol_hook \
|