Loading... # 前言 最近碰到了一个程序崩溃的问题,根据我的统计,这个问题出现的概率大概是400小时出现一次,出问题的概率比较小,而且由于未知原因,程序崩溃时的core dump文件没有生成。 后面我搭了一个测试环境反复去跑数据,连续测试了12个小时也并没有复现出来问题。这也是正常的,毕竟400小时/次的概率也是非常小的。目前可以利用的信息有 `/var/log/kern.log`文件以及不含调试信息的可执行文件。 记录一下解决问题的方法。 # `kern.log`的崩溃信息 我在系统 `/var/log/kern.log`文件中找到了崩溃信息,如下: ``` Nov 24 06:20:42 PC kernel: [ 2906.214694] A[9536]: segfault at 28 ip 00007f55572573a8 sp 00007f55367f9ec0 error 4 in B.so[7f5557249000+1d000] Nov 24 06:20:42 PC kernel: [ 2906.214714] Code: c3 49 f7 f1 48 8b 47 18 4c 8b 14 d0 48 89 d5 4d 85 d2 74 4e 4d 8b 02 49 8b 48 08 eb 24 0f 1f 44 00 00 49 8b 00 48 85 c0 74 38 <48> 8b 48 08 4d 89 c2 31 d2 49 89 c0 48 89 c8 49 f7 f1 48 39 d5 75 ``` 总共就两行,发生了段错误,比较关键的是这一行信息 `A[9536]: segfault at 28 ip 00007f55572573a8 sp 00007f55367f9ec0 error 4 in B.so[7f5557249000+1d000]` 具体来说, 1. `A[9536]`,代表名为`A`、进程号(PID)为`9536`的程序 2. `segfault at 28`,表示程序在试图访问`28`这个地址的内存时产生了段错误 3. `ip 00007f55572573a8`,表示当时程序在执行地址为`00007f55572573a8`的程序 4. `sp 00007f55367f9ec0`,表示当时程序的栈的地址 5. `error 4`,是错误码,`4`表示用户态的错误 6. `in B.so[7f5557249000+1d000]`,表示是在`B.so`文件产生的错误,这个`.so`映射到内存(VMA)中的起始地址是`7f5557249000`,其大小为`1d000` # 计算 `.so`文件的崩溃地址 我们知道 `ip 00007f55572573a8`以及 `B.so[7f5557249000+1d000]`,我们就可以计算执行的这一行指令在 `.so`文件中的相对位置,即为 `00007f55572573a8-7f5557249000=e3a8`。因此,我们需要在 `.so`文件中找到 `e3a8`地址对应的函数就可以找到是哪里出现的崩溃了。 # 找到崩溃的地方 我们可以使用 `objdump`来查看二进制可能的附带信息,这个附带信息一般都会有函数名称。因为 `objdump`里面包含的信息太多,通过 `grep`会更方便一些,找到离 `e3a8`最近的函数即可 `objdump -tT B.so | grep e3`返回 ``` 000000000000e350 w F .text 00000000000000c2 _ZN1A1B1CI1DE1FERKS2_ 000000000000e350 w DF .text 00000000000000c2 Base _ZN1A1B1CI1DE1FERKS2_ ``` 我们可以看到,离 `e3a8`最近的函数是 `_ZN1A1B1CI1DE1EERKS2_`,这个名字是经过 `Name Mangling`的,通过命令 `c++filt _ZN1A1B1CI1DE1EERKS2_`解析得到 `A::B::C<D>::E(D const&)`,这个就是崩溃时候的函数了 # Ref 1. https://utcc.utoronto.ca/~cks/space/blog/linux/KernelSegfaultMessageMeaning 2. https://en.wikipedia.org/wiki/Name_mangling Last modification:December 13th, 2021 at 05:45 pm © 允许规范转载
One comment
问个问题,你是怎么关闭右上角的登录按钮的。