linux-user: Extract load_elf_image from load_elf_interp.
Moving toward a single copy of the elf binary loading code. Fill in the details of the loaded image into a struct image_info. Adjust create_elf_tables to read from such structures instead of from a collection of passed arguments. Don't return error values from load_elf_interp; always exit(-1) with a message to stderr. Collect elf_interpreter handling in load_elf_binary to a common spot. Signed-off-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
This commit is contained in:
		
							parent
							
								
									b9329d4b53
								
							
						
					
					
						commit
						8e62a71738
					
				@ -1079,11 +1079,9 @@ static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
 | 
					static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
 | 
				
			||||||
                                   struct elfhdr * exec,
 | 
					                                   struct elfhdr *exec,
 | 
				
			||||||
                                   abi_ulong load_addr,
 | 
					                                   struct image_info *info,
 | 
				
			||||||
                                   abi_ulong load_bias,
 | 
					                                   struct image_info *interp_info)
 | 
				
			||||||
                                   abi_ulong interp_load_addr,
 | 
					 | 
				
			||||||
                                   struct image_info *info)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    abi_ulong sp;
 | 
					    abi_ulong sp;
 | 
				
			||||||
    int size;
 | 
					    int size;
 | 
				
			||||||
@ -1128,13 +1126,13 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
 | 
				
			|||||||
    NEW_AUX_ENT (AT_NULL, 0);
 | 
					    NEW_AUX_ENT (AT_NULL, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* There must be exactly DLINFO_ITEMS entries here.  */
 | 
					    /* There must be exactly DLINFO_ITEMS entries here.  */
 | 
				
			||||||
    NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
 | 
					    NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff));
 | 
				
			||||||
    NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
 | 
					    NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
 | 
				
			||||||
    NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
 | 
					    NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
 | 
				
			||||||
    NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
 | 
					    NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
 | 
				
			||||||
    NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
 | 
					    NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_info ? interp_info->load_addr : 0));
 | 
				
			||||||
    NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
 | 
					    NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
 | 
				
			||||||
    NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
 | 
					    NEW_AUX_ENT(AT_ENTRY, info->entry);
 | 
				
			||||||
    NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
 | 
					    NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
 | 
				
			||||||
    NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
 | 
					    NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
 | 
				
			||||||
    NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
 | 
					    NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
 | 
				
			||||||
