linux-user: fix ELF load alignment error

When we try to use some targets on ppc64, it can happen the target
doesn't support the host page size to align ELF load sections and
fails with:

  ELF load command alignment not page-aligned

Since commit a70daba377 ("linux-user: Tell guest about big host
page sizes") the host page size is used to align ELF sections, but
this doesn't work if the alignment required by the load section is
smaller than the host one.  For these cases, we continue to use the
TARGET_PAGE_SIZE instead of the host one.

I have tested this change on ppc64, and it fixes qemu linux-user for:
  s390x, m68k, i386, arm, aarch64, hppa
and I have tested it doesn't break the following targets:
  x86_64, mips64el, sh4
mips and mipsel abort, but I think for another reason.

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
[lv: fixed "info->alignment = 0"]
Message-Id: <20180716195349.29959-1-laurent@vivier.eu>
This commit is contained in:
Laurent Vivier 2018-07-16 21:53:49 +02:00
parent 5b3ecd3d94
commit 33143c446e
2 changed files with 10 additions and 1 deletions

View File

@ -1875,7 +1875,13 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
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_PHNUM, (abi_ulong)(exec->e_phnum));
NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(MAX(TARGET_PAGE_SIZE, getpagesize())));
if ((info->alignment & ~qemu_host_page_mask) != 0) {
/* Target doesn't support host page size alignment */
NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
} else {
NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(MAX(TARGET_PAGE_SIZE,
qemu_host_page_size)));
}
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_ENTRY, info->entry);
@ -2202,6 +2208,7 @@ static void load_elf_image(const char *image_name, int image_fd,
/* Find the maximum size of the image and allocate an appropriate
amount of memory to handle that. */
loaddr = -1, hiaddr = 0;
info->alignment = 0;
for (i = 0; i < ehdr->e_phnum; ++i) {
if (phdr[i].p_type == PT_LOAD) {
abi_ulong a = phdr[i].p_vaddr - phdr[i].p_offset;
@ -2213,6 +2220,7 @@ static void load_elf_image(const char *image_name, int image_fd,
hiaddr = a;
}
++info->nsegs;
info->alignment |= phdr[i].p_align;
}
}

View File

@ -51,6 +51,7 @@ struct image_info {
abi_ulong file_string;
uint32_t elf_flags;
int personality;
abi_ulong alignment;
/* The fields below are used in FDPIC mode. */
abi_ulong loadmap_addr;