2007-02-20 Hollis Blanchard <hollis@penguinppc.org>

* include/grub/elfload.h (grub_elf32_load_hook_t): Return grub_err_t.
	All users updated.
	(grub_elf64_load_hook_t): Likewise.
	* kern/elf.c: Call `grub_error_push' before `grub_error'. Improve
	debug output.
This commit is contained in:
hollisb 2007-02-20 22:46:12 +00:00
parent 3ce27299eb
commit 9b09e6fca0
4 changed files with 67 additions and 28 deletions

View file

@ -1,3 +1,11 @@
2007-02-20 Hollis Blanchard <hollis@penguinppc.org>
* include/grub/elfload.h (grub_elf32_load_hook_t): Return grub_err_t.
All users updated.
(grub_elf64_load_hook_t): Likewise.
* kern/elf.c: Call `grub_error_push' before `grub_error'. Improve
debug output.
2007-02-20 Hollis Blanchard <hollis@penguinppc.org> 2007-02-20 Hollis Blanchard <hollis@penguinppc.org>
* kern/mm.c: Update copyright. * kern/mm.c: Update copyright.

View file

@ -37,8 +37,10 @@ struct grub_elf_file
}; };
typedef struct grub_elf_file *grub_elf_t; typedef struct grub_elf_file *grub_elf_t;
typedef int (*grub_elf32_load_hook_t) (Elf32_Phdr *phdr, grub_addr_t *addr); typedef grub_err_t (*grub_elf32_load_hook_t)
typedef int (*grub_elf64_load_hook_t) (Elf64_Phdr *phdr, grub_addr_t *addr); (Elf32_Phdr *phdr, grub_addr_t *addr);
typedef grub_err_t (*grub_elf64_load_hook_t)
(Elf64_Phdr *phdr, grub_addr_t *addr);
grub_elf_t grub_elf_open (const char *); grub_elf_t grub_elf_open (const char *);
grub_elf_t grub_elf_file (grub_file_t); grub_elf_t grub_elf_file (grub_file_t);

View file

