Android Native程序crash的一些定位方法简介
Android Native程序crash的一些定位方法简介
经常,避免不了,我们的代码会崩溃。如果crash在native代码上,Android会和其他Linux一样,生成一份core dump,将程序运行时的内存,寄存器状态,堆栈指针,内存管理信息以及各种函数调用堆栈信息等存到一个文件中,供调试者使用分析。
Core Dump的生成
Android的Core dump叫tombstone,墓碑文件。由专门的一个daemon服务debuggerd来搜集,保存到/data/tombstone/目录下[logcat中也会打印一份简要信息,基本够分析用]。一般生成过程为:
- 系统异常,内核丢出来signal信号
- 应用中,bionic中实现的默认signal处理过程,通过socket将pid/tid和异常退出信息,发给debuggerd进程
- debuggerd得到pid/tid信息,通过ptrace挂到异常进程,得到异常进程的各种信息,然后生成墓碑文件,保存起来。
debuggerd的具体实现和ptrace就不展开讲了,以前研究挂钩子和benchmark分析处理的时候,参考了这里不少代码。有兴趣同学可以好好学习一下这个,也可以玩出花来的。比如以前做老化测试,就是改了捕鱼达人的金钱,脚本一直放炮整周末自动老化,不过现在好多apk都防着ptrace了,你想调试它它就自杀,越来越没意思了…
Tombstone文件的基本信息:
Tombstone信息通常由如下几部分组成:
1. 系统信息
包括编译信息、版本号、进程信息等。
2. 异常信息
包括产生的异常的原因,如signal 11(即段错误,内存访问异常)、异常所在位置等。
3. 寄存器信息
Dump当前线程栈中的寄存器值,包括通用寄存器和浮点寄存器的值。
4. backtrace信息
Dump当前进程栈中的调用栈。这个信息对异常分析非常有用。Backtrace信息已经做过符号定位和demangle,PC地址已经减去基地址,基本可以直接和so文件中的偏移地址对应。
5. 栈帧数据
以ascii形式,dump当前线程栈的栈帧信息。
6. 通用寄存器周边数据信息
通用寄存器很可能存储的是指针等信息,Android的tombstone会将通用寄存器周边数据也dump出来供分析。
7. 进程的logcat信息
Tombstone中还会dump在发生异常前,该进程输出的logcat信息。
其中,3,4,5,6,7每个线程信息都有对应信息。也不展开详说了,基本玩Android的都见过,除了墓碑文件中保存,在dropbox下,以及logcat的DEBUG TAG打出来的log中也有。
错误大体定位
简单说一下tombstone文件的阅读方式,大体定位错误方法。
一般对tombstone文件,除了知道是哪个进程挂了外,我们首要要知道的,是下面画圈圈的几个信息:
第一个,是signum,一般debuggerd关注的是SIGILL,SIGBUS,SIGABRT,SIGFPE,SIGSEGV,SIGPIPE等。而这里,估计九成都是SIGSEGV (即signal 11),段错误,和非法内存访问等价。
第二个是sigcode。对于段错误来说,sigcode一般就两个:SEGV_MAPERR和SEGV_ACCERR,字面意思,一个是map错误,一个是访问错误。
第三个是错误地址。
简单定位
错误九成以上都是段错误,主要关注这个,其他像非法指令、浮点出错等,也可以分析一下,一般要么是代码越界改写,要么是系统硬件不稳定造成的
对于段错误,基本上大多是SEGV_MAPERR。先说一下段错误的两种类型:
SEGV_MAPERR:这个说明访问出错的地址,压根就没内map到进程地址空间来,这种情况,通常就是野指针,或者越界访问,当然访问空指针也是属于这类。
SEGV_ACCERR:这个说明访问出错地址,被map到地址空间来了,但是没访问权限。基本上是指针越界或野指针,比如写只读map的内存地址。
这里的tombstone中的错误地址,就是非法操作的地址。现在Adroid已经使用了ALSR(地址空间随机布局),错误地址也一般不容易猜出大约哪里出问题,不过有一类地址,还是比较容易猜出来的:即地址的值比较小,基本上都是空指针访问了。地址值是小于4K的地址,可以认为就是解引用空指针了。
根据错误地址,错误类型,再通过tombstone给出的backtrace信息,使用编译时带符号的那份库,用addr2line查PC,直接得到出错的行号,结合错误原因,基本上可以定位错误了,修复即可。
几个错误例子
SEGV_MAPERR,错误的虚拟地址。怀疑野指针或越界。可以通过addr2line定位到行号。
一般我们看backtrace,并不是死板的看栈帧最顶上的。一般最顶上的都是C库,C库通常是被调用的底层函数库,不会做太多容错处理,一般认为是调用它的code给出的参数等有问题,再回溯几个栈帧看一下。这里很明显可以看到,是栈帧号3的地方出问题了,调用的是realloc,可能是越界或野指针,错的代码在这:
SharedBuffer* SharedBuffer::editResize(size_t newSize) const
{if (onlyOwner()) {SharedBuffer* buf = const_cast<SharedBuffer*>(this);if (buf->mSize == newSize) return buf;buf = (SharedBuffer*)realloc(buf, sizeof(SharedBuffer) + newSize); //错在这if (buf != NULL) {buf->mSize = newSize;return buf;}}SharedBuffer* sb = alloc(newSize);if (sb) {const size_t mySize = mSize;memcpy(sb->data(), data(), newSize < mySize ? newSize : mySize);release();}return sb;
}
看一下代码逻辑,基本先怀疑传入的参数newSize有异常,加一些trace,复现看看。
Dalvik虚拟机中有空指针, addr2line看一下具体位置,再看上下文查逻辑
这种错误,已经报说heap有异常,corrupt了。一般是有人越界写,或者double free都有可能,这个要查。很多时候还不是必现的,主要查一下临界区的保护问题。
主动自杀abort的,这个查到代码调用的地方,看一下逻辑就好。其实tombstone上,这类问题,同时会打印abort的原因,解决就好。
Android Native程序crash的一些定位方法简介相关推荐
- App控件定位:Android 控件介绍及元素定位方法
本文将分享Android相关基础知识和Android APP控件定位工具的使用方法. 目录 Android基础知识 Android布局 Android四大组件 1.activity 2.Service ...
- android系统应用程序设置时间,Android应用程序设置系统时间的方法
Android应用程序获取系统时间的方法: System.currentTimeMillis(); Android SDK虽然提供了设置系统时间的方法SystemClock.setCurrentTim ...
- 定位程序Crash常用工具和方法
一.引言 任何程序正确则只有一种结果,但是错误却有千万种,而众多的错误有些是可容忍,有些则是致命的,如除零错误.堆栈溢出.内存越界等导致程序Crash.由于很多错误并不是发生在开发工作者调试阶段,而是 ...
- android应用程序永久获取root权限方法,怎么使Android应用程序获得root权限
一般来说, Android 下的应用程序可以逗直接地得到的最大的权限为 system ,但是如果我们需要在程序中执行某些需要 root 权限的命令,如 ifconfig 等,就需要 root 权限了. ...
- androidsettitle方法_在Android应用程序中,Toolbar.setTitle方法无效-应用程序名称显示为标题...
MYYA 以上答案完全正确,但对我不起作用.我通过以下方法解决了我的问题.实际上我的XML是这样的: 我已 ...
- Android应用程序获取ROOT权限的方法
android中如何通过代码检测是否有root权限? public class MainActivity extends Activity { @Override protected void ...
- 国内android应用商城中程序隐私泄露分析,Android应用程序隐私数据泄露检测
摘要: Android智能手机中存储着用户的隐私数据,这些隐私数据泄露,会使用户蒙受经济损失及人身伤害.然而,目前第三方应用软件市场中存在许多恶意软件或漏洞软件,但现有的对Android应用软件检测技 ...
- 如何取消Google Play商店和Android应用程序订阅
BigTunaOnline/ShutterstockBigTunaOnline / Shutterstock The Google Play Store plays host to all in-ap ...
- UI自动化测试之元素定位方法
Python语言Selenium库UI自动化测试(一)元素定位方法 简介 当我们日常搭建自动化测试框架时,用Python调用浏览器时,通常有Requests库.Selenium库 这两个库是进行爬虫或 ...
最新文章
- 服务器技术综述(二)
- 【大话设计模式】——浅谈设计模式基础
- Spring Boot 2.x基础教程:使用JdbcTemplate访问MySQL数据库
- 自动化监控--zabbix中的show value详解
- [POI2008] Poc (原名 Trians) Treap+Hash
- android setGravity()的使用
- 第九次psp例行报告
- concat函数_三、P57-61 MySQL中常用函数
- AI修复技术为何这么强?原来背后的技术是……
- cms核心功能_如何根据这些重要功能选择合适的CMS
- pytorch模型保存
- addressof表达式不能转换为long_2.3 C++赋值运算符与表达式 | 将有符号数据赋给无符号...
- C#中 构造函数的执行
- Modown v4.11+Erphpdown10.01资源付费下载插件
- 蓝牙打印机CPCL编程手册~汉印HM-A300
- 大学计算机培训策划书,大学计划书的范文
- Android Studio 微信登录
- 邮件群发平台是什么意思?如何选择邮件群发平台
- 二维dct变换例题_数字图像处理试题(带答案)
- Visionpro工具用途中文介绍