/* Intel 80386/80486-specific support for 32-bit ELF
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
- 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+ 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "bfdlink.h"
#include "libbfd.h"
#include "elf-bfd.h"
return 0;
}
+static reloc_howto_type *
+elf_i386_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ const char *r_name)
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof (elf_howto_table) / sizeof (elf_howto_table[0]); i++)
+ if (elf_howto_table[i].name != NULL
+ && strcasecmp (elf_howto_table[i].name, r_name) == 0)
+ return &elf_howto_table[i];
+
+ return NULL;
+}
+
static void
elf_i386_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
arelent *cache_ptr,
&& (sec->flags & SEC_ALLOC) != 0
&& (r_type != R_386_PC32
|| (h != NULL
- && (! info->symbolic
+ && (! SYMBOLIC_BIND (info, h)
|| h->root.type == bfd_link_hash_defweak
|| !h->def_regular))))
|| (ELIMINATE_COPY_RELOCS
if (name == NULL)
return FALSE;
- if (strncmp (name, ".rel", 4) != 0
+ if (! CONST_STRNEQ (name, ".rel")
|| strcmp (bfd_get_section_name (abfd, sec),
name + 4) != 0)
{
static asection *
elf_i386_gc_mark_hook (asection *sec,
- struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info,
Elf_Internal_Rela *rel,
struct elf_link_hash_entry *h,
Elf_Internal_Sym *sym)
{
if (h != NULL)
- {
- switch (ELF32_R_TYPE (rel->r_info))
- {
- case R_386_GNU_VTINHERIT:
- case R_386_GNU_VTENTRY:
- break;
-
- default:
- switch (h->root.type)
- {
- case bfd_link_hash_defined:
- case bfd_link_hash_defweak:
- return h->root.u.def.section;
-
- case bfd_link_hash_common:
- return h->root.u.c.p->section;
-
- default:
- break;
- }
- }
- }
- else
- return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
-
- return NULL;
+ switch (ELF32_R_TYPE (rel->r_info))
+ {
+ case R_386_GNU_VTINHERIT:
+ case R_386_GNU_VTENTRY:
+ return NULL;
+ }
+
+ return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
}
/* Update the got entry reference counts for the section being removed. */
if (htab->elf.hplt != NULL)
strip_section = FALSE;
}
- else if (strncmp (bfd_get_section_name (dynobj, s), ".rel", 4) == 0)
+ else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rel"))
{
if (s->size != 0 && s != htab->srelplt && s != htab->srelplt2)
relocs = TRUE;
howto = elf_howto_table + indx;
r_symndx = ELF32_R_SYM (rel->r_info);
-
- if (info->relocatable)
- {
- bfd_vma val;
- bfd_byte *where;
-
- /* This is a relocatable link. We don't have to change
- anything, unless the reloc is against a section symbol,
- in which case we have to adjust according to where the
- section symbol winds up in the output section. */
- if (r_symndx >= symtab_hdr->sh_info)
- continue;
-
- sym = local_syms + r_symndx;
- if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
- continue;
-
- sec = local_sections[r_symndx];
- val = sec->output_offset;
- if (val == 0)
- continue;
-
- where = contents + rel->r_offset;
- switch (howto->size)
- {
- /* FIXME: overflow checks. */
- case 0:
- val += bfd_get_8 (input_bfd, where);
- bfd_put_8 (input_bfd, val, where);
- break;
- case 1:
- val += bfd_get_16 (input_bfd, where);
- bfd_put_16 (input_bfd, val, where);
- break;
- case 2:
- val += bfd_get_32 (input_bfd, where);
- bfd_put_32 (input_bfd, val, where);
- break;
- default:
- abort ();
- }
- continue;
- }
-
- /* This is a final link. */
h = NULL;
sym = NULL;
sec = NULL;
relocation = (sec->output_section->vma
+ sec->output_offset
+ sym->st_value);
- if ((sec->flags & SEC_MERGE)
- && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+
+ if (ELF_ST_TYPE (sym->st_info) == STT_SECTION
+ && ((sec->flags & SEC_MERGE) != 0
+ || (info->relocatable
+ && sec->output_offset != 0)))
{
- asection *msec;
bfd_vma addend;
bfd_byte *where = contents + rel->r_offset;
abort ();
}
- msec = sec;
- addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend);
- addend -= relocation;
- addend += msec->output_section->vma + msec->output_offset;
+ if (info->relocatable)
+ addend += sec->output_offset;
+ else
+ {
+ asection *msec = sec;
+ addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec,
+ addend);
+ addend -= relocation;
+ addend += msec->output_section->vma + msec->output_offset;
+ }
switch (howto->size)
{
unresolved_reloc, warned);
}
- if (r_symndx == 0)
+ if (sec != NULL && elf_discarded_section (sec))
{
- /* r_symndx will be zero only for relocs against symbols from
- removed linkonce sections, or sections discarded by a linker
- script. For these relocs, we just want the section contents
- zeroed. Avoid any special processing in the switch below. */
- r_type = R_386_NONE;
-
- relocation = 0;
- if (howto->pc_relative)
- relocation = (input_section->output_section->vma
- + input_section->output_offset
- + rel->r_offset);
+ /* For relocs against symbols from removed linkonce sections,
+ or sections discarded by a linker script, we just want the
+ section contents zeroed. Avoid any special processing. */
+ _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
+ rel->r_info = 0;
+ rel->r_addend = 0;
+ continue;
}
+ if (info->relocatable)
+ continue;
+
switch (r_type)
{
case R_386_GOT32:
&& h->dynindx != -1
&& (r_type == R_386_PC32
|| !info->shared
- || !info->symbolic
+ || !SYMBOLIC_BIND (info, h)
|| !h->def_regular))
outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
else
val = bfd_get_8 (input_bfd, contents + roff + 1);
BFD_ASSERT (val == 0x10);
- /* Now modify the instruction as appropriate. */
- bfd_put_8 (output_bfd, 0x90, contents + roff);
+ /* Now modify the instruction as appropriate. Use
+ xchg %ax,%ax instead of 2 nops. */
+ bfd_put_8 (output_bfd, 0x66, contents + roff);
bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
continue;
}
/* Now modify the instruction as appropriate. */
if (tls_type != GOT_TLS_IE_NEG)
{
- /* nop; nop */
- bfd_put_8 (output_bfd, 0x90, contents + roff);
+ /* xchg %ax,%ax */
+ bfd_put_8 (output_bfd, 0x66, contents + roff);
bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
}
else
return plt->vma + (i + 1) * PLT_ENTRY_SIZE;
}
+/* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */
+
+static bfd_boolean
+elf_i386_hash_symbol (struct elf_link_hash_entry *h)
+{
+ if (h->plt.offset != (bfd_vma) -1
+ && !h->def_regular
+ && !h->pointer_equality_needed)
+ return FALSE;
+
+ return _bfd_elf_hash_symbol (h);
+}
#define TARGET_LITTLE_SYM bfd_elf32_i386_vec
#define TARGET_LITTLE_NAME "elf32-i386"
#define bfd_elf32_bfd_is_local_label_name elf_i386_is_local_label_name
#define bfd_elf32_bfd_link_hash_table_create elf_i386_link_hash_table_create
#define bfd_elf32_bfd_reloc_type_lookup elf_i386_reloc_type_lookup
+#define bfd_elf32_bfd_reloc_name_lookup elf_i386_reloc_name_lookup
#define elf_backend_adjust_dynamic_symbol elf_i386_adjust_dynamic_symbol
#define elf_backend_check_relocs elf_i386_check_relocs
#define elf_backend_relocate_section elf_i386_relocate_section
#define elf_backend_size_dynamic_sections elf_i386_size_dynamic_sections
#define elf_backend_always_size_sections elf_i386_always_size_sections
+#define elf_backend_omit_section_dynsym \
+ ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
#define elf_backend_plt_sym_val elf_i386_plt_sym_val
+#define elf_backend_hash_symbol elf_i386_hash_symbol
#include "elf32-target.h"
#define TARGET_LITTLE_SYM bfd_elf32_i386_freebsd_vec
#undef TARGET_LITTLE_NAME
#define TARGET_LITTLE_NAME "elf32-i386-freebsd"
+#undef ELF_OSABI
+#define ELF_OSABI ELFOSABI_FREEBSD
/* The kernel recognizes executables as valid only if they carry a
"FreeBSD" label in the ELF header. So we put this label on all
i_ehdrp = elf_elfheader (abfd);
/* Put an ABI label supported by FreeBSD >= 4.1. */
- i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
+ i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
#ifdef OLD_FREEBSD_ABI_LABEL
/* The ABI label supported by FreeBSD <= 4.0 is quite nonstandard. */
memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8);
#define TARGET_LITTLE_SYM bfd_elf32_i386_vxworks_vec
#undef TARGET_LITTLE_NAME
#define TARGET_LITTLE_NAME "elf32-i386-vxworks"
-
+#undef ELF_OSABI
/* Like elf_i386_link_hash_table_create but with tweaks for VxWorks. */