mirror of https://github.com/xqemu/xqemu.git
linux-user: Reduce lseek+reads while loading elf files.
Define BPRM_BUF_SIZE to 1k and read that amount initially. If the data we want from the binary is in this buffer, use it instead of reading from the file again. Signed-off-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
This commit is contained in:
parent
d97ef72eed
commit
9955ffac9a
|
@ -1159,7 +1159,8 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
|
||||||
|
|
||||||
static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
|
static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
|
||||||
int interpreter_fd,
|
int interpreter_fd,
|
||||||
abi_ulong *interp_load_addr)
|
abi_ulong *interp_load_addr,
|
||||||
|
char bprm_buf[BPRM_BUF_SIZE])
|
||||||
{
|
{
|
||||||
struct elf_phdr *elf_phdata = NULL;
|
struct elf_phdr *elf_phdata = NULL;
|
||||||
struct elf_phdr *eppnt;
|
struct elf_phdr *eppnt;
|
||||||
|
@ -1202,17 +1203,15 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
|
||||||
return ~((abi_ulong)0UL);
|
return ~((abi_ulong)0UL);
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
|
i = interp_elf_ex->e_phnum * sizeof(struct elf_phdr);
|
||||||
if(retval >= 0) {
|
if (interp_elf_ex->e_phoff + i <= BPRM_BUF_SIZE) {
|
||||||
retval = read(interpreter_fd,
|
memcpy(elf_phdata, bprm_buf + interp_elf_ex->e_phoff, i);
|
||||||
(char *) elf_phdata,
|
} else {
|
||||||
sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
|
retval = pread(interpreter_fd, elf_phdata, i, interp_elf_ex->e_phoff);
|
||||||
}
|
if (retval != i) {
|
||||||
if (retval < 0) {
|
perror("load_elf_interp");
|
||||||
perror("load_elf_interp");
|
exit(-1);
|
||||||
exit(-1);
|
}
|
||||||
free (elf_phdata);
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
#ifdef BSWAP_NEEDED
|
#ifdef BSWAP_NEEDED
|
||||||
eppnt = elf_phdata;
|
eppnt = elf_phdata;
|
||||||
|
@ -1470,17 +1469,15 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
|
i = elf_ex.e_phnum * sizeof(struct elf_phdr);
|
||||||
if(retval > 0) {
|
if (elf_ex.e_phoff + i <= BPRM_BUF_SIZE) {
|
||||||
retval = read(bprm->fd, (char *) elf_phdata,
|
memcpy(elf_phdata, bprm->buf + elf_ex.e_phoff, i);
|
||||||
elf_ex.e_phentsize * elf_ex.e_phnum);
|
} else {
|
||||||
}
|
retval = pread(bprm->fd, (char *) elf_phdata, i, elf_ex.e_phoff);
|
||||||
|
if (retval != i) {
|
||||||
if (retval < 0) {
|
perror("load_elf_binary");
|
||||||
perror("load_elf_binary");
|
exit(-1);
|
||||||
exit(-1);
|
}
|
||||||
free (elf_phdata);
|
|
||||||
return -errno;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BSWAP_NEEDED
|
#ifdef BSWAP_NEEDED
|
||||||
|
@ -1524,13 +1521,16 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);
|
if (elf_ppnt->p_offset + elf_ppnt->p_filesz <= BPRM_BUF_SIZE) {
|
||||||
if(retval >= 0) {
|
memcpy(elf_interpreter, bprm->buf + elf_ppnt->p_offset,
|
||||||
retval = read(bprm->fd, elf_interpreter, elf_ppnt->p_filesz);
|
elf_ppnt->p_filesz);
|
||||||
}
|
} else {
|
||||||
if(retval < 0) {
|
retval = pread(bprm->fd, elf_interpreter, elf_ppnt->p_filesz,
|
||||||
perror("load_elf_binary2");
|
elf_ppnt->p_offset);
|
||||||
exit(-1);
|
if (retval != elf_ppnt->p_filesz) {
|
||||||
|
perror("load_elf_binary2");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the program interpreter is one of these two,
|
/* If the program interpreter is one of these two,
|
||||||
|
@ -1544,39 +1544,24 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
|
||||||
ibcs2_interpreter = 1;
|
ibcs2_interpreter = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
retval = open(path(elf_interpreter), O_RDONLY);
|
||||||
printf("Using ELF interpreter %s\n", path(elf_interpreter));
|
if (retval < 0) {
|
||||||
#endif
|
perror(elf_interpreter);
|
||||||
if (retval >= 0) {
|
exit(-1);
|
||||||
retval = open(path(elf_interpreter), O_RDONLY);
|
|
||||||
if(retval >= 0) {
|
|
||||||
interpreter_fd = retval;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
perror(elf_interpreter);
|
|
||||||
exit(-1);
|
|
||||||
/* retval = -errno; */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
interpreter_fd = retval;
|
||||||
|
|
||||||
if (retval >= 0) {
|
retval = read(interpreter_fd, bprm->buf, BPRM_BUF_SIZE);
|
||||||
retval = lseek(interpreter_fd, 0, SEEK_SET);
|
|
||||||
if(retval >= 0) {
|
|
||||||
retval = read(interpreter_fd,bprm->buf,128);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (retval >= 0) {
|
|
||||||
interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
|
|
||||||
interp_elf_ex = *((struct elfhdr *) bprm->buf); /* elf exec-header */
|
|
||||||
}
|
|
||||||
if (retval < 0) {
|
if (retval < 0) {
|
||||||
perror("load_elf_binary3");
|
perror("load_elf_binary3");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
free (elf_phdata);
|
|
||||||
free(elf_interpreter);
|
|
||||||
close(bprm->fd);
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
if (retval < BPRM_BUF_SIZE) {
|
||||||
|
memset(bprm->buf, 0, BPRM_BUF_SIZE - retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
|
||||||
|
interp_elf_ex = *((struct elfhdr *) bprm->buf); /* elf exec-header */
|
||||||
}
|
}
|
||||||
elf_ppnt++;
|
elf_ppnt++;
|
||||||
}
|
}
|
||||||
|
@ -1823,10 +1808,9 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
|
||||||
if (elf_interpreter) {
|
if (elf_interpreter) {
|
||||||
if (interpreter_type & 1) {
|
if (interpreter_type & 1) {
|
||||||
elf_entry = load_aout_interp(&interp_ex, interpreter_fd);
|
elf_entry = load_aout_interp(&interp_ex, interpreter_fd);
|
||||||
}
|
} else if (interpreter_type & 2) {
|
||||||
else if (interpreter_type & 2) {
|
|
||||||
elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
|
elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
|
||||||
&interp_load_addr);
|
&interp_load_addr, bprm->buf);
|
||||||
}
|
}
|
||||||
reloc_func_desc = interp_load_addr;
|
reloc_func_desc = interp_load_addr;
|
||||||
|
|
||||||
|
|
|
@ -96,18 +96,16 @@ static int prepare_binprm(struct linux_binprm *bprm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = lseek(bprm->fd, 0L, SEEK_SET);
|
retval = read(bprm->fd, bprm->buf, BPRM_BUF_SIZE);
|
||||||
if(retval >= 0) {
|
if (retval < 0) {
|
||||||
retval = read(bprm->fd, bprm->buf, 128);
|
|
||||||
}
|
|
||||||
if(retval < 0) {
|
|
||||||
perror("prepare_binprm");
|
perror("prepare_binprm");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
/* return(-errno); */
|
|
||||||
}
|
}
|
||||||
else {
|
if (retval < BPRM_BUF_SIZE) {
|
||||||
return(retval);
|
/* Make sure the rest of the loader won't read garbage. */
|
||||||
|
memset(bprm->buf + retval, 0, BPRM_BUF_SIZE - retval);
|
||||||
}
|
}
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Construct the envp and argv tables on the target stack. */
|
/* Construct the envp and argv tables on the target stack. */
|
||||||
|
@ -163,8 +161,7 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
bprm->p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
|
bprm->p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
|
||||||
for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
|
memset(bprm->page, 0, sizeof(bprm->page));
|
||||||
bprm->page[i] = NULL;
|
|
||||||
retval = open(filename, O_RDONLY);
|
retval = open(filename, O_RDONLY);
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
* task_struct fields in the kernel
|
* task_struct fields in the kernel
|
||||||
*/
|
*/
|
||||||
struct image_info {
|
struct image_info {
|
||||||
|
abi_ulong load_bias;
|
||||||
abi_ulong load_addr;
|
abi_ulong load_addr;
|
||||||
abi_ulong start_code;
|
abi_ulong start_code;
|
||||||
abi_ulong end_code;
|
abi_ulong end_code;
|
||||||
|
@ -144,12 +145,16 @@ extern unsigned long mmap_min_addr;
|
||||||
*/
|
*/
|
||||||
#define MAX_ARG_PAGES 33
|
#define MAX_ARG_PAGES 33
|
||||||
|
|
||||||
|
/* Read a good amount of data initially, to hopefully get all the
|
||||||
|
program headers loaded. */
|
||||||
|
#define BPRM_BUF_SIZE 1024
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This structure is used to hold the arguments that are
|
* This structure is used to hold the arguments that are
|
||||||
* used when loading binaries.
|
* used when loading binaries.
|
||||||
*/
|
*/
|
||||||
struct linux_binprm {
|
struct linux_binprm {
|
||||||
char buf[128];
|
char buf[BPRM_BUF_SIZE] __attribute__((aligned));
|
||||||
void *page[MAX_ARG_PAGES];
|
void *page[MAX_ARG_PAGES];
|
||||||
abi_ulong p;
|
abi_ulong p;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
Loading…
Reference in New Issue