assembly 在编译器优化的二进制映像上运行时,GDB是否显示错误的数据?

bxpogfeg  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(88)

我有一个准则-

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无法正确打印?

mbskvtky

mbskvtky1#

这似乎是编译器的问题。info address arg2的输出显示第二个参数arg2在堆栈位置中不包含条目。

相关问题