crash 是 Linux 内核开发中流行的调试工具。特别是它提供了强大的使用搜索命令进行内存搜索的功能。但是,它有点不方便,因为在移动每个进程的调用堆栈时没有查看局部变量的功能。

应读者要求,这篇文章,我将介绍如何从 vmcore 中提取堆栈转储并将调用堆栈上传到 Trace32。

使用命令“./crash64 vmcore vmlinux”运行崩溃实用程序。

$./crash64 vmcore vmlinux
......
please wait... (gathering kmem slab cache data)
crash64: invalid kernel virtual address: 48773a9004 type: "array cache limit"
....
WARNING: cannot determine starting stack frame for task ffffffc87bb4cc00
KERNEL: vmlinux
DUMPFILE: vmcore
CPUS: 4
DATE: Thu Jan 15 05:02:48 1987
UPTIME: 00:02:01
LOAD AVERAGE: 0.01, 0.01, 0.01
TASKS: 107
NODENAME: Xilinx-ZCU102-2016_3
RELEASE: 4.6.0
VERSION: #1 SMP Tue Apr 4 17:38:35 KST 2017
MACHINE: aarch64 (unknown Mhz)
MEMORY: 4 GB
PANIC: "sysrq: SysRq : Trigger a crash"
PID: 0
COMMAND: "swapper/0"
TASK: ffffff8008bd3400 (1 of 4) [THREAD_INFO: ffffff8008bc4000]
CPU: 0
STATE: TASK_RUNNING (ACTIVE)

查看第一条消息,命令 “echo /proc/sysrq-trigger” 导致了强制内核崩溃。

我们来看看 pid 为 1549 的 sh 进程的调用栈。

