/* 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.
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),
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];
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;
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;
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
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);
}
}
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] == ' ')
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;
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,
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
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);
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,
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:
(_("%B: `%s' accessed both as normal and "
"thread local symbol"),
abfd, name);
+ bfd_set_error (bfd_error_bad_value);
return FALSE;
}
}
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
}
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;
case R_386_32:
case R_386_PC32:
+ case R_386_SIZE32:
if (info->shared
&& (h == NULL || h->type != STT_GNU_IFUNC))
break;
if (pc_count || count)
{
h->needs_plt = 1;
- h->plt.refcount += 1;
h->non_got_ref = 1;
+ if (h->plt.refcount <= 0)
+ h->plt.refcount = 1;
+ else
+ h->plt.refcount += 1;
}
}
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)
{
/* 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;
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
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
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))
if (info->shared && h->non_got_ref)
{
Elf_Internal_Rela outrel;
- bfd_byte *loc;
asection *sreloc;
bfd_vma offset;
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,
{
asection *s;
Elf_Internal_Rela outrel;
- bfd_byte *loc;
s = htab->elf.srelgot;
if (s == NULL)
+ 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;
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
&& (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
|| h->root.type == bfd_link_hash_undefined)))
{
Elf_Internal_Rela outrel;
- bfd_byte *loc;
bfd_boolean skip, relocate;
asection *sreloc;
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
if (!info->executable)
{
Elf_Internal_Rela outrel;
- bfd_byte *loc;
asection *sreloc;
outrel.r_offset = rel->r_offset
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 */
else
{
Elf_Internal_Rela outrel;
- bfd_byte *loc;
int dr_type;
asection *sreloc;
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);
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))
{
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)
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:
else
{
Elf_Internal_Rela outrel;
- bfd_byte *loc;
if (htab->elf.srelgot == NULL)
abort ();
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
{
Elf_Internal_Rela outrel;
asection *sreloc;
- bfd_byte *loc;
outrel.r_offset = rel->r_offset
+ input_section->output_section->vma
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)
+ 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
&& (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. */
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. */
+ 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;
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))
{
#define elf_backend_plt_sym_val elf_i386_plt_sym_val
#define elf_backend_hash_symbol elf_i386_hash_symbol
#define elf_backend_add_symbol_hook elf_i386_add_symbol_hook
-#undef elf_backend_post_process_headers
-#define elf_backend_post_process_headers _bfd_elf_set_osabi
#include "elf32-target.h"
static void
elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info)
{
- _bfd_elf_set_osabi (abfd, info);
+ _bfd_elf_post_process_headers (abfd, info);
#ifdef OLD_FREEBSD_ABI_LABEL
/* The ABI label supported by FreeBSD <= 4.0 is quite nonstandard. */
#undef elf_backend_want_plt_sym
#define elf_backend_want_plt_sym 0
#undef elf_backend_post_process_headers
-#define elf_backend_post_process_headers _bfd_elf_set_osabi
#undef elf_backend_static_tls_alignment
/* NaCl uses substantially different PLT entries for the same effects. */
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. */
#define elf_backend_arch_data &elf_i386_vxworks_arch_bed
#undef elf_backend_relocs_compatible
-#undef elf_backend_post_process_headers
#undef elf_backend_add_symbol_hook
#define elf_backend_add_symbol_hook \
elf_vxworks_add_symbol_hook