Index: bfd/elf32-i386.c |
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c |
index 7d3652d81ce983ae3499e279427c61feb6db557a..4574c598bad3c548ccb1327fe9018d9ec19272c0 100644 |
--- a/bfd/elf32-i386.c |
+++ b/bfd/elf32-i386.c |
@@ -1,6 +1,6 @@ |
/* Intel 80386/80486-specific support for 32-bit ELF |
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, |
- 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 |
+ 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 |
Free Software Foundation, Inc. |
This file is part of BFD, the Binary File Descriptor library. |
@@ -133,7 +133,9 @@ static reloc_howto_type elf_howto_table[]= |
HOWTO(R_386_TLS_TPOFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, |
bfd_elf_generic_reloc, "R_386_TLS_TPOFF32", |
TRUE, 0xffffffff, 0xffffffff, FALSE), |
- EMPTY_HOWTO (38), |
+ HOWTO(R_386_SIZE32, 0, 2, 32, FALSE, 0, complain_overflow_unsigned, |
+ bfd_elf_generic_reloc, "R_386_SIZE32", |
+ TRUE, 0xffffffff, 0xffffffff, FALSE), |
HOWTO(R_386_TLS_GOTDESC, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, |
bfd_elf_generic_reloc, "R_386_TLS_GOTDESC", |
TRUE, 0xffffffff, 0xffffffff, FALSE), |
@@ -312,6 +314,10 @@ elf_i386_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, |
TRACE ("BFD_RELOC_386_TLS_TPOFF32"); |
return &elf_howto_table[R_386_TLS_TPOFF32 - R_386_tls_offset]; |
+ case BFD_RELOC_SIZE32: |
+ TRACE ("BFD_RELOC_SIZE32"); |
+ return &elf_howto_table[R_386_SIZE32 - R_386_tls_offset]; |
+ |
case BFD_RELOC_386_TLS_GOTDESC: |
TRACE ("BFD_RELOC_386_TLS_GOTDESC"); |
return &elf_howto_table[R_386_TLS_GOTDESC - R_386_tls_offset]; |
@@ -419,10 +425,10 @@ elf_i386_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) |
return FALSE; |
/* pr_cursig */ |
- elf_tdata (abfd)->core_signal = bfd_get_32 (abfd, note->descdata + 20); |
+ elf_tdata (abfd)->core->signal = bfd_get_32 (abfd, note->descdata + 20); |
/* pr_pid */ |
- elf_tdata (abfd)->core_lwpid = bfd_get_32 (abfd, note->descdata + 24); |
+ elf_tdata (abfd)->core->lwpid = bfd_get_32 (abfd, note->descdata + 24); |
/* pr_reg */ |
offset = 28; |
@@ -437,10 +443,10 @@ elf_i386_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) |
case 144: /* Linux/i386 */ |
/* pr_cursig */ |
- elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12); |
+ elf_tdata (abfd)->core->signal = bfd_get_16 (abfd, note->descdata + 12); |
/* pr_pid */ |
- elf_tdata (abfd)->core_lwpid = bfd_get_32 (abfd, note->descdata + 24); |
+ elf_tdata (abfd)->core->lwpid = bfd_get_32 (abfd, note->descdata + 24); |
/* pr_reg */ |
offset = 72; |
@@ -465,9 +471,9 @@ elf_i386_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) |
if (pr_version != 1) |
return FALSE; |
- elf_tdata (abfd)->core_program |
+ elf_tdata (abfd)->core->program |
= _bfd_elfcore_strndup (abfd, note->descdata + 8, 17); |
- elf_tdata (abfd)->core_command |
+ elf_tdata (abfd)->core->command |
= _bfd_elfcore_strndup (abfd, note->descdata + 25, 81); |
} |
else |
@@ -478,11 +484,11 @@ elf_i386_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) |
return FALSE; |
case 124: /* Linux/i386 elf_prpsinfo. */ |
- elf_tdata (abfd)->core_pid |
+ elf_tdata (abfd)->core->pid |
= bfd_get_32 (abfd, note->descdata + 12); |
- elf_tdata (abfd)->core_program |
+ elf_tdata (abfd)->core->program |
= _bfd_elfcore_strndup (abfd, note->descdata + 28, 16); |
- elf_tdata (abfd)->core_command |
+ elf_tdata (abfd)->core->command |
= _bfd_elfcore_strndup (abfd, note->descdata + 44, 80); |
} |
} |
@@ -491,7 +497,7 @@ elf_i386_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) |
onto the end of the args in some (at least one anyway) |
implementations, so strip it off if it exists. */ |
{ |
- char *command = elf_tdata (abfd)->core_command; |
+ char *command = elf_tdata (abfd)->core->command; |
int n = strlen (command); |
if (0 < n && command[n - 1] == ' ') |
@@ -931,7 +937,7 @@ elf_i386_link_hash_table_create (bfd *abfd) |
struct elf_i386_link_hash_table *ret; |
bfd_size_type amt = sizeof (struct elf_i386_link_hash_table); |
- ret = (struct elf_i386_link_hash_table *) bfd_malloc (amt); |
+ ret = (struct elf_i386_link_hash_table *) bfd_zmalloc (amt); |
if (ret == NULL) |
return NULL; |
@@ -944,18 +950,6 @@ elf_i386_link_hash_table_create (bfd *abfd) |
return NULL; |
} |
- ret->sdynbss = NULL; |
- ret->srelbss = NULL; |
- ret->plt_eh_frame = NULL; |
- ret->tls_ldm_got.refcount = 0; |
- ret->next_tls_desc_index = 0; |
- ret->sgotplt_jump_table_size = 0; |
- ret->sym_cache.abfd = NULL; |
- ret->srelplt2 = NULL; |
- ret->tls_module_base = NULL; |
- ret->next_jump_slot_index = 0; |
- ret->next_irelative_index = 0; |
- |
ret->loc_hash_table = htab_try_create (1024, |
elf_i386_local_htab_hash, |
elf_i386_local_htab_eq, |
@@ -982,7 +976,7 @@ elf_i386_link_hash_table_free (struct bfd_link_hash_table *hash) |
htab_delete (htab->loc_hash_table); |
if (htab->loc_hash_memory) |
objalloc_free ((struct objalloc *) htab->loc_hash_memory); |
- _bfd_generic_link_hash_table_free (hash); |
+ _bfd_elf_link_hash_table_free (hash); |
} |
/* Create .plt, .rel.plt, .got, .got.plt, .rel.got, .dynbss, and |
@@ -1448,6 +1442,7 @@ elf_i386_check_relocs (bfd *abfd, |
struct elf_link_hash_entry *h; |
Elf_Internal_Sym *isym; |
const char *name; |
+ bfd_boolean size_reloc; |
r_symndx = ELF32_R_SYM (rel->r_info); |
r_type = ELF32_R_TYPE (rel->r_info); |
@@ -1517,73 +1512,9 @@ elf_i386_check_relocs (bfd *abfd, |
break; |
} |
- /* Since STT_GNU_IFUNC symbol must go through PLT, we handle |
- it here if it is defined in a non-shared object. */ |
- if (h->type == STT_GNU_IFUNC |
- && h->def_regular) |
- { |
- /* It is referenced by a non-shared object. */ |
- h->ref_regular = 1; |
- h->needs_plt = 1; |
- |
- /* STT_GNU_IFUNC symbol must go through PLT. */ |
- h->plt.refcount += 1; |
- |
- /* STT_GNU_IFUNC needs dynamic sections. */ |
- if (htab->elf.dynobj == NULL) |
- htab->elf.dynobj = abfd; |
- |
- switch (r_type) |
- { |
- default: |
- if (h->root.root.string) |
- name = h->root.root.string; |
- else |
- name = bfd_elf_sym_name (abfd, symtab_hdr, isym, |
- NULL); |
- (*_bfd_error_handler) |
- (_("%B: relocation %s against STT_GNU_IFUNC " |
- "symbol `%s' isn't handled by %s"), abfd, |
- elf_howto_table[r_type].name, |
- name, __FUNCTION__); |
- bfd_set_error (bfd_error_bad_value); |
- return FALSE; |
- |
- case R_386_32: |
- h->non_got_ref = 1; |
- h->pointer_equality_needed = 1; |
- if (info->shared) |
- { |
- /* We must copy these reloc types into the |
- output file. Create a reloc section in |
- dynobj and make room for this reloc. */ |
- sreloc = _bfd_elf_create_ifunc_dyn_reloc |
- (abfd, info, sec, sreloc, |
- &((struct elf_i386_link_hash_entry *) h)->dyn_relocs); |
- if (sreloc == NULL) |
- return FALSE; |
- } |
- break; |
- |
- case R_386_PC32: |
- h->non_got_ref = 1; |
- break; |
- |
- case R_386_PLT32: |
- break; |
- |
- case R_386_GOT32: |
- case R_386_GOTOFF: |
- h->got.refcount += 1; |
- if (htab->elf.sgot == NULL |
- && !_bfd_elf_create_got_section (htab->elf.dynobj, |
- info)) |
- return FALSE; |
- break; |
- } |
- |
- continue; |
- } |
+ /* It is referenced by a non-shared object. */ |
+ h->ref_regular = 1; |
+ h->root.non_ir_ref = 1; |
} |
if (! elf_i386_tls_transition (info, abfd, sec, NULL, |
@@ -1615,6 +1546,10 @@ elf_i386_check_relocs (bfd *abfd, |
h->plt.refcount += 1; |
break; |
+ case R_386_SIZE32: |
+ size_reloc = TRUE; |
+ goto do_size; |
+ |
case R_386_TLS_IE_32: |
case R_386_TLS_IE: |
case R_386_TLS_GOTIE: |
@@ -1707,6 +1642,7 @@ elf_i386_check_relocs (bfd *abfd, |
(_("%B: `%s' accessed both as normal and " |
"thread local symbol"), |
abfd, name); |
+ bfd_set_error (bfd_error_bad_value); |
return FALSE; |
} |
} |
@@ -1761,6 +1697,8 @@ elf_i386_check_relocs (bfd *abfd, |
h->pointer_equality_needed = 1; |
} |
+ size_reloc = FALSE; |
+do_size: |
/* If we are creating a shared library, and this is a reloc |
against a global symbol, or a non PC relative reloc |
against a local symbol, then we need to copy the reloc |
@@ -1857,7 +1795,8 @@ elf_i386_check_relocs (bfd *abfd, |
} |
p->count += 1; |
- if (r_type == R_386_PC32) |
+ /* Count size relocation as PC-relative relocation. */ |
+ if (r_type == R_386_PC32 || size_reloc) |
p->pc_count += 1; |
} |
break; |
@@ -2023,6 +1962,7 @@ elf_i386_gc_sweep_hook (bfd *abfd, |
case R_386_32: |
case R_386_PC32: |
+ case R_386_SIZE32: |
if (info->shared |
&& (h == NULL || h->type != STT_GNU_IFUNC)) |
break; |
@@ -2066,10 +2006,44 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info, |
{ |
struct elf_i386_link_hash_table *htab; |
asection *s; |
+ struct elf_i386_link_hash_entry *eh; |
+ struct elf_dyn_relocs *p; |
/* STT_GNU_IFUNC symbol must go through PLT. */ |
if (h->type == STT_GNU_IFUNC) |
{ |
+ /* All local STT_GNU_IFUNC references must be treate as local |
+ calls via local PLT. */ |
+ if (h->ref_regular |
+ && SYMBOL_CALLS_LOCAL (info, h)) |
+ { |
+ bfd_size_type pc_count = 0, count = 0; |
+ struct elf_dyn_relocs **pp; |
+ |
+ eh = (struct elf_i386_link_hash_entry *) h; |
+ for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) |
+ { |
+ pc_count += p->pc_count; |
+ p->count -= p->pc_count; |
+ p->pc_count = 0; |
+ count += p->count; |
+ if (p->count == 0) |
+ *pp = p->next; |
+ else |
+ pp = &p->next; |
+ } |
+ |
+ if (pc_count || count) |
+ { |
+ h->needs_plt = 1; |
+ h->non_got_ref = 1; |
+ if (h->plt.refcount <= 0) |
+ h->plt.refcount = 1; |
+ else |
+ h->plt.refcount += 1; |
+ } |
+ } |
+ |
if (h->plt.refcount <= 0) |
{ |
h->plt.offset = (bfd_vma) -1; |
@@ -2155,9 +2129,6 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info, |
if (ELIMINATE_COPY_RELOCS |
&& !get_elf_i386_backend_data (info->output_bfd)->is_vxworks) |
{ |
- struct elf_i386_link_hash_entry * eh; |
- struct elf_dyn_relocs *p; |
- |
eh = (struct elf_i386_link_hash_entry *) h; |
for (p = eh->dyn_relocs; p != NULL; p = p->next) |
{ |
@@ -2226,7 +2197,8 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) |
if (h->type == STT_GNU_IFUNC |
&& h->def_regular) |
return _bfd_elf_allocate_ifunc_dyn_relocs (info, h, &eh->dyn_relocs, |
- plt_entry_size, 4); |
+ plt_entry_size, |
+ plt_entry_size, 4); |
else if (htab->elf.dynamic_sections_created |
&& h->plt.refcount > 0) |
{ |
@@ -2247,7 +2219,7 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) |
/* If this is the first .plt entry, make room for the special |
first entry. */ |
if (s->size == 0) |
- s->size += plt_entry_size; |
+ s->size = plt_entry_size; |
h->plt.offset = s->size; |
@@ -2536,6 +2508,153 @@ elf_i386_readonly_dynrelocs (struct elf_link_hash_entry *h, void *inf) |
return TRUE; |
} |
+/* Convert |
+ mov foo@GOT(%reg), %reg |
+ to |
+ lea foo@GOTOFF(%reg), %reg |
+ with the local symbol, foo. */ |
+ |
+static bfd_boolean |
+elf_i386_convert_mov_to_lea (bfd *abfd, asection *sec, |
+ struct bfd_link_info *link_info) |
+{ |
+ Elf_Internal_Shdr *symtab_hdr; |
+ Elf_Internal_Rela *internal_relocs; |
+ Elf_Internal_Rela *irel, *irelend; |
+ bfd_byte *contents; |
+ struct elf_i386_link_hash_table *htab; |
+ bfd_boolean changed_contents; |
+ bfd_boolean changed_relocs; |
+ bfd_signed_vma *local_got_refcounts; |
+ |
+ /* Don't even try to convert non-ELF outputs. */ |
+ if (!is_elf_hash_table (link_info->hash)) |
+ return FALSE; |
+ |
+ /* Nothing to do if there are no codes, no relocations or no output. */ |
+ if ((sec->flags & (SEC_CODE | SEC_RELOC)) != (SEC_CODE | SEC_RELOC) |
+ || sec->reloc_count == 0 |
+ || discarded_section (sec)) |
+ return TRUE; |
+ |
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
+ |
+ /* Load the relocations for this section. */ |
+ internal_relocs = (_bfd_elf_link_read_relocs |
+ (abfd, sec, NULL, (Elf_Internal_Rela *) NULL, |
+ link_info->keep_memory)); |
+ if (internal_relocs == NULL) |
+ return FALSE; |
+ |
+ htab = elf_i386_hash_table (link_info); |
+ changed_contents = FALSE; |
+ changed_relocs = FALSE; |
+ local_got_refcounts = elf_local_got_refcounts (abfd); |
+ |
+ /* Get the section contents. */ |
+ if (elf_section_data (sec)->this_hdr.contents != NULL) |
+ contents = elf_section_data (sec)->this_hdr.contents; |
+ else |
+ { |
+ if (!bfd_malloc_and_get_section (abfd, sec, &contents)) |
+ goto error_return; |
+ } |
+ |
+ irelend = internal_relocs + sec->reloc_count; |
+ for (irel = internal_relocs; irel < irelend; irel++) |
+ { |
+ unsigned int r_type = ELF32_R_TYPE (irel->r_info); |
+ unsigned int r_symndx = ELF32_R_SYM (irel->r_info); |
+ unsigned int indx; |
+ struct elf_link_hash_entry *h; |
+ |
+ if (r_type != R_386_GOT32) |
+ continue; |
+ |
+ /* Get the symbol referred to by the reloc. */ |
+ if (r_symndx < symtab_hdr->sh_info) |
+ { |
+ Elf_Internal_Sym *isym; |
+ |
+ isym = bfd_sym_from_r_symndx (&htab->sym_cache, |
+ abfd, r_symndx); |
+ |
+ /* STT_GNU_IFUNC must keep R_386_GOT32 relocation. */ |
+ if (ELF_ST_TYPE (isym->st_info) != STT_GNU_IFUNC |
+ && bfd_get_8 (input_bfd, |
+ contents + irel->r_offset - 2) == 0x8b) |
+ { |
+ bfd_put_8 (output_bfd, 0x8d, |
+ contents + irel->r_offset - 2); |
+ irel->r_info = ELF32_R_INFO (r_symndx, R_386_GOTOFF); |
+ if (local_got_refcounts != NULL |
+ && local_got_refcounts[r_symndx] > 0) |
+ local_got_refcounts[r_symndx] -= 1; |
+ changed_contents = TRUE; |
+ changed_relocs = TRUE; |
+ } |
+ continue; |
+ } |
+ |
+ indx = r_symndx - symtab_hdr->sh_info; |
+ h = elf_sym_hashes (abfd)[indx]; |
+ BFD_ASSERT (h != NULL); |
+ |
+ while (h->root.type == bfd_link_hash_indirect |
+ || h->root.type == bfd_link_hash_warning) |
+ h = (struct elf_link_hash_entry *) h->root.u.i.link; |
+ |
+ /* STT_GNU_IFUNC must keep R_386_GOT32 relocation. We also avoid |
+ optimizing _DYNAMIC since ld.so may use its link-time address. */ |
+ if (h->def_regular |
+ && h->type != STT_GNU_IFUNC |
+ && h != htab->elf.hdynamic |
+ && SYMBOL_REFERENCES_LOCAL (link_info, h) |
+ && bfd_get_8 (input_bfd, |
+ contents + irel->r_offset - 2) == 0x8b) |
+ { |
+ bfd_put_8 (output_bfd, 0x8d, |
+ contents + irel->r_offset - 2); |
+ irel->r_info = ELF32_R_INFO (r_symndx, R_386_GOTOFF); |
+ if (h->got.refcount > 0) |
+ h->got.refcount -= 1; |
+ changed_contents = TRUE; |
+ changed_relocs = TRUE; |
+ } |
+ } |
+ |
+ if (contents != NULL |
+ && elf_section_data (sec)->this_hdr.contents != contents) |
+ { |
+ if (!changed_contents && !link_info->keep_memory) |
+ free (contents); |
+ else |
+ { |
+ /* Cache the section contents for elf_link_input_bfd. */ |
+ elf_section_data (sec)->this_hdr.contents = contents; |
+ } |
+ } |
+ |
+ if (elf_section_data (sec)->relocs != internal_relocs) |
+ { |
+ if (!changed_relocs) |
+ free (internal_relocs); |
+ else |
+ elf_section_data (sec)->relocs = internal_relocs; |
+ } |
+ |
+ return TRUE; |
+ |
+ error_return: |
+ if (contents != NULL |
+ && elf_section_data (sec)->this_hdr.contents != contents) |
+ free (contents); |
+ if (internal_relocs != NULL |
+ && elf_section_data (sec)->relocs != internal_relocs) |
+ free (internal_relocs); |
+ return FALSE; |
+} |
+ |
/* Set the sizes of the dynamic sections. */ |
static bfd_boolean |
@@ -2586,6 +2705,9 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) |
{ |
struct elf_dyn_relocs *p; |
+ if (!elf_i386_convert_mov_to_lea (ibfd, s, info)) |
+ return FALSE; |
+ |
for (p = ((struct elf_dyn_relocs *) |
elf_section_data (s)->local_dynrel); |
p != NULL; |
@@ -2713,15 +2835,10 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) |
if (htab->elf.sgotplt) |
{ |
- struct elf_link_hash_entry *got; |
- got = elf_link_hash_lookup (elf_hash_table (info), |
- "_GLOBAL_OFFSET_TABLE_", |
- FALSE, FALSE, FALSE); |
- |
/* Don't allocate .got.plt section if there are no GOT nor PLT |
entries and there is no reference to _GLOBAL_OFFSET_TABLE_. */ |
- if ((got == NULL |
- || !got->ref_regular_nonweak) |
+ if ((htab->elf.hgot == NULL |
+ || !htab->elf.hgot->ref_regular_nonweak) |
&& (htab->elf.sgotplt->size |
== get_elf_backend_data (output_bfd)->got_header_size) |
&& (htab->elf.splt == NULL |
@@ -3073,6 +3190,7 @@ elf_i386_relocate_section (bfd *output_bfd, |
bfd_reloc_status_type r; |
unsigned int indx; |
int tls_type; |
+ bfd_vma st_size; |
r_type = ELF32_R_TYPE (rel->r_info); |
if (r_type == R_386_GNU_VTINHERIT |
@@ -3105,6 +3223,7 @@ elf_i386_relocate_section (bfd *output_bfd, |
relocation = (sec->output_section->vma |
+ sec->output_offset |
+ sym->st_value); |
+ st_size = sym->st_size; |
if (ELF_ST_TYPE (sym->st_info) == STT_SECTION |
&& ((sec->flags & SEC_MERGE) != 0 |
@@ -3192,11 +3311,13 @@ elf_i386_relocate_section (bfd *output_bfd, |
else |
{ |
bfd_boolean warned ATTRIBUTE_UNUSED; |
+ bfd_boolean ignored ATTRIBUTE_UNUSED; |
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, |
r_symndx, symtab_hdr, sym_hashes, |
h, sec, relocation, |
- unresolved_reloc, warned); |
+ unresolved_reloc, warned, ignored); |
+ st_size = h->size; |
} |
if (sec != NULL && discarded_section (sec)) |
@@ -3257,7 +3378,6 @@ elf_i386_relocate_section (bfd *output_bfd, |
if (info->shared && h->non_got_ref) |
{ |
Elf_Internal_Rela outrel; |
- bfd_byte *loc; |
asection *sreloc; |
bfd_vma offset; |
@@ -3291,10 +3411,7 @@ elf_i386_relocate_section (bfd *output_bfd, |
outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); |
sreloc = htab->elf.irelifunc; |
- loc = sreloc->contents; |
- loc += (sreloc->reloc_count++ |
- * sizeof (Elf32_External_Rel)); |
- bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); |
+ elf_append_rel (output_bfd, sreloc, &outrel); |
/* If this reloc is against an external symbol, we |
do not want to fiddle with the addend. Otherwise, |
@@ -3448,7 +3565,6 @@ elf_i386_relocate_section (bfd *output_bfd, |
{ |
asection *s; |
Elf_Internal_Rela outrel; |
- bfd_byte *loc; |
s = htab->elf.srelgot; |
if (s == NULL) |
@@ -3458,9 +3574,7 @@ elf_i386_relocate_section (bfd *output_bfd, |
+ htab->elf.sgot->output_offset |
+ off); |
outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); |
- loc = s->contents; |
- loc += s->reloc_count++ * sizeof (Elf32_External_Rel); |
- bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); |
+ elf_append_rel (output_bfd, s, &outrel); |
} |
local_got_offsets[r_symndx] |= 1; |
@@ -3565,6 +3679,11 @@ elf_i386_relocate_section (bfd *output_bfd, |
unresolved_reloc = FALSE; |
break; |
+ case R_386_SIZE32: |
+ /* Set to symbol size. */ |
+ relocation = st_size; |
+ /* Fall through. */ |
+ |
case R_386_32: |
case R_386_PC32: |
if ((input_section->flags & SEC_ALLOC) == 0 |
@@ -3575,7 +3694,7 @@ elf_i386_relocate_section (bfd *output_bfd, |
&& (h == NULL |
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT |
|| h->root.type != bfd_link_hash_undefweak) |
- && (r_type != R_386_PC32 |
+ && ((r_type != R_386_PC32 && r_type != R_386_SIZE32) |
|| !SYMBOL_CALLS_LOCAL (info, h))) |
|| (ELIMINATE_COPY_RELOCS |
&& !info->shared |
@@ -3588,7 +3707,6 @@ elf_i386_relocate_section (bfd *output_bfd, |
|| h->root.type == bfd_link_hash_undefined))) |
{ |
Elf_Internal_Rela outrel; |
- bfd_byte *loc; |
bfd_boolean skip, relocate; |
asection *sreloc; |
@@ -3633,10 +3751,7 @@ elf_i386_relocate_section (bfd *output_bfd, |
goto check_relocation_error; |
} |
- loc = sreloc->contents; |
- loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel); |
- |
- bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); |
+ elf_append_rel (output_bfd, sreloc, &outrel); |
/* If this reloc is against an external symbol, we do |
not want to fiddle with the addend. Otherwise, we |
@@ -3651,7 +3766,6 @@ elf_i386_relocate_section (bfd *output_bfd, |
if (!info->executable) |
{ |
Elf_Internal_Rela outrel; |
- bfd_byte *loc; |
asection *sreloc; |
outrel.r_offset = rel->r_offset |
@@ -3661,9 +3775,7 @@ elf_i386_relocate_section (bfd *output_bfd, |
sreloc = elf_section_data (input_section)->sreloc; |
if (sreloc == NULL) |
abort (); |
- loc = sreloc->contents; |
- loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel); |
- bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); |
+ elf_append_rel (output_bfd, sreloc, &outrel); |
} |
/* Fall through */ |
@@ -3889,7 +4001,6 @@ elf_i386_relocate_section (bfd *output_bfd, |
else |
{ |
Elf_Internal_Rela outrel; |
- bfd_byte *loc; |
int dr_type; |
asection *sreloc; |
@@ -3900,6 +4011,7 @@ elf_i386_relocate_section (bfd *output_bfd, |
if (GOT_TLS_GDESC_P (tls_type)) |
{ |
+ bfd_byte *loc; |
outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_DESC); |
BFD_ASSERT (htab->sgotplt_jump_table_size + offplt + 8 |
<= htab->elf.sgotplt->size); |
@@ -3957,11 +4069,7 @@ elf_i386_relocate_section (bfd *output_bfd, |
htab->elf.sgot->contents + off); |
outrel.r_info = ELF32_R_INFO (indx, dr_type); |
- loc = sreloc->contents; |
- loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel); |
- BFD_ASSERT (loc + sizeof (Elf32_External_Rel) |
- <= sreloc->contents + sreloc->size); |
- bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); |
+ elf_append_rel (output_bfd, sreloc, &outrel); |
if (GOT_TLS_GD_P (tls_type)) |
{ |
@@ -3979,11 +4087,7 @@ elf_i386_relocate_section (bfd *output_bfd, |
outrel.r_info = ELF32_R_INFO (indx, |
R_386_TLS_DTPOFF32); |
outrel.r_offset += 4; |
- sreloc->reloc_count++; |
- loc += sizeof (Elf32_External_Rel); |
- BFD_ASSERT (loc + sizeof (Elf32_External_Rel) |
- <= sreloc->contents + sreloc->size); |
- bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); |
+ elf_append_rel (output_bfd, sreloc, &outrel); |
} |
} |
else if (tls_type == GOT_TLS_IE_BOTH) |
@@ -3995,9 +4099,7 @@ elf_i386_relocate_section (bfd *output_bfd, |
htab->elf.sgot->contents + off + 4); |
outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_TPOFF); |
outrel.r_offset += 4; |
- sreloc->reloc_count++; |
- loc += sizeof (Elf32_External_Rel); |
- bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); |
+ elf_append_rel (output_bfd, sreloc, &outrel); |
} |
dr_done: |
@@ -4179,7 +4281,6 @@ elf_i386_relocate_section (bfd *output_bfd, |
else |
{ |
Elf_Internal_Rela outrel; |
- bfd_byte *loc; |
if (htab->elf.srelgot == NULL) |
abort (); |
@@ -4192,9 +4293,7 @@ elf_i386_relocate_section (bfd *output_bfd, |
bfd_put_32 (output_bfd, 0, |
htab->elf.sgot->contents + off + 4); |
outrel.r_info = ELF32_R_INFO (0, R_386_TLS_DTPMOD32); |
- loc = htab->elf.srelgot->contents; |
- loc += htab->elf.srelgot->reloc_count++ * sizeof (Elf32_External_Rel); |
- bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); |
+ elf_append_rel (output_bfd, htab->elf.srelgot, &outrel); |
htab->tls_ldm_got.offset |= 1; |
} |
relocation = htab->elf.sgot->output_section->vma |
@@ -4218,7 +4317,6 @@ elf_i386_relocate_section (bfd *output_bfd, |
{ |
Elf_Internal_Rela outrel; |
asection *sreloc; |
- bfd_byte *loc; |
outrel.r_offset = rel->r_offset |
+ input_section->output_section->vma |
@@ -4234,9 +4332,7 @@ elf_i386_relocate_section (bfd *output_bfd, |
sreloc = elf_section_data (input_section)->sreloc; |
if (sreloc == NULL) |
abort (); |
- loc = sreloc->contents; |
- loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel); |
- bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); |
+ elf_append_rel (output_bfd, sreloc, &outrel); |
if (indx) |
continue; |
else if (r_type == R_386_TLS_LE_32) |
@@ -4371,7 +4467,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, |
|| plt == NULL |
|| gotplt == NULL |
|| relplt == NULL) |
- return FALSE; |
+ abort (); |
/* Get the index in the procedure linkage table which |
corresponds to this symbol. This is the index of this symbol |
@@ -4441,7 +4537,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, |
+ got_offset); |
rel.r_info = ELF32_R_INFO (htab->elf.hplt->indx, R_386_32); |
bfd_elf32_swap_reloc_out (output_bfd, &rel, |
- loc + sizeof (Elf32_External_Rel)); |
+ loc + sizeof (Elf32_External_Rel)); |
} |
} |
else |
@@ -4524,7 +4620,6 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, |
&& (elf_i386_hash_entry(h)->tls_type & GOT_TLS_IE) == 0) |
{ |
Elf_Internal_Rela rel; |
- bfd_byte *loc; |
/* This symbol has an entry in the global offset table. Set it |
up. */ |
@@ -4582,15 +4677,12 @@ do_glob_dat: |
rel.r_info = ELF32_R_INFO (h->dynindx, R_386_GLOB_DAT); |
} |
- loc = htab->elf.srelgot->contents; |
- loc += htab->elf.srelgot->reloc_count++ * sizeof (Elf32_External_Rel); |
- bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); |
+ elf_append_rel (output_bfd, htab->elf.srelgot, &rel); |
} |
if (h->needs_copy) |
{ |
Elf_Internal_Rela rel; |
- bfd_byte *loc; |
/* This symbol needs a copy reloc. Set it up. */ |
@@ -4604,9 +4696,7 @@ do_glob_dat: |
+ h->root.u.def.section->output_section->vma |
+ h->root.u.def.section->output_offset); |
rel.r_info = ELF32_R_INFO (h->dynindx, R_386_COPY); |
- loc = htab->srelbss->contents; |
- loc += htab->srelbss->reloc_count++ * sizeof (Elf32_External_Rel); |
- bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); |
+ elf_append_rel (output_bfd, htab->srelbss, &rel); |
} |
return TRUE; |
@@ -4631,7 +4721,9 @@ elf_i386_finish_local_dynamic_symbol (void **slot, void *inf) |
dynamic linker, before writing them out. */ |
static enum elf_reloc_type_class |
-elf_i386_reloc_type_class (const Elf_Internal_Rela *rela) |
+elf_i386_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED, |
+ const asection *rel_sec ATTRIBUTE_UNUSED, |
+ const Elf_Internal_Rela *rela) |
{ |
switch (ELF32_R_TYPE (rela->r_info)) |
{ |
@@ -5204,19 +5296,33 @@ static const struct elf_i386_backend_data elf_i386_nacl_arch_bed = |
0, /* is_vxworks */ |
}; |
+static bfd_boolean |
+elf32_i386_nacl_elf_object_p (bfd *abfd) |
+{ |
+ /* Set the right machine number for a NaCl i386 ELF32 file. */ |
+ bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_i386_i386_nacl); |
+ return TRUE; |
+} |
+ |
#undef elf_backend_arch_data |
#define elf_backend_arch_data &elf_i386_nacl_arch_bed |
+#undef elf_backend_object_p |
+#define elf_backend_object_p elf32_i386_nacl_elf_object_p |
#undef elf_backend_modify_segment_map |
#define elf_backend_modify_segment_map nacl_modify_segment_map |
#undef elf_backend_modify_program_headers |
#define elf_backend_modify_program_headers nacl_modify_program_headers |
+#undef elf_backend_final_write_processing |
+#define elf_backend_final_write_processing nacl_final_write_processing |
#include "elf32-target.h" |
/* Restore defaults. */ |
+#undef elf_backend_object_p |
#undef elf_backend_modify_segment_map |
#undef elf_backend_modify_program_headers |
+#undef elf_backend_final_write_processing |
/* VxWorks support. */ |