程序死掉了,没有 core 文件怎么查?

当C/C++程序coredump且无core文件时,可以使用dmesg查看内核环缓存区信息寻找线索,结合addr2line定位core的内存地址对应代码位置,辅助调试。通过addr2line命令,可以将内存地址转换为源代码行,从而了解core的原因。
摘要由CSDN通过智能技术生成


对于 C/C++程序员来说,如果程序 core dump 了,没有 core 文件就很难知道发生了什么,只能重新更改系统配置,让 core 文件产生(通常是在.bash_profile 中,加上 ulimit -c unlimited),以便下次 core 的时候可以产生 core 文件,方便调试,除此之外,还是有其他办法的,那就是采用查看 dmesg 和 add2line 方式来定位 core 的位置。

一、dmesg

dmesg 用来显示内核环缓存区内容(kernel-ring buffer),内核将各种消息放这里。硬件和模块初始化信息填充在这里面,还有程序 oom 了,或者程序 core 了,也可以从这里面看到些蛛丝马迹,遇到疑难问题,我挺喜欢用这个命令查看下的,不过如果简单输入dmesg,打印出来的信息没有具体时间,如下:

[    6.396632] ip_tables: (C) 2000-2006 Netfilter Core Team
[    6.397395] systemd[1]: Inserted module 'ip_tables'
[    6.829500] EXT4-fs (vda1): re-mounted. Opts: (null)
[    6.971834] systemd-journald[474]: Received request to flush runtime journal from PID 1
[    7.228993] piix4_smbus 0000:00:01.3: SMBus Host Controller at 0x700, revision 0
[    7.241443] input: PC Speaker as /devices/platform/pcspkr/input/input5
[    7.273676] cryptd: max_cpu_qlen set to 1000
[    7.288223] AVX2 version of gcm_enc/dec engaged.
[    7.288970] AES CTR mode by8 optimization enabled
[    7.332362] alg: No test for __gcm-aes-aesni (__driver-gcm-aes-aesni)
[    7.340363] alg: No test for __generic-gcm-aes-aesni (__driver-generic-gcm-aes-aesni)
[    7.381571] ppdev: user-space parallel port driver
[    7.571710] type=1305 audit(1615624005.114:3): audit_pid=712 old=0 auid=4294967295 ses=4294967295 res=1
[    7.747291] random: crng init done

为了更容易看,可以通过-H 参数里面会显示具体时间,加上-L 参数,彩色打印,如下:
在这里插入图片描述

二、利用 addr2line 定位 core 的位置

写个简单的例子,如下:

#include <stdio.h>
int main()
{
  int* p = NULL;
  *p = 0;
  printf("core\n");
  return 0;
}

因为 p 指针没有分配地址,所以 *p = 0 会 core,输入dmesg 显示如下:

[3307172.176109] 1[10848]: segfault at 0 ip 0000000000400578 sp 00007ffcb052a550 error 6 in 1[400000+1000]

编译下:

 g++ 1.c -o abc -g

运行:./abc,会 core,通过 dmesg 我们来查看下 core 的信息:
在这里插入图片描述
来看下如下信息:

abc[10870]: segfault at 0 ip 0000000000400578 sp 00007fff22cccb60 error 6 in abc[400000+1000]

其中abc为程序名字,10870为运行时候的进程 ID,segfault at引起故障的地址为 0,ip 表示 core 的内存地址:0000000000400578,sp 后面地址为 堆栈指针地址,这个没啥用,error 6 这个比较重要,是为多种原因的位运算得到的结果:

error code是位运算,说明:
 
bit2: 值为1表示是用户态程序内存访问越界,值为0表示是内核态程序内存访问越界
bit1: 值为1表示是写操作导致内存访问越界,值为0表示是读操作导致内存访问越界
bit0: 值为1表示没有足够的权限访问非法地址的内容,值为0表示访问的非法地址根本没有对应的页面,也就是无效地址

6 换成二进制是:110, 即 是用户态程序内存访问越界和写操作导致内存访问越界。知道指令的地址,就可以查看地址对应的代码位置,命令如下:

[root@iZbp10p2g1civrw4ggigvfZ soft]# addr2line -s -f -e ./abc 0000000000400578
main
1.c:6

顺利定义到代码在 1.c 文件的第六行。

利用 addr2line 定位 库中 core 的位置

写一个一定会 core 的代码,如下:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3
  4 int main(int argc ,char*  argv[])
  5 {
  6   char * pstr = NULL;
  7   char * pstr2 = (char*)malloc(sizeof(char)*10);
  8   memcpy(pstr,pstr2,20);
  9   printf(" core\n");
 10   return 0;
 11 }

运行下 dmesg 查看 core 信息:

[3390574.284000] def[18554]: segfault at 0 ip 00007f0c420f8c16 sp 00007fff9e6dee98 error 6 in libc-2.17.so[7f0c41fa2000+1c3000]

由于 core 的位置在库中,首先库的基地址为:7f0c41fa2000,core 的位置为 00007f0c420f8c16,计算下 core 的位置在库中的偏移量:

>>> 0x7f0c420f8c16-0x7f0c41fa2000
1403926
>>> hex(1403926)
'0x156c16'

找到动态库,反编译出汇编代码,根据地址进行定位:

objdump  -DCgl libc-2.17.so  > 1.txt
# 搜索:156c16
vim 1.txt

运气好的话,先上移动可以看到定位到的函数,如果运气一般,还是无法查到具体的 core 的库函数,如下图:
在这里插入图片描述

转载于:https://blog.csdn.net/mseaspring/article/details/116382811

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值