daily update
[deliverable/binutils-gdb.git] / bfd / elfcode.h
index 87b2663551b6c5ad7be2ea802d7fa44c2aa7e6e2..a285a133088321287e98baf78eb83222c8242ba2 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
@@ -28,12 +28,12 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 /* Problems and other issues to resolve.
 
    (1) BFD expects there to be some fixed number of "sections" in
-        the object file.  I.E. there is a "section_count" variable in the
+       the object file.  I.E. there is a "section_count" variable in the
        bfd structure which contains the number of sections.  However, ELF
        supports multiple "views" of a file.  In particular, with current
        implementations, executable files typically have two tables, a
@@ -139,10 +139,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 */
@@ -458,6 +459,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.
 
@@ -545,7 +565,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)
@@ -607,13 +627,15 @@ elf_object_p (bfd *abfd)
        goto got_no_match;
     }
 
-  /* Remember the entry point specified in the ELF file header.  */
-  bfd_set_start_address (abfd, i_ehdrp->e_entry);
-
   if (i_ehdrp->e_shoff != 0)
     {
+      bfd_signed_vma where = i_ehdrp->e_shoff;
+
+      if (where != (file_ptr) where)
+       goto got_wrong_format_error;
+
       /* Seek to the section header table in the file.  */
-      if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET) != 0)
+      if (bfd_seek (abfd, (file_ptr) where, SEEK_SET) != 0)
        goto got_no_match;
 
       /* Read the first section header at index 0, and convert to internal
@@ -625,11 +647,46 @@ elf_object_p (bfd *abfd)
       /* If the section count is zero, the actual count is in the first
         section header.  */
       if (i_ehdrp->e_shnum == SHN_UNDEF)
-       i_ehdrp->e_shnum = i_shdr.sh_size;
+       {
+         i_ehdrp->e_shnum = i_shdr.sh_size;
+         if (i_ehdrp->e_shnum != i_shdr.sh_size
+             || i_ehdrp->e_shnum == 0)
+           goto got_wrong_format_error;
+       }
 
       /* And similarly for the string table index.  */
       if (i_ehdrp->e_shstrndx == SHN_XINDEX)
-       i_ehdrp->e_shstrndx = i_shdr.sh_link;
+       {
+         i_ehdrp->e_shstrndx = i_shdr.sh_link;
+         if (i_ehdrp->e_shstrndx != i_shdr.sh_link)
+           goto got_wrong_format_error;
+       }
+
+      /* Sanity check that we can read all of the section headers.
+        It ought to be good enough to just read the last one.  */
+      if (i_ehdrp->e_shnum != 1)
+       {
+         /* Check that we don't have a totally silly number of sections.  */
+         if (i_ehdrp->e_shnum > (unsigned int) -1 / sizeof (x_shdr)
+             || i_ehdrp->e_shnum > (unsigned int) -1 / sizeof (i_shdr))
+           goto got_wrong_format_error;
+
+         where += (i_ehdrp->e_shnum - 1) * sizeof (x_shdr);
+         if (where != (file_ptr) where)
+           goto got_wrong_format_error;
+         if ((bfd_size_type) where <= i_ehdrp->e_shoff)
+           goto got_wrong_format_error;
+
+         if (bfd_seek (abfd, (file_ptr) where, SEEK_SET) != 0)
+           goto got_no_match;
+         if (bfd_bread (&x_shdr, sizeof x_shdr, abfd) != sizeof (x_shdr))
+           goto got_no_match;
+
+         /* Back to where we were.  */
+         where = i_ehdrp->e_shoff + sizeof (x_shdr);
+         if (bfd_seek (abfd, (file_ptr) where, SEEK_SET) != 0)
+           goto got_no_match;
+       }
     }
 
   /* Allocate space for a copy of the section header table in
@@ -673,6 +730,16 @@ elf_object_p (bfd *abfd)
            goto got_no_match;
          elf_swap_shdr_in (abfd, &x_shdr, i_shdrp + shindex);
 
+         /* Sanity check sh_link and sh_info.  */
+         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)
+             && ! 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
             D_PAGED.  */
          if (i_shdrp[shindex].sh_size != 0
@@ -685,6 +752,24 @@ elf_object_p (bfd *abfd)
        }
     }
 
+  /* A further sanity check.  */
+  if (i_ehdrp->e_shnum != 0)
+    {
+      if (! valid_section_index_p (i_ehdrp->e_shstrndx, elf_numsections (abfd)))
+       {
+         /* PR 2257:
+            We used to just goto got_wrong_format_error here
+            but there are binaries in existance for which this test
+            will prevent the binutils from working with them at all.
+            So we are kind, and reset the string index value to 0
+            so that at least some processing can be done.  */
+         i_ehdrp->e_shstrndx = SHN_UNDEF;
+         _bfd_error_handler (_("warning: %s has a corrupt string table index - ignoring"), abfd->filename);
+       }
+    }
+  else if (i_ehdrp->e_shstrndx != SHN_UNDEF)
+    goto got_wrong_format_error;
+
   /* Read in the program headers.  */
   if (i_ehdrp->e_phnum == 0)
     elf_tdata (abfd)->phdr = NULL;
@@ -726,8 +811,8 @@ elf_object_p (bfd *abfd)
            shindex += SHN_HIRESERVE + 1 - SHN_LORESERVE;
        }
 
-      /* Set up group pointers.  */
-      if (! _bfd_elf_setup_group_pointers (abfd))
+      /* Set up ELF sections for SHF_GROUP and SHF_LINK_ORDER.  */
+      if (! _bfd_elf_setup_sections (abfd))
        goto got_wrong_format_error;
     }
 
