如何在Android中为本机库加载事件设置断点?
我认为在 dlopen()上设置断点是一个很好的起点,但是,即使 libc.so >的符号,gdb也找不到dlopen函数和 / system / bin / linker 已加载。
看起来Android也使用了一些特殊格式的.so文件,因为nm工具也没有报告 dlopen()位置。
是否有针对此问题的解决方法或特定于Android的.so转储工具,它可以帮助按名称查找函数地址,以便我可以手动设置断点?
编辑:
我要做的是设置一个断点,该断点应该在加载任何本机库时触发,即当任何代码(甚至在我的库中)都调用 dlopen()函数时。
问题是Android GDB不支持挂起的断点。我的情况是这样的:
如果我在#1之后设置断点,它将无法工作,因为库仍然不存在,并且android-gdb将无法重新绑定它。如果我让程序运行,然后再次停止并设置一个断点,我已经超过#3,这样断点就没用了。
我试图通过在#1处设置断点到 dlopen()来解决它,然后当它命中并加载库(即#2)时,我将设置实际的断点。
使用普通的ARM nm和objdump没有任何帮助。 NM'ing libc.so显示 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()中设置断点,以便在加载库时设置实际的断点?
答案 0 :(得分:3)
通常任何arm objdump都应该可以工作,但是你的ndk目录中会有一个。 即使是非武器重建也可能有效。
我不确定为什么你期望在库中找到dlopen(),除非它明确地使用它来打开另一个库 - 通常,人们会认为它将从libdvm.so调用,无论如何我相信它实现是在libdl.so(有一个为android构建的grep版本是一个非常有用的东西 - 你可以在lib目录中找到字符串,但如果你想找到它们是导入还是导出你可能需要adb pull和objdump感兴趣的文件。)
如果您正在尝试断开正在加载的库文件,您可以尝试实现一个静态初始化函数(C级或加载时的jni)并在那里放置一个断点。
编辑:
事实证明,arm的objdump不会通过用于从共享库导入的符号的plt解码链接,尽管它适用于某些其他平台,如x86。这可能使得很难理解被剥离调试符号的二进制文件,正如您对设备上的系统库所期望的那样。我能够修补binutils来源为arm做这个。最终我希望在某个地方提交,但与此同时,https://github.com/cstratton/binutils-android-decodeplt
可以获得修补版本的来源。我在一个prebuilt-linux-x86 /目录中放了一个objdump二进制文件,虽然我不知道它是多么便携。