Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 6323 → Rev 6324

/contrib/toolchain/binutils/bfd/elf32-i386.c
1,7 → 1,5
/* Intel 80386/80486-specific support for 32-bit ELF
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
Free Software Foundation, Inc.
Copyright (C) 1993-2015 Free Software Foundation, Inc.
 
This file is part of BFD, the Binary File Descriptor library.
 
31,6 → 29,7
#include "objalloc.h"
#include "hashtab.h"
#include "dwarf2.h"
#include "opcode/i386.h"
 
/* 386 uses REL relocations instead of RELA. */
#define USE_REL 1
39,7 → 38,7
 
static reloc_howto_type elf_howto_table[]=
{
HOWTO(R_386_NONE, 0, 0, 0, FALSE, 0, complain_overflow_bitfield,
HOWTO(R_386_NONE, 0, 3, 0, FALSE, 0, complain_overflow_dont,
bfd_elf_generic_reloc, "R_386_NONE",
TRUE, 0x00000000, 0x00000000, FALSE),
HOWTO(R_386_32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
148,10 → 147,13
HOWTO(R_386_IRELATIVE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_386_IRELATIVE",
TRUE, 0xffffffff, 0xffffffff, FALSE),
HOWTO(R_386_GOT32X, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_386_GOT32X",
TRUE, 0xffffffff, 0xffffffff, FALSE),
 
/* Another gap. */
#define R_386_irelative (R_386_IRELATIVE + 1 - R_386_tls_offset)
#define R_386_vt_offset (R_386_GNU_VTINHERIT - R_386_irelative)
#define R_386_ext2 (R_386_GOT32X + 1 - R_386_tls_offset)
#define R_386_vt_offset (R_386_GNU_VTINHERIT - R_386_ext2)
 
/* GNU extension to record C++ vtable hierarchy. */
HOWTO (R_386_GNU_VTINHERIT, /* type */
334,6 → 336,10
TRACE ("BFD_RELOC_386_IRELATIVE");
return &elf_howto_table[R_386_IRELATIVE - R_386_tls_offset];
 
case BFD_RELOC_386_GOT32X:
TRACE ("BFD_RELOC_386_GOT32X");
return &elf_howto_table[R_386_GOT32X - R_386_tls_offset];
 
case BFD_RELOC_VTABLE_INHERIT:
TRACE ("BFD_RELOC_VTABLE_INHERIT");
return &elf_howto_table[R_386_GNU_VTINHERIT - R_386_vt_offset];
373,15 → 379,17
&& ((indx = r_type - R_386_ext_offset) - R_386_standard
>= R_386_ext - R_386_standard)
&& ((indx = r_type - R_386_tls_offset) - R_386_ext
>= R_386_irelative - R_386_ext)
&& ((indx = r_type - R_386_vt_offset) - R_386_irelative
>= R_386_vt - R_386_irelative))
>= R_386_ext2 - R_386_ext)
&& ((indx = r_type - R_386_vt_offset) - R_386_ext2
>= R_386_vt - R_386_ext2))
{
(*_bfd_error_handler) (_("%B: invalid relocation type %d"),
abfd, (int) r_type);
indx = R_386_NONE;
}
BFD_ASSERT (elf_howto_table [indx].type == r_type);
/* PR 17512: file: 0f67f69d. */
if (elf_howto_table [indx].type != r_type)
return NULL;
return &elf_howto_table[indx];
}
 
582,6 → 590,24
0, 0, 0, 0 /* replaced with offset to start of .plt. */
};
 
/* Entries in the GOT procedure linkage table look like this. */
 
static const bfd_byte elf_i386_got_plt_entry[8] =
{
0xff, 0x25, /* jmp indirect */
0, 0, 0, 0, /* replaced with offset of this symbol in .got. */
0x66, 0x90 /* xchg %ax,%ax */
};
 
/* Entries in the PIC GOT procedure linkage table look like this. */
 
static const bfd_byte elf_i386_pic_got_plt_entry[8] =
{
0xff, 0xa3, /* jmp *offset(%ebx) */
0, 0, 0, 0, /* replaced with offset of this symbol in .got. */
0x66, 0x90 /* xchg %ax,%ax */
};
 
/* .eh_frame covering the .plt section. */
 
static const bfd_byte elf_i386_eh_frame_plt[] =
738,6 → 764,17
(GOT_TLS_GD_P (type) || GOT_TLS_GDESC_P (type))
unsigned char tls_type;
 
/* Symbol is referenced by R_386_GOTOFF relocation. */
unsigned int gotoff_ref : 1;
 
/* Reference count of C/C++ function pointer relocations in read-write
section which can be resolved at run-time. */
bfd_signed_vma func_pointer_refcount;
 
/* Information about the GOT PLT entry. Filled when there are both
GOT and PLT relocations against the same function. */
union gotplt_union plt_got;
 
/* Offset of the GOTPLT entry reserved for the TLS descriptor,
starting at the end of the jump table. */
bfd_vma tlsdesc_got;
787,6 → 824,7
asection *sdynbss;
asection *srelbss;
asection *plt_eh_frame;
asection *plt_got;
 
union
{
828,7 → 866,7
== I386_ELF_DATA ? ((struct elf_i386_link_hash_table *) ((p)->hash)) : NULL)
 
#define elf_i386_compute_jump_table_size(htab) \
((htab)->next_tls_desc_index * 4)
((htab)->elf.srelplt->reloc_count * 4)
 
/* Create an entry in an i386 ELF linker hash table. */
 
856,6 → 894,9
eh = (struct elf_i386_link_hash_entry *) entry;
eh->dyn_relocs = NULL;
eh->tls_type = GOT_UNKNOWN;
eh->gotoff_ref = 0;
eh->func_pointer_refcount = 0;
eh->plt_got.offset = (bfd_vma) -1;
eh->tlsdesc_got = (bfd_vma) -1;
}
 
924,11 → 965,28
ret->elf.indx = sec->id;
ret->elf.dynstr_index = ELF32_R_SYM (rel->r_info);
ret->elf.dynindx = -1;
ret->func_pointer_refcount = 0;
ret->plt_got.offset = (bfd_vma) -1;
*slot = ret;
}
return &ret->elf;
}
 
/* Destroy an i386 ELF linker hash table. */
 
static void
elf_i386_link_hash_table_free (bfd *obfd)
{
struct elf_i386_link_hash_table *htab
= (struct elf_i386_link_hash_table *) obfd->link.hash;
 
if (htab->loc_hash_table)
htab_delete (htab->loc_hash_table);
if (htab->loc_hash_memory)
objalloc_free ((struct objalloc *) htab->loc_hash_memory);
_bfd_elf_link_hash_table_free (obfd);
}
 
/* Create an i386 ELF linker hash table. */
 
static struct bfd_link_hash_table *
957,28 → 1015,14
ret->loc_hash_memory = objalloc_create ();
if (!ret->loc_hash_table || !ret->loc_hash_memory)
{
free (ret);
elf_i386_link_hash_table_free (abfd);
return NULL;
}
ret->elf.root.hash_table_free = elf_i386_link_hash_table_free;
 
return &ret->elf.root;
}
 
/* Destroy an i386 ELF linker hash table. */
 
static void
elf_i386_link_hash_table_free (struct bfd_link_hash_table *hash)
{
struct elf_i386_link_hash_table *htab
= (struct elf_i386_link_hash_table *) hash;
 
if (htab->loc_hash_table)
htab_delete (htab->loc_hash_table);
if (htab->loc_hash_memory)
objalloc_free ((struct objalloc *) htab->loc_hash_memory);
_bfd_elf_link_hash_table_free (hash);
}
 
/* Create .plt, .rel.plt, .got, .got.plt, .rel.got, .dynbss, and
.rel.bss sections in DYNOBJ, and set up shortcuts to them in our
hash table. */
996,13 → 1040,28
return FALSE;
 
htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss");
if (!info->shared)
htab->srelbss = bfd_get_linker_section (dynobj, ".rel.bss");
 
if (!htab->sdynbss
|| (!info->shared && !htab->srelbss))
if (!htab->sdynbss)
abort ();
 
if (bfd_link_executable (info))
{
/* Always allow copy relocs for building executables. */
asection *s = bfd_get_linker_section (dynobj, ".rel.bss");
if (s == NULL)
{
const struct elf_backend_data *bed = get_elf_backend_data (dynobj);
s = bfd_make_section_anyway_with_flags (dynobj,
".rel.bss",
(bed->dynamic_sec_flags
| SEC_READONLY));
if (s == NULL
|| ! bfd_set_section_alignment (dynobj, s,
bed->s->log_file_align))
return FALSE;
}
htab->srelbss = s;
}
 