@@ -739,6 +824,9 @@ elf_object_p (bfd *abfd)
        goto got_wrong_format_error;
     }
 
+  /* Remember the entry point specified in the ELF file header.  */
+  bfd_set_start_address (abfd, i_ehdrp->e_entry);
+
   /* If we have created any reloc sections that are associated with
      debugging sections, mark the reloc sections as debugging as well.  */
   for (s = abfd->sections; s != NULL; s = s->next)
@@ -810,6 +898,12 @@ elf_write_relocs (bfd *abfd, asection *sec, void *data)
   if (sec->reloc_count == 0)
     return;
 
+  /* If we have opened an existing file for update, reloc_count may be
+     set even though we are not linking.  In that case we have nothing
+     to do.  */
+  if (sec->orelocation == NULL)
+    return;
+
   rela_hdr = &elf_section_data (sec)->rel_hdr;
 
   rela_hdr->sh_size = rela_hdr->sh_entsize * sec->reloc_count;
@@ -1042,7 +1136,7 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic)
             symcount);
 
          /* Slurp in the symbols without the version information,
-             since that is more helpful than just quitting.  */
+            since that is more helpful than just quitting.  */
          verhdr = NULL;
        }
 
@@ -1069,7 +1163,7 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic)
          memcpy (&sym->internal_elf_sym, isym, sizeof (Elf_Internal_Sym));
          sym->symbol.the_bfd = abfd;
 
-         sym->symbol.name = bfd_elf_sym_name (abfd, hdr, isym);
+         sym->symbol.name = bfd_elf_sym_name (abfd, hdr, isym, NULL);
 
          sym->symbol.value = isym->st_value;
 
@@ -1107,7 +1201,7 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic)
            sym->symbol.section = bfd_abs_section_ptr;
 
          /* If this is a relocatable file, then the symbol value is
-             already section relative.  */
+            already section relative.  */
          if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
            sym->symbol.value -= sym->symbol.section->vma;
 
@@ -1269,10 +1363,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;
        }
@@ -1370,7 +1463,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)
 {
@@ -1396,7 +1489,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)
 {
@@ -1408,77 +1503,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,
@@ -1499,7 +1523,7 @@ NAME(_bfd_elf,bfd_from_remote_memory)
   (bfd *templ,
    bfd_vma ehdr_vma,
    bfd_vma *loadbasep,
-   int (*target_read_memory) (bfd_vma, char *, int))
+   int (*target_read_memory) (bfd_vma, bfd_byte *, int))
 {
   Elf_External_Ehdr x_ehdr;    /* Elf file header, external form */
   Elf_Internal_Ehdr i_ehdr;    /* Elf file header, internal form */
@@ -1508,13 +1532,13 @@ NAME(_bfd_elf,bfd_from_remote_memory)
   bfd *nbfd;
   struct bfd_in_memory *bim;
   int contents_size;
-  char *contents;
+  bfd_byte *contents;
   int err;
   unsigned int i;
   bfd_vma loadbase;
 
   /* Read in the ELF header in external format.  */
-  err = target_read_memory (ehdr_vma, (char *) &x_ehdr, sizeof x_ehdr);
+  err = target_read_memory (ehdr_vma, (bfd_byte *) &x_ehdr, sizeof x_ehdr);
   if (err)
     {
       bfd_set_error (bfd_error_system_call);
@@ -1574,7 +1598,7 @@ NAME(_bfd_elf,bfd_from_remote_memory)
       bfd_set_error (bfd_error_no_memory);
       return NULL;
     }
-  err = target_read_memory (ehdr_vma + i_ehdr.e_phoff, (char *) x_phdrs,
+  err = target_read_memory (ehdr_vma + i_ehdr.e_phoff, (bfd_byte *) x_phdrs,
                            i_ehdr.e_phnum * sizeof x_phdrs[0]);
   if (err)
     {
@@ -1591,7 +1615,10 @@ NAME(_bfd_elf,bfd_from_remote_memory)
   for (i = 0; i < i_ehdr.e_phnum; ++i)
     {
       elf_swap_phdr_in (templ, &x_phdrs[i], &i_phdrs[i]);
-      if (i_phdrs[i].p_type == PT_LOAD)
+      /* IA-64 vDSO may have two mappings for one segment, where one mapping
+        is executable only, and one is read only.  We must not use the
+        executable one.  */
+      if (i_phdrs[i].p_type == PT_LOAD && (i_phdrs[i].p_flags & PF_R))
        {
          bfd_vma segment_end;
          segment_end = (i_phdrs[i].p_offset + i_phdrs[i].p_filesz
@@ -1638,7 +1665,10 @@ NAME(_bfd_elf,bfd_from_remote_memory)
     }
 
   for (i = 0; i < i_ehdr.e_phnum; ++i)
-    if (i_phdrs[i].p_type == PT_LOAD)
+    /* IA-64 vDSO may have two mappings for one segment, where one mapping
+       is executable only, and one is read only.  We must not use the
+       executable one.  */
+    if (i_phdrs[i].p_type == PT_LOAD && (i_phdrs[i].p_flags & PF_R))
       {
        bfd_vma start = i_phdrs[i].p_offset & -i_phdrs[i].p_align;
        bfd_vma end = (i_phdrs[i].p_offset + i_phdrs[i].p_filesz
This page took 0.03059 seconds and 4 git commands to generate.