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>
|
2007-02-20 Hollis Blanchard <hollis@penguinppc.org>
|
||||||
|
|
||||||
* kern/mm.c: Update copyright.
|
* kern/mm.c: Update copyright.
|
||||||
|
|
|
@ -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);
|
||||||
|
|
73
kern/elf.c
73
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))
|
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))
|
||||||
return grub_error (GRUB_ERR_READ_ERROR, "Cannot read program headers");
|
{
|
||||||
|
grub_error_push ();
|
||||||
|
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))
|
||||||
return grub_error (GRUB_ERR_READ_ERROR, "Cannot read program headers");
|
{
|
||||||
|
grub_error_push ();
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
Loading…
Reference in a new issue