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