Bug 302709

Summary: valgrind for ARM needs extra tls support for android emulator under Linux
Product: [Developer tools] valgrind Reporter: John Reiser <jreiser>
Component: generalAssignee: Julian Seward <jseward>
Status: RESOLVED FIXED    
Severity: normal CC: philippe.waroquiers, zach.frey
Priority: NOR    
Version: 3.7 SVN   
Target Milestone: ---   
Platform: Compiled Sources   
OS: Linux   
Latest Commit: Version Fixed In:
Attachments: GENOFFSET(ARM,arm,TPIDRURO)
enhance dispatch-arm-linux.S for CPU without tls hardware
how to obtain and install adroid emulator

Description John Reiser 2012-06-28 17:37:32 UTC
Valgrind for ARM needs extra support for tls (ThreadLocalStorage) in order to run valgrind tools for ARM apps under the android emulator for ARM on Linux x86 or x86_64.  Without this extra support, then running any valgrind tool under the android emulator for ARM gets an immediate SIGSEGV.  As diagnosed by Philippe Waroquiers, the android emulator claims that its CPU is armv7 except that it does not support tls.  The string "tls" is missing from the Features that are listed by /proc/cpuinfo:
=====
android emulator:
***********************************************************
cat /proc/cpuinfo
Processor	: ARMv7 Processor rev 0 (v7l)
BogoMIPS	: 78.84
Features	: swp half thumb fastmult vfp edsp neon vfpv3 
CPU implementer	: 0x41
CPU architecture: 7
CPU variant	: 0x0
CPU part	: 0xc08
CPU revision	: 0

Hardware	: Goldfish
Revision	: 0000
Serial		: 0000000000000000

dual-core A9 in galaxy S 2:
**********************************************************
# cat /proc/cpuinfo                               
Processor       : ARMv7 Processor rev 1 (v7l)
processor       : 0
BogoMIPS        : 1592.52
 
Features        : swp half thumb fastmult vfp edsp neon vfpv3 tls
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x2
CPU part        : 0xc09
CPU revision    : 1
 
Hardware        : SMDK4210
Revision        : 000e 


pandaboard:
***********************************************************
$ cat /proc/cpuinfo
    Processor       : ARMv7 Processor rev 2 (v7l)
    processor       : 0
    BogoMIPS        : 596.46
     
    processor       : 1
    BogoMIPS        : 582.68
     
    Features        : swp half thumb fastmult vfp edsp thumbee neon
vfpv3 tls
    CPU implementer : 0x41
    CPU architecture: 7
    CPU variant     : 0x1
    CPU part        : 0xc09
    CPU revision    : 2
     
    Hardware        : OMAP4 Panda board
    Revision        : 0020
    Serial    : 0000000000000000 
=====

The fix is two short patches to svn-3.8.0, which will be attached.  One patch adds a symbol in VEX, the other patch enhances dispatch-arm-linux.S.




Reproducible: Always

Steps to Reproduce:
1. adb shell   # Android Debug Bridge (x86* tool which gives a shell in the emulated Android ARM environmentl)
2. /data/local/Inst/bin/valgrind --tool=none date

Actual Results:  
==511== Command: date
==511== 
[1] + Stopped (signal)        ./valgrind --tool=none date
# ==511== 
==511== Process terminating with default action of signal 11 (SIGSEGV)
==511==  Access not within mapped region at address 0x4004F4D0
==511==    at 0x481C754: __libc_preinit (in /system/lib/libc.so)
==511==  If you believe this happened as a result of a stack
==511==  overflow in your program's main thread (unlikely but
==511==  possible), you can try to increase the size of the
==511==  main thread stack using the --main-stacksize= flag.
==511==  The main thread stack size used in this run was 8388608.


