Tombstone crash

本文详细介绍了Android平台上应用程序可能产生的四种类型的崩溃,特别是Tombstone类型的crash,并提供了使用monkey工具进行测试的方法,以及如何制造此类crash的具体步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 首先,android平台应用程序可能产生以下四种crash:
App层:
Force close crash
ANR crash
Native层:
Tombstone crash
Kernel层:
Kernel panic
比较难定位,可以查看/proc/last_kmsg来辅助定位。

最近需要通过monkey工具测试Tombstone类型的crash,抓取log并分析。通过monkey测试,如果要抓取native类型的crash,需要加上--monitor-native-crash参数:

seed=$(date +%Y%m%d%H%m%S)
monkey -s $seed --pkg-whitelist-file ${your-package-list} --monitor-native-crashes --kill-process-after-error -v -v -v 2000000000

这样,monkey在跑出crash后,在/data/system/dropbox 和 /data/tombstones目录下会生成相关日志,moneky会停止发送事件流并退出测试.值得注意的是,/data/tombstones文件夹下只会保存10个日志,超过10个后,最早创建的会被替换。而monkey是通过监视这个文件夹下的文件数量变化来判断是否有tombtone类型的crash产生的。因此,当/data/tombstones文件夹下超过10个文件后,如果再有tombstone crash产生的话,monkey是不能检测到的,它会继续发送事件流。为了避免这个问题,可以在每次运行monkey之前先清空一下这个文件夹。

另外,在settings.db中的secure表中有三个字段:dropbox:data_app_wtf,dropbox:data_app_anr,dropbox:data_app_crash。如果设置为enabled,每当有app crash之后,在/data/system/dropbox这个文件夹下都会产生相关的日志信息,这对于分析调试问题都是第一手的信息。

如何制造tombstone类型的crash?
这需要通过jni调用一个native的so文件,在本地代码中抛出异常即可。
可以编写如下代码tombstone_gen.cpp:
int main(int argc, char **argv) {
  int *p=0;
  *p=1;    //will seg fault
  return 0;
}
参照development/samples/SimpleJNI的示例,运行build出的apk即可。

关于jni调用,也有几个问题:
1.FindClass,RegisterNatives等找不到:
target thumb C: libtombstonec <= development/samples/AndroidDemos/jni/tombstone_gen.c
development/samples/AndroidDemos/jni/tombstone_gen.c: In function 'registerNativeMethods':
development/samples/AndroidDemos/jni/tombstone_gen.c:48: error: request for member 'FindClass' in something not a structure or union
development/samples/AndroidDemos/jni/tombstone_gen.c:53: error: request for member 'RegisterNatives' in something not a structure or union
development/samples/AndroidDemos/jni/tombstone_gen.c: In function 'JNI_OnLoad':
development/samples/AndroidDemos/jni/tombstone_gen.c:97: error: request for member 'GetEnv' in something not a structure or union
make: *** [out/target/product/generic/obj/SHARED_LIBRARIES/libtombstonec_intermediates/tombstone_gen.o] Error 1

问题原因在于:
如果是C程序,要用 (*env)->
如果是C++要用 env->
因此有两种解决方法:
1、将 (*env)-> 改为 env->
2、将c文件改为cpp文件,改为c++的方式编译。

2、运行时异常java.lang.UnsatisfiedLinkError
tombstone_gen.cpp中
static const char *classPathName = "com/android/demo/AndroidDemos";
类名有误,导致类链接错误。

最后,关于jni中JNINativeMethod相关解释:
http://hi.baidu.com/zhlg_hzh/blog/item/f0d782081f2f45d963d986f5.html

### 关于 Android Tombstone 源码 在 Android 系统中,`Tombstone` 文件用于保存应用程序崩溃时的状态信息。这些文件由 `debuggerd` 创建并存储在 `/data/tombstones/` 目录下。为了理解 `Tombstone` 的工作原理及其源码实现,可以从以下几个方面入手: #### 1. debuggerd 和 tombstoned 进程交互机制 当发生崩溃事件时,`crash_dump64` 函数会调用 `tombstoned_connect()` 方法尝试通过 Unix domain socket 连接至 `tombstoned` 守护进程[^1]。 ```cpp // crash_dump.cpp void crash_dump64(const siginfo_t* info, ucontext_t* uc) { ... int fd = tombstoned_connect(); if (fd >= 0) { // 发送信号处理逻辑给 tombstoned send_signal_info(fd, info); close(fd); } } ``` #### 2. 处理不同类型信号 根据传入的 `siginfo->si_signo` 字段值决定具体操作:如果该字段等于零,则执行完整的堆栈转储;否则仅捕获回溯信息。 ```cpp // tombstoned.c static void handle_crash(int sock_fd, struct sockaddr_un *addr) { uint32_t type; read(sock_fd, &type, sizeof(type)); switch(type){ case DUMP_TOMBSTONE: dump_full_tombstone(...); break; case BACKTRACE_ONLY: capture_backtrace_only(...);break; default: ; } } ``` #### 3. 记录帧的方式 值得注意的是,`Tombstone` 在记录函数调用链时采用逆序方式,即最近一次调用位于顶部(#00),这有助于快速定位问题根源所在[^2]。 ```cpp // backtrace.cc void Backtrace::Dump(FILE* fp) const { fprintf(fp,"stack:\n"); for (size_t i=frames_.size();i>0;i--) { Frame& frame = frames_[i-1]; PrintFrameInfo(frame,fp); } } ``` #### 4. SIGRTMIN 到 SIGRTMAX 范围内的实时信号支持 定义了 `_NSIG` 来表示最大可能存在的信号数量加一(含实时信号),确保能够覆盖所有标准及自定义信号类型[^3]。 ```cpp #define _NSIG 65 /* Biggest signal number + 1 */ ... enum SignalNumber : int { SIGHUP, SIGINT, ... , SIGRTMIN = 34, SIGRTMAX = (_NSIG - 1), }; ``` 以上展示了部分核心模块的工作流程以及相关联的重要数据结构定义。对于更深入的研究者来说,建议直接阅读 AOSP (Android Open Source Project)中的相应组件代码库获取最新版本的具体细节。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值