当前位置: 首页 > news >正文

【Linux】coredump 文件的例子分析

1. 生成 core 文件

  • 网上很多教程,我这里举一种
  1. 临时开启 生成 core 文件
# 0 就是没有开 coredump 功能
root@swd-Lenovo-G40-80:/home/swd/pros/c--learn/0.test_codes/demos# ulimit -c
0
# 设置值临时为 unlimited
root@swd-Lenovo-G40-80:/home/swd/pros/c--learn/0.test_codes/demos# ulimit -c unlimited
# 检查值为 unlimited
root@swd-Lenovo-G40-80:/home/swd/pros/c--learn/0.test_codes/demos# ulimit -c
unlimited
# 可以看到下面的字段 core file size 的值为 unlimited
root@swd-Lenovo-G40-80:/home/swd/pros/c--learn/0.test_codes/demos# ulimit -a
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 31282
max locked memory       (kbytes, -l) 65536
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 31282
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
  1. 修改保存的文件位置
vim /etc/sysctl.conf# 添加下面两行kernel.core_pattern=/var/core/core_%e_%p
kernel.core_uses_pid=0# 使修改生效
sysctl -p /etc/sysctl.conf# 创建文件夹 /var/core
mkdir -p /var/core

2. 创建一个例子

// demo1.cc 
#include <iostream>
using namespace std;int main()
{int *p = nullptr;cout << *p << endl;return 0;
}
  1. 编译、运行,会报 (core dumped)
g++ -o demo1 demo1.cc
./demo1
Segmentation fault (core dumped)
  1. 查看生成的 core_dump 文件:
# 拷到当前目录
cp /var/core/core_demo1_5392 .
# 查看文件
ls
core_demo1_5392   demo1  demo1.cc 
  1. 使用 gdb 分析,可以看到直接报 Segmentation fault
