"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.
This commit is contained in:
peter 1998-10-16 03:04:15 +00:00
parent 9ed6de7bdd
commit aaea4c752d

View File

@ -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 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off,
free(dp);
if (shdr)
free(shdr);
if (phdr)
free(phdr);
return ret;
}