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 可能会显示如此负的指令偏移量吗?
是的:在<bar+4294965726>
中,GDB 将偏移量解释为有符号整数:4294965726 == -1570
这是一个 GDB 错误吗?
是的。
不幸的是,目前尚不清楚如何重现这一点,或者为什么 GDB 决定显示与 bar
的偏移量,而不是显示与 foo
的偏移量。否则,将很难创建正确的错误报告。
【讨论】:
有趣的是,在反汇编中,gdb 正确显示了je 0x7ffff5c82e58 <foo+232>
,然后在该地址上它可能会显示与bar
的负偏移量。听起来它有两种不同的方式来解析符号,所以它甚至不一致。以上是关于GDB 显示损坏的指令地址偏移的主要内容,如果未能解决你的问题,请参考以下文章
GDB核心转储具有损坏的堆栈,显示“堆栈帧无法访问地址0x12处的内存”
gdb 反向调试失败并显示“进程记录不支持地址处的指令 0xf0d”