Crash工具用于解析Vmcore文件,Vmcore文件为通过kdump等手段收集的操作系统core dump信息,在不采用压缩的情况下,其相当于整个物理内存的镜像,所以其中包括了最全面、最完整的信息,对于分析定位各种疑难问题有极大的帮助。配置kdump后,在内核panic后,会自动进入kump流程,搜集Vmcore。
Crash工具即为专门用于分析vmcore文件的工具,其中提供了大量的实用分析命令,极大的提高了vmcore的分析效率。
在分析vmcore的过程中,常常需要解析内核某个流程中的关键变量的值,以便确认故障当时系统的状态,本文主要介绍变量的解析方法,主要分全局变量和局部变量两种情况。
1、全局变量解析非常简单,可通过在crash中直接p <变量名>打印,如:

1.crash> p jiffies
2.jiffies = $3 = 5540265294

2、局部变量的解析比较复杂。
Vmcore搜集的仅为故障当时内存使用情况的一个快照,是静态信息,无法进行动态调试(虽然听说可以,但没见过~~),对于某个进程而言,在Vmcore中能发掘的进程上下文信息,通常只有堆栈和寄存器的值。而我们了解,通常局部变量在栈中分配,但也可能直接使用寄存器保存,所以可以(也只能)通过“寻找局部变量跟堆栈或寄存器的关系”来解析局部变量的值。所以这里分两种情况:
1)位于栈中的局部变量
这种情况比较常见,此时,局部变量必然位于某一级函数的堆栈中,该局部变量可能通过指针一级级向底层函数传递,所以可能位于多个函数的堆栈中,可以从不同的函数堆栈中解析。但解析会比较困难,难点在于难以确认相关变量在堆栈中的具体位置,解析方法很灵活,需要结合相关源代码,仔细分析流程,找到关键的点,更多的取决于分析者的经验和代码理解能力。
如下以实例说明解析过程:
vmcore中某阻塞的进程有如下的堆栈:

1.crash> bt 9242
2.PID: 9242 TASK: ffff8805f3a21540 CPU: 4 COMMAND: "xxx"
3. #0 [ffff8805f3a23428] schedule at ffffffff814f8b42
4. #1 [ffff8805f3a234f0] schedule_timeout at ffffffff814f9a6d
5. #2 [ffff8805f3a235a0] __down at ffffffff814fa992
6. #3 [ffff8805f3a235f0] down at ffffffff81097c11
7. #4 [ffff8805f3a23620] xfs_buf_lock at ffffffffa0523433 [xfs]
8. #5 [ffff8805f3a23650] _xfs_buf_find at ffffffffa05235f2 [xfs]
9. #6 [ffff8805f3a236c0] xfs_buf_get at ffffffffa05237db [xfs]
10. #7 [ffff8805f3a23700] xfs_buf_read at ffffffffa0523e4c [xfs]
11. #8 [ffff8805f3a23730] xfs_trans_read_buf at ffffffffa0519a98 [xfs]
12. #9 [ffff8805f3a23780] xfs_read_agf at ffffffffa04cfd26 [xfs]
13.#10 [ffff8805f3a237c0] xfs_alloc_read_agf at ffffffffa04cfe99 [xfs]
14.#11 [ffff8805f3a237f0] xfs_alloc_fix_freelist at ffffffffa04d28a1 [xfs]
15.#12 [ffff8805f3a238d0] xfs_alloc_vextent at ffffffffa04d2e16 [xfs]

可以看出,进程阻塞在信号量上,需要解析如下函数中xfs_buf_t *bp变量的值,以确认其中bp->b_sema信号量的状态。

1.void
2.xfs_buf_lock(
3.    xfs_buf_t        *bp)
4.{5.    trace_xfs_buf_lock(bp, _RET_IP_);
6.
7.    if (atomic_read(&bp->b_io_remaining))
8.        blk_run_address_space(bp->b_target->bt_mapping);
9.    down(&bp->b_sema);
10.    XB_SET_OWNER(bp);
11.
12.    trace_xfs_buf_lock_done(bp, _RET_IP_);
13.}

该变量是通过入参从上级函数传入的,而跟踪上级函数会发现其为在上级函数_xfs_buf_find中分配
bp变量是在上级函数_xfs_buf_find定义局部变量,那么其通常会在该级栈中分配空间。但难点还在于如何确认该变量在堆栈中的位置,关键在于找到“寄存器和堆栈关联”的地方,还得分析关键代码流程:

