From: malc <av1474@comtv.ru>
To: Richard Henderson <rth@twiddle.net>
Cc: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH 12/14] linux-user: Re-use load_elf_image for the main binary.
Date: Mon, 5 Apr 2010 22:14:17 +0400 (MSD) [thread overview]
Message-ID: <alpine.LNX.2.00.1004052213510.14271@linmac> (raw)
In-Reply-To: <878d3e21b6ae87a80fda3a4653a3a2ba8e1e94bd.1270486025.git.rth@twiddle.net>
On Mon, 5 Apr 2010, Richard Henderson wrote:
> This requires moving the PT_INTERP extraction and GUEST_BASE
> handling into load_elf_image. Key this off a non-null pointer
> argument to receive the interpreter name.
>
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
> linux-user/elfload.c | 269 ++++++++++----------------------------------------
> 1 files changed, 53 insertions(+), 216 deletions(-)
>
> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> index c58387a..100efdc 100644
> --- a/linux-user/elfload.c
> +++ b/linux-user/elfload.c
> @@ -829,9 +829,6 @@ struct exec
> #define ZMAGIC 0413
> #define QMAGIC 0314
>
> -/* max code+data+bss+brk space allocated to ET_DYN executables */
> -#define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
> -
> /* Necessary parameters */
> #define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
> #define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
> @@ -1168,7 +1165,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
> On return: INFO values will be filled in, as necessary or available. */
>
> static void load_elf_image(const char *image_name, int image_fd,
> - struct image_info *info,
> + struct image_info *info, char **pinterp_name,
> char bprm_buf[BPRM_BUF_SIZE])
> {
> struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
> @@ -1228,6 +1225,20 @@ static void load_elf_image(const char *image_name, int image_fd,
> if (load_addr == -1) {
> goto exit_perror;
> }
> + } else if (pinterp_name != NULL) {
> + /* This is the main executable. Make sure that the low
> + address does not conflict with MMAP_MIN_ADDR. */
> + /* ??? Ideally, we'd check against more than just the
> + minimum mmap address, but also against the QEMU program
> + image itself. I.e. find a range that does not conflict
> + with PAGE_RESERVED entries. Except that we havn't read
> + those in yet, since that code uses the guest_base that
> + we set up here. Blah. */
> +#if defined(CONFIG_USE_GUEST_BASE)
> + if (HOST_PAGE_ALIGN(loaddr) < mmap_min_addr) {
> + guest_base = HOST_PAGE_ALIGN(mmap_min_addr);
> + }
> +#endif
> }
> load_bias = load_addr - loaddr;
>
> @@ -1289,6 +1300,30 @@ static void load_elf_image(const char *image_name, int image_fd,
> info->brk = vaddr_em;
> }
> }
> + } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
> + char *interp_name;
> +
> + if (*pinterp_name) {
> + errmsg = "Multiple PT_INTERP entries";
> + goto exit_errmsg;
> + }
> + interp_name = malloc(eppnt->p_filesz);
malloc can fail
> +
> + if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
> + memcpy(interp_name, bprm_buf + eppnt->p_offset,
> + eppnt->p_filesz);
> + } else {
> + retval = pread(image_fd, interp_name, eppnt->p_filesz,
Indentation seems off.
> + eppnt->p_offset);
> + if (retval != eppnt->p_filesz) {
> + goto exit_perror;
> + }
> + }
> + if (interp_name[eppnt->p_filesz - 1] != 0) {
> + errmsg = "Invalid PT_INTERP entry";
> + goto exit_errmsg;
> + }
> + *pinterp_name = interp_name;
> }
> }
>
> @@ -1335,7 +1370,7 @@ static void load_elf_interp(const char *filename, struct image_info *info,
> memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
> }
>
> - load_elf_image(filename, fd, info, bprm_buf);
> + load_elf_image(filename, fd, info, NULL, bprm_buf);
> return;
>
> exit_perror:
> @@ -1479,230 +1514,31 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
> {
> struct image_info interp_info;
> struct elfhdr elf_ex;
> - abi_ulong load_addr, load_bias;
> - int load_addr_set = 0;
> - int i;
> - struct elf_phdr * elf_ppnt;
> - struct elf_phdr *elf_phdata;
> - abi_ulong k, elf_brk;
> - int retval;
> char *elf_interpreter = NULL;
> - abi_ulong elf_entry;
> - int status;
> - abi_ulong start_code, end_code, start_data, end_data;
> - abi_ulong elf_stack;
>
> - status = 0;
> - load_addr = 0;
> - load_bias = 0;
> - elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */
> + info->start_mmap = (abi_ulong)ELF_START_MMAP;
> + info->mmap = 0;
> + info->rss = 0;
> +
> + load_elf_image(bprm->filename, bprm->fd, info,
> + &elf_interpreter, bprm->buf);
>
> - /* First of all, some simple consistency checks */
> - if (!elf_check_ident(&elf_ex)) {
> - return -ENOEXEC;
> - }
> - bswap_ehdr(&elf_ex);
> - if (!elf_check_ehdr(&elf_ex)) {
> - return -ENOEXEC;
> - }
> + /* ??? We need a copy of the elf header for passing to create_elf_tables.
> + If we do nothing, we'll have overwritten this when we re-use bprm->buf
> + when we load the interpreter. */
> + elf_ex = *(struct elfhdr *)bprm->buf;
>
> bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
> bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p);
> bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p);
> if (!bprm->p) {
> - retval = -E2BIG;
> - }
> -
> - /* Now read in all of the header information */
> - elf_phdata = (struct elf_phdr *)
> - malloc(elf_ex.e_phnum * sizeof(struct elf_phdr));
> - if (elf_phdata == NULL) {
> - return -ENOMEM;
> - }
> -
> - 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);
> - }
> - }
> - bswap_phdr(elf_phdata, elf_ex.e_phnum);
> -
> - elf_brk = 0;
> - elf_stack = ~((abi_ulong)0UL);
> - start_code = ~((abi_ulong)0UL);
> - end_code = 0;
> - start_data = 0;
> - end_data = 0;
> -
> - elf_ppnt = elf_phdata;
> - for(i=0;i < elf_ex.e_phnum; i++) {
> - if (elf_ppnt->p_type == PT_INTERP) {
> - if (elf_ppnt->p_offset + elf_ppnt->p_filesz <= BPRM_BUF_SIZE) {
> - elf_interpreter = bprm->buf + elf_ppnt->p_offset;
> - } else {
> - elf_interpreter = alloca(elf_ppnt->p_filesz);
> - retval = pread(bprm->fd, elf_interpreter, elf_ppnt->p_filesz,
> - elf_ppnt->p_offset);
> - if (retval != elf_ppnt->p_filesz) {
> - perror("load_elf_binary");
> - exit(-1);
> - }
> - }
> - }
> - elf_ppnt++;
> - }
> -
> - /* OK, This is the point of no return */
> - info->end_data = 0;
> - info->end_code = 0;
> - info->start_mmap = (abi_ulong)ELF_START_MMAP;
> - info->mmap = 0;
> - elf_entry = (abi_ulong) elf_ex.e_entry;
> -
> -#if defined(CONFIG_USE_GUEST_BASE)
> - /*
> - * In case where user has not explicitly set the guest_base, we
> - * probe here that should we set it automatically.
> - */
> - if (!have_guest_base) {
> - /*
> - * Go through ELF program header table and find out whether
> - * any of the segments drop below our current mmap_min_addr and
> - * in that case set guest_base to corresponding address.
> - */
> - for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum;
> - i++, elf_ppnt++) {
> - if (elf_ppnt->p_type != PT_LOAD)
> - continue;
> - if (HOST_PAGE_ALIGN(elf_ppnt->p_vaddr) < mmap_min_addr) {
> - guest_base = HOST_PAGE_ALIGN(mmap_min_addr);
> - break;
> - }
> - }
> + fprintf(stderr, "%s: %s\n", bprm->filename, strerror(E2BIG));
> + exit(-1);
> }
> -#endif /* CONFIG_USE_GUEST_BASE */
>
> /* Do this so that we can load the interpreter, if need be. We will
> change some of these later */
> - info->rss = 0;
> bprm->p = setup_arg_pages(bprm->p, bprm, info);
> - info->start_stack = bprm->p;
> -
> - /* Now we do a little grungy work by mmaping the ELF image into
> - * the correct location in memory. At this point, we assume that
> - * the image should be loaded at fixed address, not at a variable
> - * address.
> - */
> -
> - for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
> - int elf_prot = 0;
> - int elf_flags = 0;
> - abi_ulong error;
> -
> - if (elf_ppnt->p_type != PT_LOAD)
> - continue;
> -
> - if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
> - if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
> - if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
> - elf_flags = MAP_PRIVATE | MAP_DENYWRITE;
> - if (elf_ex.e_type == ET_EXEC || load_addr_set) {
> - elf_flags |= MAP_FIXED;
> - } else if (elf_ex.e_type == ET_DYN) {
> - /* Try and get dynamic programs out of the way of the default mmap
> - base, as well as whatever program they might try to exec. This
> - is because the brk will follow the loader, and is not movable. */
> - /* NOTE: for qemu, we do a big mmap to get enough space
> - without hardcoding any address */
> - error = target_mmap(0, ET_DYN_MAP_SIZE,
> - PROT_NONE, MAP_PRIVATE | MAP_ANON,
> - -1, 0);
> - if (error == -1) {
> - perror("mmap");
> - exit(-1);
> - }
> - load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr);
> - }
> -
> - error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr),
> - (elf_ppnt->p_filesz +
> - TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
> - elf_prot,
> - (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
> - bprm->fd,
> - (elf_ppnt->p_offset -
> - TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
> - if (error == -1) {
> - perror("mmap");
> - exit(-1);
> - }
> -
> -#ifdef LOW_ELF_STACK
> - if (TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack)
> - elf_stack = TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr);
> -#endif
> -
> - if (!load_addr_set) {
> - load_addr_set = 1;
> - load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
> - if (elf_ex.e_type == ET_DYN) {
> - load_bias += error -
> - TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
> - load_addr += load_bias;
> - }
> - }
> - k = elf_ppnt->p_vaddr;
> - if (k < start_code)
> - start_code = k;
> - if (start_data < k)
> - start_data = k;
> - k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
> - if ((elf_ppnt->p_flags & PF_X) && end_code < k)
> - end_code = k;
> - if (end_data < k)
> - end_data = k;
> - k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
> - if (k > elf_brk) {
> - elf_brk = TARGET_PAGE_ALIGN(k);
> - }
> -
> - /* If the load segment requests extra zeros (e.g. bss), map it. */
> - if (elf_ppnt->p_filesz < elf_ppnt->p_memsz) {
> - abi_ulong base = load_bias + elf_ppnt->p_vaddr;
> - zero_bss(base + elf_ppnt->p_filesz,
> - base + elf_ppnt->p_memsz, elf_prot);
> - }
> - }
> -
> - elf_entry += load_bias;
> - elf_brk += load_bias;
> - start_code += load_bias;
> - end_code += load_bias;
> - start_data += load_bias;
> - end_data += load_bias;
> -
> - info->load_bias = load_bias;
> - info->load_addr = load_addr;
> - info->entry = elf_entry;
> - info->start_brk = info->brk = elf_brk;
> - info->end_code = end_code;
> - info->start_code = start_code;
> - info->start_data = start_data;
> - info->end_data = end_data;
> - info->personality = PER_LINUX;
> -
> - free(elf_phdata);
> -
> - if (qemu_log_enabled()) {
> - load_symbols(&elf_ex, bprm->fd, load_bias);
> - }
> -
> - close(bprm->fd);
>
> if (elf_interpreter) {
> load_elf_interp(elf_interpreter, &interp_info, bprm->buf);
> @@ -1734,6 +1570,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
> if (elf_interpreter) {
> info->load_addr = interp_info.load_addr;
> info->entry = interp_info.entry;
> + free(elf_interpreter);
> }
>
> #ifdef USE_ELF_CORE_DUMP
>
--
mailto:av1474@comtv.ru
next prev parent reply other threads:[~2010-04-05 18:14 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
2010-03-31 22:12 ` [Qemu-devel] [PATCH 01/14] linux-user: Handle filesz < memsz for any PT_LOAD segment Richard Henderson
2010-04-04 18:38 ` [Qemu-devel] [PATCH 13/14] linux-user: Build vdso for x64 Richard Henderson
2010-04-04 19:07 ` [Qemu-devel] [PATCH 03/14] linux-user: Reindent elfload.c Richard Henderson
2010-04-04 19:34 ` [Qemu-devel] [PATCH 04/14] linux-user: Reduce lseek+reads while loading elf files Richard Henderson
2010-04-04 19:35 ` [Qemu-devel] [PATCH 05/14] linux-user: Fix ELF_DATA for Alpha Richard Henderson
2010-04-04 19:54 ` [Qemu-devel] [PATCH 06/14] linux-user: Clean up byte-swapping in elfload.c Richard Henderson
2010-04-04 21:16 ` [Qemu-devel] [PATCH 07/14] linux-user: Load symbols from the interpreter Richard Henderson
2010-04-04 22:04 ` [Qemu-devel] [PATCH 08/14] linux-user: Improve consistency checking in elf headers Richard Henderson
2010-04-04 22:14 ` [Qemu-devel] [PATCH 09/14] linux-user: Put the stack guard page at the top Richard Henderson
2010-04-04 22:31 ` [Qemu-devel] [PATCH 10/14] linux-user: Remove partial support for a.out interpreters Richard Henderson
2010-04-05 0:46 ` [Qemu-devel] [PATCH 11/14] linux-user: Extract load_elf_image from load_elf_interp Richard Henderson
2010-04-05 2:13 ` [Qemu-devel] [PATCH 14/14] linux-user: Load a VDSO for x86-64 Richard Henderson
2010-04-05 16:26 ` [Qemu-devel] [PATCH 02/14] Add more DT_* and AT_* constants to qemu's copy of elf.h Richard Henderson
2010-04-05 16:37 ` [Qemu-devel] [PATCH 12/14] linux-user: Re-use load_elf_image for the main binary Richard Henderson
2010-04-05 18:14 ` malc [this message]
2010-04-05 18:38 ` Richard Henderson
2010-04-28 19:36 ` [Qemu-devel] [PATCH 00/14] Implement VDSO for x86-64-linux-user, v2 Richard Henderson
2010-04-28 19:39 ` [Qemu-devel] [PATCH 04/14] linux-user: Reduce lseek+reads while loading elf files Richard Henderson
2010-04-28 19:39 ` [Qemu-devel] [PATCH 01/14] linux-user: Handle filesz < memsz for any PT_LOAD segment Richard Henderson
2010-04-28 19:39 ` [Qemu-devel] [PATCH 02/14] Add more DT_* and AT_* constants to qemu's copy of elf.h Richard Henderson
2010-04-28 19:39 ` [Qemu-devel] [PATCH 09/14] linux-user: Put the stack guard page at the top Richard Henderson
2010-04-28 19:39 ` [Qemu-devel] [PATCH 06/14] linux-user: Clean up byte-swapping in elfload.c Richard Henderson
2010-04-28 19:39 ` [Qemu-devel] [PATCH 10/14] linux-user: Remove partial support for a.out interpreters Richard Henderson
2010-04-28 19:39 ` [Qemu-devel] [PATCH 05/14] linux-user: Fix ELF_DATA for Alpha Richard Henderson
2010-04-28 19:39 ` [Qemu-devel] [PATCH 08/14] linux-user: Improve consistency checking in elf headers Richard Henderson
2010-04-28 19:39 ` [Qemu-devel] [PATCH 11/14] linux-user: Extract load_elf_image from load_elf_interp Richard Henderson
2010-04-28 19:39 ` [Qemu-devel] [PATCH 14/14] linux-user: Load a VDSO for x86-64 Richard Henderson
2010-04-28 19:39 ` [Qemu-devel] [PATCH 13/14] linux-user: Build vdso for x64 Richard Henderson
2010-04-28 19:39 ` [Qemu-devel] [PATCH 07/14] linux-user: Load symbols from the interpreter Richard Henderson
2010-04-28 19:39 ` [Qemu-devel] [PATCH 03/14] linux-user: Reindent elfload.c Richard Henderson
2010-04-28 19:39 ` [Qemu-devel] [PATCH 12/14] linux-user: Re-use load_elf_image for the main binary Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 00/12] Cleanup linux-user/elfload.c, v2 Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 01/12] linux-user: Handle filesz < memsz for any PT_LOAD segment Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 02/12] Add more DT_* and AT_* constants to qemu's copy of elf.h Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 03/12] linux-user: Reindent elfload.c Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 04/12] linux-user: Reduce lseek+reads while loading elf files Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 05/12] linux-user: Define ELF_DATA generically Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 06/12] linux-user: Clean up byte-swapping in elfload.c Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 07/12] linux-user: Load symbols from the interpreter Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 08/12] linux-user: Improve consistency checking in elf headers Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 09/12] linux-user: Put the stack guard page at the top Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 10/12] linux-user: Remove partial support for a.out interpreters Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 11/12] linux-user: Extract load_elf_image from load_elf_interp Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 12/12] linux-user: Re-use load_elf_image for the main binary 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=alpine.LNX.2.00.1004052213510.14271@linmac \
--to=av1474@comtv.ru \
--cc=qemu-devel@nongnu.org \
--cc=rth@twiddle.net \
/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).