@@ -475,7 +475,7 @@
/* 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);
}
Do you think this is a genuine bug?
Steve.
** Affects: qemu
Importance: Undecided
Status: New
--
arm-semi mishandling SYS_HEAPINFO
https://bugs.launchpad.net/bugs/656285
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
Status in QEMU: New
Bug description:
I am running qemu-arm on a 32-bit fedora-7 i386 machine:
$ /home/bri0633/users/clarkes/qemu/build/arm-linux-user/qemu-arm --version
qemu-arm version 0.12.3, Copyright (c) 2003-2008 Fabrice Bellard
When I try to run an arm semi-hosted executable, I sometimes get unexpected segv and sometimes not, depending on the executable. The symptom is:
$ /home/bri0633/users/clarkes/qemu/build/arm-linux-user/qemu-arm -cpu cortex-a9 -- a.out
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
Segmentation fault
It appear to be because of the handling of the SYS_HEAPINFO syscall in arm-semi.c. There it tries to allocate 128M for the heap by calling do_brk() which calls target_mmap(). This is the DEBUG_MMAP diagnostic:
mmap: start=0x00009000 len=0x08001000 prot=rw- flags=MAP_FIXED MAP_ANON MAP_PRIVATE fd=0 offset=00000000
but this mmap is failing because there are shared libraries (and the gate page) mapped there:
$ ldd /home/bri0633/users/clarkes/qemu/build/arm-linux-user/qemu-arm
linux-gate.so.1 => (0x00880000)
librt.so.1 => /lib/librt.so.1 (0x03409000)
libpthread.so.0 => /lib/libpthread.so.0 (0x00d7d000)
libm.so.6 => /lib/libm.so.6 (0x00d4b000)
libc.so.6 => /lib/libc.so.6 (0x00bf5000)
/lib/ld-linux.so.2 (0x00bd6000)
However, it seems that the code in arm-semi.c does not interpret the result of do_brk() correctly, and thinks that the mapping succeeded.
The following patch appears to fix the problem:
$ diff -u arm-semi.c.orig arm-semi.c
@@ -475,7 +475,7 @@
/* 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);
}