【发布时间】:2012-06-28 06:48:14
【问题描述】:
如何在 Android 中为原生库加载事件设置断点?
我认为在 dlopen() 上设置断点是一个很好的起点,但是,即使 libc.so 的符号,gdb 也无法找到 dlopen 函数strong> 和 /system/bin/linker 已加载。
看起来 Android 正在使用一些特殊格式的 .so 文件,因为 nm 工具也不报告 dlopen() 位置。
是否有任何解决该问题的方法或 Android 特定的 .so 转储工具可以帮助通过名称定位函数地址,以便我可以手动设置断点?
编辑:
我要做的是设置一个断点,该断点应在加载任何本机库时触发,即当任何代码(甚至不在我的库中)调用 dlopen() 函数时。
问题在于 Android GDB 不支持挂起的断点。我的场景是这样的:
- 我启动我的应用程序并停止它。
- 应用程序已恢复并加载我的原生库。
- 我的函数是从库中调用的(仅在应用加载时调用一次)。
如果我在 #1 之后设置断点,它将无法工作,因为库仍然不存在并且 android-gdb 将无法重新绑定它。如果我让程序运行,然后再次停止它并设置断点,我已经过了#3,所以断点将无用。
我试图通过在 #1 处将断点设置为 dlopen() 来解决它,然后当它命中并加载库(即 #2)时,我将设置实际断点。
使用正常的 ARM nm 和 objdump 没有任何帮助。对 libc.so 进行 NM 显示 dlopen() 未定义:
00016188 T dlmemalign
U dlopen
00016338 T dlpvalloc
/system/bin/linker 二进制文件物理上包含 dlopen 文本(.rodata 部分的第一个字节),但是 nm 显示以下文本:
arm-linux-androideabi-nm.exe: linker: No symbols
用 objdump 反汇编它不会给出符号名称。
通过谷歌搜索 android 源代码发现了这个源文件:
http://dexandroid.googlecode.com/svn/trunk/bionic/linker/dlfcn.c
看起来 dlopen() 确实是在 /system/bin/linker 中定义的,但它使用了一些非标准的符号解析机制(至少,基于第一条评论):
/* This file hijacks the symbols stubbed out in libdl.so. */
那么,回到问题上来,如何在 dlopen() 中设置断点,以便在加载库时设置实际断点?
【问题讨论】:
标签: android c++ android-ndk gdb