coredump是什么?

coredump一般我们说是核心转储,就是在进程异常时的一个快照,保存了异常时的内存、寄存器、堆栈等数据。这些数据存储成一个文件,而且是一个ELF文件格式,可通过readelf读取查看。

为何需要coredump?

在android系统上,一般程序在native或者art中异常后会在data/tombstones下生成对应的tombstone文件,这个文件一般已经包含了很多native程序的重要信息,结合symbol,我们会对异常原因有个初步判断,而且一般的简单问题可以有个初步分析结论。但对于较难的问题,仅有tombstone不足以判断异常原因,尤其是需要查看一些较多分支,对象地址数据没有在tombstone中输出时,我们就需要更多的寄存器和内存信息。这就需要抓起coredump来分析。

如何抓取coredump?

1,设置要抓取进程的rlimit

#define RLIM_INFINITY 0x7fffffffUL
......
221        rl.rlim_cur = RLIM_INFINITY;
222        rl.rlim_max = RLIM_INFINITY;
223        if (setrlimit(RLIMIT_CORE, &rl) < 0) {//异常打印
}

上面即设置core文件大小不限。

在android中,不同平台调用时机有区别,以某平台调用时机为例,在zygote fork进程时执行,其时序如下:

//frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
487static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
488                                     jint debug_flags, jobjectArray javaRlimits,
489                                     jlong permittedCapabilities, jlong effectiveCapabilities,
490                                     jint mount_external,
491                                     jstring java_se_info, jstring java_se_name,
492                                     bool is_system_server, jintArray fdsToClose,
493                                     jintArray fdsToIgnore,
494                                     jstring instructionSet, jstring dataDir) {
......
529  pid_t pid = fork();
531  if (pid == 0) {
......//这里执行java方法
669    env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags,
670                              is_system_server, instructionSet);
671    if (env->ExceptionCheck()) {
672      RuntimeAbort(env, __LINE__, "Error calling post fork hooks.");
673    }
674  } else if (pid > 0) {
.....
}// gCallPostForkChildHooks对应的Java方法如下
832int register_com_android_internal_os_Zygote(JNIEnv* env) {
833  gZygoteClass = MakeGlobalRefOrDie(env, FindClassOrDie(env, kZygoteClassName));
834  gCallPostForkChildHooks = GetStaticMethodIDOrDie(env, gZygoteClass, "callPostForkChildHooks",
835                                                   "(IZLjava/lang/String;)V");callPostForkChildHookspostForkChild(×××)nativePostForkChild(); //JniZygoteHooks_nativePostForkChild(); //native方法EnableDebugFeaturesEnableDebugger()setrlimit()

2,设置coredump存储路径和core文件名称

mkdir /data/core  0777  root  root

write /proc/sys/kernel/core_pattern  "data/core/%E.%p.%e"

即创建一个放置core的路径,且具有读写权限,然后设置了文件的名称,若不设置,则名称为core,可以用cat 查看,路径在可执行程序路径下。

对应某q公司,则设置了一个属性,persist.debug.trace,当其为1时,出发init执行上述两条命令:

device/q**/common/rootdir/etc/init.***.rcon property:persist.debug.trace=1mkdir /data/core  0777  root  rootwrite /proc/sys/kernel/core_pattern  "data/core/%E.%p.%e"

关于core文件名称的格式意义如下:

%p 出Core进程的PID

%u 出Core进程的UID

%s 造成Core的signal号

%t 出Core的时间,从1970-01-0100:00:00开始的秒数

%e 出core进程对应的可执行文件名

3,然后等待触发native crash

补充:

对于抓取fulldump话,需要增加一个步骤:adb shell echo 0x27 > /proc/pid/coredump_filter,进程重启需要重新执行

1278    snprintf(path,sizeof(path),"/proc/%d/coredump_filter",pid);
......
1283        if (is_full) {
1284            write(fd, "39", 2);    /*0x27
1285        } else {
1286            write(fd, "35", 2);    /*0x23
1287        }

这一步如果动态或者监控的话,可以通过hook执行。以某android厂商为例,hook了android的debuggerd进程的syscall,然后在发现进程正要处理的是SYS_tgkill信号时,就增加一个方法调用,之后在执行正常的syscall。

160extern "C" long hook_syscall(long number, ...) {
......
165    if (SYS_tgkill == number) {
166        int pid = va_arg(ap,int);
167        int tid = va_arg(ap,int);
168        int signal = va_arg(ap,int);
169        ****_native_debug_process(pid,tid);
170        ret = syscall(SYS_tgkill, pid, tid, signal);//先在context初始化时hook了pthread_setname_np,在hook_pthread_setname_np执行时设置了syscall的hook函数hook_syscall180extern "C" int hook_pthread_setname_np(pthread_t thread, const char* name) {
181    MILOGI("hook hook_pthread_setname_np name=%s", name);
182#if defined(__LP64__)
183  const char* sigsendersname = "debuggerd64:sig";
184#else
185  const char* sigsendersname = "debuggerd:sig";
186#endif
187    if (!strcmp(name,sigsendersname)) {
188        SoInfo si;
189        if (si.replace("syscall",(const uintptr_t)&hook_syscall)) {

android上有可能存在selinux的权限问题,可以将se关闭(adb shell setenforce 0),重启后需要重新关闭se。

对于已经启动的进程,rlimit不好更改,目前只能gdb attach到目标进程更改。

如何使用coredump?

coredump一般通过gdb调试,同时需要准备对应版本的symbol文件一起调试。

1,启动gdb

./prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-gdb(gdb路径)

或者prebuilts/gdb/linux-x86/bin/gdb

2,加载coredump

core-file    coredump_file(coredump文件)

file

3. 设置symbol路径,即当前栈中用的可执行文件的symbol位置

file ~/symbols/out/target/product/项目名称/symbols/system/bin/app_process32 (一般app的话,是app_process,注意32位和64位的区别)

set solib-search-path   symbols/system/lib/

4. 然后通过gdb命令查看,几个常用命令如下:

bt:查看对应当前线程栈
set arm force-mode thumb:汇编按照thumb命令解析
info r:查看当前帧寄存器
info thread:列出进程的所有线程
t num:切换到num线程
f num:切换到num帧
disassemble 0x9d73320c-0x30,+0x32:反汇编一段地址
x /10x 0x9d7331fc:按16进制,读取10个指定地址内存
p *(android::JavaBBinder*)0x8bb5c500:把指定地址按照指定数据类型解析数据;
set print pretty on:设置良好的阅读模式
directory ~/disk/androidO/:指定源码路径

其他命令不再列出

如何查看是否已开启coredump?

:/ # ulimit -a
-t: time(cpu-seconds)     unlimited
-f: file(blocks)          unlimited
-c: coredump(blocks)      0     //coredump大小为0,即关闭,可以通过ulimit -c size或者ulimit -c unlimited来指定size大小或者不限制大小
-d: data(KiB)             unlimited
-s: stack(KiB)            8192
-l: lockedmem(KiB)        65536
-n: nofiles(descriptors)  32768
-p: processes             21499
-i: sigpending            21499
-q: msgqueue(bytes)       819200
-e: maxnice               40
-r: maxrtprio             0
-m: resident-set(KiB)     unlimited
-v: address-space(KiB)    unlimited

补充一篇不错的类似文章:https://blog.csdn.net/tenfyguo/article/details/8159176

coredump介绍相关推荐

  1. coredump介绍和使用

    目录 1 什么是coredump 2 如何开启coredump功能 2.1 设置core文件的大小的方法: 2.2 设置core文件的路径 3 出现coredump的几种情况 3.1 内存访问越界 3 ...

  2. Linux 下Coredump分析与配置

    查看全文 http://www.taodudu.cc/news/show-5652543.html 相关文章: coredump配置.产生原理.分析及示例 segmentation fault 常见原 ...

  3. 万变不离其宗——程序动态分析(gdb)

     万剑归宗是无名的招数,但是它却道出一个道理.不管剑招多么花哨,多么厉害,最终还是需要回归正宗与朴实.程序也是一样,不管代码如何实现,不论语言如何,技巧如何,最终也是要能够被正确,有效,可靠的运行 ...

  4. android coredump,coredump功能介绍

    [coredump简介] blog.csdn.net/tenfyguo/article/details/8159176 [如何打开coredump功能] 1.打开kernel编译开关 @kernel/ ...

  5. Linux调试——gdb调试器的简单使用调试coredump文件

    文章目录 一.背景 二.gdb的指令与使用 1.gdb的基本指令. 2.gdb指令的简单使用 1.进入gdb模式 2.实例说明 三.调试coredump文件 前提:本质上是在调试程序崩溃之后的内存镜像 ...

  6. Linux 系统服务管理器(初始化系统/init system) -- systemd 及命令 systemctl 的详细介绍

    文章目录 一.系统服务管理器 systemd (一)systemd 的特性 (二)systemd 与 传统 init 系统的区别 (三)systemd 的目录和文件 (四)systemd 的 Unit ...

  7. Linux下coredump调试3:补录

    本篇文章记录在coredump调试过程中记录的其它事项. 一般地,调试的方式多种多样,不可能将其一网打尽.就笔者而言,一般喜欢用print大法,分段注解法,版本回退法,等等.实在无招,则用coredu ...

  8. Linux下coredump调试1:使用

    李迟按: 调试是程序员的一项基本能力,经历过大大小小的实战,随着见识的增长,只要用心留意并做总结,相信调试的能力会越来越好.写程序不可能没有bug,只是bug容易不容易被发现,bug的危害大不大.笔者 ...

  9. coredump gdb 调试_CRASH安装和调试

    一.Crash?当linux系统内核发生崩溃的时候,可以通过KEXEC+KDUMP等方式收集内核崩溃之前的内存,生成一个转储elf文件vmcore或者其他dump形式.内核开发者通过分析该elf du ...

最新文章

  1. redis-3.0.2集群部署
  2. ubuntu java开发环境搭建(jdk+tomcat+eclipse)
  3. easyUI tree 多选框设置是否级联选中
  4. as2的Key.isDown方法在as3的代替
  5. 6.4 SQL Server 加密
  6. python基础(set)补充
  7. oracle 循环块,Oracle语句块PL/SQL循环判断
  8. MySQL 5.5/5.6——概述 MySQL 客户端程序
  9. Snort 中文手册
  10. [生存志] 第14节 历代大事件概览 西汉
  11. WPF打开子窗口给父窗口添加蒙版效果
  12. 【年薪百万之IT界大神成长之路零】年薪百万之IT界大神成长之路
  13. 以下11條小建議,幫助你們的異地戀一直保持活力
  14. STM32软件模拟IIC---读写驱动AT24Cxx
  15. 利用Python进行数据分析 学习笔记
  16. R语言中的线性判别分析
  17. Android 12 Watchdog(4) Trace生成过程
  18. linux切换用户时释放资源,linux 切换用户报Resource temporarily unavailable
  19. Android与iOS在DES加密算法上的统一
  20. 横向评测常见的优秀国外5个域名注册商

热门文章

  1. thymeleaf入门基础语法笔记
  2. 找到第一个不重复的字符
  3. linux ubuntu bt5 基本配置
  4. 基于机器算法的美国研究生院入学录取率预测系统实现
  5. Python-增加b站视频播放量
  6. 【JTAG】STIL格式详解
  7. 苹果html5,苹果新官网上线 使用HTML5全副武装
  8. linux禁用网络连接wifi,禁用IPv6,解决Debian8系统无线网络掉线问题
  9. [每日App一]QQ主题要逆天!轻轻松松月入30万!
  10. 对于电脑快捷键的掌握。