天天看點

遇到segfault但是沒有coredump檔案如何定位問題?

生産環境定位問題往往遇到各種限制,比如事後日志發現程式是收到SIGSEGV退出了(segment fault),但是因為:

  1. 沒配置limit
  2. 存儲空間不夠了
  3. 其他未知原因

沒有正常生成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。

定位方法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

遇到segfault但是沒有coredump檔案如何定位問題?