7

*EDIT June 2020: Unbelievably I came to my own (3 year old) question here from google after trying to help a coworker debug native code in our app on his new mac. AndroidStudio 4.0 with Gradle 6 and debugging native code is still something like sorcery! We have 3 developers, only 1 machine is this working. Same code base, same version of AndroidStudio, all 3 running Catalina. I'm just baffled.

EDIT: This is still unresolved. I suspected based on the comments that my use of an old NDK (10d) might be a problem so I upgraded to 15c and dealt with all the issues to get my stuff to compile with clang and the new c++ library. Unfortunately ndk-gdb is broken in 15c and my attempts to hack the python to make it work didn't get me anywhere. I then used Android Studio 3.0 preview and I'm back to where I was before - I can see stack information but all the code is assembly in lldb. Work must go on - I am back to using logcat for debugging :(

I come to you with a bruised forehead from numerous hits on the wall.

I'll try to be concise and provide all relevant information at the same time. If there is any relevant info I haven't included please let me know.

Synopsis:

I am maintaining an Android app as part of my job. I have had to resort to logging to debug native code because although I can set breakpoints and hit them, I can't view the source or variable information.

I've spent many hours and google searches trying to understand what I'm missing, yet still no luck.

My build environment is OSX using Android NDK r10D, and gradle 3.2 to build the APK.

I'm trying to use AndroidStudio 3.0 beta 6 to install and debug the APK.

My Android.manifest includes in the tag:

android:debuggable="true"

Native Code:

This is sample output from compiling one of the native c++ files with -v for verbosity:

~/src/libraries/cBase$ make android
Building obj/Binary.ao
Using built-in specs.
COLLECT_GCC=arm-linux-androideabi-g++
Target: arm-linux-androideabi
Configured with: /s/ndk-toolchain/src/build/../gcc/gcc-4.8/configure --prefix=/tmp/ndk-User/build/toolchain/prefix --target=arm-linux-androideabi --host=x86_64-apple-darwin --build=x86_64-apple-darwin --with-gnu-as --with-gnu-ld --enable-languages=c,c++ --with-gmp=/tmp/ndk-User/build/toolchain/temp-install --with-mpfr=/tmp/ndk-User/build/toolchain/temp-install --with-mpc=/tmp/ndk-User/build/toolchain/temp-install --with-cloog=/tmp/ndk-User/build/toolchain/temp-install --with-isl=/tmp/ndk-User/build/toolchain/temp-install --with-ppl=/tmp/ndk-User/build/toolchain/temp-install --disable-ppl-version-check --disable-cloog-version-check --disable-isl-version-check --enable-cloog-backend=isl --with-host-libstdcxx='-static-libgcc -lstdc++ -lm' --disable-libssp --enable-threads --disable-nls --disable-libmudflap --disable-libgomp --disable-libstdc__-v3 --disable-sjlj-exceptions --disable-shared --disable-tls --disable-libitm --with-float=soft --with-fpu=vfp --with-arch=armv5te --enable-target-optspace --enable-initfini-array --disable-nls --prefix=/tmp/ndk-User/build/toolchain/prefix --with-sysroot=/tmp/ndk-User/build/toolchain/prefix/sysroot --with-binutils-version=2.24 --with-mpfr-version=3.1.1 --with-mpc-version=1.0.1 --with-gmp-version=5.0.5 --with-gcc-version=4.8 --with-gdb-version=7.6 --with-python=/Users/User/mydroid/ndk/prebuilt/darwin-x86_64/bin/python-config.sh --with-gxx-include-dir=/tmp/ndk-User/build/toolchain/prefix/include/c++/4.8 --with-bugurl=http://source.android.com/source/report-bugs.html --enable-languages=c,c++ --disable-bootstrap --enable-plugins --enable-libgomp --disable-libsanitizer --enable-gold --enable-graphite=yes --with-cloog-version=0.18.0 --with-isl-version=0.11.1 --enable-eh-frame-hdr-for-static --with-arch=armv5te --program-transform-name='s&^&arm-linux-androideabi-&' --enable-gold=default
Thread model: posix
gcc version 4.8 (GCC) 
COLLECT_GCC_OPTIONS='-Wextra' '-Wall' '-g' '-v' '-D' 'ANDROID' '-O0' '-g' '-c' '-MMD' '-MP' '-I' '/Users/spartygw/src/libraries' '-I' '/Users/spartygw/src/libraries/thirdparty' '-I' '/Users/spartygw/src/libraries/thirdparty/jpeg' '-I' '/Users/spartygw/src/libraries/thirdparty/zlib' '-I' '/Users/spartygw/src/include' '-I' '/Users/spartygw/android-toolchain/sysroot/usr/include' '-D' '__ARM_ARCH_5__' '-D' '__ARM_ARCH_5T__' '-D' '__ARM_ARCH_5E__' '-D' '__ARM_ARCH_5TE__' '-D' '__ANDROID__' '-D' 'DEBUG' '-o' 'obj/Binary.ao' '-march=armv5te' '-mfloat-abi=soft' '-mfpu=vfp' '-mtls-dialect=gnu'
 /Users/spartygw/android-toolchain/bin/../libexec/gcc/arm-linux-androideabi/4.8/cc1plus -quiet -v -I /Users/spartygw/src/libraries -I /Users/spartygw/src/libraries/thirdparty -I /Users/spartygw/src/libraries/thirdparty/jpeg -I /Users/spartygw/src/libraries/thirdparty/zlib -I /Users/spartygw/src/include -I /Users/spartygw/android-toolchain/sysroot/usr/include -iprefix /Users/spartygw/android-toolchain/bin/../lib/gcc/arm-linux-androideabi/4.8/ -isysroot /Users/spartygw/android-toolchain/bin/../sysroot -MMD obj/Binary.d -MP -MQ obj/Binary.ao -D_GNU_SOURCE -D ANDROID -D __ARM_ARCH_5__ -D __ARM_ARCH_5T__ -D __ARM_ARCH_5E__ -D __ARM_ARCH_5TE__ -D __ANDROID__ -D DEBUG Binary.cc -mbionic -fpic -quiet -dumpbase Binary.cc -march=armv5te -mfloat-abi=soft -mfpu=vfp -mtls-dialect=gnu -auxbase-strip obj/Binary.ao -g -g -O0 -Wextra -Wall -version -fexceptions -frtti -o /var/folders/03/hpjtv8c969scgcc5121ybrwr0000gn/T//ccciFNCN.s
GNU C++ (GCC) version 4.8 (arm-linux-androideabi)
    compiled by GNU C version 4.2.1 (Apple Inc. build 5666) (dot 3), GMP version 5.0.5, MPFR version 3.1.1, MPC version 1.0.1
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/Users/spartygw/android-toolchain/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/include"
ignoring nonexistent directory "/Users/spartygw/android-toolchain/bin/../lib/gcc/../../include/c++/4.8/backward"
ignoring duplicate directory "/Users/spartygw/android-toolchain/bin/../lib/gcc/../../lib/gcc/arm-linux-androideabi/4.8/include"
ignoring nonexistent directory "/Users/spartygw/android-toolchain/bin/../sysroot/usr/local/include"
ignoring duplicate directory "/Users/spartygw/android-toolchain/bin/../lib/gcc/../../lib/gcc/arm-linux-androideabi/4.8/include-fixed"
ignoring nonexistent directory "/Users/spartygw/android-toolchain/bin/../lib/gcc/../../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/include"
ignoring nonexistent directory "/Users/spartygw/src/include"
ignoring duplicate directory "/Users/spartygw/android-toolchain/sysroot/usr/include"
  as it is a non-system directory that duplicates a system directory
#include "..." search starts here:
#include <...> search starts here:
 /Users/spartygw/src/libraries
 /Users/spartygw/src/libraries/thirdparty
 /Users/spartygw/src/libraries/thirdparty/jpeg
 /Users/spartygw/src/libraries/thirdparty/zlib
 /Users/spartygw/android-toolchain/bin/../lib/gcc/arm-linux-androideabi/4.8/include
 /Users/spartygw/android-toolchain/bin/../lib/gcc/arm-linux-androideabi/4.8/include-fixed
 /Users/spartygw/android-toolchain/bin/../lib/gcc/../../include/c++/4.8
 /Users/spartygw/android-toolchain/bin/../lib/gcc/../../include/c++/4.8/arm-linux-androideabi
 /Users/spartygw/android-toolchain/bin/../sysroot/usr/include
End of search list.
GNU C++ (GCC) version 4.8 (arm-linux-androideabi)
    compiled by GNU C version 4.2.1 (Apple Inc. build 5666) (dot 3), GMP version 5.0.5, MPFR version 3.1.1, MPC version 1.0.1
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 7c7303e2f21bf352ab9993b8ba84df0b
                                                                                                                                                  ^
COLLECT_GCC_OPTIONS='-Wextra' '-Wall' '-g' '-v' '-D' 'ANDROID' '-O0' '-g' '-c' '-MMD' '-MP' '-I' '/Users/spartygw/src/libraries' '-I' '/Users/spartygw/src/libraries/thirdparty' '-I' '/Users/spartygw/src/libraries/thirdparty/jpeg' '-I' '/Users/spartygw/src/libraries/thirdparty/zlib' '-I' '/Users/spartygw/src/include' '-I' '/Users/spartygw/android-toolchain/sysroot/usr/include' '-D' '__ARM_ARCH_5__' '-D' '__ARM_ARCH_5T__' '-D' '__ARM_ARCH_5E__' '-D' '__ARM_ARCH_5TE__' '-D' '__ANDROID__' '-D' 'DEBUG' '-o' 'obj/Binary.ao' '-march=armv5te' '-mfloat-abi=soft' '-mfpu=vfp' '-mtls-dialect=gnu'
 /Users/spartygw/android-toolchain/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/as -v -I /Users/spartygw/src/libraries -I /Users/spartygw/src/libraries/thirdparty -I /Users/spartygw/src/libraries/thirdparty/jpeg -I /Users/spartygw/src/libraries/thirdparty/zlib -I /Users/spartygw/src/include -I /Users/spartygw/android-toolchain/sysroot/usr/include -march=armv5te -mfloat-abi=soft -mfpu=vfp -meabi=5 --noexecstack -o obj/Binary.ao /var/folders/03/hpjtv8c969scgcc5121ybrwr0000gn/T//ccciFNCN.s
GNU assembler version 2.24 (arm-linux-androideabi) using BFD version (GNU Binutils) 2.24
COMPILER_PATH=/Users/spartygw/android-toolchain/bin/../libexec/gcc/arm-linux-androideabi/4.8/:/Users/spartygw/android-toolchain/bin/../libexec/gcc/:/Users/spartygw/android-toolchain/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/
LIBRARY_PATH=/Users/spartygw/android-toolchain/bin/../lib/gcc/arm-linux-androideabi/4.8/:/Users/spartygw/android-toolchain/bin/../lib/gcc/:/Users/spartygw/android-toolchain/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/lib/:/Users/spartygw/android-toolchain/bin/../sysroot/usr/lib/
COLLECT_GCC_OPTIONS='-Wextra' '-Wall' '-g' '-v' '-D' 'ANDROID' '-O0' '-g' '-c' '-MMD' '-MP' '-I' '/Users/spartygw/src/libraries' '-I' '/Users/spartygw/src/libraries/thirdparty' '-I' '/Users/spartygw/src/libraries/thirdparty/jpeg' '-I' '/Users/spartygw/src/libraries/thirdparty/zlib' '-I' '/Users/spartygw/src/include' '-I' '/Users/spartygw/android-toolchain/sysroot/usr/include' '-D' '__ARM_ARCH_5__' '-D' '__ARM_ARCH_5T__' '-D' '__ARM_ARCH_5E__' '-D' '__ARM_ARCH_5TE__' '-D' '__ANDROID__' '-D' 'DEBUG' '-o' 'obj/Binary.ao' '-march=armv5te' '-mfloat-abi=soft' '-mfpu=vfp' '-mtls-dialect=gnu'

Android.mk:

My Android.mk in the jni directory looks like this:

LOCAL_PATH := $(call my-dir)


############## libGabObjs ##################
include $(CLEAR_VARS)
LOCAL_MODULE = libGabObjs
LOCAL_SRC_FILES := libGabObjs_android.a
ifneq (,$(wildcard $(LOCAL_SRC_FILES)))
  include $(PREBUILT_STATIC_LIBRARY)
endif
######################################

#####################################
############## libavcodec ##############
include $(CLEAR_VARS)

LOCAL_MODULE := libavcodec
LOCAL_SRC_FILES := ../../../../lib/third-party/arm-android/libavcodec.so

include $(PREBUILT_SHARED_LIBRARY)
#####################################

############## libavutil ##############
include $(CLEAR_VARS)

LOCAL_MODULE := libavutil
LOCAL_SRC_FILES := ../../../../lib/third-party/arm-android/libavutil.so

include $(PREBUILT_SHARED_LIBRARY)
#####################################

############## libswscale ##############
include $(CLEAR_VARS)

LOCAL_MODULE := libswscale
LOCAL_SRC_FILES := ../../../../lib/third-party/arm-android/libswscale.so

include $(PREBUILT_SHARED_LIBRARY)
#####################################

############## libspeex ##############
include $(CLEAR_VARS)

LOCAL_MODULE := libspeex
LOCAL_SRC_FILES := ../../../../lib/third-party/arm-android/libspeex.a

include $(PREBUILT_STATIC_LIBRARY)
#####################################

############## libspeexdsp ##############
include $(CLEAR_VARS)

LOCAL_MODULE := libspeexdsp
LOCAL_SRC_FILES := ../../../../lib/third-party/arm-android/libspeexdsp.a

include $(PREBUILT_STATIC_LIBRARY)
#####################################

############## libjpeg ##############
include $(CLEAR_VARS)

LOCAL_MODULE := libjpeg
LOCAL_SRC_FILES := ../../../../lib/third-party/arm-android/libjpeg.a

include $(PREBUILT_STATIC_LIBRARY)
#####################################

############## libcrypto ############
include $(CLEAR_VARS)

LOCAL_MODULE := libcrypto
LOCAL_SRC_FILES := ../../../../lib/third-party/arm-android/libcrypto.a

include $(PREBUILT_STATIC_LIBRARY)
#####################################

############## libssl #############
include $(CLEAR_VARS)

LOCAL_MODULE := libssl
LOCAL_SRC_FILES := ../../../../lib/third-party/arm-android/libssl.a

include $(PREBUILT_STATIC_LIBRARY)
#####################################


############## libcutils #############
#include $(CLEAR_VARS)

#LOCAL_MODULE := libcutils
#LOCAL_SRC_FILES := ../../../../lib/third-party/arm-android/libcutils.so

#include $(PREBUILT_SHARED_LIBRARY)
#####################################





############## libs ############
include $(CLEAR_VARS)

LOCAL_MODULE := vhc_jnilib

LOCAL_SRC_FILES := video_codec_jni.cpp \
                   MyBaseThread.cc \
                   MicMonitor.cpp \
                   framework.cpp \
                   GabrielJni.cpp



LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/../../../libraries/ \
$(LOCAL_PATH)/../../../libraries/thirdparty/

LOCAL_STATIC_LIBRARIES := \
libGabObjs \
libssl \
libcrypto \
libjpeg \
libspeex \
libspeexdsp

LOCAL_SHARED_LIBRARIES := \
libavcodec libavutil libswscale

A_DEFINES :=  -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -D__ANDROID__ -DDEBUG $(ADDDEF)
DEFINES :=$(DEFINES) 
LOCAL_LDLIBS = -lOpenSLES -lz -llog -landroid
LOCAL_CPPFLAGS := -D_FILE_OFFSET_BITS=64 -DDEBUG -D__ANDROID__
LOCAL_CFLAGS = -DFIXED_POINT -DEXPORT="" -g -O0 -fexceptions -funroll-loops -UHAVE_CONFIG_H -I../../libraries

include $(BUILD_SHARED_LIBRARY)


####
####
#### now build older vhcjnilib for lollipop and older
####
####


#####################################
############## libavcodec_lollipop ##############
include $(CLEAR_VARS)

LOCAL_MODULE := libavcodec_lollipop
LOCAL_SRC_FILES := ../../../../lib/third-party/arm-android/libavcodec_lollipop.so

include $(PREBUILT_SHARED_LIBRARY)
#####################################

############## libavutil_lollipop ##############
include $(CLEAR_VARS)

LOCAL_MODULE := libavutil_lollipop
LOCAL_SRC_FILES := ../../../../lib/third-party/arm-android/libavutil_lollipop.so

include $(PREBUILT_SHARED_LIBRARY)
#####################################

############## libswscale_lollipop ##############
include $(CLEAR_VARS)

LOCAL_MODULE := libswscale_lollipop
LOCAL_SRC_FILES := ../../../../lib/third-party/arm-android/libswscale_lollipop.so

include $(PREBUILT_SHARED_LIBRARY)
#####################################



############## libs ############
include $(CLEAR_VARS)

LOCAL_MODULE := vhc_jnilib_lollipop

LOCAL_SRC_FILES := video_codec_jni.cpp \
                   MyBaseThread.cc \
                   MicMonitor.cpp \
                   framework.cpp \
                   GabrielJni.cpp



LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/../../../libraries/ \
$(LOCAL_PATH)/../../../libraries/thirdparty/

LOCAL_STATIC_LIBRARIES := \
libGabObjs \
libssl \
libcrypto \
libjpeg \
libspeex \
libspeexdsp

LOCAL_SHARED_LIBRARIES := \
libavcodec_lollipop libavutil_lollipop libswscale_lollipop

A_DEFINES :=  -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -D__ANDROID__ -DDEBUG $(ADDDEF)
DEFINES :=$(DEFINES) 
LOCAL_LDLIBS = -lOpenSLES -lz -llog -landroid
LOCAL_CPPFLAGS := -D_FILE_OFFSET_BITS=64 -DDEBUG -D__ANDROID__
LOCAL_CFLAGS = -DFIXED_POINT -DEXPORT="" -g -fexceptions -funroll-loops -UHAVE_CONFIG_H -I../../libraries

include $(BUILD_SHARED_LIBRARY)

Application.mk:

APP_STL                 := stlport_static
APP_PLATFORM            := android-10
APP_ABI                 := armeabi-v7a
APP_OPTIM               := debug

My build.gradle file:

//////////////////////////////////////////////////////////////////////////////

// need this for password dialog 
import groovy.swing.SwingBuilder

buildscript {
    System.properties['com.android.build.gradle.overrideVersionCheck'] = 'true'

    repositories {
        jcenter()
    }

    dependencies {
        // Current Gradle version.
        final GradleVersion gradleVersion = GradleVersion.current()

        // Gradle version 3.0+ requires a different classpath 
        final GradleVersion gradle3 = GradleVersion.version('3.0')

        // Compare versions.
        if (gradleVersion >= gradle3) {
            println "Your Gradle version is at least 3.0"
            classpath 'com.android.tools.build:gradle:2.2.0'
        } else {
            println "Your Gradle version is older than 3.0"
            classpath 'com.android.tools.build:gradle:2.1.0'
        }
    }
}


apply plugin: 'com.android.application'

android {
    lintOptions {
        disable 'LongLogTag','ProtectedPermissions','AppLinksAutoVerifyError','MangledCRLF'
    }

    defaultConfig {
        applicationId "com.mycompany.myapp.myclass"
    }   


    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
            jniLibs.srcDirs = ['libs']
        }

        debug.setRoot('build-types/debug')
        release.setRoot('build-types/release')
    }


    signingConfigs {
        release {
            // We can leave these in environment variables
            storeFile file(String.valueOf(System.getenv("PKCS12_FILE")))
            keyAlias "mykey"

            // These two lines make gradle believe that the signingConfigs
            // section is complete. Without them, tasks like installRelease
            // will not be available!
            storePassword "notYourRealPassword"
            keyPassword "notYourRealPassword"
        }
    }

    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
        debug {
            debuggable true
            jniDebuggable true
        }
    }
}

