/* Intel 80386/80486-specific support for 32-bit ELF
- Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
- Free Software Foundation, Inc.
+ Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+ 2003, 2004 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
}
\f
/* Support for core dump NOTE sections. */
+
static bfd_boolean
elf_i386_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
{
int offset;
- size_t raw_size;
+ size_t size;
- switch (note->descsz)
+ if (note->namesz == 8 && strcmp (note->namedata, "FreeBSD") == 0)
{
- default:
- return FALSE;
+ int pr_version = bfd_get_32 (abfd, note->descdata);
+
+ if (pr_version != 1)
+ return FALSE;
+
+ /* pr_cursig */
+ elf_tdata (abfd)->core_signal = bfd_get_32 (abfd, note->descdata + 20);
+
+ /* pr_pid */
+ elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24);
+
+ /* pr_reg */
+ offset = 28;
+ size = bfd_get_32 (abfd, note->descdata + 8);
+ }
+ else
+ {
+ switch (note->descsz)
+ {
+ default:
+ return FALSE;
- case 144: /* Linux/i386 */
- /* pr_cursig */
- elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
+ case 144: /* Linux/i386 */
+ /* pr_cursig */
+ elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
- /* pr_pid */
- elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24);
+ /* pr_pid */
+ elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24);
- /* pr_reg */
- offset = 72;
- raw_size = 68;
+ /* pr_reg */
+ offset = 72;
+ size = 68;
- break;
+ break;
+ }
}
/* Make a ".reg/999" section. */
return _bfd_elfcore_make_pseudosection (abfd, ".reg",
- raw_size, note->descpos + offset);
+ size, note->descpos + offset);
}
static bfd_boolean
elf_i386_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
{
- switch (note->descsz)
+ if (note->namesz == 8 && strcmp (note->namedata, "FreeBSD") == 0)
{
- default:
+ int pr_version = bfd_get_32 (abfd, note->descdata);
+
+ if (pr_version != 1)
return FALSE;
- case 124: /* Linux/i386 elf_prpsinfo */
- elf_tdata (abfd)->core_program
- = _bfd_elfcore_strndup (abfd, note->descdata + 28, 16);
- elf_tdata (abfd)->core_command
- = _bfd_elfcore_strndup (abfd, note->descdata + 44, 80);
+ elf_tdata (abfd)->core_program
+ = _bfd_elfcore_strndup (abfd, note->descdata + 8, 17);
+ elf_tdata (abfd)->core_command
+ = _bfd_elfcore_strndup (abfd, note->descdata + 25, 81);
+ }
+ else
+ {
+ switch (note->descsz)
+ {
+ default:
+ return FALSE;
+
+ case 124: /* Linux/i386 elf_prpsinfo. */
+ elf_tdata (abfd)->core_program
+ = _bfd_elfcore_strndup (abfd, note->descdata + 28, 16);
+ elf_tdata (abfd)->core_command
+ = _bfd_elfcore_strndup (abfd, note->descdata + 44, 80);
+ }
}
/* Note that for some reason, a spurious space is tacked
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;
int n = strlen (command);
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_386_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_386_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
return FALSE;
break;
runtime process image. */
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
{
- htab->srelbss->_raw_size += sizeof (Elf32_External_Rel);
+ htab->srelbss->size += sizeof (Elf32_External_Rel);
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY;
}
/* Apply the required alignment. */
s = htab->sdynbss;
- s->_raw_size = BFD_ALIGN (s->_raw_size, (bfd_size_type) (1 << power_of_two));
+ s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two));
if (power_of_two > bfd_get_section_alignment (htab->elf.dynobj, s))
{
if (! bfd_set_section_alignment (htab->elf.dynobj, s, power_of_two))
/* Define the symbol as being at this point in the section. */
h->root.u.def.section = s;
- h->root.u.def.value = s->_raw_size;
+ h->root.u.def.value = s->size;
/* Increment the section size to make room for the symbol. */
- s->_raw_size += h->size;
+ s->size += h->size;
return TRUE;
}
-/* This is the condition under which elf_i386_finish_dynamic_symbol
- will be called from elflink.h. If elflink.h doesn't call our
- finish_dynamic_symbol routine, we'll need to do something about
- initializing any .plt and .got entries in elf_i386_relocate_section. */
-#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, SHARED, H) \
- ((DYN) \
- && ((SHARED) \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \
- && ((H)->dynindx != -1 \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
-
/* Allocate space in .plt, .got and associated reloc sections for
dynamic relocs. */
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
/* If this is the first .plt entry, make room for the special
first entry. */
- if (s->_raw_size == 0)
- s->_raw_size += PLT_ENTRY_SIZE;
+ if (s->size == 0)
+ s->size += PLT_ENTRY_SIZE;
- h->plt.offset = s->_raw_size;
+ h->plt.offset = s->size;
/* If this symbol is not defined in a regular file, and we are
not generating a shared library, then set the symbol to this
}
/* Make room for this entry. */
- s->_raw_size += PLT_ENTRY_SIZE;
+ s->size += PLT_ENTRY_SIZE;
/* We also need to make an entry in the .got.plt section, which
will be placed in the .got section by the linker script. */
- htab->sgotplt->_raw_size += 4;
+ htab->sgotplt->size += 4;
/* We also need to make an entry in the .rel.plt section. */
- htab->srelplt->_raw_size += sizeof (Elf32_External_Rel);
+ htab->srelplt->size += sizeof (Elf32_External_Rel);
}
else
{
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
s = htab->sgot;
- h->got.offset = s->_raw_size;
- s->_raw_size += 4;
+ h->got.offset = s->size;
+ s->size += 4;
/* R_386_TLS_GD needs 2 consecutive GOT slots. */
if (tls_type == GOT_TLS_GD || tls_type == GOT_TLS_IE_BOTH)
- s->_raw_size += 4;
+ s->size += 4;
dyn = htab->elf.dynamic_sections_created;
/* R_386_TLS_IE_32 needs one dynamic relocation,
R_386_TLS_IE resp. R_386_TLS_GOTIE needs one dynamic relocation,
need two), R_386_TLS_GD needs one if local symbol and two if
global. */
if (tls_type == GOT_TLS_IE_BOTH)
- htab->srelgot->_raw_size += 2 * sizeof (Elf32_External_Rel);
+ htab->srelgot->size += 2 * sizeof (Elf32_External_Rel);
else if ((tls_type == GOT_TLS_GD && h->dynindx == -1)
|| (tls_type & GOT_TLS_IE))
- htab->srelgot->_raw_size += sizeof (Elf32_External_Rel);
+ htab->srelgot->size += sizeof (Elf32_External_Rel);
else if (tls_type == GOT_TLS_GD)
- htab->srelgot->_raw_size += 2 * sizeof (Elf32_External_Rel);
+ htab->srelgot->size += 2 * sizeof (Elf32_External_Rel);
else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|| h->root.type != bfd_link_hash_undefweak)
&& (info->shared
|| WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
- htab->srelgot->_raw_size += sizeof (Elf32_External_Rel);
+ htab->srelgot->size += sizeof (Elf32_External_Rel);
}
else
h->got.offset = (bfd_vma) -1;
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
for (p = eh->dyn_relocs; p != NULL; p = p->next)
{
asection *sreloc = elf_section_data (p->sec)->sreloc;
- sreloc->_raw_size += p->count * sizeof (Elf32_External_Rel);
+ sreloc->size += p->count * sizeof (Elf32_External_Rel);
}
return TRUE;
s = bfd_get_section_by_name (dynobj, ".interp");
if (s == NULL)
abort ();
- s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
+ s->size = sizeof ELF_DYNAMIC_INTERPRETER;
s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
}
}
else if (p->count != 0)
{
srel = elf_section_data (p->sec)->sreloc;
- srel->_raw_size += p->count * sizeof (Elf32_External_Rel);
+ srel->size += p->count * sizeof (Elf32_External_Rel);
if ((p->sec->output_section->flags & SEC_READONLY) != 0)
info->flags |= DF_TEXTREL;
}
{
if (*local_got > 0)
{
- *local_got = s->_raw_size;
- s->_raw_size += 4;
+ *local_got = s->size;
+ s->size += 4;
if (*local_tls_type == GOT_TLS_GD
|| *local_tls_type == GOT_TLS_IE_BOTH)
- s->_raw_size += 4;
+ s->size += 4;
if (info->shared
|| *local_tls_type == GOT_TLS_GD
|| (*local_tls_type & GOT_TLS_IE))
{
if (*local_tls_type == GOT_TLS_IE_BOTH)
- srel->_raw_size += 2 * sizeof (Elf32_External_Rel);
+ srel->size += 2 * sizeof (Elf32_External_Rel);
else
- srel->_raw_size += sizeof (Elf32_External_Rel);
+ srel->size += sizeof (Elf32_External_Rel);
}
}
else
{
/* Allocate 2 got entries and 1 dynamic reloc for R_386_TLS_LDM
relocs. */
- htab->tls_ldm_got.offset = htab->sgot->_raw_size;
- htab->sgot->_raw_size += 8;
- htab->srelgot->_raw_size += sizeof (Elf32_External_Rel);
+ htab->tls_ldm_got.offset = htab->sgot->size;
+ htab->sgot->size += 8;
+ htab->srelgot->size += sizeof (Elf32_External_Rel);
}
else
htab->tls_ldm_got.offset = -1;
}
else if (strncmp (bfd_get_section_name (dynobj, s), ".rel", 4) == 0)
{
- if (s->_raw_size != 0 && s != htab->srelplt)
+ if (s->size != 0 && s != htab->srelplt)
relocs = TRUE;
/* We use the reloc_count field as a counter if we need
continue;
}
- if (s->_raw_size == 0)
+ if (s->size == 0)
{
/* If we don't need this section, strip it from the
output file. This is mostly to handle .rel.bss and
section's contents are written out. This should not happen,
but this way if it does, we get a R_386_NONE reloc instead
of garbage. */
- s->contents = bfd_zalloc (dynobj, s->_raw_size);
+ s->contents = bfd_zalloc (dynobj, s->size);
if (s->contents == NULL)
return FALSE;
}
the .dynamic section. The DT_DEBUG entry is filled in by the
dynamic linker and used by the debugger. */
#define add_dynamic_entry(TAG, VAL) \
- bfd_elf32_add_dynamic_entry (info, (TAG), (VAL))
+ _bfd_elf_add_dynamic_entry (info, TAG, VAL)
if (info->executable)
{
return FALSE;
}
- if (htab->splt->_raw_size != 0)
+ if (htab->splt->size != 0)
{
if (!add_dynamic_entry (DT_PLTGOT, 0)
|| !add_dynamic_entry (DT_PLTRELSZ, 0)
{
bfd_boolean warned;
- RELOC_FOR_GLOBAL_SYMBOL (h, sym_hashes, r_symndx, symtab_hdr, relocation, sec, unresolved_reloc, info, warned);
+ RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
+ r_symndx, symtab_hdr, sym_hashes,
+ h, sec, relocation,
+ unresolved_reloc, warned);
}
switch (r_type)
if (off >= (bfd_vma) -2)
abort ();
- relocation = htab->sgot->output_offset + off;
+ relocation = htab->sgot->output_section->vma
+ + htab->sgot->output_offset + off
+ - htab->sgotplt->output_section->vma
+ - htab->sgotplt->output_offset;
break;
case R_386_GOTOFF:
/* Relocation is relative to the start of the global offset
table. */
- /* Note that sgot->output_offset is not involved in this
- calculation. We always want the start of .got. If we
- defined _GLOBAL_OFFSET_TABLE in a different way, as is
+ /* Note that sgot is not involved in this
+ calculation. We always want the start of .got.plt. If we
+ defined _GLOBAL_OFFSET_TABLE_ in a different way, as is
permitted by the ABI, we might have to change this
calculation. */
- relocation -= htab->sgot->output_section->vma;
+ relocation -= htab->sgotplt->output_section->vma
+ + htab->sgotplt->output_offset;
break;
case R_386_GOTPC:
/* Use global offset table as symbol value. */
- relocation = htab->sgot->output_section->vma;
+ relocation = htab->sgotplt->output_section->vma
+ + htab->sgotplt->output_offset;
unresolved_reloc = FALSE;
break;
BFD_ASSERT (rel->r_offset >= 2);
type = bfd_get_8 (input_bfd, contents + rel->r_offset - 2);
BFD_ASSERT (type == 0x8d || type == 0x04);
- BFD_ASSERT (rel->r_offset + 9 <= input_section->_raw_size);
+ BFD_ASSERT (rel->r_offset + 9 <= input_section->size);
BFD_ASSERT (bfd_get_8 (input_bfd,
contents + rel->r_offset + 4)
== 0xe8);
else
{
BFD_ASSERT ((val & 0xf8) == 0x80 && (val & 7) != 4);
- if (rel->r_offset + 10 <= input_section->_raw_size
+ if (rel->r_offset + 10 <= input_section->size
&& bfd_get_8 (input_bfd,
contents + rel->r_offset + 9) == 0x90)
{
addl $foo, %reg. */
BFD_ASSERT (rel->r_offset >= 1);
val = bfd_get_8 (input_bfd, contents + rel->r_offset - 1);
- BFD_ASSERT (rel->r_offset + 4 <= input_section->_raw_size);
+ BFD_ASSERT (rel->r_offset + 4 <= input_section->size);
if (val == 0xa1)
{
/* movl foo, %eax. */
BFD_ASSERT (rel->r_offset >= 2);
type = bfd_get_8 (input_bfd, contents + rel->r_offset - 2);
val = bfd_get_8 (input_bfd, contents + rel->r_offset - 1);
- BFD_ASSERT (rel->r_offset + 4 <= input_section->_raw_size);
+ BFD_ASSERT (rel->r_offset + 4 <= input_section->size);
BFD_ASSERT ((val & 0xc0) == 0x80 && (val & 7) != 4);
if (type == 0x8b)
{
abort ();
if (r_type == ELF32_R_TYPE (rel->r_info))
{
- relocation = htab->sgot->output_offset + off;
+ bfd_vma g_o_t = htab->sgotplt->output_section->vma
+ + htab->sgotplt->output_offset;
+ relocation = htab->sgot->output_section->vma
+ + htab->sgot->output_offset + off - g_o_t;
if ((r_type == R_386_TLS_IE || r_type == R_386_TLS_GOTIE)
&& tls_type == GOT_TLS_IE_BOTH)
relocation += 4;
if (r_type == R_386_TLS_IE)
- relocation += htab->sgot->output_section->vma;
+ relocation += g_o_t;
unresolved_reloc = FALSE;
}
else
BFD_ASSERT (rel->r_offset >= 2);
type = bfd_get_8 (input_bfd, contents + rel->r_offset - 2);
BFD_ASSERT (type == 0x8d || type == 0x04);
- BFD_ASSERT (rel->r_offset + 9 <= input_section->_raw_size);
+ BFD_ASSERT (rel->r_offset + 9 <= input_section->size);
BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset + 4)
== 0xe8);
BFD_ASSERT (rel + 1 < relend);
/* leal foo(%reg), %eax; call ___tls_get_addr; nop
Change it into:
movl %gs:0, %eax; subl $foo@gottpoff(%reg), %eax. */
- BFD_ASSERT (rel->r_offset + 10 <= input_section->_raw_size);
+ BFD_ASSERT (rel->r_offset + 10 <= input_section->size);
BFD_ASSERT ((val & 0xf8) == 0x80 && (val & 7) != 4);
BFD_ASSERT (bfd_get_8 (input_bfd,
contents + rel->r_offset + 9)
if (tls_type == GOT_TLS_IE_BOTH)
off += 4;
}
- bfd_put_32 (output_bfd, htab->sgot->output_offset + off,
+ bfd_put_32 (output_bfd,
+ htab->sgot->output_section->vma
+ + htab->sgot->output_offset + off
+ - htab->sgotplt->output_section->vma
+ - htab->sgotplt->output_offset,
contents + roff + 8);
/* Skip R_386_PLT32. */
rel++;
== 0x8d);
val = bfd_get_8 (input_bfd, contents + rel->r_offset - 1);
BFD_ASSERT ((val & 0xf8) == 0x80 && (val & 7) != 4);
- BFD_ASSERT (rel->r_offset + 9 <= input_section->_raw_size);
+ BFD_ASSERT (rel->r_offset + 9 <= input_section->size);
BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset + 4)
== 0xe8);
BFD_ASSERT (rel + 1 < relend);
bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
htab->tls_ldm_got.offset |= 1;
}
- relocation = htab->sgot->output_offset + off;
+ relocation = htab->sgot->output_section->vma
+ + htab->sgot->output_offset + off
+ - htab->sgotplt->output_section->vma
+ - htab->sgotplt->output_offset;
unresolved_reloc = FALSE;
break;
abort ();
dyncon = (Elf32_External_Dyn *) sdyn->contents;
- dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
+ dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
for (; dyncon < dynconend; dyncon++)
{
Elf_Internal_Dyn dyn;
continue;
case DT_PLTGOT:
- dyn.d_un.d_ptr = htab->sgot->output_section->vma;
+ s = htab->sgotplt;
+ dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
break;
case DT_JMPREL:
case DT_PLTRELSZ:
s = htab->srelplt;
- dyn.d_un.d_val = s->_raw_size;
+ dyn.d_un.d_val = s->size;
break;
case DT_RELSZ:
s = htab->srelplt;
if (s == NULL)
continue;
- dyn.d_un.d_val -= s->_raw_size;
+ dyn.d_un.d_val -= s->size;
break;
case DT_REL:
continue;
if (dyn.d_un.d_ptr != s->output_section->vma + s->output_offset)
continue;
- dyn.d_un.d_ptr += s->_raw_size;
+ dyn.d_un.d_ptr += s->size;
break;
}
}
/* Fill in the first entry in the procedure linkage table. */
- if (htab->splt && htab->splt->_raw_size > 0)
+ if (htab->splt && htab->splt->size > 0)
{
if (info->shared)
memcpy (htab->splt->contents,
if (htab->sgotplt)
{
/* Fill in the first three entries in the global offset table. */
- if (htab->sgotplt->_raw_size > 0)
+ if (htab->sgotplt->size > 0)
{
bfd_put_32 (output_bfd,
(sdyn == NULL ? 0
elf_section_data (htab->sgotplt->output_section)->this_hdr.sh_entsize = 4;
}
+
+ if (htab->sgot && htab->sgot->size > 0)
+ elf_section_data (htab->sgot->output_section)->this_hdr.sh_entsize = 4;
+
return TRUE;
}
+/* Return address for Ith PLT stub in section PLT, for relocation REL
+ or (bfd_vma) -1 if it should not be included. */
+
+static bfd_vma
+elf_i386_plt_sym_val (bfd_vma i, const asection *plt,
+ const arelent *rel ATTRIBUTE_UNUSED)
+{
+ return plt->vma + (i + 1) * PLT_ENTRY_SIZE;
+}
+
+
#define TARGET_LITTLE_SYM bfd_elf32_i386_vec
#define TARGET_LITTLE_NAME "elf32-i386"
#define ELF_ARCH bfd_arch_i386
#define elf_backend_reloc_type_class elf_i386_reloc_type_class
#define elf_backend_relocate_section elf_i386_relocate_section
#define elf_backend_size_dynamic_sections elf_i386_size_dynamic_sections
+#define elf_backend_plt_sym_val elf_i386_plt_sym_val
#include "elf32-target.h"