2007-04-06 Matt Thomas <matt@netbsd.org>
[deliverable/binutils-gdb.git] / bfd / elfcode.h
index 9bb66e11c0cf8f329708420da1909319bb025947..3c295502df70658a40202fdbedc53f515dfa0ae0 100644 (file)
@@ -1,6 +1,6 @@
 /* ELF executable support for BFD.
    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
    Written by Fred Fish @ Cygnus Support, from information published
    in "UNIX System V Release 4, Programmers Guide: ANSI C and
@@ -139,10 +139,11 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
 #define LOG_FILE_ALIGN 2
 #endif
 
-#ifdef DEBUG
+#if DEBUG & 2
 static void elf_debug_section (int, Elf_Internal_Shdr *);
+#endif
+#if DEBUG & 1
 static void elf_debug_file (Elf_Internal_Ehdr *);
-static char *elf_symbol_flags (flagword);
 #endif
 \f
 /* Structure swapping routines */
@@ -165,7 +166,7 @@ static char *elf_symbol_flags (flagword);
 /* Translate an ELF symbol in external format into an ELF symbol in internal
    format.  */
 
-void
+bfd_boolean
 elf_swap_symbol_in (bfd *abfd,
                    const void *psrc,
                    const void *pshn,
@@ -187,9 +188,10 @@ elf_swap_symbol_in (bfd *abfd,
   if (dst->st_shndx == SHN_XINDEX)
     {
       if (shndx == NULL)
-       abort ();
+       return FALSE;
       dst->st_shndx = H_GET_32 (abfd, shndx->est_shndx);
     }
+  return TRUE;
 }
 
 /* Translate an ELF symbol in internal format into an ELF symbol in external
@@ -458,6 +460,25 @@ elf_file_p (Elf_External_Ehdr *x_ehdrp)
          && (x_ehdrp->e_ident[EI_MAG3] == ELFMAG3));
 }
 
+/* Determines if a given section index is valid.  */
+
+static inline bfd_boolean
+valid_section_index_p (unsigned index, unsigned num_sections)
+{
+  /* Note: We allow SHN_UNDEF as a valid section index.  */
+  if (index < SHN_LORESERVE || index > SHN_HIRESERVE)
+    return index < num_sections;
+  
+  /* We disallow the use of reserved indcies, except for those
+     with OS or Application specific meaning.  The test make use
+     of the knowledge that:
+       SHN_LORESERVE == SHN_LOPROC
+     and
+       SHN_HIPROC == SHN_LOOS - 1  */
+  /* XXX - Should we allow SHN_XINDEX as a valid index here ?  */
+  return (index >= SHN_LOPROC && index <= SHN_HIOS);
+}
+
 /* Check to see if the file associated with ABFD matches the target vector
    that ABFD points to.
 
@@ -479,6 +500,8 @@ elf_object_p (bfd *abfd)
   struct bfd_preserve preserve;
   asection *s;
   bfd_size_type amt;
+  const bfd_target *target;
+  const bfd_target * const *target_ptr;
 
   preserve.marker = NULL;
 
@@ -522,10 +545,12 @@ elf_object_p (bfd *abfd)
   if (!bfd_preserve_save (abfd, &preserve))
     goto got_no_match;
 
+  target = abfd->xvec;
+
   /* Allocate an instance of the elf_obj_tdata structure and hook it up to
      the tdata pointer in the bfd.  */
 
-  if (! (*abfd->xvec->_bfd_set_format[bfd_object]) (abfd))
+  if (! (*target->_bfd_set_format[bfd_object]) (abfd))
     goto got_no_match;
   preserve.marker = elf_tdata (abfd);
 
@@ -545,7 +570,7 @@ elf_object_p (bfd *abfd)
   if (i_ehdrp->e_shoff == 0 && i_ehdrp->e_type == ET_REL)
     goto got_wrong_format_error;
 
-  /* As a simple sanity check, verify that the what BFD thinks is the
+  /* As a simple sanity check, verify that what BFD thinks is the
      size of each section header table entry actually matches the size
      recorded in the file, but only if there are any sections.  */
   if (i_ehdrp->e_shentsize != sizeof (x_shdr) && i_ehdrp->e_shnum != 0)
@@ -565,8 +590,6 @@ elf_object_p (bfd *abfd)
       && (ebd->elf_machine_alt2 == 0
          || i_ehdrp->e_machine != ebd->elf_machine_alt2))
     {
-      const bfd_target * const *target_ptr;
-
       if (ebd->elf_machine_code != EM_NONE)
        goto got_wrong_format_error;
 
@@ -607,6 +630,45 @@ elf_object_p (bfd *abfd)
        goto got_no_match;
     }
 