dependencies {
    compile 'com.android.support:support-v4:23.1.1'
    compile 'com.google.android.gms:play-services:8.4.0'
}

task askForPasswords {
    doLast {
        def pw = ''

        if(System.console() == null) {
            new SwingBuilder().edt {
                dialog(modal: true, title: 'Enter password', alwaysOnTop: true, resizable: false, locationRelativeTo: null, pack: true, show: true) {
                    vbox { // Put everything below each other
                        label(text: "Signing the APK...Enter the keystore password:")
                        def input1 = passwordField()
                        button(defaultButton: true, text: 'OK', actionPerformed: {
                            pw = new String(input1.password);
                            dispose();
                        })
                    }
                }
            }
        } else {
            // Must create String because System.readPassword() returns char[]
            // (and assigning that below fails silently)
            pw = new String(System.console().readPassword("Keystore password: "))
        }



        android.signingConfigs.release.storePassword = pw
        android.signingConfigs.release.keyPassword = pw
    }
}

tasks.whenTaskAdded { theTask -> 
    if (theTask.name.equals("packageRelease")) {
        theTask.dependsOn "askForPasswords"
    }
}

task getVersion() {
  println GradleVersion.current().getVersion()
}
Marcin Orlowski
  • 72,056
  • 11
  • 123
  • 141
