I am having a code like -
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
}
The program has crashed and created a core like -
#2 0x000055ea29cceb76 in func [__be_func...] (arg1=arg1@entry=0x7f8bcc440098, arg2=arg2@entry=0x0) at myfile.c:121
You could notice that the second argument arg2
is shown by GDB as 0x0.
However, if it was NULL then program could have crashed at line#112 itself.
So I decided to disassemble the code and below is the excerpt after disassembling the above function -
(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
...
...
...
...
My analysis is -
Since arg2
is only used at line# 112, may be due to compiler optimisation, it is not saved onto the stack frame and just held in register %rsi
. And once after the execution of line# 112, the value in %rsi
has got changed and arg2
is lost indefinitely.
If my analysis is correct, shouldn't GDB shown arg2
as <optimized out>
in the callstack rather than as 0x0?
Edit#1 to my analysis -
when I dumped the stackframe of the function 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
As you can see the 2nd argument arg2
is not really NULL.
Important thing to notice is - 1st argument is stored as 0x80007f8bcc440098
, whereas 2nd argument is stored as 0x00007f8bcd651748
.
The difference is that 1st argument's MSB bit is set to 1.
Why is GDB not printing rightly when the address's MSB is not set to 1?
It appear to be an issue with compiler.
Output of info address arg2
showed that 2nd argument arg2
doesn't contains an entry in stack location.