在GDB+GdbServer调试环境中是否支持使用调用函数命令?
问题复现
使用GDB调试SurfaceFlinger等Android原生程序时,无法调用函数获取运行结果,例如执行p region.isEmpty()命令查看region.isEmpty()的返回值时会触发如下报错:
(gdb) p bounds.isEmpty()
Warning:
Cannot insert breakpoint 0.
Cannot access memory at address 0x4000
命令已中止。
在GDB调用函数期间发生错误,对包含android::Region::isEmpty() const函数的表达式求值将被终止,函数执行完成后GDB将静默停止。
根因分析
- Android原生程序默认编译带优化参数,
android::Region::isEmpty()属于内联函数,正式版本镜像中未保留独立的函数符号入口,GDB无法定位到正确的函数执行地址 - 远程调试Android目标设备时,GDB的地址空间映射存在偏移,调用函数时GDB尝试插入临时断点的地址
0x4000属于未被映射的非法内存区间,触发访问失败 - Android 12及以上版本系统默认开启代码段内存保护,GDB没有权限在只读的代码段插入临时断点用于函数调用后的执行恢复,也会触发该错误
解决方案
- 执行GDB配置命令关闭临时断点校验:
配置完成后再尝试调用函数,可规避大部分断点插入失败问题set unwindonsignal off set call-scratch-on-fly on - 避免直接调用内联成员函数,改为访问底层成员变量计算结果:
android::Region的空状态由内部的mBounds矩形边界决定,直接执行p mBounds.left == mBounds.right || mBounds.top == mBounds.bottom即可得到和isEmpty()完全等价的结果 - 如果是自行编译调试用系统镜像,添加编译参数
-fno-omit-frame-pointer -O0,关闭编译优化、保留完整的函数符号信息,从根源解决函数调用失败问题
内容的提问来源于stack exchange,提问作者ypk
相关产品推荐
相关产品推荐