gdb demo1 core_demo1_5392
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from demo1...(no debugging symbols found)...done.
[New LWP 5392]
Core was generated by `./demo1'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00005555a0b4089e in main ()
(gdb) 
  1. 分析:
    可以看到,#0 0x00005555a0b4089e in main ()指出,是在 main 函数的地址 0x00005555a0b4089e 出现错误。

  2. 继续分析:

# 使用 bt (back trace 回溯),看到是上面的问题
(gdb) bt
#0  0x00005555a0b4089e in main ()
# 使用 disassemble  地址, +line 命令,查看报错的上下文,看到箭头 => 就是出错的地方, => 0x00005555a0b4089e <main+20>:        mov    (%rax),%eax
(gdb) disassemble 0x00005555a0b40890, +60
Dump of assembler code from 0x5555a0b40890 to 0x5555a0b408cc:0x00005555a0b40890 <main+6>: in     (%dx),%al0x00005555a0b40891 <main+7>: adc    %cl,-0x39(%rax)0x00005555a0b40894 <main+10>:        rex.RB clc 0x00005555a0b40896 <main+12>:        add    %al,(%rax)0x00005555a0b40898 <main+14>:        add    %al,(%rax)0x00005555a0b4089a <main+16>:        mov    -0x8(%rbp),%rax
=> 0x00005555a0b4089e <main+20>:        mov    (%rax),%eax0x00005555a0b408a0 <main+22>:        mov    %eax,%esi0x00005555a0b408a2 <main+24>:        lea    0x200777(%rip),%rdi        # 0x5555a0d41020 <_ZSt4cout@@GLIBCXX_3.4>0x00005555a0b408a9 <main+31>:        callq  0x5555a0b40760 <_ZNSolsEi@plt>0x00005555a0b408ae <main+36>:        mov    %rax,%rdx0x00005555a0b408b1 <main+39>:        mov    0x200718(%rip),%rax        # 0x5555a0d40fd00x00005555a0b408b8 <main+46>:        mov    %rax,%rsi0x00005555a0b408bb <main+49>:        mov    %rdx,%rdi0x00005555a0b408be <main+52>:        callq  0x5555a0b40740 <_ZNSolsEPFRSoS_E@plt>0x00005555a0b408c3 <main+57>:        mov    $0x0,%eax0x00005555a0b408c8 <main+62>:        leaveq 0x00005555a0b408c9 <main+63>:        retq   0x00005555a0b408ca <_Z41__static_initialization_and_destruction_0ii+0>:      push   %rbp0x00005555a0b408cb <_Z41__static_initialization_and_destruction_0ii+1>:      mov    %rsp,%rbp
End of assembler dump.
# 使用 info reg 查看寄存器的值,可以看到 rax 的值是 0,mov    (%rax),%eax 汇编指的是 对 rax 存的地址进行取值,rax 是 0 即空指针,所以这是踩空指针。
(gdb) info reg
rax            0x0      0
rbx            0x0      0
rcx            0xa0     160
rdx            0x7ffdd25abf58   140728132616024
rsi            0x7ffdd25abf48   140728132616008
rdi            0x1      1
rbp            0x7ffdd25abe60   0x7ffdd25abe60
rsp            0x7ffdd25abe50   0x7ffdd25abe50
r8             0x7f5f3311bd80   140046855421312
r9             0x0      0
r10            0x6      6
r11            0x7f5f3324af30   140046856662832
r12            0x5555a0b40780   93826256734080
r13            0x7ffdd25abf40   140728132616000
r14            0x0      0
r15            0x0      0
rip            0x5555a0b4089e   0x5555a0b4089e <main+20>
eflags         0x10206  [ PF IF RF ]
cs             0x33     51
ss             0x2b     43
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0
(gdb) 

分析看上面的 # 注释

  1. 对源程序进行反汇编
objdump -s -d demo1 > demo1.S
  1. demo1.S 的重要部分,我们看到上面 gdb 出来的结果:出错的语句在0x00005555a0b4089e <main+20>: mov (%rax),%eax
    我们没看到0x00005555a0b4089e,但是看到了 <main+20>,我们看到反汇编出来的 main0x000000000000088a ,将它的位置偏移 20
    得到:0x89e 所以得到: 89e: 8b 00 mov (%rax),%eax
0000000000000880 <frame_dummy>:880:	55                   	push   %rbp881:	48 89 e5             	mov    %rsp,%rbp884:	5d                   	pop    %rbp885:	e9 66 ff ff ff       	jmpq   7f0 <register_tm_clones>000000000000088a <main>:88a:	55                   	push   %rbp88b:	48 89 e5             	mov    %rsp,%rbp88e:	48 83 ec 10          	sub    $0x10,%rsp892:	48 c7 45 f8 00 00 00 	movq   $0x0,-0x8(%rbp)899:	00 89a:	48 8b 45 f8          	mov    -0x8(%rbp),%rax	89e:	8b 00                	mov    (%rax),%eax    // 也就是这一行,可以看出它的形式跟 gdb 分析出来的也是一样的8a0:	89 c6                	mov    %eax,%esi8a2:	48 8d 3d 77 07 20 00 	lea    0x200777(%rip),%rdi        # 201020 <_ZSt4cout@@GLIBCXX_3.4>8a9:	e8 b2 fe ff ff       	callq  760 <_ZNSolsEi@plt>8ae:	48 89 c2             	mov    %rax,%rdx8b1:	48 8b 05 18 07 20 00 	mov    0x200718(%rip),%rax        # 200fd0 <_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@GLIBCXX_3.4>8b8:	48 89 c6             	mov    %rax,%rsi8bb:	48 89 d7             	mov    %rdx,%rdi8be:	e8 7d fe ff ff       	callq  740 <_ZNSolsEPFRSoS_E@plt>8c3:	b8 00 00 00 00       	mov    $0x0,%eax8c8:	c9                   	leaveq 8c9:	c3                   	retq   

根据汇编,如果熟悉,可以直接定位到代码,如果不熟,那么从上面基本可以定位到是哪个函数,可以加汇编标记定位语句

#include <iostream>
using namespace std;int main()
{// 添加特殊的数字 $0x11111111 这个用不到的数字作为标记,记录是在第几行__asm__("sub $0x11111111,%rsp");int *p = nullptr;__asm__("sub $0x22222222,%rsp");cout << *p << endl;__asm__("sub $0x33333333,%rsp");return 0;
}

重新编译得到的汇编如下,可以看到刚刚那行出问题的那一行,看到在 $0x22222222$0x33333333 之间:

0000000000000880 <frame_dummy>:880:	55                   	push   %rbp881:	48 89 e5             	mov    %rsp,%rbp884:	5d                   	pop    %rbp885:	e9 66 ff ff ff       	jmpq   7f0 <register_tm_clones>000000000000088a <main>:88a:	55                   	push   %rbp88b:	48 89 e5             	mov    %rsp,%rbp88e:	48 83 ec 10          	sub    $0x10,%rsp892:	48 81 ec 11 11 11 11 	sub    $0x11111111,%rsp899:	48 c7 45 f8 00 00 00 	movq   $0x0,-0x8(%rbp)8a0:	00 8a1:	48 81 ec 22 22 22 22 	sub    $0x22222222,%rsp8a8:	48 8b 45 f8          	mov    -0x8(%rbp),%rax8ac:	8b 00                	mov    (%rax),%eax		// 这是刚刚那行出问题的那一行,看到在 $0x22222222 和 $0x33333333 之间8ae:	89 c6                	mov    %eax,%esi8b0:	48 8d 3d 69 07 20 00 	lea    0x200769(%rip),%rdi        # 201020 <_ZSt4cout@@GLIBCXX_3.4>8b7:	e8 a4 fe ff ff       	callq  760 <_ZNSolsEi@plt>8bc:	48 89 c2             	mov    %rax,%rdx8bf:	48 8b 05 0a 07 20 00 	mov    0x20070a(%rip),%rax        # 200fd0 <_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@GLIBCXX_3.4>8c6:	48 89 c6             	mov    %rax,%rsi8c9:	48 89 d7             	mov    %rdx,%rdi8cc:	e8 6f fe ff ff       	callq  740 <_ZNSolsEPFRSoS_E@plt>8d1:	48 81 ec 33 33 33 33 	sub    $0x33333333,%rsp8d8:	b8 00 00 00 00       	mov    $0x0,%eax8dd:	c9                   	leaveq 8de:	c3                   	retq   

对应代码就可以清晰得出,然后就可以进行分析。

	__asm__("sub $0x22222222,%rsp");cout << *p << endl;   // 就是这一行出了问题__asm__("sub $0x33333333,%rsp");

3. 加 -g 的debug

#include <iostream>
using namespace std;int main()
{int *p = nullptr;cout << *p << endl;return 0;
}
  • 省去了所有的步骤,直接告诉你是第几行出错!!!!
oot@swd-Lenovo-G40-80:/home/swd/pros/c--learn/0.test_codes/demos# g++ -o demo1 demo1.cc -g
root@swd-Lenovo-G40-80:/home/swd/pros/c--learn/0.test_codes/demos# ./demo1 
Segmentation fault (core dumped)
root@swd-Lenovo-G40-80:/home/swd/pros/c--learn/0.test_codes/demos# cp /var/core/core_demo1_6898 .
root@swd-Lenovo-G40-80:/home/swd/pros/c--learn/0.test_codes/demos# gdb demo1 core_demo1_6898 
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from demo1...done.
[New LWP 6898]
Core was generated by `./demo1'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x000055e6d02ce89e in main () at demo1.cc:9
9           cout << *p << endl;
(gdb) 

