GDB 显示损坏的指令地址偏移

Posted

技术标签:

【中文标题】GDB 显示损坏的指令地址偏移【英文标题】:GDB shows broken instruction address offset 【发布时间】:2019-09-17 10:36:26 【问题描述】:
$ gdb --version
GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git

我正在使用 gdb 进行调试,但遇到了一些奇怪的地址偏移。我有一个用C++ 编写的共享库,其函数foo 反汇编如下(第一个片段):

Dump of assembler code for function foo:
   0x00007ffff5c82d70 <+0>:     push   rbp
   0x00007ffff5c82d71 <+1>:     mov    rbp,rsp
   0x00007ffff5c82d74 <+4>:     push   r15
   0x00007ffff5c82d76 <+6>:     push   r14
   0x00007ffff5c82d78 <+8>:     push   r13
   0x00007ffff5c82d7a <+10>:    push   r12
   0x00007ffff5c82d7c <+12>:    push   rbx
   0x00007ffff5c82d7d <+13>:    sub    rsp,0x18
   0x00007ffff5c82d81 <+17>:    test   rdi,rdi
   0x00007ffff5c82d84 <+20>:    mov    DWORD PTR [rbp-0x34],r8d
   0x00007ffff5c82d88 <+24>:    je     0x7ffff5c82e58 <foo+232>
   0x00007ffff5c82d8e <+30>:    mov    r15,rsi
   0x00007ffff5c82d91 <+33>:    mov    r14,rdx
   0x00007ffff5c82d94 <+36>:    mov    r13d,ecx
   0x00007ffff5c82d97 <+39>:    mov    rbx,rdi
   0x00007ffff5c82d9a <+42>:    jmp    0x7ffff5c82ded <foo+125>
   0x00007ffff5c82d9c <+44>:    nop    DWORD PTR [rax+0x0]
   # Where do these negative offsets come from?
   0x00007ffff5c82da0 <+-1632>: mov    r9d,DWORD PTR [r12]
   0x00007ffff5c82da4 <+-1628>: lea    rcx,[rip+0xcadbe2]        
   0x00007ffff5c82dab <+-1621>: lea    rdx,[rip+0xcadde6]        
   0x00007ffff5c82db2 <+-1614>: lea    rdi,[rip+0xcadb67]   
   #...
   # negative offset of some unrelated function `bar`
   0x00007ffff5c82e19 <+-1511>: js     0x7ffff5c82dde <bar+4294965726>

这样的负偏移点被解释为属于一些不相关的功能(我没有找到任何可以匹配这些功能的东西)bar

这些事情在使用 GUI gdb 前端时会引起混乱。

知道为什么 gdb 可能会显示如此负的指令偏移量吗?它是一个 GDB 错误吗?如果是这样,有什么解决方法吗?

我试图找出有关此函数的objdump 输出,但没有发现任何奇怪的地方(与 gdb 示例中的片段相同):

$ objdump -M intel -d libsomelib.so | grep -A 100 -i "0000000000e78d70"                                                        
0000000000e78d70 <foo>:                                                                                   
  e78d70:       55                      push   rbp                                                                                                                                                                 
  e78d71:       48 89 e5                mov    rbp,rsp                                                                                                                                                             
  e78d74:       41 57                   push   r15                                                                                                                                                                 
  e78d76:       41 56                   push   r14                                                                                                                                                                 
  e78d78:       41 55                   push   r13                                                                                                                                                                 
  e78d7a:       41 54                   push   r12                                                                                                                                                                 
  e78d7c:       53                      push   rbx                                                                                                                                                                 
  e78d7d:       48 83 ec 18             sub    rsp,0x18                                                                                                                                                            
  e78d81:       48 85 ff                test   rdi,rdi                                                                                                                                                             
  e78d84:       44 89 45 cc             mov    DWORD PTR [rbp-0x34],r8d                                                                                                                                            
  e78d88:       0f 84 ca 00 00 00       je     e78e58 <foo+0xe8>                                          
  e78d8e:       49 89 f7                mov    r15,rsi                                                                                                                                                             
  e78d91:       49 89 d6                mov    r14,rdx                                                                                                                                                             
  e78d94:       41 89 cd                mov    r13d,ecx                                                                                                                                                            
  e78d97:       48 89 fb                mov    rbx,rdi                                                                                                                                                             
  e78d9a:       eb 51                   jmp    e78ded <foo+0x7d>                                          
  e78d9c:       0f 1f 40 00             nop    DWORD PTR [rax+0x0]                                                                                                                                                 
  e78da0:       45 8b 0c 24             mov    r9d,DWORD PTR [r12]                                                                                                                                                 
  e78da4:       48 8d 0d e2 db ca 00    lea    rcx,[rip+0xcadbe2]                                                           
  e78dab:       48 8d 15 e6 dd ca 00    lea    rdx,[rip+0xcadde6]                                                           
  e78db2:       48 8d 3d 67 db ca 00    lea    rdi,[rip+0xcadb67]                                                        
  //...
  //just fine
  e78e19:       78 c3                   js     e78dde <foo+0x6e> 

gdb 和 objdump 的输出之间的明显区别可以在最后一行看到。

GDB:

0x00007ffff5c82e19 <+-1511>: js     0x7ffff5c82dde <bar+4294965726>

objdump:

e78e19:       78 c3                   js     e78dde <foo+0x6e>

【问题讨论】:

似乎将数据解释为代码 - 控制无法到达那些指令,至少不是从这里显示的内容。 【参考方案1】:

知道为什么 gdb 可能会显示如此负的指令偏移量吗?

是的:在&lt;bar+4294965726&gt; 中,GDB 将偏移量解释为有符号整数:4294965726 == -1570

这是一个 GDB 错误吗?

是的。

不幸的是,目前尚不清楚如何重现这一点,或者为什么 GDB 决定显示与 bar 的偏移量,而不是显示与 foo 的偏移量。否则,将很难创建正确的错误报告。

【讨论】:

有趣的是,在反汇编中,gdb 正确显示了je 0x7ffff5c82e58 &lt;foo+232&gt;,然后在该地址上它可能会显示与bar 的负偏移量。听起来它有两种不同的方式来解析符号,所以它甚至不一致。

以上是关于GDB 显示损坏的指令地址偏移的主要内容,如果未能解决你的问题,请参考以下文章

GDB核心转储具有损坏的堆栈,显示“堆栈帧无法访问地址0x12处的内存”

gdb 反向调试失败并显示“进程记录不支持地址处的指令 0xf0d”

GDB 调试命令

gdb layout regs: GDB显示详细指令和寄存器信息

x/nfu-用gdb查看内存

如何获取 gdb tui 程序集输出以显示指令?