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 |