1._xfs_buf_find(
2.    xfs_buftarg_t        *btp,    /* block device target        */
3.    xfs_off_t        ioff,    /* starting offset of range    */
4.    size_t            isize,    /* length of range        */
5.    xfs_buf_flags_t        flags,
6.    xfs_buf_t        *new_bp)
7.{8.    xfs_off_t        range_base;
9.    size_t            range_length;
10.    xfs_bufhash_t        *hash;
11.    xfs_buf_t        *bp, *n;
12.
13.    range_base = (ioff << BBSHIFT);
14.    range_length = (isize << BBSHIFT);
15....
16.found:
17.    spin_unlock(&hash->bh_lock);
18.
19.    /* Attempt to get the semaphore without sleeping,
20.     * if this does not work then we need to drop the
21.     * spinlock and do a hard attempt on the semaphore.
22.     */
23.    if (down_trylock(&bp->b_sema)) {24.        if (!(flags & XBF_TRYLOCK)) {25.            /* wait for buffer ownership */
26.            xfs_buf_lock(bp);
27.            XFS_STATS_INC(xb_get_locked_waited);

可以看到,bp是作为xfs_buf_lock函数的入参传入的,那这里应该会通过寄存器或其它方式进行传参,则必然会对bp所在的堆栈位置进行操作,由此应能找到bp在堆栈中的位置。
反汇编相关代码:

1.crash> dis -l _xfs_buf_find
2./usr/src/debug/kernel-2.6.32-220.el6/linux-2.6.32-220.el6.x86_64/fs/xfs/linux-2.6/xfs_buf.c: 431
3.0xffffffffa05234f0 <_xfs_buf_find>: push %rbp
4.0xffffffffa05234f1 <_xfs_buf_find+1>: mov %rsp,%rbp
5.0xffffffffa05234f4 <_xfs_buf_find+4>: push %r15
6.0xffffffffa05234f6 <_xfs_buf_find+6>: push %r14
7....
8.0xffffffffa05235e6 <_xfs_buf_find+246>: mov %rcx,%rdi
9.0xffffffffa05235e9 <_xfs_buf_find+249>: mov %rcx,-0x58(%rbp) //可以看出rbp偏移0x58即为入参bp的值
10.0xffffffffa05235ed <_xfs_buf_find+253>: callq 0xffffffffa05233e0 <xfs_buf_lock> //此处调用xfs_buf_lock
11....

找到调用xfs_buf_lock函数的地方,在此之前准备入参,操作了堆栈-0x58(%rbp) ,可以看出rbp偏移0x58即为入参bp的值
再看看堆栈中-0x58(%rbp)中的内容具体是啥:

1.crash> bt -f 9242
2.PID: 9242 TASK: ffff8805f3a21540 CPU: 4 COMMAND: "xxx"
3. #0 [ffff8805f3a23428] schedule at ffffffff814f8b42
4.    ffff8805f3a23430: 0000000000000082 ffff8805f3a234a8
5.    ffff8805f3a23440: 0000000181164d0e ffff880c20518300
6.    ffff8805f3a23450: 00051200f3a21b00 ffff880c20518300
7.    ffff8805f3a23460: 00051200f3a21540 ffff8805f3a21af8
8.    ffff8805f3a23470: ffff8805f3a23fd8 000000000000f4e8
9.    ffff8805f3a23480: ffff8805f3a21af8 ffff880c20e1a080
10.    ffff8805f3a23490: ffff8805f3a21540 ffff8805f3a234d8
11.    ffff8805f3a234a0: 0000000000000246 ffff880c1d102400
12.    ffff8805f3a234b0: 0000000000000246 ffff8805f3a234d8
13.    ffff8805f3a234c0: ffff8802ecd784b8 7fffffffffffffff
14.    ffff8805f3a234d0: ffff8805f3a235a8 7fffffffffffffff
15.    ffff8805f3a234e0: 0000000000000200 ffff8805f3a23598
16.    ffff8805f3a234f0: ffffffff814f9a6d
17....#5 [ffff8805f3a23650] _xfs_buf_find at ffffffffa05235f2 [xfs]ffff8805f3a23658: ffff8805f563e600 ffff8802ecd78480ffff8805f3a23668: 0001400500000000 ffff8805f563e690ffff8805f3a23678: ffff8805f3a236b8 0000000000000001ffff8805f3a23688: ffff8805f3a21af8 ffff8808fe07c0c0ffff8805f3a23698: 0000000000014005 000000003a382231ffff8805f3a236a8: 0000000000000001 ffff8805f563e0c0
rsp--> ffff8805f3a236b8: ffff8805f3a236f8 ffffffffa05237db

我们知道:
(1)栈的地址是向低地址延伸的,也就是说压栈时,sp(栈顶地址)减小。
(2)第一个压栈的上级函数的返回地址,所以其中的ffffffffa05237db为上级函数的返回地址(从上述堆栈中可以明显看出~)
在_xfs_buf_find()函数反汇编的第一句,就对rbp(即上级堆栈栈帧指针)进行了压栈,所以 ffff8805f3a236f8为rbp。
0xffffffffa05234f0 <_xfs_buf_find>: push %rbp
此时的rsp应该就是ffff8805f3a236b8:接下来:
0xffffffffa05234f1 <_xfs_buf_find+1>: mov %rsp,%rbp
那么此时的rbp也就等于ffff8805f3a236b8,那么rbp-0x58就是ffff8802ecd78480即为我们苦苦寻找的bp指针了!!

Crash 变量解析相关推荐

  1. Crash工具实战-变量解析【转】

    转自:http://blog.chinaunix.net/uid-14528823-id-4358785.html Crash工具实战-变量解析 Crash工具用于解析Vmcore文件,Vmcore文 ...

  2. crash工具解析_Android Crash 工具

    crash工具解析_Android Crash 工具_weixin_39543655的博客-CSDN博客本篇文章主要介绍Android开发中的部分知识点,通过阅读本篇文章,您将收获以下内容:一.Cra ...

  3. PHP几种常见魔术方法与魔术变量解析

    PHP几种常见魔术方法与魔术变量解析 先不多说,直接上代码,如下: 1 class Demo 2 { 3 private $str = 'str'; 4 5 //实例化时自动加载function 6 ...

  4. PHP字符串中的变量解析(+教你如何在PHP字符串中加入变量)

    定义字符串的时候,用单引号或者双引号都是可以的.我个人习惯是用双引号. 在输出字符串的时候,若字符串中含有字符串变量,使用单引号和双引号则是有区别的.如下面程序: 1 2 3 4 5 6 7 8 &l ...

  5. SHELL常见的系统变量解析

    SHELL常见的系统变量解析 : $0 当前脚本的名称 $n 当前脚本不能的 第n个参数,n=,1,2-10 $* 当前脚本的所有参数(不包括程序本身) $# 当前脚本的参数个数不包括程序本身() $ ...

  6. linux shell变量的,linux shell变量解析

    摘要 腾兴网为您分享:linux shell变量解析,智影,智联招聘,智慧消防,音恋等软件知识,以及考拉fm电台,快快游戏,京东企业购app,pdf加密工具,高德导航3d版,电脑驱动,兰溪新闻,我爱网 ...

  7. python私有变量什么意思_Python私有变量解析

    这篇文章主要为大家详细介绍了Python私有变量解析,具有一定的参考价值,可以用来参考一下. 对python这个高级语言感兴趣的小伙伴,下面一起跟随512笔记的小编两巴掌来看看吧! 私有变量表示方法 ...

  8. crash工具解析_Linux 后台开发常用调试工具

    shell脚本-变量_Linux 基础_JAVA架构师-创客学院 01 总览 编译阶段 nm 获取二进制文件包含的符号信息 strings 获取二进制文件包含的字符串常量 strip 去除二进制文件包 ...

  9. iOS: Crash文件解析

    原文出处: smileEvday   欢迎分享原创到伯乐头条 开发程序的过程中不管我们已经如何小心,总是会在不经意间遇到程序闪退.脑补一下当你在一群人面前自信的拿着你的App做功能预演的时候,流畅的操 ...

最新文章

  1. mysql的日期差值按天表示_MySql计算日期差值和常用sql
  2. HDU 1005 Number Sequence
  3. 每次digital painting 之后,都可以把作品放到这里,比较好看,也和nft相关度比较大
  4. 吴恩达课程翻译_中文学习资源:斯坦福大学CS231n计算机视觉课程
  5. 前端测试利器--Browser-Sync启动命令
  6. 博士读了12年,一篇文章没有
  7. android使用perfetto工具步骤
  8. 如何让service不被系统杀掉
  9. P1754 球迷购票问题 (卡特兰数,递推)
  10. python提取pdf发票信息_python读取pdf(发票)
  11. 【光耦 Normalized...和 CTR 测试条件及测试曲线 解读 : PC817和LTV-1007-TP1-G】
  12. Linux usleep不准问题排查
  13. 如何实现限制上传或下载速度
  14. delphi(XE2)实现图片异形窗体,支持摆放控件
  15. Android 文件外/内部存储的获取各种存储目录路径
  16. 定义一个三角形类(TRI)及其派生类三角柱体类(COL)。其中三角形类可以计算三角形的面积和周长;三角柱体类可以计算柱体的体积和表面积。其具体要求如下: (1)TRI的成员如下:  私有数据成员 
  17. 深度学习之SSD总结
  18. 如何进行Modbus 通讯测试
  19. Unity开发乐视三合一体感摄像头(1)
  20. 5分钟做一个php的增删改查案例

热门文章

  1. 排列组合——n个人平均分成m组
  2. 机器视觉python-openCV实验—— 实验三 人脸装饰物添加
  3. VS Code 杀死 IDEA?!
  4. 树莓派3b+ CENTOS7 制作备份Raspberry Pi树莓派SD卡的img映像文件(不用dd命令)[转载]...
  5. uniapp中的nvue和vue之间的区别---uniapp原生开发008
  6. ubuntu 20.04 安装 QQ 和 Wechat 及其卸载
  7. 数据库_触发器和事件
  8. Unity - 优化 Vector3.ProjectOnPlane
  9. java计算机毕业设计高校游泳馆信息管理MyBatis+系统+LW文档+源码+调试部署
  10. 一个前端人眼中的区块链