diff options
author | Peter Maydell | 2020-01-23 15:38:43 +0100 |
---|---|---|
committer | Peter Maydell | 2020-01-23 15:38:43 +0100 |
commit | b7c359c748a2e3ccb97a184b9739feb2cd48de2f (patch) | |
tree | b08fefe2ba5816d620286165bf3fa006bfb84a2a /linux-user/elfload.c | |
parent | Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (diff) | |
parent | linux-user: Add support for read/clear RTC voltage low detector using ioctls (diff) | |
download | qemu-b7c359c748a2e3ccb97a184b9739feb2cd48de2f.tar.gz qemu-b7c359c748a2e3ccb97a184b9739feb2cd48de2f.tar.xz qemu-b7c359c748a2e3ccb97a184b9739feb2cd48de2f.zip |
Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-5.0-pull-request' into staging
Fix mmap guest space and brk
Add FS/FD/RTC/KCOV ioctls
# gpg: Signature made Thu 23 Jan 2020 08:21:41 GMT
# gpg: using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C
# gpg: issuer "laurent@vivier.eu"
# gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [full]
# gpg: aka "Laurent Vivier <laurent@vivier.eu>" [full]
# gpg: aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [full]
# Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F 5173 F30C 38BD 3F2F BE3C
* remotes/vivier2/tags/linux-user-for-5.0-pull-request:
linux-user: Add support for read/clear RTC voltage low detector using ioctls
linux-user: Add support for getting/setting RTC PLL correction using ioctls
linux-user: Add support for getting/setting RTC wakeup alarm using ioctls
linux-user: Add support for getting/setting RTC periodic interrupt and epoch using ioctls
linux-user: Add support for getting/setting RTC time and alarm using ioctls
linux-user: Add support for enabling/disabling RTC features using ioctls
linux-user: Add support for TYPE_LONG and TYPE_ULONG in do_ioctl()
linux-user: Add support for KCOV_INIT_TRACE ioctl
linux-user: Add support for KCOV_<ENABLE|DISABLE> ioctls
configure: Detect kcov support and introduce CONFIG_KCOV
linux-user: Add support for FDFMT<BEG|TRK|END> ioctls
linux-user: Add support for FD<SETEMSGTRESH|SETMAXERRS|GETMAXERRS> ioctls
linux-user: Add support for FS_IOC32_<GET|SET>VERSION ioctls
linux-user: Add support for FS_IOC32_<GET|SET>FLAGS ioctls
linux-user: Add support for FS_IOC_<GET|SET>VERSION ioctls
linux-user: Reserve space for brk
linux-user:Fix align mistake when mmap guest space
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'linux-user/elfload.c')
-rw-r--r-- | linux-user/elfload.c | 75 |
1 files changed, 57 insertions, 18 deletions
diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 07b16cc0f4..f3080a1635 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -10,6 +10,7 @@ #include "qemu/path.h" #include "qemu/queue.h" #include "qemu/guest-random.h" +#include "qemu/units.h" #ifdef _ARCH_PPC64 #undef ARCH_DLINFO @@ -2191,7 +2192,7 @@ unsigned long init_guest_space(unsigned long host_start, * to where we need to put the commpage. */ munmap((void *)real_start, host_size); - real_size = aligned_size + qemu_host_page_size; + real_size = aligned_size + align; real_start = (unsigned long) mmap((void *)real_start, real_size, PROT_NONE, flags, -1, 0); if (real_start == (unsigned long)-1) { @@ -2364,24 +2365,51 @@ static void load_elf_image(const char *image_name, int image_fd, } } - load_addr = loaddr; - if (ehdr->e_type == ET_DYN) { - /* The image indicates that it can be loaded anywhere. Find a - location that can hold the memory space required. If the - image is pre-linked, LOADDR will be non-zero. Since we do - not supply MAP_FIXED here we'll use that address if and - only if it remains available. */ - load_addr = target_mmap(loaddr, hiaddr - loaddr, PROT_NONE, - MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, - -1, 0); - if (load_addr == -1) { - goto exit_perror; + if (pinterp_name != NULL) { + /* + * This is the main executable. + * + * Reserve extra space for brk. + * We hold on to this space while placing the interpreter + * and the stack, lest they be placed immediately after + * the data segment and block allocation from the brk. + * + * 16MB is chosen as "large enough" without being so large + * as to allow the result to not fit with a 32-bit guest on + * a 32-bit host. + */ + info->reserve_brk = 16 * MiB; + hiaddr += info->reserve_brk; + + if (ehdr->e_type == ET_EXEC) { + /* + * Make sure that the low address does not conflict with + * MMAP_MIN_ADDR or the QEMU application itself. + */ + probe_guest_base(image_name, loaddr, hiaddr); } - } else if (pinterp_name != NULL) { - /* This is the main executable. Make sure that the low - address does not conflict with MMAP_MIN_ADDR or the - QEMU application itself. */ - probe_guest_base(image_name, loaddr, hiaddr); + } + + /* + * Reserve address space for all of this. + * + * In the case of ET_EXEC, we supply MAP_FIXED so that we get + * exactly the address range that is required. + * + * Otherwise this is ET_DYN, and we are searching for a location + * that can hold the memory space required. If the image is + * pre-linked, LOADDR will be non-zero, and the kernel should + * honor that address if it happens to be free. + * + * In both cases, we will overwrite pages in this range with mappings + * from the executable. + */ + load_addr = target_mmap(loaddr, hiaddr - loaddr, PROT_NONE, + MAP_PRIVATE | MAP_ANON | MAP_NORESERVE | + (ehdr->e_type == ET_EXEC ? MAP_FIXED : 0), + -1, 0); + if (load_addr == -1) { + goto exit_perror; } load_bias = load_addr - loaddr; @@ -2860,6 +2888,17 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info) bprm->core_dump = &elf_core_dump; #endif + /* + * If we reserved extra space for brk, release it now. + * The implementation of do_brk in syscalls.c expects to be able + * to mmap pages in this space. + */ + if (info->reserve_brk) { + abi_ulong start_brk = HOST_PAGE_ALIGN(info->brk); + abi_ulong end_brk = HOST_PAGE_ALIGN(info->brk + info->reserve_brk); + target_munmap(start_brk, end_brk - start_brk); + } + return 0; } |