spartygw
  • 3,289
  • 2
  • 27
  • 51
  • Just to clarify you are using/following the separate build instructions for the ndk-gdb: https://developer.android.com/ndk/guides/ndk-gdb.html ? Also related SO question: https://stackoverflow.com/questions/42358194/how-to-debug-android-studio-project-using-ndk-and-jni-line-by-line-to-see-the – Morrison Chang Oct 04 '17 at 17:26
  • So from that related question it seems that the consensus is that logging is what most folks are doing. Sad to read that. Regarding ndk-gdb I am confused on how that is supposed to be run. I am trying to use Android Studio as the debugger interface. It seems to work as far as hitting breakpoints and looking at the stack for threads but all debug symbols seem stripped. I suspected it is a compiler flag to the cross compiler that is not enabling debug but I can't see what I might be doing wrong. – spartygw Oct 04 '17 at 18:35
  • Have you tried [to set symbol source map](https://stackoverflow.com/a/32660754/192373)? – Alex Cohn Oct 04 '17 at 20:37
  • I did but I still see assembly when a breakpoint is hit. Compiling with `-g -O0 and -DDEBUG` is all I should need to do to cross compile and keep debug symbols right? Thanks for looking at my question. – spartygw Oct 06 '17 at 11:56
  • NDK new versions do replace the old MK files for cmake files. Using those enable you to build trough AndroidStudio, and that was usually enough to debug native code. – Marcos Vasconcelos Oct 10 '17 at 15:03
  • Almost 3 years later and I've run into another case where a development machine fails to enable debugging native code through android studio. Funny that googling brought me to my old post and there's still no answer. I love the Android OS but the tools to support development on it are waaaay behind the likes of Xcode for iOS – spartygw Jun 11 '20 at 19:25

0 Answers0