Android Studio 调试已经编译好的带符号SO

使用Visual Studio 2017开发android ndk一文中已经讲了如何使用Visual Studio高效的进行ndk开发,那么问题来了,使用Visual Studio确实能加快代码的编写速度,但是由于程序是运行在android手机上的,如何进行debug便成了问题。

以前debug都是使用GDB,这个工具确实不好用,Android Studio 2.2版本带来了全新的对Android Native代码的开发以及调试支持,另外LLDB的Android调试插件也日渐成熟,安装LLDB+LLVM插件后,Android Studio对C/C++进行调试将是主流。

1.安装LLDB等插件

从SDK Manager中安装CMake,LLDB,NDK,其中ndk版本要大于r12。

2.打开工程Native调试

第一步:在build.gradle文件debug编译类型中添加debuggable true和jniDebuggable true两个设置

    buildTypes {
        debug {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            debuggable true
            jniDebuggable true
        }
    }

或者直接中项目设置中打开,效果是一样的。

工程右键->open Module Setting->

第二步:使用native调试方式启动程序

第三步:使用debug按钮启动程序

注意:必须使用debug按钮启动程序,java调试时可以在程序启动后点击Attach debugger按钮再进行调试,native的调试不可以使用此方法。这是因为使用Native的调试方式启动程序是需要启动在手机上启动lldb-server程序,并进程端口映射和远程连接。

3.设置LLDB参数

对so进行调试必须要解决两个问题:

1.要提供带有符号表so;

2.如何将符号表so与源码关联。

问题一:

我们编译出的含有so的文件夹有两个,其中libs目录中为无调试符号的so,obj目录下为带调试符号的so。

如果调试,我们需要指定带符号表的so所在的位置,根据目录结构,我们将符号表目录指向到obj\local目录。

这样就完成了带符号表的so与无符号表so的映射。

问题二:

带符号表的so中会携带编译时文件在文件系统中的绝对路径,如果是本机编译+本机AS调试,则无需进行源码路径的映射,Android Studio会自动帮你完成映射,但如果so并非本机编译,则需要将so中源码路径映射到本机的源码路径。

进行映射前,我们必须先知道带符号的so中记录的文件路径。

安装启动调试:

程序启动后,打开debug标签,激活lldb命令窗口

这里介绍一个LLDB添加断点的命令:

下面三句功能是一样的,都是向Test.cpp文件的第14行添加断点,只不过是不同的简写版本。

(lldb) breakpoint set --file Test.cpp --line 14
(lldb) br s -f Test.cpp -l 14
(lldb) b Test.cpp:14

再看一眼我们的测试代码

添加断点效果如下,说明断点添加成功。

放开程序,让程序继续执行:

执行一个可以触发断点的操作,让程序进入刚刚添加的断点,进入断点后,切换到Variables窗口,就可以看到实时变量了。

再切换回LLDB窗口,输入source info命令就可以看到断点文件的路径了