if (get_elf_i386_backend_data (dynobj)->is_vxworks
&& !elf_vxworks_create_dynamic_sections (dynobj, info,
&htab->srelplt2))
1075,6 → 1134,10
eind->tls_type = GOT_UNKNOWN;
}
 
/* Copy gotoff_ref so that elf_i386_adjust_dynamic_symbol will
generate a R_386_COPY reloc. */
edir->gotoff_ref |= eind->gotoff_ref;
 
if (ELIMINATE_COPY_RELOCS
&& ind->root.type != bfd_link_hash_indirect
&& dir->dynamic_adjusted)
1089,8 → 1152,16
dir->pointer_equality_needed |= ind->pointer_equality_needed;
}
else
{
if (eind->func_pointer_refcount > 0)
{
edir->func_pointer_refcount += eind->func_pointer_refcount;
eind->func_pointer_refcount = 0;
}
 
_bfd_elf_link_hash_copy_indirect (info, dir, ind);
}
}
 
/* Return TRUE if the TLS access code sequence support transition
from R_TYPE. */
1305,7 → 1376,7
case R_386_TLS_IE_32:
case R_386_TLS_IE:
case R_386_TLS_GOTIE:
if (info->executable)
if (bfd_link_executable (info))
{
if (h == NULL)
to_type = R_386_TLS_LE_32;
1321,7 → 1392,7
{
unsigned int new_to_type = to_type;
 
if (info->executable
if (bfd_link_executable (info)
&& h != NULL
&& h->dynindx == -1
&& (tls_type & GOT_TLS_IE))
1347,7 → 1418,7
break;
 
case R_386_TLS_LDM:
if (info->executable)
if (bfd_link_executable (info))
to_type = R_386_TLS_LE_32;
break;
 
1403,6 → 1474,10
return TRUE;
}
 
/* Rename some of the generic section flags to better document how they
are used here. */
#define need_convert_load sec_flg0
 
/* Look through the relocs for a section during the first phase, and
calculate needed space in the global offset table, procedure linkage
table, and dynamic reloc sections. */
1419,8 → 1494,9
const Elf_Internal_Rela *rel;
const Elf_Internal_Rela *rel_end;
asection *sreloc;
bfd_boolean use_plt_got;
 
if (info->relocatable)
if (bfd_link_relocatable (info))
return TRUE;
 
BFD_ASSERT (is_i386_elf (abfd));
1429,6 → 1505,10
if (htab == NULL)
return FALSE;
 
use_plt_got = (!get_elf_i386_backend_data (abfd)->is_vxworks
&& (get_elf_i386_backend_data (abfd)
== &elf_i386_arch_bed));
 
symtab_hdr = &elf_symtab_hdr (abfd);
sym_hashes = elf_sym_hashes (abfd);
 
1440,6 → 1520,7
unsigned int r_type;
unsigned long r_symndx;
struct elf_link_hash_entry *h;
struct elf_i386_link_hash_entry *eh;
Elf_Internal_Sym *isym;
const char *name;
bfd_boolean size_reloc;
1489,6 → 1570,7
h = (struct elf_link_hash_entry *) h->root.u.i.link;
}
 
eh = (struct elf_i386_link_hash_entry *) h;
if (h != NULL)
{
/* Create the ifunc sections for static executables. If we
1500,11 → 1582,13
default:
break;
 
case R_386_GOTOFF:
eh->gotoff_ref = 1;
case R_386_32:
case R_386_PC32:
case R_386_PLT32:
case R_386_GOT32:
case R_386_GOTOFF:
case R_386_GOT32X:
if (htab->elf.dynobj == NULL)
htab->elf.dynobj = abfd;
if (!_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
1515,6 → 1599,10
/* It is referenced by a non-shared object. */
h->ref_regular = 1;
h->root.non_ir_ref = 1;
 
if (h->type == STT_GNU_IFUNC)
elf_tdata (info->output_bfd)->has_gnu_symbols
|= elf_gnu_symbol_ifunc;
}
 
if (! elf_i386_tls_transition (info, abfd, sec, NULL,
1553,11 → 1641,12
case R_386_TLS_IE_32:
case R_386_TLS_IE:
case R_386_TLS_GOTIE:
if (!info->executable)
if (!bfd_link_executable (info))
info->flags |= DF_STATIC_TLS;
/* Fall through */
 
case R_386_GOT32:
case R_386_GOT32X:
case R_386_TLS_GD:
case R_386_TLS_GOTDESC:
case R_386_TLS_DESC_CALL:
1568,7 → 1657,10
switch (r_type)
{
default:
case R_386_GOT32: tls_type = GOT_NORMAL; break;
case R_386_GOT32:
case R_386_GOT32X:
tls_type = GOT_NORMAL;
break;
case R_386_TLS_GD: tls_type = GOT_TLS_GD; break;
case R_386_TLS_GOTDESC:
case R_386_TLS_DESC_CALL:
1673,7 → 1765,7
 
case R_386_TLS_LE_32:
case R_386_TLS_LE:
if (info->executable)
if (bfd_link_executable (info))
break;
info->flags |= DF_STATIC_TLS;
/* Fall through */
1680,7 → 1772,7
 
case R_386_32:
case R_386_PC32:
if (h != NULL && info->executable)
if (h != NULL && bfd_link_executable (info))
{
/* If this reloc is in a read-only section, we might
need a copy reloc. We can't check reliably at this
1693,9 → 1785,23
/* We may need a .plt entry if the function this reloc
refers to is in a shared lib. */
h->plt.refcount += 1;
if (r_type != R_386_PC32)
if (r_type == R_386_PC32)
{
/* Since something like ".long foo - ." may be used
as pointer, make sure that PLT is used if foo is
a function defined in a shared library. */
if ((sec->flags & SEC_CODE) == 0)
h->pointer_equality_needed = 1;
}
else
{
h->pointer_equality_needed = 1;
/* R_386_32 can be resolved at run-time. */
if (r_type == R_386_32
&& (sec->flags & SEC_READONLY) == 0)
eh->func_pointer_refcount += 1;
}
}
 
size_reloc = FALSE;
do_size:
1720,7 → 1826,7
may need to keep relocations for symbols satisfied by a
dynamic library if we manage to avoid copy relocs for the
symbol. */
if ((info->shared
if ((bfd_link_pic (info)
&& (sec->flags & SEC_ALLOC) != 0
&& (r_type != R_386_PC32
|| (h != NULL
1728,7 → 1834,7
|| h->root.type == bfd_link_hash_defweak
|| !h->def_regular))))
|| (ELIMINATE_COPY_RELOCS
&& !info->shared
&& !bfd_link_pic (info)
&& (sec->flags & SEC_ALLOC) != 0
&& h != NULL
&& (h->root.type == bfd_link_hash_defweak
1756,7 → 1862,7
relocations we need for this symbol. */
if (h != NULL)
{
head = &((struct elf_i386_link_hash_entry *) h)->dyn_relocs;
head = &eh->dyn_relocs;
}
else
{
1820,8 → 1926,46
default:
break;
}
 
if (use_plt_got
&& h != NULL
&& h->plt.refcount > 0
&& (((info->flags & DF_BIND_NOW) && !h->pointer_equality_needed)
|| h->got.refcount > 0)
&& htab->plt_got == NULL)
{
/* Create the GOT procedure linkage table. */
unsigned int plt_got_align;
const struct elf_backend_data *bed;
 
bed = get_elf_backend_data (info->output_bfd);
BFD_ASSERT (sizeof (elf_i386_got_plt_entry) == 8
&& (sizeof (elf_i386_got_plt_entry)
== sizeof (elf_i386_pic_got_plt_entry)));
plt_got_align = 3;
 
if (htab->elf.dynobj == NULL)
htab->elf.dynobj = abfd;
htab->plt_got
= bfd_make_section_anyway_with_flags (htab->elf.dynobj,
".plt.got",
(bed->dynamic_sec_flags
| SEC_ALLOC
| SEC_CODE
| SEC_LOAD
| SEC_READONLY));
if (htab->plt_got == NULL
|| !bfd_set_section_alignment (htab->elf.dynobj,
htab->plt_got,
plt_got_align))
return FALSE;
}
 
if ((r_type == R_386_GOT32 || r_type == R_386_GOT32X)
&& (h == NULL || h->type != STT_GNU_IFUNC))
sec->need_convert_load = 1;
}
 
return TRUE;
}
 
1860,7 → 2004,7
bfd_signed_vma *local_got_refcounts;
const Elf_Internal_Rela *rel, *relend;
 
if (info->relocatable)
if (bfd_link_relocatable (info))
return TRUE;
 
htab = elf_i386_hash_table (info);
1943,6 → 2087,7
case R_386_TLS_IE:
case R_386_TLS_GOTIE:
case R_386_GOT32:
case R_386_GOT32X:
if (h != NULL)
{
if (h->got.refcount > 0)
1963,7 → 2108,7
case R_386_32:
case R_386_PC32:
case R_386_SIZE32:
if (info->shared
if (bfd_link_pic (info)
&& (h == NULL || h->type != STT_GNU_IFUNC))
break;
/* Fall through */
1973,7 → 2118,15
{
if (h->plt.refcount > 0)
h->plt.refcount -= 1;
if (r_type == R_386_32
&& (sec->flags & SEC_READONLY) == 0)
{
struct elf_i386_link_hash_entry *eh
= (struct elf_i386_link_hash_entry *) h;
if (eh->func_pointer_refcount > 0)
eh->func_pointer_refcount -= 1;
}
}
break;
 
case R_386_GOTOFF:
2103,12 → 2256,14
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 (info->shared)
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)
GOT nor R_386_GOTOFF relocation, we don't need to generate a copy
reloc. */
eh = (struct elf_i386_link_hash_entry *) h;
if (!h->non_got_ref && !eh->gotoff_ref)
return TRUE;
 
/* If -z nocopyreloc was given, we won't generate them either. */
2122,14 → 2277,15
if (htab == NULL)
return FALSE;
 
/* If there aren't any dynamic relocs in read-only sections, then
we can keep the dynamic relocs and avoid the copy reloc. This
doesn't work on VxWorks, where we can not have dynamic relocations
(other than copy and jump slot relocations) in an executable. */
/* If there aren't any dynamic relocs in read-only sections nor
R_386_GOTOFF relocation, then we can keep the dynamic relocs and
avoid the copy reloc. This doesn't work on VxWorks, where we can
not have dynamic relocations (other than copy and jump slot
relocations) in an executable. */
if (ELIMINATE_COPY_RELOCS
&& !eh->gotoff_ref
&& !get_elf_i386_backend_data (info->output_bfd)->is_vxworks)
{
eh = (struct elf_i386_link_hash_entry *) h;
for (p = eh->dyn_relocs; p != NULL; p = p->next)
{
s = p->sec->output_section;
2165,7 → 2321,7
 
s = htab->sdynbss;
 
return _bfd_elf_adjust_dynamic_copy (h, s);
return _bfd_elf_adjust_dynamic_copy (info, h, s);
}
 
/* Allocate space in .plt, .got and associated reloc sections for
2192,6 → 2348,29
 
plt_entry_size = GET_PLT_ENTRY_SIZE (info->output_bfd);
 
/* Clear the reference count of function pointer relocations if
symbol isn't a normal function. */
if (h->type != STT_FUNC)
eh->func_pointer_refcount = 0;
 
/* We can't use the GOT PLT if pointer equality is needed since
finish_dynamic_symbol won't clear symbol value and the dynamic
linker won't update the GOT slot. We will get into an infinite
loop at run-time. */
if (htab->plt_got != NULL
&& h->type != STT_GNU_IFUNC
&& !h->pointer_equality_needed
&& h->plt.refcount > 0
&& h->got.refcount > 0)
{
/* Don't use the regular PLT if there are both GOT and GOTPLT
reloctions. */
h->plt.offset = (bfd_vma) -1;
 
/* Use the GOT PLT. */
eh->plt_got.refcount = 1;
}
 
/* Since STT_GNU_IFUNC symbol must go through PLT, we handle it
here if it is defined and referenced in a non-shared object. */
if (h->type == STT_GNU_IFUNC
2199,9 → 2378,30
return _bfd_elf_allocate_ifunc_dyn_relocs (info, h, &eh->dyn_relocs,
plt_entry_size,
plt_entry_size, 4);
/* Don't create the PLT entry if there are only function pointer
relocations which can be resolved at run-time. */
else if (htab->elf.dynamic_sections_created
&& h->plt.refcount > 0)
&& (h->plt.refcount > eh->func_pointer_refcount
|| eh->plt_got.refcount > 0))
{
bfd_boolean use_plt_got;
 
/* Clear the reference count of function pointer relocations
if PLT is used. */
eh->func_pointer_refcount = 0;
 
if ((info->flags & DF_BIND_NOW) && !h->pointer_equality_needed)
{
/* Don't use the regular PLT for DF_BIND_NOW. */
h->plt.offset = (bfd_vma) -1;
 
/* Use the GOT PLT. */
h->got.refcount = 1;
eh->plt_got.refcount = 1;
}
 
use_plt_got = eh->plt_got.refcount > 0;
 
/* Make sure this symbol is output as a dynamic symbol.
Undefined weak syms won't yet be marked as dynamic. */
if (h->dynindx == -1
2211,16 → 2411,21
return FALSE;
}
 
if (info->shared
if (bfd_link_pic (info)
|| WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h))
{
asection *s = htab->elf.splt;
asection *got_s = htab->plt_got;
 
/* If this is the first .plt entry, make room for the special
first entry. */
first entry. The .plt section is used by prelink to undo
prelinking for dynamic relocations. */
if (s->size == 0)
s->size += plt_entry_size;
s->size = plt_entry_size;
 
if (use_plt_got)
eh->plt_got.offset = got_s->size;
else
h->plt.offset = s->size;
 
/* If this symbol is not defined in a regular file, and we are
2228,26 → 2433,42
location in the .plt. This is required to make function
pointers compare as equal between the normal executable and
the shared library. */
if (! info->shared
if (! bfd_link_pic (info)
&& !h->def_regular)
{
if (use_plt_got)
{
/* We need to make a call to the entry of the GOT PLT
instead of regular PLT entry. */
h->root.u.def.section = got_s;
h->root.u.def.value = eh->plt_got.offset;
}
else
{
h->root.u.def.section = s;
h->root.u.def.value = h->plt.offset;
}
}
 
/* Make room for this entry. */
if (use_plt_got)
got_s->size += sizeof (elf_i386_got_plt_entry);
else
{
s->size += 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 script. */
/* We also need to make an entry in the .got.plt section,
which will be placed in the .got section by the linker
script. */
htab->elf.sgotplt->size += 4;
 
/* We also need to make an entry in the .rel.plt section. */
htab->elf.srelplt->size += sizeof (Elf32_External_Rel);
htab->elf.srelplt->reloc_count++;
}
 
if (get_elf_i386_backend_data (info->output_bfd)->is_vxworks
&& !info->shared)
&& !bfd_link_pic (info))
{
/* VxWorks has a second set of relocations for each PLT entry
in executables. They go in a separate relocation section,
2284,7 → 2505,7
/* If R_386_TLS_{IE_32,IE,GOTIE} symbol is now local to the binary,
make it a R_386_TLS_LE_32 requiring no TLS entry. */
if (h->got.refcount > 0
&& info->executable
&& bfd_link_executable (info)
&& h->dynindx == -1
&& (elf_i386_hash_entry(h)->tls_type & GOT_TLS_IE))
h->got.offset = (bfd_vma) -1;
2336,7 → 2557,7
else if (! GOT_TLS_GDESC_P (tls_type)
&& (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|| h->root.type != bfd_link_hash_undefweak)
&& (info->shared
&& (bfd_link_pic (info)
|| WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
htab->elf.srelgot->size += sizeof (Elf32_External_Rel);
if (GOT_TLS_GDESC_P (tls_type))
2354,7 → 2575,7
space for pc-relative relocs that have become local due to symbol
visibility changes. */
 
if (info->shared)
if (bfd_link_pic (info))
{
/* The only reloc that uses pc_count is R_386_PC32, which will
appear on a call or on something like ".long foo - .". We
2411,9 → 2632,10
{
/* For the non-shared case, discard space for relocs against
symbols which turn out to need copy relocs or are not
dynamic. */
dynamic. Keep dynamic relocations for run-time function
pointer initialization. */
 
if (!h->non_got_ref
if ((!h->non_got_ref || eh->func_pointer_refcount > 0)
&& ((h->def_dynamic
&& !h->def_regular)
|| (htab->elf.dynamic_sections_created
2436,6 → 2658,7
}
 
eh->dyn_relocs = NULL;
eh->func_pointer_refcount = 0;
 
keep: ;
}
2496,8 → 2719,9
 
info->flags |= DF_TEXTREL;
 
if (info->warn_shared_textrel && info->shared)
info->callbacks->einfo (_("%P: %B: warning: relocation against `%s' in readonly section `%A'.\n"),
if ((info->warn_shared_textrel && bfd_link_pic (info))
|| info->error_textrel)
info->callbacks->einfo (_("%P: %B: warning: relocation against `%s' in readonly section `%A'\n"),
p->sec->owner, h->root.root.string,
p->sec);
 
2508,14 → 2732,27
return TRUE;
}
 
/* Convert
mov foo@GOT(%reg), %reg
/* With the local symbol, foo, we convert
mov foo@GOT[(%reg1)], %reg2
to
lea foo@GOTOFF(%reg), %reg
with the local symbol, foo. */
lea foo[@GOTOFF(%reg1)], %reg2
and convert
call/jmp *foo@GOT[(%reg)]
to
nop call foo/jmp foo nop
When PIC is false, convert
test %reg1, foo@GOT[(%reg2)]
to
test $foo, %reg1
and convert
binop foo@GOT[(%reg1)], %reg2
to
binop $foo, %reg2
where binop is one of adc, add, and, cmp, or, sbb, sub, xor
instructions. */
 
static bfd_boolean
elf_i386_convert_mov_to_lea (bfd *abfd, asection *sec,
elf_i386_convert_load (bfd *abfd, asection *sec,
struct bfd_link_info *link_info)
{
Elf_Internal_Shdr *symtab_hdr;
2531,10 → 2768,10
if (!is_elf_hash_table (link_info->hash))
return FALSE;
 
/* Nothing to do if there are no codes, no relocations or no output. */
/* Nothing to do if there is no need or no output. */
if ((sec->flags & (SEC_CODE | SEC_RELOC)) != (SEC_CODE | SEC_RELOC)
|| sec->reloc_count == 0
|| discarded_section (sec))
|| sec->need_convert_load == 0
|| bfd_is_abs_section (sec->output_section))
return TRUE;
 
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
2567,33 → 2804,97
unsigned int r_symndx = ELF32_R_SYM (irel->r_info);
unsigned int indx;
struct elf_link_hash_entry *h;
unsigned int opcode;
unsigned int modrm;
bfd_vma roff;
bfd_boolean baseless;
Elf_Internal_Sym *isym;
unsigned int addend;
unsigned int nop;
bfd_vma nop_offset;
 
if (r_type != R_386_GOT32)
if (r_type != R_386_GOT32 && r_type != R_386_GOT32X)
continue;
 
/* Get the symbol referred to by the reloc. */
roff = irel->r_offset;
if (roff < 2)
continue;
 
/* Addend for R_386_GOT32 and R_386_GOT32X relocations must be 0. */
addend = bfd_get_32 (abfd, contents + roff);
if (addend != 0)
continue;
 
modrm = bfd_get_8 (abfd, contents + roff - 1);
baseless = (modrm & 0xc7) == 0x5;
 
if (r_type == R_386_GOT32X
&& baseless
&& bfd_link_pic (link_info))
{
/* For PIC, disallow R_386_GOT32X without a base register
since we don't know what the GOT base is. Allow
R_386_GOT32 for existing object files. */
const char *name;
 
if (r_symndx < symtab_hdr->sh_info)
{
Elf_Internal_Sym *isym;
isym = bfd_sym_from_r_symndx (&htab->sym_cache, abfd,
r_symndx);
name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
}
else
{
indx = r_symndx - symtab_hdr->sh_info;
h = elf_sym_hashes (abfd)[indx];
BFD_ASSERT (h != NULL);
name = h->root.root.string;
}
 
(*_bfd_error_handler)
(_("%B: direct GOT relocation R_386_GOT32X against `%s' without base register can not be used when making a shared object"),
abfd, name);
goto error_return;
}
 
opcode = bfd_get_8 (abfd, contents + roff - 2);
 
/* It is OK to convert mov to lea. */
if (opcode != 0x8b)
{
/* Only convert R_386_GOT32X relocation for call, jmp or
one of adc, add, and, cmp, or, sbb, sub, test, xor
instructions. */
if (r_type != R_386_GOT32X)
continue;
 
/* It is OK to convert indirect branch to direct branch. It
is OK to convert adc, add, and, cmp, or, sbb, sub, test,
xor only when PIC is false. */
if (opcode != 0xff && bfd_link_pic (link_info))
continue;
}
 
/* Try to convert R_386_GOT32 and R_386_GOT32X. Get the symbol
referred to by the reloc. */
if (r_symndx < symtab_hdr->sh_info)
{
isym = bfd_sym_from_r_symndx (&htab->sym_cache,
abfd, r_symndx);
 
/* STT_GNU_IFUNC must keep R_386_GOT32 relocation. */
if (ELF_ST_TYPE (isym->st_info) != STT_GNU_IFUNC
&& bfd_get_8 (input_bfd,
contents + irel->r_offset - 2) == 0x8b)
{
bfd_put_8 (output_bfd, 0x8d,
contents + irel->r_offset - 2);
irel->r_info = ELF32_R_INFO (r_symndx, R_386_GOTOFF);
if (local_got_refcounts != NULL
&& local_got_refcounts[r_symndx] > 0)
local_got_refcounts[r_symndx] -= 1;
changed_contents = TRUE;
changed_relocs = TRUE;
}
/* STT_GNU_IFUNC must keep GOT32 relocations. */
if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
continue;
 
h = NULL;
if (opcode == 0x0ff)
/* Convert "call/jmp *foo@GOT[(%reg)]". */
goto convert_branch;
else
/* Convert "mov foo@GOT[(%reg1)], %reg2",
"test %reg1, foo@GOT(%reg2)" and
"binop foo@GOT[(%reg1)], %reg2". */
goto convert_load;
}
 
indx = r_symndx - symtab_hdr->sh_info;
2604,25 → 2905,149
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
/* STT_GNU_IFUNC must keep R_386_GOT32 relocation. We also avoid
optimizing _DYNAMIC since ld.so may use its link-time address. */
if (h->def_regular
&& h->type != STT_GNU_IFUNC
&& h != htab->elf.hdynamic
&& SYMBOL_REFERENCES_LOCAL (link_info, h)
&& bfd_get_8 (input_bfd,
contents + irel->r_offset - 2) == 0x8b)
/* STT_GNU_IFUNC must keep GOT32 relocations. */
if (h->type == STT_GNU_IFUNC)
continue;
 
if (opcode == 0xff)
{
bfd_put_8 (output_bfd, 0x8d,
contents + irel->r_offset - 2);
irel->r_info = ELF32_R_INFO (r_symndx, R_386_GOTOFF);
/* We have "call/jmp *foo@GOT[(%reg)]". */
if ((h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
&& SYMBOL_REFERENCES_LOCAL (link_info, h))
{
/* The function is locally defined. */
convert_branch:
/* Convert R_386_GOT32X to R_386_PC32. */
if (modrm == 0x15 || (modrm & 0xf8) == 0x90)
{
/* Convert to "nop call foo". ADDR_PREFIX_OPCODE
is a nop prefix. */
modrm = 0xe8;
nop = link_info->call_nop_byte;
if (link_info->call_nop_as_suffix)
{
nop_offset = roff + 3;
irel->r_offset -= 1;
}
else
nop_offset = roff - 2;
}
else
{
/* Convert to "jmp foo nop". */
modrm = 0xe9;
nop = NOP_OPCODE;
nop_offset = roff + 3;
irel->r_offset -= 1;
}
 
bfd_put_8 (abfd, nop, contents + nop_offset);
bfd_put_8 (abfd, modrm, contents + irel->r_offset - 1);
/* When converting to PC-relative relocation, we
need to adjust addend by -4. */
bfd_put_32 (abfd, -4, contents + irel->r_offset);
irel->r_info = ELF32_R_INFO (r_symndx, R_386_PC32);
 
if (h)
{
if (h->got.refcount > 0)
h->got.refcount -= 1;
}
else
{
if (local_got_refcounts != NULL
&& local_got_refcounts[r_symndx] > 0)
local_got_refcounts[r_symndx] -= 1;
}
 
changed_contents = TRUE;
changed_relocs = TRUE;
}
}
else
{
/* We have "mov foo@GOT[(%re1g)], %reg2",
"test %reg1, foo@GOT(%reg2)" and
"binop foo@GOT[(%reg1)], %reg2".
 
Avoid optimizing _DYNAMIC since ld.so may use its
link-time address. */
if (h == htab->elf.hdynamic)
continue;
 
/* def_regular is set by an assignment in a linker script in
bfd_elf_record_link_assignment. */
if ((h->def_regular
|| h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
&& SYMBOL_REFERENCES_LOCAL (link_info, h))
{
convert_load:
if (opcode == 0x8b)
{
/* Convert "mov foo@GOT(%reg1), %reg2" to
"lea foo@GOTOFF(%reg1), %reg2". */
if (r_type == R_386_GOT32X
&& (baseless || !bfd_link_pic (link_info)))
{
r_type = R_386_32;
/* For R_386_32, convert
"lea foo@GOTOFF(%reg1), %reg2" to
"lea foo@GOT, %reg2". */
if (!baseless)
{
modrm = 0x5 | (modrm & 0x38);
bfd_put_8 (abfd, modrm, contents + roff - 1);
}
}
else
r_type = R_386_GOTOFF;
opcode = 0x8d;
}
else
{
if (opcode == 0x85)
{
/* Convert "test %reg1, foo@GOT(%reg2)" to
"test $foo, %reg1". */
modrm = 0xc0 | (modrm & 0x38) >> 3;
opcode = 0xf7;
}
else
{
/* Convert "binop foo@GOT(%reg1), %reg2" to
"binop $foo, %reg2". */
modrm = (0xc0
| (modrm & 0x38) >> 3
| (opcode & 0x3c));
opcode = 0x81;
}
bfd_put_8 (abfd, modrm, contents + roff - 1);
r_type = R_386_32;
}
 
bfd_put_8 (abfd, opcode, contents + roff - 2);
irel->r_info = ELF32_R_INFO (r_symndx, r_type);
 
if (h)
{
if (h->got.refcount > 0)
h->got.refcount -= 1;
}
else
{
if (local_got_refcounts != NULL
&& local_got_refcounts[r_symndx] > 0)
local_got_refcounts[r_symndx] -= 1;
}
 
changed_contents = TRUE;
changed_relocs = TRUE;
}
}
}
 
if (contents != NULL
&& elf_section_data (sec)->this_hdr.contents != contents)
{
2676,7 → 3101,7
if (htab->elf.dynamic_sections_created)
{
/* Set the contents of the .interp section to the interpreter. */
if (info->executable)
if (bfd_link_executable (info) && !info->nointerp)
{
s = bfd_get_linker_section (dynobj, ".interp");
if (s == NULL)
2688,7 → 3113,7
 
/* Set up .got offsets for local syms, and space for local dynamic
relocs. */
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
{
bfd_signed_vma *local_got;
bfd_signed_vma *end_local_got;
2705,7 → 3130,7
{
struct elf_dyn_relocs *p;
 
if (!elf_i386_convert_mov_to_lea (ibfd, s, info))
if (!elf_i386_convert_load (ibfd, s, info))
return FALSE;
 
for (p = ((struct elf_dyn_relocs *)
2736,8 → 3161,9
&& (info->flags & DF_TEXTREL) == 0)
{
info->flags |= DF_TEXTREL;
if (info->warn_shared_textrel && info->shared)
info->callbacks->einfo (_("%P: %B: warning: relocation in readonly section `%A'.\n"),
if ((info->warn_shared_textrel && bfd_link_pic (info))
|| info->error_textrel)
info->callbacks->einfo (_("%P: %B: warning: relocation in readonly section `%A'\n"),
p->sec->owner, p->sec);
}
}
2777,7 → 3203,7
|| *local_tls_type == GOT_TLS_IE_BOTH)
s->size += 4;
}
if (info->shared
if (bfd_link_pic (info)
|| GOT_TLS_GD_ANY_P (*local_tls_type)
|| (*local_tls_type & GOT_TLS_IE))
{
2885,6 → 3311,7
else if (s == htab->elf.sgotplt
|| s == htab->elf.iplt
|| s == htab->elf.igotplt
|| s == htab->plt_got
|| s == htab->plt_eh_frame
|| s == htab->sdynbss)
{
2955,7 → 3382,7
#define add_dynamic_entry(TAG, VAL) \
_bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
if (info->executable)
if (bfd_link_executable (info))
{
if (!add_dynamic_entry (DT_DEBUG, 0))
return FALSE;
2963,12 → 3390,19
 
if (htab->elf.splt->size != 0)
{
if (!add_dynamic_entry (DT_PLTGOT, 0)
|| !add_dynamic_entry (DT_PLTRELSZ, 0)
/* DT_PLTGOT is used by prelink even if there is no PLT
relocation. */
if (!add_dynamic_entry (DT_PLTGOT, 0))
return FALSE;
 
if (htab->elf.srelplt->size != 0)
{
if (!add_dynamic_entry (DT_PLTRELSZ, 0)
|| !add_dynamic_entry (DT_PLTREL, DT_REL)
|| !add_dynamic_entry (DT_JMPREL, 0))
return FALSE;
}
}
 
if (relocs)
{
2985,6 → 3419,15
 
if ((info->flags & DF_TEXTREL) != 0)
{
if ((elf_tdata (output_bfd)->has_gnu_symbols
& elf_gnu_symbol_ifunc) == elf_gnu_symbol_ifunc)
{
info->callbacks->einfo
(_("%P%X: read-only segment has dynamic IFUNC relocations; recompile with -fPIC\n"));
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
 
if (!add_dynamic_entry (DT_TEXTREL, 0))
return FALSE;
}
3034,6 → 3477,7
tlsbase = (struct elf_link_hash_entry *)bh;
tlsbase->def_regular = 1;
tlsbase->other = STV_HIDDEN;
tlsbase->root.linker_def = 1;
(*bed->elf_backend_hide_symbol) (info, tlsbase, TRUE);
}
}
3086,7 → 3530,7
struct elf_i386_link_hash_table *htab;
struct bfd_link_hash_entry *base;
 
if (!info->executable)
if (!bfd_link_executable (info))
return;
 
htab = elf_i386_hash_table (info);
3150,6 → 3594,7
bfd_vma *local_got_offsets;
bfd_vma *local_tlsdesc_gotents;
Elf_Internal_Rela *rel;
Elf_Internal_Rela *wrel;
Elf_Internal_Rela *relend;
bfd_boolean is_vxworks_tls;
unsigned plt_entry_size;
3166,7 → 3611,7
/* We have to handle relocations in vxworks .tls_vars sections
specially, because the dynamic loader is 'weird'. */
is_vxworks_tls = (get_elf_i386_backend_data (output_bfd)->is_vxworks
&& info->shared
&& bfd_link_pic (info)
&& !strcmp (input_section->output_section->name,
".tls_vars"));
 
3174,17 → 3619,18
 
plt_entry_size = GET_PLT_ENTRY_SIZE (output_bfd);
 
rel = relocs;
rel = wrel = relocs;
relend = relocs + input_section->reloc_count;
for (; rel < relend; rel++)
for (; rel < relend; wrel++, rel++)
{
unsigned int r_type;
reloc_howto_type *howto;
unsigned long r_symndx;
struct elf_link_hash_entry *h;
struct elf_i386_link_hash_entry *eh;
Elf_Internal_Sym *sym;
asection *sec;
bfd_vma off, offplt;
bfd_vma off, offplt, plt_offset;
bfd_vma relocation;
bfd_boolean unresolved_reloc;
bfd_reloc_status_type r;
3191,17 → 3637,22
unsigned int indx;
int tls_type;
bfd_vma st_size;
asection *resolved_plt;
 
r_type = ELF32_R_TYPE (rel->r_info);
if (r_type == R_386_GNU_VTINHERIT
|| r_type == R_386_GNU_VTENTRY)
{
if (wrel != rel)
*wrel = *rel;
continue;
}
 
if ((indx = r_type) >= R_386_standard
&& ((indx = r_type - R_386_ext_offset) - R_386_standard
>= R_386_ext - R_386_standard)
&& ((indx = r_type - R_386_tls_offset) - R_386_ext
>= R_386_irelative - R_386_ext))
>= R_386_ext2 - R_386_ext))
{
(*_bfd_error_handler)
(_("%B: unrecognized relocation (0x%x) in section `%A'"),
3227,7 → 3678,7
 
if (ELF_ST_TYPE (sym->st_info) == STT_SECTION
&& ((sec->flags & SEC_MERGE) != 0
|| (info->relocatable
|| (bfd_link_relocatable (info)
&& sec->output_offset != 0)))
{
bfd_vma addend;
3263,7 → 3714,7
abort ();
}
 
if (info->relocatable)
if (bfd_link_relocatable (info))
addend += sec->output_offset;
else
{
3294,7 → 3745,7
break;
}
}
else if (!info->relocatable
else if (!bfd_link_relocatable (info)
&& ELF32_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
{
/* Relocate against local STT_GNU_IFUNC symbol. */
3311,21 → 3762,40
else
{
bfd_boolean warned ATTRIBUTE_UNUSED;
bfd_boolean ignored ATTRIBUTE_UNUSED;
 
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
unresolved_reloc, warned);
unresolved_reloc, warned, ignored);
st_size = h->size;
}
 
if (sec != NULL && discarded_section (sec))
RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
rel, 1, relend, howto, 0, contents);
{
_bfd_clear_contents (howto, input_bfd, input_section,
contents + rel->r_offset);
wrel->r_offset = rel->r_offset;
wrel->r_info = 0;
wrel->r_addend = 0;
 
if (info->relocatable)
/* For ld -r, remove relocations in debug sections against
sections defined in discarded sections. Not done for
eh_frame editing code expects to be present. */
if (bfd_link_relocatable (info)
&& (input_section->flags & SEC_DEBUGGING))
wrel--;
 
continue;
}
 
if (bfd_link_relocatable (info))
{
if (wrel != rel)
*wrel = *rel;
continue;
}
 
/* Since STT_GNU_IFUNC symbol must go through PLT, we handle
it here if it is defined in a non-shared object. */
if (h != NULL
3336,9 → 3806,17
bfd_vma plt_index;
const char *name;
 
if ((input_section->flags & SEC_ALLOC) == 0
|| h->plt.offset == (bfd_vma) -1)
if ((input_section->flags & SEC_ALLOC) == 0)
{
/* Dynamic relocs are not propagated for SEC_DEBUGGING
sections because such sections are not SEC_ALLOC and
thus ld.so will not process them. */
if ((input_section->flags & SEC_DEBUGGING) != 0)
continue;
abort ();
}
else if (h->plt.offset == (bfd_vma) -1)
abort ();
 
/* STT_GNU_IFUNC symbol must go through PLT. */
if (htab->elf.splt != NULL)
3374,7 → 3852,7
case R_386_32:
/* Generate dynamic relcoation only when there is a
non-GOT reference in a shared object. */
if (info->shared && h->non_got_ref)
if (bfd_link_pic (info) && h->non_got_ref)
{
Elf_Internal_Rela outrel;
asection *sreloc;
3396,7 → 3874,7
 
if (h->dynindx == -1
|| h->forced_local
|| info->executable)
|| bfd_link_executable (info))
{
/* This symbol is resolved locally. */
outrel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE);
3425,6 → 3903,7
goto do_relocation;
 
case R_386_GOT32:
case R_386_GOT32X:
base_got = htab->elf.sgot;
off = h->got.offset;
 
3499,9 → 3978,67
}
}
 
eh = (struct elf_i386_link_hash_entry *) h;
switch (r_type)
{
case R_386_GOT32X:
/* Avoid optimizing _DYNAMIC since ld.so may use its
link-time address. */
if (h == htab->elf.hdynamic)
goto r_386_got32;
 
if (bfd_link_pic (info))
{
/* It is OK to convert mov to lea and convert indirect
branch to direct branch. It is OK to convert adc,
add, and, cmp, or, sbb, sub, test, xor only when PIC
is false. */
unsigned int opcode, addend;
addend = bfd_get_32 (input_bfd, contents + rel->r_offset);
if (addend != 0)
goto r_386_got32;
opcode = bfd_get_8 (input_bfd, contents + rel->r_offset - 2);
if (opcode != 0x8b && opcode != 0xff)
goto r_386_got32;
}
 
/* Resolve "mov GOT[(%reg)], %reg",
"call/jmp *GOT[(%reg)]", "test %reg, foo@GOT[(%reg)]"
and "binop foo@GOT[(%reg)], %reg". */
if (h == NULL
|| (h->plt.offset == (bfd_vma) -1
&& h->got.offset == (bfd_vma) -1)
|| htab->elf.sgotplt == NULL)
abort ();
 
offplt = (htab->elf.sgotplt->output_section->vma
+ htab->elf.sgotplt->output_offset);
 
/* It is relative to .got.plt section. */
if (h->got.offset != (bfd_vma) -1)
/* Use GOT entry. */
relocation = (htab->elf.sgot->output_section->vma
+ htab->elf.sgot->output_offset
+ h->got.offset - offplt);
else
/* Use GOTPLT entry. */
relocation = (h->plt.offset / plt_entry_size - 1 + 3) * 4;
 
if (!bfd_link_pic (info))
{
/* If not PIC, add the .got.plt section address for
baseless addressing. */
unsigned int modrm;
modrm = bfd_get_8 (input_bfd, contents + rel->r_offset - 1);
if ((modrm & 0xc7) == 0x5)
relocation += offplt;
}
 
unresolved_reloc = FALSE;
break;
 
case R_386_GOT32:
r_386_got32:
/* Relocation is to the entry for this symbol in the global
offset table. */
if (htab->elf.sgot == NULL)
3513,8 → 4050,10
 
off = h->got.offset;
dyn = htab->elf.dynamic_sections_created;
if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
|| (info->shared
if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn,
bfd_link_pic (info),
h)
|| (bfd_link_pic (info)
&& SYMBOL_REFERENCES_LOCAL (info, h))
|| (ELF_ST_VISIBILITY (h->other)
&& h->root.type == bfd_link_hash_undefweak))
3560,7 → 4099,7
bfd_put_32 (output_bfd, relocation,
htab->elf.sgot->contents + off);
 
if (info->shared)
if (bfd_link_pic (info))
{
asection *s;
Elf_Internal_Rela outrel;
3593,11 → 4132,11
/* Relocation is relative to the start of the global offset
table. */
 
/* Check to make sure it isn't a protected function symbol
for shared library since it may not be local when used
as function address. We also need to make sure that a
symbol is defined locally. */
if (info->shared && h)
/* Check to make sure it isn't a protected function or data
symbol for shared library since it may not be local when
used as function address or with copy relocation. We also
need to make sure that a symbol is referenced locally. */
if (!bfd_link_executable (info) && h)
{
if (!h->def_regular)
{
3625,14 → 4164,16
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
else if (!info->executable
&& !SYMBOLIC_BIND (info, h)
&& h->type == STT_FUNC
else if (!SYMBOL_REFERENCES_LOCAL (info, h)
&& (h->type == STT_FUNC
|| h->type == STT_OBJECT)
&& ELF_ST_VISIBILITY (h->other) == STV_PROTECTED)
{
(*_bfd_error_handler)
(_("%B: relocation R_386_GOTOFF against protected function `%s' can not be used when making a shared object"),
input_bfd, h->root.root.string);
(_("%B: relocation R_386_GOTOFF against protected %s `%s' can not be used when making a shared object"),
input_bfd,
h->type == STT_FUNC ? "function" : "data",
h->root.root.string);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
3663,7 → 4204,8
if (h == NULL)
break;
 
if (h->plt.offset == (bfd_vma) -1
if ((h->plt.offset == (bfd_vma) -1
&& eh->plt_got.offset == (bfd_vma) -1)
|| htab->elf.splt == NULL)
{
/* We didn't make a PLT entry for this symbol. This
3672,9 → 4214,20
break;
}
 
relocation = (htab->elf.splt->output_section->vma
+ htab->elf.splt->output_offset
+ h->plt.offset);
if (h->plt.offset != (bfd_vma) -1)
{
resolved_plt = htab->elf.splt;
plt_offset = h->plt.offset;
}
else
{
resolved_plt = htab->plt_got;
plt_offset = eh->plt_got.offset;
}
 
relocation = (resolved_plt->output_section->vma
+ resolved_plt->output_offset
+ plt_offset);
unresolved_reloc = FALSE;
break;
 
3689,7 → 4242,8
|| is_vxworks_tls)
break;
 
if ((info->shared
/* Copy dynamic function pointer relocations. */
if ((bfd_link_pic (info)
&& (h == NULL
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|| h->root.type != bfd_link_hash_undefweak)
3696,10 → 4250,10
&& ((r_type != R_386_PC32 && r_type != R_386_SIZE32)
|| !SYMBOL_CALLS_LOCAL (info, h)))
|| (ELIMINATE_COPY_RELOCS
&& !info->shared
&& !bfd_link_pic (info)
&& h != NULL
&& h->dynindx != -1
&& !h->non_got_ref
&& (!h->non_got_ref || eh->func_pointer_refcount > 0)
&& ((h->def_dynamic
&& !h->def_regular)
|| h->root.type == bfd_link_hash_undefweak
3731,7 → 4285,7
else if (h != NULL
&& h->dynindx != -1
&& (r_type == R_386_PC32
|| !info->shared
|| !bfd_link_pic (info)
|| !SYMBOLIC_BIND (info, h)
|| !h->def_regular))
outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
3762,7 → 4316,7
break;
 
case R_386_TLS_IE:
if (!info->executable)
if (!bfd_link_executable (info))
{
Elf_Internal_Rela outrel;
asection *sreloc;
3832,6 → 4386,7
contents + roff);
/* Skip R_386_PC32/R_386_PLT32. */
rel++;
wrel++;
continue;
}
else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTDESC)
4171,6 → 4726,7
contents + roff + 8);
/* Skip R_386_PLT32. */
rel++;
wrel++;
continue;
}
else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTDESC)
4268,6 → 4824,7
"\x65\xa1\0\0\0\0\x90\x8d\x74\x26", 11);
/* Skip R_386_PC32/R_386_PLT32. */
rel++;
wrel++;
continue;
}
 
4303,7 → 4860,8
break;
 
case R_386_TLS_LDO_32:
if (!info->executable || (input_section->flags & SEC_CODE) == 0)
if (!bfd_link_executable (info)
|| (input_section->flags & SEC_CODE) == 0)
relocation -= elf_i386_dtpoff_base (info);
else
/* When converting LDO to LE, we must negate. */
4312,7 → 4870,7
 
case R_386_TLS_LE_32:
case R_386_TLS_LE:
if (!info->executable)
if (!bfd_link_executable (info))
{
Elf_Internal_Rela outrel;
asection *sreloc;
4408,8 → 4966,31
return FALSE;
}
}
 
if (wrel != rel)
*wrel = *rel;
}
 
if (wrel != rel)
{
Elf_Internal_Shdr *rel_hdr;
size_t deleted = rel - wrel;
 
rel_hdr = _bfd_elf_single_rel_hdr (input_section->output_section);
rel_hdr->sh_size -= rel_hdr->sh_entsize * deleted;
if (rel_hdr->sh_size == 0)
{
/* It is too late to remove an empty reloc section. Leave
one NONE reloc.
??? What is wrong with an empty section??? */
rel_hdr->sh_size = rel_hdr->sh_entsize;
deleted -= 1;
}
rel_hdr = _bfd_elf_single_rel_hdr (input_section);
rel_hdr->sh_size -= rel_hdr->sh_entsize * deleted;
input_section->reloc_count -= deleted;
}
 
return TRUE;
}
 
4425,6 → 5006,7
struct elf_i386_link_hash_table *htab;
unsigned plt_entry_size;
const struct elf_i386_backend_data *abed;
struct elf_i386_link_hash_entry *eh;
 
htab = elf_i386_hash_table (info);
if (htab == NULL)
4433,6 → 5015,8
abed = get_elf_i386_backend_data (output_bfd);
plt_entry_size = GET_PLT_ENTRY_SIZE (output_bfd);
 
eh = (struct elf_i386_link_hash_entry *) h;
 
if (h->plt.offset != (bfd_vma) -1)
{
bfd_vma plt_index;
4460,7 → 5044,7
it up. */
 
if ((h->dynindx == -1
&& !((h->forced_local || info->executable)
&& !((h->forced_local || bfd_link_executable (info))
&& h->def_regular
&& h->type == STT_GNU_IFUNC))
|| plt == NULL
4491,7 → 5075,7
}
 
/* Fill in the entry in the procedure linkage table. */
if (! info->shared)
if (! bfd_link_pic (info))
{
memcpy (plt->contents + h->plt.offset, abed->plt->plt_entry,
abed->plt->plt_entry_size);
4513,7 → 5097,7
s = ((h->plt.offset - abed->plt->plt_entry_size)
/ abed->plt->plt_entry_size);
/* K: Number of relocations for PLTResolve. */
if (info->shared)
if (bfd_link_pic (info))
k = PLTRESOLVE_RELOCS_SHLIB;
else
k = PLTRESOLVE_RELOCS;
4561,7 → 5145,7
+ gotplt->output_offset
+ got_offset);
if (h->dynindx == -1
|| ((info->executable
|| ((bfd_link_executable (info)
|| ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
&& h->def_regular
&& h->type == STT_GNU_IFUNC))
4597,9 → 5181,54
plt->contents + h->plt.offset
+ abed->plt->plt_plt_offset);
}
}
else if (eh->plt_got.offset != (bfd_vma) -1)
{
bfd_vma got_offset, plt_offset;
asection *plt, *got, *gotplt;
const bfd_byte *got_plt_entry;
 
if (!h->def_regular)
/* Offset of displacement of the indirect jump. */
bfd_vma plt_got_offset = 2;
 
/* Set the entry in the GOT procedure linkage table. */
plt = htab->plt_got;
got = htab->elf.sgot;
gotplt = htab->elf.sgotplt;
got_offset = h->got.offset;
 
if (got_offset == (bfd_vma) -1
|| plt == NULL
|| got == NULL
|| gotplt == NULL)
abort ();
 
/* Fill in the entry in the GOT procedure linkage table. */
if (! bfd_link_pic (info))
{
got_plt_entry = elf_i386_got_plt_entry;
got_offset += got->output_section->vma + got->output_offset;
}
else
{
got_plt_entry = elf_i386_pic_got_plt_entry;
got_offset += (got->output_section->vma
+ got->output_offset
- gotplt->output_section->vma
- gotplt->output_offset);
}
 
plt_offset = eh->plt_got.offset;
memcpy (plt->contents + plt_offset, got_plt_entry,
sizeof (elf_i386_got_plt_entry));
bfd_put_32 (output_bfd, got_offset,
plt->contents + plt_offset + plt_got_offset);
}
 
if (!h->def_regular
&& (h->plt.offset != (bfd_vma) -1
|| eh->plt_got.offset != (bfd_vma) -1))
{
/* Mark the symbol as undefined, rather than as defined in
the .plt section. Leave the value if there were any
relocations where pointer equality matters (this is a clue
4612,7 → 5241,6
if (!h->pointer_equality_needed)
sym->st_value = 0;
}
}
 
if (h->got.offset != (bfd_vma) -1
&& ! GOT_TLS_GD_ANY_P (elf_i386_hash_entry(h)->tls_type)
4638,7 → 5266,7
if (h->def_regular
&& h->type == STT_GNU_IFUNC)
{
if (info->shared)
if (bfd_link_pic (info))
{
/* Generate R_386_GLOB_DAT. */
goto do_glob_dat;
4661,7 → 5289,7
return TRUE;
}
}
else if (info->shared
else if (bfd_link_pic (info)
&& SYMBOL_REFERENCES_LOCAL (info, h))
{
BFD_ASSERT((h->got.offset & 1) != 0);
4720,10 → 5348,27
dynamic linker, before writing them out. */
 
static enum elf_reloc_type_class
elf_i386_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
elf_i386_reloc_type_class (const struct bfd_link_info *info,
const asection *rel_sec ATTRIBUTE_UNUSED,
const Elf_Internal_Rela *rela)
{
bfd *abfd = info->output_bfd;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
struct elf_link_hash_table *htab = elf_hash_table (info);
unsigned long r_symndx = ELF32_R_SYM (rela->r_info);
Elf_Internal_Sym sym;
 
if (htab->dynsym == NULL
|| !bed->s->swap_symbol_in (abfd,
(htab->dynsym->contents
+ r_symndx * sizeof (Elf32_External_Sym)),
0, &sym))
abort ();
 
/* Check relocation against STT_GNU_IFUNC symbol. */
if (ELF32_ST_TYPE (sym.st_info) == STT_GNU_IFUNC)
return reloc_class_ifunc;
 
switch (ELF32_R_TYPE (rela->r_info))
{
case R_386_RELATIVE:
4827,7 → 5472,7
/* Fill in the first entry in the procedure linkage table. */
if (htab->elf.splt && htab->elf.splt->size > 0)
{
if (info->shared)
if (bfd_link_pic (info))
{
memcpy (htab->elf.splt->contents, abed->plt->pic_plt0_entry,
abed->plt->plt0_entry_size);
4885,7 → 5530,7
->this_hdr.sh_entsize = 4;
 
/* Correct the .rel.plt.unloaded relocations. */
if (abed->is_vxworks && !info->shared)
if (abed->is_vxworks && !bfd_link_pic (info))
{
int num_plts = (htab->elf.splt->size
/ abed->plt->plt_entry_size) - 1;
4892,7 → 5537,7
unsigned char *p;
 
p = htab->srelplt2->contents;
if (info->shared)
if (bfd_link_pic (info))
p += PLTRESOLVE_RELOCS_SHLIB * sizeof (Elf32_External_Rel);
else
p += PLTRESOLVE_RELOCS * sizeof (Elf32_External_Rel);
4976,16 → 5621,98
return TRUE;
}
 
/* Return address for Ith PLT stub in section PLT, for relocation REL
or (bfd_vma) -1 if it should not be included. */
/* Return an array of PLT entry symbol values. */
 
static bfd_vma
elf_i386_plt_sym_val (bfd_vma i, const asection *plt,
const arelent *rel ATTRIBUTE_UNUSED)
static bfd_vma *
elf_i386_get_plt_sym_val (bfd *abfd, asymbol **dynsyms, asection *plt,
asection *relplt)
{
return plt->vma + (i + 1) * GET_PLT_ENTRY_SIZE (plt->owner);
bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean);
arelent *p;
long count, i;
bfd_vma *plt_sym_val;
bfd_vma plt_offset;
bfd_byte *plt_contents;
const struct elf_i386_backend_data *bed
= get_elf_i386_backend_data (abfd);
Elf_Internal_Shdr *hdr;
 
/* Get the .plt section contents. */
plt_contents = (bfd_byte *) bfd_malloc (plt->size);
if (plt_contents == NULL)
return NULL;
if (!bfd_get_section_contents (abfd, (asection *) plt,
plt_contents, 0, plt->size))
{
bad_return:
free (plt_contents);
return NULL;
}
 
slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table;
if (! (*slurp_relocs) (abfd, relplt, dynsyms, TRUE))
goto bad_return;
 
hdr = &elf_section_data (relplt)->this_hdr;
count = relplt->size / hdr->sh_entsize;
 
plt_sym_val = (bfd_vma *) bfd_malloc (sizeof (bfd_vma) * count);
if (plt_sym_val == NULL)
goto bad_return;
 
for (i = 0; i < count; i++)
plt_sym_val[i] = -1;
 
plt_offset = bed->plt->plt_entry_size;
p = relplt->relocation;
for (i = 0; i < count; i++, p++)
{
long reloc_index;
 
/* Skip unknown relocation. PR 17512: file: bc9d6cf5. */
if (p->howto == NULL)
continue;
 
if (p->howto->type != R_386_JUMP_SLOT
&& p->howto->type != R_386_IRELATIVE)
continue;
 
reloc_index = H_GET_32 (abfd, (plt_contents + plt_offset
+ bed->plt->plt_reloc_offset));
reloc_index /= sizeof (Elf32_External_Rel);
if (reloc_index >= count)
abort ();
plt_sym_val[reloc_index] = plt->vma + plt_offset;
plt_offset += bed->plt->plt_entry_size;
 
/* PR binutils/18437: Skip extra relocations in the .rel.plt
section. */
if (plt_offset >= plt->size)
break;
}
 
free (plt_contents);
 
return plt_sym_val;
}
 
/* Similar to _bfd_elf_get_synthetic_symtab. */
 
static long
elf_i386_get_synthetic_symtab (bfd *abfd,
long symcount,
asymbol **syms,
long dynsymcount,
asymbol **dynsyms,
asymbol **ret)
{
asection *plt = bfd_get_section_by_name (abfd, ".plt");
return _bfd_elf_ifunc_get_synthetic_symtab (abfd, symcount, syms,
dynsymcount, dynsyms, ret,
plt,
elf_i386_get_plt_sym_val);
}
 
/* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */
 
static bfd_boolean
5004,7 → 5731,7
 
static bfd_boolean
elf_i386_add_symbol_hook (bfd * abfd,
struct bfd_link_info * info ATTRIBUTE_UNUSED,
struct bfd_link_info * info,
Elf_Internal_Sym * sym,
const char ** namep ATTRIBUTE_UNUSED,
flagword * flagsp ATTRIBUTE_UNUSED,
5011,15 → 5738,16
asection ** secp ATTRIBUTE_UNUSED,
bfd_vma * valp ATTRIBUTE_UNUSED)
{
if ((abfd->flags & DYNAMIC) == 0
&& (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
|| ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE))
elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE;
if (ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE
&& (abfd->flags & DYNAMIC) == 0
&& bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour)
elf_tdata (info->output_bfd)->has_gnu_symbols
|= elf_gnu_symbol_unique;
 
return TRUE;
}
 
#define TARGET_LITTLE_SYM bfd_elf32_i386_vec
#define TARGET_LITTLE_SYM i386_elf32_vec
#define TARGET_LITTLE_NAME "elf32-i386"
#define ELF_ARCH bfd_arch_i386
#define ELF_TARGET_ID I386_ELF_DATA
5033,6 → 5761,7
#define elf_backend_want_plt_sym 0
#define elf_backend_got_header_size 12
#define elf_backend_plt_alignment 4
#define elf_backend_extern_protected_data 1
 
/* Support RELA for objdump of prelink objects. */
#define elf_info_to_howto elf_i386_info_to_howto_rel
5042,9 → 5771,9
 
#define bfd_elf32_bfd_is_local_label_name elf_i386_is_local_label_name
#define bfd_elf32_bfd_link_hash_table_create elf_i386_link_hash_table_create
#define bfd_elf32_bfd_link_hash_table_free elf_i386_link_hash_table_free
#define bfd_elf32_bfd_reloc_type_lookup elf_i386_reloc_type_lookup
#define bfd_elf32_bfd_reloc_name_lookup elf_i386_reloc_name_lookup
#define bfd_elf32_get_synthetic_symtab elf_i386_get_synthetic_symtab
 
#define elf_backend_adjust_dynamic_symbol elf_i386_adjust_dynamic_symbol
#define elf_backend_relocs_compatible _bfd_elf_relocs_compatible
5064,11 → 5793,8
#define elf_backend_always_size_sections elf_i386_always_size_sections
#define elf_backend_omit_section_dynsym \
((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
#define elf_backend_plt_sym_val elf_i386_plt_sym_val
#define elf_backend_hash_symbol elf_i386_hash_symbol
#define elf_backend_add_symbol_hook elf_i386_add_symbol_hook
#undef elf_backend_post_process_headers
#define elf_backend_post_process_headers _bfd_elf_set_osabi
 
#include "elf32-target.h"
 
5075,7 → 5801,7
/* FreeBSD support. */
 
#undef TARGET_LITTLE_SYM
#define TARGET_LITTLE_SYM bfd_elf32_i386_freebsd_vec
#define TARGET_LITTLE_SYM i386_elf32_fbsd_vec
#undef TARGET_LITTLE_NAME
#define TARGET_LITTLE_NAME "elf32-i386-freebsd"
#undef ELF_OSABI
5088,11 → 5814,14
static void
elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info)
{
_bfd_elf_set_osabi (abfd, info);
_bfd_elf_post_process_headers (abfd, info);
 
#ifdef OLD_FREEBSD_ABI_LABEL
{
/* The ABI label supported by FreeBSD <= 4.0 is quite nonstandard. */
Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8);
}
#endif
}
 
5108,10 → 5837,12
/* Solaris 2. */
 
#undef TARGET_LITTLE_SYM
#define TARGET_LITTLE_SYM bfd_elf32_i386_sol2_vec
#define TARGET_LITTLE_SYM i386_elf32_sol2_vec
#undef TARGET_LITTLE_NAME
#define TARGET_LITTLE_NAME "elf32-i386-sol2"
 
#undef elf_backend_post_process_headers
 
/* Restore default: we cannot use ELFOSABI_SOLARIS, otherwise ELFOSABI_NONE
objects won't be recognized. */
#undef ELF_OSABI
5133,10 → 5864,51
 
#include "elf32-target.h"
 
/* Intel MCU support. */
 
static bfd_boolean
elf32_iamcu_elf_object_p (bfd *abfd)
{
/* Set the right machine number for an IAMCU elf32 file. */
bfd_default_set_arch_mach (abfd, bfd_arch_iamcu, bfd_mach_i386_iamcu);
return TRUE;
}
 
#undef TARGET_LITTLE_SYM
#define TARGET_LITTLE_SYM iamcu_elf32_vec
#undef TARGET_LITTLE_NAME
#define TARGET_LITTLE_NAME "elf32-iamcu"
#undef ELF_ARCH
#define ELF_ARCH bfd_arch_iamcu
 
#undef ELF_MACHINE_CODE
#define ELF_MACHINE_CODE EM_IAMCU
 
#undef ELF_OSABI
 
#undef elf32_bed
#define elf32_bed elf32_iamcu_bed
 
#undef elf_backend_object_p
#define elf_backend_object_p elf32_iamcu_elf_object_p
 
#undef elf_backend_static_tls_alignment
 
#undef elf_backend_want_plt_sym
#define elf_backend_want_plt_sym 0
 
#include "elf32-target.h"
 
/* Restore defaults. */
#undef ELF_ARCH
#define ELF_ARCH bfd_arch_i386
#undef ELF_MACHINE_CODE
#define ELF_MACHINE_CODE EM_386
 
/* Native Client support. */
 
#undef TARGET_LITTLE_SYM
#define TARGET_LITTLE_SYM bfd_elf32_i386_nacl_vec
#define TARGET_LITTLE_SYM i386_elf32_nacl_vec
#undef TARGET_LITTLE_NAME
#define TARGET_LITTLE_NAME "elf32-i386-nacl"
#undef elf32_bed
5150,7 → 5922,6
#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
 
/* NaCl uses substantially different PLT entries for the same effects. */
5326,7 → 6097,7
/* VxWorks support. */
 
#undef TARGET_LITTLE_SYM
#define TARGET_LITTLE_SYM bfd_elf32_i386_vxworks_vec
#define TARGET_LITTLE_SYM i386_elf32_vxworks_vec
#undef TARGET_LITTLE_NAME
#define TARGET_LITTLE_NAME "elf32-i386-vxworks"
#undef ELF_OSABI
5344,7 → 6115,6
#define elf_backend_arch_data &elf_i386_vxworks_arch_bed
 
#undef elf_backend_relocs_compatible
#undef elf_backend_post_process_headers
#undef elf_backend_add_symbol_hook
#define elf_backend_add_symbol_hook \
elf_vxworks_add_symbol_hook