@ -75,6 +75,7 @@ grub_elf_file (grub_file_t file)
if (grub_file_read (elf->file, (char *) &elf->ehdr, sizeof (elf->ehdr)) if (grub_file_read (elf->file, (char *) &elf->ehdr, sizeof (elf->ehdr))
!= sizeof (elf->ehdr)) != sizeof (elf->ehdr))
{ {
grub_error_push ();
grub_error (GRUB_ERR_READ_ERROR, "Cannot read ELF header."); grub_error (GRUB_ERR_READ_ERROR, "Cannot read ELF header.");
goto fail; goto fail;
} }
@ -129,7 +130,10 @@ grub_elf32_load_phdrs (grub_elf_t elf)
if ((grub_file_seek (elf->file, elf->ehdr.ehdr32.e_phoff) == (grub_off_t) -1) if ((grub_file_seek (elf->file, elf->ehdr.ehdr32.e_phoff) == (grub_off_t) -1)
|| (grub_file_read (elf->file, elf->phdrs, phdrs_size) != phdrs_size)) || (grub_file_read (elf->file, elf->phdrs, phdrs_size) != phdrs_size))
{
grub_error_push ();
return grub_error (GRUB_ERR_READ_ERROR, "Cannot read program headers"); return grub_error (GRUB_ERR_READ_ERROR, "Cannot read program headers");
}
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
@ -150,10 +154,13 @@ grub_elf32_phdr_iterate (grub_elf_t elf,
for (i = 0; i < elf->ehdr.ehdr32.e_phnum; i++) for (i = 0; i < elf->ehdr.ehdr32.e_phnum; i++)
{ {
Elf32_Phdr *phdr = phdrs + i; Elf32_Phdr *phdr = phdrs + i;
grub_dprintf ("elf", "Segment %u: type 0x%x paddr 0x%lx memsz 0x%lx.\n", grub_dprintf ("elf",
"Segment %u: type 0x%x paddr 0x%lx memsz 0x%lx "
"filesz %lx\n",
i, phdr->p_type, i, phdr->p_type,
(unsigned long) phdr->p_paddr, (unsigned long) phdr->p_paddr,
(unsigned long) phdr->p_memsz); (unsigned long) phdr->p_memsz,
(unsigned long) phdr->p_filesz);
if (hook (elf, phdr, hook_arg)) if (hook (elf, phdr, hook_arg))
break; break;
} }
@ -230,20 +237,30 @@ grub_elf32_load (grub_elf_t _elf, grub_elf32_load_hook_t _load_hook,
if (load_addr < load_base) if (load_addr < load_base)
load_base = load_addr; load_base = load_addr;
grub_dprintf ("elf", "Loading segment at %llx, size 0x%llx\n", grub_dprintf ("elf", "Loading segment at 0x%llx, size 0x%llx\n",
(unsigned long long) load_addr, (unsigned long long) load_addr,
(unsigned long long) phdr->p_filesz); (unsigned long long) phdr->p_memsz);
if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1) if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1)
{ {
return grub_error (GRUB_ERR_BAD_OS, "Invalid offset in program header"); grub_error_push ();
return grub_error (GRUB_ERR_BAD_OS,
"Invalid offset in program header.");
} }
if (phdr->p_filesz if (phdr->p_filesz)
&& grub_file_read (elf->file, (void *) load_addr, phdr->p_filesz)
!= (grub_ssize_t) phdr->p_filesz)
{ {
return grub_error (GRUB_ERR_BAD_OS, "Couldn't load segment"); grub_ssize_t read;
read = grub_file_read (elf->file, (void *) load_addr, phdr->p_filesz);
if (read != (grub_ssize_t) phdr->p_filesz)
{
/* XXX How can we free memory from `load_hook'? */
grub_error_push ();
return grub_error (GRUB_ERR_BAD_OS,
"Couldn't read segment from file: "
"wanted 0x%lx bytes; read 0x%lx bytes.",
phdr->p_filesz, read);
}
} }
if (phdr->p_filesz < phdr->p_memsz) if (phdr->p_filesz < phdr->p_memsz)
@ -292,7 +309,10 @@ grub_elf64_load_phdrs (grub_elf_t elf)
if ((grub_file_seek (elf->file, elf->ehdr.ehdr64.e_phoff) == (grub_off_t) -1) if ((grub_file_seek (elf->file, elf->ehdr.ehdr64.e_phoff) == (grub_off_t) -1)
|| (grub_file_read (elf->file, elf->phdrs, phdrs_size) != phdrs_size)) || (grub_file_read (elf->file, elf->phdrs, phdrs_size) != phdrs_size))
{
grub_error_push ();
return grub_error (GRUB_ERR_READ_ERROR, "Cannot read program headers"); return grub_error (GRUB_ERR_READ_ERROR, "Cannot read program headers");
}
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
@ -313,10 +333,13 @@ grub_elf64_phdr_iterate (grub_elf_t elf,
for (i = 0; i < elf->ehdr.ehdr64.e_phnum; i++) for (i = 0; i < elf->ehdr.ehdr64.e_phnum; i++)
{ {
Elf64_Phdr *phdr = phdrs + i; Elf64_Phdr *phdr = phdrs + i;
grub_dprintf ("elf", "Segment %u: type 0x%x paddr 0x%lx memsz 0x%lx.\n", grub_dprintf ("elf",
"Segment %u: type 0x%x paddr 0x%lx memsz 0x%lx "
"filesz %lx\n",
i, phdr->p_type, i, phdr->p_type,
(unsigned long) phdr->p_paddr, (unsigned long) phdr->p_paddr,
(unsigned long) phdr->p_memsz); (unsigned long) phdr->p_memsz,
(unsigned long) phdr->p_filesz);
if (hook (elf, phdr, hook_arg)) if (hook (elf, phdr, hook_arg))
break; break;
} }
@ -393,20 +416,28 @@ grub_elf64_load (grub_elf_t _elf, grub_elf64_load_hook_t _load_hook,
if (load_addr < load_base) if (load_addr < load_base)
load_base = load_addr; load_base = load_addr;
grub_dprintf ("elf", "Loading segment at %llx, size 0x%llx\n", grub_dprintf ("elf", "Loading segment at 0x%llx, size 0x%llx\n",
(unsigned long long) load_addr, (unsigned long long) load_addr,
(unsigned long long) phdr->p_filesz); (unsigned long long) phdr->p_memsz);
if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1) if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1)
{ {
return grub_error (GRUB_ERR_BAD_OS, "Invalid offset in program header"); grub_error_push ();
return grub_error (GRUB_ERR_BAD_OS,
"Invalid offset in program header.");
} }
if (phdr->p_filesz if (phdr->p_filesz)
&& grub_file_read (elf->file, (void *) load_addr, phdr->p_filesz)
!= (grub_ssize_t) phdr->p_filesz)
{ {
return grub_error (GRUB_ERR_BAD_OS, "Couldn't load segment"); grub_ssize_t read;
read = grub_file_read (elf->file, (void *) load_addr, phdr->p_filesz);
if (read != (grub_ssize_t) phdr->p_filesz)
/* XXX How can we free memory from `load_hook'? */
grub_error_push ();
return grub_error (GRUB_ERR_BAD_OS,
"Couldn't read segment from file: "
"wanted 0x%lx bytes; read 0x%lx bytes.",
phdr->p_filesz, read);
} }
if (phdr->p_filesz < phdr->p_memsz) if (phdr->p_filesz < phdr->p_memsz)
@ -427,5 +458,3 @@ grub_elf64_load (grub_elf_t _elf, grub_elf64_load_hook_t _load_hook,
return err; return err;
} }

View file

@ -132,8 +132,8 @@ grub_linux_load32 (grub_elf_t elf)
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "Could not claim memory."); return grub_error (GRUB_ERR_OUT_OF_MEMORY, "Could not claim memory.");
/* Now load the segments into the area we claimed. */ /* Now load the segments into the area we claimed. */
auto int offset_phdr (Elf32_Phdr *phdr, grub_addr_t *addr); auto grub_err_t offset_phdr (Elf32_Phdr *phdr, grub_addr_t *addr);
int offset_phdr (Elf32_Phdr *phdr, grub_addr_t *addr) grub_err_t offset_phdr (Elf32_Phdr *phdr, grub_addr_t *addr)
{ {
/* Linux's program headers incorrectly contain virtual addresses. /* Linux's program headers incorrectly contain virtual addresses.
* Translate those to physical, and offset to the area we claimed. */ * Translate those to physical, and offset to the area we claimed. */
@ -175,8 +175,8 @@ grub_linux_load64 (grub_elf_t elf)
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "Could not claim memory."); return grub_error (GRUB_ERR_OUT_OF_MEMORY, "Could not claim memory.");
/* Now load the segments into the area we claimed. */ /* Now load the segments into the area we claimed. */
auto int offset_phdr (Elf64_Phdr *phdr, grub_addr_t *addr); auto grub_err_t offset_phdr (Elf64_Phdr *phdr, grub_addr_t *addr);
int offset_phdr (Elf64_Phdr *phdr, grub_addr_t *addr) grub_err_t offset_phdr (Elf64_Phdr *phdr, grub_addr_t *addr)
{ {
/* Linux's program headers incorrectly contain virtual addresses. /* Linux's program headers incorrectly contain virtual addresses.
* Translate those to physical, and offset to the area we claimed. */ * Translate those to physical, and offset to the area we claimed. */