Line 804... |
Line 804... |
/* The (unloaded but important) .rel.plt.unloaded section on VxWorks. */
|
/* The (unloaded but important) .rel.plt.unloaded section on VxWorks. */
|
asection *srelplt2;
|
asection *srelplt2;
|
|
|
/* 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;
|
|
|
|
/* The index of the next unused R_386_JUMP_SLOT slot in .rel.plt. */
|
|
bfd_vma next_jump_slot_index;
|
|
|
|
/* The index of the next unused R_386_IRELATIVE slot in .rel.plt. */
|
|
bfd_vma next_irelative_index;
|
};
|
};
|
|
|
/* 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 944... |
Line 950... |
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->srelplt2 = NULL;
|
ret->srelplt2 = NULL;
|
ret->tls_module_base = NULL;
|
ret->tls_module_base = NULL;
|
|
ret->next_jump_slot_index = 0;
|
|
ret->next_irelative_index = 0;
|
|
|
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,
|
NULL);
|
NULL);
|
Line 1092... |
Line 1100... |
}
|
}
|
else
|
else
|
_bfd_elf_link_hash_copy_indirect (info, dir, ind);
|
_bfd_elf_link_hash_copy_indirect (info, dir, ind);
|
}
|
}
|
|
|
typedef union
|
|
{
|
|
unsigned char c[2];
|
|
uint16_t i;
|
|
}
|
|
i386_opcode16;
|
|
|
|
/* 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. */
|
|
|
static bfd_boolean
|
static bfd_boolean
|
elf_i386_check_tls_transition (bfd *abfd, asection *sec,
|
elf_i386_check_tls_transition (bfd *abfd, asection *sec,
|
Line 1269... |
Line 1270... |
call *x@tlsdesc(%rax)
|
call *x@tlsdesc(%rax)
|
*/
|
*/
|
if (offset + 2 <= sec->size)
|
if (offset + 2 <= sec->size)
|
{
|
{
|
/* Make sure that it's a call *x@tlsdesc(%rax). */
|
/* Make sure that it's a call *x@tlsdesc(%rax). */
|
static i386_opcode16 call = { { 0xff, 0x10 } };
|
static const unsigned char call[] = { 0xff, 0x10 };
|
return bfd_get_16 (abfd, contents + offset) == call.i;
|
return memcmp (contents + offset, call, 2) == 0;
|
}
|
}
|
|
|
return FALSE;
|
return FALSE;
|
|
|
default:
|
default:
|
Line 2280... |
Line 2281... |
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->elf.srelplt->reloc_count++;
|
|
|
if (get_elf_i386_backend_data (info->output_bfd)->is_vxworks
|
if (get_elf_i386_backend_data (info->output_bfd)->is_vxworks
|
&& !info->shared)
|
&& !info->shared)
|
{
|
{
|
/* VxWorks has a second set of relocations for each PLT entry
|
/* VxWorks has a second set of relocations for each PLT entry
|
Line 2705... |
Line 2706... |
|
|
/* For every jump slot reserved in the sgotplt, reloc_count is
|
/* For every jump slot reserved in the sgotplt, reloc_count is
|
incremented. However, when we reserve space for TLS descriptors,
|
incremented. However, when we reserve space for TLS descriptors,
|
it's not incremented, so in order to compute the space reserved
|
it's not incremented, so in order to compute the space reserved
|
for them, it suffices to multiply the reloc count by the jump
|
for them, it suffices to multiply the reloc count by the jump
|
slot size. */
|
slot size.
|
|
|
|
PR ld/13302: We start next_irelative_index at the end of .rela.plt
|
|
so that R_386_IRELATIVE entries come last. */
|
if (htab->elf.srelplt)
|
if (htab->elf.srelplt)
|
|
{
|
|
htab->next_tls_desc_index = htab->elf.srelplt->reloc_count;
|
htab->sgotplt_jump_table_size = htab->next_tls_desc_index * 4;
|
htab->sgotplt_jump_table_size = htab->next_tls_desc_index * 4;
|
|
htab->next_irelative_index = htab->elf.srelplt->reloc_count - 1;
|
|
}
|
|
else if (htab->elf.irelplt)
|
|
htab->next_irelative_index = htab->elf.irelplt->reloc_count - 1;
|
|
|
|
|
if (htab->elf.sgotplt)
|
if (htab->elf.sgotplt)
|
{
|
{
|
struct elf_link_hash_entry *got;
|
struct elf_link_hash_entry *got;
|
got = elf_link_hash_lookup (elf_hash_table (info),
|
got = elf_link_hash_lookup (elf_hash_table (info),
|
Line 3237... |
Line 3248... |
bfd_set_error (bfd_error_bad_value);
|
bfd_set_error (bfd_error_bad_value);
|
return FALSE;
|
return FALSE;
|
|
|
case R_386_32:
|
case R_386_32:
|
/* Generate dynamic relcoation only when there is a
|
/* Generate dynamic relcoation only when there is a
|
non-GOF reference in a shared object. */
|
non-GOT reference in a shared object. */
|
if (info->shared && h->non_got_ref)
|
if (info->shared && h->non_got_ref)
|
{
|
{
|
Elf_Internal_Rela outrel;
|
Elf_Internal_Rela outrel;
|
bfd_byte *loc;
|
bfd_byte *loc;
|
asection *sreloc;
|
asection *sreloc;
|
bfd_vma offset;
|
bfd_vma offset;
|
|
bfd_boolean relocate;
|
|
|
/* Need a dynamic relocation to get the real function
|
/* Need a dynamic relocation to get the real function
|
adddress. */
|
adddress. */
|
offset = _bfd_elf_section_offset (output_bfd,
|
offset = _bfd_elf_section_offset (output_bfd,
|
info,
|
info,
|
Line 3264... |
Line 3276... |
if (h->dynindx == -1
|
if (h->dynindx == -1
|
|| h->forced_local
|
|| h->forced_local
|
|| info->executable)
|
|| info->executable)
|
{
|
{
|
/* This symbol is resolved locally. */
|
/* This symbol is resolved locally. */
|
outrel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE);
|
outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
|
bfd_put_32 (output_bfd,
|
relocate = TRUE;
|
(h->root.u.def.value
|
|
+ h->root.u.def.section->output_section->vma
|
|
+ h->root.u.def.section->output_offset),
|
|
contents + offset);
|
|
}
|
}
|
else
|
else
|
|
{
|
outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
|
outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
|
|
relocate = FALSE;
|
|
}
|
|
|
sreloc = htab->elf.irelifunc;
|
sreloc = htab->elf.irelifunc;
|
loc = sreloc->contents;
|
loc = sreloc->contents;
|
loc += (sreloc->reloc_count++
|
loc += (sreloc->reloc_count++
|
* sizeof (Elf32_External_Rel));
|
* sizeof (Elf32_External_Rel));
|
Line 3285... |
Line 3296... |
/* If this reloc is against an external symbol, we
|
/* If this reloc is against an external symbol, we
|
do not want to fiddle with the addend. Otherwise,
|
do not want to fiddle with the addend. Otherwise,
|
we need to include the symbol value so that it
|
we need to include the symbol value so that it
|
becomes an addend for the dynamic reloc. For an
|
becomes an addend for the dynamic reloc. For an
|
internal symbol, we have updated addend. */
|
internal symbol, we have updated addend. */
|
|
if (! relocate)
|
continue;
|
continue;
|
}
|
}
|
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
case R_386_PC32:
|
case R_386_PC32:
|
case R_386_PLT32:
|
case R_386_PLT32:
|
Line 4242... |
Line 4254... |
/* Dynamic relocs are not propagated for SEC_DEBUGGING sections
|
/* Dynamic relocs are not propagated for SEC_DEBUGGING sections
|
because such sections are not SEC_ALLOC and thus ld.so will
|
because such sections are not SEC_ALLOC and thus ld.so will
|
not process them. */
|
not process them. */
|
if (unresolved_reloc
|
if (unresolved_reloc
|
&& !((input_section->flags & SEC_DEBUGGING) != 0
|
&& !((input_section->flags & SEC_DEBUGGING) != 0
|
&& h->def_dynamic))
|
&& h->def_dynamic)
|
|
&& _bfd_elf_section_offset (output_bfd, info, input_section,
|
|
rel->r_offset) != (bfd_vma) -1)
|
{
|
{
|
(*_bfd_error_handler)
|
(*_bfd_error_handler)
|
(_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
|
(_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
|
input_bfd,
|
input_bfd,
|
input_section,
|
input_section,
|
Line 4367... |
Line 4381... |
|
|
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;
|
got_offset = h->plt.offset / plt_entry_size - 1;
|
got_offset = (plt_index + 3) * 4;
|
got_offset = (got_offset + 3) * 4;
|
}
|
}
|
else
|
else
|
{
|
{
|
plt_index = h->plt.offset / plt_entry_size;
|
got_offset = h->plt.offset / plt_entry_size;
|
got_offset = plt_index * 4;
|
got_offset = got_offset * 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)
|
{
|
{
|
Line 4434... |
Line 4448... |
bfd_put_32 (output_bfd, got_offset,
|
bfd_put_32 (output_bfd, got_offset,
|
plt->contents + h->plt.offset
|
plt->contents + h->plt.offset
|
+ abed->plt->plt_got_offset);
|
+ abed->plt->plt_got_offset);
|
}
|
}
|
|
|
/* Don't fill PLT entry for static executables. */
|
|
if (plt == htab->elf.splt)
|
|
{
|
|
bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rel),
|
|
plt->contents + h->plt.offset
|
|
+ abed->plt->plt_reloc_offset);
|
|
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
|
Line 4473... |
Line 4475... |
(h->root.u.def.value
|
(h->root.u.def.value
|
+ h->root.u.def.section->output_section->vma
|
+ h->root.u.def.section->output_section->vma
|
+ h->root.u.def.section->output_offset),
|
+ h->root.u.def.section->output_offset),
|
gotplt->contents + got_offset);
|
gotplt->contents + got_offset);
|
rel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE);
|
rel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE);
|
|
/* R_386_IRELATIVE comes last. */
|
|
plt_index = htab->next_irelative_index--;
|
}
|
}
|
else
|
else
|
|
{
|
rel.r_info = ELF32_R_INFO (h->dynindx, R_386_JUMP_SLOT);
|
rel.r_info = ELF32_R_INFO (h->dynindx, R_386_JUMP_SLOT);
|
|
plt_index = htab->next_jump_slot_index++;
|
|
}
|
loc = relplt->contents + plt_index * sizeof (Elf32_External_Rel);
|
loc = relplt->contents + plt_index * sizeof (Elf32_External_Rel);
|
bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
|
bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
|
|
|
|
/* Don't fill PLT entry for static executables. */
|
|
if (plt == htab->elf.splt)
|
|
{
|
|
bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rel),
|
|
plt->contents + h->plt.offset
|
|
+ abed->plt->plt_reloc_offset);
|
|
bfd_put_32 (output_bfd, - (h->plt.offset
|
|
+ abed->plt->plt_plt_offset + 4),
|
|
plt->contents + h->plt.offset
|
|
+ abed->plt->plt_plt_offset);
|
|
}
|
|
|
if (!h->def_regular)
|
if (!h->def_regular)
|
{
|
{
|
/* Mark the symbol as undefined, rather than as defined in
|
/* Mark the symbol as undefined, rather than as defined in
|
the .plt section. Leave the value if there were any
|
the .plt section. Leave the value if there were any
|
relocations where pointer equality matters (this is a clue
|
relocations where pointer equality matters (this is a clue
|