[2037] 2009-03-21 Vladimir Serbinenko <[email protected]>

Robert Millan <[email protected]>
Newsgroups gmane.comp.boot-loaders.grub.cvs
Message-ID <[email protected]>
Revision: 2037
          http://svn.sv.gnu.org/viewvc/?view=rev&root=grub&revision=2037
Author:   robertmh
Date:     2009-03-21 23:02:12 +0000 (Sat, 21 Mar 2009)
Log Message:
-----------
2009-03-21  Vladimir Serbinenko  <[email protected]>

        Bugfixes in multiboot for bugs uncovered by solaris kernel.

        * loader/i386/multiboot_elfxx.c (grub_multiboot_load_elf): Corrected
        limit detection.
        Use vaddr of correct segment for entry_point.

Modified Paths:
--------------
    trunk/grub2/ChangeLog
    trunk/grub2/loader/i386/multiboot_elfxx.c

Modified: trunk/grub2/ChangeLog
===================================================================
--- trunk/grub2/ChangeLog	2009-03-21 08:39:59 UTC (rev 2036)
+++ trunk/grub2/ChangeLog	2009-03-21 23:02:12 UTC (rev 2037)
@@ -1,3 +1,11 @@
+2009-03-21  Vladimir Serbinenko  <[email protected]>
+
+	Bugfixes in multiboot for bugs uncovered by solaris kernel.
+
+	* loader/i386/multiboot_elfxx.c (grub_multiboot_load_elf): Corrected
+	limit detection.
+	Use vaddr of correct segment for entry_point.
+
 2009-03-21  Bean  <[email protected]>
 
 	* commands/blocklist.c: Add include file <grub/command.h>, remove

Modified: trunk/grub2/loader/i386/multiboot_elfxx.c
===================================================================
--- trunk/grub2/loader/i386/multiboot_elfxx.c	2009-03-21 08:39:59 UTC (rev 2036)
+++ trunk/grub2/loader/i386/multiboot_elfxx.c	2009-03-21 23:02:12 UTC (rev 2037)
@@ -49,7 +49,7 @@
 {
   Elf_Ehdr *ehdr = (Elf_Ehdr *) buffer;
   char *phdr_base;
-  int lowest_segment = 0, highest_segment = 0;
+  int lowest_segment = -1, highest_segment = -1;
   int i;
 
   if (ehdr->e_ident[EI_CLASS] != ELFCLASSXX)
@@ -83,11 +83,18 @@
   for (i = 0; i < ehdr->e_phnum; i++)
     if (phdr(i)->p_type == PT_LOAD && phdr(i)->p_filesz != 0)
       {
-	if (phdr(i)->p_paddr < phdr(lowest_segment)->p_paddr)
+	/* Beware that segment 0 isn't necessarily loadable */
+	if (lowest_segment == -1 
+	    || phdr(i)->p_paddr < phdr(lowest_segment)->p_paddr)
 	  lowest_segment = i;
-	if (phdr(i)->p_paddr > phdr(highest_segment)->p_paddr)
+	if (highest_segment == -1
+	    || phdr(i)->p_paddr > phdr(highest_segment)->p_paddr)
 	  highest_segment = i;
       }
+
+  if (lowest_segment == -1)
+    return grub_error (GRUB_ERR_BAD_OS, "ELF contains no loadable segments");
+
   code_size = (phdr(highest_segment)->p_paddr + phdr(highest_segment)->p_memsz) - phdr(lowest_segment)->p_paddr;
   grub_multiboot_payload_dest = phdr(lowest_segment)->p_paddr;
 
@@ -105,8 +112,8 @@
         {
 	  char *load_this_module_at = (char *) (grub_multiboot_payload_orig + (long) (phdr(i)->p_paddr - phdr(lowest_segment)->p_paddr));
 
-	  grub_dprintf ("multiboot_loader", "segment %d: paddr=0x%lx, memsz=0x%lx\n",
-			i, (long) phdr(i)->p_paddr, (long) phdr(i)->p_memsz);
+	  grub_dprintf ("multiboot_loader", "segment %d: paddr=0x%lx, memsz=0x%lx, vaddr=0x%lx\n",
+			i, (long) phdr(i)->p_paddr, (long) phdr(i)->p_memsz, (long) phdr(i)->p_vaddr);
 
 	  if (grub_file_seek (file, (grub_off_t) phdr(i)->p_offset)
 	      == (grub_off_t) -1)
@@ -124,8 +131,18 @@
         }
     }
 
-  grub_multiboot_payload_entry_offset = ehdr->e_entry - phdr(lowest_segment)->p_vaddr;
+  for (i = 0; i < ehdr->e_phnum; i++)
+    if (phdr(i)->p_vaddr <= ehdr->e_entry 
+	&& phdr(i)->p_vaddr + phdr(i)->p_memsz > ehdr->e_entry)
+      {
+	grub_multiboot_payload_entry_offset = (ehdr->e_entry - phdr(i)->p_vaddr)
+	  + (phdr(i)->p_paddr  - phdr(lowest_segment)->p_paddr);
+	break;
+      }
 
+  if (i == ehdr->e_phnum)
+    return grub_error (GRUB_ERR_BAD_OS, "entry point isn't in a segment");
+
 #undef phdr
 
   return grub_errno;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.