+  if (ebd->elf_machine_code != EM_NONE
+      && i_ehdrp->e_ident[EI_OSABI] != ebd->elf_osabi)
+    {
+      if (ebd->elf_osabi != ELFOSABI_NONE)
+       goto got_wrong_format_error;
+
+      /* This is an ELFOSABI_NONE ELF target.  Let it match any ELF
+        target of the compatible machine for which we do not have a
+        backend with matching ELFOSABI.  */
+      for (target_ptr = bfd_target_vector;
+          *target_ptr != NULL;
+          target_ptr++)
+       {
+         const struct elf_backend_data *back;
+
+         /* Skip this target and targets with incompatible byte
+            order.  */
+         if (*target_ptr == target
+             || (*target_ptr)->flavour != bfd_target_elf_flavour
+             || (*target_ptr)->byteorder != target->byteorder
+             || ((*target_ptr)->header_byteorder
+                 != target->header_byteorder))
+           continue;
+
+         back = (const struct elf_backend_data *) (*target_ptr)->backend_data;
+         if (back->elf_osabi == i_ehdrp->e_ident[EI_OSABI]
+             && (back->elf_machine_code == i_ehdrp->e_machine
+                 || (back->elf_machine_alt1 != 0
+                     && back->elf_machine_alt1 == i_ehdrp->e_machine)
+                 || (back->elf_machine_alt2 != 0
+                     && back->elf_machine_alt2 == i_ehdrp->e_machine)))
+           {
+             /* target_ptr is an ELF backend which matches this
+                object file, so reject the ELFOSABI_NONE ELF target.  */
+             goto got_wrong_format_error;
+           }
+       }
+    }
+
   if (i_ehdrp->e_shoff != 0)
     {
       bfd_signed_vma where = i_ehdrp->e_shoff;
@@ -711,17 +773,13 @@ elf_object_p (bfd *abfd)
          elf_swap_shdr_in (abfd, &x_shdr, i_shdrp + shindex);
 
          /* Sanity check sh_link and sh_info.  */
-         if (i_shdrp[shindex].sh_link >= num_sec
-             || (i_shdrp[shindex].sh_link >= SHN_LORESERVE
-                 && i_shdrp[shindex].sh_link <= SHN_HIRESERVE))
+         if (! valid_section_index_p (i_shdrp[shindex].sh_link, num_sec))
            goto got_wrong_format_error;
 
          if (((i_shdrp[shindex].sh_flags & SHF_INFO_LINK)
               || i_shdrp[shindex].sh_type == SHT_RELA
               || i_shdrp[shindex].sh_type == SHT_REL)
-             && (i_shdrp[shindex].sh_info >= num_sec
-                 || (i_shdrp[shindex].sh_info >= SHN_LORESERVE
-                     && i_shdrp[shindex].sh_info <= SHN_HIRESERVE)))
+             && ! valid_section_index_p (i_shdrp[shindex].sh_info, num_sec))
            goto got_wrong_format_error;
 
          /* If the section is loaded, but not page aligned, clear
@@ -739,9 +797,7 @@ elf_object_p (bfd *abfd)
   /* A further sanity check.  */
   if (i_ehdrp->e_shnum != 0)
     {
-      if (i_ehdrp->e_shstrndx >= elf_numsections (abfd)
-         || (i_ehdrp->e_shstrndx >= SHN_LORESERVE
-             && i_ehdrp->e_shstrndx <= SHN_HIRESERVE))
+      if (! valid_section_index_p (i_ehdrp->e_shstrndx, elf_numsections (abfd)))
        {
          /* PR 2257:
             We used to just goto got_wrong_format_error here
@@ -833,7 +889,7 @@ elf_object_p (bfd *abfd)
     }
 
   bfd_preserve_finish (abfd, &preserve);
-  return abfd->xvec;
+  return target;
 
  got_wrong_format_error:
   /* There is way too much undoing of half-known state here.  The caller,
@@ -1222,6 +1278,12 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic)
            case STT_TLS:
              sym->symbol.flags |= BSF_THREAD_LOCAL;
              break;
+           case STT_RELC:
+             sym->symbol.flags |= BSF_RELC;
+             break;
+           case STT_SRELC:
+             sym->symbol.flags |= BSF_SRELC;
+             break;
            }
 
          if (dynamic)
@@ -1349,10 +1411,9 @@ elf_slurp_reloc_table_from_section (bfd *abfd,
        }
       else
        {
-         asymbol **ps, *s;
+         asymbol **ps;
 
          ps = symbols + ELF_R_SYM (rela.r_info) - 1;
-         s = *ps;
 
          relent->sym_ptr_ptr = ps;
        }
@@ -1450,7 +1511,7 @@ elf_slurp_reloc_table (bfd *abfd,
   return TRUE;
 }
 
-#ifdef DEBUG
+#if DEBUG & 2
 static void
 elf_debug_section (int num, Elf_Internal_Shdr *hdr)
 {
@@ -1476,7 +1537,9 @@ elf_debug_section (int num, Elf_Internal_Shdr *hdr)
           (long) hdr->sh_entsize);
   fflush (stderr);
 }
+#endif
 
+#if DEBUG & 1
 static void
 elf_debug_file (Elf_Internal_Ehdr *ehdrp)
 {
@@ -1488,77 +1551,6 @@ elf_debug_file (Elf_Internal_Ehdr *ehdrp)
   fprintf (stderr, "e_shnum      = %ld\n", (long) ehdrp->e_shnum);
   fprintf (stderr, "e_shentsize  = %ld\n", (long) ehdrp->e_shentsize);
 }
-
-static char *
-elf_symbol_flags (flagword flags)
-{
-  static char buffer[1024];
-
-  buffer[0] = '\0';
-  if (flags & BSF_LOCAL)
-    strcat (buffer, " local");
-
-  if (flags & BSF_GLOBAL)
-    strcat (buffer, " global");
-
-  if (flags & BSF_DEBUGGING)
-    strcat (buffer, " debug");
-
-  if (flags & BSF_FUNCTION)
-    strcat (buffer, " function");
-
-  if (flags & BSF_KEEP)
-    strcat (buffer, " keep");
-
-  if (flags & BSF_KEEP_G)
-    strcat (buffer, " keep_g");
-
-  if (flags & BSF_WEAK)
-    strcat (buffer, " weak");
-
-  if (flags & BSF_SECTION_SYM)
-    strcat (buffer, " section-sym");
-
-  if (flags & BSF_OLD_COMMON)
-    strcat (buffer, " old-common");
-
-  if (flags & BSF_NOT_AT_END)
-    strcat (buffer, " not-at-end");
-
-  if (flags & BSF_CONSTRUCTOR)
-    strcat (buffer, " constructor");
-
-  if (flags & BSF_WARNING)
-    strcat (buffer, " warning");
-
-  if (flags & BSF_INDIRECT)
-    strcat (buffer, " indirect");
-
-  if (flags & BSF_FILE)
-    strcat (buffer, " file");
-
-  if (flags & DYNAMIC)
-    strcat (buffer, " dynamic");
-
-  if (flags & ~(BSF_LOCAL
-               | BSF_GLOBAL
-               | BSF_DEBUGGING
-               | BSF_FUNCTION
-               | BSF_KEEP
-               | BSF_KEEP_G
-               | BSF_WEAK
-               | BSF_SECTION_SYM
-               | BSF_OLD_COMMON
-               | BSF_NOT_AT_END
-               | BSF_CONSTRUCTOR
-               | BSF_WARNING
-               | BSF_INDIRECT
-               | BSF_FILE
-               | BSF_DYNAMIC))
-    strcat (buffer, " unknown-bits");
-
-  return buffer;
-}
 #endif
 \f
 /* Create a new BFD as if by bfd_openr.  Rather than opening a file,
This page took 0.028305 seconds and 4 git commands to generate.