You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 13下libart.so的uprobe符号偏移适配问题求助

问题背景

在Android x86_64模拟器中,使用Rust的aya框架为libart.so库设置uprobe时,该操作在Android 14(内核6.1)中正常,但在Android 13(内核5.15)中无响应。两款系统均通过perf_event_open系统调用挂载uprobe,且libart.so是由zygote进程预加载、所有应用共享的核心库。

环境配置

Android 13

  • 符号art::JNIEnvExt::DeleteLocalRef(_jobject*)在libart.so中的偏移:0x601300
  • .text段虚拟地址:0x35ff00,ELF文件内偏移:0x15ff00
  • 运行时maps显示可执行段基址:7388c1d5f000

Android 14

  • 同符号在libart.so中的偏移:0x684d00
  • .text段虚拟地址:0x200000,ELF文件内偏移:0x200000
  • 运行时maps显示可执行段基址:7720d2000000

运行时行为

  • Android 13:perf_event_open传入的config2参数为0x601300,调用返回ENOTSUPP错误
  • Android 14:perf_event_open传入的config2参数为0x684d00,调用成功且能正常捕获符号调用

bpftrace验证

  • Android 14:bpftrace使用0x684d00作为config2设置uprobe,功能正常
  • Android 13:bpftrace传入的config2为0x401300(比符号偏移少0x200000,该值正好是.text段虚拟地址与ELF内偏移的差值);在Rust程序中手动减去该偏移后,uprobe恢复正常工作

核心疑问

原本认为ELF文件中偏移0x15ff00的.text段会被直接映射到虚拟地址0x35ff00,为什么还需要额外应用这个映射差值?


解答

这本质是不同内核版本对uprobe的config2参数要求存在差异:

  1. 内核5.15(Android 13)的规则
    该版本内核要求config2传入的是符号在ELF文件中的绝对偏移,而非库加载到内存后,符号相对于库基址的虚拟地址偏移。
    你拿到的0x601300是符号加载后的虚拟偏移,要转换成ELF文件内的偏移,必须减去.text段的「虚拟地址与文件内偏移的差值」——也就是0x35ff00 - 0x15ff00 = 0x200000,最终得到0x601300 - 0x200000 = 0x401300,这才是内核5.15能识别的config2值。

  2. 内核6.1(Android 14)的规则
    该版本内核简化了参数逻辑,直接接受加载后的虚拟地址偏移作为config2。刚好Android 14中.text段的虚拟地址与文件内偏移完全一致(均为0x200000),所以符号的虚拟偏移和ELF内偏移完全相同,直接使用0x684d00就能正常工作。

简单来说:内核5.15认的是「符号在ELF文件里的位置」,内核6.1认的是「符号在内存里的位置」,这就是你需要额外调整偏移的核心原因。

内容的提问来源于stack exchange,提问作者Sergej Isbrecht

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 01:23:14