1. 安装NDK
2.设置NDK_ROOT
export NDK_ROOT=PATH/TO/YOUR/ANDROID/NDK/ROOT
3. 下载valgrind-3.11.0.tar.bz2
4. tar -xzf valgrind-3.11.0.tar.bz2
5. cd valgrind-3.11.0
6. 设置工具链 :
ARCH_ABI="arm-linux-androideabi-4.8"
HOSTOSN="darwin-x86_64"
export AR="$NDK_ROOT/toolchains/${ARCH_ABI}/prebuilt/${HOSTOSN}/bin/arm-linux-androideabi-ar"
export LD="$NDK_ROOT/toolchains/${ARCH_ABI}/prebuilt/${HOSTOSN}/bin/arm-linux-androideabi-ld"
export CC="$NDK_ROOT/toolchains/${ARCH_ABI}/prebuilt/${HOSTOSN}/bin/arm-linux-androideabi-gcc"
export CXX="$NDK_ROOT/toolchains/${ARCH_ABI}/prebuilt/${HOSTOSN}/bin/arm-linux-androideabi-g++"
#这个rand要设置,要不然就会在ld的时候用了默认的ranlib, 出错:no archive symbol table (run ranlib)
export RANLIB="$NDK_ROOT/toolchains/${ARCH_ABI}/prebuilt/${HOSTOSN}/bin/arm-linux-androideabi-ranlib"
export STRIP="$NDK_ROOT/toolchains/${ARCH_ABI}/prebuilt/${HOSTOSN}/bin/arm-linux-androideabi-strip"
7.设置sysroot, 记得要export,不然configure的时候,就会出错:"configure: error: C compiler cannot create executables"
export CPPFLAGS="--sysroot=$NDK_ROOT/platforms/android-19/arch-arm"
export CFLAGS="--sysroot=$NDK_ROOT/platforms/android-19/arch-arm"
android-19/ 这个挑一下你本地有的最新的就好。
8. configure, 生成makefile
./configure --prefix="/data/local/Inst" \
--host="armv7-unknown-linux" \
--target="armv7-unknown-linux" \
--with-tmpdir="/sdcard "
完成之后必须看到这两行,要是是其它的,这个出错了,看readme.android文件的说明。
# Platform variant: android
# Primary -DVGPV string: -DVGPV_arm_linux_android=1
9. 编译和生成:
make -j 4
10. 把编译好的文件整理出来到Inst目录
make -j4 install DESTDIR=`pwd`/Inst
完成之后,全部要完装的文件都在当前目录下的Inst里了。
11. 上传到手机
adb push Inst/data/local/ /data/local/Inst
使用:
写一个 start_valgrind.sh 上传到手机的 /data/local下:
#!/system/bin/sh
PACKAGE="com.example.hellojni"
# Callgrind tool
#VGPARAMS='-v --error-limit=no --trace-children=yes --log-file=/sdcard/valgrind.log.%p --tool=callgrind --callgrind-out-file=/sdcard/callgrind.out.%p'
# Memcheck tool
VGPARAMS='-v --error-limit=no --trace-children=yes --log-file=/sdcard/valgrind.log.%p --tool=memcheck --leak-check=full --show-reachable=yes'
export TMPDIR=/data/data/$PACKAGE
exec /data/local/Inst/bin/valgrind $VGPARAMS $*
本地写一个脚本: bootstrap_valgrind.sh
#!/usr/bin/env bash
PACKAGE="com.example.hellojni"
adb push start_valgrind.sh /data/local/
adb shell chmod 777 /data/local/start_valgrind.sh
adb root
adb shell "setprop wrap.$PACKAGE 'logwrapper /data/local/start_valgrind.sh'"
echo "wrap.$PACKAGE: $(adb shell getprop wrap.$PACKAGE)"
adb shell am force-stop $PACKAGE
#这个是关闭selinux, 要不然会出acv denied的错误
adb shell setenforce 0
#adb shell mount -o remount,rw -t ext4 /dev/block/platform/msm_sdcc.1/by-name/system /system
adb shell am start -a android.intent.action.MAIN -n $PACKAGE/.HelloJni
adb logcat -c
adb logcat
如果没有这个 adb shell setenforce 0 命令, 有会下面的错, 是因为selinux的权限问题,不让访问。
<36>[ 1365.720814] type=1400 audit(1472452195.847:5): avc: denied { write } for pid=2396 comm="main" path="pipe:[16280]" dev="pipefs" ino=16280 scontext=u:r:untrusted_app:s0 tcontext=u:r:zygote:s0 tclass=fifo_file
....这里去写pid就会出错
W/Zygote ( 198): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
补丁,实际跑的时候nexus5下还有一个出错的:
--13298-- Reading EXIDX entries: 19 attempted, 19 successful
disInstr(arm): unhandled instruction: 0xEC510F1E
cond=14(0xE) 27:20=197(0xC5) 4:4=1 3:0=14(0xE)
==13298== valgrind: Unrecognised instruction at address 0x4b1a908.
==13298== at 0x4B1A908: _armv7_tick (in /system/lib/libcrypto.so)
==13298== Your program just tried to execute an instruction that Valgrind
==13298== did not recognise. There are two possible reasons for this.
==13298== 1. Your program has a bug and erroneously jumped to a non-code
==13298== location. If you are running Memcheck and you just saw a
==13298== warning about a bad jump, it's probably your program's fault.
==13298== 2. The instruction is legitimate but Valgrind doesn't handle it,
==13298== i.e. it's Valgrind's fault. If you think this is the case or
==13298== you are not sure, please let us know and we'll try to fix it.
==13298== Either way, Valgrind will now raise a SIGILL signal which will
==13298== probably kill your program.
需要改改 valgrind-3.11.0/VEX/priv/guest_arm_toIR.c 17257行,加上以下代码:
/*
disInstr(arm): unhandled instruction: 0xEC510F1E
cond=14(0xE) 27:20=197(0xC5) 4:4=1 3:0=14(0xE)
*/
/*mrrc p15, 1, r0, r1, c14 */
if (0xEC510F1E == (insn & 0xFFFF0FFF)) {
UInt rK = INSN(15,12);
UInt rM = INSN(19,16);
if (rK <= 14&&rM <= 14) {
putIRegA(rK, mkU32(0), condT, Ijk_Boring);
putIRegA(rM, mkU32(0), condT, Ijk_Boring);
DIP("mrrc p15,1,r%u,r%u,r1,c14\n",rM,rK);
goto decode_success;
}
}