Loading linux-user/elfload.c +77 −33 Original line number Diff line number Diff line Loading @@ -1426,6 +1426,73 @@ bool guest_validate_base(unsigned long guest_base) } #endif unsigned long init_guest_space(unsigned long host_start, unsigned long host_size, unsigned long guest_start, bool fixed) { unsigned long current_start, real_start; int flags; assert(host_start || host_size); /* If just a starting address is given, then just verify that * address. */ if (host_start && !host_size) { if (guest_validate_base(host_start)) { return host_start; } else { return (unsigned long)-1; } } /* Setup the initial flags and start address. */ current_start = host_start & qemu_host_page_mask; flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE; if (fixed) { flags |= MAP_FIXED; } /* Otherwise, a non-zero size region of memory needs to be mapped * and validated. */ 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 *)current_start, host_size, PROT_NONE, flags, -1, 0); if (real_start == (unsigned long)-1) { return (unsigned long)-1; } if ((real_start == current_start) && guest_validate_base(real_start - guest_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); current_start += qemu_host_page_size; if (host_start == current_start) { /* Theoretically possible if host doesn't have any suitably * aligned areas. Normally the first mmap will fail. */ return (unsigned long)-1; } } return real_start; } static void probe_guest_base(const char *image_name, abi_ulong loaddr, abi_ulong hiaddr) { Loading @@ -1452,46 +1519,23 @@ static void probe_guest_base(const char *image_name, } } 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); /* Setup the initial guest memory space with ranges gleaned from * the ELF image that is being loaded. */ real_start = init_guest_space(host_start, host_size, loaddr, false); if (real_start == (unsigned long)-1) { goto exit_perror; } guest_base = real_start - loaddr; if ((real_start == host_start) && guest_validate_base(guest_base)) { 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; } } guest_base = real_start - loaddr; qemu_log("Relocating guest address space from 0x" TARGET_ABI_FMT_lx " to 0x%lx\n", loaddr, real_start); } return; exit_perror: errmsg = strerror(errno); exit_errmsg: fprintf(stderr, "%s: %s\n", image_name, errmsg); exit(-1); Loading linux-user/qemu.h +13 −0 Original line number Diff line number Diff line Loading @@ -210,6 +210,19 @@ void fork_end(int child); */ bool guest_validate_base(unsigned long guest_base); /* Creates the initial guest address space in the host memory space using * the given host start address hint and size. The guest_start parameter * specifies the start address of the guest space. guest_base will be the * difference between the host start address computed by this function and * guest_start. If fixed is specified, then the mapped address space must * start at host_start. The real start address of the mapped memory space is * returned or -1 if there was an error. */ unsigned long init_guest_space(unsigned long host_start, unsigned long host_size, unsigned long guest_start, bool fixed); #include "qemu-log.h" /* strace.c */ Loading Loading
linux-user/elfload.c +77 −33 Original line number Diff line number Diff line Loading @@ -1426,6 +1426,73 @@ bool guest_validate_base(unsigned long guest_base) } #endif unsigned long init_guest_space(unsigned long host_start, unsigned long host_size, unsigned long guest_start, bool fixed) { unsigned long current_start, real_start; int flags; assert(host_start || host_size); /* If just a starting address is given, then just verify that * address. */ if (host_start && !host_size) { if (guest_validate_base(host_start)) { return host_start; } else { return (unsigned long)-1; } } /* Setup the initial flags and start address. */ current_start = host_start & qemu_host_page_mask; flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE; if (fixed) { flags |= MAP_FIXED; } /* Otherwise, a non-zero size region of memory needs to be mapped * and validated. */ 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 *)current_start, host_size, PROT_NONE, flags, -1, 0); if (real_start == (unsigned long)-1) { return (unsigned long)-1; } if ((real_start == current_start) && guest_validate_base(real_start - guest_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); current_start += qemu_host_page_size; if (host_start == current_start) { /* Theoretically possible if host doesn't have any suitably * aligned areas. Normally the first mmap will fail. */ return (unsigned long)-1; } } return real_start; } static void probe_guest_base(const char *image_name, abi_ulong loaddr, abi_ulong hiaddr) { Loading @@ -1452,46 +1519,23 @@ static void probe_guest_base(const char *image_name, } } 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); /* Setup the initial guest memory space with ranges gleaned from * the ELF image that is being loaded. */ real_start = init_guest_space(host_start, host_size, loaddr, false); if (real_start == (unsigned long)-1) { goto exit_perror; } guest_base = real_start - loaddr; if ((real_start == host_start) && guest_validate_base(guest_base)) { 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; } } guest_base = real_start - loaddr; qemu_log("Relocating guest address space from 0x" TARGET_ABI_FMT_lx " to 0x%lx\n", loaddr, real_start); } return; exit_perror: errmsg = strerror(errno); exit_errmsg: fprintf(stderr, "%s: %s\n", image_name, errmsg); exit(-1); Loading
linux-user/qemu.h +13 −0 Original line number Diff line number Diff line Loading @@ -210,6 +210,19 @@ void fork_end(int child); */ bool guest_validate_base(unsigned long guest_base); /* Creates the initial guest address space in the host memory space using * the given host start address hint and size. The guest_start parameter * specifies the start address of the guest space. guest_base will be the * difference between the host start address computed by this function and * guest_start. If fixed is specified, then the mapped address space must * start at host_start. The real start address of the mapped memory space is * returned or -1 if there was an error. */ unsigned long init_guest_space(unsigned long host_start, unsigned long host_size, unsigned long guest_start, bool fixed); #include "qemu-log.h" /* strace.c */ Loading