9

Hello I'm trying to build valgrind for android-arm. On Linux Mint 13 it fails with:

$ make
echo "# This is a generated file, composed of the following suppression rules:" > default.supp
echo "# " exp-sgcheck.supp xfree-3.supp xfree-4.supp glibc-2.X-drd.supp glibc-2.34567-NPTL-helgrind.supp glibc-2.X.supp  >> default.supp
cat exp-sgcheck.supp xfree-3.supp xfree-4.supp glibc-2.X-drd.supp glibc-2.34567-NPTL-helgrind.supp glibc-2.X.supp  >> default.supp
make  all-recursive
make[1]: Entering directory `/home/matt/Desktop/valgrind/valgrind-3.8.1'
Making all in include
make[2]: Entering directory `/home/matt/Desktop/valgrind/valgrind-3.8.1/include'
make[2]: Nothing to be done for `all'.
make[2]: Leaving directory `/home/matt/Desktop/valgrind/valgrind-3.8.1/include'
Making all in VEX
make[2]: Entering directory `/home/matt/Desktop/valgrind/valgrind-3.8.1/VEX'
make  all-am
make[3]: Entering directory `/home/matt/Desktop/valgrind/valgrind-3.8.1/VEX'
gcc -DHAVE_CONFIG_H -I. -I..  -I.. -I../include -I../VEX/pub -DVGA_arm=1 -DVGO_linux=1 -DVGP_arm_linux=1 -DVGPV_arm_linux_vanilla=1 -Ipriv  -m32 -O2 -g -Wall -Wmissing-prototypes -Wshadow -Wpointer-arith -Wstrict-prototypes -Wmissing-declarations -Wno-format-zero-length -fno-strict-aliasing -fno-builtin -marm -mcpu=cortex-a8 -Wbad-function-cast -Wcast-qual -Wcast-align -fstrict-aliasing -Wno-long-long  -Wno-pointer-sign -fno-stack-protector -MT libvex_arm_linux_a-main_globals.o -MD -MP -MF .deps/libvex_arm_linux_a-main_globals.Tpo -c -o libvex_arm_linux_a-main_globals.o `test -f 'priv/main_globals.c' || echo './'`priv/main_globals.c
gcc: warning: ‘-mcpu=’ is deprecated; use ‘-mtune=’ or ‘-march=’ instead
cc1: error: unrecognised command line option ‘-marm’
priv/main_globals.c:1:0: error: bad value (cortex-a8) for -mtune= switch
make[3]: *** [libvex_arm_linux_a-main_globals.o] Error 1
make[3]: Leaving directory `/home/matt/Desktop/valgrind/valgrind-3.8.1/VEX'
make[2]: *** [all] Error 2
make[2]: Leaving directory `/home/matt/Desktop/valgrind/valgrind-3.8.1/VEX'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/home/matt/Desktop/valgrind/valgrind-3.8.1'
make: *** [all] Error 2

I am using ndk-r8e and valgrind 3.8.1. The configure ends with:

     Maximum build arch: arm
     Primary build arch: arm
   Secondary build arch: 
               Build OS: linux
   Primary build target: ARM_LINUX
 Secondary build target: 
       Platform variant: vanilla
  Primary -DVGPV string: -DVGPV_arm_linux_vanilla=1
     Default supp files: exp-sgcheck.supp xfree-3.supp xfree-4.supp glibc-2.X-drd.supp glibc-2.34567-NPTL-helgrind.supp glibc-2.X.supp 

What can I do to fix this? Alternatively, are there any pre-built android-arm valgrind binaries that I can use?