crash64> bt 1549
PID: 1549 TASK: ffffffc87bae6f00 CPU: 1 COMMAND: "sh"
#0 [ffffffc87bbdbb40] __switch_to at ffffff8008086b34
#1 [ffffffc87bbdbb60] __schedule at ffffff80088778a0
#2 [ffffffc87bbdbbb0] schedule at ffffff8008877cbc
#3 [ffffffc87bbdbbd0] schedule_timeout at ffffff800887a5a8
#4 [ffffffc87bbdbc50] wait_woken at ffffff80080d273c
#5 [ffffffc87bbdbc80] n_tty_read at ffffff80084892f8
#6 [ffffffc87bbdbd90] tty_read at ffffff8008482d10
#7 [ffffffc87bbdbdd0] __vfs_read at ffffff800818add0
#8 [ffffffc87bbdbe50] vfs_read at ffffff800818bc38
#9 [ffffffc87bbdbe90] sys_read at ffffff800818d0f8
#10 [ffffffc87bbdbed0] el0_svc_naked at ffffff8008085e2c
PC: 0000007f87126bb8 LR: 00000000004a6edc SP: 0000007fc2acbf10
X29: 0000007fc2acbf10 X28: 0000007fc2acc1e0 X27: 00000000004e5000
X26: ffffffffffffffff X25: 0000000000000001 X24: 00000000004e8a84
X23: 0000000000000001 X22: 00000000004de5f4 X21: 00000000004ea000
X20: 0000007f871ae7d0 X19: 00000000004e9a38 X18: 0000000000000001
X17: 0000007f87126bd0 X16: 0000000000000000 X15: 0000000000000070
X14: 0000000000000000 X13: 0000000000000000 X12: 0000000000000000
X11: 0000000000000000 X10: 0000000000000000 X9: 0000000000000004
X8: 000000000000003f X7: 30322d3230315543 X6: 0000007f8701c01d
X5: 248290f6fb60f00d X4: 00000000004e0000 X3: 00000000004e0000
X2: 0000000000000001 X1: 0000007fc2acbf4f X0: 0000000000000000
ORIG_X0: 0000000000000000 SYSCALLNO: 3f PSTATE: 60000000
crash64> task 1549
PID: 1549 TASK: ffffffc87bae6f00 CPU: 1 COMMAND: "sh"
struct task_struct {
state = 0x1,
stack = 0xffffffc87bbd8000, //<<--
usage = {
...
thread = {
cpu_context = {
x19 = 0xffffffc87bac4680 ,
x20 = 0xffffffc87bae6f00 , x21 =
0xffffffc87bae6f00,
x22 = 0xffffffc879160100,
x23 = 0xffffffc87bae7398,
x24 = 0xffffff8008bca000,
x25 = 0x0,
x26 = 0xffffff80092a6000,
x27 = 0x0,
x28 = 0xffffffc87b16d400,
fp = 0xffffffc87bbdbb40,
sp = 0xffffffc87bbdbb40, pc
= 0866b00

进程栈顶地址为 0xffffffc87bbd8000,在 x19~pc 字段中可以看到最后执行的寄存器集信息。

让我们转储进程堆栈。由于是 aarch64 位架构,栈大小为0x4000。所以你可以转储地址范围的堆栈。0xffffffc87bbd8000 -- 0xffffffc87bbd8000+0x4000

使用 crash 实用程序支持的 rd 命令提取内存转储。

crash64> rd 0xffffffc87bbd8000 -e 0xffffffc87bbdd000 -r stack_dump.bin

20480 字节从 0xffffffc87bbd8000 复制到 stack_dump.bin。地址0xffffffc87bbd8000是内存起始地址,0xffffffc87bbdd000是内存结束地址。将此范围内存转储保存到文件 stack_dump.bin。

通过使用 Trace32 (T32) 加载堆栈转储来恢复调用堆栈。

T32

现在轮到 T32 模拟器了。

首先,使用以下命令初始化系统。

sys.cpu cortexa53

sys.u

将以下 stack_dump.bin 转储加载到 T32。

d.load.bin stack_dump.bin /noclear 0xffffffc87bbd8000

/noclear 选项忽略并且不会覆盖以前的内存转储,其中 0xffffffc87bbd8000 是内存偏移地址。

崩溃实用程序提取了 0xffffffc87bbd8000 内存地址转储,因此 T32 上的 0xffffffc87bbd8000 给出了地址偏移量。

crash64> rd 0xffffffc87bbd8000 -e 0xffffffc87bbdd000 -r stack_dump.bin

20480 字节从 0xffffffc87bbd8000 复制到 stack_dump.bin。

让我们加载下一个 vmlinux。

Data.LOAD.elf vmlinux /nocode /noclear

现在我们已经加载了进程堆栈转储,是时候使用 T32 查看调用堆栈了。让我们首先回顾一下我们在 crash 实用程序中看到的进程寄存器信息。

thread = {
cpu_context = {
x19 = 0xffffffc87bac4680,
x20 = 0xffffffc87bae6f00 , x21 =
0xffffffc87bae6f00,
x22 = 0xffffffc879160100,
x23 = 0xffffffc87bae7398,
x24 = 0xffffff8008bca000,
x25 = 0x0,
x26 = 0xffffff80092a6000,
x27 = 0x0,
x28 = 0xffffffc87b16d400,
fp = 0xffffffc87bbdbb40,
sp = 0xffffffc87bbdbb40,
pc = 0xffffff8008086b38
},

让我们参考上面的寄存器集信息,将寄存器从 pc 加载到 T32 的 x28。在 T32 模拟器中输入以下命令。

rs pc 0xffffff8008086b38

rs sp 0xffffffc87bbdbb40

rs x29 0xffffffc87bbdbb40

rs x28 0xffffffc87b16d400

...

在 T32 上输入“vf”命令查看调用堆栈。

-000|__switch_to(prev = 0x0, next = 0x0)
-001|__schedule(preempt = FALSE)
-002|test_bit(inline)
-002|test_ti_thread_flag(inline)
-002|need_resched(inline)
-002|schedule()
-003|schedule_timeout(timeout = 9223372036854775807)
-004|wait_woken(wait = 0xFFFFFFC87BBDBD68, ?, ?)
-005|test_ti_thread_flag(inline)
-005|test_tsk_thread_flag(inline)
-005|signal_pending(inline)
-005|n_tty_read(tty = 0xFFFFFFC87B16D400, file = 0xFFFFFFC87BA05000, buf = 0x0000007FC2ACBF4F, nr = 18446743524089577028)
-006|tty_read(file = 0xFFFFFFC87BA05000, buf = 0x0000007FC2ACBF4F, count = 1, ?)
-007|__vfs_read(file = 0x0000007FC2ACBF4F, buf = ???, count = ???, pos = ???)
-008|vfs_read(file = 0xFFFFFFC87BA05000, buf = 0x0000007FC2ACBF4F, ?, pos = 0xFFFFFFC87BBDBEC8)
-009|SYSC_read(inline)
-009|sys_read(?, buf = 548726947663, count = 1)
-010|el0_svc_naked(asm)
---|end of frame

单击 vf 窗口中的 Up 图标以移动调用堆栈。

-006|tty_read(file = 0xFFFFFFC87BA05000, buf = 0x0000007FC2ACBF4F, count = 1, ?)
-007|__vfs_read(file = 0x0000007FC2ACBF4F, buf = ???, count = ???, pos = ???)
-008|vfs_read(file = 0xFFFFFFC87BA05000, buf = 0x0000007FC2ACBF4F, ?, pos = 0xFFFFFFC87BBDBEC8)
-009|SYSC_read(inline)
-009|sys_read(?, buf = 548726947663, count = 1)
-010|el0_svc_naked(asm)
---|end of frame

本文介绍了如何通过仅从 vmcore 转储进程堆栈来查看 T32 上的调用堆栈。这样就可以在 T32 上的 vmcore 中看到内存转储。

关于 Trace32 的升级用法,我这里有一份文档,欢迎关注视频号获取。

系统崩溃分析 - vmcore 加载到 Trace32相关推荐

  1. win7ie11调用java失败,win7纯净版系统下ie11无法加载java插件

    在win7纯净版系统中,我们会使用系统自带IE11浏览器来上网,最近有用户在使用IE11上网的时候无法加载java插件,导致网页无法全部显示,我们碰到这个问题应该怎么解决呢?下面给大家讲解一下win7 ...

  2. Launcher3源码分析(LauncherModel加载数据)

    LauncherModel继承BroadcastReceiver,显然是一个广播接收者.在上一篇Launcher的启动中讲到桌面数据的加载工作是在LauncherModel中执行的,那么它是如何加载数 ...

  3. Mybatis3源码分析(05)-加载Configuration-加载MappedStatement

    2019独角兽企业重金招聘Python工程师标准>>> Mybatis3源码分析(05)-加载Configuration-加载MappedStatement 博客分类: java m ...

  4. springboot集成mybatis源码分析-启动加载mybatis过程(二)

    springboot集成mybatis源码分析-启动加载mybatis过程(二) 1.springboot项目最核心的就是自动加载配置,该功能则依赖的是一个注解@SpringBootApplicati ...

  5. 微信JSSDK多图片上传并且解决IOS系统上传一直加载的问题

    微信JSSDK多图片上传并且解决IOS系统上传一直加载的问题 参考文章: (1)微信JSSDK多图片上传并且解决IOS系统上传一直加载的问题 (2)https://www.cnblogs.com/co ...

  6. 【SemiDrive源码分析】【X9芯片启动流程】27 - AP1 Android Preloader启动流程分析(加载atf、tos、bootloader镜像后进入BL31环境)

    [SemiDrive源码分析][X9芯片启动流程]27 - AP1 Android Preloader启动流程分析(加载atf.tos.bootloader镜像后进入BL31环境) 一.Android ...

  7. 红橙Darren视频笔记setContentView源码分析 xml加载的过程

    setContentView过程分析 从继承Activity的类开始进行分析 MainActivity setContentView(R.layout.activity_main); Activity ...

  8. Spring源码分析4---IOC加载过程补充总结

    原文出自:http://cmsblogs.com IOC 之 获取验证模型 DTD 与 XSD 的区别 DTD(Document Type Definition),即文档类型定义,为 XML 文件的验 ...

  9. Linux系统程序运行时加载动态库路径顺序

    程序运行时加载动态库路径顺序(Linux) 在linux系统中,如果程序需要加载动态库,它会按照一定的顺序(优先级)去查找: 链接时路径(Link-time path)和运行时路径(Run-time ...

  10. 电脑重装系统Win10“initpki.dll”加载失败怎么办?

    ​最近有非常多的小伙伴在使用电脑的时候会被提示initpki.dll模块加载失败或者找不到在指定的模块情况,这导致我们无法正常是去使用,那么遇到这种问题应该如何去解决呢? 更多电脑重装系统教程尽在小白 ...

最新文章

  1. FCKeditor 2.6 精简版
  2. Python PhantomJS 爬虫 示例
  3. linux / 命令行 / LD_DEBUG 命令
  4. makefile文件的书写规则(make和makefile)
  5. Sublime Text 2 快捷键用法大全
  6. java定义一个静态类_Java中的静态类
  7. ssas对数据仓库_SSAS中的多对多关系简介
  8. 禁止拖放对象文本被选择的方法
  9. Python 层次分析法 AHP
  10. 2dx cound not find libcocos2dcpp.so
  11. 如何在同一台电脑上打开多个iPhone模拟器
  12. 计算机网络-什么是计算机网络?
  13. Python深度学习-NLP实战:FastText实现中文文本分类(代码已跑通!)
  14. 基于迭代情绪交互网络的对话情绪识别
  15. 串口通信协议--UART、RS-232、RS-485、RS-422
  16. C++的继承和派生(一)父类和派生类(子类)的介绍以及派生类的访问控制
  17. PINN内嵌物理知识神经网络投稿期刊总结
  18. 中标麒麟安装达梦数据库安装
  19. html中iframe全屏显示,如何让iframe中的元素全屏
  20. Kali Linux - 嗅探和欺骗及密码破解工具

热门文章

  1. 阴阳是世界的生成之理,亦是其发展之理。道生一,一生二,二生三,三生万物。...
  2. 双摄像头实时视频拼接(平移模型)
  3. Win10任务栏图标变成空白方块解决办法
  4. Three 之 three.js (webgl)shader 中 Texture 贴图 uv 坐标的相关简单说明,并简单测试 UV 重复旋转偏移效果
  5. 功能测试————Siri
  6. 在命令行中快速移动光标的快捷键
  7. 如何在51单片机实现日程提醒(生日闹钟)
  8. 给学妹学弟们的看书小建议!
  9. 2021年中国物流仓储系统集成商竞争力排行TOP20
  10. arduino 44键盘制作简易计算器