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:
parent
3ce27299eb
commit
9b09e6fca0
4 changed files with 67 additions and 28 deletions
|
@ -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>
|
||||
|
||||
* kern/mm.c: Update copyright.
|
||||
|
|
|
@ -37,8 +37,10 @@ struct grub_elf_file
|
|||
};
|
||||
typedef struct grub_elf_file *grub_elf_t;
|
||||
|
||||
typedef int (*grub_elf32_load_hook_t) (Elf32_Phdr *phdr, grub_addr_t *addr);
|
||||
typedef int (*grub_elf64_load_hook_t) (Elf64_Phdr *phdr, grub_addr_t *addr);
|
||||
typedef grub_err_t (*grub_elf32_load_hook_t)
|
||||
(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_file (grub_file_t);
|
||||
|
|
69
kern/elf.c
69
kern/elf.c
|
@ -75,6 +75,7 @@ grub_elf_file (grub_file_t file)
|
|||
if (grub_file_read (elf->file, (char *) &elf->ehdr, sizeof (elf->ehdr))
|
||||
!= sizeof (elf->ehdr))
|
||||
{
|
||||
grub_error_push ();
|
||||
grub_error (GRUB_ERR_READ_ERROR, "Cannot read ELF header.");
|
||||
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)
|
||||
|| (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_ERR_NONE;
|
||||
}
|
||||
|
@ -150,10 +154,13 @@ grub_elf32_phdr_iterate (grub_elf_t elf,
|
|||
for (i = 0; i < elf->ehdr.ehdr32.e_phnum; 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,
|
||||
(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))
|
||||
break;
|
||||
}
|
||||
|
@ -230,20 +237,30 @@ grub_elf32_load (grub_elf_t _elf, grub_elf32_load_hook_t _load_hook,
|
|||
if (load_addr < load_base)
|
||||
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) phdr->p_filesz);
|
||||
(unsigned long long) phdr->p_memsz);
|
||||
|
||||
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
|
||||
&& grub_file_read (elf->file, (void *) load_addr, phdr->p_filesz)
|
||||
!= (grub_ssize_t) phdr->p_filesz)
|
||||
if (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)
|
||||
|
@ -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)
|
||||
|| (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_ERR_NONE;
|
||||
}
|
||||
|
@ -313,10 +333,13 @@ grub_elf64_phdr_iterate (grub_elf_t elf,
|
|||
for (i = 0; i < elf->ehdr.ehdr64.e_phnum; 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,
|
||||
(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))
|
||||
break;
|
||||
}
|
||||
|
@ -393,20 +416,28 @@ grub_elf64_load (grub_elf_t _elf, grub_elf64_load_hook_t _load_hook,
|
|||
if (load_addr < load_base)
|
||||
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) phdr->p_filesz);
|
||||
(unsigned long long) phdr->p_memsz);
|
||||
|
||||
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
|
||||
&& grub_file_read (elf->file, (void *) load_addr, phdr->p_filesz)
|
||||
!= (grub_ssize_t) phdr->p_filesz)
|
||||
if (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)
|
||||
|
@ -427,5 +458,3 @@ grub_elf64_load (grub_elf_t _elf, grub_elf64_load_hook_t _load_hook,
|
|||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -132,8 +132,8 @@ grub_linux_load32 (grub_elf_t elf)
|
|||
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "Could not claim memory.");
|
||||
|
||||
/* Now load the segments into the area we claimed. */
|
||||
auto int offset_phdr (Elf32_Phdr *phdr, grub_addr_t *addr);
|
||||
int offset_phdr (Elf32_Phdr *phdr, grub_addr_t *addr)
|
||||
auto grub_err_t 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.
|
||||
* 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.");
|
||||
|
||||
/* Now load the segments into the area we claimed. */
|
||||
auto int offset_phdr (Elf64_Phdr *phdr, grub_addr_t *addr);
|
||||
int offset_phdr (Elf64_Phdr *phdr, grub_addr_t *addr)
|
||||
auto grub_err_t 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.
|
||||
* Translate those to physical, and offset to the area we claimed. */
|
||||
|
|
Loading…
Reference in a new issue