diff options
author | peter <peter@FreeBSD.org> | 1998-10-16 03:04:15 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1998-10-16 03:04:15 +0000 |
commit | a8354e7057ecc1506a7ee2d57e04b8e3b63bc8e0 (patch) | |
tree | ad069f71dd229b63d256bd22730d0c8884501fd1 /sys/boot/common | |
parent | d7cc2cb36c77a91d19922907e0bbb6941b4821a2 (diff) | |
download | FreeBSD-src-a8354e7057ecc1506a7ee2d57e04b8e3b63bc8e0.zip FreeBSD-src-a8354e7057ecc1506a7ee2d57e04b8e3b63bc8e0.tar.gz |
"fix" the gzipped kernel load problem by having the loader check that it
can seek back to the first PT_LOAD and doing a close/reopen if it cannot.
This is because the first PT_LOAD section includes the ELF headers.
This fixes gzipped kernels on the i386, it should solve mike's problem
for the Alpha.
Diffstat (limited to 'sys/boot/common')
-rw-r--r-- | sys/boot/common/load_elf.c | 55 |
1 files changed, 33 insertions, 22 deletions
diff --git a/sys/boot/common/load_elf.c b/sys/boot/common/load_elf.c index e29996b..b2b38c7 100644 --- a/sys/boot/common/load_elf.c +++ b/sys/boot/common/load_elf.c @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: load_elf.c,v 1.6 1998/10/14 00:41:17 peter Exp $ + * $Id: load_elf.c,v 1.7 1998/10/15 21:56:47 dfr Exp $ */ #include <sys/param.h> @@ -40,7 +40,7 @@ #include "bootstrap.h" -static int elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t loadaddr, Elf_Ehdr *ehdr, int kernel); +static int elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t loadaddr, Elf_Ehdr *ehdr, Elf_Phdr *phdr, int kernel); char *elf_kerneltype = "elf kernel"; char *elf_moduletype = "elf module"; @@ -55,12 +55,14 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) { struct loaded_module *mp, *kmp; Elf_Ehdr ehdr; + Elf_Phdr *phdr; int fd; int err, kernel; u_int pad; char *s; mp = NULL; + phdr = NULL; /* * Open the image, read and validate the ELF header @@ -162,7 +164,31 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) printf("%s ", filename); #endif - mp->m_size = elf_loadimage(mp, fd, dest, &ehdr, kernel); + phdr = malloc(ehdr.e_phnum * sizeof(*phdr)); + if (phdr == NULL) { + err = ENOMEM; + goto out; + } + + if (lseek(fd, ehdr.e_phoff, SEEK_SET) == -1) { + printf("elf_loadexec: lseek for phdr failed\n"); + goto ioerr; + } + if (read(fd, phdr, ehdr.e_phnum * sizeof(*phdr)) != + ehdr.e_phnum * sizeof(*phdr)) { + printf("elf_loadmodule: cannot read program header\n"); + goto ioerr; + } + if (lseek(fd, 0, SEEK_SET) == -1) { + close(fd); + if ((fd = open(filename, O_RDONLY)) == -1) { + printf("elf_loadmodule: cannot reset file position\n"); + mod_discard(mp); + return errno; + } + } + + mp->m_size = elf_loadimage(mp, fd, dest, &ehdr, phdr, kernel); if (mp->m_size == 0 || mp->m_addr == 0) goto ioerr; @@ -179,6 +205,8 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) oerr: mod_discard(mp); out: + if (phdr) + free(phdr); close(fd); return(err); } @@ -189,10 +217,9 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) */ static int elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off, - Elf_Ehdr *ehdr, int kernel) + Elf_Ehdr *ehdr, Elf_Phdr *phdr, int kernel) { int i, j; - Elf_Phdr *phdr; Elf_Shdr *shdr; int ret; vm_offset_t firstaddr; @@ -225,20 +252,6 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off, #endif } - phdr = malloc(ehdr->e_phnum * sizeof(*phdr)); - if (phdr == NULL) - goto out; - - if (lseek(fd, ehdr->e_phoff, SEEK_SET) == -1) { - printf("elf_loadexec: lseek for phdr failed\n"); - goto out; - } - if (read(fd, phdr, ehdr->e_phnum * sizeof(*phdr)) != - ehdr->e_phnum * sizeof(*phdr)) { - printf("elf_loadexec: cannot read program header\n"); - goto out; - } - for (i = 0; i < ehdr->e_phnum; i++) { /* We want to load PT_LOAD segments only.. */ if (phdr[i].p_type != PT_LOAD) @@ -379,7 +392,7 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off, #else if (i == symstrindex) printf("+"); - printf("0x%lx+0x%lx", sizeof(size), size); + printf("0x%lx+0x%lx", (long)sizeof(size), size); #endif if (lseek(fd, shdr[i].sh_offset, SEEK_SET) == -1) { @@ -503,7 +516,5 @@ out: free(dp); if (shdr) free(shdr); - if (phdr) - free(phdr); return ret; } |