生产环境定位问题往往遇到各种限制,比如事后日志发现程序是收到SIGSEGV退出了(segment fault),但是因为:
- 没配置limit
- 存储空间不够了
- 其他未知原因
没有正常生成core文件,那么这会如何定位问题呢?
场景构造
测试程序ctest,明显的空指针错误。
#include <stdio.h>
struct Ctest
{
int i;
};
int main()
{
printf("hi\n");
printf("hi\n");
struct Ctest *c;
c->i = 10;
printf("hi %d\n", c->i);
printf("hi\n");
return 0;
}
执行后:
$ ./ctest
hi
hi
Segmentation fault (core dumped)
但是没有生成core文件。
定位方法1
系统中的任何程序收到SIGSEGV都会记录在内核日志中:
dmesg -T
[Mon Jul 11 15:51:08 2022] ctest[9040]: segfault at 0 ip 0000000000401162 sp 00007ffcc0d3a0a0 error 6 in ctest[401000+1000]
这条日志的含义:
-
9040
:进程号 -
segfault
:错误名称 -
ip 0000000000401162
:instruction pointer就是代码执行位置的指针 -
sp 00007ffcc0d3a0a0
:程序执行栈指针 -
error 6
:Architecture-specific flags; see arch/*/mm/fault.c for your platform.
最后的error 6是按二进制来使用的,含义需要找对应平台的fault.c中具体查询。‘’
我们关心的只是程序运行到哪里报错了,所以只需要关注ip 0000000000401162
$ addr2line -e ./ctest 0000000000401162
/tmp/ctest.c:14
可以看到程序在执行14行的时候,收到内核的SIGSEGV。
以上方法是段错误在程序中,那么段错误在共享库中,该如何定位???
扩展
如果程序崩溃在共享库中,例如 process_name[10678]: segfault at 1 ip 00007f6ddc43c650 sp 00000000461b41a8 error 4 in libc-2.4.so[7f6ddc3ca000+127000]
指令的实际地址是:00007f6ddc43c650 - 7f6ddc3ca000 = 0x72650
> 可以通过反汇编 objdump -dgS libc-2.4.so > output 然后在output文件中搜索72650,同样也可以定位到具体的函数。
定位方法2
dump二进制编译信息objdump -d ./ctest | more
可以看到401162位置上的movl $0xa,(%rax)
,直接看汇编代码:
- 将立即数0xa(十进制的10)赋给寄存器rax记录的地址
- 但是rax并没有分配任何地址,所以使用非法地址越界报错
(复杂代码的汇编可读性很差,建议使用方法1)
objdump -d ./ctest | more
0000000000401142 <main>:
401142: 55 push %rbp
401143: 48 89 e5 mov %rsp,%rbp
401146: 48 83 ec 10 sub $0x10,%rsp
40114a: bf 10 20 40 00 mov $0x402010,%edi
40114f: e8 dc fe ff ff callq 401030 <puts@plt>
401154: bf 10 20 40 00 mov $0x402010,%edi
401159: e8 d2 fe ff ff callq 401030 <puts@plt>
40115e: 48 8b 45 f8 mov -0x8(%rbp),%rax
401162: c7 00 0a 00 00 00 movl $0xa,(%rax) # 将立即数0xa(十进制的10)赋给寄存器rax记录的地址
# 但是rax并没有分配任何地址,所以使用非法地址越界报错
401168: 48 8b 45 f8 mov -0x8(%rbp),%rax
40116c: 8b 00 mov (%rax),%eax
40116e: 89 c6 mov %eax,%esi
401170: bf 13 20 40 00 mov $0x402013,%edi
401175: b8 00 00 00 00 mov $0x0,%eax
40117a: e8 c1 fe ff ff callq 401040 <printf@plt>
40117f: bf 10 20 40 00 mov $0x402010,%edi
401184: e8 a7 fe ff ff callq 401030 <puts@plt>
401189: b8 00 00 00 00 mov $0x0,%eax
40118e: c9 leaveq
40118f: c3 retq
使用GDB来验证下,给地址3赋值,越界访问后收到内核信号SIGSEGV文章来源:https://www.toymoban.com/news/detail-401219.html
文章来源地址https://www.toymoban.com/news/detail-401219.html
到了这里,关于GDB:遇到segfault但是没有core文件如何定位问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!