我有一个准则-
100 static void
101 func (<struct type1> *arg1, <struct type2> **arg2)
102 {
103 <struct type2> *var1;
...
...
...
112 var1 = *arg2; /* arg2 is no where else used in this function */
113 if (!var1) {
114 return;
115 }
...
... /* var1 has been referenced to read its properties and to set its properties */
120
...
...
125 my_free(); /* crash happened at this line - my_free() would call __free() */
...
...
130
}
程序崩溃了,并创建了一个内核-
#2 0x000055ea29cceb76 in func [__be_func...] (arg1=arg1@entry=0x7f8bcc440098, arg2=arg2@entry=0x0) at myfile.c:121
您可能会注意到第二个参数arg2
被GDB显示为0x 0。但是,如果它是NULL,那么程序可能会在第112行崩溃。
所以我决定反汇编代码,下面是反汇编上述函数后的摘录-
(gdb) disass
Dump of assembler code for function func:
0x000055ea29cce790 <+0>: push %rbp
0x000055ea29cce791 <+1>: mov %rsp,%rbp
0x000055ea29cce794 <+4>: push %r15
0x000055ea29cce796 <+6>: push %r14
0x000055ea29cce798 <+8>: push %r13
0x000055ea29cce79a <+10>: push %r12
0x000055ea29cce79c <+12>: push %rbx
0x000055ea29cce79d <+13>: sub $0x38,%rsp
0x000055ea29cce7a1 <+17>: mov %rdi,%r14
0x000055ea29cce7a4 <+20>: movabs $0x8000000000000000,%r15
0x000055ea29cce7ae <+30>: addq $0x1,0x1864a08a(%rip)
0x000055ea29cce7b6 <+38>: lea -0x1(%r15),%rdx
0x000055ea29cce7ba <+42>: mov %rdi,-0x38(%rbp)
0x000055ea29cce7be <+46>: and %rdx,%r14
0x000055ea29cce7c1 <+49>: and %rdx,%rsi
0x000055ea29cce7c4 <+52>: mov $0xffffffffffffff7f,%r13
0x000055ea29cce7cb <+59>: and 0x50(%r14),%r13
0x000055ea29cce7cf <+63>: movl $0x1000000,-0x50(%rbp)
0x000055ea29cce7d6 <+70>: movl $0x0,-0x48(%rbp)
0x000055ea29cce7dd <+77>: mov (%rsi),%rcx
0x000055ea29cce7e0 <+80>: bswap %rcx
0x000055ea29cce7e3 <+83>: mov %rcx,%rbx
0x000055ea29cce7e6 <+86>: mov %rdx,-0x40(%rbp)
0x000055ea29cce7ea <+90>: and %rdx,%rbx
0x000055ea29cce7ed <+93>: je 0x55ea29ccebcb
0x000055ea29cce7f3 <+99>: bswap %r13
0x000055ea29cce7f6 <+102>: testb $0x20,0x10d0(%r14)
0x000055ea29cce7fe <+110>: jne 0x55ea29cce80b
0x000055ea29cce800 <+112>: cmpl $0x0,0x48(%r14)
0x000055ea29cce805 <+117>: je 0x55ea29cce9e1
0x000055ea29cce80b <+123>: mov %rsi,-0x58(%rbp)
0x000055ea29cce80f <+127>: mov 0x1210(%r14),%r11
0x000055ea29cce816 <+134>: bswap %r11
...
...
...
...
我的分析是-由于arg2
只在第112行使用,可能是由于编译器优化,它没有保存到堆栈帧中,而只是保存在寄存器%rsi
中。一旦执行了第112行,%rsi
中的值就发生了变化,arg2
将无限期丢失。如果我的分析是正确的,GDB是否应该在调用堆栈中将arg2
显示为<optimized out>
而不是0x 0?
分析的第一个编辑点-当我转储函数func
的堆栈帧时
(gdb) i r rbp
rbp 0x7f8bcd651730 0x7f8bcd651730
(gdb) x/13xg 0x7F8BCD6516D0
0x7f8bcd6516d0: 0x0000000b00000006
0x00007f8bcd651748 <--- stored register %rsi value, which represents the 2nd argument - ie `arg2`
0x7f8bcd6516e0: 0x0000000001000000
0x0000000000000000
0x7f8bcd6516f0: 0x7fffffffffffffff
0x80007f8bcc440098 <--- stored register %rdi value, which represents the 1st argument - ie `arg1`
0x7f8bcd651700: 0x80007f8bd51a6230
0x00007f8bd51a6248
0x7f8bcd651710: 0x00007f8bcd651748
0x00007f8bd51a6230
0x7f8bcd651720: 0x80007f8bcc440098
0x0000000000000000
0x7f8bcd651730: 0x00007f8bcd651780
如您所见,第二个参数arg2
实际上并不是NULL。
需要注意的是-第一个参数存储为0x80007f8bcc440098
,而第二个参数存储为0x00007f8bcd651748
。不同之处在于第一个参数的MSB位设置为1。为什么当地址的MSB未设置为1时,GDB无法正确打印?
1条答案
按热度按时间mbskvtky1#
这似乎是编译器的问题。
info address arg2
的输出显示第二个参数arg2
在堆栈位置中不包含条目。