Context is developing an android app that uses several static executable binaries through sh
syscall. One of the binaries eventually segfaults when using a samsung galaxy s4 cellphone (but not when using emulator or a Sony Xperia tipo cellphone), so following http://embetek.blogspot.com.es/2011/10/valgrind-for-arm.html with several custom modifications (CFLAGS='-static -march=armv7-a') end up getting a
$ ldd valgrind
not a dynamic executable
$ file valgrind
valgrind: ELF 32-bit LSB executable, ARM, version 1 (SYSV),
statically linked, for GNU/Linux 3.2.0, not stripped.
Loaded on the target phone (versioned android 4.2.2 kernel 3.4...), (context.getFilesDir() + File.separator + "valgrind").canExecute()
returns false.
Running sh -c PATH...valgrind
tells valgrind: can't execute: Permission denied
and status 126 on exit.
Emulator seems to run kernel 2.6... so there adb shell
and executing valgrind
there told something similar but more decorated telling about a kernel version mismatch: literally
llostatic/files/valgrind <
FATAL: kernel too old
Segmentation fault
(context.getFilesDir() + File.separator + "valgrind").setExecute()
is failing by unknown reason was failing because it wasn't being done at all (was doing something like dumpAssetToFile("valgrind"){/* Many things suppressed here. */ argument.setExecute() /* Done wrong without a files dir path ask */}
.
Now valgrind
seems to be correctly calling for a memcheck-arm-linux
, but I didn't yet made it recognize it.
Even a execution of "sh -c \"PATH=$PATH:" + getFilesDir() + File.separator + " " + getFilesDir() + File.separator + "busybox strace valgrind -v " + BINARY + " " + ARGS + " " + "2>&1\""
does not do what I expect. It is not exactly this what gets executed, but am outputting this to stderr.
W/System.err(6918): commandStrArr[0]: sh
W/System.err(6918): commandStrArr[1]: -c
W/System.err(6918): commandStrArr[2]: PATH=$PATH:/data/data/NAMESPACE/files/ busy
box strace valgrind -v /data/data/NAMESPACE/files/BINARY ARGS 2>&1
W/System.err(6918): strace: applet not found
W/System.err(6918): valgrind: failed to start tool 'memcheck' for platform 'arm-l
inux': No such file or directory
W/System.err(6918): Error: BINARY exited with status nonzero (1).
My read of this is that busybox
can not emulate strace
, but is anyway executing as a command and args from what it thinks as args[2] to the end of its view of arguments. valgrind
is loading well but can not find memcheck
. A context here is memcheck-arm-linux
is an asset' ed static binary dumped to the files directory together with those working valgrind
and busybox
. I can not be able to be sure memcheck-arm-linux
is exactly what is asking for, if I can't get a system calls trace. IMHO It would be a gotcha not being memcheck-arm-linux
what valgrind
is calling here "'memcheck' for platform 'arm-linux'".
Additional info (abstract the cwds please):
$ file busybox
busybox: ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically linked, for
GNU/Linux 3.2.0, stripped
[...]
$ file coregrind/valgrind
coregrind/valgrind: ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically
linked, for GNU/Linux 3.2.0, not stripped
[...]
$ file memcheck/memcheck-arm-linux
memcheck/memcheck-arm-linux: ELF 32-bit LSB executable, ARM, version 1 (SYSV), st
atically linked, not stripped
Does anybody see why valgrind
seems no to be accepting memcheck-arm-linux
as a valid memcheck
tool?
Finally strace
gave solution to this problem.
Don't still have the trace, but strace
told very clearly that valgrind
was calling memcheck-arm-linux
with a wrong path. Was looking some path from the host compiler machine that obviously don't exist in the target machine.
That hinted the valgrind
build command should be changed from
$ export CROSS_COMPILE=arm-unknown-linux-gnueabi- && export CC=${CROSS_COMPILE}gc
c && export CPP=${CROSS_COMPILE}cpp && export CXX=${CROSS_COMPILE}g++ && export L
D=${CROSS_COMPILE}ld && export AR=${CROSS_COMPILE}ar && ./configure --target=arm-
unknown-linux-gnueabi --host=armv7a-none-linux-gnueabi --prefix=$HOME/valgrind-3.
6.1/construct CFLAGS='-static -march=armv7-a' -verbose 2>&1 && make clean && make
-j4 && make
to:
$ export CROSS_COMPILE=arm-unknown-linux-gnueabi- && export CC=${CROSS_COMPILE}gc
c && export CPP=${CROSS_COMPILE}cpp && export CXX=${CROSS_COMPILE}g++ && export L
D=${CROSS_COMPILE}ld && export AR=${CROSS_COMPILE}ar && ./configure --target=arm-
unknown-linux-gnueabi --host=armv7a-none-linux-gnueabi --prefix=/data/data/$APK_P
ACKAGE_NAMESPACE/files CFLAGS='-static -march=armv7-a' -verbose 2>&1 && make clea
n && make -j4 && make
You can see --prefix
is now correctly set to a path that exists in the target device, and is valid. Hardcoded. Dirty. Ugly. But is working now.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With