Matthew Mitchell
  • 5,293
  • 14
  • 70
  • 122
  • The reason the configure script gets the kernel version wrong it that it is using the mac kernel version. However changing that one line to fake the configure script leads to a whole lot of errors later on. My recommendation is compiling on a linux machine (or VM) and just moving the binary over. – FDinoff May 14 '13 at 23:56
  • Hmmm. That's a good and very obvious idea. I wonder why I didn't try doing it on linux. I will do so in a little while. – Matthew Mitchell May 15 '13 at 16:15
  • Hmm. It's coming out with `Platform variant: vanilla` and `Primary -DVGPV string: -DVGPV_arm_linux_vanilla=1` on linux, using the same commands as above. – Matthew Mitchell May 15 '13 at 19:45
  • Your automake is somehow checking build system kernel version instead of host kernel version. Do you think there is a way to change this, by maybe using --build as the warning suggests ? – AlexK May 17 '13 at 12:51
  • @MatthewMitchell I think the Primary -DVGPV line is supposed to say `-DVGPV_arm_linux_android=1` and platform variant is also supposed to be `android`. However since I don't have access to my linux machine until monday I can't confirm this. – FDinoff May 18 '13 at 15:53
  • According to the README it should do, yes. I don't know why it doesn't when I run ./configure – Matthew Mitchell May 18 '13 at 15:55
  • @MatthewMitchell Can you post the line that you use to run configure – FDinoff May 18 '13 at 16:01
  • I use `CPPFLAGS="--sysroot=$NDK_HOME/platforms/android-14/arch-arm -DANDROID_HARDWARE_$HWKIND" CFLAGS="--sysroot=$NDK_HOME/platforms/android-14/arch-arm" sudo ./configure --prefix=/data/local/Inst --host=armv7-unknown-linux --target=armv7-unknown-linux --with-tmpdir=/sdcard0` – Matthew Mitchell May 18 '13 at 19:18
  • Why does the make output display gcc and not the ndk compiler? – Matthew Mitchell May 22 '13 at 15:57
  • @MatthewMitchell Because by default GNU Make uses the system GCC unless you define CC environment variable. Also for an easy way to build Valgrind for Android see my script here: http://stackoverflow.com/a/19255251/313113 – Alex Bitek Oct 08 '13 at 18:35

4 Answers4

19

For building and installing Valgrind for Android use the bash script below, which I prefer to call build_valgrind.sh

To run with RUN_HELLO_JNI_THROUGH_VALGRIND=true you need two additional scripts (bootstrap_valgrind.sh, start_valgrind.sh) in the directory you run the script below from.

Running the script with the RUN_HELLO_JNI_THROUGH_VALGRIND=true flag will build the hello-jni application from the samples directory inside the Android NDK HOME, deploy it to the phone and run it through Valgrind, using either callgrind or memcheck tool, which you can specify in the start_valgrind.sh script.

The other two scripts are described here: https://stackoverflow.com/a/19235439/313113

Here's my directory structure:

|-- build_valgrind.sh (the script below)
|-- bootstrap_valgrind.sh (second script from https://stackoverflow.com/a/19235439/313113)
|-- start_valgrind.sh (first script from https://stackoverflow.com/a/19235439/313113)
|-- valgrind-3.10.0 (will be extracted by build_valgrind.sh)
`-- valgrind-3.10.0.tar.bz2 (will be downloaded by build_valgrind.sh)

I've tested that its working (memcheck and callgrind tools) on a Samsung Galaxy Nexus device with CyanogenMod 10.2.1 and Android 4.3.1 and CyanogenMod 11 20140804 snapshot, Android 4.4.4

You can see the file size of the generated output with: adb shell ls -lR "/sdcard/*grind*"

The build_valgrind.sh script:

#!/usr/bin/env bash

#set -x 

function extract()
{
     if [ -f "$1" ] ; then
         case "$1" in
             *.tar.bz2)   tar xvjf "$1"     ;;
             *.tar.gz)    tar xvzf "$1"     ;;
             *.bz2)       bunzip2 "$1"      ;;
             *.rar)       unrar x "$1"      ;;
             *.gz)        gunzip "$1"       ;;
             *.tar)       tar xvf "$1"      ;;
             *.tbz2)      tar xvjf "$1"     ;;
             *.tgz)       tar xvzf "$1"     ;;
             *.zip)       unzip "$1"        ;;
             *.Z)         uncompress "$1"   ;;
             *.7z)        7z x "$1"         ;;
             *)           echo "$1 cannot be extracted via >extract<" ;;
         esac
     else
         echo "'$1' is not a valid file"
     fi
}

RUN_HELLO_JNI_THROUGH_VALGRIND=true
VALGRIND_VERSION="3.10.0"
VALGRIND_EXTENSION=".tar.bz2"
VALGRIND_DIRECTORY="valgrind-${VALGRIND_VERSION}"
VALGRIND_TARBALL="valgrind-${VALGRIND_VERSION}${VALGRIND_EXTENSION}"

# Only download Valgrind tarball again if not already downloaded
if [[ ! -f "${VALGRIND_TARBALL}" ]]; then
  wget -v -nc "http://valgrind.org/downloads/${VALGRIND_TARBALL}"
fi

# Only extract Valgrind tarball again if not already extracted
if [[ ! -d "$VALGRIND_DIRECTORY" ]]; then
  extract "$VALGRIND_TARBALL"
fi

# Ensure ANDROID_NDK_HOME is set
if [[ ! -z "$ANDROID_NDK_HOME" ]]; then
  export ANDROID_NDK_HOME="$HOME/Software/Android/android-ndk-r10c"
fi

# Ensure ANDOID_SDK_HOME is set
if [[ ! -z "$ANDROID_SDK_HOME" ]]; then
  export ANDROID_SDK_HOME="$HOME/Software/Android/android-sdk/"
fi

if [[ ! -d "$VALGRIND_DIRECTORY" ]];
then
  echo "Problem with extracting Valgrind from $VALGRIND_TARBALL into $VALGRIND_DIRECTORY!!!"
  exit -1
fi

# Move to extracted directory
cd "$VALGRIND_DIRECTORY"

# ARM Toolchain
ARCH_ABI="arm-linux-androideabi-4.9"
export AR="$ANDROID_NDK_HOME/toolchains/${ARCH_ABI}/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ar"
export LD="$ANDROID_NDK_HOME/toolchains/${ARCH_ABI}/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ld"
export CC="$ANDROID_NDK_HOME/toolchains/${ARCH_ABI}/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc"
export CXX="$ANDROID_NDK_HOME/toolchains/${ARCH_ABI}/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++"

[[ ! -d "$ANDROID_NDK_HOME" || ! -f "$AR" || ! -f "$LD" || ! -f "$CC" || ! -f "$CXX" ]] && echo "Make sure AR, LD, CC, CXX variables are defined correctly. Ensure ANDROID_NDK_HOME is defined also" && exit -1

# Configure build
export HWKIND="nexus_s"
ANDROID_PLATFORM=android-18
export CPPFLAGS="--sysroot=$ANDROID_NDK_HOME/platforms/${ANDROID_PLATFORM}/arch-arm -DANDROID_HARDWARE_$HWKIND"
export CFLAGS="--sysroot=$ANDROID_NDK_HOME/platforms/${ANDROID_PLATFORM}/arch-arm"

# BUG: For some reason file command is unable to detect if the file does not exist with ! -f , it says it doesn't exist even when it does!!!
BUILD=false
if [[ "${VALGRIND_DIRECTORY}/Inst/data/local/Inst/bin/valgrind" = *"No such file or directory"* ]]; then
  BUILD=true
fi

if [[ "$BUILD" = true ]];
then
  ./configure --prefix="/data/local/Inst" \
  --host="armv7-unknown-linux" \
  --target="armv7-unknown-linux" \
  --with-tmpdir="/sdcard "

  [[ $? -ne 0 ]] && echo "Can't configure!" && exit -1

  # Determine the number of jobs (commands) to be run simultaneously by GNU Make
  NO_CPU_CORES=$(grep -c ^processor /proc/cpuinfo)

  if [ $NO_CPU_CORES -le 8 ]; then
    JOBS=$(($NO_CPU_CORES+1))
  else
    JOBS=${NO_CPU_CORES}
  fi

  # Compile Valgrind 
  make -j "${JOBS}"

  [[ $? -ne 0 ]] && echo "Can't compile!" && exit -1

  # Install Valgrind locally
  make -j "${JOBS}" install DESTDIR="$(pwd)/Inst"
  [[ $? -ne 0 ]] && echo "Can't install!" && exit -1
fi

# Push local Valgrind installtion to the phone
if [[ $(adb shell ls -ld /data/local/Inst/bin/valgrind) = *"No such file or directory"* ]];
then
  adb root
  adb remount
  adb shell "[ ! -d /data/local/Inst ] && mkdir /data/local/Inst"
  adb push Inst /
  adb shell "ls -l /data/local/Inst"

  # Ensure Valgrind on the phone is running
  adb shell "/data/local/Inst/bin/valgrind --version"

  # Add Valgrind executable to PATH (this might fail)
  adb shell "export PATH=$PATH:/data/local/Inst/bin/"
fi

if [ $RUN_HELLO_JNI_THROUGH_VALGRIND = true ]; then
  PACKAGE="com.example.hellojni"

  # The location of the Hello JNI sample application
  HELLO_JNI_PATH="$ANDROID_NDK_HOME/samples/hello-jni"

  pushd "$HELLO_JNI_PATH" 

  # Update build target to the desired Android SDK version
  ANDROID_PROJECT_TARGET="android-18"
  android update project --target "$ANDROID_PROJECT_TARGET" --path . --name hello-jni --subprojects

  # Enable Android NDK build with Ant
  echo '<?xml version="1.0" encoding="utf-8"?>

    <project name="HelloJni" basedir="." default="debug">

    <target name="-pre-build">
      <exec executable="${ndk.dir}/ndk-build" failonerror="true"/>
    </target>

    <target name="clean" depends="android_rules.clean">
      <exec executable="${ndk.dir}/ndk-build" failonerror="true">
      <arg value="clean"/>
      </exec>
    </target> 

    </project>
  ' > "custom_rules.xml"

  # Set NDK HOME for Ant (only if not already set)
  if ! grep -P -q "ndk.dir=.+" "local.properties" ; then
    echo -e "\nndk.dir=$ANDROID_NDK_HOME" >> "local.properties"
  fi

  # Fix for Java 8 warning (warning: [options] source value 1.5 is obsolete and will be removed in a future release)
  echo "java.compilerargs=-Xlint:-options" >> "ant.properties"

  # Workaround INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES error
  adb uninstall "$PACKAGE"

  # Build Hello JNI project in debug mode and install it on the device
  ant clean && ant debug && ant installd

  popd

  cd ..  

  # Start HelloJNI app 
  adb shell am start -a android.intent.action.MAIN -n $PACKAGE/.HelloJni

  # Make the script executable
  chmod a+x bootstrap_valgrind.sh

  # Run application through Valgrind on the phone
  /usr/bin/env bash bootstrap_valgrind.sh

  adb shell ls -lR "/sdcard/*grind*"
  adb shell ls -lR "/storage/sdcard0/*grind*"
  adb shell ls -lR "/storage/sdcard1/*grind*"
fi

exit 0 
Community
  • 1
  • 1
Alex Bitek
  • 6,529
  • 5
  • 47
  • 77
  • Thanks. This script may indeed be useful for some though it's not the answer to my particular problem. I'm going to put up an answer stating what my problem was, as I figured it out. – Matthew Mitchell Oct 08 '13 at 19:06
  • Everyone should be aware that you cannot currently cross compile Valgrind like this on OSX 10.9.x Additionally, you may need to disable the kernel check during the ./configure step. – Jeff Schmitz Jun 12 '14 at 23:40
  • @JeffSchmitz Why? What are some reasons why this wouldn't work on OS X? I've tested the script on a GNU/Linux desktop. – Alex Bitek Jun 13 '14 at 06:03
  • Take a look at the Valgrind website, they state support for osx 10.7 and some support for 10.8. "AMD64/Darwin (Mac OS X 10.7, with limited support for 10.8) is available" You can get it to build most of the way, but eventually you get linker errors during compilation. My best guess is that some of the PATH elements changed locations between 10.7/8/9, and as a result, linking fails. I ended up compiling on a Linux VM with no issues. – Jeff Schmitz Jun 16 '14 at 21:02
  • I get this error on Ubuntu 14.04 with ndk-10c: gcc: warning: ‘-mcpu=’ is deprecated; use ‘-mtune=’ or ‘-march=’ instead gcc: error: unrecognized command line option ‘-marm’ Makefile:1154: recipe for target 'priv/libvex_arm_linux_a-main_globals.o' failed make[3]: *** [priv/libvex_arm_linux_a-main_globals.o] Error 1 make[3]: *** Waiting for unfinished jobs.... gcc: warning: ‘-mcpu=’ is deprecated; use ‘-mtune=’ or ‘-march=’ instead gcc: error: unrecognized command line option ‘-marm’ – ssk Oct 30 '14 at 17:48
  • @ssk Are you using my scripts? I've just tried it with Android NDK r10c and it works. I've also made some updates to the above build_valgrind.sh script. Try again and let me know how it goes. – Alex Bitek Oct 30 '14 at 18:57
  • @Dr.SkyLizard Yes, I used a script derived from yours: http://pastebin.com/NMdrT6J8. Here is the error that I am seeing: http://pastebin.com/i8t08dP9 – ssk Oct 30 '14 at 19:30
  • @ssk You are using the *wrong* toolchain! i.e. a non ARM one. Make sure $ANDROID_NDK_HOME points to the correct path to the Android NDK and that $ANDROID_NDK_HOME/toolchains/${ARCH_ABI}/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc is a valid path to the C compiler executable within the NDK (also check for the other toolchain commands, linker, C++ compiler, etc.) – Alex Bitek Oct 30 '14 at 21:34
  • @bitek Im following your answer about build and run valgrind android. But I can not see any log... Im using grandle. This is my script. Can you help me find error in my scipt. Link Script. https://stackoverflow.com/questions/46802787/valgrind-android-doesnt-show-log – huy nguyen Oct 19 '17 at 03:57
2

This gets valgrind to compile for me on linux. (using android-ndk-r8e and valgrind-3.8.1)

There was no need to run autogen.sh since I downloaded the tar ball from the website.

Also make sure the TOOLCHAIN= line points to a valid toolchain.

export NDK_HOME=$HOME/Downloads/android-ndk-r8e

export HWKIND=generic

export TOOLCHAIN=$NDK_HOME/toolchains/arm-linux-androideabi-4.7/prebuilt/linux-x86_64/bin/arm-linux-androideabi

export AR=$TOOLCHAIN-ar
export LD=$TOOLCHAIN-ld
export CC=$TOOLCHAIN-gcc

CPPFLAGS="--sysroot=$NDK_HOME/platforms/android-14/arch-arm -DANDROID_HARDWARE_$HWKIND" \
    CFLAGS="--sysroot=$NDK_HOME/platforms/android-14/arch-arm" \
    ./configure --prefix=/data/local/Inst \
    --host=armv7-unknown-linux --target=armv7-unknown-linux \
    --with-tmpdir=/sdcard

make 

It eventually came up with a compile error saying

$NDK_HOME/platforms/android-14/arch-arm/usr/include/elf.h:58:3: error: unknown type name 'uint32_t'

It seem like someone forgot to add #include <stdint.h> somewhere. To fix this I edited $NDK_HOME/platforms/android-14/arch-arm/usr/include/elf.h and added #include <stdint.h> to the include section of this header. NOTE: This is probably not the best fix but it is the one that I came up with that fixed the compilation errors.


On mac I was able to get it to compile up until the unknown type uint32_t part by changing how the configure script checks the kernel version.

Inside the configure script search of a line kernel=`uname -r` and change it to kernel=3.9.2. (There are two kernel=`uname -r` lines replace the first one or both if you feel like it)

This stops the configure script from looking at the host kernel when deciding how it should build valgrind. (uname -r grabs the host kernel)

I believe adding the #include <stdint.h> to elf.h should work on mac to but I have not tested it.

FDinoff
  • 30,689
  • 5
  • 75
  • 96
  • Thanks for the answer. I get `cc1: error: unrecognised command line option ‘-marm’` on Linux Mint when running make after following your instructions. What distribution are you using? – Matthew Mitchell May 18 '13 at 14:51
  • Or instead if you could upload your binary, that would be great. I have no idea why I can't find a single binary online. – Matthew Mitchell May 18 '13 at 14:55
  • It was gentoo. Also I was using 64bit Version can you make sure the tool chain points to the 32 bit version if needed. (It might also be good if you could point put all the commands in a shell script so you could check for typos) I can upload the binary latter if needed. – FDinoff May 18 '13 at 15:07
  • I am using the 32-bit but made sure I was using the right path. – Matthew Mitchell May 18 '13 at 15:30
  • I've edited the question to give the full make output on Linux Mint. – Matthew Mitchell May 18 '13 at 15:45
2

in android tutorial one option is missed RANLIB, after I set it - I finally compiled valgrind-3.11.0 on osx for android

#/bin/sh

echo "NKDROOT: " $NDKROOT

export ANRDOID_TOOLCHAIN="arm-linux-androideabi-4.9"

# Set up toolchain paths.
#
# For ARM
export AR=$NDKROOT/toolchains/$ANRDOID_TOOLCHAIN/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-ar
export LD=$NDKROOT/toolchains/$ANRDOID_TOOLCHAIN/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-ld
export CC=$NDKROOT/toolchains/$ANRDOID_TOOLCHAIN/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-gcc
export CXX=$NDKROOT/toolchains/$ANRDOID_TOOLCHAIN/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-g++
export RANLIB=$NDKROOT/toolchains/$ANRDOID_TOOLCHAIN/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-ranlib

echo "AR: " $AR
echo "LD: " $LD
echo "CC: " $CC
echo "CXX: " $CXX

[[ ! -d "$NDKROOT" || ! -f "$AR" || ! -f "$LD" || ! -f "$CC" || ! -f "$CXX" ]] && echo "Make sure AR, LD, CC, CXX variables are defined correctly. Ensure NDKROOT is defined also" && exit -1

./autogen.sh

#if [ $? -ne 0 ]
#then
#    exit 1
#else
#    echo "autogen success!"
#fi

# for ARM
ANDROID_PLATFORM=android-3
ANDROID_SYSROOT="$NDKROOT/platforms/${ANDROID_PLATFORM}/arch-arm"
echo "SYSROOT: " $ANDROID_SYSROOT

export HWKIND=generic 
export CPPFLAGS="--sysroot=$ANDROID_SYSROOT -DANDROID_HARDWARE_$HWKIND"
export CFLAGS="--sysroot=$ANDROID_SYSROOT -DANDROID_HARDWARE_$HWKIND"
export LDFLAGS="--sysroot=$ANDROID_SYSROOT -DANDROID_HARDWARE_$HWKIND"
export ARFLAGS="--sysroot=$ANDROID_SYSROOT -DANDROID_HARDWARE_$HWKIND"

./configure \
    --prefix=/data/local/Inst \
    --host=armv7-unknown-linux --target=armv7-unknown-linux \
    --with-tmpdir=/sdcard

if [ $? -ne 0 ]
then
    exit 1
else
    echo "configure success!"
fi
# note: on android emulator, android-14 platform was also tested and works.
# It is not clear what this platform nr really is.

make -j7
if [ $? -ne 0 ]
then
    exit 1
else
    echo "build success!"
fi

make -j7 install DESTDIR=`pwd`/Inst
1

The problem I had was that the configure script was ignoring the environment variables. To configure the make file I instead did this:

sudo ./configure --prefix=/data/local/Inst --host=armv7-unknown-linux --target=armv7-unknown-linux --with-tmpdir=/sdcard0 CPPFLAGS="--sysroot=$NDKROOT/platforms/android-3/arch-arm -DANDROID_HARDWARE_$HWKIND" CFLAGS="--sysroot=$NDKROOT/platforms/android-3/arch-arm" CC=$CC LD=$LD AR=$AR

This ensures the variables are set properly and works with Linux Mint 13. It does not work on OSX Mountain Lion however. I'd advise anyone using OSX without access to a linux installation to try using linux on a virtual machine.

Matthew Mitchell
  • 5,293
  • 14
  • 70
  • 122