Merge remote-tracking branch 'riku/linux-user-for-upstream' into staging
This commit is contained in:
		
						commit
						cd59dd8734
					
				@ -440,15 +440,16 @@ uint32_t do_arm_semihosting(CPUState *env)
 | 
			
		||||
            /* Some C libraries assume the heap immediately follows .bss, so
 | 
			
		||||
               allocate it using sbrk.  */
 | 
			
		||||
            if (!ts->heap_limit) {
 | 
			
		||||
                long ret;
 | 
			
		||||
                abi_ulong ret;
 | 
			
		||||
 | 
			
		||||
                ts->heap_base = do_brk(0);
 | 
			
		||||
                limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE;
 | 
			
		||||
                /* Try a big heap, and reduce the size if that fails.  */
 | 
			
		||||
                for (;;) {
 | 
			
		||||
                    ret = do_brk(limit);
 | 
			
		||||
                    if (ret != -1)
 | 
			
		||||
                    if (ret >= limit) {
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                    limit = (ts->heap_base >> 1) + (limit >> 1);
 | 
			
		||||
                }
 | 
			
		||||
                ts->heap_limit = limit;
 | 
			
		||||
 | 
			
		||||
@ -927,7 +927,7 @@ struct exec
 | 
			
		||||
#define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
 | 
			
		||||
#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
 | 
			
		||||
 | 
			
		||||
#define DLINFO_ITEMS 12
 | 
			
		||||
#define DLINFO_ITEMS 13
 | 
			
		||||
 | 
			
		||||
static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
 | 
			
		||||
{
 | 
			
		||||
@ -1202,6 +1202,9 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
 | 
			
		||||
{
 | 
			
		||||
    abi_ulong sp;
 | 
			
		||||
    int size;
 | 
			
		||||
    int i;
 | 
			
		||||
    abi_ulong u_rand_bytes;
 | 
			
		||||
    uint8_t k_rand_bytes[16];
 | 
			
		||||
    abi_ulong u_platform;
 | 
			
		||||
    const char *k_platform;
 | 
			
		||||
    const int n = sizeof(elf_addr_t);
 | 
			
		||||
@ -1231,6 +1234,20 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
 | 
			
		||||
        /* FIXME - check return value of memcpy_to_target() for failure */
 | 
			
		||||
        memcpy_to_target(sp, k_platform, len);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * Generate 16 random bytes for userspace PRNG seeding (not
 | 
			
		||||
     * cryptically secure but it's not the aim of QEMU).
 | 
			
		||||
     */
 | 
			
		||||
    srand((unsigned int) time(NULL));
 | 
			
		||||
    for (i = 0; i < 16; i++) {
 | 
			
		||||
        k_rand_bytes[i] = rand();
 | 
			
		||||
    }
 | 
			
		||||
    sp -= 16;
 | 
			
		||||
    u_rand_bytes = sp;
 | 
			
		||||
    /* FIXME - check return value of memcpy_to_target() for failure */
 | 
			
		||||
    memcpy_to_target(sp, k_rand_bytes, 16);
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * Force 16 byte _final_ alignment here for generality.
 | 
			
		||||
     */
 | 
			
		||||
@ -1271,6 +1288,8 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
 | 
			
		||||
    NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
 | 
			
		||||
    NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
 | 
			
		||||
    NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
 | 
			
		||||
    NEW_AUX_ENT(AT_RANDOM, (abi_ulong) u_rand_bytes);
 | 
			
		||||
 | 
			
		||||
    if (k_platform)
 | 
			
		||||
        NEW_AUX_ENT(AT_PLATFORM, u_platform);
 | 
			
		||||
#ifdef ARCH_DLINFO
 | 
			
		||||
@ -1288,6 +1307,78 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
 | 
			
		||||
    return sp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void probe_guest_base(const char *image_name,
 | 
			
		||||
                             abi_ulong loaddr, abi_ulong hiaddr)
 | 
			
		||||
{
 | 
			
		||||
    /* Probe for a suitable guest base address, if the user has not set
 | 
			
		||||
     * it explicitly, and set guest_base appropriately.
 | 
			
		||||
     * In case of error we will print a suitable message and exit.
 | 
			
		||||
     */
 | 
			
		||||
#if defined(CONFIG_USE_GUEST_BASE)
 | 
			
		||||
    const char *errmsg;
 | 
			
		||||
    if (!have_guest_base && !reserved_va) {
 | 
			
		||||
        unsigned long host_start, real_start, host_size;
 | 
			
		||||
 | 
			
		||||
        /* Round addresses to page boundaries.  */
 | 
			
		||||
        loaddr &= qemu_host_page_mask;
 | 
			
		||||
        hiaddr = HOST_PAGE_ALIGN(hiaddr);
 | 
			
		||||
 | 
			
		||||
        if (loaddr < mmap_min_addr) {
 | 
			
		||||
            host_start = HOST_PAGE_ALIGN(mmap_min_addr);
 | 
			
		||||
        } else {
 | 
			
		||||
            host_start = loaddr;
 | 
			
		||||
            if (host_start != loaddr) {
 | 
			
		||||
                errmsg = "Address overflow loading ELF binary";
 | 
			
		||||
                goto exit_errmsg;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        host_size = hiaddr - loaddr;
 | 
			
		||||
        while (1) {
 | 
			
		||||
            /* Do not use mmap_find_vma here because that is limited to the
 | 
			
		||||
               guest address space.  We are going to make the
 | 
			
		||||
               guest address space fit whatever we're given.  */
 | 
			
		||||
            real_start = (unsigned long)
 | 
			
		||||
                mmap((void *)host_start, host_size, PROT_NONE,
 | 
			
		||||
                     MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
 | 
			
		||||
            if (real_start == (unsigned long)-1) {
 | 
			
		||||
                goto exit_perror;
 | 
			
		||||
            }
 | 
			
		||||
            if (real_start == host_start) {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            /* That address didn't work.  Unmap and try a different one.
 | 
			
		||||
               The address the host picked because is typically right at
 | 
			
		||||
               the top of the host address space and leaves the guest with
 | 
			
		||||
               no usable address space.  Resort to a linear search.  We
 | 
			
		||||
               already compensated for mmap_min_addr, so this should not
 | 
			
		||||
               happen often.  Probably means we got unlucky and host
 | 
			
		||||
               address space randomization put a shared library somewhere
 | 
			
		||||
               inconvenient.  */
 | 
			
		||||
            munmap((void *)real_start, host_size);
 | 
			
		||||
            host_start += qemu_host_page_size;
 | 
			
		||||
            if (host_start == loaddr) {
 | 
			
		||||
                /* Theoretically possible if host doesn't have any suitably
 | 
			
		||||
                   aligned areas.  Normally the first mmap will fail.  */
 | 
			
		||||
                errmsg = "Unable to find space for application";
 | 
			
		||||
                goto exit_errmsg;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        qemu_log("Relocating guest address space from 0x"
 | 
			
		||||
                 TARGET_ABI_FMT_lx " to 0x%lx\n",
 | 
			
		||||
                 loaddr, real_start);
 | 
			
		||||
        guest_base = real_start - loaddr;
 | 
			
		||||
    }
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
exit_perror:
 | 
			
		||||
    errmsg = strerror(errno);
 | 
			
		||||
exit_errmsg:
 | 
			
		||||
    fprintf(stderr, "%s: %s\n", image_name, errmsg);
 | 
			
		||||
    exit(-1);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Load an ELF image into the address space.
 | 
			
		||||
 | 
			
		||||
   IMAGE_NAME is the filename of the image, to use in error messages.
 | 
			
		||||
@ -1373,63 +1464,7 @@ static void load_elf_image(const char *image_name, int image_fd,
 | 
			
		||||
        /* This is the main executable.  Make sure that the low
 | 
			
		||||
           address does not conflict with MMAP_MIN_ADDR or the
 | 
			
		||||
           QEMU application itself.  */
 | 
			
		||||
#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 && !reserved_va) {
 | 
			
		||||
            unsigned long host_start, real_start, host_size;
 | 
			
		||||
 | 
			
		||||
            /* Round addresses to page boundaries.  */
 | 
			
		||||
            loaddr &= qemu_host_page_mask;
 | 
			
		||||
            hiaddr = HOST_PAGE_ALIGN(hiaddr);
 | 
			
		||||
 | 
			
		||||
            if (loaddr < mmap_min_addr) {
 | 
			
		||||
                host_start = HOST_PAGE_ALIGN(mmap_min_addr);
 | 
			
		||||
            } else {
 | 
			
		||||
                host_start = loaddr;
 | 
			
		||||
                if (host_start != loaddr) {
 | 
			
		||||
                    errmsg = "Address overflow loading ELF binary";
 | 
			
		||||
                    goto exit_errmsg;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            host_size = hiaddr - loaddr;
 | 
			
		||||
            while (1) {
 | 
			
		||||
                /* Do not use mmap_find_vma here because that is limited to the
 | 
			
		||||
                   guest address space.  We are going to make the
 | 
			
		||||
                   guest address space fit whatever we're given.  */
 | 
			
		||||
                real_start = (unsigned long)
 | 
			
		||||
                    mmap((void *)host_start, host_size, PROT_NONE,
 | 
			
		||||
                         MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
 | 
			
		||||
                if (real_start == (unsigned long)-1) {
 | 
			
		||||
                    goto exit_perror;
 | 
			
		||||
                }
 | 
			
		||||
                if (real_start == host_start) {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                /* That address didn't work.  Unmap and try a different one.
 | 
			
		||||
                   The address the host picked because is typically right at
 | 
			
		||||
                   the top of the host address space and leaves the guest with
 | 
			
		||||
                   no usable address space.  Resort to a linear search.  We
 | 
			
		||||
                   already compensated for mmap_min_addr, so this should not
 | 
			
		||||
                   happen often.  Probably means we got unlucky and host
 | 
			
		||||
                   address space randomization put a shared library somewhere
 | 
			
		||||
                   inconvenient.  */
 | 
			
		||||
                munmap((void *)real_start, host_size);
 | 
			
		||||
                host_start += qemu_host_page_size;
 | 
			
		||||
                if (host_start == loaddr) {
 | 
			
		||||
                    /* Theoretically possible if host doesn't have any suitably
 | 
			
		||||
                       aligned areas.  Normally the first mmap will fail.  */
 | 
			
		||||
                    errmsg = "Unable to find space for application";
 | 
			
		||||
                    goto exit_errmsg;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            qemu_log("Relocating guest address space from 0x"
 | 
			
		||||
                     TARGET_ABI_FMT_lx " to 0x%lx\n", loaddr, real_start);
 | 
			
		||||
            guest_base = real_start - loaddr;
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
        probe_guest_base(image_name, loaddr, hiaddr);
 | 
			
		||||
    }
 | 
			
		||||
    load_bias = load_addr - loaddr;
 | 
			
		||||
 | 
			
		||||
@ -1643,9 +1678,9 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
 | 
			
		||||
{
 | 
			
		||||
    int i, shnum, nsyms, sym_idx = 0, str_idx = 0;
 | 
			
		||||
    struct elf_shdr *shdr;
 | 
			
		||||
    char *strings;
 | 
			
		||||
    struct syminfo *s;
 | 
			
		||||
    struct elf_sym *syms, *new_syms;
 | 
			
		||||
    char *strings = NULL;
 | 
			
		||||
    struct syminfo *s = NULL;
 | 
			
		||||
    struct elf_sym *new_syms, *syms = NULL;
 | 
			
		||||
 | 
			
		||||
    shnum = hdr->e_shnum;
 | 
			
		||||
    i = shnum * sizeof(struct elf_shdr);
 | 
			
		||||
@ -1670,24 +1705,19 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
 | 
			
		||||
    /* Now know where the strtab and symtab are.  Snarf them.  */
 | 
			
		||||
    s = malloc(sizeof(*s));
 | 
			
		||||
    if (!s) {
 | 
			
		||||
        return;
 | 
			
		||||
        goto give_up;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    i = shdr[str_idx].sh_size;
 | 
			
		||||
    s->disas_strtab = strings = malloc(i);
 | 
			
		||||
    if (!strings || pread(fd, strings, i, shdr[str_idx].sh_offset) != i) {
 | 
			
		||||
        free(s);
 | 
			
		||||
        free(strings);
 | 
			
		||||
        return;
 | 
			
		||||
        goto give_up;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    i = shdr[sym_idx].sh_size;
 | 
			
		||||
    syms = malloc(i);
 | 
			
		||||
    if (!syms || pread(fd, syms, i, shdr[sym_idx].sh_offset) != i) {
 | 
			
		||||
        free(s);
 | 
			
		||||
        free(strings);
 | 
			
		||||
        free(syms);
 | 
			
		||||
        return;
 | 
			
		||||
        goto give_up;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    nsyms = i / sizeof(struct elf_sym);
 | 
			
		||||
@ -1710,16 +1740,18 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* No "useful" symbol.  */
 | 
			
		||||
    if (nsyms == 0) {
 | 
			
		||||
        goto give_up;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Attempt to free the storage associated with the local symbols
 | 
			
		||||
       that we threw away.  Whether or not this has any effect on the
 | 
			
		||||
       memory allocation depends on the malloc implementation and how
 | 
			
		||||
       many symbols we managed to discard.  */
 | 
			
		||||
    new_syms = realloc(syms, nsyms * sizeof(*syms));
 | 
			
		||||
    if (new_syms == NULL) {
 | 
			
		||||
        free(s);
 | 
			
		||||
        free(syms);
 | 
			
		||||
        free(strings);
 | 
			
		||||
        return;
 | 
			
		||||
        goto give_up;
 | 
			
		||||
    }
 | 
			
		||||
    syms = new_syms;
 | 
			
		||||
 | 
			
		||||
@ -1734,6 +1766,13 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
 | 
			
		||||
    s->lookup_symbol = lookup_symbolxx;
 | 
			
		||||
    s->next = syminfos;
 | 
			
		||||
    syminfos = s;
 | 
			
		||||
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
give_up:
 | 
			
		||||
    free(s);
 | 
			
		||||
    free(strings);
 | 
			
		||||
    free(syms);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 | 
			
		||||
 | 
			
		||||
@ -379,12 +379,11 @@ static int load_flat_file(struct linux_binprm * bprm,
 | 
			
		||||
    abi_long result;
 | 
			
		||||
    abi_ulong realdatastart = 0;
 | 
			
		||||
    abi_ulong text_len, data_len, bss_len, stack_len, flags;
 | 
			
		||||
    abi_ulong memp = 0; /* for finding the brk area */
 | 
			
		||||
    abi_ulong extra;
 | 
			
		||||
    abi_ulong reloc = 0, rp;
 | 
			
		||||
    int i, rev, relocs = 0;
 | 
			
		||||
    abi_ulong fpos;
 | 
			
		||||
    abi_ulong start_code, end_code;
 | 
			
		||||
    abi_ulong start_code;
 | 
			
		||||
    abi_ulong indx_len;
 | 
			
		||||
 | 
			
		||||
    hdr = ((struct flat_hdr *) bprm->buf);		/* exec-header */
 | 
			
		||||
@ -491,7 +490,6 @@ static int load_flat_file(struct linux_binprm * bprm,
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        reloc = datapos + (ntohl(hdr->reloc_start) - text_len);
 | 
			
		||||
        memp = realdatastart;
 | 
			
		||||
 | 
			
		||||
    } else {
 | 
			
		||||
 | 
			
		||||
@ -506,7 +504,6 @@ static int load_flat_file(struct linux_binprm * bprm,
 | 
			
		||||
        realdatastart = textpos + ntohl(hdr->data_start);
 | 
			
		||||
        datapos = realdatastart + indx_len;
 | 
			
		||||
        reloc = (textpos + ntohl(hdr->reloc_start) + indx_len);
 | 
			
		||||
        memp = textpos;
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_BINFMT_ZFLAT
 | 
			
		||||
#error code needs checking
 | 
			
		||||
@ -552,11 +549,10 @@ static int load_flat_file(struct linux_binprm * bprm,
 | 
			
		||||
 | 
			
		||||
    /* The main program needs a little extra setup in the task structure */
 | 
			
		||||
    start_code = textpos + sizeof (struct flat_hdr);
 | 
			
		||||
    end_code = textpos + text_len;
 | 
			
		||||
 | 
			
		||||
    DBG_FLT("%s %s: TEXT=%x-%x DATA=%x-%x BSS=%x-%x\n",
 | 
			
		||||
            id ? "Lib" : "Load", bprm->filename,
 | 
			
		||||
            (int) start_code, (int) end_code,
 | 
			
		||||
            (int) start_code, (int) (textpos + text_len),
 | 
			
		||||
            (int) datapos,
 | 
			
		||||
            (int) (datapos + data_len),
 | 
			
		||||
            (int) (datapos + data_len),
 | 
			
		||||
 | 
			
		||||
@ -26,22 +26,6 @@ abi_long memcpy_to_target(abi_ulong dest, const void *src,
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int in_group_p(gid_t g)
 | 
			
		||||
{
 | 
			
		||||
    /* return TRUE if we're in the specified group, FALSE otherwise */
 | 
			
		||||
    int		ngroup;
 | 
			
		||||
    int		i;
 | 
			
		||||
    gid_t	grouplist[NGROUPS];
 | 
			
		||||
 | 
			
		||||
    ngroup = getgroups(NGROUPS, grouplist);
 | 
			
		||||
    for(i = 0; i < ngroup; i++) {
 | 
			
		||||
	if(grouplist[i] == g) {
 | 
			
		||||
	    return 1;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int count(char ** vec)
 | 
			
		||||
{
 | 
			
		||||
    int		i;
 | 
			
		||||
@ -57,7 +41,7 @@ static int prepare_binprm(struct linux_binprm *bprm)
 | 
			
		||||
{
 | 
			
		||||
    struct stat		st;
 | 
			
		||||
    int mode;
 | 
			
		||||
    int retval, id_change;
 | 
			
		||||
    int retval;
 | 
			
		||||
 | 
			
		||||
    if(fstat(bprm->fd, &st) < 0) {
 | 
			
		||||
	return(-errno);
 | 
			
		||||
@ -73,14 +57,10 @@ static int prepare_binprm(struct linux_binprm *bprm)
 | 
			
		||||
 | 
			
		||||
    bprm->e_uid = geteuid();
 | 
			
		||||
    bprm->e_gid = getegid();
 | 
			
		||||
    id_change = 0;
 | 
			
		||||
 | 
			
		||||
    /* Set-uid? */
 | 
			
		||||
    if(mode & S_ISUID) {
 | 
			
		||||
    	bprm->e_uid = st.st_uid;
 | 
			
		||||
	if(bprm->e_uid != geteuid()) {
 | 
			
		||||
	    id_change = 1;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Set-gid? */
 | 
			
		||||
@ -91,9 +71,6 @@ static int prepare_binprm(struct linux_binprm *bprm)
 | 
			
		||||
     */
 | 
			
		||||
    if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
 | 
			
		||||
	bprm->e_gid = st.st_gid;
 | 
			
		||||
	if (!in_group_p(bprm->e_gid)) {
 | 
			
		||||
		id_change = 1;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    retval = read(bprm->fd, bprm->buf, BPRM_BUF_SIZE);
 | 
			
		||||
 | 
			
		||||
@ -318,7 +318,8 @@ void cpu_loop(CPUX86State *env)
 | 
			
		||||
                                          env->regs[R_EDX],
 | 
			
		||||
                                          env->regs[R_ESI],
 | 
			
		||||
                                          env->regs[R_EDI],
 | 
			
		||||
                                          env->regs[R_EBP]);
 | 
			
		||||
                                          env->regs[R_EBP],
 | 
			
		||||
                                          0, 0);
 | 
			
		||||
            break;
 | 
			
		||||
#ifndef TARGET_ABI32
 | 
			
		||||
        case EXCP_SYSCALL:
 | 
			
		||||
@ -330,7 +331,8 @@ void cpu_loop(CPUX86State *env)
 | 
			
		||||
                                          env->regs[R_EDX],
 | 
			
		||||
                                          env->regs[10],
 | 
			
		||||
                                          env->regs[8],
 | 
			
		||||
                                          env->regs[9]);
 | 
			
		||||
                                          env->regs[9],
 | 
			
		||||
                                          0, 0);
 | 
			
		||||
            env->eip = env->exception_next_eip;
 | 
			
		||||
            break;
 | 
			
		||||
#endif
 | 
			
		||||
@ -734,7 +736,8 @@ void cpu_loop(CPUARMState *env)
 | 
			
		||||
                                                  env->regs[2],
 | 
			
		||||
                                                  env->regs[3],
 | 
			
		||||
                                                  env->regs[4],
 | 
			
		||||
                                                  env->regs[5]);
 | 
			
		||||
                                                  env->regs[5],
 | 
			
		||||
                                                  0, 0);
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    goto error;
 | 
			
		||||
@ -830,7 +833,8 @@ void cpu_loop(CPUState *env)
 | 
			
		||||
                                                  env->regs[2],
 | 
			
		||||
                                                  env->regs[3],
 | 
			
		||||
                                                  env->regs[4],
 | 
			
		||||
                                                  env->regs[5]);
 | 
			
		||||
                                                  env->regs[5],
 | 
			
		||||
                                                  0, 0);
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    goto error;
 | 
			
		||||
@ -1017,7 +1021,8 @@ void cpu_loop (CPUSPARCState *env)
 | 
			
		||||
            ret = do_syscall (env, env->gregs[1],
 | 
			
		||||
                              env->regwptr[0], env->regwptr[1],
 | 
			
		||||
                              env->regwptr[2], env->regwptr[3],
 | 
			
		||||
                              env->regwptr[4], env->regwptr[5]);
 | 
			
		||||
                              env->regwptr[4], env->regwptr[5],
 | 
			
		||||
                              0, 0);
 | 
			
		||||
            if ((abi_ulong)ret >= (abi_ulong)(-515)) {
 | 
			
		||||
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
 | 
			
		||||
                env->xcc |= PSR_CARRY;
 | 
			
		||||
@ -1610,7 +1615,7 @@ void cpu_loop(CPUPPCState *env)
 | 
			
		||||
            env->crf[0] &= ~0x1;
 | 
			
		||||
            ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
 | 
			
		||||
                             env->gpr[5], env->gpr[6], env->gpr[7],
 | 
			
		||||
                             env->gpr[8]);
 | 
			
		||||
                             env->gpr[8], 0, 0);
 | 
			
		||||
            if (ret == (uint32_t)(-TARGET_QEMU_ESIGRETURN)) {
 | 
			
		||||
                /* Returning from a successful sigreturn syscall.
 | 
			
		||||
                   Avoid corrupting register state.  */
 | 
			
		||||
@ -2071,7 +2076,7 @@ void cpu_loop(CPUMIPSState *env)
 | 
			
		||||
                                 env->active_tc.gpr[5],
 | 
			
		||||
                                 env->active_tc.gpr[6],
 | 
			
		||||
                                 env->active_tc.gpr[7],
 | 
			
		||||
                                 arg5, arg6/*, arg7, arg8*/);
 | 
			
		||||
                                 arg5, arg6, arg7, arg8);
 | 
			
		||||
            }
 | 
			
		||||
            if (ret == -TARGET_QEMU_ESIGRETURN) {
 | 
			
		||||
                /* Returning from a successful sigreturn syscall.
 | 
			
		||||
@ -2159,7 +2164,8 @@ void cpu_loop (CPUState *env)
 | 
			
		||||
                             env->gregs[6],
 | 
			
		||||
                             env->gregs[7],
 | 
			
		||||
                             env->gregs[0],
 | 
			
		||||
                             env->gregs[1]);
 | 
			
		||||
                             env->gregs[1],
 | 
			
		||||
                             0, 0);
 | 
			
		||||
            env->gregs[0] = ret;
 | 
			
		||||
            break;
 | 
			
		||||
        case EXCP_INTERRUPT:
 | 
			
		||||
@ -2228,7 +2234,8 @@ void cpu_loop (CPUState *env)
 | 
			
		||||
                             env->regs[12], 
 | 
			
		||||
                             env->regs[13], 
 | 
			
		||||
                             env->pregs[7], 
 | 
			
		||||
                             env->pregs[11]);
 | 
			
		||||
                             env->pregs[11],
 | 
			
		||||
                             0, 0);
 | 
			
		||||
            env->regs[10] = ret;
 | 
			
		||||
            break;
 | 
			
		||||
        case EXCP_DEBUG:
 | 
			
		||||
@ -2287,7 +2294,8 @@ void cpu_loop (CPUState *env)
 | 
			
		||||
                             env->regs[7], 
 | 
			
		||||
                             env->regs[8], 
 | 
			
		||||
                             env->regs[9], 
 | 
			
		||||
                             env->regs[10]);
 | 
			
		||||
                             env->regs[10],
 | 
			
		||||
                             0, 0);
 | 
			
		||||
            env->regs[3] = ret;
 | 
			
		||||
            env->sregs[SR_PC] = env->regs[14];
 | 
			
		||||
            break;
 | 
			
		||||
@ -2397,7 +2405,8 @@ void cpu_loop(CPUM68KState *env)
 | 
			
		||||
                                          env->dregs[3],
 | 
			
		||||
                                          env->dregs[4],
 | 
			
		||||
                                          env->dregs[5],
 | 
			
		||||
                                          env->aregs[0]);
 | 
			
		||||
                                          env->aregs[0],
 | 
			
		||||
                                          0, 0);
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case EXCP_INTERRUPT:
 | 
			
		||||
@ -2575,7 +2584,8 @@ void cpu_loop (CPUState *env)
 | 
			
		||||
                sysret = do_syscall(env, trapnr,
 | 
			
		||||
                                    env->ir[IR_A0], env->ir[IR_A1],
 | 
			
		||||
                                    env->ir[IR_A2], env->ir[IR_A3],
 | 
			
		||||
                                    env->ir[IR_A4], env->ir[IR_A5]);
 | 
			
		||||
                                    env->ir[IR_A4], env->ir[IR_A5],
 | 
			
		||||
                                    0, 0);
 | 
			
		||||
                if (trapnr == TARGET_NR_sigreturn
 | 
			
		||||
                    || trapnr == TARGET_NR_rt_sigreturn) {
 | 
			
		||||
                    break;
 | 
			
		||||
@ -2706,7 +2716,8 @@ void cpu_loop(CPUS390XState *env)
 | 
			
		||||
                           env->regs[4],
 | 
			
		||||
                           env->regs[5],
 | 
			
		||||
                           env->regs[6],
 | 
			
		||||
                           env->regs[7]);
 | 
			
		||||
                           env->regs[7],
 | 
			
		||||
                           0, 0);
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case EXCP_ADDR:
 | 
			
		||||
 | 
			
		||||
@ -192,7 +192,8 @@ abi_long do_brk(abi_ulong new_brk);
 | 
			
		||||
void syscall_init(void);
 | 
			
		||||
abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 | 
			
		||||
                    abi_long arg2, abi_long arg3, abi_long arg4,
 | 
			
		||||
                    abi_long arg5, abi_long arg6);
 | 
			
		||||
                    abi_long arg5, abi_long arg6, abi_long arg7,
 | 
			
		||||
                    abi_long arg8);
 | 
			
		||||
void gemu_log(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
 | 
			
		||||
extern THREAD CPUState *thread_env;
 | 
			
		||||
void cpu_loop(CPUState *env);
 | 
			
		||||
 | 
			
		||||
@ -981,8 +981,8 @@ restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax)
 | 
			
		||||
        env->regs[R_ECX] = tswapl(sc->ecx);
 | 
			
		||||
        env->eip = tswapl(sc->eip);
 | 
			
		||||
 | 
			
		||||
        cpu_x86_load_seg(env, R_CS, lduw(&sc->cs) | 3);
 | 
			
		||||
        cpu_x86_load_seg(env, R_SS, lduw(&sc->ss) | 3);
 | 
			
		||||
        cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3);
 | 
			
		||||
        cpu_x86_load_seg(env, R_SS, lduw_p(&sc->ss) | 3);
 | 
			
		||||
 | 
			
		||||
        tmpflags = tswapl(sc->eflags);
 | 
			
		||||
        env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
 | 
			
		||||
@ -2080,7 +2080,6 @@ long do_sigreturn(CPUState *env)
 | 
			
		||||
        uint32_t up_psr, pc, npc;
 | 
			
		||||
        target_sigset_t set;
 | 
			
		||||
        sigset_t host_set;
 | 
			
		||||
        abi_ulong fpu_save_addr;
 | 
			
		||||
        int err, i;
 | 
			
		||||
 | 
			
		||||
        sf_addr = env->regwptr[UREG_FP];
 | 
			
		||||
@ -2120,10 +2119,11 @@ long do_sigreturn(CPUState *env)
 | 
			
		||||
		err |= __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        err |= __get_user(fpu_save_addr, &sf->fpu_save);
 | 
			
		||||
 | 
			
		||||
        //if (fpu_save)
 | 
			
		||||
        //        err |= restore_fpu_state(env, fpu_save);
 | 
			
		||||
        /* FIXME: implement FPU save/restore:
 | 
			
		||||
         * __get_user(fpu_save, &sf->fpu_save);
 | 
			
		||||
         * if (fpu_save)
 | 
			
		||||
         *        err |= restore_fpu_state(env, fpu_save);
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
        /* This is pretty much atomic, no amount locking would prevent
 | 
			
		||||
         * the races which exist anyways.
 | 
			
		||||
@ -2228,7 +2228,6 @@ void sparc64_set_context(CPUSPARCState *env)
 | 
			
		||||
    target_mc_gregset_t *grp;
 | 
			
		||||
    abi_ulong pc, npc, tstate;
 | 
			
		||||
    abi_ulong fp, i7, w_addr;
 | 
			
		||||
    unsigned char fenab;
 | 
			
		||||
    int err;
 | 
			
		||||
    unsigned int i;
 | 
			
		||||
 | 
			
		||||
@ -2293,7 +2292,11 @@ void sparc64_set_context(CPUSPARCState *env)
 | 
			
		||||
    if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]), 
 | 
			
		||||
                 abi_ulong) != 0)
 | 
			
		||||
        goto do_sigsegv;
 | 
			
		||||
    err |= __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
 | 
			
		||||
    /* FIXME this does not match how the kernel handles the FPU in
 | 
			
		||||
     * its sparc64_set_context implementation. In particular the FPU
 | 
			
		||||
     * is only restored if fenab is non-zero in:
 | 
			
		||||
     *   __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
 | 
			
		||||
     */
 | 
			
		||||
    err |= __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
 | 
			
		||||
    {
 | 
			
		||||
        uint32_t *src, *dst;
 | 
			
		||||
 | 
			
		||||
@ -550,6 +550,15 @@ _syscall5(int, sys_ppoll, struct pollfd *, fds, nfds_t, nfds,
 | 
			
		||||
          size_t, sigsetsize)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(TARGET_NR_pselect6)
 | 
			
		||||
#ifndef __NR_pselect6
 | 
			
		||||
# define __NR_pselect6 -1
 | 
			
		||||
#endif
 | 
			
		||||
#define __NR_sys_pselect6 __NR_pselect6
 | 
			
		||||
_syscall6(int, sys_pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds,
 | 
			
		||||
          fd_set *, exceptfds, struct timespec *, timeout, void *, sig);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern int personality(int);
 | 
			
		||||
extern int flock(int, int);
 | 
			
		||||
extern int setfsuid(int);
 | 
			
		||||
@ -709,49 +718,81 @@ char *target_strerror(int err)
 | 
			
		||||
 | 
			
		||||
static abi_ulong target_brk;
 | 
			
		||||
static abi_ulong target_original_brk;
 | 
			
		||||
static abi_ulong brk_page;
 | 
			
		||||
 | 
			
		||||
void target_set_brk(abi_ulong new_brk)
 | 
			
		||||
{
 | 
			
		||||
    target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
 | 
			
		||||
    brk_page = HOST_PAGE_ALIGN(target_brk);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//#define DEBUGF_BRK(message, args...) do { fprintf(stderr, (message), ## args); } while (0)
 | 
			
		||||
#define DEBUGF_BRK(message, args...)
 | 
			
		||||
 | 
			
		||||
/* do_brk() must return target values and target errnos. */
 | 
			
		||||
abi_long do_brk(abi_ulong new_brk)
 | 
			
		||||
{
 | 
			
		||||
    abi_ulong brk_page;
 | 
			
		||||
    abi_long mapped_addr;
 | 
			
		||||
    int	new_alloc_size;
 | 
			
		||||
 | 
			
		||||
    if (!new_brk)
 | 
			
		||||
        return target_brk;
 | 
			
		||||
    if (new_brk < target_original_brk)
 | 
			
		||||
        return target_brk;
 | 
			
		||||
    DEBUGF_BRK("do_brk(%#010x) -> ", new_brk);
 | 
			
		||||
 | 
			
		||||
    brk_page = HOST_PAGE_ALIGN(target_brk);
 | 
			
		||||
    if (!new_brk) {
 | 
			
		||||
        DEBUGF_BRK("%#010x (!new_brk)\n", target_brk);
 | 
			
		||||
        return target_brk;
 | 
			
		||||
    }
 | 
			
		||||
    if (new_brk < target_original_brk) {
 | 
			
		||||
        DEBUGF_BRK("%#010x (new_brk < target_original_brk)\n", target_brk);
 | 
			
		||||
        return target_brk;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* If the new brk is less than this, set it and we're done... */
 | 
			
		||||
    if (new_brk < brk_page) {
 | 
			
		||||
    /* If the new brk is less than the highest page reserved to the
 | 
			
		||||
     * target heap allocation, set it and we're almost done...  */
 | 
			
		||||
    if (new_brk <= brk_page) {
 | 
			
		||||
        /* Heap contents are initialized to zero, as for anonymous
 | 
			
		||||
         * mapped pages.  */
 | 
			
		||||
        if (new_brk > target_brk) {
 | 
			
		||||
            memset(g2h(target_brk), 0, new_brk - target_brk);
 | 
			
		||||
        }
 | 
			
		||||
	target_brk = new_brk;
 | 
			
		||||
        DEBUGF_BRK("%#010x (new_brk <= brk_page)\n", target_brk);
 | 
			
		||||
    	return target_brk;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* We need to allocate more memory after the brk... */
 | 
			
		||||
    new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
 | 
			
		||||
    /* We need to allocate more memory after the brk... Note that
 | 
			
		||||
     * we don't use MAP_FIXED because that will map over the top of
 | 
			
		||||
     * any existing mapping (like the one with the host libc or qemu
 | 
			
		||||
     * itself); instead we treat "mapped but at wrong address" as
 | 
			
		||||
     * a failure and unmap again.
 | 
			
		||||
     */
 | 
			
		||||
    new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page);
 | 
			
		||||
    mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
 | 
			
		||||
                                        PROT_READ|PROT_WRITE,
 | 
			
		||||
                                        MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
 | 
			
		||||
                                        MAP_ANON|MAP_PRIVATE, 0, 0));
 | 
			
		||||
 | 
			
		||||
    if (mapped_addr == brk_page) {
 | 
			
		||||
        target_brk = new_brk;
 | 
			
		||||
        brk_page = HOST_PAGE_ALIGN(target_brk);
 | 
			
		||||
        DEBUGF_BRK("%#010x (mapped_addr == brk_page)\n", target_brk);
 | 
			
		||||
        return target_brk;
 | 
			
		||||
    } else if (mapped_addr != -1) {
 | 
			
		||||
        /* Mapped but at wrong address, meaning there wasn't actually
 | 
			
		||||
         * enough space for this brk.
 | 
			
		||||
         */
 | 
			
		||||
        target_munmap(mapped_addr, new_alloc_size);
 | 
			
		||||
        mapped_addr = -1;
 | 
			
		||||
        DEBUGF_BRK("%#010x (mapped_addr != -1)\n", target_brk);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        DEBUGF_BRK("%#010x (otherwise)\n", target_brk);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if defined(TARGET_ALPHA)
 | 
			
		||||
    /* We (partially) emulate OSF/1 on Alpha, which requires we
 | 
			
		||||
       return a proper errno, not an unchanged brk value.  */
 | 
			
		||||
    if (is_error(mapped_addr)) {
 | 
			
		||||
        return -TARGET_ENOMEM;
 | 
			
		||||
    }
 | 
			
		||||
    return -TARGET_ENOMEM;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    if (!is_error(mapped_addr)) {
 | 
			
		||||
	target_brk = new_brk;
 | 
			
		||||
    }
 | 
			
		||||
    /* For everything else, return the previous break. */
 | 
			
		||||
    return target_brk;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -787,6 +828,20 @@ static inline abi_long copy_from_user_fdset(fd_set *fds,
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline abi_ulong copy_from_user_fdset_ptr(fd_set *fds, fd_set **fds_ptr,
 | 
			
		||||
                                                 abi_ulong target_fds_addr,
 | 
			
		||||
                                                 int n)
 | 
			
		||||
{
 | 
			
		||||
    if (target_fds_addr) {
 | 
			
		||||
        if (copy_from_user_fdset(fds, target_fds_addr, n))
 | 
			
		||||
            return -TARGET_EFAULT;
 | 
			
		||||
        *fds_ptr = fds;
 | 
			
		||||
    } else {
 | 
			
		||||
        *fds_ptr = NULL;
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
 | 
			
		||||
                                          const fd_set *fds,
 | 
			
		||||
                                          int n)
 | 
			
		||||
@ -952,6 +1007,7 @@ static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect)
 | 
			
		||||
/* do_select() must return target values and target errnos. */
 | 
			
		||||
static abi_long do_select(int n,
 | 
			
		||||
                          abi_ulong rfd_addr, abi_ulong wfd_addr,
 | 
			
		||||
@ -962,26 +1018,17 @@ static abi_long do_select(int n,
 | 
			
		||||
    struct timeval tv, *tv_ptr;
 | 
			
		||||
    abi_long ret;
 | 
			
		||||
 | 
			
		||||
    if (rfd_addr) {
 | 
			
		||||
        if (copy_from_user_fdset(&rfds, rfd_addr, n))
 | 
			
		||||
            return -TARGET_EFAULT;
 | 
			
		||||
        rfds_ptr = &rfds;
 | 
			
		||||
    } else {
 | 
			
		||||
        rfds_ptr = NULL;
 | 
			
		||||
    ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
 | 
			
		||||
    if (ret) {
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
    if (wfd_addr) {
 | 
			
		||||
        if (copy_from_user_fdset(&wfds, wfd_addr, n))
 | 
			
		||||
            return -TARGET_EFAULT;
 | 
			
		||||
        wfds_ptr = &wfds;
 | 
			
		||||
    } else {
 | 
			
		||||
        wfds_ptr = NULL;
 | 
			
		||||
    ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
 | 
			
		||||
    if (ret) {
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
    if (efd_addr) {
 | 
			
		||||
        if (copy_from_user_fdset(&efds, efd_addr, n))
 | 
			
		||||
            return -TARGET_EFAULT;
 | 
			
		||||
        efds_ptr = &efds;
 | 
			
		||||
    } else {
 | 
			
		||||
        efds_ptr = NULL;
 | 
			
		||||
    ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
 | 
			
		||||
    if (ret) {
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (target_tv_addr) {
 | 
			
		||||
@ -1008,6 +1055,7 @@ static abi_long do_select(int n,
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static abi_long do_pipe2(int host_pipe[], int flags)
 | 
			
		||||
{
 | 
			
		||||
@ -3751,7 +3799,7 @@ static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
 | 
			
		||||
#ifndef TARGET_ABI32
 | 
			
		||||
static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
 | 
			
		||||
{
 | 
			
		||||
    abi_long ret;
 | 
			
		||||
    abi_long ret = 0;
 | 
			
		||||
    abi_ulong val;
 | 
			
		||||
    int idx;
 | 
			
		||||
 | 
			
		||||
@ -3773,13 +3821,13 @@ static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
 | 
			
		||||
            idx = R_FS;
 | 
			
		||||
        val = env->segs[idx].base;
 | 
			
		||||
        if (put_user(val, addr, abi_ulong))
 | 
			
		||||
            return -TARGET_EFAULT;
 | 
			
		||||
            ret = -TARGET_EFAULT;
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        ret = -TARGET_EINVAL;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -4484,7 +4532,8 @@ int get_osversion(void)
 | 
			
		||||
   All errnos that do_syscall() returns must be -TARGET_<errcode>. */
 | 
			
		||||
abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 | 
			
		||||
                    abi_long arg2, abi_long arg3, abi_long arg4,
 | 
			
		||||
                    abi_long arg5, abi_long arg6)
 | 
			
		||||
                    abi_long arg5, abi_long arg6, abi_long arg7,
 | 
			
		||||
                    abi_long arg8)
 | 
			
		||||
{
 | 
			
		||||
    abi_long ret;
 | 
			
		||||
    struct stat st;
 | 
			
		||||
@ -5569,7 +5618,102 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef TARGET_NR_pselect6
 | 
			
		||||
    case TARGET_NR_pselect6:
 | 
			
		||||
	    goto unimplemented_nowarn;
 | 
			
		||||
        {
 | 
			
		||||
            abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr;
 | 
			
		||||
            fd_set rfds, wfds, efds;
 | 
			
		||||
            fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
 | 
			
		||||
            struct timespec ts, *ts_ptr;
 | 
			
		||||
 | 
			
		||||
            /*
 | 
			
		||||
             * The 6th arg is actually two args smashed together,
 | 
			
		||||
             * so we cannot use the C library.
 | 
			
		||||
             */
 | 
			
		||||
            sigset_t set;
 | 
			
		||||
            struct {
 | 
			
		||||
                sigset_t *set;
 | 
			
		||||
                size_t size;
 | 
			
		||||
            } sig, *sig_ptr;
 | 
			
		||||
 | 
			
		||||
            abi_ulong arg_sigset, arg_sigsize, *arg7;
 | 
			
		||||
            target_sigset_t *target_sigset;
 | 
			
		||||
 | 
			
		||||
            n = arg1;
 | 
			
		||||
            rfd_addr = arg2;
 | 
			
		||||
            wfd_addr = arg3;
 | 
			
		||||
            efd_addr = arg4;
 | 
			
		||||
            ts_addr = arg5;
 | 
			
		||||
 | 
			
		||||
            ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
 | 
			
		||||
            if (ret) {
 | 
			
		||||
                goto fail;
 | 
			
		||||
            }
 | 
			
		||||
            ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
 | 
			
		||||
            if (ret) {
 | 
			
		||||
                goto fail;
 | 
			
		||||
            }
 | 
			
		||||
            ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
 | 
			
		||||
            if (ret) {
 | 
			
		||||
                goto fail;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            /*
 | 
			
		||||
             * This takes a timespec, and not a timeval, so we cannot
 | 
			
		||||
             * use the do_select() helper ...
 | 
			
		||||
             */
 | 
			
		||||
            if (ts_addr) {
 | 
			
		||||
                if (target_to_host_timespec(&ts, ts_addr)) {
 | 
			
		||||
                    goto efault;
 | 
			
		||||
                }
 | 
			
		||||
                ts_ptr = &ts;
 | 
			
		||||
            } else {
 | 
			
		||||
                ts_ptr = NULL;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            /* Extract the two packed args for the sigset */
 | 
			
		||||
            if (arg6) {
 | 
			
		||||
                sig_ptr = &sig;
 | 
			
		||||
                sig.size = _NSIG / 8;
 | 
			
		||||
 | 
			
		||||
                arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1);
 | 
			
		||||
                if (!arg7) {
 | 
			
		||||
                    goto efault;
 | 
			
		||||
                }
 | 
			
		||||
                arg_sigset = tswapl(arg7[0]);
 | 
			
		||||
                arg_sigsize = tswapl(arg7[1]);
 | 
			
		||||
                unlock_user(arg7, arg6, 0);
 | 
			
		||||
 | 
			
		||||
                if (arg_sigset) {
 | 
			
		||||
                    sig.set = &set;
 | 
			
		||||
                    target_sigset = lock_user(VERIFY_READ, arg_sigset,
 | 
			
		||||
                                              sizeof(*target_sigset), 1);
 | 
			
		||||
                    if (!target_sigset) {
 | 
			
		||||
                        goto efault;
 | 
			
		||||
                    }
 | 
			
		||||
                    target_to_host_sigset(&set, target_sigset);
 | 
			
		||||
                    unlock_user(target_sigset, arg_sigset, 0);
 | 
			
		||||
                } else {
 | 
			
		||||
                    sig.set = NULL;
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                sig_ptr = NULL;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            ret = get_errno(sys_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
 | 
			
		||||
                                         ts_ptr, sig_ptr));
 | 
			
		||||
 | 
			
		||||
            if (!is_error(ret)) {
 | 
			
		||||
                if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
 | 
			
		||||
                    goto efault;
 | 
			
		||||
                if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
 | 
			
		||||
                    goto efault;
 | 
			
		||||
                if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
 | 
			
		||||
                    goto efault;
 | 
			
		||||
 | 
			
		||||
                if (ts_addr && host_to_target_timespec(ts_addr, &ts))
 | 
			
		||||
                    goto efault;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
#endif
 | 
			
		||||
    case TARGET_NR_symlink:
 | 
			
		||||
        {
 | 
			
		||||
@ -6029,8 +6173,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef TARGET_NR_syscall
 | 
			
		||||
    case TARGET_NR_syscall:
 | 
			
		||||
    	ret = do_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
 | 
			
		||||
    	break;
 | 
			
		||||
        ret = do_syscall(cpu_env, arg1 & 0xffff, arg2, arg3, arg4, arg5,
 | 
			
		||||
                         arg6, arg7, arg8, 0);
 | 
			
		||||
        break;
 | 
			
		||||
#endif
 | 
			
		||||
    case TARGET_NR_wait4:
 | 
			
		||||
        {
 | 
			
		||||
@ -7058,7 +7203,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 | 
			
		||||
    case TARGET_NR_osf_sigprocmask:
 | 
			
		||||
        {
 | 
			
		||||
            abi_ulong mask;
 | 
			
		||||
            int how = arg1;
 | 
			
		||||
            int how;
 | 
			
		||||
            sigset_t set, oldset;
 | 
			
		||||
 | 
			
		||||
            switch(arg1) {
 | 
			
		||||
@ -7077,7 +7222,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 | 
			
		||||
            }
 | 
			
		||||
            mask = arg2;
 | 
			
		||||
            target_to_host_old_sigset(&set, &mask);
 | 
			
		||||
            sigprocmask(arg1, &set, &oldset);
 | 
			
		||||
            sigprocmask(how, &set, &oldset);
 | 
			
		||||
            host_to_target_old_sigset(&mask, &oldset);
 | 
			
		||||
            ret = mask;
 | 
			
		||||
        }
 | 
			
		||||
@ -7717,8 +7862,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 | 
			
		||||
#if defined(TARGET_NR_sync_file_range)
 | 
			
		||||
    case TARGET_NR_sync_file_range:
 | 
			
		||||
#if TARGET_ABI_BITS == 32
 | 
			
		||||
#if defined(TARGET_MIPS)
 | 
			
		||||
        ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
 | 
			
		||||
                                        target_offset64(arg5, arg6), arg7));
 | 
			
		||||
#else
 | 
			
		||||
        ret = get_errno(sync_file_range(arg1, target_offset64(arg2, arg3),
 | 
			
		||||
                                        target_offset64(arg4, arg5), arg6));
 | 
			
		||||
#endif /* !TARGET_MIPS */
 | 
			
		||||
#else
 | 
			
		||||
        ret = get_errno(sync_file_range(arg1, arg2, arg3, arg4));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -370,7 +370,7 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
 | 
			
		||||
        TaskState *ts = env->opaque;
 | 
			
		||||
        /* Allocate the heap using sbrk.  */
 | 
			
		||||
        if (!ts->heap_limit) {
 | 
			
		||||
            long ret;
 | 
			
		||||
            abi_ulong ret;
 | 
			
		||||
            uint32_t size;
 | 
			
		||||
            uint32_t base;
 | 
			
		||||
 | 
			
		||||
@ -379,8 +379,9 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
 | 
			
		||||
            /* Try a big heap, and reduce the size if that fails.  */
 | 
			
		||||
            for (;;) {
 | 
			
		||||
                ret = do_brk(base + size);
 | 
			
		||||
                if (ret != -1)
 | 
			
		||||
                if (ret >= (base + size)) {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                size >>= 1;
 | 
			
		||||
            }
 | 
			
		||||
            ts->heap_limit = base + size;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user