Expected Results:  
No SIGSEGV.
Comment 1 John Reiser 2012-06-28 17:39:47 UTC
Created attachment 72200 [details]
GENOFFSET(ARM,arm,TPIDRURO)
Comment 2 John Reiser 2012-06-28 17:41:06 UTC
Created attachment 72201 [details]
enhance dispatch-arm-linux.S for CPU without tls hardware
Comment 3 John Reiser 2012-06-28 17:45:06 UTC
Here is the code at the SIGSEGV; it's in the target app's libc.so:
(gdb) x/9i __libc_preinit
0x1674c <__libc_preinit>:    ldr r0, [pc, #20]   ; (0x16764 <__libc_preinit+24>)  ### r0= 0xffff0ff0
0x1674e <__libc_preinit+2>:     movs    r2, #0
0x16750 <__libc_preinit+4>:     push    {r4, lr}
0x16752 <__libc_preinit+6>:     ldr     r3, [r0, #0]   ### r3= *(void **)0xffff0ff0
***==>0x16754 <__libc_preinit+8>:     ldr     r0, [r3, #12]   ### SIGSEGV here
0x16756 <__libc_preinit+10>:    str     r2, [r3, #12]
0x16758 <__libc_preinit+12>:    bl      0x27c64 <__libc_init_common>
0x1675c <__libc_preinit+16>:    bl      0x16160 <malloc_debug_init>
0x16760 <__libc_preinit+20>:	pop	{r4, pc}   ### return
(gdb) x/4x 0x16764
0x16764 <__libc_preinit+24>:    0xffff0ff0      0xe24dd008      0xe2102003     0xf5d0f000

Here is the approximate calling environment [it's old, but useful information]:
http://nv-tegra.nvidia.com/gitweb/?p=android/platform/bionic.git;a=commitdiff_plain;h=b56b5659b3996e98c2060f168d1cff1474e77d2a
+void __libc_prenit(void)
+{
+    /* Read the ELF data pointer form a special slot of the
+     * TLS area, then call __libc_init_common with it.
+     *
+     * Note that:
+     * - we clear the slot so no other initializer sees its value.
+     * - __libc_init_common() will change the TLS area so the old one
+     *   won't be accessible anyway.
+     */
+    void**      tls_area = (void**)__get_tls();
+    unsigned*   elfdata   = tls_area[TLS_SLOT_BIONIC_PREINIT];
+
+    tls_area[TLS_SLOT_BIONIC_PREINIT] = NULL;
+
+    __libc_init_common(elfdata);
+}
Comment 4 John Reiser 2012-06-28 23:31:32 UTC
Created attachment 72206 [details]
how to obtain and install adroid emulator

Modified from original by Philippe Waroquiers.  Note that android emulator is a 32-bit (i686) application.  If you have a plain 64-bit x86_64 environment, then you will have to install some 32-bit packages.  I got cryptic and unhelpful error messages before installing the 32-bit packages; I resorted to using strace to find some causes.  On Fedora-17, the packages which I needed were:
glibc.i686
ncurses-libs.i686
libgcc.i686
libstdc++.i686
zlib.i686
libXrender.i686
libXrandr.i686
libXext.i686
and their dependencies
libXau.i686
libxcb.i686
libX11.i686
Comment 5 Philippe Waroquiers 2012-07-04 22:03:34 UTC
Fixed in revision 12710
Thanks for the problem analysis and solution.
Note that after discussion, it was deemed better to not touch the asm dispatcher
but rather execute the sys_set_tls syscall in the C code.
At least for me, it worked similarly to the asm dispatcher changes.
Comment 6 Zach Frey 2012-10-05 04:03:21 UTC
I am still seeing what appears to be these symptoms using valgrind-3.8.1 for ARM Android.

~ # valgrind --tool=none date
==1674== Nulgrind, the minimal Valgrind tool
==1674== Copyright (C) 2002-2012, and GNU GPL'd, by Nicholas Nethercote.
==1674== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==1674== Command: date
==1674==
[1]+  Stopped (signal)           valgrind --tool=none date
~ # ==1674==
==1674== Process terminating with default action of signal 11 (SIGSEGV)
==1674==  Access not within mapped region at address 0x0
==1674==    at 0xAFD26274: __libc_fini (in /system/lib/libc.so)
==1674==  If you believe this happened as a result of a stack
==1674==  overflow in your program's main thread (unlikely but
==1674==  possible), you can try to increase the size of the
==1674==  main thread stack using the --main-stacksize= flag.
==1674==  The main thread stack size used in this run was 8388608.
==1674==

Info for the board in question:

~ # cat /proc/cpuinfo
Processor       : ARMv7 Processor rev 2 (v7l)
BogoMIPS        : 597.64
Features        : swp half thumb fastmult vfp edsp thumbee neon vfpv3
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x3
CPU part        : 0xc08
CPU revision    : 2

Hardware        : Lectronix Georgetown Board
Revision        : 0020
Serial          : 0000000000000000

Please advise if there is additional information that would be helpful or if there is something I can try.
Comment 7 John Reiser 2012-10-05 04:52:44 UTC
The source code function assign_guest_tls() in file  valgrind-3.8.1/coregrind/m_syswrap/syswrap-arm-linux.c must be built with:
   #define ANDROID_HARDWARE_emulator

Did you do that?
Comment 8 Zach Frey 2012-10-05 13:44:25 UTC
No, I compiled with ANDROID_HARDWARE_generic, as my target is a custom ARM board, not the emulator.
Comment 9 John Reiser 2012-10-05 14:26:37 UTC
(In reply to comment #8)
> No, I compiled with ANDROID_HARDWARE_generic, as my target is a custom ARM
> board, not the emulator.

Compiled instances of valgrind are target-specific, and the android emulator is a different target.  See the instructions in valgrind-3.8.1/README.android.  (My position is that valgrind should detect at runtime the omission of 'tls' in the Features string from /proc/cpuinfo  and adjust accordingly.  Obviously the code does not do that.)
Comment 10 Zach Frey 2012-10-05 14:56:52 UTC
On Fri, Oct 5, 2012 at 10:26 AM, John Reiser <jreiser@bitwagon.com> wrote:

>
> (My position is that valgrind should detect at runtime the omission of
> 'tls' in
> the Features string from /proc/cpuinfo  and adjust accordingly.  Obviously
> the
> code does not do that.)
>

I assumed that would be how a fix would be implemented; obviously that was
wrong on my part.

I've been advised that our board actually does have tls enabled; it is just
that /proc/cpuinfo was failing to report it. However, correcting that does
not affect the problem.
Comment 11 John Reiser 2012-10-05 15:09:27 UTC
(In reply to comment #10)
> I've been advised that our board actually does have tls enabled; it is just
> that /proc/cpuinfo was failing to report it. However, correcting that does
> not affect the problem.

It's the android emulator which removes 'tls' from the Features string.  The emulator doesn't want to write the code to support "tls hardware".
Comment 12 Zach Frey 2012-10-05 16:38:38 UTC
On Fri, Oct 5, 2012 at 11:09 AM, John Reiser <jreiser@bitwagon.com> wrote:

> https://bugs.kde.org/show_bug.cgi?id=302709
>


> It's the android emulator which removes 'tls' from the Features string.
>  The
> emulator doesn't want to write the code to support "tls hardware".
>

That makes sense re: the emulator.

Patching my local copy of coregrind/m_syswrap/syswrap-arm-linux.c to
include ANDROID_HARDWARE_generic in the #ifdef with
ANDROID_HARDWARE_emulator appears to work for me.