eclipse下进行NDK断点调试时,有时候会出现断点失效,即断不住的现象,而且经常会报错:No symbol table is loaded. Use the “file” command。下面就总结一下可能的原因和解决办法。
1. 注意编译时要加上-g选项
使用过gcc的都知道,这是最基本的一点,编译时使用该选项,可以在生成的so文件中包含调试信息。网上的很多资料中也都提到,工程的jni路径下所写的哪些Application.mk和Android.mk,其中包含的编译选项(CFLAG,APP_CFLAGS,LOCAL_CFLAGS等),要包含-g。其实如果用ndk-build NDK_DEBUG=1 编译工程时,该选项是默认的。所以断点失效很有可能不是这个原因造成的。
2.看程序是否已经运行到so库加载的地方
网上的很多资料都没有提到,但其实是很关键的一点,那就是你的程序必须已经加载了该断点所在文件对应的so库,如确定程序已经执行过了System.loadLibrary("lib_name");
否则是不可能断住的。
3.查看是否加载了断点文件相应的so文件的symbol table
根据提示,No symbol table is loaded. Use the “file” command可知,符号表没有加载进来,所以程序在断点处停不住。可以使用info shared
命令查看当前有哪些共享库,并且哪些的符号表已经加载的信息。以我调试的ijkplayer工程为例,可以直接在eclipse的console中键入info shared
:
回车后再在任何一个c源文件中加断点,就可以看到结果(这可能是一个bug,回车后不能直接看到执行结果,需要再下一次断点才行):
From To Syms Read Shared Object Library
0xb0001000 0xb0006868 Yes F:\WorkSpace\my-ijkplayer\obj\local\armeabi-v7a\linker
0x40036100 0x40064208 Yes F:\WorkSpace\my-ijkplayer\obj\local\armeabi-v7a\libc.so
No libstdc++.so
No libm.so
No liblog.so
No libcutils.so
No libz.so
No libutils.so
No libbinder.so
No libexpat.so
No libcrypto.so
No libgabi++.so
No libicuuc.so
No libicui18n.so
No libssl.so
No libstlport.so
No libnativehelper.so
No libnetutils.so
No libGLESv2_dbg.so
No libEGL.so
No libwpa_client.so
No libhardware_legacy.so
No libpixelflinger.so
No libhardware.so
No libemoji.so
No libjpeg.so
No libskia.so
No libui.so
No libGLESv2.so
No libmemalloc.so
No libQcomUI.so
No libgui.so
No libcamera_client.so
No libsqlite.so
No libdvm.so
No libGLESv1_CM.so
No libETC1.so
No libsonivox.so
No libstagefright_foundation.so
No libmedia.so
No libnfc_ndef.so
No libusbhost.so
No libharfbuzz.so
No libhwui.so
No libtilerenderer.so
No libbluedroid.so
No libdbus.so
No libandroid_runtime.so
No libvorbisidec.so
No libstagefright_yuv.so
No libdrmframework.so
No libchromium_net.so
No libstagefright_amrnb_common.so
No libstagefright_enc_common.so
No libstagefright_avc_common.so
No libstagefright.so
No libmtp.so
No libexif.so
No libmedia_jni.so
No libbcc.so
No libbcinfo.so
No libRS.so
No librs_jni.so
No libandroid.so
No libv8.so
No libwebcore.so
No libGLES_android.so
No libgsl.so
No libgenlock.so
No libEGL_adreno200.so
No libGLESv1_CM_adreno200.so
No libGLESv2_adreno200.so
No eglsubAndroid.so
No libq3dtools_adreno200.so
No libsc-a2xx.so
No liboverlay.so
No gralloc.msm8660.so
0x605173c0 0x606fd750 No F:\WorkSpace\my-ijkplayer\obj\local\armeabi-v7a\libijkffmpeg.so
No libwilhelm.so
No libOpenSLES.so
0x6095c9a8 0x6099471c No F:\WorkSpace\my-ijkplayer\obj\local\armeabi-v7a\libijksdl.so
0x609ced64 0x609e7c80 No F:\WorkSpace\my-ijkplayer\obj\local\armeabi-v7a\libijkplayer.so
其中的libijkffmpeg.so,libijksdl.so和libijkplayer.so就是我的工程里生成的so库。可以看到,其中的Syms Read列为No,这标明这些so库的调试信息或者说符号表还没有加载。那么如何才能加载呢?gdb为我们提供了方法。可以通过file so文件路径
的方法加载,也可以用sharedlibrary
命令,一次性加载所有的so库符号表:
再次运行info shared
,可以看到结果:
0x605173c0 0x606fd750 Yes F:\WorkSpace\my-ijkplayer\obj\local\armeabi-v7a\libijkffmpeg.so
No libwilhelm.so
No libOpenSLES.so
0x6095c9a8 0x6099471c Yes F:\WorkSpace\my-ijkplayer\obj\local\armeabi-v7a\libijksdl.so
0x609ced64 0x609e7c80 Yes F:\WorkSpace\my-ijkplayer\obj\local\armeabi-v7a\libijkplayer.so
其中Syms Read列变为了Yes,标明其符号表已经加载。此时在进行调试,断点就可以进入了:
4.参考文献
Android NDK断点失效原因及解决方案http://www.importnew.com/1768.html,其中分析了断点调试的原理,感兴趣的可以看一下。