| 26 |
#include "elf-bfd.h" |
#include "elf-bfd.h" |
| 27 |
#include "elf-vxworks.h" |
#include "elf-vxworks.h" |
| 28 |
#include "bfd_stdint.h" |
#include "bfd_stdint.h" |
| 29 |
|
#include "objalloc.h" |
| 30 |
|
#include "hashtab.h" |
| 31 |
|
|
| 32 |
/* 386 uses REL relocations instead of RELA. */ |
/* 386 uses REL relocations instead of RELA. */ |
| 33 |
#define USE_REL 1 |
#define USE_REL 1 |
| 140 |
HOWTO(R_386_TLS_DESC, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, |
HOWTO(R_386_TLS_DESC, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, |
| 141 |
bfd_elf_generic_reloc, "R_386_TLS_DESC", |
bfd_elf_generic_reloc, "R_386_TLS_DESC", |
| 142 |
TRUE, 0xffffffff, 0xffffffff, FALSE), |
TRUE, 0xffffffff, 0xffffffff, FALSE), |
| 143 |
|
HOWTO(R_386_IRELATIVE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, |
| 144 |
|
bfd_elf_generic_reloc, "R_386_IRELATIVE", |
| 145 |
|
TRUE, 0xffffffff, 0xffffffff, FALSE), |
| 146 |
|
|
| 147 |
/* Another gap. */ |
/* Another gap. */ |
| 148 |
#define R_386_tls (R_386_TLS_DESC + 1 - R_386_tls_offset) |
#define R_386_irelative (R_386_IRELATIVE + 1 - R_386_tls_offset) |
| 149 |
#define R_386_vt_offset (R_386_GNU_VTINHERIT - R_386_tls) |
#define R_386_vt_offset (R_386_GNU_VTINHERIT - R_386_irelative) |
| 150 |
|
|
| 151 |
/* GNU extension to record C++ vtable hierarchy. */ |
/* GNU extension to record C++ vtable hierarchy. */ |
| 152 |
HOWTO (R_386_GNU_VTINHERIT, /* type */ |
HOWTO (R_386_GNU_VTINHERIT, /* type */ |
| 321 |
TRACE ("BFD_RELOC_386_TLS_DESC"); |
TRACE ("BFD_RELOC_386_TLS_DESC"); |
| 322 |
return &elf_howto_table[R_386_TLS_DESC - R_386_tls_offset]; |
return &elf_howto_table[R_386_TLS_DESC - R_386_tls_offset]; |
| 323 |
|
|
| 324 |
|
case BFD_RELOC_386_IRELATIVE: |
| 325 |
|
TRACE ("BFD_RELOC_386_IRELATIVE"); |
| 326 |
|
return &elf_howto_table[R_386_IRELATIVE]; |
| 327 |
|
|
| 328 |
case BFD_RELOC_VTABLE_INHERIT: |
case BFD_RELOC_VTABLE_INHERIT: |
| 329 |
TRACE ("BFD_RELOC_VTABLE_INHERIT"); |
TRACE ("BFD_RELOC_VTABLE_INHERIT"); |
| 330 |
return &elf_howto_table[R_386_GNU_VTINHERIT - R_386_vt_offset]; |
return &elf_howto_table[R_386_GNU_VTINHERIT - R_386_vt_offset]; |
| 364 |
&& ((indx = r_type - R_386_ext_offset) - R_386_standard |
&& ((indx = r_type - R_386_ext_offset) - R_386_standard |
| 365 |
>= R_386_ext - R_386_standard) |
>= R_386_ext - R_386_standard) |
| 366 |
&& ((indx = r_type - R_386_tls_offset) - R_386_ext |
&& ((indx = r_type - R_386_tls_offset) - R_386_ext |
| 367 |
>= R_386_tls - R_386_ext) |
>= R_386_irelative - R_386_ext) |
| 368 |
&& ((indx = r_type - R_386_vt_offset) - R_386_tls |
&& ((indx = r_type - R_386_vt_offset) - R_386_irelative |
| 369 |
>= R_386_vt - R_386_tls)) |
>= R_386_vt - R_386_irelative)) |
| 370 |
{ |
{ |
| 371 |
(*_bfd_error_handler) (_("%B: invalid relocation type %d"), |
(*_bfd_error_handler) (_("%B: invalid relocation type %d"), |
| 372 |
abfd, (int) r_type); |
abfd, (int) r_type); |
| 577 |
#define PLTRESOLVE_RELOCS 2 |
#define PLTRESOLVE_RELOCS 2 |
| 578 |
#define PLT_NON_JUMP_SLOT_RELOCS 2 |
#define PLT_NON_JUMP_SLOT_RELOCS 2 |
| 579 |
|
|
|
/* The i386 linker needs to keep track of the number of relocs that it |
|
|
decides to copy as dynamic relocs in check_relocs for each symbol. |
|
|
This is so that it can later discard them if they are found to be |
|
|
unnecessary. We store the information in a field extending the |
|
|
regular ELF linker hash table. */ |
|
|
|
|
|
struct elf_i386_dyn_relocs |
|
|
{ |
|
|
struct elf_i386_dyn_relocs *next; |
|
|
|
|
|
/* The input section of the reloc. */ |
|
|
asection *sec; |
|
|
|
|
|
/* Total number of relocs copied for the input section. */ |
|
|
bfd_size_type count; |
|
|
|
|
|
/* Number of pc-relative relocs copied for the input section. */ |
|
|
bfd_size_type pc_count; |
|
|
}; |
|
|
|
|
| 580 |
/* i386 ELF linker hash entry. */ |
/* i386 ELF linker hash entry. */ |
| 581 |
|
|
| 582 |
struct elf_i386_link_hash_entry |
struct elf_i386_link_hash_entry |
| 584 |
struct elf_link_hash_entry elf; |
struct elf_link_hash_entry elf; |
| 585 |
|
|
| 586 |
/* Track dynamic relocs copied for this symbol. */ |
/* Track dynamic relocs copied for this symbol. */ |
| 587 |
struct elf_i386_dyn_relocs *dyn_relocs; |
struct elf_dyn_relocs *dyn_relocs; |
| 588 |
|
|
| 589 |
#define GOT_UNKNOWN 0 |
#define GOT_UNKNOWN 0 |
| 590 |
#define GOT_NORMAL 1 |
#define GOT_NORMAL 1 |
| 650 |
struct elf_link_hash_table elf; |
struct elf_link_hash_table elf; |
| 651 |
|
|
| 652 |
/* Short-cuts to get to dynamic linker sections. */ |
/* Short-cuts to get to dynamic linker sections. */ |
|
asection *sgot; |
|
|
asection *sgotplt; |
|
|
asection *srelgot; |
|
|
asection *splt; |
|
|
asection *srelplt; |
|
| 653 |
asection *sdynbss; |
asection *sdynbss; |
| 654 |
asection *srelbss; |
asection *srelbss; |
| 655 |
|
|
| 674 |
section, plus whatever space is used by the jump slots. */ |
section, plus whatever space is used by the jump slots. */ |
| 675 |
bfd_vma sgotplt_jump_table_size; |
bfd_vma sgotplt_jump_table_size; |
| 676 |
|
|
| 677 |
/* Small local sym to section mapping cache. */ |
/* Small local sym cache. */ |
| 678 |
struct sym_sec_cache sym_sec; |
struct sym_cache sym_cache; |
| 679 |
|
|
| 680 |
/* _TLS_MODULE_BASE_ symbol. */ |
/* _TLS_MODULE_BASE_ symbol. */ |
| 681 |
struct bfd_link_hash_entry *tls_module_base; |
struct bfd_link_hash_entry *tls_module_base; |
| 682 |
|
|
| 683 |
|
/* Used by local STT_GNU_IFUNC symbols. */ |
| 684 |
|
htab_t loc_hash_table; |
| 685 |
|
void *loc_hash_memory; |
| 686 |
}; |
}; |
| 687 |
|
|
| 688 |
/* Get the i386 ELF linker hash table from a link_info structure. */ |
/* Get the i386 ELF linker hash table from a link_info structure. */ |
| 696 |
/* Create an entry in an i386 ELF linker hash table. */ |
/* Create an entry in an i386 ELF linker hash table. */ |
| 697 |
|
|
| 698 |
static struct bfd_hash_entry * |
static struct bfd_hash_entry * |
| 699 |
link_hash_newfunc (struct bfd_hash_entry *entry, |
elf_i386_link_hash_newfunc (struct bfd_hash_entry *entry, |
| 700 |
struct bfd_hash_table *table, |
struct bfd_hash_table *table, |
| 701 |
const char *string) |
const char *string) |
| 702 |
{ |
{ |
| 703 |
/* Allocate the structure if it has not already been allocated by a |
/* Allocate the structure if it has not already been allocated by a |
| 704 |
subclass. */ |
subclass. */ |
| 725 |
return entry; |
return entry; |
| 726 |
} |
} |
| 727 |
|
|
| 728 |
|
/* Compute a hash of a local hash entry. We use elf_link_hash_entry |
| 729 |
|
for local symbol so that we can handle local STT_GNU_IFUNC symbols |
| 730 |
|
as global symbol. We reuse indx and dynstr_index for local symbol |
| 731 |
|
hash since they aren't used by global symbols in this backend. */ |
| 732 |
|
|
| 733 |
|
static hashval_t |
| 734 |
|
elf_i386_local_htab_hash (const void *ptr) |
| 735 |
|
{ |
| 736 |
|
struct elf_link_hash_entry *h |
| 737 |
|
= (struct elf_link_hash_entry *) ptr; |
| 738 |
|
return ELF_LOCAL_SYMBOL_HASH (h->indx, h->dynstr_index); |
| 739 |
|
} |
| 740 |
|
|
| 741 |
|
/* Compare local hash entries. */ |
| 742 |
|
|
| 743 |
|
static int |
| 744 |
|
elf_i386_local_htab_eq (const void *ptr1, const void *ptr2) |
| 745 |
|
{ |
| 746 |
|
struct elf_link_hash_entry *h1 |
| 747 |
|
= (struct elf_link_hash_entry *) ptr1; |
| 748 |
|
struct elf_link_hash_entry *h2 |
| 749 |
|
= (struct elf_link_hash_entry *) ptr2; |
| 750 |
|
|
| 751 |
|
return h1->indx == h2->indx && h1->dynstr_index == h2->dynstr_index; |
| 752 |
|
} |
| 753 |
|
|
| 754 |
|
/* Find and/or create a hash entry for local symbol. */ |
| 755 |
|
|
| 756 |
|
static struct elf_link_hash_entry * |
| 757 |
|
elf_i386_get_local_sym_hash (struct elf_i386_link_hash_table *htab, |
| 758 |
|
bfd *abfd, const Elf_Internal_Rela *rel, |
| 759 |
|
bfd_boolean create) |
| 760 |
|
{ |
| 761 |
|
struct elf_i386_link_hash_entry e, *ret; |
| 762 |
|
asection *sec = abfd->sections; |
| 763 |
|
hashval_t h = ELF_LOCAL_SYMBOL_HASH (sec->id, |
| 764 |
|
ELF32_R_SYM (rel->r_info)); |
| 765 |
|
void **slot; |
| 766 |
|
|
| 767 |
|
e.elf.indx = sec->id; |
| 768 |
|
e.elf.dynstr_index = ELF32_R_SYM (rel->r_info); |
| 769 |
|
slot = htab_find_slot_with_hash (htab->loc_hash_table, &e, h, |
| 770 |
|
create ? INSERT : NO_INSERT); |
| 771 |
|
|
| 772 |
|
if (!slot) |
| 773 |
|
return NULL; |
| 774 |
|
|
| 775 |
|
if (*slot) |
| 776 |
|
{ |
| 777 |
|
ret = (struct elf_i386_link_hash_entry *) *slot; |
| 778 |
|
return &ret->elf; |
| 779 |
|
} |
| 780 |
|
|
| 781 |
|
ret = (struct elf_i386_link_hash_entry *) |
| 782 |
|
objalloc_alloc ((struct objalloc *) htab->loc_hash_memory, |
| 783 |
|
sizeof (struct elf_i386_link_hash_entry)); |
| 784 |
|
if (ret) |
| 785 |
|
{ |
| 786 |
|
memset (ret, 0, sizeof (*ret)); |
| 787 |
|
ret->elf.indx = sec->id; |
| 788 |
|
ret->elf.dynstr_index = ELF32_R_SYM (rel->r_info); |
| 789 |
|
ret->elf.dynindx = -1; |
| 790 |
|
ret->elf.plt.offset = (bfd_vma) -1; |
| 791 |
|
ret->elf.got.offset = (bfd_vma) -1; |
| 792 |
|
*slot = ret; |
| 793 |
|
} |
| 794 |
|
return &ret->elf; |
| 795 |
|
} |
| 796 |
|
|
| 797 |
/* Create an i386 ELF linker hash table. */ |
/* Create an i386 ELF linker hash table. */ |
| 798 |
|
|
| 799 |
static struct bfd_link_hash_table * |
static struct bfd_link_hash_table * |
| 806 |
if (ret == NULL) |
if (ret == NULL) |
| 807 |
return NULL; |
return NULL; |
| 808 |
|
|
| 809 |
if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc, |
if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, |
| 810 |
|
elf_i386_link_hash_newfunc, |
| 811 |
sizeof (struct elf_i386_link_hash_entry))) |
sizeof (struct elf_i386_link_hash_entry))) |
| 812 |
{ |
{ |
| 813 |
free (ret); |
free (ret); |
| 814 |
return NULL; |
return NULL; |
| 815 |
} |
} |
| 816 |
|
|
|
ret->sgot = NULL; |
|
|
ret->sgotplt = NULL; |
|
|
ret->srelgot = NULL; |
|
|
ret->splt = NULL; |
|
|
ret->srelplt = NULL; |
|
| 817 |
ret->sdynbss = NULL; |
ret->sdynbss = NULL; |
| 818 |
ret->srelbss = NULL; |
ret->srelbss = NULL; |
| 819 |
ret->tls_ldm_got.refcount = 0; |
ret->tls_ldm_got.refcount = 0; |
| 820 |
ret->next_tls_desc_index = 0; |
ret->next_tls_desc_index = 0; |
| 821 |
ret->sgotplt_jump_table_size = 0; |
ret->sgotplt_jump_table_size = 0; |
| 822 |
ret->sym_sec.abfd = NULL; |
ret->sym_cache.abfd = NULL; |
| 823 |
ret->is_vxworks = 0; |
ret->is_vxworks = 0; |
| 824 |
ret->srelplt2 = NULL; |
ret->srelplt2 = NULL; |
| 825 |
ret->plt0_pad_byte = 0; |
ret->plt0_pad_byte = 0; |
| 826 |
ret->tls_module_base = NULL; |
ret->tls_module_base = NULL; |
| 827 |
|
|
| 828 |
|
ret->loc_hash_table = htab_try_create (1024, |
| 829 |
|
elf_i386_local_htab_hash, |
| 830 |
|
elf_i386_local_htab_eq, |
| 831 |
|
NULL); |
| 832 |
|
ret->loc_hash_memory = objalloc_create (); |
| 833 |
|
if (!ret->loc_hash_table || !ret->loc_hash_memory) |
| 834 |
|
{ |
| 835 |
|
free (ret); |
| 836 |
|
return NULL; |
| 837 |
|
} |
| 838 |
|
|
| 839 |
return &ret->elf.root; |
return &ret->elf.root; |
| 840 |
} |
} |
| 841 |
|
|
| 842 |
/* Create .got, .gotplt, and .rel.got sections in DYNOBJ, and set up |
/* Destroy an i386 ELF linker hash table. */ |
|
shortcuts to them in our hash table. */ |
|
| 843 |
|
|
| 844 |
static bfd_boolean |
static void |
| 845 |
create_got_section (bfd *dynobj, struct bfd_link_info *info) |
elf_i386_link_hash_table_free (struct bfd_link_hash_table *hash) |
| 846 |
{ |
{ |
| 847 |
struct elf_i386_link_hash_table *htab; |
struct elf_i386_link_hash_table *htab |
| 848 |
|
= (struct elf_i386_link_hash_table *) hash; |
|
if (! _bfd_elf_create_got_section (dynobj, info)) |
|
|
return FALSE; |
|
| 849 |
|
|
| 850 |
htab = elf_i386_hash_table (info); |
if (htab->loc_hash_table) |
| 851 |
htab->sgot = bfd_get_section_by_name (dynobj, ".got"); |
htab_delete (htab->loc_hash_table); |
| 852 |
htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt"); |
if (htab->loc_hash_memory) |
| 853 |
if (!htab->sgot || !htab->sgotplt) |
objalloc_free ((struct objalloc *) htab->loc_hash_memory); |
| 854 |
abort (); |
_bfd_generic_link_hash_table_free (hash); |
|
|
|
|
htab->srelgot = bfd_make_section_with_flags (dynobj, ".rel.got", |
|
|
(SEC_ALLOC | SEC_LOAD |
|
|
| SEC_HAS_CONTENTS |
|
|
| SEC_IN_MEMORY |
|
|
| SEC_LINKER_CREATED |
|
|
| SEC_READONLY)); |
|
|
if (htab->srelgot == NULL |
|
|
|| ! bfd_set_section_alignment (dynobj, htab->srelgot, 2)) |
|
|
return FALSE; |
|
|
return TRUE; |
|
| 855 |
} |
} |
| 856 |
|
|
| 857 |
/* Create .plt, .rel.plt, .got, .got.plt, .rel.got, .dynbss, and |
/* Create .plt, .rel.plt, .got, .got.plt, .rel.got, .dynbss, and |
| 863 |
{ |
{ |
| 864 |
struct elf_i386_link_hash_table *htab; |
struct elf_i386_link_hash_table *htab; |
| 865 |
|
|
|
htab = elf_i386_hash_table (info); |
|
|
if (!htab->sgot && !create_got_section (dynobj, info)) |
|
|
return FALSE; |
|
|
|
|
| 866 |
if (!_bfd_elf_create_dynamic_sections (dynobj, info)) |
if (!_bfd_elf_create_dynamic_sections (dynobj, info)) |
| 867 |
return FALSE; |
return FALSE; |
| 868 |
|
|
| 869 |
htab->splt = bfd_get_section_by_name (dynobj, ".plt"); |
htab = elf_i386_hash_table (info); |
|
htab->srelplt = bfd_get_section_by_name (dynobj, ".rel.plt"); |
|
| 870 |
htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss"); |
htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss"); |
| 871 |
if (!info->shared) |
if (!info->shared) |
| 872 |
htab->srelbss = bfd_get_section_by_name (dynobj, ".rel.bss"); |
htab->srelbss = bfd_get_section_by_name (dynobj, ".rel.bss"); |
| 873 |
|
|
| 874 |
if (!htab->splt || !htab->srelplt || !htab->sdynbss |
if (!htab->sdynbss |
| 875 |
|| (!info->shared && !htab->srelbss)) |
|| (!info->shared && !htab->srelbss)) |
| 876 |
abort (); |
abort (); |
| 877 |
|
|
| 878 |
if (htab->is_vxworks |
if (htab->is_vxworks |
| 879 |
&& !elf_vxworks_create_dynamic_sections (dynobj, info, &htab->srelplt2)) |
&& !elf_vxworks_create_dynamic_sections (dynobj, info, |
| 880 |
|
&htab->srelplt2)) |
| 881 |
return FALSE; |
return FALSE; |
| 882 |
|
|
| 883 |
return TRUE; |
return TRUE; |
| 899 |
{ |
{ |
| 900 |
if (edir->dyn_relocs != NULL) |
if (edir->dyn_relocs != NULL) |
| 901 |
{ |
{ |
| 902 |
struct elf_i386_dyn_relocs **pp; |
struct elf_dyn_relocs **pp; |
| 903 |
struct elf_i386_dyn_relocs *p; |
struct elf_dyn_relocs *p; |
| 904 |
|
|
| 905 |
/* Add reloc counts against the indirect sym to the direct sym |
/* Add reloc counts against the indirect sym to the direct sym |
| 906 |
list. Merge any entries against the same section. */ |
list. Merge any entries against the same section. */ |
| 907 |
for (pp = &eind->dyn_relocs; (p = *pp) != NULL; ) |
for (pp = &eind->dyn_relocs; (p = *pp) != NULL; ) |
| 908 |
{ |
{ |
| 909 |
struct elf_i386_dyn_relocs *q; |
struct elf_dyn_relocs *q; |
| 910 |
|
|
| 911 |
for (q = edir->dyn_relocs; q != NULL; q = q->next) |
for (q = edir->dyn_relocs; q != NULL; q = q->next) |
| 912 |
if (q->sec == p->sec) |
if (q->sec == p->sec) |
| 1001 |
type = bfd_get_8 (abfd, contents + offset - 2); |
type = bfd_get_8 (abfd, contents + offset - 2); |
| 1002 |
if (r_type == R_386_TLS_GD) |
if (r_type == R_386_TLS_GD) |
| 1003 |
{ |
{ |
| 1004 |
/* Check transition from LD access model. Only |
/* Check transition from GD access model. Only |
| 1005 |
leal foo@tlsgd(,%reg,1), %eax; call ___tls_get_addr |
leal foo@tlsgd(,%reg,1), %eax; call ___tls_get_addr |
| 1006 |
leal foo@tlsgd(%reg), %eax; call ___tls_get_addr; nop |
leal foo@tlsgd(%reg), %eax; call ___tls_get_addr; nop |
| 1007 |
can transit to different access model. */ |
can transit to different access model. */ |
| 1053 |
return FALSE; |
return FALSE; |
| 1054 |
|
|
| 1055 |
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
| 1056 |
|
/* Use strncmp to check ___tls_get_addr since ___tls_get_addr |
| 1057 |
|
may be versioned. */ |
| 1058 |
return (h != NULL |
return (h != NULL |
| 1059 |
&& h->root.root.string != NULL |
&& h->root.root.string != NULL |
| 1060 |
&& (ELF32_R_TYPE (rel[1].r_info) == R_386_PC32 |
&& (ELF32_R_TYPE (rel[1].r_info) == R_386_PC32 |
| 1061 |
|| ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32) |
|| ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32) |
| 1062 |
&& (strcmp (h->root.root.string, "___tls_get_addr") == 0)); |
&& (strncmp (h->root.root.string, "___tls_get_addr", |
| 1063 |
|
15) == 0)); |
| 1064 |
|
|
| 1065 |
case R_386_TLS_IE: |
case R_386_TLS_IE: |
| 1066 |
/* Check transition from IE access model: |
/* Check transition from IE access model: |
| 1149 |
unsigned int *r_type, int tls_type, |
unsigned int *r_type, int tls_type, |
| 1150 |
const Elf_Internal_Rela *rel, |
const Elf_Internal_Rela *rel, |
| 1151 |
const Elf_Internal_Rela *relend, |
const Elf_Internal_Rela *relend, |
| 1152 |
struct elf_link_hash_entry *h) |
struct elf_link_hash_entry *h, |
| 1153 |
|
unsigned long r_symndx) |
| 1154 |
{ |
{ |
| 1155 |
unsigned int from_type = *r_type; |
unsigned int from_type = *r_type; |
| 1156 |
unsigned int to_type = from_type; |
unsigned int to_type = from_type; |
| 1225 |
from_type, rel, relend)) |
from_type, rel, relend)) |
| 1226 |
{ |
{ |
| 1227 |
reloc_howto_type *from, *to; |
reloc_howto_type *from, *to; |
| 1228 |
|
const char *name; |
| 1229 |
|
|
| 1230 |
from = elf_i386_rtype_to_howto (abfd, from_type); |
from = elf_i386_rtype_to_howto (abfd, from_type); |
| 1231 |
to = elf_i386_rtype_to_howto (abfd, to_type); |
to = elf_i386_rtype_to_howto (abfd, to_type); |
| 1232 |
|
|
| 1233 |
|
if (h) |
| 1234 |
|
name = h->root.root.string; |
| 1235 |
|
else |
| 1236 |
|
{ |
| 1237 |
|
Elf_Internal_Sym *isym; |
| 1238 |
|
struct elf_i386_link_hash_table *htab; |
| 1239 |
|
htab = elf_i386_hash_table (info); |
| 1240 |
|
isym = bfd_sym_from_r_symndx (&htab->sym_cache, |
| 1241 |
|
abfd, r_symndx); |
| 1242 |
|
name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL); |
| 1243 |
|
} |
| 1244 |
|
|
| 1245 |
(*_bfd_error_handler) |
(*_bfd_error_handler) |
| 1246 |
(_("%B: TLS transition from %s to %s against `%s' at 0x%lx " |
(_("%B: TLS transition from %s to %s against `%s' at 0x%lx " |
| 1247 |
"in section `%A' failed"), |
"in section `%A' failed"), |
| 1248 |
abfd, sec, from->name, to->name, |
abfd, sec, from->name, to->name, name, |
|
h ? h->root.root.string : "a local symbol", |
|
| 1249 |
(unsigned long) rel->r_offset); |
(unsigned long) rel->r_offset); |
| 1250 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
| 1251 |
return FALSE; |
return FALSE; |
| 1289 |
unsigned int r_type; |
unsigned int r_type; |
| 1290 |
unsigned long r_symndx; |
unsigned long r_symndx; |
| 1291 |
struct elf_link_hash_entry *h; |
struct elf_link_hash_entry *h; |
| 1292 |
|
Elf_Internal_Sym *isym; |
| 1293 |
|
const char *name; |
| 1294 |
|
|
| 1295 |
r_symndx = ELF32_R_SYM (rel->r_info); |
r_symndx = ELF32_R_SYM (rel->r_info); |
| 1296 |
r_type = ELF32_R_TYPE (rel->r_info); |
r_type = ELF32_R_TYPE (rel->r_info); |
| 1304 |
} |
} |
| 1305 |
|
|
| 1306 |
if (r_symndx < symtab_hdr->sh_info) |
if (r_symndx < symtab_hdr->sh_info) |
| 1307 |
h = NULL; |
{ |
| 1308 |
|
/* A local symbol. */ |
| 1309 |
|
isym = bfd_sym_from_r_symndx (&htab->sym_cache, |
| 1310 |
|
abfd, r_symndx); |
| 1311 |
|
if (isym == NULL) |
| 1312 |
|
return FALSE; |
| 1313 |
|
|
| 1314 |
|
/* Check relocation against local STT_GNU_IFUNC symbol. */ |
| 1315 |
|
if (ELF32_ST_TYPE (isym->st_info) == STT_GNU_IFUNC) |
| 1316 |
|
{ |
| 1317 |
|
h = elf_i386_get_local_sym_hash (htab, abfd, rel, |
| 1318 |
|
TRUE); |
| 1319 |
|
if (h == NULL) |
| 1320 |
|
return FALSE; |
| 1321 |
|
|
| 1322 |
|
/* Fake a STT_GNU_IFUNC symbol. */ |
| 1323 |
|
h->type = STT_GNU_IFUNC; |
| 1324 |
|
h->def_regular = 1; |
| 1325 |
|
h->ref_regular = 1; |
| 1326 |
|
h->forced_local = 1; |
| 1327 |
|
h->root.type = bfd_link_hash_defined; |
| 1328 |
|
} |
| 1329 |
|
else |
| 1330 |
|
h = NULL; |
| 1331 |
|
} |
| 1332 |
else |
else |
| 1333 |
{ |
{ |
| 1334 |
|
isym = NULL; |
| 1335 |
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
| 1336 |
while (h->root.type == bfd_link_hash_indirect |
while (h->root.type == bfd_link_hash_indirect |
| 1337 |
|| h->root.type == bfd_link_hash_warning) |
|| h->root.type == bfd_link_hash_warning) |
| 1338 |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
| 1339 |
} |
} |
| 1340 |
|
|
| 1341 |
|
if (h != NULL) |
| 1342 |
|
{ |
| 1343 |
|
/* Create the ifunc sections for static executables. If we |
| 1344 |
|
never see an indirect function symbol nor we are building |
| 1345 |
|
a static executable, those sections will be empty and |
| 1346 |
|
won't appear in output. */ |
| 1347 |
|
switch (r_type) |
| 1348 |
|
{ |
| 1349 |
|
default: |
| 1350 |
|
break; |
| 1351 |
|
|
| 1352 |
|
case R_386_32: |
| 1353 |
|
case R_386_PC32: |
| 1354 |
|
case R_386_PLT32: |
| 1355 |
|
case R_386_GOT32: |
| 1356 |
|
case R_386_GOTOFF: |
| 1357 |
|
if (!_bfd_elf_create_ifunc_sections (abfd, info)) |
| 1358 |
|
return FALSE; |
| 1359 |
|
break; |
| 1360 |
|
} |
| 1361 |
|
|
| 1362 |
|
/* Since STT_GNU_IFUNC symbol must go through PLT, we handle |
| 1363 |
|
it here if it is defined in a non-shared object. */ |
| 1364 |
|
if (h->type == STT_GNU_IFUNC |
| 1365 |
|
&& h->def_regular) |
| 1366 |
|
{ |
| 1367 |
|
/* It is referenced by a non-shared object. */ |
| 1368 |
|
h->ref_regular = 1; |
| 1369 |
|
h->needs_plt = 1; |
| 1370 |
|
|
| 1371 |
|
/* STT_GNU_IFUNC symbol must go through PLT. */ |
| 1372 |
|
h->plt.refcount += 1; |
| 1373 |
|
|
| 1374 |
|
/* STT_GNU_IFUNC needs dynamic sections. */ |
| 1375 |
|
if (htab->elf.dynobj == NULL) |
| 1376 |
|
htab->elf.dynobj = abfd; |
| 1377 |
|
|
| 1378 |
|
switch (r_type) |
| 1379 |
|
{ |
| 1380 |
|
default: |
| 1381 |
|
if (h->root.root.string) |
| 1382 |
|
name = h->root.root.string; |
| 1383 |
|
else |
| 1384 |
|
name = bfd_elf_sym_name (abfd, symtab_hdr, isym, |
| 1385 |
|
NULL); |
| 1386 |
|
(*_bfd_error_handler) |
| 1387 |
|
(_("%B: relocation %s against STT_GNU_IFUNC " |
| 1388 |
|
"symbol `%s' isn't handled by %s"), abfd, |
| 1389 |
|
elf_howto_table[r_type].name, |
| 1390 |
|
name, __FUNCTION__); |
| 1391 |
|
bfd_set_error (bfd_error_bad_value); |
| 1392 |
|
return FALSE; |
| 1393 |
|
|
| 1394 |
|
case R_386_32: |
| 1395 |
|
h->non_got_ref = 1; |
| 1396 |
|
h->pointer_equality_needed = 1; |
| 1397 |
|
if (info->shared) |
| 1398 |
|
{ |
| 1399 |
|
/* We must copy these reloc types into the |
| 1400 |
|
output file. Create a reloc section in |
| 1401 |
|
dynobj and make room for this reloc. */ |
| 1402 |
|
sreloc = _bfd_elf_create_ifunc_dyn_reloc |
| 1403 |
|
(abfd, info, sec, sreloc, |
| 1404 |
|
&((struct elf_i386_link_hash_entry *) h)->dyn_relocs); |
| 1405 |
|
if (sreloc == NULL) |
| 1406 |
|
return FALSE; |
| 1407 |
|
} |
| 1408 |
|
break; |
| 1409 |
|
|
| 1410 |
|
case R_386_PC32: |
| 1411 |
|
h->non_got_ref = 1; |
| 1412 |
|
break; |
| 1413 |
|
|
| 1414 |
|
case R_386_PLT32: |
| 1415 |
|
break; |
| 1416 |
|
|
| 1417 |
|
case R_386_GOT32: |
| 1418 |
|
case R_386_GOTOFF: |
| 1419 |
|
h->got.refcount += 1; |
| 1420 |
|
if (htab->elf.sgot == NULL |
| 1421 |
|
&& !_bfd_elf_create_got_section (htab->elf.dynobj, |
| 1422 |
|
info)) |
| 1423 |
|
return FALSE; |
| 1424 |
|
break; |
| 1425 |
|
} |
| 1426 |
|
|
| 1427 |
|
continue; |
| 1428 |
|
} |
| 1429 |
|
} |
| 1430 |
|
|
| 1431 |
if (! elf_i386_tls_transition (info, abfd, sec, NULL, |
if (! elf_i386_tls_transition (info, abfd, sec, NULL, |
| 1432 |
symtab_hdr, sym_hashes, |
symtab_hdr, sym_hashes, |
| 1433 |
&r_type, GOT_UNKNOWN, |
&r_type, GOT_UNKNOWN, |
| 1434 |
rel, rel_end, h)) |
rel, rel_end, h, r_symndx)) |
| 1435 |
return FALSE; |
return FALSE; |
| 1436 |
|
|
| 1437 |
switch (r_type) |
switch (r_type) |
| 1539 |
tls_type |= old_tls_type; |
tls_type |= old_tls_type; |
| 1540 |
else |
else |
| 1541 |
{ |
{ |
| 1542 |
|
if (h) |
| 1543 |
|
name = h->root.root.string; |
| 1544 |
|
else |
| 1545 |
|
name = bfd_elf_sym_name (abfd, symtab_hdr, isym, |
| 1546 |
|
NULL); |
| 1547 |
(*_bfd_error_handler) |
(*_bfd_error_handler) |
| 1548 |
(_("%B: `%s' accessed both as normal and " |
(_("%B: `%s' accessed both as normal and " |
| 1549 |
"thread local symbol"), |
"thread local symbol"), |
| 1550 |
abfd, |
abfd, name); |
|
h ? h->root.root.string : "<local>"); |
|
| 1551 |
return FALSE; |
return FALSE; |
| 1552 |
} |
} |
| 1553 |
} |
} |
| 1565 |
case R_386_GOTOFF: |
case R_386_GOTOFF: |
| 1566 |
case R_386_GOTPC: |
case R_386_GOTPC: |
| 1567 |
create_got: |
create_got: |
| 1568 |
if (htab->sgot == NULL) |
if (htab->elf.sgot == NULL) |
| 1569 |
{ |
{ |
| 1570 |
if (htab->elf.dynobj == NULL) |
if (htab->elf.dynobj == NULL) |
| 1571 |
htab->elf.dynobj = abfd; |
htab->elf.dynobj = abfd; |
| 1572 |
if (!create_got_section (htab->elf.dynobj, info)) |
if (!_bfd_elf_create_got_section (htab->elf.dynobj, info)) |
| 1573 |
return FALSE; |
return FALSE; |
| 1574 |
} |
} |
| 1575 |
if (r_type != R_386_TLS_IE) |
if (r_type != R_386_TLS_IE) |
| 1585 |
|
|
| 1586 |
case R_386_32: |
case R_386_32: |
| 1587 |
case R_386_PC32: |
case R_386_PC32: |
| 1588 |
if (h != NULL && !info->shared) |
if (h != NULL && info->executable) |
| 1589 |
{ |
{ |
| 1590 |
/* If this reloc is in a read-only section, we might |
/* If this reloc is in a read-only section, we might |
| 1591 |
need a copy reloc. We can't check reliably at this |
need a copy reloc. We can't check reliably at this |
| 1637 |
&& (h->root.type == bfd_link_hash_defweak |
&& (h->root.type == bfd_link_hash_defweak |
| 1638 |
|| !h->def_regular))) |
|| !h->def_regular))) |
| 1639 |
{ |
{ |
| 1640 |
struct elf_i386_dyn_relocs *p; |
struct elf_dyn_relocs *p; |
| 1641 |
struct elf_i386_dyn_relocs **head; |
struct elf_dyn_relocs **head; |
| 1642 |
|
|
| 1643 |
/* We must copy these reloc types into the output file. |
/* We must copy these reloc types into the output file. |
| 1644 |
Create a reloc section in dynobj and make room for |
Create a reloc section in dynobj and make room for |
| 1663 |
} |
} |
| 1664 |
else |
else |
| 1665 |
{ |
{ |
|
void **vpp; |
|
| 1666 |
/* Track dynamic relocs needed for local syms too. |
/* Track dynamic relocs needed for local syms too. |
| 1667 |
We really need local syms available to do this |
We really need local syms available to do this |
| 1668 |
easily. Oh well. */ |
easily. Oh well. */ |
| 1669 |
|
void **vpp; |
| 1670 |
asection *s; |
asection *s; |
| 1671 |
s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, |
Elf_Internal_Sym *isym; |
| 1672 |
sec, r_symndx); |
|
| 1673 |
if (s == NULL) |
isym = bfd_sym_from_r_symndx (&htab->sym_cache, |
| 1674 |
|
abfd, r_symndx); |
| 1675 |
|
if (isym == NULL) |
| 1676 |
return FALSE; |
return FALSE; |
| 1677 |
|
|
| 1678 |
|
s = bfd_section_from_elf_index (abfd, isym->st_shndx); |
| 1679 |
|
if (s == NULL) |
| 1680 |
|
s = sec; |
| 1681 |
|
|
| 1682 |
vpp = &elf_section_data (s)->local_dynrel; |
vpp = &elf_section_data (s)->local_dynrel; |
| 1683 |
head = (struct elf_i386_dyn_relocs **)vpp; |
head = (struct elf_dyn_relocs **)vpp; |
| 1684 |
} |
} |
| 1685 |
|
|
| 1686 |
p = *head; |
p = *head; |
| 1781 |
if (r_symndx >= symtab_hdr->sh_info) |
if (r_symndx >= symtab_hdr->sh_info) |
| 1782 |
{ |
{ |
| 1783 |
struct elf_i386_link_hash_entry *eh; |
struct elf_i386_link_hash_entry *eh; |
| 1784 |
struct elf_i386_dyn_relocs **pp; |
struct elf_dyn_relocs **pp; |
| 1785 |
struct elf_i386_dyn_relocs *p; |
struct elf_dyn_relocs *p; |
| 1786 |
|
|
| 1787 |
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
| 1788 |
while (h->root.type == bfd_link_hash_indirect |
while (h->root.type == bfd_link_hash_indirect |
| 1803 |
if (! elf_i386_tls_transition (info, abfd, sec, NULL, |
if (! elf_i386_tls_transition (info, abfd, sec, NULL, |
| 1804 |
symtab_hdr, sym_hashes, |
symtab_hdr, sym_hashes, |
| 1805 |
&r_type, GOT_UNKNOWN, |
&r_type, GOT_UNKNOWN, |
| 1806 |
rel, relend, h)) |
rel, relend, h, r_symndx)) |
| 1807 |
return FALSE; |
return FALSE; |
| 1808 |
|
|
| 1809 |
switch (r_type) |
switch (r_type) |
| 1867 |
struct elf_i386_link_hash_table *htab; |
struct elf_i386_link_hash_table *htab; |
| 1868 |
asection *s; |
asection *s; |
| 1869 |
|
|
| 1870 |
|
/* STT_GNU_IFUNC symbol must go through PLT. */ |
| 1871 |
|
if (h->type == STT_GNU_IFUNC) |
| 1872 |
|
{ |
| 1873 |
|
if (h->plt.refcount <= 0) |
| 1874 |
|
{ |
| 1875 |
|
h->plt.offset = (bfd_vma) -1; |
| 1876 |
|
h->needs_plt = 0; |
| 1877 |
|
} |
| 1878 |
|
return TRUE; |
| 1879 |
|
} |
| 1880 |
|
|
| 1881 |
/* If this is a function, put it in the procedure linkage table. We |
/* If this is a function, put it in the procedure linkage table. We |
| 1882 |
will fill in the contents of the procedure linkage table later, |
will fill in the contents of the procedure linkage table later, |
| 1883 |
when we know the address of the .got section. */ |
when we know the address of the .got section. */ |
| 1953 |
if (ELIMINATE_COPY_RELOCS && !htab->is_vxworks) |
if (ELIMINATE_COPY_RELOCS && !htab->is_vxworks) |
| 1954 |
{ |
{ |
| 1955 |
struct elf_i386_link_hash_entry * eh; |
struct elf_i386_link_hash_entry * eh; |
| 1956 |
struct elf_i386_dyn_relocs *p; |
struct elf_dyn_relocs *p; |
| 1957 |
|
|
| 1958 |
eh = (struct elf_i386_link_hash_entry *) h; |
eh = (struct elf_i386_link_hash_entry *) h; |
| 1959 |
for (p = eh->dyn_relocs; p != NULL; p = p->next) |
for (p = eh->dyn_relocs; p != NULL; p = p->next) |
| 2005 |
dynamic relocs. */ |
dynamic relocs. */ |
| 2006 |
|
|
| 2007 |
static bfd_boolean |
static bfd_boolean |
| 2008 |
allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) |
elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) |
| 2009 |
{ |
{ |
| 2010 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
| 2011 |
struct elf_i386_link_hash_table *htab; |
struct elf_i386_link_hash_table *htab; |
| 2012 |
struct elf_i386_link_hash_entry *eh; |
struct elf_i386_link_hash_entry *eh; |
| 2013 |
struct elf_i386_dyn_relocs *p; |
struct elf_dyn_relocs *p; |
| 2014 |
|
|
| 2015 |
if (h->root.type == bfd_link_hash_indirect) |
if (h->root.type == bfd_link_hash_indirect) |
| 2016 |
return TRUE; |
return TRUE; |
| 2020 |
entry in the hash table, thus we never get to see the real |
entry in the hash table, thus we never get to see the real |
| 2021 |
symbol in a hash traversal. So look at it now. */ |
symbol in a hash traversal. So look at it now. */ |
| 2022 |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
| 2023 |
|
eh = (struct elf_i386_link_hash_entry *) h; |
| 2024 |
|
|
| 2025 |
info = (struct bfd_link_info *) inf; |
info = (struct bfd_link_info *) inf; |
| 2026 |
htab = elf_i386_hash_table (info); |
htab = elf_i386_hash_table (info); |
| 2027 |
|
|
| 2028 |
if (htab->elf.dynamic_sections_created |
/* Since STT_GNU_IFUNC symbol must go through PLT, we handle it |
| 2029 |
&& h->plt.refcount > 0) |
here if it is defined and referenced in a non-shared object. */ |
| 2030 |
|
if (h->type == STT_GNU_IFUNC |
| 2031 |
|
&& h->def_regular) |
| 2032 |
|
return _bfd_elf_allocate_ifunc_dyn_relocs (info, h, |
| 2033 |
|
&eh->dyn_relocs, |
| 2034 |
|
PLT_ENTRY_SIZE, 4); |
| 2035 |
|
else if (htab->elf.dynamic_sections_created |
| 2036 |
|
&& h->plt.refcount > 0) |
| 2037 |
{ |
{ |
| 2038 |
/* Make sure this symbol is output as a dynamic symbol. |
/* Make sure this symbol is output as a dynamic symbol. |
| 2039 |
Undefined weak syms won't yet be marked as dynamic. */ |
Undefined weak syms won't yet be marked as dynamic. */ |
| 2047 |
if (info->shared |
if (info->shared |
| 2048 |
|| WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h)) |
|| WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h)) |
| 2049 |
{ |
{ |
| 2050 |
asection *s = htab->splt; |
asection *s = htab->elf.splt; |
| 2051 |
|
|
| 2052 |
/* If this is the first .plt entry, make room for the special |
/* If this is the first .plt entry, make room for the special |
| 2053 |
first entry. */ |
first entry. */ |
| 2073 |
|
|
| 2074 |
/* We also need to make an entry in the .got.plt section, which |
/* We also need to make an entry in the .got.plt section, which |
| 2075 |
will be placed in the .got section by the linker script. */ |
will be placed in the .got section by the linker script. */ |
| 2076 |
htab->sgotplt->size += 4; |
htab->elf.sgotplt->size += 4; |
| 2077 |
|
|
| 2078 |
/* We also need to make an entry in the .rel.plt section. */ |
/* We also need to make an entry in the .rel.plt section. */ |
| 2079 |
htab->srelplt->size += sizeof (Elf32_External_Rel); |
htab->elf.srelplt->size += sizeof (Elf32_External_Rel); |
| 2080 |
htab->next_tls_desc_index++; |
htab->next_tls_desc_index++; |
| 2081 |
|
|
| 2082 |
if (htab->is_vxworks && !info->shared) |
if (htab->is_vxworks && !info->shared) |
| 2111 |
h->needs_plt = 0; |
h->needs_plt = 0; |
| 2112 |
} |
} |
| 2113 |
|
|
|
eh = (struct elf_i386_link_hash_entry *) h; |
|
| 2114 |
eh->tlsdesc_got = (bfd_vma) -1; |
eh->tlsdesc_got = (bfd_vma) -1; |
| 2115 |
|
|
| 2116 |
/* If R_386_TLS_{IE_32,IE,GOTIE} symbol is now local to the binary, |
/* If R_386_TLS_{IE_32,IE,GOTIE} symbol is now local to the binary, |
| 2135 |
return FALSE; |
return FALSE; |
| 2136 |
} |
} |
| 2137 |
|
|
| 2138 |
s = htab->sgot; |
s = htab->elf.sgot; |
| 2139 |
if (GOT_TLS_GDESC_P (tls_type)) |
if (GOT_TLS_GDESC_P (tls_type)) |
| 2140 |
{ |
{ |
| 2141 |
eh->tlsdesc_got = htab->sgotplt->size |
eh->tlsdesc_got = htab->elf.sgotplt->size |
| 2142 |
- elf_i386_compute_jump_table_size (htab); |
- elf_i386_compute_jump_table_size (htab); |
| 2143 |
htab->sgotplt->size += 8; |
htab->elf.sgotplt->size += 8; |
| 2144 |
h->got.offset = (bfd_vma) -2; |
h->got.offset = (bfd_vma) -2; |
| 2145 |
} |
} |
| 2146 |
if (! GOT_TLS_GDESC_P (tls_type) |
if (! GOT_TLS_GDESC_P (tls_type) |
| 2159 |
need two), R_386_TLS_GD needs one if local symbol and two if |
need two), R_386_TLS_GD needs one if local symbol and two if |
| 2160 |
global. */ |
global. */ |
| 2161 |
if (tls_type == GOT_TLS_IE_BOTH) |
if (tls_type == GOT_TLS_IE_BOTH) |
| 2162 |
htab->srelgot->size += 2 * sizeof (Elf32_External_Rel); |
htab->elf.srelgot->size += 2 * sizeof (Elf32_External_Rel); |
| 2163 |
else if ((GOT_TLS_GD_P (tls_type) && h->dynindx == -1) |
else if ((GOT_TLS_GD_P (tls_type) && h->dynindx == -1) |
| 2164 |
|| (tls_type & GOT_TLS_IE)) |
|| (tls_type & GOT_TLS_IE)) |
| 2165 |
htab->srelgot->size += sizeof (Elf32_External_Rel); |
htab->elf.srelgot->size += sizeof (Elf32_External_Rel); |
| 2166 |
else if (GOT_TLS_GD_P (tls_type)) |
else if (GOT_TLS_GD_P (tls_type)) |
| 2167 |
htab->srelgot->size += 2 * sizeof (Elf32_External_Rel); |
htab->elf.srelgot->size += 2 * sizeof (Elf32_External_Rel); |
| 2168 |
else if (! GOT_TLS_GDESC_P (tls_type) |
else if (! GOT_TLS_GDESC_P (tls_type) |
| 2169 |
&& (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT |
&& (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT |
| 2170 |
|| h->root.type != bfd_link_hash_undefweak) |
|| h->root.type != bfd_link_hash_undefweak) |
| 2171 |
&& (info->shared |
&& (info->shared |
| 2172 |
|| WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))) |
|| WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))) |
| 2173 |
htab->srelgot->size += sizeof (Elf32_External_Rel); |
htab->elf.srelgot->size += sizeof (Elf32_External_Rel); |
| 2174 |
if (GOT_TLS_GDESC_P (tls_type)) |
if (GOT_TLS_GDESC_P (tls_type)) |
| 2175 |
htab->srelplt->size += sizeof (Elf32_External_Rel); |
htab->elf.srelplt->size += sizeof (Elf32_External_Rel); |
| 2176 |
} |
} |
| 2177 |
else |
else |
| 2178 |
h->got.offset = (bfd_vma) -1; |
h->got.offset = (bfd_vma) -1; |
| 2196 |
should avoid writing assembly like ".long foo - .". */ |
should avoid writing assembly like ".long foo - .". */ |
| 2197 |
if (SYMBOL_CALLS_LOCAL (info, h)) |
if (SYMBOL_CALLS_LOCAL (info, h)) |
| 2198 |
{ |
{ |
| 2199 |
struct elf_i386_dyn_relocs **pp; |
struct elf_dyn_relocs **pp; |
| 2200 |
|
|
| 2201 |
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) |
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) |
| 2202 |
{ |
{ |
| 2211 |
|
|
| 2212 |
if (htab->is_vxworks) |
if (htab->is_vxworks) |
| 2213 |
{ |
{ |
| 2214 |
struct elf_i386_dyn_relocs **pp; |
struct elf_dyn_relocs **pp; |
| 2215 |
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) |
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) |
| 2216 |
{ |
{ |
| 2217 |
if (strcmp (p->sec->output_section->name, ".tls_vars") == 0) |
if (strcmp (p->sec->output_section->name, ".tls_vars") == 0) |
| 2286 |
return TRUE; |
return TRUE; |
| 2287 |
} |
} |
| 2288 |
|
|
| 2289 |
|
/* Allocate space in .plt, .got and associated reloc sections for |
| 2290 |
|
local dynamic relocs. */ |
| 2291 |
|
|
| 2292 |
|
static bfd_boolean |
| 2293 |
|
elf_i386_allocate_local_dynrelocs (void **slot, void *inf) |
| 2294 |
|
{ |
| 2295 |
|
struct elf_link_hash_entry *h |
| 2296 |
|
= (struct elf_link_hash_entry *) *slot; |
| 2297 |
|
|
| 2298 |
|
if (h->type != STT_GNU_IFUNC |
| 2299 |
|
|| !h->def_regular |
| 2300 |
|
|| !h->ref_regular |
| 2301 |
|
|| !h->forced_local |
| 2302 |
|
|| h->root.type != bfd_link_hash_defined) |
| 2303 |
|
abort (); |
| 2304 |
|
|
| 2305 |
|
return elf_i386_allocate_dynrelocs (h, inf); |
| 2306 |
|
} |
| 2307 |
|
|
| 2308 |
/* Find any dynamic relocs that apply to read-only sections. */ |
/* Find any dynamic relocs that apply to read-only sections. */ |
| 2309 |
|
|
| 2310 |
static bfd_boolean |
static bfd_boolean |
| 2311 |
readonly_dynrelocs (struct elf_link_hash_entry *h, void *inf) |
elf_i386_readonly_dynrelocs (struct elf_link_hash_entry *h, void *inf) |
| 2312 |
{ |
{ |
| 2313 |
struct elf_i386_link_hash_entry *eh; |
struct elf_i386_link_hash_entry *eh; |
| 2314 |
struct elf_i386_dyn_relocs *p; |
struct elf_dyn_relocs *p; |
| 2315 |
|
|
| 2316 |
if (h->root.type == bfd_link_hash_warning) |
if (h->root.type == bfd_link_hash_warning) |
| 2317 |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
| 2381 |
|
|
| 2382 |
for (s = ibfd->sections; s != NULL; s = s->next) |
for (s = ibfd->sections; s != NULL; s = s->next) |
| 2383 |
{ |
{ |
| 2384 |
struct elf_i386_dyn_relocs *p; |
struct elf_dyn_relocs *p; |
| 2385 |
|
|
| 2386 |
for (p = ((struct elf_i386_dyn_relocs *) |
for (p = ((struct elf_dyn_relocs *) |
| 2387 |
elf_section_data (s)->local_dynrel); |
elf_section_data (s)->local_dynrel); |
| 2388 |
p != NULL; |
p != NULL; |
| 2389 |
p = p->next) |
p = p->next) |
| 2422 |
end_local_got = local_got + locsymcount; |
end_local_got = local_got + locsymcount; |
| 2423 |
local_tls_type = elf_i386_local_got_tls_type (ibfd); |
local_tls_type = elf_i386_local_got_tls_type (ibfd); |
| 2424 |
local_tlsdesc_gotent = elf_i386_local_tlsdesc_gotent (ibfd); |
local_tlsdesc_gotent = elf_i386_local_tlsdesc_gotent (ibfd); |
| 2425 |
s = htab->sgot; |
s = htab->elf.sgot; |
| 2426 |
srel = htab->srelgot; |
srel = htab->elf.srelgot; |
| 2427 |
for (; local_got < end_local_got; |
for (; local_got < end_local_got; |
| 2428 |
++local_got, ++local_tls_type, ++local_tlsdesc_gotent) |
++local_got, ++local_tls_type, ++local_tlsdesc_gotent) |
| 2429 |
{ |
{ |
| 2432 |
{ |
{ |
| 2433 |
if (GOT_TLS_GDESC_P (*local_tls_type)) |
if (GOT_TLS_GDESC_P (*local_tls_type)) |
| 2434 |
{ |
{ |
| 2435 |
*local_tlsdesc_gotent = htab->sgotplt->size |
*local_tlsdesc_gotent = htab->elf.sgotplt->size |
| 2436 |
- elf_i386_compute_jump_table_size (htab); |
- elf_i386_compute_jump_table_size (htab); |
| 2437 |
htab->sgotplt->size += 8; |
htab->elf.sgotplt->size += 8; |
| 2438 |
*local_got = (bfd_vma) -2; |
*local_got = (bfd_vma) -2; |
| 2439 |
} |
} |
| 2440 |
if (! GOT_TLS_GDESC_P (*local_tls_type) |
if (! GOT_TLS_GDESC_P (*local_tls_type) |
| 2456 |
|| ! GOT_TLS_GDESC_P (*local_tls_type)) |
|| ! GOT_TLS_GDESC_P (*local_tls_type)) |
| 2457 |
srel->size += sizeof (Elf32_External_Rel); |
srel->size += sizeof (Elf32_External_Rel); |
| 2458 |
if (GOT_TLS_GDESC_P (*local_tls_type)) |
if (GOT_TLS_GDESC_P (*local_tls_type)) |
| 2459 |
htab->srelplt->size += sizeof (Elf32_External_Rel); |
htab->elf.srelplt->size += sizeof (Elf32_External_Rel); |
| 2460 |
} |
} |
| 2461 |
} |
} |
| 2462 |
else |
else |
| 2468 |
{ |
{ |
| 2469 |
/* Allocate 2 got entries and 1 dynamic reloc for R_386_TLS_LDM |
/* Allocate 2 got entries and 1 dynamic reloc for R_386_TLS_LDM |
| 2470 |
relocs. */ |
relocs. */ |
| 2471 |
htab->tls_ldm_got.offset = htab->sgot->size; |
htab->tls_ldm_got.offset = htab->elf.sgot->size; |
| 2472 |
htab->sgot->size += 8; |
htab->elf.sgot->size += 8; |
| 2473 |
htab->srelgot->size += sizeof (Elf32_External_Rel); |
htab->elf.srelgot->size += sizeof (Elf32_External_Rel); |
| 2474 |
} |
} |
| 2475 |
else |
else |
| 2476 |
htab->tls_ldm_got.offset = -1; |
htab->tls_ldm_got.offset = -1; |
| 2477 |
|
|
| 2478 |
/* Allocate global sym .plt and .got entries, and space for global |
/* Allocate global sym .plt and .got entries, and space for global |
| 2479 |
sym dynamic relocs. */ |
sym dynamic relocs. */ |
| 2480 |
elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, info); |
elf_link_hash_traverse (&htab->elf, elf_i386_allocate_dynrelocs, info); |
| 2481 |
|
|
| 2482 |
|
/* Allocate .plt and .got entries, and space for local symbols. */ |
| 2483 |
|
htab_traverse (htab->loc_hash_table, |
| 2484 |
|
elf_i386_allocate_local_dynrelocs, |
| 2485 |
|
info); |
| 2486 |
|
|
| 2487 |
/* For every jump slot reserved in the sgotplt, reloc_count is |
/* For every jump slot reserved in the sgotplt, reloc_count is |
| 2488 |
incremented. However, when we reserve space for TLS descriptors, |
incremented. However, when we reserve space for TLS descriptors, |
| 2489 |
it's not incremented, so in order to compute the space reserved |
it's not incremented, so in order to compute the space reserved |
| 2490 |
for them, it suffices to multiply the reloc count by the jump |
for them, it suffices to multiply the reloc count by the jump |
| 2491 |
slot size. */ |
slot size. */ |
| 2492 |
if (htab->srelplt) |
if (htab->elf.srelplt) |
| 2493 |
htab->sgotplt_jump_table_size = htab->next_tls_desc_index * 4; |
htab->sgotplt_jump_table_size = htab->next_tls_desc_index * 4; |
| 2494 |
|
|
| 2495 |
/* We now have determined the sizes of the various dynamic sections. |
/* We now have determined the sizes of the various dynamic sections. |
| 2502 |
if ((s->flags & SEC_LINKER_CREATED) == 0) |
if ((s->flags & SEC_LINKER_CREATED) == 0) |
| 2503 |
continue; |
continue; |
| 2504 |
|
|
| 2505 |
if (s == htab->splt |
if (s == htab->elf.splt |
| 2506 |
|| s == htab->sgot |
|| s == htab->elf.sgot |
| 2507 |
|| s == htab->sgotplt |
|| s == htab->elf.sgotplt |
| 2508 |
|
|| s == htab->elf.iplt |
| 2509 |
|
|| s == htab->elf.igotplt |
| 2510 |
|| s == htab->sdynbss) |
|| s == htab->sdynbss) |
| 2511 |
{ |
{ |
| 2512 |
/* Strip this section if we don't need it; see the |
/* Strip this section if we don't need it; see the |
| 2520 |
} |
} |
| 2521 |
else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rel")) |
else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rel")) |
| 2522 |
{ |
{ |
| 2523 |
if (s->size != 0 && s != htab->srelplt && s != htab->srelplt2) |
if (s->size != 0 |
| 2524 |
|
&& s != htab->elf.srelplt |
| 2525 |
|
&& s != htab->srelplt2) |
| 2526 |
relocs = TRUE; |
relocs = TRUE; |
| 2527 |
|
|
| 2528 |
/* We use the reloc_count field as a counter if we need |
/* We use the reloc_count field as a counter if we need |
| 2580 |
return FALSE; |
return FALSE; |
| 2581 |
} |
} |
| 2582 |
|
|
| 2583 |
if (htab->splt->size != 0) |
if (htab->elf.splt->size != 0) |
| 2584 |
{ |
{ |
| 2585 |
if (!add_dynamic_entry (DT_PLTGOT, 0) |
if (!add_dynamic_entry (DT_PLTGOT, 0) |
| 2586 |
|| !add_dynamic_entry (DT_PLTRELSZ, 0) |
|| !add_dynamic_entry (DT_PLTRELSZ, 0) |
| 2599 |
/* If any dynamic relocs apply to a read-only section, |
/* If any dynamic relocs apply to a read-only section, |
| 2600 |
then we need a DT_TEXTREL entry. */ |
then we need a DT_TEXTREL entry. */ |
| 2601 |
if ((info->flags & DF_TEXTREL) == 0) |
if ((info->flags & DF_TEXTREL) == 0) |
| 2602 |
elf_link_hash_traverse (&htab->elf, readonly_dynrelocs, info); |
elf_link_hash_traverse (&htab->elf, |
| 2603 |
|
elf_i386_readonly_dynrelocs, info); |
| 2604 |
|
|
| 2605 |
if ((info->flags & DF_TEXTREL) != 0) |
if ((info->flags & DF_TEXTREL) != 0) |
| 2606 |
{ |
{ |
| 2695 |
multiple times, it is idempotent. */ |
multiple times, it is idempotent. */ |
| 2696 |
|
|
| 2697 |
static void |
static void |
| 2698 |
set_tls_module_base (struct bfd_link_info *info) |
elf_i386_set_tls_module_base (struct bfd_link_info *info) |
| 2699 |
{ |
{ |
| 2700 |
struct bfd_link_hash_entry *base; |
struct bfd_link_hash_entry *base; |
| 2701 |
|
|
| 2715 |
This is PT_TLS segment p_vaddr. */ |
This is PT_TLS segment p_vaddr. */ |
| 2716 |
|
|
| 2717 |
static bfd_vma |
static bfd_vma |
| 2718 |
dtpoff_base (struct bfd_link_info *info) |
elf_i386_dtpoff_base (struct bfd_link_info *info) |
| 2719 |
{ |
{ |
| 2720 |
/* If tls_sec is NULL, we should have signalled an error already. */ |
/* If tls_sec is NULL, we should have signalled an error already. */ |
| 2721 |
if (elf_hash_table (info)->tls_sec == NULL) |
if (elf_hash_table (info)->tls_sec == NULL) |
| 2727 |
if STT_TLS virtual address is ADDRESS. */ |
if STT_TLS virtual address is ADDRESS. */ |
| 2728 |
|
|
| 2729 |
static bfd_vma |
static bfd_vma |
| 2730 |
tpoff (struct bfd_link_info *info, bfd_vma address) |
elf_i386_tpoff (struct bfd_link_info *info, bfd_vma address) |
| 2731 |
{ |
{ |
| 2732 |
struct elf_link_hash_table *htab = elf_hash_table (info); |
struct elf_link_hash_table *htab = elf_hash_table (info); |
| 2733 |
|
|
| 2771 |
&& !strcmp (input_section->output_section->name, |
&& !strcmp (input_section->output_section->name, |
| 2772 |
".tls_vars")); |
".tls_vars")); |
| 2773 |
|
|
| 2774 |
set_tls_module_base (info); |
elf_i386_set_tls_module_base (info); |
| 2775 |
|
|
| 2776 |
rel = relocs; |
rel = relocs; |
| 2777 |
relend = relocs + input_section->reloc_count; |
relend = relocs + input_section->reloc_count; |
| 2799 |
&& ((indx = r_type - R_386_ext_offset) - R_386_standard |
&& ((indx = r_type - R_386_ext_offset) - R_386_standard |
| 2800 |
>= R_386_ext - R_386_standard) |
>= R_386_ext - R_386_standard) |
| 2801 |
&& ((indx = r_type - R_386_tls_offset) - R_386_ext |
&& ((indx = r_type - R_386_tls_offset) - R_386_ext |
| 2802 |
>= R_386_tls - R_386_ext)) |
>= R_386_irelative - R_386_ext)) |
| 2803 |
{ |
{ |
| 2804 |
(*_bfd_error_handler) |
(*_bfd_error_handler) |
| 2805 |
(_("%B: unrecognized relocation (0x%x) in section `%A'"), |
(_("%B: unrecognized relocation (0x%x) in section `%A'"), |
| 2891 |
break; |
break; |
| 2892 |
} |
} |
| 2893 |
} |
} |
| 2894 |
|
else if (!info->relocatable |
| 2895 |
|
&& ELF32_ST_TYPE (sym->st_info) == STT_GNU_IFUNC) |
| 2896 |
|
{ |
| 2897 |
|
/* Relocate against local STT_GNU_IFUNC symbol. */ |
| 2898 |
|
h = elf_i386_get_local_sym_hash (htab, input_bfd, |
| 2899 |
|
rel, FALSE); |
| 2900 |
|
if (h == NULL) |
| 2901 |
|
abort (); |
| 2902 |
|
|
| 2903 |
|
/* Set STT_GNU_IFUNC symbol value. */ |
| 2904 |
|
h->root.u.def.value = sym->st_value; |
| 2905 |
|
h->root.u.def.section = sec; |
| 2906 |
|
} |
| 2907 |
} |
} |
| 2908 |
else |
else |
| 2909 |
{ |
{ |
| 2929 |
if (info->relocatable) |
if (info->relocatable) |
| 2930 |
continue; |
continue; |
| 2931 |
|
|
| 2932 |
|
/* Since STT_GNU_IFUNC symbol must go through PLT, we handle |
| 2933 |
|
it here if it is defined in a non-shared object. */ |
| 2934 |
|
if (h != NULL |
| 2935 |
|
&& h->type == STT_GNU_IFUNC |
| 2936 |
|
&& h->def_regular) |
| 2937 |
|
{ |
| 2938 |
|
asection *plt, *gotplt, *base_got; |
| 2939 |
|
bfd_vma plt_index; |
| 2940 |
|
const char *name; |
| 2941 |
|
|
| 2942 |
|
if ((input_section->flags & SEC_ALLOC) == 0 |
| 2943 |
|
|| h->plt.offset == (bfd_vma) -1) |
| 2944 |
|
abort (); |
| 2945 |
|
|
| 2946 |
|
/* STT_GNU_IFUNC symbol must go through PLT. */ |
| 2947 |
|
if (htab->elf.splt != NULL) |
| 2948 |
|
{ |
| 2949 |
|
plt = htab->elf.splt; |
| 2950 |
|
gotplt = htab->elf.sgotplt; |
| 2951 |
|
} |
| 2952 |
|
else |
| 2953 |
|
{ |
| 2954 |
|
plt = htab->elf.iplt; |
| 2955 |
|
gotplt = htab->elf.igotplt; |
| 2956 |
|
} |
| 2957 |
|
|
| 2958 |
|
relocation = (plt->output_section->vma |
| 2959 |
|
+ plt->output_offset + h->plt.offset); |
| 2960 |
|
|
| 2961 |
|
switch (r_type) |
| 2962 |
|
{ |
| 2963 |
|
default: |
| 2964 |
|
if (h->root.root.string) |
| 2965 |
|
name = h->root.root.string; |
| 2966 |
|
else |
| 2967 |
|
name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, |
| 2968 |
|
NULL); |
| 2969 |
|
(*_bfd_error_handler) |
| 2970 |
|
(_("%B: relocation %s against STT_GNU_IFUNC " |
| 2971 |
|
"symbol `%s' isn't handled by %s"), input_bfd, |
| 2972 |
|
elf_howto_table[r_type].name, |
| 2973 |
|
name, __FUNCTION__); |
| 2974 |
|
bfd_set_error (bfd_error_bad_value); |
| 2975 |
|
return FALSE; |
| 2976 |
|
|
| 2977 |
|
case R_386_32: |
| 2978 |
|
/* Generate dynamic relcoation only when there is a |
| 2979 |
|
non-GOF reference in a shared object. */ |
| 2980 |
|
if (info->shared && h->non_got_ref) |
| 2981 |
|
{ |
| 2982 |
|
Elf_Internal_Rela outrel; |
| 2983 |
|
bfd_byte *loc; |
| 2984 |
|
asection *sreloc; |
| 2985 |
|
bfd_vma offset; |
| 2986 |
|
|
| 2987 |
|
/* Need a dynamic relocation to get the real function |
| 2988 |
|
adddress. */ |
| 2989 |
|
offset = _bfd_elf_section_offset (output_bfd, |
| 2990 |
|
info, |
| 2991 |
|
input_section, |
| 2992 |
|
rel->r_offset); |
| 2993 |
|
if (offset == (bfd_vma) -1 |
| 2994 |
|
|| offset == (bfd_vma) -2) |
| 2995 |
|
abort (); |
| 2996 |
|
|
| 2997 |
|
outrel.r_offset = (input_section->output_section->vma |
| 2998 |
|
+ input_section->output_offset |
| 2999 |
|
+ offset); |
| 3000 |
|
|
| 3001 |
|
if (h->dynindx == -1 |
| 3002 |
|
|| h->forced_local |
| 3003 |
|
|| info->executable) |
| 3004 |
|
{ |
| 3005 |
|
/* This symbol is resolved locally. */ |
| 3006 |
|
outrel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE); |
| 3007 |
|
bfd_put_32 (output_bfd, |
| 3008 |
|
(h->root.u.def.value |
| 3009 |
|
+ h->root.u.def.section->output_section->vma |
| 3010 |
|
+ h->root.u.def.section->output_offset), |
| 3011 |
|
contents + offset); |
| 3012 |
|
} |
| 3013 |
|
else |
| 3014 |
|
outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); |
| 3015 |
|
|
| 3016 |
|
sreloc = htab->elf.irelifunc; |
| 3017 |
|
loc = sreloc->contents; |
| 3018 |
|
loc += (sreloc->reloc_count++ |
| 3019 |
|
* sizeof (Elf32_External_Rel)); |
| 3020 |
|
bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); |
| 3021 |
|
|
| 3022 |
|
/* If this reloc is against an external symbol, we |
| 3023 |
|
do not want to fiddle with the addend. Otherwise, |
| 3024 |
|
we need to include the symbol value so that it |
| 3025 |
|
becomes an addend for the dynamic reloc. For an |
| 3026 |
|
internal symbol, we have updated addend. */ |
| 3027 |
|
continue; |
| 3028 |
|
} |
| 3029 |
|
|
| 3030 |
|
case R_386_PC32: |
| 3031 |
|
case R_386_PLT32: |
| 3032 |
|
goto do_relocation; |
| 3033 |
|
|
| 3034 |
|
case R_386_GOT32: |
| 3035 |
|
base_got = htab->elf.sgot; |
| 3036 |
|
off = h->got.offset; |
| 3037 |
|
|
| 3038 |
|
if (base_got == NULL) |
| 3039 |
|
abort (); |
| 3040 |
|
|
| 3041 |
|
if (off == (bfd_vma) -1) |
| 3042 |
|
{ |
| 3043 |
|
/* We can't use h->got.offset here to save state, or |
| 3044 |
|
even just remember the offset, as finish_dynamic_symbol |
| 3045 |
|
would use that as offset into .got. */ |
| 3046 |
|
|
| 3047 |
|
if (htab->elf.splt != NULL) |
| 3048 |
|
{ |
| 3049 |
|
plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1; |
| 3050 |
|
off = (plt_index + 3) * 4; |
| 3051 |
|
base_got = htab->elf.sgotplt; |
| 3052 |
|
} |
| 3053 |
|
else |
| 3054 |
|
{ |
| 3055 |
|
plt_index = h->plt.offset / PLT_ENTRY_SIZE; |
| 3056 |
|
off = plt_index * 4; |
| 3057 |
|
base_got = htab->elf.igotplt; |
| 3058 |
|
} |
| 3059 |
|
|
| 3060 |
|
if (h->dynindx == -1 |
| 3061 |
|
|| h->forced_local |
| 3062 |
|
|| info->symbolic) |
| 3063 |
|
{ |
| 3064 |
|
/* This references the local defitionion. We must |
| 3065 |
|
initialize this entry in the global offset table. |
| 3066 |
|
Since the offset must always be a multiple of 8, |
| 3067 |
|
we use the least significant bit to record |
| 3068 |
|
whether we have initialized it already. |
| 3069 |
|
|
| 3070 |
|
When doing a dynamic link, we create a .rela.got |
| 3071 |
|
relocation entry to initialize the value. This |
| 3072 |
|
is done in the finish_dynamic_symbol routine. */ |
| 3073 |
|
if ((off & 1) != 0) |
| 3074 |
|
off &= ~1; |
| 3075 |
|
else |
| 3076 |
|
{ |
| 3077 |
|
bfd_put_32 (output_bfd, relocation, |
| 3078 |
|
base_got->contents + off); |
| 3079 |
|
h->got.offset |= 1; |
| 3080 |
|
} |
| 3081 |
|
} |
| 3082 |
|
|
| 3083 |
|
relocation = off; |
| 3084 |
|
|
| 3085 |
|
/* Adjust for static executables. */ |
| 3086 |
|
if (htab->elf.splt == NULL) |
| 3087 |
|
relocation += gotplt->output_offset; |
| 3088 |
|
} |
| 3089 |
|
else |
| 3090 |
|
{ |
| 3091 |
|
relocation = (base_got->output_section->vma |
| 3092 |
|
+ base_got->output_offset + off |
| 3093 |
|
- gotplt->output_section->vma |
| 3094 |
|
- gotplt->output_offset); |
| 3095 |
|
/* Adjust for static executables. */ |
| 3096 |
|
if (htab->elf.splt == NULL) |
| 3097 |
|
relocation += gotplt->output_offset; |
| 3098 |
|
} |
| 3099 |
|
|
| 3100 |
|
goto do_relocation; |
| 3101 |
|
|
| 3102 |
|
case R_386_GOTOFF: |
| 3103 |
|
relocation -= (gotplt->output_section->vma |
| 3104 |
|
+ gotplt->output_offset); |
| 3105 |
|
goto do_relocation; |
| 3106 |
|
} |
| 3107 |
|
} |
| 3108 |
|
|
| 3109 |
switch (r_type) |
switch (r_type) |
| 3110 |
{ |
{ |
| 3111 |
case R_386_GOT32: |
case R_386_GOT32: |
| 3112 |
/* Relocation is to the entry for this symbol in the global |
/* Relocation is to the entry for this symbol in the global |
| 3113 |
offset table. */ |
offset table. */ |
| 3114 |
if (htab->sgot == NULL) |
if (htab->elf.sgot == NULL) |
| 3115 |
abort (); |
abort (); |
| 3116 |
|
|
| 3117 |
if (h != NULL) |
if (h != NULL) |
| 3143 |
else |
else |
| 3144 |
{ |
{ |
| 3145 |
bfd_put_32 (output_bfd, relocation, |
bfd_put_32 (output_bfd, relocation, |
| 3146 |
htab->sgot->contents + off); |
htab->elf.sgot->contents + off); |
| 3147 |
h->got.offset |= 1; |
h->got.offset |= 1; |
| 3148 |
} |
} |
| 3149 |
} |
} |
| 3165 |
else |
else |
| 3166 |
{ |
{ |
| 3167 |
bfd_put_32 (output_bfd, relocation, |
bfd_put_32 (output_bfd, relocation, |
| 3168 |
htab->sgot->contents + off); |
htab->elf.sgot->contents + off); |
| 3169 |
|
|
| 3170 |
if (info->shared) |
if (info->shared) |
| 3171 |
{ |
{ |
| 3173 |
Elf_Internal_Rela outrel; |
Elf_Internal_Rela outrel; |
| 3174 |
bfd_byte *loc; |
bfd_byte *loc; |
| 3175 |
|
|
| 3176 |
s = htab->srelgot; |
s = htab->elf.srelgot; |
| 3177 |
if (s == NULL) |
if (s == NULL) |
| 3178 |
abort (); |
abort (); |
| 3179 |
|
|
| 3180 |
outrel.r_offset = (htab->sgot->output_section->vma |
outrel.r_offset = (htab->elf.sgot->output_section->vma |
| 3181 |
+ htab->sgot->output_offset |
+ htab->elf.sgot->output_offset |
| 3182 |
+ off); |
+ off); |
| 3183 |
outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); |
outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); |
| 3184 |
loc = s->contents; |
loc = s->contents; |
| 3193 |
if (off >= (bfd_vma) -2) |
if (off >= (bfd_vma) -2) |
| 3194 |
abort (); |
abort (); |
| 3195 |
|
|
| 3196 |
relocation = htab->sgot->output_section->vma |
relocation = htab->elf.sgot->output_section->vma |
| 3197 |
+ htab->sgot->output_offset + off |
+ htab->elf.sgot->output_offset + off |
| 3198 |
- htab->sgotplt->output_section->vma |
- htab->elf.sgotplt->output_section->vma |
| 3199 |
- htab->sgotplt->output_offset; |
- htab->elf.sgotplt->output_offset; |
| 3200 |
break; |
break; |
| 3201 |
|
|
| 3202 |
case R_386_GOTOFF: |
case R_386_GOTOFF: |
| 3252 |
defined _GLOBAL_OFFSET_TABLE_ in a different way, as is |
defined _GLOBAL_OFFSET_TABLE_ in a different way, as is |
| 3253 |
permitted by the ABI, we might have to change this |
permitted by the ABI, we might have to change this |
| 3254 |
calculation. */ |
calculation. */ |
| 3255 |
relocation -= htab->sgotplt->output_section->vma |
relocation -= htab->elf.sgotplt->output_section->vma |
| 3256 |
+ htab->sgotplt->output_offset; |
+ htab->elf.sgotplt->output_offset; |
| 3257 |
break; |
break; |
| 3258 |
|
|
| 3259 |
case R_386_GOTPC: |
case R_386_GOTPC: |
| 3260 |
/* Use global offset table as symbol value. */ |
/* Use global offset table as symbol value. */ |
| 3261 |
relocation = htab->sgotplt->output_section->vma |
relocation = htab->elf.sgotplt->output_section->vma |
| 3262 |
+ htab->sgotplt->output_offset; |
+ htab->elf.sgotplt->output_offset; |
| 3263 |
unresolved_reloc = FALSE; |
unresolved_reloc = FALSE; |
| 3264 |
break; |
break; |
| 3265 |
|
|
| 3273 |
break; |
break; |
| 3274 |
|
|
| 3275 |
if (h->plt.offset == (bfd_vma) -1 |
if (h->plt.offset == (bfd_vma) -1 |
| 3276 |
|| htab->splt == NULL) |
|| htab->elf.splt == NULL) |
| 3277 |
{ |
{ |
| 3278 |
/* We didn't make a PLT entry for this symbol. This |
/* We didn't make a PLT entry for this symbol. This |
| 3279 |
happens when statically linking PIC code, or when |
happens when statically linking PIC code, or when |
| 3281 |
break; |
break; |
| 3282 |
} |
} |
| 3283 |
|
|
| 3284 |
relocation = (htab->splt->output_section->vma |
relocation = (htab->elf.splt->output_section->vma |
| 3285 |
+ htab->splt->output_offset |
+ htab->elf.splt->output_offset |
| 3286 |
+ h->plt.offset); |
+ h->plt.offset); |
| 3287 |
unresolved_reloc = FALSE; |
unresolved_reloc = FALSE; |
| 3288 |
break; |
break; |
| 3402 |
input_section, contents, |
input_section, contents, |
| 3403 |
symtab_hdr, sym_hashes, |
symtab_hdr, sym_hashes, |
| 3404 |
&r_type, tls_type, rel, |
&r_type, tls_type, rel, |
| 3405 |
relend, h)) |
relend, h, r_symndx)) |
| 3406 |
return FALSE; |
return FALSE; |
| 3407 |
|
|
| 3408 |
if (r_type == R_386_TLS_LE_32) |
if (r_type == R_386_TLS_LE_32) |
| 3435 |
"\x65\xa1\0\0\0\0\x81\xe8\0\0\0", 12); |
"\x65\xa1\0\0\0\0\x81\xe8\0\0\0", 12); |
| 3436 |
roff = rel->r_offset + 6; |
roff = rel->r_offset + 6; |
| 3437 |
} |
} |
| 3438 |
bfd_put_32 (output_bfd, tpoff (info, relocation), |
bfd_put_32 (output_bfd, elf_i386_tpoff (info, relocation), |
| 3439 |
contents + roff); |
contents + roff); |
| 3440 |
/* Skip R_386_PC32/R_386_PLT32. */ |
/* Skip R_386_PC32/R_386_PLT32. */ |
| 3441 |
rel++; |
rel++; |
| 3462 |
below with 0x86. */ |
below with 0x86. */ |
| 3463 |
bfd_put_8 (output_bfd, val ^ 0x86, |
bfd_put_8 (output_bfd, val ^ 0x86, |
| 3464 |
contents + roff - 1); |
contents + roff - 1); |
| 3465 |
bfd_put_32 (output_bfd, -tpoff (info, relocation), |
bfd_put_32 (output_bfd, -elf_i386_tpoff (info, relocation), |
| 3466 |
contents + roff); |
contents + roff); |
| 3467 |
continue; |
continue; |
| 3468 |
} |
} |
| 3530 |
break; |
break; |
| 3531 |
} |
} |
| 3532 |
} |
} |
| 3533 |
bfd_put_32 (output_bfd, -tpoff (info, relocation), |
bfd_put_32 (output_bfd, -elf_i386_tpoff (info, relocation), |
| 3534 |
contents + rel->r_offset); |
contents + rel->r_offset); |
| 3535 |
continue; |
continue; |
| 3536 |
} |
} |
| 3576 |
else |
else |
| 3577 |
BFD_FAIL (); |
BFD_FAIL (); |
| 3578 |
if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTIE) |
if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTIE) |
| 3579 |
bfd_put_32 (output_bfd, -tpoff (info, relocation), |
bfd_put_32 (output_bfd, -elf_i386_tpoff (info, relocation), |
| 3580 |
contents + rel->r_offset); |
contents + rel->r_offset); |
| 3581 |
else |
else |
| 3582 |
bfd_put_32 (output_bfd, tpoff (info, relocation), |
bfd_put_32 (output_bfd, elf_i386_tpoff (info, relocation), |
| 3583 |
contents + rel->r_offset); |
contents + rel->r_offset); |
| 3584 |
continue; |
continue; |
| 3585 |
} |
} |
| 3586 |
} |
} |
| 3587 |
|
|
| 3588 |
if (htab->sgot == NULL) |
if (htab->elf.sgot == NULL) |
| 3589 |
abort (); |
abort (); |
| 3590 |
|
|
| 3591 |
if (h != NULL) |
if (h != NULL) |
| 3611 |
int dr_type, indx; |
int dr_type, indx; |
| 3612 |
asection *sreloc; |
asection *sreloc; |
| 3613 |
|
|
| 3614 |
if (htab->srelgot == NULL) |
if (htab->elf.srelgot == NULL) |
| 3615 |
abort (); |
abort (); |
| 3616 |
|
|
| 3617 |
indx = h && h->dynindx != -1 ? h->dynindx : 0; |
indx = h && h->dynindx != -1 ? h->dynindx : 0; |
| 3620 |
{ |
{ |
| 3621 |
outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_DESC); |
outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_DESC); |
| 3622 |
BFD_ASSERT (htab->sgotplt_jump_table_size + offplt + 8 |
BFD_ASSERT (htab->sgotplt_jump_table_size + offplt + 8 |
| 3623 |
<= htab->sgotplt->size); |
<= htab->elf.sgotplt->size); |
| 3624 |
outrel.r_offset = (htab->sgotplt->output_section->vma |
outrel.r_offset = (htab->elf.sgotplt->output_section->vma |
| 3625 |
+ htab->sgotplt->output_offset |
+ htab->elf.sgotplt->output_offset |
| 3626 |
+ offplt |
+ offplt |
| 3627 |
+ htab->sgotplt_jump_table_size); |
+ htab->sgotplt_jump_table_size); |
| 3628 |
sreloc = htab->srelplt; |
sreloc = htab->elf.srelplt; |
| 3629 |
loc = sreloc->contents; |
loc = sreloc->contents; |
| 3630 |
loc += (htab->next_tls_desc_index++ |
loc += (htab->next_tls_desc_index++ |
| 3631 |
* sizeof (Elf32_External_Rel)); |
* sizeof (Elf32_External_Rel)); |
| 3636 |
{ |
{ |
| 3637 |
BFD_ASSERT (! unresolved_reloc); |
BFD_ASSERT (! unresolved_reloc); |
| 3638 |
bfd_put_32 (output_bfd, |
bfd_put_32 (output_bfd, |
| 3639 |
relocation - dtpoff_base (info), |
relocation - elf_i386_dtpoff_base (info), |
| 3640 |
htab->sgotplt->contents + offplt |
htab->elf.sgotplt->contents + offplt |
| 3641 |
+ htab->sgotplt_jump_table_size + 4); |
+ htab->sgotplt_jump_table_size + 4); |
| 3642 |
} |
} |
| 3643 |
else |
else |
| 3644 |
{ |
{ |
| 3645 |
bfd_put_32 (output_bfd, 0, |
bfd_put_32 (output_bfd, 0, |
| 3646 |
htab->sgotplt->contents + offplt |
htab->elf.sgotplt->contents + offplt |
| 3647 |
+ htab->sgotplt_jump_table_size + 4); |
+ htab->sgotplt_jump_table_size + 4); |
| 3648 |
} |
} |
| 3649 |
} |
} |
| 3650 |
|
|
| 3651 |
sreloc = htab->srelgot; |
sreloc = htab->elf.srelgot; |
| 3652 |
|
|
| 3653 |
outrel.r_offset = (htab->sgot->output_section->vma |
outrel.r_offset = (htab->elf.sgot->output_section->vma |
| 3654 |
+ htab->sgot->output_offset + off); |
+ htab->elf.sgot->output_offset + off); |
| 3655 |
|
|
| 3656 |
if (GOT_TLS_GD_P (tls_type)) |
if (GOT_TLS_GD_P (tls_type)) |
| 3657 |
dr_type = R_386_TLS_DTPMOD32; |
dr_type = R_386_TLS_DTPMOD32; |
| 3663 |
dr_type = R_386_TLS_TPOFF32; |
dr_type = R_386_TLS_TPOFF32; |
| 3664 |
|
|
| 3665 |
if (dr_type == R_386_TLS_TPOFF && indx == 0) |
if (dr_type == R_386_TLS_TPOFF && indx == 0) |
| 3666 |
bfd_put_32 (output_bfd, relocation - dtpoff_base (info), |
bfd_put_32 (output_bfd, |
| 3667 |
htab->sgot->contents + off); |
relocation - elf_i386_dtpoff_base (info), |
| 3668 |
|
htab->elf.sgot->contents + off); |
| 3669 |
else if (dr_type == R_386_TLS_TPOFF32 && indx == 0) |
else if (dr_type == R_386_TLS_TPOFF32 && indx == 0) |
| 3670 |
bfd_put_32 (output_bfd, dtpoff_base (info) - relocation, |
bfd_put_32 (output_bfd, |
| 3671 |
htab->sgot->contents + off); |
elf_i386_dtpoff_base (info) - relocation, |
| 3672 |
|
htab->elf.sgot->contents + off); |
| 3673 |
else if (dr_type != R_386_TLS_DESC) |
else if (dr_type != R_386_TLS_DESC) |
| 3674 |
bfd_put_32 (output_bfd, 0, |
bfd_put_32 (output_bfd, 0, |
| 3675 |
htab->sgot->contents + off); |
htab->elf.sgot->contents + off); |
| 3676 |
outrel.r_info = ELF32_R_INFO (indx, dr_type); |
outrel.r_info = ELF32_R_INFO (indx, dr_type); |
| 3677 |
|
|
| 3678 |
loc = sreloc->contents; |
loc = sreloc->contents; |
| 3687 |
{ |
{ |
| 3688 |
BFD_ASSERT (! unresolved_reloc); |
BFD_ASSERT (! unresolved_reloc); |
| 3689 |
bfd_put_32 (output_bfd, |
bfd_put_32 (output_bfd, |
| 3690 |
relocation - dtpoff_base (info), |
relocation - elf_i386_dtpoff_base (info), |
| 3691 |
htab->sgot->contents + off + 4); |
htab->elf.sgot->contents + off + 4); |
| 3692 |
} |
} |
| 3693 |
else |
else |
| 3694 |
{ |
{ |
| 3695 |
bfd_put_32 (output_bfd, 0, |
bfd_put_32 (output_bfd, 0, |
| 3696 |
htab->sgot->contents + off + 4); |
htab->elf.sgot->contents + off + 4); |
| 3697 |
outrel.r_info = ELF32_R_INFO (indx, |
outrel.r_info = ELF32_R_INFO (indx, |
| 3698 |
R_386_TLS_DTPOFF32); |
R_386_TLS_DTPOFF32); |
| 3699 |
outrel.r_offset += 4; |
outrel.r_offset += 4; |
| 3707 |
else if (tls_type == GOT_TLS_IE_BOTH) |
else if (tls_type == GOT_TLS_IE_BOTH) |
| 3708 |
{ |
{ |
| 3709 |
bfd_put_32 (output_bfd, |
bfd_put_32 (output_bfd, |
| 3710 |
indx == 0 ? relocation - dtpoff_base (info) : 0, |
(indx == 0 |
| 3711 |
htab->sgot->contents + off + 4); |
? relocation - elf_i386_dtpoff_base (info) |
| 3712 |
|
: 0), |
| 3713 |
|
htab->elf.sgot->contents + off + 4); |
| 3714 |
outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_TPOFF); |
outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_TPOFF); |
| 3715 |
outrel.r_offset += 4; |
outrel.r_offset += 4; |
| 3716 |
sreloc->reloc_count++; |
sreloc->reloc_count++; |
| 3736 |
} |
} |
| 3737 |
else if (r_type == ELF32_R_TYPE (rel->r_info)) |
else if (r_type == ELF32_R_TYPE (rel->r_info)) |
| 3738 |
{ |
{ |
| 3739 |
bfd_vma g_o_t = htab->sgotplt->output_section->vma |
bfd_vma g_o_t = htab->elf.sgotplt->output_section->vma |
| 3740 |
+ htab->sgotplt->output_offset; |
+ htab->elf.sgotplt->output_offset; |
| 3741 |
relocation = htab->sgot->output_section->vma |
relocation = htab->elf.sgot->output_section->vma |
| 3742 |
+ htab->sgot->output_offset + off - g_o_t; |
+ htab->elf.sgot->output_offset + off - g_o_t; |
| 3743 |
if ((r_type == R_386_TLS_IE || r_type == R_386_TLS_GOTIE) |
if ((r_type == R_386_TLS_IE || r_type == R_386_TLS_GOTIE) |
| 3744 |
&& tls_type == GOT_TLS_IE_BOTH) |
&& tls_type == GOT_TLS_IE_BOTH) |
| 3745 |
relocation += 4; |
relocation += 4; |
| 3781 |
if (tls_type == GOT_TLS_IE_POS) |
if (tls_type == GOT_TLS_IE_POS) |
| 3782 |
contents[roff + 6] = 0x03; |
contents[roff + 6] = 0x03; |
| 3783 |
bfd_put_32 (output_bfd, |
bfd_put_32 (output_bfd, |
| 3784 |
htab->sgot->output_section->vma |
htab->elf.sgot->output_section->vma |
| 3785 |
+ htab->sgot->output_offset + off |
+ htab->elf.sgot->output_offset + off |
| 3786 |
- htab->sgotplt->output_section->vma |
- htab->elf.sgotplt->output_section->vma |
| 3787 |
- htab->sgotplt->output_offset, |
- htab->elf.sgotplt->output_offset, |
| 3788 |
contents + roff + 8); |
contents + roff + 8); |
| 3789 |
/* Skip R_386_PLT32. */ |
/* Skip R_386_PLT32. */ |
| 3790 |
rel++; |
rel++; |
| 3822 |
off += 4; |
off += 4; |
| 3823 |
|
|
| 3824 |
bfd_put_32 (output_bfd, |
bfd_put_32 (output_bfd, |
| 3825 |
htab->sgot->output_section->vma |
htab->elf.sgot->output_section->vma |
| 3826 |
+ htab->sgot->output_offset + off |
+ htab->elf.sgot->output_offset + off |
| 3827 |
- htab->sgotplt->output_section->vma |
- htab->elf.sgotplt->output_section->vma |
| 3828 |
- htab->sgotplt->output_offset, |
- htab->elf.sgotplt->output_offset, |
| 3829 |
contents + roff); |
contents + roff); |
| 3830 |
continue; |
continue; |
| 3831 |
} |
} |
| 3871 |
input_section, contents, |
input_section, contents, |
| 3872 |
symtab_hdr, sym_hashes, |
symtab_hdr, sym_hashes, |
| 3873 |
&r_type, GOT_UNKNOWN, rel, |
&r_type, GOT_UNKNOWN, rel, |
| 3874 |
relend, h)) |
relend, h, r_symndx)) |
| 3875 |
return FALSE; |
return FALSE; |
| 3876 |
|
|
| 3877 |
if (r_type != R_386_TLS_LDM) |
if (r_type != R_386_TLS_LDM) |
| 3888 |
continue; |
continue; |
| 3889 |
} |
} |
| 3890 |
|
|
| 3891 |
if (htab->sgot == NULL) |
if (htab->elf.sgot == NULL) |
| 3892 |
abort (); |
abort (); |
| 3893 |
|
|
| 3894 |
off = htab->tls_ldm_got.offset; |
off = htab->tls_ldm_got.offset; |
| 3899 |
Elf_Internal_Rela outrel; |
Elf_Internal_Rela outrel; |
| 3900 |
bfd_byte *loc; |
bfd_byte *loc; |
| 3901 |
|
|
| 3902 |
if (htab->srelgot == NULL) |
if (htab->elf.srelgot == NULL) |
| 3903 |
abort (); |
abort (); |
| 3904 |
|
|
| 3905 |
outrel.r_offset = (htab->sgot->output_section->vma |
outrel.r_offset = (htab->elf.sgot->output_section->vma |
| 3906 |
+ htab->sgot->output_offset + off); |
+ htab->elf.sgot->output_offset + off); |
| 3907 |
|
|
| 3908 |
bfd_put_32 (output_bfd, 0, |
bfd_put_32 (output_bfd, 0, |
| 3909 |
htab->sgot->contents + off); |
htab->elf.sgot->contents + off); |
| 3910 |
bfd_put_32 (output_bfd, 0, |
bfd_put_32 (output_bfd, 0, |
| 3911 |
htab->sgot->contents + off + 4); |
htab->elf.sgot->contents + off + 4); |
| 3912 |
outrel.r_info = ELF32_R_INFO (0, R_386_TLS_DTPMOD32); |
outrel.r_info = ELF32_R_INFO (0, R_386_TLS_DTPMOD32); |
| 3913 |
loc = htab->srelgot->contents; |
loc = htab->elf.srelgot->contents; |
| 3914 |
loc += htab->srelgot->reloc_count++ * sizeof (Elf32_External_Rel); |
loc += htab->elf.srelgot->reloc_count++ * sizeof (Elf32_External_Rel); |
| 3915 |
bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); |
bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); |
| 3916 |
htab->tls_ldm_got.offset |= 1; |
htab->tls_ldm_got.offset |= 1; |
| 3917 |
} |
} |
| 3918 |
relocation = htab->sgot->output_section->vma |
relocation = htab->elf.sgot->output_section->vma |
| 3919 |
+ htab->sgot->output_offset + off |
+ htab->elf.sgot->output_offset + off |
| 3920 |
- htab->sgotplt->output_section->vma |
- htab->elf.sgotplt->output_section->vma |
| 3921 |
- htab->sgotplt->output_offset; |
- htab->elf.sgotplt->output_offset; |
| 3922 |
unresolved_reloc = FALSE; |
unresolved_reloc = FALSE; |
| 3923 |
break; |
break; |
| 3924 |
|
|
| 3925 |
case R_386_TLS_LDO_32: |
case R_386_TLS_LDO_32: |
| 3926 |
if (info->shared || (input_section->flags & SEC_CODE) == 0) |
if (info->shared || (input_section->flags & SEC_CODE) == 0) |
| 3927 |
relocation -= dtpoff_base (info); |
relocation -= elf_i386_dtpoff_base (info); |
| 3928 |
else |
else |
| 3929 |
/* When converting LDO to LE, we must negate. */ |
/* When converting LDO to LE, we must negate. */ |
| 3930 |
relocation = -tpoff (info, relocation); |
relocation = -elf_i386_tpoff (info, relocation); |
| 3931 |
break; |
break; |
| 3932 |
|
|
| 3933 |
case R_386_TLS_LE_32: |
case R_386_TLS_LE_32: |
| 3959 |
if (indx) |
if (indx) |
| 3960 |
continue; |
continue; |
| 3961 |
else if (r_type == R_386_TLS_LE_32) |
else if (r_type == R_386_TLS_LE_32) |
| 3962 |
relocation = dtpoff_base (info) - relocation; |
relocation = elf_i386_dtpoff_base (info) - relocation; |
| 3963 |
else |
else |
| 3964 |
relocation -= dtpoff_base (info); |
relocation -= elf_i386_dtpoff_base (info); |
| 3965 |
} |
} |
| 3966 |
else if (r_type == R_386_TLS_LE_32) |
else if (r_type == R_386_TLS_LE_32) |
| 3967 |
relocation = tpoff (info, relocation); |
relocation = elf_i386_tpoff (info, relocation); |
| 3968 |
else |
else |
| 3969 |
relocation = -tpoff (info, relocation); |
relocation = -elf_i386_tpoff (info, relocation); |
| 3970 |
break; |
break; |
| 3971 |
|
|
| 3972 |
default: |
default: |
| 3990 |
return FALSE; |
return FALSE; |
| 3991 |
} |
} |
| 3992 |
|
|
| 3993 |
|
do_relocation: |
| 3994 |
r = _bfd_final_link_relocate (howto, input_bfd, input_section, |
r = _bfd_final_link_relocate (howto, input_bfd, input_section, |
| 3995 |
contents, rel->r_offset, |
contents, rel->r_offset, |
| 3996 |
relocation, 0); |
relocation, 0); |
| 4053 |
bfd_vma got_offset; |
bfd_vma got_offset; |
| 4054 |
Elf_Internal_Rela rel; |
Elf_Internal_Rela rel; |
| 4055 |
bfd_byte *loc; |
bfd_byte *loc; |
| 4056 |
|
asection *plt, *gotplt, *relplt; |
| 4057 |
|
|
| 4058 |
|
/* When building a static executable, use .iplt, .igot.plt and |
| 4059 |
|
.rel.iplt sections for STT_GNU_IFUNC symbols. */ |
| 4060 |
|
if (htab->elf.splt != NULL) |
| 4061 |
|
{ |
| 4062 |
|
plt = htab->elf.splt; |
| 4063 |
|
gotplt = htab->elf.sgotplt; |
| 4064 |
|
relplt = htab->elf.srelplt; |
| 4065 |
|
} |
| 4066 |
|
else |
| 4067 |
|
{ |
| 4068 |
|
plt = htab->elf.iplt; |
| 4069 |
|
gotplt = htab->elf.igotplt; |
| 4070 |
|
relplt = htab->elf.irelplt; |
| 4071 |
|
} |
| 4072 |
|
|
| 4073 |
/* This symbol has an entry in the procedure linkage table. Set |
/* This symbol has an entry in the procedure linkage table. Set |
| 4074 |
it up. */ |
it up. */ |
| 4075 |
|
|
| 4076 |
if (h->dynindx == -1 |
if ((h->dynindx == -1 |
| 4077 |
|| htab->splt == NULL |
&& !((h->forced_local || info->executable) |
| 4078 |
|| htab->sgotplt == NULL |
&& h->def_regular |
| 4079 |
|| htab->srelplt == NULL) |
&& h->type == STT_GNU_IFUNC)) |
| 4080 |
|
|| plt == NULL |
| 4081 |
|
|| gotplt == NULL |
| 4082 |
|
|| relplt == NULL) |
| 4083 |
abort (); |
abort (); |
| 4084 |
|
|
| 4085 |
/* Get the index in the procedure linkage table which |
/* Get the index in the procedure linkage table which |
| 4086 |
corresponds to this symbol. This is the index of this symbol |
corresponds to this symbol. This is the index of this symbol |
| 4087 |
in all the symbols for which we are making plt entries. The |
in all the symbols for which we are making plt entries. The |
| 4088 |
first entry in the procedure linkage table is reserved. */ |
first entry in the procedure linkage table is reserved. |
|
plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1; |
|
| 4089 |
|
|
| 4090 |
/* Get the offset into the .got table of the entry that |
Get the offset into the .got table of the entry that |
| 4091 |
corresponds to this function. Each .got entry is 4 bytes. |
corresponds to this function. Each .got entry is 4 bytes. |
| 4092 |
The first three are reserved. */ |
The first three are reserved. |
| 4093 |
got_offset = (plt_index + 3) * 4; |
|
| 4094 |
|
For static executables, we don't reserve anything. */ |
| 4095 |
|
|
| 4096 |
|
if (plt == htab->elf.splt) |
| 4097 |
|
{ |
| 4098 |
|
plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1; |
| 4099 |
|
got_offset = (plt_index + 3) * 4; |
| 4100 |
|
} |
| 4101 |
|
else |
| 4102 |
|
{ |
| 4103 |
|
plt_index = h->plt.offset / PLT_ENTRY_SIZE; |
| 4104 |
|
got_offset = plt_index * 4; |
| 4105 |
|
} |
| 4106 |
|
|
| 4107 |
/* Fill in the entry in the procedure linkage table. */ |
/* Fill in the entry in the procedure linkage table. */ |
| 4108 |
if (! info->shared) |
if (! info->shared) |
| 4109 |
{ |
{ |
| 4110 |
memcpy (htab->splt->contents + h->plt.offset, elf_i386_plt_entry, |
memcpy (plt->contents + h->plt.offset, elf_i386_plt_entry, |
| 4111 |
PLT_ENTRY_SIZE); |
PLT_ENTRY_SIZE); |
| 4112 |
bfd_put_32 (output_bfd, |
bfd_put_32 (output_bfd, |
| 4113 |
(htab->sgotplt->output_section->vma |
(gotplt->output_section->vma |
| 4114 |
+ htab->sgotplt->output_offset |
+ gotplt->output_offset |
| 4115 |
+ got_offset), |
+ got_offset), |
| 4116 |
htab->splt->contents + h->plt.offset + 2); |
plt->contents + h->plt.offset + 2); |
| 4117 |
|
|
| 4118 |
if (htab->is_vxworks) |
if (htab->is_vxworks) |
| 4119 |
{ |
{ |
| 4135 |
loc = (htab->srelplt2->contents + reloc_index |
loc = (htab->srelplt2->contents + reloc_index |
| 4136 |
* sizeof (Elf32_External_Rel)); |
* sizeof (Elf32_External_Rel)); |
| 4137 |
|
|
| 4138 |
rel.r_offset = (htab->splt->output_section->vma |
rel.r_offset = (htab->elf.splt->output_section->vma |
| 4139 |
+ htab->splt->output_offset |
+ htab->elf.splt->output_offset |
| 4140 |
+ h->plt.offset + 2), |
+ h->plt.offset + 2), |
| 4141 |
rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32); |
rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32); |
| 4142 |
bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); |
bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); |
| 4143 |
|
|
| 4144 |
/* Create the R_386_32 relocation referencing the beginning of |
/* Create the R_386_32 relocation referencing the beginning of |
| 4145 |
the PLT for this GOT entry. */ |
the PLT for this GOT entry. */ |
| 4146 |
rel.r_offset = (htab->sgotplt->output_section->vma |
rel.r_offset = (htab->elf.sgotplt->output_section->vma |
| 4147 |
+ htab->sgotplt->output_offset |
+ htab->elf.sgotplt->output_offset |
| 4148 |
+ got_offset); |
+ got_offset); |
| 4149 |
rel.r_info = ELF32_R_INFO (htab->elf.hplt->indx, R_386_32); |
rel.r_info = ELF32_R_INFO (htab->elf.hplt->indx, R_386_32); |
| 4150 |
bfd_elf32_swap_reloc_out (output_bfd, &rel, |
bfd_elf32_swap_reloc_out (output_bfd, &rel, |
| 4153 |
} |
} |
| 4154 |
else |
else |
| 4155 |
{ |
{ |
| 4156 |
memcpy (htab->splt->contents + h->plt.offset, elf_i386_pic_plt_entry, |
memcpy (plt->contents + h->plt.offset, elf_i386_pic_plt_entry, |
| 4157 |
PLT_ENTRY_SIZE); |
PLT_ENTRY_SIZE); |
| 4158 |
bfd_put_32 (output_bfd, got_offset, |
bfd_put_32 (output_bfd, got_offset, |
| 4159 |
htab->splt->contents + h->plt.offset + 2); |
plt->contents + h->plt.offset + 2); |
| 4160 |
} |
} |
| 4161 |
|
|
| 4162 |
bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rel), |
/* Don't fill PLT entry for static executables. */ |
| 4163 |
htab->splt->contents + h->plt.offset + 7); |
if (plt == htab->elf.splt) |
| 4164 |
bfd_put_32 (output_bfd, - (h->plt.offset + PLT_ENTRY_SIZE), |
{ |
| 4165 |
htab->splt->contents + h->plt.offset + 12); |
bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rel), |
| 4166 |
|
plt->contents + h->plt.offset + 7); |
| 4167 |
|
bfd_put_32 (output_bfd, - (h->plt.offset + PLT_ENTRY_SIZE), |
| 4168 |
|
plt->contents + h->plt.offset + 12); |
| 4169 |
|
} |
| 4170 |
|
|
| 4171 |
/* Fill in the entry in the global offset table. */ |
/* Fill in the entry in the global offset table. */ |
| 4172 |
bfd_put_32 (output_bfd, |
bfd_put_32 (output_bfd, |
| 4173 |
(htab->splt->output_section->vma |
(plt->output_section->vma |
| 4174 |
+ htab->splt->output_offset |
+ plt->output_offset |
| 4175 |
+ h->plt.offset |
+ h->plt.offset |
| 4176 |
+ 6), |
+ 6), |
| 4177 |
htab->sgotplt->contents + got_offset); |
gotplt->contents + got_offset); |
| 4178 |
|
|
| 4179 |
/* Fill in the entry in the .rel.plt section. */ |
/* Fill in the entry in the .rel.plt section. */ |
| 4180 |
rel.r_offset = (htab->sgotplt->output_section->vma |
rel.r_offset = (gotplt->output_section->vma |
| 4181 |
+ htab->sgotplt->output_offset |
+ gotplt->output_offset |
| 4182 |
+ got_offset); |
+ got_offset); |
| 4183 |
rel.r_info = ELF32_R_INFO (h->dynindx, R_386_JUMP_SLOT); |
if (h->dynindx == -1 |
| 4184 |
loc = htab->srelplt->contents + plt_index * sizeof (Elf32_External_Rel); |
|| ((info->executable |
| 4185 |
|
|| ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) |
| 4186 |
|
&& h->def_regular |
| 4187 |
|
&& h->type == STT_GNU_IFUNC)) |
| 4188 |
|
{ |
| 4189 |
|
/* If an STT_GNU_IFUNC symbol is locally defined, generate |
| 4190 |
|
R_386_IRELATIVE instead of R_386_JUMP_SLOT. Store addend |
| 4191 |
|
in the .got.plt section. */ |
| 4192 |
|
bfd_put_32 (output_bfd, |
| 4193 |
|
(h->root.u.def.value |
| 4194 |
|
+ h->root.u.def.section->output_section->vma |
| 4195 |
|
+ h->root.u.def.section->output_offset), |
| 4196 |
|
gotplt->contents + got_offset); |
| 4197 |
|
rel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE); |
| 4198 |
|
} |
| 4199 |
|
else |
| 4200 |
|
rel.r_info = ELF32_R_INFO (h->dynindx, R_386_JUMP_SLOT); |
| 4201 |
|
loc = relplt->contents + plt_index * sizeof (Elf32_External_Rel); |
| 4202 |
bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); |
bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); |
| 4203 |
|
|
| 4204 |
if (!h->def_regular) |
if (!h->def_regular) |
| 4227 |
/* This symbol has an entry in the global offset table. Set it |
/* This symbol has an entry in the global offset table. Set it |
| 4228 |
up. */ |
up. */ |
| 4229 |
|
|
| 4230 |
if (htab->sgot == NULL || htab->srelgot == NULL) |
if (htab->elf.sgot == NULL || htab->elf.srelgot == NULL) |
| 4231 |
abort (); |
abort (); |
| 4232 |
|
|
| 4233 |
rel.r_offset = (htab->sgot->output_section->vma |
rel.r_offset = (htab->elf.sgot->output_section->vma |
| 4234 |
+ htab->sgot->output_offset |
+ htab->elf.sgot->output_offset |
| 4235 |
+ (h->got.offset & ~(bfd_vma) 1)); |
+ (h->got.offset & ~(bfd_vma) 1)); |
| 4236 |
|
|
| 4237 |
/* If this is a static link, or it is a -Bsymbolic link and the |
/* If this is a static link, or it is a -Bsymbolic link and the |
| 4239 |
of a version file, we just want to emit a RELATIVE reloc. |
of a version file, we just want to emit a RELATIVE reloc. |
| 4240 |
The entry in the global offset table will already have been |
The entry in the global offset table will already have been |
| 4241 |
initialized in the relocate_section function. */ |
initialized in the relocate_section function. */ |
| 4242 |
if (info->shared |
if (h->def_regular |
| 4243 |
&& SYMBOL_REFERENCES_LOCAL (info, h)) |
&& h->type == STT_GNU_IFUNC) |
| 4244 |
|
{ |
| 4245 |
|
if (info->shared) |
| 4246 |
|
{ |
| 4247 |
|
/* Generate R_386_GLOB_DAT. */ |
| 4248 |
|
goto do_glob_dat; |
| 4249 |
|
} |
| 4250 |
|
else |
| 4251 |
|
{ |
| 4252 |
|
if (!h->pointer_equality_needed) |
| 4253 |
|
abort (); |
| 4254 |
|
|
| 4255 |
|
/* For non-shared object, we can't use .got.plt, which |
| 4256 |
|
contains the real function addres if we need pointer |
| 4257 |
|
equality. We load the GOT entry with the PLT entry. */ |
| 4258 |
|
asection *plt = htab->elf.splt ? htab->elf.splt : htab->elf.iplt; |
| 4259 |
|
bfd_put_32 (output_bfd, |
| 4260 |
|
(plt->output_section->vma |
| 4261 |
|
+ plt->output_offset + h->plt.offset), |
| 4262 |
|
htab->elf.sgot->contents + h->got.offset); |
| 4263 |
|
return TRUE; |
| 4264 |
|
} |
| 4265 |
|
} |
| 4266 |
|
else if (info->shared |
| 4267 |
|
&& SYMBOL_REFERENCES_LOCAL (info, h)) |
| 4268 |
{ |
{ |
| 4269 |
BFD_ASSERT((h->got.offset & 1) != 0); |
BFD_ASSERT((h->got.offset & 1) != 0); |
| 4270 |
rel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); |
rel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); |
| 4272 |
else |
else |
| 4273 |
{ |
{ |
| 4274 |
BFD_ASSERT((h->got.offset & 1) == 0); |
BFD_ASSERT((h->got.offset & 1) == 0); |
| 4275 |
|
do_glob_dat: |
| 4276 |
bfd_put_32 (output_bfd, (bfd_vma) 0, |
bfd_put_32 (output_bfd, (bfd_vma) 0, |
| 4277 |
htab->sgot->contents + h->got.offset); |
htab->elf.sgot->contents + h->got.offset); |
| 4278 |
rel.r_info = ELF32_R_INFO (h->dynindx, R_386_GLOB_DAT); |
rel.r_info = ELF32_R_INFO (h->dynindx, R_386_GLOB_DAT); |
| 4279 |
} |
} |
| 4280 |
|
|
| 4281 |
loc = htab->srelgot->contents; |
loc = htab->elf.srelgot->contents; |
| 4282 |
loc += htab->srelgot->reloc_count++ * sizeof (Elf32_External_Rel); |
loc += htab->elf.srelgot->reloc_count++ * sizeof (Elf32_External_Rel); |
| 4283 |
bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); |
bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); |
| 4284 |
} |
} |
| 4285 |
|
|
| 4305 |
bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); |
bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); |
| 4306 |
} |
} |
| 4307 |
|
|
| 4308 |
/* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. |
/* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. SYM may |
| 4309 |
|
be NULL for local symbols. |
| 4310 |
|
|
| 4311 |
On VxWorks, the _GLOBAL_OFFSET_TABLE_ symbol is not absolute: it |
On VxWorks, the _GLOBAL_OFFSET_TABLE_ symbol is not absolute: it |
| 4312 |
is relative to the ".got" section. */ |
is relative to the ".got" section. */ |
| 4313 |
if (strcmp (h->root.root.string, "_DYNAMIC") == 0 |
if (sym != NULL |
| 4314 |
|| (!htab->is_vxworks && h == htab->elf.hgot)) |
&& (strcmp (h->root.root.string, "_DYNAMIC") == 0 |
| 4315 |
|
|| (!htab->is_vxworks && h == htab->elf.hgot))) |
| 4316 |
sym->st_shndx = SHN_ABS; |
sym->st_shndx = SHN_ABS; |
| 4317 |
|
|
| 4318 |
return TRUE; |
return TRUE; |
| 4319 |
} |
} |
| 4320 |
|
|
| 4321 |
|
/* Finish up local dynamic symbol handling. We set the contents of |
| 4322 |
|
various dynamic sections here. */ |
| 4323 |
|
|
| 4324 |
|
static bfd_boolean |
| 4325 |
|
elf_i386_finish_local_dynamic_symbol (void **slot, void *inf) |
| 4326 |
|
{ |
| 4327 |
|
struct elf_link_hash_entry *h |
| 4328 |
|
= (struct elf_link_hash_entry *) *slot; |
| 4329 |
|
struct bfd_link_info *info |
| 4330 |
|
= (struct bfd_link_info *) inf; |
| 4331 |
|
|
| 4332 |
|
return elf_i386_finish_dynamic_symbol (info->output_bfd, info, |
| 4333 |
|
h, NULL); |
| 4334 |
|
} |
| 4335 |
|
|
| 4336 |
/* Used to decide how to sort relocs in an optimal manner for the |
/* Used to decide how to sort relocs in an optimal manner for the |
| 4337 |
dynamic linker, before writing them out. */ |
dynamic linker, before writing them out. */ |
| 4338 |
|
|
| 4370 |
{ |
{ |
| 4371 |
Elf32_External_Dyn *dyncon, *dynconend; |
Elf32_External_Dyn *dyncon, *dynconend; |
| 4372 |
|
|
| 4373 |
if (sdyn == NULL || htab->sgot == NULL) |
if (sdyn == NULL || htab->elf.sgot == NULL) |
| 4374 |
abort (); |
abort (); |
| 4375 |
|
|
| 4376 |
dyncon = (Elf32_External_Dyn *) sdyn->contents; |
dyncon = (Elf32_External_Dyn *) sdyn->contents; |
| 4391 |
continue; |
continue; |
| 4392 |
|
|
| 4393 |
case DT_PLTGOT: |
case DT_PLTGOT: |
| 4394 |
s = htab->sgotplt; |
s = htab->elf.sgotplt; |
| 4395 |
dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; |
dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; |
| 4396 |
break; |
break; |
| 4397 |
|
|
| 4398 |
case DT_JMPREL: |
case DT_JMPREL: |
| 4399 |
s = htab->srelplt; |
s = htab->elf.srelplt; |
| 4400 |
dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; |
dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; |
| 4401 |
break; |
break; |
| 4402 |
|
|
| 4403 |
case DT_PLTRELSZ: |
case DT_PLTRELSZ: |
| 4404 |
s = htab->srelplt; |
s = htab->elf.srelplt; |
| 4405 |
dyn.d_un.d_val = s->size; |
dyn.d_un.d_val = s->size; |
| 4406 |
break; |
break; |
| 4407 |
|
|
| 4412 |
what Solaris does. However, UnixWare can not handle |
what Solaris does. However, UnixWare can not handle |
| 4413 |
that case. Therefore, we override the DT_RELSZ entry |
that case. Therefore, we override the DT_RELSZ entry |
| 4414 |
here to make it not include the JMPREL relocs. */ |
here to make it not include the JMPREL relocs. */ |
| 4415 |
s = htab->srelplt; |
s = htab->elf.srelplt; |
| 4416 |
if (s == NULL) |
if (s == NULL) |
| 4417 |
continue; |
continue; |
| 4418 |
dyn.d_un.d_val -= s->size; |
dyn.d_un.d_val -= s->size; |
| 4422 |
/* We may not be using the standard ELF linker script. |
/* We may not be using the standard ELF linker script. |
| 4423 |
If .rel.plt is the first .rel section, we adjust |
If .rel.plt is the first .rel section, we adjust |
| 4424 |
DT_REL to not include it. */ |
DT_REL to not include it. */ |
| 4425 |
s = htab->srelplt; |
s = htab->elf.srelplt; |
| 4426 |
if (s == NULL) |
if (s == NULL) |
| 4427 |
continue; |
continue; |
| 4428 |
if (dyn.d_un.d_ptr != s->output_section->vma + s->output_offset) |
if (dyn.d_un.d_ptr != s->output_section->vma + s->output_offset) |
| 4435 |
} |
} |
| 4436 |
|
|
| 4437 |
/* Fill in the first entry in the procedure linkage table. */ |
/* Fill in the first entry in the procedure linkage table. */ |
| 4438 |
if (htab->splt && htab->splt->size > 0) |
if (htab->elf.splt && htab->elf.splt->size > 0) |
| 4439 |
{ |
{ |
| 4440 |
if (info->shared) |
if (info->shared) |
| 4441 |
{ |
{ |
| 4442 |
memcpy (htab->splt->contents, elf_i386_pic_plt0_entry, |
memcpy (htab->elf.splt->contents, elf_i386_pic_plt0_entry, |
| 4443 |
sizeof (elf_i386_pic_plt0_entry)); |
sizeof (elf_i386_pic_plt0_entry)); |
| 4444 |
memset (htab->splt->contents + sizeof (elf_i386_pic_plt0_entry), |
memset (htab->elf.splt->contents + sizeof (elf_i386_pic_plt0_entry), |
| 4445 |
htab->plt0_pad_byte, |
htab->plt0_pad_byte, |
| 4446 |
PLT_ENTRY_SIZE - sizeof (elf_i386_pic_plt0_entry)); |
PLT_ENTRY_SIZE - sizeof (elf_i386_pic_plt0_entry)); |
| 4447 |
} |
} |
| 4448 |
else |
else |
| 4449 |
{ |
{ |
| 4450 |
memcpy (htab->splt->contents, elf_i386_plt0_entry, |
memcpy (htab->elf.splt->contents, elf_i386_plt0_entry, |
| 4451 |
sizeof(elf_i386_plt0_entry)); |
sizeof(elf_i386_plt0_entry)); |
| 4452 |
memset (htab->splt->contents + sizeof (elf_i386_plt0_entry), |
memset (htab->elf.splt->contents + sizeof (elf_i386_plt0_entry), |
| 4453 |
htab->plt0_pad_byte, |
htab->plt0_pad_byte, |
| 4454 |
PLT_ENTRY_SIZE - sizeof (elf_i386_plt0_entry)); |
PLT_ENTRY_SIZE - sizeof (elf_i386_plt0_entry)); |
| 4455 |
bfd_put_32 (output_bfd, |
bfd_put_32 (output_bfd, |
| 4456 |
(htab->sgotplt->output_section->vma |
(htab->elf.sgotplt->output_section->vma |
| 4457 |
+ htab->sgotplt->output_offset |
+ htab->elf.sgotplt->output_offset |
| 4458 |
+ 4), |
+ 4), |
| 4459 |
htab->splt->contents + 2); |
htab->elf.splt->contents + 2); |
| 4460 |
bfd_put_32 (output_bfd, |
bfd_put_32 (output_bfd, |
| 4461 |
(htab->sgotplt->output_section->vma |
(htab->elf.sgotplt->output_section->vma |
| 4462 |
+ htab->sgotplt->output_offset |
+ htab->elf.sgotplt->output_offset |
| 4463 |
+ 8), |
+ 8), |
| 4464 |
htab->splt->contents + 8); |
htab->elf.splt->contents + 8); |
| 4465 |
|
|
| 4466 |
if (htab->is_vxworks) |
if (htab->is_vxworks) |
| 4467 |
{ |
{ |
| 4470 |
/* Generate a relocation for _GLOBAL_OFFSET_TABLE_ + 4. |
/* Generate a relocation for _GLOBAL_OFFSET_TABLE_ + 4. |
| 4471 |
On IA32 we use REL relocations so the addend goes in |
On IA32 we use REL relocations so the addend goes in |
| 4472 |
the PLT directly. */ |
the PLT directly. */ |
| 4473 |
rel.r_offset = (htab->splt->output_section->vma |
rel.r_offset = (htab->elf.splt->output_section->vma |
| 4474 |
+ htab->splt->output_offset |
+ htab->elf.splt->output_offset |
| 4475 |
+ 2); |
+ 2); |
| 4476 |
rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32); |
rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32); |
| 4477 |
bfd_elf32_swap_reloc_out (output_bfd, &rel, |
bfd_elf32_swap_reloc_out (output_bfd, &rel, |
| 4478 |
htab->srelplt2->contents); |
htab->srelplt2->contents); |
| 4479 |
/* Generate a relocation for _GLOBAL_OFFSET_TABLE_ + 8. */ |
/* Generate a relocation for _GLOBAL_OFFSET_TABLE_ + 8. */ |
| 4480 |
rel.r_offset = (htab->splt->output_section->vma |
rel.r_offset = (htab->elf.splt->output_section->vma |
| 4481 |
+ htab->splt->output_offset |
+ htab->elf.splt->output_offset |
| 4482 |
+ 8); |
+ 8); |
| 4483 |
rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32); |
rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32); |
| 4484 |
bfd_elf32_swap_reloc_out (output_bfd, &rel, |
bfd_elf32_swap_reloc_out (output_bfd, &rel, |
| 4489 |
|
|
| 4490 |
/* UnixWare sets the entsize of .plt to 4, although that doesn't |
/* UnixWare sets the entsize of .plt to 4, although that doesn't |
| 4491 |
really seem like the right value. */ |
really seem like the right value. */ |
| 4492 |
elf_section_data (htab->splt->output_section) |
elf_section_data (htab->elf.splt->output_section) |
| 4493 |
->this_hdr.sh_entsize = 4; |
->this_hdr.sh_entsize = 4; |
| 4494 |
|
|
| 4495 |
/* Correct the .rel.plt.unloaded relocations. */ |
/* Correct the .rel.plt.unloaded relocations. */ |
| 4496 |
if (htab->is_vxworks && !info->shared) |
if (htab->is_vxworks && !info->shared) |
| 4497 |
{ |
{ |
| 4498 |
int num_plts = (htab->splt->size / PLT_ENTRY_SIZE) - 1; |
int num_plts = (htab->elf.splt->size / PLT_ENTRY_SIZE) - 1; |
| 4499 |
unsigned char *p; |
unsigned char *p; |
| 4500 |
|
|
| 4501 |
p = htab->srelplt2->contents; |
p = htab->srelplt2->contents; |
| 4521 |
} |
} |
| 4522 |
} |
} |
| 4523 |
|
|
| 4524 |
if (htab->sgotplt) |
if (htab->elf.sgotplt) |
| 4525 |
{ |
{ |
| 4526 |
/* Fill in the first three entries in the global offset table. */ |
/* Fill in the first three entries in the global offset table. */ |
| 4527 |
if (htab->sgotplt->size > 0) |
if (htab->elf.sgotplt->size > 0) |
| 4528 |
{ |
{ |
| 4529 |
bfd_put_32 (output_bfd, |
bfd_put_32 (output_bfd, |
| 4530 |
(sdyn == NULL ? 0 |
(sdyn == NULL ? 0 |
| 4531 |
: sdyn->output_section->vma + sdyn->output_offset), |
: sdyn->output_section->vma + sdyn->output_offset), |
| 4532 |
htab->sgotplt->contents); |
htab->elf.sgotplt->contents); |
| 4533 |
bfd_put_32 (output_bfd, 0, htab->sgotplt->contents + 4); |
bfd_put_32 (output_bfd, 0, htab->elf.sgotplt->contents + 4); |
| 4534 |
bfd_put_32 (output_bfd, 0, htab->sgotplt->contents + 8); |
bfd_put_32 (output_bfd, 0, htab->elf.sgotplt->contents + 8); |
| 4535 |
} |
} |
| 4536 |
|
|
| 4537 |
elf_section_data (htab->sgotplt->output_section)->this_hdr.sh_entsize = 4; |
elf_section_data (htab->elf.sgotplt->output_section)->this_hdr.sh_entsize = 4; |
| 4538 |
} |
} |
| 4539 |
|
|
| 4540 |
if (htab->sgot && htab->sgot->size > 0) |
if (htab->elf.sgot && htab->elf.sgot->size > 0) |
| 4541 |
elf_section_data (htab->sgot->output_section)->this_hdr.sh_entsize = 4; |
elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 4; |
| 4542 |
|
|
| 4543 |
|
/* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols. */ |
| 4544 |
|
htab_traverse (htab->loc_hash_table, |
| 4545 |
|
elf_i386_finish_local_dynamic_symbol, |
| 4546 |
|
info); |
| 4547 |
|
|
| 4548 |
return TRUE; |
return TRUE; |
| 4549 |
} |
} |
| 4571 |
return _bfd_elf_hash_symbol (h); |
return _bfd_elf_hash_symbol (h); |
| 4572 |
} |
} |
| 4573 |
|
|
| 4574 |
|
/* Hook called by the linker routine which adds symbols from an object |
| 4575 |
|
file. */ |
| 4576 |
|
|
| 4577 |
|
static bfd_boolean |
| 4578 |
|
elf_i386_add_symbol_hook (bfd * abfd ATTRIBUTE_UNUSED, |
| 4579 |
|
struct bfd_link_info * info ATTRIBUTE_UNUSED, |
| 4580 |
|
Elf_Internal_Sym * sym, |
| 4581 |
|
const char ** namep ATTRIBUTE_UNUSED, |
| 4582 |
|
flagword * flagsp ATTRIBUTE_UNUSED, |
| 4583 |
|
asection ** secp ATTRIBUTE_UNUSED, |
| 4584 |
|
bfd_vma * valp ATTRIBUTE_UNUSED) |
| 4585 |
|
{ |
| 4586 |
|
if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC) |
| 4587 |
|
elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE; |
| 4588 |
|
|
| 4589 |
|
return TRUE; |
| 4590 |
|
} |
| 4591 |
|
|
| 4592 |
#define TARGET_LITTLE_SYM bfd_elf32_i386_vec |
#define TARGET_LITTLE_SYM bfd_elf32_i386_vec |
| 4593 |
#define TARGET_LITTLE_NAME "elf32-i386" |
#define TARGET_LITTLE_NAME "elf32-i386" |
| 4594 |
#define ELF_ARCH bfd_arch_i386 |
#define ELF_ARCH bfd_arch_i386 |
| 4610 |
|
|
| 4611 |
#define bfd_elf32_bfd_is_local_label_name elf_i386_is_local_label_name |
#define bfd_elf32_bfd_is_local_label_name elf_i386_is_local_label_name |
| 4612 |
#define bfd_elf32_bfd_link_hash_table_create elf_i386_link_hash_table_create |
#define bfd_elf32_bfd_link_hash_table_create elf_i386_link_hash_table_create |
| 4613 |
|
#define bfd_elf32_bfd_link_hash_table_free elf_i386_link_hash_table_free |
| 4614 |
#define bfd_elf32_bfd_reloc_type_lookup elf_i386_reloc_type_lookup |
#define bfd_elf32_bfd_reloc_type_lookup elf_i386_reloc_type_lookup |
| 4615 |
#define bfd_elf32_bfd_reloc_name_lookup elf_i386_reloc_name_lookup |
#define bfd_elf32_bfd_reloc_name_lookup elf_i386_reloc_name_lookup |
| 4616 |
|
|
| 4634 |
((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true) |
((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true) |
| 4635 |
#define elf_backend_plt_sym_val elf_i386_plt_sym_val |
#define elf_backend_plt_sym_val elf_i386_plt_sym_val |
| 4636 |
#define elf_backend_hash_symbol elf_i386_hash_symbol |
#define elf_backend_hash_symbol elf_i386_hash_symbol |
| 4637 |
|
#define elf_backend_add_symbol_hook elf_i386_add_symbol_hook |
| 4638 |
|
#undef elf_backend_post_process_headers |
| 4639 |
|
#define elf_backend_post_process_headers _bfd_elf_set_osabi |
| 4640 |
|
|
| 4641 |
#include "elf32-target.h" |
#include "elf32-target.h" |
| 4642 |
|
|
| 4654 |
executables and (for simplicity) also all other object files. */ |
executables and (for simplicity) also all other object files. */ |
| 4655 |
|
|
| 4656 |
static void |
static void |
| 4657 |
elf_i386_post_process_headers (bfd *abfd, |
elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info) |
|
struct bfd_link_info *info ATTRIBUTE_UNUSED) |
|
| 4658 |
{ |
{ |
| 4659 |
Elf_Internal_Ehdr *i_ehdrp; |
_bfd_elf_set_osabi (abfd, info); |
|
|
|
|
i_ehdrp = elf_elfheader (abfd); |
|
| 4660 |
|
|
|
/* Put an ABI label supported by FreeBSD >= 4.1. */ |
|
|
i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi; |
|
| 4661 |
#ifdef OLD_FREEBSD_ABI_LABEL |
#ifdef OLD_FREEBSD_ABI_LABEL |
| 4662 |
/* The ABI label supported by FreeBSD <= 4.0 is quite nonstandard. */ |
/* The ABI label supported by FreeBSD <= 4.0 is quite nonstandard. */ |
| 4663 |
memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8); |
memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8); |
| 4665 |
} |
} |
| 4666 |
|
|
| 4667 |
#undef elf_backend_post_process_headers |
#undef elf_backend_post_process_headers |
| 4668 |
#define elf_backend_post_process_headers elf_i386_post_process_headers |
#define elf_backend_post_process_headers elf_i386_fbsd_post_process_headers |
| 4669 |
#undef elf32_bed |
#undef elf32_bed |
| 4670 |
#define elf32_bed elf32_i386_fbsd_bed |
#define elf32_bed elf32_i386_fbsd_bed |
| 4671 |
|
|
| 4672 |
|
#undef elf_backend_add_symbol_hook |
| 4673 |
|
|
| 4674 |
#include "elf32-target.h" |
#include "elf32-target.h" |
| 4675 |
|
|
| 4676 |
/* VxWorks support. */ |
/* VxWorks support. */ |