相关文章:

  • c++day1
  • C#线程 ConcurrentQueue安全队列介绍
  • 前端技术探秘-Nodejs的CommonJS规范实现原理 | 京东物流技术团队
  • 【TIDB】TiDB认证考试PTCA 练习题 题库
  • 【javaWeb】HTTP协议
  • Spring事件注解@EventListener【观察】
  • 【面试HOT200】滑动窗口篇
  • Centos8部署LNMP架构
  • php使用Session实现简单购物车功能
  • git commmit type格式
  • 小程序静默授权获取unionid
  • Jenkins 配置节点交换内存
  • java:简单入门定时任务的几种方式Timer、Quartz、Spring Task
  • 隐式类型转化
  • 使用Arrays.asList与不使用的区别
  • 《深入 React 技术栈》
  • angular学习第一篇-----环境搭建
  • IDEA常用插件整理
  • java 多线程基础, 我觉得还是有必要看看的
  • MobX
  • SpringCloud集成分布式事务LCN (一)
  • Vue学习第二天
  • 蓝海存储开关机注意事项总结
  • 使用前端开发工具包WijmoJS - 创建自定义DropDownTree控件(包含源代码)
  • 系统认识JavaScript正则表达式
  • 一道面试题引发的“血案”
  • 【运维趟坑回忆录 开篇】初入初创, 一脸懵
  • 阿里云API、SDK和CLI应用实践方案
  • ​2021半年盘点,不想你错过的重磅新书
  • #QT项目实战(天气预报)
  • #常见电池型号介绍 常见电池尺寸是多少【详解】
  • (pojstep1.3.1)1017(构造法模拟)
  • (python)数据结构---字典
  • (第二周)效能测试
  • (二)c52学习之旅-简单了解单片机
  • (简单) HDU 2612 Find a way,BFS。
  • (每日持续更新)jdk api之FileFilter基础、应用、实战
  • (三)终结任务
  • (已解决)报错:Could not load the Qt platform plugin “xcb“
  • (已解决)什么是vue导航守卫
  • (转贴)用VML开发工作流设计器 UCML.NET工作流管理系统
  • .cfg\.dat\.mak(持续补充)
  • .net core 实现redis分片_基于 Redis 的分布式任务调度框架 earth-frost
  • .NET Micro Framework初体验
  • .NET NPOI导出Excel详解
  • .net web项目 调用webService
  • .net 中viewstate的原理和使用
  • .NET/C# 在 64 位进程中读取 32 位进程重定向后的注册表
  • .net和php怎么连接,php和apache之间如何连接
  • /etc/sudoer文件配置简析
  • @FeignClient注解,fallback和fallbackFactory
  • @软考考生,这份软考高分攻略你须知道
  • @在php中起什么作用?
  • [2016.7 test.5] T1
  • [2669]2-2 Time类的定义