mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-05 16:53:55 -06:00
linux-user: Use elf_et_dyn_base for ET_DYN with interpreter
Follow the lead of the linux kernel in fs/binfmt_elf.c, in which an ET_DYN executable which uses an interpreter (usually a PIE executable) is loaded away from where the interpreter itself will be loaded. Tested-by: Helge Deller <deller@gmx.de> Reviewed-by: Helge Deller <deller@gmx.de> Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
ad25051bae
commit
1ea06ded0d
1 changed files with 25 additions and 2 deletions
|
@ -3107,6 +3107,8 @@ static void load_elf_image(const char *image_name, int image_fd,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
load_addr = loaddr;
|
||||||
|
|
||||||
if (pinterp_name != NULL) {
|
if (pinterp_name != NULL) {
|
||||||
/*
|
/*
|
||||||
* This is the main executable.
|
* This is the main executable.
|
||||||
|
@ -3136,11 +3138,32 @@ static void load_elf_image(const char *image_name, int image_fd,
|
||||||
*/
|
*/
|
||||||
probe_guest_base(image_name, loaddr, hiaddr);
|
probe_guest_base(image_name, loaddr, hiaddr);
|
||||||
} else {
|
} else {
|
||||||
|
abi_ulong align;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The binary is dynamic, but we still need to
|
* The binary is dynamic, but we still need to
|
||||||
* select guest_base. In this case we pass a size.
|
* select guest_base. In this case we pass a size.
|
||||||
*/
|
*/
|
||||||
probe_guest_base(image_name, 0, hiaddr - loaddr);
|
probe_guest_base(image_name, 0, hiaddr - loaddr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Avoid collision with the loader by providing a different
|
||||||
|
* default load address.
|
||||||
|
*/
|
||||||
|
load_addr += elf_et_dyn_base;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: Better support for mmap alignment is desirable.
|
||||||
|
* Since we do not have complete control over the guest
|
||||||
|
* address space, we prefer the kernel to choose some address
|
||||||
|
* rather than force the use of LOAD_ADDR via MAP_FIXED.
|
||||||
|
* But without MAP_FIXED we cannot guarantee alignment,
|
||||||
|
* only suggest it.
|
||||||
|
*/
|
||||||
|
align = pow2ceil(info->alignment);
|
||||||
|
if (align) {
|
||||||
|
load_addr &= -align;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3155,13 +3178,13 @@ static void load_elf_image(const char *image_name, int image_fd,
|
||||||
*
|
*
|
||||||
* Otherwise this is ET_DYN, and we are searching for a location
|
* Otherwise this is ET_DYN, and we are searching for a location
|
||||||
* that can hold the memory space required. If the image is
|
* that can hold the memory space required. If the image is
|
||||||
* pre-linked, LOADDR will be non-zero, and the kernel should
|
* pre-linked, LOAD_ADDR will be non-zero, and the kernel should
|
||||||
* honor that address if it happens to be free.
|
* honor that address if it happens to be free.
|
||||||
*
|
*
|
||||||
* In both cases, we will overwrite pages in this range with mappings
|
* In both cases, we will overwrite pages in this range with mappings
|
||||||
* from the executable.
|
* from the executable.
|
||||||
*/
|
*/
|
||||||
load_addr = target_mmap(loaddr, (size_t)hiaddr - loaddr + 1, PROT_NONE,
|
load_addr = target_mmap(load_addr, (size_t)hiaddr - loaddr + 1, PROT_NONE,
|
||||||
MAP_PRIVATE | MAP_ANON | MAP_NORESERVE |
|
MAP_PRIVATE | MAP_ANON | MAP_NORESERVE |
|
||||||
(ehdr->e_type == ET_EXEC ? MAP_FIXED_NOREPLACE : 0),
|
(ehdr->e_type == ET_EXEC ? MAP_FIXED_NOREPLACE : 0),
|
||||||
-1, 0);
|
-1, 0);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue