From patchwork Thu Oct 7 12:56:28 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [Bug,656285,NEW] arm-semi mishandling SYS_HEAPINFO Date: Thu, 07 Oct 2010 02:56:28 -0000 From: Stephen Clarke <656285@bugs.launchpad.net> X-Patchwork-Id: 67057 Message-Id: <20101007125628.8009.23815.malonedeb@soybean.canonical.com> To: qemu-devel@nongnu.org Public bug reported: 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 Do you think this is a genuine bug? Steve. --- arm-semi.c.orig 2010-09-21 13:19:15.000000000 +0100 +++ arm-semi.c 2010-10-07 13:23:13.000000000 +0100 @@ -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 --- arm-semi.c.orig 2010-09-21 13:19:15.000000000 +0100 +++ arm-semi.c 2010-10-07 13:23:13.000000000 +0100 @@ -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); }