diff --git a/ChangeLog b/ChangeLog index 9a782a613..9633c838f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2007-02-20 Hollis Blanchard + + * 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 * kern/mm.c: Update copyright. diff --git a/include/grub/elfload.h b/include/grub/elfload.h index 7e17435d8..d4f44b8d2 100644 --- a/include/grub/elfload.h +++ b/include/grub/elfload.h @@ -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); diff --git a/kern/elf.c b/kern/elf.c index d10dca08d..4d616cc74 100644 --- a/kern/elf.c +++ b/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)) - 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; } @@ -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)) - 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; } @@ -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; } - - diff --git a/loader/powerpc/ieee1275/linux.c b/loader/powerpc/ieee1275/linux.c index 696e8ba01..3e37eafb2 100644 --- a/loader/powerpc/ieee1275/linux.c +++ b/loader/powerpc/ieee1275/linux.c @@ -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. */