未使用调试器标志编译的代码出现分段错误

segmentation fault has occurred on a code which was not compiled using debugger flags

本文关键字:分段 错误 代码 调试器 标志 编译 未使用      更新时间:2023-10-16

我的系统上的一个进程出现了分段错误。从核心文件中,我得到了以下信息。

#0  0x00007f8768c06cfb in TestDummy::work() () from libCont.so
#1  0x00007f8768bfb5ee in Test::work() () from libCont.so
#2  0x00007f8768c5fa7b in Test::worker_threads() () from libCont.so
#3  0x00007f873fffe830 in ?? ()
#4  0x0000000000000000 in ?? ()

请注意,我无法重新创建这个分段错误,我所拥有的只是系统上的这个核心文件,以确定出了什么问题。注意:代码不是使用调试器标志(即"g++-g")编译的,因此调试信息不可用。

我尝试了什么我试图拆开并阅读完整的第0帧,以确定确切的崩溃点,但无济于事。

有人能告诉我进一步调试它的方法吗?

我试图掩饰并阅读完整的0帧,以确定确切的崩溃点,但这对没有帮助

您不需要确定确切的崩溃点:GDB已经告诉您它是什么:它是地址0x7f8768c06cfb的指令。

可能说的是"尽管看了反汇编,我仍然不明白是哪个源代码行导致了问题"。我们可以帮助您,但前提是您在问题中实际显示源代码和反汇编。

您的唯一其他选择是:

  1. 找一位当地的大师,你可以向他展示来源和拆解,他会像我们一样帮助你,或者
  2. 按照Lightness Races in Orbit告诉你的做:用完全相同的标志重建二进制文件,但也添加-g。假设你有一个封闭的构建,并且可以在足够接近的状态下重建你的原始二进制文件(nm new-binary的输出应该与nm old-binary的输出匹配),GDB会告诉你地址0x7f8768c06cfb对应的行

注意:您实际上不必使用-g重建整个二进制文件。仅重建包含TestDummy::work()的源并重新链接libCont.so就足够了。

我认为有一种方法可以调试没有使用调试器标志编译的核心。我想用下面的例子来解释它。

(gdb) disassemble 
Dump of assembler code for function mystrcpy:  
 0x0804852a <+0>:   push   %ebp  
 0x0804852b <+1>:   mov    %esp,%ebp  
 0x0804852d <+3>:   sub    $0x10,%esp  
 0x08048530 <+6>:   mov    0x8(%ebp),%eax 
  0x08048533 <+9>:  mov    %eax,-0x4(%ebp)  
 0x08048536 <+12>:  jmp    0x8048540 <mystrcpy+22>
   0x08048538 <+14>:    addl   $0x1,0xc(%ebp)  
 0x0804853c <+18>:  addl   $0x1,0x8(%ebp)
   0x08048540 <+22>:    mov    0xc(%ebp),%eax 
  0x08048543 <+25>: movzbl (%eax),%edx 
  0x08048546 <+28>: mov    0x8(%ebp),%eax
=> 0x08048549 <+31>:    mov    %dl,(%eax)  
 0x0804854b <+33>:  mov    0x8(%ebp),%eax  
 0x0804854e <+36>:  movzbl (%eax),%eax
   0x08048551 <+39>:    test   %al,%al 
  0x08048553 <+41>: jne  
  0x8048538 <mystrcpy+14>  
 0x08048555 <+43>:  mov    -0x4(%ebp),%eax
   0x08048558 <+46>:    leave   
  0x08048559 <+47>: 
ret    End of assembler dump.

现在,实际上显示"=>"符号的行是罪魁祸首。(=>0x08048549<+31>:mov%dl,(%eax))

我们可以使用gdb命令来了解显示问题的行发生了什么。

  gdb) print $eax //print command
     $1 = 0
    (gdb) print $dl
     $2 = 118
    (gdb) print/c $dl
     $3 = 118 'v‘
    (gdb) info frame //info frame command
    Stack level 0, frame at 0xffbf8b90: eip = 0x8048549 in mystrcpy; saved eip =   0x80485cd called by frame at 0xffbf8bc0 Arglist at 0xffbf8b88, args:  Locals at 0xffbf8b88, Previous frame's sp is 0xffbf8b90 Saved registers:  ebp at 0xffbf8b88, eip at 0xffbf8b8c
    (gdb) x/x $ebp+4 //base pointer + 4 
    0xffbf8b8c: 0x080485cd
    (gdb) info symbol 0x080485cd  //info symbol command 
     connect + 115 in section .text of /home/vmahajan/a.out
     (gdb) x/x $ebp+4 
     0xffbf8b8c:    0x080485cd
    (gdb) x/x $ebp+8 
     0xffbf8b90:    0x00000000
    (gdb) x/x $ebp+12 
     0xffbf8b94:    0xffbf91f3
    (gdb) print/s (char *)0xffbf91f3
     $5 = 0xffbf91f3 "vishal“