(lldb) source info
Lines found in module `libtest.so
[0x0000007fa59025e0-0x0000007fa59025ec): E:\workspace\viso_studio_workspace\Android\Project1\Project1\.\.\Test.cpp:14

这里我们已经知道带有符号表的文件路径是E:\workspace\viso_studio_workspace\Android\Project1\Project1,

而我们本地源码目录为C:\Users\guozr\source\repos\Project2\Project2,故我们需要将Project1目录映射到Project2目录。

这里又要介绍一个映射目录的命令:

命令第一个路径为so构建路径,第二个命令为本机源码路径。

(lldb) settings set target.source-map /buildbot/path /my/path

这里我们需要替换为如下命令:

(lldb) settings set target.source-map E:\workspace\viso_studio_workspace\Android\Project1\Project1 C:\Users\guozr\source\repos\Project2\Project2

这个命令我们可以在程序启动后,使用类似前面添加断点的方式设置,也可以通过as提供的LLDB Startup Commands选项卡设置,这样调试程序一启动就完成了目录映射。

如下:

通过上面的设置,我们已经将源文件关联到了带符号表的so中,由于Android Studio对Native调试的支持,现在我们就可以将关联的c++源文件直接拖到Android Studio中打开,然后直接使用Android Studio编辑器界面中左边面板直接设置和去掉断点了。

更多LLDB命令请参考

GDB to LLDB command map — The LLDB Debugger

补充:

在很多情况下,我们app会分成很多不同的module,所以经常会出现将还有native代码的so库文件放在lib module中,这时我们就会遇到native代码无法debug的问题。

这时我们首先想到的是开启lib module的debug,

debug {
    debuggable true
    jniDebuggable true
}

然而你开启这个选项后仍然无法debug,

通过编译时查看gradle日志可以看出,通过compile project(":library")的方式,打包到app内的lib module实际是release方式编译的,即使你app上选择的是debug方式打包,lib module参与打包的方式仍然是release方式,由于release是不能debug的,所以你一直无法debug。

......
:library:compileReleaseJavaWithJavac UP-TO-DATE
:library:extractReleaseAnnotations UP-TO-DATE
:library:mergeReleaseShaders UP-TO-DATE
:library:compileReleaseShaders UP-TO-DATE
:library:generateReleaseAssets UP-TO-DATE
:library:mergeReleaseAssets UP-TO-DATE
:library:mergeReleaseProguardFiles UP-TO-DATE
:library:packageReleaseRenderscript UP-TO-DATE
:library:packageReleaseResources UP-TO-DATE
:library:processReleaseJavaRes UP-TO-DATE
:library:transformResourcesWithMergeJavaResForRelease UP-TO-DATE
:library:transformClassesAndResourcesWithSyncLibJarsForRelease UP-TO-DATE
:library:mergeReleaseJniLibFolders UP-TO-DATE
:library:transformNative_libsWithMergeJniLibsForRelease UP-TO-DATE
:library:transformNative_libsWithSyncJniLibsForRelease UP-TO-DATE
:library:bundleRelease UP-TO-DATE
......
:app:validateSigningDebug
:app:packageDebug UP-TO-DATE
:app:assembleDebug UP-TO-DATE

BUILD SUCCESSFUL

Total time: 11.475 secs

因此,要想debug,必须让lib module以debug的方式参与打包,方式如下。

在Library工程gradle中添加publishNonDefault true标识:

android {
    publishNonDefault true
}

在app的gradle文件中使用如下方式添加依赖:

debugCompile project(path: ':library', configuration: 'debug')
releaseCompile project(path: ':library', configuration: 'release')

好的,接下来继续你的表演吧。

要在 Android Studio调试so文件,您需要进行以下配置: 1. 在 app 的 build.gradle 文件中添加以下代码: ``` android { defaultConfig { ndk { // 设置需要调试的CPU架构 abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' } } } ``` 2. 在项目的 build.gradle 文件中添加以下代码: ``` android { externalNativeBuild { cmake { // 设置cmake的版本 version "3.10.2" // 设置需要编译的CMake文件路径 path "CMakeLists.txt" } } } ``` 3. 在 CMakeLists.txt 文件中添加以下代码: ``` # 添加头文件搜索路径 include_directories(${CMAKE_SOURCE_DIR}/include) # 添加预编译库搜索路径 link_directories(${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}) # 添加需要编译的C++文件 add_library( native-lib SHARED native-lib.cpp ) # 添加需要链接的预编译库 target_link_libraries( native-lib log ) ``` 4. 在 MainActivity.java 文件中添加以下代码: ``` static { System.loadLibrary("native-lib"); } public native String stringFromJNI(); ``` 5. 在 native-lib.cpp 文件中添加以下代码: ``` #include <jni.h> #include <string> extern "C" JNIEXPORT jstring JNICALL Java_com_example_myapplication_MainActivity_stringFromJNI( JNIEnv* env, jobject /* this */) { std::string hello = "Hello from C++"; return env->NewStringUTF(hello.c_str()); } ``` 6. 在 Android Studio 中选择 Run > Edit Configurations,然后添加一个新的配置。 7. 在配置中选择您的应用程序模块,并将“Launch Options”设置为“Nothing”。 8. 在“Debugger”选项卡中,选择“Attach debugger to Android process”。 9. 在“Debugger”选项卡中,将“Debugger type”设置为“Native”. 10. 现在您可以启动应用程序,并在应用程序中调用 `stringFromJNI()` 方法,以便在 ndk 中进行调试。 希望这些步骤能够帮助您在 Android Studio 中成功调试so文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值