]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - bfd/elf32-i386.c
This commit was manufactured by cvs2svn to create branch 'gdb_6_2-branch'.
[thirdparty/binutils-gdb.git] / bfd / elf32-i386.c
index 876efc6ab0c4b0ef4efa1f3cfd57db9cc12fe460..97891a58783ab5de9b2be38d07e39ac5930b4f88 100644 (file)
@@ -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
-   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.
 
@@ -346,55 +346,90 @@ elf_i386_is_local_label_name (bfd *abfd, const char *name)
 }
 \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);
@@ -1122,14 +1157,14 @@ elf_i386_check_relocs (bfd *abfd,
          /* 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;
 
@@ -1394,7 +1429,7 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info,
      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;
     }
 
@@ -1406,7 +1441,7 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info,
 
   /* 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))
@@ -1415,25 +1450,14 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info,
 
   /* 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.  */
 
@@ -1465,7 +1489,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
       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;
        }
 
@@ -1476,10 +1500,10 @@ 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->_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
@@ -1494,14 +1518,14 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
            }
 
          /* 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
        {
@@ -1533,16 +1557,16 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
       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,
@@ -1550,17 +1574,17 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
         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;
@@ -1622,7 +1646,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
          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;
            }
 
@@ -1641,7 +1665,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   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;
@@ -1701,7 +1725,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
          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;
        }
     }
@@ -1740,7 +1764,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
              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;
                }
@@ -1761,19 +1785,19 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
        {
          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
@@ -1785,9 +1809,9 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
     {
       /* 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;
@@ -1813,7 +1837,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
        }
       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
@@ -1826,7 +1850,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
          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
@@ -1847,7 +1871,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
         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;
     }
@@ -1860,7 +1884,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
         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)
        {
@@ -1868,7 +1892,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
            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)
@@ -2144,7 +2168,10 @@ elf_i386_relocate_section (bfd *output_bfd,
        {
          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)
@@ -2234,24 +2261,29 @@ elf_i386_relocate_section (bfd *output_bfd,
          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;
 
@@ -2417,7 +2449,7 @@ elf_i386_relocate_section (bfd *output_bfd,
                  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);
@@ -2443,7 +2475,7 @@ elf_i386_relocate_section (bfd *output_bfd,
                  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)
                        {
@@ -2486,7 +2518,7 @@ elf_i386_relocate_section (bfd *output_bfd,
                     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.  */
@@ -2543,7 +2575,7 @@ elf_i386_relocate_section (bfd *output_bfd,
                  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)
                    {
@@ -2672,12 +2704,15 @@ elf_i386_relocate_section (bfd *output_bfd,
            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
@@ -2689,7 +2724,7 @@ elf_i386_relocate_section (bfd *output_bfd,
              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);
@@ -2713,7 +2748,7 @@ elf_i386_relocate_section (bfd *output_bfd,
                  /* 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)
@@ -2734,7 +2769,11 @@ elf_i386_relocate_section (bfd *output_bfd,
                  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++;
@@ -2757,7 +2796,7 @@ elf_i386_relocate_section (bfd *output_bfd,
                          == 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);
@@ -2796,7 +2835,10 @@ elf_i386_relocate_section (bfd *output_bfd,
              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;
 
@@ -3118,7 +3160,7 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
        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;
@@ -3132,7 +3174,8 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
              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:
@@ -3142,7 +3185,7 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
 
            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:
@@ -3155,7 +3198,7 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
              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:
@@ -3167,7 +3210,7 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
                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;
            }
 
@@ -3175,7 +3218,7 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
        }
 
       /* 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,
@@ -3206,7 +3249,7 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
   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
@@ -3218,9 +3261,24 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
 
       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
@@ -3258,6 +3316,7 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
 #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"