GDB:尝试取消引用通用指针
如何使GDB在x/s
等打印function中进行额外的解引用?
当我在x/
I中尝试显式解引用时,会出现错误“尝试取消引用通用指针”。 使用x/
多次工作,因为每次使用都包含隐式解引用,但这很烦人,因为我必须复制并粘贴每个中间结果。
例
考虑非常有用的C程序, example.c
:
#include int main(int argc, char **argv) { printf("argv[0] = %s\n", argv[0]); }
如果我构建它并将其加载到GDB中,我看到argv
存储在0xc(%ebp)
,因为它的双重因素作为第二个参数传递给第24行的printf
(即0x4(%esp)
):
$ gcc -o example example.c $ gdb example (gdb) disass main Dump of assembler code for function main: 0x080483e4 : push %ebp 0x080483e5 : mov %esp,%ebp 0x080483e7 : and $0xfffffff0,%esp 0x080483ea : sub $0x10,%esp 0x080483ed : mov 0xc(%ebp),%eax 0x080483f0 : mov (%eax),%edx 0x080483f2 : mov $0x80484e0,%eax 0x080483f7 : mov %edx,0x4(%esp) 0x080483fb : mov %eax,(%esp) 0x080483fe : call 0x8048300 0x08048403 : leave 0x08048404 : ret End of assembler dump.
我打破printf
并使用参数first
和second
运行程序:
(gdb) break *main + 26 Breakpoint 1 at 0x80483fe (gdb) run first second Starting program: /var/tmp/SO-attempt-to-dereference-generic-pointer/example first second
我尝试在GDB中打印argv[0]
,但是我得到了“通用指针”错误:
Breakpoint 1, 0x080483e5 in main () (gdb) x/s **(0xc + $ebp) Attempt to dereference a generic pointer.
但是,通过使用’x / xw’手动取消引用几次,我最终能够打印argv[0]
(和argv[1]
):
(gdb) x/xw 0xc + $ebp 0xbfffeba4: 0xbfffec34 (gdb) x/xw 0xbfffec34 0xbfffec34: 0xbfffedc8 (gdb) x/s 0xbfffedc8 0xbfffedc8: "/var/tmp/SO-attempt-to-dereference-generic-pointer/example" (gdb) x/xw 0xbfffec34 + 4 0xbfffec38: 0xbfffee03 (gdb) x/s 0xbfffee03 0xbfffee03: "first" (gdb)
但这是烦人的和间接的(因为指针编程不会是?)
解决方案是在解除引用之前强制转换指针。
例如,从我们上面的位置开始:
(gdb) x/s **((char ***) (0xc + $ebp)) 0xbfffedc8: "/var/tmp/SO-attempt-to-dereference-generic-pointer/example" (gdb) x/s *(*((char ***) (0xc + $ebp)) + 1) 0xbfffee03: "first" (gdb) x/s *(*((char ***) (0xc + $ebp)) + 2) 0xbfffee09: "second"
请注意,堆栈地址0xc + $ebp
本身是指向该堆栈位置内容的指针,因此我们需要char ***
而不是char **
。