Blob Blame History Raw
2007-09-23  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* elfcode.h (NAME(_bfd_elf,bfd_from_remote_memory)): New variables
	X_SHDR_SHSTRTAB and I_SHDR_SHSTRTAB.  Fixed the CONTENTS_SIZE trimming
	check for its aligned size between the last segment and still before
	the section header end.  Added variables check to cover also the
	section header string table.

--- gdb-7.4.50.20120120-orig/bfd/elfcode.h	2012-02-29 09:17:08.000000000 +0100
+++ gdb-7.4.50.20120120/bfd/elfcode.h	2012-02-29 10:23:03.000000000 +0100
@@ -1621,6 +1621,8 @@ NAME(_bfd_elf,bfd_from_remote_memory)
   Elf_Internal_Ehdr i_ehdr;	/* Elf file header, internal form */
   Elf_External_Phdr *x_phdrs;
   Elf_Internal_Phdr *i_phdrs, *last_phdr;
+  Elf_External_Shdr *x_shdrs;
+  Elf_Internal_Shdr *i_shdrs;
   bfd *nbfd;
   struct bfd_in_memory *bim;
   int contents_size;
@@ -1740,24 +1742,46 @@ NAME(_bfd_elf,bfd_from_remote_memory)
 
   /* Trim the last segment so we don't bother with zeros in the last page
      that are off the end of the file.  However, if the extra bit in that
-     page includes the section headers, keep them.  */
-  if ((bfd_vma) contents_size > last_phdr->p_offset + last_phdr->p_filesz
-      && (bfd_vma) contents_size >= (i_ehdr.e_shoff
-				     + i_ehdr.e_shnum * i_ehdr.e_shentsize))
+     page includes the section headers os the section header string table,
+     keep them.  */
+  if ((bfd_vma) contents_size > last_phdr->p_offset + last_phdr->p_filesz)
+    contents_size = last_phdr->p_offset + last_phdr->p_filesz;
+
+  if ((bfd_vma) contents_size < i_ehdr.e_shoff
+				+ i_ehdr.e_shnum * i_ehdr.e_shentsize)
+    contents_size = i_ehdr.e_shoff + i_ehdr.e_shnum * i_ehdr.e_shentsize;
+
+  /* Verify also all the sections fit into CONTENTS_SIZE.  */
+
+  x_shdrs = bfd_malloc (i_ehdr.e_shnum * (sizeof *x_shdrs + sizeof *i_shdrs));
+  if (x_shdrs == NULL)
     {
-      contents_size = last_phdr->p_offset + last_phdr->p_filesz;
-      if ((bfd_vma) contents_size < (i_ehdr.e_shoff
-				     + i_ehdr.e_shnum * i_ehdr.e_shentsize))
-	contents_size = i_ehdr.e_shoff + i_ehdr.e_shnum * i_ehdr.e_shentsize;
+      free (x_phdrs);
+      bfd_set_error (bfd_error_no_memory);
+      return NULL;
     }
+  err = target_read_memory (ehdr_vma + i_ehdr.e_shoff, (bfd_byte *) x_shdrs,
+			    i_ehdr.e_shnum * sizeof *x_shdrs);
+  if (err)
+    i_shdrs = NULL;
   else
-    contents_size = last_phdr->p_offset + last_phdr->p_filesz;
+    {
+      i_shdrs = (Elf_Internal_Shdr *) &x_shdrs[i_ehdr.e_shnum];
+      for (i = 0; i < i_ehdr.e_shnum; ++i)
+	{
+	  elf_swap_shdr_in (templ, &x_shdrs[i], &i_shdrs[i]);
+
+	  if ((bfd_vma) contents_size < i_shdrs[i].sh_offset + i_shdrs[i].sh_size)
+	    contents_size = i_shdrs[i].sh_offset + i_shdrs[i].sh_size;
+	}
+    }
 
   /* Now we know the size of the whole image we want read in.  */
   contents = (bfd_byte *) bfd_zmalloc (contents_size);
   if (contents == NULL)
     {
       free (x_phdrs);
+      free (x_shdrs);
       bfd_set_error (bfd_error_no_memory);
       return NULL;
     }
@@ -1776,6 +1800,7 @@ NAME(_bfd_elf,bfd_from_remote_memory)
 	if (err)
 	  {
 	    free (x_phdrs);
+	    free (x_shdrs);
 	    free (contents);
 	    bfd_set_error (bfd_error_system_call);
 	    errno = err;
@@ -1784,10 +1809,32 @@ NAME(_bfd_elf,bfd_from_remote_memory)
       }
   free (x_phdrs);
 
-  /* If the segments visible in memory didn't include the section headers,
+  if (i_shdrs)
+    {
+      memcpy (contents + i_ehdr.e_shoff, x_shdrs,
+	      i_ehdr.e_shnum * sizeof *x_shdrs);
+
+      for (i = 0; i < i_ehdr.e_shnum; ++i)
+	{
+	  bfd_vma start = i_shdrs[i].sh_offset;
+	  bfd_vma end = i_shdrs[i].sh_offset + i_shdrs[i].sh_size;
+
+	  if (end > (bfd_vma) contents_size)
+	    end = contents_size;
+	  err = target_read_memory (ehdr_vma + start, contents + start,
+				    end - start);
+	  if (err)
+	    {
+	      i_shdrs = NULL;
+	      break;
+	    }
+	}
+    }
+  free (x_shdrs);
+
+  /* If the segments readable in memory didn't include the section headers,
      then clear them from the file header.  */
-  if ((bfd_vma) contents_size < (i_ehdr.e_shoff
-				 + i_ehdr.e_shnum * i_ehdr.e_shentsize))
+  if (i_shdrs == NULL)
     {
       memset (&x_ehdr.e_shoff, 0, sizeof x_ehdr.e_shoff);
       memset (&x_ehdr.e_shnum, 0, sizeof x_ehdr.e_shnum);