Add a few helper functions for zeroing kernel space and reading

from specified file offsets. Make use of these in load_elf.c.
This commit is contained in:
Ian Dowse 2004-08-28 14:57:34 +00:00
parent a53b524bb4
commit c0b43624d5
3 changed files with 82 additions and 37 deletions

View File

@ -76,6 +76,9 @@ char *unargv(int argc, char *argv[]);
void hexdump(caddr_t region, size_t len);
size_t strlenout(vm_offset_t str);
char *strdupout(vm_offset_t str);
void kern_bzero(vm_offset_t dest, size_t len);
int kern_pread(int fd, vm_offset_t dest, size_t len, off_t off);
void *alloc_pread(int fd, off_t off, size_t len);
/* bcache.c */
int bcache_init(u_int nblks, size_t bsize);

View File

@ -241,10 +241,8 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off)
int ret;
vm_offset_t firstaddr;
vm_offset_t lastaddr;
void *buf;
size_t resid, chunk;
size_t chunk;
ssize_t result;
vm_offset_t dest;
Elf_Addr ssym, esym;
Elf_Dyn *dp;
Elf_Addr adp;
@ -305,14 +303,10 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off)
phdr[i].p_vaddr + off, fpcopy);
}
if (phdr[i].p_filesz > fpcopy) {
if (lseek(ef->fd, (off_t)(phdr[i].p_offset + fpcopy),
SEEK_SET) == -1) {
printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadexec: cannot seek\n");
goto out;
}
if (archsw.arch_readin(ef->fd, phdr[i].p_vaddr + off + fpcopy,
phdr[i].p_filesz - fpcopy) != (ssize_t)(phdr[i].p_filesz - fpcopy)) {
printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadexec: archsw.readin failed\n");
if (kern_pread(ef->fd, phdr[i].p_vaddr + off + fpcopy,
phdr[i].p_filesz - fpcopy, phdr[i].p_offset + fpcopy) != 0) {
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
"_loadimage: read failed\n");
goto out;
}
}
@ -324,22 +318,8 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off)
(long)(phdr[i].p_vaddr + off + phdr[i].p_memsz - 1));
#endif
/* no archsw.arch_bzero */
buf = malloc(PAGE_SIZE);
if (buf == NULL) {
printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: malloc() failed\n");
goto out;
}
bzero(buf, PAGE_SIZE);
resid = phdr[i].p_memsz - phdr[i].p_filesz;
dest = phdr[i].p_vaddr + off + phdr[i].p_filesz;
while (resid > 0) {
chunk = min(PAGE_SIZE, resid);
archsw.arch_copyin(buf, dest, chunk);
resid -= chunk;
dest += chunk;
}
free(buf);
kern_bzero(phdr[i].p_vaddr + off + phdr[i].p_filesz,
phdr[i].p_memsz - phdr[i].p_filesz);
}
#ifdef ELF_VERBOSE
printf("\n");
@ -361,16 +341,10 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off)
chunk = ehdr->e_shnum * ehdr->e_shentsize;
if (chunk == 0 || ehdr->e_shoff == 0)
goto nosyms;
shdr = malloc(chunk);
if (shdr == NULL)
goto nosyms;
if (lseek(ef->fd, (off_t)ehdr->e_shoff, SEEK_SET) == -1) {
printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: cannot lseek() to section headers");
goto nosyms;
}
result = read(ef->fd, shdr, chunk);
if (result < 0 || (size_t)result != chunk) {
printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: read section headers failed");
shdr = alloc_pread(ef->fd, ehdr->e_shoff, chunk);
if (shdr == NULL) {
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
"_loadimage: failed to read section headers");
goto nosyms;
}
symtabindex = -1;

View File

@ -93,6 +93,74 @@ strdupout(vm_offset_t str)
return(result);
}
/* Zero a region in kernel space. */
void
kern_bzero(vm_offset_t dest, size_t len)
{
char buf[256];
size_t chunk, resid;
bzero(buf, sizeof(buf));
resid = len;
while (resid > 0) {
chunk = min(sizeof(buf), resid);
archsw.arch_copyin(buf, dest, chunk);
resid -= chunk;
dest += chunk;
}
}
/*
* Read the specified part of a file to kernel space. Unlike regular
* pread, the file pointer is advanced to the end of the read data,
* and it just returns 0 if successful.
*/
int
kern_pread(int fd, vm_offset_t dest, size_t len, off_t off)
{
ssize_t nread;
if (lseek(fd, off, SEEK_SET) == -1) {
printf("\nlseek failed\n");
return (-1);
}
nread = archsw.arch_readin(fd, dest, len);
if (nread != len) {
printf("\nreadin failed\n");
return (-1);
}
return (0);
}
/*
* Read the specified part of a file to a malloced buffer. The file
* pointer is advanced to the end of the read data.
*/
void *
alloc_pread(int fd, off_t off, size_t len)
{
void *buf;
ssize_t nread;
buf = malloc(len);
if (buf == NULL) {
printf("\nmalloc(%d) failed\n", (int)len);
return (NULL);
}
if (lseek(fd, off, SEEK_SET) == -1) {
printf("\nlseek failed\n");
free(buf);
return (NULL);
}
nread = read(fd, buf, len);
if (nread != len) {
printf("\nread failed\n");
free(buf);
return (NULL);
}
return (buf);
}
/*
* Display a region in traditional hexdump format.
*/