@ -1158,51 +1156,60 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
 | 
				
			|||||||
    return sp;
 | 
					    return sp;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Load an ELF image into the address space.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
 | 
					   IMAGE_NAME is the filename of the image, to use in error messages.
 | 
				
			||||||
                                 int interpreter_fd,
 | 
					   IMAGE_FD is the open file descriptor for the image.
 | 
				
			||||||
                                 abi_ulong *interp_load_addr,
 | 
					
 | 
				
			||||||
 | 
					   BPRM_BUF is a copy of the beginning of the file; this of course
 | 
				
			||||||
 | 
					   contains the elf file header at offset 0.  It is assumed that this
 | 
				
			||||||
 | 
					   buffer is sufficiently aligned to present no problems to the host
 | 
				
			||||||
 | 
					   in accessing data at aligned offsets within the buffer.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   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,
 | 
				
			||||||
                           char bprm_buf[BPRM_BUF_SIZE])
 | 
					                           char bprm_buf[BPRM_BUF_SIZE])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    struct elf_phdr *elf_phdata  =  NULL;
 | 
					    struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
 | 
				
			||||||
    abi_ulong load_addr, load_bias, loaddr, hiaddr;
 | 
					    struct elf_phdr *phdr;
 | 
				
			||||||
    int retval;
 | 
					    abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
 | 
				
			||||||
    abi_ulong error;
 | 
					    int i, retval;
 | 
				
			||||||
    int i;
 | 
					    const char *errmsg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bswap_ehdr(interp_elf_ex);
 | 
					    /* First of all, some simple consistency checks */
 | 
				
			||||||
    if (!elf_check_ehdr(interp_elf_ex)) {
 | 
					    errmsg = "Invalid ELF image for this architecture";
 | 
				
			||||||
        return ~((abi_ulong)0UL);
 | 
					    if (!elf_check_ident(ehdr)) {
 | 
				
			||||||
 | 
					        goto exit_errmsg;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    bswap_ehdr(ehdr);
 | 
				
			||||||
 | 
					    if (!elf_check_ehdr(ehdr)) {
 | 
				
			||||||
 | 
					        goto exit_errmsg;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Now read in all of the header information */
 | 
					    i = ehdr->e_phnum * sizeof(struct elf_phdr);
 | 
				
			||||||
    elf_phdata =  (struct elf_phdr *)
 | 
					    if (ehdr->e_phoff + i <= BPRM_BUF_SIZE) {
 | 
				
			||||||
        malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
 | 
					        phdr = (struct elf_phdr *)(bprm_buf + ehdr->e_phoff);
 | 
				
			||||||
    if (!elf_phdata)
 | 
					 | 
				
			||||||
        return ~((abi_ulong)0UL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    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 {
 | 
					    } else {
 | 
				
			||||||
        retval = pread(interpreter_fd, elf_phdata, i, interp_elf_ex->e_phoff);
 | 
					        phdr = (struct elf_phdr *) alloca(i);
 | 
				
			||||||
 | 
					        retval = pread(image_fd, phdr, i, ehdr->e_phoff);
 | 
				
			||||||
        if (retval != i) {
 | 
					        if (retval != i) {
 | 
				
			||||||
            perror("load_elf_interp");
 | 
					            goto exit_read;
 | 
				
			||||||
            exit(-1);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    bswap_phdr(elf_phdata, interp_elf_ex->e_phnum);
 | 
					    bswap_phdr(phdr, ehdr->e_phnum);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Find the maximum size of the image and allocate an appropriate
 | 
					    /* Find the maximum size of the image and allocate an appropriate
 | 
				
			||||||
       amount of memory to handle that.  */
 | 
					       amount of memory to handle that.  */
 | 
				
			||||||
    loaddr = -1, hiaddr = 0;
 | 
					    loaddr = -1, hiaddr = 0;
 | 
				
			||||||
    for (i = 0; i < interp_elf_ex->e_phnum; ++i) {
 | 
					    for (i = 0; i < ehdr->e_phnum; ++i) {
 | 
				
			||||||
        if (elf_phdata[i].p_type == PT_LOAD) {
 | 
					        if (phdr[i].p_type == PT_LOAD) {
 | 
				
			||||||
            abi_ulong a = elf_phdata[i].p_vaddr;
 | 
					            abi_ulong a = phdr[i].p_vaddr;
 | 
				
			||||||
            if (a < loaddr) {
 | 
					            if (a < loaddr) {
 | 
				
			||||||
                loaddr = a;
 | 
					                loaddr = a;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            a += elf_phdata[i].p_memsz;
 | 
					            a += phdr[i].p_memsz;
 | 
				
			||||||
            if (a > hiaddr) {
 | 
					            if (a > hiaddr) {
 | 
				
			||||||
                hiaddr = a;
 | 
					                hiaddr = a;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -1210,7 +1217,7 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    load_addr = loaddr;
 | 
					    load_addr = loaddr;
 | 
				
			||||||
    if (interp_elf_ex->e_type == ET_DYN) {
 | 
					    if (ehdr->e_type == ET_DYN) {
 | 
				
			||||||
        /* The image indicates that it can be loaded anywhere.  Find a
 | 
					        /* The image indicates that it can be loaded anywhere.  Find a
 | 
				
			||||||
           location that can hold the memory space required.  If the
 | 
					           location that can hold the memory space required.  If the
 | 
				
			||||||
           image is pre-linked, LOADDR will be non-zero.  Since we do
 | 
					           image is pre-linked, LOADDR will be non-zero.  Since we do
 | 
				
			||||||
@ -1220,14 +1227,22 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
 | 
				
			|||||||
                                MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
 | 
					                                MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
 | 
				
			||||||
                                -1, 0);
 | 
					                                -1, 0);
 | 
				
			||||||
        if (load_addr == -1) {
 | 
					        if (load_addr == -1) {
 | 
				
			||||||
            perror("mmap");
 | 
					            goto exit_perror;
 | 
				
			||||||
            exit(-1);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    load_bias = load_addr - loaddr;
 | 
					    load_bias = load_addr - loaddr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < interp_elf_ex->e_phnum; i++) {
 | 
					    info->load_bias = load_bias;
 | 
				
			||||||
        struct elf_phdr *eppnt = elf_phdata + i;
 | 
					    info->load_addr = load_addr;
 | 
				
			||||||
 | 
					    info->entry = ehdr->e_entry + load_bias;
 | 
				
			||||||
 | 
					    info->start_code = -1;
 | 
				
			||||||
 | 
					    info->end_code = 0;
 | 
				
			||||||
 | 
					    info->start_data = -1;
 | 
				
			||||||
 | 
					    info->end_data = 0;
 | 
				
			||||||
 | 
					    info->brk = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < ehdr->e_phnum; i++) {
 | 
				
			||||||
 | 
					        struct elf_phdr *eppnt = phdr + i;
 | 
				
			||||||
        if (eppnt->p_type == PT_LOAD) {
 | 
					        if (eppnt->p_type == PT_LOAD) {
 | 
				
			||||||
            abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em;
 | 
					            abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em;
 | 
				
			||||||
            int elf_prot = 0;
 | 
					            int elf_prot = 0;
 | 
				
			||||||
@ -1242,12 +1257,9 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            error = target_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po,
 | 
					            error = target_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po,
 | 
				
			||||||
                                elf_prot, MAP_PRIVATE | MAP_FIXED,
 | 
					                                elf_prot, MAP_PRIVATE | MAP_FIXED,
 | 
				
			||||||
                                interpreter_fd, eppnt->p_offset - vaddr_po);
 | 
					                                image_fd, eppnt->p_offset - vaddr_po);
 | 
				
			||||||
            if (error == -1) {
 | 
					            if (error == -1) {
 | 
				
			||||||
                /* Real error */
 | 
					                goto exit_perror;
 | 
				
			||||||
                close(interpreter_fd);
 | 
					 | 
				
			||||||
                free(elf_phdata);
 | 
					 | 
				
			||||||
                return ~((abi_ulong)0UL);
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            vaddr_ef = vaddr + eppnt->p_filesz;
 | 
					            vaddr_ef = vaddr + eppnt->p_filesz;
 | 
				
			||||||
@ -1257,18 +1269,79 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
 | 
				
			|||||||
            if (vaddr_ef < vaddr_em) {
 | 
					            if (vaddr_ef < vaddr_em) {
 | 
				
			||||||
                zero_bss(vaddr_ef, vaddr_em, elf_prot);
 | 
					                zero_bss(vaddr_ef, vaddr_em, elf_prot);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* Find the full program boundaries.  */
 | 
				
			||||||
 | 
					            if (elf_prot & PROT_EXEC) {
 | 
				
			||||||
 | 
					                if (vaddr < info->start_code) {
 | 
				
			||||||
 | 
					                    info->start_code = vaddr;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					                if (vaddr_ef > info->end_code) {
 | 
				
			||||||
 | 
					                    info->end_code = vaddr_ef;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (elf_prot & PROT_WRITE) {
 | 
				
			||||||
 | 
					                if (vaddr < info->start_data) {
 | 
				
			||||||
 | 
					                    info->start_data = vaddr;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if (vaddr_ef > info->end_data) {
 | 
				
			||||||
 | 
					                    info->end_data = vaddr_ef;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if (vaddr_em > info->brk) {
 | 
				
			||||||
 | 
					                    info->brk = vaddr_em;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (info->end_data == 0) {
 | 
				
			||||||
 | 
					        info->start_data = info->end_code;
 | 
				
			||||||
 | 
					        info->end_data = info->end_code;
 | 
				
			||||||
 | 
					        info->brk = info->end_code;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (qemu_log_enabled()) {
 | 
					    if (qemu_log_enabled()) {
 | 
				
			||||||
        load_symbols(interp_elf_ex, interpreter_fd, load_bias);
 | 
					        load_symbols(ehdr, image_fd, load_bias);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    close(interpreter_fd);
 | 
					    close(image_fd);
 | 
				
			||||||
    free(elf_phdata);
 | 
					    return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    *interp_load_addr = load_addr;
 | 
					 exit_read:
 | 
				
			||||||
    return ((abi_ulong) interp_elf_ex->e_entry) + load_bias;
 | 
					    if (retval >= 0) {
 | 
				
			||||||
 | 
					        errmsg = "Incomplete read of file header";
 | 
				
			||||||
 | 
					        goto exit_errmsg;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					 exit_perror:
 | 
				
			||||||
 | 
					    errmsg = strerror(errno);
 | 
				
			||||||
 | 
					 exit_errmsg:
 | 
				
			||||||
 | 
					    fprintf(stderr, "%s: %s\n", image_name, errmsg);
 | 
				
			||||||
 | 
					    exit(-1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void load_elf_interp(const char *filename, struct image_info *info,
 | 
				
			||||||
 | 
					                            char bprm_buf[BPRM_BUF_SIZE])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int fd, retval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fd = open(path(filename), O_RDONLY);
 | 
				
			||||||
 | 
					    if (fd < 0) {
 | 
				
			||||||
 | 
					        goto exit_perror;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    retval = read(fd, bprm_buf, BPRM_BUF_SIZE);
 | 
				
			||||||
 | 
					    if (retval < 0) {
 | 
				
			||||||
 | 
					        goto exit_perror;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (retval < BPRM_BUF_SIZE) {
 | 
				
			||||||
 | 
					        memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    load_elf_image(filename, fd, info, bprm_buf);
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 exit_perror:
 | 
				
			||||||
 | 
					    fprintf(stderr, "%s: %s\n", filename, strerror(errno));
 | 
				
			||||||
 | 
					    exit(-1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int symfind(const void *s0, const void *s1)
 | 
					static int symfind(const void *s0, const void *s1)
 | 
				
			||||||
@ -1405,26 +1478,21 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
 | 
				
			|||||||
int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 | 
					int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 | 
				
			||||||
                    struct image_info * info)
 | 
					                    struct image_info * info)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    struct image_info interp_info;
 | 
				
			||||||
    struct elfhdr elf_ex;
 | 
					    struct elfhdr elf_ex;
 | 
				
			||||||
    struct elfhdr interp_elf_ex;
 | 
					 | 
				
			||||||
    int interpreter_fd = -1; /* avoid warning */
 | 
					 | 
				
			||||||
    abi_ulong load_addr, load_bias;
 | 
					    abi_ulong load_addr, load_bias;
 | 
				
			||||||
    int load_addr_set = 0;
 | 
					    int load_addr_set = 0;
 | 
				
			||||||
    unsigned char ibcs2_interpreter;
 | 
					 | 
				
			||||||
    int i;
 | 
					    int i;
 | 
				
			||||||
    abi_ulong mapped_addr;
 | 
					 | 
				
			||||||
    struct elf_phdr * elf_ppnt;
 | 
					    struct elf_phdr * elf_ppnt;
 | 
				
			||||||
    struct elf_phdr *elf_phdata;
 | 
					    struct elf_phdr *elf_phdata;
 | 
				
			||||||
    abi_ulong k, elf_brk;
 | 
					    abi_ulong k, elf_brk;
 | 
				
			||||||
    int retval;
 | 
					    int retval;
 | 
				
			||||||
    char * elf_interpreter;
 | 
					    char *elf_interpreter = NULL;
 | 
				
			||||||
    abi_ulong elf_entry, interp_load_addr = 0;
 | 
					    abi_ulong elf_entry;
 | 
				
			||||||
    int status;
 | 
					    int status;
 | 
				
			||||||
    abi_ulong start_code, end_code, start_data, end_data;
 | 
					    abi_ulong start_code, end_code, start_data, end_data;
 | 
				
			||||||
    abi_ulong reloc_func_desc = 0;
 | 
					 | 
				
			||||||
    abi_ulong elf_stack;
 | 
					    abi_ulong elf_stack;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ibcs2_interpreter = 0;
 | 
					 | 
				
			||||||
    status = 0;
 | 
					    status = 0;
 | 
				
			||||||
    load_addr = 0;
 | 
					    load_addr = 0;
 | 
				
			||||||
    load_bias = 0;
 | 
					    load_bias = 0;
 | 
				
			||||||
@ -1467,7 +1535,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    elf_brk = 0;
 | 
					    elf_brk = 0;
 | 
				
			||||||
    elf_stack = ~((abi_ulong)0UL);
 | 
					    elf_stack = ~((abi_ulong)0UL);
 | 
				
			||||||
    elf_interpreter = NULL;
 | 
					 | 
				
			||||||
    start_code = ~((abi_ulong)0UL);
 | 
					    start_code = ~((abi_ulong)0UL);
 | 
				
			||||||
    end_code = 0;
 | 
					    end_code = 0;
 | 
				
			||||||
    start_data = 0;
 | 
					    start_data = 0;
 | 
				
			||||||
@ -1476,82 +1543,21 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 | 
				
			|||||||
    elf_ppnt = elf_phdata;
 | 
					    elf_ppnt = elf_phdata;
 | 
				
			||||||
    for(i=0;i < elf_ex.e_phnum; i++) {
 | 
					    for(i=0;i < elf_ex.e_phnum; i++) {
 | 
				
			||||||
        if (elf_ppnt->p_type == PT_INTERP) {
 | 
					        if (elf_ppnt->p_type == PT_INTERP) {
 | 
				
			||||||
            if ( elf_interpreter != NULL )
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                free (elf_phdata);
 | 
					 | 
				
			||||||
                free(elf_interpreter);
 | 
					 | 
				
			||||||
                close(bprm->fd);
 | 
					 | 
				
			||||||
                return -EINVAL;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            /* This is the program interpreter used for
 | 
					 | 
				
			||||||
             * shared libraries - for now assume that this
 | 
					 | 
				
			||||||
             * is an a.out format binary
 | 
					 | 
				
			||||||
             */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            elf_interpreter = (char *)malloc(elf_ppnt->p_filesz);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (elf_interpreter == NULL) {
 | 
					 | 
				
			||||||
                free (elf_phdata);
 | 
					 | 
				
			||||||
                close(bprm->fd);
 | 
					 | 
				
			||||||
                return -ENOMEM;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (elf_ppnt->p_offset + elf_ppnt->p_filesz <= BPRM_BUF_SIZE) {
 | 
					            if (elf_ppnt->p_offset + elf_ppnt->p_filesz <= BPRM_BUF_SIZE) {
 | 
				
			||||||
                memcpy(elf_interpreter, bprm->buf + elf_ppnt->p_offset,
 | 
					                elf_interpreter = bprm->buf + elf_ppnt->p_offset;
 | 
				
			||||||
                       elf_ppnt->p_filesz);
 | 
					 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
 | 
					                elf_interpreter = alloca(elf_ppnt->p_filesz);
 | 
				
			||||||
                retval = pread(bprm->fd, elf_interpreter, elf_ppnt->p_filesz,
 | 
					                retval = pread(bprm->fd, elf_interpreter, elf_ppnt->p_filesz,
 | 
				
			||||||
                               elf_ppnt->p_offset);
 | 
					                               elf_ppnt->p_offset);
 | 
				
			||||||
                if (retval != elf_ppnt->p_filesz) {
 | 
					                if (retval != elf_ppnt->p_filesz) {
 | 
				
			||||||
                    perror("load_elf_binary2");
 | 
					                    perror("load_elf_binary");
 | 
				
			||||||
                    exit(-1);
 | 
					                    exit(-1);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					 | 
				
			||||||
            /* If the program interpreter is one of these two,
 | 
					 | 
				
			||||||
               then assume an iBCS2 image. Otherwise assume
 | 
					 | 
				
			||||||
               a native linux image. */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            /* JRP - Need to add X86 lib dir stuff here... */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
 | 
					 | 
				
			||||||
                strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) {
 | 
					 | 
				
			||||||
                ibcs2_interpreter = 1;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            retval = open(path(elf_interpreter), O_RDONLY);
 | 
					 | 
				
			||||||
            if (retval < 0) {
 | 
					 | 
				
			||||||
                perror(elf_interpreter);
 | 
					 | 
				
			||||||
                exit(-1);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            interpreter_fd = retval;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            retval = read(interpreter_fd, bprm->buf, BPRM_BUF_SIZE);
 | 
					 | 
				
			||||||
            if (retval < 0) {
 | 
					 | 
				
			||||||
                perror("load_elf_binary3");
 | 
					 | 
				
			||||||
                exit(-1);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if (retval < BPRM_BUF_SIZE) {
 | 
					 | 
				
			||||||
                memset(bprm->buf, 0, BPRM_BUF_SIZE - retval);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            interp_elf_ex = *((struct elfhdr *) bprm->buf);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        elf_ppnt++;
 | 
					        elf_ppnt++;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Some simple consistency checks for the interpreter */
 | 
					 | 
				
			||||||
    if (elf_interpreter) {
 | 
					 | 
				
			||||||
        if (!elf_check_ident(&interp_elf_ex)) {
 | 
					 | 
				
			||||||
            free(elf_interpreter);
 | 
					 | 
				
			||||||
            free(elf_phdata);
 | 
					 | 
				
			||||||
            close(bprm->fd);
 | 
					 | 
				
			||||||
            close(interpreter_fd);
 | 
					 | 
				
			||||||
            return -ELIBBAD;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* OK, This is the point of no return */
 | 
					    /* OK, This is the point of no return */
 | 
				
			||||||
    info->end_data = 0;
 | 
					    info->end_data = 0;
 | 
				
			||||||
    info->end_code = 0;
 | 
					    info->end_code = 0;
 | 
				
			||||||
@ -1710,7 +1716,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 | 
				
			|||||||
                load_bias += error -
 | 
					                load_bias += error -
 | 
				
			||||||
                    TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
 | 
					                    TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
 | 
				
			||||||
                load_addr += load_bias;
 | 
					                load_addr += load_bias;
 | 
				
			||||||
                reloc_func_desc = load_bias;
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        k = elf_ppnt->p_vaddr;
 | 
					        k = elf_ppnt->p_vaddr;
 | 
				
			||||||
@ -1743,19 +1748,15 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 | 
				
			|||||||
    start_data += load_bias;
 | 
					    start_data += load_bias;
 | 
				
			||||||
    end_data += load_bias;
 | 
					    end_data += load_bias;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (elf_interpreter) {
 | 
					    info->load_bias = load_bias;
 | 
				
			||||||
        elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
 | 
					    info->load_addr = load_addr;
 | 
				
			||||||
                                    &interp_load_addr, bprm->buf);
 | 
					    info->entry = elf_entry;
 | 
				
			||||||
        reloc_func_desc = interp_load_addr;
 | 
					    info->start_brk = info->brk = elf_brk;
 | 
				
			||||||
        free(elf_interpreter);
 | 
					    info->end_code = end_code;
 | 
				
			||||||
 | 
					    info->start_code = start_code;
 | 
				
			||||||
        if (elf_entry == ~((abi_ulong)0UL)) {
 | 
					    info->start_data = start_data;
 | 
				
			||||||
            printf("Unable to load interpreter\n");
 | 
					    info->end_data = end_data;
 | 
				
			||||||
            free(elf_phdata);
 | 
					    info->personality = PER_LINUX;
 | 
				
			||||||
            exit(-1);
 | 
					 | 
				
			||||||
            return 0;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    free(elf_phdata);
 | 
					    free(elf_phdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1764,46 +1765,38 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    close(bprm->fd);
 | 
					    close(bprm->fd);
 | 
				
			||||||
    info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef LOW_ELF_STACK
 | 
					    if (elf_interpreter) {
 | 
				
			||||||
    info->start_stack = bprm->p = elf_stack - 4;
 | 
					        load_elf_interp(elf_interpreter, &interp_info, bprm->buf);
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
    bprm->p = create_elf_tables(bprm->p,
 | 
					 | 
				
			||||||
                                bprm->argc,
 | 
					 | 
				
			||||||
                                bprm->envc,
 | 
					 | 
				
			||||||
                                &elf_ex,
 | 
					 | 
				
			||||||
                                load_addr, load_bias,
 | 
					 | 
				
			||||||
                                interp_load_addr,
 | 
					 | 
				
			||||||
                                info);
 | 
					 | 
				
			||||||
    info->load_addr = reloc_func_desc;
 | 
					 | 
				
			||||||
    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->start_stack = bprm->p;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if 0
 | 
					        /* If the program interpreter is one of these two, then assume
 | 
				
			||||||
    printf("(start_brk) %x\n" , info->start_brk);
 | 
					           an iBCS2 image.  Otherwise assume a native linux image.  */
 | 
				
			||||||
    printf("(end_code) %x\n" , info->end_code);
 | 
					
 | 
				
			||||||
    printf("(start_code) %x\n" , info->start_code);
 | 
					        if (strcmp(elf_interpreter, "/usr/lib/libc.so.1") == 0
 | 
				
			||||||
    printf("(end_data) %x\n" , info->end_data);
 | 
					            || strcmp(elf_interpreter, "/usr/lib/ld.so.1") == 0) {
 | 
				
			||||||
    printf("(start_stack) %x\n" , info->start_stack);
 | 
					            info->personality = PER_SVR4;
 | 
				
			||||||
    printf("(brk) %x\n" , info->brk);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ( info->personality == PER_SVR4 )
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
            /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
 | 
					            /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
 | 
				
			||||||
           and some applications "depend" upon this behavior.
 | 
					               and some applications "depend" upon this behavior.  Since
 | 
				
			||||||
           Since we do not have the power to recompile these, we
 | 
					               we do not have the power to recompile these, we emulate
 | 
				
			||||||
           emulate the SVr4 behavior.  Sigh.  */
 | 
					               the SVr4 behavior.  Sigh.  */
 | 
				
			||||||
        mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
 | 
					            target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
 | 
				
			||||||
                        MAP_FIXED | MAP_PRIVATE, -1, 0);
 | 
					                        MAP_FIXED | MAP_PRIVATE, -1, 0);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    info->entry = elf_entry;
 | 
					    bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &elf_ex,
 | 
				
			||||||
 | 
					                                info, (elf_interpreter ? &interp_info : NULL));
 | 
				
			||||||
 | 
					    info->start_stack = bprm->p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* If we have an interpreter, set that as the program's entry point.
 | 
				
			||||||
 | 
					       Copy the load_addr as well, to help PPC64 interpret the entry
 | 
				
			||||||
 | 
					       point as a function descriptor.  Do this after creating elf tables
 | 
				
			||||||
 | 
					       so that we copy the original program entry point into the AUXV.  */
 | 
				
			||||||
 | 
					    if (elf_interpreter) {
 | 
				
			||||||
 | 
					        info->load_addr = interp_info.load_addr;
 | 
				
			||||||
 | 
					        info->entry = interp_info.entry;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef USE_ELF_CORE_DUMP
 | 
					#ifdef USE_ELF_CORE_DUMP
 | 
				
			||||||
    bprm->core_dump = &elf_core_dump;
 | 
					    bprm->core_dump = &elf_core_dump;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user