From: Richard Henderson <rth@twiddle.net>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 04/12] linux-user: Reduce lseek+reads while loading elf files.
Date: Tue, 27 Jul 2010 10:25:30 -0700 [thread overview]
Message-ID: <1280251538-6860-5-git-send-email-rth@twiddle.net> (raw)
In-Reply-To: <1280251538-6860-1-git-send-email-rth@twiddle.net>
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>
---
linux-user/elfload.c | 104 ++++++++++++++++++++---------------------------
linux-user/linuxload.c | 17 +++-----
linux-user/qemu.h | 7 +++-
3 files changed, 57 insertions(+), 71 deletions(-)
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 6ea1e8d..4a48c85 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -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,
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 *eppnt;
@@ -1202,17 +1203,15 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
return ~((abi_ulong)0UL);
}
- retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
- if(retval >= 0) {
- retval = read(interpreter_fd,
- (char *) elf_phdata,
- sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
- }
- if (retval < 0) {
- perror("load_elf_interp");
- exit(-1);
- free (elf_phdata);
- return retval;
+ i = interp_elf_ex->e_phnum * sizeof(struct elf_phdr);
+ if (interp_elf_ex->e_phoff + i <= BPRM_BUF_SIZE) {
+ memcpy(elf_phdata, bprm_buf + interp_elf_ex->e_phoff, i);
+ } else {
+ retval = pread(interpreter_fd, elf_phdata, i, interp_elf_ex->e_phoff);
+ if (retval != i) {
+ perror("load_elf_interp");
+ exit(-1);
+ }
}
#ifdef BSWAP_NEEDED
eppnt = elf_phdata;
@@ -1470,17 +1469,15 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
return -ENOMEM;
}
- retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
- if(retval > 0) {
- retval = read(bprm->fd, (char *) elf_phdata,
- elf_ex.e_phentsize * elf_ex.e_phnum);
- }
-
- if (retval < 0) {
- perror("load_elf_binary");
- exit(-1);
- free (elf_phdata);
- return -errno;
+ i = elf_ex.e_phnum * sizeof(struct elf_phdr);
+ if (elf_ex.e_phoff + i <= BPRM_BUF_SIZE) {
+ memcpy(elf_phdata, bprm->buf + elf_ex.e_phoff, i);
+ } else {
+ retval = pread(bprm->fd, (char *) elf_phdata, i, elf_ex.e_phoff);
+ if (retval != i) {
+ perror("load_elf_binary");
+ exit(-1);
+ }
}
#ifdef BSWAP_NEEDED
@@ -1524,13 +1521,16 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
return -ENOMEM;
}
- retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);
- if(retval >= 0) {
- retval = read(bprm->fd, elf_interpreter, elf_ppnt->p_filesz);
- }
- if(retval < 0) {
- perror("load_elf_binary2");
- exit(-1);
+ if (elf_ppnt->p_offset + elf_ppnt->p_filesz <= BPRM_BUF_SIZE) {
+ memcpy(elf_interpreter, bprm->buf + elf_ppnt->p_offset,
+ elf_ppnt->p_filesz);
+ } else {
+ retval = pread(bprm->fd, elf_interpreter, elf_ppnt->p_filesz,
+ elf_ppnt->p_offset);
+ if (retval != elf_ppnt->p_filesz) {
+ perror("load_elf_binary2");
+ exit(-1);
+ }
}
/* 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;
}
-#if 0
- printf("Using ELF interpreter %s\n", path(elf_interpreter));
-#endif
- if (retval >= 0) {
- retval = open(path(elf_interpreter), O_RDONLY);
- if(retval >= 0) {
- interpreter_fd = retval;
- }
- else {
- perror(elf_interpreter);
- exit(-1);
- /* retval = -errno; */
- }
+ retval = open(path(elf_interpreter), O_RDONLY);
+ if (retval < 0) {
+ perror(elf_interpreter);
+ exit(-1);
}
+ interpreter_fd = retval;
- if (retval >= 0) {
- 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 */
- }
+ retval = read(interpreter_fd, bprm->buf, BPRM_BUF_SIZE);
if (retval < 0) {
perror("load_elf_binary3");
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++;
}
@@ -1823,10 +1808,9 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
if (elf_interpreter) {
if (interpreter_type & 1) {
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,
- &interp_load_addr);
+ &interp_load_addr, bprm->buf);
}
reloc_func_desc = interp_load_addr;
diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c
index 13ad9aa..9ee27c3 100644
--- a/linux-user/linuxload.c
+++ b/linux-user/linuxload.c
@@ -96,18 +96,16 @@ static int prepare_binprm(struct linux_binprm *bprm)
}
}
- retval = lseek(bprm->fd, 0L, SEEK_SET);
- if(retval >= 0) {
- retval = read(bprm->fd, bprm->buf, 128);
- }
- if(retval < 0) {
+ retval = read(bprm->fd, bprm->buf, BPRM_BUF_SIZE);
+ if (retval < 0) {
perror("prepare_binprm");
exit(-1);
- /* return(-errno); */
}
- else {
- return(retval);
+ if (retval < BPRM_BUF_SIZE) {
+ /* 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. */
@@ -163,8 +161,7 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
int i;
bprm->p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
- for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
- bprm->page[i] = NULL;
+ memset(bprm->page, 0, sizeof(bprm->page));
retval = open(filename, O_RDONLY);
if (retval < 0)
return retval;
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 1878d5a..0a61274 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -31,6 +31,7 @@
* task_struct fields in the kernel
*/
struct image_info {
+ abi_ulong load_bias;
abi_ulong load_addr;
abi_ulong start_code;
abi_ulong end_code;
@@ -144,12 +145,16 @@ extern unsigned long mmap_min_addr;
*/
#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
* used when loading binaries.
*/
struct linux_binprm {
- char buf[128];
+ char buf[BPRM_BUF_SIZE] __attribute__((aligned));
void *page[MAX_ARG_PAGES];
abi_ulong p;
int fd;
--
1.7.1.1
next prev parent reply other threads:[~2010-07-27 18:16 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-07-27 17:25 [Qemu-devel] [PATCH 00/12 v4] Clean up linux-user/elfload.c Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 01/12] linux-user: Handle filesz < memsz for any PT_LOAD segment Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 02/12] Add more DT_* and AT_* constants to qemu's copy of elf.h Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 03/12] linux-user: Reindent elfload.c Richard Henderson
2010-07-27 17:25 ` Richard Henderson [this message]
2010-07-27 17:25 ` [Qemu-devel] [PATCH 05/12] linux-user: Define ELF_DATA generically Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 06/12] linux-user: Clean up byte-swapping in elfload.c Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 07/12] linux-user: Load symbols from the interpreter Richard Henderson
2010-07-27 18:45 ` malc
2010-07-27 19:59 ` Richard Henderson
2010-07-27 20:39 ` malc
2010-07-27 20:44 ` malc
2010-07-28 22:16 ` Edgar E. Iglesias
2010-07-27 17:25 ` [Qemu-devel] [PATCH 08/12] linux-user: Improve consistency checking in elf headers Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 09/12] linux-user: Put the stack guard page at the top Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 10/12] linux-user: Remove partial support for a.out interpreters Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 11/12] linux-user: Extract load_elf_image from load_elf_interp Richard Henderson
2010-07-28 22:00 ` Edgar E. Iglesias
2010-07-28 23:18 ` Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 12/12] linux-user: Re-use load_elf_image for the main binary Richard Henderson
2010-07-29 7:09 ` [Qemu-devel] [PATCH 00/12 v4] Clean up linux-user/elfload.c Edgar E. Iglesias
2010-08-09 16:52 ` Jan-Simon Möller
2010-08-10 16:21 ` Richard Henderson
-- strict thread matches above, loose matches on Subject: below --
2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 04/12] linux-user: Reduce lseek+reads while loading elf files Richard Henderson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1280251538-6860-5-git-send-email-rth@twiddle.net \
--to=rth@twiddle.net \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).