]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - bfd/elf32-i386.c
bfd/
[thirdparty/binutils-gdb.git] / bfd / elf32-i386.c
index 227bc9e7289a973fe8d31dc7d42939ef1b5db315..35cb7c62fcd54117c897ea91f9832300593e5e0a 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, 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.
 
@@ -18,8 +18,8 @@
    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"
@@ -330,6 +330,20 @@ elf_i386_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
   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,
@@ -2264,51 +2278,6 @@ elf_i386_relocate_section (bfd *output_bfd,
       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;
@@ -2320,10 +2289,12 @@ elf_i386_relocate_section (bfd *output_bfd,
          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;
 
@@ -2357,10 +2328,16 @@ elf_i386_relocate_section (bfd *output_bfd,
                  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)
                {
@@ -2393,21 +2370,20 @@ elf_i386_relocate_section (bfd *output_bfd,
                                   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:
@@ -3856,6 +3832,7 @@ elf_i386_hash_symbol (struct elf_link_hash_entry *h)
 #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
@@ -3872,6 +3849,8 @@ elf_i386_hash_symbol (struct elf_link_hash_entry *h)
 #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
 
@@ -3883,6 +3862,8 @@ elf_i386_hash_symbol (struct elf_link_hash_entry *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
@@ -3897,7 +3878,7 @@ elf_i386_post_process_headers (bfd *abfd,
   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);
@@ -3917,7 +3898,7 @@ elf_i386_post_process_headers (bfd *abfd,
 #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.  */